<> <> <> <> <> <<>> <> Directory Rope, DragOpsCross; Imports Atom, IO, BitOps, Cucumber, Dragon, RoseRun, RoseTypes, CacheOps, DragOpsCrossUtils; Cedar fieldAdr: INTEGER = PRtoByte[euField]; marAdr: INTEGER = PRtoByte[euMAR]; Remark: PROC [ message: Rope.ROPE ] = {RoseRun.DisableableStop[Remark, message]}; <> FieldOp: PROC[aluLeft, aluRight, fieldDesc: Dragon.HexWord] RETURNS [result:Dragon.HexWord] = BEGIN fd: DragOpsCross.FieldDescriptor _ DragOpsCrossUtils.CardToFieldDescriptor[fieldDesc MOD 65536]; shiftout: BitOps.BitDWord _ [0,0]; -- to begin cleanly maskhole: BitOps.BitDWord _ BitOps.doubleMasks[fd.mask]; <> Dragon.Assert[fd.shift < 33]; Dragon.Assert[fd.mask < 33]; SELECT fd.shift FROM 0 => shiftout _ Dragon.LTD[aluLeft]; -- no shift 32 => shiftout _ Dragon.LTD[aluRight]; -- full shift ENDCASE => { <> shiftout _ BitOps.MDTD [Dragon.LTD[aluLeft], 32, fd.shift, 32-fd.shift, shiftout, 32, 0, 32-fd.shift]; <> shiftout _ BitOps.MDTD [Dragon.LTD[aluRight], 32, 0, fd.shift, shiftout, 32, 32-fd.shift, fd.shift] }; result _ Dragon.LFD[BitOps.DAND[shiftout, maskhole]]; -- mask shiftout IF fd.insert THEN { mask2: BitOps.BitDWord _ BitOps.doubleMasks[fd.shift]; -- another intermediate mask <> maskhole _ BitOps.DNOT[BitOps.DXOR[maskhole, mask2],32]; <> result _ WordOp[or, result, WordOp[and, aluRight, Dragon.LFD[maskhole] ] ] }; END; <> DoubleADD: PROC[al, bl: Dragon.HexWord, carry: BOOL] RETURNS [sl: Dragon.HexWord, c32: BOOL] = { Xor: PROC[x, y: BOOL] RETURNS [z: BOOL] = {RETURN[(x AND NOT y) OR (y AND NOT x)]}; ai, bi: BOOL; s: BOOL _ FALSE; c: BOOL _ carry; i: INTEGER; sum: BitOps.BitDWord _ [0,0]; FOR i IN [1..32] DO ai _ EBFL[al, 32-i]; bi _ EBFL[bl, 32-i]; s _ Xor[ai, Xor[bi, c]]; c _ (ai AND bi) OR (bi AND c) OR (ai AND c); sum _ BitOps.IBID[s, sum, 32, 32-i]; ENDLOOP; RETURN[Dragon.LFD[sum], c]}; <> <> DoubleSUB: PROC[a, b: Dragon.HexWord, carry: BOOL] RETURNS [dif: Dragon.HexWord, c32: BOOL] ={ [dif, c32] _ DoubleADD[a, WordOp[not,b], NOT carry]}; PRtoByte:PROC[pr:DragOpsCross.ProcessorRegister] RETURNS [byte:Dragon.HexByte] = {byte _ LOOPHOLE[pr]}; WordOp: PROC[op:{not, or, and, xor}, left, right:Dragon.HexWord _ 0] RETURNS[result:Dragon.HexWord] = { RETURN[Dragon.LFD[SELECT op FROM not => BitOps.DNOT [Dragon.LTD[left], 32], or => BitOps.DOR [Dragon.LTD[left], Dragon.LTD[right]], and => BitOps.DAND [Dragon.LTD[left], Dragon.LTD[right]], xor => BitOps.DXOR [Dragon.LTD[left], Dragon.LTD[right]], ENDCASE => ERROR]] }; EBFL: PROC[word: Dragon.HexWord, index: CARDINAL] RETURNS[BOOL] = { RETURN[ BitOps.EBFD[Dragon.LTD[word], 32, index]] }; DblShiftRt: PROC[msb: BOOL, ltIn, rtIn: Dragon.HexWord] RETURNS[ltOut, rtOut: Dragon.HexWord] = {rtOut _ ShiftRt[EBFL[ltIn, 31], rtIn]; ltOut _ ShiftRt[msb, ltIn]}; ShiftRt: PROC[msb: BOOL, w: Dragon.HexWord] RETURNS[r: Dragon.HexWord] = {r_Dragon.LFD[BitOps.IBID[msb, BitOps.MDTD[Dragon.LTD[w],32,0,31,[0,0],32,1,31],32,0]]}; DblShiftLt: PROC[ltIn, rtIn: Dragon.HexWord, lsb: BOOL] RETURNS[cry: BOOL, ltOut, rtOut: Dragon.HexWord] = {cry _ EBFL[ltIn,0]; ltOut _ ShiftLt[ltIn, EBFL[rtIn, 0]]; rtOut _ ShiftLt[rtIn, lsb]}; ShiftLt: PROC[w: Dragon.HexWord, lsb: BOOL] RETURNS[r: Dragon.HexWord] = {r_Dragon.LFD[BitOps.IBID[lsb, BitOps.MDTD[Dragon.LTD[w],32,1,31,[0,0],32,0,31],32,31]]}; ; EU: CELL [ <<>> <> <<>> <

> EPData=INT[32], -- address/data to cache/FP during PhA, data to/from cache/FP during PhB EPRejectB> PhA, PhB> <> <> <> <> <> <> <> KBus= INT[32], -- a, b, and c ram addresses are multiplexed on KBus. a=[0..7], b=[8..15], c=[16..23], addresses during PhiB, data during PhiA, data direction is EU -> IFU if cAdr in [ifuXBus..ifuLast] during the previous PhiB, otherwise it is IFU -> EU or FP. <> EUAluLeftisR1BA, EUAluLeftisR3BA < BOOL, -- same timing as RAM addresses: 1B EUAluRightisKBA, EUAluRightisR1BA, EUAluRightisR3BA < BOOL, -- same timing as RAM addresses: 1B EUS1isR1BA, EUS1isR3BA < BOOL, -- same timing as RAM addresses: 1B EUR2isR3BA < BOOL, -- sent when data is in result1: 2B EUS3isR3BA < BOOL, -- sent when data is in store2: 2B EUHoldCarryBA < BOOL, -- received on PhB following a CCTrap or an EUCache Fault, and prevents any carry change on next PhA. <> EUR3isR2AB < BOOL, -- multiplexor control on R3: 3A EUWriteToPBusAB < BOOL, -- sent by the IFU during 3A, stable during 3B; specifies read/write to Cache on 3B. Used for Store instructions, and issued every instruction following an EPrejectB. This is not necessary, but so far OK and simple. EUCheckPParityAB < BOOL, -- sent by the IFU during 3A, stable during 3B; instructs EU to Check parity of cache reads. <> EUAluOpAB< EnumType["Dragon.ALUOps"], -- sent on 1A, used during 2B. Not latched by EU. EUCondSelAB< EnumType["Dragon.CondSelects"], -- idem for timing <> EUTrapBA< BOOL, -- if selected condition is true then trap EUConditionBA> BOOL, -- selected condition sent to IFU during 2B, latched during PhA to hide precharge in the carry propagator and other things. InstrCountAB> <> <> DShiftAB> euLogRef: REF REF, <<>> <> aluLeft, aluRight, aluOut: Dragon.HexWord, result1, result2, result3: Dragon.HexWord, store1, store2, store3: Dragon.HexWord, <<>> <> <> <> <<128: euJunk i.e. no write>> <<129: (currently spare)>> <<130: euMAR>> <<131: euField>> <<132 through 147 are auxilliary registers>> <<148 thru 151: (currently spare)>> <<152 through 163 are constants>> <> aAdr, bAdr, cAdr: Dragon.HexByte, ram: ARRAY Dragon.HexByte OF Dragon.HexWord, field: Dragon.HexWord, -- a copy is kept as RAM[fieldAdr], another copy is in the field unit. Any write is performed to both physical locations, any read is from the most convenient location. <<>> <> mqAB, mqBA: Dragon.HexWord, mulcandSAB, mulcandSBA: BOOL, mulProdSAB, mulProdSBA: BOOL, mulSubAB, mulSubBA: BOOL, divisorSAB, divisorSBA: BOOL, divendSAB, divendSBA: BOOL, divZeroAB, divZeroBA: BOOL, divRmsbAB, divRmsbBA: BOOL, divRCorrAB, divRCorrBA: BOOL, divQIncrAB, divQIncrBA: BOOL, <<>> mar: Dragon.HexWord, -- contains the faulty address after a cache access <> kBusAB: Dragon.HexWord, -- a register to hold KBus for use in the field unit if required carryAB, carryBA: BOOL, -- carryBA is the output of the adder modified by the opcode of the previous operation and latched if no trap; carryAB is a copy of carryBA if there is no reject or fault. conditionB: BOOL, overflow: BOOL, -- temporary state, does not survive through a whole cycle <> rejectBA: BOOL, -- a copy of EPRejectB stable during PhiA faultBA: BOOL, -- a latched veriosn of EPFaultB # None parityResult3, parityStore3: BOOL -- parity associated to the register EvalSimple log _ NARROW[euLogRef^]; ram[PRtoByte[euConstant]] _ 0; -- done by IFU <> <<>> IF PhA THEN { Dragon.Assert[aAdr>=0 AND aAdr<164]; <<>> <> Dragon.Assert[NOT (EUAluLeftisR1BA AND EUAluLeftisR3BA)]; Dragon.Assert[NOT Dragon.MoreThanOneOf[EUAluRightisR1BA, EUAluRightisR3BA, EUAluRightisKBA]]; Dragon.Assert[NOT (EUS1isR1BA AND EUS1isR3BA)]; Dragon.Assert[NOT (EUAluLeftisR1BA AND EUAluLeftisR3BA)]; <<>> <> IF rejectBA AND faultBA THEN {ram[marAdr] _ result3}; -- save the faulty address IF NOT (EUHoldCarryBA OR rejectBA OR (EUTrapBA AND EUConditionBA)) THEN {carryAB _ carryBA}; <<>> <> mqAB _ mqBA; mulcandSAB _ mulcandSBA; mulProdSAB _ mulProdSBA; mulSubAB _ mulSubBA; divisorSAB _ divisorSBA; divendSAB _ divendSBA; divZeroAB _ divZeroBA; divRmsbAB _ divRmsbBA; divRCorrAB _ divRCorrBA; divQIncrAB _ divQIncrBA; rejected _ rejectBA; IF NOT rejectBA THEN { kBusAB _ Dragon.LFD[KBus]; aluLeft _ SELECT TRUE FROM EUAluLeftisR1BA => result1, EUAluLeftisR3BA => result3, ENDCASE => ram[aAdr]; -- watch out for illegal addresses aluRight _ SELECT TRUE FROM EUAluRightisR1BA => result1, EUAluRightisR3BA => result3, EUAluRightisKBA => Dragon.LFD[KBus], ENDCASE => ram[bAdr]; -- watch out for illegal addresses store1 _ SELECT TRUE FROM EUS1isR1BA => result1, EUS1isR3BA => result3, ENDCASE => ram[bAdr]; -- watch out for illegal addresses result2 _ SELECT TRUE FROM EUR2isR3BA => result3, ENDCASE => result1; <> EPData _ Dragon.LTD[result1]; store3 _ SELECT TRUE FROM EUS3isR3BA => result3, ENDCASE => store2; parityStore3 _ IF EUS3isR3BA THEN parityResult3 ELSE CacheOps.Parity32[store2]; <> <> SELECT TRUE FROM <> cAdr IN [PRtoByte[euStack] .. PRtoByte[euConstant]+12) => ram[cAdr] _ result3; <> cAdr IN [PRtoByte[ifuXBus] .. PRtoByte[ifuLast]] => KBus _ Dragon.LTD[result3]; ENDCASE => Dragon.Assert[FALSE, "EU cAdr out of range"]; phBLastFLAG _ FALSE; }; }; <<>> <<>> <> IF PhB THEN { -- EPFaultB ??? PlusOrMinusAluRight: Dragon.HexWord; -- temporary used for subtraction c32: BOOL; IF NOT phBLastFLAG AND log # IO.noWhereStream THEN { reset _ resetting AND NOT ResetAB; EULog[InstrCountAB,aAdr,aluLeft,bAdr,aluRight,store1,cAdr,result3]; resetting _ ResetAB}; phBLastFLAG _ TRUE; rejectBA _ EPRejectB; <> faultBA _ EPFaultB#None; <> aAdr _ BitOps.ECFD[KBus, 32, 0, 8]; bAdr _ BitOps.ECFD[KBus, 32, 8, 8]; cAdr _ BitOps.ECFD[KBus, 32, 16, 8]; <> < EUR3isR2AB>> Dragon.Assert[NOT EUWriteToPBusAB OR EUR3isR2AB]; IF EUWriteToPBusAB THEN { -- store in progress EPData _ Dragon.LTD[store3]; -- send data to Cache (Store) EPParityB _ CacheOps.Parity32[store3]; -- EMM, was parityStore3 result3 _ result2} <> ELSE { -- either a fetch, an op, or a move in progress IF rejectBA -- Fetch with reject => save address in result3 and don't listen to IFU THEN result3 _ result2 ELSE -- Fetch without reject -- IF EUR3isR2AB THEN result3 _ result2 -- op or move ELSE { result3 _ Dragon.LFD[EPData]; parityResult3 _ EPParityB; IF EUCheckPParityAB AND CacheOps.Parity32[result3]#parityResult3 THEN EPNPErrorB _ FALSE } }; <> store2 _ store1; <> <> carryBA _ carryAB; mqBA _ mqAB; divisorSBA _ divisorSAB; divendSBA _ divendSAB; divZeroBA _ divZeroAB; divRmsbBA _ divRmsbAB; divRCorrBA _ divRCorrAB; divQIncrBA _ divQIncrAB; mulcandSBA _ mulcandSAB; mulProdSBA _ mulProdSAB; mulSubBA _ mulSubAB; SELECT EUAluOpAB FROM SAdd => { [aluOut, c32] _ DoubleADD[aluLeft, aluRight, carryAB]; result1 _ aluOut; carryBA _ FALSE}; SSub => { [aluOut, c32] _ DoubleSUB[aluLeft, aluRight, carryAB]; result1 _ aluOut; carryBA _ FALSE}; UAdd => { [aluOut, c32] _ DoubleADD[aluLeft, aluRight, carryAB]; result1 _ aluOut; carryBA _ c32}; USub => { [aluOut, c32] _ DoubleSUB[aluLeft, aluRight, carryAB]; result1 _ aluOut; carryBA _ NOT c32}; VAdd => { [aluOut, c32] _ DoubleADD[aluLeft, aluRight, FALSE]; result1 _ aluOut}; VSub => { [aluOut, c32] _ DoubleSUB[aluLeft, aluRight, FALSE]; result1 _ aluOut}; LAdd => { [aluOut, c32] _ DoubleADD[aluLeft, aluRight, FALSE]; result1 _ aluOut; carryBA _ FALSE}; LSub => { [aluOut, c32] _ DoubleSUB[aluLeft, aluRight, FALSE]; result1 _ aluOut; carryBA _ FALSE}; FOP => { -- field descriptor provided by Field result1 _ aluOut _ FieldOp[aluLeft, aluRight, field]}; FOPK => { -- field descriptor provided by kBusAB. Otherwise identical to FOP result1 _ aluOut _ FieldOp[aluLeft, aluRight, kBusAB]}; And => { result1 _ aluOut _ WordOp[and, aluLeft, aluRight]}; Or => { result1 _ aluOut _ WordOp[or, aluLeft, aluRight]}; Xor => { result1 _ aluOut _ WordOp[xor, aluLeft, aluRight]}; BndChk => { [aluOut, c32] _ DoubleSUB[aluLeft, aluRight, FALSE]; result1 _ aluLeft}; MulLdS => { aluOut _ aluLeft; -- typically, aluOut will be tested for 0 result1 _ 0; mqBA _ aluRight; mulcandSBA _ EBFL[aluLeft, 0]; mulProdSBA _ FALSE; mulSubBA _ FALSE}; MulLdU => { aluOut _ aluLeft; -- typically, aluOut will be tested for 0 result1 _ 0; mqBA _ aluRight; mulcandSBA _ FALSE; mulProdSBA _ FALSE; mulSubBA _ FALSE}; MulStep => { tempR1, tempMQ: Dragon.HexWord; zero: BOOL _ EBFL[mqAB, 30] AND EBFL[mqAB, 31] AND mulSubAB OR ~EBFL[mqAB, 30] AND ~EBFL[mqAB, 31] AND ~mulSubAB; two: BOOL _ EBFL[mqAB, 30] AND ~EBFL[mqAB, 31] AND ~mulSubAB OR ~EBFL[mqAB, 30] AND EBFL[mqAB, 31] AND mulSubAB; one: BOOL _ ~zero AND ~two; mulSubBA _ EBFL[mqAB, 30]; <> <> <> SELECT TRUE FROM zero => { aluOut _ aluLeft; mulProdSBA _ mulProdSAB; [tempR1, tempMQ] _ DblShiftRt[mulProdSBA, aluOut, mqAB]; [result1, mqBA] _ DblShiftRt[mulProdSBA, tempR1, tempMQ]}; one => { IF mulSubBA THEN [aluOut, carryBA] _ DoubleSUB [aluLeft, aluRight, FALSE] ELSE [aluOut, carryBA] _ DoubleADD [aluLeft, aluRight, FALSE]; mulProdSBA _ mulSubBA#mulcandSAB; [tempR1, tempMQ] _ DblShiftRt[mulProdSBA, aluOut, mqAB]; [result1, mqBA] _ DblShiftRt[mulProdSBA, tempR1, tempMQ]}; two => { [tempR1, tempMQ] _ DblShiftRt[mulProdSAB, aluLeft, mqAB]; IF mulSubBA THEN [aluOut, carryBA] _ DoubleSUB [tempR1, aluRight, FALSE] ELSE [aluOut, carryBA] _ DoubleADD [tempR1, aluRight, FALSE]; mulProdSBA _ mulSubBA#mulcandSAB; [result1, mqBA] _ DblShiftRt[mulProdSBA, aluOut, tempMQ]}; ENDCASE => ERROR}; MulAdj => { IF mulSubAB THEN [aluOut, ] _ DoubleADD [aluLeft, aluRight, FALSE] ELSE aluOut _ aluLeft; result1 _ aluOut}; RdMQ => { result1 _ aluOut _ mqAB}; <> DivLdDbl => { result1 _ aluOut _ aluLeft; mqBA _ aluRight }; <> DivLdU => { aluOut _ aluLeft; carryBA _ FALSE; divendSBA _ FALSE; divisorSBA _ FALSE; divZeroBA _ aluOut=0; result1 _ aluOut }; DivLdS => { aluOut _ aluLeft; carryBA _ EBFL[mqAB, 0]; divendSBA _ EBFL[aluLeft, 0]; divisorSBA _ EBFL[aluRight, 0]; divZeroBA _ aluOut=0 AND ~EBFL[mqAB,0]; [divRmsbBA, result1, mqBA] _ DblShiftLt[aluOut, mqAB, EBFL[aluRight,0]=EBFL[aluLeft,0]] }; <> DivCkU => { -- Check for carry on first subtract [aluOut, carryBA] _ DoubleSUB[aluLeft, aluRight, FALSE]; -- Trap if carry divZeroBA _ aluOut=0 AND ~EBFL[mqAB,0]; [divRmsbBA, result1, mqBA] _ DblShiftLt[aluOut, mqAB, FALSE] }; DivCkS => { -- Check aluOut on first operation after a shift - result thrown away IF EBFL[mqAB,31] THEN [aluOut, ] _ DoubleSUB [aluLeft, aluRight, carryAB] -- note carry-in ELSE [aluOut, ] _ DoubleADD [aluLeft, aluRight, carryAB]; -- from DivLdS result1 _ aluLeft }; -- aluOut will be tested here - see DivOvFl. <> DivStep => { notLocked: BOOL _ divRmsbAB = (divisorSAB = EBFL[mqAB,31]); -- Rmsb = SignRem IF EBFL[mqAB,31] THEN [aluOut, carryBA] _ DoubleSUB [aluLeft, aluRight, FALSE] ELSE [aluOut, carryBA] _ DoubleADD [aluLeft, aluRight, FALSE]; divZeroBA _ ~EBFL[mqAB,0] AND (divZeroAB OR (notLocked AND carryBA AND aluOut=0)); -- new zero only possible if not locked [divRmsbBA, result1, mqBA] _ DblShiftLt[aluOut, mqAB, (EBFL[mqAB,31] # (carryBA = divRmsbAB) )] }; -- reverse op if Rmsb = carry DivAdjM => { notLocked: BOOL _ divRmsbAB = (divisorSAB = EBFL[mqAB,31]); -- Rmsb = SignRem newRemS: BOOL; IF EBFL[mqAB,31] THEN [aluOut, carryBA] _ DoubleSUB [aluLeft, aluRight, FALSE] ELSE [aluOut, carryBA] _ DoubleADD [aluLeft, aluRight, FALSE]; divZeroBA _ ((notLocked AND carryBA AND aluOut=0) OR divZeroAB); newRemS _ notLocked # carryBA; divRCorrBA _ ~divisorSAB AND newRemS OR divisorSAB AND ~newRemS AND ~divZeroBA OR newRemS AND divZeroBA; divQIncrBA _ divisorSAB AND divZeroBA; mqBA _ ShiftLt[mqAB, (EBFL[mqAB,31] # (carryBA = divRmsbAB) )]; result1 _ aluOut }; DivAdjR => { notLocked: BOOL _ divRmsbAB = (divisorSAB = EBFL[mqAB,31]); -- Rmsb = SignRem newRemS: BOOL; IF EBFL[mqAB,31] THEN [aluOut, carryBA] _ DoubleSUB [aluLeft, aluRight, FALSE] ELSE [aluOut, carryBA] _ DoubleADD [aluLeft, aluRight, FALSE]; divZeroBA _ ((notLocked AND carryBA AND aluOut=0) OR divZeroAB); newRemS _ notLocked # carryBA; divRCorrBA _ ~divendSAB AND newRemS OR divendSAB AND ~newRemS AND ~divZeroBA OR newRemS AND divZeroBA; divQIncrBA _ ~divendSAB AND divisorSAB OR divendSAB AND ~divisorSAB AND ~divZeroBA OR divisorSAB AND divZeroBA; mqBA _ ShiftLt[mqAB, (EBFL[mqAB,31] # (carryBA = divRmsbAB) )]; result1 _ aluOut }; DivAdj => { result1Alt: Dragon.HexWord _ IF divRCorrAB THEN aluRight ELSE 0; IF EBFL[mqAB,31] THEN [aluOut, ] _ DoubleSUB [aluLeft, result1Alt, FALSE] ELSE [aluOut, ] _ DoubleADD [aluLeft, result1Alt, FALSE]; carryBA _ divQIncrAB; mqBA _ mqAB; result1 _ aluOut}; ENDCASE => ERROR Stop["Invalid ALU Operation"]; <> SELECT EUAluOpAB FROM SSub, USub, VSub, LSub => [PlusOrMinusAluRight, ] _ DoubleSUB[0, aluRight, FALSE]; ENDCASE => PlusOrMinusAluRight _ aluRight; overflow _ (EBFL[aluLeft, 0] = EBFL[PlusOrMinusAluRight, 0]) AND (EBFL[aluLeft, 0] # EBFL[aluOut, 0]); <> conditionB _ SELECT EUCondSelAB FROM EZ => aluOut=0, -- aluOut=0 LZ => EBFL[aluOut, 0], -- aluOut<0 by checking the high-order bit LE => (aluOut=0) OR EBFL[aluOut, 0], -- aluOut<=0, OvFl => overflow, BC => NOT (NOT EBFL[aluLeft, 0] -- 0<=arg -- AND EBFL[aluOut, 0] -- arg-limit<0 --), IL => (EBFL[aluLeft, 0]#EBFL[aluLeft, 1]) OR (EBFL[aluRight, 0]#EBFL[aluRight, 1]) OR (EBFL[aluOut, 0]#EBFL[aluOut, 1]), DivOvFl => (SELECT EUAluOpAB FROM DivCkU => carryBA, DivCkS => (IF aluOut=0 THEN (divendSAB = divisorSAB) ELSE (divendSAB = (aluOut>=20000000000B))), ENDCASE => ERROR Stop["Invalid ALU Operation for DivMul condition"]), False => FALSE, NE => aluOut#0, -- aluOut#0 GE => NOT EBFL[aluOut, 0], -- aluOut>=0 by checking the high-order bit GZ => NOT ((aluOut=0) OR EBFL[aluOut, 0]), -- aluOut>0, NotOvFl => NOT overflow, NotBC => NOT EBFL[aluLeft, 0] -- 0<=arg -- AND EBFL[aluOut, 0] -- arg-limit<0 --, NotIL => NOT ((EBFL[aluLeft, 0]#EBFL[aluLeft, 1]) OR (EBFL[aluRight, 0]#EBFL[aluRight, 1]) OR (EBFL[aluOut, 0]#EBFL[aluOut, 1])), True => TRUE, ENDCASE => ERROR Stop["Invalid EUConditionBA Code"]; EUConditionBA _ conditionB }; Initializer IF initData#NIL THEN WITH initData SELECT FROM pl: Atom.PropList => BEGIN r: REF; IF (r _ pl.GetPropFromList[$LogRef]) # NIL THEN euLogRef _ NARROW[r, REF REF]; END; ENDCASE => NULL; <<>> <<>> ENDCELL; CEDAR -- Logging stuff EULog:PROC[ instr: BitOps.BitDWord, aRam: Dragon.HexByte, left: Dragon.HexWord, bRam: Dragon.HexByte, right: Dragon.HexWord, store: Dragon.HexWord, cRam: Dragon.HexByte, result: Dragon.HexWord] = { SELECT TRUE FROM reset => { log.Flush[]; log.PutF["\n\n\nEULog.txt %g", IO.time[] ]; log.PutF["\n**Reset**" ]}; rejected => { log.PutF["\n**Rejected**" ]}; ENDCASE => { log.PutF["\n%5g", IO.card[ Dragon.LFD[instr] ] ]; log.PutF[" %02x:%08x", IO.card[aRam], IO.card[ left ] ]; log.PutF[" %02x:%08x", IO.card[bRam], IO.card[ right ] ]; log.PutF[":%08x", IO.card[ store ] ]; log.PutF[" %02x:%08x", IO.card[cRam], IO.card[ result ] ]; } }; reset, resetting: BOOL _ FALSE; rejected: BOOL _ FALSE; phBLastFLAG: BOOL _ FALSE; log: IO.STREAM _ IO.noWhereStream; EUStateHandler: Cucumber.Handler = NEW[Cucumber.HandlerRep _ [ PrepareWhole: EUStatePrepareProc, PartTransfer: EUTransferProc ]]; EUStatePrepareProc: PROC [ whole: REF ANY, where: IO.STREAM, direction: Cucumber.Direction, data: REF ANY ] RETURNS [ leaveTheseToMe: Cucumber.SelectorList ] -- Cucumber.Bracket -- = {leaveTheseToMe _ LIST[$euLogRef]}; EUTransferProc: PROC [ whole: REF ANY, part: Cucumber.Path, where: IO.STREAM, direction: Cucumber.Direction, data: REF ANY ] -- Cucumber.PartTransferProc -- = {NULL}; Cucumber.Register[EUStateHandler, CODE[EUStateRec]];