Basics.mesa
For Dragon
Copyright © 1985 by Xerox Corporation. All rights reserved.
Levin on September 20, 1983 11:00 am
Russ Atkinson (RRA) February 27, 1985 8:10:50 pm PST
Doug Wyatt, February 26, 1985 2:49:33 pm PST
Carl Hauser, November 24, 1986 2:26:40 pm PST
Commonly-used types and values
Word: TYPE = DragOps.Word;
bytesPerWord: NAT = 4;
charsPerWord: NAT = bytesPerWord;
bitsPerByte: NAT = 8;
bitsPerChar: NAT = bitsPerByte;
bitsPerWord: NAT = bitsPerByte*bytesPerWord;
bitsPerHalfword: NAT = bitsPerWord/2;
logBitsPerByte: NAT = 3; --LogBase2[bitsPerByte]
logBitsPerChar: NAT = logBitsPerByte;
logBytesPerWord: NAT = 2; --LogBase2[bytesPerWord]
logCharsPerWord: NAT = logBytesPerWord;
logBitsPerWord: NAT = logBitsPerByte + logBytesPerWord;
LongNumber:
TYPE =
MACHINE
DEPENDENT
RECORD [
this needs further attention
SELECT
OVERLAID *
FROM
real => [real: REAL],
ptr => [ptr: POINTER],
card => [card: CARD32],
int => [int: INT32],
pair => [hi, lo:
CARD16],
note: high order word precedes low order word
bytes => [hh, hl, lh, ll: BYTE],
bits => [bits:
PACKED
ARRAY [0..bitsPerWord)
OF
BOOL],
note: bits [0..16) are in the high word, bits [16..32) are in the low word
ENDCASE
];
ShortNumber:
TYPE =
MACHINE
DEPENDENT
RECORD [
SELECT
OVERLAID *
FROM
sc => [sc: CARD16],
si => [si: INT16],
bytes => [hi, lo: BYTE],
bits => [bits:
PACKED
ARRAY [0..bitsPerHalfword)
OF
BOOL],
note: bit n is higher order than bit n+1
ENDCASE
];
BytePair: TYPE = MACHINE DEPENDENT RECORD [high, low: BYTE];
Comparison: TYPE = {less, equal, greater};
RawWords: TYPE = RECORD [SEQUENCE COMPUTED CARD OF WORD];
RawCards: TYPE = RECORD [SEQUENCE COMPUTED CARD OF CARD];
RawBytes: TYPE = RECORD [PACKED SEQUENCE COMPUTED CARD OF BYTE];
RawChars: TYPE = RECORD [PACKED SEQUENCE COMPUTED CARD OF CHAR];
UnsafeBlock:
TYPE =
RECORD [
An UnsafeBlock describes the byte sequence base[startIndex..startIndex+count).
base: POINTER TO RawBytes ← NIL,
startIndex: INT ← 0,
count: INT ← 0
];
PageCount: TYPE = INT; -- was in PrincOps, try it here for Dragon.
Logic utilities
BitOp:
TYPE =
PROC [
Word,
Word]
RETURNS [
Word];
BITAND: BitOp
= TRUSTED MACHINE CODE {
041H -- AND
};
BITOR: BitOp
= TRUSTED MACHINE CODE {
040H -- OR
};
BITXOR: BitOp
= TRUSTED MACHINE CODE {
0C8H, 0EEH, 0DDH -- RXOR Under, Under, PopTop
};
BITNOT:
PROC [
Word]
RETURNS [
Word]
= TRUSTED MACHINE CODE {
0C8H, 0ECH, 0C6H -- RXOR Top, CONSTANT -1, Top
};
BITSHIFT:
PROC [value:
Word, count:
INT]
RETURNS [
WORD]
... shifts the value by the count. If count is positive, the shift is to the left. If count is negative, the count is to the right.
= INLINE {
IF count >= 0
THEN RETURN [LOOPHOLE[ShiftLeft[LOOPHOLE[value], LOOPHOLE[count, NAT]]]]
ELSE RETURN [LOOPHOLE[ShiftRight[LOOPHOLE[value], LOOPHOLE[-count, NAT]]]]
};
Field Extraction
LowHalf:
PROC [n:
CARD]
RETURNS [
CARD16]
= TRUSTED INLINE { RETURN[LOOPHOLE[n, LongNumber].lo] };
HighHalf:
PROC [n:
CARD]
RETURNS [
CARD16]
= TRUSTED INLINE { RETURN[LOOPHOLE[n, LongNumber].hi] };
Byte0:
PROC [n:
CARD]
RETURNS [
BYTE]
= TRUSTED INLINE { RETURN[LOOPHOLE[n, LongNumber].hh] };
Byte1:
PROC [n:
CARD]
RETURNS [
BYTE]
= TRUSTED INLINE { RETURN[LOOPHOLE[n, LongNumber].hl] };
Byte2:
PROC [n:
CARD]
RETURNS [
BYTE]
= TRUSTED INLINE { RETURN[LOOPHOLE[n, LongNumber].lh] };
Byte3:
PROC [n:
CARD]
RETURNS [
BYTE]
= TRUSTED INLINE { RETURN[LOOPHOLE[n, LongNumber].ll] };
LowByte:
PROC [n:
CARD16]
RETURNS [
BYTE]
= TRUSTED INLINE { RETURN[LOOPHOLE[n, BytePair].low] };
HighByte:
PROC [n:
CARD16]
RETURNS [
BYTE]
= TRUSTED INLINE { RETURN[LOOPHOLE[n, BytePair].high] };
Other operations on long numbers
SwapHalves:
PROC [n: LongNumber]
RETURNS [LongNumber]
= TRUSTED INLINE { RETURN[ [pair[hi: n.lo, lo: n.hi]] ] };
... swaps the 16-bit halves of the 32-bit LongNumber
ExtractHalfWordField: PROC [n: LongNumber, right: [0..bitsPerWord)] RETURNS [CARD16]
= TRUSTED INLINE {
... shifts n right by the given # of bits and returns the resulting low-order 16 bits.
NYI[];
};
ExtractWordField: PROC [n1: LongNumber, n2: LongNumber, right: [0..2*bitsPerWord)] RETURNS [CARD]
= TRUSTED INLINE {
... shifts n1 catenated with n2 right by the given # of bits and returns the resulting low-order 32 bits.
NYI[];
};
Shift:
PROC [ln: LongNumber, dist: [-31..31] ]
RETURNS [LongNumber]
= TRUSTED INLINE {
... shifts left if dist is positive, right if it is negative.
IF dist >= 0
THEN RETURN [ShiftLeft[ln, LOOPHOLE[dist, NAT]]]
ELSE RETURN [ShiftRight[ln, LOOPHOLE[-dist, NAT]]]
};
ShiftLeft:
PROC [ln: LongNumber, dist: [-31..31]]
RETURNS [new: LongNumber]
= TRUSTED INLINE {
... shifts one LongNumber left by dist bits and returns the shifted LongNumber. Shifting left by 1 bit is equivalent to doubling the number.
NYI[];
};
DoubleWordShiftLeft:
PROC [w0,w1: LongNumber, dist: [0..64)]
RETURNS [new: LongNumber] =
TRUSTED
INLINE {
... shifts two Dragon words left by dist bits and returns the leftmost word.
NYI[];
};
ShiftRight:
PROC [ln: LongNumber, dist: [-31..31]
]
RETURNS [new: LongNumber]
= TRUSTED INLINE {
... shifts one LongNumber left by dist bits and returns the shifted LongNumber. Shifting right by 1 bit is equivalent to halving the number.
NYI[];
};
Block copying utilities
Move:
PROC [from:
POINTER, nwords:
CARD, to:
POINTER]
= TRUSTED INLINE {
Trinity instructions will make this more efficient in the overlapping case.
Ordered:
PROC [lp:
POINTER]
RETURNS [
ORDERED
POINTER] =
TRUSTED MACHINE CODE {};
IF Ordered[to]
IN [Ordered[from]..Ordered[from]+nwords)
THEN FOR i: CARDINAL DECREASING IN [0..nwords) DO (to+i)^ ← (from+i)^; ENDLOOP
ELSE Copy[from: from, to: to, nwords: nwords];
};
Copy:
PROC [from:
POINTER, nwords:
CARD, to:
POINTER]
= INLINE {NYI[]};
ByteBlt: PROC [to, from: ByteBltBlock] RETURNS [nBytes: CARD];
This will be a machine code procedure in Trinity.
Miscellaneous
Fill:
PROC [where:
POINTER, nwords:
CARD, value:
WORD]
= INLINE {NYI[]};
PUSH:
PROC
RETURNS [
WORD]
= TRUSTED MACHINE CODE {
048H -- DUP
};
GetClockPulses: SAFE PROC RETURNS [CARD]
= {NYI[]};
VERSION: SAFE PROC RETURNS [VersionResult]
= {NYI[]};
Carl Hauser, October 13, 1986 11:23:32 am PDT
Working on conversion for Dragon .
changes to:
LongNumber reordered contained words, bytes and bits; renamed the tags and subfields
ShortNumber retyped the subfields; renamed the tags and subfields
UnsafeBlock retyped the base field.
Philosophy: explicitly identify the number of bits in every parameter and result. We don't have WORD32 in the language, but notice that BitsPerWord in the above is 32. An alternative philosophy would be to say that Basics is "generic" and should be expressed in the parameters should use the natural-word-length types: CARDINAL, INT, etc. During the transition this may not be a good thing.