*----------------------------------------------------------- Title[Stack.mc...November 23, 1982 5:12 PM...Taft]; * Stack instructions (PrincOps, chapter 5) *----------------------------------------------------------- % CONTENTS, by order of occurence Stack primitives REC Recover REC2 Recover Two DIS Discard DIS2 Discard Two EXCH Exchange DEXCH Double Exchange DUP Duplicate DDUP Double Duplicate EXDIS Exchange Discard Check instructions BNDCK Bounds Check NILCKL Nil Check Long Unary operations NEG Negate INC Increment DINC Double Increment ADDSB Add Signed Byte DEC Decrement DBL Double DDBL Double Double TRPL Triple LINT Lengthen Integer SHIFTSB Shift Signed Byte Logical operations AND And DAND Double And IOR Inclusive Or DIOR Double Inclusive Or XOR Exclusive Or DXOR Double Exclusive Or SHIFT Shift DSHIFT Double Shift ROTATE Rotate Arithmetic operations ADD Add SUB Subtract DADD Double Add DSUB Double Subtract ADC Add Double to Cardinal ACD Add Cardinal to Double MUL Multiply DMUL Double Multiply (not implemented) SDIV Signed Divide UDIV Unsigned Divide LUDIV Long Unsigned Divide SDDIV Signed Double Divide (not implemented) UDDIV Unsigned Double Divide (not implemented) DCMP Double Compare UDCMP Unsigned Double Compare % TopLevel; *----------------------------------------------------------- IFUR[REC, 1]; * Recover * 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). *----------------------------------------------------------- StkP+1, NextOpcode; *----------------------------------------------------------- IFUR[REC2, 1]; * Recover Two * SP ← SP+2; *----------------------------------------------------------- StkP+2, NextOpcode; *----------------------------------------------------------- IFUR[DIS, 1]; * Discard * SP ← SP-1; *----------------------------------------------------------- StkP-1, NextOpcode; *----------------------------------------------------------- IFUR[DIS2, 1]; * Discard Two * SP ← SP-2; *----------------------------------------------------------- StkP-2, NextOpcode; *----------------------------------------------------------- IFUR[EXCH, 1]; * Exchange * v: UNSPECIFIED ← Pop[]; u: UNSPECIFIED ← Pop[]; Push[v]; Push[u]; *----------------------------------------------------------- T← Stack&-1, Call[StackSwap]; StackGetsQ: Stack← Q, NextOpcode; *----------------------------------------------------------- IFUR[DEXCH, 1]; * Double Exchange * v: LONG UNSPECIFIED ← PopLong[]; u: LONG UNSPECIFIED ← PopLong[]; * PushLong[v]; PushLong[u]; *----------------------------------------------------------- T← Stack&-2, Call[StackSwap]; T← Stack&-2; Stack&+2← T, Cnt← Stack&+2; Stack&+1← Cnt, Branch[StackGetsQ]; Subroutine; StackSwap: Stack&+1← T, Q← Stack&+1, Return; TopLevel; *----------------------------------------------------------- IFUR[DUP, 1]; * Duplicate * u: UNSPECIFIED ← Pop[]; Push[u]; Push[u]; *----------------------------------------------------------- Stack+1← Stack&+1, NextOpcode; *----------------------------------------------------------- IFUR[DDUP, 1]; * Double Duplicate * u: LONG UNSPECIFIED ← PopLong[]; PushLong[u]; PushLong[u]; *----------------------------------------------------------- T← Stack&-1; Stack+2← Stack&+2, Branch[ExitPushT]; *----------------------------------------------------------- IFUR[EXDIS, 1]; * Exchange Discard * u: UNSPECIFIED ← Pop[]; [] ← Pop[]; Push[u]; *----------------------------------------------------------- Stack-1← Stack&-1, NextOpcode; *----------------------------------------------------------- IFUR[BNDCK, 1]; * Bounds Check * range: CARDINAL ← Pop[]; index: CARDINAL ← Pop[]; Push[index]; * IF index>=range THEN BoundsTrap[]; *----------------------------------------------------------- T← Stack&-1; PD← T-(Stack)-1; * Carry← 1 iff index<range T← sBoundsTrap, DblBranch[DoFaultT, NoFaultF, Carry']; *----------------------------------------------------------- NewOp; ESCEntry[NILCKL], * NIL Check Long * p: LONG POINTER ← PopLong[]; PushLong[p]; IF p=NIL THEN PointerTrap[]; *----------------------------------------------------------- T← Stack&-1; PD← T OR (Stack&+1); T← sPointerTrap, DblBranch[DoFaultT, NoFaultF, ALU=0]; NoFaultF: NextOpcode; DoFaultT: Branch[SavePCAndTrap]; *----------------------------------------------------------- IFUR[NEG, 1, N[0]]; * Negate * i: INTEGER ← Pop[]; Push[-i]; *----------------------------------------------------------- Stack← (ID)-(Stack), NextOpcode; *----------------------------------------------------------- IFUR[INC, 1, N[1]]; * Increment * s: CARDINAL ← Pop[]; Push[s+1]; IFUR[ADDSB, 2, SignExtend]; * Add Signed Byte * i: INTEGER ← Pop[]; Push[i+SignExtend[GetCodeByte[]]]; *----------------------------------------------------------- Stack← (ID)+(Stack), NextOpcode; *----------------------------------------------------------- IFUR[DINC, 1, N[1]]; * Double Increment * s: LONG CARDINAL ← PopLong[]; PushLong[s+1]; *----------------------------------------------------------- T← ID, StkP-1, Branch[ADCTail]; *----------------------------------------------------------- IFUR[DEC, 1]; * Decrement * s: CARDINAL ← Pop[]; Push[s-1]; *----------------------------------------------------------- Stack← (Stack)-1, NextOpcode; *----------------------------------------------------------- IFUR[DBL, 1]; * Double * u: UNSPECIFIED ← Pop[]; Push[Shift[u, 1]]; *----------------------------------------------------------- Stack← (Stack)+(Stack), NextOpcode; *----------------------------------------------------------- IFUR[DDBL, 1]; * Double Double * u: LONG UNSPECIFIED ← PopLong[]; PushLong[LongShift[u, 1]]; *----------------------------------------------------------- T← Stack&-1; Stack&+1← (Stack&+1)+(Stack&+1), Branch[AddTail]; *----------------------------------------------------------- IFUR[TRPL, 1]; * Triple * s: CARDINAL ← Pop[]; Push[s*3]; *----------------------------------------------------------- T← (A← Stack) LSH 1, Branch[AddTail]; * Carry← 0 *----------------------------------------------------------- NewOp; ESCEntry[LINT]; * Lengthen Integer * i: INTEGER ← Pop[]; Push[i]; Push[IF i<0 THEN -1 ELSE 0]; *----------------------------------------------------------- T← RSH[Stack&+1, 17]; Stack← (0S)-T, NextOpcode; *----------------------------------------------------------- IFUR[SHIFTSB, 2, SignExtend]; * Shift Signed Byte * u: UNSPECIFIED ← Pop[]; shift: INTEGER ← SignExtend[GetCodeByte]; * IF shift NOT IN [-15..15] THEN ERROR; -- asserted, not required to be checked * Push[Shift[u, shift]]; *----------------------------------------------------------- T← ID, Branch[ShiftStackByT]; *----------------------------------------------------------- IFUR[AND, 1]; * And * v: UNSPECIFIED ← Pop[]; u: UNSPECIFIED ← Pop[]; Push[And[u, v]]; *----------------------------------------------------------- T← Stack&-1; AndTail: Stack← (Stack) AND T, NextOpcode; *----------------------------------------------------------- NewOp; ESCEntry[DAND]; * Double And * v: LONG UNSPECIFIED ← PopLong[]; u: LONG UNSPECIFIED ← PopLong[]; * PushLong[LongAnd[u, v]]; *----------------------------------------------------------- T← Stack&-1, Call[QGStackPop2]; Stack&+1← (Stack&+1) AND Q, Branch[AndTail]; *----------------------------------------------------------- IFUR[IOR, 1]; * Inclusive Or * v: UNSPECIFIED ← Pop[]; u: UNSPECIFIED ← Pop[]; Push[Or[u, v]]; *----------------------------------------------------------- T← Stack&-1; IorTail: Stack← (Stack) OR T, NextOpcode; *----------------------------------------------------------- NewOp; ESCEntry[DIOR]; * Double Inclusive Or * v: LONG UNSPECIFIED ← PopLong[]; u: LONG UNSPECIFIED ← PopLong[]; * PushLong[LongOr[u, v]]; *----------------------------------------------------------- T← Stack&-1, Call[QGStackPop2]; Stack&+1← (Stack&+1) OR Q, Branch[IorTail]; *----------------------------------------------------------- NewOp; ESCEntry[XOR], * Exclusive Or * v: UNSPECIFIED ← Pop[]; u: UNSPECIFIED ← Pop[]; Push[Xor[u, v]]; *----------------------------------------------------------- T← Stack&-1; XorTail: Stack← (Stack) XOR T, NextOpcode; *----------------------------------------------------------- NewOp; ESCEntry[DXOR]; * Double Exclusive Or * v: LONG UNSPECIFIED ← PopLong[]; u: LONG UNSPECIFIED ← PopLong[]; * PushLong[LongXor[u, v]]; *----------------------------------------------------------- T← Stack&-1, Call[QGStackPop2]; Stack&+1← (Stack&+1) XOR Q, Branch[XorTail]; *----------------------------------------------------------- IFUR[SHIFT, 1]; * Shift * shift: INTEGER ← Pop[]; u: UNSPECIFIED ← Pop[]; Push[Shift[u, shift]]; * Shifts left if shift>0, right if shift<0. *----------------------------------------------------------- T← Stack&-1; * If left shift (shift >= 0): LCY[T, R, shift mod 20B] -- T=0 in both cases * If right shift (shift < 0): LCY[R, T, shift mod 20B] ShiftStackByT: RTemp0← LSH[T, 10], Branch[.+2, ALU<0]; * Position shift to count field PD← (17S)-T, Branch[.+2]; * Test for shift > 15 PD← (17S)+T; * Test for shift < -15 T← (RTemp0) XOR (20000C), Branch[ShiftGr15, ALU<0]; ShiftStackWithShCT: T← A0, ShC← T; ShiftTail: Stack← ShiftNoMask[Stack]; RestoreStdShC: ShC← StdShC, NextOpcode; * |Shift| > 15 ShiftGr15: Stack← A0, NextOpcode; *----------------------------------------------------------- NewOp; ESCEntry[DSHIFT], * Double Shift * shift: INTEGER ← Pop[]; u: LONG UNSPECIFIED ← PopLong[]; PushLong[LongShift[u, shift]]; *----------------------------------------------------------- RTemp0← T; * Placement; ESCEntry: T = STK[StkP] T← T+(37C), StkP-2; * See if shift IN [-37B..37B] PD← T-(77C); T← DPF[RTemp0, 4, 10], * Position shift to ShC count field Branch[DShiftZero, Carry]; * Branch if out of range RTemp0← LSH[RTemp0, 13], * Position 20 bit to sign Branch[DShiftRight, R<0]; * Branch if shift negative * Left shift. Set up ShC for LCY[T, R, shift MOD 20B] T← T OR (20000C); T← A0, ShC← T, RTemp0, DblBranch[DShL0to17, DShL20to37, R>=0]; * Right shift. Set up ShC for LCY[R, T, shift MOD 20B] DShiftRight: T← T OR (10000C), StkP+1; T← A0, ShC← T, RTemp0, DblBranch[DShR1to17, DShR20to37, R<0]; * Shift IN [0..17] (left shift). LCY[T, R, shift MOD 20B]. * StkP addresses low-order word; T=0 DShL0to17: Stack&+1← ShiftNoMask[Stack&+1], Q← Stack&+1; * low← LCY[0, low, shift MOD 20B] T← Q, Branch[ShiftTail]; * T← low; high← LCY[low, high, shift MOD 20B] * Shift IN [20..37] (left shift). LCY[T, R, shift MOD 20B]. * StkP addresses low-order word DShL20to37: T← Stack&+1← A0, Q← Stack&+1; * low← 0 Stack← Q, Branch[ShiftTail]; * high← low; high← LCY[0, low, shift MOD 20B] * Shift IN [-1..-20] (right shift). LCY[R, T, shift MOD 20B]. * StkP addresses high-order word; T=0 DShR1to17: Stack&-1← ShiftNoMask[Stack&-1], Q← Stack&-1; * high← LCY[high, 0, shift MOD 20B] T← Q; * T← high RShiftTail: Stack&+1← ShiftNoMask[Stack&+1], * low← LCY[low, high, shift MOD 20B] Branch[RestoreStdShC]; * Shift IN [-21..-37] (right shift). LCY[R, T, shift MOD 20B]. * StkP addresses high-order word DShR20to37: T← Stack&-1← A0, Q← Stack&-1; * high← 0 Stack← Q, Branch[RShiftTail]; * low← high; low← LCY[high, 0, shift MOD 20B] * Shift NOT IN [-37B..37B]. Just set the answer to zero. DShiftZero: Stack← T← A0, Branch[ExitPushT]; *----------------------------------------------------------- NewOp; ESCEntry[ROTATE]; * Rotate * rotate: INTEGER ← Pop[]; u: UNSPECIFIED ← Pop[]; Push[Rotate[u, shift]]; * Rotates left if shift>0, right if shift<0. *----------------------------------------------------------- * Set to perform LCY[R, R, shift mod 20B] T← DPF[Stack&-1, 4, 10], Branch[ShiftStackWithShCT]; *----------------------------------------------------------- IFUR[ADD, 1]; * Add * t: CARDINAL ← Pop[]; s: CARDINAL ← Pop[]; Push[s+t]; *----------------------------------------------------------- T← A← Stack&-1; * Carry← 0 (so AddTail can be used by DADD) AddTail: Stack← (Stack)+T, XorSavedCarry, NextOpcode; *----------------------------------------------------------- IFUR[SUB, 1]; * Subtract * t: CARDINAL ← Pop[]; s: CARDINAL ← Pop[]; Push[s-t]; *----------------------------------------------------------- T← (Stack&-1)-(0C); * Carry← 1 (so SubTail can be used by DSUB) SubTail: Stack← (Stack)-T-1, XorSavedCarry, NextOpcode; *----------------------------------------------------------- IFUR[DADD, 1]; * Double Add * t: LONG CARDINAL ← PopLong[]; s: LONG CARDINAL ← PopLong[]; PushLong[s+t]; *----------------------------------------------------------- T← Stack&-1, Call[QGStackPop2]; DAddTail: Stack&+1← (Stack&+1)+Q, Branch[AddTail]; *----------------------------------------------------------- IFUR[DSUB, 1]; * Double Subtract * t: LONG CARDINAL ← PopLong[]; s: LONG CARDINAL ← PopLong[]; PushLong[s-t]; *----------------------------------------------------------- T← Stack&-1, Call[QGStackPop2]; Stack&+1← (Stack&+1)-Q, Branch[SubTail]; *----------------------------------------------------------- IFUR[ADC, 1]; * Add Double to Cardinal * t: CARDINAL ← Pop[]; s: LONG CARDINAL ← PopLong[]; PushLong[s+LONG[t]]; *----------------------------------------------------------- T← Stack&-2; ADCTail: * Here from DINC Stack&+1← (Stack&+1)+T; Stack← A← Stack, XorSavedCarry, NextOpcode; *----------------------------------------------------------- IFUR[ACD, 1]; * Add Cardinal to Double * t: LONG CARDINAL ← PopLong[]; s: CARDINAL ← Pop[]; PushLong[LONG[s]+t]; *----------------------------------------------------------- T← Stack&-1; Stack&-1← A0, Q← Stack&-1, Branch[DAddTail]; *----------------------------------------------------------- QGStackPop2: * Executes "Q← Stack&-2" * Common part of setup for several Double logical and arithmetic instructions. *----------------------------------------------------------- Subroutine; Q← Stack&-2, Return; TopLevel; *----------------------------------------------------------- IFUR[MUL, 1]; * 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; T← Stack&+1, Call[MulSub]; * T,,Q ← Q*T Stack&-1← T, Branch[StackGetsQ], DispTable[1, 2, 2]; * Squash leftover Multiply dispatch *----------------------------------------------------------- ESCOpcodeUnimpl[DMUL]; * Double Multiply * t: LONG CARDINAL ← PopLong[]; s: LONG CARDINAL ← PopLong[]; * PushLong[LONG[s]*t]; * Note: returns only low 32 bits of (potentially) 64-bit result. *----------------------------------------------------------- *----------------------------------------------------------- MulSub: * Unsigned 16-bit by 16-bit multiply subroutine * Entry conditions: * T = multiplicand * Q = multiplier * Exit conditions: * T = high-order 16 bits of product * Q = low-order 16 bits of product * May leave a Q[14] dispatch pending, which must be squashed by the caller. * Clobbers MulDivArg *----------------------------------------------------------- Subroutine; MulDivArg← Q; MulDivArg, Cnt← 16S, Branch[.+2, R odd]; MulDivArg← A0, Multiply, Branch[M0]; MulDivArg← A0, Multiply, Branch[M1]; *----------------------------------------------------------- DispTable[4]; * here after Q[14] was 0 (no add) and continue M0: MulDivArg← (A← MulDivArg), Multiply, DblBranch[M0E, M0, Cnt=0&-1]; * here after Q[14] was 0 (no add) and exit M0E: MulDivArg← (A← MulDivArg), Multiply, Branch[MXIT0]; * here after Q[14] was 1 (add) and continue M1: MulDivArg← (MulDivArg)+T, Multiply, DblBranch[M0E, M0, Cnt=0&-1]; * here after Q[14] was 1 (add) and exit MulDivArg← (MulDivArg)+T, Multiply, Branch[MXIT0]; *----------------------------------------------------------- * This squashes one Multiply dispatch, but there is still one pending. MXIT0: T← MulDivArg, DispTable[1, 2, 2], Return; TopLevel; *----------------------------------------------------------- NewOp; ESCEntry[SDIV]; * Signed Divide * k: INTEGER ← Pop[]; j: INTEGER ← Pop[]; * IF k=0 THEN DivZeroTrap[]; * Push[j/k]; Push[j MOD k]; [] ← Pop[]; *----------------------------------------------------------- MulDivArg← Stack&-1, Branch[.+2, R>=0]; MulDivArg← (0S)-(MulDivArg); * Divisor negative, make positive T← Stack&+1; RTemp0← (Stack&-1) XOR T, Branch[.+2, ALU>=0]; * Remember XOR of signs T← (0S)-T; * Dividend negative T← A0, Q← T; * DivSub computes [Q: quotient, T: remainder] ← (T,,Q) / MulDivArg * It does not return but traps directly if an overflow occurs. Call[DivSub]; Stack+1← T, Stack&+1, Branch[.+2, R>=0]; * Remainder should have sign of dividend Stack← (0S)-(Stack); T← Q, RTemp0, Branch[.+2, R>=0]; * Quotient sign should be XOR of operand signs T← (0S)-T; Stack-1← T, NextOpcode; *----------------------------------------------------------- NewOp; ESCEntry[UDIV], * Unsigned Divide * t: CARDINAL ← Pop[]; s: CARDINAL ← Pop[]; * IF t=0 THEN DivZeroTrap[]; * Push[s/t]; Push[s MOD t]; [] ← Pop[]; *----------------------------------------------------------- T← A0; MulDivArg← Stack&-1, Branch[DoLongUDiv]; *----------------------------------------------------------- NewOp; ESCEntry[LUDIV]; * Long Unsigned Divide * t: CARDINAL ← Pop[]; s: LONG CARDINAL ← PopLong[]; * IF t=0 THEN DivZeroTrap[]; * IF HighHalf[s]>=t THEN DivideCheckTrap[]; * Push[LowHalf[s/LONG[t]]; Push[LowHalf[s MOD LONG[t]]; [] ← Pop[]; *----------------------------------------------------------- MulDivArg← Stack&-1; T← Stack&-1; * DivSub computes [Q: quotient, T: remainder] ← (T,,Q) / MulDivArg * It does not return but traps directly if an overflow occurs. DoLongUDiv: Q← Stack&+1, Call[DivSub]; Stack&-1← T, Branch[StackGetsQ]; * Leave remainder above TOS *----------------------------------------------------------- ESCOpcodeUnimpl[SDDIV]; * Signed Double Divide * k: LONG INTEGER ← PopLong[]; j: LONG INTEGER ← PopLong[]; * IF k=0 THEN DivZeroTrap[]; * PushLong[j/k]; PushLong[j MOD k]; [] ← PopLong; *----------------------------------------------------------- *----------------------------------------------------------- ESCOpcodeUnimpl[UDDIV]; * Unsigned Double Divide * t: LONG CARDINAL ← PopLong[]; s: LONG CARDINAL ← PopLong[]; * IF t=0 THEN DivZeroTrap[]; * PushLong[s/t]; PushLong[s MOD t]; [] ← PopLong; *----------------------------------------------------------- *----------------------------------------------------------- DivSub: * Unsigned 32-bit by 16-bit divide * Enter: T,,Q = dividend * MulDivArg = divisor * Normal exit: T=remainder, Q=quotient * Failure: does not return but rather generates one of the following traps: * sDivZeroTrap division by zero * sDivCheckTrap high half of dividend >= divisor * Clobbers MulDivArg, DivTemp *----------------------------------------------------------- Subroutine; PD← T-(MulDivArg); * Trap if T >= MulDivArg (unsigned) PD← MulDivArg, Branch[DivTrap, Carry]; Cnt← 17S, PD← T, Branch[Dneg, ALU<0]; T← T-(MulDivArg), Divide, DblBranch[NormalExit, D3, Cnt=0&-1]; D2: T← T+(MulDivArg), Divide, Branch[NormalExit, Cnt=0&-1]; D3: Branch[D2, Carry']; T← T-(MulDivArg), Divide, Branch[D3, Cnt#0&-1]; NormalExit: Branch[DaddLabel, Carry']; T-(MulDivArg), Divide; T← T-(MulDivArg), DblBranch[FinalAdd, OKExit, ALU<0]; DaddLabel: T+(MulDivArg), Divide; T← T+(MulDivArg), Branch[FinalAdd, ALU<0]; OKExit: Return; FinalAdd: T← T+(MulDivArg), Return; Dneg: DivTemp← T+T, Branch[Dneg1, ALU<0]; Dneg0: T← A← T, Divide, Branch[Fudge2, Cnt=0&-1]; DivTemp← T+T, DblBranch[Dneg1, Dneg0, R<0]; Dneg1: T← T-(MulDivArg), Divide, Branch[Fudge3, Cnt=0&-1]; Dneg3: PD← T, Branch[.+2, Carry']; DivTemp← T+T, DblBranch[Dneg1, Dneg0, ALU<0]; T← T+(MulDivArg), Divide, Branch[Fudge4, Cnt=0&-1]; DnegG: PD← T, Branch[.+2, ALU>=0]; T← T-(MulDivArg), CDivide, DblBranch[Fudge4, DnegG, Cnt=0&-1]; DivTemp← T+T, DblBranch[Dneg1, Dneg0, ALU<0]; Fudge2: PD← T-(MulDivArg); Fudge21: Branch[F23, Carry]; F22: PD← A← T, Divide, Return; F23: PD← T-(MulDivArg), Divide, Branch[Fudge42]; Fudge3: PD← T-(MulDivArg), Branch[Fudge21, Carry]; PD← A← T, CDivide, Branch[FinalAdd]; Fudge4: PD← T-(MulDivArg), Branch[.+2, ALU<0]; DblBranch[F23, F22, Carry]; PD← T-(MulDivArg), CDivide; Fudge42: T← T-(MulDivArg), Return; TopLevel; DivTrap: Branch[.+2, ALU#0]; T← sDivZeroTrap, Branch[SavePCAndTrap]; T← sDivCheckTrap, Branch[SavePCAndTrap]; *----------------------------------------------------------- IFUR[DCMP, 1]; * Double Compare * t: LONG INTEGER ← PopLong[]; u: LONG INTEGER ← PopLong[]; * Push[SELECT TRUE FROM * s>t => 1, * s=t => 0, * s<t => -1, * ENDCASE]; *----------------------------------------------------------- * Complement the signs of both 32-bit operands, then do an unsigned compare. T← (Stack&-2) XOR (100000C); Stack&+1← (Stack&+1) XOR (100000C), Branch[UnsignedComp1]; *----------------------------------------------------------- IFUR[UDCMP, 1]; * Unsigned Double Compare * t: LONG CARDINAL ← PopLong[]; u: LONG CARDINAL ← PopLong[]; * Push[SELECT TRUE FROM * s>t => 1, * s=t => 0, * s<t => -1, * ENDCASE]; *----------------------------------------------------------- T← Stack&-1; * Compute s-t UnsignedComp1: T← Stack&-2, Q← T; T← (Stack&+1)-T; Stack← (Stack)-Q-1, XorSavedCarry; * Have carry out of last (high) subtraction iff s>=t T← (Stack&-1) OR T, Branch[.+2, Carry]; Stack← T-T-1, NextOpcode; * s<t, return -1 * T=0 iff s=t PD← T-1; * Carry out unless T=0 Stack← (ID)-1, XorSavedCarry, NextOpcode; * ID=1 here; return 0 or 1