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