{LispMatrix.mc
by cal 13-Dec-84 10:31:52
	
	(MATRIXMPY  M  N  K  A.MATRIX  B.MATRIX  C.MATRIX)
	    performs C.MATRIX ← A.MATRIX  *  B.MATRIX
		where A.MATRIX is a matrix of M rows by N columns
		and  B.MATRIX is a matrix of N rows by K columns
		and  C.MATRIX is a matrix of M rows by K columns

	the contents of A.MATRIX is A[m=0, n=0]
	the contents of A.MATRIX + 1 is A[m=0, n=1]
	.
	.
	the contents of A.MATRIX + N - 1 is A[m=0, n=N - 1]
	the contents of A.MATRIX + N is A[m=1, n=0]
	etc.


	has the following builtin 'sizes'
	alpha	size
	1		A[3,3]  B[3,3]  C[3,3]  M = 3, N = 3, K = 3
	2		A[4,4]  B[4,4]  C[4,4]  M = 4, N = 4, K = 4
	3		A[1,3]  B[3,3]  C[1,3]  M = 1, N = 3, K = 3
	4		A[3,3]  B[3,1]  C[3,1]  M = 3, N = 3, K = 1
	5		A[1,4]  B[4,4]  C[1,4]  M = 1, N = 4, K = 4
	6		A[4,4]  B[4,1]  C[4,1]  M = 4, N = 4, K = 1

 -- basically
	FOR m = 0 to M - 1
		FOR k = 0 to K - 1
			sum ← 0
			FOR n = 0 to N - 1
				sum ← sum + A[m, n] * B[n, k]
			NEXT n
		C[m, k] ← sum
		NEXT k
	NEXT m

	timing:	{ 25 + 1 * N + 10 * N↑2 + 8 * N↑3}
	3 x 3 x 3  ==  334 clicks  ~~  6000 per second
	4 x 4 x 4  ==  701 clicks  ~~  2850 per second
}

{	defs moved to MoreLispDefs.dfn
RegDef[rA, R, 6],{Rx}
RegDef[rB, R, 0],{TOS}
RegDef[rC, R, 1],{TOSH}

RegDef[rhrA, RH, 6],{Rx}
RegDef[rhrB, RH, 0],{TOS}
RegDef[rhrC, RH, 1],{TOSH}

RegDef[urAVlo, U, 02],	{Low VA of matrix A}
RegDef[urAVhi, U, 03],	{High VA of matrix A}
RegDef[urBVlo, U, 60],	{Low VA of matrix B}
RegDef[urBVhi, U, 05],	{High VA of matrix B}
RegDef[urCVlo, U, 06],	{Low VA of matrix C}
RegDef[urCVhi, U, 07],	{High VA of matrix C}
RegDef[uNinit, U, 08],	{Initial value of nCOUNT}
RegDef[uKinit, U, 0A],	{Initial value of kCOUNT}
RegDef[umCOUNT, U, 0B], {Current value of mCOUNT}
RegDef[ukCOUNT, U, 0C], {Current value of kCOUNT}
RegDef[unCOUNT, U, 36], {Current value of nCOUNT, when saved}
RegDef[udeltaA1, U, 31],	{-2(N-1)}
RegDef[udeltaB0, U, 33],	{+2K}
RegDef[udeltaB1, U, 35],	{-2(N-1)(K)+2}
RegDef[udeltaB2, U, 37],	{-2(N)(K)+2}
{RegDef[uTOSH, U, 1D],}
{RegDef[uTOS, U, 0D],}

Set[L0.delta0, 0],
Set[L0.delta1, 1],
Set[L0.delta2, 2],
Set[L0.deltaI, 3],

Set[L1.mxnotfirst, 1],
Set[L1.mxfirst, 2],
{Set[L1.matufn, 7],}

Set[ib.333, 1],
Set[ib.444, 2],
Set[ib.133, 3],
Set[ib.331, 4],
Set[ib.144, 5],
Set[ib.441, 6];
Set[L1.lm, 9];
Set[L1.matexit, 0A];
}

	
{@MATRIXMPY:
	Bank ← PolyBank,			c1;
	,					c2;
	CROSS[POLYcode],			c3;

	uTOS ← TOS,				c1, at[POLYcode];
	Ybus ← Q, YDisp,			c2;
	uTOSH ← TOSH, DISP4[misc3disp],		c3;
	
	end in bank 1 & 2}
	
	
	

	at[ib.333, 10, misc3disp]:
	MAR ← [rhS, S - 1], GOTO[mxmgo],	c1;	{For 3X3X3}

	at[ib.444, 10, misc3disp]:
	MAR ← [rhS, S - 1], GOTO[mxmgo],	c1;	{For 4X4X4}

	at[ib.133, 10, misc3disp]:
	MAR ← [rhS, S - 1], GOTO[mxmgo],	c1;	{For 3X1X3}

	at[ib.331, 10, misc3disp]:
	MAR ← [rhS, S - 1], GOTO[mxmgo],	c1;	{For 3X3X1}

	at[ib.144, 10, misc3disp]:
	MAR ← [rhS, S - 1], GOTO[mxmgo],	c1;	{For 4X1X4}

	at[ib.441, 10, misc3disp]:
	MAR ← [rhS, S - 1], GOTO[mxmgo],	c1;	{For 4X4X1}
	
	

mxmgo:	FloatNop, CANCELBR[$, 2],	c2;
	TT{Bhi} ← MD,			c3;	{Bhi is high VA of matrix B}

	urCVlo ← TOS,	L1 ← L1.lm,	c1;	{Save Clo in urCVlo}
	CALL[LFASaveRegsHere],		c2;

	S ← S + 4,			c1, at[L1.lm, 10, LFASaveRegsRet];
	urCVhi ← TOSH,			c2;	{Save Chi in urCVhi}
	urBVhi ← TT, 			c3;	{Save Bhi in urBVhi}

	MAR ← [rhS, S + 0],		c1;	{Point to BLo}
	S ← S - 2,			c2;
	Rx{Blo} ← MD,			c3;	{Blo is low VA of matrix B}

	MAR ← [rhS, S - 1],		c1;	{Point to Ahi}
	urBVlo ← Rx, CANCELBR[$, 2],	c2;	{Save Blo in urBVlo}
	TT{Ahi} ← MD,			c3;	{Ahi is high VA of matrix A}

	MAR ← [rhS, S + 0],		c1;	{Point to Alo}
	urAVhi ← TT,			c2;	{Save Ahi in urAVhi}
	TT{Alo} ← MD,			c3;	{Alo is low VA of matrix A}

	S ← S + 2, L1 ← L1.mxfirst,	c1;
	urAVlo ← TT,			c2;	{Save Alo in urAVlo}	
	TT ← 0FF + 1,		 	c3;	{set PPort to read}
	
	Q ← uPPsave,			c1;
	PPort ← Q and ~TT,		c2;
	Xbus ← ibNA, XDisp,		c3;

	DISP4[mxwhich, 0],		c1;
	
{===================================================================	
  setup for 3 x 3 x 3
 =================================================================== }

	at[ib.333, 10, mxwhich], 
	Q ← 3,				c2;	
	uNinit ← Q,			c3;	{uNinit=3}

	,			c1;	
	uKinit ← Q,			c2;	{uKini=3}
	umCOUNT ← Q,			c3;	{umCount=3}

	ukCOUNT ← Q,			c1;	{ukCount=3}
	unCOUNT ← Q,			c2;	{unCount=3}
	Q ← 4,				c3;	{2(N-1)}

	udeltaA1 ← Q,			c1;	{udeltaA1=4}
	Q ← 6,				c2;	{2K}	
	udeltaB0 ← Q,			c3;	{udeltaB0=6}

	Q ← 10'd,			c1;	{2(N-1)(K)-2}
	udeltaB1 ← Q,			c2;	{udeltaB1=10}
	Q ← 16'd,			c3;	{2(N)(K)-2}

	udeltaB2 ← Q, GOTO[mxmaps],	c1;	{udeltaB2=16}
	
	
{===================================================================	
  setup for 4 x 4 x 4
 =================================================================== }
	
	at[ib.444, 10, mxwhich], 
	Q ← 4,				c2;
	uNinit ← Q,			c3;	{uNinit=4}	

	,			c1;
	uKinit ← Q,			c2;	{uKinit=4}
	umCOUNT ← Q,			c3;	{umCOUNT=4}

	ukCOUNT ← Q,			c1;	{ukCOUNT=4}	
	unCOUNT ← Q,			c2;	{unCOUNT=4}
	Q ← 6,				c3;	{2(N-1)}

	udeltaA1 ← Q,			c1;	{udeltaA1=6}
	Q ← 8,				c2;	{2K}
	udeltaB0 ← Q,			c3;	{udeltaB0=8}

	Q ← 22'd,			c1;	{2(N-1)(K)-2}
	udeltaB1 ← Q,			c2;	{udeltaB1=22}
	Q ← 30'd,			c3;	{2(N)(K)-2}

	udeltaB2 ← Q, GOTO[mxmaps],	c1;	{udeltaB2=30}
	
{===================================================================	
  setup for 3x1x3
 =================================================================== }	
	
	at[ib.133, 10, mxwhich], 
	Q ← 3,				c2;
	uNinit ← Q,			c3;

	uKinit ← Q,			c1;
	unCOUNT ← Q,			c2;
	ukCOUNT ← Q,			c3;

	Q ← 1,				c1;
	umCOUNT ← Q,			c2;
	Q ← 4,				c3;

	udeltaA1 ← Q,			c1;	{udeltaA1 ← 2(N-1)}
	Q ← 6,				c2;
	udeltaB0 ← Q,			c3;	{udeltaB0 ← 2K}

	Q ← 10'd,			c1;
	udeltaB1 ← Q,			c2;	{udeltaB1 ← 2(N-1)(K)-2}
	Q ← 16'd,			c3;

	udeltaB2 ← Q, GOTO[mxmaps],	c1;	{udeltaB2 ← 2(N)(K)-2}
	
{===================================================================	
  setup for 3x3x1
 =================================================================== }		

	at[ib.331, 10, mxwhich], 
	Q ← 3,				c2;
	uNinit ← Q,			c3;

	,			c1;
	umCOUNT ← Q,			c2;
	unCOUNT ← Q,			c3;

	Q ← 1,				c1;
	ukCOUNT ← Q,			c2;
	uKinit ← Q,			c3;

	Q ← 4,				c1;
	udeltaB2 ← Q,			c2;	{udeltaB2 ← 2(N)(K)-2}
	udeltaA1 ← Q,			c3;	{udeltaA1 ← 2(N-1)}

	Q ← 2,				c1;
	udeltaB0 ← Q,			c2;	{udeltaB0 ← 2K}
	Q ← 2'd,			c3;

	udeltaB1 ← Q, GOTO[mxmaps],		c1;	{udeltaB1 ← 2(N-1)(K)-2}

	
{===================================================================	
  setup for 4x1x4
 =================================================================== }		

	at[ib.144, 10, mxwhich], 
	Q ← 4,				c2;
	uNinit ← Q,			c3;

	uKinit ← Q,			c1;
	unCOUNT ← Q,			c2;
	ukCOUNT ← Q,			c3;

	Q ← 1,				c1;
	umCOUNT ← Q,		c2;
	Q ← 6{2(N-1)},			c3;

	udeltaA1 ← Q,			c1;	{udeltaA1 ← 2(N-1)}
	Q ← 8{2K},			c2;
	udeltaB0 ← Q,			c3;	{udeltaB0 ← 2K}

	Q ← 22'd{2(N-1)(K)},		c1;
	udeltaB1 ← Q,			c2;	{udeltaB1 ← 2(N-1)(K)-2}
	Q ← 30'd{2(N)(K)-2},		c3;

	udeltaB2 ← Q, GOTO[mxmaps],	c1;	{udeltaB2 ← 2(N)(K)-2}
	
{===================================================================	
  setup for 4x4x1
 =================================================================== }		

	at[ib.441, 10, mxwhich], 
	Q ← 4,				c2;
	uNinit ← Q,			c3;

	{uMinit ← Q},			c1;
	unCOUNT ← Q,			c2;
	umCOUNT ← Q,		c3;

	Q ← 1,				c1;
	ukCOUNT ← Q,			c2;
	uKinit ← Q,			c3;

	Q ← 6,				c1;
	udeltaA1 ← Q,			c2;	{udeltaA1 ← 2(M-1)}
	udeltaB2 ← Q,			c3;	{udeltaB2 ← 2(N)(K)-2}

	Q ← 2,				c1;
	udeltaB0 ← Q,			c2;	{udeltaB0 ← 2K}
	Q ← 4'd,			c3;

	udeltaB1 ← Q, GOTO[mxmaps],	c1;	{udeltaB1 ← 2(N-1)(K)-2}

	
{=====================================================================}
{=====================================================================}
		

mxmaps:
	rA ← urAVlo, L0 ← L0.deltaI,				c2;	{Store low VA of A into rA}
	TT ← urAVlo, GOTO[fixrAI],				c3;	{Move it into TT, goto fixrAI}

	at[L0.deltaI, 4, rAfixed],
	rB ← urBVlo,						c2;	{Store low VA of B into rB}	
	TT ← urBVlo, GOTO[fixrBI],				c3;	{Move it into TT, goto fixrBI}

	at[L0.deltaI, 4, rBfixed],
	rC ← urCVlo,						c2;	{Store low VA of C into rC}
	TT ← urCVlo, GOTO[fixrCI],				c3;	{Move it into TT, goto fixrCI}

	at[L0.deltaI, 4, rCfixed],
	FloatNop,						c2;
	FloatMode.RN.AI.IEEE, FloatPIPE, 			c3;

mxinit:
	ufloatplus ← 0, L0 ← L0.delta0,				c1;	{Initialize to 0}
	FloatAB ← ufloatplus, FLPlus,				c2;	{Load AB of FPT chip with 0}
	FloatAB ← ufloatplus,					c3;	{Perform addition}

	MAR ← [rhrA, rA + 0],					c1;	{Point to first element of A}
	Q{nCOUNT} ← uNinit,					c2;	{Initialize column count}
	FloatAB{Ahi} ← MD,					c3;	{Load A H into AB of FPT chip}
	
	MAR ← [rhrA, rA + 1],					c1;	{Point to A L}
	TT ← udeltaB0, CANCELBR[$, 2],				c2;
	FloatAB{Alo} ← MD,					c3;	{Load A L into AB of FPT chip}

	MAR ← rB ← [rhrB, rB + 0],				c1;	{Point to first element of B}
	,							c2;
	FloatA{Bhi} ← MD, FLTimes.A.B, GOTO[mxstart],		c3;	{Load B H into A of FPT chip}

mxloop:
	MAR ← rA ← [rhrA, rA + 2], DISP4[mxcheck2, 3],		c1;	{Point to next column of A}
	FloatA{prodlo} ← FloatResult, BRANCH[$, fixrA0, 1],	c2, at[0F, 10, mxcheck2];	{Load Prod L}
mxrAret:
	FloatAB ← MD,						c3;	{Load A H into AB}

	MAR ← [rhrA, rA + 1],					c1;	{Point to A L}
	CANCELBR[$, 2],						c2;
	FloatAB ← MD,						c3;	{Load A L into AB of FPT chip}

	MAR ← rB ← [rhrB, rB + TT{2K}],				c1;	{Point to element of matrix B}
	BRANCH[$, fixrB0, 1],					c2;	{Check for page carry}
mxrBret:
	FloatA{Bhi} ← MD, FLTimes.A.B,				c3;	{Load B H into A of FPT chip}

mxstart:
	MAR ← [rhrB, rB + 1],					c1;	{Point to B L}
	CANCELBR[$, 2],						c2;
	FloatA{Blo} ← MD,					c3;	{Load B L into A of FPT chip}
									{Perform multiplication} 

	FloatPump,						c1;
	FloatPump,						c2;
	FloatPump, FloatUnloadS, Float.M,			c3;

	FloatPump, FloatUnloadS, Float.L,			c1;
	FloatAB{sumhi} ← FloatResult,				c2;	{Load Sum H into AB of FPT chip}
	Xbus ← PPort, XDisp,					c3;	{Get status, and test}

	FloatAB{sumlo} ← FloatResult, DISP4[mxcheck1, 3],	c1;	{Load Sum L into AB of FPT chip}
	FloatPump, FloatUnloadP, Float.M,			c2, at[0F, 10, mxcheck1];	{If OK}
	FloatPump, FloatUnloadP, Float.L,			c3;

	FloatA{prodhi} ← FloatResult, FLPlus,			c1;	{Load Prod H into A of FPT chip}
	Q{nCOUNT} ← Q{nCOUNT} - 1, ZeroBr,			c2;	{Decrement count}
	Xbus ← PPort, XDisp, BRANCH[mxloop, mxterm],		c3;	{Get status, and test}

mxterm:
	FloatA{prodlo} ← FloatResult, DISP4[mxcheck3, 3],	c1;
	FloatPump,						c2, at[0F, 10, mxcheck3];
	FloatPump,						c3;

	FloatPump,						c1;
	FloatPump,						c2;
	FloatPump,						c3;

	FloatPump,						c1;
	FloatPump, FloatUnloadS, Float.M,			c2;
	FloatPump, FloatUnloadS, Float.L,			c3;

	Q ← FloatResult,					c1;
	L1Disp,							c2;
	DISP4[mx?first],					c3;
	
	MAR ← rC ← [rhrC, rC + 0], L1 ← L1.mxnotfirst,		c1, at[L1.mxfirst, 10, mx?first];
	MDR{sumhi} ←  Q, LOOPHOLE[wok], GOTO[mxrCcont],		c2;		{Store result H}

	MAR ← rC ← [rhrC, rC + 2],				c1, at[L1.mxnotfirst, 10, mx?first];
	MDR{sumhi} ←  Q, LOOPHOLE[wok], BRANCH[$, fixrC, 1],	c2;	{Store result H}
	
mxrCcont:

	Xbus ← PPort, XDisp,					c3;	{Get status, and test}

	MAR ← [rhrC, rC + 1], DISP4[mxcheck4, 3], 			c1;	{Point to C L}
	MDR{sumlo} ← FloatResult, LOOPHOLE[wok], CANCELBR[$, 2],	c2, at[0F, 10, mxcheck4];	{Store result L}
								
	Q ← ukCOUNT,							c3;

	Q ← Q - 1, ZeroBr,					c1;	{Decrement K count}
	ukCOUNT ← Q, BRANCH[mxmoreK, mxKdone],			c2;	{and test}

mxmoreK:

{	set nCOUNT to N {done in mxinit}
	set rA to A[m, 0]  {was A[m, N-1] + 1}{delta = -2(N-1)}
	set rB to B[0, k]  {was B[N-1, k-1] + 1}{delta = -2(N-1)*(K)+2}
	GOTO[mxinit]
}

	Q ← udeltaA1, L0 ← L0.delta1,				c3;

	rA ← rA - Q, PgCarryBr,					c1;	{Adjust pointer for matrix A}
	BRANCH[fixrA1, lmrAdn],					c2;
	GOTO[lmrAdn],					c2, at[L0.delta1, 4, rAfixed];
lmrAdn:
	Q ← udeltaB1,						c3;

	rB ← rB - Q, PgCarryBr,					c1;	{Adjust pointer for matrix B}
	BRANCH[fixrB1, lmrBdn],					c2;
	GOTO[lmrBdn],					c2, at[L0.delta1, 4, rBfixed];
lmrBdn:
	GOTO[mxinit],						c3;

mxKdone:

{	decrement mCOUNT, exit if done
	set kCOUNT to K
	set nCOUNT to N {done in mxinit}
	set rA to A[m, 0]  {was A[m-1, N-1] + 1}{delta = +2}
	set rB to B[0, 0]  {was B[n-1, k-1] + 1}{delta = -2(N*K)+2}
	GOTO[mxinit]
}

	Q ← umCOUNT, L0 ← L0.delta2,				c3;
	
	Q ← Q - 1, ZeroBr, L1 ← L1.matexit,			c1;	{Decrement M count}
	umCOUNT ← Q, BRANCH[$, mxfinished],			c2;	{Check if multiplication is finished}
	Q ← uKinit, L1 ← L1.mxnotfirst,				c3;

	rA ← rA + 2, PgCarryBr,					c1;	{Adjust pointer for matrix A}	
	ukCOUNT ← Q, BRANCH[$, fixrA2],				c2, at[L0.delta2, 4, rAfixed];	{Restore ukCOUNT}
	Q ← udeltaB2,						c3;

   	rB ← rB - Q, PgCarryBr,					c1;	{Adjust pointer for matrix B}
	BRANCH[fixrB2, lmrBdn2],					c2;
	GOTO[lmrBdn2],					c2, at[L0.delta2, 4, rBfixed];
lmrBdn2:
	GOTO[mxinit],						c3;
	
	
{============================================================================
 EXIT POINT
 ============================================================================}	
 

mxfinished:

	,							c3;

	,							c1;
	Xbus ← ib,						c2;
	Q ← 4, CALL[RestoreRegsHere],				c3;

	at[L1.matexit, 10, RestoreRegsRet],
	TOSH ← uTOSH,						c2;
	TOS ← uTOS, GOTO[c1.pc2B2],				c3;




{
******** small mpy  8 bits by 8 bits ******** 

	{	TT ←  Rx * Q	}
	TT ← 0,							c3;
	
	Ybus ← Rx and 1, NZeroBr, GOTO[firstmore],		c1;
firstmore:
	BRANCH[ftimes0, ftimes1],				c2;
ftimes1:
	TT ← TT + Q, GOTO[loop],				c3;
ftimes0:
	Ybus ← Rx, ZeroBr, GOTO[loop],				c3;
	
loop:
	Rx ← RShift1 Rx, SE ← 0, YDisp, BRANCH[more, thru],	c1;
more:
	Q ← Q + Q, BRANCH[times0, times1, 0D],			c2;
times1:
	TT ← TT + Q, GOTO[loop],				c3;
times0:
	Ybus ← Rx, ZeroBr, GOTO[loop],				c3;
thru:
	,							c2;
	


	
	inner loop registers:
	rA -- Rx
	rB -- TOS
	rC -- TOSH
	nCOUNT -- Q
	deltaB0 {+2K} -- TT


	remapping routines:
	fixrA {+2}
	fixrB {+2K}
	fixrC {+2}

	rB {-2(N-1)(K)+2}
	rB {-2(N)(K)+2}
	rA for {-2(N-1)}
}


{******** rA remapping ***********************************}

fixrA0:
	unCOUNT ← Q, GOTO[fixrAplus],				c3;

fixrA1:
	GOTO[fixrAminus],					c3;

fixrA2:
	GOTO[fixrAplus],					c3;

rAok:
	TT ← udeltaB0, L0Disp,					c3;
	
ma10:	MAR ← rA ← [rhrA, Q + 0], DISP2[rAfixed],		c1;	{Point to element of matrix A}
	Q ← unCOUNT, GOTO[mxrAret], LOOPHOLE[natc],		c2, at[L0.delta0, 4, rAfixed];

fixrAplus:
	TT ← urAVlo,						c1;	{Load low VA of A into TT}
	Q ← 0FF + 1,						c2;	{Prepare to add 1 page}
	TT ← TT + Q, CarryBr,					c3;	{Add 1 page, check for carry}

fixrAI:
	Q ← urAVhi, BRANCH[rAno64p, rA64p],			c1;	{Move high VA of A into Q}
rAno64p:
	urAVlo ← TT, GOTO[rArhok],				c2;	{No carry, save new low VA of A}
rArhok:
	rhTT ← Q LRot0,						c3;	{rhTT contains urAVhi}

	Map ← [rhTT, TT],					c1;	
	Q ← rA,							c2;	{Q now contains urAVlo}
	rhrA ← rA ← MD, XwdDisp,				c3;

	Map ← [rhTT, TT], DISP2[rAfixFlags],			c1;
	MDR ← rA or 10, GOTO[rAok],				c2, at[0,4,rAfixFlags];
	MDR ← rA or 10, GOTO[rAok],				c2, at[1,4,rAfixFlags];
	MDR ← rA or 10, GOTO[rAok],				c2, at[2,4,rAfixFlags];
	GOTO[MATpagefault],					c2, at[3,4,rAfixFlags];

rA64p:
	Q ← Q + 1, GOTO[rA64ch],				c2;	{Propagate carry to H word}
									{Q now contains high VA of A}
rA64ch:
	urAVhi ← Q,						c3;	{Update urAVhi}
	
	GOTO[rAno64p],						c1;

fixrAminus:

	TT ← urAVlo,						c1;	{Store low VA of A in TT}
	Q ← 0FF + 1,						c2;	{Prepare to subtract 1 page}
	TT ← TT - Q, CarryBr,					c3;	{Subtract, check for borrow}

	Q ← urAVhi, BRANCH[rA64m, rAno64m],			c1;	{Load High VA of A into Q}
	
rAno64m:
	urAVlo ← TT, GOTO[rArhok],				c2;	{No borrow, save new low VA of A}

rA64m:
	Q ← Q - 1, GOTO[rA64ch],				c2;	{Borrow, subtract high VA of A}
	

{******* rB remapping ***********************************}

fixrB0:
	unCOUNT ← Q, GOTO[fixrBplus],				c3;

fixrB1:
	GOTO[fixrBminus],					c3;

fixrB2:
	GOTO[fixrBminus],					c3;

rBok:
	TT ← udeltaB0, L0Disp,					c3;
	
	MAR ← rB ← [rhrB, Q + 0], DISP2[rBfixed],		c1;
	Q ← unCOUNT, GOTO[mxrBret], LOOPHOLE[natc],		c2, at[L0.delta0, 4, rBfixed];

fixrBplus:
	TT ← urBVlo,						c1;	{Load low VA of B into TT}
	Q ← 0FF + 1,						c2;	{Prepare to add 1 page}
	TT ← TT + Q, CarryBr,					c3;	{Add 1 page, check for carry}

fixrBI:
	Q ← urBVhi, BRANCH[rBno64p, rB64p],			c1;	{Move high VA of B into Q}
rBno64p:
	urBVlo ← TT, GOTO[rBrhok],				c2;	{No carry, save new low VA of B}
rBrhok:
	rhTT ← Q LRot0,						c3;	{rhTT contains urBVhi}

	Map ← [rhTT, TT],					c1;
	Q ← rB,							c2;	{Q now contains urBVlo}
	rhrB ← rB ← MD, XwdDisp,				c3;

	Map ← [rhTT, TT], DISP2[rBfixFlags],			c1;
	MDR ← rB or 10, GOTO[rBok],				c2, at[0,4,rBfixFlags];
	MDR ← rB or 10, GOTO[rBok],				c2, at[1,4,rBfixFlags];
	MDR ← rB or 10, GOTO[rBok],				c2, at[2,4,rBfixFlags];
	GOTO[MATpagefault],					c2, at[3,4,rBfixFlags];
	
rB64p:
	Q ← Q + 1, GOTO[rB64ch],				c2;	{Propagate carry to H word}
								{Q now contains high VA of B}
rB64ch:
	urBVhi ← Q,						c3;	{Update urBVhi}
	
	GOTO[rBno64p],						c1;

fixrBminus:
	TT ← urBVlo,						c1;	{Store low VA of B in TT}
	Q ← 0FF + 1,						c2;	{Prepare to subtract 1 page}
	TT ← TT - Q, CarryBr,					c3;	{Subtract, check for borrow}

	Q ← urBVhi, BRANCH[rB64m, rBno64m],			c1;	{Load High VA of B into Q}
rBno64m:
	urBVlo ← TT, GOTO[rBrhok],				c2;	{No borrow, save new low VA of B}

rB64m:
	Q ← Q - 1, GOTO[rB64ch],				c2;	{Borrow, subtract high VA of B}
	

{******* rC remapping ***********************************}

fixrC:
	unCOUNT{not really} ← Q, GOTO[fixrCplus],		c3;

rCok:
	L0Disp, 						c3;
	
	MAR ← rC ← [rhrC, Q + 0], DISP2[rCfixed],		c1;
	MDR ← unCOUNT, GOTO[mxrCcont],				c2, at[L0.delta0, 4, rCfixed];

fixrCplus:
	TT ← urCVlo,						c1;	{Load low VA of C into TT}
	Q ← 0FF + 1,						c2;	{Prepare to add 1 page}
	TT ← TT + Q, CarryBr,					c3;	{Add 1 page, check for carry}

fixrCI:
	Q ← urCVhi, BRANCH[rCno64p, rC64p],			c1;	{Move high VA of C into Q}
rCno64p:
	urCVlo ← TT, GOTO[rCrhok],				c2;	{No carry, save new low VA of C}
rCrhok:
	rhTT ← Q LRot0,						c3;	{rhTT contains urCVhi}

	Map ← [rhTT, TT],					c1;
	Q ← rC,							c2;	{Q now contains urBVlo}
	rhrC ← rC ← MD, XwdDisp,				c3;

	Map ← [rhTT, TT], DISP2[rCfixFlags, 1],			c1;
	MDR ← rC or 30, GOTO[rCok],				c2, at[1,4,rCfixFlags];
	Rx ← rC, GOTO[MATpagefault],				c2, at[3,4,rCfixFlags];

rC64p:
	Q ← Q + 1, GOTO[rC64ch],				c2;	{Propagate carry to H word}
									{Q now contains high VA of C}
rC64ch:
	urCVhi ← Q,						c3;	{Update urCVhi}
	GOTO[rCno64p],						c1;


	GOTO[MatUfn], L1 ← L1.matufn,      			c2, at[03, 10, mxcheck1];
	GOTO[MatUfn], L1 ← L1.matufn,				c2, at[07, 10, mxcheck1];
	GOTO[MatUfn], L1 ← L1.matufn,				c2, at[0B, 10, mxcheck1];

	CANCELBR[MatUfn, 7], L1 ← L1.matufn,			c2, at[03, 10, mxcheck2];
	CANCELBR[MatUfn, 7], L1 ← L1.matufn,			c2, at[07, 10, mxcheck2];
	CANCELBR[MatUfn, 7], L1 ← L1.matufn,			c2, at[0B, 10, mxcheck2];

	GOTO[MatUfn], L1 ← L1.matufn,				c2, at[03, 10, mxcheck3];
	GOTO[MatUfn], L1 ← L1.matufn,				c2, at[07, 10, mxcheck3];
	GOTO[MatUfn], L1 ← L1.matufn,				c2, at[0B, 10, mxcheck3];

	CANCELBR[MatUfn, 7], L1 ← L1.matufn,			c2, at[03, 10, mxcheck4];
	CANCELBR[MatUfn, 7], L1 ← L1.matufn,			c2, at[07, 10, mxcheck4];
	CANCELBR[MatUfn, 7], L1 ← L1.matufn,			c2, at[0B, 10, mxcheck4];

MATpagefault:

	TOS ← uTOS,						c3;

	TOSH ← uTOSH,						c1;
	L1 ← L1.LFApf,						c2;
	Q ← 0, CALL[RestoreRegsHere],				c3;

MatUfn:
	,							c3;
ufnstop:
	TOS ← uTOS,						c1;
	TOSH ← uTOSH,						c2;
	Q ← 0, CALL[RestoreRegsHere],				c3;

	at[L1.matufn, 10, RestoreRegsRet],
	GOTO[ufnX3],						c2;

	{ E N D }