<> <> <> DIRECTORY DragOpsCross, DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport; GenField: CEDAR PROGRAM IMPORTS DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport = BEGIN OPEN DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport; Word: TYPE = DragOpsCross.Word; ZerosWord: Word = DragOpsCross.ZerosWord; All: PROC = { area: Area = GetCurrentArea[]; startNext: Label = GenLabel[]; drJDB[UseLabel16[startNext]]; GenTextFetch[]; GenByteFetchUnchecked[]; GenBytePtrFetch[]; GenTextStore[]; GenByteStoreUnchecked[]; GenBytePtrStore[]; GenExtractField[]; GenExtractFieldSingle[]; GenDepositField[]; GenDepositFieldSingle[]; WordAlign[area]; SetLabel[startNext]; <> <<>> MakeLabelGlobal["GenField.startNext", startNext]; }; <> GenTextFetch: PROC = { <<(if open coded: 9 instructions, 9 cycles min)>> rR: RegSpec = reg0; rI: RegSpec = reg1; entryLabel: Label = GenLabel[]; ProcedureEntry[entryLabel, 2]; MakeLabelGlobal["Basics.TextFetch", entryLabel]; drLRIn[rR, 1]; <> drLRn[rI]; drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 30, shift: 30]]]; drRADD[rR, rR, popSrc]; drRRI[rR, rR, 2]; <> <> drBC[]; <> drSHL[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 5, shift: 3]]]; <> drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 8, shift: 8]]]; <> drRFU[rR, const0, rR]; <> <<>> ProcedureExit[1]; }; GenByteFetchUnchecked: PROC = { <<(if open coded: 6 instructions, 6 cycles min)>> rR: RegSpec = reg0; rI: RegSpec = reg1; entryLabel: Label = GenLabel[]; ProcedureEntry[entryLabel, 2]; MakeLabelGlobal["Basics.ByteFetchUnchecked", entryLabel]; drDUP[]; <> drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 30, shift: 30]]]; <> drRRX[rR, rR, popSrc]; <> drSHL[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 5, shift: 3]]]; <> drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 8, shift: 8]]]; <> drRFU[rR, const0, rR]; <> ProcedureExit[1]; }; GenBytePtrFetch: PROC = { <<(if open coded: 6 instructions, 7 cycles min)>> rBA: RegSpec = reg0; entryLabel: Label = GenLabel[]; ProcedureEntry[entryLabel, 1]; MakeLabelGlobal["Basics.BytePtrFetch", entryLabel]; drDUP[]; <> drSHL[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 5, shift: 3]]]; <> drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 8, shift: 8]]]; <> drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 30, shift: 30]]]; drRB[0]; <> drRFU[rBA, const0, popSrc]; <> ProcedureExit[1]; }; GenTextStore: PROC = { <<(if open coded: 11 instructions, 12 cycles min)>> rR: RegSpec = reg0; rI: RegSpec = reg1; rB: RegSpec = reg2; entryLabel: Label = GenLabel[]; ProcedureEntry[entryLabel, 3]; MakeLabelGlobal["Basics.TextStore", entryLabel]; drLRIn[rR, 1]; <> drRVSUB[pushDst, const3, rI]; <> drSHL[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 5, shift: 3]]]; <> drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 12, shift: 6]]]; <<[S] _ [S] + [S]*64>> drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 8, shift: 0]]]; <> drRBC[topDst, rI, topSrc]; <> drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 30, shift: 30]]]; <> drQADD[topAtop, rR]; <> drRSB[2]; <> drRFU[topDst, rB, topSrc]; <> drWSB[2]; <> ProcedureExit[0]; }; GenByteStoreUnchecked: PROC = { <<(if open coded: 9 instructions, 9 cycles min)>> rB: RegSpec = reg0; -- the byte (B: BYTE) rP: RegSpec = reg1; -- the base pointer (P: LONG POINTER) rI: RegSpec = reg2; -- the byte index (I: INT) entryLabel: Label = GenLabel[]; ProcedureEntry[entryLabel, 3]; MakeLabelGlobal["Basics.ByteStoreUnchecked", entryLabel]; drRVSUB[pushDst, const3, rI]; <> drSHL[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 5, shift: 3]]]; <> drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 12, shift: 6]]]; <<[S] _ [S] + [S]*64>> drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 8, shift: 0]]]; <> drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 30, shift: 30]]]; <> drRRX[pushDst, topSrc, rP]; <> drRVADD[belowDst, belowSrc, rP]; <> drRFU[topDst, rB, topSrc]; <> drWSB[0]; <> ProcedureExit[0]; }; GenBytePtrStore: PROC = { <<(if open coded: 8 instructions, 9 cycles min)>> rC: RegSpec = reg0; rP: RegSpec = reg1; entryLabel: Label = GenLabel[]; ProcedureEntry[entryLabel, 2]; MakeLabelGlobal["Basics.BytePtrStore", entryLabel]; drRVSUB[pushDst, const3, rP]; <> drSHL[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 5, shift: 3]]]; <> drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 12, shift: 6]]]; <<[S] _ [S] + [S]*64>> drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 8, shift: 0]]]; <> drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 30, shift: 30]]]; <> drRSB[0]; <> drRFU[topDst, rC, topSrc]; <> drWSB[0]; <> ProcedureExit[0]; }; <> <> <<>> GenExtractField: PROC = { <<(if open coded: 13 instructions, 14 cycles min)>> <<>> <> rP: RegSpec = reg0; -- the base pointer rI: RegSpec = reg1; -- the offset (in bits) rB: RegSpec = reg2; -- the field size [0..32] <> 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}>> drSHD[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 6+6, shift: 6]]]; drFSDB[0]; <> <> 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]; <> 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}>> drSHD[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 6+6, shift: 6]]]; drFSDB[0]; <> <> 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]; <> ProcedureExit[1]; }; GenDepositField: PROC = { <<(if open coded (with plenty of spare regs):>> < 16 instructions, 21 cycles min,>> < 26 instructions, 27 cycles min)>> <> 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 <> 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]; <> drRVADD[pushDst, rI, rB]; <> drRVSUB[pushDst, const0, rBI]; drSHL[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 5, shift: 0]]]; <> drRVADD[pushDst, rSH, rB]; <> { <> drLRn[rMSK]; drLRn[rSH]; <<[S] = SH>> <<[S-1] = MSK>> drSHD[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]]]; <> <<= FD[insert: TRUE, mask: MSK, shift: SH]>> drRVSUB[pushDst, rBI, const1]; drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 32-5, shift: 32-5]]]; drRVADD[rP, popSrc, rP]; <
> drLRIn[rP, 0]; <> drRFU[topDst, rF, topSrc]; <> drSRIn[rP, 0]; <> drRJLEB[topSrc, c32, UseLabel8B[exitLabel]]; <> }; <> drLRn[rSH]; drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[insert: FALSE, mask: 32, shift: 0]]]; <> 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]; <> drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 0, shift: 0]]]; <> <<= FD[insert: TRUE, mask: MSK-32, shift: 0]>> drRRX[pushDst, rP, constN1]; <> drRVSUB[rP, rP, const1]; <> drRFU[topDst, rF, topSrc]; <> drSRIn[rP, 0]; <> SetLabel[exitLabel]; ProcedureExit[0]; }; GenDepositFieldSingle: PROC = { <> <> <<(the caller promises to not cross a word boundary)>> <<(if open coded: 13 instructions, 14 cycles min)>> <> 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 <> 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]; <> drRVSUB[pushDst, const0, rBI]; drSHL[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 5, shift: 0]]]; <> drRVADD[pushDst, rSH, rB]; <> <<[S] = MSK>> <<[S-1] = SH>> drLRn[rSH]; <<[S] = SH>> <<[S-1] = MSK>> drSHD[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]]]; <> <<= FD[insert: TRUE, mask: MSK, shift: SH]>> drLRn[rI]; drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 32-5, shift: 32-5]]]; drRVADD[rP, popSrc, rP]; <> drLRIn[rP, 0]; <> drRFU[topDst, rF, topSrc]; <> drSRIn[rP, 0]; <> ProcedureExit[0]; }; END.