DragOpsCrossUtils.mesa
Copyright © 1984, 1985, 1986 by Xerox Corporation. All rights reserved.
Russ Atkinson (RRA) September 11, 1986 1:39:24 pm PDT
These definitions provide INLINE and MACHINE CODE procedures for manipulating Dragon values using PrincOps machines.
DIRECTORY
DragOpsCross,
PrincOps;
DragOpsCrossUtils: CEDAR DEFINITIONS = BEGIN OPEN DragOpsCross;
Instruction size
InstToBytes: PROC [inst: Inst] RETURNS [NAT] = INLINE {
SELECT ORD[inst] FROM
< 40B => RETURN [1];
< 100B => RETURN [5];
ENDCASE => RETURN [ORD[inst] / 100B];
};
InstToFormat: PROC [inst: Inst] RETURNS [InstFormat] = INLINE {
SELECT ORD[inst] / 8 FROM
2 => RETURN [OIformat];
3 => IF inst IN [dLC8..dLC11] THEN RETURN [OIformat];
6 => RETURN [OQBformat];
10B, 11B, 12B => RETURN [OIformat];
14B, 15B, 16B, 17B => RETURN [LRformat];
20B => RETURN [QRformat];
21B, 22B, 23B => RETURN [OBformat];
24B, 25B, 26B, 27B => RETURN [LRBformat];
30B, 31B => RETURN [RRformat];
32B => RETURN [ODBformat];
33B => IF inst IN [dRAI..dWRI] THEN RETURN [LRRBformat] ELSE RETURN [ODBformat];
34B, 35B => RETURN [RJBformat];
36B => RETURN [JBBformat];
37B => RETURN [ODBformat];
ENDCASE;
RETURN [illegal];
};
InstFormat: TYPE = {OIformat, OQBformat, LRformat, QRformat, OBformat, LRBformat, RRformat, ODBformat, LRRBformat, RJBformat, JBBformat, illegal};
A few type conversions
BytePCToWordAddress: PROC
[pc: ByteAddress] RETURNS [addr: Word, index: [0..bytesPerWord)] = INLINE {
index ← HalfToCard[HalfAnd[LowHalf[pc], CardToHalf[bytesPerWord-1]]];
addr ← HalvesToWord[[
HalfShift[HighHalf[pc], -2],
HalfOr[HalfShift[LowHalf[pc], -2], HalfShift[HighHalf[pc], 14]]
]];
};
WordAddressToBytePC: PROC
[addr: Word, index: [0..bytesPerWord) ← 0] RETURNS [pc: ByteAddress] = INLINE {
card: CARD = WordToCard[addr];
RETURN [[CardToWord[card+card+card+card+index]]];
};
IOOperandToCard: PROC [ioop: IOOperand] RETURNS [CARDINAL] = TRUSTED INLINE {
RETURN [LOOPHOLE[ioop]];
};
CardToIOOperand: PROC [card: CARDINAL] RETURNS [IOOperand] = TRUSTED INLINE {
RETURN [LOOPHOLE[card]];
};
FieldDescriptorToCard: PROC
[fd: FieldDescriptor] RETURNS [CARDINAL] = TRUSTED INLINE {
RETURN [LOOPHOLE[fd]];
};
CardToFieldDescriptor: PROC
[card: CARDINAL] RETURNS [FieldDescriptor] = TRUSTED INLINE {
RETURN [LOOPHOLE[card]];
};
Dragon unit conversions
BytesToWord: PROC [fb: FourBytes] RETURNS [Word] = TRUSTED INLINE {
RETURN[LOOPHOLE[fb, Word]];
};
BytesToHalf: PROC [tb: TwoBytes] RETURNS [Half] = TRUSTED INLINE {
RETURN[LOOPHOLE[tb, Half]];
};
WordToBytes: PROC [w: Word] RETURNS [FourBytes] = TRUSTED INLINE {
RETURN[LOOPHOLE[w, FourBytes]];
};
HalfToBytes: PROC [h: Half] RETURNS [TwoBytes] = TRUSTED INLINE {
RETURN[LOOPHOLE[h, TwoBytes]];
};
HalvesToWord: PROC [th: TwoHalves] RETURNS [Word] = TRUSTED INLINE {
RETURN[LOOPHOLE[th, Word]];
};
WordToHalves: PROC [w: Word] RETURNS [TwoHalves] = TRUSTED INLINE {
RETURN[LOOPHOLE[w, TwoHalves]];
};
HighHalf: PROC [w: Word] RETURNS [Half] = TRUSTED INLINE {
RETURN[LOOPHOLE[w, TwoHalves][0]];
};
LowHalf: PROC [w: Word] RETURNS [Half] = TRUSTED INLINE {
RETURN[LOOPHOLE[w, TwoHalves][1]];
};
LeftHalf: PROC [w: Word] RETURNS [Half] = TRUSTED INLINE {
RETURN[LOOPHOLE[w, TwoHalves][0]];
};
RightHalf: PROC [w: Word] RETURNS [Half] = TRUSTED INLINE {
RETURN[LOOPHOLE[w, TwoHalves][1]];
};
SwapHalves: PROC [w: Word] RETURNS [Word] = TRUSTED MACHINE CODE {
PrincOps.zEXCH;
};
DragOps/PrincOps conversions
Note: the Dragon convention is to have the low order half word (16 bits) in the right half of the word (32 bits), while the Dorado convention is to have the low order word (16 bits) in the left half of the doubleword (32 bits).
WordToInt: PROC [w: Word] RETURNS [INT] = TRUSTED MACHINE CODE {
PrincOps.zEXCH;
};
IntToWord: PROC [int: INT] RETURNS [Word] = TRUSTED MACHINE CODE {
PrincOps.zEXCH;
};
WordToCard: PROC [w: Word] RETURNS [CARD] = TRUSTED MACHINE CODE {
PrincOps.zEXCH;
};
HalfToCard: PROC [h: Half] RETURNS [CARDINAL] = TRUSTED INLINE {
RETURN [LOOPHOLE[h, CARDINAL]];
};
ByteToCard: PROC [b: Byte] RETURNS [[0..255]] = TRUSTED INLINE {
RETURN [LOOPHOLE[b]];
};
CardToWord: PROC [card: CARD] RETURNS [Word] = TRUSTED MACHINE CODE {
PrincOps.zEXCH;
};
CardToHalf: PROC [card: CARDINAL] RETURNS [Half] = TRUSTED INLINE {
RETURN [LOOPHOLE[card, Half]];
};
CardToByte: PROC [card: [0..255]] RETURNS [Byte] = TRUSTED INLINE {
RETURN [LOOPHOLE[card, Byte]];
};
Word basic operations
DragAnd: PROC [a,b: Word] RETURNS [Word] = INLINE {
This procedure is a 32-bit AND
RETURN [HalvesToWord[[
HalfAnd[LeftHalf[a], LeftHalf[b]],
HalfAnd[RightHalf[a], RightHalf[b]]
]]];
};
DragOr: PROC [a,b: Word] RETURNS [Word] = INLINE {
This procedure is a 32-bit OR
RETURN [HalvesToWord[[
HalfOr[LeftHalf[a], LeftHalf[b]],
HalfOr[RightHalf[a], RightHalf[b]]
]]];
};
DragXor: PROC [a,b: Word] RETURNS [Word] = INLINE {
This procedure is a 32-bit XOR
RETURN [HalvesToWord[[
HalfXor[LeftHalf[a], LeftHalf[b]],
HalfXor[RightHalf[a], RightHalf[b]]
]]];
};
DragNot: PROC [w: Word] RETURNS [Word] = INLINE {
This procedure is a 32-bit XOR
RETURN [HalvesToWord[[
HalfNot[LeftHalf[w]],
HalfNot[RightHalf[w]]
]]];
};
VanillaAdd: PROC [a,b: Word] RETURNS [Word] = INLINE {
This procedure is just a convenience to add without carry or overflow.
RETURN [IntToWord[WordToInt[a]+WordToInt[b]]];
};
VanillaSub: PROC [a,b: Word] RETURNS [Word] = INLINE {
This procedure is just a convenience to subtract without carry or overflow.
RETURN [IntToWord[WordToInt[a]-WordToInt[b]]];
};
AddDelta: PROC [delta: INT, w: Word] RETURNS [Word] = TRUSTED MACHINE CODE {
This procedure is a convenience to use when adding a small delta to a word. It is faster than using VanillaAdd directly.
PrincOps.zEXCH;
PrincOps.zDADD;
PrincOps.zEXCH;
};
Halfword basic operations
HalfNot: PROC [h: Half] RETURNS [nh: Half] = TRUSTED MACHINE CODE {
This procedure is just a convenience to invert a half word.
PrincOps.zLIN1;
PrincOps.zXOR
};
HalfAnd: PROC [h0,h1: Half] RETURNS [h: Half] = TRUSTED MACHINE CODE {
This procedure is just a convenience to AND two half words.
PrincOps.zAND;
};
HalfOr: PROC [h0,h1: Half] RETURNS [h: Half] = TRUSTED MACHINE CODE {
This procedure is just a convenience to OR two half words.
PrincOps.zOR;
};
HalfXor: PROC [h0,h1: Half] RETURNS [h: Half] = TRUSTED MACHINE CODE {
This procedure is just a convenience to OR two half words.
PrincOps.zXOR;
};
HalfShift: PROC [h: Half, dist: INTEGER] RETURNS [Half] = TRUSTED MACHINE CODE {
This procedure is just a half word shift left (if dist >= 0) or right (if dist <= 0).
PrincOps.zSHIFT;
};
Shift utility inlines
DoubleWordShiftLeft: PROC
[w0,w1: Word, dist: SixBitIndex] RETURNS [Word] = TRUSTED INLINE {
This procedure shifts two Dragon words left by dist bits and returns the leftmost word.
SELECT dist FROM
< 16 =>
RETURN [HalvesToWord[[
HalfOr[HalfShift[LeftHalf[w0], dist], HalfShift[RightHalf[w0], dist-16]],
HalfOr[HalfShift[RightHalf[w0], dist], HalfShift[LeftHalf[w1], dist-16]]]]];
ENDCASE => {
RETURN [HalvesToWord[[
HalfOr[HalfShift[RightHalf[w0], dist-16], HalfShift[LeftHalf[w1], dist-32]],
HalfOr[HalfShift[LeftHalf[w1], dist-16], HalfShift[RightHalf[w1], dist-32]]]]];
};
};
SingleWordShiftLeft: PROC
[word: Word, dist: SixBitIndex] RETURNS [Word] = TRUSTED INLINE {
This procedure shifts one Dragon word left by dist bits and returns the shifted word.
SELECT dist FROM
< 16 =>
RETURN [HalvesToWord[[
HalfOr[HalfShift[LeftHalf[word], dist], HalfShift[RightHalf[word], dist-16]],
HalfShift[RightHalf[word], dist]]]];
ENDCASE => {
RETURN [HalvesToWord[[HalfShift[RightHalf[word], dist-16], ZerosHalf]]];
};
};
SingleWordShiftRight: PROC
[word: Word, dist: SixBitIndex] RETURNS [Word] = TRUSTED INLINE {
This procedure shifts one Dragon word right by dist bits and returns the shifted word.
SELECT dist FROM
< 16 =>
RETURN [HalvesToWord[[
HalfShift[LeftHalf[word], -dist],
HalfOr[HalfShift[LeftHalf[word], 16-dist], HalfShift[RightHalf[word], -dist]]
]]];
ENDCASE => {
RETURN [HalvesToWord[[ZerosHalf, HalfShift[LeftHalf[word], 16-dist]]]];
};
};
Utilities for calculating PCs from Xops and trap indexes
XopToBytePC: PROC [inst: Inst] RETURNS [LONG CARDINAL] = INLINE {
RETURN [LOOPHOLE[inst, CARDINAL]*TrapWidthBytes+XopBase*bytesPerWord];
};
TrapIndexToBytePC: PROC [tx: TrapIndex] RETURNS [LONG CARDINAL] = INLINE {
RETURN [LOOPHOLE[tx, CARDINAL]*TrapWidthBytes+TrapBase*bytesPerWord];
};
Field unit definition
FieldUnit: PROC [Left, Right: Word, fd: FieldDescriptor] RETURNS [out: Word] = INLINE {
shifter: Word = DoubleWordShiftLeft[Left, Right, fd.shift];
The shifter output has the input double word shifted left by fd.shift bits
mask: Word ← SingleWordShiftRight[OnesWord, 32-fd.mask];
The default mask has fd.mask 1s right-justified in the word
IF fd.insert
THEN {
mask ← DragAnd[mask, SingleWordShiftLeft[OnesWord, fd.shift]];
clear rightmost fd.shift bits of the mask
out ← DragAnd[mask, shifter];
1 bits in the mask select the shifter output
out ← DragOr[out, DragAnd[DragNot[mask], Right]];
0 bits in the mask select bits from Right to OR in to the result
}
ELSE
out ← DragAnd[mask, shifter];
1 bits in the mask select the shifter output
};
END.