% *** *** *** *** Rev-1>EDMemAbort.mc Revision 1.1 May 2, 1980 *** *** *** *** ********************************************************************************************** *** EDMemAbort.mc : Memory Abort Test microcode *** Purpose : Test the memory reference abort conditions. *** Minimum Hardware : Standard 4 CPU boards & 96K memory board. *** Approximate Run Time : 88 seconds. *** Written by : Bill Kennedy, March 15, 1978 *** Modified by : Chuck Thacker, June 16, 1979 *** Modified by : P.Hardjadinata, December 12, 1979 Standardize title page and code format. Implement looping and standard labels. *** Modified by : C. Thacker, May 2, 1980 Changed assembly procedure: added command file MemAbort.cm ********************************************************************************************** ********************************************************************************************** *SubTest Description: * SUBTEST 0: Generate random number and set the instruction type accordingly. * SUBTEST 1: Check double-word and quad-word overflow using REG for SRCDEST. * SUBTEST 2: Check double-word and quad-word overflow using the stack for SRCDEST. * SUBTEST 3: Check that stack is as expected when done with SubTest 2. Expected value for stack is in ExpStack. * SUBTEST 4: * Attempt to decrement stack during PFETCH2 using the stack. Check expected stack against actual. * Check value read from memory against what was expected. * SUBTEST 5: * Check that attempting to increment the stack during a PSTORE1 yields the expected results in the stack. * Check that attempting to increment the stack during a PSTORE2 yields the expected results in the stack. * Check that attempting to increment the stack during a PSTORE4 yields the expected results in the stack. ********************************************************************************************** *BreakPoints: * ErrorOvflSet: Overflow bit is set when it shouldn't be. * ErrorDidTrans: Transferred data when not supposed to. * ErrorNoOvfl: Overflow bit is not set when it should be. * ErrorDataCompare: Data transferred did not compare. * Error3: Stack Pointer is not as expected in SubTest2. * Error41: Stack Pointer is not as expected in doing PFETCH2. * Error42: Data is not as expected in doing PFETCH2. * Error51: Stack Pointer is not as expected in doing PSTORE1. * Error52: Stack Pointer is not as expected in doing PSTORE2. * Error53: Stack Pointer is not as expected in doing PSTORE4. * PageCountError1: No page. * PageCountError2: Page Count larger than allowed. * Passed-EDMemAbort-Test: Passed all tests, and all passes. ********************************************************************************************** * ShortLoop Logic Analyzer Sync Points at Control Store address: * ErrorOvlSet: Control Store address 471 at SUBTEST1 or 410 at SUBTEST2. * ErrorDidTrans: Control Store address 471 at SUBTEST1 or 410 at SUBTEST2. * ErrorNoOvfl: Control Store address 471 at SUBTEST1 or 410 at SUBTEST2. * ErrorDataCompare: Control Store address 471 at SUBTEST1 or 410 at SUBTEST2. * Error3: Control Store address 410 at SUBTEST2. * Error41: Control Store address 456 at SUBTEST4. * Error42: Control Store address 456 at SUBTEST4. * Error51: Control Store address 613 at CASET51. * Error52: Control Store address 547 at CASET52. * Error53: Control Store address 570 at CASET54. ********************************************************************************************** *Special Reg. Definition: * ShortLoop: At any breakpoint, the user has the choice of setting ShortLoop to a 1 to loop on the current test. During the short loop, the user can modify the type of memory transfer and the memory address by changing XA. 1, the current test will loop repeatedly for trouble shooting 0, no looping in current test * XA: This test is driven by a sequence of random 16 bit words. The arguments of the test are built up from the random word (XA) as follows: XA[0-1]: selects the register to be used for SRCDEST in PFetch or PStore 0 = register block 0 (RegBlock0) 1 = register block 1 (RegBlock1) 2 = register block 2 (RegBlock2) 3 = register block 3 (RegBlock3) XA[2-3]: type of action to be done 0 = double fetch 1 = quad fetch 2 = double store 3 = quad store XA[8-15]: selects the memory location on a page XA[0-11]: selects the page number * TestCounter: A Counter that keep track of how many loops have been executed in the main loop. The maximum possible loop here is 64K times. * PageCount: Register containing the actual number of pages of memory. ********************************************************************************************** *Subroutine Description: * Check: Sets up TRANSFER flag for later use. It is set up based on the type of transfer to be done. If at the end, TRANSFER = 0, then no actual transfer of data should take place and QUADOVF should be set. * CheckValues: This routine checks the register block or memory for transfers: At exit from this routine, TempReg will be 0 or -1. If it is 0, then registers on fetch or memory on store were equal to what was tried to be read or written. If it is -1, then they were'nt as expected or tested. * IncPanel: Increment the Maintenance Panel. On entry to subroutine, t contains the count of the number of times to increment from 0. * InitMem: to initialize all of available memory to known values (page number XOR'ed with displacement on page). * SetUpBaseRegs: Set up the base registers for page access to main memory based on Current Page contents. Base Page Even is the even base register for references and Base Page Odd is the odd base register. * SetUpInstructions: set up the memory reference instructions - build them in Control Store in 700 and 720. * SetUpRegs: Set up the register block with zeroes before executing any transfers. Additionally, determine what the stack pointer should be after the stack transfer and put it in TempReg for later use by caller. * TestResults: Test the results of tests 1 or 2 and see if they worked as expected. On entry, TRANSFER and QUADOVF determine which way to go. If TRANSFER is equal to zero, then no transfer should occur. * WritePage: actually do the writing in all locations in a page. ********************************************************************************************** % ********************************************************************************************** *INITIALIZATION: *BUILTIN[INSERT,24]; *INSERT[d0lang]; TITLE[MemAbort]; ********** R-Registers: ********** RV[Revision,0,1]; * REVISION 1 RV[Run-Time,1,130]; * Run-Time is 130B or 88D seconds RV[Transfer,2]; *register used to determine whether data should actually transfer RV[PassCount,3, 0]; *outer loop counter RV[MaxPass,4, 2]; *number of times PassCount is to repeat before breakpointing RV[TestCounter, 5]; * inner loop counter RV[SubTest,6, 0]; *contains SubTest number at time of failure RV[ShortLoop,7, 0]; * 1 => loop on current test, 0 => continue to the next test RV[CA, 10]; *used in random number generation, A*XA + CA RV[XA, 11]; *random number generated via A*XA + CA RV[CS0,12]; *used in writing and reading control store word 0 RV[CS1,13]; *used in writing and reading control store word 1 RV[CS2,14]; *used in writing and reading control store word 2 RV[CurrentReg,15]; *contains the current register to be used in memory instruction RV[OldReg,16]; *contains the old (last) register used in the memory instruction RV[InstructionAddress,17]; *contains address of control store being used to build instructions RV[BasePageEven,20]; *base page number to be used in memory instruction RV[BasePageOdd,21]; *odd base page number to be used in memory instruction RV[TypeReg,22]; *contains the type of memory reference to be done RV[CurrentPage,23]; *current page number to be used in memory instruction RV[OldPage,24]; *old page number last used in memory instruction RV[CurrentLoc,25]; *location within a page being addressed by memory reference RV[OldLoc,26]; *contains old (last) location within a page addressed by memory reference RV[ExpStack,27]; *contains expected stack when checking stack updating RV[TempReg,30]; *temporary register used throughout program RV[TempReg2,31]; *temporary register used throughout program RV[TempReg3,32]; *temporary register used throughout program RV[TempReg4,33]; *temporary register used throughout program RV[TempReg5, 34]; *temporary register RV[TempReg6, 62]; *temporary register RV[APCSave,36]; *register used to save APC in Subroutine Call RV[C177776,37, 177776]; *constant used in check routine * put the register block used for memory transfers well away from all other * registers to prevent contamination. * Note that registers at 40 thru 47 are also used although no called out here. RV[RegBlockAdd,35,50]; *contains address of register block used in memory references RV[RegBlock, 50]; *register block used for SRC/DEST in memory transfers RV[RegBlock0, 50]; *first register in register block RV[RegBlock1, 51]; *second register in register block RV[RegBlock2, 52]; *third register in register block RV[RegBlock3, 53]; *fourth register in register block RV[RegBlock4, 54]; *fifth register in register block RV[RegBlock5, 55]; *sixth register in register block RV[RegBlock6, 56]; *seventh register in register block RV[RegBlock7, 57]; *eighth register in register block RV[C177774,60, 177774]; *constant used in check routine RV[PageCount,61]; *register containing the actual number of pages of memory Set[SpecialLoc1,500]; *location in control store for dispatch table 1 Set[SpecialLoc2,600]; *location in control store for dispatch table 2 Set[MainPage,1]; *tag for Main Program page number Set[SubPage1,2]; *tag for Sub-Program page number 1 Set[sp1b,lshift[SubPage1,10]]; *base address of SubPage1 Set[SubPage2,3]; *tag for Sub-Program page number 2 ********************************************************************************************** *** MAIN routine: ONPAGE[MainPage]; go: Start: CLEARMPANEL; * initialize counters, registers, and random number XA _ AND[0377, 123]C; *Load16Bits (XA _ 123) XA _ (XA) OR (AND[177400, 123]C); CA _ AND[0377, 33031]C; *Load16Bits (CA _ 33031) CA _ (CA) OR (AND[177400, 33031]C); PassCount _ 0C; TestCounter _ 0C; LOADPAGE[SubPage1]; * go initialize memory to known values (addresses) CallP[InitMem]; CurrentPage _ 0C; BigLoop:t _ (PassCount) + 1; * to check if MaxPass has already been reached LU _ (MaxPass) - (t); GOTO[MainLoop, ALU >= 0]; t _ PassCount; * go increment the maintenance panel equal to PassCount LOADPAGE[SubPage2]; CallP[IncPanel]; Passed-EDMemAbort-Test: BREAKPOINT; *go to Midas GOTO[START]; MainLoop:t _ TestCounter _ (TestCounter) + 1; GOTO[NextPass,CARRY]; *if test counter has overflowed, increment Big Loop GOTO[SubTest0]; NextPass:PassCount _ (PassCount) + 1; *increment big loop counter GOTO[BigLoop]; *** SUBTEST 0 *** SubTest0:SubTest _ 0C; *initialize test number INCMPANEL; t _ (CurrentPage); *Copy (OldPage _ CurrentPage) OldPage _ t; t _ XA; *Random (4005*XA + CA mod 2**16) t _ (LSH[XA, 2]) + t; t _ (LSH[XA, 13]) + t; t _ (CA) + t; XA _ t; t _ LDF[XA,0,14]; *Assign (CurrentPage _ LDF[XA,0,14]) CurrentPage _ t; LU _ (PageCount) - (t) - 1; *IF CurrentPage > PageCount THEN Assign OldPage GOTO[UseCurrentPage, ALU >= 0]; t _ (OldPage); *Copy (CurrentPage _ OldPage) CurrentPage _ t; UseCurrentPage: t _ LDF[XA,10,10]; *Assign (CurrentLoc _ LDF[XA,10,10]) CurrentLoc _ t; t _ LDF[XA,0,2]; *Assign (CurrentReg _ (RegBlockAdd OR XA[0:1])) t _ ((RegBlockAdd) OR (t)); CurrentReg _ t; SET[TypeSel, SpecialLoc1]; *Select type of reference based on XA[2:3] DISPATCH[XA, 2, 2]; DISP[SwitchTypeSel]; SwitchTypeSel: GOTO[Case0], AT[TypeSel, 0]; GOTO[Case1], AT[TypeSel, 1]; GOTO[Case2], AT[TypeSel, 2]; GOTO[Case3], AT[TypeSel, 3]; Case0: TypeReg _ 5C; *Type = PFETCH2 t _ 1C; t _ ((CurrentReg) + t); *Copy (ExpStack _ (CurrentReg) + t) ExpStack _ t; GOTO[EndTypeSel]; Case1: TypeReg _ 6C; *Type = PFETCH4 t _ ((CurrentReg)); *Copy (ExpStack _ (CurrentReg)) ExpStack _ t; GOTO[EndTypeSel]; Case2: TypeReg _ 11C; *Type = PSTORE2 t _ 1C; t _ ((CurrentReg) - t); *Copy (ExpStack _ (CurrentReg) - t) ExpStack _ t; GOTO[EndTypeSel]; Case3: TypeReg _ 12C; *Type = PSTORE4 t _ ((CurrentReg)); *Copy (ExpStack _ (CurrentReg)) ExpStack _ t; EndTypeSel: LOADPAGE[SubPage1]; *check that conditions are right with register and location CallP[Check]; LOADPAGE[SubPage1]; *build memory reference instructions in CS CallP[SetUpInstructions]; LOADPAGE[SubPage1]; *set up the Base registers used in memory transfers CallP[SetUpBaseRegs]; *** SUBTEST 1 *** SubTest1:SubTest _ 1C, AT [471]; TempReg _ (ZERO) - 1; LOADPAGE[SubPage1]; *set up the registers used in memory transfers CallP[SetUpRegs]; t _ CurrentLoc; PFETCH4[BasePageEven,RegBlock], AT [700];*this instruction gets rebuilt at run time LOADPAGE[SubPage2]; *see if everything worked the way we think it should CallP[TestResults]; ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[SubTest1]; *** SUBTEST 2 *** SubTest2:SubTest _ 2C, AT [410]; *initialize registers TempReg _ (ZERO) - 1; LOADPAGE[SubPage1]; *set up the registers used in memory transfers CallP[SetUpRegs]; STKP _ TempReg ; *put register in the stack as determined in SetUpRegs t _ CurrentLoc; PFETCH4[BasePageEven,Stack], AT [720];*this instruction gets rebuilt at run time LOADPAGE[SubPage2]; *see if everything worked the way we think it should CallP[TestResults]; ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[SubTest2]; *** SUBTEST 3 *** SubTest3:SubTest _ 3C; t _ STKP; *save the stack pointer TempReg4 _ t; TempReg4 _ (TempReg4) XNOR (0C); * put stack in proper order t _ LDF[TempReg4,10,10]; * get the stack that was saved and test it for expected value LU _ (ExpStack) - (t); *IF ExpStack=STKP THEN GOTO SubTest4 GOTO[SubTest4, ALU = 0]; Error3: BREAKPOINT; *Test 3 failed - stack not as expected ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[SubTest2]; nop; *** SUBTEST 4 *** SubTest4:SubTest _ 4C; *assign SubTestNumber into SubTest LOADPAGE[SubPage1], AT [456]; *set up the registers used in memory transfers CallP[SetUpRegs]; t _ (RegBlockAdd); *Copy (ExpStack _ (RegBlockAdd)) ExpStack _ t; t _ (RegBlockAdd) - 1; *and TempReg and STKP with RegBlockAdd - 1 TempReg _ t; STKP _ TempReg; t _ 0C; PFETCH2[BasePageEven,Stack]; *go do a fetch using stack t _ STACK&-1; *and try to update the stack during fetch TempReg _ t; *stuff data read into temporary register t _ STKP; * save the stack pointer CS1 _ t; * in CS1 temporarily CS1 _ (CS1) XNOR (0C); * invert it t _ LDF[CS1,10,10]; * now get just the bits wanted for test ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[SubTest4]; LU _ (ExpStack) - (t); *IF ExpStack=STKP THEN GOTO PassSubTest41 GOTO[PassSubTest41, ALU = 0]; Error41:BREAKPOINT; *Test 4 subtest 1 failed - stack not as expected ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[SubTest4]; nop; PassSubTest41: t _ (CurrentPage) XOR (1C); *calculate what data should have been LU _ (TempReg) - (t); *Is TempReg=ExpectedData ? GOTO[SubTest5, ALU = 0]; Error42:BREAKPOINT; *Test 4 subtest 2 failed - data not as expected ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[SubTest4]; nop; *** SUBTEST 5 *** SubTest5:SubTest _ 5C; LOADPAGE[SubPage1]; *set up the SRC/DEST registers used in memory transfers again CallP[SetUpRegs]; SET[TypeSelLoc2, SpecialLoc2]; *Use XA[2:3] to select cases DISPATCH[XA, 2, 2]; DISP[SwitchTypeSelLoc2]; SwitchTypeSelLoc2: GOTO[CaseT51], AT[TypeSelLoc2, 0];* PStore1 GOTO[CaseT52], AT[TypeSelLoc2, 1];* PStore2 GOTO[CaseT53], AT[TypeSelLoc2, 2]; GOTO[CaseT54], AT[TypeSelLoc2, 3];* PStore4 CaseT51:t _ ((RegBlockAdd)), AT [613];*Copy (ExpStack and STKP _ (RegBlockAdd)) ExpStack _ t; STKP _ RegBlockAdd; t _ 0C; * load displacement PSTORE1[BasePageEven,Stack]; *store into main memory t _ STACK&+1; * and try to increment stack during memory store TempReg _ t; *stuff the data away for later use t _ STKP; * get the present value of the stack pointer CS1 _ t; * in CS1 temporarily CS1 _ (CS1) XNOR (0C); * invert it t _ LDF[CS1,10,10]; * now get just the bits wanted for test LU _ (ExpStack) - (t); *IF ExpStack=STKP THEN GOTO PassSubTest51 GOTO[PassSubTest51, ALU = 0]; Error51:ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[CaseT51]; nop; BREAKPOINT; *Test 5 subtest 1 failed - stack not as expected ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[CaseT51]; nop; PassSubTest51: GOTO[EndswitchT5]; CaseT52:t _ ((RegBlockAdd) + (2C)), AT [547];*Copy (ExpStack _ (RegBlockAdd) + (2C)) ExpStack _ t; t _ (RegBlockAdd) + (3C); TempReg _ t; *put the stack in temporary register STKP _ TempReg; * set up stack t _ 0C; * load displacement PSTORE2[BasePageEven,Stack]; *store into main memory t _ STACK&+1; * and try to increment stack during memory store TempReg _ t; *stuff the data away for later use t _ STKP; * get the present value of the stack pointer CS1 _ t; * in CS1 temporarily CS1 _ (CS1) XNOR (0C); * invert it t _ LDF[CS1,10,10]; * now get just the bits wanted for test LU _ (ExpStack) - (t); *IF ExpStack=STKP THEN GOTO PassSubTest52 GOTO[PassSubTest52, ALU = 0]; Error52:ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[CaseT52]; nop; BREAKPOINT; *Test 5 subtest 2 failed - stack not as expected ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[CaseT52]; nop; PassSubTest52: GOTO[EndswitchT5]; CaseT53:GOTO[MainLoop]; *PSTORE3 - no such thing so ignore CaseT54:t _ (RegBlockAdd) + (4C), AT [570]; *Copy (ExpStack _ (RegBlockAdd) + (4C)) ExpStack _ t; t _ (RegBlockAdd) + (3C); TempReg _ t; *put calculated stack in temporary register STKP _ TempReg; * set up stack t _ 0C; * load displacement PSTORE4[BasePageEven,Stack]; *store into main memory t _ STACK&+1; * and try to increment stack during memory store TempReg _ t; *stuff the data away for later use t _ STKP; * get the present value of the stack pointer CS1 _ t; * in CS1 temporarily CS1 _ (CS1) XNOR (0C); * invert it t _ LDF[CS1,10,10]; * now get just the bits wanted for test LU _ (ExpStack) - (t); *IF ExpStack=STKP THEN GOTO PassSubTest53 GOTO[EndswitchT5, ALU = 0]; Error53:ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[CaseT54]; nop; BREAKPOINT; *Test 5 subtest 3 failed - stack not as expected ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[CaseT54]; nop; EndswitchT5: LOADPAGE[SubPage1]; CALLP[WritePage]; *go rewrite contaminated page GOTO[MainLoop]; *go back through loop ********** SUBROUTINE: Check ********** * * Sets up TRANSFER flag for later use. It is set up based on the type * of transfer to be done. If at the end, TRANSFER = 0, then no actual * transfer of data should take place and QUADOVF should be set. ONPAGE[SubPage1]; Check: Transfer _ 1C; * initialize the flag LU _ LDF[TypeReg,17,1]; *IF QuadWordTransfer THEN GOTO QuadWordTransfer GOTO[QuadWordTransfer, ALU = 0]; t _ LDF[CurrentLoc,16,2]; * double transfer, now see if its modulo 3 CS0 _ t; *use CS0 as temporary register t _ 3C; LU _ (CS0) - t; *Is CurrentLoc = 3 Modulo 4 ? GOTO[Yes3Modulo4, ALU = 0]; GOTO[QuadWordTransfer]; Yes3Modulo4: Transfer _ 0C; * yes, CurrentLoc = 3 Modulo 4 so set flag for no transfer GOTO[EndOfCheck]; QuadWordTransfer: LU _ LDF[TypeReg,17,1]; GOTO[Skip001,ALU=0]; * skip if quad transfer t _ C177776; GOTO[ANDIT]; Skip001:t _ C177774; ANDIT: CurrentLoc _ (CurrentLoc) AND (t); EndOfCheck: RETURN; ********** SUBROUTINE: CheckValues ********** * * This routine checks the register block or memory for transfers. * At exit from this routine, TempReg will be 0 or -1. * If it is 0, then registers on fetch or memory on store were equal to what was * tried to be read or written. * If it is -1, then they were'nt as expected or tested. ONPAGE[SubPage2]; CheckValues: TempReg _ 0C; *init. to 'Pass" t _ STKP; * Save the stack before using it TempReg4 _ t; * save it in one of the temproary registers LU _ (TypeReg) - (10C); *Is this a fetch action ? GOTO[StoreAction, ALU >= 0]; FetchAction: LU _ (TypeReg) - (6C); *What kind of fetch type? GOTO[NotDblFetch, ALU >= 0]; DblFetch: t _ CS0 _ 1C; * using CS0 as counter, set it to 1 for double t _ (CurrentLoc) ANDNOT (t); * put location in proper base TempReg2 _ t; GOTO[EndOfFetchTypeCheck]; NotDblFetch: t _ CS0 _ 3C; * using CS0 as counter, set it to 3 for quad t _ (CurrentLoc) ANDNOT (t); * put location in proper base TempReg2 _ t; EndOfFetchTypeCheck: STKP _ CurrentReg; * initialize the stack t _ (0C); * FOR CS1 IN[0C..CS0] DO CS1 _ t; CheckFetch: t _ (CS0); LU _ (CS1) - (t) - 1; GOTO[EndOfFetchCheck, ALU >= 0]; t _ CS1; t _ (TempReg2) + (t); t _ ((CurrentPage) XOR (t)); *Copy (CS2 _ (CurrentPage) XOR (t)) CS2 _ t; t _ STACK&+1; LU _ (CS2) - (t); *Is CS2=T ? GOTO[FetchDataMatch, ALU = 0]; TempReg _ (ZERO) - 1; * set flag to error FetchDataMatch: CS1 _ (CS1) + 1; *Increment FOR loop counter GOTO[CheckFetch]; EndOfFetchCheck: GOTO[EndOfStoreCheck]; StoreAction: LU _ (TypeReg) - (12C); *What type of Store ? GOTO[NotDblStore, ALU >= 0]; DblStore: t _ CS0 _ 1C; * using CS0, set it to 1 for double store t _ (CurrentLoc) ANDNOT (t); * put location in proper base TempReg2 _ t; GOTO[EndOfStoreTypeCheck]; NotDblStore: t _ CS0 _ 3C; * using CS0, set it to 3 for quad store t _ (CurrentLoc) ANDNOT (t); * put location in proper base TempReg2 _ t; EndOfStoreTypeCheck: t _ (0C); * FOR CS1 IN[0C..CS0] DO CS1 _ t; CheckStore: t _ (CS0); LU _ (CS1) - (t) - 1; GOTO[EndOfStoreCheck, ALU >= 0]; t _ CS1; t _ (TempReg2) + t; PFETCH1[BasePageEven,CS2]; nop; nop; nop; nop; nop; nop; TempReg5 _ t; * put address in t away for a bit t _ ((CurrentPage) XOR (t)); *Copy (TempReg3 _ (CurrentPage) XOR (t)) TempReg3 _ t; t _ TempReg5; * now get the address put away above PSTORE1[BasePageEven,TempReg3]; LU _ (CS2); *Is CS2=t ? GOTO[StoreDataMatch, ALU = 0]; TempReg _ (ZERO) - 1; StoreDataMatch: CS1 _ (CS1) + 1; *Increment FOR loop counter GOTO[CheckStore]; EndOfStoreCheck: TempReg4 _ (TempReg4) XNOR (0C); * complement saved stack STKP _ TempReg4; * and restore the stack RETURN; ********** SUBROUTINE: IncPanel ********** * * Increment the Maintenance Panel. * On entry to subroutine, t contains the count of the * number of times to increment from 0. ONPAGE[SubPage2]; IncPanel:TempReg _ t, CLEARMPANEL; * first put panel at zero TempReg6 _ 6C; GOTO[., R>=0], TempReg6 _ (TempReg6) - 1; GOTO[.+1]; IncLoop:INCMPANEL; GOTO[.+1]; TempReg _ (TempReg) - 1; *decrement the counter GOTO[IncLoop, ALU # 0]; * keep it up until it is zero RETURN; ********** SUBROUTINE: InitMem ********** * * Check that we actually got a value for Page Count with limits of * 00 THEN GOTO NoPageCountError1 GOTO[NoPageCountError1, ALU >= 0]; t _ 2C; PageCountError1: BREAKPOINT; *Page Count says no pages goto[NoPageCountError2]; NoPageCountError1: t _ 40000C; *maximum allowed pages in 2 to power 22 LU _ (PageCount) - (t) - 1; *IF PageCount<=40000 THEN GOTO NoPageCountError2 GOTO[NoPageCountError2, ALU < 0]; t _ 3C; PageCountError2: BREAKPOINT; *Page count larger than allowed NoPageCountError2: CurrentPage _ 0C; t _ 0C; USECTASK; t _ APC&APCTASK; TempReg _ t; InitLoop:LOADPAGE[SubPage1]; CallP[SetUpBaseRegs]; LOADPAGE[SubPage1]; CallP[WritePage]; t _ (CurrentPage) _ (CurrentPage) + 1; * increment page counter LU _ (PageCount) - (t) - 1; *IF CurrentPage<=PageCount THEN GOTO InitLoop GOTO[InitLoop, ALU >= 0]; APC&APCTASK _ TempReg; RETURN; ********** SUBROUTINE: SetUpBaseRegs ********** * * Set up the base registers for page access to main memory based on Current * Page contents. Base Page Even is the even base register for references and * Base Page Odd is the odd base register. ONPAGE[SubPage1]; SetUpBaseRegs: t _ (LDF[CurrentPage,10,10]); * get the lower 8 bits of page number BasePageEven _ t; BasePageEven _ LSH[BasePageEven,10]; * shift into upper 8 bits t _ (LDF[CurrentPage,0,10]); * get the upper eight bits of page number BasePageOdd _ t; BasePageOdd _ LSH[BasePageOdd,10]; * shift into upper 8 bits BasePageOdd _ (BasePageOdd) OR (t); *put in both halfs BasePageOdd _ (BasePageOdd) + 1; * add 1 to lower half RETURN; ********** SUBROUTINE: SetUpInstructions ********** * * set up the memory reference instructions - build them in Control Store in * 700 and 720. ONPAGE[SubPage1]; SetUpInstructions: InstructionAddress _ AND[0377, 700]C;*Load16Bits (InstructionAddress _ 700) InstructionAddress _ (InstructionAddress) OR (AND[177400, 700]C); t _ (InstructionAddress); *Copy (CS2 _ InstructionAddress) CS2 _ t; t _ 0C; APCTASK&APC _ (CS2); READCS; t _ CSData, AT[sp1b,10]; CS0 _ t; t _ 1C; APCTASK&APC _ (CS2); READCS; t _ CSData, AT[sp1b,20]; CS1 _ t; t _ 3C; APCTASK&APC _ (CS2); READCS; t _ CSData, AT[sp1b,30]; CS2 _ t; CS2 _ RSH[CS2, 14]; t _ LDF[TypeReg, 14, 4]; *CopyField (CS0[06, 4] _ TypeReg[14, 4], temp is TempReg) TempReg _ 4C; TempReg _ (TempReg) - 1; TempReg _ (TempReg) OR (LSHIFT[06, 4]C); CYCLECONTROL _ TempReg; TempReg _ t; t _ WFA[TempReg]; CS0 _ WFB[(CS0) OR t]; t _ LDF[CurrentReg, 10, 6]; *CopyField (CS0[12, 6] _ CurrentReg[10, 6], temp is TempReg) TempReg _ 6C; TempReg _ (TempReg) - 1; TempReg _ (TempReg) OR (LSHIFT[12, 4]C); CYCLECONTROL _ TempReg; TempReg _ t; t _ WFA[TempReg]; CS0 _ WFB[(CS0) OR t]; t _ LDF[CurrentReg, 16, 2]; *CopyField (CS1[0, 2] _ CurrentReg[16, 2], temp is TempReg) TempReg _ 2C; TempReg _ (TempReg) - 1; TempReg _ (TempReg) OR (LSHIFT[0, 4]C); CYCLECONTROL _ TempReg; TempReg _ t; t _ WFA[TempReg]; CS1 _ WFB[(CS1) OR t]; t _ CS0; *WriteCS (write control store location 'InstructionAddress') TempReg _ t; *put CS0 in the temp. reg. t _ CS1; *get CS1 TempReg _ t _ (TempReg) XOR (t);*exclusive or the first two CS words t _ (LDF[CS2,14,4]) XOR (t); *now exclusive or the third CS word with the result TempReg _ t _ (LDF[TempReg,0,10]) XOR (t);*now start halfing process to get parity TempReg _ t _ (LDF[TempReg,10,4]) XOR (t); TempReg _ t _ (LDF[TempReg,14,2]) XOR (t); TempReg _ t _ (LDF[TempReg,16,1]) XNOR (t); *Do last part and complement it t _ (LDF[TempReg,17,1]); *put parity bit in the t-register CS1 _ (CS1) XOR (t); * exclusive or the parity bit into bit 31 of CS (15 of CS1) t _ (CS2); LU _ (CS0); APCTASK&APC _ (InstructionAddress); WriteCS0&2; LU _ (CS1), AT[sp1b,40]; APCTASK&APC _ (InstructionAddress); WriteCS1; InstructionAddress _ AND[0377, 720]C, AT[sp1b,50];*Load16Bits (InstructionAddress _ 720) InstructionAddress _ (InstructionAddress) OR (AND[177400, 720]C); t _ (InstructionAddress); *Copy (CS2 _ InstructionAddress) CS2 _ t; t _ 0C; APCTASK&APC _ (CS2); READCS; t _ CSData, AT[sp1b,60]; CS0 _ t; t _ 1C; APCTASK&APC _ (CS2); READCS; t _ CSData, AT[sp1b,70]; CS1 _ t; t _ 3C; APCTASK&APC _ (CS2); READCS; t _ CSData, AT[sp1b,100]; CS2 _ t; CS2 _ RSH[CS2, 14]; t _ LDF[TypeReg, 14, 4]; *CopyField (CS0[06, 4] _ TypeReg[14, 4], temp is TempReg) TempReg _ 4C; TempReg _ (TempReg) - 1; TempReg _ (TempReg) OR (LSHIFT[06, 4]C); CYCLECONTROL _ TempReg; TempReg _ t; t _ WFA[TempReg]; CS0 _ WFB[(CS0) OR t]; t _ CS0; *WriteCS (write control store location 'InstructionAddress') TempReg _ t; *put CS0 in the temp. reg. t _ CS1; *get CS1 TempReg _ t _ (TempReg) XOR (t);*exclusive or the first two CS words t _ (LDF[CS2,14,4]) XOR (t); *now exclusive or the third CS word with the result TempReg _ t _ (LDF[TempReg,0,10]) XOR (t);*now start halfing process to get parity TempReg _ t _ (LDF[TempReg,10,4]) XOR (t); TempReg _ t _ (LDF[TempReg,14,2]) XOR (t); TempReg _ t _ (LDF[TempReg,16,1]) XNOR (t); *Do last part and complement it t _ (LDF[TempReg,17,1]); *put parity bit in the t-register CS1 _ (CS1) XOR (t); * exclusive or the parity bit into bit 31 of CS (15 of CS1) t _ (CS2); LU _ (CS0); APCTASK&APC _ (InstructionAddress); WriteCS0&2; LU _ (CS1), AT[sp1b,110]; APCTASK&APC _ (InstructionAddress); WriteCS1; RETURN, AT[sp1b,120]; ********** SUBROUTINE: SetUpRegs ********** * * Set up the register block with zeroes before executing any transfers. * Additionally, determine what the stack pointer should be after the * stack transfer and put it in TempReg for later use by caller. ONPAGE[SubPage1]; SetUpRegs: STKP _ RegBlockAdd; * set up stack to point to register block t _ (0C); * FOR TempReg IN[0C..17C] DO TempReg _ t; TempRegClear: t _ (17C); LU _ (TempReg) - (t) - 1; GOTO[EndTempRegClear, ALU >= 0]; STACK&+1 _ 0C; * zero out the registers TempReg _ (TempReg) + 1; *Increment FOR loop counter GOTO[TempRegClear]; EndTempRegClear: LU _ (LDF[TypeReg,17,1]); *Is this DoubleWordTransfer ? GOTO[NotDoubleWordTrans, ALU = 0]; LU _ (TypeReg) - (11C); *Is it a fetch type transfer ? GOTO[StoreTypeTrans, ALU >= 0]; FetchTypeTrans: t _ ((CurrentReg) - 1); *Yes, it's a fetch type transfer TempReg _ t; *Copy (TempReg _ (CurrentReg) - 1) GOTO[EndOfSetUpRegs]; StoreTypeTrans: t _ ((CurrentReg) + 1); *Copy (TempReg _ (CurrentReg) + 1) TempReg _ t; GOTO[EndOfSetUpRegs]; NotDoubleWordTrans: t _ (CurrentReg); *Copy (TempReg _ CurrentReg) TempReg _ t; EndOfSetUpRegs: RETURN; ********** SUBROUTINE: TestResults ********** * * Test the results of tests 1 or 2 and see if they worked as expected. * On entry, TRANSFER and QUADOVF determine which way to go. If TRANSFER * is equal to zero, then no transfer should occur. ONPAGE[SubPage2]; TestResults:t _ 0C; USECTASK; t _ APC&APCTASK; APCSave _ t; GOTO[QuadIsSet, QUADOVF]; *see if overflow bit is set QuadIsNotSet:LU _ (Transfer); *Do the transfer ? GOTO[YesTransfer, ALU # 0]; NoTransfer:LU _ (SubTest) - (2C); * see if it is test 2(1270) GOTO[ErrorNoOvfl, ALU = 0]; * if it is, then BREAKPOINT GOTO[YesTransfer]; * if not, it is not an error ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[GetOutOfHere]; nop; ErrorNoOvfl:BREAKPOINT; * overflow bit is not set when it should be goto[GetOutOfHere]; YesTransfer:LOADPAGE[SubPage2]; CallP[CheckValues]; *go check memory/registers to check on transfers LU _ (TempReg); *Is TempReg<0 ? GOTO[EndOfQuadIsNotSet, ALU >= 0]; ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[GetOutOfHere]; ErrorDataCompare: BREAKPOINT; * data transferred did not compare goto[GetOutOfHere]; EndOfQuadIsNotSet: GOTO[GetOutOfHere]; QuadIsSet:LU _ (Transfer); *Do the transfer ? GOTO[NoTransferQS, ALU = 0]; ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[GetOutOfHere]; ErrorOvflSet:BREAKPOINT; * overflow bit is set when it shouldn't be goto[GetOutOfHere]; NoTransferQS:LOADPAGE[SubPage2]; CallP[CheckValues]; LU _ (TempReg); *Is TempReg=0 ? GOTO[GetOutOfHere, ALU # 0]; ShortLoop _ ShortLoop, goto[.+2, R EVEN]; * Looping if ShortLoop is selected goto[GetOutOfHere]; ErrorDidTrans: BREAKPOINT; * transferred data when not supposed to GetOutOfHere: APC&APCTASK _ APCSave; RETURN; ********** SUBROUTINE: WritePage ********** * * actually do the writing in all locations in a page ONPAGE[SubPage1]; WritePage:CurrentLoc _ 0C; * FOR CurrentLoc IN[0C..377C] DO WriteLoop:t _ (377C); LU _ (CurrentLoc) - (t) - 1; GOTO[EndWriteLoop, ALU >= 0]; t _ CurrentLoc; *get the displacement t _ ((CurrentPage) XOR (t)); *Copy (RegBlock0 _ (CurrentPage) XOR (t)) RegBlock0 _ t; t _ CurrentLoc; *get the displacement, again PSTORE1[BasePageEven,RegBlock0]; *write the location CurrentLoc _ (CurrentLoc) + 1; *Increment FOR loop counter GOTO[WriteLoop]; EndWriteLoop: RETURN; END; * to end the MAIN routine