*-----------------------------------------------------------
Title[DMesaArith...July 8, 1980 4:27 PM...Taft];
* Arithmetic and logical operations
*-----------------------------------------------------------
%
CONTENTS, by order of occurrence

NOOPDo nothing
ADD, SUBBinary arithmetic operations
AND, OR, XORLogical operations
DBL, NEG, INCUnary operations
SHIFTLeft and right shifts
MUL, DIV, LDIVMultiply and divide
DADD, DSUBDouble-precision add and substract
DCOMP, DUCOMPDouble-precision compare and unsigned compare
%


*-----------------------------------------------------------
IFUR[NOOP, 1, L];
* No-op
* Alto Mesa: prevent an interrupt from occurring immediately after a NOOP.
* This is to ensure no interrupt between XFER and the first "useful"
* instruction transferred to by XFER.
*-----------------------------------------------------------

T← NOT (PCX’), DblBranch[NoopResc, NoopExit, Reschedule];
:IfMEP;
T← NOT (PCX’), Stack← MD, DblBranch[NoopResc, NoopExit, Reschedule];
T← NOT (PCX’), StkP+1, DblBranch[NoopResc, NoopExit, Reschedule];
:EndIf;

NoopExit:
IFUNext0;
NoopResc:
T← T+1, NoReschedule;* T← PCX+1
PCF← T;
Reschedule, Branch[NoopExit];

*-----------------------------------------------------------
IFUR[ADD, 1, L];
* t ← Pop[]; s ← Pop[]; Push[s+t];
IFUR[ADD01, 1, L];
* Same as Add -- Alto Mesa only
*-----------------------------------------------------------

T← Stack&-1, Branch[ADDM2];
:IfMEP;
Stack-1← T+MD, IFUNext0;
:EndIf;
ADDM2:
StackT← (StackT)+T, IFUNext2;


*-----------------------------------------------------------
IFUR[SUB, 1, L];
* t ← Pop[]; s ← Pop[]; Push[s-t];
*-----------------------------------------------------------

T← Stack&-1, Branch[SUBM2];
:IfMEP;
Stack-1← T-MD, IFUNext0;
:EndIf;
SUBM2:
StackT← (StackT)-T, IFUNext2;


*-----------------------------------------------------------
IFUR[AND, 1, L];
* v ← Pop[]; u ← Pop[]; Push[BitAnd[u, v]];
*-----------------------------------------------------------

T← Stack&-1, Branch[ANDM2];
:IfMEP;
Stack-1← T AND MD, IFUNext0;
:EndIf;
ANDM2:
StackT← (StackT) AND T, IFUNext2;


*-----------------------------------------------------------
IFUR[OR, 1, L];
* v ← Pop[]; u ← Pop[]; Push[BitOr[u, v]];
*-----------------------------------------------------------

T← Stack&-1, Branch[ORM2];
:IfMEP;
Stack-1← T OR MD, IFUNext0;
:EndIf;
ORM2:
StackT← (StackT) OR T, IFUNext2;


*-----------------------------------------------------------
IFUR[XOR, 1, L];
* v ← Pop[]; u ← Pop[]; Push[BitXor[u, v]];
*-----------------------------------------------------------

T← Stack&-1, Branch[XORM2];
:IfMEP;
Stack-1← T XOR MD, IFUNext0;
:EndIf;
XORM2:
StackT← (StackT) XOR T, IFUNext2;


*-----------------------------------------------------------
IFUR[DBL, 1, L];
* u ← Pop[]; Push[BitShift[u, 1]];
*-----------------------------------------------------------

StackT← (StackT) LSH 1, IFUNext2;
:IfMEP;
T← Stack&-1← MD LSH 1, IFUNext2;
Stack+1← T+T, IFUNext0;
:EndIf;

*-----------------------------------------------------------
IFUR[NEG, 1, L, N[0]];
* j: INTEGER ← Pop[]; Push[-j];
*-----------------------------------------------------------

StackT← (ID)-(StackT), IFUNext2;
:IfMEP;
T← Stack&-1← (ID)-MD, IFUNext2;
Stack+1← (ID)-T, IFUNext0;
:EndIf;


*-----------------------------------------------------------
IFUR[INC, 1, L];
* s: CARDINAL ← Pop[]; Push[s+1];
*-----------------------------------------------------------

StackT← (StackT)+1, IFUNext2;
:IfMEP;
T← Stack&-1← MD+1, IFUNext2;
Stack+1← T+1, IFUNext0;
:EndIf;


*-----------------------------------------------------------
IFUR[SHIFT, 1, L];
* shift: INTEGER ← Pop[]; u: UNSPECIFIED ← Pop[]; Push[BitShift[u, shift]];
* Shifts left if shift>0, right if shift<0.
*-----------------------------------------------------------

T← Stack&-1, Branch[SHIFTM1];
:IfMEP;
T← PD← MD, StkP-1, Branch[SHIFTM1];
PD← T, Branch[SHIFTM1];
:EndIf;

SHIFTM1:
* If left shift (x >= 0): LCY[T, R, x mod 20b]
* If right shift (x < 0): LCY[R, T, x mod 20b]
RTemp0← LSH[T, 10], Branch[.+2, ALU<0]; * Position x to count field
PD← (17S)-T, Branch[.+2];* Test for x > 15
PD← (17S)+T;* Test for x < -15
RTemp0← (RTemp0) XOR (20000C), Branch[ShiftGr15, ALU<0];
T← A0, ShC← RTemp0;
StackT← ShiftNoMask[StackT], IFUNext2;
ShiftGr15:
StackT← A0, IFUNext2;

*-----------------------------------------------------------
IFUR[MUL, 1, L];
* Multiply
* t: CARDINAL ← Pop[]; s: CARDINAL ← Pop[]; PushLong[LONG[s]*t]; [] ← Pop[];
* Note: computes 32-bit result and leaves high word above TOS.
*-----------------------------------------------------------

Q← Stack&-1, Branch[MULM1];
:IfMEP;
Q← MD, StkP-1, Branch[MULM1];
Q← T, Branch[MULM1];
:EndIf;

MULM1:
T← Stack&+1, Call[MulSub];* T,,Q ← Q*T
Stack&-1← T;
StackT← Q, IFUNext2;


*-----------------------------------------------------------
IFUR[DIV, 1, L];
* Unsigned divide
* t: CARDINAL ← Pop[]; s: CARDINAL ← Pop[];
* IF t=0 THEN ZeroDivisor[];
-- test not implemented in Alto Mesa 5.0
* Push[s/t]; Push[s MOD t]; [] ← Pop[];
*-----------------------------------------------------------

MulDivArg← Stack&-1, Branch[DIVM1];
:IfMEP;
MulDivArg← MD, StkP-1, Branch[DIVM1];
MulDivArg← T, Branch[DIVM1];
:EndIf;

DIVM1:
T← A0, Branch[LDIVM2];


*-----------------------------------------------------------
IFUR[LDIV, 1, L];
* t: CARDINAL ← Pop[]; s: LONG CARDINAL ← PopLong[];
* IF t=0 THEN ZeroDivisor[];
-- tests not implemented in Alto Mesa 5.0
* IF HighHalf[s]>=t THEN DivideCheck[];
* Push[LowHalf[s/LONG[t]]; Push[LowHalf[s MOD LONG[t]]; [] ← Pop[];
*-----------------------------------------------------------

MulDivArg← Stack&-1, Branch[LDIVM1];
:IfMEP;
Stack← MD, Branch[.-1];
MulDivArg← T, Branch[LDIVM1];
:EndIf;

LDIVM1:
T← Stack&-1;

* DivSub computes [Q: quotient, T: remainder] ← (T,,Q) / MulDivArg
* DivSub returns +1 normally, +2 if an overflow occurred.

:If[AltoMode];
********** Alto version **********
LDIVM2:
Q← Stack&+1, Call[DivSub];
Stack&-1← T, DispTable[1, 1, 1]; * Leave remainder above TOS;
* ignore overflow return branch
:Else;
******** PrincOps version ********
LDIVM2:
Q← Stack&+1, SCall[DivSub];
Stack&-1← T, Branch[.+2];* Leave remainder above TOS
StkP-2, Branch[SavePCAndTrap];* Failure: T has trap code
:EndIf;
**********************************

StackT← Q, IFUNext2;* Quotient

*-----------------------------------------------------------
IFUR[DADD, 1, L];
* Double Add
* t: LONG CARDINAL ← PopLong[]; s: LONG CARDINAL ← PopLong[];
* r: LONG CARDINAL ← s+t; PushLong[r];
* Push[IF r<s THEN 1 ELSE 0]; [] ← Pop[]; -- not implemented in Mesa 5.0
* The last statement saves the carry bit above TOS.
*-----------------------------------------------------------

T← Stack&-1, Branch[DADDM2];
:IfMEP;
T← MD, Q← T, StkP-3, Branch[DADDM1];
:EndIf;
DADDM2:
Q← Stack&-2, Branch[DADDM1];

DADDM1:
Stack&+1← (Stack&+1)+Q;*y+w
StackT← (StackT)+T, XorSavedCarry, IFUNext2;


*-----------------------------------------------------------
IFUR[DSUB, 1, L];
* Double Subtract
* t: LONG CARDINAL ← PopLong[]; s: LONG CARDINAL ← PopLong[];
* r: LONG CARDINAL ← s-t; PushLong[r];
* Push[IF r<s THEN 0 ELSE 1]; [] ← Pop[]; -- not implemented in Mesa 5.0
* The last statement saves the carry bit above TOS.
*-----------------------------------------------------------

T← Stack&-1, Branch[DSUBM2];
:IfMEP;
T← MD, Q← T, StkP-3, Branch[DSUBM1];
:EndIf;
DSUBM2:
Q← Stack&-2, Branch[DSUBM1];

DSUBM1:
Stack&+1← (Stack&+1)-Q;
StackT← (StackT)-T-1, XorSavedCarry, IFUNext2;

*-----------------------------------------------------------
IFUR[DCOMP, 1, L];
* Signed double precision compare
* k: LONG INTEGER ← PopLong[]; j: LONG INTEGER ← PopLong[];
* Push[SELECT TRUE FROM
* j<k => -1,
* j=k => 0,
* j>k => 1,
* ENDCASE];
*-----------------------------------------------------------

T← (Stack&-2) XOR (100000C), Branch[DCOMPM1];
:IfMEP;
Stack← MD, Branch[.-1];
T← T XOR (100000C), StkP-1, Branch[DCOMPM1];
:EndIf;

DCOMPM1:
* Complement the signs of the 32-bit operands, then do an unsigned compare.
Stack← (Stack) XOR (100000C), Branch[DUCOMPM1];


*-----------------------------------------------------------
IFUR[DUCOMP, 1, L];
* Unsigned double precision compare
* t: LONG CARDINAL ← PopLong[]; s: LONG CARDINAL ← PopLong[];
* Push[SELECT TRUE FROM
* s<t => -1,
* s=t => 0,
* s>t => 1,
* ENDCASE];
*-----------------------------------------------------------

T← Stack&-2, Branch[DUCOMPM1];
:IfMEP;
T← MD, StkP-2, Branch[DUCOMPM1];
StkP-1, Branch[DUCOMPM1];
:EndIf;

DUCOMPM1:
PD← (Stack&+1)-T;* PD← z-x (compare high parts)
T← B← Stack&-2, Branch[.+2, ALU=0];
DblBranch[DUCOMPpos, DUCOMPneg, Carry];

PD← (Stack)-T;* PD← w-y (compare low parts)
DUCOMPlow:
Branch[.+2, ALU=0];
DblBranch[DUCOMPpos, DUCOMPneg, Carry];

StackT← A0, IFUNext2;
DUCOMPneg:
StackT← 177777C, IFUNext2;
DUCOMPpos:
StackT← 1C, IFUNext2;