IF PhB
AND ~hold3AB
THEN
-- EPFaultB ???
BEGIN
-- Temporary
PlusOrMinusAluRight, aluOut: Dragon.HexWord;
c32, overflow, conditionB: BOOL;
rejectBA ← EPRejectB;
EPRejectB 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 result3BA depends upon EPRejectB, and the choice is made during the same PhiB as it is received. So this statement has to be first. I'll try to get rid of this pb by shooting all cases where EPRejectB is needed during PhiB.
faultBA ← EPFaultB#Dragon.None AND EPRejectB;
Updating the RAM addresses
aAdr ← ECFD[KBus, 32, 0, 8];
bAdr ← ECFD[KBus, 32, 8, 8];
cAdr ← ECFD[KBus, 32, 16, 8];
-- aAdr in proper range (push in finer simulation???)
Dragon.Assert[
aAdr IN [0..128) -- stack
OR aAdr IN [130..135] -- euMAR, euField, and FP add
OR aAdr IN [140..143] -- FP mult
OR aAdr IN [144..155] -- constants
OR aAdr IN [160..176)]; -- aux
-- bAdr in proper range
Dragon.Assert[
bAdr IN [0..128) -- stack
OR bAdr IN [130..135] -- euMAR, euField, and FP add
OR bAdr IN [140..143] -- FP mult
OR bAdr IN [144..155] -- constants
OR bAdr IN [160..176)]; -- aux
-- cAdr in proper range
Dragon.Assert[
-- EUMar cannot be written using cAdr
cAdr IN [0..128] -- stack+euJunk
OR cAdr IN [131..135] -- no MAR, but euField and FP add
OR cAdr IN [140..143] -- FP mult
OR cAdr IN [144..155] -- constants
OR cAdr IN [160..176] -- aux
OR cAdr IN [240..255]]; -- IFU regs
-- PBus: notice that in case of reject during a store, we keep sending the data even though it is useless
-- The default source for result3BA is result3AB; the only case where we update that register with the value found on the PBus is when a fetch terminates with no reject.
Dragon.Assert[NOT (EUWriteToPBus3AB AND EURes3BisPBus3AB)]; -- just for simulation
IF EUWriteToPBus3AB
THEN
-- store in progress
BEGIN
EPData ← Dragon.LTD[store3AB]; -- send data to Cache (Store)
result3BA ← result3AB -- save the address in result3BA, done normally since NOT EURes3BisPBus3AB
END
ELSE
-- either a fetch, an op, or a move in progress, but no write on the PBus
SELECT
TRUE
FROM
~rejectBA
AND EURes3BisPBus3AB =>
-- Fetch without reject
result3BA ← Dragon.LFD[EPData];
rejectBA
OR (~rejectBA
AND ~EURes3BisPBus3AB) =>
-- Fetch with reject, op, move
result3BA ← result3AB;
ENDCASE => ERROR;
Data pipe
store2BA ← store2AB;
Alu and Field Unit computation
Set Default values of state
carryBA ← carryAB; -- ???
SELECT EUAluOp2AB
FROM
SAdd => {
[aluOut, c32] ← DoubleADD[leftOp2AB, rightOp2AB, carryAB];
result2BA ← aluOut;
carryBA ← FALSE};
SSub => {
[aluOut, c32] ← DoubleSUB[leftOp2AB, rightOp2AB, carryAB];
result2BA ← aluOut;
carryBA ← FALSE};
UAdd => {
[aluOut, c32] ← DoubleADD[leftOp2AB, rightOp2AB, carryAB];
result2BA ← aluOut;
carryBA ← c32};
USub => {
[aluOut, c32] ← DoubleSUB[leftOp2AB, rightOp2AB, carryAB];
result2BA ← aluOut;
carryBA ← NOT c32};
VAdd, VAdd2 => {
[aluOut, c32] ← DoubleADD[leftOp2AB, rightOp2AB, FALSE];
result2BA ← aluOut};
VSub => {
[aluOut, c32] ← DoubleSUB[leftOp2AB, rightOp2AB, FALSE];
result2BA ← aluOut};
LAdd => {
[aluOut, c32] ← DoubleADD[leftOp2AB, rightOp2AB, FALSE];
result2BA ← aluOut;
carryBA ← FALSE};
LSub => {
[aluOut, c32] ← DoubleSUB[leftOp2AB, rightOp2AB, FALSE];
result2BA ← aluOut;
carryBA ← FALSE};
FOP => {
-- field descriptor provided by Field
result2BA ← aluOut ← FieldOp[leftOp2AB, rightOp2AB, field]};
FOPK => {
-- field descriptor provided by kBusAB. Otherwise identical to FOP
result2BA ← aluOut ← FieldOp[leftOp2AB, rightOp2AB, kBusAB]};
And => {
result2BA ← aluOut ← WordOp[and, leftOp2AB, rightOp2AB]};
Or => {
result2BA ← aluOut ← WordOp[or, leftOp2AB, rightOp2AB]};
Xor => {
result2BA ← aluOut ← WordOp[xor, leftOp2AB, rightOp2AB]};
BndChk => {
[aluOut, c32] ← DoubleSUB[leftOp2AB, rightOp2AB, FALSE];
result2BA ← leftOp2AB};
MulLd, MulStep, RdMQ, DivLdDbl, DivCk, DivStep, DivAdjQ, DivAdjR => {NULL}; -- ???
ENDCASE => ERROR Stop["Invalid ALU Operation"];
-- Here we compute the overflow by checking the high-order bits of the operands (leftOp2AB and rightOp2AB or - rightOp2AB) and of the result
SELECT EUAluOp2AB
FROM
SSub, USub, VSub, LSub =>
[PlusOrMinusAluRight, ] ← DoubleSUB[0, rightOp2AB, FALSE];
ENDCASE => PlusOrMinusAluRight ← rightOp2AB;
overflow ← (EBFL[leftOp2AB, 0] = EBFL[PlusOrMinusAluRight, 0]) AND (EBFL[leftOp2AB, 0] # EBFL[aluOut, 0]);
-- Condition and trap generation
conditionB ←
SELECT EUCondSel2AB
FROM
False => FALSE,
EZ => aluOut=0, -- not necessarily after a sub!!!
LZ => EBFL[aluOut, 0], -- aluOut<0 by checking the high-order bit
LE => (aluOut=0) OR EBFL[aluOut, 0], -- aluOut<=0,
True => TRUE,
NE => aluOut#0,
GE => NOT EBFL[aluOut, 0],
GZ => NOT ((aluOut=0) OR EBFL[aluOut, 0]), -- aluOut>0,
OvFl => overflow,
BC => EBFL[leftOp2AB, 0] OR -- arg < 0
NOT EBFL[aluOut, 0], -- arg-limit >= 0
IL => (EBFL[leftOp2AB, 0]#EBFL[leftOp2AB, 1]) OR
(EBFL[rightOp2AB, 0]#EBFL[rightOp2AB, 1]) OR
(EBFL[aluOut, 0]#EBFL[aluOut, 1]), -- No: 3 bits!!!
DivOvFl => FALSE, -- for now...
NotOvFl => NOT overflow,
NotBC => NOT EBFL[leftOp2AB, 0] -- 0<=arg -- AND EBFL[aluOut, 0] -- arg-limit<0 --,
NotIL => NOT ((EBFL[leftOp2AB, 0]#EBFL[leftOp2AB, 1]) OR
(EBFL[rightOp2AB, 0]#EBFL[rightOp2AB, 1]) OR
(EBFL[aluOut, 0]#EBFL[aluOut, 1])),
Kernal => ECFD[Dragon.LTD[aluOut], 32, 0, 4]=0, -- msb(aluOut, 4)=0
ENDCASE => ERROR Stop["Invalid EUCondition2BA Code"];
EUCondition2BA ← conditionB;
END;