GenInstrDecodePLAExceptions:
PROC = {
OPEN DOC: DragOpsCross;
T: BOOL = TRUE;
all: Dragon.Byte ← ByteTopSig[8];
BEX: TYPE = BoolExpr;
ifuSLim: BEX ← BE[m:[alpha: all], d:[alpha: DOC.ProcessorRegister[ifuSLimit ].ORD]];
ifuYgL: BEX ← BE[m:[alpha: all], d:[alpha: DOC.ProcessorRegister[ifuYoungestL ].ORD]];
ifuYgPC: BEX ← BE[m:[alpha: all], d:[alpha: DOC.ProcessorRegister[ifuYoungestPC ].ORD]];
ifuElL: BEX ← BE[m:[alpha: all], d:[alpha: DOC.ProcessorRegister[ifuEldestL ].ORD]];
ifuElPC: BEX ← BE[m:[alpha: all], d:[alpha: DOC.ProcessorRegister[ifuEldestPC ].ORD]];
ifuAddr: BoolExpr ← BE[m:[alpha: 360B], d:[alpha: 360B]]; -- last 16
reset: BoolExpr ← BE[m:[reset: TRUE], d:[reset: TRUE]];
userMode0: BoolExpr ← BE[m:[userMode0: TRUE], d:[userMode0: TRUE]];
pop0ping: BoolExpr ← BE[m:[popPending: TRUE], d:[popPending: TRUE]];
push0ing: BoolExpr ← BE[m:[pushPending: TRUE], d:[pushPending: TRUE]];
state0: BoolExpr ← BE[m:[state: ByteTopSig[8]], d:[state: 0]];
current0: BoolExpr ← state0;
Set InstStarting bit
Set[ s: state0, out: [instStarting0: TRUE] ];
Do Exceptions
Note: Reset must be asserted for at least three machine cycles.
Set[s: reset, out: [
nextMacro: jump, -- helps clear Fetchindexing
microCycleNext: next,
protMicroCycle: TRUE,
pcNext: fromPCBus,
pcBusSrc: trapGen,
lSource: [ zero, zero ],
sSource: [ l, zero ],
aluOp: UAdd, -- clears EU carry flag
aReg: constantZero,
bReg: constantZero,
flagSrc: clear ]];
current ← BE[m: [reset: TRUE], d:[reset: FALSE]];
Set[s: current, m:[state: ByteTopSig[8]], d:[state: 112
-- Resetting -- ], out: [
nextMacro: jump, -- helps clear Fetchindexing
microCycleNext: next,
protMicroCycle: TRUE,
pcNext: fromPCBus,
pcBusSrc: trapGen,
lSource: [ zero, zero ],
sSource: [ l, zero ],
aluOp: UAdd, -- clears EU carry flag
aReg: constantZero,
bReg: constantZero,
flagSrc: clear ]];
Set[s: current, m:[state: ByteTopSig[8]], d:[state: 113
-- Reset finished -- ], out: [
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: pc,
lSource: [ zero, one ],
sSource: [ l, zero ],
aluOp: UAdd, -- clears EU carry flag
aReg: constantZero,
bReg: constantZero ]];
Set[s: current, m:[state: ByteTopSig[8]], d:[state: 116
-- trap0 -- ], out: [
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: trapGen,
flagSrc: clear,
lSource: [ l3, zero ],
sSource: [ s3, zero ] ]];
Set[s: current, m:[state: ByteTopSig[8]],d:[state: 120
-- cJump -- ], out: [
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: pipe3,
flagSrc: lev3,
lSource: [ l3, zero ], -- should be 2, but 2 = 3 for cJump
sSource: [ s2, zero ] ]]; -- S of instr AFTER CJump
Set[s: current, m:[state: ByteTopSig[1]], d:[state: 128 -- bubble --], out: Delayed];
Not An Exception
current ← And[current, BE[m: [state: ByteTopSig[2]], d:[state: 0]]];
Instruction not ready
Set[s: current,
m:[instReady: TRUE], d:[instReady: FALSE], out: Delayed];
current ← And[current, BE[m: [instReady: TRUE], d: [instReady: TRUE]]];
Returns must wait for push0 or pop0. Today (October 25, 1985 11:54:04 am PDT) Russ Atkinson promised to make stack underflow illegal (by altering the PC of the bottom frame to point to a trap handler), so trapping an empty instruction stack is no longer necessary.
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dRET]]];
Set[s: And[instr, Or[pop0ping, push0ing]], out: [
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next, -- so we can recognize first cycle of RET
condEffect0: bubble]];
Set[s: And[instr, Not[Or[pop0ping, push0ing]] ], out: [
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: stack,
flagSrc: stack,
lSource: [ zero, stack ],
sSource: [ l, alpha ],
pop0: TRUE ]];
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dRETN]]];
Set[s: And[instr, Or[pop0ping, push0ing]], out: [
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next, -- so we can recognize first cycle of RET
condEffect0: bubble ]];
Set[s: And[instr, Not[Or[pop0ping, push0ing]]
], out: [
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: stack,
flagSrc: stack,
lSource: [ zero, stack ],
pop0: TRUE ]];
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dRETK]]];
Set[s: And[instr, userMode0, state0], out: [condSel: ModeFault]]; -- OR it in
Set[s: And[instr, state0], out: [
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next,
bReg: abStackTop,
cReg: toIfuXBus,
kPadsIn0: TRUE,
flagSrc: stack,
lSource: [ zero, stack ],
sSource: [ l, alpha ]] ];
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 1], out: NoOpMicro];
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 1], out: [pop0: TRUE]];
... just add it in. This pop0 logically belongs with state 3, but can be piped ahead because the pop0 doesn't actually happen until three cycles later. This allows a return following a RETK to proceed without wait states.
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 2], out: NoOpMicro];
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 3], out: [
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: stack,
x1ADstStatus: TRUE]];
... x1ADstStatus is not pipelined, so it's generated at stage 0B to apply to the destination register address that has reached stage 3B.
Note: We formerly trapped ALS if the stack was empty. Russ Atkinson now (and has done for some time) guarantees that to be impossible. EMM October 25, 1985 11:26:44 am PDT.
ALS
Look for the case of a Call - ALS sequence broken by a Reschedule which returns with an empty IStack. ALS (L←S+alpha) => that the stack is expected to contain some local values which (if IStack is empty) have been swapped out.
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dALS]] ];
Set[s: And[instr, pop0ping], out: Delayed];
Set[s: And[instr, Not[pop0ping], empty, Not[push0ing]], out: Trap];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dALS], out:[lSource: [s, alpha]]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dASL], out:[sSource: [l, alpha]]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dAL], out:[lSource: [l, alpha]]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dAS], out:[sSource: [s, alpha]]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dDIS], out:[popSa: TRUE]];
LIP
check addr to determine if IFU or EU. EU has no special conditions.
Unfortunately, LIP from an IFU register sometimes has early side effects, including pop0ping the control stack. Therefore its last microinstruction must not experience any pipeline interference.
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dLIP]]];
Set[s: And[instr, Not[ifuAddr]], out: [
bReg: [ zero, alpha ],
cReg: [ s, offset, one ],
pushSc: TRUE ] ];
instr ← And[instr, ifuAddr];
Set[s: instr, m:[state: ByteTopSig[8]], d:[state:
0], out:[
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next,
pushSc: TRUE ] ]; -- aborts if EU stack overflow
Set[s: And[instr,
userMode0, state0,
ifuElPC], out: [condSel:
ModeFault] ];
OR's in with other bits, protects just LIP IFUEldestPC
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 1], out:NoOpMicro]; -- wait
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 2], out:NoOpMicro]; -- wait
Set[s: instr, m:[state: ByteTopSig[8]], d:[state:
3], out: [
nextMacro: hold,
bReg: fromIfuXBus,
pcNext: fromPCBus,
microCycleNext: next,
kIsRtOp0: TRUE,
cReg: [ s, offset, zero ] ] ];
Set[s: And[instr, BE[m:[state: ByteTopSig[8]], d:[state: 3], ifuStat]],
out: [x2ASrcStatus0: TRUE]]; -- add in register-specific bits, on time
Add in register-specific bits, one cycle delayed
instr ← And[instr, BE[m:[state: ByteTopSig[8]], d:[state: 4]]];
Set[s: And[instr, ifuSLim], out: [x1ASrcSLimit:T ]];
Set[s: And[instr, ifuYgL], out: [x1ASrcStack:T, xBusStackL:T ]];
Set[s: And[instr, ifuYgPC], out: [x1ASrcStack:T ]];
Set[s: And[instr, ifuElL], out: [x1ASrcStack:T, xBusStackEldest:T, xBusStackL:T ]];
Set[s: And[instr, ifuElPC], out: [x1ASrcStack:T, xBusStackEldest:T ]];
Set[s: And[instr, ifuYgL], out: [x1ASrcStackL:T]];
Set[s: And[instr, ifuYgPC], out: [x1ASrcStackP:T]];
Set[s: And[instr, ifuElL], out: [x1ASrcStackL:T]];
Set[s: And[instr, ifuElPC], out: [x1ASrcStackP:T]];
SIP
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dSIP]]];
Set[s: And[instr, userMode0, state0], out: [condSel: ModeFault] ];
-- trap if userMode0
Set[s: And[instr, Not[ifuAddr]], out: [
bReg: abStackTop,
cReg: [ zero, alpha ],
popSb: TRUE ] ];
Set[s: instr,
m: [alpha: ByteTopSig[8]], d: [alpha: DragOpsCross.ProcessorRegister[euField].ORD],
out: [cIsField0: TRUE ] ];
instr ← And[instr, ifuAddr];
Set[s: instr, m:[state: ByteTopSig[8]], d:[state:
0], out:[
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next,
bReg: abStackTop,
popSb: TRUE,
cReg: toIfuXBus,
kPadsIn0: TRUE ] ];
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 1], out:NoOpMicro]; -- wait
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 2], out:NoOpMicro]; -- wait
temp ← And[instr, BE[m:[state: ByteTopSig[8]], d:[state: 3]]];
Set[s: temp, out: NoOpMicro];
Register-specific bits, to be broadcast in phase 1A
Set[s: And[temp, ifuStat], out: [x1ADstStatus:T ]];
Set[s: And[temp, ifuSLim], out: [x1ADstSLimit:T ]];
Set[s: And[temp, ifuYgL], out: [x1ADstStack:T, xBusStackL:T ]];
Set[s: And[temp, ifuYgPC], out: [x1ADstStack:T ]];
Set[s: And[temp, ifuElL], out: [x1ADstStack: T, xBusStackEldest:T, xBusStackL:T ]];
Set[s: And[temp, ifuElPC], out: [x1ADstStack:T, xBusStackEldest:T ]];
This final state is necessary because a RET instruction can follow a SIP to IFUYoungestPC or IFUYoungestL, and perhaps in other cases as well.
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 4], out:[ ]]};
GenInstrDecodePLAXfers:
PROC = {
Used in RR and RJB instructions
src0: BoolExpr ← BE[m:[alpha: 300B], d:[alpha: 0B]];
src1: BoolExpr ← BE[m:[alpha: 300B], d:[alpha: 100B]];
srTop: BoolExpr ← BE[m:[alpha: 200B], d:[alpha: 200B]];
srPop: BoolExpr ← BE[m:[alpha: 300B], d:[alpha: 300B]];
opt: BoolExpr ← BE[m:[alpha: 040B], d:[alpha: 040B]];
aux: BoolExpr ← BE[m:[alpha: 020B], d:[alpha: 020B]];
m ← [
aReg: abStackTop,
x2ALitSource: alpha,
popSa: TRUE,
aluOp: VSub,
condEffect0: macroJump,
condSel: EZ,
nextMacro: get,
pcPipeSrc: offSetPC ]; -- pcOffSetSrc: betaS
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJEBB], out:m];
m.condSel ← NE;
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJNEBB], out:m];
m ← [
aReg: abStackTop,
x2ALitSource: alpha,
popSa: TRUE,
aluOp: VSub,
condEffect0: macroJump,
condSel: EZ,
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: offSetPC, -- pcOffSetSrc: betaS
pcPipeSrc: seqPC
];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJNEBBJ], out:m];
m.condSel ← NE;
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJEBBJ], out:m];
dRJ*B and dRJ*BJ - Bit 4 distinguishes between them
instr ← And[current, BE[m:[op: InstrTopSig[4]], d:[op: dRJEB]]]; -- RJ*B and RJ*BJ
Main Body
Set[s:current, m:[op: InstrTopSig[5]], d:[op:
dRJEB], out:[
--
RJ*B
aluOp: VSub,
condSelIsOp57: TRUE,
condEffect0: macroJump,
nextMacro: get,
pcPipeSrc: offSetPC ] ]; -- pcOffSetSrc: betaS
Set[s:current, m:[op: InstrTopSig[5]], d:[op:
dRJEBJ], out:[
--
RJ*BJ
aluOp: VSub,
condSelIsOp57: TRUE,
condEffect0: macroJump,
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: offSetPC, -- pcOffSetSrc: betaS
pcPipeSrc: seqPC] ];
AReg
Set[s: And[ src0, instr], out:[aReg:[ cBase, offset, zero ]]];
Set[s: And[ src1, instr], out:[aReg:[ cBase, offset, one ]]];
Set[s: And[ srTop, instr], out:[aReg:[ s, offset, zero ]]];
BReg
Set[s: And[ Not[opt], aux, instr], out:[bReg:[ aBase, alpha47 ]]];
Set[s: And[ Not[opt], Not[aux], instr], out:[bReg:[ l, alpha47 ]]];
Set[s: And[opt, instr], m:[alpha: 010B], d:[alpha: 000B], out:[bReg:[ cBase, alpha47 ]]];
Set[s: And[opt, instr], m:[alpha: 004B], d:[alpha: 000B], out:[bReg:[ cBase, alpha47 ]]];
Set[s: And[opt, instr], m:[alpha: 015B], d:[alpha: 014B], out:[bReg:[ s, offset, zero ]]];
Set[s: And[opt, instr], m:[alpha: 015B], d:[alpha: 015B], out:[bReg:[ s, offset, minus1 ]]];
Stack
Set[s: And[srPop, instr], out:[popSa: TRUE]];
Set[s: And[opt, instr], m:[alpha: 016B], d:[alpha: 016B], out:[popSb: TRUE]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJ1], out: DefaultMicro]; -- to mark as ~Xops
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJ2], out: DefaultMicro]; -- to mark as ~Xops
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJ3], out: DefaultMicro]; -- to mark as ~Xops
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJ5], out: DefaultMicro]; -- to mark as ~Xops
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dJSR]]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 0], out:[
-- toIfuXBus ← [S]
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next,
bReg: abStackTop,
cReg: toIfuXBus,
kPadsIn0: TRUE ]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 1], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 2], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 3], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 4], out:[
-- S ← S-1
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: offSetPC, -- pcOffSetSrc: xA,
popSa: TRUE ]];
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dJSD]]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 0], out:[
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next,
bReg: abStackTop,
cReg: toIfuXBus,
kPadsIn0: TRUE ]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 1], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 2], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 3], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 4], out:[
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: x,
popSa: TRUE ]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op:
dJB], out:[
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: offSetPC ]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op:
dJDB], out:[
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: offSetPC ]]; -- pcOffSetSrc: alphaBetaS
Set[s:current, m:[op: InstrTopSig[8]], d:[op:
dJQB], out:[
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: alpBetGamDel ]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op:
dLFC], out:[
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: offSetPC, -- pcOffSetSrc: alphaBetaS,
pcPipeSrc: seqPC,
push0: TRUE ]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op:
dDFC], out:[
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: alpBetGamDel,
pcPipeSrc: seqPC,
push0: TRUE ]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op:
dKFC], out:[
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: xopGen,
pcPipeSrc: seqPC,
push0: TRUE,
flagSrc: clear ]];
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dSFC]]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state:
0], out:[
-- toIfuXBus ← [S]
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next,
bReg: abStackTop,
cReg: toIfuXBus,
kPadsIn0: TRUE ]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 1], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 2], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 3], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state:
4], out:[
-- S ← S-1
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: x,
pcPipeSrc: seqPC,
popSa: TRUE,
push0: TRUE ]];
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dSFCI]]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state:
0], out:[
-- toIfuXBus ← [S]^
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next,
bReg: abStackTop,
cReg: toIfuXBus,
kPadsIn0: TRUE,
dPCmnd: Fetch,
dPCmndIsRd0: TRUE ]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 1], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 2], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 3], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state:
4], out:[
-- S ← S-1
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: x,
pcPipeSrc: seqPC,
push0: TRUE ]] };
current ← old;
GenInstrDecodePLAExceptions[];
GenInstrDecodePLAXfers[]};