IF PhA
THEN {
cReg: DragOpsCross.ProcessorRegister;
DragonRosemary.Assert[aAdr>=0 AND aAdr<164];
No simultaneous bypass control signals on
IF NOT (rejectBA OR EUCondition2B) THEN {carryAB ← carryBA};
IF
NOT rejectBA
THEN {
SELECT EUAluLeftSrc1BA
FROM
aBus => aluLeft ← (
SELECT aAdr
FROM
DragOpsCross.ProcessorRegister[euConstant].ORD => 0,
ENDCASE => ram[aAdr] -- watch out for illegal addresses
);
rBus => aluLeft ← result2BA;
cBus => aluLeft ← cBusResult3BA;
ENDCASE => DragonRosemary.Assert[FALSE];
SELECT EUAluRightSrc1BA
FROM
bBus => aluRight ← (
SELECT bAdr
FROM
DragOpsCross.ProcessorRegister[euConstant].ORD => 0,
ENDCASE => ram[bAdr] -- watch out for illegal addresses
);
rBus => aluRight ← result2BA;
cBus => aluRight ← cBusResult3BA;
kBus => aluRight ← DragonRoseExtras.LFD[KBus];
fCtlReg => aluRight ← field;
ENDCASE => DragonRosemary.Assert[FALSE];
SELECT EUStore2ASrc1BA
FROM
bBus => store2AB ← (
SELECT bAdr
FROM
DragOpsCross.ProcessorRegister[euConstant].ORD => 0,
ENDCASE => ram[bAdr] -- watch out for illegal addresses
);
cBus => store2AB ← cBusResult3BA;
rBus => store2AB ← result2BA;
ENDCASE => DragonRosemary.Assert[FALSE];
result3AB ← result2BA;
Always send address to Cache during PhiA
drive[DPData] ← drive;
DPData ← DragonRoseExtras.LTD[result2BA];
store3AB ←
SELECT EUSt3AisCBus2BA
FROM
TRUE => cBusResult3BA,
ENDCASE => store2BA;
IF
NOT rejectBA
AND cIsField
THEN field ← cBusResult3BA;
ALULeft2AB ← DragonRoseExtras.LTD[aluLeft];
ALURight2AB ← DragonRoseExtras.LTD[aluRight];
Store2AB ← DragonRoseExtras.LTD[store2AB];
};
-- On every PhA with RejectBA the faulty address is saved in ram[euMAR]; the EU generates the appropriate cAdr when RejectBA is sensed, so the rule is: we always write into the register file! (Q: what about euToKBus? LMM)
SELECT (cReg ←
VAL[cAdr])
FROM
IN [euStack .. euJunk), euMAR,
IN [euField .. euBogus) =>
ram[cAdr] ← cBusResult3BA;
euJunk => NULL;
euToKBus => {
-- don't mind reject???
drive[KBus] ← drive;
KBus ← DragonRoseExtras.LTD[cBusResult3BA];
};
ENDCASE => DragonRosemary.Assert[FALSE, "EU cAdr out of range"];
};
IF PhB
THEN {
c32, cx: BOOL;
rejectBA ← DPRejectB;
DPRejectB is valid at the end of PhiB but bogus during PhiA, so it must be latched at the end of PhiB. A current problem is that the source for cBusResult3BA depends upon DPRejectB, and the choice is made during the same PhiB as it is received. So this statement has to be first.
Updating the RAM addresses
aAdr ← BitOps.ECFD[KBus, 32, Dragon.aRegKBusPos, 8];
bAdr ← BitOps.ECFD[KBus, 32, Dragon.bRegKBusPos, 8];
cAdr ←
IF rejectBA
THEN DragOpsCross.ProcessorRegister[euMAR].
ORD
ELSE BitOps.ECFD[KBus, 32, Dragon.cRegKBusPos, 8];
cIsField ← BitOps.EBFD[KBus, 32, 24];
EUAluLeftSrc1BA ← VAL[BitOps.ECFD[KBus, 32, 25, 2]];
EUAluRightSrc1BA ← VAL[BitOps.ECFD[KBus, 32, 27, 3]];
EUStore2ASrc1BA ← VAL[BitOps.ECFD[KBus, 32, 30, 2]];
PBus: notice that in case of reject during a store, we keep sending the data even though it is useless
DragonRosemary.Assert[NOT (EUWriteToPBus3AB AND EURes3BisPBus3AB)];
SELECT
TRUE
FROM
EUWriteToPBus3AB => {
-- store in progress
drive[DPData] ← drive;
DPData ← DragonRoseExtras.LTD[store3AB]; -- send data to Cache (Store)
cBusResult3BA ← result3AB};
save the address in cBusResult3BA, done normally since NOT EURes3BisPBus3AB;
ENDCASE => {
-- either a fetch, an op, or a move in progress
IF rejectBA
-- Fetch with reject => save address in cBusResult3BA and don't listen to IFU
THEN cBusResult3BA ← result3AB
ELSE
-- Fetch without reject --
IF EURes3BisPBus3AB
THEN {
cBusResult3BA ← DragonRoseExtras.LFD[DPData];}
ELSE cBusResult3BA ← result3AB}; -- op or move ;
Data pipe
store2BA ← store2AB;
Alu and Field Unit computation
Set Default values of state
carryBA ← carryAB;
SELECT EUAluOp2AB
FROM
SAdd => {
[aluOut, c32] ← DoubleADD[aluLeft, aluRight, carryAB];
result2BA ← aluOut;
carryBA ← FALSE};
SSub => {
[aluOut, cx] ← DoubleADD[aluLeft, DoubleNOT[aluRight], NOT carryAB];
c32 ← NOT cx;
result2BA ← aluOut;
carryBA ← FALSE};
UAdd => {
[aluOut, c32] ← DoubleADD[aluLeft, aluRight, carryAB];
result2BA ← aluOut;
carryBA ← c32};
USub => {
[aluOut, cx] ← DoubleADD[aluLeft, DoubleNOT[aluRight], NOT carryAB];
c32 ← NOT cx;
result2BA ← aluOut;
carryBA ← c32};
VAdd, VAdd2 => {
[aluOut, c32] ← DoubleADD[aluLeft, aluRight, FALSE];
result2BA ← aluOut};
VSub => {
[aluOut, cx] ← DoubleADD[aluLeft, DoubleNOT[aluRight], TRUE];
c32 ← NOT cx;
result2BA ← aluOut};
LAdd => {
[aluOut, c32] ← DoubleADD[aluLeft, aluRight, FALSE];
result2BA ← aluOut;
carryBA ← FALSE};
LSub => {
[aluOut, cx] ← DoubleADD[aluLeft, DoubleNOT[aluRight], TRUE];
c32 ← NOT cx;
result2BA ← aluOut;
carryBA ← FALSE};
FOP => {
result2BA ← aluOut ← FieldOp[aluLeft, store2AB, aluRight]};
And => {
result2BA ← aluOut ← WordOp[and, aluLeft, aluRight]};
Or => {
result2BA ← aluOut ← WordOp[or, aluLeft, aluRight]};
Xor => {
result2BA ← aluOut ← WordOp[xor, aluLeft, aluRight]};
BndChk => {
[aluOut, cx] ← DoubleADD[aluLeft, DoubleNOT[aluRight], TRUE];
c32 ← NOT cx;
result2BA ← aluLeft};
ENDCASE => ERROR Stop["Invalid ALU Operation"];
Condition and trap generation
conditionB ←
SELECT EUCondSel2AB
FROM
False => FALSE,
EZ => aluOut=0, -- aluOut=0
LZ => (c32 # (EBFL[aluLeft, 0] # EBFL[aluRight, 0])), -- VSub<0
LE => (aluOut=0) OR (c32 # (EBFL[aluLeft, 0] # EBFL[aluRight, 0])), -- VSub<=0,
AddressCheckFault => aluOut < DragOpsCross.KernalLimit,
NE => aluOut#0, -- aluOut#0
GE => NOT (c32 # (EBFL[aluLeft, 0] # EBFL[aluRight, 0])), -- VSub>=0
GZ => NOT ((aluOut=0) OR (c32 # (EBFL[aluLeft, 0] # EBFL[aluRight, 0]))), -- VSub>0
OvFl => ((c32 # EBFL[aluOut, 0]) # (EBFL[aluLeft, 0] # EBFL[aluRight, 0])),
BC => NOT c32,
IL => (ELispFL[aluLeft] IN (0..7) ) OR
(ELispFL[aluRight] IN (0..7) ) OR
(ELispFL[aluOut] IN (0..7) ),
NotBC => c32,
NotIL => NOT ((ELispFL[aluLeft] IN (0..7) ) OR
(ELispFL[aluRight] IN (0..7) ) OR
(ELispFL[aluOut] IN (0..7) )),
ModeFault => TRUE,
ENDCASE => ERROR Stop["Invalid EUCondition2B Code"];
EUCondition2B ← conditionB;
CBusResult3BA ← DragonRoseExtras.LTD[cBusResult3BA];
};