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 = { 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 = { 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 = { 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 = { 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]]]; 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 = { 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]]]; 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 = { 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]]]; 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 = { 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]]]; drSHD[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 6+6, shift: 6]]]; drFSDB[0]; drRVSUB[pushDst, rBI, const1]; drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 32-5, shift: 32-5]]]; drQRX[topAtop, rP]; drLRn[rI]; drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 32-5, shift: 32-5]]]; drQRX[topAtop, rP]; drRFU[reg0, topSrc, belowSrc]; ProcedureExit[1]; }; GenExtractFieldSingle: PROC = { 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]]]; drSHD[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 6+6, shift: 6]]]; drFSDB[0]; drSHR[DragOpsCrossUtils.FieldDescriptorToCard[[mask: 32-5, shift: 32-5]]]; drRX[]; drRFU[reg0, topSrc, topSrc]; ProcedureExit[1]; }; GenDepositField: PROC = { 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]; drSHD[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 6+6, shift: 6]]]; drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 0, shift: 0]]]; 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]]]; drRFU[rF, const0, rF]; drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 0, shift: 0]]]; drRRX[pushDst, rP, constN1]; drRVSUB[rP, rP, const1]; drRFU[topDst, rF, topSrc]; drSRIn[rP, 0]; SetLabel[exitLabel]; ProcedureExit[0]; }; GenDepositFieldSingle: PROC = { 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]; drLRn[rSH]; drSHD[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 6+6, shift: 6]]]; drFSDB[DragOpsCrossUtils.FieldDescriptorToCard[[insert: TRUE, mask: 0, shift: 0]]]; 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. ZGenField.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) April 1, 1986 1:21:15 am PST Control flow falls through to the next file that gets generated. Byte Fetch and Store routines (if open coded: 9 instructions, 9 cycles min) push the bound (at (rR+1)^) read the word containing the byte rR _ (rR + (rI / 4))^ bounds check [S-1] (which is rI) against [S] (which is the bound) make it into a byte index ([S] = (rI * 8) MOD 32) setup Field _ FD[0, 8, 8]+[S]; S_S-1 isolate the byte (into the return value) (if open coded: 6 instructions, 6 cycles min) push the index (rI) make the index a word index (rI_rI/4; [S] = rI) {overwrites rI} fetch the word into rR (no overhead words) make rI into a byte index ([S] = (rI * 8) MOD 32) setup Field _ FD[0, 8, 8]+[S]; S_S-1 isolate the byte (into the return value) (if open coded: 6 instructions, 7 cycles min) byte addr in [S], [S-1] make it into a byte index ([S] = (rI * 8) MOD 32) setup Field _ FD[0, 8, 8]+[S]; S_S-1 fetch the word (no overhead) isolate the byte (into the return value) (if open coded: 11 instructions, 12 cycles min) push the bound push 3 - i make it into a byte index ([S] = ((3-i) * 8) MOD 32) [S] _ [S] + [S]*64 setup Field _ FD[1, 8, 0]+[S]; S_S-1 bounds check rI against [S] (the bound) make the index a word index ([S] = rI / 4) add in the base address fetch the word (2 words of overhead) insert the byte store the changed word (if open coded: 9 instructions, 9 cycles min) push (3-I) make it into a byte index ([S] = ((3-P) * 8) MOD 32) [S] _ [S] + [S]*64 setup Field _ FD[1, 8, 0]+[S]; S_S-1 make the index a word index ([S] = rI / 4) fetch the word (no overhead) adjust the dest address in the dead cycle insert the byte store the changed word (if open coded: 8 instructions, 9 cycles min) push (3-P) make it into a byte index ([S] = ((3-P) * 8) MOD 32) [S] _ [S] + [S]*64 setup Field _ FD[1, 8, 0]+[S]; S_S-1 make the index a word index ([S] = rI / 4) fetch the word (2 words of overhead) insert the byte store the changed word Field Extract & Deposit routines In these routines a bit field is described by (P, I, B), where P is a word pointer, I is a bit index (unsigned), and B is a number of bits (in [0..32], but unchecked). We follow the convention that bit 0 is the most-significant bit in a binary number (aka Big-Endian). In the general case fields are allowed to cross word boundaries, in the single case fields must stay within a word. (if open coded: 13 instructions, 14 cycles min) Arguments Locals [S] = (B+I) MOD 32 {the # of bits to shift left} setup the field descriptor (no constant part, unfortunately) FD = [mask: B, shift: (B+I) MOD 32] [S] = B+I-1 {to give offset of rightmost bit} [S] = right word [S] = B {to give offset of leftmost bit} [S] = left word, [S-1] = right word Extract the field & put it into the return reg (if open coded: 7 instructions, 8 cycles min) [S] = (B+I) MOD 32 {the # of bits to shift left} setup the field descriptor (no constant part, unfortunately) FD = [mask: B, shift: (B+I) MOD 32] [S] = (I / 32) {to give offset of lst bit} [S] = word containing field Extract the field & put it into the return reg (if open coded (with plenty of spare regs): single word => 16 instructions, 21 cycles min, double word => 26 instructions, 27 cycles min) Arguments Locals c32: WORD _ 32 BI: WORD _ B+I SH: WORD = (-B-I) MOD 32 MSK: WORD = SH+B This part stores the right part of the field, which is the only part for single-word stores. [S] = SH [S-1] = MSK [S] holds the new field descriptor (without the insert bit) = FD[insert: FALSE, mask: MSK, shift: SH] setup the field descriptor (with the insert bit) = FD[insert: TRUE, mask: MSK, shift: SH] form the address of the word to modify Fetch the word to modify Insert the field Store the modified word back IF MSK <= 32 THEN GO TO exitLabel; At this point the right part has been done, so we try to do the left part setup the field descriptor to shift F right [S] holds the new field descriptor (without the insert bit) = FD[insert: FALSE, mask: MSK-32, shift: 0] Shift the field to get the remainder setup the field descriptor to insert the remaining F = FD[insert: TRUE, mask: MSK-32, shift: 0] Fetch the word to modify Adjust rP while twiddling our thumbs Insert the field Store the modified word back 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: 13 instructions, 14 cycles min) Arguments Locals BI: WORD _ B+I SH: WORD = (-B-I) MOD 32 MSK: WORD = SH+B [S] = MSK [S-1] = SH [S] = SH [S-1] = MSK [S] holds the new field descriptor (without the insert bit) = FD[insert: FALSE, mask: MSK, shift: SH] setup the field descriptor (with the insert bit) = FD[insert: TRUE, mask: MSK, shift: SH] form the address of the word to modify Fetch the word to modify Insert the field Store the modified word back Ê$@˜codešœ ™ Kšœ Ïmœ1™