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
DIRECTORY
DragOps;
Basics: CEDAR DEFINITIONS
= BEGIN
Temporary placeholder
NYI: PROC [] RETURNS [] ~ INLINE {
};
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.
Arithmetic utilities
CompareCard: PROC [a, b: CARD] RETURNS [c: Comparison]
= INLINE {
c ← SELECT TRUE FROM
a=b => equal,
a>b => greater,
ENDCASE => less;
};
CompareINT: PROC [a, b: INT] RETURNS [c: Comparison]
= INLINE {
c ← SELECT TRUE FROM
a=b => equal,
a>b => greater,
ENDCASE => less;
};
Mult: PROC [CARD, CARD] RETURNS [product: CARD]
= INLINE {NYI[]};
Div: PROC [num, den: CARD] RETURNS [CARD]
= {NYI[]};
Can raise RuntimeError.DivideCheck on overflow or RuntimeError.ZeroDivisor if den = 0.
DivMod: PROC [num, den: CARD] RETURNS [quotient, remainder: CARD]
= {NYI[]};
Can raise RuntimeError.DivideCheck on overflow or RuntimeError.ZeroDivisor if den = 0.
Bounds checking
BoundsCheck: PROC [value, bound: CARD] RETURNS [CARD]
= TRUSTED MACHINE CODE {
043H -- BC
};
... RETURN [IF value >= bound THEN ERROR RuntimeError.BoundsCheck ELSE value]
NonNegative: PROC [value: INT] RETURNS [INT]
= TRUSTED MACHINE CODE {
083H, 027H -- QBC TopATop, CONSTANT 80000000H
};
... IF value < 0 THEN ERROR RuntimeError.BoundsCheck ELSE RETURN [value]
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[]};
Utilities for BitBlt and TextBlt (wizards only)
AlignedBBTable: PROC [ip: POINTER TO BBTableSpace] RETURNS [b: BBptr]
= INLINE {
align: TYPE = MACHINE DEPENDENT RECORD [
s: [0..WORD.LAST/BBTableAlignment), z: [0..BBTableAlignment)];
b ← LOOPHOLE[ip + BBTableAlignment - 1];
LOOPHOLE[b, align].z ← 0;
};
BITBLT: PROC [ptr: BBptr]
= {NYI[]};
AlignedTextBltArg: PROC [ip: POINTER TO TextBltArgSpace]
RETURNS
[p: POINTER TO TextBltArg]
= INLINE {
align: TYPE = MACHINE DEPENDENT RECORD [
s: [0..WORD.LAST/TextBltArgAlignment), z: [0..TextBltArgAlignment)];
p ← LOOPHOLE[ip + TextBltArgAlignment - 1];
LOOPHOLE[p, align].z ← 0;
};
TextBlt: PROC [
index: CARD, bitPos: CARD, micaPos: CARD,
count: INT, ptr: POINTER TO TextBltArg]
RETURNS
[
newIndex: CARD, newBitPos: CARD, newMicaPos: CARD,
newCount: INT, result: TextBltResult
]
= { NYI[]};
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.
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.