There are eleven instruction formats. They vary in length from 1 to 5 bytes and specify operations on from 0 to 3 operands. Nine of the formats have an opcode occupying 8 bits. Two formats have a 4-bit opcode followed by a 4-bit specification for an operand. The operands may be specified implicitly or explicitly; they may be registers or be determined from an index register and an offset. In all cases the way in which the operands are specified is determined implicitly from the opcode.
Here are brief definitions of terms and abbreviations used in describing the instruction formats and instructions:
Implicit (abbreviated I) — The location of the operands are implicit in the opcode of the instruction. Some of the instructions specify some operands implicitly and some operands explicitly. The term implicit is used to describe the format for a particular instruction if and only if no operands are designated explicitly.
Literal (abbreviated L)— The instruction contains the operand itself, rather than an address or other information describing where the operand is. A frequently-used synonym for the term literal is immediate.
Register (abbreviated R) — The address fields of the instruction specify register operands.
Indexed Register (abbreviated X) — Indexed-Register instructions have an operand whose address is the sum of an offset and the contents of a register.
Mem — memory word
Mem[addr] — the contents of that register or memory at address addr
Aux — auxiliary register
Const — constants register
ProcReg — processor register
ProcBus — processor bus
FieldDesc — field unit descriptor
FieldOp — field operation
FP — floating point
Offset — offset indicates a non-negative byte displacement.
Displacement — displacement indicates a signed byte displacement.
sExt[x] — The signed magnitude of x, a 2's complement number, is extended to the width of the destination.
zExt[x] — The unsigned (positive) magnitude of x is extended of the width of the destination.
m — an integer in the range [0..8)
n — an integer in the range [0..8)
Implicit Operand Specification:
I Implicit
[Artwork node; type 'ArtworkInterpress on' to command tool]
This format is used to perform stack operations. The operand (if any) is implicitly specified by in the opcode.
Example: Add. ADD: Stack[S-1] ← Stack[S] + Stack[S-1] + Carry; Carry ← 0; S ← S — 1;
Literal Operand Specification:
LB Literal Byte
[Artwork node; type 'ArtworkInterpress on' to command tool]
For LB instructions the literal byte following the opcode is used in 1 of 3 ways. It is zero-extended to 32 bits for stack operations: operand ← zExt[literal]. It is used as a 32-bit signed displacement when computing a new PC: operand ← sExt[literal]. And, it is used to calculate a displacement from S or L: operand ← literal. In calculating displacement from S or L, all arithmetic is performed modulo the size of the EU Stack.
Example: Add Byte. ADDB: Stack[S] ← Stack[S] + zExt[literal] + Carry; Carry ← 0.
LH Literal Halfword
[Artwork node; type 'ArtworkInterpress on' to command tool]
For LH instructions the literal halfword following the opcode is used in 1 of 3 ways. It is zero-extended to 32 bits for stack operations: operand ← zExt[literal]. It is used as a 32-bit signed displacement when computing a new PC: operand ← sExt[literal]. The low-order 13 bits are used as a descriptor for Field Unit operations: operand ← Low13Bits[literal].
Example: Load Immediate Double Byte. Stack[S+1] ← zExt[literal]; S ← S + 1.
LW Literal Word
[Artwork node; type 'ArtworkInterpress on' to command tool]
For LW instructions the operand is the 32-bit literal quantity following the opcode, operand ← literal.
Example: Load Immediate Quad Byte. LIQB: Stack[S+1] ← literal; S ← S + 1.
LBD Literal Byte Displacement
[Artwork node; type 'ArtworkInterpress on' to command tool]
LBD instructions have two operands. The first operand is a literal used for comparison with the top of the stack, operand1 ← zExt[literal]. The second operand is a signed displacement, operand2 ← sExt[displacement], used in computing the new PC, PC ← PC+operand2.
Example: Jump Equal Byte Byte. JEBB: If Stack[S] = zExt[literal] then PC ← PC + sExt[displacement]; S ← S — 1.
Register Operand Specification:
The Registers to Register, Quick Register and Register Displacement formats take operands from registers. The Registers to Register format selects a destination operand (Rc) and 2 source operands (Ra and Rb). The Quick Register format is a tighter form of the Registers to Register format; it provides the same decoding as the Registers to Register format for the Rb operand, but limits the possibilities for Ra and Rc to 4 different pairs of locations. The Register Displacement format provides the same decoding as the Registers to Register format for the Rb operand and gives 4 possibilities for the second operand, Rs. (Rs stands for short source register.)
The algorithms used to select Rc, Ra and Rb, and Rs are given here by the CEDAR program, OperandSpeciferImpl.
Here are the definitions used by the CEDAR implementation.
OperandSpecifier:
CEDAR
DEFINITIONS = {
Here are the type definitions used in accessing Locals[], AuxRegs[] and Constants[]:
AuxiliaryRegisterIndex: TYPE = CARDINAL [0..15];
LocalRegisterIndex: TYPE = CARDINAL [0..15];
ConstantRegisterIndex: TYPE = CARDINAL [0..11];
ShortConstantIndex: TYPE = ConstantRegisterIndex [0..1];
Some types for strong type checking.
SourceDeltaS: TYPE = INTEGER [-1..0];
DestinationDeltaS: TYPE = INTEGER [0..+1];
Here are the abstract locations and specifiers for source operands (Ra and Rb):
SourceLocation: TYPE = {AuxReg, Local, Constant, Top, Under};
SourceSpecifier:
TYPE =
RECORD [
SELECT location: SourceLocation
FROM
AuxReg => [aux: AuxiliaryRegisterIndex],
Local => [local: LocalRegisterIndex],
Constant => [constant: ConstantRegisterIndex],
Top => [deltaS: SourceDeltaS],
Under => [deltaS: SourceDeltaS],
ENDCASE
];
Here are the abstract locations and specifiers for destination operands (Rc):
DestinationLocation: TYPE = {AuxReg, Local, Constant, Top, Under, Push};
DestinationSpecifier:
TYPE =
RECORD [
SELECT location: DestinationLocation
FROM
AuxReg => [aux: AuxiliaryRegisterIndex],
Local => [local: LocalRegisterIndex],
Constant2 => [constant: ConstantRegisterIndex],
Top => [-- deltaS: 0 --],
Under => [-- deltaS: 0 --],
Push => [-- deltaS: 1 --],
ENDCASE
];
Here are the abstract locations and specifiers for shortCASpecifier operands (Rc and Ra):
ShortCASpecifier:
TYPE =
RECORD [
location: ShortCASelector
These are the supporting definitions that reflect the mappings between bit patterns and names
SourceSelector:
TYPE =
MACHINE
DEPENDENT {
Constant0 (0), Constant1, Constant2, Constant3,
Constant4 (4), Constant5, Constant6, Constant7,
Constant8 (8), Constant9, Constant10, Constant11,
Top (12), Under, PopTop, PopUnder (15)
};
DestinationSelector:
TYPE =
MACHINE
DEPENDENT {
Constant0 (0), Constant1, Constant2, Constant3,
Constant4 (4), Constant5, Constant6, Constant7,
Constant8 (8), Constant9, Constant10, Constant11,
Top (12), Under, Push, Reserved (15)
};
ShortCASelector:
TYPE =
MACHINE
DEPENDENT {
TopAtop(0), PushAtop, PushA0, PushA1 (3)
};
ShortSourceSelector:
TYPE =
MACHINE
DEPENDENT {
Constant0 (0), Constant1, Top, PopTop (3)
};
Translations from bit patterns to operand specifiers
SourceOperand: PUBLIC PROCEDURE [auxFlag: BOOL, operandFlag: BOOL, operandSelector: SourceSelector] RETURNS [SourceSpecifier];
DestinationOperand: PUBLIC PROCEDURE [auxFlag: BOOL, operandFlag: BOOL, operandSelector: DestinationSelector] RETURNS [DestinationSpecifier];
ShortCAOperand: PUBLIC PROCEDURE [operandSelector: OperandSpecifier.ShortCASelector] RETURNS [C: OperandSpecifier.DestinationSpecifier, A: OperandSpecifier.SourceSpecifier];
ShortSourceOperand: PUBLIC PROCEDURE [operandSelector: ShortSourceSelector] RETURNS [SourceSpecifier];
}.
Here is the code that actually selects the registers to be used for destination operands (Rc), source operands (Ra and Rb) and short source operands (Rs):
DIRECTORY
OperandSpecifier;
OperandSpecifierImpl:
CEDAR
PROGRAM
EXPORTS OperandSpecifier = {
SourceOperand:
PUBLIC
PROCEDURE [auxFlag:
BOOL, operandFlag:
BOOL, operandSelector: OperandSpecifier.SourceSelector]
RETURNS [OperandSpecifier.SourceSpecifier] = {
IF operandFlag
THEN
IF auxFlag
THEN RETURN [[AuxReg[aux: ORD[operandSelector]]]]
ELSE RETURN [[Local[local: ORD[operandSelector]]]]
ELSE
SELECT operandSelector
FROM
IN [Constant0..Constant11] =>
RETURN [[Constant[constant: ORD[operandSelector]]]];
Top =>
RETURN [[Top[deltaS: 0]]];
Under =>
RETURN [[Under[deltaS: 0]]];
PopTop =>
RETURN [[Top[deltaS: -1]]];
PopUnder =>
RETURN [[Under[deltaS: -1]]];
};
DestinationOperand:
PUBLIC PROCEDURE [auxFlag:
BOOL, operandFlag:
BOOL, operandSelector: OperandSpecifier.DestinationSelector]
RETURNS [OperandSpecifier.DestinationSpecifier] = {
IF operandFlag
THEN
IF auxFlag
THEN RETURN [[AuxReg[aux: ORD[operandSelector]]]]
ELSE RETURN [[Local[local: ORD[operandSelector]]]]
ELSE
SELECT operandSelector
FROM
IN [Constant0..Constant11] =>
RETURN [[Constant[constant: ORD[operandSelector]]]];
Top =>
RETURN [[Top[-- deltaS: 0 --]]];
Under =>
RETURN [[Under[-- deltaS: 0 --]]];
Push =>
RETURN [[Push[-- deltaS: +1 --]]];
};
Short encoding for C and A operands of the QR format instructions. The B operand is always a general operand.
ShortCAOperand:
PUBLIC
PROCEDURE [operandSelector: OperandSpecifier.ShortCASelector]
RETURNS [C: OperandSpecifier.DestinationSpecifier, A: OperandSpecifier.SourceSpecifier] = {
SELECT operandSelector
FROM
TopAtop =>
RETURN [[Top[--deltaS: 0--]], [Top[deltaS: 0]]];
PushAtop =>
RETURN [[Push[--deltaS: 1--]], [Top[deltaS: 0]]];
PushA0 =>
RETURN [[Push[--deltaS: 1--]], [Constant[constant: 0]]];
PushA1 =>
RETURN [[Push[--deltaS: 1--]], [Constant[constant: 1]]];
ShortSourceOperand:
PUBLIC PROCEDURE [operandSelector: OperandSpecifier.ShortSourceSelector]
RETURNS [OperandSpecifier.SourceSpecifier] = {
SELECT operandSelector
FROM
Constant0 =>
RETURN [[Constant[constant: 0]]];
Constant1 =>
RETURN [[Constant[constant: 1]]];
Top =>
RETURN [[Top[deltaS: 0]]];
PopTop =>
RETURN [[Top[deltaS: -1]]];
};
}.
RRR Registers to Register
[Artwork node; type 'ArtworkInterpress on' to command tool]
Instructions in the RRR format perform an operation with the contents of 2 registers and store the result in a third register, Rc ← Ra op Rb. F[] contains four boolean flags that determine which registers the three operand specifiers, a, b, and c, refer to.
Using the code for operand specifiers given above, Ra, Rb and Rc are specified by the following procedure calls:
Ra: OperandSpecifier.SourceSpecifier ← OperandSpecifier.SourceOperand[auxFlag: F[4], operandFlag: F[1], operandSelector: a];
Rb: OperandSpecifier.SourceSpecifier ← OperandSpecifier.SourceOperand[[auxFlag: F[4], operandFlag: F[3], operandSelector: b];
Rc: OperandSpecifier.DestinationSpecifier ← OperandSpecifier.DestinationOperand: [auxFlag: F[4], operandFlag: F[2], operandSelector: c];
Example: Register OR. ROR: Rc ← Ra or Rb.
Here are three of the most significant uses of the RRR instruction. For a complete listing of the important uses of the RRR instruction, see Appendix xx.
Rb Rc Ra
[Artwork node; type 'ArtworkInterpress on' to command tool]
[Artwork node; type 'ArtworkInterpress on' to command tool]
This instruction is an optimization of DUP followed by an operation.
It saves a memory reference.
[Artwork node; type 'ArtworkInterpress on' to command tool]
QR Quick Register
[Artwork node; type 'ArtworkInterpress on' to command tool]
The QR format is a tighter encoding of the RRR format. Rb is specified in the same manner that it is specified in the RRR format. Ra and Rc can take on 4 different pairs of values:
[Artwork node; type 'ArtworkInterpress on' to command tool]
Instructions in the QR format take less space than instructions in the RRR format; consequently, more of them can fit into the IFU cache. QR instructions will execute faster than RRR instructions and should be used when possible.
Using the code for operand specifiers given above, Ra, Rb and Rc are specified by the following procedure calls:
Ra & Rc: OperandSpecifier.ShortCASpecifier ← OperandSpecifier.ShortCAOperand[operandSelector: ShortCASelector];
Rb: OperandSpecifier.SourceSpecifier ← OperandSpecifier.SourceOperand[[auxFlag: F[2], operandFlag: F[1], operandSelector: b];
Example: Quick Lisp SUBtract. QLSUB: Stack[S] ← Stack[S] — Rb. Carry ← 0.
RD Register Displacement
[Artwork node; type 'ArtworkInterpress on' to command tool]
This format provides access to 3 operands, Rs (short source register), Rb, and a displacement. Instructions using this format compare Rs and Rb and jump to the PC given by PC+sExt[displacement] if the indicated comparision of Rs with Rb is true.
Using the code for operand specifiers given above, Rs and Rb are specified by the following procedure calls:
Rs: OperandSpecifierShort.SourceSpecifier ← OperandSpecifier.ShortSourceOperand[operandSelector: Rs];
Rb: OperandSpecifier.SourceSpecifier ← OperandSpecifier.SourceOperand[[auxFlag: F[2], operandFlag: F[1], operandSelector: b];
Example: Register Jump Equal Byte. RJEB: If Rs = Rb then PC ← PC + sExt[displacement].
LR
Locals Register
[Artwork node; type 'ArtworkInterpress on' to command tool]
LR instructions have a 4-bit opcode. The next 4 bits are an index into Locals and specify the operand, operand = Locals[n].
Example: Store Register n. SRn: Locals[n] ← Stack[S]; S ← S — 1. { :n| 0 <= n < 16}.