<> <> <> 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[]; GenStringCompare[]; WordAlign[area]; SetLabel[startNext]; <> <<>> MakeLabelGlobal["GenField.startNext", startNext]; }; <> GenTextFetch: PROC = { <<(if open coded: 10 instructions, 10 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]; <> <> drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 16, shift: 0]]]; <> 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: 12 instructions, 13 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]]]; <> drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 16, 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}>> drSHDL[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}>> drSHDL[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>> 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]]]; <> <<= 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: 12 instructions, 13 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>> 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]]]; <> <<= 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]; }; GenStringCompare: PROC = { <> rS1: RegSpec = reg0; -- string S1 rS2: RegSpec = reg1; -- string S2 <> rDelta: RegSpec = reg2; -- rW2-rW1 rL1: RegSpec = reg3; -- L1 _ S1.len rL2: RegSpec = reg4; -- L2 _ S2.len rMin: RegSpec = reg5; -- rMin _ MIN[L1, L2] rDiv: RegSpec = reg6; -- rDiv _ rMin / 4 rMod: RegSpec = reg7; -- rMod _ rMin MOD 4 rW1: RegSpec = reg8; -- last word from S1 rW2: RegSpec = reg9; -- last word from S2 rRel: RegSpec = reg10; -- rRel _ 1 <> minFound: Label = GenLabel[]; loopLabel: Label = GenLabel[]; countDone: Label = GenLabel[]; lenOnly: Label = GenLabel[]; retEqual: Label = GenLabel[]; carryOut: Label = GenLabel[]; entryLabel: Label = GenLabel[]; ProcedureEntry[entryLabel, 2]; MakeLabelGlobal["Basics.CompareString", entryLabel]; <> drLC0[]; -- rDelta drLRIn[rS1, 0]; -- rL1 _ rS1.len ExtractField[first: 16, bits: 16]; drLRIn[rS2, 0]; -- rL2 _ rS2.len ExtractField[first: 16, bits: 16]; drDUP[]; drRJGEB[topSrc, rL1, UseLabel8B[minFound]]; drROR[topDst, rL1, const0]; SetLabel[minFound]; -- rMin _ MIN[L1, L2] drLRn[rMin]; ExtractField[first: 0, bits: 30]; -- rDiv _ rMin / 4 drRAND[pushDst, rMin, const3]; -- rMod _ rMin MOD 4 drLC0[]; -- rW1 _ 0 drLC0[]; -- rW2 _ 0 drLC1[]; -- rRel _ 1 <> drRJGB[topSrc, rDiv, UseLabel8B[countDone]]; SetLabel[loopLabel]; drRRX[rW1, rS1, rRel]; -- rW1 _ (LOOPHOLE[rS1, WordPtr]+rRel)^ drRRX[rW2, rS2, rRel]; -- rW2 _ (LOOPHOLE[rS2, WordPtr]+rRel)^ drADDB[1]; -- rRel _ rRel + 1 drRUSUB[rDelta, rW2, rW1]; -- rDelta _ rW2 - rW1 (set carry) drRJNEB[const0, rDelta, UseLabel8B[carryOut]]; -- IF rDelta = 0 THEN LOOP; drRJLEBJ[topSrc, rDiv, UseLabel8B[loopLabel]]; -- IF rRel <= rDiv THEN LOOP; <> SetLabel[countDone]; drRJEB[const0, rMod, UseLabel8B[lenOnly]]; drRRX[rW1, rS1, rRel]; drRRX[rW2, rS2, rRel]; drLRn[rMod]; ShiftLeft[3]; drFSDB[FieldDescriptorToCard[[mask: 32, shift: 0]]]; drRFU[rW1, const0, rW1]; drRFU[rW2, const0, rW2]; drRUSUB[rDelta, rW2, rW1]; drRJNEB[const0, rDelta, UseLabel8B[carryOut]]; <> SetLabel[lenOnly]; drRUSUB[rDelta, rL2, rL1]; drRJNEB[const0, rDelta, UseLabel8B[carryOut]]; <> SetLabel[retEqual]; drROR[reg0, const0, const1]; ProcedureExit[1]; < S2)>> SetLabel[carryOut]; drRADD[reg0, const0, const0]; drRADD[reg0, reg0, reg0]; ProcedureExit[1]; }; END.