DIRECTORY DragOps; Basics: CEDAR DEFINITIONS = BEGIN NYI: PROC [] RETURNS [] ~ INLINE { }; 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 [ SELECT OVERLAID * FROM real => [real: REAL], ptr => [ptr: POINTER], card => [card: CARD32], int => [int: INT32], pair => [hi, lo: CARD16], bytes => [hh, hl, lh, ll: BYTE], bits => [bits: PACKED ARRAY [0..bitsPerWord) OF BOOL], 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], 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 [ base: POINTER TO RawBytes _ NIL, startIndex: INT _ 0, count: INT _ 0 ]; PageCount: TYPE = INT; -- was in PrincOps, try it here for Dragon. 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[]}; BoundsCheck: PROC [value, bound: CARD] RETURNS [CARD] = TRUSTED MACHINE CODE { 043H -- BC }; NonNegative: PROC [value: INT] RETURNS [INT] = TRUSTED MACHINE CODE { 083H, 027H -- QBC TopATop, CONSTANT 80000000H }; 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] = INLINE { IF count >= 0 THEN RETURN [LOOPHOLE[ShiftLeft[LOOPHOLE[value], LOOPHOLE[count, NAT]]]] ELSE RETURN [LOOPHOLE[ShiftRight[LOOPHOLE[value], LOOPHOLE[-count, NAT]]]] }; 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] }; SwapHalves: PROC [n: LongNumber] RETURNS [LongNumber] = TRUSTED INLINE { RETURN[ [pair[hi: n.lo, lo: n.hi]] ] }; Shift: PROC [ln: LongNumber, dist: [-31..31] ] RETURNS [LongNumber] = TRUSTED INLINE { 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 { NYI[]; }; DoubleWordShiftLeft: PROC [w0,w1: LongNumber, dist: [0..64)] RETURNS [new: LongNumber] = TRUSTED INLINE { NYI[]; }; ShiftRight: PROC [ln: LongNumber, dist: [-31..31] ] RETURNS [new: LongNumber] = TRUSTED INLINE { NYI[]; }; Move: PROC [from: POINTER, nwords: CARD, to: POINTER] = TRUSTED INLINE { 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[]}; Fill: PROC [where: POINTER, nwords: CARD, value: WORD] = INLINE {NYI[]}; PUSH: PROC RETURNS [WORD] = TRUSTED MACHINE CODE { 048H -- DUP }; END. δBasics.mesa For Dragon Copyright c 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 Temporary placeholder Commonly-used types and values this needs further attention note: high order word precedes low order word note: bits [0..16) are in the high word, bits [16..32) are in the low word note: bit n is higher order than bit n+1 An UnsafeBlock describes the byte sequence base[startIndex..startIndex+count). Arithmetic utilities 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 ... RETURN [IF value >= bound THEN ERROR RuntimeError.BoundsCheck ELSE value] ... IF value < 0 THEN ERROR RuntimeError.BoundsCheck ELSE RETURN [value] Logic utilities ... 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. Field Extraction Other operations on long numbers ... 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[]; }; ... shifts left if dist is positive, right if it is negative. ... shifts one LongNumber left by dist bits and returns the shifted LongNumber. Shifting left by 1 bit is equivalent to doubling the number. ... shifts two Dragon words left by dist bits and returns the leftmost word. ... shifts one LongNumber left by dist bits and returns the shifted LongNumber. Shifting right by 1 bit is equivalent to halving the number. Block copying utilities Trinity instructions will make this more efficient in the overlapping case. ByteBlt: PROC [to, from: ByteBltBlock] RETURNS [nBytes: CARD]; This will be a machine code procedure in Trinity. Miscellaneous 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[]}; 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. Κ ˜codešœ ™ KšΠbl ™ Kšœ Οmœ1™Kšœ1™1K™—K™ K™š £œŸœ Ÿœ Ÿœ Ÿœ˜6KšœŸœŸœ˜K˜—š€œŸœŸœŸœ˜KšœŸœŸœ˜Kšœ ˜ Kšœ˜K˜—š £œŸœŸœŸœŸœ™(Kšœ ™ K™—š€œŸœŸœŸœ™*Kšœ ™ K™——šœ0™0š £œŸœŸœŸœŸœ ™EKšœŸœ™ š œŸœŸœŸ œŸœ™(KšœŸœŸœ.™>—KšœŸœ™(KšŸœ™K™K™—š€œŸœ ™Kšœ ™ —K™š£œŸœŸœŸœŸœŸœŸœ ™\KšœŸœ™ š œŸœŸœŸ œŸœ™(KšœŸœŸœ4™D—KšœŸœ™+KšŸœ™Kšœ™K™—š£œŸœ Ÿœ Ÿœ Ÿœ ŸœŸœŸœ Ÿ œ Ÿœ ŸœŸœ Ÿœ™ΘKšœ ™ —K™K˜K˜—KšŸœ˜™-K™"šœ ™ KšΟr œ*₯œ₯™UKš₯ œ₯œ₯™BKš₯ œ™#—K™‰—K™—…—x/t