*-----------------------------------------------------------
Title[DMesaLS.mc...April 4, 1982 11:51 AM...Taft];
* Loads and Stores, plus various other stack operations
*-----------------------------------------------------------
%

CONTENTS, by order of occurence

Load/Store (16 bits)
LLn, LGnLoad Local n, Load Global n
SLn, SGnStore Local n, Store Global n
PLnPut Local n
LInLoad Immediate n
LIN1Load Immediate -1
LINILoad Immediate Negative Infinity
LIWLoad Immediate Word
LCOLoad Code Offset
LINBLoad Immediate Negative Byte

Load/Store (32 bits)
LLDB, LGDBLoad Local Double Byte, Load Global Double Byte
SLDB, SGDBStore Local Double Byte, Store Global Double Byte

Stack maintenance
PUSHincrement StkP
POPdecrement StkP
DUPduplicate TOS
EXCHExchange top two stack items
NILCK, NILCKLNil check
BNDCKBounds check

Machine Register Access
RRRead register
WRWrite register
%

TopLevel;

* Load/Store (16 bits)

*--------------------------------------------------------------------
IFUR[LL0, 1, L, N[4]];
* Load Local n: Push[FetchMDS[L+n]↑];
IFUR[LL1, 1, L, N[5]];
IFUR[LL2, 1, L, N[6]];
IFUR[LL3, 1, L, N[7]];
IFUR[LL4, 1, L, N[10]];
IFUR[LL5, 1, L, N[11]];
IFUR[LL6, 1, L, N[12]];
IFUR[LL7, 1, L, N[13]];
IFUR[LLB, 2, L];
* Load Local Byte: Push[FetchMDS[L+alpha]↑];
IFUR[LG0, 1, G, N[3]];
* Load Global n: Push[FetchMDS[G+n]↑];
IFUR[LG1, 1, G, N[4]];
IFUR[LG2, 1, G, N[5]];
IFUR[LG3, 1, G, N[6]];
IFUR[LG4, 1, G, N[7]];
IFUR[LG5, 1, G, N[10]];
IFUR[LG6, 1, G, N[11]];
IFUR[LG7, 1, G, N[12]];
IFUR[LGB, 2, G];
* Load Global Byte: Push[FetchMDS[G+alpha]↑];
*--------------------------------------------------------------------

Fetch← ID, T← StackNoUfl&+1, IFUNext1;
:IfMEP;
Fetch← ID, T← Stack&+1← MD, IFUNext1;
Fetch← ID, StkP+2, IFUNext1;
:Else;
PushMD:
Stack← MD, IFUNext0, Global;* Branched to by all IFUNext1
:EndIF;


*--------------------------------------------------------------------
IFUR[SL0, 1, L, N[4]];
* Store Local n: StoreMDS[L+n]↑ ← Pop[];
IFUR[SL1, 1, L, N[5]];
IFUR[SL2, 1, L, N[6]];
IFUR[SL3, 1, L, N[7]];
IFUR[SL4, 1, L, N[10]];
IFUR[SL5, 1, L, N[11]];
IFUR[SL6, 1, L, N[12]];
IFUR[SL7, 1, L, N[13]];
IFUR[SLB, 2, L];
* Store Local Byte: StoreMDS[L+alpha]↑ ← Pop[];
IFUR[SG0, 1, G, N[3]];
* Store Global n: StoreMDS[G+n]↑ ← Pop[];
IFUR[SG1, 1, G, N[4]];
IFUR[SG2, 1, G, N[5]];
IFUR[SG3, 1, G, N[6]];
IFUR[SGB, 2, G];
* Store Global Byte: StoreMDS[G+alpha]↑ ← Pop[];
*--------------------------------------------------------------------

Store← ID, DBuf← Stack&-1, IFUNext0CF;
:IfMEP;
Store← ID, Stack&-1← DBuf← MD, IFUNext0;
Store← ID, DBuf← T, IFUNext0;
:Else;
CheckFault0:
T← MD, IFUNext0, Global;* Branched to by all IFUNext0CF
:EndIf;

*--------------------------------------------------------------------
IFUR[PL0, 1, L, N[4]];
* Put Local n: StoreMDS[L+n]↑ ← Pop[]; SP ← SP+1;
IFUR[PL1, 1, L, N[5]];
IFUR[PL2, 1, L, N[6]];
IFUR[PL3, 1, L, N[7]];
*--------------------------------------------------------------------

:IfMEP;
Store← ID, T← DBuf← Stack&-1, IFUNext2;
Store← ID, T← Stack&-1← DBuf← MD, IFUNext2;
Store← ID, DBuf← T, IFUNext2;
:Else;
Store← ID, DBuf← Stack, IFUNext0CF;
:EndIf;


*--------------------------------------------------------------------
IFUR[LI0, 1, L, N[0]];
* Load Immediate n: Push[n];
IFUR[LI1, 1, L, N[1]];
IFUR[LI2, 1, L, N[2]];
IFUR[LI3, 1, L, N[3]];
IFUR[LI4, 1, L, N[4]];
IFUR[LI5, 1, L, N[5]];
IFUR[LI6, 1, L, N[6]];
IFUR[LIB, 2, L];
* Load Immediate Byte: Push[alpha];
*--------------------------------------------------------------------

Stack+1← ID, IFUNext0;
:IfMEP;
T← ID, Stack&+1← MD, Branch[PushT];
Stack+2← ID, IFUNext0;
:EndIf;

PushT:
StackT← T, IFUNext2;* Tail of many load instructions


*--------------------------------------------------------------------
IFUR[LIN1, 1, L, N[0]];
* Load Immediate Negative One: Push[177777B];
IFUR[LINI, 1, L, N[2]];
* Load Immediate Negative Infinity: Push[100000B];
*--------------------------------------------------------------------

T← (ID-1) RCY 1, StkP+1, Branch[PushT];
:IfMEP;
T← (ID-1) RCY 1, Stack&+1← MD, Branch[PushT];
T← (ID-1) RCY 1, StkP+2, Branch[PushT];
:EndIf;


*--------------------------------------------------------------------
IFUR[LINB, 2, L];
* Load Immediate Negative Byte:
* Push[BitOr[alpha, 177400B]];
* Note: PrincOps definition is: Push[SignExtend[alpha]];
* however, both Alto and D0 implement LINB as given here.
*--------------------------------------------------------------------

T← (ID) OR (177400C), StkP+1, Branch[PushT];
:IfMEP;
T← (ID) OR (177400C), Stack&+1← MD, Branch[PushT];
T← (ID) OR (177400C), StkP+2, Branch[PushT];
:EndIf;

:If[AltoMode];
********** Alto version **********
*--------------------------------------------------------------------
IFUR[LIW, 3, Code, N[4]];
* Load Immediate Word: Push[256*alpha + beta];
UndefOp[MOpLCO];
* LCO undefined in Alto mode
* Alto Mesa: This is an aligned 3-byte instruction.
*--------------------------------------------------------------------

RTemp0← (ID)-(PCX’)-1, Branch[LIWM1];* RTemp0← PCX+4
:IfMEP;
Stack← MD, Branch[.-1];
StkP+1, Branch[.-2];
:EndIf;

LIWM1:
T← (RTemp0) RSH 1, A← ID, Branch[.+2, R odd];
PCF← RTemp0;
T← T-1;
Fetch← T, T← StackNoUfl&+1, IFUNext1;

:Else;
******** PrincOps version ********
*--------------------------------------------------------------------
IFUR[LIW, 3, L];
* Load Immediate Word: Push[256*alpha + beta];
IFUR[LCO, 3, L];
* Load Code Offset -- same as LIW
*--------------------------------------------------------------------

T← ID, StkP+1, Branch[LIWM1];
:IfMEP;
T← ID, Stack&+1← MD, Branch[LIWM1];
T← ID, StkP+2, Branch[LIWM1];
:EndIf;

LIWM1:
T← LSH[T, 10];
StackT← (ID) OR T, IFUNext2;
:EndIf;
**********************************

* Load/Store (32 bits)

*--------------------------------------------------------------------
IFUR[LLDB, 2, L];
* Load Local Double Byte:
* Push[FetchMDS[L+alpha]↑]; Push[FetchMDS[L+alpha+1]↑];
IFUR[LGDB, 2, G];
* Load Global Double Byte:
* Push[FetchMDS[G+alpha]↑]; Push[FetchMDS[G+alpha+1]↑];
* This microcode is also the tail of RDBL.
*--------------------------------------------------------------------

T← (Fetch← ID)+1, StkP+1, Branch[LDBM1];
:IfMEP;
T← (Fetch← ID)+1, Stack&+1← MD, Branch[LDBM1];
T← (Fetch← ID)+1, StkP+2, Branch[LDBM1];
:EndIf;

LDBM1:
Fetch← T, T← Stack&+1← MD, IFUNext1;


*------------------------------------------------------------------
IFUR[SLDB, 2, L];
* Store Local Double Byte:
* StoreMDS[L+alpha+1]↑ ← Pop[]; StoreMDS[L+alpha]↑ ← Pop[];
IFUR[SGDB, 2, G];
* Store Global Double Byte:
* StoreMDS[G+alpha+1]↑ ← Pop[]; StoreMDS[G+alpha]↑ ← Pop[];
* This microcode is also the tail of WDBL.
*-------------------------------------------------------------------

StkP-1, Branch[SDBM2];
:IfMEP;
T← (Store← ID)+1, DBuf← T, Stack← MD, Branch[SDBM1];
:EndIf;
SDBM2:
T← (Store← ID)+1, DBuf← Stack&+1, Branch[SDBM1];

SDBM1:
Store← T, DBuf← Stack&-2, IFUNext0CF;

* Stack maintenance

*-----------------------------------------------------------
IFUR[PUSH, 1, L];
* Push: SP ← SP+1;
* This is legal (to a maximum of two levels):
*
1. After instructions that only pop the stack (i.e., that don’t
*
push any results onto it), or
*
2. After instructions that explicitly leave results above TOS
*
(e.g., DIV).
* Entry 1 is not possible because it implies that rule 1 has been violated.
*-----------------------------------------------------------

StkP+1, IFUNext0;
:IfMEP;
Branch[.], Breakpoint;
StkP+2, IFUNext0;
:EndIf;


*-----------------------------------------------------------
IFUR[POP, 1, L];
* Pop: SP ← SP-1;
*-----------------------------------------------------------

StkP-1, IFUNext0;
:IfMEP;
Stack&-1← MD, IFUNext0;
IFUNext0;
:EndIf;


*-----------------------------------------------------------
IFUR[EXCH, 1, L];
* Exchange: v ← Pop[]; u ← Pop[]; Push[v]; Push[u];
*-----------------------------------------------------------

T← Stack&-1, Branch[EXCHM2];
:IfMEP;
Stack&-1← T← MD, Branch[.+1];
:EndIf;
EXCHM2:
Stack&+1← T, Q← Stack&+1, Branch[EXCHM1];

EXCHM1:
StackT← Q, IFUNext2;


*-----------------------------------------------------------
IFUR[DUP, 1, L];
* Duplicate: u ← Pop[]; Push[u]; Push[u];
*-----------------------------------------------------------

Stack+1← Stack&+1, IFUNext0;
:IfMEP;
T← Stack&+1← MD, IFUNext1;
Stack+2← T, IFUNext0;
:EndIf;

*-----------------------------------------------------------
IFUR[NILCK, 1, L];
* NIL Check:
* p: POINTER ← Pop[]; Push[p]; IF p=NIL THEN PointerTrap[];
*-----------------------------------------------------------

PD← Stack, Branch[NILCKM1];
:IfMEP;
Stack← PD← MD, Branch[NILCKM1];
PD← T, StkP+1, Branch[NILCKM1];
:EndIf;

NILCKM1:
T← sPointerFault, DblBranch[DoFaultT, NoFaultF, ALU=0];


*-----------------------------------------------------------
IFUR[NILCKL, 1, L];
* NIL Check Long:
* p: LONG POINTER ← PopLong[]; PushLong[p]; IF p=NIL THEN PointerTrap[];
*-----------------------------------------------------------

T← Stack&-1, Branch[NILCKLM2];
:IfMEP;
PD← T OR MD, Stack← MD, Branch[NILCKM1];
:EndIf;
NILCKLM2: PD← T OR (Stack&+1), Branch[NILCKM1];


*-----------------------------------------------------------
IFUR[BNDCK, 1, L];
* Bounds Check:
* v: CARDINAL ← Pop[]; u: CARDINAL ← Pop[]; Push[u];
* IF u>=v THEN BoundsTrap[];
*-----------------------------------------------------------

T← Stack&-1, Branch[BNDCKM2];
:IfMEP;
PD← MD-T-1, Stack&-1← MD, Branch[BNDCKM1];
:EndIf;
BNDCKM2: PD← T-(Stack)-1, Branch[BNDCKM1];

BNDCKM1:
* Carry <=> TOS<x
T← sBoundsFault, DblBranch[DoFaultT, NoFaultF, Carry’];
NoFaultF:
StackT← StackT, IFUNext2;
DoFaultT:
Branch[SavePCAndTrap];

*-----------------------------------------------------------
IFUR[RR, 2, L];
* Read Register: Push[Register[alpha]];
* If alpha is out of bounds, pushes 0.
*-----------------------------------------------------------
Set[nRRegs, IfE[AltoMode, 0, 11, 7]];
* Number of defined registers

T← (ID)-(Add[nRRegs]C), StkP+1, Branch[RRM1];
:IfMEP;
T← (ID)-(Add[nRRegs]C), Stack&+1← MD, Branch[RRM1];
T← (ID)-(Add[nRRegs]C), StkP+2, Branch[RRM1];
:EndIf;

RRM1:
T← T+(Add[nRRegs]C), Branch[RROutOfBounds, ALU>=0];
BigBDispatch← T;
Branch[RRTable];

RROutOfBounds:
T← A0, Branch[PushT];

*-----------------------------------------------------------
RRTable: DispTable[nRRegs];
:If[AltoMode];
********** Alto version **********
T← A0, Branch[PushT];* 0 undefined
T← WDC, Branch[PushT];* 1 WDC
T← XTSReg, Branch[PushT];* 2 Xfer trap state
T← A0, Branch[PushT];* 3 Xfer trap parameter -- unimplemented
T← ATPReg, Branch[PushT];* 4 Alloc trap parameter
T← OTPReg, Branch[PushT];* 5 Other trap parameter
T← MDSHi, Branch[PushT];* 6 high part of MDS
:Else;
******** PrincOps version ********
T← CurrentPSB, Branch[PushT];* 0 current PSB
T← WDC, Branch[PushT];* 1 WDC
T← XTSReg, Branch[PushT];* 2 Xfer trap state
T← A0, Branch[PushT];* 3 undefined
T← A0, Branch[PushT];* 4 undefined
T← A0, Branch[PushT];* 5 undefined
T← MDSHi, Branch[PushT];* 6 high part of MDS
T← A0, Branch[PushT];* 7 undefined
T← CurrentTime, Branch[PushT];* 10 process time in ticks
:EndIf;
**********************************
*-----------------------------------------------------------

*-----------------------------------------------------------
IFUR[WR, 2, L];
* Write Register: Register[alpha] ← Pop[];
* If alpha is out of bounds, pops argument and does nothing else.
*-----------------------------------------------------------
Set[nWRegs, IfE[AltoMode, 0, 11, 3]];
* Number of defined registers

T← (ID)-(Add[nWRegs]C), Branch[WRM1];
:IfMEP;
T← (ID)-(Add[nWRegs]C), Stack← MD, Branch[WRM1];
T← (ID)-(Add[nWRegs]C), StkP+1, Branch[WRM1];
:EndIf;

WRM1:
T← T+(Add[nWRegs]C), Branch[WROutOfBounds, ALU>=0];
BigBDispatch← T;
T← Stack&-1, Branch[WRTable];

WROutOfBounds:
IFUNext0;

*-----------------------------------------------------------
WRTable: DispTable[nWRegs];
:If[AltoMode];
********** Alto version **********
IFUNext0;* 0 undefined
WDC← T+1, Branch[DWDCM1];* 1 WDC
XTSReg← T, IFUNext0;* 2 Xfer trap state
:Else;
******** PrincOps version ********
CurrentPSB← T, IFUNext0;* 0 current PSB
WDC← T, Reschedule, IFUNext0;* 1 WDC
XTSReg← T, IFUNext0;* 2 Xfer trap state
MDSHi← T, Call[SetMDS];* 3 high part of MDS
IFUNext0;* 4 undefined
IFUNext0;* 5 undefined
IFUNext0;* 6 undefined
IFUNext0;* 7 undefined
CurrentTime← T, IFUNext0;* 10 current process time
*-----------------------------------------------------------

Subroutine;
SetMDS:
T← Link;
TopLevel;
MemBase← G, Call[SetMDSBRHi];
MemBase← L, Call[SetMDSBRHi];
MemBase← SD, Call[SetMDSBRHi];
MemBase← MDS;
Link← T, Branch[SetMDSBRHi];

Subroutine;

SetMDSBRHi:
BRHi← MDSHi, Return;

TopLevel;

:EndIf;
**********************************