: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];