:TITLE[Low.0mc...October 25, 1982 12:38 PM, van Melle]; * GetBase.n, op 310 * {base} => {val(int)} @GetBase: lspUFN _ 310c, call[lspSetBase], opcode[310]; T _ NextData[IBuf]; PFetch1[lspGenBr, lspL1]; * This can page fault T _ lspL1; * Wait for fault TOSGetsTSmall: * TOS _ MakeSmallPos(T) Stack&-1 _ (smallpl), goto[PushTP7]; * GetBasePtr.n, op 311 * {base} => {val(ptr)} @GetBasePtr: lspUFN _ 311c, call[lspSetBase], opcode[311]; T _ NextData[IBuf]; Stack&-2; * Fetch to stack will push PFetch2[lspGenBr, Stack]; * This can page fault T _ Stack&-1; * Redundant but saves 1 inst Stack _ rhmask[Stack], goto[PushTP7]; * GetBits.n.fd, op 312 * {base} => {val(int)} @GetBits: lspUFN _ 312c, call[lspSetBase], opcode[312]; T _ NextData[IBuf]; PFetch1[lspGenBr, lspL1]; * This can page fault lu _ CycleControl _ NextData[IBuf]; T _ RF[lspL1], goto[TOSGetsTSmall]; * PutBase.n, op 315 * {base, val(int)} => {val(int)} @PutBase: loadpage[pgHstack], call[CheckElt2P7], opcode[315]; lspUFN _ 315c, call[GetVal&Base]; * val in L1, base in lspGenBr T _ NextData[IBuf]; PStore1[lspGenBr, lspL1], goto[pb1]; * This can page fault * PutBasePtr.n, op 316 * {base, val(ptr)} => {val(ptr)} @PutBasePtr: loadpage[pgHstack], call[CheckElt2P7], opcode[316]; T _ Stack&-1; lspL1 _ T; * get val in L0,1 T _ Stack&-1; lspL0 _ T, call[lspSetBase]; * base in lspGenBr T _ NextData[IBuf]; PStore2[lspGenBr, lspL0]; * This can page fault pb1: lspL1 _ lspL1; * Wait for fault PopState1: StkState _ rsh[StkState, 1], goto[nxiLBL]; * PutBits.n.fd, op 317 * {base, val(int)} => {val(ptr)} @PutBits: loadpage[pgHstack], call[CheckElt2P7], opcode[317]; lspUFN _ 317c, call[GetVal&Base]; * val in L1, base in lspGenBr T _ NextData[IBuf]; PFetch1[lspGenBr, lspL4]; * Get old word lu _ CycleControl _ NextData[IBuf]; lspLN _ T; T _ WFA[lspL1]; * mask new value lspL4 _ (WFB[lspL4]) or T; * insert it into old word T _ lspLN; PStore1[lspGenBr, lspL4], goto[PopState1]; * Store it back * GetBaseByte, op 302 * {base, disp} => {val(int-byte)} @GetBaseByte: loadpage[pgHstack], call[CheckElt2P7], opcode[302]; lspUFN _ 302c, call[GetVal&Base]; * val in L1, base in lspGenBr T _ rsh[lspL1, 1]; * word offset PFetch1[lspGenBr, lspL4]; * This can page fault lspL1, skip[R odd]; * which byte? T _ rsh[lspL4, 10], goto[Gbb1]; T _ rhmask[lspL4], goto[Gbb1]; Gbb1: StkState _ rsh[StkState, 1], goto[TOSGetsTSmall]; * -> GetBase exit * PutBaseByte, op 307 * {base, disp, val} => {val(int-byte)} @PutBaseByte: loadpage[pgHStack], call[CheckElt3P7], opcode[307]; lspUFN _ 307c, call[CheckSmallp]; T _ Stack&-2; * L3 _ val lspL3 _ T, call[GetVal&Base]; * disp in L1, base in lspGenBr T _ lspL1 _ rsh[lspL1, 1], goto[PBBodd, Rodd]; PFetch1[lspGenBr, lspL4]; T _ lsh[lspL3, 10]; lspL4 _ (rhmask[lspL4]) or T, goto[PBBDone]; PBBodd: PFetch1[lspGenBr, lspL4]; T _ rhmask[lspL3]; lspL4 _ (lhmask[lspL4]) or T; PBBDone: T _ lspL1; pstore1[lspGenBr, lspL4]; T _ lspL3; StkState_ rsh[StkState, 2], goto[TOSGetsTSmall]; GetVal&Base: * Pop small integer TOS into L1, punting if not * Then put new TOS into lspGenBr/Hi T _ Stack&-1; lu _ (Stack&-1) xor (smallpl); lspL1 _ T, goto[lspSetBase, alu=0]; goto[ufnLBL]; lspSetBase: * Turn TOS into LspGenBr,Hi as basereg * Gotcha: don't do mem op in next inst T _ Stack&-1; lspGenBr _ T; T _ lsh[Stack, 10]; T _ (rhmask[Stack&+1]) + T + 1; lspGenBrHi _ T, return; * AddBase, op 320 * {ptr, nbr} => {ptr} @AddBase: loadpage[pgHStack], call[CheckElt2P7], opcode[320]; T _ Stack&-1; * lo addend lu _ (Stack) xor (smallpl); * smallpos? lu _ (Stack&-1) xor (smallneg), skip[alu#0]; lspL0 _ Zero, goto[.adb2]; * hi = 0 lspL0 _ (Zero) - 1, goto[.adb2, alu=0]; * hi = -1 lspUFN _ 320c, goto[ufnLBL]; .adb2: Stack _ (Stack) + T; * add lo base and lo addend Stack&-1, FreezeResult; T _ lspL0, FreezeResult; Stack _ (Stack) + T, UseCOutAsCIn; * add hi's Stack&+1, goto[PopState1]; * lo result * Vag2, op 321 * {nbr, nbr} => {ptr} @Vag2: loadpage[pgHStack], call[CheckElt2P7], opcode[321]; T _ Stack&-1; * T _ b lu _ (Stack&-2) - (smallpl); * test b small lu _ (Stack&+1) - (smallpl), skip[alu=0]; * test a small lspUFN _ 321c, goto[ufnLBL]; skip[alu=0]; lspUFN _ 321c, goto[ufnLBL]; Stack&-1 _ Stack&-1; * hiloc(TOS) _ a * then loloc(TOS) _ b (= T) StkState _ rsh[StkState, 1], goto[PushTP7]; * Hiloc, op 322, Push the high order word of the TOS onto the stack as an integer @HiLoc: Stack&-1, opcode[322]; T _ Stack&+1, goto[TOSGetsTSmall]; * LoLoc, op 323, Replace TOS with the low order word of TOS as an integer @LoLoc: Stack&-1 _ (smallpl), opcode[323]; Stack&+1, goto[nxiLBL]; * (BLT destaddr sourceaddr nwords) * moves TOS words from @TOS-1 to @TOS-2, right to left * @BLT: loadpage[pgHStack], call[CheckElt3P7], opcode[304]; * ensure 3 cells on stack T _ Stack&-1; lu _ (Stack&-1) xor (smallpl); * Is tos small? lspL1 _ T, skip[alu=0]; * Save count for int check lspUfn _ 304c, goto[ufnLBL]; * no, punt T _ Stack&-1; * get source address lspL2 _ T; T _ lsh[Stack, 10]; T _ (rhmask[Stack&-1]) + T + 1; * make L2,3 a basereg lspL3 _ T, loadpage[opPage3]; * get dest in lspGenBr lspInstFlag _ (InBltState), callp[lspSetBase]; * pagefault flag * Now have lspLN = nwords, lspGenBr = dest, lspL2,3 = source * Stack is pointing at dest. Our strategy is to use Stack as * the offset in memory operations. Stack is updated on each iteration, * but only once we are sure there is no fault from the previous iteration. * Stack is thus completely correct for Interrupts, needs only slight * adjustment (incrementing nwords) on Pagefault. When Stack reaches * zero we are finished. Stack&+2; Stack&+2, call[BLTLp]; * Point Stkp at nwords BLTLp: lu _ Stack; * don't update Stack til after fault T _ Stack _ (Stack) - 1, goto[BltXit, alu=0]; PFetch1[lspL2, xBuf]; * xBuf _ datum nop; PStore1[lspGenBr, xBuf]; * store in dest goto[BltInt, IntPending]; return; BltInt: * Take interrupt unless count was less than critical amount lu _ (lspL1) - (BltInterruptableMinWords); loadpage[opPage0], skip[alu>=0]; return; * don't take interrupt yet gotop[TakeInterrupt]; BltXit: Stack&-2; Stack&-2, loadpage[5]; lspInstFlag _ (NormalState), goto[Pop2P5]; * net 2 pop BltFault: * come here on pagefault * need to restore nwords so that the last attempt is retried Stack _ (Stack) + 1, goto[lspDoFault], at[FaultDisp, InBltState!]; :END[Low]; (1792)