<> <> <<>> <> <<>> InstructionExecute: PUBLIC PROC [processor: Processor, mi: MicroInstruction] = { p: Processor = processor; -- for a short name SELECT control FROM nextInst => {}; <> doSwitch => <> ForceBufferEmpty[]; doCall, doAbort, doReturn => { lastCallDelta: INT _ p.stats.instructions - p.lastCallRtn; ForceBufferEmpty[]; IF control = doReturn THEN { currentSize: NAT _ p.stackEntries; stackedStatus: TamarinOps.StackedStatusWord _ p.ifuStack[youngest].status; SELECT currentSize FROM = 0 => { SIGNAL OutsideEnvelope["IFU control stack empty on return!"]; thisPC _ TrapPC[StackUnderflowTrap]; GO TO badGnus; }; > IFUStackSize => { SIGNAL OutsideEnvelope["IFU control stack is too full during return!"]; GO TO badGnus; }; > IFUOverflow => IF stackedStatus.trapsEnabled THEN { SIGNAL OutsideEnvelope["IFU control stack is too full during return!"]; GO TO badGnus; }; ENDCASE; p.trapsEnabled _ stackedStatus.trapsEnabled; p.userMode _ stackedStatus.userMode; p.stackEntries _ currentSize - 1; thisPC _ p.ifuStack[youngest].pc; p.regs[ifuL] _ regL _ RegToWord[VAL[stackedStatus.lBase]]; p.youngest _ youngest _ (youngest + (MonkeyIFUStackSize - 1)) MOD MonkeyIFUStackSize; EXITS badGnus => {}; } ELSE { <> newSize: NAT _ p.stackEntries+1; stackedStatus: TamarinOps.StackedStatusWord _ [ version: CurrentProcVersion, userMode: p.userMode, trapsEnabled: p.trapsEnabled, lBase: ORD[WordToReg[regL]] ]; IF newSize > IFUStackSize THEN SIGNAL OutsideEnvelope["IFU control stack too full!"] ELSE { p.stackEntries _ newSize; p.youngest _ youngest _ (youngest + 1) MOD MonkeyIFUStackSize; }; p.ifuStack[youngest] _ [rtnPC, stackedStatus]; IF control = doAbort THEN <> p.userMode _ p.trapsEnabled _ FALSE; IF tx # NoFault THEN <> IF p.logger # NIL AND p.logger.instDone # NIL THEN p.logger.instDone[p.logger.data, p, newPC, rtnPC, doAbort, cycles]; }; SELECT lastCallDelta FROM >= 3, < 0 => {}; ENDCASE => { <> cycles _ cycles + (3-lastCallDelta); p.stats.returnInterlockCycles _ p.stats.returnInterlockCycles + lastCallDelta; }; p.lastCallRtn _ p.stats.instructions; }; ENDCASE => ERROR; p.regs[ifuPC] _ thisPC; p.stats.cycles _ p.stats.cycles+cycles; p.stats.instBytes _ p.stats.instBytes+nBytes; }; MemoryCycle: PROC [processor: Processor] ~ { <> IF instBuffer.busyUntil <= initCycles+cycles THEN { <> IF valid <= max-bytesPerWord THEN { <> fetchPC: Word _ IntToWord[WordToInt[newPC] + valid]; IF instBuffer.validWords = instBuffer.max THEN FlushInstWord[]; <> [wordAddr, rbi] _ BytePCToWordAddress[[fetchPC]]; IF rbi # 0 THEN ERROR; -- rats! we blew it! [word, tx, rCycles] _ p.ifuCache.fetch[p.ifuCache, wordAddr, initCycles+cycles, p.userMode]; p.stats.lookaheadProbes _ p.stats.lookaheadProbes + 1; IF rCycles # 0 THEN { <> instBuffer.busyUntil _ p.ifuCache.sharedBase.busyUntil; p.stats.lookaheadRejects _ p.stats.lookaheadRejects + rCycles; }; IF tx = NoFault THEN { <> instBuffer[instBuffer.validWords] _ word; instBuffer.validWords _ instBuffer.validWords + 1; }; tx _ NoFault; <> }; }; };