DIRECTORY PrincOps USING [zAND, zBNDCK, zDCOMP, zDIV, zDUCOMP, zEXCH, zINC, zLDIV, zLIN1, zLINI, zMUL, zOR, zPUSH, zSHIFT, zXOR]; Basics: CEDAR DEFINITIONS = BEGIN OPEN PrincOps; bytesPerWord: NAT = 2; charsPerWord: NAT = bytesPerWord; bitsPerByte: NAT = 8; bitsPerChar: NAT = bitsPerByte; bitsPerWord: NAT = bitsPerByte*bytesPerWord; logBitsPerByte: NAT = 3; --LogBase2[bitsPerByte] logBitsPerChar: NAT = logBitsPerByte; logBytesPerWord: NAT = 1; --LogBase2[bytesPerWord] logCharsPerWord: NAT = logBytesPerWord; logBitsPerWord: NAT = logBitsPerByte + logBytesPerWord; BYTE: TYPE = [0..377B]; Byte: TYPE = BYTE; Word: TYPE = WORD; CARD: TYPE = LONG CARDINAL; LongNumber: TYPE = MACHINE DEPENDENT RECORD [ SELECT OVERLAID * FROM real => [real: REAL], lp => [lp: LONG POINTER], lc => [lc: CARD], li => [li: INT], pair => [lo, hi: WORD], num => [lowbits, highbits: CARDINAL], bytes => [lh, ll, hh, hl: BYTE], bits => [bits: PACKED ARRAY [0..bitsPerWord*2) OF BOOL], ENDCASE ]; ShortNumber: TYPE = MACHINE DEPENDENT RECORD [ SELECT OVERLAID * FROM sc => [lc: CARDINAL], si => [li: INTEGER], bytes => [hi, lo: BYTE], bits => [bits: PACKED ARRAY [0..bitsPerWord) OF BOOL], ENDCASE ]; BytePair: TYPE = MACHINE DEPENDENT RECORD [high, low: BYTE]; Comparison: TYPE = MACHINE DEPENDENT {less(0), equal(1), greater(2)}; RawWords: TYPE = RECORD [SEQUENCE COMPUTED CARDINAL OF WORD]; RawCards: TYPE = RECORD [SEQUENCE COMPUTED CARDINAL OF CARDINAL]; RawBytes: TYPE = RECORD [PACKED SEQUENCE COMPUTED CARDINAL OF BYTE]; RawChars: TYPE = RECORD [PACKED SEQUENCE COMPUTED CARDINAL OF CHAR]; UnsafeBlock: TYPE = RECORD [ base: LONG POINTER TO RawBytes _ NIL, startIndex: INT _ 0, count: INT _ 0 ]; CompareLC: PROC [a, b: CARD] RETURNS [Comparison] = TRUSTED MACHINE CODE { zDUCOMP; zINC; }; CompareCard: PROC [a, b: CARD] RETURNS [Comparison] = TRUSTED MACHINE CODE { zDUCOMP; zINC; }; CompareINT: PROC [a, b: INT] RETURNS [Comparison] = TRUSTED MACHINE CODE { zDCOMP; zINC; }; DivMod: PROC [num, den: CARDINAL] RETURNS [quotient, remainder: CARDINAL] = TRUSTED MACHINE CODE { zDIV; zPUSH; }; LongMult: PROC [CARDINAL, CARDINAL] RETURNS [product: CARD] = TRUSTED MACHINE CODE { zMUL; zPUSH; }; LongDiv: PROC [num: CARD, den: CARDINAL] RETURNS [CARDINAL] = TRUSTED MACHINE CODE { zLDIV; }; LongDivMod: PROC [num: CARD, den: CARDINAL] RETURNS [quotient, remainder: CARDINAL] = TRUSTED MACHINE CODE { zLDIV; zPUSH; }; BoundsCheck: PROC [value: CARDINAL, bound: CARDINAL] RETURNS [CARDINAL] = TRUSTED MACHINE CODE { zBNDCK }; BoundsCheckHighHalf: PROC [value: INT, bound: CARDINAL] RETURNS [INT] = TRUSTED MACHINE CODE { zBNDCK }; NonNegative: PROC [value: INT] RETURNS [INT] = TRUSTED MACHINE CODE { zLINI; zBNDCK; }; BitOp: TYPE = PROC [WORD, WORD] RETURNS [WORD]; BITAND: BitOp = TRUSTED MACHINE CODE { zAND }; BITOR: BitOp = TRUSTED MACHINE CODE { zOR }; BITXOR: BitOp = TRUSTED MACHINE CODE { zXOR }; BITNOT: PROC [WORD] RETURNS [WORD] = TRUSTED MACHINE CODE { zLIN1; zXOR; }; BITSHIFT: PROC [value: WORD, count: INTEGER] RETURNS [WORD] = TRUSTED MACHINE CODE { zSHIFT }; LowHalf: PROC [n: CARD] RETURNS [WORD] = TRUSTED INLINE { RETURN[LOOPHOLE[n, LongNumber].lowbits] }; HighHalf: PROC [n: CARD] RETURNS [WORD] = TRUSTED INLINE { RETURN[LOOPHOLE[n, LongNumber].highbits] }; LowByte: PROC [n: WORD] RETURNS [BYTE] = TRUSTED INLINE { RETURN[LOOPHOLE[n, BytePair].low] }; HighByte: PROC [n: WORD] RETURNS [BYTE] = TRUSTED INLINE { RETURN[LOOPHOLE[n, BytePair].high] }; SwapHalves: PROC [n: LongNumber] RETURNS [LongNumber] = TRUSTED MACHINE CODE { zEXCH }; ExtractWordField: PROC [n: LongNumber, right: [0..2*bitsPerWord)] RETURNS [CARDINAL] = TRUSTED INLINE { RETURN [BITOR [BITSHIFT[n.lo, -right], BITSHIFT[n.hi, 16-right]] ]; }; DoubleShift: PROC [ln: LongNumber, dist: INTEGER] RETURNS [LongNumber] = TRUSTED INLINE { IF dist >= 0 THEN RETURN [DoubleShiftLeft[ln, LOOPHOLE[dist, NAT]]] ELSE RETURN [DoubleShiftRight[ln, LOOPHOLE[-dist, NAT]]] }; DoubleShiftLeft: PROC [ln: LongNumber, dist: NAT] RETURNS [new: LongNumber] = TRUSTED INLINE { RETURN [ [pair[ lo: BITSHIFT[ln.lo, dist], hi: BITOR[BITSHIFT[ln.hi, dist], BITSHIFT[ln.lo, dist-16]] ]]]; }; DoubleShiftRight: PROC [ln: LongNumber, dist: NAT] RETURNS [new: LongNumber] = TRUSTED INLINE { RETURN [ [pair[ lo: BITOR[BITSHIFT[ln.lo, -dist], BITSHIFT[ln.hi, 16-dist]], hi: BITSHIFT[ln.hi, -dist] ]]]; }; DoubleAnd: PROC [a,b: LongNumber] RETURNS [LongNumber] = INLINE { RETURN [ [num[ lowbits: BITAND[a.lowbits, b.lowbits], highbits: BITAND[a.highbits, b.highbits] ]]]; }; DoubleOr: PROC [a,b: LongNumber] RETURNS [LongNumber] = INLINE { RETURN [ [num[ lowbits: BITOR[a.lowbits, b.lowbits], highbits: BITOR[a.highbits, b.highbits] ]]]; }; DoubleNot: PROC [ln: LongNumber] RETURNS [LongNumber] = INLINE { RETURN [ [num[ lowbits: BITNOT[ln.lowbits], highbits: BITNOT[ln.highbits] ]]]; }; DoubleXor: PROC [a,b: LongNumber] RETURNS [LongNumber] = INLINE { RETURN [ [num[ lowbits: BITXOR[a.lowbits, b.lowbits], highbits: BITXOR[a.highbits, b.highbits] ]]]; }; END. ¬Basics.mesa 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 Commonly-used types and values note: low order word precedes high order word like pair, but only present for compatibility note: bits [0..16) are in the low word, bits [16..32) are in the high word note: bit n is higher order than bit n+1 An UnsafeBlock describes the byte sequence base[startIndex..startIndex+count). Arithmetic utilities Can raise RuntimeError.ZeroDivisor. Can raise RuntimeError.DivideCheck on overflow or RuntimeError.ZeroDivisor if den = 0. 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 HighHalf[LOOPHOLE[value, CARD]] < bound THEN RETURN [value] ELSE ERROR RuntimeError.BoundsCheck; example: BoundsCheckHighHalf[int, 400B] will check for int IN [0..2**24) example: BoundsCheckHighHalf[int, 100000B] will check for int >= 0 warning: bound > 100000B will give peculiar results ... 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 ... shifts n right by the given # of bits and returns the resulting low-order 16 bits. This is equivalent to (but much faster than) LowHalf[n.lc / BITSHIFT[1, right]]. ... shifts left if the number is positive, right if it is negative. Notice that unlike the single shift operations, distances outside of [-31..31] result in 0, rather than wrapping. ... shifts one LongNumber left by dist bits and returns the shifted LongNumber. Shifting left by 1 bit is equivalent to doubling the pairber. ... shifts one LongNumber left by dist bits and returns the shifted LongNumber. Shifting right by 1 bit is equivalent to halving the pairber. DoubleAnd is a 32-bit AND DoubleOr is a 32-bit OR DoubleNot is a 32-bit NOT DoubleXor is a 32-bit XOR Κ Β˜codešœ ™ Kšœ Οmœ1™K˜—K˜š ‘œžœžœžœžœ˜&Kš œžœžœžœžœ˜7K˜—š ‘œžœžœžœžœ˜'Kš œžœžœžœžœ˜8K˜——™ š‘ œžœžœ ˜5Kšœžœžœžœ ˜!Kšœ4™4—K˜š‘œžœ,žœžœ˜TKšœžœžœ˜Kšœ”žœ ™¨Kšžœžœžœžœ˜CKšœ˜K˜—š‘ œžœžœžœ ˜FKšœžœžœ˜Kšœ·™·šžœ ˜ Kšžœžœžœžœ˜6Kšžœžœžœžœ˜8—K˜K˜—š‘œžœžœžœ˜KKšœžœžœ˜KšœŽ™Žšžœ ˜Kšœžœ˜Kšœžœžœžœ˜:K˜—K˜K˜—š‘œžœžœžœ˜LKšœžœžœ˜KšœŽ™Žšžœ ˜Kšœžœžœžœ˜