{File name: Stack.mc Author: R. Garner, Created: 12 April 1979, Description: PrincOps version 3.0 microcode for Dandelion, (ADD, SUB, DADD, and DSUB based on Wildflower microcode by R. Levin, 18 Oct 1978), Daniels, 15-Jun-83 18:31:45 new instruction set Sandman, February 10, 1982 2:17 PM Restore stack on Divide traps, Sandman, January 25, 1982 1:55 PM Don't advance PC on NILCKL, Sandman, Dec 3, 1981 9:02 AM New instruction set, Last Edited: Jim Frandeen, March 26, 1981 3:16 PM: change SuppressTimingWarning to LOOPHOLE[niblTiming], Last Edited: Garner, April 8, 1980 5:29 PM, } { REC Recover REC2 Recover Two DIS Discard DIS2 Discard Two EXCH Exchange DEXCH Double Exchange DUP Duplicate DDUP Double Duplicate BNDCK Bounds Check NEG Negate INC Increment DEC Decrement ADDSB Add Signed Byte DINC Double Increment DBL Double DDBL Double Double TRPL Triple LINT Lengthen Integer (ESC opcode) AND And IOR Inclusive Or XOR Exclusive Or (ESC opcode) SHIFTSB Shift Signed Byte ROTATE Rotate SHIFT Shift DAND Double And DIOR Double Inclusive Or DXOR Double Exclusive Or DSHIFT Double Shift ADD Add SUB Subtract DADD Double Add DSUB Double Subtract ADC Add Double to Cardinal ACD Add Cardinal to Double MUL Multiply UDIV Unsigned Divide (ESC opcode) LUDIV Long Unsigned Divide (ESC opcode) DCMP Double Compare UDCMP Unsigned Double Compare } {***************************************************************************** REC *****************************************************************************} @REC: push, c1, opcode[242'b]; STK ← TOS, PC ← PC + PC16, IBDisp, push, GOTO[SLa], c2; {***************************************************************************** REC2 *****************************************************************************} @REC2: push, c1, opcode[243'b]; STK ← TOS, push, c2; TOS ← STK, pop, GOTO[@REC], c3; {***************************************************************************** DIS *****************************************************************************} @DIS: push, c1, opcode[244'b]; STK ← TOS, PC ← PC + PC16, IBDisp, pop, GOTO[SLa], c2; {***************************************************************************** DIS2 *****************************************************************************} @DIS2: push, c1, opcode[245'b]; STK ← TOS, pop, c2; TOS ← STK, pop, GOTO[@DIS], c3; {***************************************************************************** EXCH *****************************************************************************} @EXCH: T ← STK, fXpop, fZpop, push, GOTO[LIn], c1, opcode[246'b]; {***************************************************************************** DEXCH *****************************************************************************} @DEXCH: Rx ← STK, pop, c1, opcode[247'b]; Q ← STK, pop, c2; T ← STK, fXpop, push, c3; DDTail: STK ← Rx, push, c1; STK ← TOS, push, PC ← PC + PC16, IBDisp, c2; STK ← T, TOS ← Q, DISPNI[OpTable], c3; {***************************************************************************** DUP *****************************************************************************} @DUP: fXpop, push, c1, opcode[250'b]; PC ← PC+PC16, push, IBDisp, c2; STK ← TOS, push, fZpop, DISPNI[OpTable], c3; {***************************************************************************** DDUP *****************************************************************************} @DDUP: T ← STK, fXpop, fZpop, push, c1, opcode[251'b]; Rx ← T, c2; Q ← TOS, GOTO[DDTail], c3; {***************************************************************************** EXDIS *****************************************************************************} @EXDIS: pop, GOTO[NegIB], c1, opcode[252'b]; {***************************************************************************** BNDCK *****************************************************************************} @BNDCK: TT ← STK, fXpop, fZpop, push, c1, opcode[74'b]; Ybus ← TT-TOS, CarryBr, push, c2; T ← sBoundsTrap, STK ← TOS, pop, BRANCH[NotBND, BND], c3; NotBND: TOS ← TT, pop, GOTO[NegIB], c1; BND: GOTO[Trapc2], c1; {***************************************************************************** NILCKL *****************************************************************************} @NILCKL: [] ← STK or TOS, ZeroBr, fXpop, fZpop, c1, at[6,10,ESC2n]; T ← sPointerTrap, push, BRANCH[NotNIL, NIL], c2; NotNIL: GOTO[NxtInstc1], c3; NIL: PC ← PC - 1, GOTO[BND], c3; {***************************************************************************** NEG *****************************************************************************} @NEG: TOS ← -TOS, c1, opcode[253'b]; NegIB: IBDisp, fXpop, push, c2; NegNI: PC ← PC+PC16, DISPNI[OpTable], c3; {***************************************************************************** INC *****************************************************************************} @INC: TOS ← TOS + 1, GOTO[NegIB], c1, opcode[254'b]; {***************************************************************************** DEC *****************************************************************************} @DEC: TOS ← TOS - 1, GOTO[NegIB], c1, opcode[255'b]; {***************************************************************************** ADDSB *****************************************************************************} @ADDSB: T ← ib, XLDisp, c1, opcode[264'b]; TT ← ~0FF xor T, BRANCH[AddSBP, AddSBN, XLowNeg], c2; AddSBP: TOS ← TOS + T, GOTO[Addpc2], c3; AddSBN: TOS ← TOS + TT, GOTO[Addpc2], c3; Addpc2: PC ← PC+PC16, GOTO[NegIB], c1; {***************************************************************************** DINC *****************************************************************************} @DINC: T ← STK, fXpop, fZpop, push, c1, opcode[256'b]; T ← T + 1, CarryBr, c2; STK ← T, BRANCH[DINCa, DINCb, 2], c3; DINCa: GOTO[NegIB], c1; DINCb: TOS ← TOS + 1, GOTO[NegIB], c1; {***************************************************************************** DBL *****************************************************************************} @DBL: TOS ← LShift1 TOS, GOTO[NegIB], c1, opcode[257'b]; {***************************************************************************** DDBL *****************************************************************************} @DDBL: T ← LShift1 STK, SE ← 0, XHDisp, c1, opcode[260'b]; STK ← T, fXpop, fZpop, push, BRANCH[DDBLa, DDBLb, 2], c2; DDBLa: TOS ← TOS LShift1, SE ← 0, GOTO[DDBLc], c3; DDBLb: TOS ← TOS LShift1, SE ← 1, GOTO[DDBLc], c3; DDBLc: GOTO[NegIB], c1; {***************************************************************************** TRPL *****************************************************************************} @TRPL: T ← LShift1 TOS, GOTO[add], c1, opcode[261'b]; {***************************************************************************** LINT *****************************************************************************} @LINT: Ybus ← TOS, NegBr, fXpop, push, c1, at[8,10,ESC1n]; push, IBDisp, BRANCH[LINTa, LINTb], c2; LINTa: TOS ← 0, push, fZpop, DISPNI[OpTable], c3; LINTb: TOS ← TOS xor ~TOS, push, fZpop, DISPNI[OpTable], c3; {***************************************************************************** IOR *****************************************************************************} @IOR: TOS ← STK or TOS, pop, GOTO[NegIB], c1, opcode[263'b]; {***************************************************************************** AND *****************************************************************************} @AND: TOS ← STK and TOS, pop, GOTO[NegIB], c1, opcode[262'b]; {***************************************************************************** XOR *****************************************************************************} @XOR: TOS ← STK xor TOS, fXpop, fZpop, GOTO[IBDispOnly], c1, at[2,10,ESC1n]; {***************************************************************************** ROTATE *****************************************************************************} @ROTATE: T ← STK, pop, L2←L2.Rotate, c1, at[6,10,ESC1n]; rhT ← 0, Ybus ← TOS, YDisp, c2; TT ← T LRot1, fXpop, push, DISP4[CycleMask], c3; GOTO[IBDispOnly], c1, at[L2.Rotate,10,MaskRet]; {***************************************************************************** SHIFTSB *****************************************************************************} { shift= rotate (shift-1)[12-15] int mask final mask 000F 15 left 14'd 7FFF 8000 000E 14 left 13'd 3FFF C000 : : : : : 0001 1 left 0 1 FFFE 0000 none 15'd FFFF FFFF FFFF 15 left(1 r) 14'd 7FFF 7FFF FFFE 14 left(2 r) 13'd 3FFF 3FFF : : : : : FFF2 2 left 1 3 3 FFF1 (-15'd) 1 left(15 r) 0 1 1} {At entry to SHIFT, TOS=shift and STK=u. For CycleMask, shift is used to determine the rotation and (shift-1) the mask. FOR SHIFTSB and SHIFT, (shift-1) is placed in RH[T] and used for both shift and mask. Since we are rotating one less, we rotate it one before calling CycleMask. (shift-1) is used to determine the mask since this has the same conventions as the size specifier of a field descriptor. Thus shift=15 implies mask=7FFF, shift=1 implies mask=1, and shift=0 implies a mask of FFFF. At the beginning of the SHIFT code, a check is made to determine if the absolute value of shift is greater than 15 (which implies a zero result). If (shift-1) is positive, shifting is canceled if "shift" greater than 15. If (shift-1) is negative, shifting is canceld if (shift-1) is less than -16 (i.e., (shift-1) + 16 doesn't produce a carry). Link2 is loaded with the results of the (shift-1) test so that CycleMask returns to either SSBNorm or SSBInv. For values of shift from 15 to 1, i.e. (shift-1) positive, the mask which CycleMask computes should be inverted, so control goes to ShInvRet in this case. If (shift-1) was negative, control returns at ShNormRet and the mask in TT is not inverted.} @SHIFTSB: Rx ← ib, XRefBr, c1, opcode[174'b]; T ← ~0FF xor Rx, BRANCH[SSBa, SSBb], c2; SSBa: rhT ← (Rx-1) LRot0, NegBr, LOOPHOLE[niblTiming], GOTO[SSBc], c3; SSBb: rhT ← (T-1) LRot0, NegBr, LOOPHOLE[niblTiming], GOTO[SSBc], c3; SSBc: PC ← PC + PC16, L2←L2.SSBInv, BRANCH[SSBd, SSBe], c1; SSBd: T ← TOS LRot1, Xbus ← rhT, XDisp, GOTO[SSBf], c2; SSBe: T ← TOS LRot1, Xbus ← rhT, XDisp, GOTO[SSBf], c2; SSBf: TT ← LRot1 T, DISP4[CycleMask], c3; {Subroutine CycleMask = 1 click} TOS ← ~TT and TOS, fXpop, push, GOTO[NegIB], c1, at[L2.SSBInv,10,MaskRet]; TOS ← TOS and TT, fXpop, push, GOTO[NegIB], c1, at[L2.SSBNorm,10,MaskRet]; {***************************************************************************** SHIFT *****************************************************************************} @SHIFT: rhT ← Q ← (TOS-1) LRot0, NegBr, LOOPHOLE[niblTiming], c1, opcode[173'b]; T ← STK LRot1, pop, L2←L2.SSBInv, BRANCH[Sa, Sb], c2; Sa: [] ← TOS and ~0F, ZeroBr, GOTO[Sc], c3; Sb: [] ← Q + 0F + 1, CarryBr, GOTO[Sc], c3; Sc: TOS ← 0, BRANCH[NegIB, Sd], c1; Sd: Xbus ← rhT, XDisp, GOTO[SSBf], c2; {***************************************************************************** DAND *****************************************************************************} @DAND: T ← STK, pop, c1, at[3,10,ESC1n]; TOS ← TOS and STK, pop, c2; T ← T and STK, fXpop, fZpop, push, c3; DANDa: STK ← T, GOTO[IBDispOnly], c1; {***************************************************************************** DIOR *****************************************************************************} @DIOR: T ← STK, pop, c1, at[4,10,ESC1n]; TOS ← TOS or STK, pop, c2; T ← T or STK, fXpop, fZpop, push, GOTO[DANDa], c3; {***************************************************************************** DXOR *****************************************************************************} @DXOR: T ← STK, pop, c1, at[5,10,ESC1n]; TOS ← TOS xor STK, pop, c2; T ← T xor STK, fXpop, fZpop, push, GOTO[DANDa], c3; {***************************************************************************** DSHIFT *****************************************************************************} @DSHIFT: Rx ← -TOS, NegBr, pop, c1, at[7,10,ESC1n]; Q ← STK, fXpop, fZpop, push, BRANCH[DSa, DSb], c2; DSb: T ← TOS and 1F, L0←0, c3; Ybus ← TOS xor T, NZeroBr, push, c1; TT ← STK, pop, BRANCH[DSc, DSd], c2; DSc: T ← T - 1, NegBr, L0Disp, c3; STK ← Q, DISP2[DSe], c1; DSe: TT ← DLShift1 TT, Cin ← 1, GOTO[DSc], c2, at[0,4,DSe]; TOS ← TT, IBDisp, GOTO[DISPNIonly], c2, at[1,4,DSe]; TT ← DRShift1 TT, Cin ← 1, GOTO[DSc], c2, at[2,4,DSe]; TOS ← ~TT, IBDisp, GOTO[DISPNIonly], c2, at[3,4,DSe]; DSa: T ← Rx and 1F, L0 ← 2, c3; Ybus ← Rx xor T, NZeroBr, push, c1; TT ← ~STK, pop, BRANCH[DSc, DSd], c2; DSd: STK ← TOS ← 0, GOTO[NxtInstc1], c3; {***************************************************************************** ADD *****************************************************************************} @ADD: T ← STK, pop, c1, opcode[265'b]; add: TOS ← T + TOS, IBDisp, fXpop, push, GOTO[NegNI], c2; {***************************************************************************** SUB *****************************************************************************} @SUB: T ← STK, pop, c1, opcode[266'b]; TOS ← T - TOS, IBDisp, fXpop, push, GOTO[NegNI], c2; {***************************************************************************** DADD *****************************************************************************} @DADD: T ← STK {T ← b}, pop {point to u}, c1, opcode[267'b]; Q ← STK {Q ← u}, pop {point to v}, c2; TT ← STK {TT ← v}, fXpop, fZpop, push, c3; DAdd: T ← T+TT {t←v+b}, CarryBr, c1; STK ← T, PC ← PC+PC16, IBDisp, BRANCH[DANC, DAC], c2; DANC: TOS ← Q+TOS {TOS←u+a}, DISPNI[OpTable], c3; DAC: TOS ← Q+TOS+1 {TOS←u+a+1}, DISPNI[OpTable], c3; {***************************************************************************** DSUB *****************************************************************************} @DSUB: T ← STK {T ← b}, pop {point to u}, c1, opcode[270'b]; Q ← STK {Q ← u}, pop {point to v}, c2; TT ← STK {TT ← v}, fXpop, fZpop, push, {Underflow?} c3; T ← TT-T {t←v-b}, CarryBr, c1; STK ← T, PC ← PC+PC16, IBDisp, BRANCH[DSNC, DSC], c2; DSNC: TOS ← Q-TOS-1 {TOS←u-a-1}, DISPNI[OpTable], c3; DSC: TOS ← Q-TOS {TOS←u-a}, DISPNI[OpTable], c3; {***************************************************************************** ADC *****************************************************************************} @ADC: Q ← STK, pop, c1, opcode[271'b]; TT ← STK, fXpop, fZpop, push, c2; PC ← PC+PC16, c3; ADCa: TT ← TT + TOS, CarryBr, push, fZpop, {RRIT comes here} c1; STK ← TT, TOS ← 0, IBDisp, BRANCH[DANC, DAC], c2; {***************************************************************************** ACD *****************************************************************************} @ACD: T ← STK, pop, c1, opcode[272'b]; Q ← 0, c2; TT ← STK, fXpop, fZpop, push, GOTO[DAdd], c3; {***************************************************************************** AL0IB *****************************************************************************} @AL0IB: MAR ← [rhL, L+0], push, c1, opcode[273'b]; T ← ib, c2; TOS ← MD, STK ← TOS, push, fZpop, c3; PC ← PC + PC16, GOTO[add], c1; {***************************************************************************** MUL *****************************************************************************} {Timing: 18 clicks - click of init + 16*(click of inner loop) + click of cleanup} {This code implements a basic add-shift unsigned mulitply. Q holds the multiplicand (s) and TOS the mulitplier (t). TT holds the loop count. T and Q are the concatenated double word result, with the most significant bits being formed in T and the least significant in Q. The DoubleRightShift1 shifts Cout of the current alu computation into bit 0 of the double length result (T,,Q). At the end, Q is pushed onto the stack, and T is left above the stack.} @MUL: Q ← STK, fXpop, fZpop, push, c1, opcode[274'b]; T ← 0, push {point at ~}, c2; PC ← PC+PC16, c3; TT ← 10, c1; MLoop: Ybus ← Q and 1, NZeroBr, c2; TT ← TT - 1, ZeroBr, BRANCH[MP0, MP1], c3; MP0: T ← DARShift1 (T+0), BRANCH[MLoop, MLDEnd], c1; MP1: T ← DARShift1 (T + TOS), BRANCH[MLoop, MLDEnd], c1; MLDEnd: STK ← T, pop, IBDisp, c2; TOS ← ~Q, pop, DISPNI[OpTable], c3; {***************************************************************************** UDIV *****************************************************************************} @UDIV: T ← 0, L0←0, c1, at[0C,10,ESC1n]; Q ← STK, fXpop, fZpop, push, GOTO[LDiv], c2; {***************************************************************************** LUDIV *****************************************************************************} {This code implements a basic subtract-shift unsigned restoring divide. TOS holds the divisor (t) and the concatenation T,,Q holds the double length dividend (long). TT holds the loop count. The final quotient appears in Q and the remainder in T. The DoubleLeftShift1 shifts Cin into bit 17B of the accumulating quotient. At the end, Q is pushed onto the stack, and T is left above the stack.} @LUDIV: T ← STK, pop, L0←2, c1, at[0D,10,ESC1n]; Q ← STK {long.low}, fXpop, fZpop, push, c2; LDiv: Ybus ← TOS, ZeroBr, c3; Ybus ← T - TOS, CarryBr, L0Disp, BRANCH[LDivNoZD, LDivZD], c1; LDivNoZD: TT ← sDivCheckTrap, DISP2[LDivOK], c2; LDivOK: TT ← 10, GOTO[Quot0], c3, at[0,4,LDivOK]; TT ← 10, GOTO[Quot0], c3, at[2,4,LDivOK]; LDivLoop: Ybus ← T - TOS, CarryBr, BRANCH[QuotUnk, QuotIs1], c2, at[0,2,LDivEnd]; QuotUnk: TT ← TT - 1, ZeroBr, BRANCH[Quot0, Quot1, YOdd], c3, at[0,2,QuotIs1]; QuotIs1: TT ← TT - 1, ZeroBr, CANCELBR[Quot1], c3, at[1,2,QuotUnk]; Quot0: T ← DLShift1 T, SE←0, NegBr, BRANCH[LDivLoop, LDivEnd], c1; Quot1: T ← DLShift1 (T - TOS), SE←1, NegBr, BRANCH[LDivLoop, LDivEnd], c1; LDivEnd: push {point at rem}, BRANCH[RemAdj0, RemAdj1], c2, at[1,2,LDivLoop]; RemAdj0: T ← RShift1 T, SE←0, GOTO[DEnd], c3; RemAdj1: T ← RShift1 T, SE←1, GOTO[DEnd], c3; DEnd: GOTO[MLDEnd], c1; LDivZD: TT ← sDivZeroTrap, DISP2[LDivOv,1], c2, at[1,2,LDivNoZD]; LDivOv: T ← TT, GOTO[DivTrap], c3, at[1,4,LDivOK]; T ← TT, push, GOTO[DivTrap], c3, at[3,4,LDivOK]; DivTrap: PC ← PC - 1, GOTO[Trapc2], c1; {***************************************************************************** UDCMP *****************************************************************************} @UDCMP: T ← STK {s}, pop, c1, opcode[276'b]; TT ← STK {x}, pop, c2; comp: TT ← DARShift1 (TT-TOS) {x-r}, ZeroBr, c3; Ybus ← TT, NegBr {carry of x-r}, BRANCH[CHighNE, CompLow], c1; CHighNE: PC ← PC+PC16, IBDisp, pop, BRANCH[CompL, CompG], c2; CompL: TOS ← ~TOS xor TOS, fXpop, push, DISPNI[OpTable], c3; CompG: TOS ← 1, fXpop, push, DISPNI[OpTable], c3; CompLow: TT ← STK {y}, pop, CANCELBR[$], c2; TT ← DARShift1 (TT-T) {y-s}, ZeroBr, c3; Ybus ← TT, NegBr {carry of y-s}, BRANCH[CLowNE, CompE], c1; CLowNE: PC ← PC+PC16, IBDisp, BRANCH[CompL, CompG], c2; CompE: TOS ← 0, IBDisp, fXpop, push, CANCELBR[NegNI], c2; {***************************************************************************** DCMP *****************************************************************************} @DCMP: T ← STK {s}, pop, c1, opcode[275'b]; Q ← STK {x}, pop, c2; TT ← u8000, c3; TOS ← TOS + TT, c1; TT ← TT + Q, GOTO[comp] c2;