BitOpsImpl.mesa
Last edited by: Barth, April 12, 1984 2:22:54 pm PST
Last Edited by: Spreitzer, May 2, 1985 4:33:38 pm PDT
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 CARDINALALL[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: INTEGERINTEGER[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: INTEGERINTEGER[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: INTEGERLENGTH[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: INTEGERLENGTH[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};
ExtractCardinalFSingleSwitch, ECFSS: PUBLIC PROC [container: Switch] RETURNS [result: [0..1]] =
{result ← SELECT container.val FROM L => 0, X => ERROR, H => 1, ENDCASE => ERROR};
InsertCardinalInSingleSwitch, ICISS: PUBLIC PROC [source: [0..1], container: Switch, si: StrengthIndex, how: BoolStrengths] RETURNS [newContainer: Switch] =
{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;
FOR i: INTEGER IN [(destPad+destinationPosition) +.. destinationWidth) DO
destBits[i] ← sourceBits[i + (sourcePad+sourcePosition - (destPad+destinationPosition))]
ENDLOOP;
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: CARDINALBITOR[
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: CARDINALLENGTH[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.