GenExtractField:
PROC = {
(if open coded: 13 instructions, 14 cycles min)
Arguments
rP: RegSpec = reg0; -- the base pointer
rI: RegSpec = reg1; -- the offset (in bits)
rB: RegSpec = reg2; -- the field size [0..32]
Locals
rBI: RegSpec = reg3; -- B+I
entryLabel: Label = GenLabel[];
ProcedureEntry[entryLabel, 3];
MakeLabelGlobal["Basics.ExtractField", entryLabel];
drRVADD[pushDst, rI, rB]; -- BI: WORD ← B+I
drLRn[rB];
drLRn[rBI];
drSHL[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 5, shift: 0]]];
[S] = (B+I) MOD 32 {the # of bits to shift left}
drSHDL[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 6+6, shift: 6]]];
drFSDB[0];
setup the field descriptor (no constant part, unfortunately)
FD = [mask: B, shift: (B+I) MOD 32]
drRVSUB[pushDst, rBI, const1];
[S] = B+I-1 {to give offset of rightmost bit}
drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 32-5, shift: 32-5]]];
drQRX[topAtop, rP];
[S] = right word
drLRn[rI];
[S] = B {to give offset of leftmost bit}
drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 32-5, shift: 32-5]]];
drQRX[topAtop, rP];
[S] = left word, [S-1] = right word
drRFU[reg0, topSrc, belowSrc];
Extract the field & put it into the return reg
ProcedureExit[1];
};
GenExtractFieldSingle:
PROC = {
(if open coded: 7 instructions, 8 cycles min)
rP: RegSpec = reg0; -- the base pointer
rI: RegSpec = reg1; -- the offset (in bits)
rB: RegSpec = reg2; -- the field size [0..32]
entryLabel: Label = GenLabel[];
ProcedureEntry[entryLabel, 3];
MakeLabelGlobal["Basics.ExtractFieldSingle", entryLabel];
drRVADD[pushDst, rI, rB];
drSHL[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 5, shift: 0]]];
[S] = (B+I) MOD 32 {the # of bits to shift left}
drSHDL[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 6+6, shift: 6]]];
drFSDB[0];
setup the field descriptor (no constant part, unfortunately)
FD = [mask: B, shift: (B+I) MOD 32]
drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 32-5, shift: 32-5]]];
[S] = (I / 32) {to give offset of lst bit}
drRX[];
[S] = word containing field
drRFU[reg0, topSrc, topSrc];
Extract the field & put it into the return reg
ProcedureExit[1];
};
GenDepositField:
PROC = {
(if open coded (with plenty of spare regs):
single word => 16 instructions, 21 cycles min,
double word => 26 instructions, 27 cycles min)
Arguments
rP: RegSpec = reg0; -- the base pointer
rI: RegSpec = reg1; -- the offset (in bits)
rB: RegSpec = reg2; -- the field size [0..32]
rF: RegSpec = reg3; -- the field to insert
Locals
c32: RegSpec = reg4; -- 32
rBI: RegSpec = reg5; -- B+I
rSH: RegSpec = reg6; -- 31&(-B-I) {bits to shift left}
rMSK: RegSpec = reg7; -- SH+B {bits to mask}
entryLabel: Label = GenLabel[];
exitLabel: Label = GenLabel[];
ProcedureEntry[entryLabel, 4];
MakeLabelGlobal["Basics.DepositField", entryLabel];
drLIB[32];
c32: WORD ← 32
drRVADD[pushDst, rI, rB];
BI: WORD ← B+I
drRVSUB[pushDst, const0, rBI];
drSHL[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 5, shift: 0]]];
SH: WORD = (-B-I) MOD 32
drRVADD[pushDst, rSH, rB];
MSK: WORD = SH+B
{
This part stores the right part of the field, which is the only part for single-word stores.
drLRn[rMSK];
drLRn[rSH];
[S] = SH
[S-1] = MSK
drSHDL[DragOpsCrossUtils.FieldDescriptorToCard[[insert:
TRUE, mask: 6+6, shift: 6]]];
[S] holds the new field descriptor (without the insert bit)
= FD[insert: FALSE, mask: MSK, shift: SH]
drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[insert:
TRUE, mask: 0, shift: 0]]];
setup the field descriptor (with the insert bit)
= FD[insert: TRUE, mask: MSK, shift: SH]
drRVSUB[pushDst, rBI, const1];
drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 32-5, shift: 32-5]]];
drRVADD[rP, popSrc, rP];
form the address of the word to modify
drLRIn[rP, 0];
Fetch the word to modify
drRFU[topDst, rF, topSrc];
Insert the field
drSRIn[rP, 0];
Store the modified word back
drRJLEB[topSrc, c32, UseLabel8B[exitLabel]];
IF MSK <= 32 THEN GO TO exitLabel;
};
At this point the right part has been done, so we try to do the left part
drLRn[rSH];
drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[insert:
FALSE, mask: 32, shift: 0]]];
setup the field descriptor to shift F right
drRVSUB[pushDst, rMSK, c32];
drSHL[DragOpsCrossUtils.FieldDescriptorToCard[[insert:
FALSE, mask: 6+6, shift: 6]]];
[S] holds the new field descriptor (without the insert bit)
= FD[insert: FALSE, mask: MSK-32, shift: 0]
drRFU[rF, const0, rF];
Shift the field to get the remainder
drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[insert:
TRUE, mask: 0, shift: 0]]];
setup the field descriptor to insert the remaining F
= FD[insert: TRUE, mask: MSK-32, shift: 0]
drRRX[pushDst, rP, constN1];
Fetch the word to modify
drRVSUB[rP, rP, const1];
Adjust rP while twiddling our thumbs
drRFU[topDst, rF, topSrc];
Insert the field
drSRIn[rP, 0];
Store the modified word back
SetLabel[exitLabel];
ProcedureExit[0];
};
GenDepositFieldSingle:
PROC = {
DepositFieldSingle: PROC [P: PTR, I: WORD, B: [0..32], F: WORD]
deposits F into the field described by (P, I, B)
(the caller promises to not cross a word boundary)
(if open coded: 12 instructions, 13 cycles min)
Arguments
rP: RegSpec = reg0; -- the base pointer
rI: RegSpec = reg1; -- the offset (in bits)
rB: RegSpec = reg2; -- the field size [0..32]
rF: RegSpec = reg3; -- the field to insert
Locals
rBI: RegSpec = reg4; -- B+I
rSH: RegSpec = reg5; -- 31&(-B-I) {bits to shift left}
rMSK: RegSpec = reg6; -- SH+B {bits to mask}
entryLabel: Label = GenLabel[];
ProcedureEntry[entryLabel, 4];
MakeLabelGlobal["Basics.DepositFieldSingle", entryLabel];
drRVADD[pushDst, rI, rB];
BI: WORD ← B+I
drRVSUB[pushDst, const0, rBI];
drSHL[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 5, shift: 0]]];
SH: WORD = (-B-I) MOD 32
drRVADD[pushDst, rSH, rB];
MSK: WORD = SH+B
[S] = MSK
[S-1] = SH
drSHDR[DragOpsCrossUtils.FieldDescriptorToCard[[insert:
TRUE, mask: 6+6, shift: 6]]];
[S] holds the new field descriptor (without the insert bit)
= FD[insert: FALSE, mask: MSK, shift: SH]
drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[insert:
TRUE, mask: 0, shift: 0]]];
setup the field descriptor (with the insert bit)
= FD[insert: TRUE, mask: MSK, shift: SH]
drLRn[rI];
drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 32-5, shift: 32-5]]];
drRVADD[rP, popSrc, rP];
form the address of the word to modify
drLRIn[rP, 0];
Fetch the word to modify
drRFU[topDst, rF, topSrc];
Insert the field
drSRIn[rP, 0];
Store the modified word back
ProcedureExit[0];
};