*----------------------------------------------------------- Title[DMesaArith...July 8, 1980 4:27 PM...Taft]; * Arithmetic and logical operations *----------------------------------------------------------- % CONTENTS, by order of occurrence NOOP Do nothing ADD, SUB Binary arithmetic operations AND, OR, XOR Logical operations DBL, NEG, INC Unary operations SHIFT Left and right shifts MUL, DIV, LDIV Multiply and divide DADD, DSUB Double-precision add and substract DCOMP, DUCOMP Double-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 -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 -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; (1552)