{<Dicentra>Microcode>Dawn.mc, HGM, 12-Nov-84 16:28:24 From Garner's Sunlight of November 12, 1981} Reserve[0F5F, 0FFF]; { section used by the CP Kernel } {This Diagnostic test for the Dandelion CP is based on the philosophy that faults are the "stuck-at" type. The test verifies the CP in three steps: first that all buses and signals can "wiggle," i.e., they are neither stuck at 1 or stuck at 0. (examples are the X, Y, and (internal) F buses.) Next, each of the memories is tested (examples are R, RH, and SU). Finally, the ALU operations (such as "plus" and "xor") are tested: looking for correct results only in enough cases to verify no stuck internal buses. Thus, these 3 tests verify that operands can be correctly read, transmitted across the required buses, and operated upon. This method differs from an approach which tries all combinations of operands, operations, and bus utilizations--a nearly impossible task. Note that some intermitent faults can be found by repeating these tests a large number of times. If an X bus bit is stuck and it is due to a broken driver, the driver can not be located by this test program (or ANY microcode program). This test gnerally assumes that the CP board has been wired correctly. It is assumed the CS and TPC have been checked by the IOP. Therefore lines such as INIA, pfS, prA, etc. are not listed in the comments and are assumed OK. The tests are organized as: 0. Branch logic tests 1. LRotn and Bus tests 2. Operation tests a. constant on X bus b. logic c. Shift/Cycle test {SE}, long modes d. LRotn/Cycle tests e. arithmetic {intra-carry, Cin, Cin←pc16} f. stackP tests g. MAR← effects {auto-branch, MDR← canceled; alu[0-7] effects} 3. Memory tests a. stackP b. R & RH regs c. Link regs d. SU regs {incl. addr. modes} e. Main Memory 4. ibTest 5. microcode traps {MemErr, VirtAdrErr, StackErr, IBErr} 6. Timing tests } MacroDef[AlwaysIBDisp, (IBDisp, IBPtr←1)]; RegDef[R0,R,0], RegDef[rhR0,RH,0]; RegDef[R1,R,1], RegDef[rhR1,RH,1]; RegDef[R2,R,2], RegDef[rhR2,RH,2]; RegDef[R3,R,3], RegDef[rhR3,RH,3]; RegDef[RErr,R,4], RegDef[rhRErr,RH,4]; RegDef[rTempA,R,5]; RegDef[rTempB,R,6]; RegDef[R4,R,4], RegDef[rhR4,RH,4]; RegDef[R5,R,5], RegDef[rhR5,RH,5]; RegDef[R6,R,6], RegDef[rhR6,RH,6]; RegDef[R7,R,7], RegDef[rhR7,RH,7]; RegDef[R8,R,8], RegDef[rhR8,RH,8]; RegDef[R9,R,9], RegDef[rhR9,RH,9]; RegDef[RA,R,0A], RegDef[rhRA,RH,0A]; RegDef[RB,R,0B], RegDef[rhRB,RH,0B]; RegDef[RC,R,0C], RegDef[rhRC,RH,0C]; RegDef[RD,R,0D], RegDef[rhRD,RH,0D]; RegDef[RE,R,0E], RegDef[rhRE,RH,0E]; RegDef[TestCnt,R,0E]; RegDef[RF,R,0F], RegDef[rhRF,RH,0F]; RegDef[uSaveTestCnt, U,1]; RegDef[uD0, U, 0D0]; RegDef[U0, UY,0]; RegDef[U1, UY,1]; RegDef[U2, UY,2]; RegDef[U3, UY,3]; RegDef[U4, UY,4]; RegDef[U5, UY,5]; RegDef[U6, UY,6]; RegDef[U7, UY,7]; RegDef[U8, UY,8]; RegDef[U9, UY,9]; RegDef[UA, UY,0A]; RegDef[UB, UY,0B]; RegDef[UC, UY,0C]; RegDef[UD, UY,0D]; RegDef[UE, UY,0E]; RegDef[UF, UY,0F]; RegDef[U5A, U, 5A], RegDef[UA5, U, 0A5]; {0. Branch Tests} {Are any address lines stuck 0?} Go: TestCnt ← 0, {Initialize TestCount} c1; {Are any address lines stuck 1?} bt1: RErr ← 0, { Initialize Error Register} c2, at[0FF]; bt2: Noop, c3, at[0F00]; {In the following branch tests, branch conditions are not specified in c3 so the TC registers is not implicitly tested.} {Can we do a Cycle2 branch? Is Cycle2 stuck 0?} bt3: Noop, c1, at[0AA0]; XC2npcDisp, c2; Noop, BRANCH[C2Bad0x, C2Good0x, 0D], c3; C2Br: GOTO[BranchBad], c1, at[0,10]; GOTO[BranchBad], c1, at[1,10,C2Br]; GOTO[BranchBad], c1, at[2,10,C2Br]; GOTO[BranchBad], c1, at[3,10,C2Br]; GOTO[BranchBad], c1, at[4,10,C2Br]; GOTO[BranchBad], c1, at[5,10,C2Br]; GOTO[BranchBad], c1, at[6,10,C2Br]; GOTO[BranchBad], c1, at[7,10,C2Br]; GOTO[BranchBad], c1, at[8,10,C2Br]; GOTO[BranchBad], c1, at[9,10,C2Br]; GOTO[BranchBad], c1, at[0A,10,C2Br]; GOTO[BranchBad], c1, at[0B,10,C2Br]; GOTO[BranchBad], c1, at[0C,10,C2Br]; C2Bad0x: GOTO[C2Bad0], c1, at[0D,10,C2Br]; GOTO[BranchBad], c1, at[0E,10,C2Br]; {Is Cycle2 stuck 1?} C2Good0x: XC2npcDisp, c1, at[0F,10,C2Br]; BRANCH[C2Good1, C2Bad1, 0D], c2; {Can we do a NegBr? Is F.0 stuck 0? Secondary test of aF=7 in bit 0.} C2Good1: Noop, c3; [] ← ~R0 xor R0, NegBr, c1; BRANCH[NegBad0, NegGood0], c2; {Is F.0 stuck 1?} NegGood0: Noop, c3; [] ← 0 {doesn't use X bus}, NegBr, c1; BRANCH[NegGood1, NegBad1], c2; {Can we do a ZeroBr? Is FZero stuck 0?} NegGood1: Noop, c3; [] ← 0, ZeroBr, c1; BRANCH[ZeroBad0, ZeroGood0], c2; {Is FZero stuck 1?} ZeroGood0: Noop, c3; [] ← ~R0 xor R0, ZeroBr, c1; BRANCH[ZeroGood1, ZeroBad1], c2; {Can we do a NZeroBr? Is FNonZero stuck 0?} ZeroGood1: Noop, c3; [] ← ~R0 xor R0, NZeroBr, c1; BRANCH[NZeroBad0, NZeroGood0], c2; {Is FNonZero stuck 1?} NZeroGood0: Noop, c3; [] ← 0, NZeroBr, c1; BRANCH[NZeroGood1, NZeroBad1], c2; {Can we do an OvBr? Is Ovr stuck 0? Secondary test of RShift1.} NZeroGood1: R0 ← RShift1 (~R0 xor R0), {R0 ← 7FFF} c3; R0 ← R0 + R0, PgCrOvDisp, c1; R2 ← 0, BRANCH[OvBad0, OvGood0, 2], c2; {Is Ovr stuck 1?} OvGood0: R0 ← 0, c3; R2 ← R0 + 0, PgCrOvDisp, c1; ClrIntErr, BRANCH[OvGood1, OvBad1, 2], c2; {Can we do a MesaIntBr? Is MesaInt stuck 0? Secondary test of ClrIntErr & MesaIntRq.} OvGood1: MesaIntRq, c3; MesaIntBr, c1; BRANCH[MIBad0, MIGood0], c2; {Is MesaInt stuck 1?} MIGood0: ClrIntErr, c3; MesaIntBr, c1; BRANCH[MIGood1, MIBad1], c2; {R0 register test. Can we write R0 with 0's?} MIGood1: R0 ← 0, c3; [] ← R0, ZeroBr, c1; BRANCH[R0ZeroBad, R0ZeroGd], c2; {Can we write R0 with 1's?} R0ZeroGd: R0 ← ~R0 {R0←0FFFF}, c3; [] ← ~R0, ZeroBr, c1; BRANCH[R0OneBad, QTest], c2; {Q register test. Can we write Q with 0's?} QTest: Q ← 0, c3; [] ← Q, ZeroBr, c1; BRANCH[QZeroBad, QZeroGd], c2; {Can we write Q with 1's?} QZeroGd: Q ← ~Q {Q←0FFFF}, c3; [] ← ~Q, ZeroBr, c1; BRANCH[QOneBad, QOneGd], c2; {Can we do a NibCarryBr? Is NibCarry stuck 0?} QOneGd: R0 ← 0, c3; [] ← -R0 {doens't use x bus}, NibCarryBr, c1; BRANCH[NibCBad0, NibCGood0], c2; {Is NibCarry stuck 1?} NibCGood0: Noop, c3; [] ← R0 + 0, NibCarryBr, c1; BRANCH[NibCGood1, NibCBad1], c2; {Can we do a PgCarryBr? Is PageCarry stuck 0? (add test)} NibCGood1: R0 ← ~R0 xor R0, c3; [] ← R0 + 1, PgCarryBr, c1; BRANCH[PgCyBad0, PgCyGood0], c2; {Is PageCarry stuck 1? (add test)} PgCyGood0: R0 ← 0, c3; [] ← R0 + 0, PgCarryBr, c1; BRANCH[PgCyGood1, PgCyBad1], c2; {Can we do a PgCrossBr? Is PageCross stuck 0? (subtract test) Does aF.2 flip result?} PgCyGood1: R0 ← 0, c3; [] ← R0 - 1, PgCrOvDisp, c1; BRANCH[PgCBad0a, PgCGood0a, 1], c2; {Is PageCross stuck 1? (subtract test)} PgCGood0a: R0 ← 1, c3; [] ← R0 - 1, PgCrOvDisp, c1; BRANCH[PgCGood1a, PgCBad1a, 1], c2; {Is PageCross stuck 0? (add test)} PgCGood1a: R0 ← ~R0 xor R0, c3; [] ← R0 + 1, PgCrOvDisp, c1; BRANCH[PgCBad0b, PgCGood0b, 1], c2; {Is PageCross stuck 1? (add test)} PgCGood0b: R0 ← 0, c3; [] ← R0 + 0, PgCrOvDisp, c1; BRANCH[PgCGood1b, PgCBad1b, 1], c2; {Can we do a CarryBr? Is Carry stuck 0?} PgCGood1b: R0 ← ~R0 xor R0, c3; [] ← R0 + 1, CarryBr, c1; BRANCH[CarryBad0, CarryGood0], c2; {Is Carry stuck 1?} CarryGood0: R0 ← 0, c3; [] ← R0 + 0, CarryBr, c1; BRANCH[CarryGood1, CarryBad1], c2; {Can we do a XRefBr? Is X.11 stuck 0? Secondary test of constant on X.11} CarryGood1: Xbus ← 0 {precharge X}, c3; Xbus ← (~R0 xor R0) LRot0, XRefBr, c1; BRANCH[XRefBad0, XRefGood0], c2; {Is X.11 stuck 1?} XRefGood0: Xbus ← (~R0 xor R0) LRot0 {precharge X}, c3; Xbus ← 0, XRefBr, c1; BRANCH[XRefGood1, XRefBad1], c2; {Can we do a XDisp? Is X[12-15] stuck 0? Can we put a nibble onto X bus?} XRefGood1: R0 ← 0, Xbus ← 0 {precharge X}, c3; Xbus ← 0F, XDisp, c1; R1 ← R0, ZeroBr, DISP4[XDispT0], c2; XDispT0: CANCELBR[XDispBad0], c3, at[0,10]; CANCELBR[XDispBad0], c3, at[1,10,XDispT0]; CANCELBR[XDispBad0], c3, at[2,10,XDispT0]; CANCELBR[XDispBad0], c3, at[3,10,XDispT0]; CANCELBR[XDispBad0], c3, at[4,10,XDispT0]; CANCELBR[XDispBad0], c3, at[5,10,XDispT0]; CANCELBR[XDispBad0], c3, at[6,10,XDispT0]; CANCELBR[XDispBad0], c3, at[7,10,XDispT0]; CANCELBR[XDispBad0], c3, at[8,10,XDispT0]; CANCELBR[XDispBad0], c3, at[9,10,XDispT0]; CANCELBR[XDispBad0], c3, at[0A,10,XDispT0]; CANCELBR[XDispBad0], c3, at[0B,10,XDispT0]; CANCELBR[XDispBad0], c3, at[0C,10,XDispT0]; CANCELBR[XDispBad0], c3, at[0D,10,XDispT0]; CANCELBR[XDispBad0], c3, at[0E,10,XDispT0]; {Is X[12-15] stuck 1?} XDispGood0: Xbus ← 0F {precharge X}, BRANCH[XwdDisp0, $], c3, at[0F,10,XDispT0]; Xbus ← 0, XDisp, c1; R1 ← R1 + 1, DISP4[XDispT1], c2; {Is X[9,10] stuck 1?} XwdDisp0: Xbus ← 0, XwdDisp, c1; R1 ← R1 + 10, DISP4[XDispT1, 0C], c2; XDispT1: GOTO[XDispGood1], c3, at[0,10]; GOTO[XDispBad1], c3, at[1,10,XDispT1]; GOTO[XDispBad1], c3, at[2,10,XDispT1]; GOTO[XDispBad1], c3, at[3,10,XDispT1]; GOTO[XDispBad1], c3, at[4,10,XDispT1]; GOTO[XDispBad1], c3, at[5,10,XDispT1]; GOTO[XDispBad1], c3, at[6,10,XDispT1]; GOTO[XDispBad1], c3, at[7,10,XDispT1]; GOTO[XDispBad1], c3, at[8,10,XDispT1]; GOTO[XDispBad1], c3, at[9,10,XDispT1]; GOTO[XDispBad1], c3, at[0A,10,XDispT1]; GOTO[XDispBad1], c3, at[0B,10,XDispT1]; GOTO[XDispGood1], c3, at[0C,10,XDispT1]; GOTO[XDispBad1], c3, at[0D,10,XDispT1]; GOTO[XDispBad1], c3, at[0E,10,XDispT1]; GOTO[XDispBad1], c3, at[0F,10,XDispT1]; {Can we do a XwdDisp? Is X[9,10] stuck 0?} XDispGood1: Noop, c1; [] ← R0, ZeroBr, {come through here twice} c2; R0 ← ~R0 xor R0, Xbus ← 0 {precharge X}, BRANCH[XwdGood1, $], c3; Xbus ← R0 LRot0, XwdDisp, c1; [] ← R0, ZeroBr, DISP4[XDispT0, 0C], c2; {Can we do a YDisp? Is Y[12-15] stuck 0? Secondary test of nibble} XwdGood1: Ybus ← 0F, YDisp, c1; DISP4[YDispT0], c2; YDispT0: GOTO[YDispBad0], c3, at[0,10,YDispT0]; GOTO[YDispBad0], c3, at[1,10,YDispT0]; GOTO[YDispBad0], c3, at[2,10,YDispT0]; GOTO[YDispBad0], c3, at[3,10,YDispT0]; GOTO[YDispBad0], c3, at[4,10,YDispT0]; GOTO[YDispBad0], c3, at[5,10,YDispT0]; GOTO[YDispBad0], c3, at[6,10,YDispT0]; GOTO[YDispBad0], c3, at[7,10,YDispT0]; GOTO[YDispBad0], c3, at[8,10,YDispT0]; GOTO[YDispBad0], c3, at[9,10,YDispT0]; GOTO[YDispBad0], c3, at[0A,10,YDispT0]; GOTO[YDispBad0], c3, at[0B,10,YDispT0]; GOTO[YDispBad0], c3, at[0C,10,YDispT0]; GOTO[YDispBad0], c3, at[0D,10,YDispT0]; GOTO[YDispBad0], c3, at[0E,10,YDispT0]; {Is X[12-15] stuck 1?} YDispGood0: Ybus ← 0F {precharge Y}, c3, at[0F,10,YDispT0]; Ybus ← 0, YDisp, c1; DISP4[YDispT1], c2; YDispT1: Xbus ← 0 {precharge X}, GOTO[YDispGood1], c3, at[0,10,YDispT1]; GOTO[YDispBad1], c3, at[1,10,YDispT1]; GOTO[YDispBad1], c3, at[2,10,YDispT1]; GOTO[YDispBad1], c3, at[3,10,YDispT1]; GOTO[YDispBad1], c3, at[4,10,YDispT1]; GOTO[YDispBad1], c3, at[5,10,YDispT1]; GOTO[YDispBad1], c3, at[6,10,YDispT1]; GOTO[YDispBad1], c3, at[7,10,YDispT1]; GOTO[YDispBad1], c3, at[8,10,YDispT1]; GOTO[YDispBad1], c3, at[9,10,YDispT1]; GOTO[YDispBad1], c3, at[0A,10,YDispT1]; GOTO[YDispBad1], c3, at[0B,10,YDispT1]; GOTO[YDispBad1], c3, at[0C,10,YDispT1]; GOTO[YDispBad1], c3, at[0D,10,YDispT1]; GOTO[YDispBad1], c3, at[0E,10,YDispT1]; GOTO[YDispBad1], c3, at[0F,10,YDispT1]; {Can we do a XLDisp? Is X.8 stuck 0? Secondary test of constant on X.8} YDispGood1: Xbus ← (~R0 xor R0) LRot0, XLDisp, c1; BRANCH[X8Bad0, X8Good0,1], c2; {Is X.8 stuck 1?} X8Good0: Xbus ← (~R0 xor R0) LRot0 {precharge X}, c3; Xbus ← 0, XLDisp, c1; R0 ← ~R0 xor R0, BRANCH[X8Good1, X8Bad1,1], c2; {Can we do a XHDisp? Is X.0 stuck 0? Secondary test of LRot0} X8Good1: Xbus ← 0 {precharge X}, c3; Xbus ← (~R0 xor R0) LRot0, XHDisp, c1; BRANCH[X0Bad0, X0Good0,2], c2; {Is X.0 stuck 1?} X0Good0: TestCnt ← TestCnt + 1, { TestCnt=1 } c3; Xbus ← 0, XHDisp, c1; R0 ← ~R0 xor R0, BRANCH[X0Good1, X0Bad1,2], c2; {1. LRotn test & bus tests.} {These tests check for stuck at faults on either the X or Y bus; the A bypass or F bus; or the LRotn cycler. A fault on either the X,Y, F or A bus will be caught by LRot0Bad0 or LRot0Bad1.} {Is LRot0 stuck 0?} X0Good1: R2 ← (R0 LRot0), {R0 had 0FFFF} c3; R0 ← R2 xor R0, ZeroBr, c1; {Is LRot0 stuck 1?} R3 ← R0 LRot0, BRANCH[LRot0Bad1, $],{R0 = 0} c2; R1 ← R3, ZeroBr, c3; {Is RRot0 stuck 0?} R3 ← (R2 RRot1), BRANCH[LRot0Bad0, $],{R2=FFFF} c1; R2 ← R2 xor R3, ZeroBr, c2; {Is RRot0 stuck 1?} R1 ← R2 RRot1, BRANCH[RRot0Bad1, $],{R2=0} c3; [] ← R1, ZeroBr, {R3 = FFFF} c1; {Is cycleY ok?} R0 ← R3 LRot1, pCall1, BRANCH[RRot0Bad0, $], c2; [] ← R0 xor R3, ZeroBr, c3; BRANCH[LRot0YBad, $], c1; Noop, c2; {Is LRot4 stuck 0?} LRot0Good1: R2 ← (R0 LRot4), {R0 had FFFF} c3; R0 ← R2 xor R0, ZeroBr, c1; R1 ← 0, BRANCH[LRot4Bad0, LRot4Good0], c2; {Is LRot4 stuck 1?} LRot4Good0: R3 ← R1 LRot4, c3; R1 ← R3 xor R1, ZeroBr, c1; R0 ← ~R0 xor R0, BRANCH[LRot4Bad1, LRot4Good1], c2; {Is LRot8 stuck 0?} LRot4Good1: R2 ← (R0 LRot8), {R0 had FFFF} c3; R0 ← R2 xor R0, ZeroBr, c1; R1 ← 0, BRANCH[LRot8Bad0, LRot8Good0], c2; {Is LRot8 stuck 1?} LRot8Good0: R3 ← R1 LRot0, c3; R1 ← R3 xor R1, ZeroBr, c1; R0 ← ~R0 xor R0, BRANCH[LRot8Bad1, LRot8Good1], c2; {Is LRot12 stuck 0?} LRot8Good1: R2 ← (R0 LRot12), {R0 had FFFF} c3; R0 ← R2 xor R0, ZeroBr, c1; R1 ← 0, BRANCH[LRot12Bad0, LRot12Gd0], c2; {Is LRot12 stuck 1?} LRot12Gd0: R3 ← R1 LRot4, c3; R1 ← R3 xor R1, ZeroBr, c1; TestCnt ← TestCnt + 1, {TestCnt=2} BRANCH[LRot12Bad1, LRot12Gd1], c2; {2a. constant on X bus.} {Check whether Nibble and byte can place all their bits onto the X bus.} {Check that 0 thru F can be placed onto X bus. This primarily tests the S241 which places a Nibble onto Xbus. Instruction at NibTable actually tests internal zero.} LRot12Gd1: R0 ← 0, YDisp, c3; NibGood: R1 ← R0 + 1, NibCarryBr, DISP4[NibTable], c1; NibTable: R2 ← 0 xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[0, 10, NibTable]; R2 ← 1 xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[1, 10, NibTable]; R2 ← 2 xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[2, 10, NibTable]; R2 ← 3 xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[3, 10, NibTable]; R2 ← 4 xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[4, 10, NibTable]; R2 ← 5 xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[5, 10, NibTable]; R2 ← 6 xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[6, 10, NibTable]; R2 ← 7 xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[7, 10, NibTable]; R2 ← 8 xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[8, 10, NibTable]; R2 ← 9 xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[9, 10, NibTable]; R2 ← 0A xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[0A, 10, NibTable]; R2 ← 0B xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[0B, 10, NibTable]; R2 ← 0C xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[0C, 10, NibTable]; R2 ← 0D xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[0D, 10, NibTable]; R2 ← 0E xor R0, ZeroBr, BRANCH[NibLoop, NibFail], c2, at[0E, 10, NibTable]; R2 ← 0F xor R0, ZeroBr, BRANCH[NibTestFail, ByteTest], c2, at[0F, 10, NibTable]; NibLoop: R0 ← R1, YDisp, BRANCH[NibBad, NibGood], c3; NibFail: CANCELBR[NibBug], c3; NibTestFail: CANCELBR[NibBug], c3; NibBug: GOTO[NibBad], c1; {Check that 0 thru F0 (incr. by 10) can be placed onto X bus. This primarily tests the S257 which places bits 0-3 of constant onto X bus.} ByteTest: R3 ← 0, CANCELBR[ByteCont], c3; ByteCont: R3 ← R3 + 1, YDisp, c1; R2 ← R3 LRot4, DISP4[ByteTable], c2; ByteTable: R2 ← 0, GOTO[ByteLast], c3, at[0, 10, ByteTable]; R0 ← 10, GOTO[ByteLoop], c3, at[1, 10, ByteTable]; R0 ← 20, GOTO[ByteLoop], c3, at[2, 10, ByteTable]; R0 ← 30, GOTO[ByteLoop], c3, at[3, 10, ByteTable]; R0 ← 40, GOTO[ByteLoop], c3, at[4, 10, ByteTable]; R0 ← 50, GOTO[ByteLoop], c3, at[5, 10, ByteTable]; R0 ← 60, GOTO[ByteLoop], c3, at[6, 10, ByteTable]; R0 ← 70, GOTO[ByteLoop], c3, at[7, 10, ByteTable]; R0 ← 80, GOTO[ByteLoop], c3, at[8, 10, ByteTable]; R0 ← 90, GOTO[ByteLoop], c3, at[9, 10, ByteTable]; R0 ← 0A0, GOTO[ByteLoop], c3, at[0A, 10, ByteTable]; R0 ← 0B0, GOTO[ByteLoop], c3, at[0B, 10, ByteTable]; R0 ← 0C0, GOTO[ByteLoop], c3, at[0C, 10, ByteTable]; R0 ← 0D0, GOTO[ByteLoop], c3, at[0D, 10, ByteTable]; R0 ← 0E0, GOTO[ByteLoop], c3, at[0E, 10, ByteTable]; R0 ← 0F0, GOTO[ByteLoop], c3, at[0F, 10, ByteTable]; ByteLoop: R2 ← R0 xor R2, ZeroBr, c1; BRANCH[ByteBad, ByteGood], c2; ByteGood: GOTO[ByteCont], c3; ByteLast: R2 ← 0 xor R2, ZeroBr, c1; BRANCH[ByteBug, ByteDone], c2; ByteDone: TestCnt ← TestCnt + 1, { TestCnt=3 } c3; R2 ← 0, c1; R0 ← 0, GOTO[LogicTest], c2; {2.b Logic tests. Check that logical operations work with no stuck results.} {or} {Can we do "0 or 0"?} LogicTest: R1 ← ~R1 xor R1, {R0 is set to Zero in ByteTest} c3; R2 ← R0 or R2, ZeroBr, {R2 is Zero from ByteTest} c1; R3 ← ~R3 xor R3, BRANCH[S0or0Bad, S0or0Good], c2; {Can we do "0 or 1"?} S0or0Good: R2 ← R1 or R2, c3; R3 ← R3 xor R2, ZeroBr, c1; R2 ← ~R2 xor R2, BRANCH[S0or1Bad, S0or1Good], c2; {Can we do "1 or 0"?} S0or1Good: R2 ← R2 or R0, c3; R1 ← R1 xor R2, ZeroBr, c1; R0 ← ~R0 xor R0, BRANCH[S1or0Bad, S1or0Good], c2; {Can we do "1 or 1"?} S1or0Good: R2 ← R2 or R3, c3; R0 ← R0 xor R2, ZeroBr, c1; R3 ← ~R3 xor R3, BRANCH[S1or1Bad, S1or1Good], c2; {and} {Can we do "0 and 0"?} S1or1Good: R0 ← 0, c3; R0 ← R0 and R0, ZeroBr, c1; R1 ← ~R1 xor R1, BRANCH[S0and0Bad, S0and0Good], c2; {Can we do "0 and 1"?} S0and0Good: Noop, c3; R1 ← R0 and R1, ZeroBr, c1; R2 ← ~R2 xor R2, BRANCH[S0and1Bad, S0and1Good], c2; {Can we do "1 and 0"?} S0and1Good: Noop, c3; R0 ← R1 and R0, ZeroBr, c1; R1 ← ~R1 xor R1, BRANCH[S1and0Bad, S1and0Good], c2; {Can we do "1 and 1"?} S1and0Good: R3 ← R2 and R3, c3; R1 ← R1 xor R2, ZeroBr, c1; BRANCH[S1and1Bad, S1and1Good], c2; {~R and S} {Can we do "~0 and 0"?} S1and1Good: R3 ← ~R3 xor R3, c3; R2 ← ~R2 and R2, ZeroBr, { R2 had FFFF } c1; R1 ← ~R1 xor R1, BRANCH[N0and0Bad, N0and0Good], c2; {Can we do "~0 and 1"?} N0and0Good: R1 ← ~R2 and R1, c3; R3 ← R3 xor R1, ZeroBr, { R3 had FFFF } c1; R2 ← ~R2 xor R2, BRANCH[N0and1Bad, N0and1Good], c2; {Can we do "~1 and 0"?} N0and1Good: R0 ← 0, c3; R0 ← ~R1 and R0, ZeroBr, c1; R3 ← ~R3 xor R3, BRANCH[N1and0Bad, N1and0Good], c2; {Can we do "~1 and 1"?} N1and0Good: R0 ← 0, c3; R3 ← ~R2 and R3, ZeroBr, c1; R3 ← ~R3 xor R3, BRANCH[N1and1Bad, N1and1Good], c2; {xor} {Can we do "0 xor 0"?} N1and1Good: Noop, c3; R0 ← R0 xor R0, ZeroBr, {R0 had 0 } c1; R1 ← ~R1 xor R1, BRANCH[S0xor0Bad, S0xor0Good], c2; {Can we do "0 xor 1"?} S0xor0Good: R1 ← R0 xor R1, c3; R3 ← R3 xor R1, ZeroBr, c1; R2 ← ~R2 xor R2, BRANCH[S0xor1Bad, S0xor1Good], c2; {Can we do "1 xor 0"?} S0xor1Good: R0 ← R2 xor R0, c3; R1 ← R1 xor R2, ZeroBr, c1; R3 ← ~R3 xor R3, BRANCH[S1xor0Bad, S1xor0Good], c2; {Can we do "1 xor 1"?} S1xor0Good: R2 ← ~R2 xor R2, c3; R2 ← R2 xor R3, ZeroBr, c1; R1 ← ~R1 xor R1, BRANCH[S1xor1Bad, S1xor1Good], c2; {xnor} {Can we do "~0 xor 0"?} S1xor1Good: R0 ← ~R0 xor R0, c3; R1 ← R1 xor R0, ZeroBr, c1; R2 ← ~R2 xor R2, BRANCH[N0xor0Bad, N0xor0Good], c2; {Can we do "~0 xor 1"?} N0xor0Good: R0 ← 0, c3; R2 ← ~R0 xor R2, ZeroBr, c1; R1 ← ~R1 xor R1, BRANCH[N0xor1Bad, N0xor1Good], c2; {Can we do "~1 xor 0"?} N0xor1Good: Noop, c3; R0 ← ~R1 xor R0, ZeroBr, c1; BRANCH[N1xor0Bad, N1xor0Good], c2; {Can we do "~1 xor 1"?} N1xor0Good: R2 ← ~R2 xor R2, c3; R2 ← R1 xor R2, ZeroBr, c1; TestCnt ← TestCnt + 1 {TestCnt=4}, BRANCH[N1xor1Bad, N1xor1Good], c2; {2.c Shift/cycle tests.} {The single bit shifting hardware is tested in two steps: (1) internal/intra 2901 shifting and (2) external shift ends. (1) is tested by right/left shifting a solitary 1/0 through an R resister (and Q). (2) is tested by trying 0/1 ShiftEnds for each of the 4 types of long/short/shifting/cyclying. A third test compares the results of LRotn with 4n single bit shifts.} {(1): Shift a solitary 1 right throught R0, and then back left again from where it started.} N1xor1Good: R0 ← RShift1 0, SE←1, {R0←8000'x} c3; R1 ← 15'd, c1; ShiftR1Loop: R0 ← RShift1 R0, SE←0, c2; R1 ← R1 - 1, ZeroBr, c3; BRANCH[ShiftR1Loop, ShiftR1Done], c1; {R0 should be 1.} ShiftR1Done: R2 ← R0 xor 1, ZeroBr, c2; BRANCH[ShiftR1Bad, ShiftR1Good], c3; {Now start shifting Solitary 1 back to the left.} ShiftR1Good: R1 ← 15'd, c1; ShiftL1Loop: R0 ← LShift1 R0, SE←0, c2; R1 ← R1 - 1, ZeroBr, c3; BRANCH[ShiftL1Loop, ShiftL1Done], c1; {R0 should be 8000'x now.} ShiftL1Done: R2 ← RShift1 0, SE←1, c2; R2 ← R0 xor R2, ZeroBr, c3; BRANCH[ShiftL1Bad, ShiftL1Good], c1; {Now shift a solitary 0 right/left through R0.} ShiftL1Good: R0 ← RShift1 (~R0 xor R0), SE←0, {R0←7FFF'x} c2; R1 ← 15'd, c3; ShiftR0Loop: R0 ← RShift1 R0, SE←1, c1; R1 ← R1 - 1, ZeroBr, c2; BRANCH[ShiftR0Loop, ShiftR0Done], c3; {R0 should be FFFE'x.} ShiftR0Done: R2 ← ~1 xor R0, ZeroBr, c1; BRANCH[ShiftR0Bad, ShiftR0Good], c2; {Now start shifting Solitary 0 back to the left.} ShiftR0Good: R1 ← 15'd, c3; ShiftL0Loop: R0 ← LShift1 R0, SE←1, c1; R1 ← R1 - 1, ZeroBr, c2; rhR2 ← 0FF, BRANCH[ShiftL0Loop, ShiftL0Done], c3; {R0 should be 7FFF'x now.} ShiftL0Done: R2 ← RShift1 (~R2 xor R2), SE←0, c1; R2 ← R0 xor R2, ZeroBr, c2; Q ← 0, BRANCH[ShiftL0Bad, ShiftL0Good], c3; {Double Shifts, cycleX} ShiftL0Good: R2 ← RShift1 (~R2 xor R2), SE ← 0, {R2 has 7FFF} c1; R3 ← ~R2, {R3 has 8000} c2; R4 ← -2, {R4 has FFFE} c3; {DRShift1 SE=0,R=FFFE,Q=0} R5 ← DRShift1 R4, SE ← 0, {Q has 0} c1; [] ← R5 xor R2, ZeroBr, c2; [] ← R3 xor Q, ZeroBr, BRANCH[DRSftBad0, $], c3; R5 ← 1, BRANCH[DRSftBadQ1, $], c1; Q ← ~R2 xor R2, c2; {DRShift1 SE=1,R=1,Q=FFFF} R5 ← DRShift1 R5, SE ← 1, c3; [] ← R5 xor R3, ZeroBr, c1; R5 ← R2 xor Q, ZeroBr, BRANCH[DRSftBad1, $], c2; Q ← R3, BRANCH[DRSftBadQ0, $], c3; {DLShift1 R=0,Q=8000,SE=1} R5 ← DLShift1 R5, SE ← 1, c1; [] ← R5 xor 1, ZeroBr, c2; [] ← Q, ZeroBr, BRANCH[DLSftBad0, $], c3; R5 ← ~R5 xor R5, BRANCH[DLSftBadQ0, $], c1; Q ← R2, c2; {DLShift1 R=FFFF,Q=7FFF,SE=0} R5 ← DLShift1 R5, SE ← 0, c3; R5 ← R5 xor R4, ZeroBr, c1; [] ← ~Q, ZeroBr, BRANCH[DLSftBad1, $], c2; BRANCH[DLSftBadQ1, $], c3; {DALShift1 R=0,Q=FFFF,SE=1} R5 ← DALShift1 R5, SE ← 1, c1; [] ← R4 xor Q, ZeroBr, c2; Q ← R5 xor 1, ZeroBr, BRANCH[DALSftBadQ0, $], c3; R5 ← ~R5 xor R5, BRANCH[DALSftBad1, $], c1; {DALShift1 R=FFFF,Q=0,SE=0} R5 ← DALShift1 R5, SE ← 0, c2; [] ← R5 xor R4, ZeroBr, c3; R5 ← Q xor 1, ZeroBr, BRANCH[DALSftBad0, $], c1; {DARShift1 SE=1,R=0,Q=xx} R5 ← DARShift1 (R5 - R5), BRANCH[DALSftBadQ1, $], c2; [] ← R5 xor R3, ZeroBr, c3; R5 ← ~R5 xor R5, BRANCH[DARSftBad1, $], c1; {DARShift1 SE=0,R=FFFF,Q=xx} R5 ← DARShift1 (R5 + 0), c2; R5 ← R5 xor R2, ZeroBr, c3; {cycleY} Q ← 0, BRANCH[DARSftBad0, $], c1; R5 ← DRShift1 R4, SE ← 0, pCall1 {force cycleY}, c2; [] ← R5 xor R2, ZeroBr, GOTO[LRotnTest], c3; {2.d LRotn/cycle tests.} {This test places a 1 or 0 in every bit position and then LRotn's (n=0,4,8,12) it and compares the result with the same value shifted via LRot1's. R0 = 0, 4, 8, 0C for LRot0, LRot4, LRot8, LRot12 R1 = 1, 2, 4, ..., 8000 and then FFFE, FFFD, ...., 7FFF R2 = LRotn'd value of R0 R3 = LRot1'd value of R0. {R2 should always equal R3} R4 = temp} LRotnTest: R1 ← 1 {start with ..001}, BRANCH[DRZSftBad0, $], c1; NextPh: R0 ← 0, c2; NextRot: Noop, c3; R4 ← R0, YDisp, c1; R3 ← R1, DISP4[LRotn], c2; LRotn: R2 ← R1 LRot0, GOTO[L1Rot], c3, at[0,10,LRotn]; R2 ← R1 LRot4, GOTO[L1Rot], c3, at[4,10,LRotn]; R2 ← R1 LRot8, GOTO[L1Rot], c3, at[8,10,LRotn]; R2 ← R1 LRot12, GOTO[L1Rot], c3, at[0C,10,LRotn]; L1Rot: R4 ← R4 - 1, NegBr, c1; R3 ← R3, BRANCH[$, LRotComp], c2; R3 ← R3 LRot1, GOTO[L1Rot], c3; LRotComp: Noop, {Scope} c3; R2 ← R2, c1; R3 ← R3, c2; Q ← R2 {LRotn} xor R3 {LRot1}, NZeroBr, c3; R0 ← R0 + 4, NibCarryBr, BRANCH[$, BadLRot], c1; R0 ← R0 and 0F, BRANCH[NextRot, $], c2; R1 ← R1 LRot1, c3; R4 ← R1 and 7, c1; [] ← R4 xor 1, NZeroBr {have we returned to start: ..001 or ..110?}, c2; [] ← R4 xor 6, NZeroBr, BRANCH[$, LRotP2], c3; R1 ← ~R1, CANCELBR[NextPh], c1; LRotP2: BRANCH[$, Ph2Cont], c1; Noop, c2; GOTO[ArithTest], c3; Ph2Cont: GOTO[NextRot], c2; {2.e Arithmetic, intra-carry tests, Cin←pc16} {Test sum of 1010+1100 in each nibble of ALU and look for carry into next stage. Cin=0} ArithTest: R0 ← 0A, c1; R1 ← 0C, c2; Q ← R0 + R1 {Q = 0016}, c3; R2 ← 16, c1; [] ← Q xor R2, ZeroBr, c2; BRANCH[Sum12Bad, Sum12Good], c3; Sum12Good: R0 ← R0 LRot4 {R0 = 00A0}, c1; R1 ← R1 LRot4 {R1 = 00C0}, c2; Q ← R0 + R1 {Q = 0160}, c3; R2 ← R2 LRot4, c1; [] ← Q xor R2, ZeroBr, c2; BRANCH[Sum8Bad, Sum8Good], c3; Sum8Good: R0 ← R0 LRot4 {R0 = 0A00}, c1; R1 ← R1 LRot4 {R1 = 0C00}, c2; Q ← R0 + R1 {Q = 1600}, c3; R2 ← R2 LRot4, c1; [] ← Q xor R2, ZeroBr, c2; R2 ← 6, BRANCH[Sum4Bad, Sum4Good], c3; Sum4Good: R0 ← R0 LRot4 {R0 = A000}, c1; R1 ← R1 LRot4 {R1 = C000}, c2; Q ← R0 + R1, CarryBr {Q = 6000}, c3; R2 ← R2 LRot12, BRANCH[Sum0CyBd, Sum0CyGd], c1; Sum0CyGd: [] ← Q xor R2, ZeroBr, c2; BRANCH[Sum0Bad, Sum0Good], c3; {Test subtraction of 0011 - 1001 in each nibble of ALU and look for carry into next stage. Cin=1} Sum0Good: R0 ← 3, c1; R1 ← 9, c2; Q ← R0 - R1 {Q ← -6}, c3; Noop, c1; [] ← Q xor ~5, ZeroBr, c2; BRANCH[Sub12Bad, Sub12Good], c3; Sub12Good: R0 ← R0 LRot4 {R0 = 0030}, c1; R1 ← R1 LRot4 {R1=0090}, c2; Q ← R0 - R1 {Q ← FFA0}, c3; R2 ← ~5F, c1; [] ← Q xor R2, ZeroBr, c2; R2 ← 0FA, BRANCH[Sub8Bad, Sub8Good], c3; Sub8Good: R0 ← R0 LRot4 {R0 = 0300}, c1; R1 ← R1 LRot4 {R1=0900}, c2; Q ← R0 - R1 {Q ← FA00}, c3; R2 ← R2 LRot8 , c1; [] ← Q xor R2, ZeroBr, c2; R2 ← 0A, BRANCH[Sub4Bad, Sub4Good], c3; Sub4Good: R0 ← R0 LRot4 {R0 = 3000}, c1; R1 ← R1 LRot4 {R1=9000}, c2; Q ← R0 - R1 {Q ← A000}, c3; R2 ← R2 LRot12 , c1; R3 ← Q xor R2, ZeroBr, c2; BRANCH[Sub0Bad, Sub0Good], c3; {Test complete carry propagation first with Cin=1, then Cin=0.} Sub0Good: R1 ← R3 - 1 {R1←FFFF, Cin=0} {R3=0 from above} , c1; R2 ← R1 + 1 {R2←0, Cin=1}, ZeroBr, c2; BRANCH[ArithBad, ArithGood], c3; {Try Cin=pc16, XC2npcDisp. First set pc16=1.} ArithGood: XC2npcDisp, c1; R0 ← 0, BRANCH[NoFlip, Flip, 0E], c2; NoFlip: GOTO[TestCinpc16], c3; Flip: Cin ← pc16, GOTO[TestCinpc16], c3; TestCinpc16: R1 ← R0 + PC16 {pc16=1}, Xbus←rhR1 {force fXCin←pc16}, c1; R2 ← R1 xor 1, ZeroBr, c2; BRANCH[PC16OneBad, PC16OneGd], c3; PC16OneGd: R2 ← R0 + PC16 {pc16=0}, ZeroBr, pCall0 {force fZCin←pc16}, c1; TestCnt ← TestCnt + 1 {TestCnt=5}, BRANCH[PC16ZBad, PC16ZGd], c2; PC16ZGd: GOTO[CheckStkP], c3; {2.f stackP tests.} CheckStkP: stackP ← R1 ← 0F, c1; R2 ← ErrnIBnStkp and R1, ZeroBr, c2; stackP ← R2, BRANCH[StckP1Bad, $], c3; {Try all versions of push & pop} [] ← ~ErrnIBnStkp and R1, ZeroBr, {stkP=0} c1; push {fXpush}, Xbus ← 5, XRefBr, BRANCH[Stack0Bad, $], c2; push {fYpush}, rhR1 ← R1 LRot0, CANCELBR[$], c3; push {fZpush}, pCall1, MesaIntBr, {stkP = 3} c1; R3 ← ~ErrnIBnStkp and R1, CANCELBR[$] c2; [] ← R3 xor 3, ZeroBr, c3; BRANCH[StackPsBad, $], c1; fXpop, c2; fZpop, c3; push, pop, c1; R3 ← ~ErrnIBnStkp and R1, c2; [] ← R3 xor 1, ZeroBr, c3; TestCnt ← TestCnt + 1 {TestCnt=6}, BRANCH[StackPoBad, MAReffect],c1; {2.g MAR← effects (See memory test for MDR← cancelled. See ibTest for IBDisp canceled.} {Check for branch in INIA.10. High half function "0 or B".} MAReffect: R0 ← ~R0 xor R0 {R0←0FFFF}, c2; rhR1 ← 1, R1 ← 0, c3; {Before MAR: R0=FFFF, R1=0. After MAR: R1=0} MAR ← R1 ← [rhR1, R0+1], c1; BRANCH[MarPgCr1Bd, MarPgCr1Gd, 1], c2; MarPgCr1Gd: Noop, c3; Noop, c1; [] ← R1, ZeroBr {no carry into high half?}, c2; R0 ← 0, BRANCH[MarHigh0Bd, MarHigh0Gd], c3; {Before MAR: R0=0, R1=0. After MAR: R1=FF} MarHigh0Gd: MAR ← R1 ← [rhR1, R0-1], c1; BRANCH[MarPgCr0Bd, MarPgCr0Gd, 1], c2; MarPgCr0Gd: Noop, c3; R2 ← 0FF, c1; [] ← R1 xor R2, ZeroBr {no carry into high half?}, c2; TestCnt ← TestCnt + 1 {TestCnt=7}, BRANCH[MarHigh1Bd, RrhTest], c3; {3b. R & RH register test.} {Write each R & RH register with its address (R0=0) and complement of address (R0=0FFFF). "Q xor R0" is the R register address, i.e. Q holds both the address & address complement.} RrhTest: R0 ← 0, c1; uSaveTestCnt ← TestCnt, c2; WriteRAddr1: Q ← R0 {Q←0 or 0FFFF}, c3; WriteRAddr: [] ← Q xor R0, YDisp, c1; DISP4[WrRAddr], c2; WrRAddr: R0 ← Q, rhR0 ← Q LRot0, GOTO[WrRAddrL], c3, at[0,10,WrRAddr]; R1 ← Q, rhR1 ← Q LRot0, GOTO[WrRAddrL], c3, at[1,10,WrRAddr]; R2 ← Q, rhR2 ← Q LRot0, GOTO[WrRAddrL], c3, at[2,10,WrRAddr]; R3 ← Q, rhR3 ← Q LRot0, GOTO[WrRAddrL], c3, at[3,10,WrRAddr]; R4 ← Q, rhR4 ← Q LRot0, GOTO[WrRAddrL], c3, at[4,10,WrRAddr]; R5 ← Q, rhR5 ← Q LRot0, GOTO[WrRAddrL], c3, at[5,10,WrRAddr]; R6 ← Q, rhR6 ← Q LRot0, GOTO[WrRAddrL], c3, at[6,10,WrRAddr]; R7 ← Q, rhR7 ← Q LRot0, GOTO[WrRAddrL], c3, at[7,10,WrRAddr]; R8 ← Q, rhR8 ← Q LRot0, GOTO[WrRAddrL], c3, at[8,10,WrRAddr]; R9 ← Q, rhR9 ← Q LRot0, GOTO[WrRAddrL], c3, at[9,10,WrRAddr]; RA ← Q, rhRA ← Q LRot0, GOTO[WrRAddrL], c3, at[0A,10,WrRAddr]; RB ← Q, rhRB ← Q LRot0, GOTO[WrRAddrL], c3, at[0B,10,WrRAddr]; RC ← Q, rhRC ← Q LRot0, GOTO[WrRAddrL], c3, at[0C,10,WrRAddr]; RD ← Q, rhRD ← Q LRot0, GOTO[WrRAddrL], c3, at[0D,10,WrRAddr]; RE ← Q, rhRE ← Q LRot0, GOTO[WrRAddrL], c3, at[0E,10,WrRAddr]; RF ← Q, rhRF ← Q LRot0, GOTO[WrRAddrL], c3, at[0F,10,WrRAddr]; WrRAddrL: Q ← Q xor R0, c1; Q ← Q + 1, NibCarryBr, c2; Q ← Q xor R0, BRANCH[WriteRAddr, ReadRAddr1], c3; {Verify the above write. Each R reg should contain its address or ~address} ReadRAddr1: Q ← R0 {Q←0 or 0FFFF}, GOTO[ReadRAddrx], c1; ReadRAddr2: [] ← Q xor R0, YDisp, GOTO[ReadRAddrx], c1; ReadRAddrx: DISP4[RdRAddr], c2; RdRAddr: [] ← R0 xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[0,10,RdRAddr]; [] ← R1 xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[1,10,RdRAddr]; [] ← R2 xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[2,10,RdRAddr]; [] ← R3 xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[3,10,RdRAddr]; [] ← R4 xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[4,10,RdRAddr]; [] ← R5 xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[5,10,RdRAddr]; [] ← R6 xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[6,10,RdRAddr]; [] ← R7 xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[7,10,RdRAddr]; [] ← R8 xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[8,10,RdRAddr]; [] ← R9 xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[9,10,RdRAddr]; [] ← RA xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[0A,10,RdRAddr]; [] ← RB xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[0B,10,RdRAddr]; [] ← RC xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[0C,10,RdRAddr]; [] ← RD xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[0D,10,RdRAddr]; [] ← RE xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[0E,10,RdRAddr]; [] ← RF xor Q, ZeroBr, GOTO[RdRAddrL], c3, at[0F,10,RdRAddr]; {Verify the above write. Each RH reg should contain its address or ~address} RdRAddrL: [] ← Q xor R0, YDisp, BRANCH[RBad, RGood], c1; RGood: Q ← Q and 0FF, DISP4[RdRHAddr], c2; RdRHAddr: [] ← rhR0 xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[0,10,RdRHAddr]; [] ← rhR1 xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[1,10,RdRHAddr]; [] ← rhR2 xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[2,10,RdRHAddr]; [] ← rhR3 xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[3,10,RdRHAddr]; [] ← rhR4 xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[4,10,RdRHAddr]; [] ← rhR5 xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[5,10,RdRHAddr]; [] ← rhR6 xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[6,10,RdRHAddr]; [] ← rhR7 xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[7,10,RdRHAddr]; [] ← rhR8 xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[8,10,RdRHAddr]; [] ← rhR9 xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[9,10,RdRHAddr]; [] ← rhRA xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[0A,10,RdRHAddr]; [] ← rhRB xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[0B,10,RdRHAddr]; [] ← rhRC xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[0C,10,RdRHAddr]; [] ← rhRD xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[0D,10,RdRHAddr]; [] ← rhRE xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[0E,10,RdRHAddr]; [] ← rhRF xor Q, ZeroBr, GOTO[RdRHAddrL], c3, at[0F,10,RdRHAddr]; RdRHAddrL: R0 ← R0 and ~0FF, BRANCH[RHBad, RHGood], c1; RHGood: Q ← Q or R0 {restore Q to 0 or 0FFFF}, c2; R0 ← (R0 LRot8) or R0 {restore R0 to 0 or 0FFFF}, c3; Q ← Q xor R0, c1; Q ← Q + 1, NibCarryBr, c2; Q ← Q xor R0, BRANCH[ReadRAddr2, $], c3; [] ← R0, ZeroBr, c1; R0 ← ~R0 {R0←0FFFF}, BRANCH[LinkTest, WriteRAddr1], c2; {3c. Link Register tests. Write each link with address (Q=0) & ~address (Q=0FFFF). R1 holds data from link register, R0 is the address.} {Write Links with their address} LinkTest: L0 ← 0, TestCnt ← uSaveTestCnt, c3; L1 ← 1, TestCnt ← TestCnt + 1 {TestCnt=8}, c1; L2 ← 2, c2; L3 ← 3, c3; L4 ← 4, c1; L5 ← 5, c2; L6 ← 6, c3; L7 ← 7, Q ← 0, c1; R0 ← 0, GOTO[RdLAddr], c2; {Verify the above write. Each Link reg should contain its address or complement address} ReadLAddr: [] ← R0, YDisp, c1; DISP3[RdLAddr], c2; RdLAddr: L0Disp, GOTO[RdLAddrL], c3, at[0,10,RdLAddr]; L1Disp, GOTO[RdLAddrL], c3, at[1,10,RdLAddr]; L2Disp, GOTO[RdLAddrL], c3, at[2,10,RdLAddr]; L3Disp, GOTO[RdLAddrL], c3, at[3,10,RdLAddr]; L4Disp, GOTO[RdLAddrL], c3, at[4,10,RdLAddr]; L5Disp, GOTO[RdLAddrL], c3, at[5,10,RdLAddr]; L6Disp, GOTO[RdLAddrL], c3, at[6,10,RdLAddr]; L7Disp, GOTO[RdLAddrL], c3, at[7,10,RdLAddr]; RdLAddrL: DISP4[LinkValue], c1; LinkValue: R1 ← 0 , GOTO[LinkValueL], c2, at[0,10,LinkValue]; R1 ← 1 , GOTO[LinkValueL], c2, at[1,10,LinkValue]; R1 ← 2 , GOTO[LinkValueL], c2, at[2,10,LinkValue]; R1 ← 3 , GOTO[LinkValueL], c2, at[3,10,LinkValue]; R1 ← 4 , GOTO[LinkValueL], c2, at[4,10,LinkValue]; R1 ← 5 , GOTO[LinkValueL], c2, at[5,10,LinkValue]; R1 ← 6 , GOTO[LinkValueL], c2, at[6,10,LinkValue]; R1 ← 7 , GOTO[LinkValueL], c2, at[7,10,LinkValue]; R1 ← 8 , GOTO[LinkValueL], c2, at[8,10,LinkValue]; R1 ← 9 , GOTO[LinkValueL], c2, at[9,10,LinkValue]; R1 ← 0A , GOTO[LinkValueL], c2, at[0A,10,LinkValue]; R1 ← 0B , GOTO[LinkValueL], c2, at[0B,10,LinkValue]; R1 ← 0C , GOTO[LinkValueL], c2, at[0C,10,LinkValue]; R1 ← 0D , GOTO[LinkValueL], c2, at[0D,10,LinkValue]; R1 ← 0E , GOTO[LinkValueL], c2, at[0E,10,LinkValue]; R1 ← 0F , GOTO[LinkValueL], c2, at[0F,10,LinkValue]; LinkValueL: R1 ← R1 xor Q, c3; R1 ← R1 and 0F, c1; Noop, c2; [] ← R0 xor R1, ZeroBr, c3; BRANCH[LinkBad, LinkGood], c1; LinkGood: [] ← R0 xor 7, ZeroBr, c2; R0 ← R0 + 1, BRANCH[ReadLAddr, $], c3; Noop, c1; [] ← Q, ZeroBr, c2; BRANCH[UTest, WrLCAddr], c3; {WriteLinks with ~address.} WrLCAddr: Q ← ~Q {Q←0FFFF}, c1; L0 ← 0F, c2; L1 ← 0E, c3; L2 ← 0D, c1; L3 ← 0C, c2; L4 ← 0B, c3; L5 ← 0A, c1; L6 ← 9, c2; L7 ← 8, R0 ← 0, GOTO[ReadLAddr], c3; {3d. SU regs test} {Simple U reg tests. Can we write UA5 with 0's?} UTest: UA5 ← 0, CANCELBR[$, 0F], c1; [] ← UA5, ZeroBr, c2; TestCnt ← TestCnt + 1 {TestCnt=9}, BRANCH[UA5ZeroBad, UA5ZeroGd], c3; {Can we write UA5 with 1's?} UA5ZeroGd: UA5 ← ~RA xor RA, c1; [] ← ~UA5, ZeroBr, c2; BRANCH[UA5OneBad, UA5OneGd], c3; {Can we write U5A with 0's?} UA5OneGd: U5A ← 0, CANCELBR[$, 0F], c1; [] ← U5A, ZeroBr, c2; Q ← 0, BRANCH[U5AZeroBad, U5AZeroGd], c3; {Can we write U5A with 1's?} U5AZeroGd: U5A ← ~R5 xor R5, c1; [] ← ~U5A, ZeroBr, c2; R0 ← 0A, BRANCH[U5AOneBad, U5AOneGd], c3; {Can we address U5A via AltUaddr?} U5AOneGd: [] ← R0, AltUaddr, c1; [] ← ~U5, ZeroBr, c2; Q ← 0, BRANCH[U5OneBad, WriteUAddr2], c3; {Complete U reg test. Write all U regs with their addresses (Q=0) and with the inverse of their address (Q=0FFFF). R0 holds U addr.} WriteUAddr2: R0 ← 0, GOTO[WriteUAddrx] {Q=0}, c1; WriteUAddr1: R0 ← 0, GOTO[WriteUAddrx], c1; WriteUAddr: Xbus ← R0 LRot12, XDisp, c1; WriteUAddrx: R0 ← R0 xor Q, Ybus ← R0, AltUaddr, DISP4[WrUAddr], c*; WrUAddr: U0 ← R0, GOTO[WrUAddrL], c3, at[0,10,WrUAddr]; U1 ← R0, GOTO[WrUAddrL], c3, at[1,10,WrUAddr]; U2 ← R0, GOTO[WrUAddrL], c3, at[2,10,WrUAddr]; U3 ← R0, GOTO[WrUAddrL], c3, at[3,10,WrUAddr]; U4 ← R0, GOTO[WrUAddrL], c3, at[4,10,WrUAddr]; U5 ← R0, GOTO[WrUAddrL], c3, at[5,10,WrUAddr]; U6 ← R0, GOTO[WrUAddrL], c3, at[6,10,WrUAddr]; U7 ← R0, GOTO[WrUAddrL], c3, at[7,10,WrUAddr]; U8 ← R0, GOTO[WrUAddrL], c3, at[8,10,WrUAddr]; U9 ← R0, GOTO[WrUAddrL], c3, at[9,10,WrUAddr]; UA ← R0, GOTO[WrUAddrL], c3, at[0A,10,WrUAddr]; UB ← R0, GOTO[WrUAddrL], c3, at[0B,10,WrUAddr]; UC ← R0, GOTO[WrUAddrL], c3, at[0C,10,WrUAddr]; UD ← R0, GOTO[WrUAddrL], c3, at[0D,10,WrUAddr]; UE ← R0, GOTO[WrUAddrL], c3, at[0E,10,WrUAddr]; UF ← R0, GOTO[WrUAddrL], c3, at[0F,10,WrUAddr]; WrUAddrL: R0 ← R0 xor Q, c1; R0 ← R0 + 1, PgCarryBr, c2; BRANCH[WriteUAddr, ReadUAddr1], c3; {Verify the above write. Each U reg should contain its address or complement address} ReadUAddr2: CANCELBR[ReadUAddr], c3; ReadUAddr1: R0 ← 0, GOTO[ReadUAddrx], c1; ReadUAddr: Xbus ← R0 LRot12, XDisp, c1; ReadUAddrx: [] ← R0, AltUaddr, DISP4[RdUAddr], c*; RdUAddr: R1 ← U0 , GOTO[RdUAddrL], c3, at[0,10,RdUAddr]; R1 ← U1 , GOTO[RdUAddrL], c3, at[1,10,RdUAddr]; R1 ← U2 , GOTO[RdUAddrL], c3, at[2,10,RdUAddr]; R1 ← U3 , GOTO[RdUAddrL], c3, at[3,10,RdUAddr]; R1 ← U4 , GOTO[RdUAddrL], c3, at[4,10,RdUAddr]; R1 ← U5 , GOTO[RdUAddrL], c3, at[5,10,RdUAddr]; R1 ← U6 , GOTO[RdUAddrL], c3, at[6,10,RdUAddr]; R1 ← U7 , GOTO[RdUAddrL], c3, at[7,10,RdUAddr]; R1 ← U8 , GOTO[RdUAddrL], c3, at[8,10,RdUAddr]; R1 ← U9 , GOTO[RdUAddrL], c3, at[9,10,RdUAddr]; R1 ← UA , GOTO[RdUAddrL], c3, at[0A,10,RdUAddr]; R1 ← UB , GOTO[RdUAddrL], c3, at[0B,10,RdUAddr]; R1 ← UC , GOTO[RdUAddrL], c3, at[0C,10,RdUAddr]; R1 ← UD , GOTO[RdUAddrL], c3, at[0D,10,RdUAddr]; R1 ← UE , GOTO[RdUAddrL], c3, at[0E,10,RdUAddr]; R1 ← UF , GOTO[RdUAddrL], c3, at[0F,10,RdUAddr]; RdUAddrL: R1 ← R1 xor Q, c1; [] ← R1 xor R0, ZeroBr, c2; BRANCH[UBad, UGood], c3; UGood: R0 ← R0 + 1, PgCarryBr, c1; [] ← Q, ZeroBr, BRANCH[ReadUAddr2, $], c2; Q ← ~Q, BRANCH[STKtst, WriteUAddr1], c3; {check stackP addressing. Read low 16 U registers via stackP} STKtst: R0 ← stackP ← 0, c1; STKLp: Noop, c2; Xbus ← 0 {precharge X}, c3; Q ← ~STK xor R0, NZeroBr, c1; R0 ← R0 + 1, NibCarryBr, BRANCH[$, STKAddrBad], c2; BRANCH[$, MemTest], c3; push, GOTO[STKLp], c1; {3e. Memory tests.} {Simple memory testing} MemTest: R0 ← 5, c1; rhR0 ← 1, c2; TestCnt ← TestCnt + 1 {TestCnt=0A}, c3; MemTestZeros: MAR ← [rhR0, R0+0], c1; MDR ← 0, c2; Noop, c3; MAR ← [rhR0, R0+0], c1; Noop, c2; R1 ← MD, c3; [] ← R1, ZeroBr, c1; BRANCH[MDNotZero, $], c2; R3 ← R3 xor ~R3, c3; MemTestOnes: MAR ← [rhR0, R0+0], c1; MDR ← R3, c2; Noop, c3; MAR ← [rhR0, R0+0], c1; Noop, c2; R1 ← MD, c3; [] ← R1 xor R3, ZeroBr, c1; BRANCH[MDNotOnes, $], c2; R4 ← R0+0FF, c3; {Simple MAR operation} {Does page cross cancel write?} MarCrossCancel: MAR ← [rhR0, R4-0FF], c1; MDR ← 0F, CANCELBR[$, 2], LOOPHOLE[wok],c2; Noop, c3; MAR ← [rhR0, R0+0], c1; Noop, c2; R1 ← MD, c3; [] ← R1 xor R3, ZeroBr, c1; BRANCH[MDRCanBad, $], c2; GOTO[MapTest], c3; {Simple Map operation} MapTest: Map ← [rhR0, R0] {Map[100]}, c1; MDR ← 2, c2; Noop, c3; Map ← [rhR0, R0], c1; Noop, c2; R1 ← MD, c3; [] ← R1 xor 2, ZeroBr, c1; R0 ← 0FF+1, BRANCH[SimMapBad, $], c2; rhR0 ← 1, c3; MAR ← [rhR0, R0+0] {Map[100]}, c1; Noop, c2; R1 ← MD, c3; [] ← R1 xor 2, ZeroBr, c1; BRANCH[SimMMBad, $], c2; GOTO[ibTests], c3; {4.0 IB tests} Set[Full, 2]; Set[Word,3]; Set[Byte,1]; Set[Empty,0]; {IBPtr←0 should set ibPtr to Word.} ibTests: TestCnt ← TestCnt + 1 {TestCnt=0B}, c1; IBPtr←0, c2; R1 ← ~ErrnIBnStkp, c3; R1 ← R1 LRot12, c1; R1 ← R1 and 3, c2; R2 ← R1 xor Word, ZeroBr, c3; BRANCH[IBPtr0Bad, IBPtr0Good], c1; {IBPtr←1 should set ibPtr to Byte.} IBPtr0Good: IBPtr←1, c2; R1 ← ~ErrnIBnStkp, c3; R1 ← R1 LRot12, c1; R1 ← R1 and 3, c2; R2 ← R1 xor Byte, ZeroBr, c3; BRANCH[IBPtr1Bad, IBPtr1Good], c1; {Load IB with 2 bytes (0ABCD) & read each of them (twice) via IBPtr←n} IBPtr1Good: R1 ← 0AB, c2; R1 ← R1 LRot8, c3; R1 ← R1 or 0CD {R1 ← 0ABCD}, c1; IB ← R1 LRot0, c2; IBPtr ← 0 {ibFront←0AB}, c3; R2 ← 0AB, c1; Xbus ← 54 {precharge X}, c2; R3 ← ibNA xor R2, ZeroBr, c3; R3 ← ibNA xor R2, ZeroBr, BRANCH[IBLeftaBad, IBLeftaGood], c1; IBLeftaGood: R2 ← 0CD, BRANCH[IBLeftbBad, IBLeftbGood], c2; IBLeftbGood: IBPtr ← 1 {ibFront←0CD}, c3; Xbus ← 32 {precharge X}, c1; R3 ← ibNA xor R2, ZeroBr, c2; R3 ← ibNA xor R2, ZeroBr, BRANCH[IBRaBad, IBRaGood], c3; IBRaGood: R2 ← 0C, BRANCH[IBRbBad, IBRbGood], c1; {Try ibLow & ibHigh} IBRbGood: Xbus ← 3 {precharge X}, c2; R4 ← ibHigh xor R2, ZeroBr, c3; R2 ← 0D, BRANCH[IBHighBad, IBHighGood], c1; IBHighGood: Xbus ← 2 {precharge X}, c2; R4 ← ibLow xor R2, ZeroBr, c3; BRANCH[IBLowBad, IBLowGood], c1; {PageCross should cancel IBDisp and AlwaysIBDisp. ibPtr should still be Byte} IBLowGood: rhR0 ← 1, c2; R0 ← 0, c3; MAR ← [rhR0, R0-1], c1; IBDisp, CANCELBR[$,2], c2; Noop, c3; MAR ← [rhR0, R0-1], c1; AlwaysIBDisp, CANCELBR[$,2], c2; R2 ← ~ErrnIBnStkp, c3; R2 ← R2 LRot12, c1; R2 ← R2 and 3, c2; R3 ← R2 xor Byte, ZeroBr, c3; BRANCH[IBPtr1xBad, IBPtr1xGood], c1; {Try a Not-Empty refill trap (loc 500) via IBPtr←0. R4 must be 5 at loc 500} IBPtr1xGood: IBPtr ← 0, c2; R4 ← 5, c3; ClrIntErr {clear a possible MInt}, c1; IBDisp {should trap}, c2; GOTO[IBNullTable], c3; NETrap: R3 ← R4 xor 5, ZeroBr, c1, at[500]; BRANCH[NETrapBad, NETrapGood], c2; {Load IB with 4 bytes (0ABCD 5432), execute 3 ←ib's and an IBDisp which should do an Empty refill trap (loc 400). R4 must be a 4 at loc 400)} NETrapGood: IB ← R1 LRot0 {IB ← 0ABCD}, c3; IBPtr←0, R1 ← ~R1 {R1 ← 5432}, c1; R4 ← 4, c2; R2 ← 0AB, c3; Xbus ← 54 {precharge X}, c1; R3 ← ib xor R2, ZeroBr, c2; IB ← R1 LRot0, BRANCH[IBaBad, IBaGood], c3; IBaGood: R2 ← 0CD, c1; R3 ← ib xor R2, ZeroBr, c2; BRANCH[IBbBad, IBbGood], c3; IBbGood: R2 ← 54, c1; R3 ← ib xor R2, ZeroBr, c2; BRANCH[IBcBad, IBcGood], c3; IBcGood: R2 ← 32, c1; R3 ← ib xor R2, ZeroBr {buffer empty now}, c2; BRANCH[IBdBad, IBdGood], c3; IBdGood: ClrIntErr {clear a possible MInt}, c1; IBDisp {should trap}, c2; GOTO[IBNullTable], c3; ETrap: R3 ← R4 xor 4, ZeroBr, c1, at[400]; BRANCH[ETrapBad, ETrapGood], c2; {Try an MInt trap (on an empty buffer)} ETrapGood: MesaIntRq, c3; R4 ← 6 {buffer is still empty}, c1; IBDisp {should trap}, c2; GOTO[IBNullTable], c3; NEMIntTrap: GOTO[EMTrapBad], c1, at[700]; EMIntTrap: R3 ← R4 xor 6, ZeroBr, c1, at[600]; R2 ← 0AA, BRANCH[EMTrapBad, EMTrapG], c2; {Try an AlwaysIBDisp to 0AF (with MInt ON)} EMTrapG: IB ← R2 LRot0, c3; R4 ← R4+0, IBPtr ← 1, c1; AlwaysIBDisp, c2; R4 ← 0,ClrIntErr, GOTO[IBTable0F], c3; {Try an IBDisp to 05F} IBDispaG: R2 ← 22, c2; R2 ← R2 LRot8, c3; R2 ← R2 or 55, c1; IB ← R2 LRot0 {IB←2255}, c2; R2 ← R2 or 77, c3; IBPtr ← 0, c1; Xbus ← ib, c2; IB ← ~R2 LRot0 {IB←DD88}, c3; R4 ← 0+0, c1; IBDisp, c2; GOTO[IBTable0F], c3; {Try an AlwaysIBDisp to 0FA} IBDispbG: R2 ← 0FA, c2; IB ← R2 LRot0, c3; R4 ← R4+0, IBPtr ← 1, c1; AlwaysIBDisp, c2; R4 ← 0, GOTO[IBTableF0], c3; {Try an AlwaysIBDisp to 0F5} IBDispcG: R2 ← 0F5, c2; IB ← R2 LRot8, c3; R4 ← R4+0, IBPtr ← 0, c1; AlwaysIBDisp, c2; R4 ← 0, GOTO[IBTableF0], c3; IBNullTable: Noop, GOTO[IBTrapBad], c1, at[800]; {Extra landing places for Dicentra: The low 4 bits of NIA don't get ORed in} GOTO[IBDispaG], c1, at[8AA]; GOTO[IBDispbG], c1, at[855]; GOTO[IBDispcG], c1, at[9AA]; GOTO[IBDispdG], c1, at[955]; IBTable0F: GOTO[IBDispabBad], c1, at[80F]; GOTO[IBDispabBad], c1, at[81F]; GOTO[IBDispabBad], c1, at[82F]; GOTO[IBDispabBad], c1, at[83F]; GOTO[IBDispabBad], c1, at[84F]; GOTO[IBDispbG], c1, at[85F]; GOTO[IBDispabBad], c1, at[86F]; GOTO[IBDispabBad], c1, at[87F]; GOTO[IBDispabBad], c1, at[88F]; GOTO[IBDispabBad], c1, at[89F]; GOTO[IBDispaG], c1, at[8AF]; GOTO[IBDispabBad], c1, at[8BF]; GOTO[IBDispabBad], c1, at[8CF]; GOTO[IBDispabBad], c1, at[8DF]; GOTO[IBDispabBad], c1, at[8EF]; IBTableF0: GOTO[IBDispcdBad], c1, at[9F0]; GOTO[IBDispcdBad], c1, at[9F1]; GOTO[IBDispcdBad], c1, at[9F2]; GOTO[IBDispcdBad], c1, at[9F3]; GOTO[IBDispcdBad], c1, at[9F4]; GOTO[IBDispdG], c1, at[9F5]; GOTO[IBDispcdBad], c1, at[9F6]; GOTO[IBDispcdBad], c1, at[9F7]; GOTO[IBDispcdBad], c1, at[9F8]; GOTO[IBDispcdBad], c1, at[9F9]; GOTO[IBDispcG], c1, at[9FA]; GOTO[IBDispcdBad], c1, at[9FB]; GOTO[IBDispcdBad], c1, at[9FC]; GOTO[IBDispcdBad], c1, at[9FD]; GOTO[IBDispcdBad], c1, at[9FE]; GOTO[IBDispcdBad], c1, at[9FF]; IBDispdG: Noop, c2; TestCnt ← TestCnt + 1 {TestCnt=0C}, GOTO[TrapTest], c3; {5. Microcode trap tests} Set[StkOVF, 0F]; Trap: R1 ← RRot1 ErrnIBnStkp, ClrIntErr, CANCELBR[$, 0F], c1, at[0]; Xbus ← R1 LRot0, XwdDisp, c2; DISP2[TrapType], c3; {Should never get CS Parity Err} Parity: GOTO[CSPar], c1, at[0,4,TrapType]; Init: GOTO[NotCSPar], c1, at[1,4,TrapType]; Stack: GOTO[NotCSPar], c1, at[2,4,TrapType]; IB: GOTO[NotCSPar], c1, at[3,4,TrapType]; NotCSPar: R7 ← UA5, c2; R7 ← R7 xor 0E2, c3; {Which Trap Test are we doing?} [] ← R7, NZeroBr, c1; [] ← R0 xor 0, ZeroBr, BRANCH[$, BadTrapB], c2; [] ← R0 xor 1, ZeroBr, BRANCH[$, StkSimUF], c3; [] ← R0 xor 2, ZeroBr, BRANCH[$, StkSim2UF], c1; [] ← R0 xor 3, ZeroBr, BRANCH[$, Stk2UF], c2; [] ← R0 xor 4, ZeroBr, BRANCH[$, StkOF], c3; [] ← R0 xor 5, ZeroBr, BRANCH[$, StkOFp] c1; Ybus ← R0 xor 6, BRANCH[$, StkEReg], c2; Ybus ← R0 xor 7, c3; Ybus ← R0 xor 8, c1; [] ← R0 xor 9, ZeroBr, c2; [] ← R0 xor 0A, ZeroBr, BRANCH[$, IBTestc2], c3; BRANCH[BadTrapA, IBEReg], c1; {Set UA5 to E2 to indicate legit trap through 0} TrapTest: R0 ← 0E2, c1; UA5 ← R0, c2; R0 ← 0, c3; {Stack Pointer overflow & underflow tests} StkUF: stackP ← 0, c1; pop, GOTO[WaitTrapc3], c2, at[0F,10]; StkSimUF: stackP ← 0, CANCELBR[$], c1; R0 ← 1, fXpop, push, GOTO[WaitTrapc3], c2; StkSim2UF: stackP ← 1, CANCELBR[$], c2; R0 ← 2, c3; fXpop, fZpop, push, GOTO[WaitTrapc2], c1; Stk2UF: stackP ← 1, CANCELBR[$], c3; R0 ← 3, c1; fXpop, fZpop, GOTO[WaitTrapc3], c2; StkOF: stackP ← StkOVF, CANCELBR[$], c1; R0 ← 4, push, GOTO[WaitTrapc3], c2; StkOFp: stackP ← StkOVF, CANCELBR[$], c2; R0 ← 5, c3; push, fZpop, GOTO[WaitTrapc2], c1; {Does Error register really say stackP error?} StkEReg: Xbus ← R1 LRot0, XwdDisp, CANCELBR[$], c3; DISP2[StkEE], c1; StkEE: GOTO[ErrRStkp], c2, at[0,4,StkEE]; GOTO[ErrRStkp], c2, at[1,4,StkEE]; rhR2 ← R2 ← 1, GOTO[MemF], c2, at[2,4,StkEE]; {EKErr=2 on stackP err} GOTO[ErrRStkp] c2, at[3,4,StkEE]; MemF: IBPtr←1, c3; { Used to test mem stuff} {IBEmpty error NOT in c1} IBTestc1: Xbus ← ib, {IB empty now} c1; R0←9, c2; Xbus ← ib, GOTO[WaitTrapc1], c3; {IBEmpty error in c1. Should cancel mem write.} IBTestc2: MAR ← [rhR2, R2+0], CANCELBR[$], c1; MDR ← 0, c2; R0 ← 0A, c3; MAR ← [rhR2, R2+0], Xbus ← ib, c1; MDR ← 0FF, GOTO[FastTrapc3], c2; {Does Error register really say IBEmpty error?} IBEReg: Xbus ← R1 LRot0, XwdDisp, CANCELBR[$], c2; DISP2[IBEE], c3; IBEE: GOTO[ErrRibEm], c1, at[0,4,IBEE]; GOTO[ErrRibEm], c1, at[1,4,IBEE]; GOTO[ErrRibEm], c1, at[2,4,IBEE]; {reset Trap-test indicators} Noop, {EKErr=3 on IBEmpty err} c1, at[3,4,IBEE]; UA5 ← 0, c2; R0 ← 0E, c3; {was mem write canceled? Loc 1 should be 0} MAR ← [rhR2, R2+0], c1; Noop, c2; R3 ← MD, c3; [] ← R3, ZeroBr, c1; BRANCH[IBEMemW, CritTime], c2; {Wait a click for ErrorProm to decode error} WaitTrapc2: Noop, c2; WaitTrapc3: Noop, c3; WaitTrapc1: Noop, c1; Noop, c2; FastTrapc3: Noop, c3; GOTO[DidntTrap], {trap should happen by now} c1; {6. Test those X bus operations which have large (>134 nS) cycle times} CritTime: TestCnt ← TestCnt + 1 {=0D}, c3; {[]←U or R, ZeroBr} U5A ← 0, c1; UA5 ← ~RA xor RA, c2; [] ← U5A xor 0, ZeroBr, c3; {[]←U or R, NegBr} BRANCH[UZeroBrBad, $], c1; UNeg: Ybus ← U5A, c2; [] ← UA5 xor 0, NegBr, c3; BRANCH[UNegBrBad, $], c1; UStkp: stackP ← 0, c2; stackP ← UA5 xor 0, c3; {stackP ← U or R} R0 ← ErrnIBnStkp, c1; R0 ← R0 and 0F, c2; [] ← R0, ZeroBr, c3; BRANCH[UstkpBad, $], c1; URot: R0 ← 0F, c2; U5A ← R0, c3; {R ← Rot1 U} R1 ← LRot1 U5A, c1; UA5 ← R1, c2; R2 ← RRot1 UA5, c3; [] ← R2 xor 0F, ZeroBr, c1; BRANCH[URot1Bad, $], c2; UPage: R0 ← 2, c3; {R ← U + R, PgCarryBr, LOOPHOLE[byte]} UA5 ← R0, c1; RA ← 0FE, c2; Xbus ← U5A, c3; [] ← RA + UA5, PgCarryBr, LOOPHOLE[byteTiming], c1; MemNib: rhR0 ← 1, BRANCH[UByPgCyBad, $], c2; R0 ← 5, c3; {R ← MD + R, LOOPHOLE[Nibble]; MDR ← byte} MAR ← [rhR0, R0+0], c1; MDR ← 0FD, c2; Noop, c3; MAR ← [rhR0, R0+0], c1; R1 ← 4, c2; R2 ← MD + R1, LOOPHOLE[niblTiming], c3; R2 ← R2 and 0F, c1; R2 ← R2 xor 1, ZeroBr, c2; R4 ← 0, BRANCH[MNibByBad, $], c3; {"Freeze" test: check U reg access and D-input to F=0 output. Loop 256 times.} rhR0 ← R0 ← 1, c1; RD ← 0AA, c2; RD ← (RD LRot8) or RD, c3; MAR ← [rhR0, R0+0], c1; MDR ← RD {MDR←0AAAA}, c2; RD ← uD0 ← ~RD {rd←5555}, c3; UFZeroT: MAR ← [rhR0, R0+0], IBPtr←1, c1; Noop, c2; IB ← MD {MD=0AAAA}, c3; Ybus ← RD xor uD0, NZeroBr, c1; R4 ← R4 + 1, PgCarryBr, BRANCH[$, UFZeroBad], c2; BRANCH[UFZeroT, $], c3; {R ← RH + R, PgCarryBr, LOOPHOLE[Byte]} rhPage: rhR0 ← 0FC, c1; R0 ← 5, c2; Xbus ← rhRF, c3; R0 ← rhR0 + R0, PgCarryBr, LOOPHOLE[byteTiming], c1; R0 ← R0 and 0FF, BRANCH[RHByPgBad, $], c2; [] ← R0 xor 1, ZeroBr, c3; {[] ← R + Byte, CarryBr} BRANCH[RHByArBad, $], c1; ByCarry: R0 ← R0 xor ~R0, c2; R1 ← R0 + 0F, CarryBr, c3; BRANCH[ByCyBrBad, $], c1; GOTO[EndTests], c2; {Pass number in upper 8 bits of TestCnt, "0D" in low half.} EndTests: R1 ← TestCnt and 0F, c3; [] ← R1 xor 0D, ZeroBr, c1; TestCnt ← TestCnt and ~0F, BRANCH[TestSeqErr, $], c2; TestCnt ← TestCnt + 0FF + 1, c3; Noop, c1; [] ← TestCnt, ZeroBr, c2; BRANCH[More, BumpMP], c3; BumpMP: Noop, c1; ExtCtrl ← 3, {Gets Bumped on rising edge} c2; ExtCtrl ← 7, c3; More: GOTO[bt1], c1; {Bad breakpoints} BranchBad: RErr ← 1, GOTO[Error], c*; C2Bad0: RErr ← 2, GOTO[Error], c*; C2Bad1: RErr ← 3, GOTO[Error], c*; NegBad0: RErr ← 4, GOTO[Error], c*; NegBad1: RErr ← 5, GOTO[Error], c*; ZeroBad0: RErr ← 6, GOTO[Error], c*; ZeroBad1: RErr ← 7, GOTO[Error], c*; NZeroBad0: RErr ← 8, GOTO[Error], c*; NZeroBad1: RErr ← 9, GOTO[Error], c*; OvBad0: RErr ← 0A, GOTO[Error], c*; OvBad1: RErr ← 0B, GOTO[Error], c*; MIBad0: RErr ← 0C, GOTO[Error], c*; MIBad1: RErr ← 0D, GOTO[Error], c*; R0ZeroBad: RErr ← 0E, GOTO[Error], c*; R0OneBad: RErr ← 0F, GOTO[Error], c*; QZeroBad: RErr ← 10, GOTO[Error], c*; QOneBad: RErr ← 11, GOTO[Error], c*; NibCBad0: RErr ← 12, GOTO[Error], c*; NibCBad1: RErr ← 13, GOTO[Error], c*; PgCyBad0: RErr ← 14, GOTO[Error], c*; PgCyBad1: RErr ← 15, GOTO[Error], c*; PgCBad0a: RErr ← 16, GOTO[Error], c*; PgCBad1a: RErr ← 17, GOTO[Error], c*; PgCBad0b: RErr ← 18, GOTO[Error], c*; PgCBad1b: RErr ← 19, GOTO[Error], c*; CarryBad0: RErr ← 1A, GOTO[Error], c*; CarryBad1: RErr ← 1B, GOTO[Error], c*; XRefBad0: RErr ← 1C, GOTO[Error], c*; XRefBad1: RErr ← 1D, GOTO[Error], c*; XDispBad0: RErr ← 1E, GOTO[Error], c*; XDispBad1: RErr ← 1F, GOTO[Error], c*; YDispBad0: RErr ← 20, GOTO[Error], c*; YDispBad1: RErr ← 21, GOTO[Error], c*; X8Bad0: RErr ← 22, GOTO[Error], c*; X8Bad1: RErr ← 23, GOTO[Error], c*; X0Bad0: RErr ← 24, GOTO[Error], c*; X0Bad1: RErr ← 25, GOTO[Error], c*; LRot0Bad1: RErr ← 26, GOTO[Error], c*; LRot0Bad0: RErr ← 27, GOTO[Error], c*; RRot0Bad1: RErr ← 28, GOTO[Error], c*; RRot0Bad0: RErr ← 29, GOTO[Error], c*; LRot0YBad: RErr ← 2A, GOTO[Error], c*; LRot4Bad0: RErr ← 2B, GOTO[Error], c*; LRot4Bad1: RErr ← 2C, GOTO[Error], c*; LRot8Bad0: RErr ← 2D, GOTO[Error], c*; LRot8Bad1: RErr ← 2E, GOTO[Error], c*; LRot12Bad0: RErr ← 2F, GOTO[Error], c*; LRot12Bad1: RErr ← 30, GOTO[Error], c*; {R0 contains the intented value, x} NibBad: RErr ← 31, CANCELBR[Error], c*; {x} ByteBad: RErr ← 32, CANCELBR[Error], c*; ByteBug: RErr ← 33, GOTO[Error], c*; S0or0Bad: RErr ← 34, GOTO[Error], c*; S0or1Bad: RErr ← 35, GOTO[Error], c*; S1or0Bad: RErr ← 36, GOTO[Error], c*; S1or1Bad: RErr ← 37, GOTO[Error], c*; S0and0Bad: RErr ← 38, GOTO[Error], c*; S0and1Bad: RErr ← 39, GOTO[Error], c*; S1and0Bad: RErr ← 3A, GOTO[Error], c*; S1and1Bad: RErr ← 3B, GOTO[Error], c*; N0and0Bad: RErr ← 3C, GOTO[Error], c*; N0and1Bad: RErr ← 3D, GOTO[Error], c*; N1and0Bad: RErr ← 3E, GOTO[Error], c*; N1and1Bad: RErr ← 3F, GOTO[Error], c*; S0xor0Bad: RErr ← 40, GOTO[Error], c*; S0xor1Bad: RErr ← 41, GOTO[Error], c*; S1xor0Bad: RErr ← 42, GOTO[Error], c*; S1xor1Bad: RErr ← 43, GOTO[Error], c*; N0xor0Bad: RErr ← 44, GOTO[Error], c*; N0xor1Bad: RErr ← 45, GOTO[Error], c*; N1xor0Bad: RErr ← 46, GOTO[Error], c*; N1xor1Bad: RErr ← 47, GOTO[Error], c*; Sum12Bad: RErr ← 48, GOTO[Error], c*; Sum8Bad: RErr ← 49, GOTO[Error], c*; Sum4Bad: RErr ← 4A, GOTO[Error], c*; Sum0Bad: RErr ← 4B, GOTO[Error], c*; Sum0CyBd: RErr ← 4C, GOTO[Error], c*; Sub12Bad: RErr ← 4D, GOTO[Error], c*; Sub8Bad: RErr ← 4E, GOTO[Error], c*; Sub4Bad: RErr ← 4F, GOTO[Error], c*; Sub0Bad: RErr ← 50, GOTO[Error], c*; ArithBad: RErr ← 51, GOTO[Error], c*; PC16OneBad: RErr ← 52, GOTO[Error], c*; PC16ZBad: RErr ← 53, GOTO[Error], c*; MarPgCr1Bd: RErr ← 54, GOTO[Error], c*; MarHigh0Bd: RErr ← 55, GOTO[Error], c*; MarPgCr0Bd: RErr ← 56, GOTO[Error], c*; MarHigh1Bd: RErr ← 57, GOTO[Error], c*; ShiftR1Bad: RErr ← 58, GOTO[Error], c*; ShiftL1Bad: RErr ← 59, GOTO[Error], c*; ShiftR0Bad: RErr ← 5A, GOTO[Error], c*; ShiftL0Bad: RErr ← 5B, GOTO[Error], c*; StckP1Bad: RErr ← 5C, CANCELBR[Error], c*; Stack0Bad: RErr ← 5D, CANCELBR[Error], c*; StackPsBad: RErr ← 5E, CANCELBR[Error], c*; StackPoBad: RErr ← 5F, CANCELBR[Error], c*; DRSftBad0: RErr ← 60, CANCELBR[Error], c1; DRSftBadQ1: RErr ← 61, CANCELBR[Error], c*; DRSftBad1: RErr ← 62, CANCELBR[Error], c3; DRSftBadQ0: RErr ← 63, CANCELBR[Error], c1; DLSftBad0: RErr ← 64, CANCELBR[Error], c1; DLSftBadQ1: RErr ← 65, CANCELBR[Error], c1; DLSftBad1: RErr ← 66, CANCELBR[Error], c3; DLSftBadQ0: RErr ← 67, CANCELBR[Error], c*; DALSftBadQ0: RErr ← 68, CANCELBR[Error], c*; DALSftBad1: RErr ← 69, CANCELBR[Error], c*; DALSftBad0: RErr ← 70, CANCELBR[Error], c*; DALSftBadQ1: RErr ← 71, CANCELBR[Error], c*; DARSftBad0: RErr ← 72, GOTO[Error], c*; DARSftBad1: RErr ← 73, GOTO[Error], c*; DRZSftBad0: RErr ← 74, CANCELBR[Error], c*; {R1 has the data what was LRot'd incorrectly, R0 = n for LRotn, R2 has the LRotn'd value, and R3 has the value as rotated by LRot1's} BadLRot: RErr ← 0AF, CANCELBR[Error], c*; {R0 contains the U reg address, R1 contains the data from the U reg (or compl of data if Q=0FFF} UBad: RErr ← 75, GOTO[Error], c1; U5OneBad: RErr ← 76, GOTO[Error], c*; UA5ZeroBad: RErr ← 77, GOTO[Error], c*; UA5OneBad: RErr ← 78, GOTO[Error], c*; U5AOneBad: RErr ← 79, GOTO[Error], c*; U5AZeroBad: RErr ← 7A, GOTO[Error], c*; STKAddrBad: RErr ← 0B0, CANCELBR[Error], c*; {Q holds the R register address (or ~Q if R0=0FFFF).} RBad: RErr ← 7B, CANCELBR[Error, 0F], c*; {Q holds the RH register address (or ~Q if R0=0FFFF).} RHBad: RErr ← 7C, GOTO[Error], c*; {R0 is the link address. R1 holds the contents of the Link reg.} LinkBad: RErr ← 7D, GOTO[Error], c*; {Simple mem tests.} MDNotZero: RErr ← 7E, GOTO[Error], c*; MDNotOnes: RErr ← 0B2, GOTO[Error], c*; MDRCanBad: RErr ← 7F, GOTO[Error], c*; SimMapBad: RErr ← 80, GOTO[Error], c*; SimMMBad: RErr ← 0A1, GOTO[Error], c*; MStatBad0: RErr ← 81, GOTO[Error], c*; MStatBad1: RErr ← 82, GOTO[Error], c*; {Bad ib breaks} IBPtr0Bad: RErr ← 83, GOTO[Error], c*; IBPtr1Bad: RErr ← 84, GOTO[Error], c*; IBLeftaBad: RErr ← 85, CANCELBR[Error], c2; IBLeftbBad: RErr ← 86, GOTO[Error], c3; IBRaBad: RErr ← 87, CANCELBR[Error], c*; IBRbBad: RErr ← 88, GOTO[Error], c*; IBHighBad: RErr ← 89, GOTO[Error], c*; IBLowBad: RErr ← 8A, GOTO[Error], c*; IBPtr1xBad: RErr ← 8B, GOTO[Error], c*; NETrapBad: RErr ← 8C, GOTO[Error], c*; IBaBad: RErr ← 8D, GOTO[Error], c*; IBbBad: RErr ← 8E, GOTO[Error], c*; IBcBad: RErr ← 8F, GOTO[Error], c*; IBdBad: RErr ← 90, GOTO[Error], c*; ETrapBad: RErr ← 91, GOTO[Error], c*; EMTrapBad: RErr ← 92, GOTO[Error], c*; IBEmptyBad: RErr ← 93, GOTO[Error], c*; IBDispaBad: RErr ← 94, GOTO[Error], c*; IBDispbBad: RErr ← 95, GOTO[Error], c*; IBDispcBad: RErr ← 96, GOTO[Error], c*; IBDispdBad: RErr ← 97, GOTO[Error], c*; IBDispabBad: RErr ← 98, GOTO[Error], c*; IBDispcdBad: RErr ← 99, GOTO[Error], c*; IBTrapBad: RErr ← 9A, GOTO[Error], c*; {trap test which failed is in R0. If R0 is not in [0..x] & UA5 does not equal 0E2, control reached Loc 0 not during the trap test.} BadTrapA: RErr←9B, GOTO[Error], c*; BadTrapB: RErr←0AC, CANCELBR[Error], c*; DidntTrap: RErr←0AD, GOTO[Error], c*; ErrRStkp: RErr←9C, GOTO[Error], c*; {ErrRVirt: RErr←9D, GOTO[Error], c*; Removed Rev O} ErrRMem: RErr←9E, GOTO[Error], c*; ErrRibEm: RErr←9F, GOTO[Error], c*; IBEMemW: RErr←0A0, GOTO[Error], c*; CSPar: RErr←0AE, GOTO[Error], c*; {Bad Timing Test Breaks} UZeroBrBad: RErr←0A2, GOTO[Error], c*; UNegBrBad: RErr←0A3, GOTO[Error], c*; UstkpBad: RErr←0A4, GOTO[Error], c*; URot1Bad: RErr←0A5, GOTO[Error], c*; UByPgCyBad: RErr←0A6, GOTO[Error], c*; MNibByBad: RErr←0A8, GOTO[Error], c*; RHByPgBad: RErr←0A9, GOTO[Error], c*; RHByArBad: RErr←0AA, GOTO[Error], c*; ByCyBrBad: RErr←0AB, GOTO[Error], c*; UFZeroBad: RErr←0B1, CANCELBR[Error], c*; TestSeqErr: RErr ← 0FC, GOTO[Error], c*; { error code used up thru "0B2", also used are 0FC, 0FD, and 0FE } { Patch to loop on wild branch} Error: ExtCtrl ← 5, {Clear and visible} c*, at[40F]; ErrorAgain: XC2npcDisp, c*, at[41D]; BRANCH[ErrorAgain, Go, 0D], c*, at[420];