<> <> <> DIRECTORY Basics USING [bitsPerWord, BITAND, BITOR, BITXOR, BITNOT, BITSHIFT], BitOps, BitSwOps, SwitchTypes; BitOpsImpl: CEDAR PROGRAM IMPORTS Basics EXPORTS BitOps, BitSwOps = PUBLIC BEGIN OPEN Basics, BitOps, BitSwOps; bitsPerWord: CARDINAL = Basics.bitsPerWord; none: SwitchTypes.Strength = SwitchTypes.none; wordMasks: PUBLIC ARRAY [0 .. Basics.bitsPerWord] OF CARDINAL _ ALL[BitWordZero]; doubleMasks: PUBLIC ARRAY [0 .. 2*Basics.bitsPerWord] OF BitDWord _ ALL[[BitWordZero, BitWordOnes]]; BitsPtr: TYPE = LONG POINTER TO PACKED ARRAY CARDINAL OF BOOL; WordAsBits: TYPE = PACKED ARRAY [0..LastWBit] OF BOOL; LongAsWords: TYPE = MACHINE DEPENDENT RECORD [ low: CARDINAL, high: CARDINAL]; ToS: PROC [sl: StrengthenedLevel] RETURNS [s: PACKED ARRAY StrengthIndex OF SwitchTypes.Strength] = INLINE BEGIN SELECT sl.level FROM L => {s[u] _ none; s[d] _ sl.strength}; X => {s[u] _ sl.strength; s[d] _ sl.strength}; H => {s[u] _ sl.strength; s[d] _ none}; ENDCASE => ERROR; END; ExtractBoolFWord, EBFW: PROC [container: BitWord, containerWidth, bitPosition: CARDINAL] RETURNS [result: BOOL] = { t:WordAsBits _ LOOPHOLE[container]; IF containerWidth>bitsPerWord OR bitPosition>(containerWidth-1) THEN ERROR; RETURN[t[bitPosition+bitsPerWord-containerWidth]]; }; InsertBoolInWord, IBIW: PROC [source: BOOL, container: BitWord, containerWidth, bitPosition: CARDINAL] RETURNS [newContainer: BitWord] = { t:WordAsBits _ LOOPHOLE[container]; IF containerWidth>bitsPerWord OR bitPosition>(containerWidth-1) THEN ERROR; t[bitPosition+bitsPerWord-containerWidth] _ source; RETURN[LOOPHOLE[t]]; }; ExtractBoolFDouble, EBFD: PUBLIC PROC [container: BitDWord, containerWidth, bitPosition: CARDINAL] RETURNS [result: BOOL] = TRUSTED {result _ EBFM[DESCRIPTOR[container], containerWidth, bitPosition]}; InsertBoolInDouble, IBID: PUBLIC PROC [source: BOOL, container: BitDWord, containerWidth, bitPosition: CARDINAL] RETURNS [newContainer: BitDWord] = TRUSTED { newContainer _ container; IBIM[source, DESCRIPTOR[newContainer], containerWidth, bitPosition]}; ExtractBoolFMultiple, EBFM: PROC [container: BitMWord, containerWidth, bitPosition: CARDINAL] RETURNS [result: BOOL] = TRUSTED { pos: CARDINAL _ bitPosition+LENGTH[container]*bitsPerWord-containerWidth; word: CARDINAL _ pos/bitsPerWord; IF word>=LENGTH[container] THEN ERROR; RETURN[EBFW[container[word], bitsPerWord, pos MOD bitsPerWord]]; }; InsertBoolInMultiple, IBIM: PROC [source: BOOL, container: BitMWord, containerWidth, bitPosition: CARDINAL] = TRUSTED { pos: CARDINAL _ bitPosition+LENGTH[container]*bitsPerWord-containerWidth; word: CARDINAL _ pos/bitsPerWord; IF word >= LENGTH[container] THEN ERROR; container[word] _ IBIW[source, container[word], bitsPerWord, pos MOD bitsPerWord]; }; ExtractBoolFSwitch, EBFS: PUBLIC PROC [container: SwitchMWord, containerWidth, bitPosition: CARDINAL] RETURNS [result: BOOL] = TRUSTED {result _ SELECT container[bitPosition].val FROM L => FALSE, X => ERROR, H => TRUE, ENDCASE => ERROR}; InsertBoolInSwitch, IBIS: PUBLIC PROC [source: BOOL, container: SwitchMWord, containerWidth, bitPosition: CARDINAL, si: StrengthIndex, how: BoolStrengths] = TRUSTED {container[bitPosition].s[si] _ how[source]}; SpecialInsertBoolInSwitch, SIBIS: PUBLIC PROC [source: BOOL, container: SwitchMWord, containerWidth, bitPosition: CARDINAL, how: BoolSwitches] = TRUSTED {container[bitPosition].s _ ToS[how[source]]}; ExtractBoolFSingleSwitch, EBFSS: PUBLIC PROC [container: Switch] RETURNS [result: BOOL] = {result _ SELECT container.val FROM L => FALSE, X => ERROR, H => TRUE, ENDCASE => ERROR}; InsertBoolInSingleSwitch, IBISS: PUBLIC PROC [source: BOOL, container: Switch, si: StrengthIndex, how: BoolStrengths] RETURNS [newContainer: Switch] = {newContainer _ container; newContainer.s[si] _ how[source]}; SpecialInsertBoolInSingleSwitch, SIBISS: PUBLIC PROC [source: BOOL, container: Switch, how: BoolSwitches] RETURNS [newContainer: Switch] = {newContainer _ container; newContainer.s _ ToS[how[source]]}; ExtractCardinalFWord, ECFW: PROC [container: BitWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] RETURNS [result: CARDINAL] = { shift: INTEGER _ INTEGER[fieldPosition] + fieldWidth - containerWidth; IF containerWidth > bitsPerWord OR shift > 0 THEN ERROR; RETURN[BITAND[BITSHIFT[container, shift], wordMasks[fieldWidth]]]; }; InsertCardinalInWord, ICIW: PROC [source: CARDINAL, container: BitWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] RETURNS [newContainer: BitWord] = { shift: INTEGER _ INTEGER[containerWidth] - (fieldPosition+fieldWidth); IF containerWidth > bitsPerWord OR shift < 0 THEN ERROR; RETURN[BITOR[BITSHIFT[source, shift], BITAND[BITNOT[BITSHIFT[wordMasks[fieldWidth], shift]], container]]]; }; ExtractCardinalFDouble, ECFD: PUBLIC PROC [container: BitDWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] RETURNS [result: CARDINAL] = TRUSTED {result _ ECFM[DESCRIPTOR[container], containerWidth, fieldPosition, fieldWidth]}; InsertCardinalInDouble, ICID: PUBLIC PROC [source: CARDINAL, container: BitDWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] RETURNS [newContainer: BitDWord] = TRUSTED { newContainer _ container; ICIM[source, DESCRIPTOR[newContainer], containerWidth, fieldPosition, fieldWidth]}; ExtractCardinalFMultiple, ECFM: PROC [container: BitMWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] RETURNS [result: CARDINAL] = TRUSTED { containerSize: INTEGER _ LENGTH[container] * bitsPerWord; endBit: INTEGER = (containerSize - containerWidth) + fieldPosition + fieldWidth-1; endWord: INTEGER = endBit/bitsPerWord; lowWidth: INTEGER = (endBit MOD bitsPerWord) + 1; IF INTEGER[containerWidth]>containerSize OR fieldPosition+fieldWidth>containerWidth THEN ERROR; result _ BITSHIFT[container[endWord], lowWidth-bitsPerWord]; IF lowWidth < INTEGER[fieldWidth] THEN result _ BITOR[BITSHIFT[container[endWord-1], lowWidth], result]; result _ BITAND[result, wordMasks[fieldWidth]]; }; InsertCardinalInMultiple, ICIM: PROC [source: CARDINAL, container: BitMWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] = TRUSTED { containerSize: INTEGER _ LENGTH[container] * bitsPerWord; endBit: INTEGER = (containerSize - containerWidth) + fieldPosition + fieldWidth-1; endWord: INTEGER = endBit/bitsPerWord; lowWidth: INTEGER = (endBit MOD bitsPerWord) + 1; lowShift: INTEGER = bitsPerWord - lowWidth; IF INTEGER[containerWidth]>containerSize OR fieldPosition+fieldWidth>containerWidth THEN ERROR; container[endWord] _ BITOR[ BITSHIFT[source, lowShift], BITAND[ BITNOT[BITSHIFT[wordMasks[fieldWidth], lowShift]], container[endWord]]]; IF lowWidth < INTEGER[fieldWidth] THEN container[endWord-1] _ BITOR[ BITSHIFT[source, -lowWidth], BITAND[ BITNOT[BITSHIFT[wordMasks[fieldWidth], -lowWidth]], container[endWord-1]]]; }; ExtractCardinalFSwitch, ECFS: PUBLIC PROC [container: SwitchMWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] RETURNS [result: CARDINAL] = { IF fieldWidth > bitsPerWord THEN ERROR; result _ 0; FOR i: CARDINAL IN [0 .. fieldWidth) DO result _ result * 2; IF EBFS[container, containerWidth, fieldPosition+i] THEN result _ result+1; ENDLOOP}; InsertCardinalInSwitch, ICIS: PUBLIC PROC [source: CARDINAL, container: SwitchMWord, containerWidth, fieldPosition, fieldWidth: CARDINAL, si: StrengthIndex, how: BoolStrengths] = { IF fieldWidth > bitsPerWord THEN ERROR; FOR i: CARDINAL DECREASING IN [0 .. fieldWidth) DO bit: BOOL = 0 # (source MOD 2); IBIS[bit, container, containerWidth, fieldPosition+i, si, how]; source _ source / 2; ENDLOOP}; SpecialInsertCardinalInSwitch, SICIS: PUBLIC PROC [source: CARDINAL, container: SwitchMWord, containerWidth, fieldPosition, fieldWidth: CARDINAL, how: BoolSwitches] = { IF fieldWidth > bitsPerWord THEN ERROR; FOR i: CARDINAL DECREASING IN [0 .. fieldWidth) DO bit: BOOL = 0 # (source MOD 2); SIBIS[bit, container, containerWidth, fieldPosition+i, how]; source _ source / 2; ENDLOOP}; <> <<{result _ SELECT container.val FROM L => 0, X => ERROR, H => 1, ENDCASE => ERROR};>> <<>> <> <<{newContainer _ container; newContainer.s[si] _ how[source=1]};>> ExtractLongFWord, ELFW: PROC [container: BitWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] RETURNS [result: Long] = {result _ ECFW[container, containerWidth, fieldPosition, fieldWidth]}; InsertLongInWord, ILIW: PROC [source: Long, container: BitWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] RETURNS [newContainer: BitWord] = {newContainer _ ILIW[source, container, containerWidth, fieldPosition, fieldWidth]}; ExtractLongFDouble, ELFD: PROC [container: BitDWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] RETURNS [result: Long] = TRUSTED {result _ ELFM[DESCRIPTOR[container], containerWidth, fieldPosition, fieldWidth]}; InsertLongInDouble, ILID: PROC [source: Long, container: BitDWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] RETURNS [newContainer: BitDWord] = TRUSTED { newContainer _ container; ILIM[source, DESCRIPTOR[newContainer], containerWidth, fieldPosition, fieldWidth]}; ExtractLongFMultiple, ELFM: PROC [container: BitMWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] RETURNS [result: Long] = { IF fieldWidth <= bitsPerWord THEN RETURN [ECFM[container, containerWidth, fieldPosition, fieldWidth]] ELSE TRUSTED {law: LongAsWords; rem: CARDINAL = fieldWidth - bitsPerWord; law.high _ ECFM[container, containerWidth, fieldPosition, rem]; law.low _ ECFM[container, containerWidth, fieldPosition+rem, bitsPerWord]; result _ LOOPHOLE[law]}}; InsertLongInMultiple, ILIM: PROC [source: Long, container: BitMWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] = { IF fieldWidth <= bitsPerWord THEN ICIM[source, container, containerWidth, fieldPosition, fieldWidth] ELSE TRUSTED {law: LongAsWords _ LOOPHOLE[source]; rem: CARDINAL = fieldWidth - bitsPerWord; ICIM[law.high, container, containerWidth, fieldPosition, rem]; ICIM[law.low, container, containerWidth, fieldPosition+rem, bitsPerWord]}}; ExtractLongFSwitch, ELFS: PUBLIC PROC [container: SwitchMWord, containerWidth, fieldPosition, fieldWidth: CARDINAL] RETURNS [result: Long] = { IF fieldWidth > 2*bitsPerWord THEN ERROR; result _ 0; FOR i: CARDINAL IN [0 .. 2*fieldWidth) DO result _ result * 2; IF EBFS[container, containerWidth, fieldPosition+i] THEN result _ result+1; ENDLOOP}; InsertLongInSwitch, ILIS: PUBLIC PROC [source: Long, container: SwitchMWord, containerWidth, fieldPosition, fieldWidth: CARDINAL, si: StrengthIndex, how: BoolStrengths] = { IF fieldWidth > 2*bitsPerWord THEN ERROR; FOR i: CARDINAL DECREASING IN [0 .. 2*fieldWidth) DO bit: BOOL = 0 # (source MOD 2); IBIS[bit, container, containerWidth, fieldPosition+i, si, how]; source _ source / 2; ENDLOOP}; SpecialInsertLongInSwitch, SILIS: PUBLIC PROC [source: Long, container: SwitchMWord, containerWidth, fieldPosition, fieldWidth: CARDINAL, how: BoolSwitches] = { IF fieldWidth > 2*bitsPerWord THEN ERROR; FOR i: CARDINAL DECREASING IN [0 .. 2*fieldWidth) DO bit: BOOL = 0 # (source MOD 2); SIBIS[bit, container, containerWidth, fieldPosition+i, how]; source _ source / 2; ENDLOOP}; MoveWordToWord, MWTW: PROC [sourceContainer: BitWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: BitWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL] RETURNS [newContainer: BitWord] = { IF sourceWidth # destinationWidth THEN ERROR; RETURN[ICIW[ECFW[sourceContainer, sourceContainerWidth, sourcePosition, sourceWidth], destinationContainer, destinationContainerWidth, destinationPosition, destinationWidth]]; }; MoveWordToDouble, MWTD: PROC [sourceContainer: BitWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: BitDWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL] RETURNS [newContainer: BitDWord] = TRUSTED { newContainer _ destinationContainer; MWTM[sourceContainer, sourceContainerWidth, sourcePosition, sourceWidth, DESCRIPTOR[newContainer], destinationContainerWidth, destinationPosition, destinationWidth]}; MoveWordToMultiple, MWTM: PROC [sourceContainer: BitWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: BitMWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL] = { IF sourceWidth # destinationWidth THEN ERROR; ICIM[ECFW[sourceContainer, sourceContainerWidth, sourcePosition, sourceWidth], destinationContainer, destinationContainerWidth, destinationPosition, destinationWidth]; }; ConvertWordToSwitch, CWTS: PUBLIC PROC [sourceContainer: BitWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: SwitchMWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL, si: StrengthIndex, how: BoolStrengths] = TRUSTED { source: ARRAY [0 .. 0] OF CARDINAL _ [sourceContainer]; IF sourceContainerWidth > bitsPerWord THEN ERROR; CMTS[DESCRIPTOR[source], sourceContainerWidth, sourcePosition, sourceWidth, destinationContainer, destinationContainerWidth, destinationPosition, destinationWidth, si, how]}; SpecialConvertWordToSwitch, SCWTS: PUBLIC PROC [sourceContainer: BitWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: SwitchMWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL, how: BoolSwitches] = TRUSTED { source: ARRAY [0 .. 0] OF CARDINAL _ [sourceContainer]; IF sourceContainerWidth > bitsPerWord THEN ERROR; SCMTS[DESCRIPTOR[source], sourceContainerWidth, sourcePosition, sourceWidth, destinationContainer, destinationContainerWidth, destinationPosition, destinationWidth, how]}; MoveDoubleToWord, MDTW: PROC [sourceContainer: BitDWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: BitWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL] RETURNS [newContainer: BitWord] = TRUSTED {newContainer _ MMTW[DESCRIPTOR[sourceContainer], sourceContainerWidth, sourcePosition, sourceWidth, destinationContainer, destinationContainerWidth, destinationPosition, destinationWidth]}; MoveDoubleToDouble, MDTD: PROC [sourceContainer: BitDWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: BitDWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL] RETURNS [newContainer: BitDWord] = TRUSTED { newContainer _ destinationContainer; MMTM[DESCRIPTOR[sourceContainer], sourceContainerWidth, sourcePosition, sourceWidth, DESCRIPTOR[newContainer], destinationContainerWidth, destinationPosition, destinationWidth]}; MoveDoubleToMultiple, MDTM: PROC [sourceContainer: BitDWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: BitMWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL] = TRUSTED {MMTM[DESCRIPTOR[sourceContainer], sourceContainerWidth, sourcePosition, sourceWidth, destinationContainer, destinationContainerWidth, destinationPosition, destinationWidth]}; ConvertDoubleToSwitch, CDTS: PROC [sourceContainer: BitDWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: SwitchMWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL, si: StrengthIndex, how: BoolStrengths] = TRUSTED { IF sourceContainerWidth > 2*bitsPerWord THEN ERROR; CMTS[DESCRIPTOR[sourceContainer], sourceContainerWidth, sourcePosition, sourceWidth, destinationContainer, destinationContainerWidth, destinationPosition, destinationWidth, si, how]}; SpecialConvertDoubleToSwitch, SCDTS: PUBLIC PROC [sourceContainer: BitDWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: SwitchMWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL, how: BoolSwitches] = TRUSTED { IF sourceContainerWidth > 2*bitsPerWord THEN ERROR; SCMTS[DESCRIPTOR[sourceContainer], sourceContainerWidth, sourcePosition, sourceWidth, destinationContainer, destinationContainerWidth, destinationPosition, destinationWidth, how]}; MoveMultipleToWord, MMTW: PROC [sourceContainer: BitMWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: BitWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL] RETURNS [newContainer: BitWord] = { IF sourceWidth # destinationWidth THEN ERROR; RETURN[ICIW[ECFM[sourceContainer, sourceContainerWidth, sourcePosition, sourceWidth], destinationContainer, destinationContainerWidth, destinationPosition, destinationWidth]]; }; MoveMultipleToDouble, MMTD: PROC [sourceContainer: BitMWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: BitDWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL] RETURNS [newContainer: BitDWord] = TRUSTED { newContainer _ destinationContainer; MMTM[sourceContainer, sourceContainerWidth, sourcePosition, sourceWidth, DESCRIPTOR[newContainer], destinationContainerWidth, destinationPosition, destinationWidth]}; MoveMultipleToMultiple, MMTM: PROC [sourceContainer: BitMWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: BitMWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL] = { IF destinationWidth # sourceWidth THEN ERROR; IF destinationWidth <= bitsPerWord THEN ICIM[ ECFM[sourceContainer, sourceContainerWidth, sourcePosition, sourceWidth], destinationContainer, destinationContainerWidth, destinationPosition, destinationWidth] ELSE TRUSTED { sourcePad: INTEGER = LENGTH[sourceContainer]*bitsPerWord - sourceContainerWidth; destPad: INTEGER = LENGTH[destinationContainer]*bitsPerWord - destinationContainerWidth; <> <> <> firstDest: INTEGER = (destPad+destinationPosition) / bitsPerWord; lastDest: INTEGER = (destPad+destinationPosition + destinationWidth - 1) / bitsPerWord; delta: INTEGER = (sourcePad+sourcePosition) - (destPad+destinationPosition); l: INTEGER = LENGTH[sourceContainer] - 1; db1: INTEGER _ delta MOD bitsPerWord; dw1: INTEGER _ delta / bitsPerWord; db2, dw2: INTEGER; firstBits: INTEGER = bitsPerWord - ((destPad+destinationPosition) MOD bitsPerWord); nextBits: INTEGER = bitsPerWord-1 - ((destPad + destinationPosition + destinationWidth - 1) MOD bitsPerWord); IF dw1*bitsPerWord+db1 # delta THEN ERROR; IF delta < 0 THEN {db1 _ db1 + bitsPerWord; dw1 _ dw1 - 1}; db2 _ db1 - bitsPerWord; dw2 _ dw1 + 1; FOR destIndex: INTEGER IN [firstDest .. lastDest] DO dest: CARDINAL _ BITOR[ BITSHIFT[sourceContainer[MAX[destIndex + dw1, 0]], db1], BITSHIFT[sourceContainer[MIN[destIndex + dw2, l]], db2]]; IF destIndex = firstDest THEN destinationContainer[destIndex] _ BITOR[ BITAND[dest, wordMasks[firstBits]], BITAND[destinationContainer[destIndex], BITNOT[wordMasks[firstBits]]]] ELSE IF destIndex = lastDest THEN destinationContainer[destIndex] _ BITOR[ BITAND[dest, BITNOT[wordMasks[nextBits]]], BITAND[destinationContainer[destIndex], wordMasks[nextBits]]] ELSE destinationContainer[destIndex] _ dest; ENDLOOP; }; }; ConvertMultipleToSwitch, CMTS: PUBLIC PROC [sourceContainer: BitMWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: SwitchMWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL, si: StrengthIndex, how: BoolStrengths] = TRUSTED { bits: BitsPtr _ LOOPHOLE[@sourceContainer[0]]; bitsOff: CARDINAL = (bitsPerWord - (sourceContainerWidth MOD bitsPerWord)) MOD bitsPerWord; IF sourceWidth # destinationWidth THEN ERROR; IF sourceWidth > sourceContainerWidth THEN ERROR; IF destinationWidth > destinationContainerWidth THEN ERROR; FOR i: CARDINAL IN [0 .. sourceWidth) DO destinationContainer[destinationPosition+i].s[si] _ how[bits[bitsOff+sourcePosition+i]]; ENDLOOP}; SpecialConvertMultipleToSwitch, SCMTS: PROC [sourceContainer: BitMWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: SwitchMWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL, how: BoolSwitches] = TRUSTED { bits: BitsPtr _ LOOPHOLE[@sourceContainer[0]]; bitsOff: CARDINAL = (bitsPerWord - (sourceContainerWidth MOD bitsPerWord)) MOD bitsPerWord; IF sourceWidth # destinationWidth THEN ERROR; IF sourceWidth > sourceContainerWidth THEN ERROR; IF destinationWidth > destinationContainerWidth THEN ERROR; FOR i: CARDINAL IN [0 .. sourceWidth) DO destinationContainer[destinationPosition+i].s _ ToS[how[bits[bitsOff+sourcePosition+i]]]; ENDLOOP}; ConvertSwitchToWord, CSTW: PUBLIC PROC [sourceContainer: SwitchMWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: BitWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL] RETURNS [newContainer: BitWord] = TRUSTED { dest: ARRAY [0 .. 0] OF CARDINAL _ [destinationContainer]; IF destinationContainerWidth > bitsPerWord THEN ERROR; CSTM[sourceContainer, sourceContainerWidth, sourcePosition, sourceWidth, DESCRIPTOR[dest], destinationContainerWidth, destinationPosition, destinationWidth]; newContainer _ dest[0]}; ConvertSwitchToDouble, CSTD: PUBLIC PROC [sourceContainer: SwitchMWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: BitDWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL] RETURNS [newContainer: BitDWord] = TRUSTED { IF destinationContainerWidth > 2*bitsPerWord THEN ERROR; newContainer _ destinationContainer; CSTM[sourceContainer, sourceContainerWidth, sourcePosition, sourceWidth, DESCRIPTOR[newContainer], destinationContainerWidth, destinationPosition, destinationWidth]}; ConvertSwitchToMultiple, CSTM: PUBLIC PROC [sourceContainer: SwitchMWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: BitMWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL] = TRUSTED { bits: BitsPtr = LOOPHOLE[@destinationContainer[0]]; bitsOff: CARDINAL = (bitsPerWord - (destinationContainerWidth MOD bitsPerWord)) MOD bitsPerWord; IF sourceWidth # destinationWidth THEN ERROR; IF sourceWidth > sourceContainerWidth THEN ERROR; IF destinationWidth > destinationContainerWidth THEN ERROR; FOR i: CARDINAL IN [0 .. sourceWidth) DO bits[bitsOff+destinationPosition+i] _ SELECT sourceContainer[sourcePosition+i].val FROM L => FALSE, X => ERROR, H => TRUE, ENDCASE => ERROR; ENDLOOP}; MoveSwitchToSwitch, MSTS: PUBLIC PROC [sourceContainer: SwitchMWord, sourceContainerWidth, sourcePosition, sourceWidth: CARDINAL, destinationContainer: SwitchMWord, destinationContainerWidth, destinationPosition, destinationWidth: CARDINAL] = TRUSTED { IF sourceWidth # destinationWidth THEN ERROR; IF sourceWidth > sourceContainerWidth THEN ERROR; IF destinationWidth > destinationContainerWidth THEN ERROR; FOR i: CARDINAL IN [0 .. destinationWidth) DO destinationContainer[destinationPosition+i] _ sourceContainer[sourcePosition+i]; ENDLOOP}; WordAND, WAND: PROC [op1, op2: BitWord] RETURNS [result: BitWord] = {result _ BITAND[op1, op2]}; WordOR, WOR: PROC [op1, op2: BitWord] RETURNS [result: BitWord] = {result _ BITOR[op1, op2]}; WordXOR, WXOR: PROC [op1, op2: BitWord] RETURNS [result: BitWord] = {result _ BITXOR[op1, op2]}; WordNOT, WNOT: PROC [op: BitWord, containerWidth: CARDINAL] RETURNS [result: BitWord] = {result _ BITAND[wordMasks[containerWidth], BITNOT[op]]}; WordShift, WShift: PROC [op: BitWord, containerWidth: CARDINAL, shift: INTEGER] RETURNS [result: BitWord] = {result _ BITAND[wordMasks[containerWidth], BITSHIFT[op, shift]]}; DoubleAND, DAND: PROC [op1, op2: BitDWord] RETURNS [result: BitDWord] = {result _ [BITAND[op1[0], op2[0]], BITAND[op1[1], op2[1]]]}; DoubleOR, DOR: PROC [op1, op2: BitDWord] RETURNS [result: BitDWord] = {result _ [BITOR[op1[0], op2[0]], BITOR[op1[1], op2[1]]]}; DoubleXOR, DXOR: PROC [op1, op2: BitDWord] RETURNS [result: BitDWord] = {result _ [BITXOR[op1[0], op2[0]], BITXOR[op1[1], op2[1]]]}; DoubleNOT, DNOT: PROC [op: BitDWord, containerWidth: CARDINAL] RETURNS [result: BitDWord] = { IF containerWidth>bitsPerWord THEN result _ [BITAND[wordMasks[containerWidth-bitsPerWord], BITNOT[op[0]]], BITNOT[op[1]]] ELSE result _ [0, BITAND[wordMasks[containerWidth], BITNOT[op[1]]]]}; DoubleShift, DShift: PROC [op: BitDWord, containerWidth: CARDINAL, shift: INTEGER] RETURNS [result: BitDWord] = { SELECT shift FROM >0 => { result[0] _ BITOR[BITSHIFT[op[0], shift], BITSHIFT[op[1], shift-bitsPerWord]]; result[1] _ BITSHIFT[op[1], shift]; }; <0 => { result[0] _ BITSHIFT[op[0], shift]; result[1] _ BITOR[BITSHIFT[op[1], shift], BITSHIFT[op[0], bitsPerWord+shift]]; }; =0 => RETURN[op]; ENDCASE; IF containerWidth>bitsPerWord THEN result[0] _ BITAND[result[0], wordMasks[containerWidth-bitsPerWord]] ELSE {result[0] _ 0; result[1] _ BITAND[result[1], wordMasks[containerWidth]]}; }; MulitipleAND, MAND: PROC [op1: BitMWord, op2: BitMWord, result: BitMWord] = TRUSTED { IF LENGTH[op1]#LENGTH[op2] OR LENGTH[op1]#LENGTH[result] THEN ERROR; FOR i:CARDINAL IN [0..LENGTH[op1]) DO result[i] _ BITAND[op1[i], op2[i]]; ENDLOOP; }; MulitipleOR, MOR: PROC [op1: BitMWord, op2: BitMWord, result: BitMWord] = TRUSTED { IF LENGTH[op1]#LENGTH[op2] OR LENGTH[op1]#LENGTH[result] THEN ERROR; FOR i:CARDINAL IN [0..LENGTH[op1]) DO result[i] _ BITOR[op1[i], op2[i]]; ENDLOOP; }; MulitipleXOR, MXOR: PROC [op1: BitMWord, op2: BitMWord, result: BitMWord] = TRUSTED { IF LENGTH[op1]#LENGTH[op2] OR LENGTH[op1]#LENGTH[result] THEN ERROR; FOR i:CARDINAL IN [0..LENGTH[op1]) DO result[i] _ BITXOR[op1[i], op2[i]]; ENDLOOP; }; MulitipleNOT, MNOT: PROC [op: BitMWord, containerWidth: CARDINAL, result: BitMWord] = TRUSTED { IF LENGTH[op]#LENGTH[result] THEN ERROR; FOR i:CARDINAL IN [0..LENGTH[op]) DO result[i] _ BITNOT[op[i]]; ENDLOOP; op[0] _ BITAND[op[0], wordMasks[containerWidth - (LENGTH[op] -1) * bitsPerWord]] }; MulitipleShift, MShift: PROC [op: BitMWord, containerWidth: CARDINAL, shift: INTEGER, result: BitMWord] = TRUSTED { IF LENGTH[op]#LENGTH[result] THEN ERROR; SELECT shift FROM <0 => { FOR i: CARDINAL _ LENGTH[op], i-1 UNTIL i=0 DO result[i] _ BITOR[BITSHIFT[op[i], shift], BITSHIFT[op[i-1], bitsPerWord+shift]]; ENDLOOP; result[0] _ BITSHIFT[op[0], shift]; }; >0 => { FOR i:CARDINAL IN [0..LENGTH[op]-1) DO result[i] _ BITOR[BITSHIFT[op[i], shift], BITSHIFT[op[i+1], shift-bitsPerWord]]; ENDLOOP; result[LENGTH[op]-1] _ BITSHIFT[op[LENGTH[op]-1], shift]; }; =0 => FOR i:CARDINAL IN [0..LENGTH[op]) DO result[i] _ op[i]; ENDLOOP; ENDCASE; op[0] _ BITAND[op[0], wordMasks[containerWidth - (LENGTH[op] -1) * bitsPerWord]] }; Start: PROC = BEGIN n: CARDINAL _ 0; wordMasks[0] _ doubleMasks[0][1] _ 0; FOR i: CARDINAL IN [1 .. bitsPerWord] DO wordMasks[i] _ doubleMasks[bitsPerWord+i][0] _ doubleMasks[i][1] _ n _ n + n+ 1; ENDLOOP; END; Start[]; END.