{File name:  Xfer.mc
 Description: Xfer and related opcodes,
AHL/JAC 21-Sep-87 15:04:46 set uGFI to 0 in trapping case as Trapping+2
AHL/JPM 20-Feb-87 10:39:31 Favor frame links over code links.
JPM 9-Jan-87 14:13:34 Fix bug in LGC (typo)
AHL/JPM 6-Jan-87 11:31:42 Changes for MDS relief
JPM 11-Feb-85 14:00:21 Separate stackP ← and push by one instr. (at DSKc)
JPM 3-Jan-85 15:29:46 Fix branch mask at XCe (mask top 3 bits)
JPM 11-Oct-84 14:04:04 Fix bug in rewritten StashPC routine (wrong-way branch)
JPM 10-Oct-84 12:12:45 Fix XFTrap branch (must now mask bit 12); changed StashPC routine to decrement PCpage
JPM 28-Sep-84 9:52:26 Use hardware to enable/disable interrupts (at @DI, @EI, @XE, and XFTrap)
JPM 11-Sep-84 13:35:25 Fix BRANCH mask after XWtOKDisp; fix allocation error
DEG 1-Sep-84 19:57:28 Add copyright notice.
JPM, 22-Jun-84 9:55:20, replace XRefBr at THx+1 by XDisp (using bit 12), replace XDirtyDisp by XWtOKDisp
HGM, 28-Nov-83  6:56:06, Dicentra version
HGM, 25-Nov-83 19:20:31, MesaIntBr on way to Reschedule (and lots of CANCLEBRs)
HGM, 25-Nov-83 19:20:31, Check c2 at TrapGo
HGM, 28-Sep-83  3:57:11, Dangling branch at LGCa
AXD 25-Oct-83 18:30:07 Rearrange LFC so that uXferType isn't at fZ = ←ib.
AXD 22-Sep-83 15:06:44 Don't use TOS in GLFrame.
AXD 17-Jun-83 12:03:30 new instruction set
RXJ 3-Aug-83 11:18:00
JGS March 5, 1982  12:02 PM Disable same G after RET trap fix
JGS January 26, 1982  4:00 PM XferTraps vs disabled for module
JGS January 22, 1982 XferTraps vs fsi last of page
JGS November 17, 1981  10:35 AM New Instruction Set
Last edited by JXF      February 11, 1981  1:54 PM: catch KFCB for Block Equal
Created by RXJ}

{ 	Copyright (C) 1981, 1982, 1983, 1984, 1985 by Xerox Corporation.  All rights reserved.}

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

{LoadGC returns - Link 2; relative to LGCRtn}
MacroDef[LGCr, at[#1,10,LGCRtn]];
Set[L2.LGCFrame,9];{1 mod 3};
Set[L2.LGCFr,0B];{3 mod 3};
Set[L2.XProc,0D]; {must be odd; same as XCode, AllocSub}


{AllocSub returns - Link 2}
MacroDef[Allocr, at[#1,10,AllocRtn]];
{Set[L2.XProc,0D]; {must be odd; same as XCode, LoadGC}}
Set[L2.AF,0C];

{XCode returns - Link 2}
MacroDef[XCoder, at[#1,10,XCodeRtn]];
{Set[L2.XProc,0D]; {must be odd; same as LoadGC, AllocSub}}
Set[L2.XFrame,0A];

{GetLink returns - Link 2; relative to GLRtn}
MacroDef[GLr, at[#1,10,GLRtn]];
Set[L2.LLKBLink,0];
Set[L2.RKIBLink,1];
Set[L2.RKDIBLink,3];
Set[L2.EFCLink,2];

{XMDSWrite returns - Link 2; relative to XWRtn}
MacroDef[XWr, at[#1,10,XWRtn]];
Set[L2.POSpc,5]; {also SPCr}
Set[L2.PI,6];
Set[L2.DSKLoop,7];
Set[L2.DSKStkp,8];

{XMDSRead returns - Link 2; relative to XRRtn}
MacroDef[XRr, at[#1,10,XRRtn]];
Set[L2.LSKStkp,9];
Set[L2.LSKLoop,0A];
Set[L2.XSource,0B];
Set[L2.XIndirect,0C];


{****************************************************************************
	LKB - Link Byte
****************************************************************************}

@LKB:	T ← ib, push{tos},					c1, opcode[172'b];
	PC ← PC + 1, push{destlo},					c2;
	TT ← STK, pop{tos},						c3;

	MAR ← [rhL, L+0], pop,						c1;
	MDR ← TT - T, IBDisp, GOTO[DISPNIonly],				c2;


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

@EFC0:	T ← 3, L2←L2.EFCnSpc, GOTO[EFCn],		c1, opcode[337'b];
@EFC1:	T ← 5, L2←L2.EFCnSpc, GOTO[EFCn],		c1, opcode[340'b];
@EFC2:	T ← 7, L2←L2.EFCnSpc, GOTO[EFCn],		c1, opcode[341'b];
@EFC3:	T ← 9, L2←L2.EFCnSpc, GOTO[EFCn],		c1, opcode[342'b];
@EFC4:	T ← 0B, L2←L2.EFCnSpc, GOTO[EFCn],		c1, opcode[343'b];
@EFC5:	T ← 0D, L2←L2.EFCnSpc, GOTO[EFCn],		c1, opcode[344'b];
@EFC6:	T ← 0F, L2←L2.EFCnSpc, GOTO[EFCn],		c1, opcode[345'b];
@EFC7:	T ← 11, L2←L2.EFCnSpc, GOTO[EFCn],		c1, opcode[346'b];
@EFC8:	T ← 13, L2←L2.EFCnSpc, GOTO[EFCn],		c1, opcode[347'b];
@EFC9:	T ← 15, L2←L2.EFCnSpc, GOTO[EFCn],		c1, opcode[350'b];
@EFC10:	T ← 17, L2←L2.EFCnSpc, GOTO[EFCn],		c1, opcode[351'b];
@EFC11:	T ← 19, L2←L2.EFCnSpc, GOTO[EFCn],		c1, opcode[352'b];
@EFC12:	T ← 1B, L2←L2.EFCnSpc, GOTO[EFCn],		c1, opcode[353'b];

EFCn:	TT ← UvPCpage, push, L1←1, CALL[StashPC1],			c2;
	rhT ← xtFC1, CANCELBR[EFCGetLink],				c3, SPCr[L2.EFCnSpc];

{****************************************************************************
	EFCB - External Function Call Byte
****************************************************************************}
@EFCB:	T ← ib + 1,						c1, opcode[354'b];
	TT ← UvPCpage, L1←2, push,					c2;
	Q ← UvC, L2←L2.EFCBSpc, GOTO[StashPCa],				c3;
	rhT ← xtFC2, T ← T + T + 1, CANCELBR[$],			c3, SPCr[L2.EFCBSpc];

EFCGetLink:
	MAR ← [rhG, G-GF.word], L2←L2.EFCLink, GOTO[GetLink],		c1;

{****************************************************************************
	LFC - Local Function Call
****************************************************************************}

@LFC:	T ← UvL, L2←L2.LFCSpc,					c1, opcode[355'b];
	TT ← UvPCpage, push, L1←3, CALL[StashPC3],			c2;
	rhT ← xtFC3, STK ← TOS, CANCELBR[$],			c3, SPCr[L2.LFCSpc];
	
	uSourceLo ← T,							c1;
	Rx ← XferType.lfc,						c2;
	uXferType ← Rx,							c3;
	
	TT ← ib, pop,							c1;
	TT ← TT LRot8, L2←L2.XProc,					c2;
	TT ← TT or ib, GOTO[SameG],					c3;


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

@SFC:	T ← STK, push, L2←L2.SFCSpc,				c1, opcode[356'b];
	TT ← UvPCpage, L1←1, CALL[StashPC1],				c2;
	STK ← Q ← TOS, rhT ← xtSFC1, CANCELBR[$],		c3, SPCr[L2.SFCSpc];

	Rx ← XferType.call,						c1;
	uXferType ← Rx, pop,						c2;
	TT ← UvL, L1←L1.Xfer,						c3;
	
	uSourceLo ← TT, pop,						c1;
	uDestHi ← TT ← Q, pop,						c2;
SFCa:	uDestLo ← T, YDisp, GOTO[XFER],					c3;


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

@RET:	MAR ← [rhL,L-LF.word], L0←0,				c1, opcode[357'b];
	Rx ← UvPCpage, CANCELBR[$,0],					c2;
	TT ← MD{fsi}, uRetPChi ← Rx,					c3;

RETa:	T ← PC LShift1, Cin←pc16,					c1;
	UreturnPC ← T, L0Disp,						c2;
	Rx ← UvC, BRANCH[RETb, AFa],					c3;

RETb:	uRetC ← Rx, Rx ← XferType.ret,					c1;
	Ufsi ← TT, TT ← 0,						c2;
	uSourceLo ← TT,							c3;

	MAR ← [rhL,L-LF.returnLink], push, L1←L1.Xfer,			c1;
	rhT ← xtRET, STK ← TOS, CANCELBR[$,0],				c2;
	T ← MD, uXferType ← Rx, pop, XDisp, GOTO[XFER],			c3;


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

@LLKB:	T ← ib + 1, push, L2←L2.LLKBLink,			c1, opcode[167'b];
	STK ← TOS, push, PC ← PC + 1, L1←L1.Pop2Dec2, 			c2;
LLKBa:	rhTT ← UvGhigh,							c3;

	MAR ← [rhG,G-GF.word],						c1;
	TT ← UvG, CANCELBR[$,0],					c2;
	T ← T + T + 1, Xbus ← MD, XLDisp, GOTO[GLd],			c3;
	
	STK ← T, CANCELBR[$,0F],			     c1, GLr[L2.LLKBLink];
	TOS ← TT, push, fZpop, IBDisp, GOTO[DISPNIonly],		c2;


{****************************************************************************
	RKIB - Read Link Indirect Byte
****************************************************************************}

@RKIB:	T ← ib + 1, push, L2←L2.RKIBLink,			c1, opcode[170'b];
	STK ← TOS, push, PC ← PC + 1, L1←L1.Pop2Dec2, GOTO[LLKBa],	c2;

	Map ← Q ← [rhTT, T], CANCELBR[$,0F],		     c1, GLr[L2.RKIBLink];
	pop, L1←L1.PopDec2, GOTO[RLMpc3],				c2;


{****************************************************************************
	RKDIB - Read Link Double Indirect Byte
****************************************************************************}

@RKDIB:	T ← ib + 1, push, L2←L2.RKDIBLink,			c1, opcode[171'b];
	STK ← TOS, push, PC ← PC + 1, L1←L1.Pop2Dec2, GOTO[LLKBa],	c2;

	Map ← Q ← [rhTT, T], CANCELBR[$,0F],		    c1, GLr[L2.RKDIBLink];
	pop, L1←L1.Pop2Dec2, GOTO[RDLMc3],				c2;


{****************************************************************************
	PO - Port Out
****************************************************************************}

@POR:	PC ← PC - 1, L2←L2.POSpc, GOTO[POa],		c1, at[0E,10,ESC0n];

@PO:	PC ← PC - 1, L2←L2.POSpc,			c1, at[0D,10,ESC0n];
POa:	TT ← UvPCpage, L1←2, CALL[StashPC2],				c2;
	TT ← STK, L0←L0.XWrite, pop, CANCELBR[$],	c3, SPCr[L2.POSpc];

	Map ← Q ← [rhMDS,TT], L1←L1.Xfer, pop,				c1;
	T ← UvL, CALL[XWritex],						c2;
	Q ← TT + 1, rhT ← xtSFC2, 			c3, XWr[L2.POSpc];

	Map ← Q ← [rhMDS, Q + 1], L2←L2.EFCLink,			c1;
	Rx ← XferType.port, GOTO[GLe],					c2;
	

{****************************************************************************
	PI - Port In
****************************************************************************}

@PI:	T ← 0, L1←L1.PopDec2, push{tos},			c1, at[0C,10,ESC0n];
	rhTT ← UvMDS, push{dest},					c2;
	Rx ← STK{dest}, push{source}, L2←L2.PI,				c3;

	Map ← [rhTT,Rx], TT ← STK{source}, pop{dest},			c1;
	Q ← Rx, pop{tos}, L0←L0.XWrite, CALL[XWritex],			c2;
	T ← TT, ZeroBr,						c3, XWr[L2.PI];

	TOS ← STK, pop, BRANCH[PIa,IBDispOnly],				c1;
PIa:	Q ← Q + 2, push,						c2;
	L1←L1.Dec2,							c3;
	
	Map ← [rhMDS, Q],						c1;
	L0←L0.W, GOTO[WMpc3],						c2;

{****************************************************************************
	KFCB - Kernel Function Call Byte
****************************************************************************}

@KFCB:	T ← ib, L2←L2.KFCBSpc,					c1, opcode[360'b];
	TT ← UvPCpage, L1←2, push, CALL[StashPC2],			c2;
	T ← T + T + 1, rhT ← xtFC2,  CANCELBR[$],		c3, SPCr[L2.KFCBSpc];

	Rx ← XferType.call, STK ← TOS, pop,				c1;
KFCBa:	TOS ← LShift1 0FF, SE ← 1,					c2;
	rhTT ← UvMDS,							c3;

	Map ← Q ← [rhMDS, TOS + T], L2←L2.EFCLink,			c1;
	TT ← UvL, GOTO[GLe],						c2;


{****************************************************************************
	AF - Allocate frame
****************************************************************************}

@AF:	UrL ← L, L ← rhL, pop,					c1, at[0A,10,ESC0n];
	UrLHi ← L, push, L0←1,						c2;
	PC ← PC - 1, GOTO[RETa],					c3;

AFa:	uRetC ← Rx, L2←L2.AF,						c1;
	Rx ← UvPCpage, Cin←pc16,					c2;
	uRetPChi ← Rx,							c3;

	rhT ← xtAF,							c1;
	T ← 0FF + 1,							c2;
	L1←L1.Xfer,							c3;

	Map ← Q ← [rhMDS, T + TOS], L1←L1.Xfer,	 CALL[AllocSub],	c1;

	rhL ← UrLHi,						c3, Allocr[L2.AF];

	TOS ← TT,							c1;
	L ← UrL, IBDisp, GOTO[NegNI],					c2;


{****************************************************************************
	FF - Free frame
****************************************************************************}

@FF:	Map ← uFrame ← Q ← [rhMDS, TOS], L1←L1.Dec2,		c1, at[0B,10,ESC0n];
	L0←L0.FF,							c2;
	rhRx ← Rx ← MD, XWtOKDisp,					c3;

	MAR ← [rhRx, Q-LF.word], BRANCH[FFMUD,$,0D],		c1, WMFRet[L0.FF];
	Q ← 0FF, CANCELBR[$,0],						c2;
	TT ← MD and Q,							c3;

	Map ← [rhMDS, Q + 1], L2←1,					c1;
	GOTO[Freex],							c2;

FFb:	MAR ← [rhRx, Q+0], GOTO[Wb],					c1;

FFMUD:	CANCELBR[WMapFix,0],						c2;


{****************************************************************************
	DI - Disable Interrupts
****************************************************************************}

@DI:	T ← uWDC, ClrIE,					c1, at[0,10,ESC1n];
	T ← T+1, PgCarryBr,						c2;
	uWDC ← T, BRANCH[DIa, DIb],					c3;

DIa:	GOTO[IBDispOnly],						c1;

DIb:	T ← sInterruptError, GOTO[Trapc2],				c1;


{****************************************************************************
	EI - Enable Interrupts
****************************************************************************}

@EI:	T ← uWDC, ZeroBr,					c1, at[1,10,ESC1n];
	T ← T - 1, ZeroBr, BRANCH[EIa, EIb],				c2;
EIa:	uWDC ← T, BRANCH[EIc, EId],					c3;
EIb:	uWDC ← T, CANCELBR[DIb,1],					c3;

EIc:	GOTO[IBDispOnly],						c1;
EId:	SetIE, GOTO[IBDispOnly],					c1;

 
{****************************************************************************
	DSK - Dump Stack
****************************************************************************}

@DSK:	Q ← UvL, L1←L1.Dec2,					c1, at[0,10,ESC2n];
	Q ← Q + ib, L2←0,						c2;
	Rx ← State.word,						c3;

DSKg:	T ← UBrkByte,							c1;
	T ← T LRot8, L2Disp,						c2;
	UBrkByte ← 0, BRANCH[DSKf, PSSf],				c3;

DSKf:	TT ← ~ErrnIBnStkp,						c1;
	TT ← TT and 0F, L2←L2.DSKStkp,					c2;
	T ← T or TT,							c3;

	Map ← Q ← [rhMDS, Q+Rx], CALL[XWrite],				c1;
	T ← TT + 4, NibCarryBr,					c3, XWr[L2.DSKStkp];

	Q ← Q - State.word, BRANCH[DSTa, DSTb],				c1;
DSTa:	stackP ← TT ← TT + 2, GOTO[DSKc],				c2;
DSTb:	stackP ← TT ← 0E, GOTO[DSKc],					c2;

DSKc:	Q ← Q + TT, L2←L2.DSKLoop,					c3;

	Map ← Q ← [rhMDS, Q - 1], push,					c1;
DSKd:	T ← STK, pop, CALL[XWritex],					c2;
	TT ← TT - 1, ZeroBr,					c3, XWr[L2.DSKLoop];

	Map ← Q ← [rhMDS, Q - 1], BRANCH[DSKd, DSKe],			c1;

DSKe:	PC ← PC + PC16, pop, IBDisp, GOTO[DISPNIonly],			c2;
	

{****************************************************************************
	LSK - Load Stack
****************************************************************************}

@LSK:	T ← UvL, L1←L1.Dec2,					c1, at[3,10,ESC2n];
	T ← T + ib, L2←L2.LSKStkp,					c2;
	TOS ← State.word,						c3;

	Map ← Q ← [rhMDS, TOS + T],					c1;
	stackP ← 1, L0←L0.XRead, CALL[XReadx],				c2;

	rhT ← TT LRot8, T ← TT + 1,				c1, XRr[L2.LSKStkp];
	T ← rhT, uPsbLink ← T,						c2;
	TT ← TT + 4, NibCarryBr,					c3;

	UBrkByte ← T, BRANCH[LSKa, LSKb],				c1;
LSKa:	TT ← TT and 0F, GOTO[LSKc],					c2;
LSKb:	TT ← 10, GOTO[LSKc],						c2;
LSKc:	T ← TT - 2, L2←L2.LSKLoop,					c3;

LSKf:	Map ← Q ← [rhMDS, Q-TOS], CALL[XRead],				c1;

	T ← T - 1, ZeroBr, push,				c1, XRr[L2.LSKLoop];
	STK ← TT, BRANCH[LSKd, LSKe],					c2;
LSKd:	TOS ← TOS xor ~TOS, GOTO[LSKf],					c3;

LSKe:	stackP ← uPsbLink,						c3;

	PC ← PC + PC16,							c1;
	TOS ← STK, pop, IBDisp, GOTO[DISPNIonly],			c2;


{****************************************************************************
	XF - XFER and Free
****************************************************************************}

@XF:	MAR ← [rhL, L-LF.word],					c1, at[2,10,ESC2n];
	rhT ← xtXF, CANCELBR[$,0],					c2;
	T ← MD, L2←L2.XSpc, GOTO[XEb],					c3;


{****************************************************************************
	XE - XFER and Enable
****************************************************************************}

@XE:	T ← uWDC, ZeroBr,					c1, at[1,10,ESC2n];
	T ← T - 1, rhT ← xtX, BRANCH[XEa, $],				c2;
	uWDC ← T, GOTO[DIb],						c3;

XEa:	uWDC ← T, ZeroBr, L2←L2.XSpc,					c3;
XEb:	PC ← PC - 1, BRANCH[XEc, XEd],					c1;
XEc:	TT ← UvPCpage, L1←3, CALL[StashPC3],				c2;
XEd:	TT ← UvPCpage, L1←3, SetIE, CALL[StashPC3],			c2;
	Ufsi ← T, CANCELBR[$],					c3, SPCr[L2.XSpc];

	TT ← UvL, L1←L1.Xfer,						c1;
	T ← TT + ib + 1, L0←L0.XRead,					c2;
	rhTT ← UvMDS,							c3;

	Map ← Q ← [rhMDS, T - 1], L2←L2.XSource,			c1;
	uFrame ← TT, CALL[XReadx],					c2;
	
	Map ← Q ← [rhMDS, T + 1], L2←L2.EFCLink,		c1, XRr[L2.XSource];
	Rx ← XferType.xfer, GOTO[GLe],					c2;



{****************************************************************************
	BRK - BreakPoint
****************************************************************************}

@BRK:	T ← UBrkByte, ZeroBr, push,				c1, opcode[75'b];
	STK ← TOS, pop, BRANCH[BRKa, BRKb],				c2;
BRKb:	G ← 0, GOTO[Trapc1],						c3;

BRKa:	UBrkByte ← 0,							c3;

BRKc:	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:
	T and uDestHi 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 enters at one of:
		XferFrame, XferProc1, XferIndirect, XferProc3
****************************************************************************}
XFER:	Map ← Q ← [rhMDS, T], uDestLo ← T, DISP4[XferFrame,0C],	c1, GLr[L2.EFCLink];


{ ********* Frame link ********* }
XferFrame:
	rhTT ← GFTHi, [] ← Q, ZeroBr,				c2, at[0C,10,XferFrame];
	L ← MD, rhL ← MD, XWtOKDisp, BRANCH[$,ControlTrap],		c3;

XFStartRead:
	MAR ← [rhL, Q-LF.globalLink], BRANCH[XFMUD,XFMOK,0D],		c1;
	MAR ← [rhL, Q-LF.globalLink], BRANCH[XFMUD,XFMOK,0D],	c1, WMFRet[L0.Xfer];
XFMUD:	Rx ← L, CANCELBR[WMapFix,0],					c2;

XFMOK:	T ← UvL, CANCELBR[$,0],						c2;
	T ← MD {global link}, uFrame ← T, L2 ← L2.XFrame,		c3;

	MAR ← L ← [rhL, Q-LF.pc], {fix L in LGC subroutine}		c1;
	TOS ← Q, CANCELBR[$,0],						c2;
	TT ← MD {pc}, GOTO[LGC],					c3;

	UvL ← TOS,						c1, XCoder[L2.XFrame];
	uPCCross ← 0,							c2;
	Q ← T - 1, Xbus ← rhT, XDisp,					c3;

	Map ← [rhMDS, T], L2 ← 8, push, DISP4[XFTrap,8],		c1;
XFTrap:	Rx ← Rx + 1,						c2, at[8,10,XFTrap];
	uWDC ← Rx, ClrIE, GOTO[XPEnd],					c3;
XFCall:	GOTO[XferDone],						c2, at[0A,10,XFTrap];
XFRet:	TT ← Ufsi and Q, L2←0, GOTO[Freex,0],			c2, at[0B,10,XFTrap];
XFCalI:	T ← uSourceLo, push, GOTO[XPSD],			c2, at[0E,10,XFTrap];
XFRetI:	T ← uSourceLo, push, GOTO[XPSD],			c2, at[0F,10,XFTrap];

{ ********* Indirect link ********* }
XferIndirect:
	T ← rhT,						c2, at[0E,10,XferFrame];
	T ← T or 4, L2←L2.XIndirect, {set indirect xfer bit}		c3;

	Map ← Q ← [rhMDS, Q+1], L0←L0.XRead,				c1;
	rhT ← T LRot0, GOTO[XReadx],					c2;

	MAR ← [rhRx, Q-1],					c1, XRr[L2.XIndirect];
	T ← UvL, CANCELBR[$,0],						c2;
	T ← MD, uFrame ← T, XDisp,					c3;

	Map ← Q ← [rhMDS, T], DISP4[XferFrame,0C],			c1;



{ ********* Old Procedure descriptor ********* }
XferProc1:
	rhTT ← GFTHi, Q ← T-1, ZeroBr,				c2, at[0D,10,XferFrame];
	rhRx ← Rx ← MD, XRefBr, BRANCH[$,UnboundTrap],			c3;

	MAR ← [rhRx, Q-GF.word], L0←L0.XGfi, BRANCH[XOPa,XOPb],	c1, RMFRet[L0.XGfi];
XOPa:	CANCELBR[RMapFix,0],						c2;
XOPb:	T ← ~3, L2←L2.XProc, CANCELBR[$,0],				c2;
	T ← MD and T, GOTO[LGC],					c3;



{ ********* New Procedure descriptor ********* }
XferProc3:
	T ← T and ~3, ZeroBr, L2←L2.XProc,			c2, at[0F,10,XferFrame];
	rhTT ← GFTHi, BRANCH[XNPa,XNPb],				c3;

XNPa:	Map ← Q ← [rhTT, T], GOTO[LGCx],				c1;
XNPb:	T ← sUnbound, GOTO[UBTa],					c1;


XAlloc:	Map ← Q ← [rhMDS, T or ib], CALL[AllocSub],		c1, XCoder[L2.XProc];

	uPCCross ← 0,						c3, Allocr[L2.XProc];

	MAR ← Q ← [rhL, Q-LF.globalLink],				c1;
	MDR ← TOS, L ← Q + LF.globalLink, CANCELBR[$,0],		c2;
	UvL ← TT, Xbus ← rhT, XDisp, push,				c3;

XPEnd:	MAR ← [rhL,L-LF.returnLink], L2 ← 8, DISP4[XPTrap,8],		c1;
XPTrap:	MDR ← uSourceLo, CANCELBR[XTrap,0],		c2, at[8,10,XPTrap];
XPCall:	MDR ← uSourceLo, CANCELBR[XferDone,0],		c2, at[0A,10,XPTrap];
XPRet:	MDR ← uSourceLo, CANCELBR[XPFree,0],		c2, at[0B,10,XPTrap];
XPCalI:	MDR ← T ← uSourceLo, push, CANCELBR[XPSD,0],	c2, at[0E,10,XPTrap];
XPRetI:	MDR ← T ← uSourceLo, push, CANCELBR[XPSD,0],	c2, at[0F,10,XPTrap];

XTrap:	T ← UrG, ZeroBr,						c3;

	BRANCH[STPa, STPb],						c1;
STPb:	GOTO[XferDone],							c2;
STPa:	Noop,								c2;
STPc:	T ← T - 1, Ybus ← T, YDisp,					c3;

	MAR ← [rhL, L+T], DISP4[STPd],					c1;
	MDR ← uTrapParm0, CANCELBR[XferDone,0],			c2, at[1,10,STPd];
	MDR ← uTrapParm1, CANCELBR[STPc,0],			c2, at[2,10,STPd];
	MDR ← uTrapParm2, CANCELBR[STPc,0],			c2, at[3,10,STPd];

XPSD:	TT ← uDestLo, push,						c3;

	STK ← T, pop, L2Disp,						c1;
	STK ← TT, pop, BRANCH[XferDone,XPFree,0E],			c2;
XPFree:	Q ← 0FF,							c3;

	{map av item}
Free:	Map ← [rhMDS, Q + 1], GOTO[XFRet],				c1;

Freex:	rhRx ← Rx ← MD, XWtOKDisp,					c3;

	{store new head, fetch old head}
	MAR ← [rhRx,TT+0], L0←L0.Free, BRANCH[FreeMUD,FreeMOK,0D],	c1;
	MAR ← [rhRx,Q+0], BRANCH[XXXXX,XXXX,1],			c1, WMFRet[L0.Free];
FreeMUD:
	Q ← TT + Q + 1, GOTO[WMapFix],					c2;

XXXXX:	GOTO[XXXXX],							c*;
XXXX:	GOTO[FreeMO2],							c2;

FreeMOK:
	Q ← TT + Q + 1,							c2;
FreeMO2:
	T ← MD{old list head},						c3;

	MAR ← [rhRx, Q+0],						c1;
	MDR ← Rx ← uFrame,						c2;
	Noop,								c3;

	{map old frame}
	Map ← Q ← [rhMDS,Rx],						c1;
	L2Disp,								c2;
	rhRx ← Rx ← MD, BRANCH[$, FFb],					c3;

	{store old list head}
	MAR ← [rhRx,Q+0],						c1;
	MDR ← T,							c2;

XferDone:
	TT ← RShift1 uXTS, XLDisp,					c3;

XTail:	uPCValid ← PC xor ~PC, BRANCH[$, XferTrap, 2],			c1;
	uXTS ← TT, IBDisp, GOTO[SLa],					c2;

XferTrap:
	TT ← TT LShift1, SE ← 1, uXTS ← TT,				c2;
	Rx ← uXferType,							c3;

	MAR ← [rhG, G-GF.word],						c1;
	T ← 30, CANCELBR[$,0],						c2;
	Xbus ← MD, XDisp, uTrapParm2 ← Rx,				c3;

XTc:	[] ← T and ~ErrnIBnStkp, ZeroBr, BRANCH[XTa, XTb, 0D],		c1;
XTa:	uXTS ← TT, IBDisp, CANCELBR[SLa,1],				c2;
XTb:	[] ← PC - PC16, PgCarryBr, pop, BRANCH[XTd, XTe],		c2;
XTd:	T ← sXferTrap, Cin←pc16, CANCELBR[XTg, 1],			c3;
XTe:	T ← sXferTrap, Cin←pc16, BRANCH[XTf, XTg],			c3;

XTf:	uPCCross ← TT xor ~TT, GOTO[XTh],				c1;
XTg:	GOTO[XTh],							c1;
XTh:	TT ← uDestHi,							c2;
	uTrapParm1 ← TT,						c3;
	
	TT ← uDestLo,							c1;
	uTrapParm0 ← TT,						c2;
	G ← 3, GOTO[Trapc1],						c3;

{****************************************************************************
LoadGC subroutine:
    Entry:
	rhTT has GFTHi
	T has gfi
    Exit:
	G, rhG, UvG, UvGhigh, UvC, UvChigh, PC, rhPC, UvPCpage set up
	traps if page fault or odd codebase
	returnee executed on c1
****************************************************************************}
LGC:	Map ← Q ← [rhTT, T],						c1;
LGCx:	[] ← Q xor uGFI, ZeroBr, L0←L0.GFTRead,				c2;
	rhRx ← Rx ← MD, XRefBr, IBPtr ← 1, BRANCH[$,SameG],		c3;

	MAR ← [rhRx, Q+GFTE.codeLo], BRANCH[LGCa,LGCb],		c1, RLMFRet[L0.GFTRead];
LGCa:	CANCELBR[RLMapFix,0],						c2;
LGCb:	uTT ← PC ← TT, CANCELBR[$,0],					c2;
	T ← MD{low codebase}, XLDisp, uGFI ← T,				c3;

	MAR ← [rhRx, Q+GFTE.globalHi], BRANCH[$,CodeTrap,2],		c1;
	PC ← RShift1 PC, SE ← 0, ZeroBr, CANCELBR[$,0],			c2;
	rhTT ← TT ← MD{high global frame}, BRANCH[XCa,XCb],		c3;

XCb:	T ← sUnbound, GOTO[UBTa],					c1;
XCa:	MAR ← Rx ← [rhRx, Q+GFTE.globalLo], XC2npcDisp,			c1;
	UvGhigh ← TT, BRANCH[xcOdd,xcEven,0E],				c2;
xcOdd:	Q ← MD{low global frame}, GOTO[XMapG],				c3;
xcEven:	Q ← MD{low global frame}, Cin←pc16, GOTO[XMapG],		c3;

XMapG:	Map ← UvG ← [rhTT, Q],						c1;
	PC ← PC + T,							c2;
	G ← rhG ← MD, XRefBr, UvC ← T,					c3;

LGCe:	MAR ← [rhRx, Rx+GFTE.codeHi], BRANCH[LGCc,LGCd],		c1;
LGCc:	T ← qPageFault, CANCELBR[GMapFix,0],				c2;
LGCd:	T ← 0FF + 1, CANCELBR[$,0],					c2;
	rhTT ← TT ← MD{high codebase},					c3;

	MAR ← G ← [rhG, Q+0],						c1;
SGRet:	UvChigh ← TT, L ← L + 1 {for frame links},			c2;
XCode:	TT ← PC and ~0FF, L0←L0.XCode,					c3;

	Map ← UvPCpage ← [rhTT, TT],					c1;
	Q ← PC, Xbus ← ib,						c2;
	PC ← rhPC ← MD, XRefBr,						c3;

	MAR ← Q ← [rhPC, Q+0], Xbus ← uTT, XLDisp, BRANCH[XCd,XCe], c1, RMFRet[L0.XCode];
XCd:	Rx ← PC, CANCELBR[RCMapFix,3],					c2;
XCe:	Rx ← uWDC, L2Disp, BRANCH[xcE,xcO,0E],				c2;
xcE:	IB ← MD, PC ← Q, Cin←pc16, RET[XCodeRtn],			c3;
xcO:	IB ← MD, PC ← Q, IBPtr←1, RET[XCodeRtn],			c3;

SameG:	rhTT ← UvChigh, XC2npcDisp, CANCELBR[$,1],		c1, RLMFRet[L0.SameG];
	uTT ← TT, BRANCH[sgOdd,sgEven,0E],				c2;
sgOdd:	PC ← UvC, GOTO[sg],						c3;
sgEven:	PC ← UvC, Cin←pc16, GOTO[sg],					c3;

sg:	TT ← RShift1 TT, ZeroBr, IBPtr ← 1,				c1;
	PC ← PC + TT, BRANCH[sgX,sgY],					c2;
sgY:	GOTO[UnboundTrap],						c3;
sgX:	T ← 0FF + 1,							c3;

	TT ← UvChigh, GOTO[SGRet],					c1;

GMapFix:
	Xbus ← G LRot0, XwdDisp, L3←L3.rhTT.Q,				c3;

	Map ← [rhTT, Q], DISP2[GMapa],					c1;
GMapa:	MDR ← G or map.referenced, GOTO[GMapb],			c2, at[0,4];
	MDR ← G or map.referenced, GOTO[GMapb],			c2, at[1,4,GMapa];
	MDR ← G or map.referenced, GOTO[GMapb],			c2, at[2,4,GMapa];
	uGFI ← 0, L1Disp, DISP4[RTrap],				c2, at[3,4,GMapa];
GMapb:	Xbus ← 1, XDisp, GOTO[LGCe],					c3;


{****************************************************************************
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
****************************************************************************}

CodeTrap:
	T ← sCodeTrap, CANCELBR[$,0],					c2;
	TT ← uGFI,							c3;

	G ← 1, GOTO[THz],						c1;
	
ControlTrap:
	T ← sControlTrap, CANCELBR[$,0F],				c1;
	TT ← uSourceLo,							c2;
	G ← 1, GOTO[TH],						c3;
	
UnboundTrap:
	T ← sUnbound, CANCELBR[$,1],					c1;
UBTa:	TT ← uDestLo,							c2;
	Rx ← uDestHi,							c3;

	G ← 2,								c1;
	uTrapParm1 ← Rx,						c2;
	Noop,								c3;

TH:	Noop,								c1;
THz:	TOS ← UvL, L3←L3.XTrap,						c2;
THa:	Xbus ← rhT, XwdDisp,						c3;

	Map ← [rhMDS, TOS], DISP2[THb],					c1;
THb:	Q ← 0, GOTO[THc],					c2, at[0,4,THb];
	Q ← 1, GOTO[THc],					c2, at[1,4,THb];
	Q ← 2, GOTO[THc],					c2, at[2,4,THb];
	Q ← 3, GOTO[THc],					c2, at[3,4,THb];
THc:	L ← rhL ← MD,							c3;

	MAR ← L ← [rhL, TOS+0],						c1;
	Xbus ← rhT, XLDisp,						c2;
	uTrapParm0 ← TT, BRANCH[THx, THy, 1],				c3;

THy:	push,								c1;
	push,								c2;
	Noop,								c3;

THx:	MAR ← [rhL, L-LF.pc],						c1;
	Xbus ← rhT, XDisp, CANCELBR[$,0],				c2;
	PC ← MD, L3Disp, BRANCH[THd, THe, 7],				c3;

TrapGo:	uPCValid ← 0, CANCELBR[$],			c3, SPCr[L2.TRAPSpc];
	rhT ← xtTrap, T ← T + T + 1, GOTO[Trapping],			c1;

THd:	MAR ← [rhL, L-LF.pc], CANCELBR[$,1],				c1;
	MDR ← PC - Q, L3Disp, CANCELBR[$,0],				c2;
	uPCValid ← 0, BRANCH[$, XferFault],				c3;

	rhT ← xtTrap, T ← T + T + 1,					c1;
Trapping:
	UrG ← G,							c2;
	Rx ← XferType.trap,						c3;

	uGFI ← 0{disable SameG}, GOTO[KFCBa],				c1;

FaultGo:
	uPCValid ← 0, CANCELBR[$,1],			c3, SPCr[L2.FAULTSpc];
XferFault:
	Rx ← pFault, GOTO[SaveRegs],					c1;

THe:	Q ← uRetC, XC2npcDisp, L2←L2.TRAPSpc, BRANCH[THj, THk],	c1;
THj:	PC ← RShift1 UreturnPC, SE ← 0, XLDisp, BRANCH[THf, THg, 0E],	c2;
THk:	PC ← RShift1 UreturnPC, SE ← 0, XLDisp, BRANCH[THf, THg, 0E],	c2;
THf:	UvC ← Q, Cin←pc16, BRANCH[THh, THi, 2],				c3;
THg:	UvC ← Q, BRANCH[THh, THi, 2],					c3;

THh:	TT ← uRetPChi, GOTO[THl],					c1;
THi:	TT ← uRetPChi, Cin←pc16, GOTO[THl],				c1;
THl:	uGFI ← 0{disable SameG}, L1←0, GOTO[StashPC0],			c2;


{****************************************************************************
Xfer Page Faults:
    Entry:
	push from R/WTrap
	L3 tells where VA is;
    Exit:
	returns to Xfer's Trap handler
****************************************************************************}
XPF:	Rx ← pFault, L3Disp, GOTO[XPFa],	c1, at[L1.Xfer,10,RTrapFix];
	Rx ← pFault, L3Disp, GOTO[XPFa],	c1, at[L1.Xfer,10,RLTrapFix];
	Rx ← pFault, L3Disp, GOTO[XPFa],	c1, at[L1.Xfer,10,WTrapFix];

XPFa:	TOS ← UvL, L3Disp, BRANCH[XPFb, XPFc, 2],			c2;
XPFb:	uFaultParm0 ← Q, BRANCH[XPFd, XPFe, 1],				c3;
XPFc:	uFaultParm0 ← TT, BRANCH[XPFd, XPFe, 1],			c3;

XPFd:	Q ← rhMDS, L3←L3.XFault, GOTO[XPFf],				c1;
XPFe:	Q ← rhTT, L3←L3.XFault, GOTO[XPFf],				c1;
XPFf:	uFaultParm1 ← Q, pop, GOTO[THa],				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 large, 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 UvGhigh
	Rx has 0
	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;
StashPC3:	Q ← UvC, GOTO[StashPCa],				c3;

StashPCa:	Rx ← 0, Xbus ← uPCCross, XRefBr,			c1;
StashPCa1:	Q ← TT - Q, L1Disp, BRANCH[StGood,StCross],		c2;

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-LF.pc], L2Disp, BRANCH[St0, St1, 2],		c1;
St0:	MDR ← TT-1, rhTT ← UvGhigh, MesaIntBr, RET[SpcRtn],		c2;
St1:	MDR ← TT, rhTT ← UvGhigh, MesaIntBr, RET[SpcRtn],		c2;

{page carry and uPCCross#0 => UvPCpage must be decremented}
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.word]
	T has 2*index + 3
	rhTT has UvGhigh
	Link2 has return index
    Exit:
	T and uDestHi have destination control link
	L has caller frame
	TOS saved in STK
	TT and Q smashed
	returnee executed on c1
****************************************************************************}

GetLink:
	TT ← UvG, L1←L1.Xfer, CANCELBR[$,0],				c2;
	Rx ← Rx + 1, Xbus ← MD, XLDisp, STK ← TOS, pop,			c3;

GLd:	Map ← Q ← [rhTT, TT-T-1], BRANCH[GLFrame,GLCode,2],		c1;
GLFrame:TT ← UvL,							c2;
GLe:	rhRx ← Rx ← MD, XRefBr, uXferType ← Rx,				c3;

	MAR ← [rhRx, Q+1], L0←L0.CLRead, BRANCH[$,GLa],		c1, RLMFRet[L0.CLRead];
	CANCELBR[RLMapFix,0],						c2;
GLa:	uSourceLo ← TT, CANCELBR[$,0],					c2;
GLf:	rhTT ← TT ← MD,							c3;

	MAR ← [rhRx, Q+0], L1←L1.Xfer,					c1;
GLc:	uDestHi ← TT, L2Disp, CANCELBR[$,0],				c2;
	T ← MD, XDisp, RET[GLRtn],					c3;

GLCode:
{This code takes advantage of two facts:
  1) UvC is always even (i.e. the LSB is 0);
  2) DRShift1 and DLShift1 are not symmetric, so the shifted bit is inverted.
 Thus TT acquires the value (UvC+1).} 
	TT ← DRShift1 UvC,						c2;
	rhTT ← UvChigh, TT ← DLShift1 TT,				c3;

	Map ← Q ← [rhTT, TT-T], GOTO[GLFrame],				c1;


{****************************************************************************
Alloc subroutine:
    Entry:
	calling instruction executed on c1
	Map fetch started on AV
    Exit:
	rhL set up
	TOS has uGFI
	Q, TT has new frame L (VA)
	PC incremented for Xfer
	returns through L2 relative to AllocRtn
	returnee executed on c1
****************************************************************************}

AllocSub:
	uFaultParm0 ← T ← Q, L0←L0.Alloc1,				c2;
	rhRx ← Rx ← MD, XWtOKDisp,					c3;

Alloc1:	MAR ← [rhRx, T+0], BRANCH[AllocMUD1,$,0D],	c1, WMFRet[L0.Alloc1];
	TOS ← uGFI,							c2;
	TT ← MD, XDisp, uRx ← Rx,					c3;

	Map ← Q ← [rhMDS, TT], DISP4[AV0,0C],				c1;
AV0:	PC ← PC + PC16, L0←L0.Alloc2,			c2, at[0C,10,AV0];
	rhL ← MD, L ← MD, XWtOKDisp,					c3;

	MAR ← [rhL, TT+0], BRANCH[AllocMUD2,$,0D],	c1, WMFRet[L0.Alloc2];
	Rx ← uRx,							c2;
	uTTemp ← TT, TT ← MD,						c3;

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

AV3:	TT ← RShift1 TT, GOTO[AV2a],			c2, at[0F,10,AV0];
AV2:	TT ← RShift1 TT, GOTO[AV2a],			c2, at[0E,10,AV0];
AV2a:	T ← RShift1 TT, Xbus ← 2, XDisp, GOTO[Alloc1],			c3;

AV1:	T ← qFrameFault,				c2, at[0D,10,AV0];
	Q ← 0FF, L3←L3.rhMDS.Q,						c3;

	Q ← Q and uFaultParm0, push, L3Disp, GOTO[XPFa],		c1;

AllocMUD1: GOTO[WMapFix],						c2;
AllocMUD2: Rx ← L, GOTO[WMapFix],					c2;

{****************************************************************************
XRead subroutine:
    Entry:
	calling instruction executed on c1 and includes:
		Map ← Q ← [mumble]
	Link2 has return index
    Exit:
	TT has memory data
	XDisp pending on data in T
	L1 smashed
	returnee executed on c1
****************************************************************************}

XRead:	Noop,								c2;
XReadx:	rhRx ← Rx ← MD, XRefBr,						c3;

XReady:	MAR ← [rhRx,Q+0], BRANCH[XRMUD,$],		c1, RMFRet[L0.XRead];
XReadz:	L2Disp, CANCELBR[$,0],						c2;
	TT ← MD, LOOPHOLE[mdok], RET[XRRtn],				c3;

XRMUD:	GOTO[RMapFix],							c2;


{****************************************************************************
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
****************************************************************************}

XWrite:	L0←L0.XWrite,							c2;
XWritex:
	rhRx ← Rx ← MD, XWtOKDisp,					c3;

	MAR ← [rhRx,Q+0], L2Disp, BRANCH[XWMUD,$,0D],	c1, WMFRet[L0.XWrite];
	MDR ← T, RET[XWRtn],						c2;
XWMUD:	Noop, CANCELBR[WMapFix, 0F],					c2;