{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;