Dragon Opcodes
To DragonCore^.pa Date March 27, 1987
From Edward Fiala Location PARC
Subject Opcode Diagnostics Organization CSL
XEROX
Release as [Indigo]<Dragon>Documentation>DragonDiagnostics.tioga
Came from [Ivy]<Fiala>Dragon>DragonDiagnostics.tioga
Last edited by Edward Fiala March 27, 1987
Abstract This document describes Dragon opcode diagnostic programs intended originally for use with Lizard, but now also configured for direct hardware testing using the Softcard. Their objective is to provide a reasonably thorough test of the Dragon IFU and EU in relatively few cycles under the assumption that the cache and memory system work perfectly and introduce no complications. The diagnostics have been written for use with slow simulators (1 instruction per 3 seconds is the slowest), where concise rather than thorough testing is the rule.
All of these diagnostics have been debugged against Lizard's machine simulation by first loading the diagnostic with "quad -cx GenDebugger GenXXX" (where "GenXXX" is the name of the diagnostic); several diagnostics then require that you use the interpreter to turn off Lizard's more careful error checking by doing "← LizardLiverImpl.careful ← FALSE"; finally do "Run". The diagnostics assume that Pause[] and Halt[x] will stop simulation and report their location, and Lizard has facilities for showing the values in registers. The diagnostics also assume that transferring control to undefined locations will either cause an IFU page fault, if the page has no declared memory locations on it, or execute a Pause[] opcode, if the page exists but the particular location hasn't been initialized (Or the simulator can give an "outside defined envelope" message when this occurs.). Similarly, they assume that reading or writing an undeclared memory location causes an EU page fault.
The assumed initial condition established by Reset is as follows:
1) Reschedule is disabled, so no process switching will preempt the diagnostic, whose execution begins at the label "Start" in GenDebugger.
2) All registers have undefined values. The IFU state looks as though a procedure with no arguments has just been entered.
All of the diagnostics execute Halt[177777B] as their last instruction; this normally means that the diagnostic completed all tests without error. In the event of an error, a one-byte Pause opcode (0) will usually be executed, or an "outside defined envelope" message may be given.
A comment at the beginning of each file gives the number of instructions executed by the diagnostic and the PC and cycle at which it terminates when correctly executed.
Each diagnostic consists of a procedure called "All" inside which one procedure is defined for each separate test; following these definitions are procedure calls which instantiate the diagnostic. Execution of every diagnostic begins at the Reset trap location in GenDebugger; the Reset code finishes with a jump to userBasePC = 4040000B and sets the output PC to this location. The first instruction instantiated by the diagnostic is then placed at userBasePC. For example, in GenReg the definitions inside "All" are followed by the following statements which instantiate the diagnostic:
Begin at PC = userBasePC = 1010000B * 4, L = 1, S = 0 as established in GenDebugger.
GenEUSL[];
GenIFUSL[];
Halt[177777B]; --Terminate here at the end of the program
The Reset code in GenDebugger will be followed by the code instantiated by GenEUSL[], which in turn is followed by the code instantiated by GenIFUSL[] and a Halt. (These statements would be followed by statements to instantiate Traps and Xops, though there aren't any in GenReg.) If it is necessary to "home in" on an error being reported by the diagnostic, one approach is to comment out the instantiating procedures selectively until only the one detecting a problem remains. Then examine that procedure to decide how to proceed. Often, a test sequence is defined by a procedure which is called a number of times with different test values; these can be selectively commented out to isolate a particular set of test values that fails.
1. Softcard vs. Lizard Operation
DebuggerDefs.mesa and GenDebugger.mesa must be understood to run the diagnostics.
DebuggerDefs.mesa defines two BOOLEAN switches, withSoftCard and massiveTesting. The first step in using the diagnostics is to edit these switches into the desired configuration, recompile everything, and build new quad files. DebuggerDefs.mesa also defines the table locations where machine state is saved by GenDebugger.
Normally withSoftCard = massiveTesting = FALSE for testing with slow simulators, TRUE for testing with the Softcard. However, all diagnostics assembled assembled with withSoftCard = TRUE, except GenTraps, will also run under Lizard, though testing will not be as thorough. massiveTesting = TRUE enables additional tests; presently this doesn't do much, but someday it might. withSoftCard controls conditional assembly of diagnostic code which must be different with the Softcard than with Lizard. When withSoftCard = TRUE, all memory references in the diagnostic are confined to word addresses [1,000,000B..2,000,000B) or, equivalently, to byte addresses [4,000,000B..10,000,000B); in addition, tests involving the CST instruction, which is not supported by the Softcard, are disabled. When withSoftCard = FALSE, these restrictions are relaxed for more thorough testing of the PC and memory address logic.
GenDebugger must be loaded ahead of each diagnostic described below. Its purpose is to provide the Reset code and a debugging interface when diagnostics are run on the Softcard; it implements the Reset, Pause[] (opcode 0), and Halt[x] (opcode 377B) traps. Only the Reset trap is used when diagnostics are run under Lizard.
On the Softcard, Pause[] or Halt[] execute the Xop procedures defined in GenDebugger; these save the state of the IFU and EU in storage for access by a Daybreak program using the Softcard, wait for the Softcard to signal "proceed", and then reload the machine state and continue. For the diagnostics below, no purpose would be served by continuing, so the debugger serves principally to save the state of the machine where it can be examined. The details of GenDebugger operation are described by comments in the source file.
When run under Lizard, Pause[] or Halt[x] stops simulation, but bugging "Run" again causes execution to continue at the Xop trap for the opcode; this feature can be used to debug the GenDebugger module itself using Lizard. The abbreviateReset BOOLEAN switch must be used when GenDebugger is itself debugged.
2. GenJumpTest.mesa
The first test executes all the different unconditional jumps. All code runs in Kernel mode with traps disabled. For testing with the Softcard, the withSoftCard BOOLEAN switch must be set TRUE; this switch disables the JQB tests which go to storage locations outside the 1 megabyte area supported by the Softcard. For testing with Lizard, withSoftCard can be either TRUE or FALSE, but more thorough testing occurs if the switch is FALSE.
First, the relative jumps JDB and JB are exercised to determine that the displacement bits of these opcodes and the PC adder generate and propagate logic works. Next, J1, J2, J3, and J5 are tested. Finally, using JQB, each PC bit is tested in isolation by jumping to a sequence of locations.
Because of my unfamiliarity with the PC adder, this test will not thoroughly exercise the carry propagate terms of the adder, though many cases are tested. No page faults should occur.
Machine features tested by this diagnostics are as follows:
1) Opcodes.
JQB PC ← AlphaBetaGammaDelta
JDB PC ← PC + AlphaBetaS
JB PC ← PC + Alpha
J1 Noop of length 1 (used as jump)
J2 Noop of length 2 (used as jump)
J3 Noop of length 3 (used as jump)
J5 Noop of length 5 (used as jump)
2) All bits of the PC (when withSoftCard = FALSE).
3) All bits of the PC adder with carry being generated and not generated from each bit position, and with some carry propagation situations.
This diagnostic is run from Lizard by:
quad -cx GenDebugger GenJumpTest
3. GenLICJ.mesa
GenLICJ is the most basic diagnostic for non-jump instructions; it presupposes that GenJumpTest completes successfully; no traps are enabled during the diagnostic, which runs in Kernel mode, and no faults, traps, or procedure calls should occur. Equality comparisons on the conditional jumps require most of the EU's adder to work. Initially, reasonably thorough testing is carried out using LIQB, RJEB, RJEBJ, RJNEB, and RJNEBJ opcodes with stack addressing modes. Each of the 32 bits of LIQB is tested individually. RJEB and RJNEB equality comparisons are tested with each argument in the matching and complementary state and 0. For example, in testing the value 4, comparisons would be done as follows:
4 vs 0
0 vs 4
4 vs 4
4' vs 0'
0' vs 4'
4' vs 4'
The tests are done using both the EU's A bypass path and no bypass path. Then the B bypass path is tested by using RAND to move [s] into const0 before comparing const0 to [s]. The LIQB test should reveal problems in the K bus, EU equality comparison, EU bypass and direct paths, and IFU conditional jump mechanism. It will not be obvious from a failure which of LIQB, RJEB, RJNEB, K bus, A direct path, B direct path, A bypass path, or B bypass path has failed; but failure of one of these should result in the program hitting a Pause.
Next, LIDB is tested against LIQB and then LIB is tested against LIDB using RJEB and RJNEB.
Finally, JEBB, JEBBJ, JNEBB, and JNEBBJ are tested against LIB.
Machine features tested by this diagnostic are as follows:
1) Push of immediate constant.
LIB [S] ← AlphaZ; S ← S+1.
LIDB [S] ← AlphaBetaZ; S ← S+1.
LIQB [S] ← AlphaBetaGammaDelta; S ← S+1.
2) Register comparing conditional jumps (Rb = [S - 1]- only and Ra = const0 or [S]-).
RJEB Ra=Rb => PC ← PC+BetaS; predict no jump
RJEBJ Ra=Rb => PC ← PC+BetaS; predict jump
RJNEB Ra#Rb => PC ← PC+BetaS; predict no jump
RJNEBJ Ra#Rb => PC ← PC+BetaS; predict jump
3) Literal match conditional jumps.
JEBB AlphaZ = [S] => PC ← PC+BetaS; S ← S-1; predict no jump
JEBBJ AlphaZ = [S] => PC ← PC+BetaS; S ← S-1; predict jump
JNEBB AlphaZ # [S] => PC ← PC+BetaS; S ← S-1; predict no jump
JNEBBJ AlphaZ # [S] => PC ← PC+BetaS; S ← S-1; predict jump
4) All 32 K bus bits.
5) All 32 bits of EU subtraction.
6) EU A and B direct paths and bypass paths.
This program is run from Lizard by:
quad -cx GenDebugger GenLICJ
4. GenReg.mesa
This diagnostic requires GenLICJ and GenJumpTest to work. No faults or traps should occur during this test, which runs in Kernel mode.
The first test is generated by GenEUSL which tests EU regsiters with no traps enabled. LIQB and SIP are used to write registers; then LIP, LIQB, RJEBJ are used to read back and compare each value read against what was written. All the EU registers except 1, 2, and const0 are tested first; then registers 1 and 2 are tested; const0 is not tested because of its implicit use in one-operand opcodes such as LIQB and because it is hard-wired to the value 0. Two passes of testing are carried out; first pass values written into consecutive registers are 1, 2, 4, 8, ..., etc. (cycling a single-bit value each time); second pass values complement those written in the first pass.
The second test is generated by GenIFUSL, which tests the IFU stack and ifuSLimit registers with no traps enabled; ifuXBus and ifuStatus registers are not tested. The method of testing and values used in testing are similar to the EU test described above. The first method uses SIP[ifuEldestL / PC] to push L and PC and LIP[ifuEldestL / PC] to read and check results; all 15 levels of the ifu stack are written and then all are read and checked.
The second method uses LFC to advance the ifu stack position and SIP[ifuYoungestL / PC] to write values; it checks the results with LIP[ifuEldestL / PC]; all 15 levels are tested. The third method pushes and writes the PC with LFC and writes L with SIP[ifuYoungestL]; it reads and checks by doing a RETN and using LIP[ifuYoungestL] to check L. At the conclusion of this test, the ifu stack, ifuYoungestL/PC, ifuEldestL/PC, and the parts of LFC and RETN associated with the PC have been tested. The parts of LFC and RETN associated with L and S are have not been tested, however.
Machine features tested by this diagnostic are as follows:
1) Read and write special registers.
LIP [S+1] ← PReg[Alpha]; S ← S+1.
SIP PReg[Alpha] ← [S]; S ← S - 1; {kernel}.
The IFU has the following registers:
PC 32 bits
S 7 bits
L 7 bits
SLimit 7 bits
EldestL 32 bits (eldest L and status in the IFU stack)
EldestPC 32 bits (eldest PC in IFU stack; reading EldestPC
removes the eldest entry while writing EldestPC
adds a new eldest entry.
YoungestL 32 bits (youngest L and status in the IFU stack)
YoungestPC 32 bits
The EU has the following registers (see DragOpsCross.mesa):
euStack [0..127)
euJunk 128 (not tested)
euMAR 130
euField 131
euConstants [132..144)
euAux [144..160)
[160..239] are illegal registers
2) Partial testing of procedure call and return with respect to correctly using 15 levels of the IFU stack, pushing and popping the PC and L.
LFC Call proc at PC+AlphaBetaS.
RETN Return from proc; no change to S.
This diagnostic can be run from Lizard by:
quad -cx GenDebugger GenReg
5. GenXopLS.mesa
This diagnostic, which runs in Kernel mode with traps disabled, assumes that operations tested by GenJumpTest, GenLICJ, and GenReg all work. It tests all the S and L adjusting opcodes and XOP's. It requires "← LizardLiverImpl.careful ← FALSE" to the interpreter before execution. Machine features tested are as follows:
1) S and L adjusting opcodes.
AL L ← (L+Alpha) mod 128.
AS S ← (S+Alpha) mod 128.
DIS S ← (S — 1) mod 128.
ASL S ← (L+Alpha) mod 128; stack overflow not checked.
ALS L ← (S + Alpha) mod 128. Used at procedure entry to establish base of local frame.
2) Undefined operations.
XOP1 1-byte xops {[1..17b], [30b..37b], 112b, [117b..123b], 125B, and [130b..137b]}.
XOP2 2-byte xops push AlphaZ before trapping {215b, 223b, [234b..236b]}.
XOP3 3-byte xops push AlphaBetaZ (?) before trapping {323b, [364b..367b], [374b..376b]}.
XOP5 5-byte xops push AlphaBetaGammaDelta before trapping
{[40b..60b], [63b..65b], [70b..77b]}.
The Pause Xop (0) and the Halt Xop (377b) are not tested. Also, the following Xops have undefined behavior and are not tested either in this diagnostic or others: 311B, 313B, 337B, 340B, 344B, 350B, and 354B.
This diagnostic can be run from Lizard by:
quad -cx GenDebugger GenXopLS
6. GenCall.mesa
This diagnostic assumes that operations tested by GenJumpTest, GenLICJ, GenReg, and GenXopLS all work; any failure results in a Pause[] and successful completion is indicated by a Halt[177777B]. The operation of the IFU procedure stack for non-trapping cases was tested by GenReg. All code runs in Kernel mode with traps disabled.
This diagnostic performs the following tests:
1) Procedure calls when they aren't supposed to trap.
LFC Call proc at PC+AlphaBetaS; each bit of AlphaBetaS is tested.
DFC Call proc at AlphaBetaGammaDelta; each bit of AlphaBetaGammaDelta
is tested.
2) Procedure return instructions.
RETN Return from proc; no change to S.
RET Return from proc; S ← (L+Alpha) mod 128; each bit of Alpha is tested.
This diagnostic can be run from Lizard by:
quad -cx GenDebugger GenCall
7. GenSJ.mesa
This diagnostic assumes operations tested by GenJumpTest, GenLICJ, and GenCall work.
The JSR (PC-relative stack jump) and JSD (absolute stack jump) opcodes are tested in Kernel mode with traps disabled in such a way that every bit in the back path from the EU to the IFU is individually tested.
The SFC opcode is tested by executing a sequence of calls that exercises all the PC bits without overflowing the IFU call stack. Before each call, 200B is added to a counter at [S] which is initially 0. Then RETN is executed to return from each of the calls; before each RETN, 1 is added to the counter at [S]. After all the calls and returns have been executed, the counter is checked to make sure that control has successfully passed through all the SFC and RETN opcodes.
Halt[177777B] is executed at the successful end of the test. It is assumed that the simulator stops execution on either Pause or Halt.
Machine features tested by this diagnostic are as follows:
1) JSR PC ← PC+[S]; S ← S-1.
2) JSD PC ← [S]; S ← S - 1.
3) SFC Call proc at [S]; S ← S-1.
This diagnostic can be run from Lizard by:
quad -cx GenDebugger GenSJ
8. GenMove.mesa
This diagnostic assumes that operations tested by GenLICJ and GenRegCall all work. No faults, traps, or procedure calls should occur upon any error); no EU memory references are made; no EU arithmetic is used except that which results from equality comparisons on conditional jumps; and all code is executed in Kernel mode with traps disabled.
All register-to-register move operations are tested by using RJEB/RJEBJ to compare the value in the destination register with the value in the source register after executing the move. The program presently tests each operation with the values 0 and -1. Opcodes tested by this diagnostic are as follows:
1) Register-to-register moves
EXDIS [S-1] ← [S]; S ← S-1
DUP [S+1] ← [S]; S ← S+1
LCn [S] ← Constants[n]; S ← S+1 for n = [0..11].
LRn [S+1] ← [L+n]; S ← S+1 for n = [0..15].
SRn [L+n] ← [S]; S ← S-1 for n = [0..15].
This program is run from Lizard by:
quad -cx GenDebugger GenMove
9. GenLogic.mesa
This diagnostic assumes that operations tested by GenLICJ, GenCall, and GenReg all work. No faults, traps, or procedure calls should occur; no EU memory references are made; no EU arithmetic is used except that which results from equality comparisons on conditional jumps; and all code is executed in Kernel mode with traps disabled.
First, the logic operations RAND, ROR, and RXOR are tested using every bit combination with stack arguments; these tests aim primarily at verifying the hardware's ability to execute the AND, OR, and XOR operations. Then, the RRR format addressing modes are thoroughly checked using ROR. Next, the QR format addressing modes are tested using QAND to test the argument specified in 2 bits and QOR to test the argument specified by 6 bits.
Opcodes tested by this diagnostic are as follows:
ROR Rc ← Ra or Rb.
RXOR Rc ← Ra xor Rb.
RAND Rc ← Ra and Rb.
QAND Quick And. [S] ← Rs and Rb.
QOR Quick Or. [S] ← Rs or Rb.
OR [S-1] ← [S] or [S-1], S ← S-1.
AND [S-1] ← [S] and [S-1], S ← S-1.
This program is run from Lizard by:
quad -cx GenDebugger GenLogic
10. GenArith.mesa
This diagnostic requires GenLICJ, GenReg, GenCall, and GenLogic to work correctly. The addressing modes for RRR and QR format opcodes are assumed to have already been tested by GenLogic, so the tests in GenArith are not particularly concerned with the registers from which the values being tested derive. The purpose of the diagnostic is to test all arithmetic opcodes except the Lisp arithmetic opcodes, and it is run entirely in Kernel mode with traps disabled.
First, addition is tested using RUADD; carry generation is tested for each of the 32 bit positions by seeing whether the presence of a 1 in the same bit position of both arguments correctly causes a carry into the next higher bit and the absence of a 1 in either argument correctly causes no carry; the carry-out of the adder is also tested. Then carry propagation is tested by adding -1 to each of 1, 2, 4, ....
Next, the inverter used by subtraction and adder carry-out is tested using RUSUB.
Finally, the various add and subtract opcodes are tested on various values, some of which cause integer overflow.
Opcodes tested by this diagnostic are as follows:
RVADD Rc ← Ra + Rb; no overflow checking, no use or modification of Carry.
RVSUB Rc ← Ra - Rb; no overflow checking, no use or modification of Carry.
RUADD Rc ← Ra + Rb + Carry; Carry ← carry-out.
RUSUB Rc ← Ra - Rb - Carry; Carry ← not[carry-out].
Integers - overflow occurs when the result won't fit in a word (= carry out of bit 0 is not equal to the carry out of bit 1).
RADD Rc ← Ra + Rb + Carry; Carry ← 0; trap on overflow.
RSUB Rc ← Ra - Rb - Carry; Carry ← 0; trap on overflow.
ADD [S-1] ← [S] + [S-1]; S ← S-1; trap on overflow.
SUB [S-1] ← [S-1] - [S] - Carry; Carry ← 0; S ← S-1; trap on overflow.
ADDB [S] ← [S] + AlphaZ + Carry; trap on overflow.
SUBB [S] ← [S] - AlphaBetaZ - Carry; trap on overflow.
ADDDB [S] ← [S] + AlphaBetaZ + Carry; trap on overflow.
SUBDB [S] ← [S] - AlphaZ - Carry; Carry ← 0; trap on overflow.
QADD [S] ← [S] + Rb + Carry; Carry ← 0; trap on overflow.
QSUB [S] ← [S] - Rb - Carry; Carry ← 0; trap on overflow.
ADDQB [S] ← [S] + abcd + Carry; Carry ← 0; trap on overflow.
SUBQB [S] ← [S] - abcd - Carry; Carry ← 0; trap on overflow.
This diagnostic can be run from Lizard by:
quad -cx GenDebugger GenArith
11. GenLisp.mesa
The purpose of the diagnostic is to test all Lisp arithmetic opcodes. In Lisp arithmetic, the Carry bit is not used as an input, and is set to 0 always; if either operand or the result is not in the range [-229..229) (top three bits being all 0s or all 1s), a Lisp NaN (Not a Number) trap is taken.
This diagnostic requires GenLICJ, GenReg, GenCall, GenLogic, and GenArith to work correctly. The addressing modes for RRR and QR format opcodes are assumed to have already been tested by GenLogic, and basic adder operation is assumed tested by GenArith, so GenLisp is principally concerned only with testing distinctive properties of Lisp arithmetic. Execution is entirely in Kernel mode with traps disabled.
Opcodes tested by this diagnostic are as follows:
RLADD Rc ← Ra + Rb; Carry ← 0; trap on Lisp NaN.
RLSUB Rc ← Ra - Rb; Carry ← 0; trap on Lisp NaN.
LADD [S-1] ← [S] + [S-1]; Carry ← 0; S ← S-1. Trap on Lisp NaN.
LSUB [S-1] ← [S-1] - [S]; Carry ← 0; S ← S-1. Trap on Lisp NaN.
QLADD [S] ← [S] + Rb; Carry ← 0; trap on Lisp NaN.
QLSUB [S] ← [S] - Rb; Carry ← 0; trap on Lisp NaN.
This diagnostic can be run from Lizard by:
quad -cx GenDebugger GenLisp
12. GenRBC.mesa
The purpose of GenRBC is to test the arithmetic comparison conditional jumps and bounds-checking opcodes; this is done entirely in Kernel mode with traps disabled. Since, addressing modes for RRR and QR format opcodes have been tested by GenLogic and adder operation by GenArith, the tests in GenRBC are concerned primarily with testing only the unique properties of the opcodes being tested.
This diagnostic requires GenLICJ, GenReg, GenCall, GenLogic, and GenArith to work correctly.
Opcodes tested by this diagnostic are as follows:
1) Arithmetic comparison conditional jumps
RJGB Ra>Rb => PC ← PC+BetaS; predict no jump
RJGBJ Ra>Rb => PC ← PC+BetaS; predict jump
RJGEB Ra>=Rb => PC ← PC+BetaS; predict no jump
RJGEBJ Ra>=Rb => PC ← PC+BetaS; predict jump
RJLB Ra<Rb => PC ← PC+BetaS; predict no jump
RJLBJ Ra<Rb => PC ← PC+BetaS; predict jump
RJLEB Ra<=Rb => PC ← PC+BetaS; predict no jump
RJLEBJ Ra<=Rb => PC ← PC+BetaS; predict jump
2) Conditional trap opcodes
RBC Register Bounds Check. If Ra < Rb (unsigned), then Rc ← Ra,
else trap; Carry is not used or set. This instruction is used to
check indexes against bounds and to narrow a number to fit
into a subrange.
BC Bounds Check. Bounds-check trap if [S-1] >= [S]; otherwise,
S ← S-1; Carry is not used or set.
QBC Quick Bounds Check. If Rs < Rb (unsigned) then Rsd ← Rss
else trap.
This diagnostic can be run from Lizard by:
quad -cx GenDebugger GenRBC
13. GenFieldUnit.mesa
This diagnostic requires GenLICJ, GenReg, and GenLogic to work correctly. No faults, traps, or procedure calls should occur, and all code is executed in Kernel mode with traps disabled. No EU memory references are made; no EU arithmetic is used except that which results from equality comparisons on conditional jumps.
SHL, SHR, SHDL, SHDR, and RFU are each tested in a sequence of 21 instructions which is replicated for a variety of input values, shift counts, and masks.
The following opcodes are tested:
SHL Shift Logical. [S] ← FieldUnit[[S], 0, AlphaBeta]
SHR Shift Rotate. [S] ← FieldUnit[[S], [S], AlphaBeta]
SHDL Shift Double. [S-1] ← FieldUnit[[S-1], [S], AlphaBeta]; S ← S - 1.
SHDR Shift Double. [S-1] ← FieldUnit[[S], [S-1], AlphaBeta]; S ← S - 1.
RFU [Rc] ← FieldUnit[[Ra],[Rb],Field].
FSDB Field Setup Double Byte. FieldDescriptor ← [S] + AlphaBeta; S ← S - 1.
This diagnostic can be run from Lizard by:
quad -cx GenDebugger GenField
14. GenRW.mesa
This diagnostic requires GenLICJ, GenReg, GenLogic, GenCall, and GenArith work correctly. No procedure calls, page faults, or traps should occur during testing; and all code is executed in Kernel mode.
During the first test, SRI0 is used to write data values into storage; then the values are read back with LRI0 and checked; the values written are 1, 2, 4, ..., etc. so this tests the PBus bits. During the second test, the addressing is tested by choosing addresses with similar patterns and again writing with SRI0 and reading with LRI0.
After addressing and data values are exercised with SRI0 and LRI0, the other operations are tested by writing consecutive storage values using all the other write opcodes and then reading the values back with the read opcodes.
Finally, the CST opcode is tested.
The following opcodes are tested:
1) Load register from memory instructions
LRIn [S+1] ← Mem(Locals[n]+AlphaZ); S ← S+1 for n = [0..15].
RB [S] ← Mem([S]+AlphaZ).
QRX [S] ← Mem(Rs + Rb).
RSB [S+1] ← Mem([S]+AlphaZ); S ← S+1.
RRX [Rc] ← Mem([Ra]+[Rb]).
RX [S-1] ← Mem([S-1] + [S]); S ← S-1.
LGF [S+1] ← Mem(Aux0+AlphaZ)^; S ← S+1.
RRI Locals[BetaL] ← Mem(Locals[BetaR]+AlphaZ).
RAI Locals[BetaL] ← Mem(AuxRegs[BetaR]+AlphaZ).
2) Store register into memory instructions
SRIn Mem(Locals[n]+AlphaZ) ← [S]; S ← S-1 for n = [0..15].
WB Mem([S]+AlphaZ) ← [S-1]; S ← S-2.
WSB Mem([S-1]+AlphaZ) ← [S]; S ← S-2.
PSB Mem([S-1]+AlphaZ) ← [S]; S ← S-1.
WRI Mem(Locals[BetaR]+AlphaZ) ← Locals[BetaL].
WAI Mem(AuxRegs[BetaR]+AlphaZ) ← Locals[BetaL].
3) Conditional store instruction
CST [S+1] ← Mem([S-2]+AlphaZ); [S+1]=[S] => Mem([S-2]+AlphaZ) ← [S-1];
S ← S+1; special: atomic
This diagnostic can be run from Lizard by:
quad -cx GenDebugger GenRW
15. GenSFCI
This diagnostic requires GenLICJ, GenReg, GenLogic, GenCall, GenArith, and GenRW to work correctly. No page faults or traps should occur; all code is executed in Kernel mode with traps disabled.
The following opcodes are tested:
SFCI Call procedure at Mem([S]).
This diagnostic can be run from Lizard by:
quad -cx GenDebugger GenSFCI
16. GenTraps.mesa
Unlike the other diagnostics, withSoftcard = FALSE is required to run this diagnostic under Lizard.
For thorough testing, this diagnostic should be run last since it executes many different instructions in its test of user mode (GenJumpTest, GenLICJ, GenReg, and GenXopLS are the most important prerequisites.). However, when testing with simulators, this diagnostic provides a good quick test of the IFU and EU. Unlike most other diagnostics, XPause[] (opcode 2, a 1 byte Xop) is used to report most failures instead of Pause[] (opcode 0); XPause[] turns off user mode and disables traps, if necessary, then jumps to the debugger.
It performs the following tests:
1) That Kernel function call and return works.
KFC Kernel Function Call. PC←InstTrap[KFC];
set kernel mode and disable traps; S←S+1.
2) That SIP[ifuYoungestL] and LIP[ifuYoungestL] correctly set and read the user mode and trap enable status bits for the caller's context and that a RET to the context with the changed status behaves correctly for that status. (Reading and writing ifuYoungestL and ifuEldestL was tested in GenReg; only correct enabling and disabling of traps and correct entering of user mode is tested here).
3) That all instructions legal in user mode don't trap, and those illegal in user mode cause a mode fault trap. Only one Xop of each length (1, 2, 3, and 5 bytes) is tested, only one of the 16 opcodes in each of the LRIn, SRIn, LRn, SRn, and LCn groups is tested. The illegal instructions are all SIP's, and LIP[IFUEldestPC] (an active operation).
4) That any write of a constant or aux0 to aux7 causes a mode fault.
5) When IFUStatus[TrapsEnabled] = TRUE:
a) That an IFU stack overflow trap occurs precisely on the 12th call when a LFC, DFC, SFC, SFCI, KFC, or 1, 2, 3, 5-byte XOP is executed, or at the onset of any other trap.
b) That an IFU stack overflow trap does not occur with 11 call stack entries when several ordinary instructions, JQB, JDB, JB, JSR, JSD, or RET is executed.
c) That an EU stack overflow trap occurs when an instruction would put S in the range [SLimit .. SLimit+16) for several opcodes that push the stack; for AS[n], ASL[n], RET[n], and RETK[n] for one value of SLimit and several values of n.
d) That an EU stack overflow trap occurs when an instruction would put S in the range [SLimit .. SLimit+16) for several opcodes that pop the stack.
d) That an EU stack overflow trap does not occur when ASL[n] makes S equal to SLimit - 1 or SLimit + 16 and does occur when ASL[n] makes S equal to SLimit or SLimit + 15 for SLimit = 1, 2, 4, 8, 16, 32, 64, or 111.
6) That an IFU page fault occurs in sequence when jumping, calling, returning, falling through, or conditionally jumping (predicted both ways) into an undeclared page.
7) That an IFU page fault does not occur when the untaken path of a conditional jump (predicted both ways) lies in an undeclared page.
8) That an EU page fault occurs in the proper sequence on memory read, memory write, CST, and SFCI instructions; registers which would have been affected by the faulting instruction are not modified; and the euMAR register is loaded with the memory address of the fault.
9) That mode fault trap prevails over bounds check, overflow, NaN, EU stack overflow, and EU page fault.
10) That an EU stack overflow trap is lower priority than all other traps.
(Since memory faults, bounds check, and overflow or NaN are three mutually exclusive groups of traps, the relative priority of these does not have to be tested. Also, reenabling traps with an EU or IFU stack overflow condition existing is illegal.)
This diagnostic can be run from Lizard by:
quad -cx GenDebugger GenTraps
17. GenTraps2.mesa
NOT DEBUGGED YET.
This diagnostic tests a few loose ends that could not conveniently be tested in GenTraps.
1) Verify that with traps enabled IFU stack overflow trap prevails over an IFU page fault trap that causes the IFU stack overflow condition.
2) ****Verify that EU stack overflow trap prevails over reschedule when a SIP enables traps and the EU stack overflow and reschedule-waiting conditions are both true.
This diagnostic can be run from Lizard by:
quad -cx GenDebugger GenTraps2
Features Known To Be Not Tested
The following opcodes or features are not presently tested for various reasons.
1) The three IO opcodes are not tested. In the definitions below, Address = AlphaZ and PCommand = BetaZ; the high-order bit of PCommand is 0 on a non-cache operation, 1 on a cache operation; the low-order bit of PCommand is 0 on a read or 1 on a write. On cache operations bits [1..4] determine which bytes of a cache memory word are affected (10b writes the high-order byte only, 4b the second byte only, 2b the third byte only, and 1b the least significant byte only; 14b the high two bytes; etc.) and bits [5..6] determine which cache operation is performed.
IOD IsRead[PCommand] =>
[S+1] ← Dispatch[Address, PCommand]; S ← S+1.
IsWrite[PCommand] =>
[] ← Dispatch[Address, [S], PCommand]; S ← S-1.
IODA IsRead[PCommand] =>
[S] ← Dispatch[Address + [S], PCommand].
IsWrite[PCommand] =>
[] ← Dispatch[Address + [S], [S-1], PCommand]; S ← S-2.
ION IsRead[PCommand] =>
[S+1] ← Dispatch[Address, PCommand].
IsWrite[PCommand] =>
[] ← Dispatch[Address, [S], PCommand].
2) The machine state after reset is not verified (no specification available).
3) The two high-order memory address bits are only tested in the zero state because of a Lizard limitation. When withSoftCard = TRUE, only the region [1,000,000B..2,000,000B) is tested.
4) The undefined opcodes are never tested.
5) EUWriteFault, MemAccessFault, IOAccessFault, and Reschedule are not tested (not supported by Lizard).
6) That IFU stack overflow occurs in preference to a mode fault when traps are enabled on a user mode RADD that gets a mode fault trap with the IFU stack going into overflow at the onset of the trap (Lizard bug); tests for this are commented out in GenTraps.
7) IFU page fault priority over EU stack overflow.