:Title[LMEM]; * Edit History * March 11, 1985 6:17 PM, Masinter, fix bug where BLT * of number > 2^15 would always exit * February 2, 1985 2:55 PM, Masinter, attempt to fix bug where BLT * January 21, 1985 11:54 AM, Masinter, bum VAG2 a bit, clean up a * PAGEFAULTOK or two * January 17, 1984 4:02 AM, JonL, added .pbsFetch for PUTBASEN and * PUTBITS * January 17, 1984 2:10 AM, JonL, added .gbsFetch for use by GETBASEN, * GETBASEPTRN, and GETBITS; also tailed them out thru REPSMT2 * January 17, 1984 1:25 AM, JonL, abstracted .addrNfetch, changed * DOGETBYTE to .getByte and let it use LTEMP1 instead of LTEMP0 * January 17, 1984 12:51 AM, JonL, squeezed one inst out of opADDBASE * January 13, 1984 10:42 PM, JonL, spawned LMEM off LOW.mc * January 4, 1984 7:08 PM, JonL, tailed opPUTBASEPTR and opPUTBITS * into TL.POP1. * December 15, 1983 3:45 PM, JonL, HILOC to tail into REPTMD1 *-------------------------------------------------------------------- * Low-Level Memory referencing *-------------------------------------------------------------------- TOP LEVEL; knowrbase[LTEMP0]; InsSet[LispInsSet, 1]; *-------------------------------------------------------------------- opHILOC: *-------------------------------------------------------------------- fetch_ TSP, T_ (SmallHi), branch[REPTMD1]; regOP1[322, StackM2BR, opHILOC, noNData]; *-------------------------------------------------------------------- opLOLOC: *-------------------------------------------------------------------- store_ TSP, dbuf_ SmallHi, NextOpCode; regOP1[323, StackM2BR, opLOLOC, noNData]; *-------------------------------------------------------------------- opADDBASE: *-------------------------------------------------------------------- T_ (fetch_ TSP) - 1, flipMemBase, Call[.addrNfetch]; branch[.adbs1, alu#0], LTEMP1_ (LTEMP1) + (Md); * + Lo.word of addr branch[.+2, carry], LEFT_ (LEFT) + 1; TSP_ (store_ T) + 1, dbuf_ LTEMP1, NextOpCode; * Done - fast case T_ (store_ T) - 1, dbuf_ LTEMP1; * Carry over into next TSP_ (fetch_ T) + (2c); * next segment LTEMP0_ (1s) + (Md); store_ T, dbuf_ LTEMP0, NextOpCode; SUBROUTINE; .addrNfetch: * Enter and exit with StackBR * Leaves 0 on pd iff TOS is a smallposp LTEMP0_ Md, T_ (fetch_ T) - (2c); * LTEMP0_ Hi.word of n LTEMP1_ Md, (fetch_ T); * LTEMP1_ Lo.word of n pd_ (LTEMP0) xor (SmallHi), Return; * Is n a smallP? TOPLEVEL; .adbs1: CallUFN; % * This could continue something like . . . LEFT_ (LEFT) - 1, memBase_ StackM2BR; T_ (fetch_ TSP) - 1, flipMemBase, Call[.UNBOX1]; T_ (TSP) + 1, flipMemBase; * Change back to StackM2BR T_ (fetch_ T) - 1; * TSP was "pulled back" (fetch_ T), LTEMP1_ Md; * LTEMP1_ lo.word of addr T_ (LTEMP1) + Q, LTEMP1_ T; * Lo.word sum LTEMP0_ (LTEMP0) + (Md), XorSavedCarry; * Hi.word sum T_ (store_ LTEMP1) + 1, dbuf_ T; * Store Lo.word (store_ T), dbuf_ LTEMP0, NextOpCode; * Store Hi.word % regOP1[320, StackM2BR, opADDBASE, noNData]; *-------------------------------------------------------------------- opVAG2: *-------------------------------------------------------------------- T_ (fetch_ TSP) - 1, flipMemBase, Call[.UNBOX2]; T_ (store_ TSP) + 1, dbuf_ Q; TSP_ (store_ T) + 1, dbuf_ LTEMP1, NextOpCode; regOP1[321, StackM2BR, opVAG2, noNData]; *-------------------------------------------------------------------- opBLT: * (destinationaddr sourceaddr #wds) *-------------------------------------------------------------------- * Defined to move one word at a time, from the high end to the * low end, and be continuable after interrupts. * These highly-bummed ideas are taken from Taft's implementation of * Mesa BLT and BLTL, found in DMesaRW.mc * Enter with: * Q set to 20b * T set to number of words to move minus one * stack has running count (minus 1) * Branch back around the loop: * stack updated to next value * T set up 17 for the next full munch * Before starting the transfer, touch the last word of the source and * destination blocks, to force any page faults that would happen, to * happen now rather than in the inner loop. Maybe need not touch the * first words, since a fault there will abort the loop before it has * done anything permanent. Also, "pre-warm" the cache for the next * time around. T_ (fetch_ TSP) - 1, flipMemBase, Call[.addrNfetch]; Branch[.+2, alu=0], T_ T - 1; CallUFN; * Punt: #wds not smallposp LTEMP2_ Md, T_ (fetch_ T) - 1; * Why 2 for StkP? 'Cause LTEMP0_ Md, T_ (fetch_ T) - 1; * BitBlt does it that way LTEMP3_ Md, (fetch_ T), T_ (2c); * Fetch on hi.word of Dest T_ pd_ LTEMP1, StkP_ T; * LTEMP1 had #wds to move branch[.bltxit, alu=0], * zero words to transfer? T_ Md, stack_ T - 1, memBase_ BBDSTBR; * Stack_ #wds-1 branch[.+2, alu>=0], BRHi_ T; CallUFN; * call UFN if > 2^15 words T_ (20c); Q_ T, T_ T - 1; * Q_ (20c), T_ (17c) BRLo_ LTEMP3; T_ (stack) and T, memBase_ BBSRCBR; * T_ #wds-1 mod 20b BRHi_ LTEMP0; BRLo_ LTEMP2; PSTATE_ (add[PS.PFOK!, PS.INBLT!]c); .bltloop: Cnt_ T; LTEMP0_ T_ (FETCH_ stack) - T; * Fetch on first src wd LTEMP2_ (FETCH_ T) - (Q); * Fetch on last src wd PreFetch_ LTEMP2, flipMemBase; FETCH_ stack; * Fetch on first dest wd FETCH_ LTEMP0; * Fetch on last dest wd PreFetch_ LTEMP2, T_ MD, flipMemBase; * Synchronize PageFaults *** Here's the tight inner loop to move a munch .bltmm: fetch_ stack, flipMemBase; stack_ (STORE_ stack) - 1, dbuf_ Md, flipMembase, Branch[.bltmm, Cnt#0&-1]; *** pd_ stack, Branch[.+2, Reschedule']; * Tails into BitBlt code if Branch[BBXitToContinue]; * need to xit for interrupt T_ (17c), Branch[.bltloop, alu>=0]; * Should be 17 or -1, not 0 .bltdone: PSTATE_ A0; .bltxit: LEFT_ (LEFT) + (2c); * LEFT is re-computed if TSP_ (TSP) - (4c), NextOpCode; * there is a fault-out % T_ (fetch_ TSP) + 1; LTEMP0_ Md, T_ (fetch_ T) - (2c); pd_ (LTEMP0) xor (SmallHi); branch[.+2, alu=0], LTEMP2_ Md, T_ (fetch_ T) - 1; CallUFN; LTEMP1_ Md, T_ (fetch_ T) - 1; LTEMP0_ Md, T_ (fetch_ T) - 1; LTEMP3_ Md, fetch_ T, pd _ T_ (LTEMP2); branch[.+2, alu#0], LTEMP2_ Md, memBase_ BBDSTBR, T_ T - 1; branch[.bltdone]; * no words to copy Cnt_ T; * number of words to transfer - 1 BRHi_ LTEMP2; BRLo_ LTEMP3; memBase_ BBSRCBR; BRHi_ LTEMP0; BRLo_ LTEMP1; * and now for the loop. This should really keep state in Stack a la BITBLT: PAGEFAULTOK; FETCH_ T, flipMemBase; T_ (store_ T) - 1, dbuf_ MD, flipMembase, branch[.-1, Cnt#0&-1]; PAGEFAULTNOTOK; .bltdone: Left_ (Left) + (2c); TSP_ (TSP) - (4c), NextOpCode; % regOP1[304, StackM2BR, opBLT, noNData]; *-------------------------------------------------------------------- opGETBASEN: *-------------------------------------------------------------------- T_ (fetch_ TSP) + 1, Call[.gbsFetch]; PAGEFAULTOK; IFETCH_ LTEMP0; T_ MD, memBase_ StackM2BR, Branch[REPSMALLT]; regOP2[310, StackM2BR, opGETBASEN, noNData]; SUBROUTINE; .gbsFetch: T_ Md, fetch_ T, LTEMP1_ (rhmask); LTEMP0_ Md, memBase_ ScratchLZBR; BrHi_ T, Return; TOPLEVEL; *-------------------------------------------------------------------- opGETBITS: *-------------------------------------------------------------------- T_ (fetch_ TSP) + 1, Call[.gbsFetch]; PAGEFAULTOK; IFETCH_ LTEMP0, TisID; memBase_ StackM2BR; LTEMP0_ MD, RF_ Id; T_ ShiftLMask[LTEMP0], memBase_ StackM2BR, Branch[REPSMALLT]; regOP3[312, StackM2BR, opGETBITS, noNData]; *-------------------------------------------------------------------- opGETBASEPTRN: *-------------------------------------------------------------------- T_ (fetch_ TSP) + 1, Call[.gbsFetch]; PAGEFAULTOK; LTEMP0_ (IFETCH_ LTEMP0) + 1; T_ MD, ifetch_ LTEMP0; PAGEFAULTNOTOK; T_ T and (LTEMP1), memBase_ StackM2BR; T_ Md, TSP_ (store_ TSP) + 1, dbuf_ T, Branch[REPSMT2]; regOP2[311, StackM2BR, opGETBASEPTRN, noNData]; *-------------------------------------------------------------------- opGETBASEBYTE: *-------------------------------------------------------------------- T_ (fetch_ TSP) - 1, flipMemBase, Call[.addrNfetch]; * See opADDBASE branch[.+2, alu=0], T_ T - 1; CallUFN; * Index not smallPosp fetch_ T, LTEMP0_ Md; memBase_ LScratchBR, LEFT_ (LEFT) + 1; LTEMP0_ Md, BrLo_ LTEMP0; BrHi_ LTEMP0, call[.getByte]; T_ (store_ T) + 1, dbuf_ SmallHi; TSP_ (store_ T) + 1, dbuf_ LTEMP1, NextOpCode; regOP1[302, StackM2BR, opGETBASEBYTE, noNData]; SUBROUTINE; .getByte: * called by BIN, GETBASEBYTE; * Assumes current memBase is pointer, LTEMP1 is byte offset * Returns byte in LTEMP1 * Must not clobber T dblbranch[.dgbeven, .dgbodd, R even], LTEMP1_ (LTEMP1) rsh 1; .dgbeven: PAGEFAULTOK; FETCH_ LTEMP1; LTEMP1_ MD, memBase_ StackBR; PAGEFAULTNOTOK; LTEMP1_ RSH[LTEMP1, 10], return; .dgbodd: PAGEFAULTOK; FETCH_ LTEMP1; LTEMP1_ MD, memBase_ StackBR; PAGEFAULTNOTOK; LTEMP1_ (LTEMP1) and (rhmask), return; TOP LEVEL; *-------------------------------------------------------------------- opPUTBASEN: *-------------------------------------------------------------------- T_ (fetch_ TSP) + 1, Call[.pbsFetch]; * fetch val hi STORE_ T, dbuf_ LTEMP0; :if[Debugging]; T_ MD, TSP _ (TSP) - (2c); PAGEFAULTNOTOK, NextOpCode; :else; T_ MD, TSP _ (TSP) - (2c), NextOpCode; * wait for faults :endif; SUBROUTINE; .pbsFetch: LTEMP0_ Md, T_ (fetch_ T) - (3c); * LTEMP0_ Hi.newByte pd_ (LTEMP0) xor (SmallHi); * check for smallPosp branch[.+2, alu=0], LTEMP0_ Md, Q_ Md, * LTEMP0_ newByte T_ (fetch_ T) + 1; TOPLEVEL; CallUFN; SUBROUTINE; LTEMP2_ Md, fetch_ T; * LTEMP2_ Hi.addr LEFT_ (LEFT) + 1, memBase_ ScratchLZBR; T_ (Id) + (Md); * T_ Lo.addr + alpha branch[.+2, carry'], BrHi_ LTEMP2; LTEMP2_ (LTEMP2) + 1, branch[.-1]; :if[Debugging]; PAGEFAULTOK, Return; :else; Return; :endif; TOPLEVEL; regOP2[315, StackM2BR, opPUTBASEN, noNData]; *-------------------------------------------------------------------- opPUTBITS: *-------------------------------------------------------------------- T_ (fetch_ TSP) + 1, Call[.pbsFetch]; * fetch val hi FETCH_ T; WF_ Id, LTEMP1_ T; T_ ShMdBothMasks[LTEMP0]; PAGEFAULTNOTOK; store_ LTEMP1, dbuf_ T, Branch[TL.POP1]; regOP3[317, StackM2BR, opPUTBITS, noNData]; *-------------------------------------------------------------------- opPUTBASEPTRN: *-------------------------------------------------------------------- T_ (fetch_ TSP) + 1; * fetch val hi LTEMP0_ Md, T_ (fetch_ T) - (3c); * fetch val lo Q_ Md, T_ (fetch_ T) + 1; * fetch addrhi LTEMP2_ Md, fetch_ T; * LTEMP0, Q have newval memBase_ ScratchLZBR, LEFT_ (LEFT) + 1; T_ (Id) + (Md); branch[.+2, carry'], BrHi_ LTEMP2; LTEMP2_ (LTEMP2) + 1, branch[.-1]; :if[Debugging]; PAGEFAULTOK; T_ (STORE_ T) + 1, dbuf_ LTEMP0; STORE_ T, dbuf_ Q; PAGEFAULTNOTOK, Branch[TL.POP1]; :else; T_ (STORE_ T) + 1, dbuf_ LTEMP0; STORE_ T, dbuf_ Q, Branch[TL.POP1]; :endif; regOP2[316, StackM2BR, opPUTBASEPTRN, noNData]; *-------------------------------------------------------------------- opPUTBASEBYTE: * PUTBASEBYTE(base, displacement, value) *-------------------------------------------------------------------- T_ (TSP) - 1; T_ (fetch_ T) - 1; LTEMP0_ Md, T_ (fetch_ T) - 1; * LTEMP0 has new byte pd_ (LTEMP0) and not (rhmask); LTEMP1_ Md, T_ (fetch_ T) - 1, branch[.+2, alu=0]; CallUFN; pd_ (LTEMP1) xor (SmallHi); LTEMP1_ Md, T_ (fetch_ T) - 1, branch[.+2, alu=0];* LTEMP1_offset CallUFN; LTEMP2_ Md, T_ (fetch_ T) - 1; pd_ (LTEMP2) xor (SmallHi); LTEMP2_ Md, fetch_ T, branch[.+2, alu=0]; CallUFN; LEFT_ (LEFT) + 1, memBase_ LScratchBR; LTEMP2_ Md, BrLo_ LTEMP2; BrHi_ LTEMP2; PAGEFAULTOK; branch[.putRight, R odd], LTEMP1_ (LTEMP1) rsh 1; FETCH_ LTEMP1; T_ Md, TSP_ T; * CAN FAULT T_ T and (rhmask); Q_ LTEMP0; LTEMP0_ LSH[LTEMP0, 10]; T_ T + (LTEMP0), branch[.restoreByte]; .putRight: FETCH_ LTEMP1; T_ Md, TSP_ T; * CAN FAULT T_ T and (lhmask); T_ T + (LTEMP0), Q_ LTEMP0, branch[.restoreByte]; .restoreByte: store_ LTEMP1, dbuf_ T; PAGEFAULTNOTOK; LEFT_ (LEFT) + 1, memBase_ StackBR; TSP_ (store_ TSP) + 1, dbuf_ SmallHi; TSP_ (store_ TSP) + 1, dbuf_ Q, NextOpCode; regOP1[307, StackBR, opPUTBASEBYTE, noNData];