DRAFT
INSTRUCTIONSET - VERSION 3
INSTRUCTIONSET - VERSION 3
DRAGON PROJECT — FOR INTERNAL XEROX USE ONLY
DRAGON PROJECT — FOR INTERNAL XEROX USE ONLY
DRAGON PROJECT — FOR INTERNAL XEROX USE ONLY
3 INSTRUCTION SET
Lissy Bland
Dragon-86-01    Revised March, 1987
© Copyright 1986 Xerox Corporation. All rights reserved.
Abstract: This chapter describes the instruction set. The instructions are divided into fourteen categories: Addition, Subtraction, Logical Operations, Loads, Stores, Input/Output, Field Unit, IFU Indices, NoOps, Unconditional Jumps, Conditional Jumps, Bounds Checks, Procedure Calls and Returns, and Lisp. Within these categories, the instructions are described in order of increasing complexity.
Keywords: instruction set, instructions, instruction formats, opcodes, interpretation of operands
FileName: [Indigo]<Dragon>Documentation>Princops>InstructionSet.tioga, .ip
XEROX  Xerox Corporation
   Palo Alto Research Center
   3333 Coyote Hill Road
   Palo Alto, California 94304



3 INSTRUCTION SET
3.0 Notational Conventions
3.0.1 Semi-colons
In the instruction definitions, statements separated by semi-colons are executed sequentially. For example, the Add Byte (ADDB) instruction is described by the following equations:
1) Stack[S]Stack[S] + zExt[literal] + Carry;
2) Carry ← 0.
And, the Interpretation of Operands for the Add Byte instruction is Signed. That is, the Carry referenced in the first equation is the Carry resulting from the previous operation. (See the definitions of Signed, Unsigned, Lisp, and Small Integer Arithmetic in section 2.2.1.) The Carry referenced in the second equation is the Carry resulting from Add Byte instruction itself. If that Add Byte instruction had resulted in integer overflow, an integer overflow trap instruction would have been taken. In any event, the Carry is set to 0 after the instruction is executed.
3.0.2 DS
DS is used to indicate the effect of the instruction on the stack pointer, S. DS is set to zero at the beginning of each instruction. S is incremented by DS after instruction execution.
3.0.3 Font Changes
In the instruction definitions, implicit and explicit operands are distinguished by a font change. Explicit operands are printed in TimesRoman (the normal font). Implicit operands are printed in Helvetica. When a bold typeface is used, the difference between the two fonts is fairly subtle. For example, in the following instruction, Stack[S+1] ← zExt[literal]; Stack[S+1], an implicit operand, is given in the Helvetica font and literal, an explicit operand, is given in the TimesRoman font.
3.0.4 Conventions for Instruction Names
Instructions in the Registers to Register Format (defined below) have names beginning with the word Register and mnemonics beginning with the letter R. Instructions in the Quick Register Format (also defined below) have names beginning with the Quick and mnemonics beginning with the letter Q. Instrucions that take all their operands from Stack have no adjectives in their instruction names.
Here are three of the instructions that perform addition:
1) RADD Rc ← Ra + Rb + Carry; Carry ← 0; trap on overflow.
Instruction Name: Register Add.
2) QADD Stack[S] ← Rs + Rb + Carry; Carry ← 0.
Name Instruction: Quick Add.
3) ADD Stack[S-1]Stack[S] + Stack[S-1] + Carry; Carry ← 0; DS ← DS — 1;
Instruction Name: Add.
3.1 Addition
ADDB Stack[S]Stack[S] + zExt[literal] + Carry; Carry ← 0.
Instruction Name: Add Byte.
Opcode: 10010100, 94.
Interpretation of Operands: Signed.
Format: Literal Byte (LB).
0 8 15
opcode | literal
ADDDB Stack[S]Stack[S] + zExt[literal] + Carry; Carry ← 0.
Instruction Name: Add Double byte.
Opcode: 11010100, D4.
Interpretation of operands: Signed.
Format: Literal Halfword (LH).
0 8 23
opcode | literal
ADDQB Stack[S]Stack[S] + zExt[literal] + Carry; Carry ← 0.
Instruction Name: Add Quad Byte.
Opcode: 00110100, 34.
Interpretation of Operands: Signed.
Format: Literal Word (LW).
0 8 39
opcode | literal
ADD Stack[S-1]Stack[S] + Stack[S-1] + Carry; Carry ← 0; DSDS — 1;
Instruction Name: Add.
Opcode: 01000100, 44.
Interpretation of Operands: Signed.
Format: Implicit (I).
0 7
opcode
RADD Rc ← Ra + Rb + Carry; Carry ← 0; trap on overflow.
Instruction Name: Register Add.
Opcode: 11000100, C4.
Interpretation of operands: Signed.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a

QADD Rc ← Ra + Rb + Carry; Carry ← 0; trap on overflow.
Name Instruction: Quick Add.
Opcode: 10000100, 84.
Interpretation of operands: Signed.
Format: Quick Register (QR).
0 8 10 12 15
opcode |c|a|F[]| b
RUADD Rc ← Ra + Rb + Carry; Carry ← CarryOut.
Instruction Name: Register Unsigned Add.
Opcode: 11001110, CE.
Interpretation of operands: Unsigned.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a
RVADD Rc ← Ra + Rb.
Instruction Name: Register Vanilla Add.
Opcode: 11001100, CC.
Interpretation of Operands: Small Integer.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a
3.2 Subtraction
SUBB Stack[S]Stack[S] — zExt[literal] — Carry. Carry ← 0.
Instruction Name: Subtract Byte.
Opcode: 10010101, 95.
Interpretation of operands: Signed.
Format: Literal Byte (LB).
0 8 15
opcode | literal
SUBDB Stack[S]Stack[S] — zExt[literal] — Carry; Carry ← 0.
Instruction Name: Subtract Double Byte.
Opcode: 11010101, D5.
Interpretation of operands: Signed.
Format: Literal Halfword (LH).
0 8 23
opcode | literal
SUBQB Stack[S]Stack[S] — zExt[literal] — Carry; Carry ← 0.
Instruction Name: Subtract Quad Byte.
Opcode: 00110101, 35.
Format: Literal Word (LW).
0 8 39
opcode | literal
SUB Stack[S-1 ] Stack[S-1 ] — Stack[S] — Carry. Carry ← 0; DSDS — 1.
Instruction Name: Substract.
Opcode: 01000101, 45.
Format: Implicit (I).
0 7
opcode
RSUB Rc ← Ra — Rb — Carry. Carry ← 0.
Instruction Name: Register Subtract.
Opcode: 11000101, C5.
Interpretation of operands: Signed.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a
QSUB Rc ← Ra — Rb — Carry; Carry ← 0; trap on overflow.
Instruction Name: Quick Subtract.
Opcode: 10000101, 85.
Interpretation of operands: Signed.
Format: Quick Register (QR).
0 8 10 12 15
opcode |c|a|F[]| b
RUSUB Rc ← Ra — Rb — Carry; Carry ← ~ CarryOut
Instruction Name: Register Unsigned Subtract.
Opcode: 11001111, CF.
Interpretation of operands: Unsigned.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a
RVSUB Rc ← Ra — Rb.
Instruction Name: Register Vanilla Subtract.
Opcode: 11001101, CD.
Interpretaion of Operands: Small Integer.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a
3.3 Logical Operations
AND Stack[S-1]Stack[S] AND Stack[S-1]; DSDS — 1;
Instruction Name: AND.
Opcode: 01000001, 41.
Format: Implicit (I).
0 7
opcode
RAND Rc ← Ra AND Rb.
Instruction Name: Register AND.
Opcode: 11000001, C1.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a
QAND Rc ← Ra AND Rb.
Instruction Name: Quick AND.
Opcode: 10000001, 81.
Format: Quick Register (QR).
0 8 10 12 15
opcode |c|a|F[]| b
OR Stack[S-1]Stack[S] OR Stack[S-1]; DSDS — 1.
Instruction Name: OR.
Opcode: 01000000, 40.
Format: Implicit (I).
0 7
opcode
ROR Rc ← Ra OR Rb.
Instruction Name: Register OR.
Opcode: 11000000, C0.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a

QOR Rc ← Ra OR Rb.
Instruction Name: Quick OR.
Opcode: 10000000, 80.
Format: Quick Register (QR).
0 8 10 12 15
opcode |c|a|F[]| b
RXOR Rc ← Ra XOR Rb.
Instruction Name: Register XOR.
Opcode: 11001000, C8.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a
3.4 Loads
The word load is used in an instruction name if the instruction pushes something onto the EU stack. The word read is used in the instruction name if the instruction retrieves something from memory. (c.f. Store/write, section 3.5)
LIB Stack[S+1] ← zExt[literal]; DSDS + 1.
Instruction Name: Load Immediate Byte.
Opcode: 10010010, 92.
Format: Literal Byte (LB).
0 8 15
opcode | literal
LIDB Stack[S+1] ← zExt[literal]; DSDS + 1.
Instruction Name: Load Immediate Double Byte.
Opcode: 11010010, D2.
Format: Literal Halfword (LH).
0 8 23
opcode | literal
LIQB Stack[S+1] ← literal; DSDS + 1.
Instruction Name: Load Immediate Quad Byte.
Opcode: 00110010, 32.
Format: Literal Word (LW).
0 8 39
opcode | literal
LRn Stack[S+1] ← Locals[n]; DSDS + 1. n IN[0..16).
Instruction Name: Load Register n.
Opcodes: 01100000 — 01101111, 60 — 6F.
Format: Locals Register (LR).
0 4 7
op | n
Note: The opcode for the LRn, LCm, LRIn, SRn, and SRIn can be viewed as (opcode + (n | m)). (c.f. the instruction map contained in [Indigo]<Dragon>Documentation>PrincOps>InstructionSetSum.tioga.)
LCm Stack[S+1] ← Constants[m]; DSDS + 1. m IN[0..12).
Instruction Name: Load Constant m.
Opcodes: 00010000 - 00011011, 10 - 1C (12 instructions).
Format: Implicit (I).
0 7
opcode
Note: The opcode for the LRn, LCm, LRIn, SRn, and SRIn can be viewed as (opcode + (n | m)). (c.f. the instruction map contained in [Indigo]<Dragon>Documentation>PrincOps>InstructionSetSum.tioga.)
LRIn Stack[S+1] ← Mem[Locals[n] + zExt[offset]]; DSDS + 1. n IN[0..16)..
Instruction Name: Load Register Indexed n.
Opcodes: 10100000 — 10101111, A0 - AF.
Format: Index Register Offset (XO).
0 4 8 15
op | n | offset
Note: The opcode for the LRn, LCm, LRIn, SRn, and SRIn can be viewed as (opcode + (n | m)). (c.f. the instruction map contained in [Indigo]<Dragon>Documentation>PrincOps>InstructionSetSum.tioga.)
RB Stack[S] ← Mem[Stack[S] + zExt[literal]]).
Instruction Name: Read using byte offset.
Opcode: 10011000, 98.
Format: Literal Byte (LB).
0 8 15
opcode | literal
QRX Rc ← Mem[Ra + Rb].
Instruction Name: Quick Read indeXed.
Opcode: 10000010, 82.
Format: Quick Register (QR).
0 8 10 12 15
opcode |c|a|F[]| b
Note: This is a short form of RRX.
RSB Stack[S+1] ← Mem[Stack[S] + zExt[literal]]; DSDS + 1.
Instruction Name: Read Save using Byte offset.
Opcode: 10011010, 9A.
Format: Literal Byte (LB).
0 8 15
opcode | literal
RRX Rc ← Mem[Ra + Rb].
Instruction Name: Register Read indeXed.
Opcode: 11000010, C2.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a
RX Stack[S-1] ← Mem[Stack[S-1] + Stack[S]]; DSDS — 1.
Instruction Name: Read indeXed.
Opcode: 01000010, 42.
Format: Implicit (I).
0 7
opcode
LGF Stack[S+1] ← Mem[Aux[0] + zExt[literal]]; DSDS + 1.
Instruction Name: Load Global Frame.
Opcode: 11010000, D0.
Format: Literal Halfwork (LH).
0 8 23
opcode | literal
Note: This instruction may be used to load the global frame pointer from the global frame table into a Stack register. In general, the LIQB instruction is faster than the LGF instruction because it loads the global frame pointer from the instruction stream, not from memory.
RRI Locals[regA] ← Memory[Locals[regB] + zExt[offset]].
Instruction Name: Read Register Indexed.
Opcode: 11011010, DA.
Format: Index—Register Register—Offset (XRO).
0 8 16 20 23
opcode | offset | regA | regB
RAI Locals[regA] ← Mem[Aux[regB] + zExt[offset]].
Instruction Name: Read Auxiliary register Indexed.
Opcode: 11011000, D8.
Format: Index—Register Register—Offset (XRO).
0 8 16 20 23
opcode | offset | regA | regB
LIP Stack[S+1] ← ProcReg[literal]; DSDS + 1.
Instruction Name: Load from Internal Processor register.
Opcode: 10010000, 90.
Format: Literal Byte (LB).
0 8 15
opcode | literal
Notes:
1) ProcReg is an abbreviation for Processor Registers. It is an enumerated type of 256 registers that includes all registers which can be accessed using LIP and SIP (Store to Internal Processor register) instructions. For a complete listing of the accessible registers contained in ProcReg see Chapter 2.0.
2) LIP[EldestPC] is illegal in user mode.
3) LIP requires 1 cycle on any EU register and 5 cycles on any IFU register. The extra cycles on IFU registers are required to ensure that instructions immediately before the LIP do not modify the register that LIP is reading.
4) The Field register read by LIP is a shadow copy of the collection of gates which actually control the field unit; the shadow copy exists to facilitate saving and restoring the state of the field unit on a process switch. The shadow register is loaded whenever the Field register is loaded by either SIP or FSDB.
5) A LIP to an undefined register number, [160..239] or [246..255], will cause no harmful effect and manipulate the stack in the normal way; the value pushed is undefined. Register numbers in the range [0..239] have the same timing as a legal EU LIP; [240..255] have the same timing as a legal IFU LIP.
3.5 Stores
In general, the word store is used in an instruction name if the instruction moves data from Stack to an EU register ( Locals[], Constants[] or AuxRegs[]). The word write is used if the instruction moves data from Stack to Memory. Put Swapped is used for instructions that take a pointer and value from Stack, write the value to Memory at a small offset from the pointer, pop the value from the Stack, and leave the pointer on Stack. Write Swapped is like Put Swapped except that the pointer is not left on top of Stack. (The SRI instruction does not follow these conventions.)
EXDIS Stack[S—1]Stack[S]; DSDS — 1.
Instruction Name: EXchange DIScard.
Opcode: 01001011, 4B.
Format: Implicit (I).
0 7
opcode
DUP Stack[S+1]Stack[S]; DSDS + 1.
Instruction Name: Duplicate.
Opcode: 01001000, 48.
Format: Implicit (I).
0 7
opcode
SRn Locals[n] ← Stack[S]; DSDS — 1. n IN[0..16).
Instruction Name: Store Register n.
Opcodes: 01110000 — 01111111, 70 - 7F.
Format: Locals Register (LR).
0 4 7
op | n
WB Mem[Stack[S] + zExt[literal]] ← Stack[S—1]; DSDS — 2.
Instruction Name: Write using Byte offset.
Opcode: 10011001, 99.
Format: Literal Byte (LB).
0 8 15
opcode | literal
Note: The opcode for the LRn, LCm, LRIn, SRn, and SRIn can be viewed as (opcode + (n | m)). (c.f. the instruction map contained in [Indigo]<Dragon>Documentation>PrincOps>InstructionSetSum.tioga.)
WSB Mem[Stack[S—1] + zExt[literal]] ← Stack[S]; DSDS — 2.
Instruction Name: Write Swapped using Byte offset.
Opcode: 10011011, 9B.
Format: Literal Byte (LB).
0 8 15
opcode | literal
PSB Mem[Stack[S—1] + zExt[literal]] ← Stack[S]; DSDS — 1.
Instruction Name: Put Swapped using Byte offset.
Opcode: 10011111, 9F.
Format: Literal Byte (LB).
0 8 15
opcode | literal
SRIn Mem[Locals[n] + zExt[offset]] ← Stack[S]; DSDS — 1. n IN[0..16)..
Instruction Name: Store Register Indexed n.
Opcodes: 10110000 — 10111111, B0 - BF.
Format: Index Register Offset (XO).
0 4 8 15
op | n | offset
Note: The opcode for the LRn, LCm, LRIn, SRn, and SRIn can be viewed as (opcode + (n | m)). (c.f. the instruction map contained in [Indigo]<Dragon>Documentation>PrincOps>InstructionSetSum.tioga.)
SIP ProcReg[literal] ← Stack[S];
Instruction Name: Store to Internal Processor register.
Opcode: 10010001, 91.
Format: Literal Byte (LB).
0 8 15
opcode | literal
Notes:
SIP is the most efficient way to store into AuxRegs or Constants. See the table in Chapter 2.0 for the interpretation of the literal byte as a register number.
1) SIP is illegal in user mode.
2) SIP requires 1 cycle on any EU register, 5 cycles on any IFU register; the extra cycles on IFU registers ensure that the immediately following instructions do not use the register which SIP is modifying and that no K bus conflict occurs when SIP sends its data from the EU back to the IFU.
3) Any SIP to an undefined register number, [160..239] or [246..255], will cause no harmful effect and manipulate the stack in the normal way; 128 (Spare) may also be an undefined register; SIP[ToKbus] may interfere with K bus use by following instructions.
WRI Mem[Locals[regB] + zExt[offset]] ← Locals[regA].
Instruction Name: Write Register Indexed.
Opcode: 11011011, DB.
Format: Index—Register Register—Offset (XRO).
0 8 16 20 23
opcode | offset | regA | regB
WAI Mem[Aux[regB] + zExt[offset]] ← Locals[regA].
Instruction Name: Write Auxilliary register Indexed.
Opcode: 11011001, D9.
Format: Index—Register Register—Offset (XRO).
0 8 16 20 23
opcode | offset | regA | regB
CST (Stack[S+1] ← Mem[Stack[S-2] + zExt[literal]]; If Stack[S+1] = Stack[S] then Mem[Stack[S-2] + zExt[literal]] ← Stack[S-1]; DSDS + 1.)
Instruction Name: Conditional Store.
Opcode: 10001100, 8C.
Format: Literal Byte (LB).
0 8 15
opcode | literal
Note: CST is a instruction that is used to conditionally modify the contents of a memory location. The instruction has one explicit operand and three implicit operands from Stack. The explicit operand is used to compute a memory location, Mem[Stack[S-2] + zExt[literal]]. The three operands from Stack contain the following information:
Stack[S] = oldContents
Stack[S-1] = newContents
Stack[S-2] = basePointer
The CST instruction has the effect of atomically executing the following code:
sample: Word ← Mem[basePointer + zExt[literal]];
IF
sample = oldContents THEN Mem[basePointer + zExt[literal]] ← newContents;
Push[sample];
When the CST instruction completes, the stack pointer has increased by one (modulo the stack size) and the following words are on the stack:
Stack[S] = sample
Stack[S-1] = oldContents
Stack[S-2] = newContents
Stack[S-3] = basePointer
If the the top two words on the stack are equal, the CST has stored the new contents into the memory location. The testing and storing performed by the CST instruction are synchronized among all processors in a Dragon system. CST is primarily used to implement system primitives that synchronize processes in a system that can (potentially) use multiple processors. For complete details of the synchronization see Chapter 4.xx.
The CST instruction has a minimum cost of 3 cycles when the word is not shared with another cache, and 8 cycles when the word is shared with another cache. This cost may change with implementation changes. Bus arbitration and cache misses may increase the cost.
3.6 Input/Output Operations
Input/output or IO instructions call a Dragon processor to communicate directly with any device on the P bus. Since one of these devices is the EU cache, a processor can even do reads and writes to memory using these instructions, in addition to the normal functions of invoking IO operations.
The IO instructions have two explicit operands: an eight-bit address and a PCommand. The low-order bit of PCommand determines whether the instruction is a read or write. Inside the Dispatch procedure performed by the IO instructions, the high order bit of PCommand determines whether the instruction performs a cache or non-cache operation, in the following manner:
1. If the high-order bit is a zero, the PCommand is a non-cache operation. At the present time (September 30, 1986) none of the non-cache operations to be performed by the IO instructions has been implemented. Future versions of Dragon will use some of these reserved non-cache operations to control the floating-point unit.
2. If the high-order bit is a one, the PCommand is one of the seven cache operations defined below in PBusOps.mesa.
3. If the value of the entire PCommand is zero the instruction is a NoOp.
Non-cache operations divide the PCommand into two fields, a flag and a seven-bit reserved space, as follows:
0 1 7
f| 7bitfld
Here are the definitions for the fields used in the non-cache variant of the PCommand:
f = cacheFlag = 0
CacheFlag determines whether the instruction performs a cache or non-cache operation.
7bitfld = SevenBitField
SevenBitField will be use to select non-cache operations in future versions of the Dragon processor.
Cache operations divide the PCommand into four fields: a cache flag, a four-bit field, a two-bit field, and a read/write flag as follows:
0 1 5 7
f| 4bf |2bf|rw
Here are definitions for the fields used in the cache variant of the PCommand:
f = cacheFlag = 1
CacheFlag determines whether the instruction performs a cache or non-cache operation.
4bf = FourBitField
FourBitField is used for write operations to determine which bytes of a word are to be written. For example, if the first bit of FourBitField is a 1, the high-order byte of the cache memory word will be written. If the first two bits of FourBitField are 1's, the high half-word of cache memory will be written. (Note: Read operations always read a complete word.)
2bt = TwoBitField
TwoBitField is used to determine which cache operation is performed. (See PBusOpsImpl.mesa below for the complete decoding.)
rw = ReadOrWrite
ReadOrWrite is a bool that determines whether the operation to be performed is a read or a write. False (0) means read, true (1) means write.
In addition to the two explicit operands, the IO instructions use one or two implicit operands from Stack. Instructions that perform writes get their data from Stack. The instructions that perform reads read data into Stack[S] or Stack[S+1]. The IODA instructions use Stack[S] to increment the address information contained in the explicit address field.
Here are the definitions used in implementing the IO instructions:
DIRECTORY
CacheDefs,
DragOpsCross USING [Inst];
PBusDefs: CEDAR DEFINITIONS = {
Mappings between bit patterns found in the instructions and logical names.
Bit: TYPE ~ MACHINE DEPENDENT { zero (0), one (1) };
BitsPerWord: INT ~ 32;
BitsPerByte: INT ~ 8;
ByteBitIndex: TYPE ~ INT [0..BitsPerByte);
Byte: TYPE ~ PACKED ARRAY ByteBitIndex OF Bit;
ZerosByte: Byte ~ ALL[Bit.zero];
BytesPerWord: INT ~ BitsPerWord / BitsPerByte; -- better divide evenly!
ByteIndex: TYPE ~ INT [0..BytesPerWord);
Word: TYPE ~ PACKED ARRAY ByteIndex OF Byte;
ZerosWord: Word = ALL[ZerosByte];
TwoBitIndex: TYPE ~ INT [0..2);
TwoBitField: TYPE ~ PACKED ARRAY TwoBitIndex OF Bit;
SevenBitIndex: TYPE ~ INT [0..7);
SevenBitField: TYPE ~ PACKED ARRAY SevenBitIndex OF Bit;
FourBitIndex: TYPE ~ INT [0..4);
FourBitField: TYPE = PACKED ARRAY FourBitIndex OF Bit;
PCommand: TYPE ~ MACHINE DEPENDENT RECORD [
SELECT cacheFlag: Bit FROM
zero => [
nonCacheSelector: SevenBitField
],
one => [
writeByteSelector: FourBitField,
operation: TwoBitField,
rw: Bit
]
ENDCASE
];
NonCacheOperation: TYPE ~ PCommand.zero;
CacheOperation: TYPE ~ PCommand.one;
LiteralIOFormat: TYPE ~ MACHINE DEPENDENT RECORD [
opcode: DragOpsCross.Inst, -- the IODA, IOD, ION instructions --
address: CacheDefs.Address,
pCmd: PCommand,
pad: Byte ← ALL[zero] -- to make the compiler happy --
];
Translations from bit patterns to PBusOperations.
Dispatch: PUBLIC PROCEDURE [anAddress: Byte, data: Word ← ZerosWord, aPCommand: PCommand] RETURNS [result: Word];
CacheMemRead: PROCEDURE[anAddress: Byte] RETURNS [result: Word];
Reads a word from the given address in virtual memory.
CacheMemWrite: PROCEDURE[anAddress: Byte, data: Word, writeByteSelector: FourBitField] RETURNS [];
Writes one to four bytes to the given address in virtual memory.
CacheMemReadSpecial: PROCEDURE[anAddress: Byte] RETURNS [result: Word];
Invokes the conditional store operation on the arguments provided.
CacheNoOp: PROCEDURE[] RETURNS [];
CacheIORead: PROCEDURE[anAddress: Byte] RETURNS [result: Word];
Reads a word from the given address in I/O space.
CacheIOWrite: PROCEDURE[anAddress: Byte, data: Word] RETURNS [];
Writes a word to the given address in I/O space. Exactly one device must respond.
CacheBroadcastIOWrite: PROCEDURE[anAddress: Byte, data: Word, writeByteSelector: FourBitField] RETURNS [];
Writes from one to four bytes to the given address in I/O space. More than one device may respond.
NoOp: PROCEDURE[] RETURNS [];
ReservedNonCacheOp: PROCEDURE[anAddress: Byte] RETURNS [];
}.
—————
CacheDefs: CEDAR DEFINITIONS = {
Mappings between bit patterns found in the instructions and logical names.
Address: TYPE ~ CARD[0..256);
}.
—————
PBusDefsImpl: CEDAR PROGRAM
IMPORTS PBusDefs
EXPORTS PBusDefs
~ { OPEN PBusDefs;
IsRead: PROCEDURE [aPCommand: PCommand] RETURNS [answer: BOOL] = {
WITH aPCommand SELECT FROM
aNonCacheOperation: NonCacheOperation => {
RETURN [FALSE];
};
aCacheOperation: CacheOperation => {
RETURN [aCacheOperation.rw = Bit.zero];
};
ENDCASE => ERROR;
};
IsWrite: PROCEDURE [aPCommand: PCommand] RETURNS [answer: BOOL] = {
WITH aPCommand SELECT FROM
aNonCacheOperation: NonCacheOperation => {
RETURN [FALSE];
};
aCacheOperation: CacheOperation => {
RETURN [aCacheOperation.rw = Bit.one];
};
ENDCASE => ERROR;
};
Dispatch: PUBLIC PROCEDURE [
anAddress: Byte,
data: Word ← ZerosWord,
aPCommand: PCommand]
RETURNS
[result: Word] = {
WITH aPCommand SELECT FROM
aNonCacheOperation: NonCacheOperation => {
result ← ZerosWord;
SELECT aNonCacheOperation.nonCacheSelector FROM
ALL[Bit.zero] =>
[] ← NoOp[];
ENDCASE =>
[] ← ReservedNonCacheOp[anAddress];
};
aCacheOperation: CacheOperation => {
SELECT aCacheOperation.rw FROM
Bit.zero => {
SELECT aCacheOperation.operation FROM
TwoBitField[Bit.zero, Bit.zero] =>
result ← CacheMemRead[anAddress];
TwoBitField[Bit.zero, Bit.one] =>
result ← CacheMemReadSpecial[anAddress];
TwoBitField[Bit.one, Bit.zero] =>
result ← CacheIORead[anAddress];
TwoBitField[Bit.one, Bit.one] => {
result ← ZerosWord;
[] ← CacheNoOp[];
};
ENDCASE => ERROR;
};
Bit.one => {
result ← ZerosWord;
SELECT aCacheOperation.operation FROM
TwoBitField[Bit.zero, Bit.zero] => {
[] ← CacheMemWrite[
anAddress: anAddress,
data: data,
writeByteSelector: aCacheOperation.writeByteSelector]};
TwoBitField[Bit.zero, Bit.one] =>
[] ← CacheNoOp[];
TwoBitField[Bit.one, Bit.zero] =>
[] ← CacheIOWrite[anAddress, data];
TwoBitField[Bit.one, Bit.one] =>
[] ← CacheBroadcastIOWrite[
anAddress: anAddress,
data: data,
writeByteSelector: aCacheOperation.writeByteSelector];
ENDCASE => ERROR;
};
ENDCASE => ERROR;
};
ENDCASE => ERROR;
};
}.
IOD
IsRead[PCommand] => Stack[S+1] ← Dispatch[anAddress: Address, aPCommand: PCommand]; DSDS + 1;
IsWrite[PCommand] => [] ← Dispatch[anAddress: Address, data: Stack[S], aPCommand: PCommand]; DSDS - 1;
Instruction Name: I/O with Data from stack.
Opcode: 11011101, DD.
Format: Literal Input/Output (LIO).
0 8 16 23
opcode | address | PCommand
Note: The kernel/user modeBit is sent to the IO device. The IO device determines whether the requested instruction is legal in the current mode.
IODA
IsRead[PCommand] => Stack[S] ← Dispatch[anAddress: Address + Stack[S], aPCommand: PCommand];
IsWrite[PCommand]=> [] ← Dispatch[anAddress: Address + Stack[S], data: Stack[S-1], aPCommand: PCommand];
DSDS - 2;
Instruction Name: I/O with Data and Address from Stack.
Opcode: 11011100, DC.
Format: Literal Input/Output (LIO).
0 8 16 23
opcode | address | PCommand
Note: The kernel/user modeBit is sent to the IO device. The IO device determines whether the requested instruction is legal in the current mode.
ION
IsRead[PCommand] => Stack[S+1] ← Dispatch[anAddress: Address, aPCommand: PCommand];
IsWrite[PCommand] => [] ← Dispatch[anAddress: Address, data: Stack[S], aPCommand: PCommand];
Instruction Name: I/O with No stack adjust.
Opcode: 11011110, DE.
Format: Literal Input/Output (LIO).
0 8 16 23
opcode | address | PCommand
Note: The kernel/user modeBit is sent to the IO device. The IO device determines whether the requested instruction is legal in the current mode.
3.7 Field Unit Operations
See Chapter 2.2.3 for a complete explanation of the Field Unit.
FSDB FieldDescriptor ← Stack[S] + literal. DSDS — 1.
Instruction Name: Field Setup Double Byte.
Opcode: 11010011, D3.
Format: Literal Halfword (LH).
0 8 23
opcode | literal
Note: This instruction is equivalent to (but smaller and faster than) the two instructions, Add Double Byte (ADDDB) and Store to Internal Processor register (SIP).
RFU Rc ← FieldUnit.Operate[Ra, Rb, FieldDescriptor]
Instruction Name: Register Field Unit.
Opcode: 11001010, CA.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a
Note: This a general shift operation, including extract, insert, and shift. The Field register supplies the field descriptor.
SHL Stack[S] ← FieldUnit.Operate[Stack[S], 0, literal].
Instruction Name: Shift Left.
Opcode: 11111000, F8.
Format: Literal Halfword (LH).
0 8 23
opcode | literal
Note: This operation shifts and masks a single word. This single word is passed to Procedure FieldUnit.Operate as the Left argument. The Right argument to Procedure FieldUnit.Operate is zero. The 16-bit constant contained in literal determines the action taken. (SHL does not use or affect the Field register.) This instruction is particularly useful for left shifting, all or some right justified portion of a word.
Example:
Left Shift - If (FD.insert = false & FD.mask = 32) then FD.shift = the number of bits the original input word will be left-shifted. (Zeros are inserted on right end.)
SHR Stack[S] ← FieldUnit.Operate[Stack[S], Stack[S], literal].
Instruction Name: Shift Right.
Opcode: 11111001, F9.
Format: Literal Halfword (LH).
0 8 23
opcode | literal
Note: This operation shifts and masks a single word. This single word, Stack[S], is passed to Procedure FieldUnit.Operate as both the Left and Right arguments. The 16-bit constant contained in literal determines the action taken. (SHR does not user or affect the Field register.) It is particularly useful for shifting right, rotating words, and extracting fields.
Examples:
Right Shift - If (fieldOp.insert = false & fieldOp.shift= fieldOp.width) then 32 - fieldOp.shift = the number of bits the original input word will be right-shifted.
Rotate - If (fieldOp.insert = false & fieldOp.width = 32) then 32 - fieldOp.shift = the number of bits to right rotate from the original input.
Extract - If ( fieldOp.insert = false & fieldOp.shift >= fieldOp.width) then the final output will contain a right- justified field of length fieldOp.width extracted from the operand at bit (fieldOp.shift - 1).
SHDL Stack[S-1] ← FieldUnit.Operate[Stack[S-1], Stack[S], literal]; DSDS — 1.
Instruction Name: Shift Double Left.
Opcode: 11111010, FA.
Format: Literal Halfword (LH).
0 8 23
opcode | literal
Note: This operation shifts and masks double words. The two words, Stack[S-1] and Stack[S] are passed to Procedure FieldUnit.Operate as the Left and Right arguments, respectively. The 16-bit constant contained in literal determines the action taken. (SHDL does not use or affect the Field register.) It is especially useful for extracting arbitrary fields from a pair of words, or inserting fields.
Examples:
Extract - If ( FD.insert = false & FD.shift > FD.mask) then the final output will contain field of length FD.mask inserted into array of 32 zero's at bit position (32 -Fd.shift).
Insert - If (fieldOp.insert = true & fieldOp.width > fieldOp.shift then the final ouput will contain a field of length (fieldOp.width - fieldOp.shift) extracted from the original word beginning at bit position fieldOp.Shift + (32 - fieldOp.width) and inserted into the original input word at bit position (32 - fieldOp.shift).
SHDR Stack[S-1] ← FieldUnit.Operate[Stack[S], Stack[S-1], literal]; DSDS — 1.
Instruction Name: Shift Double Right.
Opcode: 11111011, FB.
Format: Literal Halfword (LH).
0 8 23
opcode | literal
Note: This instruction has the same semantics as SHDL with one exception: Stack[S] is the left argument and Stack[S-1] is the right argument to Procedure FieldUnit.Operate.
3.8 The IFU Indices — S and L
The S and L indices are numbers in the range [0..127]. The literal values added to these indices are also in the range [0..127]. Future versions of Dragon may double the size of the S and L indices, making S, L and the literal values used to increment them unsigned 8-bit quantities.
DIS SS — 1.
Instruction Name: Discard.
Opcode: 01001001, 49.
Format: Implicit (I).
0 7
opcode
Note: DIS is a frequently used short form for AS 127.
AL LL + literal.
Instruction Name: Add to L.
Opcode: 10001001, 89.
Interpretation of operands: Small Integer.
Format: Literal Byte (LB).
0 8 15
opcode | literal
Note: Used primarily for saving and restoring stack frames.
ALS LS + literal.
Instruction Name: Add to L from Stack.
Opcode: 10001000, 88.
Interpretation of operands: Small Integer.
Format: Literal Byte (LB).
0 8 15
opcode | literal
Note: Used at procedure entry to establish the base register index of the local frame.
AS SS + literal.
Instruction Name: Add to Stack.
Opcode: 10001011, 8B.
Interpretation of operands: Small Integer.
Format: Literal Byte (LB).
0 8 15
opcode | literal
Note: EU Stack overflow occurs when an instruction puts S in the range [SLimit..Slimit+16). The literal argument for AS should not be larger than 15; if it is, it may invalidate the test for EU Stack overflow. (A literal argument of 16 would detect EU Stack overflow, but would not leave an extra word necessary to push the IFUStatus.)
ASL SL + literal.
Instruction Name: Add to Stack from L.
Opcode: 10001010, 8A.
Interpretation of operands: Small Integer.
Format: Literal Byte (LB).
0 8 15
opcode | literal
Note: See note for AS.
3.9 - 3.11 Transfers of Control
For an explanation of the Instruction Fetch/Execute loop see Chapter 2.1.
3.9 No Operation (NoOps)
NoOps look like short jumps except that they do not clear the pre-fetch buffer in the IFU.
J1 No Operation.
Instruction Name: Jump One (1).
Opcode: 01010110, 56.
Format: Implicit (I).
0 7
opcode
Note: This instruction jumps over itself, a single byte.
J2 No Operation.
Instruction Name: Jump Two (2).
Opcode: 10010110, 96.
Format: Literal Byte (LB).
0 8 15
opcode | literal
Note: This instruction jumps over itself (two bytes).
J3 No Operation.
Instruction Name: Jump Three (3).
Opcode: 11010110, D6.
Format: Literal Halfword (LH).
0 8 23
opcode | literal
Note: This instruction jumps over itself (three bytes).
J5 No Operation.
Instruction Name: Jump Five (5).
Opcode: 00110110, 36.
Format: Literal Word (LW).
0 8 39
opcode | literal
Note: This instruction jumps over itself (five bytes).
3.10 Unconditional Jumps
JB PCPC + sExt[literal].
Instruction Name: Jump using Byte offset.
Opcode: 10010111, 97.
Format: Literal Byte (LB).
0 8 15
opcode | literal
JDB PCPC + sExt[literal].
Instruction Name: Jump using Double Byte offset.
Opcode: 11010111, D7.
Format: Literal Halfword (LH).
0 8 23
opcode | literal
JQB PC ← literal.
Instruction Name: Jump using Quad Byte offset.
Opcode: 00110111, 37.
Format: Literal Word (LW).
0 8 39
opcode | literal
Note: This instruction is useful in trap vectors and other long transfers.
JSD PC ← Stack[S]; DSDS — 1.
Instruction Name: Jump Stack Direct.
Opcode: 01001111, 4F.
Format: Implicit (I).
0 7
opcode
JSR PCPC + Stack[S]; DSDS — 1.
Instruction Name: Jump Stack Relative.
Opcode: 01010111, 57.
Format: Implicit (I).
0 7
opcode
3.11 Conditional Jumps
The conditional jump instructions are defined in pairs. One instruction of each pair predicts that the jump should be taken; its mnemonic includes a trailing lowercase j. The other instruction of the pair predicts that the jump should not be taken and does not include the trailing j.
RJEBj If Rs = Rb then PCPC + sExt[displacement].
Instruction Name: Register Jump Equal Byte. Jump predicted.
Opcode: 11101101, ED.
Format: Register Displacement (RD).
0 8 10 12 16 23
opcode |Rs|F[]| b | displ
RJEB If Rs = Rb then PCPC + sExt[displacement].
Instruction Name: Register Jump Equal Byte. Jump not predicted.
Opcode: 11100001, E1.
Format: Register Displacement (RD).
0 8 10 12 16 23
opcode |Rs|F[]| b | displ
JEBBj If Stack[S] = zExt[literal] then PCPC + sExt[displacement]; DSDS — 1.
Instruction Name: Jump Equal Byte Byte. Jump predicted.
Opcode: 11110010, F2.
Format: Literal Byte Displacement (LBD).
0 8 16 23
opcode | literal | displ
JEBB If Stack[S] = zExt[literal] then PCPC + sExt[displacement]; DSDS — 1.
Instruction Name: Jump Equal Byte Byte. Jump not predicted.
Opcode: 11110000, F0.
Format: Literal Byte Displacement (LBD).
0 8 16 23
opcode | literal | displ

JNEBBj If Stack[S] ~= zExt[literal], then PCPC + sExt[displacement]; DSDS — 1.
Instruction Name: Jump Not Equal Byte Byte. Jump predicted.
Opcode: 11110011, F3.
Format: Literal Byte Displacement (LBD).
0 8 16 23
opcode | literal | displ
JNEBB If Stack[S] ~= zExt[literal], then PCPC + sExt[displacement]; DSDS — 1.
Instruction Name: Jump Not Equal Byte Byte. Jump not predicted.
Opcode: 11110001, F1.
Interpretation of Operands: Signed.
Format: Literal Byte Displacement (LBD).
0 8 16 23
opcode | literal | displ

RJNEBj If Rs ~= Rb then PCPC + sExt[displacement].
Instruction Name: Register Jump Not Equal Byte. Jump predicted.
Opcode: 11101001, E9.
Format: Register Displacement (RD).
0 8 10 12 16 23
opcode |Rs|F[]| b | displ
RJNEB If Rs ~= Rb then PCPC + sExt[displacement].
Instruction Name: Register Jump Not Equal Byte. Jump not predicted.
Opcode: 11100101, E5.
Format: Register Displacement (RD).
0 8 10 12 16 23
opcode |Rs|F[]| b | displ
RJGBj If Rs > Rb then PCPC + sExt[displacement].
Instruction Name: Register Jump Greater Byte. Jump predicted.
Opcode: 11101011, EB.
Interpretation of Operands: Signed.
Format: Register Displacement (RD).
0 8 10 12 16 23
opcode |Rs|F[]| b | displ
RJGB If Rs > Rb then PCPC + sExt[displacement].
Instruction Name: Register Jump Greater Byte. Jump not predicted.
Opcode: 11100111, E7.
Interpretation of Operands: Signed.
Format: Register Displacement (RD).
0 8 10 12 16 23
opcode |Rs|F[]| b | displ
RJGEBj If Rs >= Rb then PCPC + sExt[displacement].
Instruction Name: Register Jump Greater Equal Byte. Jump predicted.
Opcode: 11101010, EA.
Interpretation of Operands: Signed.
Format: Register Displacement (RD).
0 8 10 12 16 23
opcode |Rs|F[]| b | displ
RJGEB If Rs >= Rb then PCPC + sExt[displacement].
Instruction Name: Register Jump Greater Equal Byte. Jump not predicted.
Opcode: 11100110, E6.
Interpretation of Operands: Signed.
Format: Register Displacement (RD).
0 8 10 12 16 23
opcode |Rs|F[]| b | displ
RJLBj If Rs < Rb then PCPC + sExt[displacement].
Instruction Name: Register Jump Less Byte. Jump predicted.
Opcode: 11101110, EE.
Interpretation of Operands: Signed.
Format: Register Displacement (RD).
0 8 10 12 16 23
opcode |Rs|F[]| b | displ
RJLB If Rs < Rb then PCPC + sExt[displacement]
Instruction Name: Register Jump Less Byte. Jump not predicted.
Opcode: 11100010, E2.
Interpretation of Operands: Signed.
Format: Register Displacement (RD).
0 8 10 12 16 23
opcode |Rs|F[]| b | displ
RJLEBj If Rs <= Rb then PCPC + sExt[displacement].
Instruction Name: Register Jump Less Equal Byte. Jump predicted.
Opcode: 11101111, EF.
Interpretation of Operands: Signed.
Format: Register Displacement (RD).
0 8 10 12 16 23
opcode |Rs|F[]| b | displ
RJLEB If Rs <= Rb then PCPC + sExt[displacement].
Instruction Name: Register Jump Less Equal Byte. Jump not predicted.
Opcode: 11100011, E3.
Interpretation of Operands: Signed.
Format: Register Displacement (RD).
0 8 10 12 16 23
opcode |Rs|F[]| b | displ
3.12 Bounds Checks
The following instructions interpret their operands as 32-bit unsigned quantities. These instructions are used to check indexes against bounds and when a number is narrowed to fit into a subrange. In using the instructions for bounds-checking, the original range a <= num < b is first reduced to 0 <= num - a < b - a; after this reduction, unsigned arithmetic is appropriate for determining whether num - a is within the desired range. The hardware checks for number >= bound by trapping iff bound - number - 1 doesn't produce carry-out = 1.
RBC If (Ra < Rb ) then Rc ← Ra else trap.
Instruction Name: Register Bounds Check.
Opcode: 11000011, C3.
Interpretation of Operands: Unsigned.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a
BC If NOT[Stack[S-1] < Stack[S]] then trap; DSDS — 1.
Instruction Name: Bounds Check.
Opcode: 01000011, 43.
Interpretation of Operands: Unsigned.
Format: Implicit (I).
0 7
opcode
Note: BC is a short form of RBC that may be used when testing values that are from the stack.
QBC If (Ra < Rb ) then Rc ← Ra else trap.
Instruction Name: Quick Bounds Check.
Opcode: 10000011, 83.
Interpretation of Operands: Unsigned.
Format: Quick Register (QR).
0 8 10 12 15
opcode |c|a|F[]| b
Note: This is a short form of RBC.
3.13 Procedure Calls and Returns
When a procedure is called, the current PC and the Status are pushed onto the IFU Stack.
SaveState: PROCEDURE [PC, Status] RETURNS [] = {
Youngest ← Youngest + 1;
handleOverflow;
IFUStack[youngest] ← [PC, Status];
};
When the overflow trap is taken, the IFU Stack contains 12 entries. Upon return, PC and Status.LBase (L) are assigned youngest values from the IFUStack:
ReturnState: PROCEDURE [] RETURNS [PC, Status] = {
[PC, Status] ← IFUStack[youngest];
Youngest ← Youngest — 1;
};
LFC SaveState[PC, Status]; PCPC + sExt[literal].
Instruction Name: Local Function Call.
Opcode: 11010001, D1.
Format: Literal Halfword (LH).
0 8 23
opcode | literal
DFC SaveState[PC, Status]; PC ← literal.
Instruction Name: Direct Function Call.
Opcode: 00110001, 31.
Format: Literal Word (LW).
0 8 39
opcode | literal
SFC SaveState[PC, Status]; PCStack[S]; DSDS — 1.
Instruction Name: Stack Function Call.
Opcode: 01001100, 4C.
Format: Implicit (I).
0 7
opcode
SFCI SaveState[PC, Status]; PC ← Mem[Stack[S]].
Instruction Name: Stack Function Call Indirect.
Opcode: 01001101, 4D.
Format: Implicit (I).
0 7
opcode
KFC SaveState[PC, Status]; Set kernel mode; PC ← InstTrap[KFC].
Instruction Name: Kernel Function Call.
Opcode: 01010100, 54.
Format: Implicit (I).
0 7
opcode
Note: This instruction is used by user (or kernel) mode code to call kernel operations.
RETN ReturnState[PC, Status];
Instruction Name: RETurn No adjustment to S.
Opcode: 01001110, 4E.
Format: Implicit (I).
0 7
opcode
RET SL + literal; ReturnState[PC, Status];
Instruction Name: RETurn.
Opcode: 10001110, 8E.
Format: Literal Byte (LB).
0 8 15
opcode | literal
3.14 Lisp Instructions
LADD Stack[S-1]Stack[S-1] + Stack[S]; Carry ← 0. DSDS — 1.
Instruction Name: Lisp ADD.
Opcode: 01000110, 46.
Interpretation of Operands: Lisp.
Format: Implicit (I).
0 7
opcode
QLADD Rc ← Ra + Rb; Carry ← 0.
Instruction Name: Quick Lisp Add.
Opcode: 10000110, 86.
Interpretation of operands: Lisp.
Format: Quick Register (QR).
0 8 10 12 15
opcode |c|a|F[]| b
Note: This is a short form of RLADD.
RLADD Rc ← Ra + Rb; Carry ← 0.
Instruction Name: Register Lisp ADD.
Opcode: 11000110, C6.
Interpretation of Operands: Lisp.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a
LSUB Stack[S-1]Stack[S-1]Stack[S]; Carry ← 0. DSDS — 1.
Instruction Name: Lisp SUBtract.
Opcode: 01000111, 47.
Interpretation of Operands: Lisp.
Format: Implicit (I).
0 7
opcode
Note: This is a short form of QLSUB and RLSUB.
QLSUB Rc ← Ra — Rb. Carry ← 0.
Instruction Name: Quick Lisp SUBtract.
Opcode: 10000111, 87.
Interpretation of Operands: Lisp.
Format: Quick Register (QR).
0 8 10 12 15
opcode |c|a|F[]| b
Note: This is a short form of RLSUB.
RLSUB Rc ← Ra — Rb. Carry ← 0.
Instruction Name: Register Lisp SUBtract.
Opcode: 11000111, C7.
Interpretation of Operands: Lisp.
Format: Registers to Register (RRR).
0 8 12 16 20 23
opcode | F[] | b | c | a