{File name FixedLoadStore.mc
Description: Mesa Load and Store op-codes
Author: Sandman
Created: February 16, 1980
Last edited: Sturgis: 14-Jun-84 15:35:18
Sandman, January 27, 1981 5:56 PM
Garner, April 1, 1980 12:20 PM}

{The Load mesa op-codes consist of the following:
OP
valbytesstktime
LL0
10’b1+11
LL1
11’b1+11
LL2
12’b1+11
LL3
13’b1+11
LL4
14’b1+11
LL5
15’b1+11
LL6
16’b1+11
LL7
17’b1+11
LLB
20’b2+11
LLDB
21’b2+22
LG0
37’b1+11
LG1
40’b1+11
LG2
41’b1+11
LG3
42’b1+11
LG4
43’b1+11
LG5
44’b1+11
LG6
45’b1+11
LG7
46’b1+11
LGB
47’b2+11
LGDB
50’b2+22
LI0
56’b1+11
LI1
57’b1+11
LI2
60’b1+11
LI3
61’b1+11
LI4
62’b1+11
LI5
63’b1+11
LI6
64’b1+11
LIN1
65’b1+11
LINI
66’b1+11
LIB
67’b2+11
LIW
70’b3+12
LINB
71’b2+11
LADRB
72’b2+12
GADRB
73’b2+12
LCO
74’b3+12
LP
161’b1+11

The Store mesa op-codes consist of the following:
OP
valbytesstktime
SL0
22’b1-11
SL1
23’b1-11
SL2
24’b1-11
SL3
25’b1-11
SL4
26’b1-11
SL5
27’b1-11
SL6
30’b1-11
SL7
31’b1-11
SLB
32’b2-11
SLDB
162’b2-22
SG0
51’b1-11
SG1
52’b1-11
SG2
53’b1-11
SG3
54’b1-11
SGB
55’b2-11
SGDB
163’b2-22
PL0
34’b101
PL1
35’b101
PL2
36’b101
PL3
37’b101}
{Times for memory operations are + 2 if page cross + 2 if fix map flags}

{L2
CarryMapRets}
Set[L2.Lcarry, 1];
Set[L2.LDcarry, 5];
Set[L2.Scarry, 0];
Set[L2.SLDcarry, 9];
Set[L2.SGDcarry, 0D]; {1 mod 4}

{*****************************************************************************
LLn{n:[0..7]} Load Local n 1 click
*****************************************************************************}
@LL0:MAR ← Q ← [rhL, L+4], L1 ← L1r.PopOnly, push, GOTO[LLns],c1, opcode[10’b];
@LL1:
MAR ← Q ← [rhL, L+5], L1 ← L1r.PopOnly, push, GOTO[LLns],c1, opcode[11’b];
@LL2:
MAR ← Q ← [rhL, L+6], L1 ← L1r.PopOnly, push, GOTO[LLns],c1, opcode[12’b];
@LL3:
MAR ← Q ← [rhL, L+7], L1 ← L1r.PopOnly, push, GOTO[LLns],c1, opcode[13’b];
@LL4:
MAR ← Q ← [rhL, L+8], L1 ← L1r.PopOnly, push, GOTO[LLns],c1, opcode[14’b];
@LL5:
MAR ← Q ← [rhL, L+9], L1 ← L1r.PopOnly, push, GOTO[LLns],c1, opcode[15’b];
@LL6:
MAR ← Q ← [rhL, L+0A], L1 ← L1r.PopOnly, push, GOTO[LLns],c1, opcode[16’b];
@LL7:
MAR ← Q ← [rhL, L+0B], L1 ← L1r.PopOnly, push, GOTO[LLns],c1, opcode[17’b];

LLns:
STK ← TOS, PC ← PC + PC16, IBDisp, L2←L2.Lcarry, BRANCH[LLTail,LLcarry,1],c2;
LLTail:
TOS ← MD, push, fZpop, DISPNI[OpTable],c3;

LLcarry:
TT ← UvL, GOTO[CarryMap],c3;

{*****************************************************************************
LLB Load Local Byte 1 click
*****************************************************************************}
@LLB:MAR ← Q ← [rhL, L+ib], L1 ← L1r.PopDec, push, GOTO[LLBs],c1, opcode[20’b];

LLBs:
STK ← TOS, PC ← PC + 1, IBDisp, L2←L2.Lcarry, BRANCH[LLTail,LLcarry,1],c2;
{*****************************************************************************
Load Carry Logic (shared between LLx and LGx)
*****************************************************************************}
CarryMap:Noop,c1;
CarryFix:
Q ← Q - TT, L2Disp,c2;
Q ← Q and 0FF, RET[CarryMapRets],c3;

LcarryMap:
Map ← Q ← [rhMDS, TT+Q],c1, at[Or[L2.Lcarry,2], 10, CarryMapRets];
PC ← PC-PC16,c2;
Rx ← rhRx ← MD, XRefBr, GOTO[RedoR],c3;

{*****************************************************************************
LGn{n:[0..7]} Load Global n 1 click
*****************************************************************************}
@LG0:MAR ← Q ← [rhG, G+3], L1 ← L1r.PopOnly, push, GOTO[LGns],c1, opcode[37’b];
@LG1:
MAR ← Q ← [rhG, G+4], L1 ← L1r.PopOnly, push, GOTO[LGns],c1, opcode[40’b];
@LG2:
MAR ← Q ← [rhG, G+5], L1 ← L1r.PopOnly, push, GOTO[LGns],c1, opcode[41’b];
@LG3:
MAR ← Q ← [rhG, G+6], L1 ← L1r.PopOnly, push, GOTO[LGns],c1, opcode[42’b];
@LG4:
MAR ← Q ← [rhG, G+7], L1 ← L1r.PopOnly, push, GOTO[LGns],c1, opcode[43’b];
@LG5:
MAR ← Q ← [rhG, G+8], L1 ← L1r.PopOnly, push, GOTO[LGns],c1, opcode[44’b];
@LG6:
MAR ← Q ← [rhG, G+9], L1 ← L1r.PopOnly, push, GOTO[LGns],c1, opcode[45’b];
@LG7:
MAR ← Q ← [rhG, G+0A], L1 ← L1r.PopOnly, push, GOTO[LGns],c1, opcode[46’b];

LGns:
STK ← TOS, PC ← PC + PC16, IBDisp, L2←L2.Lcarry, BRANCH[LGTail,LGcarry,1],c2;
LGTail:
TOS ← MD, push, fZpop, DISPNI[OpTable],c3;

LGcarry:
TT ← UvG, GOTO[CarryMap],c3;

{*****************************************************************************
LGB Load Global Byte 1 click
*****************************************************************************}
@LGB:MAR ← Q ← [rhG, G+ib], L1 ← L1r.PopDec, push, GOTO[LGBs],c1, opcode[47’b];

LGBs:
STK ← TOS, PC ← PC + 1, IBDisp, L2←L2.Lcarry, BRANCH[LGTail,LGcarry,1],c2;

{*****************************************************************************
LLDB Load Local Double Byte 2 clicks
*****************************************************************************}
@LLDB:MAR ← Q ← [rhL, L + ib], push, L1 ← L1r.PopDec,c1, opcode[21’b];
STK ← TOS, PC ← PC + PC16, L2←L2.LDcarry, BRANCH[$, LLDBcarry,1],c2;
TOS ← MD,c3;

LLDB2:
MAR ← Q ← [rhL, Q + 1], push, L1 ← L1r.Pop2DecDec,c1;
STK ← TOS, PC ← PC + PC16, IBDisp, L2←L2.Lcarry, BRANCH[LLTail,LLcarry,1],c2;

LLDBcarry:
TT ← UvL, GOTO[CarryMap],c3;
{*****************************************************************************
LGDB Load Global Double Byte 2 clicks
*****************************************************************************}
@LGDB:MAR ← Q ← [rhG, G + ib], push, L1 ← L1r.PopDec,c1, opcode[50’b];
STK ← TOS, PC ← PC + PC16, L2←L2.LDcarry, BRANCH[$, LGDBcarry,1],c2;
TOS ← MD,c3;

LGDB2:
MAR ← Q ← [rhG, Q + 1], push, L1 ← L1r.Pop2DecDec,c1;
STK ← TOS, PC ← PC + PC16, IBDisp, L2←L2.Lcarry, BRANCH[$,LGDBCarry2,1],c2;
TOS ← MD, push, fZpop, DISPNI[OpTable], c3;

LGDBcarry:
TT ← UvG, GOTO[CarryMap],c3;
{*****************************************************************************
Load Double Carry Logic (shared by LLDx and LGDx)
*****************************************************************************}
{First word on next page => remap page and get both words}
LDcarryMap:Map ← Q ← [rhMDS, TT+Q],c1, at[Or[L2.LDcarry,2], 10, CarryMapRets];
L0 ← L0.LDcarry,c2;
Rx ← rhRx ← MD, XRefBr,c3;

LDcarry:
MAR ← [rhRx, Q+0], BRANCH[LDcarryMapUD, $],c1, at[L0.LDcarry,10,RMapFixCaller];
Noop,c2;
TOS ← MD,c3;

MAR ← [rhRx, Q+1], push, GOTO[LLns],c1;

LDcarryMapUD:
CALL[RMapFix], {will return to LDcarry}c2;


{*****************************************************************************

Sturgis: 14-Jun-84 15:44:44

The following is additional carry logic for the case of second word in a page that page faults. The reason that this fix is so bad is that there are at least two case tables that are full, and so I have had to duplicate a lot of code here. The two case tables that are full are the RFixForTrap table, and RMapFixCaller.

The bug is that in the incorrect code, L1 was set to L1r.Pop2DecDec, to be used in the case of a fault, but in fact the value should have been Pop2Dec, but there is no such value, and the table is full. The reason it should have been Pop2Dec is that some joint code has temporarily subtracted 1 from the pc. Unfortunately, I can not simply replace this joint code, as the subroutine it uses has a full return list. So I must also duplicate the subroutine.

It is possible that no one else uses L1r.Pop2DecDec, in which I could replace this case with the one I want. However, it seems too painful to check this.

In the following I leave some indication of where the code is borrowed from.
*****************************************************************************}

{LGcarry}
LGDBCarry2:
TT ← UvG,c3;

{CarryMap}
Noop,c1;
Q ← Q - TT,c2;
Q ← Q and 0FF, c3;

{LcarryMap}
Map ← Q ← [rhMDS, TT+Q],c1;
Noop,c2;
Rx ← rhRx ← MD, XRefBr,c3;

{Read.RedoR}
LGDBCarry3:
MAR ← [rhRx, Q+0], BRANCH[LGDBCarry4, $], c1;
IBDisp,c2;
{LLTail}
TOS ← MD, push, fZpop, DISPNI[OpTable], c3;

{Read.RMapUD}
LGDBCarry4:
Noop,c2;
{CommonSubs.RMapFix}
Xbus ← Rx LRot0, XwdDisp, L3 ← L3.rhMDS.Q, c3;

Map ← [rhMDS,Q], DISP2[LGDBFixRFlags], c1;

LGDBFixRFlags:
MDR ← Rx or 10, GOTO[LGDBCarry5], c2, at[0,4];
MDR ← Rx or 10, GOTO[LGDBCarry5], c2, at[1,4, LGDBFixRFlags];
MDR ← Rx or 10, GOTO[LGDBCarry5], c2, at[2,4, LGDBFixRFlags];
T ← qPageFault, L1Disp, GOTO[RTrap], c2, at[3,4, LGDBFixRFlags];

LGDBCarry5:
Xbus ← 1, XDisp, GOTO[LGDBCarry3],c3;



{*****************************************************************************
LIn{n:[0..6]} Load Immeadiate n 1 click
*****************************************************************************}
@LI0:T ← 0, push, GOTO[LInTail],c1, opcode[56’b];
@LI1:
T ← 1, push, GOTO[LInTail],c1, opcode[57’b];
@LI2:
T ← 2, push, GOTO[LInTail],c1, opcode[60’b];
@LI3:
T ← 3, push, GOTO[LInTail],c1, opcode[61’b];
@LI4:
T ← 4, push, GOTO[LInTail],c1, opcode[62’b];
@LI5:
T ← 5, push, GOTO[LInTail],c1, opcode[63’b];
@LI6:
T ← 6, push, GOTO[LInTail],c1, opcode[64’b];

LInTail:
STK ← TOS, PC ← PC + PC16, IBDisp,c2;
PushT:
TOS ← T, push, fZpop, DISPNI[OpTable],c3;
{*****************************************************************************
LIN1 Load Immeadiate Negative One 1 click
*****************************************************************************}
@LIN1:T ← T xor ~T, push, GOTO[LInTail],c1, opcode[65’b];
{*****************************************************************************
LINI Load Immeadiate Negative Infinity 1 click
*****************************************************************************}
@LINI:T ← RShift1 0, SE ← 1, push, GOTO[LInTail],c1, opcode[66’b];

{*****************************************************************************
LIB Load Immeadiate Byte 1 click
*****************************************************************************}
@LIB:T ← ib, push,c1, opcode[67’b];
STK ← TOS, PC ← PC + 1, IBDisp, GOTO[PushT],c2;
{*****************************************************************************
LIW Load Immeadiate Word 2 clicks
*****************************************************************************}
@LIW:T ← ib, push,c1, opcode[70’b];
LIWx:
PC ← PC + 1,c2;
T ← T LRot8,c3;

T ← T or ib, GOTO[LInTail],c1;
{*****************************************************************************
LINB Load Immeadiate Negative Byte 1 click
*****************************************************************************}
@LINB:Q ← ib, push,c1, opcode[71’b];
STK ← TOS, PC ← PC + 1, push, fZpop, IBDisp,c2;
TOS ← Q xor ~0FF, DISPNI[OpTable],c3;
{*****************************************************************************
LADRB Local Address Byte 2 clicks
*****************************************************************************}
@LADRB:TT ← UvL,c1, opcode[72’b];
LADRBx:
T ← ib, push,c2;
PC ← PC + PC16,c3;

T ← TT + T, GOTO[LInTail],c1;
{*****************************************************************************
GADRB Global Address Byte 2 clicks
*****************************************************************************}
@GADRB:TT ← UvG, GOTO[LADRBx],c1, opcode[73’b];
{*****************************************************************************
LCO Load Code Offset 2 clicks
*****************************************************************************}
@LCO:T ← ib, push, GOTO[LIWx],c1, opcode[74’b];
{*****************************************************************************
LP Lengthen Pointer2 click
*****************************************************************************}
@LP:[] ← TOS, ZeroBr, fXpop, push,c1, opcode[161’b];
BRANCH[LPnot, LPnil],c2;
LPnot:
T ← UvMDS, GOTO[LPTail],c3;
LPnil:
T ← 0, GOTO[LPTail],c3;

LPTail:
push, GOTO[LInTail],c1;

{*****************************************************************************
SLn{n:[0..7]} Store Local n 1 click
*****************************************************************************}
@SL0:MAR ← Q ← [rhL, L+4], L1 ← L1w.DecOnly, push, GOTO[SLns],c1, opcode[22’b];
@SL1:
MAR ← Q ← [rhL, L+5], L1 ← L1w.DecOnly, push, GOTO[SLns],c1, opcode[23’b];
@SL2:
MAR ← Q ← [rhL, L+6], L1 ← L1w.DecOnly, push, GOTO[SLns],c1, opcode[24’b];
@SL3:
MAR ← Q ← [rhL, L+7], L1 ← L1w.DecOnly, push, GOTO[SLns],c1, opcode[25’b];
@SL4:
MAR ← Q ← [rhL, L+8], L1 ← L1w.DecOnly, push, GOTO[SLns],c1, opcode[26’b];
@SL5:
MAR ← Q ← [rhL, L+9], L1 ← L1w.DecOnly, push, GOTO[SLns],c1, opcode[27’b];
@SL6:
MAR ← Q ← [rhL, L+0A], L1 ← L1w.DecOnly, push, GOTO[SLns],c1, opcode[30’b];
@SL7:
MAR ← Q ← [rhL, L+0B], L1 ← L1w.DecOnly, push, GOTO[SLns],c1, opcode[31’b];

SLns:
MDR ← STK ← TOS, PC ← PC + PC16, pop, IBDisp, BRANCH[$,SLcarry,1],c2;
SLTail:
TOS ← STK, pop, DISPNI[OpTable],c3;

SLcarry:
TT ← UvL, L2←L2.Scarry, GOTO[CarryMap],c3;

{*****************************************************************************
SLB Store Local Byte 1 click
*****************************************************************************}

@SLB:
MAR ← Q ← [rhL, L+ib], L1 ← L1w.DecDec, push, GOTO[SLBs],c1, opcode[32’b];

SLBs:
MDR ← STK ← TOS, PC ← PC + 1, pop, IBDisp, BRANCH[SLTail,SLcarry,1],c2;

{*****************************************************************************
PLn{n:[0..3]} Put Local n 1 click
*****************************************************************************}
{no page carry possible on local 0-3}
@PL0:MAR ← Q ← [rhL, L+4], fXpop, push, GOTO[PLns],c1, opcode[33’b];
@PL1:
MAR ← Q ← [rhL, L+5], fXpop, push, GOTO[PLns],c1, opcode[34’b];
@PL2:
MAR ← Q ← [rhL, L+6], fXpop, push, GOTO[PLns],c1, opcode[35’b];
@PL3:
MAR ← Q ← [rhL, L+7], fXpop, push, GOTO[PLns],c1, opcode[36’b];

PLns:
MDR ← TOS, PC ← PC + PC16, IBDisp, CANCELBR[DISPNIonly,0],c2;
{*****************************************************************************
Store Carry Logic (shared between SLx and SGx)
*****************************************************************************}
ScarryMap:Map ← Q ← [rhMDS, TT+Q], {map next page}c1, at[L2.Scarry, 10, CarryMapRets];
L0 ← L0.Scarry,c2;
Rx ← rhRx ← MD, XDirtyDisp,c3;

Scarry:
MAR ← [rhRx, Q+0], BRANCH[ScarryMapUD, $, 1],c1, at[L0.Scarry,10,WMapFixCaller];
SGStore:
MDR ← TOS, IBDisp, CANCELBR[SLTail,0],c2;

ScarryMapUD:
CALL[WMapFix], {will return to Scarry}c2;

{*****************************************************************************
SGn{n:[0..7]} Store Global n 1 click
*****************************************************************************}
@SG0:Q ← G + 3, PgCarryBr, L1←L1w.DecOnly, GOTO[SGns],c1, opcode[51’b];
@SG1:
Q ← G + 4, PgCarryBr, L1←L1w.DecOnly, GOTO[SGns],c1, opcode[52’b];
@SG2:
Q ← G + 5, PgCarryBr, L1←L1w.DecOnly, GOTO[SGns],c1, opcode[53’b];
@SG3:
Q ← G + 6, PgCarryBr, L1←L1w.DecOnly, GOTO[SGns],c1, opcode[54’b];

SGns:
Xbus ← rhG, XDirtyDisp, push, BRANCH[SGnNoCross, SGnCross],c2;
SGnNoCross:
STK ← TOS, pop, PC ← PC + PC16, BRANCH[SGMapFix, SGMapOK, 1],c3;
SGnCross:
STK ← TOS, pop, PC ← PC + PC16, CANCELBR[SGCrossFix,3],c3;

SGMapOK:
MAR ← [rhG, Q+0], GOTO[SGStore]c1;
SGMapFix:TT ← UvG, L2←L2.Scarry,c1;
SGMapFixx:
Q ← Q - TT,c2;
Q ← Q and 0FF,c3;

Map ← [rhMDS, TT],c1;
L2Disp,c2;
rhG ← MD, RET[CarryMapRets],c3;

SGCrossFix:
TT ← UvG, L2←L2.Scarry, GOTO[SGMapFixx],c1;


{*****************************************************************************
SGB Store Global Byte 1 click
*****************************************************************************}
@SGB:Q ← G + ib, PgCarryBr, L1 ← L1w.DecDec,c1, opcode[55’b];

SGBs:
Xbus ← rhG, XDirtyDisp, push, BRANCH[SGbNoCross, SGbCross],c2;

SGbNoCross:
STK ← TOS, pop, PC ← PC + 1, BRANCH[SGMapFix, SGMapOK, 1],c3;
SGbCross:
STK ← TOS, pop, PC ← PC + 1, CANCELBR[SGCrossFix,3],c3;

{*****************************************************************************
SLDB Store Local Double Byte 2 clicks
*****************************************************************************}
@SLDB:MAR ← Q ← [rhL, L + ib], L1 ← L1w.NoFixes,c1, opcode[162’b];
MDR ← STK, push, L2←L2.SLDcarry, BRANCH[$, SLDBcarry,1],c2;
PC ← PC + PC16, STK ← TOS, pop,c3;

SLDB2:
MAR ← Q ← [rhL, Q + 1], pop, L1 ← L1w.PushDecDec,c1;
SLDB2x:
MDR ← TOS, PC ← PC + PC16, IBDisp, BRANCH[SLTail,SLcarry,1],c2;

SLDBcarry:
TT ← UvL, GOTO[CarryMap],c3;

{*****************************************************************************
SGDB Store Global Double Byte 2 clicks
*****************************************************************************}
@SGDB:Q ← G + ib + 1, PgCarryBr, L2←L2.SGDcarry,c1, opcode[163’b];
Xbus ← rhG, Q ← Q - 1, XDirtyDisp, push, BRANCH[$,SGDBcarry],c2;
STK ← TOS, pop, BRANCH[SGDBMapFix, SGDBMapOK, 1],c3;

SGDBMapOK:
MAR ← Q ← [rhG, Q + 0],c1;
MDR ← STK,c2;
PC ← PC + PC16,c3;

MAR ← [rhG, Q + 1], pop, GOTO[SLDB2x],c1;

SGDBMapFix:
TT ← UvG, CALL[SGMapFixx],c1;

T ← TOS, L1 ← L1w.PushDec,c1, at[L2.SGDcarry,10,CarryMapRets];
Q ← TT + Q, GOTO[WDBx],c2;

SGDBcarry:
STK ← TOS, pop, CANCELBR[$,3],c3;
TT ← UvG, CALL[SGMapFixx],c1;

{*****************************************************************************
Store Double Carry Logic (shared by SLDx)
*****************************************************************************}
{First word on next page => remap page and store both words}
SDcarryMap:Map ← Q ← [rhMDS, TT+Q],c1, at[Or[L2.SLDcarry,2], 10, CarryMapRets];
L0 ← L0.SDcarry,c2;
Rx ← rhRx ← MD, XDirtyDisp, pop,c3;

SDcarry:
MAR ← [rhRx, Q+0], BRANCH[SDcarryMapUD, $, 1],c1, at[L0.SDcarry,10,WMapFixCaller];
MDR ← STK, push,c2;
STK ← TOS, PC ← PC + PC16, pop,c3;

MAR ← [rhRx, Q+1], pop,c1;
MDR ← TOS, PC ← PC + PC16, IBDisp, CANCELBR[SLTail,0],c2;

SDcarryMapUD:
CALL[WMapFix], {will return to SDcarry}c2;

{14-Jun-84 15:36:28: Sturgis: repair nasty bug in LGDB, that occurs when second word is in a new page, and that page is not mapped in. The fix is gross, see comments in the opcode}