DIRECTORY Basics; BasicsImpl: CEDAR PROGRAM IMPORTS Basics = BEGIN OPEN Basics; ExternalNames: PROC [] = TRUSTED MACHINE CODE { "^ExternalNames\n"; "CopyWords Basics_CopyWords\n"; "MoveWords Basics_MoveWords\n"; -- may be assembly-coded - see below "FillWords Basics_FillWords\n"; -- may be assembly-coded - see below "CopyBytes Basics_CopyBytes\n"; "MoveBytes Basics_MoveBytes\n"; "FillBytes Basics_FillBytes\n"; "CopyBits Basics_CopyBits \n"; "MoveBits Basics_MoveBits \n"; "FillBits Basics_FillBits \n"; "CompareBits Basics_CompareBits\n"; "ByteBlt Basics_ByteBlt\n"; "BITSHIFT Basics_BITSHIFT\n"; "CopyBitsDecreasing Basics_CopyBitsDecreasing \n"; "RegisterLogMisalign Basics_RegisterLogMisalign\n"; }; assemblyMoveAndFillWords: BOOL ~ AssemblyMoveAndFillWords[]; AssemblyMoveAndFillWords: PROC [] RETURNS [BOOL] = TRUSTED MACHINE CODE { "*#ifdef sparc\n"; "#define AssemblyMoveAndFillWordsHelp() 1\n"; "#define Basics_MoveWords Basics_MoveWords_Soft\n"; "#define Basics_FillWords Basics_FillWords_Soft\n"; "#else\n"; "#define AssemblyMoveAndFillWordsHelp() 0\n"; "#endif\n"; ".AssemblyMoveAndFillWordsHelp"; }; bpw: NAT ~ BITS[WORD]; BitOff: TYPE = [0..bpw); BitCount: TYPE = [0..bpw]; WordsForBits: PROC [bits: CARD] RETURNS [CARD] ~ INLINE { RETURN [CARD[bits+(bpw-1)]/bpw] }; RightJustifiedOnes: PROC [n: BitCount] RETURNS [WORD] ~ INLINE { RETURN [BITLSHIFT[1, n MOD bpw] - 1 - n/bpw] }; RightJustifiedZeros: PROC [n: BitOff] RETURNS [WORD] ~ INLINE { RETURN [-BITRSHIFT[2**(bpw-1), (bpw-1)-n]] }; StartingWord: PROC [base: POINTER TO RawBits, bitIndex: CARD] RETURNS [POINTER TO RawWords] ~ TRUSTED INLINE { RETURN [LOOPHOLE[base, POINTER] + (UNITS[WORD]*(bitIndex/bpw))] }; MF: PROC [d, s, mask: WORD] RETURNS [WORD] ~ INLINE { RETURN [BITXOR[BITAND[BITXOR[s, d], mask], d]] }; CopyWords: UNSAFE PROC [ dst: POINTER TO RawWords, src: POINTER TO RawWords, count: CARDINAL] ~ { FOR i: CARDINAL IN [0..count) DO TRUSTED { dst[i] ¬ src[i] }; ENDLOOP; }; MoveWords: UNSAFE PROC [ dst: POINTER TO RawWords, src: POINTER TO RawWords, count: CARDINAL] ~ { IF LOOPHOLE[dst, CARD]= 4 DO p[0] ¬ value; p[1] ¬ value; p[2] ¬ value; p[3] ¬ value; p ¬ p + SIZE[ARRAY [0..4) OF WORD]; count ¬ count - 4; ENDLOOP; IF count = 0 THEN RETURN; p[0] ¬ value; IF count = 1 THEN RETURN; p[1] ¬ value; IF count = 2 THEN RETURN; p[2] ¬ value; }; CopyBytes: UNSAFE PROC [ dstBase: POINTER TO RawBytes, dstStart: CARD, srcBase: POINTER TO RawBytes, srcStart: CARD, count: CARDINAL] ~ TRUSTED { IF count>(CARD.LAST-dstStart) THEN RaiseBoundsFault[]; IF count>(CARD.LAST-srcStart) THEN RaiseBoundsFault[]; IF count>= 2**(BITS[WORD]-BITS[BYTE]) THEN RaiseBoundsFault[]; CopyBits[ dstBase: LOOPHOLE[dstBase], dstStart: dstStart*BITS[BYTE], srcBase: LOOPHOLE[srcBase], srcStart: srcStart*BITS[BYTE], count: count*BITS[BYTE] ]; }; MoveBytes: UNSAFE PROC [ dstBase: POINTER TO RawBytes, dstStart: CARD, srcBase: POINTER TO RawBytes, srcStart: CARD, count: CARDINAL] ~ { d0: CARD ~ LOOPHOLE[dstBase, CARD]*BYTES[UNIT]+dstStart; s0: CARD ~ LOOPHOLE[srcBase, CARD]*BYTES[UNIT]+srcStart; IF count>(CARD.LAST-dstStart) THEN RaiseBoundsFault[]; IF count>(CARD.LAST-srcStart) THEN RaiseBoundsFault[]; IF count>= 2**(BITS[WORD]-BITS[BYTE]) THEN RaiseBoundsFault[]; IF d0 IN (s0 .. s0+count) THEN { -- bad overlap FOR i: CARDINAL DECREASING IN[0..count) DO TRUSTED { dstBase[dstStart+i] ¬ srcBase[srcStart+i] }; ENDLOOP; } ELSE TRUSTED { CopyBits[ dstBase: LOOPHOLE[dstBase], dstStart: dstStart*BITS[BYTE], srcBase: LOOPHOLE[srcBase], srcStart: srcStart*BITS[BYTE], count: count*BITS[BYTE] ]; }; }; FillBytes: UNSAFE PROC [ dstBase: POINTER TO RawBytes, dstStart: CARD, count: CARDINAL, value: BYTE] ~ CHECKED { wordValue: CARD ¬ value + 100H*value; wordValue ¬ wordValue + 10000H*value; TRUSTED { FillBits[ dstBase: LOOPHOLE[dstBase], dstStart: dstStart*BITS[BYTE], count: count*BITS[BYTE], value: wordValue ]; }; }; logMisalign: PROC ¬ NIL; RegisterLogMisalign: PROC [p: PROC] ~ { logMisalign ¬ p; }; CopyBits: UNSAFE PROC [ dstBase: POINTER TO RawBits, dstStart: CARD, srcBase: POINTER TO RawBits, srcStart: CARD, count: CARDINAL] ~ CHECKED { dstCorr: CARD ~ LOOPHOLE[dstBase, CARD] MOD UNITS[WORD]; srcCorr: CARD ~ LOOPHOLE[srcBase, CARD] MOD UNITS[WORD]; IF dstCorr+srcCorr # 0 THEN { p: PROC ¬ logMisalign; IF p # NIL THEN p[]; dstBase ¬ dstBase - dstCorr; dstStart ¬ dstStart + BITS[UNIT]*dstCorr; srcBase ¬ srcBase - srcCorr; srcStart ¬ srcStart + BITS[UNIT]*srcCorr; }; IF count # 0 THEN { dst: POINTER TO RawWords ¬ StartingWord[dstBase, dstStart]; dstBit: BitOff ~ dstStart MOD bpw; src: POINTER TO RawWords ¬ StartingWord[srcBase, srcStart]; srcBit: BitOff ~ srcStart MOD bpw; ndw: CARD ~ WordsForBits[dstBit + count]; lMask: WORD ~ RightJustifiedOnes[bpw-dstBit]; rMask: WORD ~ RightJustifiedZeros[(LOOPHOLE[bpw-dstBit-count, CARD]) MOD bpw]; IF dstBit = srcBit THEN { -- Aligned case is simpler SELECT ndw FROM 1 => TRUSTED { dst[0] ¬ MF[dst[0], src[0], BITAND[lMask, rMask]]; }; 2 => TRUSTED { dst[0] ¬ MF[dst[0], src[0], lMask]; dst[1] ¬ MF[dst[1], src[1], rMask]; }; 3 => TRUSTED { dst[0] ¬ MF[dst[0], src[0], lMask]; dst[1] ¬ src[1]; dst[2] ¬ MF[dst[2], src[2], rMask]; }; ENDCASE => TRUSTED { nw: CARD ¬ LOOPHOLE[ndw-2, CARD]; dst[0] ¬ MF[dst[0], src[0], lMask]; dst ¬ dst+UNITS[WORD]; src ¬ src+UNITS[WORD]; WHILE nw >= 4 DO dst[0] ¬ src[0]; dst[1] ¬ src[1]; dst[2] ¬ src[2]; dst[3] ¬ src[3]; dst ¬ dst+UNITS[WORD]*4; src ¬ src+UNITS[WORD]*4; nw ¬ nw - 4; ENDLOOP; IF nw >= 2 THEN { dst[0] ¬ src[0]; dst[1] ¬ src[1]; dst ¬ dst+SIZE[WORD]*2; src ¬ src+SIZE[WORD]*2; nw ¬ nw - 2; }; IF nw # 0 THEN { dst[0] ¬ src[0]; dst ¬ dst+SIZE[WORD]; src ¬ src+SIZE[WORD]; }; dst[0] ¬ MF[dst[0], src[0], rMask]; }; } ELSE { -- Unaligned case. w: WORD ¬ 0; -- source word, aligned with destination hi: WORD; -- left unshifted source word lo: WORD ¬ 0; -- right unshifted source word lSA: BitOff = LOOPHOLE[srcBit-dstBit, CARDINAL] MOD bpw; -- left shift amount rSA: BitOff = LOOPHOLE[bpw - lSA, CARDINAL] MOD bpw; -- amount to shift source words right to line them up nsw: CARD = WordsForBits[srcBit + count]; fetchLastWord: BOOL ~ IF srcBit >= dstBit THEN (nsw>ndw) ELSE (nsw>=ndw); FetchNext: PROC ~ INLINE { hi ¬ lo; TRUSTED {lo ¬ src[0]}; src ¬ src+SIZE[WORD]; w ¬ BITLSHIFT[hi, lSA]+BITRSHIFT[lo, rSA] }; FetchNextOff: PROC [wordOffset: CARD] ~ INLINE { hi ¬ lo; TRUSTED {lo ¬ src[wordOffset]}; w ¬ BITLSHIFT[hi, lSA]+BITRSHIFT[lo, rSA] }; FetchLast: PROC [wordOffset: CARD, fetch: BOOL] ~ INLINE { w ¬ BITLSHIFT[lo, lSA]; IF fetch THEN TRUSTED {w ¬ w + BITRSHIFT[src[wordOffset], rSA]}; }; IF srcBit >= dstBit THEN FetchNext[]; SELECT ndw FROM 1 => TRUSTED { bothMask: WORD ~ BITAND[lMask, rMask]; FetchLast[0, fetchLastWord]; dst[0] ¬ MF[dst[0], w, bothMask]; }; 2 => TRUSTED { FetchNextOff[0]; dst[0] ¬ MF[dst[0], w, lMask]; FetchLast[1, fetchLastWord]; dst[1] ¬ MF[dst[1], w, rMask]; }; 3 => TRUSTED { FetchNextOff[0]; dst[0] ¬ MF[dst[0], w, lMask]; FetchNextOff[1]; dst[1] ¬ w; FetchLast[2, fetchLastWord]; dst[2] ¬ MF[dst[2], w, rMask]; }; ENDCASE => TRUSTED { nw: CARD ¬ LOOPHOLE[ndw-2, CARD]; FetchNextOff[0]; dst[0] ¬ MF[dst[0], w, lMask]; dst ¬ dst+SIZE[WORD]; src ¬ src+SIZE[WORD]; WHILE nw >= 2 DO FetchNextOff[0]; dst[0] ¬ w; FetchNextOff[1]; dst[1] ¬ w; dst ¬ dst+SIZE[WORD]*2; src ¬ src+SIZE[WORD]*2; nw ¬ nw - 2; ENDLOOP; IF nw # 0 THEN { FetchNextOff[0]; dst[0] ¬ w; dst ¬ dst+SIZE[WORD]; src ¬ src+SIZE[WORD]; }; FetchLast[0, fetchLastWord]; dst[0] ¬ MF[dst[0], w, rMask]; }; }; }; }; CopyBitsDecreasing: UNSAFE PROC [ dstBase: POINTER TO RawBits, dstStart: CARD, srcBase: POINTER TO RawBits, srcStart: CARD, count: CARDINAL] ~ CHECKED { dstCorr: CARD ~ LOOPHOLE[dstBase, CARD] MOD UNITS[WORD]; srcCorr: CARD ~ LOOPHOLE[srcBase, CARD] MOD UNITS[WORD]; IF dstCorr+srcCorr # 0 THEN { p: PROC ¬ logMisalign; IF p # NIL THEN p[]; dstBase ¬ dstBase - dstCorr; dstStart ¬ dstStart + BITS[UNIT]*dstCorr; srcBase ¬ srcBase - srcCorr; srcStart ¬ srcStart + BITS[UNIT]*srcCorr; }; IF count # 0 THEN { dst: POINTER TO RawWords ¬ StartingWord[dstBase, dstStart]; dstBit: BitOff ~ dstStart MOD bpw; src: POINTER TO RawWords ¬ StartingWord[srcBase, srcStart]; srcBit: BitOff ~ srcStart MOD bpw; ndw: CARD ~ WordsForBits[dstBit + count]; lMask: WORD ~ RightJustifiedOnes[bpw-dstBit]; rMask: WORD ~ RightJustifiedZeros[(LOOPHOLE[bpw-dstBit-count, CARD]) MOD bpw]; IF dstBit = srcBit THEN { -- Aligned case is simpler SELECT ndw FROM 1 => TRUSTED { dst[0] ¬ MF[dst[0], src[0], BITAND[lMask, rMask]]; }; 2 => TRUSTED { dst[1] ¬ MF[dst[1], src[1], rMask]; dst[0] ¬ MF[dst[0], src[0], lMask]; }; 3 => TRUSTED { dst[2] ¬ MF[dst[2], src[2], rMask]; dst[1] ¬ src[1]; dst[0] ¬ MF[dst[0], src[0], lMask]; }; ENDCASE => TRUSTED { nw: CARD ¬ LOOPHOLE[ndw-2, CARD]; dst ¬ dst+ndw*UNITS[WORD] - UNITS[WORD]; src ¬ src+ndw*UNITS[WORD] - UNITS[WORD]; dst[0] ¬ MF[dst[0], src[0], rMask]; WHILE nw >= 4 DO dst ¬ dst-UNITS[WORD]*4; src ¬ src-UNITS[WORD]*4; dst[3] ¬ src[3]; dst[2] ¬ src[2]; dst[1] ¬ src[1]; dst[0] ¬ src[0]; nw ¬ nw - 4; ENDLOOP; IF nw >= 2 THEN { dst ¬ dst-UNITS[WORD]*2; src ¬ src-UNITS[WORD]*2; dst[1] ¬ src[1]; dst[0] ¬ src[0]; nw ¬ nw - 2; }; IF nw # 0 THEN { dst ¬ dst-UNITS[WORD]; src ¬ src-UNITS[WORD]; dst[0] ¬ src[0]; }; dst ¬ dst-UNITS[WORD]; src ¬ src-UNITS[WORD]; dst[0] ¬ MF[dst[0], src[0], lMask]; }; } ELSE { -- Unaligned case. w: WORD ¬ 0; -- source word, aligned with destination hi: WORD ¬ 0; -- left unshifted source word lo: WORD; -- right unshifted source word lSA: BitOff = LOOPHOLE[srcBit-dstBit, CARDINAL] MOD bpw; -- left shift amount rSA: BitOff = LOOPHOLE[bpw - lSA, CARDINAL] MOD bpw; -- amount to shift source words right to line them up nsw: CARD = WordsForBits[srcBit + count]; fetchLeftmost: BOOL ~ srcBit >= dstBit; fetchRightmost: BOOL ~ IF fetchLeftmost THEN (nsw>ndw) ELSE (nsw>=ndw); FetchNext: PROC ~ INLINE { lo ¬ hi; TRUSTED {hi ¬ src[0]}; src ¬ src-UNITS[WORD]; w ¬ BITLSHIFT[hi, lSA]+BITRSHIFT[lo, rSA] }; FetchLast: PROC ~ INLINE { lo ¬ hi; IF fetchLeftmost THEN TRUSTED {hi ¬ src[0]} ELSE hi ¬ 0; w ¬ BITLSHIFT[hi, lSA]+BITRSHIFT[lo, rSA] }; src ¬ src + nsw*UNITS[WORD] - UNITS[WORD]; IF fetchRightmost THEN FetchNext[]; SELECT ndw FROM 1 => TRUSTED { bothMask: WORD ~ BITAND[lMask, rMask]; FetchLast[]; dst[0] ¬ MF[dst[0], w, bothMask]; }; 2 => TRUSTED { FetchNext[]; dst[1] ¬ MF[dst[1], w, rMask]; FetchLast[]; dst[0] ¬ MF[dst[0], w, lMask]; }; 3 => TRUSTED { FetchNext[]; dst[2] ¬ MF[dst[2], w, rMask]; FetchNext[]; dst[1] ¬ w; FetchLast[]; dst[0] ¬ MF[dst[0], w, lMask]; }; ENDCASE => TRUSTED { nw: CARD ¬ LOOPHOLE[ndw-2, CARD]; FetchNext[]; dst ¬ dst + ndw*UNITS[WORD] - UNITS[WORD]; dst[0] ¬ MF[dst[0], w, rMask]; WHILE nw >= 2 DO dst ¬ dst-UNITS[WORD]*2; FetchNext[]; dst[1] ¬ w; FetchNext[]; dst[0] ¬ w; nw ¬ nw - 2; ENDLOOP; IF nw # 0 THEN { dst ¬ dst-UNITS[WORD]; FetchNext[]; dst[0] ¬ w; }; dst ¬ dst-UNITS[WORD]; FetchLast[]; dst[0] ¬ MF[dst[0], w, lMask]; }; }; }; }; MoveBits: UNSAFE PROC [ dstBase: POINTER TO RawBits, dstStart: CARD, srcBase: POINTER TO RawBits, srcStart: CARD, count: CARDINAL] ~ CHECKED { d0: CARD ~ LOOPHOLE[dstBase, CARD]*BITS[UNIT]+dstStart; s0: CARD ~ LOOPHOLE[srcBase, CARD]*BITS[UNIT]+srcStart; IF d0 IN (s0 .. s0+count) THEN { -- bad overlap. This is a pretty slow impl right now... FOR i: CARDINAL DECREASING IN [0..count) DO TRUSTED { dstBase[dstStart+i] ¬ srcBase[srcStart+i] }; ENDLOOP; } ELSE TRUSTED { CopyBits[dstBase: dstBase, dstStart: dstStart, srcBase: srcBase, srcStart: srcStart, count: count]; }; }; FillBits: UNSAFE PROC [ dstBase: POINTER TO RawBits, dstStart: CARD, count: CARDINAL, value: WORD] ~ CHECKED { dstCorr: CARD ~ LOOPHOLE[dstBase, CARD] MOD UNITS[WORD]; IF dstCorr # 0 THEN { p: PROC ¬ logMisalign; IF p # NIL THEN p[]; dstBase ¬ dstBase - dstCorr; dstStart ¬ dstStart + BITS[UNIT]*dstCorr; }; IF count # 0 THEN { dst: POINTER TO RawWords ¬ StartingWord[dstBase, dstStart]; dstBit: BitOff ~ dstStart MOD bpw; ndw: CARD ~ WordsForBits[dstBit + count]; lMask: WORD ~ RightJustifiedOnes[bpw-dstBit]; rMask: WORD ~ RightJustifiedZeros[(LOOPHOLE[bpw-dstBit-count, CARD]) MOD bpw]; SELECT ndw FROM 1 => TRUSTED { dst[0] ¬ MF[dst[0], value, BITAND[lMask, rMask]]; }; 2 => TRUSTED { dst[0] ¬ MF[dst[0], value, lMask]; dst[1] ¬ MF[dst[1], value, rMask]; }; ENDCASE => TRUSTED { nw: CARD ¬ LOOPHOLE[ndw-2, CARD]; dst[0] ¬ MF[dst[0], value, lMask]; dst ¬ dst+UNITS[WORD]; WHILE nw >= 4 DO dst[0] ¬ value; dst[1] ¬ value; dst[2] ¬ value; dst[3] ¬ value; dst ¬ dst+UNITS[WORD]*4; nw ¬ nw - 4; ENDLOOP; IF nw >= 2 THEN { dst[0] ¬ value; dst[1] ¬ value; dst ¬ dst+UNITS[WORD]*2; nw ¬ nw - 2; }; IF nw # 0 THEN { dst[0] ¬ value; dst ¬ dst+SIZE[WORD]; }; dst[0] ¬ MF[dst[0], value, rMask]; }; }; }; CompareBits: UNSAFE PROC [ aBase: POINTER TO RawBits, aStart: CARD, bBase: POINTER TO RawBits, bStart: CARD, count: CARDINAL] RETURNS [Comparison] ~ CHECKED { aCorr: CARD ~ LOOPHOLE[aBase, CARD] MOD UNITS[WORD]; bCorr: CARD ~ LOOPHOLE[aBase, CARD] MOD UNITS[WORD]; IF aCorr+bCorr # 0 THEN { p: PROC ¬ logMisalign; IF p # NIL THEN p[]; aBase ¬ aBase - aCorr; aStart ¬ aStart + BITS[UNIT]*aCorr; bBase ¬ bBase - bCorr; bStart ¬ bStart + BITS[UNIT]*bCorr; }; IF count # 0 THEN { a: POINTER TO RawWords ¬ StartingWord[aBase, aStart]; aBit: BitOff ~ aStart MOD bpw; b: POINTER TO RawWords ¬ StartingWord[bBase, bStart]; bBit: BitOff ~ bStart MOD bpw; ndw: CARD ~ WordsForBits[aBit + count]; lMask: WORD ~ RightJustifiedOnes[bpw-aBit]; rMask: WORD ~ RightJustifiedZeros[(LOOPHOLE[bpw-aBit-count, CARD]) MOD bpw]; aWord: WORD ¬ 0; bWord: WORD ¬ 0; X: PROC [aW, bW, m: WORD] ~ INLINE { aWord ¬ BITAND[aW, m]; bWord ¬ BITAND[bW, m]; }; Y: PROC [aW, bW: WORD] ~ INLINE { aWord ¬ aW; bWord ¬ bW }; { IF aBit = bBit THEN { -- Aligned case is simpler SELECT ndw FROM 1 => TRUSTED { X[a[0], b[0], BITAND[lMask, rMask]]; IF aWord # bWord THEN GOTO Differ; }; 2 => TRUSTED { X[a[0], b[0], lMask]; IF aWord # bWord THEN GOTO Differ; X[a[1], b[1], rMask]; IF aWord # bWord THEN GOTO Differ; }; 3 => TRUSTED { X[a[0], b[0], lMask]; IF aWord # bWord THEN GOTO Differ; Y[a[1], b[1]]; IF aWord # bWord THEN GOTO Differ; X[a[2], b[2], rMask]; IF aWord # bWord THEN GOTO Differ; }; ENDCASE => TRUSTED { nw: CARD ¬ LOOPHOLE[ndw-2, CARD]; X[a[0], b[0], lMask]; IF aWord # bWord THEN GOTO Differ; a ¬ a+UNITS[WORD]; b ¬ b+UNITS[WORD]; WHILE nw >= 2 DO Y[a[0], b[0]]; IF aWord # bWord THEN GOTO Differ; Y[a[1], b[1]]; IF aWord # bWord THEN GOTO Differ; a ¬ a+SIZE[WORD]*2; b ¬ b+SIZE[WORD]*2; nw ¬ nw - 2; ENDLOOP; IF nw # 0 THEN { Y[a[0], b[0]]; IF aWord # bWord THEN GOTO Differ; a ¬ a+SIZE[WORD]; b ¬ b+SIZE[WORD]; }; X[a[0], b[0], rMask]; IF aWord # bWord THEN GOTO Differ; }; } ELSE { -- Unaligned case. w: WORD ¬ 0; -- source word, aligned with destination hi: WORD; -- left unshifted source word lo: WORD ¬ 0; -- right unshifted source word lSA: BitOff = LOOPHOLE[bBit-aBit, CARDINAL] MOD bpw; -- left shift amount rSA: BitOff = LOOPHOLE[bpw - lSA, CARDINAL] MOD bpw; -- amount to shift source words right to line them up nsw: CARD = WordsForBits[bBit + count]; fetchLastWord: BOOL ~ IF bBit >= aBit THEN (nsw>ndw) ELSE (nsw>=ndw); FetchNext: PROC ~ INLINE { hi ¬ lo; TRUSTED {lo ¬ b[0]}; b ¬ b+SIZE[WORD]; w ¬ BITLSHIFT[hi, lSA]+BITRSHIFT[lo, rSA] }; FetchNextOff: PROC [wordOffset: CARD] ~ INLINE { hi ¬ lo; TRUSTED {lo ¬ b[wordOffset]}; w ¬ BITLSHIFT[hi, lSA]+BITRSHIFT[lo, rSA] }; FetchLast: PROC [wordOffset: CARD, fetch: BOOL] ~ INLINE { w ¬ BITLSHIFT[lo, lSA]; IF fetch THEN TRUSTED {w ¬ w + BITRSHIFT[b[wordOffset], rSA]}; }; IF bBit >= aBit THEN FetchNext[]; SELECT ndw FROM 1 => TRUSTED { bothMask: WORD ~ BITAND[lMask, rMask]; FetchLast[0, fetchLastWord]; X[a[0], w, bothMask]; IF aWord # bWord THEN GOTO Differ; }; 2 => TRUSTED { FetchNextOff[0]; X[a[0], w, lMask]; IF aWord # bWord THEN GOTO Differ; FetchLast[1, fetchLastWord]; X[a[1], w, rMask]; IF aWord # bWord THEN GOTO Differ; }; 3 => TRUSTED { FetchNextOff[0]; X[a[0], w, lMask]; IF aWord # bWord THEN GOTO Differ; FetchNextOff[1]; Y[a[1], w]; IF aWord # bWord THEN GOTO Differ; FetchLast[2, fetchLastWord]; X[a[2], w, rMask]; IF aWord # bWord THEN GOTO Differ; }; ENDCASE => TRUSTED { nw: CARD ¬ LOOPHOLE[ndw-2, CARD]; FetchNextOff[0]; X[a[0], w, lMask]; IF aWord # bWord THEN GOTO Differ; a ¬ a+SIZE[WORD]; b ¬ b+SIZE[WORD]; WHILE nw >= 2 DO FetchNextOff[0]; Y[a[0], w]; IF aWord # bWord THEN GOTO Differ; FetchNextOff[1]; Y[a[1], w]; IF aWord # bWord THEN GOTO Differ; a ¬ a+SIZE[WORD]*2; b ¬ b+SIZE[WORD]*2; nw ¬ nw - 2; ENDLOOP; IF nw # 0 THEN { FetchNextOff[0]; Y[a[0], w]; IF aWord # bWord THEN GOTO Differ; a ¬ a+SIZE[WORD]; b ¬ b+SIZE[WORD]; }; FetchLast[0, fetchLastWord]; X[a[0], w, rMask]; IF aWord # bWord THEN GOTO Differ; }; }; EXITS Differ => {IF aWord < bWord THEN RETURN [less] ELSE RETURN [greater]}; }; }; RETURN [equal]; }; BITSHIFT: PROC [value: WORD, count: INTEGER] RETURNS [WORD] ~ { c: [0..bitsPerWord); c ¬ LOOPHOLE[count, CARDINAL] MOD bitsPerWord; IF count = c THEN RETURN [BITLSHIFT[value, c]]; count ¬ -count; c ¬ LOOPHOLE[count, CARDINAL] MOD bitsPerWord; IF count = c THEN RETURN [BITRSHIFT[value, c]]; RETURN [0] }; ByteBlt: UNSAFE PROC [to, from: ByteBltBlock] RETURNS [nBytes: CARDINAL] ~ { nBytes ¬ MIN[ MAX[to.startIndex, to.stopIndexPlusOne] - to.startIndex, MAX[from.startIndex, from.stopIndexPlusOne] - from.startIndex ]; TRUSTED{MoveBytes[to.blockPointer, to.startIndex, from.blockPointer, from.startIndex, nBytes]}; }; ExternalNames[]; END.  BasicsImpl.mesa Copyright Σ 1985, 1986, 1990, 1991, 1992 by Xerox Corporation. All rights reserved. JKF August 26, 1988 10:49:27 am PDT Russ Atkinson (RRA) April 19, 1990 9:58 pm PDT Willie-s, March 5, 1992 3:52 pm PST Michael Plass, September 24, 1992 12:03 pm PDT Doug Wyatt, August 27, 1991 4:38 pm PDT External Names This crockery allows the assembly-coded versions of these routines to be used in lieu of the Mesa versions; we don't assume that such routines are available on all architecures. Support for bit-oriented block operations Replaces bits of d with s under the mask. Block word operations Block byte operations Misalignment Logging This is a hook to allow detection and logging of misaligned arguments to the block-oriented procedures, using, for example, Spy. Block bit operations mask for the leftmost dest word (ones where bits are to go) mask for the rightmost dest word true if last source word needs to be fetched fetches the next aligned source bits, and bumps source pointer fetches the next word at the given offset, no pointer change fetches the final source bits on a line, avoiding a spurious fetch mask for the leftmost dest word (ones where bits are to go) mask for the rightmost dest word fetches the next aligned source bits, and bumps source pointer fetches the last (leftmost) source bits on a line, avoiding a spurious fetch NOTE: A better name might be PatternFillBits, since the value is a whole word of bits rather than a single bit. mask for the leftmost dest word (ones where bits are to go) mask for the rightmost dest word mask for the leftmost dest word (ones where bits are to go) mask for the rightmost dest word true if last source word needs to be fetched fetches the next aligned source bits, and bumps source pointer fetches the next word at the given offset, no pointer change fetches the final source bits on a line, avoiding a spurious fetch Shifts ByteBlt (compatibility). Κΐ–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ ΟeœI™TKšΟkœ ™#K™.K™#K™.K™'K™—Kšž œ˜K˜KšΟn œžœžœ˜Kšžœ˜Kšœžœžœ˜K˜headšœ™š Ÿ œžœžœžœžœ˜0Iascii˜M˜M˜DM˜DMšœ˜Mšœ˜Mšœ˜Mšœ˜Mšœ˜Mšœ˜Mšœ$˜$Mšœ˜Mšœ˜Mšœ3˜3Mšœ3˜3K˜K˜—Kšœžœ˜<šŸœžœžœžœžœžœžœ˜JK™±K˜K˜-K˜3K˜3K˜ K˜-K˜ K˜ Kšœ˜K˜——™)Kšœžœžœžœ˜Kšœžœ ˜šœ žœ ˜K˜—š Ÿ œžœžœžœžœžœ˜9Kšžœžœ˜K˜K˜—š Ÿœžœžœžœžœ˜@Kšžœž œžœ˜,K˜K˜—š Ÿœžœ žœžœžœ˜?Kšžœž œ˜*K˜K˜—šŸ œžœžœžœžœžœžœžœ žœžœ˜nKš žœžœžœžœžœ˜?Kšœ˜K˜—š žœžœžœžœžœžœ˜5K™)Kšžœžœžœžœ˜.K˜K˜——™šŸ œžœžœžœžœžœžœžœ˜dšžœžœžœ ž˜ Kšžœ˜Kšžœ˜—Kšœ˜K˜—šŸ œžœžœžœžœžœžœžœ˜dš žœžœžœžœžœ˜*šžœ˜šžœžœžœ ž˜Kšžœ˜Kšžœ˜—K˜—šžœ˜š žœžœž œžœ ž˜*Kšžœ˜Kšžœ˜—K˜——Kšœ˜K˜—šŸ œžœžœžœžœžœ žœž œ˜`Kšœžœžœžœžœžœžœžœ˜8šžœ ž˜Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kš œžœžœžœžœ˜#Kšœ˜Kšžœ˜—Kšžœ žœžœ˜Kšœ ˜ Kšžœ žœžœ˜Kšœ ˜ Kšžœ žœžœ˜Kšœ ˜ Kšœ˜——™šŸ œžœžœ žœžœžœ žœžœžœ žœžœ˜”Kšžœžœžœ žœ˜6Kšžœžœžœ žœ˜6Kš žœ žœžœžœžœžœ˜>šœ ˜ Kšœ žœžœžœ˜:Kšœ žœžœžœ˜:Kšœ žœžœ˜K˜—Kšœ˜K˜—šŸ œžœžœ žœžœžœ žœžœžœ žœ˜ŒKš œžœžœ žœžœžœ ˜8Kš œžœžœ žœžœžœ ˜8Kšžœžœžœ žœ˜6Kšžœžœžœ žœ˜6Kš žœ žœžœžœžœžœ˜>šžœžœ˜šžœΟc˜š žœžœž œžœ ž˜*Kšžœ/˜6Kšžœ˜—K˜—šžœžœ˜šœ ˜ Kšœ žœžœžœ˜:Kšœ žœžœžœ˜:Kšœ žœžœ˜K˜—K˜——Kšœ˜K˜—šŸ œžœžœ žœžœžœ žœ žœžœ˜rKšœ žœ˜%Kšœ%˜%šžœ˜ šœ ˜ Kšœ žœžœžœ˜:Kšœ žœžœ˜)Kšœ˜—K˜—Kšœ˜——™K™€Kšœ žœžœ˜šŸœžœžœ˜'Kšœ˜Kšœ˜——™šŸœžœžœ žœžœžœ žœžœžœ žœžœ˜‘Kš œ žœžœ žœžœžœžœ˜8Kš œ žœžœ žœžœžœžœ˜8šžœžœ˜Kšœžœ˜Kšžœžœžœ˜Kšœ˜Kšœžœžœ ˜)Kšœ˜Kšœžœžœ ˜)Kšœ˜—šžœ žœ˜Kšœžœžœ,˜;Kšœžœ˜"Kšœžœžœ,˜;Kšœžœ˜"Kšœžœ ˜)šœžœ"˜-Kšœ;™;—š œžœžœžœžœ˜NKšœ ™ —šžœ˜šžœ ˜!šžœž˜šœžœ˜Kšœ žœžœ˜2Kšœ˜—šœžœ˜Kšœ žœ˜#Kšœ žœ˜#Kšœ˜—šœžœ˜Kšœ žœ˜#Kšœ˜Kšœ žœ˜#Kšœ˜—šžœžœ˜Kšœžœžœžœ˜!Kšœ žœ˜#Kšœ žœžœ˜Kšœ žœžœ˜šžœ ž˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ žœžœ˜Kšœ žœžœ˜K˜ Kšžœ˜—šžœ žœ˜Kšœ˜Kšœ˜Kšœ žœžœ˜Kšœ žœžœ˜K˜ K˜—šžœžœ˜Kšœ˜Kšœ žœžœ˜Kšœ žœžœ˜K˜—Kšœ žœ˜#Kšœ˜——Kšœ˜—šžœ ˜Kšœžœ (˜5Kšœžœ ˜'Kšœžœ ˜,Kšœžœžœžœ ˜MKšœžœ žœžœ 5˜jKšœžœ ˜)š œžœžœžœ žœ ˜IKšœ,™,—šŸ œžœžœ˜Kšœ>™>K˜Kšžœ˜Kšœ žœžœ˜Kšœž œ ž œ ˜)K˜—šŸ œžœžœžœ˜0Kšœ<™™>K˜Kšžœ˜Kšœ žœžœ˜Kšœž œ ž œ ˜)K˜—šŸ œžœžœ˜KšœL™LK˜Kšžœžœžœžœ˜8Kšœž œ ž œ ˜)K˜—Kš œžœžœžœžœ˜*Kšžœžœ ˜#šžœž˜šœžœ˜Kšœ žœžœ˜&Kšœ ˜ Kšœ žœ˜!K˜—šœžœ˜K˜ Kšœ žœ˜Kšœ ˜ Kšœ žœ˜K˜—šœžœ˜K˜ Kšœ žœ˜K˜ K˜ Kšœ ˜ Kšœ žœ˜K˜—šžœžœ˜Kšœžœžœžœ˜!K˜ Kš œžœžœžœžœ˜*Kšœ žœ˜šžœ ž˜Kšœ žœžœ˜K˜ K˜ K˜ K˜ K˜ Kšžœ˜—šžœžœ˜Kšœ žœžœ˜K˜ K˜ K˜—Kšœ žœžœ˜Kšœ ˜ Kšœ žœ˜K˜——Kšœ˜——Kšœ˜—Kšœ˜K˜—šŸœžœžœ žœžœžœ žœžœžœ žœžœ˜Kš œžœžœ žœžœžœ ˜7Kš œžœžœ žœžœžœ ˜7šžœžœ˜šžœ 8˜?š žœžœž œžœ ž˜+Kšžœ/˜6Kšžœ˜—K˜—šžœžœ˜Kšœc˜cK˜——Kšœ˜K˜—šŸœžœžœ žœžœžœ žœ žœžœ˜oJ™oKš œ žœžœ žœžœžœžœ˜8šžœ žœ˜Kšœžœ˜Kšžœžœžœ˜Kšœ˜Kšœžœžœ ˜)Kšœ˜—šžœ žœ˜Kšœžœžœ,˜;Kšœžœ˜"Kšœžœ ˜)šœžœ"˜-Kšœ;™;—š œžœžœžœžœ˜NKšœ ™ —šžœž˜šœžœ˜Kšœ žœžœ˜1Kšœ˜—šœžœ˜Kšœ žœ˜"Kšœ žœ˜"Kšœ˜——šžœžœ˜Kšœžœžœžœ˜!Kšœ žœ˜"Kšœ žœžœ˜šžœ ž˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ žœžœ˜K˜ Kšžœ˜—šžœ žœ˜Kšœ˜Kšœ˜Kšœ žœžœ˜K˜ K˜—šžœžœ˜Kšœ˜Kšœ žœžœ˜K˜—Kšœ žœ˜"Kšœ˜—Kšœ˜—Kšœ˜K˜—šŸ œžœžœ žœžœžœ žœžœžœ žœžœžœ˜ Kš œžœžœžœžœžœžœ˜4Kš œžœžœžœžœžœžœ˜4šžœžœ˜Kšœžœ˜Kšžœžœžœ˜Kšœ˜Kšœžœžœ˜#Kšœ˜Kšœžœžœ˜#Kšœ˜—šžœ žœ˜Kšœžœžœ(˜5Kšœžœ˜Kšœžœžœ(˜5Kšœžœ˜Kšœžœ˜'šœžœ ˜+Kšœ;™;—š œžœžœžœžœ˜LKšœ ™ —Kšœžœ˜Kšœžœ˜šŸœžœ žœžœ˜$Kšœžœ˜Kšœžœ˜Kšœ˜—KšŸœžœ žœžœ˜;šœ˜šžœ ˜šžœ ˜!šžœž˜šœžœ˜Kš œžœžœžœžœ˜GKšœ˜—šœžœ˜Kšœžœžœžœ˜8Kšœžœžœžœ˜8Kšœ˜—šœžœ˜Kšœžœžœžœ˜8Kšœžœžœžœ˜1Kšœžœžœžœ˜8Kšœ˜—šžœžœ˜Kšœžœžœžœ˜!Kšœžœžœžœ˜8Kšœžœžœ˜Kšœžœžœ˜šžœ ž˜Kšœžœžœžœ˜1Kšœžœžœžœ˜1Kšœžœžœ˜Kšœžœžœ˜K˜ Kšžœ˜—šžœžœ˜Kšœžœžœžœ˜1Kšœžœžœ˜Kšœžœžœ˜K˜—Kšœžœžœžœ˜8Kšœ˜——Kšœ˜—šžœ ˜Kšœžœ (˜5Kšœžœ ˜'Kšœžœ ˜,Kšœžœ žœžœ ˜IKšœžœ žœžœ 5˜jKšœžœ˜'š œžœžœžœ žœ ˜EKšœ,™,—šŸ œžœžœ˜Kšœ>™>K˜Kšžœ ˜Kšœžœžœ˜Kšœž œ ž œ ˜)K˜—šŸ œžœžœžœ˜0Kšœ<™K˜—Kšžœžœ ˜!šžœž˜šœžœ˜Kšœ žœžœ˜&Kšœ˜Kšœžœžœžœ˜8K˜—šœžœ˜K˜Kšœžœžœžœ˜5K˜Kšœžœžœžœ˜5K˜—šœžœ˜K˜Kšœžœžœžœ˜5K˜Kšœ žœžœžœ˜.K˜Kšœžœžœžœ˜5K˜—šžœžœ˜Kšœžœžœžœ˜!K˜Kšœžœžœžœ˜5Kšœžœžœ˜Kšœžœžœ˜šžœ ž˜K˜Kšœ žœžœžœ˜.K˜Kšœ žœžœžœ˜.Kšœžœžœ˜Kšœžœžœ˜K˜ Kšžœ˜—šžœžœ˜K˜Kšœ žœžœžœ˜.Kšœžœžœ˜Kšœžœžœ˜K˜—K˜Kšœžœžœžœ˜5K˜——Kšœ˜——Kš žœ žœžœžœžœžœ ˜LKšœ˜—Kšœ˜—Kšžœ ˜Kšœ˜K˜——™š Πbkœžœ žœ žœžœžœ˜?Kšœ˜Kšœžœžœžœ ˜.Kšžœ žœžœž œ ˜/Kšœ˜Kšœžœžœžœ ˜.Kšžœ žœžœž œ ˜/Kšžœ˜ Kšœ˜——šœ™š Ÿœžœžœžœ žœ˜Mšœ žœ˜ Kšžœ5˜8Kšžœ:˜=Kšœ˜—KšžœX˜_Kšœ˜K˜—Kšœ˜K˜—Kšžœ˜K˜—…—E¬kό