BitOpsImpl.mesa
Last edited by: Barth, April 12, 1984 2:22:54 pm PST
Last Edited by: Spreitzer, May 3, 1984 6:31:49 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;
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};
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:
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.