Basics.mesa
For Sun-3, Sun-4, and other big-endian, 32-bit processors
Copyright Ó 1985, 1988, 1989, 1991 by Xerox Corporation. All rights reserved.
Russ Atkinson (RRA) February 27, 1985 8:10:50 pm PST
Carl Hauser, July 11, 1988 3:12:38 pm PDT
JKF August 26, 1988 12:50:28 pm PDT
Willie-s, July 25, 1991 2:56 pm PDT
Michael Plass, September 27, 1991 9:29 am PDT
Doug Wyatt, August 27, 1991 4:38 pm PDT
Commonly-used types and values
bitsPerByte: NAT ~ BITS[BYTE];
bitsPerWord: NAT ~ BITS[WORD];
bitsPerLongWord: NAT ~ BITS[CARD]; -- = bitsPerWord!
bitsPerDWord: NAT ~ BITS[DWORD]; -- = 2*bitsPerLongWord
bytesPerWord: NAT ~ BYTES[WORD];
bytesPerDWord:
NAT ~
BYTES[
DWORD];
logBitsPerByte: NAT ~ BITS[[0..bitsPerByte)]; -- LogBase2[bitsPerByte] (= 3)
logBitsPerWord: NAT ~ BITS[[0..bitsPerWord)];
logBitsPerDWord: NAT ~ BITS[[0..bitsPerDWord)];
logBytesPerWord: NAT ~ BITS[[0..bytesPerWord)];
logBytesPerDWord:
NAT ~
BITS[[0..bytesPerDWord)];
bitsPerChar: NAT ~ bitsPerByte;
logBitsPerChar: NAT ~ logBitsPerByte;
charsPerWord: NAT ~ bytesPerWord;
logCharsPerWord:
NAT ~ logBytesPerWord;
Word:
TYPE ~
MACHINE
DEPENDENT
RECORD [
-- bitsPerWord bits
SELECT
OVERLAID *
FROM
card => [card: CARD], -- assert BITS[CARD] = BITS[CARDINAL]
int => [int: INT], -- assert BITS[INT] = BITS[INTEGER]
real => [real: REAL], -- assert BITS[REAL] = BITS[WORD]
bytes => [bytes: PACKED ARRAY [0..bytesPerWord) OF BYTE],
bits => [bits:
PACKED
ARRAY [0..bitsPerWord)
OF
BOOL],
Caution: bytes and bits not necessarily in significance order!
ENDCASE
];
DWord:
TYPE ~
MACHINE
DEPENDENT
RECORD [
-- bitsPerDWord bits
SELECT
OVERLAID *
FROM
card => [card: DCARD],
int => [int: DINT],
real => [real: DREAL],
bytes => [bytes: PACKED ARRAY [0..bytesPerDWord) OF BYTE],
bits => [bits:
PACKED
ARRAY [0..bitsPerDWord)
OF
BOOL],
Caution: bytes and bits not necessarily in significance order!
ENDCASE
];
PartialComparison: TYPE ~ {less, equal, greater, incomparable};
Comparison:
TYPE ~ PartialComparison [less..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];
RawBits:
TYPE ~
RECORD [
PACKED SEQUENCE
COMPUTED
CARD
OF
CARDINAL[0..1]];
UnsafeBlock:
TYPE ~
RECORD [
base: POINTER TO RawBytes ¬ NIL,
startIndex: INT ¬ 0,
count: INT ¬ 0
];
... describes the byte sequence base[startIndex..startIndex+count).
Arithmetic utilities
CompareCard:
PROC [a, b:
CARD]
RETURNS [Comparison]
~ INLINE { RETURN[IF a=b THEN equal ELSE IF a>b THEN greater ELSE less] };
CompareInt:
PROC [a, b:
INT]
RETURNS [Comparison]
~
INLINE {
RETURN[
IF a=b
THEN equal
ELSE
IF a>b
THEN greater
ELSE less] };
CompareBits:
UNSAFE
PROC [
aBase:
POINTER
TO RawBits, aStart:
CARD,
bBase:
POINTER
TO RawBits, bStart:
CARD,
count:
CARDINAL]
RETURNS [Comparison]
~ UNCHECKED MACHINE CODE {"Basics𡤌ompareBits"};
OddCard:
PROC [n:
CARD]
RETURNS [
BOOL]
~ INLINE { RETURN [VAL[n MOD 2]] };
... cheaply tests whether n is odd; equivalent to (but faster than) (n MOD 2)#0.
OddInt:
PROC [n:
INT]
RETURNS [
BOOL]
~ INLINE { RETURN [OddCard[LOOPHOLE[n]]] };
Logic utilities
BITAND:
PROC [
WORD,
WORD]
RETURNS [
WORD]
~ TRUSTED MACHINE CODE {
"*#define XRM𡤋ITAND(x, y) (((word)(x)) & ((word)(y))).XRM𡤋ITAND"
};
BITOR:
PROC [
WORD,
WORD]
RETURNS [
WORD]
~ TRUSTED MACHINE CODE {
"*#define XRM𡤋ITOR(x, y) (((word)(x)) | ((word)(y))).XRM𡤋ITOR"
};
BITXOR:
PROC [
WORD,
WORD]
RETURNS [
WORD]
~ TRUSTED MACHINE CODE {
"*#define XRM𡤋ITXOR(x, y) (((word)(x)) ^ ((word)(y))).XRM𡤋ITXOR"
};
BITNOT:
PROC [
WORD]
RETURNS [
WORD]
~ TRUSTED MACHINE CODE {
"*#define XRM𡤋ITNOT(x) (~((word)(x))).XRM𡤋ITNOT"
};
BITLSHIFT:
PROC [value:
WORD, count: [0..bitsPerWord)]
RETURNS [
WORD]
... left-shifts the value by the count.
~ TRUSTED MACHINE CODE {
"*#define XRM𡤋ITLSHIFT(x, y) ((word)(x) << (word)(y)).XRM𡤋ITLSHIFT"
};
BITRSHIFT:
PROC [value:
WORD, count: [0..bitsPerWord)]
RETURNS [
WORD]
... right-shifts the value by the count.
~ TRUSTED MACHINE CODE {
"*#define XRM𡤋ITRSHIFT(x, y) ((word)(x) >> (word)(y)).XRM𡤋ITRSHIFT"
};
BITSHIFT:
PROC [value:
WORD, count:
INTEGER]
RETURNS [
WORD]
... shifts the value by the count. If count is positive, the shift is to the left. If count is negative, the shift is to the right.
~ TRUSTED MACHINE CODE {
"Basics𡤋ITSHIFT"
};
Block copying utilities
CopyWords:
UNSAFE
PROC [
dst:
POINTER
TO RawWords,
src:
POINTER
TO RawWords,
count:
CARDINAL]
~ UNCHECKED MACHINE CODE {
"Basics𡤌opyWords"
};
Copies a block of words: for all i in [0..count), dst[i] ¬ src[i].
The order of transfer is unspecified; destination and source should be disjoint.
MoveWords:
UNSAFE
PROC [
dst:
POINTER
TO RawWords,
src:
POINTER
TO RawWords,
count:
CARDINAL]
~ UNCHECKED MACHINE CODE {
"Basics←MoveWords"
};
Moves a block of words: ripples in proper order if destination and source overlap.
FillWords:
UNSAFE
PROC [
dst:
POINTER
TO RawWords,
count:
CARDINAL, value:
WORD]
~ UNCHECKED MACHINE CODE {
"Basics𡤏illWords"
};
Fills a block of words with a constant: for all i in [0..count), dst[i] ¬ value.
CopyBytes:
UNSAFE
PROC [
dstBase:
POINTER
TO RawBytes, dstStart:
CARD,
srcBase:
POINTER
TO RawBytes, srcStart:
CARD,
count:
CARDINAL]
~ UNCHECKED MACHINE CODE {
"Basics𡤌opyBytes"
};
Copies a block of bytes: for all i in [0..count), dstBase[dstStart+i] ¬ srcBase[srcStart+i].
The order of transfer is unspecified; destination and source should be disjoint.
MoveBytes:
UNSAFE
PROC [
dstBase:
POINTER
TO RawBytes, dstStart:
CARD,
srcBase:
POINTER
TO RawBytes, srcStart:
CARD,
count:
CARDINAL]
~ UNCHECKED MACHINE CODE {
"Basics←MoveBytes"
};
Moves a block of bytes: ripples in proper order if destination and source overlap.
FillBytes:
UNSAFE
PROC [
dstBase:
POINTER
TO RawBytes, dstStart:
CARD,
count:
CARDINAL, value:
BYTE]
~ UNCHECKED MACHINE CODE {
"Basics𡤏illBytes"
};
Fills a block of bytes with a constant: for all i in [0..count), dstBase[dstStart+i] ¬ value.
CopyBits:
UNSAFE
PROC [
dstBase:
POINTER
TO RawBits, dstStart:
CARD,
srcBase:
POINTER
TO RawBits, srcStart:
CARD,
count:
CARDINAL]
~ UNCHECKED MACHINE CODE {"Basics𡤌opyBits"};
MoveBits:
UNSAFE
PROC [
dstBase:
POINTER
TO RawBits, dstStart:
CARD,
srcBase:
POINTER
TO RawBits, srcStart:
CARD,
count:
CARDINAL]
~ UNCHECKED MACHINE CODE {"Basics←MoveBits"};
FillBits:
UNSAFE
PROC [
dstBase:
POINTER
TO RawBits, dstStart:
CARD,
count:
CARDINAL, value:
WORD]
~ UNCHECKED MACHINE CODE {"Basics𡤏illBits"};
ByteBltBlock:
TYPE ~
RECORD [blockPointer:
POINTER, startIndex, stopIndexPlusOne:
CARDINAL];
ByteBlt:
UNSAFE
PROC [to, from: ByteBltBlock]
RETURNS [nBytes:
CARDINAL]
~ TRUSTED MACHINE CODE {
"Basics𡤋yteBlt"
};
Retained for compatibility. The effect is ...
nBytes ¬ MIN[
MAX[to.startIndex, to.stopIndexPlusOne] - to.startIndex,
MAX[from.startIndex, from.stopIndexPlusOne] - from.startIndex
];
MoveBytes[to.blockPointer, to.startIndex, from.blockPointer, from.startIndex, nBytes];
32 and 16 bit types and operations
LongNumber: TYPE ~ Word32; -- for backward compatibility
Word32:
TYPE ~
MACHINE
DEPENDENT
RECORD [
-- 32 bits
SELECT
OVERLAID *
FROM
card => [card: CARD32],
int => [int: INT32],
real => [real: REAL32],
pair => [hi, lo: CARD16],
bytes => [hh, hl, lh, ll: BYTE],
bits => [bits:
PACKED
ARRAY [0..32)
OF
BOOL],
Caution: bits not necessarily in significance order!
lc => [lc: CARD], li => [li: INT], -- for backward compatibility; assert BITS[CARD]=32
ENDCASE
];
Word16:
TYPE ~
MACHINE
DEPENDENT
RECORD [
-- 16 bits
SELECT
OVERLAID *
FROM
card => [card: CARD16],
int => [int: INT16],
pair => [hi, lo: BYTE],
bits => [bits:
PACKED
ARRAY [0..16)
OF
BOOL],
Caution: bits not necessarily in significance order!
ENDCASE
];
LowHalf:
PROC [n:
CARD32]
RETURNS [
CARD16]
~ INLINE { RETURN[n MOD 2**16] };
HighHalf:
PROC [n:
CARD32]
RETURNS [
CARD16]
~ INLINE { RETURN[n / 2**16] };
LowByte:
PROC [n:
CARD16]
RETURNS [
BYTE]
~ INLINE { RETURN[n MOD 2**8] };
HighByte:
PROC [n:
CARD16]
RETURNS [
BYTE]
~ INLINE { RETURN[n / 2**8] };
Endian types and operations
HWORD: TYPE ~ MACHINE DEPENDENT RECORD [hi, lo: BYTE];
FWORD:
TYPE ~
MACHINE
DEPENDENT
RECORD [hi, lo:
HWORD];
These definitions are for things that "go on the wire"; well, mostly communication, but arguably anything that has an external representation that passes between machines, e.g. tape drives and floppy disks.
Some machines are big endian, some are little endian... Dorados, DLions, IBM 360s, Motorola 68000s, and SPARCs are big endian; PDP-11s, VAXes and Intel are little endian.
PrincOps LONGs are word swapped from a clean big endian viewpoint. Beware: Many Cedar programs, in particular RPC, send raw PrincOps (word swapped) LONGs on the wire.
Don't use CARD, CARDINAL, INT, INTEGER, WORD, or subranges bigger than a BYTE in the definition of any record going to or coming from the wire. Enumerated types bigger than a BYTE (ErrorCodes, for example) won't work either.
FFromCard32:
PROC [n:
CARD32]
RETURNS [
FWORD]
~ INLINE { RETURN[LOOPHOLE[n]] };
FFromInt32:
PROC [n:
INT32]
RETURNS [
FWORD]
~ INLINE { RETURN[LOOPHOLE[n]] };
Card32FromF:
PROC [f:
FWORD]
RETURNS [
CARD32]
~ INLINE { RETURN[LOOPHOLE[f]] };
Int32FromF:
PROC [f:
FWORD]
RETURNS [
INT32]
~ INLINE { RETURN[LOOPHOLE[f]] };
HFromCard16:
PROC [n:
CARD16]
RETURNS [
HWORD]
~ INLINE { RETURN[LOOPHOLE[n]] };
HFromInt16:
PROC [n:
INT16]
RETURNS [
HWORD]
~ INLINE { RETURN[LOOPHOLE[n]] };
Card16FromH:
PROC [h:
HWORD]
RETURNS [
CARD16]
~ INLINE { RETURN[LOOPHOLE[h]] };
Int16FromH:
PROC [h:
HWORD]
RETURNS [
INT16]
~ INLINE {
temp: PACKED RECORD[h0, h1: INT16] ~ [0, LOOPHOLE[h]];
RETURN[temp.h1]
};
END.
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.
Carl Hauser, June 11, 1987 4:10:57 pm PDT
added the Endian types and operations.
Carl Hauser, March 24, 1988 11:07:21 am PST
Removed VM parameters. Get them from the VM interface.
Jim Foote, August 26, 1988 10:50:59 am PDT
Added FillBytes, changed Fill to FillWords, added IsBound.
Michael Plass, August 2, 1991 11:54:50 am PDT
Moved the (unimplemented) arithmetic section to the (new) BasicArithmetic interface.
Removed the ERROR declarations; they were unused and redundant with RuntimeError.