<> <> <> <> <> <> <> <> Directory BitOps, DragOpsCross; Imports Atom, Cucumber, Dragon, DragonFP, DragonIFU, DragonMicroPLA, IO; IDecoder: CELL [ XBus =INT[32], <<>> <> PreOpA BOOL, JumpB >BOOL, <<>> <> ASum0B >EnumType["DragonMicroPLA.ABRegSum0"], ASum1B >EnumType["DragonMicroPLA.ABRegSum1"], BSum0B >EnumType["DragonMicroPLA.ABRegSum0"], BSum1B >EnumType["DragonMicroPLA.ABRegSum1"], CSum0A >EnumType["DragonMicroPLA.CRegSum0"], CSum1A >EnumType["DragonMicroPLA.CRegSum1"], LSum0A >EnumType["DragonMicroPLA.LSource0"], LSum1A >EnumType["DragonMicroPLA.LSource1"], SSum0A >EnumType["DragonMicroPLA.SSource0"], SSum1A >EnumType["DragonMicroPLA.SSource1"], DeltaSPlus2A >INT[2], OpBA >INT[8], AlphaBA >INT[8], BetaBA >INT[8], ReadSLimitA >BOOL, SetSLimitA >BOOL, LAB > Lev0PA >INT[32], Lev0LA >INT[8], Lev0SA >INT[8], Lev0AaddrBA BOOL, Lev0AluOpBA >EnumType["Dragon.ALUOps"], Lev0CondSelBA >EnumType["Dragon.CondSelects"], Lev0CondEffectBA >EnumType["DragonMicroPLA.CondEffect"], Lev0IStackPostEffectBA >EnumType["DragonMicroPLA.IStackPostEffect"], Lev0ITrapPostEffectBA >EnumType["DragonMicroPLA.ITrapPostEffect"], Lev0EuPBusCmdBA >EnumType["Dragon.PBusCommands"], Lev2CondSelBA EnumType["DragonMicroPLA.XBSource"], <> DontBypassBA >BOOL, KillPipeAB >BOOL, PushLevel3BA >BOOL, PushPendingAB INT[32], <> ResetAB > <> RescheduleAB > iDecoderLogRef: REF REF, phALastFLAG: BOOL, iLogged: BOOL, <> <<>> <<>> <> instReadyAB :BOOL, opNameAB :DragOpsCross.Inst, opAB :Dragon.HexByte, alphaAB :Dragon.HexByte, betaAB :Dragon.HexByte, gammaAB :Dragon.HexByte, deltaAB :Dragon.HexByte, lengthAB :[0..6), xAB :Dragon.HexWord, pAB :Dragon.HexWord, iStkOverflowAB :BOOL, iStkEmptyAB :BOOL, mTrapAB :DragonMicroPLA.MicroTrap, mStateAB :DragonMicroPLA.IFUState, ifuStatusControlAB :DragonMicroPLA.IFUStatusControl, instrCountAB :Dragon.Word, <<>> <> <> mStateBA :DragonMicroPLA.IFUState, mInstrBA :DragonMicroPLA.MicroInst, <> instReadyBA :BOOL, -- for logging gammaBA :Dragon.HexByte, deltaBA :Dragon.HexByte, lengthBA :Dragon.HexByte, cBA :Dragon.HexByte, pBA :Dragon.HexWord, lBA :Dragon.HexWord, sBA :Dragon.HexWord, xBA :Dragon.HexWord, branchBA :Dragon.HexByte, trapPBA :Dragon.HexWord, delayedBA :BOOL, doneBA :BOOL, resetBA :BOOL, rescheduleBA :BOOL, iStkOverflowBA :BOOL, pushPendingBA :BOOL, popPendingBA :BOOL, iTrapEffectPendingBA :DragonMicroPLA.ITrapPostEffect, lev3RejectBA :BOOL, lev3FaultBA :Dragon.PBusFaults, ifuStatusControlBA :DragonMicroPLA.IFUStatusControl, dHoldBA :BOOL, instrCountBA :Dragon.Word EvalSimple ReadIFUStatus: PROC[state: DragonMicroPLA.IFUState] RETURNS[l: LONG CARDINAL] = { status:DragOpsCross.IFUStatus _ ALL[FALSE]; status[rescheduleClear] _ state.rescheduleWaiting; status[inhibitClear] _ state.inhibitTraps; l _ Dragon.LFD[LOOPHOLE[status]]}; ReadStatusControl:PROC[d:BitOps.BitDWord] RETURNS[sc:DragonMicroPLA.IFUStatusControl] = { status:DragOpsCross.IFUStatus _ LOOPHOLE[d]; IF status[rescheduleClear] THEN sc.reschedule _ clear; IF status[rescheduleSet] THEN sc.reschedule _ set; IF status[inhibitClear] THEN sc.inhibit _ clear; IF status[inhibitSet] THEN sc.inhibit _ set }; SExtnd: PROC[b: Dragon.HexByte] RETURNS [l: INT] = { RETURN[ IF b>=128 THEN (LONG[b]-256) ELSE LONG[b]] }; log: IO.STREAM = NARROW[iDecoderLogRef^]; IF PhA THEN { Dragon.Assert[ resetBA OR mStateBA.exceptions IN [aboutToReset..reset] OR NOT instReadyBA OR OpBA IN (0..255), "Breakpoint XOP encountered" ]; IF NOT dHoldBA THEN { IF NOT phALastFLAG THEN { <> phALastFLAG _ TRUE; iLogged _ resetBA OR mStateBA.exceptions = aboutToReset; [mTrapAB, mStateAB] _ DragonMicroPLA.GetMicroTrap[ [ state :mStateBA, ifuStatusControl :ifuStatusControlBA, iTrapEffect3 :Lev3ITrapEffectBA, delayed :delayedBA, done :doneBA, reset :resetBA, reschedule :rescheduleBA, preFetchFaulted :PreFetchFaultedBA, pushPending :pushPendingBA, popPending :popPendingBA, iTrapEffectPending :iTrapEffectPendingBA, iStkOverflow :iStkOverflowBA, eStkOverflow :EStkOverflowBA, aluCondResult2 :EUConditionBA, aluCond2 :Lev2CondSelBA, condEffect2 :Lev2CondEffectBA, pBusReject3 :lev3RejectBA, pBusFault3 :lev3FaultBA ] ]; instrCountAB _ IF resetBA OR mStateBA.exceptions = aboutToReset THEN 0 ELSE IF ( NOT mInstrBA.dontGetNextMacro ) OR mInstrBA.doMacroJump THEN instrCountBA+1 ELSE instrCountBA }; <<>> <> SELECT mInstrBA.xASource FROM none => { }; alpha => XBus _ Dragon.LTD[AlphaBA]; beta => XBus _ Dragon.LTD[BetaBA]; betaAlpha => XBus _ Dragon.LTD[BetaBA*256 + AlphaBA]; deltaGammaBetaAlpha => XBus _ Dragon.LTD[((deltaBA*LONG[256]+gammaBA)*256+BetaBA)*256+AlphaBA]; bAddrIFUReg => { IF Lev0BaddrBA=DragonIFU.PRtoByte[ifuStatus] THEN XBus _ Dragon.LTD[ReadIFUStatus[mStateBA]]}; fpLdMode => XBus _ DragonFP.InsertLoadFunction[mode, AlphaBA, XBus]; fpLdAMsw => XBus _ DragonFP.InsertLoadFunction[aHi, AlphaBA, XBus]; fpLdALsw => XBus _ DragonFP.InsertLoadFunction[aLo, AlphaBA, XBus]; fpLdBMsw => XBus _ DragonFP.InsertLoadFunction[bHi, AlphaBA, XBus]; fpLdBLsw => XBus _ DragonFP.InsertLoadFunction[bLo, AlphaBA, XBus]; fpUnldMsw => XBus _ DragonFP.InsertUnload[msw, XBus]; fpUnldLsw => XBus _ DragonFP.InsertUnload[lsw, XBus]; ENDCASE => ERROR; <<>> ReadSLimitA _ mInstrBA.xASource=bAddrIFUReg AND Lev0BaddrBA=DragonIFU.PRtoByte[ifuSLimit]; <<>> <> xAB _ Dragon.LFD[XBus]; <> pAB _ xBA; LSum0A _ mInstrBA.lSource.s0; LSum1A _ mInstrBA.lSource.s1; DeltaSPlus2A _ 2 + (IF (mInstrBA.deltaSc = push) THEN 1 ELSE 0) - (IF (mInstrBA.deltaSa = pop) THEN 1 ELSE 0) - (IF (mInstrBA.deltaSb = pop) THEN 1 ELSE 0); SSum0A _ mInstrBA.sSource.s0; SSum1A _ mInstrBA.sSource.s1; <<>> <> instReadyAB _ InstReadyA; opAB _ PreOpA; TRUSTED {opNameAB _ LOOPHOLE[PreOpA]}; alphaAB _ PreAlphaA; betaAB _ PreBetaA; gammaAB _ PreGammaA; deltaAB _ PreDeltaA; lengthAB _ PreLengthA; <<>> <> iStkEmptyAB _ IStkEmptyA; iStkOverflowAB _ IStkTooFullA; <> SetSLimitA _ Lev3CaddrBA=DragonIFU.PRtoByte[ifuSLimit]; ifuStatusControlAB _ IF Lev3CaddrBA=DragonIFU.PRtoByte[ifuStatus] THEN ReadStatusControl[XBus] ELSE [nop, nop]; <> SELECT mInstrBA.pipedPLSASpec FROM pls => { Lev0PA _ Dragon.LTD[pBA]; Lev0LA _ lBA; Lev0SA _ sBA }; pLenLSnext => { Lev0PA _ Dragon.LTD[pBA + lengthBA]; Lev0LA _ LAB; Lev0SA _ SAB }; pAlphasLSnext => { Lev0PA _ Dragon.LTD[(pBA + SExtnd[AlphaBA])]; Lev0LA _ LAB; Lev0SA _ SAB }; ENDCASE => ERROR; <<>> <> CSum0A _ mInstrBA.cReg.s0; CSum1A _ mInstrBA.cReg.s1; KillPipeAB _ mTrapAB.killPipe; <<>> <> InstrCountAB _ Dragon.LTD[instrCountBA]; }; }; IF NOT PhA AND NOT iLogged AND log # IO.noWhereStream THEN { <> <> iLogged _ TRUE; IF mStateBA.exceptions=reset THEN { log.Flush[]; log.PutF["\n\n\nIDecoder Log %g", IO.time[] ]}; log.PutF["\n%5g", IO.card[instrCountBA] ]; SELECT TRUE FROM mStateBA.exceptions=reset => log.PutF["**Reset "]; mStateBA.exceptions=epFault => log.PutF["**EPFault "]; mStateBA.exceptions=euCC => log.PutF["**EUCC "]; mStateBA.exceptions=epReject => log.PutF["**EPReject "]; mStateBA.exceptions=cJump => log.PutF["**CJRestrt "]; mStateBA.exceptions=rschlWait => log.PutF["**Reschdl "]; mStateBA.exceptions=iStkOFlow => log.PutF["**IStkOver "]; mStateBA.exceptions=eStkOFlow => log.PutF["**EStkOver "]; mStateBA.exceptions=iFtchFault => log.PutF["**IPgFault "]; mInstrBA.doMacroJump AND xBA=4010040B => log.PutF["**IStkUndr "]; ENDCASE => log.PutF[" "]; IF mInstrBA.delayed THEN log.PutF["dly "] ELSE log.PutF[" "]; log.PutF["pc:%08x", IO.card[pBA] ]; IF NOT instReadyBA THEN log.PutF["---"] ELSE { log.PutF[" %-7g", IO.rope[opName[OpBA]]]; IF lengthBA > 3 THEN log.PutF[" %02x%02x", IO.card[deltaBA], IO.card[gammaBA]] ELSE log.PutF[" "]; IF lengthBA > 2 THEN log.PutF["%02x", IO.card[BetaBA]] ELSE log.PutF[" "]; IF lengthBA > 1 THEN log.PutF["%02x", IO.card[AlphaBA]] ELSE log.PutF[" "]; log.PutF[" l:%02x", IO.card[lBA]]; -- at beginning of instruction log.PutF[ " s:%02x", IO.card[sBA]]; -- at beginning of instruction IF NOT mInstrBA.delayed THEN { log.PutF[" a:%02x", IO.card[Lev0AaddrBA]]; log.PutF[ " b:%02x", IO.card[Lev0BaddrBA]]; log.PutF[ " c:%02x", IO.card[Lev0CaddrA]] } } }; IF PhB THEN dHoldBA _ DHoldAB; IF PhB AND NOT DHoldAB THEN { IF phALastFLAG THEN { phALastFLAG _ FALSE; [mInstrBA] _ DragonMicroPLA.GetMicroInst[ [ state :mStateAB, op :opNameAB, alpha :alphaAB, beta :betaAB, delayACycle :DelayACycleAB, iStkEmpty :iStkEmptyAB, pushPending :PushPendingAB, popPending :PopPendingAB, instReady :instReadyAB ] ] }; <> OpBA _ opAB; AlphaBA _ alphaAB; BetaBA _ betaAB; gammaBA _ gammaAB; deltaBA _ deltaAB; lengthBA _ lengthAB; instReadyBA _ instReadyAB; pBA _ pAB; lBA _ LAB; sBA _ SAB; mStateBA _ mStateAB; doneBA _ mInstrBA.doMacroJump OR ( NOT mInstrBA.dontGetNextMacro ) OR mStateAB.cycle = 0 AND NOT instReadyAB; delayedBA _ mInstrBA.delayed; resetBA _ ResetAB; rescheduleBA _ RescheduleAB; iStkOverflowBA _ iStkOverflowAB; pushPendingBA _ PushPendingAB OR mInstrBA.iStackPostEffect=push; popPendingBA _ PopPendingAB OR mInstrBA.iStackPostEffect=pop; iTrapEffectPendingBA _ IF mInstrBA.iTrapPostEffect#none THEN mInstrBA.iTrapPostEffect ELSE ITrapEffectPendingAB; lev3RejectBA _ EPRejectB; lev3FaultBA _ EPFaultB; ifuStatusControlBA _ ifuStatusControlAB; instrCountBA _ instrCountAB; <> SELECT mInstrBA.xBSource FROM pcPlusAlphaS => XBus _ Dragon.LTD[pBA+SExtnd[alphaAB]]; pcPlusBetaAlphaS => XBus _ Dragon.LTD[pBA+SExtnd[betaAB]*256 + alphaAB]; deltaGammaBetaAlpha => XBus _ Dragon.LTD[((deltaAB*LONG[256]+gammaAB)*256+betaAB)*256+alphaAB]; pc => XBus _ Dragon.LTD[pBA]; pcPlusLen => XBus _ Dragon.LTD[pBA + lengthAB]; xA => XBus _ Dragon.LTD[xAB]; pcPlusXA => XBus _ Dragon.LTD[pBA + xAB]; xopGenerator => XBus _ Dragon.LTD[16*(opAB+DragOpsCross.XopBase)]; trapPCGenerator => XBus _ Dragon.LTD[mTrapAB.trapPC]; iStackPC => {-- Driven in IStack --}; pipe3PC => {-- Driven in IPipe --}; ENDCASE => ERROR; <> xBA _ Dragon.LFD[XBus]; <> ASum0B _ mInstrBA.aReg.s0; ASum1B _ mInstrBA.aReg.s1; BSum0B _ mInstrBA.bReg.s0; BSum1B _ mInstrBA.bReg.s1; <> GetNextInstB _ NOT ResetAB AND NOT mInstrBA.dontGetNextMacro; JumpB _ ResetAB OR mInstrBA.doMacroJump; <> Lev0AluRtIsKBA _ mInstrBA.aluRtIsK; Lev0AluOpBA _ IF mInstrBA.aluOp = op47 THEN LOOPHOLE[opAB MOD 16] ELSE mInstrBA.aluOp; Lev0CondSelBA _ IF mInstrBA.condSel = op57 THEN LOOPHOLE[opAB MOD 8] ELSE mInstrBA.condSel; Lev0CondEffectBA _ mInstrBA.condEffect; DontBypassBA _ mInstrBA.dontBypass; PushLevel3BA _ mInstrBA.pushLevel3; Lev0IStackPostEffectBA _ mInstrBA.iStackPostEffect; Lev0ITrapPostEffectBA _ mInstrBA.iTrapPostEffect; Lev0EuPBusCmdBA _ mInstrBA.euPBusCmd; XBSourceBA _ mInstrBA.xBSource; }; Initializer IF initData#NIL THEN WITH initData SELECT FROM pl: Atom.PropList => BEGIN r: REF; IF (r _ pl.GetPropFromList[$LogRef]) # NIL THEN iDecoderLogRef _ NARROW[r, REF REF]; END; ENDCASE => NULL; ENDCELL; CEDAR opName:DragonIFU.DragOpTable _ DragonIFU.GenDragOpTable[]; IDecoderStateHandler: Cucumber.Handler = NEW[Cucumber.HandlerRep _ [ PrepareWhole: IDecoderStatePrepareProc, PartTransfer: IDecoderTransferProc ]]; IDecoderStatePrepareProc: PROC [ whole: REF ANY, where: IO.STREAM, direction: Cucumber.Direction, data: REF ANY ] RETURNS [ leaveTheseToMe: Cucumber.SelectorList ] -- Cucumber.Bracket -- = {leaveTheseToMe _ LIST[$iDecoderLogRef]}; IDecoderTransferProc: PROC [ whole: REF ANY, part: Cucumber.Path, where: IO.STREAM, direction: Cucumber.Direction, data: REF ANY ] -- Cucumber.PartTransferProc -- = {NULL}; Cucumber.Register[IDecoderStateHandler, CODE[IDecoderStateRec]];