DragonMicrocodeImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last edited by McCreight, April 9, 1984 11:12:17 am PST
Last edited by Curry, July 31, 1984 6:28:48 pm PDT
DIRECTORY
Dragon,
DragonFP,
DragonMicrocode,
DragOpsCross;
DragonMicrocodeImpl: CEDAR PROGRAM
IMPORTS Dragon, DragonFP
EXPORTS DragonMicrocode =
BEGIN OPEN DragonMicrocode;
IndexedTrapBytePC: PROC[trap: DragOpsCross.TrapIndex, offset: NAT 𡤀]
RETURNS[trapPC: Dragon.HexWord] = {
index: NATLOOPHOLE[trap, NAT] + offset;
trapPC ← DragOpsCross.bytesPerWord *
(DragOpsCross.TrapBase+DragOpsCross.TrapWidthWords * index) };
GetMicroTrap: PUBLIC PROC[aArgs: PHAargs] RETURNS [m: MicroTrap, newState: IFUState] = {
OPEN aArgs;
trapsCurrentlyEnabled:BOOL;
newState.delayed ← FALSE;
newState.done  ← FALSE;
newState.cycle ← (SELECT TRUE FROM
state.done   => 0,
state.delayed  => state.cycle,
aluCondResult2 AND condEffect2=microJump => 2*state.cycle,
ENDCASE   => state.cycle+1);
newState.rescheduleWaiting ←
reschedule OR
ifuStatusControl.reschedule=set OR
state.rescheduleWaiting AND ifuStatusControl.reschedule#clear;
newState.inhibitTraps ←
iTrapEffect3=disable OR
ifuStatusControl.inhibit=set OR
state.inhibitTraps AND
(ifuStatusControl.inhibit#clear AND NOT iTrapEffect3=enable);
trapsCurrentlyEnabled ←
iTrapEffectPending=enable OR
iTrapEffectPending#disable AND NOT newState.inhibitTraps;
SELECT TRUE FROM
reset => {
newState.cycle     ←  0;
newState.exceptions    ←  aboutToReset;
newState.rescheduleWaiting ←  FALSE;
newState.inhibitTraps   ←  TRUE; 
m.killPipe      ← TRUE };
state.exceptions = aboutToReset => { -- First PhA after Reset goes away
newState.cycle     ← 0;
newState.exceptions    ← reset;
newState.rescheduleWaiting ← FALSE;
newState.inhibitTraps   ← TRUE;
m.killPipe       ← TRUE };
pBusFault3 # None => {
newState.cycle   ← 0;
newState.exceptions  ← epFault;
newState.inhibitTraps ← TRUE;
m.killPipe    ← TRUE };
aluCondResult2 AND condEffect2=macroTrap AND NOT pBusReject3=> {
newState.cycle   ← 0;
newState.exceptions  ← euCC;
newState.inhibitTraps ← TRUE;
m.killPipe    ← TRUE };
pBusReject3 => { 
newState.exceptions ← epReject; 
m.killPipe ← FALSE };
aluCondResult2 AND condEffect2=macroJump => {--cond jump switched
newState.cycle  ← 0;
newState.exceptions ← cJump; 
m.killPipe   ← TRUE };
newState.cycle # 0 => { 
newState.exceptions ← none; 
m.killPipe   ← FALSE };
state.exceptions=rschlWait AND state.delayed OR
newState.rescheduleWaiting AND trapsCurrentlyEnabled=> {
newState.exceptions  ← rschlWait;
m.killPipe    ← FALSE };
state.exceptions=iStkOFlow AND state.delayed OR
iStkOverflow AND (pushPending OR NOT popPending)
AND trapsCurrentlyEnabled => {
newState.exceptions  ← iStkOFlow;
m.killPipe    ← FALSE };
state.exceptions=eStkOFlow AND state.delayed OR
eStkOverflow AND trapsCurrentlyEnabled => {
newState.exceptions  ← eStkOFlow;
m.killPipe    ← FALSE };
state.exceptions=iFtchFault AND state.delayed OR
preFetchFaulted => {
newState.exceptions  ← iFtchFault;
m.killPipe    ← FALSE };
ENDCASE => {
newState.exceptions  ← none;
m.killPipe    ← FALSE };
SELECT newState.exceptions FROM
aboutToReset => m.trapPC←IndexedTrapBytePC[ResetTrap];
reset   => m.trapPC←IndexedTrapBytePC[ResetTrap];
epFault  => m.trapPC←IndexedTrapBytePC[EUPbusTrap0,LOOPHOLE[pBusFault3,NAT]];
euCC   => m.trapPC←IndexedTrapBytePC[ALUCondEZ,LOOPHOLE[aluCond2,NAT]];
epReject  => m.trapPC𡤀
cJump  => m.trapPC𡤀
rschlWait  => m.trapPC←IndexedTrapBytePC[RescheduleTrap];
iStkOFlow => m.trapPC←IndexedTrapBytePC[IFUStackOverflowTrap];
eStkOFlow => m.trapPC←IndexedTrapBytePC[EUStackOverflowTrap];
iFtchFault => m.trapPC←IndexedTrapBytePC[IFUPageFaultTrap];
none   => m.trapPC←IndexedTrapBytePC[StackUnderflowTrap];
ENDCASE  => Dragon.Assert[FALSE]};
GetMicroInst: PUBLIC PROC [bArgs: PHBargs] RETURNS [ m: MicroInst, newState: IFUState ]={
OPEN bArgs;
opcode: DragOpsCross.Inst;
TRUSTED {opcode ← LOOPHOLE[op]};
newState ← state;
newState.delayed ← FALSE;
This should not be necessary as long as m fields are always set using m ← [ . . . ]
m ← DefaultMicro;
SELECT TRUE FROM
state.exceptions = aboutToReset => m ← [
doMacroJump: FALSE,
getNextMacro: FALSE,
xBSource: trapPCGenerator,
lSource: [ zero, one ],
sSource: [ zero, zero ] ];
state.exceptions = reset => m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: trapPCGenerator,
lSource: [ zero, one ],
sSource: [ zero, zero ] ];
state.exceptions = epFault,
state.exceptions = euCC => m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: trapPCGenerator,
xASource: bAddrIFUReg,
bReg: ifuLevel3LS,
lSource: [ xBus, zero ],
sSource: [ xBus, zero ],
pushLevel3: TRUE ];
state.exceptions = epReject =>
{m ← NoOpMicro; newState.delayed ← TRUE};
state.exceptions = cJump => m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: pipe3PC,
xASource: bAddrIFUReg,
bReg: ifuLevel3LS,
lSource: [ xBus, zero ],
sSource: [ xBus, zero ] ];
delayACycle =>
{m ← NoOpMicro; newState.delayed ← TRUE};
state.cycle#0 => {
SELECT opcode FROM
dMUL =>
SELECT state.cycle FROM
IN [1..16] => m ← [
getNextMacro: FALSE,
xBSource: pc,
aReg: [ s, minus1 ], -- Product.msw
bReg: [ s, zero ],  -- Multiplicand
cReg: [ s, minus1 ], -- Product.msw
aluOp: MulStep ];
17 => m ← [
getNextMacro: TRUE,
cReg: [ s, zero ],  -- Product.lsw ← MQ
aluOp: RdMQ ];
ENDCASE => Dragon.Assert[ FALSE, "Unimplemented Dragon microcode" ];
dDIV =>
SELECT state.cycle FROM
1 => m ← [
getNextMacro: FALSE,
xBSource: pc,
aReg: [ s, minus2 ], -- Dividend.msw to R1
bReg: [ s, minus1 ], -- Dividend.lsw to MQ
cReg: [ s, minus1 ], -- Remainder
aluOp: PassLtWtMQ ];
IN [2..33] => m ← [
getNextMacro: FALSE,
xBSource: pc,
aReg: [ s, minus1 ], -- Remainder
bReg: [ s, zero ],  -- Divisor
cReg: [ s, minus1 ], -- Remainder
aluOp: DivStep ];
34 => m ← [
getNextMacro: TRUE,
aluOp: RdMQ,   -- Quotient
cReg: [ s, minus2 ], -- Quotient
deltaS: -1 ];
ENDCASE => Dragon.Assert[ FALSE, "Unimplemented Dragon microcode" ];
dFP => {
SELECT state.cycle FROM
1 => SELECT DragonFP.GetFPOpType[alpha] FROM
setMode          => m ← [getNextMacro: TRUE];
sglUnCom, sglUnAlu, sglUnCvt  => m ← NoOpMicro;
dblUnCom, dblUnAlu, dblUnCvt,
sglBiCom, sglBiAlu,  sglBiMult => m ← [
getNextMacro: FALSE,
xBSource:   pc,
bReg:    [ s, minus1 ],
xASource:  fpLdAMsw,
euPBusCmd:  StoreFP ];
dblBiCom, dblBiAlu, dblBiMult => m ← [
getNextMacro: FALSE,
xBSource:   pc,
bReg:    [ s, minus1 ],
xASource:  fpLdBMsw,
euPBusCmd:  StoreFP ];
ENDCASE => Dragon.Assert[FALSE];
2 => SELECT DragonFP.GetFPOpType[alpha] FROM
sglUnCom, sglUnAlu, sglUnCvt,
dblUnCom, dblUnAlu, dblUnCvt,
sglBiCom, sglBiAlu,  sglBiMult => m ← NoOpMicro;
dblBiCom, dblBiAlu, dblBiMult => m ← [
getNextMacro: FALSE,
xBSource:   pc,
bReg:    [ s, minus2 ],
xASource:  fpLdALsw,
euPBusCmd:  StoreFP ];
ENDCASE => Dragon.Assert[FALSE];
3 => SELECT DragonFP.GetFPOpType[alpha] FROM
sglUnCom, sglUnAlu, sglUnCvt,
dblUnCom, dblUnAlu, dblUnCvt,
sglBiCom, sglBiAlu,  sglBiMult => m ← NoOpMicro;
dblBiCom, dblBiAlu, dblBiMult => m ← [
getNextMacro: FALSE,
xBSource:   pc,
bReg:    [ s, minus3 ],
xASource:  fpLdAMsw,
euPBusCmd:  StoreFP ];
ENDCASE => Dragon.Assert[FALSE];
4 => SELECT DragonFP.GetFPOpType[alpha] FROM
sglUnCom => m ← [
getNextMacro: TRUE,
deltaS:   -1,
xASource:  fpUnldMsw,
euPBusCmd:  FetchFPAlu ];
sglUnAlu  => m ← [
getNextMacro: TRUE,
cReg:    [ s, zero ],
xASource:  fpUnldMsw,
euPBusCmd:  FetchFPAlu ];
sglUnCvt  => m ← [
getNextMacro: FALSE,
xBSource:   pc,
cReg:    [ s, zero ],
xASource:  fpUnldMsw,
euPBusCmd:  FetchFPAlu ];
dblUnCom, dblUnAlu, dblUnCvt,
sglBiCom, sglBiAlu,  sglBiMult,
dblBiCom, dblBiAlu, dblBiMult => m ← NoOpMicro;
ENDCASE => Dragon.Assert[FALSE];
5 => SELECT DragonFP.GetFPOpType[alpha] FROM
sglUnCvt  => m ← [
getNextMacro: TRUE,
deltaS:   +1,
cReg:    [ s, one ],
xASource:  fpUnldLsw,
euPBusCmd:  FetchFPAlu ];
dblUnCom, sglBiCom => m ← [
getNextMacro: TRUE,
deltaS:   -2,
xASource:  fpUnldMsw,
euPBusCmd:  FetchFPAlu ];
dblUnAlu  => m ← [
getNextMacro: FALSE,
xBSource:   pc,
cReg:    [ s, minus1 ],
xASource:  fpUnldMsw,
euPBusCmd:  FetchFPAlu ];
dblUnCvt, sglBiAlu  => m ← [
getNextMacro: TRUE,
deltaS:   -1,
cReg:    [ s, minus1 ],
xASource:  fpUnldMsw,
euPBusCmd:  FetchFPAlu ];
sglBiMult  => m ← [
getNextMacro: TRUE,
deltaS:   -1,
cReg:    [ s, minus1 ],
xASource:  fpUnldMsw,
euPBusCmd:  FetchFPMult ];
dblBiCom, dblBiAlu, dblBiMult => m ← NoOpMicro;
ENDCASE => Dragon.Assert[FALSE];
6 => SELECT DragonFP.GetFPOpType[alpha] FROM
dblUnAlu  => m ← [
getNextMacro: TRUE,
cReg:    [ s, zero ],
xASource:  fpUnldLsw,
euPBusCmd:  FetchFPAlu ];
dblBiCom, dblBiAlu, dblBiMult => m ← NoOpMicro;
ENDCASE => Dragon.Assert[FALSE];
7 => SELECT DragonFP.GetFPOpType[alpha] FROM
dblBiCom => m ← [
getNextMacro: FALSE,
xBSource:   pc,
deltaS:   -2, -- Two more left for next cycle
xASource:  fpUnldMsw,
euPBusCmd:  FetchFPAlu ];
dblBiAlu  => m ← [
getNextMacro: FALSE,
xBSource:   pc,
cReg:    [ s, minus3 ],
xASource:  fpUnldMsw,
euPBusCmd:  FetchFPAlu ];
dblBiMult => m ← NoOpMicro;
ENDCASE => Dragon.Assert[FALSE];
8 => SELECT DragonFP.GetFPOpType[alpha] FROM
dblBiCom => m ← [
getNextMacro: TRUE,
deltaS:   -2, -- Last two
xASource:  fpUnldMsw,
euPBusCmd:  FetchFPAlu ];
dblBiAlu => m ← [
getNextMacro: TRUE,
deltaS:   -2,
cReg:    [ s, minus2 ],
xASource:  fpUnldLsw,
euPBusCmd:  FetchFPAlu ];
dblBiMult  => m ← [
getNextMacro: FALSE,
xBSource:   pc,
cReg:    [ s, minus3 ],
xASource:  fpUnldMsw,
euPBusCmd:  FetchFPMult ];
ENDCASE => Dragon.Assert[FALSE];
9 => SELECT DragonFP.GetFPOpType[alpha] FROM
dblBiMult => m ← [
getNextMacro: TRUE,
deltaS:   -2,
cReg:    [ s, minus2 ],
xASource:  fpUnldLsw,
euPBusCmd:  FetchFPMult ];
ENDCASE => Dragon.Assert[FALSE];
ENDCASE => Dragon.Assert[ FALSE, "Unimplemented Dragon microcode" ] };
dSIFUR =>
SELECT state.cycle FROM
1, 2 => m ← NoOpMicro; -- to allow ALU result to reach Result3
3 =>
S ← S-1 EU driving ifu XBus during A with S
IFU internal destination specified by level 3 cAddr
m ← [
getNextMacro: TRUE,
deltaS: -1 ];
ENDCASE => Dragon.Assert[ FALSE, "Unimplemented Dragon microcode" ];
dSJ =>
SELECT state.cycle FROM
1, 2, 3 => m ← NoOpMicro; -- to allow Xa to latch Result3
4 => -- S ← S-1
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: pcPlusXA,
deltaS: -1 ];
ENDCASE => Dragon.Assert[ FALSE, "Unimplemented Dragon microcode" ];
dSFC =>
SELECT state.cycle FROM
1, 2, 3 => m ← NoOpMicro; -- to allow Xa to latch Result3
4 => -- S ← S-1
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: xA,
deltaS: -1,
pipedPLSASpec: pLenLSnext,
iStackPostEffect: push ];
ENDCASE => Dragon.Assert[ FALSE, "Unimplemented Dragon microcode" ];
dSFCI =>
SELECT state.cycle FROM
1, 2, 3 => m ← NoOpMicro; -- to allow Xa to latch Result3
4 =>
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: xA,
deltaS: 0, -- shouldn't SFCI pop S?
pipedPLSASpec: pLenLSnext,
iStackPostEffect: push ];
ENDCASE => Dragon.Assert[ FALSE, "Unimplemented Dragon microcode" ];
dCST =>
SELECT state.cycle FROM
This cycle will invariably be Delayed (automatically) by the pipe since cycle 0 was a fetch into S+1
1 => -- IF [S+1] = [S] THEN double microPC
m ← [
getNextMacro: FALSE,
xBSource: pc,
aReg: [ s, one ],
bReg: stackTop,
aluOp: VSub,
condSel: EZ,
condEffect: microJump ];
2, 3 => m ← NoOpMicro; -- Allow ALU result to get back
4 => -- [] ← ([S-2]+alpha)^, release hold, S ← S+1
m ← [
aReg: [ s, minus2 ],
xASource: alpha,
aluRtIsK: TRUE,
deltaS: 1,
aluOp: VAdd,
euPBusCmd: Fetch ];
6 => -- target of microjump, ([S-2]+alpha)^ ← [S-1], release hold, S ← S+1
m ← [
aReg: [ s, minus2 ],
bReg: [ s, minus1 ],
xASource: alpha,
aluRtIsK: TRUE,
deltaS: 1,
aluOp: VAdd,
euPBusCmd: Store ];
ENDCASE => Dragon.Assert[ FALSE, "Unimplemented Dragon microcode" ];
dEXCH =>
SELECT state.cycle FROM
1 =>
m ← [
dontBypass: TRUE,
bReg: [ s, minus1 ],
cReg: stackTop ];
ENDCASE => Dragon.Assert[ FALSE, "Unimplemented Dragon microcode" ];
ENDCASE => -- unimplemented opcode
SELECT Dragon.OpLength[op] FROM
2, 3, 5 =>
SELECT state.cycle FROM
1 =>
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: xopGenerator,
pipedPLSASpec: pLenLSnext,
iStackPostEffect: push,
deltaS: 1 ];
ENDCASE => Dragon.Assert[ FALSE, "Unimplemented Dragon microcode" ];
ENDCASE => Dragon.Assert[ FALSE, "Unimplemented Dragon microcode" ];
}; -- of successor microinstructions of multi-micro macros
state.exceptions = rschlWait,
state.exceptions = iStkOFlow,
state.exceptions = eStkOFlow,
state.exceptions = iFtchFault => m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: trapPCGenerator,
iStackPostEffect: push,
iTrapPostEffect: disable ];
NOT instReady OR
(opcode=dRET OR opcode=dRETT OR opcode=dRETN OR opcode=dLIFUR) AND
(pushPending OR popPending) OR
opcode = dEP AND popPending =>
{m ← NoOpMicro; newState.delayed ← TRUE};
opcode = dEP AND (iStkEmpty AND NOT pushPending) =>
IStack Underflow is the default for trapPC
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: trapPCGenerator,
lSource: [ s, alpha ],
pipedPLSASpec: pLenLSnext,
iStackPostEffect: push, -- this push differentiates this trap from the following
iTrapPostEffect: disable ];
(opcode = dRET OR opcode = dRETT OR opcode = dRETN) AND
iStkEmpty =>
IStack Underflow is the default for trapPC
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: trapPCGenerator,
sSource: (IF opcode = dRET THEN [ l, alpha ] ELSE [ s, zero ]),
iTrapPostEffect: disable ];
ENDCASE => m ← DecodeFirstMicroOfNewMacro[op, alpha, beta ];
newState.done ←
m.doMacroJump OR
m.getNextMacro OR
state.cycle = 0 AND NOT instReady;
}; -- of GetMicroInst
DecodeFirstMicroOfNewMacro: PROC [
op:   Dragon.Opcode,
alpha:   Dragon.HexByte,
beta:   Dragon.HexByte ]
RETURNS [m: MicroInst] = {
instruction: PACKED ARRAY [0..3] OF Dragon.Byte = [op, alpha, beta, 0];
opcode:  DragOpsCross.Inst;
TRUSTED {opcode ← LOOPHOLE[op]};
m ← DefaultMicro; This should not be necessary as long as each case results with some m fields being set using the form m ← [ field: value ]
SELECT opcode FROM
IN DragOpsCross.JBBformatRange => {
CheckOpLength[op, 3];
m ← [
aReg: stackTop,
xASource: beta,
aluRtIsK: TRUE,
deltaS: -1,
aluOp: VSub,
condSel: (SELECT opcode FROM
dJEBB, dJNEBBJ => EZ,
ENDCASE => NE),
condEffect: macroJump,
doMacroJump: (SELECT opcode FROM
dJEBBJ, dJNEBBJ => TRUE,
ENDCASE => FALSE),
getNextMacro: (SELECT opcode FROM
dJEBBJ, dJNEBBJ => FALSE,
ENDCASE => TRUE),
xBSource: (SELECT opcode FROM
dJEBBJ, dJNEBBJ => pcPlusAlphaS,
ENDCASE => pcPlusLen),
pipedPLSASpec: (SELECT opcode FROM
dJEBBJ, dJNEBBJ => pLenLSnext,
ENDCASE => pAlphasLSnext)
] };
IN DragOpsCross.RJBformatRange => {
rj: DragOpsCross.RJBformat;
TRUSTED {rj ← LOOPHOLE[instruction]};
CheckOpLength[op, 3];
m ← [
aReg: [
s,
(SELECT TRUE FROM
rj.sd => minus1,
ENDCASE => zero) ],
bReg: [
(SELECT TRUE FROM
rj.opt AND NOT (rj.reg MOD 16 >= 8) => cBase,
rj.opt AND NOT (rj.reg MOD 8 >= 4) => cBase,
rj.opt AND (rj.reg MOD 16 >= 8) AND (rj.reg MOD 8 >= 4) => s,
NOT rj.opt AND rj.aux => aBase,
ENDCASE -- NOT rj.opt AND NOT rj.aux -- => l),
(SELECT TRUE FROM
rj.opt AND NOT (rj.reg MOD 16 >= 8) => beta47,
rj.opt AND NOT (rj.reg MOD 8 >= 4) => beta47,
rj.opt AND (rj.reg MOD 16 >= 8) AND (rj.reg MOD 8 >= 4) AND NOT (rj.reg MOD 2 >= 1) => zero,
rj.opt AND (rj.reg MOD 16 >= 8) AND (rj.reg MOD 8 >= 4) AND (rj.reg MOD 2 >= 1) => minus1,
ENDCASE -- NOT rj.opt -- => beta47)],
deltaS: (IF (rj.opt AND (rj.reg MOD 16 >= 8) AND (rj.reg MOD 8 >= 4) AND (rj.reg MOD 4 >= 2)) THEN -1 ELSE 0)+(IF rj.sdd THEN -1 ELSE 0),
aluOp: VSub,
condSel: (SELECT opcode FROM
dRJEB, dRJNEBJ => EZ,
dRJEBJ, dRJNEB => NE,
dRJLB, dRJGEBJ => LZ,
dRJLBJ, dRJGEB => GE,
dRJLEB, dRJGBJ => LE,
dRJLEBJ, dRJGB => GZ,
ENDCASE => False),
condEffect: macroJump,
doMacroJump: (SELECT opcode FROM
dRJEBJ, dRJNEBJ, dRJLBJ, dRJLEBJ, dRJGEBJ, dRJGBJ => TRUE,
ENDCASE => FALSE),
getNextMacro: (SELECT opcode FROM
dRJEBJ, dRJNEBJ, dRJLBJ, dRJLEBJ, dRJGEBJ, dRJGBJ => FALSE,
ENDCASE => TRUE),
xBSource: (SELECT opcode FROM
dRJEBJ, dRJNEBJ, dRJLBJ, dRJLEBJ, dRJGEBJ, dRJGBJ => pcPlusAlphaS,
ENDCASE => pcPlusLen),
pipedPLSASpec: (SELECT opcode FROM
dRJEBJ, dRJNEBJ, dRJLBJ, dRJLEBJ, dRJGEBJ, dRJGBJ => pLenLSnext,
ENDCASE => pAlphasLSnext)
] };
dJ1 => {CheckOpLength[op, 1]; m ← []};
dJ2 => {CheckOpLength[op, 2]; m ← []};
dJ3 => {CheckOpLength[op, 3]; m ← []};
dJ5 => {CheckOpLength[op, 5]; m ← []};
dJB => {
CheckOpLength[op, 2];
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: pcPlusAlphaS ] };
dJDB => {
CheckOpLength[op, 3];
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: pcPlusBetaAlphaS ] };
dDJ => {
CheckOpLength[op, 5];
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: deltaGammaBetaAlpha ] };
dSJ => {
CheckOpLength[op, 1];
m ← [ -- ifuXBus ← [S]
getNextMacro: FALSE,
xBSource: pc,
bReg: stackTop,
cReg: ifuXBus ] };
dRET => {
CheckOpLength[op, 2];
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: iStackPC,
xASource: bAddrIFUReg,
bReg: ifuYoungestL,
lSource: [ xBus, zero ],
sSource: [ l, alpha ],
iStackPostEffect: pop ] };
dRETN => {
CheckOpLength[op, 1];
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: iStackPC,
xASource: bAddrIFUReg,
bReg: ifuYoungestL,
lSource: [ xBus, zero ],
iStackPostEffect: pop ] };
dRETT => {
CheckOpLength[op, 1];
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: iStackPC,
xASource: bAddrIFUReg,
bReg: ifuYoungestL,
lSource: [ xBus, zero ],
iStackPostEffect: pop,
iTrapPostEffect: enable ] };
dLFC => {
CheckOpLength[op, 3];
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: pcPlusBetaAlphaS,
pipedPLSASpec: pLenLSnext,
iStackPostEffect: push ] };
dDFC => {
CheckOpLength[op, 5];
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: deltaGammaBetaAlpha,
pipedPLSASpec: pLenLSnext,
iStackPostEffect: push ] };
dSFC => {
CheckOpLength[op, 1];
m ← [ -- ifuXBus ← [S]
getNextMacro: FALSE,
xBSource: pc,
bReg: stackTop,
cReg: ifuXBus ] };
dSFCI => {
CheckOpLength[op, 1];
m ← [ -- ifuXBus ← [S]^
getNextMacro: FALSE,
xBSource: pc,
bReg: stackTop,
cReg: ifuXBus,
euPBusCmd: Fetch ] };
dIN => {
CheckOpLength[op, 2];
m ← [
aReg: stackTop,
xASource: alpha,
aluRtIsK: TRUE,
cReg: stackTop,
aluOp: VAdd,
euPBusCmd: IOFetch ] };
dRB => {
CheckOpLength[op, 2];
m ← [
aReg: stackTop,
xASource: alpha,
aluRtIsK: TRUE,
cReg: stackTop,
aluOp: VAdd,
euPBusCmd: Fetch ] };
dRSB => {
CheckOpLength[op, 2];
m ← [
aReg: stackTop,
xASource: alpha,
aluRtIsK: TRUE,
cReg: [ s, one ],
deltaS: 1,
aluOp: VAdd,
euPBusCmd: Fetch ] };
IN [dLRI0..dLRI15] => {
CheckOpLength[op, 2];
m ← [
aReg: [ l, op47 ],
xASource: alpha,
aluRtIsK: TRUE,
cReg: [ s, one ],
deltaS: 1,
aluOp: VAdd,
euPBusCmd: Fetch ] };
Save me for lisp
dLGF => {
CheckOpLength[op, 3];
m ← [
aReg: euGF,
xASource: betaAlpha,
aluRtIsK: TRUE,
cReg: [ s, one ],
deltaS: 1,
aluOp: VAdd,
euPBusCmd: Fetch ] };
dRRI, dRAI => {
CheckOpLength[op, 3];
m ← [
aReg: [
(SELECT opcode FROM
dRRI => l,
ENDCASE => aBase),
beta47],
xASource: alpha,
aluRtIsK: TRUE,
cReg: [ l, beta03 ],
aluOp: VAdd,
euPBusCmd: Fetch ] };
dRRX is with the RR instructions
dCST => {
CheckOpLength[op, 2];
m ← [
getNextMacro: FALSE,
xBSource: pc,
aReg: [ s, minus2 ],
xASource: alpha,
aluRtIsK: TRUE,
cReg: [ s, one ],
aluOp: VAdd,
euPBusCmd: FetchHold ] };
dOUT => {
CheckOpLength[op, 2];
m ← [
aReg: stackTop,
bReg: [ s, minus1 ],
xASource: alpha,
aluRtIsK: TRUE,
deltaS: -2,
aluOp: VAdd,
euPBusCmd: IOStore ] };
dWB => {
CheckOpLength[op, 2];
m ← [
aReg: stackTop,
bReg: [ s, minus1 ],
xASource: alpha,
aluRtIsK: TRUE,
deltaS: -2,
aluOp: VAdd,
euPBusCmd: Store ] };
dWSB => {
CheckOpLength[op, 2];
m ← [
aReg: [ s, minus1 ],
bReg: stackTop,
xASource: alpha,
aluRtIsK: TRUE,
deltaS: -2,
aluOp: VAdd,
euPBusCmd: Store ] };
dPSB => {
CheckOpLength[op, 2];
m ← [
aReg: [ s, minus1 ],
bReg: stackTop,
xASource: alpha,
aluRtIsK: TRUE,
deltaS: -1,
aluOp: VAdd,
euPBusCmd: Store ] };
IN [dSRI0..dSRI15] => {
CheckOpLength[op, 2];
m ← [
aReg: [ l, op47 ],
bReg: [ s, zero ],
xASource: alpha,
aluRtIsK: TRUE,
deltaS: -1,
aluOp: VAdd,
euPBusCmd: Store ] };
dWRI, dWAI => {
CheckOpLength[op, 3];
m ← [
aReg: [
(SELECT opcode FROM
dWRI => l,
ENDCASE => aBase),
beta47],
bReg: [ l, beta03 ],
xASource: alpha,
aluRtIsK: TRUE,
aluOp: VAdd,
euPBusCmd: Store ] };
dDIS => {
CheckOpLength[op, 1];
m ← [deltaS: -1] };
dAS => {
CheckOpLength[op, 2];
m ← [sSource: [s, alpha]] };
dAL => {
CheckOpLength[op, 2];
m ← [lSource: [l, alpha]] };
dASL => {
CheckOpLength[op, 2];
m ← [sSource: [ l, alpha]] };
dEP => {
CheckOpLength[op, 2];
m ← [lSource: [ s, alpha]] };
dFSDB => {
CheckOpLength[op, 3];
m ← [
xASource: betaAlpha,
aluRtIsK: TRUE,
cReg: euField ] };
dLIB => {
CheckOpLength[op, 2];
m ← [
xASource: alpha,
aluRtIsK: TRUE,
cReg: [ s, one ],
deltaS: 1 ] };
dLIDB => {
CheckOpLength[op, 3];
m ← [
xASource: betaAlpha,
aluRtIsK: TRUE,
cReg: [ s, one ],
deltaS: 1 ] };
dLIQB => {
CheckOpLength[op, 5];
m ← [
xASource: deltaGammaBetaAlpha,
aluRtIsK: TRUE,
cReg: [ s, one ],
deltaS: 1 ] };
IN [dLC0..dLC7] => {
CheckOpLength[op, 1];
m ← [
bReg: [ cBase, op47 ],
cReg: [ s, one ],
deltaS: 1 ] };
IN [dLR0..dLR15] => {
CheckOpLength[op, 1];
m ← [
bReg: [ l, op47 ],
cReg: [ s, one ],
deltaS: 1 ] };
IN [dSR0..dSR15] => {
CheckOpLength[op, 1];
m ← [
bReg: [ s, zero ],
cReg: [ l, op47 ],
deltaS: -1 ] };
dDUP => {
CheckOpLength[op, 1];
m ← [
bReg: stackTop,
cReg: [ s, one ],
deltaS: 1 ] };
dEXDIS => {
CheckOpLength[op, 1];
m ← [
bReg: stackTop,
cReg: [ s, minus1 ],
deltaS: -1 ] };
dEXCH => {
CheckOpLength[op, 1];
m ← [
getNextMacro: FALSE,
xBSource: pc,
bReg: stackTop,
cReg: [ s, minus1 ] ] };
dSEUR => {
CheckOpLength[op, 2];
m ← [
bReg: stackTop,
cReg: [ zero, alpha ],
deltaS: -1 ] };
dSIFUR => {
CheckOpLength[op, 2];
m ← [
getNextMacro: FALSE,
xBSource: pc,
bReg: stackTop,
cReg: [ zero, alpha ] ] };
dLEUR => {
CheckOpLength[op, 2];
m ← [
bReg: [ zero, alpha ],
cReg: [ s, one ],
deltaS: 1 ] };
dLIFUR => {
CheckOpLength[op, 2];
m ← [
bReg: [zero, alpha],
xASource: bAddrIFUReg,
aluRtIsK: TRUE,
cReg: [ s, one ],
deltaS: 1 ] };
dADDB => {
CheckOpLength[op, 2];
m ← [
aReg: stackTop,
xASource: alpha,
aluRtIsK: TRUE,
cReg: stackTop,
aluOp: SAdd,
condSel: OvFl ] };
dADDDB => {
CheckOpLength[op, 3];
m ← [
aReg: stackTop,
xASource: betaAlpha,
aluRtIsK: TRUE,
cReg: stackTop,
aluOp: SAdd,
condSel: OvFl ] };
dSUBB => {
CheckOpLength[op, 2];
m ← [
aReg: stackTop,
xASource: alpha,
aluRtIsK: TRUE,
cReg: stackTop,
aluOp: SSub,
condSel: OvFl ] };
dSHL, dSHR => {
CheckOpLength[op, 3];
m ← [
aReg: stackTop,
bReg: [ (IF opcode=dSHL THEN cBase ELSE s), zero ],
xASource: betaAlpha,
cReg: stackTop,
aluOp: FOPK ] };
dADD => {
CheckOpLength[op, 1];
m ← [
aReg: [ s, minus1 ],
bReg: stackTop,
cReg: [ s, minus1 ],
deltaS: -1,
aluOp: SAdd,
condSel: OvFl,
condEffect: macroTrap ] };
dSUB => {
CheckOpLength[op, 1];
m ← [
aReg: [ s, minus1 ],
bReg: [ s, zero ],
cReg: [ s, minus1 ],
deltaS: -1,
aluOp: SSub,
condSel: OvFl,
condEffect: macroTrap ] };
dMUL => {
CheckOpLength[op, 1];
m ← [
getNextMacro: FALSE,
xBSource: pc,
aReg: constantZero,  -- R1 = Product.msw ← 0
bReg: [ s, minus1 ], -- MQ = Product.lsw | Multiplier ← Multiplier
cReg: [ s, minus1 ], -- Product.msw
aluOp: PassLtWtMQ ] };
dDIV => {
CheckOpLength[op, 1];
m ← [
getNextMacro: FALSE,
xBSource: pc,
aReg: [ s, minus2 ],
bReg: [ s, zero ],
aluOp: VSub,
condSel: GE,
condEffect: macroTrap ] };
dFP => {
CheckOpLength[op, 2];
SELECT DragonFP.GetFPOpType[alpha] FROM
setMode          => m ← [
getNextMacro: FALSE, -- delay one for KBus contention
xBSource:   pc,
xASource:  fpLdMode,
euPBusCmd:  StoreFP];
sglUnCom, sglUnAlu, sglUnCvt  => m ← [
getNextMacro: FALSE,
xBSource:   pc,
bReg:    [ s, zero ],
xASource:  fpLdAMsw,
euPBusCmd:  StoreFP];
dblUnCom, dblUnAlu, dblUnCvt  => m ← [
getNextMacro: FALSE,
xBSource:   pc,
bReg:    [ s, zero ],
xASource:  fpLdALsw,
euPBusCmd:  StoreFP];
sglBiCom, sglBiAlu,  sglBiMult  => m ← [
getNextMacro: FALSE,
xBSource:   pc,
bReg:    [ s, zero ],
xASource:  fpLdBMsw,
euPBusCmd:  StoreFP];
dblBiCom, dblBiAlu, dblBiMult  => m ← [
getNextMacro: FALSE,
xBSource:   pc,
bReg:    [ s, zero ],
xASource:  fpLdBLsw,
euPBusCmd:  StoreFP];
ENDCASE => Dragon.Assert[FALSE] };
dBNDCK => {
CheckOpLength[op, 1];
m ← [
aReg: [ s, minus1 ],
bReg: [ s, zero ],
deltaS: -1,
aluOp: BndChk,
condSel: BC,
condEffect: macroTrap ] };
IN DragOpsCross.RRformatRange => {
rr: DragOpsCross.RRformat;
TRUSTED {rr ← LOOPHOLE[instruction]};
CheckOpLength[op, 3];
m ← [
aReg: [
(SELECT TRUE FROM
rr.aOpt AND NOT (rr.a MOD 16 >= 8) => cBase,
rr.aOpt AND NOT (rr.a MOD 8 >= 4) => cBase,
rr.aOpt AND (rr.a MOD 16 >= 8) AND (rr.a MOD 8 >= 4) => s,
NOT rr.aOpt AND rr.aux => aBase,
ENDCASE -- NOT rr.aOpt AND NOT rr.aux -- => l),
(SELECT TRUE FROM
rr.aOpt AND NOT (rr.a MOD 16 >= 8) => alpha47,
rr.aOpt AND NOT (rr.a MOD 8 >= 4) => alpha47,
rr.aOpt AND (rr.a MOD 16 >= 8) AND (rr.a MOD 8 >= 4) AND NOT (rr.a MOD 2 >= 1) => zero,
rr.aOpt AND (rr.a MOD 16 >= 8) AND (rr.a MOD 8 >= 4) AND (rr.a MOD 2 >= 1) => minus1,
ENDCASE -- NOT rr.aOpt -- => alpha47)],
bReg: [
(SELECT TRUE FROM
rr.bOpt AND NOT (rr.b MOD 16 >= 8) => cBase,
rr.bOpt AND NOT (rr.b MOD 8 >= 4) => cBase,
rr.bOpt AND (rr.b MOD 16 >= 8) AND (rr.b MOD 8 >= 4) => s,
NOT rr.bOpt AND rr.aux => aBase,
ENDCASE -- NOT rr.bOpt AND NOT rr.aux -- => l),
(SELECT TRUE FROM
rr.bOpt AND NOT (rr.b MOD 16 >= 8) => beta47,
rr.bOpt AND NOT (rr.b MOD 8 >= 4) => beta47,
rr.bOpt AND (rr.b MOD 16 >= 8) AND (rr.b MOD 8 >= 4) AND NOT (rr.b MOD 2 >= 1) => zero,
rr.bOpt AND (rr.b MOD 16 >= 8) AND (rr.b MOD 8 >= 4) AND (rr.b MOD 2 >= 1) => minus1,
ENDCASE -- NOT rr.bOpt -- => beta47)],
cReg: [
(SELECT TRUE FROM
rr.cOpt AND NOT (rr.c MOD 16 >= 8) => cBase,
rr.cOpt AND NOT (rr.c MOD 8 >= 4) => cBase,
rr.cOpt AND (rr.c MOD 16 >= 8) AND (rr.c MOD 8 >= 4) => s,
NOT rr.cOpt AND rr.aux => aBase,
ENDCASE -- NOT rr.cOpt AND NOT rr.aux -- => l),
(SELECT TRUE FROM
rr.cOpt AND NOT (rr.c MOD 16 >= 8) => alpha03,
rr.cOpt AND NOT (rr.c MOD 8 >= 4) => alpha03,
rr.cOpt AND (rr.c MOD 16 >= 8) AND (rr.c MOD 8 >= 4) AND NOT (rr.c MOD 4 >= 2) AND NOT (rr.c MOD 2 >= 1) => zero,
rr.cOpt AND (rr.c MOD 16 >= 8) AND (rr.c MOD 8 >= 4) AND NOT (rr.c MOD 4 >= 2) AND (rr.c MOD 2 >= 1) => minus1,
rr.cOpt AND (rr.c MOD 16 >= 8) AND (rr.c MOD 8 >= 4) AND (rr.c MOD 4 >= 2) => one,
ENDCASE -- NOT rr.cOpt -- => alpha03)],
deltaS: INT[SELECT TRUE FROM
rr.aOpt AND (rr.a MOD 16 >= 8) AND (rr.a MOD 8 >= 4) AND (rr.a MOD 4 >= 2) => -1,
ENDCASE => 0]+
INT[SELECT TRUE FROM
rr.bOpt AND (rr.b MOD 16 >= 8) AND (rr.b MOD 8 >= 4) AND (rr.b MOD 4 >= 2) => -1,
ENDCASE => 0]+
INT[SELECT TRUE FROM
rr.cOpt AND (rr.c MOD 16 >= 8) AND (rr.c MOD 8 >= 4) AND (rr.c MOD 4 >= 2) AND (rr.c MOD 2 >= 1) => 1,
ENDCASE => 0],
aluOp: (SELECT opcode FROM
dRFU => FOP,
dRADD => SAdd,
dRAND => And,
dRLADD => LAdd,
dRLSUB => LSub,
dROR => Or,
dRRX => VAdd,
dRSUB => SSub,
dRUADD => UAdd,
dRUSUB => USub,
dRVADD => VAdd,
dRVSUB => VSub,
dRXOR => Xor,
ENDCASE => Reserve31),
condSel: (SELECT opcode FROM
dRADD, dRSUB => OvFl,
dRLADD, dRLSUB => IL,
ENDCASE => False),
euPBusCmd: (SELECT opcode FROM
dRRX => Fetch,
ENDCASE => NoOp)
] };
ENDCASE => -- unimplemented opcode
SELECT Dragon.OpLength[op] FROM
1 =>
m ← [
doMacroJump: TRUE,
getNextMacro: FALSE,
xBSource: xopGenerator,
pipedPLSASpec: pLenLSnext,
iStackPostEffect: push ];
2, 3, 5 =>
m ← [
getNextMacro: FALSE,
xBSource: pc,
xASource: deltaGammaBetaAlpha,
aluRtIsK: TRUE,
cReg: [ s, one ] ];
ENDCASE => Dragon.Assert[ FALSE, "Unimplemented Dragon microcode" ];
}; -- of DecodeFirstMicroOfNewMacro
CheckOpLength: PROC [op: Dragon.HexByte, len: [0..5]] =
{Dragon.Assert[ Dragon.OpLength[op] = len ]};
END.