{File name: FixedXfer.mc
Copyright (C) 1981, 1986, 1987 by Xerox Corporation.
All rights reserved.

Trow
16-Nov-87 18:50:36 Add ClrIE to IWDC and SetIE to DWDC.
Trow
27-Oct-87 15:38:07 Fix split memory op at FreeMapFix.
Trow
26-Oct-87 23:21:40 Change XwdDisp to XdwDisp.
Trow
13-Oct-87 15:15:45 Split memory op at FreeMapFix. Fix bank cross. Reverse targets 1 and 2 of XwdDisp.
Fiala 5-Mar-87 13:47:20 Added duplicate of EFCHaveLink for entry from Bank 0.
Fiala 16-May-86 9:23:41 Changes for 4MB storage. Possible problems:
1) Who calls LGCSameG?
Frandeen August 20, 1981 2:20 PM: Fix for new assembler.
Frandeen February 11, 1981 1:54 PM: catch KFCB for Block Equal
H Sturgis: 20-Sep-82 17:19:33
Description: Xfer and related opcodes,
Created by R. Johnsson
}

{rhT encoding:
BitMeaning
9-10amount to backup PC if trap occurs 3 means RET or LSTF
12-150: Process/LST, 1: FC, 2: LSTF, 3: RET, 4: ~, 5: SFC, 6: ~, 7: RETZ, 8: Trap
12: Trap, 13: Special, 14: Free, 15: Push SD
}
Set[xtTrap, Or[Lshift[0,6],8]];
Set[xtLST, Or[Lshift[2,5],0]];
Set[xtFC1, Or[Lshift[1,5],1]];
Set[xtFC2, Or[Lshift[2,5],1]];
Set[xtLSTF, Or[Lshift[3,5],2]];
Set[xtRET, Or[Lshift[3,5],3]];
Set[xtSFC, Or[Lshift[1,5],5]];
Set[xtRETZ, Or[Lshift[3,5],7]];
Set[xtFree, 200’b];
Set[xtPSwitch, 0]; {Also in Process.df}

{Fault/Trap flag}
Set[L3.XTrap, 0];
Set[L3.XFault, 1];

{LoadGC returns - Link 2; relative to LoadGCRets}
Set[L2.LoadGCFramer,0D];
Set[L2.LoadGCprocr,0E];
Set[L2.LGCRetTrapr,0F];

{StashPC returns - Link 2; relative to StashRets}
Set[L2.EFCnStashr,0];
Set[L2.EFCBStashr,1];
Set[L2.LFCnStashr,2];
Set[L2.LFCBStashr,3];
Set[L2.SFCStashr,4];
Set[L2.KFCBStashr,5];
Set[L2.PORTOStashr,6];
Set[L2.LSTStashr,7];
Set[L2.TRAPStashr,0A]; {0 MOD 2; Also in Mesa.df}
Set[L2.FAULTStashr,0B]; {1 MOD 2; paired with L2.TRAPStashr and L3.XFault}
Set[L2.BRKStashr,8];
Set[L2.RSStashr,9]; {Also in Process.df}

{AllocSub returns - Link 2; relative to AllocRets or AllocTraps}
Set[L2.EVAllocr,0B]; {must be odd}
Set[L2.ALLOCr,0C];

{GetLink and XMDSRead returns - Link 2; relative to XMDSReadRets}
Set[L2.EFCHaveLink,0]; {must be even}
Set[L2.LLKBHaveLink,1];
Set[L2.XIndirectDone,2];
Set[L2.XGFTRead,3];
Set[L2.LSTSourcer,4];
Set[L2.LSTDestr,5];
Set[L2.LSTStkpr,6];
Set[L2.LSTloopr,7];

{XMDSWrite returns - Link 2; relative to XMDSWriteRets}
Set[L2.DSTSourcer,0];
Set[L2.DSTDestr,1];
Set[L2.DSTStkpr,2];
Set[L2.DSTLoopr,3];

{L2 codes used to indicate stackP and PC fixups}
Set[L2.Pop0Incr1or2, 0 {00xx}]; {also in Jump.mc}

{****************************************************************************
LINKB - Link Byte
****************************************************************************}

@LINKB:
T ← ib, push{tos},c1, opcode[167’b];
push{dest},c2;
TT ← STK, pop{tos},c3;

MAR ← [rhL, L+4], pop,c1;
MDR ← TT - T, IBDisp, CANCELBR[$,0],c2;
PC ← PC + 1, DISPNI[OpTable],c3;

{****************************************************************************
EFCn - External Function Call n (n = 0-15)
****************************************************************************}

@EFC0:
T ← 0, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[300’b];
@EFC1:
T ← 1, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[301’b];
@EFC2:
T ← 2, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[302’b];
@EFC3:
T ← 3, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[303’b];
@EFC4:
T ← 4, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[304’b];
@EFC5:
T ← 5, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[305’b];
@EFC6:
T ← 6, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[306’b];
@EFC7:
T ← 7, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[307’b];
@EFC8:
T ← 8, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[310’b];
@EFC9:
T ← 9, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[311’b];
@EFC10:
T ← 0A, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[312’b];
@EFC11:
T ← 0B, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[313’b];
@EFC12:
T ← 0C, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[314’b];
@EFC13:
T ← 0D, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[315’b];
@EFC14:
T ← 0E, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[316’b];
@EFC15:
T ← 0F, L2←L2.EFCnStashr, GOTO[EFCnStash],c1, opcode[317’b];

EFCnStash:
TT ← UvPCpage, L1 ← 1, CALL[StashPC1],c2;
EFCnStashr:
rhT ← xtFC1, GOTO[EFCGetLink],c3, at[L2.EFCnStashr,10,StashRets];

{****************************************************************************
EFCB - External Function Call Byte
****************************************************************************}
@EFCB:
T ← ib, L2←L2.EFCBStashr, GOTO[EFCBStash],c1, opcode[320’b];

EFCBStash:
TT ← UvPCpage, L1 ← 2, CALL[StashPC2],c2;
EFCBStashr:
rhT ← xtFC2, GOTO[EFCGetLink],c3, at[L2.EFCBStashr,10,StashRets];

EFCGetLink:
MAR ← [rhG, G+0], GOTO[GetLink], L2 ← L2.EFCHaveLink,c1;
EFCHaveLink:
Map ← Q ← [rhMDS, T], Udest ← T, L0 ← L0.XFStartRead, DISP4[XferFrame, 0C],c1, at[L2.EFCHaveLink,10,XMDSReadRets];

{Duplicate instruction for entry from Bank0 StartMesa.}
{db}
Udest ← T, YDisp, L ← 0, GOTOABS[B1EFCHaveLink],c3, at[BxEFCHaveLink];

Map ← Q ← [rhMDS, T], Udest ← T, L0 ← L0.XFStartRead, DISP4[XferFrame, 0C],c1, at[B1EFCHaveLink];



{****************************************************************************
LFCn - Local Function Call n (n = 1-16)
****************************************************************************}

{load Rx with ev offset from C-2}
@LFC1:
Rx ← 2, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[321’b];
@LFC2:
Rx ← 4, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[322’b];
@LFC3:
Rx ← 6, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[323’b];
@LFC4:
Rx ← 8, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[324’b];
@LFC5:
Rx ← 0A, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[325’b];
@LFC6:
Rx ← 0C, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[326’b];
@LFC7:
Rx ← 0E, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[327’b];
@LFC8:
Rx ← 10, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[330’b];
@LFC9:
Rx ← 12, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[331’b];
@LFC10:
Rx ← 14, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[332’b];
@LFC11:
Rx ← 16, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[333’b];
@LFC12:
Rx ← 18, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[334’b];
@LFC13:
Rx ← 1A, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[335’b];
@LFC14:
Rx ← 1C, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[336’b];
@LFC15:
Rx ← 1E, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[337’b];
@LFC16:
Rx ← 20, L2←L2.LFCnStashr, GOTO[LFCnStash],c1, opcode[340’b];

LFCnStash:
TT ← UvPCpage, push, L1 ← 1, CALL[StashPC1],c2;
LFCnStashr:
rhT ← xtFC1, T ← 0, STK ← TOS, GOTO[LFCCommon],c3, at[L2.LFCnStashr,10,StashRets];

LFCCommon:
L ← UvL, pop,c1;
TT ← UvC,c2;
TT ← TT + 1, Udest ← T,c3;

Map ← Q ← [rhTT, TT + Rx + 1], L0←L0.EVRead,c1;
TOS ← 0FF, L1 ← L1r.XFRFault,c2;
Rx ← rhRx ← MD, XRefBr, Usource ← L, GOTO[EVRead],c3;


{****************************************************************************
LFCB - Local Function Call Byte
****************************************************************************}

{load T with ev offset from C - 2}
@LFCB:
Rx ← LRot1 ib, L2←L2.LFCBStashr,c1, opcode[341’b];
TT ← UvPCpage, push, L1 ← 2, CALL[StashPC2],c2;
LFCBStashr:
rhT ← xtFC2, T ← 0, STK ← TOS, GOTO[LFCCommon],c3, at[L2.LFCBStashr,10,StashRets];

{****************************************************************************
SFC - Stack Function Call
****************************************************************************}

{load T with ev offset from C - 2}
@SFC:
Udest ← TOS, push, L2←L2.SFCStashr,c1, opcode[342’b];
TT ← UvPCpage, L1 ← 1, CALL[StashPC1],c2;
SFCStashr: STK ← TOS, T ← TOS, pop,
c3, at[L2.SFCStashr,10,StashRets];
rhT ← xtSFC,c1;
L ← UvL,c2;
T ← Udest, XDisp, GOTO[EFCHaveLink],c3;

{****************************************************************************
RET - Return
****************************************************************************}

@RET:
MAR ← [rhL,L-1], push,c1, opcode[343’b];
rhT ← xtRET, CANCELBR[$,0],c2;
T ← MD{fsi}, STK ← TOS, pop,c3;

MAR ← [rhL,L+2],c1;
L ← 0, UreturnPC ← PC, CANCELBR[$,0],c2;
T ← MD, Ufsi ← T, XDisp, GOTO[EFCHaveLink],c3;

{****************************************************************************
LLKB - Load Link Byte
****************************************************************************}

@LLKB:
T ← ib, UreturnPC ← PC, L2←L2.LLKBHaveLink,c1, opcode[344’b];
UrL ← L{clobbered by GetLink},c2;
rhT ← xtRET{for page fault fixup},c3;

rhTT ← UvChigh,c1;
Noop,c2;
Noop,c3;

MAR ← [rhG,G+0], CALL[GetLink],c1;
LLKBHaveLink:
TOS ← T, push, CANCELBR[$,0F],c1, at[L2.LLKBHaveLink,10,XMDSReadRets];
PC ← PC+1, push, fZpop, IBDisp,c2;
L ← UrL{restore}, DISPNI[OpTable],c3;

{****************************************************************************
PORTO - Port Out
****************************************************************************}
@PORTO:
push, L2←L2.PORTOStashr,c1, opcode[345’b];
TT ← UvPCpage, L1←1, CALL[StashPC1],c2;
PORTOStashr:
STK ← TOS, pop,c3, at[L2.PORTOStashr,10,StashRets];

Map ← Q ← [rhMDS,TOS], L0 ← L0.POWrite,c1;
L1 ← L1w.NoFixes,c2;
{db}
rhRx ← Rx ← MD, XdwDisp,c3;

POWrite:
MAR ← [rhRx,Q+0], DISP2[POMapFix],c1, at[L0.POWrite,10,WyMap];
POMapFix:
GOTO[WyMapFix],c2, at[0, 4, POMapFix];
{db}
GOTO[WyMapFix],c2, at[1, 4, POMapFix];
GOTO[WyMapFix],c2, at[3, 4, POMapFix];
{db}
MDR ← UvL,c2, at[2, 4, POMapFix];
rhT ← xtSFC,c3;

PORead:
MAR ← [rhRx, Q+1],c1;
L ← TOS{source}, CANCELBR[$,0],c2;
T ← MD, XDisp, GOTO[EFCHaveLink],c3;

{****************************************************************************
PORTI - Port In
****************************************************************************}
@PORTI:
L1 ← L1w.PopOnly, push{point to tos},c1, opcode[346’b];
push{point to dest},c2;
TT ← STK{dest}, push{point to source},c3;

{this reference can’t fault}
Map ← Q ← [rhMDS,TT], L0←L0.PIWrite,c1;
TT ← STK{source}, pop{point to dest},c2;
{db}
rhRx ← Rx ← MD, XdwDisp, pop{point to tos},c3;

PIWrite:
MAR ← [rhRx,Q+0], DISP2[PIMapFix],c1, at[L0.PIWrite,10,WyMap];
PIMapFix:
GOTO[WyMapFix],c2, at[0, 4, PIMapFix];
{db}
GOTO[WyMapFix],c2, at[1, 4, PIMapFix];
GOTO[WyMapFix],c2, at[3, 4, PIMapFix];
{db}
MDR ← 0,c2, at[2, 4, PIMapFix];
TOS ← TT, ZeroBr,c3;

MAR ← [rhRx,Q+1], BRANCH[$,PIZero],c1;
MDR ← TOS, TOS ← STK, IBDisp, CANCELBR[PITail,0],c2;
PITail:
PC ← PC+PC16, pop{point to tos-1}, DISPNI[OpTable],c3;

PIZero:
TOS ← STK, IBDisp, CANCELBR[PITail,0],c2;

{****************************************************************************
KFCB - Kernel Function Call Byte
****************************************************************************}
@KFCB:
T←ib, L2←L2.KFCBStashr,c1, opcode[347’b];
{Check for Block Equal instructions:
60B = sBLTECL; 52B = sBLTE; 54B = sBLTEC; 56B = sBLETL}
Q ← 30 {60B},c2;
TT ← T and 0F9 {371B: mask is 11 111 001}, c3;

[] ← T - Q {Test for 60B = BlockEqualCodeLong}, ZeroBr,c1;
Q ← 28 {50B: test for 101 xx0}, BRANCH[$,BlockEqualDisp],c2;
[] ← TT - Q {50B: test for 101 xx0}, ZeroBr,c3;

BRANCH[$, KFCBBlockEqual],c1;
TT ← UvPCpage, L1←2, push, CALL[StashPC2, $],c2;

KFCBBlockEqual:
Ybus ← T and 6, YDisp,c2;
BlockEqualDisp:
DISP3[BlockEqual],c3;

KFCBStashr:
STK←TOS, rhT ← xtFC2,c3, at[L2.KFCBStashr,10,StashRets];
KFCGo:
L ← UvL, pop,c1;
SDFetch:
TT ← uSDAddr, L2 ← L2.EFCHaveLink,c2;
SDFetchx:
TT ← TT + T,c3;

Map ← Q ← [rhMDS,TT],c1;
L ← UvL, L0←L0.XMStartRead, CALL[XMDSReadx],c2;

{****************************************************************************
DESCB - Descriptor Byte
****************************************************************************}
@DESCB:
MAR ← [rhG, G+0], push,c1, opcode[350’b];
TT ← ~3F, STK ← TOS,c2;
DESCBx:
T ← MD and TT, push, fZpop,c3;

TOS ← ib,c1;
TOS ← TOS + T + 1, IBDisp,c2;
PC ← PC + 1, DISPNI[OpTable],c3;


{****************************************************************************
DESCBS - Descriptor Byte Stack
****************************************************************************}
@DESCBS:
Map ← Q ← [rhMDS, TOS], L0 ← L0.DESCBRead,c1, opcode[351’b];
L1 ← L1r.NoFixes,c2;
rhRx ← Rx ← MD, XRefBr,c3;

DESCBRead:
MAR ← [rhRx,Q+0], BRANCH[DBSMapFix, DBSMapOK],c1, at[L0.DESCBRead,10,RyMap];
DBSMapFix:
GOTO[RyMapFix],c2;
DBSMapOK:
TT ← ~3F, GOTO[DESCBx],c2;


{****************************************************************************
ALLOC - Allocate frame
****************************************************************************}
@ALLOC:
UrL ← L, L ← rhL, pop,c1, opcode[356’b];
UrLHi ← L, push,c2;
L ← UvL, push,c3;

STK ← TOS, pop, c1;
Usource ← L, L2←L2.ALLOCr,c2;
TT ← u200, CALL[AllocSub],c3;

ALLOCr:
TOS ← Q,c3, at[L2.ALLOCr,10,AllocRets];

TT ← Usource{old UvL},c1;
PC ← PC+PC16, UvL ← TT,c2;
rhL ← UrLHi,c3;

L ← UrL, GOTO[IBDispOnly],c1;

GOTO[ALLOCf],c1, at[L2.ALLOCr,10,AllocFaults];

uFaultParm0 ← TT,c1, at[L2.ALLOCr,10,FrameFault];
ALLOCf:
L ← UrL,c2;
rhL ← UrLHi, GOTO[XferFault],c3;

{****************************************************************************
FREE - Free frame
****************************************************************************}

@FREE:
Map ← Q ← [rhMDS, TOS-1], push, L1←L1w.NoFixes,c1, opcode[357’b];
TT ← uAVAddr, L0←L0.FreeReadFsi,c2;
{db}
STK ← TOS, pop, rhRx ← Rx ← MD, XdwDisp,c3;

FreeReadFsi:
MAR ← [rhRx, Q+0], DISP2[FsiMapFix],c1, at[L0.FreeReadFsi,10,WyMap];
FsiMapFix:
GOTO[WyMapFix],c2, at[0, 4, FsiMapFix];
{db}
GOTO[WyMapFix],c2, at[1, 4, FsiMapFix];
GOTO[WyMapFix],c2, at[3, 4, FsiMapFix];
{db}
rhT ← xtFree,c2, at[2, 4, FsiMapFix];
TT ← MD or TT,c3;

Map ← Q ← [rhMDS,TT], L0←L0.FreeReadWrite,c1;
TT ← TOS, L1←L1w.XFWFault, GOTO[Freex],c2;

Freed:
MAR ← [rhRx,Q+0],c1, at[2,4,NoSD];
MDR ← TT, PC ← PC+PC16, IBDisp, GOTO[SLTail],c2;

{****************************************************************************
IWDC - Increment Wakeup Disable Counter
****************************************************************************}

@IWDC:
{db}
T ← uWDC, ClrIE,c1, opcode[360’b];
T ← T + 1, PgCarryBr,c2;
IWDCxx:
uWDC ← T, BRANCH[$, wdcOverflow],c3;

Noop,c1;
IBDisp,c2;
IWDCx:
PC ← PC + PC16, DISPNI[OpTable],c3;

wdcOverflow:
T ← sWakeupError, L2←L2.TRAPStashr,c1;
TT ← UvPCpage, L1←0, CALL[StashPC0],c2;

{****************************************************************************
DWDC - Decrement Wakeup Disable Counter
****************************************************************************}
@DWDC:
T ← uWDC, ZeroBr,c1, opcode[361’b];
{db}
T ← T - 1, ZeroBr, BRANCH[$, wdcUnderflow],c2;
{db}
TT ← uWP, ZeroBr, BRANCH[dontEnableInt, enableInt],c3;

enableInt:
{db}
SetIE, CANCELBR[$, 1],c1;
{db}
Noop,c2;
{db}
TT ← uWP, ZeroBr,c3;

dontEnableInt:
{db}
Xbus ← uPCCross, XRefBr, BRANCH[ints, noInts],c1;

ints:
TT ← LRot1 ErrnIBnStkp, MesaIntRq, BRANCH[dwdcDispatch, IWDCxx],c2;
noInts:
TT ← LRot1 ErrnIBnStkp, BRANCH[dwdcDispatch, IWDCxx],c2;

dwdcDispatch:
Xbus ← TT LRot0, XwdDisp,c3;
uWDC ← T, DISP2[dwdcBuffer],c1;

dwdcBuffer:
PC ← PC + PC16, GOTO[dwdcNE],{IBptr=3}c2, at[0,4,dwdcBuffer];
AlwaysIBDisp, GOTO[IWDCx],{IBptr=2}c2, at[1,4,dwdcBuffer];
PC ← PC + PC16, GOTO[dwdcNE],{IBptr=1}c2, at[2,4,dwdcBuffer];
PC ← PC + PC16, GOTO[dwdcE],{IBptr=0}c2, at[3,4,dwdcBuffer];

dwdcE:
GOTO[RefillE],c3;
dwdcNE:
GOTO[RefillNE],c3;

wdcUnderflow:
{db}
CANCELBR[wdcOverflow, 1],c3;

{****************************************************************************
CATCH
****************************************************************************}
@CATCH:
Xbus ← ib,c1, opcode[363’b];
IBDisp,c2;
CATCHx:
PC ← PC+1, DISPNI[OpTable],c3;

{****************************************************************************
DST - Dump State
****************************************************************************}

@DST:
Q ← ib, push, L1←L1w.PopOnly,c1, opcode[370’b];
STK ← TOS, TT ← Q + State.datam1 + 1,c2;
TOS ← UvL, L2 ← L2.DSTSourcer,c3;

Map ← Q ← [rhMDS, TOS+TT], L0 ← L0.XMStartWrite,c1;
T ← Usource, CALL[XMDSWritex],c2;
DSTSourcer:
T ← Udest, L2 ← L2.DSTDestr,c3, at[L2.DSTSourcer,10,XMDSWriteRets];

Map ← Q ← [rhMDS, Q-1], CALL[XMDSWrite],c1;
DSTDestr:
T ← ErrnIBnStkp,c3, at[L2.DSTDestr,10,XMDSWriteRets];

T ← T and 0F,c1;
T ← T xor 0F,c2;
T ← T - 1, L2 ← L2.DSTStkpr,c3;

Map ← Q ← [rhMDS,Q-1], CALL[XMDSWrite],c1;
DSTStkpr:
[] ← T - cSSm1, CarryBr,c3, at[L2.DSTStkpr,10,XMDSWriteRets];

stackP ← TT ← T+2, BRANCH[DSTNoCarry, DSTCarry],c1;
DSTCarry:
stackP ← TT ← cSS,c2;
Noop,c3;
Noop,c1;

DSTNoCarry:

Q ← Q - cSS, push,c2;
Q ← Q + TT, L2 ← L2.DSTLoopr,c3;

DSTLoop:
Map ← Q ← [rhMDS, Q-1], BRANCH[$,DSTdone],c1;
T ← STK, pop, CALL[XMDSWritex],c2;
DSTLoopr:
TT ← TT - 1, ZeroBr, GOTO[DSTLoop],c3, at[L2.DSTLoopr,10,XMDSWriteRets];

DSTdone:
pop, PC ← PC + 1, IBDisp, GOTO[DISPNIonly],c2;

{****************************************************************************
LST - Load State
****************************************************************************}
{This is not a work of art, but how often does it happen?}
@LST:
L2←L2.LSTStashr,c1, opcode[371’b];
TT ← UvPCpage, L1←2, CALL[StashPC2],c2;
rhT ← xtLST,c3, at[L2.LSTStashr,10,StashRets];

LSTCommon:
Q ← UvL, L1←L1r.NoFixes,c1;
TOS ← Q + ibNA + 1, Ufsi ← T, L0←L0.XMStartRead,c2;
TT ← State.datam1, L2←L2.LSTSourcer,c3;

Map ← Q ← [rhMDS, TOS+TT], CALL[XMDSRead],c1;

LSTSourcer:
Map ← Q ← [rhMDS, Q-1], CANCELBR[$,0F],c1, at[L2.LSTSourcer,10,XMDSReadRets];
Usource ← T, L2←L2.LSTDestr,c2;
rhRx ← Rx ← MD, XRefBr, CALL[XMStartRead],c3;

LSTDestr:
Map ← Q ← [rhMDS, Q-1], CANCELBR[$,0F],c1, at[L2.LSTDestr,10,XMDSReadRets];
Udest ← T, L2←L2.LSTStkpr,c2;
rhRx ← Rx ← MD, XRefBr, CALL[XMStartRead],c3;

LSTStkpr:
uStkDepth ← T, CANCELBR[$,0F],c1, at[L2.LSTStkpr,10,XMDSReadRets];
rhTT ← T LRot8 {BrkByte},c2;
TT ← rhTT,c3;

T ← T and 0F,c1;
Q ← T - cSSm1, CarryBr,c2;
Q ← Q + cSSp1, BRANCH[LSTload,LSTcarry],c3;

LSTcarry:
Q ← cSS,c1;
Noop,c2;
GOTO[LSTload],c3;

LSTload:
UBrkByte ← TT, L2 ← L2.LSTloopr,c1;
stackP ← 1,c2;
TT ← Q{number of items to load},c3;

LSTloop:
Map ← Q ← [rhMDS, TOS-1], push, CALL[XMDSRead],c1;

LSTloopr:
STK ← T, CANCELBR[$,0F],c1, at[L2.LSTloopr,10,XMDSReadRets];
TT ← TT - 1, ZeroBr,c2;
TOS ← TOS + 1, BRANCH[LSTloop,LSTdone],c3;

LSTdone:
stackP ← uStkDepth,c1;
L ← Usource,c2;
T ← Udest, XDisp,c3;

Map ← Q ← [rhMDS, T], Xbus ← ib, L0 ← L0.XFStartRead, DISP4[XferFrame,0C],c1;

{****************************************************************************
LSTF - Load State and Free
****************************************************************************}
@LSTF:
MAR ← [rhL, L-1],c1, opcode[372’b];
rhT ← xtLSTF, CANCELBR[$,0],c2;
T ← MD, UreturnPC ← PC, GOTO[LSTCommon],c3;

{****************************************************************************
BRK - BreakPoint
****************************************************************************}
@BRK:
T ← UBrkByte, ZeroBr, push,c1, opcode[376’b];
STK ← TOS, pop, BRANCH[ResumeBRK, Break],c2;
Break:
GOTO[Trapc1],c3;

ResumeBRK:
UBrkByte ← 0,c3;

OpDispatch:
Xbus ← T LRot12, XDisp,c1;
Ybus ← T, YDisp, DISP4[OpD0],c2;
{OpD0:}
GOTOABS[Add[OpcodeBase,0]],c3, at[0,10,OpD0];
GOTOABS[Add[OpcodeBase,10]],c3, at[1,10,OpD0];
GOTOABS[Add[OpcodeBase,20]],c3, at[2,10,OpD0];
GOTOABS[Add[OpcodeBase,30]],c3, at[3,10,OpD0];
GOTOABS[Add[OpcodeBase,40]],c3, at[4,10,OpD0];
GOTOABS[Add[OpcodeBase,50]],c3, at[5,10,OpD0];
GOTOABS[Add[OpcodeBase,60]],c3, at[6,10,OpD0];
GOTOABS[Add[OpcodeBase,70]],c3, at[7,10,OpD0];
GOTOABS[Add[OpcodeBase,80]],c3, at[8,10,OpD0];
GOTOABS[Add[OpcodeBase,90]],c3, at[9,10,OpD0];
GOTOABS[Add[OpcodeBase,0A0]],c3, at[0A,10,OpD0];
GOTOABS[Add[OpcodeBase,0B0]],c3, at[0B,10,OpD0];
GOTOABS[Add[OpcodeBase,0C0]],c3, at[0C,10,OpD0];
GOTOABS[Add[OpcodeBase,0D0]],c3, at[0D,10,OpD0];
GOTOABS[Add[OpcodeBase,0E0]],c3, at[0E,10,OpD0];
GOTOABS[Add[OpcodeBase,0F0]],c3, at[0F,10,OpD0];

{****************************************************************************
Xfer:
Entry:
Udest and T hold destination link
PC has LRot1 T (for procedure descriptor decode)
L has va of caller’s frame (to be stored into Usource)
calling instruction executed on c1 and entera at one of:
XferFrame, XferProc1, XferIndirect, XferProc3
****************************************************************************}

{ ********* Frame link ********* }
Set[L1w.XFWFaultEven,And[L1w.XFWFault,0E]];

XferFrame:
TOS ← Q, Usource ← L, L1 ← L1w.XFWFault, ZeroBr, c2, at[0C,10,XferFrame];
{db} L ← MD, rhL ← MD, XdwDisp, BRANCH[$, XferNullDest], c3;

XFStartRead:
MAR ← [rhL, Q+0], DISP2[XFMapUpdate], c1;
MAR ← [rhL, Q+0], DISP2[XFMapUpdate], c1, at[L0.XFStartRead,10,WyMap];
XFMapUpdate:
Rx ← L, GOTO[WyMapFix], c2, at[0, 4, XFMapUpdate];
{db} Rx ← L, GOTO[WyMapFix], c2, at[1, 4, XFMapUpdate];
Rx ← L, GOTO[WyMapFix], c2, at[3, 4, XFMapUpdate];
{db} TT ← UvL, c2, at[2, 4, XFMapUpdate];
TT ← MD, uFrame ← TT, L2 ← L2.LoadGCFramer, c3;

Map ← Q ← [rhMDS,TT+0], ZeroBr, GOTO[XFTestG], c1;

LoadGCFramer:
MAR ← L ← [rhL,TOS+1], c1, at[L2.LoadGCFramer,10,LoadGCRets];
UvL ← TOS, CANCELBR[$,0], {no traps after here} c2;
PC ← MD{byte pc}, UvChigh ← TT, c3;

L ← L - 1, c1;
T ← Usource, push, c2;
UvC ← Q, Xbus ← rhT, XDisp, L2←L2.Pop0Incr1or2, c3;

MAR ← [rhL, L+2], DISP4[XFTrapdone], c1;
XFLSTdone: L1←L1r.Refill, CANCELBR[XferDoneA,0], c2, at[0,10,XFLSTdone];
XFFCdone: push, CANCELBR[XFCdoneA,0], c2, at[1,10,XFLSTdone];
XFLSTFdone: TT ← Ufsi, CANCELBR[XLSTFdoneA,0], c2, at[2,10,XFLSTdone];
XFRETdone: Q ← u200, push, CANCELBR[XRETfree,0], c2, at[3,10,XFLSTdone];
XFSFCdone: TT ← Udest, push, CANCELBR[XSFCdoneA,0], c2, at[5,10,XFLSTdone];
XFRETZdone: STK ← 0, push, CANCELBR[XRETdoneA,0], c2, at[7,10,XFLSTdone];
XFTrapdone: MDR ← T, CANCELBR[XTrapdoneA,0], c2, at[8,10,XFLSTdone];

XferNullDest:
T ← sControlFault, CANCELBR[$,3], c1;
TT ← Usource, c2;
GOTO[SetTrapParm], c3;


{ ********* Indirect link ********* }
XferIndirect:
L1 ← L1r.XFRFault, c2, at[0E,10,XferFrame];
L2 ← L2.XIndirectDone, c3;

Map ← Q ← [rhMDS, T], GOTO[XMDSRead], c1;
Map ← Q ← [rhMDS, T], L0 ← L0.XFStartRead, DISP4[XferFrame,0C], c1, at[L2.XIndirectDone,10,XMDSReadRets];



{ ********* Procedure descriptor ********* }
XferProc1: PC ← T LRot1, GOTO[XferProc], c2, at[0D,10,XferFrame];
XferProc3: PC ← T LRot1, GOTO[XferProc], c2, at[0F,10,XferFrame];

XferProc: Noop, c3;

TT ← LRot1 (PC and ~7E){gfi rot8}, c1;
TT ← TT+3{(*gfi+1400b)rot8}, c2;
TOS ← TT LRot8{gfi+1400b}, c3;

{map GFT item}
Map ← Q ← [rhMDS,TOS], L0 ← L0.XGFTRead, c1;
TT ← UvL, L1 ← L1w.XFWFault, c2;
rhRx ← Rx ← MD, XRefBr, uFrame ← TT, c3;

XGFTRead: MAR ← [rhRx,Q+0], BRANCH[XGFTMapFix,XGFTMapOK], c1, at[L0.XGFTRead,10,RyMap];
XGFTMapFix: GOTO[RyMapFix], c2;

XGFTMapOK: PC ← RRot1 (7C and PC){2*ep}, c2;
G ← MD, Usource ← L, L2 ← L2.LoadGCprocr, c3;

Map ← Q ← [rhMDS, G and ~3], ZeroBr, c1;
XFTestG: [] ← Q xor UvG, NZeroBr, BRANCH[LoadGC, NullG], c2;
NullG: T ← sUnbound, CANCELBR[SetUdestC1,1], c3;

LoadGCprocr:
Xbus ← UrG, XDisp, c1, at[L2.LoadGCprocr,10,LoadGCRets];
UvC ← Q, DISP4[EVOffset, 0C], c2;
EVOffset: TOS ← PC + 2, L0 ← L0.EVRead, GOTO[EVFetch], c3, at[0C,10,EVOffset];
TOS ← PC + 102’b, L0 ← L0.EVRead, GOTO[EVFetch], c3, at[0D,10,EVOffset];
TOS ← PC + 202’b, L0 ← L0.EVRead, GOTO[EVFetch], c3, at[0E,10,EVOffset];
TOS ← PC + 302’b, L0 ← L0.EVRead, GOTO[EVFetch], c3, at[0F,10,EVOffset];

{map entry vector item}
EVFetch: Map ← Q ← [rhTT,Q+TOS], c1;
TOS ← 0FF, L1 ← L1r.XFRFault, c2;
rhRx ← Rx ← MD, XRefBr, UvChigh ← TT, c3;

EVRead: MAR ← [rhRx,Q+0], BRANCH[EVMapFix,EVMapOK], c1, at[L0.EVRead,10,RyMap];
EVMapFix: GOTO[RLyMapFix], c2;

EVMapOK: TT ← u200, c2;
PC ← MD{word pc from ev, shifted by AllocSub}, c3;

MAR ← [rhRx,Q+1], L2 ← L2.EVAllocr, c1;
PC ← LShift1 PC, ZeroBr, CANCELBR[$,0], c2;
TOS ← TOS and MD{fsize}, BRANCH[AllocSub, ZeroPC], c3;

ZeroPC: T ← sUnbound, GOTO[TrapHandler], c1;

EVAllocr: T ← Usource, CANCELBR[$], c3, at[L2.EVAllocr,10,AllocRets];

MAR ← L ← [rhL,Q+0], push, c1;
MDR ← UvG, c2;
[] ← rhT, XDisp, L2←L2.Pop0Incr1or2, c3;

MAR ← [rhL,L+2], DISP4[XTrapdone], c1;

XLSTdone: MDR ← T, L1←L1r.Refill, CANCELBR[XferDoneA,0], c2, at[0,10,XLSTdone];
XTrapdoneA: Noop, c3;

MAR ← [rhL, L+3], c1;
MDR ← UTrapParm, L1←L1r.Refill, CANCELBR[XferDoneA,0], c2;

XFCdone: MDR ← T{return link}, push, CANCELBR[XFCdoneA,0], c2, at[1,10,XLSTdone];
XFCdoneA: TT ← Udest, push, GOTO[XferDone], c3;

XLSTFdone: MDR ← T, TT ← Ufsi, CANCELBR[$,0], c2, at[2,10,XLSTdone];
XLSTFdoneA: TT ← u200 or TT, L0 ← L0.FreeReadWrite, GOTO[Free], c3;

XRETdone: CANCELBR[XRETdoneA,0], c2, at[3,10,XLSTdone];

XSFCdone: MDR ← T{return link}, TT ← Udest, push, CANCELBR[XSFCdoneA,0], c2, at[5,10,XLSTdone];
XSFCdoneA: GOTO[XferDone], c3;


XRETZdone: STK ← 0, push, CANCELBR[XRETdoneA,0], c2, at[7,10,XLSTdone];
XTrapdone: MDR ← T, CANCELBR[XTrapdoneA,0], c2, at[8,10,XLSTdone];

{these Noops are ugly, but this case is RETURNing to a procedure - rare or RETZ}
XRETdoneA: Noop, c3;
Noop, c1;
Q ← u200, push, c2;
XRETfree: TT ← Ufsi or Q, push, L0 ← L0.FreeReadWrite, GOTO[Free], c3;

{map av item}
Free: Map ← Q ← [rhMDS,TT], c1;
TT ← uFrame{frame to be freed}, L1 ← L1w.XFWFault, c2;
Freex:
{db} rhRx ← Rx ← MD, XdwDisp, c3;

{store new head, fetch old head}
FreeReadWrite:
MAR ← [rhRx,Q+0], DISP2[FreeMapFix], c1, at[L0.FreeReadWrite,10,WyMap];
FreeMapFix:
GOTO[WyMapFix], c2, at[0, 4, FreeMapFix];
{db} GOTO[WyMapFix], c2, at[1, 4, FreeMapFix];
GOTO[WyMapFix], c2, at[3, 4, FreeMapFix];
{db} T ← TT, c2, at[2, 4, FreeMapFix];
TT ← MD {old list head}, c3;

{db} MAR ← [rhRx,Q+0], c1;
{db} MDR ← T, c2;
{db} Rx ← T, c3;

{map old frame}
Map ← Q ← [rhMDS,Rx], c1;
Xbus ← rhT, XLDisp, c2;
rhRx ← Rx ← MD, DISP2[NoSD], c3;

{store old list head}
NoSD: MAR ← [rhRx,Q+0], c1, at[0,4,NoSD];
MDR ← TT, L1←L1r.Refill, GOTO[XferDoneA], c2;

LoadSD: MAR ← [rhRx,Q+0], c1, at[1,4,NoSD];
MDR ← TT, T ← 0, c2;
TT ← Udest, c3;

XferDone: STK ← T{source}, pop, c1;
STK ← TT{dest}, pop, L1←L1r.Refill, c2;
XferDoneA:
Xbus ← PC LRot0, TT ← RShift1 PC, XLDisp, c3;

T←UvC, XC2npcDisp, BRANCH[xdEven,xdOdd,2], c1;
xdEven: TT ← TT + T, BRANCH[xdEO,xdEE,0E], c2;
xdOdd: TT ← TT + T, BRANCH[xdOO,xdOE,0E], c2;
xdEE: T ← TT and 0FF, GOTO[xdRefill], c3;
xdEO: T ← TT and 0FF, Cin←pc16, GOTO[xdRefill], c3;
xdOE: T ← TT and 0FF, Cin←pc16, GOTO[xdRefill], c3;
xdOO: T ← TT and 0FF, GOTO[xdRefill], c3;

xdRefill: Rx ← RShift1 uXTS, XLDisp, c1;
uXTS ← Rx, BRANCH[$, XferTrap, 2], c2;
TOS ← STK, pop, L0 ← L0.JRemap, c3;

Map ← [rhTT, TT], c1;
TT ← TT and ~0FF, c2;
PC ← rhPC ← MD, XRefBr, uPCValid ← PC, GOTO[JRedo], c3;

XferTrap: T ← sXferTrap, pop, c3;

MAR ← [rhL, L+1], c1;
MDR ← PC, rhT ← xtTrap, CANCELBR[$,0], c2;
TT ← Udest, c3;

UTrapParm ← TT, GOTO[SDFetch], c1;


{****************************************************************************
Trap Handler:
Entry:
calling instruction on c1
UvL is valid for trapping frame
T has SD index;
Exit:
PC of UvL backed up by amount in rhT
rhT has xtTrap
goes to SDFetch
****************************************************************************}

TrapHandler:
L ← UvL, L3←L3.XTrap, c2;
XTrapFix:
Xbus ← rhT, XwdDisp, c3;

XTrap: Map ← TOS ← [rhMDS, L], DISP2[BackPC0], c1;
BackPC0:
L3Disp, GOTO[TrapGo], c2, at[0,4,BackPC0];
BackPC1:
TT ← 1, GOTO[TrapLMap], c2, at[1,4,BackPC0];
BackPC2:
TT ← 2, GOTO[TrapLMap], c2, at[2,4,BackPC0];
Xbus ← 1, XDisp, c2, at[3,4,BackPC0];
TrapLMap:
L ← rhL ← MD, BRANCH[$, RetFix], c3;

MAR ← [rhL, TOS+1], c1;
Noop, CANCELBR[$,0], c2;
PC ← MD, c3;

MAR ← [rhL, TOS+1], c1;
MDR ← PC - TT, L3Disp, CANCELBR[$,0], c2;

TrapGo: uPCValid ← 0, BRANCH[$, XferFault], c3, at[L2.TRAPStashr,10,StashRets];
rhT ← xtTrap, GOTO[SDFetch], c1;

FaultGo: uPCValid ← 0, CANCELBR[$,0], c3, at[L2.FAULTStashr,10,StashRets];
XferFault: Rx ← pFault, GOTO[SaveRegs], c1;

SetUdestC1: Noop, c1;
SetUdestC2: Noop, c2;
SetUdestAsParm:
TT ← Udest, c3;
SetTrapParm:
UTrapParm ← TT, GOTO[TrapHandler], c1;

RetFix: MAR ← L ← [rhL, TOS+0], c1;
PC ← UreturnPC, c2;
G ← MD, L1←L1w.XFWFault, c3;

Map ← Q ← [rhMDS, G], L2 ← L2.LGCRetTrapr, c1;
uTemp ← T, NZeroBr, GOTO[LoadGC], c2;

LGCRetTrapr:
T ← uTemp, L3Disp, c1, at[L2.LGCRetTrapr,10,LoadGCRets];
TT ← UvPCpage, L2 ← L2.TRAPStashr, BRANCH[XTa, XTb], c2;
XTa: L1←0, GOTO[StashPCa], c3;
XTb: L1←0, GOTO[StashPCa], c3;


{****************************************************************************
Xfer Page Faults:
Entry:
Low VA in Q
L3 tells where high VA is;
Exit:
TT has page
returns to Xfer’s Trap handler
****************************************************************************}
XFRFault: Rx ← pFault, L3Disp, GOTO[XFFixVA], c1, at[L1r.XFRFault,10,RFixForTrap];

XFWFault: Rx ← pFault, L3Disp, GOTO[XFFixVA], c1, at[L1w.XFWFault,10,WFixForTrap];
XFFixVA: uFaultParm0 ← Q, pop{pushed at R/WTrap}, DISP2[XFFormVA], c2;
XFFormVA: Q ← UvMDS, GOTO[XFFault], c3, at[L3.rhMDS.Q,4,XFFormVA];
Q ← rhTT, GOTO[XFFault], c3, at[L3.rhTT.Q,4,XFFormVA];

XFFault: uFaultParm1 ← Q, L3←L3.XFault, c1, at[L2.EVAllocr,10,AllocFaults];
L ← UvL, GOTO[XTrapFix], c2;

uFaultParm0 ← TT, c1, at[L2.EVAllocr,10,FrameFault];
GOTO[XFFormVA], c2;

AllocFault: pop{pushed at WTrap}, uFaultParm0 ← Q, c1, at[L1w.AllocFault,10,WFixForTrap];
Q ← UvMDS, L2Disp, c2;
uFaultParm1 ← Q, RET[AllocFaults], c3;

{****************************************************************************
LoadGC subroutine:
Entry:
preceeding two instructions are:
Map ← Q ← [rhMDS,globalFrameAddr], L2 ← ret, c1;
[] ← Q xor UvG, NZeroBr, L1 ← L1w.XFWFault, GOTO[LoadGC], c2;
Exit:
G, rhG, UvG set up
Q has low 16 bits of codebase (to be stored in UvC)
rhTT and TT have high bits of codebase (to be stored in UvChigh)
traps if page fault or odd codebase
returnee executed on c1
****************************************************************************}
LoadGC:
{db} G ← MD, rhG ← MD, XdwDisp, UrG ← G, CANCELBR[$, 1], c3;

MAR ← [rhG,Q+1], DISP2[LGCMapFix], c1, at[L0.LoadGCRead,10,WyMap];
LGCMapFix:
Rx ← G{map word}, CANCELBR[LGCMapFix1,0], c2, at[0, 4, LGCMapFix];
{db} Rx ← G{map word}, CANCELBR[LGCMapFix1,0], c2, at[1, 4, LGCMapFix];
Rx ← G{map word}, CANCELBR[LGCMapFix1,0], c2, at[3, 4, LGCMapFix];
{db} TT ← Q, CANCELBR[$,0], c2, at[2, 4, LGCMapFix];
Q ← MD{low codebase}, XLDisp, c3;

LoadGChigh:
MAR ← G ← [rhG, TT+2], BRANCH[$,LoadGCTrap,2], c1;
G ← G - 2, pRet2, CANCELBR[$,0], c2;
rhTT ← MD, TT ← MD, UvG ← TT, RET[LoadGCRets], c3;

LGCSameG:
MAR ← G ← [rhG, Q+0], CANCELBR[$,1], c1, at[L0.LGCSameG,10,WyMap];
Q ← UvC, L2Disp, c2;
rhTT ← TT ← UvChigh, RET[LoadGCRets], c3;

LGCMapFix1:
L0 ← L0.LoadGCRead, c3;
Noop, c1;
GOTO[WyMapFix], c2;

LoadGCTrap:
T ← sSwapTrap, CANCELBR[SetUdestAsParm,0], c2;

{****************************************************************************
StashPC subroutine:
Entry:
calling instruction executed on c2 and includes:
TT ← UvPCpage, L1 ← n, goto[StashPCn]; {n = 0,1,2}
uPCCross is -1 if UvPCpage might be one too small, 0 if UvPCpage is OK
Link1 has PC increment in low two bits
Link2 has return index
Exit:
byte PC computed and stored in L+1
rhTT has UvChigh
TT and Q smashed
returnee executed on c3
****************************************************************************}
StashPC0: Q ← UvC, GOTO[StashPCa], c3;
StashPC1: Q ← UvC, GOTO[StashPCa], c3;
StashPC2: Q ← UvC, GOTO[StashPCa], c3;

StashPCa: Xbus ← uPCCross, XRefBr, c1;
StashPCa1: Q ← TT - Q, L1Disp, BRANCH[StGood,StCross], c2;{Q←word offset to page}

StGood: TT ← 0FF and PC, BRANCH[StLT2, StEQ2, 1], c3;

StLT2: TT ← TT + Q, GOTO[StShift], c1;
StEQ2: TT ← TT + Q + 1, GOTO[StShift], c1;
StShift: TT ← LShift1 TT, SE ← pc16, c2;
TT ← TT+1, L1Disp, GOTO[StashPCb], c3;

StashPCb: MAR ← [rhL,L+1], L2Disp, BRANCH[St0, St1, 2], c1;
St0: MDR ← TT-1, rhTT ← UvChigh, RET[StashRets], c2;
St1: MDR ← TT, rhTT ← UvChigh, RET[StashRets], c2;

{no page carry and uPCCross#0 => UvPCpage must be advanced}
StCross: [] ← PC+1, PgCarryBr, CANCELBR[$, 3], c3;
Q ← UvC, BRANCH[$,StashPCa1], c1;
TT ← TT + 0FF + 1, c2;
uPCCross ← 0, GOTO[StashPCa], c3;

{****************************************************************************
GetLink subroutine:
Entry:
calling instruction executed on c1 and includes:
MAR ← [rhG, g]
T has link index
rhTT has UvChigh
Link2 has return index
Exit:
T has destination control link
L has caller frame
TOS saved in STK
TT and Q smashed
returnee executed on c1
****************************************************************************}
GetLink: TT ← UvC, push, L0←L0.CodeLinkRead, c2;
STK ← TOS, Xbus ← MD, XLDisp, pop, L1←L1r.XFRFault, c3;

Map ← [rhTT,TT-T-1], Q ← TT-T-1, BRANCH[FrameLinks,CodeLinks,2], c1;
FrameLinks: [] ← G-T-1, PgCrOvDisp, Xbus ← rhG{force rB = G}, c2;
TOS ← UvG, BRANCH[LinkOK,LinkMap,1], c3;

LinkOK: MAR ← [rhG,G-T-1], c1;
LinkOK1: L ← UvL, L2Disp, CANCELBR[$,0], c2;
LinkOK2: T ← MD, XDisp, RET[XMDSReadRets], c3;

LinkMap: Map ← Q ← [rhMDS,TOS-T-1], c1;
Noop, c2;
rhRx ← Rx ← MD, XRefBr, c3;

MAR ← [rhRx, Q+0], BRANCH[FLFix,$], c1;
L ← UvL, L2Disp, GOTO[LinkOK2], c2;
FLFix: GOTO[RyMapFix], c2;

CodeLinks: Noop, c2;
rhRx ← Rx ← MD, XRefBr, c3;

CodeLinkRead:
MAR ← [rhRx, Q+0], BRANCH[$,LinkOK1], c1, at[L0.CodeLinkRead,10,RyMap];
GOTO[RLyMapFix], c2;


{****************************************************************************
Alloc subroutine:
Entry:
calling instruction executed on c3
TOS has index
TT has u200
Exit:
rhL and UvL set up
T has UvL
Q has new frame L (VA)
TT has original TOS if trapping
PC is rotated left 1 bit
returns through L2 relative to AllocRets or AllocTraps
returnee executed on c1
****************************************************************************}

AllocSub:
Map ← Q ← [rhMDS,TOS+TT],L0←L0.AllocRead1, {Map AV} c1;
uTemp ← TOS, L1 ← L1w.AllocFault, c2;
{db} rhRx ← Rx ← MD, XdwDisp, c3;

AllocRead1:
MAR ← [rhRx,TOS+0], DISP2[AllocRMapFix], {ReadAV} c1, at[L0.AllocRead1,10,WyMap];
AllocRMapFix:
GOTO[WyMapFix], c2, at[0, 4, AllocRMapFix];
{db} GOTO[WyMapFix], c2, at[1, 4, AllocRMapFix];
GOTO[WyMapFix], c2, at[3, 4, AllocRMapFix];
{db} uBLTTemp ← Rx, c2, at[2, 4, AllocRMapFix];
TT ← MD, XDisp, c3;

Map ← Q ← [rhMDS,TT], DISP4[AV0,0C], {Map frame} c1;
AV0: L0 ← L0.AllocRead2, c2, at[0C,10,AV0];
{db} rhL ← MD, L ← MD, XdwDisp, c3;

AllocRead2:
MAR ← [rhL,TT+0], DISP2[AllocR2MapFix], {Read frame} c1, at[L0.AllocRead2,10,WyMap];
AllocR2MapFix:
Rx ← L, GOTO[WyMapFix], c2, at[0, 4, AllocR2MapFix];
{db} Rx ← L, GOTO[WyMapFix], c2, at[1, 4, AllocR2MapFix];
Rx ← L, GOTO[WyMapFix], c2, at[3, 4, AllocR2MapFix];
{db} Rx ← uBLTTemp, c2, at[2, 4, AllocR2MapFix];
UvL ← TT, TT ← MD, {no traps after here} c3;

MAR ← [rhRx,TOS+0], L2Disp, {Write AV} c1;
MDR ← TT, T ← UvL, RET[AllocRets] c2;

AV3: TOS ← RShift1 TT, GOTO[AV2a], c2, at[0F,10,AV0];
AV2: TOS ← RShift1 TT, GOTO[AV2a], c2, at[0E,10,AV0];
AV2a:
{db} TOS ← RShift1 TOS, Xbus ← rdw.x10, XDisp, GOTO[AllocRead1], c3;

AV1: T ← qFrameFault, L2Disp, c2, at[0D,10,AV0];
TT ← uTemp, RET[FrameFault], c3;

{****************************************************************************
XMDSRead subroutine:
Entry:
calling instruction executed on c1 and includes:
Map ← Q ← [mumble]
Link2 has return index
Exit:
T has memory data
XDisp pending on data in T
L1 smashed
returnee executed on c1
****************************************************************************}
XMDSRead:
L0 ← L0.XMStartRead, c2;
XMDSReadx:
rhRx ← Rx ← MD, XRefBr, c3;

XMStartRead:
MAR ← [rhRx,Q+0], BRANCH[XRxMapFix,XRMapOK], c1, at[L0.XMStartRead,10,RyMap];
XRxMapFix:
GOTO[RyMapFix], c2;

XRMapOK:
L2Disp, c2;
T ← MD, XDisp, RET[XMDSReadRets], c3;

{****************************************************************************
XMDSWrite subroutine:
Entry:
calling instruction executed on c1 and includes:
Map ← Q ← [mumble]
T has memory data
Link2 has return index
Exit:
returnee executed on c3
****************************************************************************}

XMDSWrite:
L0 ← L0.XMStartWrite, c2;
XMDSWritex:
{db} rhRx ← Rx ← MD, XdwDisp, c3;

XMStartWrite:
MAR ← [rhRx,Q+0], L2Disp, DISP2[XWxMapFix], c1, at[L0.XMStartWrite,10,WyMap];
XWxMapFix:
CANCELBR[WyMapFix, 0F], c2, at[0, 4, XWxMapFix];
{db} CANCELBR[WyMapFix, 0F], c2, at[1, 4, XWxMapFix];
CANCELBR[WyMapFix, 0F], c2, at[3, 4, XWxMapFix];
{db} MDR ← T, RET[XMDSWriteRets], c2, at[2, 4, XWxMapFix];

{
Fiala 16-May-86 9:38:54 Many edits for changes to map references on writes for 4MB storage.
September 3, 1982 2:33 PM: Sturgis: fix KFCB to use an 8 bit mask rather than a 6 bit mask in testing for the block op codes
20-Sep-82 17:24:55: fix DWDC bug at page cross
}