Dragon Opcodes
To DragonCore^.pa Date March 5, 1986
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 5, 1986
Abstract This document describes several Dragon opcode diagnostic programs for use with Lizard. The 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. It is intended for use with slow simulators (1 instruction per 3 seconds is the slowest), so concise rather than thorough testing is the rule. Later, the same diagnostics may be used to check chips.
All of these diagnostics have been debugged against Lizard's machine simulation by first loading the diagnostic with "quad -cx DiagnosticName" and then doing "Reset" and "Run". The diagnostics assume that Pause[] and Halt[x] will stop simulation and report their location. They 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, it assumes 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".
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.
1. GenJumpTest.mesa
The first test executes all the different unconditional jumps. All code runs in Kernel mode with traps disabled.
Using JQB, each PC bit is tested in isolation by jumping to a sequence of locations. Next, 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. Finally, J1, J2, J3, and J5 are tested.
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.
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 GenJumpTest
2. 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 GenLICJ
3. 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 7 bits (eldest L in the IFU stack)
EldestPC 32 bits (eldest PC in the IFU stack; reading EldestPC
removes the eldest entry while writing EldestPC adds
a new eldest entry.
YoungestL 7 bits
YoungestPC 32 bits
Status ? (rest of IFU state; whether traps are enabled, whether
a reschedule is waiting. Each status field has an
accompanying bit to indicate whether the field should
be set by a
SIP instruction.
Fields are (no positions yet assigned):
Traps {enabled, disabled}
Reschedule {clear, waiting}
Mode {kernel, user}
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 GenReg
4. GenXopLS.mesa
This diagnostic, which runs in Kernel mode with traps disabled, assumes that operations tested by GenJumpTest, GenLICJ, and GenReg all work. This diagnostic tests all the S and L adjusting opcodes and XOP's. Machine features tested by this diagnostic 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, note that 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 GenXopLS
5. 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 GenCall
6. GenSJ.mesa
This diagnostic assumes operations tested by GenJumpTest, GenLICJ, and GenCall work.
The SJ (stack jump) opcode is 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) SJ PC ← PC+[S]; S ← S-1.
2) SFC Call proc at [S]; S ← S-1.
This diagnostic can be run from Lizard by:
quad -cx GenSJ
7. 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
LC0 [S] ← Constants[0]; S ← S+1
LC1 [S] ← Constants[1]; S ← S+1
LC2 [S] ← Constants[2]; S ← S+1
LC3 [S] ← Constants[3]; S ← S+1
LC4 [S] ← Constants[4]; S ← S+1
LC5 [S] ← Constants[5]; S ← S+1
LC6 [S] ← Constants[6]; S ← S+1
LC7 [S] ← Constants[7]; S ← S+1
LR0 [S+1] ← [L+0]; S ← S+1
LR1 [S+1] ← [L+1]; S ← S+1
LR2 [S+1] ← [L+2]; S ← S+1
LR3 [S+1] ← [L+3]; S ← S+1
LR4 [S+1] ← [L+4]; S ← S+1
LR5 [S+1] ← [L+5]; S ← S+1
LR6 [S+1] ← [L+6]; S ← S+1
LR7 [S+1] ← [L+7]; S ← S+1
LR8 [S+1] ← [L+10]; S ← S+1
LR9 [S+1] ← [L+11]; S ← S+1
LR10 [S+1] ← [L+12]; S ← S+1
LR11 [S+1] ← [L+13]; S ← S+1
LR12 [S+1] ← [L+14]; S ← S+1
LR13 [S+1] ← [L+15]; S ← S+1
LR14 [S+1] ← [L+16]; S ← S+1
LR15 [S+1] ← [L+17]; S ← S+1
SR0 [L+0] ← [S]; S ← S-1
SR1 [L+1] ← [S]; S ← S-1
SR2 [L+2] ← [S]; S ← S-1
SR3 [L+3] ← [S]; S ← S-1
SR4 [L+4] ← [S]; S ← S-1
SR5 [L+5] ← [S]; S ← S-1
SR6 [L+6] ← [S]; S ← S-1
SR7 [L+7] ← [S]; S ← S-1
SR8 [L+10] ← [S]; S ← S-1
SR9 [L+11] ← [S]; S ← S-1
SR10 [L+12] ← [S]; S ← S-1
SR11 [L+13] ← [S]; S ← S-1
SR12 [L+14] ← [S]; S ← S-1
SR13 [L+15] ← [S]; S ← S-1
SR14 [L+16] ← [S]; S ← S-1
SR15 [L+17] ← [S]; S ← S-1
This program is run from Lizard by:
quad -cx GenMove
8. 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 GenLogic
9. 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 integer overflow.
RSUB Rc ← Ra - Rb - Carry; Carry ← 0; trap on integer overflow.
ADD [S-1] ← [S] + [S-1]; S ← S-1; trap on integer overflow.
SUB [S-1] ← [S-1] - [S] - Carry; Carry ← 0; S ← S-1; trap on integer overflow.
ADDB [S] ← [S] + AlphaZ + Carry; trap on integer overflow.
SUBB [S] ← [S] - AlphaBetaZ - Carry; trap on integer overflow.
ADDDB [S] ← [S] + AlphaBetaZ + Carry; trap on integer overflow.
SUBDB [S] ← [S] - AlphaZ - Carry; Carry ← 0; trap on integer overflow.
QADD [S] ← [S] + Rb + Carry; Carry ← 0; trap on integer overflow.
QSUB [S] ← [S] - Rb - Carry; Carry ← 0; trap on integer overflow.
This diagnostic can be run from Lizard by:
quad -cx GenArith
10. 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 GenLisp
11. 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 GenRBC
12. GenField.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, SHD, and RFU are each tested in a sequence of 17 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]
SHD Shift Double. [S-1] ← FieldUnit[[S-1], [S], 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 GenField
13. 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
LRI0 [S+1] ← Mem(Locals[0B]+AlphaZ); S ← S+1.
LRI1 [S+1] ← Mem(Locals[1B]+AlphaZ); S ← S+1.
LRI2 [S+1] ← Mem(Locals[2B]+AlphaZ); S ← S+1.
LRI3 [S+1] ← Mem(Locals[3B]+AlphaZ); S ← S+1.
LRI4 [S+1] ← Mem(Locals[4B]+AlphaZ); S ← S+1.
LRI5 [S+1] ← Mem(Locals[5B]+AlphaZ); S ← S+1.
LRI6 [S+1] ← Mem(Locals[6B]+AlphaZ); S ← S+1.
LRI7 [S+1] ← Mem(Locals[7B]+AlphaZ); S ← S+1.
LRI8 [S+1] ← Mem(Locals[10B]+AlphaZ); S ← S+1.
LRI9 [S+1] ← Mem(Locals[11B]+AlphaZ); S ← S+1.
LRI10 [S+1] ← Mem(Locals[12B]+AlphaZ); S ← S+1.
LRI11 [S+1] ← Mem(Locals[13B]+AlphaZ); S ← S+1.
LRI12 [S+1] ← Mem(Locals[14B]+AlphaZ); S ← S+1.
LRI13 [S+1] ← Mem(Locals[15B]+AlphaZ); S ← S+1.
LRI14 [S+1] ← Mem(Locals[16B]+AlphaZ); S ← S+1.
LRI15 [S+1] ← Mem(Locals[17B]+AlphaZ); S ← S+1.
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
SRI0 Mem(Locals[0]+AlphaZ) ← [S]; S ← S-1.
SRI1 Mem(Locals[1]+AlphaZ) ← [S]; S ← S-1.
SRI2 Mem(Locals[2]+AlphaZ) ← [S]; S ← S-1.
SRI3 Mem(Locals[3]+AlphaZ) ← [S]; S ← S-1.
SRI4 Mem(Locals[4]+AlphaZ) ← [S]; S ← S-1.
SRI5 Mem(Locals[5]+AlphaZ) ← [S]; S ← S-1.
SRI6 Mem(Locals[6]+AlphaZ) ← [S]; S ← S-1.
SRI7 Mem(Locals[7]+AlphaZ) ← [S]; S ← S-1.
SRI8 Mem(Locals[10]+AlphaZ) ← [S]; S ← S-1.
SRI9 Mem(Locals[11]+AlphaZ) ← [S]; S ← S-1.
SRI10 Mem(Locals[12]+AlphaZ) ← [S]; S ← S-1.
SRI11 Mem(Locals[13]+AlphaZ) ← [S]; S ← S-1.
SRI12 Mem(Locals[14]+AlphaZ) ← [S]; S ← S-1.
SRI13 Mem(Locals[15]+AlphaZ) ← [S]; S ← S-1.
SRI14 Mem(Locals[16]+AlphaZ) ← [S]; S ← S-1.
SRI15 Mem(Locals[17]+AlphaZ) ← [S]; S ← S-1.
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 GenRW
14. 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 GenSFCI
15. GenTraps.mesa
For thorough testing, this diagnostic should be the last one run since it executes almost all machine instructions in its test of user mode. When testing with simulators, this diagnostic provides a good quick test of the IFU and EU. GenJumpTest, GenLICJ, GenReg, and GenXopLS are the most important prerequisites. It performs the following tests:
1) Kernel function call and return.
KFC Kernel Function Call. [S+1]←Status; PC←InstTrap[KFC]; set kernel mode
and disable traps; S←S+1.
RETK Return from kernel proc; Status ← [S]; S ← L + AlphaZ; used by kernel
to return to User mode, and to return from a trap while atomically enabling traps;
an instruction trap occurs if executed in user mode.
2) The SIP[IFUStatus] and RETK instructions are tested against LIP[IFUStatus] for correctly changing from Kernel mode to User mode, for enabling and disabling traps, and for causing Reschedule when traps are enabled.
3) All instructions legal in user mode don't trap, and those illegal in user mode do trap. Only one Xop of each length (1, 2, 3, and 5 bytes) is tested, only one of the 16 opcodes in the LRIn, SRIn, LRn, and SRn groups is tested. The illegal instructions are all SIP's, RETK, and LIP[IFUEldestPC] (an active operation); executing one of these in user mode should cause mode fault trap.
4) The occurrence of the following user mode traps is tested:
a) Any write of a constant or aux0 to aux7 causes a mode fault.
b) Storing in an address < 100000000B (= KernelLimit) causes an address check.
c) IOS, IOL, and ION pass a device number in Beta in which one bit is interpreted as "Kernel mode required" and another as "Kernel address illegal". Proper trapping of IOS, IOL, and ION for different settings of these bits is checked.
5) When IFUStatus[TrapsEnabled] = TRUE:
a) 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) An IFU stack overflow trap does not occur with 11 call stack entries when several ordinary instructions, JQB, JDB, JB, SJ, or RET is executed.
c) 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; or for the push of ifuStatus at the onset of another trap.
d) 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 (**not presently tested because Lizard does not allow this).
d) 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 (**16, 32, 64, and 111 are not presently tested because Lizard does not allow these).
6) An IFU page fault occurs in sequence when jumping, calling, returning, falling through, or conditionally jumping (predicted both ways) into an undeclared page.
7) An IFU page fault does not occur when the untaken path of a conditional jump (predicted both ways) lies in an undeclared page.
8) An EU page fault occurs in the proper sequence on memory read, memory write, IOS, 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) Mode fault trap prevails over address check, bounds check, overflow, NaN, and EU page fault.
10) Address check trap prevails over EU page fault.
11) An EU stack overflow trap is lower priority than all other traps and cannot occur when KFC is the cause of EU stack overflow.
(Since address check, bounds check, overflow, and NaN are mutually exclusive the relative priority of these traps 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 GenTraps
16. 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 GenTraps2
Features Known To Be Not Tested
The following opcodes are not presently tested for various reasons.
1) For the three IO opcodes, user mode trapping and address checking are tested but other features of the opcodes are not tested.
IOL IsRead[BetaZ] => [S+1] ← PRead[AlphaZ, BetaZ]; S ← S+1.
IsWrite[BetaZ] => PWrite[AlphaZ, BetaZ, [S]]; S ← S-1.
IOS IsRead[BetaZ] => [S] ← PRead[AlphaZ + [S], BetaZ].
IsWrite[BetaZ] => PWrite[AlphaZ + [S], BetaZ, [S-1]]; S ← S-2.
IOS IsRead[BetaZ] => [S] ← PRead[AlphaZ + [S], BetaZ].
IsWrite[BetaZ] => PWrite[AlphaZ + [S], BetaZ, [S-1]]; S ← S-2.
2) EUWriteFault is not tested; this should particularly be tested on the CST opcode.
3) The machine state after reset is not verified (no specification available).
4) The two high-order memory address bits are only tested in the zero state because of a Lizard limitation.
5) The undefined opcodes are never tested.
6) Opcodes that pop the EU stack and result in EU stack overflow because S enters the restricted region [SLimit .. SLimit + 16) are not tested due to a Lizard restriction.
7) The tests in GenTraps for EU stack overflow occurring properly on ASL[n] for n = 16, 32, 64, and 111 were commented out due to a Lizard restriction.