<> <> <> <> <> 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 }; <<... RETURN [IF value >= bound THEN ERROR RuntimeError.BoundsCheck ELSE value]>> BoundsCheckHighHalf: PROC [value: INT, bound: CARDINAL] RETURNS [INT] = TRUSTED MACHINE CODE { zBNDCK }; <<... IF HighHalf[LOOPHOLE[value, CARD]] < bound>> <> <> <= 0>> < 100000B will give peculiar results>> NonNegative: PROC [value: INT] RETURNS [INT] = TRUSTED MACHINE CODE { zLINI; zBNDCK; }; <<... IF value < 0 THEN ERROR RuntimeError.BoundsCheck ELSE RETURN [value]>> <> 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 }; <<... 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.>> <> 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 }; <<... swaps the 16-bit halves of the 32-bit LongNumber>> ExtractWordField: PROC [n: LongNumber, right: [0..2*bitsPerWord)] RETURNS [CARDINAL] = TRUSTED INLINE { <<... 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]].>> RETURN [BITOR [BITSHIFT[n.lo, -right], BITSHIFT[n.hi, 16-right]] ]; }; DoubleShift: PROC [ln: LongNumber, dist: INTEGER] RETURNS [LongNumber] = TRUSTED INLINE { <<... 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. >> 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 { <<... shifts one LongNumber left by dist bits and returns the shifted LongNumber. Shifting left by 1 bit is equivalent to doubling the pairber.>> 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 { <<... shifts one LongNumber left by dist bits and returns the shifted LongNumber. Shifting right by 1 bit is equivalent to halving the pairber.>> 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.