DragOpsImpl.mesa
Russ Atkinson, June 16, 1983 9:11 am
DIRECTORY
Mopcodes;
DragOpsImpl: CEDAR PROGRAM
= BEGIN OPEN Mopcodes;
T Y P E S
FourBits: TYPE = [0..15];
FiveBits: TYPE = [0..31];
Word: TYPE = PACKED ARRAY FiveBits OF BOOL;
ZerosWord: Word ← ALL[FALSE];
OnesWord: Word ← ALL[TRUE];
Half: TYPE = PACKED ARRAY FourBits OF BOOL;
TwoHalves: TYPE = ARRAY [0..1] OF Half;
TwoWords: TYPE = ARRAY [0..1] OF Word;
FourHalves: TYPE = ARRAY [0..3] OF Half;
ShiftOp: TYPE = MACHINE DEPENDENT {shift(0), extract(1), insert(2), rCycle(3)};
FieldDescriptor: TYPE = MACHINE DEPENDENT RECORD [
pq: BOOL, -- governs whether shift distance is from k or q
mask: FiveBits, -- controls the mask generation
op: ShiftOp, -- controls which operation is performed
shiftSign: BOOL, -- gives the shift sign
shift: FiveBits]; -- gives the shift distance
Field Unit Operations
FieldUnit: PROC [t,m: Word, q: FieldDescriptor, k: FieldDescriptor] RETURNS [u: Word] = {
This procedure specifies the behavior of the Field Unit under control of a given FieldDescriptor, k. The Q register's low-order bits are also available as input as a FieldDescriptor. The inputs t & m are determined by the IFU.
op: ShiftOp ← k.op;
fd: FieldDescriptor ← IF k.pq THEN q ELSE k; -- may take specs from q register
maskSpec: FiveBits ← IF op = shift THEN fd.shift ELSE fd.mask;
shiftSpec: FiveBits ← fd.shift;
invertMask: BOOLFALSE;
su, mu, imu: Word;
SELECT op FROM
extract => invertMask ← TRUE;
shift => invertMask ← fd.shiftSign;
insert => m ← t;
rCycle => invertMask ← TRUE;
ENDCASE => ERROR;
su ← ShiftUnit[t, m, shiftSpec, op = rCycle];
mu ← MaskUnit[maskSpec, op # shift];
imu ← WordNot[mu];
u ← WordAnd[su, IF invertMask THEN imu ELSE mu];
IF op = insert THEN u ← WordOr[WordAnd[imu, m], u];
};
ShiftUnit: PROC [w0,w1: Word, shiftSpec: FiveBits, rcyc: BOOL] RETURNS [su: Word] = {
This procedure specifies the operation of the shift unit in the EU. The idea is to left shift the 64-bit quantity given by w0 & w1 by shiftSpec bits (unless rcyc, in which case we shift left by 32-shiftSpec bits). By convention, w0 is more left than w1.
dist: FiveBits ← shiftSpec;
IF rcyc THEN
IF dist = 0
THEN RETURN [w1]
ELSE dist ← 32-shiftSpec;
su ← DoubleWordShiftLeft[w0, w1, dist];
};
MaskUnit: PROC [maskSpec: FiveBits, ms0: BOOL] RETURNS [mu: Word] = {
This procedure specifies the operation of the mask unit in the EU. The idea is to generate a mask with maskSpec low-order bits of 0s, the remaining bits being 1s, unless maskSpec = 0 AND ms0, in which case, the mask is all 0s.
IF maskSpec = 0 AND ms0 THEN RETURN [ZerosWord];
mu ← DoubleWordShiftLeft[OnesWord, ZerosWord, maskSpec];
};
Dragon Primitives
WordNot: PROC [w: Word] RETURNS [Word] = {
This procedure is just a convenience to invert a Dragon word.
RETURN[HalvesToWord[HalfNot[LeftHalf[w]], HalfNot[RightHalf[w]]]];
};
WordAnd: PROC [w0,w1: Word] RETURNS [Word] = {
This procedure is just a convenience to AND two Dragon words.
RETURN[HalvesToWord[
HalfAnd[LeftHalf[w0], LeftHalf[w1]],
HalfAnd[RightHalf[w0], RightHalf[w1]]]];
};
WordOr: PROC [w0,w1: Word] RETURNS [Word] = {
This procedure is just a convenience to OR two Dragon words.
RETURN[HalvesToWord[
HalfOr[LeftHalf[w0], LeftHalf[w1]],
HalfOr[RightHalf[w0], RightHalf[w1]]]];
};
DoubleWordShiftLeft: PROC [w0,w1: Word, dist: FiveBits] RETURNS [Word] = {
This procedure shifts two Dragon words left by dist bits and returns the leftmost word. It is useful in the ShiftUnit and the MaskUnit.
SELECT dist FROM
0 => RETURN [w0];
< 16 =>
RETURN [HalvesToWord[
HalfOr[HalfShift[LeftHalf[w0], dist], HalfShift[RightHalf[w0], dist-16]],
HalfOr[HalfShift[RightHalf[w0], dist], HalfShift[LeftHalf[w1], dist-16]]]];
16 =>
RETURN [HalvesToWord[RightHalf[w0], LeftHalf[w1]]];
ENDCASE => {
dist > 16
RETURN [HalvesToWord[
HalfOr[HalfShift[RightHalf[w0], dist-16], HalfShift[LeftHalf[w1], dist-32]],
HalfOr[HalfShift[LeftHalf[w1], dist-16], HalfShift[RightHalf[w1], dist-32]]]];
};
};
WordAdd: PROC [w0,w1: Word] RETURNS [Word] = {
RETURN [IntToWord[WordToInt[w0]+WordToInt[w1]]];
};
WordSub: PROC [w0,w1: Word] RETURNS [Word] = {
RETURN [IntToWord[WordToInt[w0]-WordToInt[w1]]];
};
Dragon/Dorado conversions
Note: all conversions to/from host format are below this line, except for the implicit assumption that anything less than or equal to 16 bits needs no conversion (i.e., bytes, field descriptors).
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).
CARD: TYPE = LONG CARDINAL;
HalvesToWord: PROC [h0,h1: Half] RETURNS [Word] = TRUSTED INLINE {
RETURN[LOOPHOLE[TwoHalves[h0,h1], Word]];
};
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]];
};
WordToInt: PROC [w: Word] RETURNS [INT] = TRUSTED MACHINE CODE {
Mopcodes.zEXCH;
};
WordToCard: PROC [w: Word] RETURNS [CARD] = TRUSTED MACHINE CODE {
Mopcodes.zEXCH;
};
IntToWord: PROC [int: INT] RETURNS [Word] = TRUSTED MACHINE CODE {
Mopcodes.zEXCH;
};
CardToWord: PROC [card: CARD] RETURNS [Word] = TRUSTED MACHINE CODE {
Mopcodes.zEXCH;
};
HalfNot: PROC [h: Half] RETURNS [nh: Half] = TRUSTED MACHINE CODE {
This procedure is just a convenience to invert a half word.
Mopcodes.zLIN1;
Mopcodes.zXOR
};
HalfAnd: PROC [h0,h1: Half] RETURNS [h: Half] = TRUSTED MACHINE CODE {
This procedure is just a convenience to AND two half words.
Mopcodes.zAND;
};
HalfOr: PROC [h0,h1: Half] RETURNS [h: Half] = TRUSTED MACHINE CODE {
This procedure is just a convenience to OR two half words.
Mopcodes.zOR;
};
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).
Mopcodes.zSHIFT;
};
Debugging aids
W2I: PROC [w: Word] RETURNS [INT] = TRUSTED {
Useful for debugging
RETURN[WordToInt[w]];
};
W2C: PROC [w: Word] RETURNS [CARD] = TRUSTED {
Useful for debugging
RETURN[WordToCard[w]];
};
I2W: PROC [int: INT] RETURNS [Word] = TRUSTED {
Useful for debugging
RETURN[IntToWord[int]];
};
C2W: PROC [card: CARD] RETURNS [Word] = TRUSTED {
Useful for debugging
RETURN[CardToWord[card]];
};
END.