diff options
171 files changed, 2503 insertions, 2293 deletions
diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index 0db75df46..f97244260 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -60,8 +60,7 @@ initCPU(ThreadContext *tc, int cpuId) AlphaFault *reset = new ResetFault; - tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect()); - tc->setNextPC(tc->readPC() + sizeof(MachInst)); + tc->pcState(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect()); delete reset; } @@ -494,12 +493,14 @@ using namespace AlphaISA; Fault SimpleThread::hwrei() { - if (!(readPC() & 0x3)) + PCState pc = pcState(); + if (!(pc.pc() & 0x3)) return new UnimplementedOpcodeFault; - setNextPC(readMiscRegNoEffect(IPR_EXC_ADDR)); + pc.npc(readMiscRegNoEffect(IPR_EXC_ADDR)); + pcState(pc); - CPA::cpa()->swAutoBegin(tc, readNextPC()); + CPA::cpa()->swAutoBegin(tc, pc.npc()); if (!misspeculating()) { if (kernelStats) diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc index 9d4eeda8a..38386cce1 100644 --- a/src/arch/alpha/faults.cc +++ b/src/arch/alpha/faults.cc @@ -115,9 +115,11 @@ AlphaFault::invoke(ThreadContext *tc, StaticInstPtr inst) FaultBase::invoke(tc); countStat()++; + PCState pc = tc->pcState(); + // exception restart address - if (setRestartAddress() || !(tc->readPC() & 0x3)) - tc->setMiscRegNoEffect(IPR_EXC_ADDR, tc->readPC()); + if (setRestartAddress() || !(pc.pc() & 0x3)) + tc->setMiscRegNoEffect(IPR_EXC_ADDR, pc.pc()); if (skipFaultingInstruction()) { // traps... skip faulting instruction. @@ -125,8 +127,8 @@ AlphaFault::invoke(ThreadContext *tc, StaticInstPtr inst) tc->readMiscRegNoEffect(IPR_EXC_ADDR) + 4); } - tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + vect()); - tc->setNextPC(tc->readPC() + sizeof(MachInst)); + pc.set(tc->readMiscRegNoEffect(IPR_PAL_BASE) + vect()); + tc->pcState(pc); } void diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh index 3200201db..cbaa8e9bf 100644 --- a/src/arch/alpha/interrupts.hh +++ b/src/arch/alpha/interrupts.hh @@ -133,7 +133,7 @@ class Interrupts : public SimObject bool checkInterrupts(ThreadContext *tc) const { - return (intstatus != 0) && !(tc->readPC() & 0x3); + return (intstatus != 0) && !(tc->pcState().pc() & 0x3); } Fault diff --git a/src/arch/alpha/isa/branch.isa b/src/arch/alpha/isa/branch.isa index 974193efd..feb15b158 100644 --- a/src/arch/alpha/isa/branch.isa +++ b/src/arch/alpha/isa/branch.isa @@ -81,7 +81,7 @@ output header {{ { } - Addr branchTarget(Addr branchPC) const; + AlphaISA::PCState branchTarget(const AlphaISA::PCState &branchPC) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; @@ -106,7 +106,7 @@ output header {{ { } - Addr branchTarget(ThreadContext *tc) const; + AlphaISA::PCState branchTarget(ThreadContext *tc) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; @@ -114,18 +114,19 @@ output header {{ }}; output decoder {{ - Addr - Branch::branchTarget(Addr branchPC) const + AlphaISA::PCState + Branch::branchTarget(const AlphaISA::PCState &branchPC) const { - return branchPC + 4 + disp; + return branchPC.pc() + 4 + disp; } - Addr + AlphaISA::PCState Jump::branchTarget(ThreadContext *tc) const { - Addr NPC = tc->readPC() + 4; + PCState pc = tc->pcState(); uint64_t Rb = tc->readIntReg(_srcRegIdx[0]); - return (Rb & ~3) | (NPC & 1); + pc.set((Rb & ~3) | (pc.pc() & 1)); + return pc; } const std::string & @@ -217,7 +218,14 @@ def template JumpOrBranchDecode {{ }}; def format CondBranch(code) {{ - code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n'; + code = ''' + bool cond; + %(code)s; + PCState pc = PCS; + if (cond) + pc.npc(pc.npc() + disp); + PCS = pc; + ''' % { "code" : code } iop = InstObjParams(name, Name, 'Branch', code, ('IsDirectControl', 'IsCondControl')) header_output = BasicDeclare.subst(iop) @@ -229,16 +237,18 @@ def format CondBranch(code) {{ let {{ def UncondCtrlBase(name, Name, base_class, npc_expr, flags): # Declare basic control transfer w/o link (i.e. link reg is R31) - nolink_code = 'NPC = %s;\n' % npc_expr - nolink_iop = InstObjParams(name, Name, base_class, nolink_code, flags) + readpc_code = 'PCState pc = PCS;' + nolink_code = 'pc.npc(%s);\nPCS = pc' % npc_expr + nolink_iop = InstObjParams(name, Name, base_class, + readpc_code + nolink_code, flags) header_output = BasicDeclare.subst(nolink_iop) decoder_output = BasicConstructor.subst(nolink_iop) exec_output = BasicExecute.subst(nolink_iop) # Generate declaration of '*AndLink' version, append to decls - link_code = 'Ra = NPC & ~3;\n' + nolink_code + link_code = 'Ra = pc.npc() & ~3;\n' + nolink_code link_iop = InstObjParams(name, Name + 'AndLink', base_class, - link_code, flags) + readpc_code + link_code, flags) header_output += BasicDeclare.subst(link_iop) decoder_output += BasicConstructor.subst(link_iop) exec_output += BasicExecute.subst(link_iop) @@ -253,13 +263,13 @@ def UncondCtrlBase(name, Name, base_class, npc_expr, flags): def format UncondBranch(*flags) {{ flags += ('IsUncondControl', 'IsDirectControl') (header_output, decoder_output, decode_block, exec_output) = \ - UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags) + UncondCtrlBase(name, Name, 'Branch', 'pc.npc() + disp', flags) }}; def format Jump(*flags) {{ flags += ('IsUncondControl', 'IsIndirectControl') (header_output, decoder_output, decode_block, exec_output) = \ - UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags) + UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (pc.npc() & 1)', flags) }}; diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index fe70e4d16..e2947cf4a 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -856,15 +856,16 @@ decode OPCODE default Unknown::unknown() { // invalid pal function code, or attempt to do privileged // PAL call in non-kernel mode fault = new UnimplementedOpcodeFault; - } - else { + } else { // check to see if simulator wants to do something special // on this PAL call (including maybe suppress it) bool dopal = xc->simPalCheck(palFunc); if (dopal) { - xc->setMiscReg(IPR_EXC_ADDR, NPC); - NPC = xc->readMiscReg(IPR_PAL_BASE) + palOffset; + PCState pc = PCS; + xc->setMiscReg(IPR_EXC_ADDR, pc.npc()); + pc.npc(xc->readMiscReg(IPR_PAL_BASE) + palOffset); + PCS = pc; } } }}, IsNonSpeculative); @@ -1030,13 +1031,14 @@ decode OPCODE default Unknown::unknown() { }}, IsNonSpeculative); #endif 0x54: m5panic({{ - panic("M5 panic instruction called at pc=%#x.", xc->readPC()); + panic("M5 panic instruction called at pc=%#x.", + xc->pcState().pc()); }}, IsNonSpeculative); #define CPANN(lbl) CPA::cpa()->lbl(xc->tcBase()) 0x55: decode RA { 0x00: m5a_old({{ panic("Deprecated M5 annotate instruction executed at pc=%#x\n", - xc->readPC()); + xc->pcState().pc()); }}, IsNonSpeculative); 0x01: m5a_bsm({{ CPANN(swSmBegin); diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa index 2a0699354..ffc267cd2 100644 --- a/src/arch/alpha/isa/main.isa +++ b/src/arch/alpha/isa/main.isa @@ -46,6 +46,7 @@ output header {{ #include <iomanip> #include "arch/alpha/faults.hh" +#include "arch/alpha/types.hh" #include "config/ss_compatible_fp.hh" #include "cpu/static_inst.hh" #include "mem/request.hh" // some constructors use MemReq flags @@ -185,7 +186,7 @@ def operands {{ 'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2), 'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3), 'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), - 'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4), + 'PCS': ('PCState', 'uq', None, ( None, None, 'IsControl' ), 4), 'Runiq': ('ControlReg', 'uq', 'MISCREG_UNIQ', None, 1), 'FPCR': ('ControlReg', 'uq', 'MISCREG_FPCR', None, 1), 'IntrFlag': ('ControlReg', 'uq', 'MISCREG_INTR', None, 1), @@ -233,6 +234,12 @@ output header {{ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + void + advancePC(AlphaISA::PCState &pcState) const + { + pcState.advance(); + } }; }}; diff --git a/src/arch/alpha/predecoder.hh b/src/arch/alpha/predecoder.hh index 913bd8764..f9a716b7f 100644 --- a/src/arch/alpha/predecoder.hh +++ b/src/arch/alpha/predecoder.hh @@ -76,11 +76,11 @@ class Predecoder // Use this to give data to the predecoder. This should be used // when there is control flow. void - moreBytes(Addr pc, Addr fetchPC, MachInst inst) + moreBytes(const PCState &pc, Addr fetchPC, MachInst inst) { ext_inst = inst; #if FULL_SYSTEM - ext_inst |= (static_cast<ExtMachInst>(pc & 0x1) << 32); + ext_inst |= (static_cast<ExtMachInst>(pc.pc() & 0x1) << 32); #endif } @@ -98,7 +98,7 @@ class Predecoder // This returns a constant reference to the ExtMachInst to avoid a copy const ExtMachInst & - getExtMachInst() + getExtMachInst(PCState &pc) { return ext_inst; } diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index f68a53a6f..3c3fd9b25 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -162,15 +162,7 @@ AlphaLiveProcess::argsInit(int intSize, int pageSize) setSyscallArg(tc, 1, argv_array_base); tc->setIntReg(StackPointerReg, stack_min); - Addr prog_entry = objFile->entryPoint(); - tc->setPC(prog_entry); - tc->setNextPC(prog_entry + sizeof(MachInst)); - - // MIPS/Sparc need NNPC for delay slot handling, while - // Alpha has no delay slots... However, CPU models - // cycle PCs by PC=NPC, NPC=NNPC, etc. so setting this - // here ensures CPU-Model Compatibility across board - tc->setNextNPC(prog_entry + (2 * sizeof(MachInst))); + tc->pcState(objFile->entryPoint()); } void diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc index 5391d2056..9a2a5f23f 100644 --- a/src/arch/alpha/remote_gdb.cc +++ b/src/arch/alpha/remote_gdb.cc @@ -211,7 +211,7 @@ RemoteGDB::getregs() { memset(gdbregs.regs, 0, gdbregs.bytes()); - gdbregs.regs[KGDB_REG_PC] = context->readPC(); + gdbregs.regs[KGDB_REG_PC] = context->pcState().pc(); // @todo: Currently this is very Alpha specific. if (PcPAL(gdbregs.regs[KGDB_REG_PC])) { @@ -254,7 +254,7 @@ RemoteGDB::setregs() context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]); } #endif - context->setPC(gdbregs.regs[KGDB_REG_PC]); + context->pcState(gdbregs.regs[KGDB_REG_PC]); } void @@ -273,30 +273,28 @@ RemoteGDB::clearSingleStep() void RemoteGDB::setSingleStep() { - Addr pc = context->readPC(); - Addr npc, bpc; + PCState pc = context->pcState(); + PCState bpc; bool set_bt = false; - npc = pc + sizeof(MachInst); - // User was stopped at pc, e.g. the instruction at pc was not // executed. - MachInst inst = read<MachInst>(pc); - StaticInstPtr si(inst, pc); + MachInst inst = read<MachInst>(pc.pc()); + StaticInstPtr si(inst, pc.pc()); if (si->hasBranchTarget(pc, context, bpc)) { // Don't bother setting a breakpoint on the taken branch if it // is the same as the next pc - if (bpc != npc) + if (bpc.pc() != pc.npc()) set_bt = true; } DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n", takenBkpt, notTakenBkpt); - setTempBreakpoint(notTakenBkpt = npc); + setTempBreakpoint(notTakenBkpt = pc.npc()); if (set_bt) - setTempBreakpoint(takenBkpt = bpc); + setTempBreakpoint(takenBkpt = bpc.pc()); } // Write bytes to kernel address space for debugger. diff --git a/src/arch/alpha/stacktrace.cc b/src/arch/alpha/stacktrace.cc index 1b5a9be34..9c6b3cff0 100644 --- a/src/arch/alpha/stacktrace.cc +++ b/src/arch/alpha/stacktrace.cc @@ -145,7 +145,7 @@ StackTrace::trace(ThreadContext *_tc, bool is_call) bool usermode = (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0; - Addr pc = tc->readNextPC(); + Addr pc = tc->pcState().pc(); bool kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd; if (usermode) { @@ -168,7 +168,7 @@ StackTrace::trace(ThreadContext *_tc, bool is_call) panic("could not find address %#x", pc); stack.push_back(addr); - pc = tc->readPC(); + pc = tc->pcState().pc(); } while (ksp > bottom) { diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index b578741d9..614061ddd 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -443,8 +443,6 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc) Fault TLB::translateData(RequestPtr req, ThreadContext *tc, bool write) { - Addr pc = tc->readPC(); - mode_type mode = (mode_type)DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)); @@ -458,7 +456,7 @@ TLB::translateData(RequestPtr req, ThreadContext *tc, bool write) return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags); } - if (PcPAL(pc)) { + if (PcPAL(tc->pcState().pc())) { mode = (req->getFlags() & Request::ALTMODE) ? (mode_type)ALT_MODE_AM( tc->readMiscRegNoEffect(IPR_ALT_MODE)) diff --git a/src/arch/alpha/types.hh b/src/arch/alpha/types.hh index 0d285c3b2..06c0168cf 100644 --- a/src/arch/alpha/types.hh +++ b/src/arch/alpha/types.hh @@ -33,12 +33,15 @@ #define __ARCH_ALPHA_TYPES_HH__ #include "base/types.hh" +#include "arch/generic/types.hh" namespace AlphaISA { typedef uint32_t MachInst; typedef uint64_t ExtMachInst; +typedef GenericISA::SimplePCState<MachInst> PCState; + typedef uint64_t LargestRead; enum annotes diff --git a/src/arch/alpha/utility.cc b/src/arch/alpha/utility.cc index 11560259f..2d56ca9b8 100644 --- a/src/arch/alpha/utility.cc +++ b/src/arch/alpha/utility.cc @@ -77,8 +77,7 @@ copyRegs(ThreadContext *src, ThreadContext *dest) copyMiscRegs(src, dest); // Lastly copy PC/NPC - dest->setPC(src->readPC()); - dest->setNextPC(src->readNextPC()); + dest->pcState(src->pcState()); } void @@ -99,9 +98,9 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest) void skipFunction(ThreadContext *tc) { - Addr newpc = tc->readIntReg(ReturnAddressReg); - tc->setPC(newpc); - tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst)); + TheISA::PCState newPC = tc->pcState(); + newPC.set(tc->readIntReg(ReturnAddressReg)); + tc->pcState(newPC); } diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index 6d5b8baf6..fdac8b8d1 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -37,10 +37,19 @@ #include "arch/alpha/registers.hh" #include "base/misc.hh" #include "config/full_system.hh" +#include "cpu/static_inst.hh" #include "cpu/thread_context.hh" namespace AlphaISA { +inline PCState +buildRetPC(const PCState &curPC, const PCState &callPC) +{ + PCState retPC = callPC; + retPC.advance(); + return retPC; +} + uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp); inline bool @@ -95,6 +104,13 @@ void copyRegs(ThreadContext *src, ThreadContext *dest); void copyMiscRegs(ThreadContext *src, ThreadContext *dest); void skipFunction(ThreadContext *tc); + +inline void +advancePC(PCState &pc, const StaticInstPtr inst) +{ + pc.advance(); +} + } // namespace AlphaISA #endif // __ARCH_ALPHA_UTILITY_HH__ diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc index 6e138119c..54cf5cfe5 100644 --- a/src/arch/arm/faults.cc +++ b/src/arch/arm/faults.cc @@ -104,6 +104,7 @@ ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst) CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR) | tc->readIntReg(INTREG_CONDCODES); + Addr curPc M5_VAR_USED = tc->pcState().pc(); cpsr.mode = nextMode(); @@ -116,7 +117,7 @@ ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst) cpsr.i = 1; cpsr.e = sctlr.ee; tc->setMiscReg(MISCREG_CPSR, cpsr); - tc->setIntReg(INTREG_LR, tc->readPC() + + tc->setIntReg(INTREG_LR, curPc + (saved_cpsr.t ? thumbPcOffset() : armPcOffset())); switch (nextMode()) { @@ -139,14 +140,15 @@ ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst) panic("unknown Mode\n"); } - Addr pc M5_VAR_USED = tc->readPC(); - Addr newPc = getVector(tc) | (sctlr.te ? PcTBit : 0); + Addr newPc = getVector(tc); DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n", - name(), cpsr, pc, tc->readIntReg(INTREG_LR), newPc); - tc->setPC(newPc); - tc->setNextPC(newPc + cpsr.t ? 2 : 4 ); - tc->setMicroPC(0); - tc->setNextMicroPC(1); + name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc); + PCState pc(newPc); + pc.thumb(cpsr.t); + pc.nextThumb(pc.thumb()); + pc.jazelle(cpsr.j); + pc.nextJazelle(pc.jazelle()); + tc->pcState(pc); } void @@ -193,10 +195,10 @@ SupervisorCall::invoke(ThreadContext *tc, StaticInstPtr inst) tc->syscall(callNum); // Advance the PC since that won't happen automatically. - tc->setPC(tc->readNextPC()); - tc->setNextPC(tc->readNextNPC()); - tc->setMicroPC(0); - tc->setNextMicroPC(1); + PCState pc = tc->pcState(); + assert(inst); + inst->advancePC(pc); + tc->pcState(pc); } #endif // FULL_SYSTEM @@ -223,10 +225,10 @@ FlushPipe::invoke(ThreadContext *tc, StaticInstPtr inst) { // Set the PC to the next instruction of the faulting instruction. // Net effect is simply squashing all instructions behind and // start refetching from the next instruction. - tc->setPC(tc->readNextPC()); - tc->setNextPC(tc->readNextNPC()); - tc->setMicroPC(0); - tc->setNextMicroPC(1); + PCState pc = tc->pcState(); + assert(inst); + inst->advancePC(pc); + tc->pcState(pc); } template void AbortFault<PrefetchAbort>::invoke(ThreadContext *tc, diff --git a/src/arch/arm/insts/macromem.hh b/src/arch/arm/insts/macromem.hh index c1c8383da..018cb1de5 100644 --- a/src/arch/arm/insts/macromem.hh +++ b/src/arch/arm/insts/macromem.hh @@ -77,6 +77,18 @@ class MicroOp : public PredOp { flags[IsDelayedCommit] = true; } + + void + advancePC(PCState &pcState) const + { + if (flags[IsLastMicroop]) { + pcState.uEnd(); + } else if (flags[IsMicroop]) { + pcState.uAdvance(); + } else { + pcState.advance(); + } + } }; /** diff --git a/src/arch/arm/insts/mem.hh b/src/arch/arm/insts/mem.hh index 1baba5112..2aa4de1d7 100644 --- a/src/arch/arm/insts/mem.hh +++ b/src/arch/arm/insts/mem.hh @@ -63,8 +63,28 @@ class Swap : public PredOp std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; +class MightBeMicro : public PredOp +{ + protected: + MightBeMicro(const char *mnem, ExtMachInst _machInst, OpClass __opClass) + : PredOp(mnem, _machInst, __opClass) + {} + + void + advancePC(PCState &pcState) const + { + if (flags[IsLastMicroop]) { + pcState.uEnd(); + } else if (flags[IsMicroop]) { + pcState.uAdvance(); + } else { + pcState.advance(); + } + } +}; + // The address is a base register plus an immediate. -class RfeOp : public PredOp +class RfeOp : public MightBeMicro { public: enum AddrMode { @@ -83,7 +103,7 @@ class RfeOp : public PredOp RfeOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _base, AddrMode _mode, bool _wb) - : PredOp(mnem, _machInst, __opClass), + : MightBeMicro(mnem, _machInst, __opClass), base(_base), mode(_mode), wb(_wb), uops(NULL) {} @@ -94,7 +114,7 @@ class RfeOp : public PredOp } StaticInstPtr - fetchMicroop(MicroPC microPC) + fetchMicroop(MicroPC microPC) const { assert(uops != NULL && microPC < numMicroops); return uops[microPC]; @@ -104,7 +124,7 @@ class RfeOp : public PredOp }; // The address is a base register plus an immediate. -class SrsOp : public PredOp +class SrsOp : public MightBeMicro { public: enum AddrMode { @@ -123,7 +143,7 @@ class SrsOp : public PredOp SrsOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, uint32_t _regMode, AddrMode _mode, bool _wb) - : PredOp(mnem, _machInst, __opClass), + : MightBeMicro(mnem, _machInst, __opClass), regMode(_regMode), mode(_mode), wb(_wb), uops(NULL) {} @@ -134,7 +154,7 @@ class SrsOp : public PredOp } StaticInstPtr - fetchMicroop(MicroPC microPC) + fetchMicroop(MicroPC microPC) const { assert(uops != NULL && microPC < numMicroops); return uops[microPC]; @@ -143,7 +163,7 @@ class SrsOp : public PredOp std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; -class Memory : public PredOp +class Memory : public MightBeMicro { public: enum AddrMode { @@ -163,7 +183,7 @@ class Memory : public PredOp Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _base, bool _add) - : PredOp(mnem, _machInst, __opClass), + : MightBeMicro(mnem, _machInst, __opClass), dest(_dest), base(_base), add(_add), uops(NULL) {} @@ -174,7 +194,7 @@ class Memory : public PredOp } StaticInstPtr - fetchMicroop(MicroPC microPC) + fetchMicroop(MicroPC microPC) const { assert(uops != NULL && microPC < numMicroops); return uops[microPC]; diff --git a/src/arch/arm/insts/pred_inst.hh b/src/arch/arm/insts/pred_inst.hh index b7d4c4709..f779b46f5 100644 --- a/src/arch/arm/insts/pred_inst.hh +++ b/src/arch/arm/insts/pred_inst.hh @@ -312,7 +312,7 @@ class PredMacroOp : public PredOp } StaticInstPtr - fetchMicroop(MicroPC microPC) + fetchMicroop(MicroPC microPC) const { assert(microPC < numMicroops); return microOps[microPC]; @@ -332,6 +332,15 @@ class PredMicroop : public PredOp { flags[IsMicroop] = true; } + + void + advancePC(PCState &pcState) const + { + if (flags[IsLastMicroop]) + pcState.uEnd(); + else + pcState.uAdvance(); + } }; } diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh index ad89a1a79..fa850190f 100644 --- a/src/arch/arm/insts/static_inst.hh +++ b/src/arch/arm/insts/static_inst.hh @@ -155,6 +155,12 @@ class ArmStaticInst : public StaticInst IntRegIndex rs, uint32_t shiftAmt, ArmShiftType type, uint32_t imm) const; + void + advancePC(PCState &pcState) const + { + pcState.advance(); + } + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; static inline uint32_t @@ -219,26 +225,16 @@ class ArmStaticInst : public StaticInst static inline Addr readPC(XC *xc) { - Addr pc = xc->readPC(); - if (isThumb(pc)) - return pc + 4; - else - return pc + 8; + return xc->pcState().instPC(); } - // Perform an regular branch. template<class XC> static inline void setNextPC(XC *xc, Addr val) { - Addr npc = xc->readNextPC(); - if (isThumb(npc)) { - val &= ~mask(1); - } else { - val &= ~mask(2); - } - xc->setNextPC((npc & PcModeMask) | - (val & ~PcModeMask)); + PCState pc = xc->pcState(); + pc.instNPC(val); + xc->pcState(pc); } template<class T> @@ -279,30 +275,9 @@ class ArmStaticInst : public StaticInst static inline void setIWNextPC(XC *xc, Addr val) { - Addr stateBits = xc->readPC() & PcModeMask; - Addr jBit = PcJBit; - Addr tBit = PcTBit; - bool thumbEE = (stateBits == (tBit | jBit)); - - Addr newPc = (val & ~PcModeMask); - if (thumbEE) { - if (bits(newPc, 0)) { - newPc = newPc & ~mask(1); - } else { - panic("Bad thumbEE interworking branch address %#x.\n", newPc); - } - } else { - if (bits(newPc, 0)) { - stateBits = tBit; - newPc = newPc & ~mask(1); - } else if (!bits(newPc, 1)) { - stateBits = 0; - } else { - warn("Bad interworking branch address %#x.\n", newPc); - } - } - newPc = newPc | stateBits; - xc->setNextPC(newPc); + PCState pc = xc->pcState(); + pc.instIWNPC(val); + xc->pcState(pc); } // Perform an interworking branch in ARM mode, a regular branch @@ -311,14 +286,9 @@ class ArmStaticInst : public StaticInst static inline void setAIWNextPC(XC *xc, Addr val) { - Addr stateBits = xc->readPC() & PcModeMask; - Addr jBit = PcJBit; - Addr tBit = PcTBit; - if (!jBit && !tBit) { - setIWNextPC(xc, val); - } else { - setNextPC(xc, val); - } + PCState pc = xc->pcState(); + pc.instAIWNPC(val); + xc->pcState(pc); } inline Fault diff --git a/src/arch/arm/insts/vfp.hh b/src/arch/arm/insts/vfp.hh index 964b62673..e962704e0 100644 --- a/src/arch/arm/insts/vfp.hh +++ b/src/arch/arm/insts/vfp.hh @@ -459,6 +459,18 @@ class FpOp : public PredOp unaryOp(FPSCR &fpscr, fpType op1, fpType (*func)(fpType), bool flush, uint32_t rMode) const; + + void + advancePC(PCState &pcState) const + { + if (flags[IsLastMicroop]) { + pcState.uEnd(); + } else if (flags[IsMicroop]) { + pcState.uAdvance(); + } else { + pcState.advance(); + } + } }; class FpRegRegOp : public FpOp diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index d557cecbb..0ba62f08d 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -168,15 +168,9 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc) { if (misc_reg == MISCREG_CPSR) { CPSR cpsr = miscRegs[misc_reg]; - Addr pc = tc->readPC(); - if (pc & (ULL(1) << PcJBitShift)) - cpsr.j = 1; - else - cpsr.j = 0; - if (isThumb(pc)) - cpsr.t = 1; - else - cpsr.t = 0; + PCState pc = tc->pcState(); + cpsr.j = pc.jazelle() ? 1 : 0; + cpsr.t = pc.thumb() ? 1 : 0; return cpsr; } if (misc_reg >= MISCREG_CP15_UNIMP_START && @@ -239,13 +233,10 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) CPSR cpsr = val; DPRINTF(Arm, "Updating CPSR from %#x to %#x f:%d i:%d a:%d mode:%#x\n", miscRegs[misc_reg], cpsr, cpsr.f, cpsr.i, cpsr.a, cpsr.mode); - Addr npc = tc->readNextPC() & ~PcModeMask; - if (cpsr.j) - npc = npc | PcJBit; - if (cpsr.t) - npc = npc | PcTBit; - - tc->setNextPC(npc); + PCState pc = tc->pcState(); + pc.nextThumb(cpsr.t); + pc.nextJazelle(cpsr.j); + tc->pcState(pc); } else if (misc_reg >= MISCREG_CP15_UNIMP_START && misc_reg < MISCREG_CP15_END) { panic("Unimplemented CP15 register %s wrote with %#x.\n", @@ -414,7 +405,7 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) default: panic("Security Extensions not implemented!"); } - req->setVirt(0, val, 1, flags, tc->readPC()); + req->setVirt(0, val, 1, flags, tc->pcState().pc()); fault = tc->getDTBPtr()->translateAtomic(req, tc, mode); if (fault == NoFault) { miscRegs[MISCREG_PAR] = diff --git a/src/arch/arm/isa/formats/breakpoint.isa b/src/arch/arm/isa/formats/breakpoint.isa index d59f6a712..1825d0878 100644 --- a/src/arch/arm/isa/formats/breakpoint.isa +++ b/src/arch/arm/isa/formats/breakpoint.isa @@ -83,7 +83,7 @@ output exec {{ Breakpoint::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { - return new PrefetchAbort(xc->readPC(), ArmFault::DebugEvent); + return new PrefetchAbort(xc->pcState().pc(), ArmFault::DebugEvent); } }}; diff --git a/src/arch/arm/isa/insts/branch.isa b/src/arch/arm/isa/insts/branch.isa index e9ddd77b7..3ff9042e6 100644 --- a/src/arch/arm/isa/insts/branch.isa +++ b/src/arch/arm/isa/insts/branch.isa @@ -46,15 +46,17 @@ let {{ # B, BL for (mnem, link) in (("b", False), ("bl", True)): bCode = ''' - Addr curPc = readPC(xc); - NPC = ((curPc + imm) & mask(32)) | (curPc & ~mask(32)); + ArmISA::PCState pc = PCS; + Addr curPc = pc.instPC(); + pc.instNPC((uint32_t)(curPc + imm)); + PCS = pc; ''' if (link): bCode += ''' - if (!isThumb(curPc)) - LR = curPc - 4; - else + if (pc.thumb()) LR = curPc | 1; + else + LR = curPc - 4; ''' bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond", @@ -66,10 +68,12 @@ let {{ # BX, BLX blxCode = ''' - Addr curPc M5_VAR_USED = readPC(xc); + ArmISA::PCState pc = PCS; + Addr curPc M5_VAR_USED = pc.instPC(); %(link)s // Switch modes %(branch)s + PCS = pc; ''' blxList = (("blx", True, True), @@ -81,8 +85,8 @@ let {{ if imm: Name += "Imm" # Since we're switching ISAs, the target ISA will be the opposite - # of the current ISA. !arm is whether the target is ARM. - newPC = '(isThumb(curPc) ? (roundDown(curPc, 4) + imm) : (curPc + imm))' + # of the current ISA. pc.thumb() is whether the target is ARM. + newPC = '(pc.thumb() ? (roundDown(curPc, 4) + imm) : (curPc + imm))' base = "BranchImmCond" declare = BranchImmCondDeclare constructor = BranchImmCondConstructor @@ -97,28 +101,28 @@ let {{ // The immediate version of the blx thumb instruction // is 32 bits wide, but "next pc" doesn't reflect that // so we don't want to substract 2 from it at this point - if (!isThumb(curPc)) - LR = curPc - 4; - else + if (pc.thumb()) LR = curPc | 1; + else + LR = curPc - 4; ''' elif link: linkStr = ''' - if (!isThumb(curPc)) - LR = curPc - 4; - else + if (pc.thumb()) LR = (curPc - 2) | 1; + else + LR = curPc - 4; ''' else: linkStr = "" if imm and link: #blx with imm branchStr = ''' - Addr tempPc = ((%(newPC)s) & mask(32)) | (curPc & ~mask(32)); - FNPC = tempPc ^ PcTBit; + pc.nextThumb(!pc.thumb()); + pc.instNPC(%(newPC)s); ''' else: - branchStr = "IWNPC = %(newPC)s;" + branchStr = "pc.instIWNPC(%(newPC)s);" branchStr = branchStr % { "newPC" : newPC } code = blxCode % {"link": linkStr, @@ -136,8 +140,10 @@ let {{ #CBNZ, CBZ. These are always unconditional as far as predicates for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")): code = ''' - Addr curPc = readPC(xc); - NPC = ((curPc + imm) & mask(32)) | (curPc & ~mask(32)); + ArmISA::PCState pc = PCS; + Addr curPc = pc.instPC(); + pc.instNPC((uint32_t)(curPc + imm)); + PCS = pc; ''' predTest = "Op1 %(test)s 0" % {"test": test} iop = InstObjParams(mnem, mnem.capitalize(), "BranchImmReg", @@ -155,7 +161,11 @@ let {{ ArmISA::TLB::MustBeOne; EA = Op1 + Op2 * 2 ''' - accCode = "NPC = readPC(xc) + 2 * (Mem.uh);" + accCode = ''' + ArmISA::PCState pc = PCS; + pc.instNPC(pc.instPC() + 2 * (Mem.uh)); + PCS = pc; + ''' mnem = "tbh" else: eaCode = ''' @@ -164,7 +174,11 @@ let {{ ArmISA::TLB::MustBeOne; EA = Op1 + Op2 ''' - accCode = "NPC = readPC(xc) + 2 * (Mem.ub);" + accCode = ''' + ArmISA::PCState pc = PCS; + pc.instNPC(pc.instPC() + 2 * (Mem.ub)); + PCS = pc; + ''' mnem = "tbb" iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg", {'ea_code': eaCode, diff --git a/src/arch/arm/isa/insts/data.isa b/src/arch/arm/isa/insts/data.isa index 74eeee3b2..4d368e181 100644 --- a/src/arch/arm/isa/insts/data.isa +++ b/src/arch/arm/isa/insts/data.isa @@ -239,6 +239,10 @@ let {{ cpsrWriteByInstr(Cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi); Cpsr = ~CondCodesMask & newCpsr; CondCodes = CondCodesMask & newCpsr; + ArmISA::PCState pc = PCS; + pc.nextThumb(((CPSR)newCpsr).t); + pc.nextJazelle(((CPSR)newCpsr).j); + PCS = pc; ''' buildImmDataInst(mnem + 's', code, flagType, suffix = "ImmPclr", buildCc = False, @@ -253,7 +257,8 @@ let {{ buildDataInst("rsb", "Dest = resTemp = secondOp - Op1;", "rsb") buildDataInst("add", "Dest = resTemp = Op1 + secondOp;", "add") buildImmDataInst("adr", ''' - Dest = resTemp = (readPC(xc) & ~0x3) + + ArmISA::PCState pc = PCS; + Dest = resTemp = (pc.instPC() & ~0x3) + (op1 ? secondOp : -secondOp); ''') buildDataInst("adc", "Dest = resTemp = Op1 + secondOp + %s;" % oldC, "add") diff --git a/src/arch/arm/isa/insts/ldr.isa b/src/arch/arm/isa/insts/ldr.isa index dc043ed8e..92ad52a6d 100644 --- a/src/arch/arm/isa/insts/ldr.isa +++ b/src/arch/arm/isa/insts/ldr.isa @@ -105,12 +105,16 @@ let {{ accCode = ''' CPSR cpsr = Cpsr; SCTLR sctlr = Sctlr; - NPC = cSwap<uint32_t>(Mem.ud, cpsr.e); + ArmISA::PCState pc = PCS; + pc.instNPC(cSwap<uint32_t>(Mem.ud, cpsr.e)); uint32_t newCpsr = cpsrWriteByInstr(cpsr | CondCodes, cSwap<uint32_t>(Mem.ud >> 32, cpsr.e), 0xF, true, sctlr.nmfi); Cpsr = ~CondCodesMask & newCpsr; + pc.nextThumb(((CPSR)newCpsr).t); + pc.nextJazelle(((CPSR)newCpsr).j); + PCS = pc; CondCodes = CondCodesMask & newCpsr; ''' self.codeBlobs["memacc_code"] = accCode diff --git a/src/arch/arm/isa/insts/macromem.isa b/src/arch/arm/isa/insts/macromem.isa index 6bf789efd..a81050b1e 100644 --- a/src/arch/arm/isa/insts/macromem.isa +++ b/src/arch/arm/isa/insts/macromem.isa @@ -93,7 +93,9 @@ let {{ cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi); Cpsr = ~CondCodesMask & newCpsr; CondCodes = CondCodesMask & newCpsr; - IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0); + ArmISA::PCState pc = PCS; + pc.instIWNPC(cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0)); + PCS = pc; ''' microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', 'MicroMemOp', diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa index 5742f84ab..1abbc3de1 100644 --- a/src/arch/arm/isa/insts/misc.isa +++ b/src/arch/arm/isa/insts/misc.isa @@ -83,6 +83,10 @@ let {{ uint32_t newCpsr = cpsrWriteByInstr(Cpsr | CondCodes, Op1, byteMask, false, sctlr.nmfi); Cpsr = ~CondCodesMask & newCpsr; + ArmISA::PCState pc = PCS; + pc.nextThumb(((CPSR)newCpsr).t); + pc.nextJazelle(((CPSR)newCpsr).j); + PCS = pc; CondCodes = CondCodesMask & newCpsr; ''' msrCpsrRegIop = InstObjParams("msr", "MsrCpsrReg", "MsrRegOp", @@ -107,6 +111,10 @@ let {{ uint32_t newCpsr = cpsrWriteByInstr(Cpsr | CondCodes, imm, byteMask, false, sctlr.nmfi); Cpsr = ~CondCodesMask & newCpsr; + ArmISA::PCState pc = PCS; + pc.nextThumb(((CPSR)newCpsr).t); + pc.nextJazelle(((CPSR)newCpsr).j); + PCS = pc; CondCodes = CondCodesMask & newCpsr; ''' msrCpsrImmIop = InstObjParams("msr", "MsrCpsrImm", "MsrImmOp", @@ -462,8 +470,12 @@ let {{ decoder_output += RegRegRegRegOpConstructor.subst(usada8Iop) exec_output += PredOpExecute.subst(usada8Iop) + bkptCode = ''' + ArmISA::PCState pc = PCS; + return new PrefetchAbort(pc.pc(), ArmFault::DebugEvent); + ''' bkptIop = InstObjParams("bkpt", "BkptInst", "ArmStaticInst", - "return new PrefetchAbort(PC, ArmFault::DebugEvent);") + bkptCode) header_output += BasicDeclare.subst(bkptIop) decoder_output += BasicConstructor.subst(bkptIop) exec_output += BasicExecute.subst(bkptIop) @@ -638,7 +650,10 @@ let {{ exec_output += PredOpExecute.subst(mcr15UserIop) enterxCode = ''' - FNPC = NPC | PcJBit | PcTBit; + ArmISA::PCState pc = PCS; + pc.nextThumb(true); + pc.nextJazelle(true); + PCS = pc; ''' enterxIop = InstObjParams("enterx", "Enterx", "PredOp", { "code": enterxCode, @@ -648,7 +663,10 @@ let {{ exec_output += PredOpExecute.subst(enterxIop) leavexCode = ''' - FNPC = (NPC & ~PcJBit) | PcTBit; + ArmISA::PCState pc = PCS; + pc.nextThumb(true); + pc.nextJazelle(false); + PCS = pc; ''' leavexIop = InstObjParams("leavex", "Leavex", "PredOp", { "code": leavexCode, diff --git a/src/arch/arm/isa/operands.isa b/src/arch/arm/isa/operands.isa index 4f1b7f610..8e856e74d 100644 --- a/src/arch/arm/isa/operands.isa +++ b/src/arch/arm/isa/operands.isa @@ -54,11 +54,10 @@ def operand_types {{ let {{ maybePCRead = ''' - ((%(reg_idx)s == PCReg) ? (readPC(xc) & ~PcModeMask) : - xc->%(func)s(this, %(op_idx)s)) + ((%(reg_idx)s == PCReg) ? readPC(xc) : xc->%(func)s(this, %(op_idx)s)) ''' maybeAlignedPCRead = ''' - ((%(reg_idx)s == PCReg) ? (roundDown(readPC(xc) & ~PcModeMask, 4)) : + ((%(reg_idx)s == PCReg) ? (roundDown(readPC(xc), 4)) : xc->%(func)s(this, %(op_idx)s)) ''' maybePCWrite = ''' @@ -81,140 +80,133 @@ let {{ xc->%(func)s(this, %(op_idx)s, %(final_val)s); } ''' - - readNPC = 'xc->readNextPC() & ~PcModeMask' - writeNPC = 'setNextPC(xc, %(final_val)s)' - writeIWNPC = 'setIWNextPC(xc, %(final_val)s)' - forceNPC = 'xc->setNextPC(%(final_val)s)' }}; def operands {{ #Abstracted integer reg operands - 'Dest': ('IntReg', 'uw', 'dest', 'IsInteger', 2, + 'Dest': ('IntReg', 'uw', 'dest', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'FpDest': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 2), - 'FpDestP0': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 2), - 'FpDestP1': ('FloatReg', 'sf', '(dest + 1)', 'IsFloating', 2), - 'FpDestP2': ('FloatReg', 'sf', '(dest + 2)', 'IsFloating', 2), - 'FpDestP3': ('FloatReg', 'sf', '(dest + 3)', 'IsFloating', 2), - 'FpDestP4': ('FloatReg', 'sf', '(dest + 4)', 'IsFloating', 2), - 'FpDestP5': ('FloatReg', 'sf', '(dest + 5)', 'IsFloating', 2), - 'FpDestP6': ('FloatReg', 'sf', '(dest + 6)', 'IsFloating', 2), - 'FpDestP7': ('FloatReg', 'sf', '(dest + 7)', 'IsFloating', 2), - 'FpDestS0P0': ('FloatReg', 'sf', '(dest + step * 0 + 0)', 'IsFloating', 2), - 'FpDestS0P1': ('FloatReg', 'sf', '(dest + step * 0 + 1)', 'IsFloating', 2), - 'FpDestS1P0': ('FloatReg', 'sf', '(dest + step * 1 + 0)', 'IsFloating', 2), - 'FpDestS1P1': ('FloatReg', 'sf', '(dest + step * 1 + 1)', 'IsFloating', 2), - 'FpDestS2P0': ('FloatReg', 'sf', '(dest + step * 2 + 0)', 'IsFloating', 2), - 'FpDestS2P1': ('FloatReg', 'sf', '(dest + step * 2 + 1)', 'IsFloating', 2), - 'FpDestS3P0': ('FloatReg', 'sf', '(dest + step * 3 + 0)', 'IsFloating', 2), - 'FpDestS3P1': ('FloatReg', 'sf', '(dest + step * 3 + 1)', 'IsFloating', 2), - 'Result': ('IntReg', 'uw', 'result', 'IsInteger', 2, + 'FpDest': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 3), + 'FpDestP0': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 3), + 'FpDestP1': ('FloatReg', 'sf', '(dest + 1)', 'IsFloating', 3), + 'FpDestP2': ('FloatReg', 'sf', '(dest + 2)', 'IsFloating', 3), + 'FpDestP3': ('FloatReg', 'sf', '(dest + 3)', 'IsFloating', 3), + 'FpDestP4': ('FloatReg', 'sf', '(dest + 4)', 'IsFloating', 3), + 'FpDestP5': ('FloatReg', 'sf', '(dest + 5)', 'IsFloating', 3), + 'FpDestP6': ('FloatReg', 'sf', '(dest + 6)', 'IsFloating', 3), + 'FpDestP7': ('FloatReg', 'sf', '(dest + 7)', 'IsFloating', 3), + 'FpDestS0P0': ('FloatReg', 'sf', '(dest + step * 0 + 0)', 'IsFloating', 3), + 'FpDestS0P1': ('FloatReg', 'sf', '(dest + step * 0 + 1)', 'IsFloating', 3), + 'FpDestS1P0': ('FloatReg', 'sf', '(dest + step * 1 + 0)', 'IsFloating', 3), + 'FpDestS1P1': ('FloatReg', 'sf', '(dest + step * 1 + 1)', 'IsFloating', 3), + 'FpDestS2P0': ('FloatReg', 'sf', '(dest + step * 2 + 0)', 'IsFloating', 3), + 'FpDestS2P1': ('FloatReg', 'sf', '(dest + step * 2 + 1)', 'IsFloating', 3), + 'FpDestS3P0': ('FloatReg', 'sf', '(dest + step * 3 + 0)', 'IsFloating', 3), + 'FpDestS3P1': ('FloatReg', 'sf', '(dest + step * 3 + 1)', 'IsFloating', 3), + 'Result': ('IntReg', 'uw', 'result', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Dest2': ('IntReg', 'uw', 'dest2', 'IsInteger', 2, + 'Dest2': ('IntReg', 'uw', 'dest2', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'FpDest2': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 2), - 'FpDest2P0': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 2), - 'FpDest2P1': ('FloatReg', 'sf', '(dest2 + 1)', 'IsFloating', 2), - 'FpDest2P2': ('FloatReg', 'sf', '(dest2 + 2)', 'IsFloating', 2), - 'FpDest2P3': ('FloatReg', 'sf', '(dest2 + 3)', 'IsFloating', 2), - 'IWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 2, + 'FpDest2': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 3), + 'FpDest2P0': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 3), + 'FpDest2P1': ('FloatReg', 'sf', '(dest2 + 1)', 'IsFloating', 3), + 'FpDest2P2': ('FloatReg', 'sf', '(dest2 + 2)', 'IsFloating', 3), + 'FpDest2P3': ('FloatReg', 'sf', '(dest2 + 3)', 'IsFloating', 3), + 'IWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 3, maybePCRead, maybeIWPCWrite), - 'AIWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 2, + 'AIWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 3, maybePCRead, maybeAIWPCWrite), 'SpMode': ('IntReg', 'uw', 'intRegInMode((OperatingMode)regMode, INTREG_SP)', - 'IsInteger', 2), - 'MiscDest': ('ControlReg', 'uw', 'dest', (None, None, 'IsControl'), 2), - 'Base': ('IntReg', 'uw', 'base', 'IsInteger', 0, + 'IsInteger', 3), + 'MiscDest': ('ControlReg', 'uw', 'dest', (None, None, 'IsControl'), 3), + 'Base': ('IntReg', 'uw', 'base', 'IsInteger', 1, maybeAlignedPCRead, maybePCWrite), - 'Index': ('IntReg', 'uw', 'index', 'IsInteger', 2, + 'Index': ('IntReg', 'uw', 'index', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Op1': ('IntReg', 'uw', 'op1', 'IsInteger', 2, + 'Op1': ('IntReg', 'uw', 'op1', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'FpOp1': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 2), - 'FpOp1P0': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 2), - 'FpOp1P1': ('FloatReg', 'sf', '(op1 + 1)', 'IsFloating', 2), - 'FpOp1P2': ('FloatReg', 'sf', '(op1 + 2)', 'IsFloating', 2), - 'FpOp1P3': ('FloatReg', 'sf', '(op1 + 3)', 'IsFloating', 2), - 'FpOp1P4': ('FloatReg', 'sf', '(op1 + 4)', 'IsFloating', 2), - 'FpOp1P5': ('FloatReg', 'sf', '(op1 + 5)', 'IsFloating', 2), - 'FpOp1P6': ('FloatReg', 'sf', '(op1 + 6)', 'IsFloating', 2), - 'FpOp1P7': ('FloatReg', 'sf', '(op1 + 7)', 'IsFloating', 2), - 'FpOp1S0P0': ('FloatReg', 'sf', '(op1 + step * 0 + 0)', 'IsFloating', 2), - 'FpOp1S0P1': ('FloatReg', 'sf', '(op1 + step * 0 + 1)', 'IsFloating', 2), - 'FpOp1S1P0': ('FloatReg', 'sf', '(op1 + step * 1 + 0)', 'IsFloating', 2), - 'FpOp1S1P1': ('FloatReg', 'sf', '(op1 + step * 1 + 1)', 'IsFloating', 2), - 'FpOp1S2P0': ('FloatReg', 'sf', '(op1 + step * 2 + 0)', 'IsFloating', 2), - 'FpOp1S2P1': ('FloatReg', 'sf', '(op1 + step * 2 + 1)', 'IsFloating', 2), - 'FpOp1S3P0': ('FloatReg', 'sf', '(op1 + step * 3 + 0)', 'IsFloating', 2), - 'FpOp1S3P1': ('FloatReg', 'sf', '(op1 + step * 3 + 1)', 'IsFloating', 2), - 'MiscOp1': ('ControlReg', 'uw', 'op1', (None, None, 'IsControl'), 2), - 'Op2': ('IntReg', 'uw', 'op2', 'IsInteger', 2, + 'FpOp1': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 3), + 'FpOp1P0': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 3), + 'FpOp1P1': ('FloatReg', 'sf', '(op1 + 1)', 'IsFloating', 3), + 'FpOp1P2': ('FloatReg', 'sf', '(op1 + 2)', 'IsFloating', 3), + 'FpOp1P3': ('FloatReg', 'sf', '(op1 + 3)', 'IsFloating', 3), + 'FpOp1P4': ('FloatReg', 'sf', '(op1 + 4)', 'IsFloating', 3), + 'FpOp1P5': ('FloatReg', 'sf', '(op1 + 5)', 'IsFloating', 3), + 'FpOp1P6': ('FloatReg', 'sf', '(op1 + 6)', 'IsFloating', 3), + 'FpOp1P7': ('FloatReg', 'sf', '(op1 + 7)', 'IsFloating', 3), + 'FpOp1S0P0': ('FloatReg', 'sf', '(op1 + step * 0 + 0)', 'IsFloating', 3), + 'FpOp1S0P1': ('FloatReg', 'sf', '(op1 + step * 0 + 1)', 'IsFloating', 3), + 'FpOp1S1P0': ('FloatReg', 'sf', '(op1 + step * 1 + 0)', 'IsFloating', 3), + 'FpOp1S1P1': ('FloatReg', 'sf', '(op1 + step * 1 + 1)', 'IsFloating', 3), + 'FpOp1S2P0': ('FloatReg', 'sf', '(op1 + step * 2 + 0)', 'IsFloating', 3), + 'FpOp1S2P1': ('FloatReg', 'sf', '(op1 + step * 2 + 1)', 'IsFloating', 3), + 'FpOp1S3P0': ('FloatReg', 'sf', '(op1 + step * 3 + 0)', 'IsFloating', 3), + 'FpOp1S3P1': ('FloatReg', 'sf', '(op1 + step * 3 + 1)', 'IsFloating', 3), + 'MiscOp1': ('ControlReg', 'uw', 'op1', (None, None, 'IsControl'), 3), + 'Op2': ('IntReg', 'uw', 'op2', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'FpOp2': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 2), - 'FpOp2P0': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 2), - 'FpOp2P1': ('FloatReg', 'sf', '(op2 + 1)', 'IsFloating', 2), - 'FpOp2P2': ('FloatReg', 'sf', '(op2 + 2)', 'IsFloating', 2), - 'FpOp2P3': ('FloatReg', 'sf', '(op2 + 3)', 'IsFloating', 2), - 'Op3': ('IntReg', 'uw', 'op3', 'IsInteger', 2, + 'FpOp2': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 3), + 'FpOp2P0': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 3), + 'FpOp2P1': ('FloatReg', 'sf', '(op2 + 1)', 'IsFloating', 3), + 'FpOp2P2': ('FloatReg', 'sf', '(op2 + 2)', 'IsFloating', 3), + 'FpOp2P3': ('FloatReg', 'sf', '(op2 + 3)', 'IsFloating', 3), + 'Op3': ('IntReg', 'uw', 'op3', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Shift': ('IntReg', 'uw', 'shift', 'IsInteger', 2, + 'Shift': ('IntReg', 'uw', 'shift', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Reg0': ('IntReg', 'uw', 'reg0', 'IsInteger', 2, + 'Reg0': ('IntReg', 'uw', 'reg0', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Reg1': ('IntReg', 'uw', 'reg1', 'IsInteger', 2, + 'Reg1': ('IntReg', 'uw', 'reg1', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Reg2': ('IntReg', 'uw', 'reg2', 'IsInteger', 2, + 'Reg2': ('IntReg', 'uw', 'reg2', 'IsInteger', 3, maybePCRead, maybePCWrite), - 'Reg3': ('IntReg', 'uw', 'reg3', 'IsInteger', 2, + 'Reg3': ('IntReg', 'uw', 'reg3', 'IsInteger', 3, maybePCRead, maybePCWrite), #General Purpose Integer Reg Operands - 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'R7': ('IntReg', 'uw', '7', 'IsInteger', 2), - 'R0': ('IntReg', 'uw', '0', 'IsInteger', 2), + 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 3, maybePCRead, maybePCWrite), + 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 3, maybePCRead, maybePCWrite), + 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3, maybePCRead, maybePCWrite), + 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 3, maybePCRead, maybePCWrite), + 'R7': ('IntReg', 'uw', '7', 'IsInteger', 3), + 'R0': ('IntReg', 'uw', '0', 'IsInteger', 3), - 'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 2), - 'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', None, 2), + 'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 3), + 'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', None, 3), 'OptCondCodes': ('IntReg', 'uw', '''(condCode == COND_AL || condCode == COND_UC) ? - INTREG_ZERO : INTREG_CONDCODES''', None, 2), - 'FpCondCodes': ('IntReg', 'uw', 'INTREG_FPCONDCODES', None, 2), + INTREG_ZERO : INTREG_CONDCODES''', None, 3), + 'FpCondCodes': ('IntReg', 'uw', 'INTREG_FPCONDCODES', None, 3), #Register fields for microops - 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'IWRa' : ('IntReg', 'uw', 'ura', 'IsInteger', 2, + 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 3, maybePCRead, maybePCWrite), + 'IWRa' : ('IntReg', 'uw', 'ura', 'IsInteger', 3, maybePCRead, maybeIWPCWrite), - 'Fa' : ('FloatReg', 'sf', 'ura', 'IsFloating', 2), - 'Rb' : ('IntReg', 'uw', 'urb', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'Rc' : ('IntReg', 'uw', 'urc', 'IsInteger', 2, maybePCRead, maybePCWrite), + 'Fa' : ('FloatReg', 'sf', 'ura', 'IsFloating', 3), + 'Rb' : ('IntReg', 'uw', 'urb', 'IsInteger', 3, maybePCRead, maybePCWrite), + 'Rc' : ('IntReg', 'uw', 'urc', 'IsInteger', 3, maybePCRead, maybePCWrite), #General Purpose Floating Point Reg Operands - 'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 2), - 'Fn': ('FloatReg', 'df', 'FN', 'IsFloating', 2), - 'Fm': ('FloatReg', 'df', 'FM', 'IsFloating', 2), + 'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 3), + 'Fn': ('FloatReg', 'df', 'FN', 'IsFloating', 3), + 'Fm': ('FloatReg', 'df', 'FM', 'IsFloating', 3), #Memory Operand - 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 2), + 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 3), - 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 1), - 'Itstate': ('ControlReg', 'ub', 'MISCREG_ITSTATE', None, 2), - 'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', None, 2), - 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', None, 2), - 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', None, 2), - 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', None, 2), - 'Cpacr': ('ControlReg', 'uw', 'MISCREG_CPACR', (None, None, 'IsControl'), 2), - 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', None, 2), - 'Sctlr': ('ControlReg', 'uw', 'MISCREG_SCTLR', None, 2), - 'SevMailbox': ('ControlReg', 'uw', 'MISCREG_SEV_MAILBOX', None, 2), - 'PC': ('PC', 'ud', None, None, 2), - 'NPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2, - readNPC, writeNPC), - 'FNPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2, - readNPC, forceNPC), - 'IWNPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2, - readNPC, writeIWNPC), + 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 2), + 'Itstate': ('ControlReg', 'ub', 'MISCREG_ITSTATE', None, 3), + 'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', None, 3), + 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', None, 3), + 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', None, 3), + 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', None, 3), + 'Cpacr': ('ControlReg', 'uw', 'MISCREG_CPACR', (None, None, 'IsControl'), 3), + 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', None, 3), + 'Sctlr': ('ControlReg', 'uw', 'MISCREG_SCTLR', None, 3), + 'SevMailbox': ('ControlReg', 'uw', 'MISCREG_SEV_MAILBOX', None, 3), + #PCS needs to have a sorting index (the number at the end) less than all + #the integer registers which might update the PC. That way if the flag + #bits of the pc state are updated and a branch happens through R15, the + #updates are layered properly and the R15 update isn't lost. + 'PCS': ('PCState', 'uw', None, (None, None, 'IsControl'), 0) }}; diff --git a/src/arch/arm/isa_traits.hh b/src/arch/arm/isa_traits.hh index 8d3f0ffe3..f6aa7fcf0 100644 --- a/src/arch/arm/isa_traits.hh +++ b/src/arch/arm/isa_traits.hh @@ -123,15 +123,6 @@ namespace ArmISA INT_FIQ, NumInterruptTypes }; - - // These otherwise unused bits of the PC are used to select a mode - // like the J and T bits of the CPSR. - static const Addr PcJBitShift = 33; - static const Addr PcJBit = ULL(1) << PcJBitShift; - static const Addr PcTBitShift = 34; - static const Addr PcTBit = ULL(1) << PcTBitShift; - static const Addr PcModeMask = (ULL(1) << PcJBitShift) | - (ULL(1) << PcTBitShift); }; using namespace ArmISA; diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc index 7c4e00921..40658976b 100644 --- a/src/arch/arm/linux/system.cc +++ b/src/arch/arm/linux/system.cc @@ -103,8 +103,7 @@ LinuxArmSystem::startup() ThreadContext *tc = threadContexts[0]; // Set the initial PC to be at start of the kernel code - tc->setPC(tc->getSystemPtr()->kernelEntry & loadAddrMask); - tc->setNextPC(tc->readPC() + sizeof(MachInst)); + tc->pcState(tc->getSystemPtr()->kernelEntry & loadAddrMask); // Setup the machine type tc->setIntReg(0, 0); diff --git a/src/arch/arm/nativetrace.cc b/src/arch/arm/nativetrace.cc index d97be88a2..75546f8de 100644 --- a/src/arch/arm/nativetrace.cc +++ b/src/arch/arm/nativetrace.cc @@ -106,7 +106,7 @@ Trace::ArmNativeTrace::ThreadState::update(ThreadContext *tc) } //R15, aliased with the PC - newState[STATE_PC] = tc->readNextPC(); + newState[STATE_PC] = tc->pcState().npc(); changed[STATE_PC] = (newState[STATE_PC] != oldState[STATE_PC]); //CPSR @@ -121,7 +121,7 @@ Trace::ArmNativeTrace::check(NativeTraceRecord *record) ThreadContext *tc = record->getThread(); // This area is read only on the target. It can't stop there to tell us // what's going on, so we should skip over anything there also. - if (tc->readNextPC() > 0xffff0000) + if (tc->nextInstAddr() > 0xffff0000) return; nState.update(this); mState.update(tc); diff --git a/src/arch/arm/predecoder.cc b/src/arch/arm/predecoder.cc index 04cec59b9..456b9e4c4 100644 --- a/src/arch/arm/predecoder.cc +++ b/src/arch/arm/predecoder.cc @@ -148,11 +148,11 @@ Predecoder::process() //Use this to give data to the predecoder. This should be used //when there is control flow. void -Predecoder::moreBytes(Addr pc, Addr fetchPC, MachInst inst) +Predecoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst) { data = inst; - offset = (fetchPC >= pc) ? 0 : pc - fetchPC; - emi.thumb = isThumb(pc); + offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC; + emi.thumb = pc.thumb(); FPSCR fpscr = tc->readMiscReg(MISCREG_FPSCR); emi.fpscrLen = fpscr.len; emi.fpscrStride = fpscr.stride; diff --git a/src/arch/arm/predecoder.hh b/src/arch/arm/predecoder.hh index 2db550024..47242b8ff 100644 --- a/src/arch/arm/predecoder.hh +++ b/src/arch/arm/predecoder.hh @@ -94,7 +94,7 @@ namespace ArmISA //Use this to give data to the predecoder. This should be used //when there is control flow. - void moreBytes(Addr pc, Addr fetchPC, MachInst inst); + void moreBytes(const PCState &pc, Addr fetchPC, MachInst inst); //Use this to give data to the predecoder. This should be used //when instructions are executed in order. @@ -121,9 +121,10 @@ namespace ArmISA } //This returns a constant reference to the ExtMachInst to avoid a copy - ExtMachInst getExtMachInst() + ExtMachInst getExtMachInst(PCState &pc) { ExtMachInst thisEmi = emi; + pc.npc(pc.pc() + getInstSize()); emi = 0; return thisEmi; } diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index bc2aee4c8..a5460ac19 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -360,11 +360,11 @@ ArmLiveProcess::argsInit(int intSize, int pageSize) tc->setIntReg(ArgumentReg2, 0); } - Addr prog_entry = objFile->entryPoint(); - if (arch == ObjectFile::Thumb) - prog_entry = (prog_entry & ~mask(1)) | PcTBit; - tc->setPC(prog_entry); - tc->setNextPC(prog_entry + sizeof(MachInst)); + PCState pc; + pc.thumb(arch == ObjectFile::Thumb); + pc.nextThumb(pc.thumb()); + pc.set(objFile->entryPoint() & ~mask(1)); + tc->pcState(pc); //Align the "stack_min" to a page boundary. stack_min = roundDown(stack_min, pageSize); diff --git a/src/arch/arm/system.hh b/src/arch/arm/system.hh index fe5ba6447..c64673df5 100644 --- a/src/arch/arm/system.hh +++ b/src/arch/arm/system.hh @@ -70,7 +70,7 @@ class ArmSystem : public System // Remove the low bit that thumb symbols have set // but that aren't actually odd aligned if (addr & 0x1) - return (addr & ~1) | PcTBit; + return addr & ~1; return addr; } }; diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc index 73dd24e1c..06bb10219 100644 --- a/src/arch/arm/table_walker.cc +++ b/src/arch/arm/table_walker.cc @@ -107,7 +107,7 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _ /** @todo These should be cached or grabbed from cached copies in the TLB, all these miscreg reads are expensive */ - currState->vaddr = currState->req->getVaddr() & ~PcModeMask; + currState->vaddr = currState->req->getVaddr(); currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR); sctlr = currState->sctlr; currState->N = currState->tc->readMiscReg(MISCREG_TTBCR); diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index c0ebb52b2..239d5d8a2 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -316,7 +316,7 @@ TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode, Translation *translation, bool &delay, bool timing) { // XXX Cache misc registers and have miscreg write function inv cache - Addr vaddr = req->getVaddr() & ~PcModeMask; + Addr vaddr = req->getVaddr(); SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); uint32_t flags = req->getFlags(); @@ -362,7 +362,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode, Translation *translation, bool &delay, bool timing) { // XXX Cache misc registers and have miscreg write function inv cache - Addr vaddr = req->getVaddr() & ~PcModeMask; + Addr vaddr = req->getVaddr(); SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); uint32_t flags = req->getFlags(); diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh index 3c3b29494..57f34e3c2 100644 --- a/src/arch/arm/types.hh +++ b/src/arch/arm/types.hh @@ -43,8 +43,10 @@ #ifndef __ARCH_ARM_TYPES_HH__ #define __ARCH_ARM_TYPES_HH__ +#include "arch/generic/types.hh" #include "base/bitunion.hh" #include "base/hashmap.hh" +#include "base/misc.hh" #include "base/types.hh" namespace ArmISA @@ -188,6 +190,189 @@ namespace ArmISA Bitfield<11, 8> ltcoproc; EndBitUnion(ExtMachInst) + class PCState : public GenericISA::UPCState<MachInst> + { + protected: + + typedef GenericISA::UPCState<MachInst> Base; + + enum FlagBits { + ThumbBit = (1 << 0), + JazelleBit = (1 << 1) + }; + uint8_t flags; + uint8_t nextFlags; + + public: + PCState() : flags(0), nextFlags(0) + {} + + void + set(Addr val) + { + Base::set(val); + npc(val + (thumb() ? 2 : 4)); + } + + PCState(Addr val) : flags(0), nextFlags(0) + { set(val); } + + bool + thumb() const + { + return flags & ThumbBit; + } + + void + thumb(bool val) + { + if (val) + flags |= ThumbBit; + else + flags &= ~ThumbBit; + } + + bool + nextThumb() const + { + return nextFlags & ThumbBit; + } + + void + nextThumb(bool val) + { + if (val) + nextFlags |= ThumbBit; + else + nextFlags &= ~ThumbBit; + } + + bool + jazelle() const + { + return flags & JazelleBit; + } + + void + jazelle(bool val) + { + if (val) + flags |= JazelleBit; + else + flags &= ~JazelleBit; + } + + bool + nextJazelle() const + { + return nextFlags & JazelleBit; + } + + void + nextJazelle(bool val) + { + if (val) + nextFlags |= JazelleBit; + else + nextFlags &= ~JazelleBit; + } + + void + advance() + { + Base::advance(); + npc(pc() + (thumb() ? 2 : 4)); + flags = nextFlags; + } + + void + uEnd() + { + advance(); + upc(0); + nupc(1); + } + + Addr + instPC() const + { + return pc() + (thumb() ? 4 : 8); + } + + void + instNPC(uint32_t val) + { + npc(val &~ mask(nextThumb() ? 1 : 2)); + } + + Addr + instNPC() const + { + return npc(); + } + + // Perform an interworking branch. + void + instIWNPC(uint32_t val) + { + bool thumbEE = (thumb() && jazelle()); + + Addr newPC = val; + if (thumbEE) { + if (bits(newPC, 0)) { + newPC = newPC & ~mask(1); + } else { + panic("Bad thumbEE interworking branch address %#x.\n", + newPC); + } + } else { + if (bits(newPC, 0)) { + nextThumb(true); + newPC = newPC & ~mask(1); + } else if (!bits(newPC, 1)) { + nextThumb(false); + } else { + warn("Bad interworking branch address %#x.\n", newPC); + } + } + npc(newPC); + } + + // Perform an interworking branch in ARM mode, a regular branch + // otherwise. + void + instAIWNPC(uint32_t val) + { + if (!thumb() && !jazelle()) + instIWNPC(val); + else + instNPC(val); + } + + bool + operator == (const PCState &opc) const + { + return Base::operator == (opc) && + flags == opc.flags && nextFlags == opc.nextFlags; + } + + void + serialize(std::ostream &os) + { + Base::serialize(os); + SERIALIZE_SCALAR(flags); + SERIALIZE_SCALAR(nextFlags); + } + + void + unserialize(Checkpoint *cp, const std::string §ion) + { + Base::unserialize(cp, section); + UNSERIALIZE_SCALAR(flags); + UNSERIALIZE_SCALAR(nextFlags); + } + }; + // Shift types for ARM instructions enum ArmShiftType { LSL = 0, diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc index 7609b3991..a114ec5e0 100644 --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -128,13 +128,9 @@ readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2) void skipFunction(ThreadContext *tc) { - Addr newpc = tc->readIntReg(ReturnAddressReg); - newpc &= ~ULL(1); - if (isThumb(tc->readPC())) - tc->setPC(newpc | PcTBit); - else - tc->setPC(newpc); - tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst)); + TheISA::PCState newPC = tc->pcState(); + newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1)); + tc->pcState(newPC); } diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh index 571a74ef8..a92ab072c 100644 --- a/src/arch/arm/utility.hh +++ b/src/arch/arm/utility.hh @@ -51,10 +51,19 @@ #include "base/misc.hh" #include "base/trace.hh" #include "base/types.hh" +#include "cpu/static_inst.hh" #include "cpu/thread_context.hh" namespace ArmISA { + inline PCState + buildRetPC(const PCState &curPC, const PCState &callPC) + { + PCState retPC = callPC; + retPC.uEnd(); + return retPC; + } + inline bool testPredicate(CPSR cpsr, ConditionCode code) { @@ -93,12 +102,6 @@ namespace ArmISA { tc->activate(0); } - static inline bool - isThumb(Addr pc) - { - return (pc & PcTBit); - } - static inline void copyRegs(ThreadContext *src, ThreadContext *dest) { @@ -163,6 +166,12 @@ Fault readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2); void skipFunction(ThreadContext *tc); +inline void +advancePC(PCState &pc, const StaticInstPtr inst) +{ + inst->advancePC(pc); +} + }; diff --git a/src/arch/generic/types.hh b/src/arch/generic/types.hh new file mode 100644 index 000000000..214b01926 --- /dev/null +++ b/src/arch/generic/types.hh @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2010 Gabe Black + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_GENERIC_TYPES_HH__ +#define __ARCH_GENERIC_TYPES_HH__ + +#include <iostream> + +#include "base/types.hh" +#include "base/trace.hh" +#include "sim/serialize.hh" + +namespace GenericISA +{ + +// The guaranteed interface. +class PCStateBase +{ + protected: + Addr _pc; + Addr _npc; + + PCStateBase() {} + PCStateBase(Addr val) { set(val); } + + public: + /** + * Returns the memory address the bytes of this instruction came from. + * + * @return Memory address of the current instruction's encoding. + */ + Addr + instAddr() const + { + return _pc; + } + + /** + * Returns the memory address the bytes of the next instruction came from. + * + * @return Memory address of the next instruction's encoding. + */ + Addr + nextInstAddr() const + { + return _npc; + } + + /** + * Returns the current micropc. + * + * @return The current micropc. + */ + MicroPC + microPC() const + { + return 0; + } + + /** + * Force this PC to reflect a particular value, resetting all its other + * fields around it. This is useful for in place (re)initialization. + * + * @param val The value to set the PC to. + */ + void set(Addr val); + + bool + operator == (const PCStateBase &opc) const + { + return _pc == opc._pc && _npc == opc._npc; + } + + void + serialize(std::ostream &os) + { + SERIALIZE_SCALAR(_pc); + SERIALIZE_SCALAR(_npc); + } + + void + unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_SCALAR(_pc); + UNSERIALIZE_SCALAR(_npc); + } +}; + + +/* + * Different flavors of PC state. Only ISA specific code should rely on + * any particular type of PC state being available. All other code should + * use the interface above. + */ + +// The most basic type of PC. +template <class MachInst> +class SimplePCState : public PCStateBase +{ + protected: + typedef PCStateBase Base; + + public: + + Addr pc() const { return _pc; } + void pc(Addr val) { _pc = val; } + + Addr npc() const { return _npc; } + void npc(Addr val) { _npc = val; } + + void + set(Addr val) + { + pc(val); + npc(val + sizeof(MachInst)); + }; + + SimplePCState() {} + SimplePCState(Addr val) { set(val); } + + bool + branching() const + { + return this->npc() != this->pc() + sizeof(MachInst); + } + + // Advance the PC. + void + advance() + { + _pc = _npc; + _npc += sizeof(MachInst); + } +}; + +template <class MachInst> +std::ostream & +operator<<(std::ostream & os, const SimplePCState<MachInst> &pc) +{ + ccprintf(os, "(%#x=>%#x)", pc.pc(), pc.npc()); + return os; +} + +// A PC and microcode PC. +template <class MachInst> +class UPCState : public SimplePCState<MachInst> +{ + protected: + typedef SimplePCState<MachInst> Base; + + MicroPC _upc; + MicroPC _nupc; + + public: + + MicroPC upc() const { return _upc; } + void upc(MicroPC val) { _upc = val; } + + MicroPC nupc() const { return _nupc; } + void nupc(MicroPC val) { _nupc = val; } + + MicroPC + microPC() const + { + return _upc; + } + + void + set(Addr val) + { + Base::set(val); + upc(0); + nupc(1); + } + + UPCState() {} + UPCState(Addr val) { set(val); } + + bool + branching() const + { + return this->npc() != this->pc() + sizeof(MachInst) || + this->nupc() != this->upc() + 1; + } + + // Advance the upc within the instruction. + void + uAdvance() + { + _upc = _nupc; + _nupc++; + } + + // End the macroop by resetting the upc and advancing the regular pc. + void + uEnd() + { + this->advance(); + _upc = 0; + _nupc = 1; + } + + bool + operator == (const UPCState<MachInst> &opc) const + { + return Base::_pc == opc._pc && + Base::_npc == opc._npc && + _upc == opc._upc && _nupc == opc._nupc; + } + + void + serialize(std::ostream &os) + { + Base::serialize(os); + SERIALIZE_SCALAR(_upc); + SERIALIZE_SCALAR(_nupc); + } + + void + unserialize(Checkpoint *cp, const std::string §ion) + { + Base::unserialize(cp, section); + UNSERIALIZE_SCALAR(_upc); + UNSERIALIZE_SCALAR(_nupc); + } +}; + +template <class MachInst> +std::ostream & +operator<<(std::ostream & os, const UPCState<MachInst> &pc) +{ + ccprintf(os, "(%#x=>%#x).(%d=>%d)", + pc.pc(), pc.npc(), pc.upc(), pc.npc()); + return os; +} + +// A PC with a delay slot. +template <class MachInst> +class DelaySlotPCState : public SimplePCState<MachInst> +{ + protected: + typedef SimplePCState<MachInst> Base; + + Addr _nnpc; + + public: + + Addr nnpc() const { return _nnpc; } + void nnpc(Addr val) { _nnpc = val; } + + void + set(Addr val) + { + Base::set(val); + nnpc(val + 2 * sizeof(MachInst)); + } + + DelaySlotPCState() {} + DelaySlotPCState(Addr val) { set(val); } + + bool + branching() const + { + return !(this->nnpc() == this->npc() + sizeof(MachInst) && + (this->npc() == this->pc() + sizeof(MachInst) || + this->npc() == this->pc() + 2 * sizeof(MachInst))); + } + + // Advance the PC. + void + advance() + { + Base::_pc = Base::_npc; + Base::_npc = _nnpc; + _nnpc += sizeof(MachInst); + } + + bool + operator == (const DelaySlotPCState<MachInst> &opc) const + { + return Base::_pc == opc._pc && + Base::_npc == opc._npc && + _nnpc == opc._nnpc; + } + + void + serialize(std::ostream &os) + { + Base::serialize(os); + SERIALIZE_SCALAR(_nnpc); + } + + void + unserialize(Checkpoint *cp, const std::string §ion) + { + Base::unserialize(cp, section); + UNSERIALIZE_SCALAR(_nnpc); + } +}; + +template <class MachInst> +std::ostream & +operator<<(std::ostream & os, const DelaySlotPCState<MachInst> &pc) +{ + ccprintf(os, "(%#x=>%#x=>%#x)", + pc.pc(), pc.npc(), pc.nnpc()); + return os; +} + +// A PC with a delay slot and a microcode PC. +template <class MachInst> +class DelaySlotUPCState : public DelaySlotPCState<MachInst> +{ + protected: + typedef DelaySlotPCState<MachInst> Base; + + MicroPC _upc; + MicroPC _nupc; + + public: + + MicroPC upc() const { return _upc; } + void upc(MicroPC val) { _upc = val; } + + MicroPC nupc() const { return _nupc; } + void nupc(MicroPC val) { _nupc = val; } + + MicroPC + microPC() const + { + return _upc; + } + + void + set(Addr val) + { + Base::set(val); + upc(0); + nupc(1); + } + + DelaySlotUPCState() {} + DelaySlotUPCState(Addr val) { set(val); } + + bool + branching() const + { + return Base::branching() || this->nupc() != this->upc() + 1; + } + + // Advance the upc within the instruction. + void + uAdvance() + { + _upc = _nupc; + _nupc++; + } + + // End the macroop by resetting the upc and advancing the regular pc. + void + uEnd() + { + this->advance(); + _upc = 0; + _nupc = 1; + } + + bool + operator == (const DelaySlotUPCState<MachInst> &opc) const + { + return Base::_pc == opc._pc && + Base::_npc == opc._npc && + Base::_nnpc == opc._nnpc && + _upc == opc._upc && _nupc == opc._nupc; + } + + void + serialize(std::ostream &os) + { + Base::serialize(os); + SERIALIZE_SCALAR(_upc); + SERIALIZE_SCALAR(_nupc); + } + + void + unserialize(Checkpoint *cp, const std::string §ion) + { + Base::unserialize(cp, section); + UNSERIALIZE_SCALAR(_upc); + UNSERIALIZE_SCALAR(_nupc); + } +}; + +template <class MachInst> +std::ostream & +operator<<(std::ostream & os, const DelaySlotUPCState<MachInst> &pc) +{ + ccprintf(os, "(%#x=>%#x=>%#x).(%d=>%d)", + pc.pc(), pc.npc(), pc.nnpc(), pc.upc(), pc.nupc()); + return os; +} + +} + +#endif diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index 4e06c2ded..8e13b6a6a 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -681,71 +681,43 @@ class MemOperand(Operand): def makeAccSize(self): return self.size -class PCOperand(Operand): +class PCStateOperand(Operand): def makeConstructor(self): return '' def makeRead(self): - return '%s = xc->readPC();\n' % self.base_name + return '%s = xc->pcState();\n' % self.base_name def makeWrite(self): - return 'xc->setPC(%s);\n' % self.base_name + return 'xc->pcState(%s);\n' % self.base_name -class UPCOperand(Operand): - def makeConstructor(self): - return '' - - def makeRead(self): - if self.read_code != None: - return self.buildReadCode('readMicroPC') - return '%s = xc->readMicroPC();\n' % self.base_name - - def makeWrite(self): - if self.write_code != None: - return self.buildWriteCode('setMicroPC') - return 'xc->setMicroPC(%s);\n' % self.base_name + def makeDecl(self): + return 'TheISA::PCState ' + self.base_name + ' M5_VAR_USED;\n'; -class NUPCOperand(Operand): +class PCOperand(Operand): def makeConstructor(self): return '' def makeRead(self): - if self.read_code != None: - return self.buildReadCode('readNextMicroPC') - return '%s = xc->readNextMicroPC();\n' % self.base_name + return '%s = xc->instAddr();\n' % self.base_name - def makeWrite(self): - if self.write_code != None: - return self.buildWriteCode('setNextMicroPC') - return 'xc->setNextMicroPC(%s);\n' % self.base_name - -class NPCOperand(Operand): +class UPCOperand(Operand): def makeConstructor(self): return '' def makeRead(self): if self.read_code != None: - return self.buildReadCode('readNextPC') - return '%s = xc->readNextPC();\n' % self.base_name - - def makeWrite(self): - if self.write_code != None: - return self.buildWriteCode('setNextPC') - return 'xc->setNextPC(%s);\n' % self.base_name + return self.buildReadCode('microPC') + return '%s = xc->microPC();\n' % self.base_name -class NNPCOperand(Operand): +class NPCOperand(Operand): def makeConstructor(self): return '' def makeRead(self): if self.read_code != None: - return self.buildReadCode('readNextNPC') - return '%s = xc->readNextNPC();\n' % self.base_name - - def makeWrite(self): - if self.write_code != None: - return self.buildWriteCode('setNextNPC') - return 'xc->setNextNPC(%s);\n' % self.base_name + return self.buildReadCode('nextInstAddr') + return '%s = xc->nextInstAddr();\n' % self.base_name class OperandList(object): '''Find all the operands in the given code block. Returns an operand diff --git a/src/arch/mips/isa/base.isa b/src/arch/mips/isa/base.isa index 4e2b12fc4..cd6faf0f3 100644 --- a/src/arch/mips/isa/base.isa +++ b/src/arch/mips/isa/base.isa @@ -56,6 +56,13 @@ output header {{ void printReg(std::ostream &os, int reg) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + public: + void + advancePC(MipsISA::PCState &pc) const + { + pc.advance(); + } }; }}; diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa index 9832937b5..3f3bd370a 100644 --- a/src/arch/mips/isa/decoder.isa +++ b/src/arch/mips/isa/decoder.isa @@ -133,25 +133,34 @@ decode OPCODE_HI default Unknown::unknown() { 0x1: jr_hb({{ Config1Reg config1 = Config1; if (config1.ca == 0) { - NNPC = Rs; + pc.nnpc(Rs); } else { panic("MIPS16e not supported\n"); } + PCS = pc; }}, IsReturn, ClearHazards); default: jr({{ Config1Reg config1 = Config1; if (config1.ca == 0) { - NNPC = Rs; + pc.nnpc(Rs); } else { panic("MIPS16e not supported\n"); } + PCS = pc; }}, IsReturn); } 0x1: decode HINT { - 0x1: jalr_hb({{ Rd = NNPC; NNPC = Rs; }}, IsCall - , ClearHazards); - default: jalr({{ Rd = NNPC; NNPC = Rs; }}, IsCall); + 0x1: jalr_hb({{ + Rd = pc.nnpc(); + pc.nnpc(Rs); + PCS = pc; + }}, IsCall, ClearHazards); + default: jalr({{ + Rd = pc.nnpc(); + pc.nnpc(Rs); + PCS = pc; + }}, IsCall); } } @@ -323,9 +332,14 @@ decode OPCODE_HI default Unknown::unknown() { } format Jump { - 0x2: j({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2); }}); - 0x3: jal({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2); }}, - IsCall, Link); + 0x2: j({{ + pc.nnpc((pc.npc() & 0xF0000000) | (JMPTARG << 2)); + PCS = pc; + }}); + 0x3: jal({{ + pc.nnpc((pc.npc() & 0xF0000000) | (JMPTARG << 2)); + PCS = pc; + }}, IsCall, Link); } format Branch { @@ -694,15 +708,16 @@ decode OPCODE_HI default Unknown::unknown() { ConfigReg config = Config; SRSCtlReg srsCtl = SRSCtl; DPRINTF(MipsPRA,"Restoring PC - %x\n",EPC); + MipsISA::PCState pc = PCS; if (status.erl == 1) { status.erl = 0; - NPC = ErrorEPC; + pc.npc(ErrorEPC); // Need to adjust NNPC, otherwise things break - NNPC = ErrorEPC + sizeof(MachInst); + pc.nnpc(ErrorEPC + sizeof(MachInst)); } else { - NPC = EPC; + pc.npc(EPC); // Need to adjust NNPC, otherwise things break - NNPC = EPC + sizeof(MachInst); + pc.nnpc(EPC + sizeof(MachInst)); status.exl = 0; if (config.ar >=1 && srsCtl.hss > 0 && @@ -711,6 +726,7 @@ decode OPCODE_HI default Unknown::unknown() { //xc->setShadowSet(srsCtl.pss); } } + PCS = pc; LLFlag = 0; Status = status; SRSCtl = srsCtl; @@ -718,13 +734,15 @@ decode OPCODE_HI default Unknown::unknown() { 0x1F: deret({{ DebugReg debug = Debug; + MipsISA::PCState pc = PCS; if (debug.dm == 1) { debug.dm = 1; debug.iexi = 0; - NPC = DEPC; + pc.npc(DEPC); } else { // Undefined; } + PCS = pc; Debug = debug; }}, IsReturn, IsSerializing, IsERET); } diff --git a/src/arch/mips/isa/formats/branch.isa b/src/arch/mips/isa/formats/branch.isa index 78f973a70..232a743a7 100644 --- a/src/arch/mips/isa/formats/branch.isa +++ b/src/arch/mips/isa/formats/branch.isa @@ -89,7 +89,7 @@ output header {{ } } - Addr branchTarget(Addr branchPC) const; + MipsISA::PCState branchTarget(const MipsISA::PCState &branchPC) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; @@ -116,7 +116,7 @@ output header {{ { } - Addr branchTarget(ThreadContext *tc) const; + MipsISA::PCState branchTarget(ThreadContext *tc) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; @@ -124,17 +124,25 @@ output header {{ }}; output decoder {{ - Addr - Branch::branchTarget(Addr branchPC) const + MipsISA::PCState + Branch::branchTarget(const MipsISA::PCState &branchPC) const { - return branchPC + 4 + disp; + MipsISA::PCState target = branchPC; + target.advance(); + target.npc(branchPC.pc() + sizeof(MachInst) + disp); + target.nnpc(target.npc() + sizeof(MachInst)); + return target; } - Addr + MipsISA::PCState Jump::branchTarget(ThreadContext *tc) const { - Addr NPC = tc->readNextPC(); - return (NPC & 0xF0000000) | (disp); + MipsISA::PCState target = tc->pcState(); + Addr pc = target.pc(); + target.advance(); + target.npc((pc & 0xF0000000) | disp); + target.nnpc(target.npc() + sizeof(MachInst)); + return target; } const std::string & @@ -217,19 +225,16 @@ output decoder {{ }}; def format Branch(code, *opt_flags) {{ - not_taken_code = ' NNPC = NNPC;\n' - not_taken_code += '} \n' + not_taken_code = '' #Build Instruction Flags #Use Link & Likely Flags to Add Link/Condition Code inst_flags = ('IsDirectControl', ) for x in opt_flags: if x == 'Link': - code += 'R31 = NNPC;\n' + code += 'R31 = pc.nnpc();\n' elif x == 'Likely': - not_taken_code = ' NPC = NNPC;\n' - not_taken_code += ' NNPC = NNPC + 4;\n' - not_taken_code += '} \n' + not_taken_code = 'pc.advance();' inst_flags += ('IsCondDelaySlot', ) else: inst_flags += (x, ) @@ -241,11 +246,17 @@ def format Branch(code, *opt_flags) {{ inst_flags += ('IsCondControl', ) #Condition code - code = 'bool cond;\n' + code - code += 'if (cond) {\n' - code += ' NNPC = NPC + disp;\n' - code += '} else {\n' - code += not_taken_code + code = ''' + bool cond; + MipsISA::PCState pc = PCS; + %(code)s + if (cond) { + pc.nnpc(pc.npc() + disp); + } else { + %(not_taken_code)s + } + PCS = pc; + ''' % { "code" : code, "not_taken_code" : not_taken_code } iop = InstObjParams(name, Name, 'Branch', code, inst_flags) header_output = BasicDeclare.subst(iop) @@ -255,19 +266,16 @@ def format Branch(code, *opt_flags) {{ }}; def format DspBranch(code, *opt_flags) {{ - not_taken_code = ' NNPC = NNPC;\n' - not_taken_code += '} \n' + not_taken_code = '' #Build Instruction Flags #Use Link & Likely Flags to Add Link/Condition Code inst_flags = ('IsDirectControl', ) for x in opt_flags: if x == 'Link': - code += 'R31 = NNPC;\n' + code += 'R32 = pc.nnpc();' elif x == 'Likely': - not_taken_code = ' NPC = NNPC;\n' - not_taken_code += ' NNPC = NNPC + 4;\n' - not_taken_code += '} \n' + not_taken_code = 'pc.advance();' inst_flags += ('IsCondDelaySlot', ) else: inst_flags += (x, ) @@ -278,19 +286,19 @@ def format DspBranch(code, *opt_flags) {{ else: inst_flags += ('IsCondControl', ) - #Declaration code - decl_code = 'bool cond;\n' - decl_code += 'uint32_t dspctl;\n' - - #Fetch code - fetch_code = 'dspctl = DSPControl;\n' - #Condition code - code = decl_code + fetch_code + code - code += 'if (cond) {\n' - code += ' NNPC = NPC + disp;\n' - code += '} else {\n' - code += not_taken_code + code = ''' + MipsISA::PCState pc = PCS; + bool cond; + uint32_t dspctl = DSPControl; + %(code)s + if (cond) { + pc.nnpc(pc.npc() + disp); + } else { + %(not_taken_code)s + } + PCS = pc; + ''' % { "code" : code, "not_taken_code" : not_taken_code } iop = InstObjParams(name, Name, 'Branch', code, inst_flags) header_output = BasicDeclare.subst(iop) @@ -305,12 +313,18 @@ def format Jump(code, *opt_flags) {{ inst_flags = ('IsIndirectControl', 'IsUncondControl') for x in opt_flags: if x == 'Link': - code = 'R31 = NNPC;\n' + code + code = ''' + R31 = pc.nnpc(); + ''' + code elif x == 'ClearHazards': code += '/* Code Needed to Clear Execute & Inst Hazards */\n' else: inst_flags += (x, ) + code = ''' + MipsISA::PCState pc = PCS; + ''' + code + iop = InstObjParams(name, Name, 'Jump', code, inst_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) diff --git a/src/arch/mips/isa/includes.isa b/src/arch/mips/isa/includes.isa index 22eb3bf13..d5e1448ac 100644 --- a/src/arch/mips/isa/includes.isa +++ b/src/arch/mips/isa/includes.isa @@ -39,6 +39,7 @@ output header {{ #include <iomanip> #include "arch/mips/isa_traits.hh" +#include "arch/mips/types.hh" #include "cpu/static_inst.hh" #include "mem/packet.hh" }}; diff --git a/src/arch/mips/isa/operands.isa b/src/arch/mips/isa/operands.isa index 27cb4357a..1bb5ae5b3 100644 --- a/src/arch/mips/isa/operands.isa +++ b/src/arch/mips/isa/operands.isa @@ -151,6 +151,5 @@ def operands {{ 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), #Program Counter Operands - 'NPC': ('NPC', 'uw', None, 'IsControl', 4), - 'NNPC':('NNPC', 'uw', None, 'IsControl', 4) + 'PCS': ('PCState', 'uw', None, (None, None, 'IsControl'), 4) }}; diff --git a/src/arch/mips/mt.hh b/src/arch/mips/mt.hh index 7217c335e..3ec6cbe70 100755 --- a/src/arch/mips/mt.hh +++ b/src/arch/mips/mt.hh @@ -77,11 +77,12 @@ haltThread(TC *tc) // Save last known PC in TCRestart // @TODO: Needs to check if this is a branch and if so, // take previous instruction - tc->setMiscReg(MISCREG_TC_RESTART, tc->readNextPC()); + PCState pc = tc->pcState(); + tc->setMiscReg(MISCREG_TC_RESTART, pc.npc()); warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->threadId(), tc->getCpuPtr()->name(), - tc->readPC(), tc->readNextPC()); + pc.pc(), pc.npc()); } } @@ -91,17 +92,14 @@ restoreThread(TC *tc) { if (tc->status() != TC::Active) { // Restore PC from TCRestart - IntReg pc = tc->readMiscRegNoEffect(MISCREG_TC_RESTART); + Addr restartPC = tc->readMiscRegNoEffect(MISCREG_TC_RESTART); // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY - tc->setPC(pc); - tc->setNextPC(pc + 4); - tc->setNextNPC(pc + 8); + tc->pcState(restartPC); tc->activate(0); warn("%i: Restoring thread %i in %s @ PC %x", - curTick, tc->threadId(), tc->getCpuPtr()->name(), - tc->readPC()); + curTick, tc->threadId(), tc->getCpuPtr()->name(), restartPC); } } diff --git a/src/arch/mips/predecoder.hh b/src/arch/mips/predecoder.hh index c20fe1f5f..f059710e5 100644 --- a/src/arch/mips/predecoder.hh +++ b/src/arch/mips/predecoder.hh @@ -75,7 +75,7 @@ class Predecoder //Use this to give data to the predecoder. This should be used //when there is control flow. void - moreBytes(Addr pc, Addr fetchPC, MachInst inst) + moreBytes(const PCState &pc, Addr fetchPC, MachInst inst) { emi = inst; } @@ -94,7 +94,7 @@ class Predecoder //This returns a constant reference to the ExtMachInst to avoid a copy const ExtMachInst & - getExtMachInst() + getExtMachInst(PCState &pc) { return emi; } diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc index fa3e3bff9..26a2a0ddb 100644 --- a/src/arch/mips/process.cc +++ b/src/arch/mips/process.cc @@ -176,10 +176,7 @@ MipsLiveProcess::argsInit(int pageSize) setSyscallArg(tc, 1, argv_array_base); tc->setIntReg(StackPointerReg, stack_min); - Addr prog_entry = objFile->entryPoint(); - tc->setPC(prog_entry); - tc->setNextPC(prog_entry + sizeof(MachInst)); - tc->setNextNPC(prog_entry + (2 * sizeof(MachInst))); + tc->pcState(objFile->entryPoint()); } diff --git a/src/arch/mips/types.hh b/src/arch/mips/types.hh index c7ef6afe1..f21db51b1 100644 --- a/src/arch/mips/types.hh +++ b/src/arch/mips/types.hh @@ -31,6 +31,7 @@ #ifndef __ARCH_MIPS_TYPES_HH__ #define __ARCH_MIPS_TYPES_HH__ +#include "arch/generic/types.hh" #include "base/types.hh" namespace MipsISA @@ -39,6 +40,8 @@ namespace MipsISA typedef uint32_t MachInst; typedef uint64_t ExtMachInst; +typedef GenericISA::DelaySlotPCState<MachInst> PCState; + typedef uint64_t LargestRead; //used in FP convert & round function diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc index faae1e937..0859eb80f 100644 --- a/src/arch/mips/utility.cc +++ b/src/arch/mips/utility.cc @@ -267,10 +267,9 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest) void skipFunction(ThreadContext *tc) { - Addr newpc = tc->readIntReg(ReturnAddressReg); - tc->setPC(newpc); - tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst)); - tc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst)); + TheISA::PCState newPC = tc->pcState(); + newPC.set(tc->readIntReg(ReturnAddressReg)); + tc->pcState(newPC); } diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh index bc50027c0..2f6726c59 100644 --- a/src/arch/mips/utility.hh +++ b/src/arch/mips/utility.hh @@ -39,12 +39,22 @@ #include "base/misc.hh" #include "base/types.hh" #include "config/full_system.hh" +#include "cpu/static_inst.hh" #include "cpu/thread_context.hh" class ThreadContext; namespace MipsISA { +inline PCState +buildRetPC(const PCState &curPC, const PCState &callPC) +{ + PCState ret = callPC; + ret.advance(); + ret.pc(curPC.npc()); + return ret; +} + uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp); //////////////////////////////////////////////////////////////////////// @@ -105,6 +115,12 @@ void copyMiscRegs(ThreadContext *src, ThreadContext *dest); void skipFunction(ThreadContext *tc); +inline void +advancePC(PCState &pc, const StaticInstPtr inst) +{ + pc.advance(); +} + }; diff --git a/src/arch/power/insts/branch.cc b/src/arch/power/insts/branch.cc index c10f7c996..352c4ea57 100644 --- a/src/arch/power/insts/branch.cc +++ b/src/arch/power/insts/branch.cc @@ -52,10 +52,10 @@ PCDependentDisassembly::disassemble(Addr pc, const SymbolTable *symtab) const return *cachedDisassembly; } -Addr -BranchPCRel::branchTarget(Addr pc) const +PowerISA::PCState +BranchPCRel::branchTarget(const PowerISA::PCState &pc) const { - return (uint32_t)(pc + disp); + return (uint32_t)(pc.pc() + disp); } std::string @@ -76,8 +76,8 @@ BranchPCRel::generateDisassembly(Addr pc, const SymbolTable *symtab) const return ss.str(); } -Addr -BranchNonPCRel::branchTarget(Addr pc) const +PowerISA::PCState +BranchNonPCRel::branchTarget(const PowerISA::PCState &pc) const { return targetAddr; } @@ -98,10 +98,10 @@ BranchNonPCRel::generateDisassembly(Addr pc, const SymbolTable *symtab) const return ss.str(); } -Addr -BranchPCRelCond::branchTarget(Addr pc) const +PowerISA::PCState +BranchPCRelCond::branchTarget(const PowerISA::PCState &pc) const { - return (uint32_t)(pc + disp); + return (uint32_t)(pc.pc() + disp); } std::string @@ -124,8 +124,8 @@ BranchPCRelCond::generateDisassembly(Addr pc, const SymbolTable *symtab) const return ss.str(); } -Addr -BranchNonPCRelCond::branchTarget(Addr pc) const +PowerISA::PCState +BranchNonPCRelCond::branchTarget(const PowerISA::PCState &pc) const { return targetAddr; } @@ -149,11 +149,11 @@ BranchNonPCRelCond::generateDisassembly(Addr pc, return ss.str(); } -Addr +PowerISA::PCState BranchRegCond::branchTarget(ThreadContext *tc) const { uint32_t regVal = tc->readIntReg(_srcRegIdx[_numSrcRegs - 1]); - return (regVal & 0xfffffffc); + return regVal & 0xfffffffc; } std::string diff --git a/src/arch/power/insts/branch.hh b/src/arch/power/insts/branch.hh index dd00e42c3..7b9e78dee 100644 --- a/src/arch/power/insts/branch.hh +++ b/src/arch/power/insts/branch.hh @@ -86,7 +86,7 @@ class BranchPCRel : public PCDependentDisassembly } } - Addr branchTarget(Addr pc) const; + PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; @@ -112,7 +112,7 @@ class BranchNonPCRel : public PCDependentDisassembly } } - Addr branchTarget(Addr pc) const; + PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; @@ -187,7 +187,7 @@ class BranchPCRelCond : public BranchCond } } - Addr branchTarget(Addr pc) const; + PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; @@ -213,7 +213,7 @@ class BranchNonPCRelCond : public BranchCond } } - Addr branchTarget(Addr pc) const; + PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; @@ -231,7 +231,7 @@ class BranchRegCond : public BranchCond { } - Addr branchTarget(ThreadContext *tc) const; + PowerISA::PCState branchTarget(ThreadContext *tc) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; diff --git a/src/arch/power/insts/static_inst.hh b/src/arch/power/insts/static_inst.hh index 399e75371..91eca6fb0 100644 --- a/src/arch/power/insts/static_inst.hh +++ b/src/arch/power/insts/static_inst.hh @@ -63,6 +63,12 @@ class PowerStaticInst : public StaticInst std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + void + advancePC(PowerISA::PCState &pcState) const + { + pcState.advance(); + } }; } // PowerISA namespace diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index 3252ff14a..671f57389 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -381,12 +381,20 @@ decode OPCODE default Unknown::unknown() { // Conditionally branch relative to PC based on CR and CTR. format BranchPCRelCondCtr { - 0: bc({{ NPC = PC + disp; }}); + 0: bc({{ + PowerISA::PCState pc = PCS; + pc.npc((uint32_t)(pc.pc() + disp)); + PCS = pc; + }}); } // Conditionally branch to fixed address based on CR and CTR. format BranchNonPCRelCondCtr { - 1: bca({{ NPC = targetAddr; }}); + 1: bca({{ + PowerISA::PCState pc = PCS; + pc.npc(targetAddr); + PCS = pc; + }}); } } @@ -394,12 +402,20 @@ decode OPCODE default Unknown::unknown() { // Unconditionally branch relative to PC. format BranchPCRel { - 0: b({{ NPC = PC + disp; }}); + 0: b({{ + PowerISA::PCState pc = PCS; + pc.npc((uint32_t)(pc.pc() + disp)); + PCS = pc; + }}); } // Unconditionally branch to fixed address. format BranchNonPCRel { - 1: ba({{ NPC = targetAddr; }}); + 1: ba({{ + PowerISA::PCState pc = PCS; + pc.npc(targetAddr); + PCS = pc; + }}); } } @@ -407,12 +423,20 @@ decode OPCODE default Unknown::unknown() { // Conditionally branch to address in LR based on CR and CTR. format BranchLrCondCtr { - 16: bclr({{ NPC = LR & 0xfffffffc; }}); + 16: bclr({{ + PowerISA::PCState pc = PCS; + pc.npc(LR & 0xfffffffc); + PCS = pc; + }}); } // Conditionally branch to address in CTR based on CR. format BranchCtrCond { - 528: bcctr({{ NPC = CTR & 0xfffffffc; }}); + 528: bcctr({{ + PowerISA::PCState pc = PCS; + pc.npc(CTR & 0xfffffffc); + PCS = pc; + }}); } // Condition register manipulation instructions. diff --git a/src/arch/power/isa/formats/branch.isa b/src/arch/power/isa/formats/branch.isa index d51ed5c25..da1579ea8 100644 --- a/src/arch/power/isa/formats/branch.isa +++ b/src/arch/power/isa/formats/branch.isa @@ -48,7 +48,7 @@ let {{ # Simple code to update link register (LR). -updateLrCode = 'LR = PC + 4;' +updateLrCode = 'PowerISA::PCState lrpc = PCS; LR = lrpc.pc() + 4;' }}; @@ -105,7 +105,7 @@ def GetCondCode(br_code): cond_code = 'if(condOk(CR)) {\n' cond_code += ' ' + br_code + '\n' cond_code += '} else {\n' - cond_code += ' NPC = NPC;\n' + cond_code += ' PCS = PCS;\n' cond_code += '}\n' return cond_code @@ -119,7 +119,7 @@ def GetCtrCondCode(br_code): cond_code += 'if(ctr_ok && cond_ok) {\n' cond_code += ' ' + br_code + '\n' cond_code += '} else {\n' - cond_code += ' NPC = NPC;\n' + cond_code += ' PCS = PCS;\n' cond_code += '}\n' cond_code += 'CTR = ctr;\n' return cond_code diff --git a/src/arch/power/isa/formats/unknown.isa b/src/arch/power/isa/formats/unknown.isa index 06e6ece26..8914cf9a6 100644 --- a/src/arch/power/isa/formats/unknown.isa +++ b/src/arch/power/isa/formats/unknown.isa @@ -76,7 +76,7 @@ output exec {{ { panic("attempt to execute unknown instruction at %#x" "(inst 0x%08x, opcode 0x%x, binary: %s)", - xc->readPC(), machInst, OPCODE, inst2string(machInst)); + xc->pcState().pc(), machInst, OPCODE, inst2string(machInst)); return new UnimplementedOpcodeFault; } }}; diff --git a/src/arch/power/isa/operands.isa b/src/arch/power/isa/operands.isa index fc6c32685..908e6e0e7 100644 --- a/src/arch/power/isa/operands.isa +++ b/src/arch/power/isa/operands.isa @@ -59,8 +59,7 @@ def operands {{ 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 8), # Program counter and next - 'PC': ('PC', 'uw', None, (None, None, 'IsControl'), 9), - 'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 9), + 'PCS': ('PCState', 'uq', None, (None, None, 'IsControl'), 9), # Control registers 'CR': ('IntReg', 'uw', 'INTREG_CR', 'IsInteger', 9), diff --git a/src/arch/power/predecoder.hh b/src/arch/power/predecoder.hh index 1f3ac41cb..b1f2b6e38 100644 --- a/src/arch/power/predecoder.hh +++ b/src/arch/power/predecoder.hh @@ -83,7 +83,7 @@ class Predecoder // Use this to give data to the predecoder. This should be used // when there is control flow. void - moreBytes(Addr pc, Addr fetchPC, MachInst inst) + moreBytes(const PCState &pc, Addr fetchPC, MachInst inst) { emi = inst; } @@ -110,7 +110,7 @@ class Predecoder // This returns a constant reference to the ExtMachInst to avoid a copy const ExtMachInst & - getExtMachInst() + getExtMachInst(PCState &pcState) { return emi; } diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc index 9fb69b9f8..a34a874bc 100644 --- a/src/arch/power/process.cc +++ b/src/arch/power/process.cc @@ -256,9 +256,7 @@ PowerLiveProcess::argsInit(int intSize, int pageSize) //Set the stack pointer register tc->setIntReg(StackPointerReg, stack_min); - Addr prog_entry = objFile->entryPoint(); - tc->setPC(prog_entry); - tc->setNextPC(prog_entry + sizeof(MachInst)); + tc->pcState(objFile->entryPoint()); //Align the "stack_min" to a page boundary. stack_min = roundDown(stack_min, pageSize); diff --git a/src/arch/power/types.hh b/src/arch/power/types.hh index 6a8d1e9d3..d049cdec1 100644 --- a/src/arch/power/types.hh +++ b/src/arch/power/types.hh @@ -31,6 +31,7 @@ #ifndef __ARCH_POWER_TYPES_HH__ #define __ARCH_POWER_TYPES_HH__ +#include "arch/generic/types.hh" #include "base/bitunion.hh" #include "base/hashmap.hh" #include "base/types.hh" @@ -78,6 +79,8 @@ BitUnion32(ExtMachInst) Bitfield<19, 12> fxm; EndBitUnion(ExtMachInst) +typedef GenericISA::SimplePCState<MachInst> PCState; + // typedef uint64_t LargestRead; // // Need to use 64 bits to make sure that read requests get handled properly diff --git a/src/arch/power/utility.cc b/src/arch/power/utility.cc index d48d4870a..399ec1f56 100644 --- a/src/arch/power/utility.cc +++ b/src/arch/power/utility.cc @@ -52,8 +52,7 @@ copyRegs(ThreadContext *src, ThreadContext *dest) copyMiscRegs(src, dest); // Lastly copy PC/NPC - dest->setPC(src->readPC()); - dest->setNextPC(src->readNextPC()); + dest->pcState(src->pcState()); } void diff --git a/src/arch/power/utility.hh b/src/arch/power/utility.hh index c8cd441ba..a47fcdc46 100644 --- a/src/arch/power/utility.hh +++ b/src/arch/power/utility.hh @@ -36,10 +36,19 @@ #define __ARCH_POWER_UTILITY_HH__ #include "base/types.hh" +#include "cpu/static_inst.hh" #include "cpu/thread_context.hh" namespace PowerISA { +inline PCState +buildRetPC(const PCState &curPC, const PCState &callPC) +{ + PCState retPC = callPC; + retPC.advance(); + return retPC; +} + /** * Function to ensure ISA semantics about 0 registers. * @param tc The thread context. @@ -63,6 +72,12 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest) void skipFunction(ThreadContext *tc); +inline void +advancePC(PCState &pc, const StaticInstPtr inst) +{ + pc.advance(); +} + } // PowerISA namespace #endif // __ARCH_POWER_UTILITY_HH__ diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index df0a283b9..28ee64321 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -307,15 +307,11 @@ void doREDFault(ThreadContext *tc, TrapType tt) //MiscReg CANSAVE = tc->readMiscRegNoEffect(MISCREG_CANSAVE); MiscReg CANSAVE = tc->readMiscRegNoEffect(NumIntArchRegs + 3); MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL); - MiscReg PC = tc->readPC(); - MiscReg NPC = tc->readNextPC(); + PCState pc = tc->pcState(); TL++; - if (bits(PSTATE, 3,3)) { - PC &= mask(32); - NPC &= mask(32); - } + Addr pcMask = bits(PSTATE, 3) ? mask(32) : mask(64); //set TSTATE.gl to gl replaceBits(TSTATE, 42, 40, GL); @@ -332,9 +328,9 @@ void doREDFault(ThreadContext *tc, TrapType tt) tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE); //set TPC to PC - tc->setMiscRegNoEffect(MISCREG_TPC, PC); + tc->setMiscRegNoEffect(MISCREG_TPC, pc.pc() & pcMask); //set TNPC to NPC - tc->setMiscRegNoEffect(MISCREG_TNPC, NPC); + tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask); //set HTSTATE.hpstate to hpstate tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE); @@ -394,18 +390,14 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) //MiscReg CANSAVE = tc->readMiscRegNoEffect(MISCREG_CANSAVE); MiscReg CANSAVE = tc->readIntReg(NumIntArchRegs + 3); MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL); - MiscReg PC = tc->readPC(); - MiscReg NPC = tc->readNextPC(); - - if (bits(PSTATE, 3,3)) { - PC &= mask(32); - NPC &= mask(32); - } + PCState pc = tc->pcState(); //Increment the trap level TL++; tc->setMiscRegNoEffect(MISCREG_TL, TL); + Addr pcMask = bits(PSTATE, 3) ? mask(32) : mask(64); + //Save off state //set TSTATE.gl to gl @@ -423,9 +415,9 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE); //set TPC to PC - tc->setMiscRegNoEffect(MISCREG_TPC, PC); + tc->setMiscRegNoEffect(MISCREG_TPC, pc.pc() & pcMask); //set TNPC to NPC - tc->setMiscRegNoEffect(MISCREG_TNPC, NPC); + tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask); //set HTSTATE.hpstate to hpstate tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE); @@ -479,7 +471,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) } } -void getREDVector(MiscReg TT, Addr & PC, Addr & NPC) +void getREDVector(MiscReg TT, Addr &PC, Addr &NPC) { //XXX The following constant might belong in a header file. const Addr RSTVAddr = 0xFFF0000000ULL; @@ -554,9 +546,13 @@ void SparcFaultBase::invoke(ThreadContext * tc, StaticInstPtr inst) getPrivVector(tc, PC, NPC, trapType(), tl+1); } - tc->setPC(PC); - tc->setNextPC(NPC); - tc->setNextNPC(NPC + sizeof(MachInst)); + PCState pc; + pc.pc(PC); + pc.npc(NPC); + pc.nnpc(NPC + sizeof(MachInst)); + pc.upc(0); + pc.nupc(1); + tc->pcState(pc); } void PowerOnReset::invoke(ThreadContext * tc, StaticInstPtr inst) @@ -593,9 +589,14 @@ void PowerOnReset::invoke(ThreadContext * tc, StaticInstPtr inst) Addr PC, NPC; getREDVector(trapType(), PC, NPC); - tc->setPC(PC); - tc->setNextPC(NPC); - tc->setNextNPC(NPC + sizeof(MachInst)); + + PCState pc; + pc.pc(PC); + pc.npc(NPC); + pc.nnpc(NPC + sizeof(MachInst)); + pc.upc(0); + pc.nupc(1); + tc->pcState(pc); //These registers are specified as "undefined" after a POR, and they //should have reasonable values after the miscregfile is reset @@ -664,10 +665,7 @@ void SpillNNormal::invoke(ThreadContext *tc, StaticInstPtr inst) assert(lp); //Then adjust the PC and NPC - Addr spillStart = lp->readSpillStart(); - tc->setPC(spillStart); - tc->setNextPC(spillStart + sizeof(MachInst)); - tc->setNextNPC(spillStart + 2*sizeof(MachInst)); + tc->pcState(lp->readSpillStart()); } void FillNNormal::invoke(ThreadContext *tc, StaticInstPtr inst) @@ -681,10 +679,7 @@ void FillNNormal::invoke(ThreadContext *tc, StaticInstPtr inst) assert(lp); //Then adjust the PC and NPC - Addr fillStart = lp->readFillStart(); - tc->setPC(fillStart); - tc->setNextPC(fillStart + sizeof(MachInst)); - tc->setNextNPC(fillStart + 2*sizeof(MachInst)); + tc->pcState(lp->readFillStart()); } void TrapInstruction::invoke(ThreadContext *tc, StaticInstPtr inst) @@ -702,9 +697,9 @@ void TrapInstruction::invoke(ThreadContext *tc, StaticInstPtr inst) //We need to explicitly advance the pc, since that's not done for us //on a faulting instruction - tc->setPC(tc->readNextPC()); - tc->setNextPC(tc->readNextNPC()); - tc->setNextNPC(tc->readNextNPC() + sizeof(MachInst)); + PCState pc = tc->pcState(); + pc.advance(); + tc->pcState(pc); } #endif diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa index ce063bcdc..c6055b3a3 100644 --- a/src/arch/sparc/isa/base.isa +++ b/src/arch/sparc/isa/base.isa @@ -111,6 +111,8 @@ output header {{ void printRegArray(std::ostream &os, const RegIndex indexArray[], int num) const; + + void advancePC(SparcISA::PCState &pcState) const; }; bool passesFpCondition(uint32_t fcc, uint32_t condition); @@ -261,6 +263,12 @@ output decoder {{ } void + SparcStaticInst::advancePC(SparcISA::PCState &pcState) const + { + pcState.advance(); + } + + void SparcStaticInst::printSrcReg(std::ostream &os, int reg) const { if(_numSrcRegs > reg) diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index b9b38b569..80b29398c 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -46,14 +46,18 @@ decode OP default Unknown::unknown() { //Branch Always 0x8: bpa(19, annul_code={{ - NPC = xc->readPC() + disp; - NNPC = NPC + 4; + SparcISA::PCState pc = PCS; + pc.npc(pc.pc() + disp); + pc.nnpc(pc.npc() + 4); + PCS = pc; }}); //Branch Never 0x0: bpn(19, {{;}}, annul_code={{ - NNPC = NPC + 8; - NPC = NPC + 4; + SparcISA::PCState pc = PCS; + pc.nnpc(pc.npc() + 8); + pc.npc(pc.npc() + 4); + PCS = pc; }}); default: decode BPCC { @@ -66,14 +70,18 @@ decode OP default Unknown::unknown() { //Branch Always 0x8: ba(22, annul_code={{ - NPC = xc->readPC() + disp; - NNPC = NPC + 4; + SparcISA::PCState pc = PCS; + pc.npc(pc.pc() + disp); + pc.nnpc(pc.npc() + 4); + PCS = pc; }}); //Branch Never 0x0: bn(22, {{;}}, annul_code={{ - NNPC = NPC + 8; - NPC = NPC + 4; + SparcISA::PCState pc = PCS; + pc.nnpc(pc.npc() + 8); + pc.npc(pc.npc() + 4); + PCS = pc; }}); default: bicc(22, test={{passesCondition(Ccr<3:0>, COND2)}}); } @@ -97,14 +105,18 @@ decode OP default Unknown::unknown() format BranchN { //Branch Always 0x8: fbpa(22, annul_code={{ - NPC = xc->readPC() + disp; - NNPC = NPC + 4; + SparcISA::PCState pc = PCS; + pc.npc(pc.pc() + disp); + pc.nnpc(pc.npc() + 4); + PCS = pc; }}); //Branch Never 0x0: fbpn(22, {{;}}, annul_code={{ - NNPC = NPC + 8; - NPC = NPC + 4; + SparcISA::PCState pc = PCS; + pc.nnpc(pc.npc() + 8); + pc.npc(pc.npc() + 4); + PCS = pc; }}); default: decode BPCC { 0x0: fbpfcc0(19, test= @@ -123,14 +135,18 @@ decode OP default Unknown::unknown() format BranchN { //Branch Always 0x8: fba(22, annul_code={{ - NPC = xc->readPC() + disp; - NNPC = NPC + 4; + SparcISA::PCState pc = PCS; + pc.npc(pc.pc() + disp); + pc.nnpc(pc.npc() + 4); + PCS = pc; }}); //Branch Never 0x0: fbn(22, {{;}}, annul_code={{ - NNPC = NPC + 8; - NPC = NPC + 4; + SparcISA::PCState pc = PCS; + pc.nnpc(pc.npc() + 8); + pc.npc(pc.npc() + 4); + PCS = pc; }}); default: fbfcc(22, test= {{passesFpCondition(Fsr<11:10>, COND2)}}); @@ -138,11 +154,13 @@ decode OP default Unknown::unknown() } } 0x1: BranchN::call(30, {{ + SparcISA::PCState pc = PCS; if (Pstate<3:>) - R15 = (xc->readPC())<31:0>; + R15 = (pc.pc())<31:0>; else - R15 = xc->readPC(); - NNPC = R15 + disp; + R15 = pc.pc(); + pc.nnpc(R15 + disp); + PCS = pc; }}); 0x2: decode OP3 { format IntOp { @@ -316,10 +334,12 @@ decode OP default Unknown::unknown() 0x03: NoPriv::rdasi({{Rd = Asi;}}); 0x04: Priv::rdtick({{Rd = Tick;}}, {{Tick<63:>}}); 0x05: NoPriv::rdpc({{ + SparcISA::PCState pc = PCS; if(Pstate<3:>) - Rd = (xc->readPC())<31:0>; + Rd = (pc.pc())<31:0>; else - Rd = xc->readPC();}}); + Rd = pc.pc(); + }}); 0x06: NoPriv::rdfprs({{ //Wait for all fpops to finish. Rd = Fprs; @@ -973,7 +993,8 @@ decode OP default Unknown::unknown() 0x51: m5break({{PseudoInst::debugbreak(xc->tcBase()); }}, IsNonSpeculative); 0x54: m5panic({{ - panic("M5 panic instruction called at pc=%#x.", xc->readPC()); + SparcISA::PCState pc = PCS; + panic("M5 panic instruction called at pc=%#x.", pc.pc()); }}, No_OpClass, IsNonSpeculative); } #endif @@ -985,11 +1006,13 @@ decode OP default Unknown::unknown() fault = new MemAddressNotAligned; else { + SparcISA::PCState pc = PCS; if (Pstate<3:>) - Rd = (xc->readPC())<31:0>; + Rd = (pc.pc())<31:0>; else - Rd = xc->readPC(); - NNPC = target; + Rd = pc.pc(); + pc.nnpc(target); + PCS = pc; } }}); 0x39: Branch::return({{ @@ -1010,7 +1033,9 @@ decode OP default Unknown::unknown() fault = new MemAddressNotAligned; else { - NNPC = target; + SparcISA::PCState pc = PCS; + pc.nnpc(target); + PCS = pc; Cwp = (Cwp - 1 + NWindows) % NWindows; Cansave = Cansave + 1; Canrestore = Canrestore - 1; @@ -1082,8 +1107,10 @@ decode OP default Unknown::unknown() Ccr = Tstate<39:32>; Gl = Tstate<42:40>; Hpstate = Htstate; - NPC = Tnpc; - NNPC = Tnpc + 4; + SparcISA::PCState pc = PCS; + pc.npc(Tnpc); + pc.nnpc(Tnpc + 4); + PCS = pc; Tl = Tl - 1; }}, checkTl=true); 0x1: Priv::retry({{ @@ -1093,8 +1120,10 @@ decode OP default Unknown::unknown() Ccr = Tstate<39:32>; Gl = Tstate<42:40>; Hpstate = Htstate; - NPC = Tpc; - NNPC = Tnpc; + SparcISA::PCState pc = PCS; + pc.npc(Tpc); + pc.nnpc(Tnpc); + PCS = pc; Tl = Tl - 1; }}, checkTl=true); } diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa index faaee8842..e62e0035a 100644 --- a/src/arch/sparc/isa/formats/branch.isa +++ b/src/arch/sparc/isa/formats/branch.isa @@ -193,7 +193,7 @@ def template JumpExecute {{ %(op_decl)s; %(op_rd)s; - NNPC = xc->readNextNPC(); + PCS = PCS; %(code)s; if(fault == NoFault) @@ -289,15 +289,24 @@ let {{ def doCondBranch(name, Name, base, cond, code, opt_flags): return doBranch(name, Name, base, cond, code, code, - 'NPC = NPC; NNPC = NNPC;', - 'NNPC = NPC + 8; NPC = NPC + 4', + 'PCS = PCS;', + ''' + SparcISA::PCState pc = PCS; + pc.nnpc(pc.npc() + 8); + pc.npc(pc.npc() + 4); + PCS = pc; + ''', opt_flags) def doUncondBranch(name, Name, base, code, annul_code, opt_flags): return doBranch(name, Name, base, "true", code, annul_code, ";", ";", opt_flags) - default_branch_code = "NNPC = xc->readPC() + disp;" + default_branch_code = ''' + SparcISA::PCState pc = PCS; + pc.nnpc(pc.pc() + disp); + PCS = pc; + ''' }}; // Format for branch instructions with n bit displacements: diff --git a/src/arch/sparc/isa/formats/micro.isa b/src/arch/sparc/isa/formats/micro.isa index c1d0c4f36..b5a53a68b 100644 --- a/src/arch/sparc/isa/formats/micro.isa +++ b/src/arch/sparc/isa/formats/micro.isa @@ -81,10 +81,11 @@ output header {{ StaticInstPtr * microops; - StaticInstPtr fetchMicroop(MicroPC microPC) + StaticInstPtr + fetchMicroop(MicroPC upc) const { - assert(microPC < numMicroops); - return microops[microPC]; + assert(upc < numMicroops); + return microops[upc]; } %(MacroExecute)s @@ -102,6 +103,15 @@ output header {{ { flags[IsMicroop] = true; } + + void + advancePC(SparcISA::PCState &pcState) const + { + if (flags[IsLastMicroop]) + pcState.uEnd(); + else + pcState.uAdvance(); + } }; class SparcDelayedMicroInst : public SparcMicroInst diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index a627a2e6f..8bf6450be 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -126,8 +126,7 @@ def operands {{ #'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12), 'Frs2_low': ('FloatReg', 'uw', 'dfprl(RS2)', 'IsFloating', 12), 'Frs2_high': ('FloatReg', 'uw', 'dfprh(RS2)', 'IsFloating', 12), - 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31), - 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32), + 'PCS': ('PCState', 'udw', None, (None, None, 'IsControl'), 30), # Registers which are used explicitly in instructions 'R0': ('IntReg', 'udw', '0', None, 6), 'R1': ('IntReg', 'udw', '1', None, 7), diff --git a/src/arch/sparc/nativetrace.cc b/src/arch/sparc/nativetrace.cc index 8a1eb7a58..9bccaaf7d 100644 --- a/src/arch/sparc/nativetrace.cc +++ b/src/arch/sparc/nativetrace.cc @@ -67,16 +67,17 @@ Trace::SparcNativeTrace::check(NativeTraceRecord *record) checkReg(*(regName++), regVal, realRegVal); } + SparcISA::PCState pc = tc->pcState(); // PC read(&realRegVal, sizeof(realRegVal)); realRegVal = SparcISA::gtoh(realRegVal); - regVal = tc->readNextPC(); + regVal = pc.npc(); checkReg("pc", regVal, realRegVal); // NPC read(&realRegVal, sizeof(realRegVal)); realRegVal = SparcISA::gtoh(realRegVal); - regVal = tc->readNextNPC(); + pc.nnpc(); checkReg("npc", regVal, realRegVal); // CCR diff --git a/src/arch/sparc/predecoder.hh b/src/arch/sparc/predecoder.hh index c4ab4fe79..8a2587929 100644 --- a/src/arch/sparc/predecoder.hh +++ b/src/arch/sparc/predecoder.hh @@ -72,7 +72,7 @@ namespace SparcISA //Use this to give data to the predecoder. This should be used //when there is control flow. - void moreBytes(Addr pc, Addr fetchPC, MachInst inst) + void moreBytes(const PCState &pc, Addr fetchPC, MachInst inst) { emi = inst; //The I bit, bit 13, is used to figure out where the ASI @@ -99,7 +99,7 @@ namespace SparcISA } //This returns a constant reference to the ExtMachInst to avoid a copy - const ExtMachInst & getExtMachInst() + const ExtMachInst & getExtMachInst(PCState &pcState) { return emi; } diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 0cd8889a9..a6e21977a 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -69,41 +69,39 @@ SparcLiveProcess::SparcLiveProcess(LiveProcessParams * params, void SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc) { + PCState pc = tc->pcState(); switch(trapNum) { case 0x01: //Software breakpoint - warn("Software breakpoint encountered at pc %#x.\n", tc->readPC()); + warn("Software breakpoint encountered at pc %#x.\n", pc.pc()); break; case 0x02: //Division by zero - warn("Software signaled a division by zero at pc %#x.\n", - tc->readPC()); + warn("Software signaled a division by zero at pc %#x.\n", pc.pc()); break; case 0x03: //Flush window trap flushWindows(tc); break; case 0x04: //Clean windows warn("Ignoring process request for clean register " - "windows at pc %#x.\n", tc->readPC()); + "windows at pc %#x.\n", pc.pc()); break; case 0x05: //Range check - warn("Software signaled a range check at pc %#x.\n", - tc->readPC()); + warn("Software signaled a range check at pc %#x.\n", pc.pc()); break; case 0x06: //Fix alignment warn("Ignoring process request for os assisted unaligned accesses " - "at pc %#x.\n", tc->readPC()); + "at pc %#x.\n", pc.pc()); break; case 0x07: //Integer overflow - warn("Software signaled an integer overflow at pc %#x.\n", - tc->readPC()); + warn("Software signaled an integer overflow at pc %#x.\n", pc.pc()); break; case 0x32: //Get integer condition codes warn("Ignoring process request to get the integer condition codes " - "at pc %#x.\n", tc->readPC()); + "at pc %#x.\n", pc.pc()); break; case 0x33: //Set integer condition codes warn("Ignoring process request to set the integer condition codes " - "at pc %#x.\n", tc->readPC()); + "at pc %#x.\n", pc.pc()); break; default: panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum); @@ -402,10 +400,7 @@ SparcLiveProcess::argsInit(int pageSize) // don't have anything like that, it should be set to 0. tc->setIntReg(1, 0); - Addr prog_entry = objFile->entryPoint(); - tc->setPC(prog_entry); - tc->setNextPC(prog_entry + sizeof(MachInst)); - tc->setNextNPC(prog_entry + (2 * sizeof(MachInst))); + tc->pcState(objFile->entryPoint()); //Align the "stack_min" to a page boundary. stack_min = roundDown(stack_min, pageSize); diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc index 4eea0c077..aea40ea22 100644 --- a/src/arch/sparc/remote_gdb.cc +++ b/src/arch/sparc/remote_gdb.cc @@ -179,12 +179,14 @@ RemoteGDB::getregs() { memset(gdbregs.regs, 0, gdbregs.size); + PCState pc = context->pcState(); + if (context->readMiscReg(MISCREG_PSTATE) & PSTATE::am) { uint32_t *regs; regs = (uint32_t*)gdbregs.regs; - regs[Reg32Pc] = htobe((uint32_t)context->readPC()); - regs[Reg32Npc] = htobe((uint32_t)context->readNextPC()); + regs[Reg32Pc] = htobe((uint32_t)pc.pc()); + regs[Reg32Npc] = htobe((uint32_t)pc.npc()); for(int x = RegG0; x <= RegI0 + 7; x++) regs[x] = htobe((uint32_t)context->readIntReg(x - RegG0)); @@ -193,8 +195,8 @@ RemoteGDB::getregs() regs[Reg32Fsr] = htobe((uint32_t)context->readMiscReg(MISCREG_FSR)); regs[Reg32Csr] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 2)); } else { - gdbregs.regs[RegPc] = htobe(context->readPC()); - gdbregs.regs[RegNpc] = htobe(context->readNextPC()); + gdbregs.regs[RegPc] = htobe(pc.pc()); + gdbregs.regs[RegNpc] = htobe(pc.npc()); for(int x = RegG0; x <= RegI0 + 7; x++) gdbregs.regs[x] = htobe(context->readIntReg(x - RegG0)); @@ -224,8 +226,13 @@ RemoteGDB::getregs() void RemoteGDB::setregs() { - context->setPC(gdbregs.regs[RegPc]); - context->setNextPC(gdbregs.regs[RegNpc]); + PCState pc; + pc.pc(gdbregs.regs[RegPc]); + pc.npc(gdbregs.regs[RegNpc]); + pc.nnpc(pc.npc() + sizeof(MachInst)); + pc.upc(0); + pc.nupc(1); + context->pcState(pc); for(int x = RegG0; x <= RegI0 + 7; x++) context->setIntReg(x - RegG0, gdbregs.regs[x]); //Only the integer registers, pc and npc are set in netbsd @@ -241,6 +248,6 @@ RemoteGDB::clearSingleStep() void RemoteGDB::setSingleStep() { - nextBkpt = context->readNextPC(); + nextBkpt = context->pcState().npc(); setTempBreakpoint(nextBkpt); } diff --git a/src/arch/sparc/types.hh b/src/arch/sparc/types.hh index 70558ec6d..122fd808f 100644 --- a/src/arch/sparc/types.hh +++ b/src/arch/sparc/types.hh @@ -33,12 +33,15 @@ #include "base/bigint.hh" #include "base/types.hh" +#include "arch/generic/types.hh" namespace SparcISA { typedef uint32_t MachInst; typedef uint64_t ExtMachInst; + typedef GenericISA::DelaySlotUPCState<MachInst> PCState; + typedef Twin64_t LargestRead; struct CoreSpecific { diff --git a/src/arch/sparc/utility.cc b/src/arch/sparc/utility.cc index be4dfac84..6de44d8a3 100644 --- a/src/arch/sparc/utility.cc +++ b/src/arch/sparc/utility.cc @@ -213,20 +213,16 @@ copyRegs(ThreadContext *src, ThreadContext *dest) // Copy misc. registers copyMiscRegs(src, dest); - // Lastly copy PC/NPC - dest->setPC(src->readPC()); - dest->setNextPC(src->readNextPC()); - dest->setNextNPC(src->readNextNPC()); + dest->pcState(src->pcState()); } void skipFunction(ThreadContext *tc) { - Addr newpc = tc->readIntReg(ReturnAddressReg); - tc->setPC(newpc); - tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst)); - tc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst)); + TheISA::PCState newPC = tc->pcState(); + newPC.set(tc->readIntReg(ReturnAddressReg)); + tc->pcState(newPC); } diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index f6a585e23..0d5a4bb93 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -36,11 +36,22 @@ #include "arch/sparc/tlb.hh" #include "base/misc.hh" #include "base/bitfield.hh" +#include "cpu/static_inst.hh" #include "cpu/thread_context.hh" #include "sim/fault.hh" namespace SparcISA { + + inline PCState + buildRetPC(const PCState &curPC, const PCState &callPC) + { + PCState ret = callPC; + ret.uEnd(); + ret.pc(curPC.npc()); + return ret; + } + uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp); @@ -78,6 +89,12 @@ namespace SparcISA void skipFunction(ThreadContext *tc); + inline void + advancePC(PCState &pc, const StaticInstPtr inst) + { + inst->advancePC(pc); + } + } // namespace SparcISA #endif diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc index 4f2d97f90..7fb677c69 100644 --- a/src/arch/x86/faults.cc +++ b/src/arch/x86/faults.cc @@ -58,7 +58,8 @@ namespace X86ISA #if FULL_SYSTEM void X86FaultBase::invoke(ThreadContext * tc, StaticInstPtr inst) { - Addr pc = tc->readPC(); + PCState pcState = tc->pcState(); + Addr pc = pcState.pc(); DPRINTF(Faults, "RIP %#x: vector %d: %s\n", pc, vector, describe()); using namespace X86ISAInst::RomLabels; HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); @@ -86,8 +87,9 @@ namespace X86ISA assert(!isSoft()); tc->setIntReg(INTREG_MICRO(15), errorCode); } - tc->setMicroPC(romMicroPC(entry)); - tc->setNextMicroPC(romMicroPC(entry) + 1); + pcState.upc(romMicroPC(entry)); + pcState.nupc(romMicroPC(entry) + 1); + tc->pcState(pcState); } std::string @@ -106,9 +108,8 @@ namespace X86ISA { X86FaultBase::invoke(tc); // This is the same as a fault, but it happens -after- the instruction. - tc->setPC(tc->readNextPC()); - tc->setNextPC(tc->readNextNPC()); - tc->setNextNPC(tc->readNextNPC() + sizeof(MachInst)); + PCState pc = tc->pcState(); + pc.uEnd(); } void X86Abort::invoke(ThreadContext * tc, StaticInstPtr inst) @@ -207,9 +208,8 @@ namespace X86ISA tc->setMiscReg(MISCREG_CS_LIMIT, 0xffffffff); tc->setMiscReg(MISCREG_CS_ATTR, codeAttr); - tc->setPC(0x000000000000fff0ULL + - tc->readMiscReg(MISCREG_CS_BASE)); - tc->setNextPC(tc->readPC() + sizeof(MachInst)); + PCState pc(0x000000000000fff0ULL + tc->readMiscReg(MISCREG_CS_BASE)); + tc->pcState(pc); tc->setMiscReg(MISCREG_TSG_BASE, 0); tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff); @@ -243,8 +243,9 @@ namespace X86ISA // Update the handy M5 Reg. tc->setMiscReg(MISCREG_M5_REG, 0); MicroPC entry = X86ISAInst::RomLabels::extern_label_initIntHalt; - tc->setMicroPC(romMicroPC(entry)); - tc->setNextMicroPC(romMicroPC(entry) + 1); + pc.upc(romMicroPC(entry)); + pc.nupc(romMicroPC(entry) + 1); + tc->pcState(pc); } void @@ -263,8 +264,7 @@ namespace X86ISA // This has the base value pre-added. tc->setMiscReg(MISCREG_CS_LIMIT, 0xffff); - tc->setPC(tc->readMiscReg(MISCREG_CS_BASE)); - tc->setNextPC(tc->readPC() + sizeof(MachInst)); + tc->pcState(tc->readMiscReg(MISCREG_CS_BASE)); } #else diff --git a/src/arch/x86/insts/macroop.hh b/src/arch/x86/insts/macroop.hh index 7ead7bdc2..fcf051a37 100644 --- a/src/arch/x86/insts/macroop.hh +++ b/src/arch/x86/insts/macroop.hh @@ -73,7 +73,8 @@ class MacroopBase : public X86StaticInst StaticInstPtr * microops; - StaticInstPtr fetchMicroop(MicroPC microPC) + StaticInstPtr + fetchMicroop(MicroPC microPC) const { assert(microPC < numMicroops); return microops[microPC]; diff --git a/src/arch/x86/insts/microop.hh b/src/arch/x86/insts/microop.hh index 9b0497efc..6fc215452 100644 --- a/src/arch/x86/insts/microop.hh +++ b/src/arch/x86/insts/microop.hh @@ -114,6 +114,15 @@ namespace X86ISA } bool checkCondition(uint64_t flags, int condition) const; + + void + advancePC(PCState &pcState) const + { + if (flags[IsLastMicroop]) + pcState.uEnd(); + else + pcState.uAdvance(); + } }; } diff --git a/src/arch/x86/insts/static_inst.hh b/src/arch/x86/insts/static_inst.hh index 2df5df092..8813f216c 100644 --- a/src/arch/x86/insts/static_inst.hh +++ b/src/arch/x86/insts/static_inst.hh @@ -158,6 +158,12 @@ namespace X86ISA panic("Tried to pick with unrecognized size %d.\n", size); } } + + void + advancePC(PCState &pcState) const + { + pcState.advance(); + } }; } diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index de167d1c1..def9b7f9d 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -199,7 +199,7 @@ #endif 0x54: m5panic({{ panic("M5 panic instruction called at pc=%#x.\n", - xc->readPC()); + xc->pcState().pc()); }}, IsNonSpeculative); 0x55: m5reserved1({{ warn("M5 reserved opcode 1 ignored.\n"); diff --git a/src/arch/x86/isa/formats/unknown.isa b/src/arch/x86/isa/formats/unknown.isa index 11751e861..1108fd4a4 100644 --- a/src/arch/x86/isa/formats/unknown.isa +++ b/src/arch/x86/isa/formats/unknown.isa @@ -47,13 +47,13 @@ output header {{ /** * Class for Unknown/Illegal instructions */ - class Unknown : public StaticInst + class Unknown : public X86ISA::X86StaticInst { public: // Constructor Unknown(ExtMachInst _machInst) : - StaticInst("unknown", _machInst, No_OpClass) + X86ISA::X86StaticInst("unknown", _machInst, No_OpClass) { } diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 9ccea82dd..86ebac174 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -944,8 +944,12 @@ let {{ code = 'DoubleBits = psrc1 ^ op2;' class Wrip(WrRegOp, CondRegOp): - code = 'RIP = psrc1 + sop2 + CSBase' - else_code="RIP = RIP;" + code = ''' + X86ISA::PCState pc = PCS; + pc.npc(psrc1 + sop2 + CSBase); + PCS = pc; + ''' + else_code = "PCS = PCS;" class Wruflags(WrRegOp): code = 'ccFlagBits = psrc1 ^ op2' @@ -961,7 +965,10 @@ let {{ ''' class Rdip(RdRegOp): - code = 'DestReg = RIP - CSBase' + code = ''' + X86ISA::PCState pc = PCS; + DestReg = pc.npc() - CSBase; + ''' class Ruflags(RdRegOp): code = 'DestReg = ccFlagBits' diff --git a/src/arch/x86/isa/microops/seqop.isa b/src/arch/x86/isa/microops/seqop.isa index 57c44d48c..a3e22b0aa 100644 --- a/src/arch/x86/isa/microops/seqop.isa +++ b/src/arch/x86/isa/microops/seqop.isa @@ -169,15 +169,23 @@ let {{ return super(Eret, self).getAllocator(microFlags) iop = InstObjParams("br", "MicroBranchFlags", "SeqOpBase", - {"code": "nuIP = target", - "else_code": "nuIP = nuIP", + {"code": ''' + X86ISA::PCState pc = PCS; + pc.nupc(target); + PCS = pc; + ''', + "else_code": "PCS = PCS", "cond_test": "checkCondition(ccFlagBits, cc)"}) exec_output += SeqOpExecute.subst(iop) header_output += SeqOpDeclare.subst(iop) decoder_output += SeqOpConstructor.subst(iop) iop = InstObjParams("br", "MicroBranch", "SeqOpBase", - {"code": "nuIP = target", - "else_code": "nuIP = nuIP", + {"code": ''' + X86ISA::PCState pc = PCS; + pc.nupc(target); + PCS = pc; + ''', + "else_code": "PCS = PCS", "cond_test": "true"}) exec_output += SeqOpExecute.subst(iop) header_output += SeqOpDeclare.subst(iop) diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index d4140e414..25b73a8f2 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -97,9 +97,8 @@ def operands {{ 'FpSrcReg2': floatReg('src2', 21), 'FpDestReg': floatReg('dest', 22), 'FpData': floatReg('data', 23), - 'RIP': ('NPC', 'uqw', None, (None, None, 'IsControl'), 50), - 'uIP': ('UPC', 'uqw', None, (None, None, 'IsControl'), 51), - 'nuIP': ('NUPC', 'uqw', None, (None, None, 'IsControl'), 52), + 'PCS': ('PCState', 'udw', None, + (None, None, 'IsControl'), 50), # This holds the condition code portion of the flag register. The # nccFlagBits version holds the rest. 'ccFlagBits': intReg('INTREG_PSEUDO(0)', 60), diff --git a/src/arch/x86/nativetrace.cc b/src/arch/x86/nativetrace.cc index c5c891be9..6f92cfacf 100644 --- a/src/arch/x86/nativetrace.cc +++ b/src/arch/x86/nativetrace.cc @@ -85,7 +85,7 @@ X86NativeTrace::ThreadState::update(ThreadContext *tc) r13 = tc->readIntReg(X86ISA::INTREG_R13); r14 = tc->readIntReg(X86ISA::INTREG_R14); r15 = tc->readIntReg(X86ISA::INTREG_R15); - rip = tc->readNextPC(); + rip = tc->pcState().pc(); //This should be expanded if x87 registers are considered for (int i = 0; i < 8; i++) mmx[i] = tc->readFloatRegBits(X86ISA::FLOATREG_MMX(i)); diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh index 5b38402e0..c06ec18bc 100644 --- a/src/arch/x86/predecoder.hh +++ b/src/arch/x86/predecoder.hh @@ -188,11 +188,11 @@ namespace X86ISA //Use this to give data to the predecoder. This should be used //when there is control flow. - void moreBytes(Addr pc, Addr fetchPC, MachInst data) + void moreBytes(const PCState &pc, Addr fetchPC, MachInst data) { DPRINTF(Predecoder, "Getting more bytes.\n"); basePC = fetchPC; - offset = (fetchPC >= pc) ? 0 : pc - fetchPC; + offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC; fetchChunk = data; outOfBytes = false; process(); @@ -208,22 +208,26 @@ namespace X86ISA return emiIsReady; } + int + getInstSize() + { + int size = basePC + offset - origPC; + DPRINTF(Predecoder, + "Calculating the instruction size: " + "basePC: %#x offset: %#x origPC: %#x size: %d\n", + basePC, offset, origPC, size); + return size; + } + //This returns a constant reference to the ExtMachInst to avoid a copy - const ExtMachInst & getExtMachInst() + const ExtMachInst & + getExtMachInst(X86ISA::PCState &nextPC) { assert(emiIsReady); emiIsReady = false; + nextPC.npc(nextPC.pc() + getInstSize()); return emi; } - - int getInstSize() - { - DPRINTF(Predecoder, - "Calculating the instruction size: " - "basePC: %#x offset: %#x origPC: %#x\n", - basePC, offset, origPC); - return basePC + offset - origPC; - } }; }; diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 946a7cbe1..bb875686e 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -116,10 +116,12 @@ X86_64LiveProcess::X86_64LiveProcess(LiveProcessParams *params, void I386LiveProcess::syscall(int64_t callnum, ThreadContext *tc) { - Addr eip = tc->readPC(); + TheISA::PCState pc = tc->pcState(); + Addr eip = pc.pc(); if (eip >= vsyscallPage.base && eip < vsyscallPage.base + vsyscallPage.size) { - tc->setNextPC(vsyscallPage.base + vsyscallPage.vsysexitOffset); + pc.npc(vsyscallPage.base + vsyscallPage.vsysexitOffset); + tc->pcState(pc); } X86LiveProcess::syscall(callnum, tc); } @@ -645,11 +647,9 @@ X86LiveProcess::argsInit(int pageSize, //Set the stack pointer register tc->setIntReg(StackPointerReg, stack_min); - Addr prog_entry = objFile->entryPoint(); // There doesn't need to be any segment base added in since we're dealing // with the flat segmentation model. - tc->setPC(prog_entry); - tc->setNextPC(prog_entry + sizeof(MachInst)); + tc->pcState(objFile->entryPoint()); //Align the "stack_min" to a page boundary. stack_min = roundDown(stack_min, pageSize); diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc index ae47b14fd..3fc16e729 100644 --- a/src/arch/x86/system.cc +++ b/src/arch/x86/system.cc @@ -320,8 +320,7 @@ X86System::initState() cr0.pg = 1; tc->setMiscReg(MISCREG_CR0, cr0); - tc->setPC(tc->getSystemPtr()->kernelEntry); - tc->setNextPC(tc->readPC()); + tc->pcState(tc->getSystemPtr()->kernelEntry); // We should now be in long mode. Yay! diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 71e0b3adb..dbba52af0 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -609,7 +609,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation, #else DPRINTF(TLB, "Handling a TLB miss for " "address %#x at pc %#x.\n", - vaddr, tc->readPC()); + vaddr, tc->instAddr()); Process *p = tc->getProcessPtr(); TlbEntry newEntry; diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh index 2a0da7d65..5a208446a 100644 --- a/src/arch/x86/types.hh +++ b/src/arch/x86/types.hh @@ -42,6 +42,7 @@ #include <iostream> +#include "arch/generic/types.hh" #include "base/bitunion.hh" #include "base/cprintf.hh" #include "base/hashmap.hh" @@ -221,6 +222,8 @@ namespace X86ISA return true; } + typedef GenericISA::UPCState<MachInst> PCState; + struct CoreSpecific { int core_type; }; diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc index 624e8132f..88d5bfe58 100644 --- a/src/arch/x86/utility.cc +++ b/src/arch/x86/utility.cc @@ -72,8 +72,10 @@ void initCPU(ThreadContext *tc, int cpuId) InitInterrupt init(0); init.invoke(tc); - tc->setMicroPC(0); - tc->setNextMicroPC(1); + PCState pc = tc->pcState(); + pc.upc(0); + pc.nupc(1); + tc->pcState(pc); // These next two loops zero internal microcode and implicit registers. // They aren't specified by the ISA but are used internally by M5's @@ -231,8 +233,7 @@ copyRegs(ThreadContext *src, ThreadContext *dest) //copy float regs copyMiscRegs(src, dest); - dest->setPC(src->readPC()); - dest->setNextPC(src->readNextPC()); + dest->pcState(src->pcState()); } void diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh index 05ce53347..143fde00c 100644 --- a/src/arch/x86/utility.hh +++ b/src/arch/x86/utility.hh @@ -46,12 +46,22 @@ #include "base/misc.hh" #include "base/types.hh" #include "config/full_system.hh" +#include "cpu/static_inst.hh" #include "cpu/thread_context.hh" class ThreadContext; namespace X86ISA { + + inline PCState + buildRetPC(const PCState &curPC, const PCState &callPC) + { + PCState retPC = callPC; + retPC.uEnd(); + return retPC; + } + uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp); @@ -86,6 +96,12 @@ namespace X86ISA void copyMiscRegs(ThreadContext *src, ThreadContext *dest); void skipFunction(ThreadContext *tc); + + inline void + advancePC(PCState &pc, const StaticInstPtr inst) + { + inst->advancePC(pc); + } }; #endif // __ARCH_X86_UTILITY_HH__ diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index 68747b3d1..4a06ff307 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -645,8 +645,8 @@ BaseRemoteGDB::trap(int type) bufferSize = gdbregs.bytes() * 2 + 256; buffer = (char*)malloc(bufferSize); - DPRINTF(GDBMisc, "trap: PC=%#x NPC=%#x\n", - context->readPC(), context->readNextPC()); + TheISA::PCState pc = context->pcState(); + DPRINTF(GDBMisc, "trap: PC=%s\n", pc); clearSingleStep(); @@ -806,8 +806,7 @@ BaseRemoteGDB::trap(int type) subcmd = hex2i(&p); if (*p++ == ';') { val = hex2i(&p); - context->setPC(val); - context->setNextPC(val + sizeof(MachInst)); + context->pcState(val); } clearSingleStep(); goto out; @@ -815,8 +814,7 @@ BaseRemoteGDB::trap(int type) case GDBCont: if (p - data < (ptrdiff_t)datalen) { val = hex2i(&p); - context->setPC(val); - context->setNextPC(val + sizeof(MachInst)); + context->pcState(val); } clearSingleStep(); goto out; @@ -825,8 +823,7 @@ BaseRemoteGDB::trap(int type) subcmd = hex2i(&p); if (*p++ == ';') { val = hex2i(&p); - context->setPC(val); - context->setNextPC(val + sizeof(MachInst)); + context->pcState(val); } setSingleStep(); goto out; @@ -834,8 +831,7 @@ BaseRemoteGDB::trap(int type) case GDBStep: if (p - data < (ptrdiff_t)datalen) { val = hex2i(&p); - context->setPC(val); - context->setNextPC(val + sizeof(MachInst)); + context->pcState(val); } setSingleStep(); goto out; diff --git a/src/base/types.hh b/src/base/types.hh index 30b2d9258..5ce778572 100644 --- a/src/base/types.hh +++ b/src/base/types.hh @@ -67,6 +67,28 @@ const Tick MaxTick = LL(0x7fffffffffffffff); */ typedef uint64_t Addr; +typedef uint16_t MicroPC; + +static const MicroPC MicroPCRomBit = 1 << (sizeof(MicroPC) * 8 - 1); + +static inline MicroPC +romMicroPC(MicroPC upc) +{ + return upc | MicroPCRomBit; +} + +static inline MicroPC +normalMicroPC(MicroPC upc) +{ + return upc & ~MicroPCRomBit; +} + +static inline bool +isRomMicroPC(MicroPC upc) +{ + return MicroPCRomBit & upc; +} + const Addr MaxAddr = (Addr)-1; /** diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index e9b7daa4a..bc6f59407 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -38,6 +38,7 @@ #include <string> #include "arch/faults.hh" +#include "arch/utility.hh" #include "base/fast_alloc.hh" #include "base/trace.hh" #include "config/full_system.hh" @@ -241,36 +242,15 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Records changes to result? */ bool recordResult; - /** PC of this instruction. */ - Addr PC; - - /** Micro PC of this instruction. */ - Addr microPC; - /** Did this instruction execute, or is it predicated false */ bool predicate; protected: - /** Next non-speculative PC. It is not filled in at fetch, but rather - * once the target of the branch is truly known (either decode or - * execute). - */ - Addr nextPC; - - /** Next non-speculative NPC. Target PC for Mips or Sparc. */ - Addr nextNPC; + /** PC state for this instruction. */ + TheISA::PCState pc; - /** Next non-speculative micro PC. */ - Addr nextMicroPC; - - /** Predicted next PC. */ - Addr predPC; - - /** Predicted next NPC. */ - Addr predNPC; - - /** Predicted next microPC */ - Addr predMicroPC; + /** Predicted PC state after this instruction. */ + TheISA::PCState predPC; /** If this is a branch that was predicted taken */ bool predTaken; @@ -386,27 +366,23 @@ class BaseDynInst : public FastAlloc, public RefCounted } /** BaseDynInst constructor given a binary instruction. * @param staticInst A StaticInstPtr to the underlying instruction. - * @param PC The PC of the instruction. - * @param pred_PC The predicted next PC. - * @param pred_NPC The predicted next NPC. + * @param pc The PC state for the instruction. + * @param predPC The predicted next PC state for the instruction. * @param seq_num The sequence number of the instruction. * @param cpu Pointer to the instruction's CPU. */ - BaseDynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC, - Addr pred_PC, Addr pred_NPC, Addr pred_MicroPC, - InstSeqNum seq_num, ImplCPU *cpu); + BaseDynInst(StaticInstPtr staticInst, TheISA::PCState pc, + TheISA::PCState predPC, InstSeqNum seq_num, ImplCPU *cpu); /** BaseDynInst constructor given a binary instruction. * @param inst The binary instruction. - * @param PC The PC of the instruction. - * @param pred_PC The predicted next PC. - * @param pred_NPC The predicted next NPC. + * @param _pc The PC state for the instruction. + * @param _predPC The predicted next PC state for the instruction. * @param seq_num The sequence number of the instruction. * @param cpu Pointer to the instruction's CPU. */ - BaseDynInst(TheISA::ExtMachInst inst, Addr PC, Addr NPC, Addr microPC, - Addr pred_PC, Addr pred_NPC, Addr pred_MicroPC, - InstSeqNum seq_num, ImplCPU *cpu); + BaseDynInst(TheISA::ExtMachInst inst, TheISA::PCState pc, + TheISA::PCState predPC, InstSeqNum seq_num, ImplCPU *cpu); /** BaseDynInst constructor given a StaticInst pointer. * @param _staticInst The StaticInst for this BaseDynInst. @@ -443,45 +419,22 @@ class BaseDynInst : public FastAlloc, public RefCounted */ bool doneTargCalc() { return false; } - /** Returns the next PC. This could be the speculative next PC if it is - * called prior to the actual branch target being calculated. - */ - Addr readNextPC() { return nextPC; } - - /** Returns the next NPC. This could be the speculative next NPC if it is - * called prior to the actual branch target being calculated. - */ - Addr readNextNPC() - { -#if ISA_HAS_DELAY_SLOT - return nextNPC; -#else - return nextPC + sizeof(TheISA::MachInst); -#endif - } - - Addr readNextMicroPC() - { - return nextMicroPC; - } - /** Set the predicted target of this current instruction. */ - void setPredTarg(Addr predicted_PC, Addr predicted_NPC, - Addr predicted_MicroPC) + void setPredTarg(const TheISA::PCState &_predPC) { - predPC = predicted_PC; - predNPC = predicted_NPC; - predMicroPC = predicted_MicroPC; + predPC = _predPC; } + const TheISA::PCState &readPredTarg() { return predPC; } + /** Returns the predicted PC immediately after the branch. */ - Addr readPredPC() { return predPC; } + Addr predInstAddr() { return predPC.instAddr(); } /** Returns the predicted PC two instructions after the branch */ - Addr readPredNPC() { return predNPC; } + Addr predNextInstAddr() { return predPC.nextInstAddr(); } /** Returns the predicted micro PC after the branch */ - Addr readPredMicroPC() { return predMicroPC; } + Addr predMicroPC() { return predPC.microPC(); } /** Returns whether the instruction was predicted taken or not. */ bool readPredTaken() @@ -497,9 +450,9 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Returns whether the instruction mispredicted. */ bool mispredicted() { - return readPredPC() != readNextPC() || - readPredNPC() != readNextNPC() || - readPredMicroPC() != readNextMicroPC(); + TheISA::PCState tempPC = pc; + TheISA::advancePC(tempPC, staticInst); + return !(tempPC == predPC); } // @@ -576,7 +529,8 @@ class BaseDynInst : public FastAlloc, public RefCounted OpClass opClass() const { return staticInst->opClass(); } /** Returns the branch target address. */ - Addr branchTarget() const { return staticInst->branchTarget(PC); } + TheISA::PCState branchTarget() const + { return staticInst->branchTarget(pc); } /** Returns the number of source registers. */ int8_t numSrcRegs() const { return staticInst->numSrcRegs(); } @@ -773,30 +727,20 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Returns whether or not this instruction is squashed in the ROB. */ bool isSquashedInROB() const { return status[SquashedInROB]; } - /** Read the PC of this instruction. */ - const Addr readPC() const { return PC; } + /** Read the PC state of this instruction. */ + const TheISA::PCState pcState() const { return pc; } - /**Read the micro PC of this instruction. */ - const Addr readMicroPC() const { return microPC; } + /** Set the PC state of this instruction. */ + const void pcState(const TheISA::PCState &val) { pc = val; } - /** Set the next PC of this instruction (its actual target). */ - void setNextPC(Addr val) - { - nextPC = val; - } + /** Read the PC of this instruction. */ + const Addr instAddr() const { return pc.instAddr(); } - /** Set the next NPC of this instruction (the target in Mips or Sparc).*/ - void setNextNPC(Addr val) - { -#if ISA_HAS_DELAY_SLOT - nextNPC = val; -#endif - } + /** Read the PC of the next instruction. */ + const Addr nextInstAddr() const { return pc.nextInstAddr(); } - void setNextMicroPC(Addr val) - { - nextMicroPC = val; - } + /**Read the micro PC of this instruction. */ + const Addr microPC() const { return pc.microPC(); } bool readPredicate() { @@ -895,7 +839,7 @@ BaseDynInst<Impl>::readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags) { reqMade = true; - Request *req = new Request(asid, addr, size, flags, this->PC, + Request *req = new Request(asid, addr, size, flags, this->pc.instAddr(), thread->contextId(), threadNumber); Request *sreqLow = NULL; @@ -956,7 +900,7 @@ BaseDynInst<Impl>::writeBytes(uint8_t *data, unsigned size, } reqMade = true; - Request *req = new Request(asid, addr, size, flags, this->PC, + Request *req = new Request(asid, addr, size, flags, this->pc.instAddr(), thread->contextId(), threadNumber); Request *sreqLow = NULL; diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh index 4fb8490c1..923b204ce 100644 --- a/src/cpu/base_dyn_inst_impl.hh +++ b/src/cpu/base_dyn_inst_impl.hh @@ -62,32 +62,14 @@ my_hash_t thishash; template <class Impl> BaseDynInst<Impl>::BaseDynInst(StaticInstPtr _staticInst, - Addr inst_PC, Addr inst_NPC, - Addr inst_MicroPC, - Addr pred_PC, Addr pred_NPC, - Addr pred_MicroPC, + TheISA::PCState _pc, TheISA::PCState _predPC, InstSeqNum seq_num, ImplCPU *cpu) : staticInst(_staticInst), traceData(NULL), cpu(cpu) { seqNum = seq_num; - bool nextIsMicro = - staticInst->isMicroop() && !staticInst->isLastMicroop(); - - PC = inst_PC; - microPC = inst_MicroPC; - if (nextIsMicro) { - nextPC = inst_PC; - nextNPC = inst_NPC; - nextMicroPC = microPC + 1; - } else { - nextPC = inst_NPC; - nextNPC = nextPC + sizeof(TheISA::MachInst); - nextMicroPC = 0; - } - predPC = pred_PC; - predNPC = pred_NPC; - predMicroPC = pred_MicroPC; + pc = _pc; + predPC = _predPC; predTaken = false; initVars(); @@ -95,32 +77,14 @@ BaseDynInst<Impl>::BaseDynInst(StaticInstPtr _staticInst, template <class Impl> BaseDynInst<Impl>::BaseDynInst(TheISA::ExtMachInst inst, - Addr inst_PC, Addr inst_NPC, - Addr inst_MicroPC, - Addr pred_PC, Addr pred_NPC, - Addr pred_MicroPC, + TheISA::PCState _pc, TheISA::PCState _predPC, InstSeqNum seq_num, ImplCPU *cpu) - : staticInst(inst, inst_PC), traceData(NULL), cpu(cpu) + : staticInst(inst, _pc.instAddr()), traceData(NULL), cpu(cpu) { seqNum = seq_num; - bool nextIsMicro = - staticInst->isMicroop() && !staticInst->isLastMicroop(); - - PC = inst_PC; - microPC = inst_MicroPC; - if (nextIsMicro) { - nextPC = inst_PC; - nextNPC = inst_NPC; - nextMicroPC = microPC + 1; - } else { - nextPC = inst_NPC; - nextNPC = nextPC + sizeof(TheISA::MachInst); - nextMicroPC = 0; - } - predPC = pred_PC; - predNPC = pred_NPC; - predMicroPC = pred_MicroPC; + pc = _pc; + predPC = _predPC; predTaken = false; initVars(); @@ -301,8 +265,8 @@ template <class Impl> void BaseDynInst<Impl>::dump() { - cprintf("T%d : %#08d `", threadNumber, PC); - std::cout << staticInst->disassemble(PC); + cprintf("T%d : %#08d `", threadNumber, pc.instAddr()); + std::cout << staticInst->disassemble(pc.instAddr()); cprintf("'\n"); } @@ -311,8 +275,8 @@ void BaseDynInst<Impl>::dump(std::string &outstring) { std::ostringstream s; - s << "T" << threadNumber << " : 0x" << PC << " " - << staticInst->disassemble(PC); + s << "T" << threadNumber << " : 0x" << pc.instAddr() << " " + << staticInst->disassemble(pc.instAddr()); outstring = s.str(); } diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index a2f44106d..df5d8209b 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -241,13 +241,9 @@ class CheckerCPU : public BaseCPU result.integer = val; } - uint64_t readPC() { return thread->readPC(); } + uint64_t instAddr() { return thread->instAddr(); } - uint64_t readNextPC() { return thread->readNextPC(); } - - void setNextPC(uint64_t val) { - thread->setNextPC(val); - } + uint64_t nextInstAddr() { return thread->nextInstAddr(); } MiscReg readMiscRegNoEffect(int misc_reg) { diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 4bab778ba..f8b25ef73 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -72,10 +72,7 @@ Trace::ExeTracerRecord::traceInst(StaticInstPtr inst, bool ran) std::string sym_str; Addr sym_addr; - Addr cur_pc = PC; -#if THE_ISA == ARM_ISA - cur_pc &= ~PcModeMask; -#endif + Addr cur_pc = pc.instAddr(); if (debugSymbolTable && IsOn(ExecSymbol) #if FULL_SYSTEM @@ -85,13 +82,12 @@ Trace::ExeTracerRecord::traceInst(StaticInstPtr inst, bool ran) if (cur_pc != sym_addr) sym_str += csprintf("+%d",cur_pc - sym_addr); outs << "@" << sym_str; - } - else { + } else { outs << "0x" << hex << cur_pc; } if (inst->isMicroop()) { - outs << "." << setw(2) << dec << upc; + outs << "." << setw(2) << dec << pc.microPC(); } else { outs << " "; } diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh index 1982595eb..65950728b 100644 --- a/src/cpu/exetrace.hh +++ b/src/cpu/exetrace.hh @@ -47,10 +47,10 @@ class ExeTracerRecord : public InstRecord { public: ExeTracerRecord(Tick _when, ThreadContext *_thread, - const StaticInstPtr _staticInst, Addr _pc, bool spec, - const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0) + const StaticInstPtr _staticInst, TheISA::PCState _pc, + bool spec, const StaticInstPtr _macroStaticInst = NULL) : InstRecord(_when, _thread, _staticInst, _pc, spec, - _macroStaticInst, _upc) + _macroStaticInst) { } @@ -69,8 +69,8 @@ class ExeTracer : public InstTracer InstRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc, - const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0) + const StaticInstPtr staticInst, TheISA::PCState pc, + const StaticInstPtr macroStaticInst = NULL) { if (!IsOn(ExecEnable)) return NULL; @@ -82,7 +82,7 @@ class ExeTracer : public InstTracer return NULL; return new ExeTracerRecord(when, tc, - staticInst, pc, tc->misspeculating(), macroStaticInst, upc); + staticInst, pc, tc->misspeculating(), macroStaticInst); } }; diff --git a/src/cpu/inorder/comm.hh b/src/cpu/inorder/comm.hh index f1b3cacac..386046d1c 100644 --- a/src/cpu/inorder/comm.hh +++ b/src/cpu/inorder/comm.hh @@ -75,8 +75,8 @@ struct TimeStruct { // struct as it is used pretty frequently. bool branchMispredict; bool branchTaken; - uint64_t mispredPC; - uint64_t nextPC; + Addr mispredPC; + TheISA::PCState nextPC; unsigned branchCount; diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 5d42ba559..6cd938dc6 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -988,47 +988,6 @@ InOrderCPU::getPipeStage(int stage_num) } uint64_t -InOrderCPU::readPC(ThreadID tid) -{ - return PC[tid]; -} - - -void -InOrderCPU::setPC(Addr new_PC, ThreadID tid) -{ - PC[tid] = new_PC; -} - - -uint64_t -InOrderCPU::readNextPC(ThreadID tid) -{ - return nextPC[tid]; -} - - -void -InOrderCPU::setNextPC(uint64_t new_NPC, ThreadID tid) -{ - nextPC[tid] = new_NPC; -} - - -uint64_t -InOrderCPU::readNextNPC(ThreadID tid) -{ - return nextNPC[tid]; -} - - -void -InOrderCPU::setNextNPC(uint64_t new_NNPC, ThreadID tid) -{ - nextNPC[tid] = new_NNPC; -} - -uint64_t InOrderCPU::readIntReg(int reg_idx, ThreadID tid) { return intRegs[tid][reg_idx]; @@ -1156,15 +1115,12 @@ InOrderCPU::instDone(DynInstPtr inst, ThreadID tid) // Set the CPU's PCs - This contributes to the precise state of the CPU // which can be used when restoring a thread to the CPU after after any // type of context switching activity (fork, exception, etc.) - setPC(inst->readPC(), tid); - setNextPC(inst->readNextPC(), tid); - setNextNPC(inst->readNextNPC(), tid); + pcState(inst->pcState(), tid); if (inst->isControl()) { thread[tid]->lastGradIsBranch = true; - thread[tid]->lastBranchPC = inst->readPC(); - thread[tid]->lastBranchNextPC = inst->readNextPC(); - thread[tid]->lastBranchNextNPC = inst->readNextNPC(); + thread[tid]->lastBranchPC = inst->pcState(); + TheISA::advancePC(thread[tid]->lastBranchPC, inst->staticInst); } else { thread[tid]->lastGradIsBranch = false; } @@ -1236,15 +1192,15 @@ InOrderCPU::addToRemoveList(DynInstPtr &inst) { removeInstsThisCycle = true; if (!inst->isRemoveList()) { - DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %#x " + DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s " "[sn:%lli] to remove list\n", - inst->threadNumber, inst->readPC(), inst->seqNum); + inst->threadNumber, inst->pcState(), inst->seqNum); inst->setRemoveList(); removeList.push(inst->getInstListIt()); } else { - DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %#x " + DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %s " "[sn:%lli], already remove list\n", - inst->threadNumber, inst->readPC(), inst->seqNum); + inst->threadNumber, inst->pcState(), inst->seqNum); } } @@ -1252,23 +1208,23 @@ InOrderCPU::addToRemoveList(DynInstPtr &inst) void InOrderCPU::removeInst(DynInstPtr &inst) { - DPRINTF(InOrderCPU, "Removing graduated instruction [tid:%i] PC %#x " + DPRINTF(InOrderCPU, "Removing graduated instruction [tid:%i] PC %s " "[sn:%lli]\n", - inst->threadNumber, inst->readPC(), inst->seqNum); + inst->threadNumber, inst->pcState(), inst->seqNum); removeInstsThisCycle = true; // Remove the instruction. if (!inst->isRemoveList()) { - DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %#x " + DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s " "[sn:%lli] to remove list\n", - inst->threadNumber, inst->readPC(), inst->seqNum); + inst->threadNumber, inst->pcState(), inst->seqNum); inst->setRemoveList(); removeList.push(inst->getInstListIt()); } else { - DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %#x " + DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %s " "[sn:%lli], already on remove list\n", - inst->threadNumber, inst->readPC(), inst->seqNum); + inst->threadNumber, inst->pcState(), inst->seqNum); } } @@ -1307,24 +1263,24 @@ InOrderCPU::squashInstIt(const ListIt &instIt, ThreadID tid) { if ((*instIt)->threadNumber == tid) { DPRINTF(InOrderCPU, "Squashing instruction, " - "[tid:%i] [sn:%lli] PC %#x\n", + "[tid:%i] [sn:%lli] PC %s\n", (*instIt)->threadNumber, (*instIt)->seqNum, - (*instIt)->readPC()); + (*instIt)->pcState()); (*instIt)->setSquashed(); if (!(*instIt)->isRemoveList()) { - DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %#x " + DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s " "[sn:%lli] to remove list\n", - (*instIt)->threadNumber, (*instIt)->readPC(), + (*instIt)->threadNumber, (*instIt)->pcState(), (*instIt)->seqNum); (*instIt)->setRemoveList(); removeList.push(instIt); } else { DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i]" - " PC %#x [sn:%lli], already on remove list\n", - (*instIt)->threadNumber, (*instIt)->readPC(), + " PC %s [sn:%lli], already on remove list\n", + (*instIt)->threadNumber, (*instIt)->pcState(), (*instIt)->seqNum); } @@ -1338,10 +1294,10 @@ InOrderCPU::cleanUpRemovedInsts() { while (!removeList.empty()) { DPRINTF(InOrderCPU, "Removing instruction, " - "[tid:%i] [sn:%lli] PC %#x\n", + "[tid:%i] [sn:%lli] PC %s\n", (*removeList.front())->threadNumber, (*removeList.front())->seqNum, - (*removeList.front())->readPC()); + (*removeList.front())->pcState()); DynInstPtr inst = *removeList.front(); ThreadID tid = inst->threadNumber; @@ -1417,9 +1373,10 @@ InOrderCPU::dumpInsts() cprintf("Dumping Instruction List\n"); while (inst_list_it != instList[0].end()) { - cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" + cprintf("Instruction:%i\nPC:%s\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" "Squashed:%i\n\n", - num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, + num, (*inst_list_it)->pcState(), + (*inst_list_it)->threadNumber, (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), (*inst_list_it)->isSquashed()); inst_list_it++; diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index abe24d6ed..df6617d56 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -273,9 +273,7 @@ class InOrderCPU : public BaseCPU PipelineStage *pipelineStage[ThePipeline::NumStages]; /** Program Counters */ - TheISA::IntReg PC[ThePipeline::MaxThreads]; - TheISA::IntReg nextPC[ThePipeline::MaxThreads]; - TheISA::IntReg nextNPC[ThePipeline::MaxThreads]; + TheISA::PCState pc[ThePipeline::MaxThreads]; /** The Register File for the CPU */ union { @@ -471,22 +469,22 @@ class InOrderCPU : public BaseCPU ThreadID tid); /** Reads the commit PC of a specific thread. */ - uint64_t readPC(ThreadID tid); + TheISA::PCState + pcState(ThreadID tid) + { + return pc[tid]; + } /** Sets the commit PC of a specific thread. */ - void setPC(Addr new_PC, ThreadID tid); - - /** Reads the next PC of a specific thread. */ - uint64_t readNextPC(ThreadID tid); - - /** Sets the next PC of a specific thread. */ - void setNextPC(uint64_t val, ThreadID tid); - - /** Reads the next NPC of a specific thread. */ - uint64_t readNextNPC(ThreadID tid); + void + pcState(const TheISA::PCState &newPC, ThreadID tid) + { + pc[tid] = newPC; + } - /** Sets the next NPC of a specific thread. */ - void setNextNPC(uint64_t val, ThreadID tid); + Addr instAddr(ThreadID tid) { return pc[tid].instAddr(); } + Addr nextInstAddr(ThreadID tid) { return pc[tid].nextInstAddr(); } + MicroPC microPC(ThreadID tid) { return pc[tid].microPC(); } /** Function to add instruction onto the head of the list of the * instructions. Used when new instructions are fetched. diff --git a/src/cpu/inorder/first_stage.cc b/src/cpu/inorder/first_stage.cc index 658ce37d3..ae458c604 100644 --- a/src/cpu/inorder/first_stage.cc +++ b/src/cpu/inorder/first_stage.cc @@ -84,8 +84,8 @@ FirstStage::squash(InstSeqNum squash_seq_num, ThreadID tid) break; } DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] " - "PC %08p.\n", tid, insts[tid].front()->seqNum, - insts[tid].front()->PC); + "PC %s.\n", tid, insts[tid].front()->seqNum, + insts[tid].front()->pc); insts[tid].pop(); } diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc index 2465744e5..f672082f3 100644 --- a/src/cpu/inorder/inorder_dyn_inst.cc +++ b/src/cpu/inorder/inorder_dyn_inst.cc @@ -47,17 +47,16 @@ using namespace std; using namespace TheISA; using namespace ThePipeline; -InOrderDynInst::InOrderDynInst(TheISA::ExtMachInst machInst, Addr inst_PC, - Addr pred_PC, InstSeqNum seq_num, - InOrderCPU *cpu) - : staticInst(machInst, inst_PC), traceData(NULL), cpu(cpu) +InOrderDynInst::InOrderDynInst(TheISA::ExtMachInst machInst, + const TheISA::PCState &instPC, + const TheISA::PCState &_predPC, + InstSeqNum seq_num, InOrderCPU *cpu) + : staticInst(machInst, instPC.instAddr()), traceData(NULL), cpu(cpu) { seqNum = seq_num; - PC = inst_PC; - nextPC = PC + sizeof(MachInst); - nextNPC = nextPC + sizeof(MachInst); - predPC = pred_PC; + pc = instPC; + predPC = _predPC; initVars(); } @@ -94,7 +93,7 @@ int InOrderDynInst::instcount = 0; void InOrderDynInst::setMachInst(ExtMachInst machInst) { - staticInst = StaticInst::decode(machInst, PC); + staticInst = StaticInst::decode(machInst, pc.instAddr()); for (int i = 0; i < this->staticInst->numDestRegs(); i++) { _destRegIdx[i] = this->staticInst->destRegIdx(i); @@ -747,8 +746,8 @@ InOrderDynInst::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) void InOrderDynInst::dump() { - cprintf("T%d : %#08d `", threadNumber, PC); - cout << staticInst->disassemble(PC); + cprintf("T%d : %#08d `", threadNumber, pc.instAddr()); + cout << staticInst->disassemble(pc.instAddr()); cprintf("'\n"); } @@ -756,8 +755,8 @@ void InOrderDynInst::dump(std::string &outstring) { std::ostringstream s; - s << "T" << threadNumber << " : 0x" << PC << " " - << staticInst->disassemble(PC); + s << "T" << threadNumber << " : " << pc << " " + << staticInst->disassemble(pc.instAddr()); outstring = s.str(); } diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh index 0d42f4696..105e37657 100644 --- a/src/cpu/inorder/inorder_dyn_inst.hh +++ b/src/cpu/inorder/inorder_dyn_inst.hh @@ -41,6 +41,7 @@ #include "arch/isa_traits.hh" #include "arch/mt.hh" #include "arch/types.hh" +#include "arch/utility.hh" #include "base/fast_alloc.hh" #include "base/trace.hh" #include "base/types.hh" @@ -108,12 +109,13 @@ class InOrderDynInst : public FastAlloc, public RefCounted /** BaseDynInst constructor given a binary instruction. * @param inst The binary instruction. * @param PC The PC of the instruction. - * @param pred_PC The predicted next PC. + * @param predPC The predicted next PC. * @param seq_num The sequence number of the instruction. * @param cpu Pointer to the instruction's CPU. */ - InOrderDynInst(ExtMachInst inst, Addr PC, Addr pred_PC, InstSeqNum seq_num, - InOrderCPU *cpu); + InOrderDynInst(ExtMachInst inst, const TheISA::PCState &PC, + const TheISA::PCState &predPC, InstSeqNum seq_num, + InOrderCPU *cpu); /** BaseDynInst constructor given a binary instruction. * @param seq_num The sequence number of the instruction. @@ -269,28 +271,10 @@ class InOrderDynInst : public FastAlloc, public RefCounted InstResult instResult[MaxInstDestRegs]; /** PC of this instruction. */ - Addr PC; - - /** Next non-speculative PC. It is not filled in at fetch, but rather - * once the target of the branch is truly known (either decode or - * execute). - */ - Addr nextPC; - - /** Next next non-speculative PC. It is not filled in at fetch, but rather - * once the target of the branch is truly known (either decode or - * execute). - */ - Addr nextNPC; + TheISA::PCState pc; /** Predicted next PC. */ - Addr predPC; - - /** Predicted next NPC. */ - Addr predNPC; - - /** Predicted next microPC */ - Addr predMicroPC; + TheISA::PCState predPC; /** Address to fetch from */ Addr fetchAddr; @@ -540,33 +524,14 @@ class InOrderDynInst : public FastAlloc, public RefCounted // //////////////////////////////////////////////////////////// /** Read the PC of this instruction. */ - const Addr readPC() const { return PC; } + const TheISA::PCState &pcState() const { return pc; } /** Sets the PC of this instruction. */ - void setPC(Addr pc) { PC = pc; } - - /** Returns the next PC. This could be the speculative next PC if it is - * called prior to the actual branch target being calculated. - */ - Addr readNextPC() { return nextPC; } + void pcState(const TheISA::PCState &_pc) { pc = _pc; } - /** Set the next PC of this instruction (its actual target). */ - void setNextPC(uint64_t val) { nextPC = val; } - - /** Returns the next NPC. This could be the speculative next NPC if it is - * called prior to the actual branch target being calculated. - */ - Addr readNextNPC() - { -#if ISA_HAS_DELAY_SLOT - return nextNPC; -#else - return nextPC + sizeof(TheISA::MachInst); -#endif - } - - /** Set the next PC of this instruction (its actual target). */ - void setNextNPC(uint64_t val) { nextNPC = val; } + const Addr instAddr() { return pc.instAddr(); } + const Addr nextInstAddr() { return pc.nextInstAddr(); } + const MicroPC microPC() { return pc.microPC(); } //////////////////////////////////////////////////////////// // @@ -574,38 +539,36 @@ class InOrderDynInst : public FastAlloc, public RefCounted // //////////////////////////////////////////////////////////// /** Set the predicted target of this current instruction. */ - void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; } + void setPredTarg(const TheISA::PCState &predictedPC) + { predPC = predictedPC; } /** Returns the predicted target of the branch. */ - Addr readPredTarg() { return predPC; } + TheISA::PCState readPredTarg() { return predPC; } /** Returns the predicted PC immediately after the branch. */ - Addr readPredPC() { return predPC; } + Addr predInstAddr() { return predPC.instAddr(); } /** Returns the predicted PC two instructions after the branch */ - Addr readPredNPC() { return predNPC; } + Addr predNextInstAddr() { return predPC.nextInstAddr(); } /** Returns the predicted micro PC after the branch */ - Addr readPredMicroPC() { return predMicroPC; } + Addr readPredMicroPC() { return predPC.microPC(); } /** Returns whether the instruction was predicted taken or not. */ bool predTaken() { return predictTaken; } /** Returns whether the instruction mispredicted. */ - bool mispredicted() + bool + mispredicted() { -#if ISA_HAS_DELAY_SLOT - return predPC != nextNPC; -#else - return predPC != nextPC; -#endif + TheISA::PCState nextPC = pc; + TheISA::advancePC(nextPC, staticInst); + return !(nextPC == predPC); } - /** Returns whether the instruction mispredicted. */ - bool mistargeted() { return predPC != nextNPC; } - /** Returns the branch target address. */ - Addr branchTarget() const { return staticInst->branchTarget(PC); } + TheISA::PCState branchTarget() const + { return staticInst->branchTarget(pc); } /** Checks whether or not this instruction has had its branch target * calculated yet. For now it is not utilized and is hacked to be diff --git a/src/cpu/inorder/inorder_trace.cc b/src/cpu/inorder/inorder_trace.cc index 90c94a4f5..70a947671 100644 --- a/src/cpu/inorder/inorder_trace.cc +++ b/src/cpu/inorder/inorder_trace.cc @@ -70,15 +70,15 @@ InOrderTrace::getInstRecord(unsigned num_stages, bool stage_tracing, if (!Trace::enabled) return NULL; - return new InOrderTraceRecord(num_stages, stage_tracing, tc); + return new InOrderTraceRecord(num_stages, stage_tracing, tc, 0); } InOrderTraceRecord * InOrderTrace::getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc, - const StaticInstPtr macroStaticInst, MicroPC upc) + const StaticInstPtr staticInst, TheISA::PCState _pc, + const StaticInstPtr macroStaticInst) { - return new InOrderTraceRecord(ThePipeline::NumStages, true, tc); + return new InOrderTraceRecord(ThePipeline::NumStages, true, tc, _pc); } /* namespace Trace */ } diff --git a/src/cpu/inorder/inorder_trace.hh b/src/cpu/inorder/inorder_trace.hh index ccc868f15..fd1427500 100644 --- a/src/cpu/inorder/inorder_trace.hh +++ b/src/cpu/inorder/inorder_trace.hh @@ -47,8 +47,8 @@ class InOrderTraceRecord : public ExeTracerRecord { public: InOrderTraceRecord(unsigned num_stages, bool _stage_tracing, - ThreadContext *_thread, bool spec = false) - : ExeTracerRecord(0, _thread, NULL, 0, spec) + ThreadContext *_thread, TheISA::PCState _pc, bool spec = false) + : ExeTracerRecord(0, _thread, NULL, _pc, spec) { stageTrace = _stage_tracing; stageCycle.resize(num_stages); @@ -75,7 +75,8 @@ class InOrderTraceRecord : public ExeTracerRecord { staticInst = _staticInst; } - void setPC(Addr _pc) { PC = _pc; } + + void setPC(TheISA::PCState _pc) { pc = _pc; } }; class InOrderTrace : public InstTracer @@ -87,9 +88,9 @@ class InOrderTrace : public InstTracer InOrderTraceRecord * getInstRecord(unsigned num_stages, bool stage_tracing, ThreadContext *tc); - virtual InOrderTraceRecord *getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc, - const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0); + InOrderTraceRecord *getInstRecord(Tick when, ThreadContext *tc, + const StaticInstPtr staticInst, TheISA::PCState pc, + const StaticInstPtr macroStaticInst = NULL); }; /* namespace Trace */ } diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc index f0b48d6f6..dc36965b0 100644 --- a/src/cpu/inorder/pipeline_stage.cc +++ b/src/cpu/inorder/pipeline_stage.cc @@ -350,27 +350,21 @@ PipelineStage::squashDueToBranch(DynInstPtr &inst, ThreadID tid) toPrevStages->stageInfo[stageNum][tid].squash = true; toPrevStages->stageInfo[stageNum][tid].nextPC = inst->readPredTarg(); + toPrevStages->stageInfo[stageNum][tid].branchTaken = + inst->pcState().branching(); #if ISA_HAS_DELAY_SLOT - toPrevStages->stageInfo[stageNum][tid].branchTaken = - inst->readNextNPC() != - (inst->readNextPC() + sizeof(TheISA::MachInst)); - - toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = + toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = inst->bdelaySeqNum; InstSeqNum squash_seq_num = inst->bdelaySeqNum; #else - toPrevStages->stageInfo[stageNum][tid].branchTaken = - inst->readNextPC() != - (inst->readPC() + sizeof(TheISA::MachInst)); - toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = inst->seqNum; InstSeqNum squash_seq_num = inst->seqNum; #endif DPRINTF(InOrderStage, "Target being re-set to %08p\n", - inst->readPredTarg()); + inst->predInstAddr()); DPRINTF(InOrderStage, "[tid:%i]: Squashing after [sn:%i], " "due to [sn:%i] branch.\n", tid, squash_seq_num, inst->seqNum); @@ -398,10 +392,10 @@ PipelineStage::squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid) prevStage->insts[i]->seqNum > squash_seq_num) { // Change Comment to Annulling previous instruction DPRINTF(InOrderStage, "[tid:%i]: Squashing instruction, " - "[sn:%i] PC %08p.\n", + "[sn:%i] PC %s.\n", tid, prevStage->insts[i]->seqNum, - prevStage->insts[i]->readPC()); + prevStage->insts[i]->pcState()); prevStage->insts[i]->setSquashed(); prevStage->insts[i] = cpu->dummyBufferInst; @@ -429,8 +423,8 @@ PipelineStage::squash(InstSeqNum squash_seq_num, ThreadID tid) break; } DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] " - " PC %08p.\n", tid, skidBuffer[tid].front()->seqNum, - skidBuffer[tid].front()->PC); + " PC %s.\n", tid, skidBuffer[tid].front()->seqNum, + skidBuffer[tid].front()->pc); skidBuffer[tid].pop(); } @@ -488,8 +482,8 @@ PipelineStage::skidInsert(ThreadID tid) assert(tid == inst->threadNumber); - DPRINTF(InOrderStage,"[tid:%i]: Inserting [sn:%lli] PC:%#x into stage " - "skidBuffer %i\n", tid, inst->seqNum, inst->readPC(), + DPRINTF(InOrderStage,"[tid:%i]: Inserting [sn:%lli] PC:%s into stage " + "skidBuffer %i\n", tid, inst->seqNum, inst->pcState(), inst->threadNumber); skidBuffer[tid].push(inst); @@ -571,9 +565,9 @@ PipelineStage::activateThread(ThreadID tid) } else { DynInstPtr inst = switchedOutBuffer[tid]; - DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%#x into" + DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%s into" " stage skidBuffer %i\n", tid, inst->seqNum, - inst->readPC(), inst->threadNumber); + inst->pcState(), inst->threadNumber); // Make instruction available for pipeline processing skidBuffer[tid].push(inst); @@ -895,13 +889,12 @@ PipelineStage::processInsts(ThreadID tid) inst = insts_to_stage.front(); DPRINTF(InOrderStage, "[tid:%u]: Processing instruction [sn:%lli] " - "with PC %#x\n", - tid, inst->seqNum, inst->readPC()); + "with PC %s\n", tid, inst->seqNum, inst->pcState()); if (inst->isSquashed()) { - DPRINTF(InOrderStage, "[tid:%u]: Instruction %i with PC %#x is " + DPRINTF(InOrderStage, "[tid:%u]: Instruction %i with PC %s is " "squashed, skipping.\n", - tid, inst->seqNum, inst->readPC()); + tid, inst->seqNum, inst->pcState()); insts_to_stage.pop(); @@ -1001,8 +994,8 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed) switchedOutValid[tid] = true; // Remove Thread From Pipeline & Resource Pool - inst->squashingStage = stageNum; - inst->bdelaySeqNum = inst->seqNum; + inst->squashingStage = stageNum; + inst->bdelaySeqNum = inst->seqNum; cpu->squashFromMemStall(inst, tid); // Switch On Cache Miss @@ -1038,9 +1031,9 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed) res_stage_num = inst->nextResStage(); } } else { - DPRINTF(InOrderStage, "[tid:%u]: Instruction [sn:%i] with PC %#x " + DPRINTF(InOrderStage, "[tid:%u]: Instruction [sn:%i] with PC %s " " needed no resources in stage %i.\n", - tid, inst->seqNum, inst->readPC(), stageNum); + tid, inst->seqNum, inst->pcState(), stageNum); } return last_req_completed; @@ -1134,8 +1127,8 @@ PipelineStage::dumpInsts() while (!copy_buff.empty()) { DynInstPtr inst = copy_buff.front(); - cprintf("Inst. PC:%#x\n[tid:%i]\n[sn:%i]\n\n", - inst->readPC(), inst->threadNumber, inst->seqNum); + cprintf("Inst. PC:%s\n[tid:%i]\n[sn:%i]\n\n", + inst->pcState(), inst->threadNumber, inst->seqNum); copy_buff.pop(); } diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh index c971e400e..6df104e6c 100644 --- a/src/cpu/inorder/pipeline_stage.hh +++ b/src/cpu/inorder/pipeline_stage.hh @@ -293,15 +293,15 @@ class PipelineStage /** SeqNum of Squashing Branch Delay Instruction (used for MIPS) */ Addr bdelayDoneSeqNum[ThePipeline::MaxThreads]; - /** Instruction used for squashing branch (used for MIPS) */ - DynInstPtr squashInst[ThePipeline::MaxThreads]; - /** Tells when their is a pending delay slot inst. to send * to rename. If there is, then wait squash after the next * instruction (used for MIPS). */ bool squashAfterDelaySlot[ThePipeline::MaxThreads]; + /** Instruction used for squashing branch (used for MIPS) */ + DynInstPtr squashInst[ThePipeline::MaxThreads]; + /** Maximum size of the inter-stage buffer connecting the previous stage to * this stage (which we call a skid buffer) */ unsigned stageBufferMax; diff --git a/src/cpu/inorder/resources/bpred_unit.cc b/src/cpu/inorder/resources/bpred_unit.cc index b08a393f7..310053409 100644 --- a/src/cpu/inorder/resources/bpred_unit.cc +++ b/src/cpu/inorder/resources/bpred_unit.cc @@ -31,6 +31,7 @@ #include <list> #include <vector> +#include "arch/utility.hh" #include "base/trace.hh" #include "base/traceflags.hh" #include "config/the_isa.hh" @@ -149,7 +150,7 @@ BPredUnit::takeOverFrom() bool -BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid) +BPredUnit::predict(DynInstPtr &inst, TheISA::PCState &predPC, ThreadID tid) { // See if branch predictor predicts taken. // If so, get its target addr either from the BTB or the RAS. @@ -160,12 +161,13 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid) int asid = inst->asid; bool pred_taken = false; - Addr target; + TheISA::PCState target; ++lookups; - DPRINTF(InOrderBPred, "[tid:%i] [sn:%i] %s ... PC%#x doing branch " + DPRINTF(InOrderBPred, "[tid:%i] [sn:%i] %s ... PC %s doing branch " "prediction\n", tid, inst->seqNum, - inst->staticInst->disassemble(inst->PC), inst->readPC()); + inst->staticInst->disassemble(inst->instAddr()), + inst->pcState()); void *bp_history = NULL; @@ -185,14 +187,14 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid) } else { ++condPredicted; - pred_taken = BPLookup(pred_PC, bp_history); + pred_taken = BPLookup(predPC.instAddr(), bp_history); DPRINTF(InOrderBPred, "[tid:%i]: Branch predictor predicted %i " - "for PC %#x\n", - tid, pred_taken, inst->readPC()); + "for PC %s\n", + tid, pred_taken, inst->pcState()); } - PredictorHistory predict_record(inst->seqNum, pred_PC, pred_taken, + PredictorHistory predict_record(inst->seqNum, predPC, pred_taken, bp_history, tid); // Now lookup in the BTB or RAS. @@ -202,40 +204,37 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid) // If it's a function return call, then look up the address // in the RAS. - target = RAS[tid].top(); + TheISA::PCState rasTop = RAS[tid].top(); + target = TheISA::buildRetPC(inst->pcState(), rasTop); // Record the top entry of the RAS, and its index. predict_record.usedRAS = true; predict_record.RASIndex = RAS[tid].topIdx(); - predict_record.RASTarget = target; + predict_record.rasTarget = rasTop; assert(predict_record.RASIndex < 16); RAS[tid].pop(); - DPRINTF(InOrderBPred, "[tid:%i]: Instruction %#x is a return, " - "RAS predicted target: %#x, RAS index: %i.\n", - tid, inst->readPC(), target, predict_record.RASIndex); + DPRINTF(InOrderBPred, "[tid:%i]: Instruction %s is a return, " + "RAS predicted target: %s, RAS index: %i.\n", + tid, inst->pcState(), target, + predict_record.RASIndex); } else { ++BTBLookups; if (inst->isCall()) { -#if ISA_HAS_DELAY_SLOT - Addr ras_pc = pred_PC + instSize; // Next Next PC -#else - Addr ras_pc = pred_PC; // Next PC -#endif - - RAS[tid].push(ras_pc); + RAS[tid].push(inst->pcState()); // Record that it was a call so that the top RAS entry can // be popped off if the speculation is incorrect. predict_record.wasCall = true; - DPRINTF(InOrderBPred, "[tid:%i]: Instruction %#x was a call" - ", adding %#x to the RAS index: %i.\n", - tid, inst->readPC(), ras_pc, RAS[tid].topIdx()); + DPRINTF(InOrderBPred, "[tid:%i]: Instruction %s was a call" + ", adding %s to the RAS index: %i.\n", + tid, inst->pcState(), predPC, + RAS[tid].topIdx()); } if (inst->isCall() && @@ -243,18 +242,18 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid) inst->isDirectCtrl()) { target = inst->branchTarget(); - DPRINTF(InOrderBPred, "[tid:%i]: Setting %#x predicted" - " target to %#x.\n", - tid, inst->readPC(), target); - } else if (BTB.valid(pred_PC, asid)) { + DPRINTF(InOrderBPred, "[tid:%i]: Setting %s predicted" + " target to %s.\n", + tid, inst->pcState(), target); + } else if (BTB.valid(predPC.instAddr(), asid)) { ++BTBHits; // If it's not a return, use the BTB to get the target addr. - target = BTB.lookup(pred_PC, asid); + target = BTB.lookup(predPC.instAddr(), asid); - DPRINTF(InOrderBPred, "[tid:%i]: [asid:%i] Instruction %#x " - "predicted target is %#x.\n", - tid, asid, inst->readPC(), target); + DPRINTF(InOrderBPred, "[tid:%i]: [asid:%i] Instruction %s " + "predicted target is %s.\n", + tid, asid, inst->pcState(), target); } else { DPRINTF(InOrderBPred, "[tid:%i]: BTB doesn't have a " "valid entry.\n",tid); @@ -265,14 +264,7 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid) if (pred_taken) { // Set the PC and the instruction's predicted target. - pred_PC = target; - } else { -#if ISA_HAS_DELAY_SLOT - // This value will be inst->PC + 4 (nextPC) - // Delay Slot archs need this to be inst->PC + 8 (nextNPC) - // so we increment one more time here. - pred_PC = pred_PC + instSize; -#endif + predPC = target; } predHist[tid].push_front(predict_record); @@ -296,7 +288,7 @@ BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid) while (!predHist[tid].empty() && predHist[tid].back().seqNum <= done_sn) { // Update the branch predictor with the correct results. - BPUpdate(predHist[tid].back().PC, + BPUpdate(predHist[tid].back().pc.instAddr(), predHist[tid].back().predTaken, predHist[tid].back().bpHistory); @@ -314,13 +306,13 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid, ThreadID asid) pred_hist.front().seqNum > squashed_sn) { if (pred_hist.front().usedRAS) { DPRINTF(InOrderBPred, "BranchPred: [tid:%i]: Restoring top of RAS " - "to: %i, target: %#x.\n", + "to: %i, target: %s.\n", tid, pred_hist.front().RASIndex, - pred_hist.front().RASTarget); + pred_hist.front().rasTarget); RAS[tid].restore(pred_hist.front().RASIndex, - pred_hist.front().RASTarget); + pred_hist.front().rasTarget); } else if (pred_hist.front().wasCall) { DPRINTF(InOrderBPred, "BranchPred: [tid:%i]: Removing speculative " @@ -340,7 +332,7 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid, ThreadID asid) void BPredUnit::squash(const InstSeqNum &squashed_sn, - const Addr &corr_target, + const TheISA::PCState &corrTarget, bool actually_taken, ThreadID tid, ThreadID asid) @@ -354,8 +346,8 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ++condIncorrect; DPRINTF(InOrderBPred, "[tid:%i]: Squashing from sequence number %i, " - "setting target to %#x.\n", - tid, squashed_sn, corr_target); + "setting target to %s.\n", + tid, squashed_sn, corrTarget); squash(squashed_sn, tid); @@ -380,13 +372,13 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ++RASIncorrect; } - BPUpdate((*hist_it).PC, actually_taken, + BPUpdate((*hist_it).pc.instAddr(), actually_taken, pred_hist.front().bpHistory); - BTB.update((*hist_it).PC, corr_target, asid); + BTB.update((*hist_it).pc.instAddr(), corrTarget, asid); DPRINTF(InOrderBPred, "[tid:%i]: Removing history for [sn:%i] " - "PC %#x.\n", tid, (*hist_it).seqNum, (*hist_it).PC); + "PC %s.\n", tid, (*hist_it).seqNum, (*hist_it).pc); pred_hist.erase(hist_it); @@ -424,7 +416,7 @@ BPredUnit::BPSquash(void *bp_history) bool -BPredUnit::BPLookup(Addr &inst_PC, void * &bp_history) +BPredUnit::BPLookup(Addr inst_PC, void * &bp_history) { if (predictor == Local) { return localBP->lookup(inst_PC, bp_history); @@ -437,7 +429,7 @@ BPredUnit::BPLookup(Addr &inst_PC, void * &bp_history) void -BPredUnit::BPUpdate(Addr &inst_PC, bool taken, void *bp_history) +BPredUnit::BPUpdate(Addr inst_PC, bool taken, void *bp_history) { if (predictor == Local) { localBP->update(inst_PC, taken, bp_history); diff --git a/src/cpu/inorder/resources/bpred_unit.hh b/src/cpu/inorder/resources/bpred_unit.hh index 881bfcc95..3b1c0f4ef 100644 --- a/src/cpu/inorder/resources/bpred_unit.hh +++ b/src/cpu/inorder/resources/bpred_unit.hh @@ -83,11 +83,12 @@ class BPredUnit * Predicts whether or not the instruction is a taken branch, and the * target of the branch if it is taken. * @param inst The branch instruction. - * @param pred_PC The predicted PC is passed back through this parameter. + * @param predPC The predicted PC is passed back through this parameter. * @param tid The thread id. * @return Returns if the branch is taken or not. */ - bool predict(ThePipeline::DynInstPtr &inst, Addr &pred_PC, ThreadID tid); + bool predict(ThePipeline::DynInstPtr &inst, + TheISA::PCState &predPC, ThreadID tid); // @todo: Rename this function. void BPUncond(void * &bp_history); @@ -114,12 +115,13 @@ class BPredUnit * corrects that sn's update with the proper address and taken/not taken. * @param squashed_sn The sequence number to squash any younger updates up * until. - * @param corr_target The correct branch target. + * @param corrTarget The correct branch target. * @param actually_taken The correct branch direction. * @param tid The thread id. */ - void squash(const InstSeqNum &squashed_sn, const Addr &corr_target, - bool actually_taken, ThreadID tid, ThreadID asid = 0); + void squash(const InstSeqNum &squashed_sn, + const TheISA::PCState &corrTarget, bool actually_taken, + ThreadID tid, ThreadID asid = 0); /** * @param bp_history Pointer to the history object. The predictor @@ -134,7 +136,7 @@ class BPredUnit * has the branch predictor state associated with the lookup. * @return Whether the branch is taken or not taken. */ - bool BPLookup(Addr &inst_PC, void * &bp_history); + bool BPLookup(Addr instPC, void * &bp_history); /** * Looks up a given PC in the BTB to see if a matching entry exists. @@ -149,26 +151,26 @@ class BPredUnit * @param inst_PC The PC to look up. * @return The address of the target of the branch. */ - Addr BTBLookup(Addr &inst_PC) - { return BTB.lookup(inst_PC, 0); } + TheISA::PCState BTBLookup(Addr instPC) + { return BTB.lookup(instPC, 0); } /** * Updates the BP with taken/not taken information. - * @param inst_PC The branch's PC that will be updated. + * @param instPC The branch's PC that will be updated. * @param taken Whether the branch was taken or not taken. * @param bp_history Pointer to the branch predictor state that is * associated with the branch lookup that is being updated. * @todo Make this update flexible enough to handle a global predictor. */ - void BPUpdate(Addr &inst_PC, bool taken, void *bp_history); + void BPUpdate(Addr instPC, bool taken, void *bp_history); /** * Updates the BTB with the target of a branch. * @param inst_PC The branch's PC that will be updated. * @param target_PC The branch's target that will be added to the BTB. */ - void BTBUpdate(Addr &inst_PC, Addr &target_PC) - { BTB.update(inst_PC, target_PC,0); } + void BTBUpdate(Addr instPC, const TheISA::PCState &targetPC) + { BTB.update(instPC, targetPC, 0); } void dump(); @@ -181,22 +183,22 @@ class BPredUnit * Makes a predictor history struct that contains any * information needed to update the predictor, BTB, and RAS. */ - PredictorHistory(const InstSeqNum &seq_num, const Addr &inst_PC, - bool pred_taken, void *bp_history, - ThreadID _tid) - : seqNum(seq_num), PC(inst_PC), RASTarget(0), - RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0), - wasCall(0), bpHistory(bp_history) - { } + PredictorHistory(const InstSeqNum &seq_num, + const TheISA::PCState &instPC, bool pred_taken, + void *bp_history, ThreadID _tid) + : seqNum(seq_num), pc(instPC), rasTarget(0), RASIndex(0), + tid(_tid), predTaken(pred_taken), usedRAS(0), wasCall(0), + bpHistory(bp_history) + {} /** The sequence number for the predictor history entry. */ InstSeqNum seqNum; /** The PC associated with the sequence number. */ - Addr PC; + TheISA::PCState pc; /** The RAS target (only valid if a return). */ - Addr RASTarget; + TheISA::PCState rasTarget; /** The RAS index of the instruction (only valid if a call). */ unsigned RASIndex; diff --git a/src/cpu/inorder/resources/branch_predictor.cc b/src/cpu/inorder/resources/branch_predictor.cc index b971d959a..33b67ce4a 100644 --- a/src/cpu/inorder/resources/branch_predictor.cc +++ b/src/cpu/inorder/resources/branch_predictor.cc @@ -84,41 +84,34 @@ BranchPredictor::execute(int slot_num) DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: squashed, " "skipping prediction \n", tid, inst->seqNum); } else { - Addr pred_PC = inst->readNextPC(); + TheISA::PCState predPC = inst->pcState(); + TheISA::advancePC(predPC, inst->staticInst); if (inst->isControl()) { // If not, the pred_PC be updated to pc+8 // If predicted, the pred_PC will be updated to new target // value - bool predict_taken = branchPred.predict(inst, pred_PC, tid); + bool predict_taken = branchPred.predict(inst, predPC, tid); if (predict_taken) { DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch " "predicted true.\n", tid, seq_num); - - inst->setPredTarg(pred_PC); - predictedTaken++; } else { DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch " "predicted false.\n", tid, seq_num); - - if (inst->isCondDelaySlot()) - { - inst->setPredTarg(inst->readPC() + (2 * instSize)); - } else { - inst->setPredTarg(pred_PC); - } - predictedNotTaken++; } + inst->setPredTarg(predPC); + inst->setBranchPred(predict_taken); DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Predicted PC is " - "%08p.\n", tid, seq_num, pred_PC); + "%s.\n", tid, seq_num, predPC); } else { + inst->setPredTarg(predPC); //DPRINTF(InOrderBPred, "[tid:%i]: Ignoring [sn:%i] " // "because this isn't " // "a control instruction.\n", tid, seq_num); @@ -166,10 +159,9 @@ BranchPredictor::squash(DynInstPtr inst, int squash_stage, squash_seq_num = squash_seq_num - 1; #endif - if(squash_stage>=ThePipeline::BackEndStartStage) { - Addr corr_targ=inst->readPredPC(); - bool taken=inst->predTaken(); - branchPred.squash(squash_seq_num,corr_targ,taken,tid); + if (squash_stage >= ThePipeline::BackEndStartStage) { + bool taken = inst->predTaken(); + branchPred.squash(squash_seq_num, inst->readPredTarg(), taken, tid); } else { branchPred.squash(squash_seq_num, tid); } diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index 73deacb12..e7f689ffa 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -392,15 +392,16 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size, unsigned slot_idx = cache_req->getSlot(); if (tlb_mode == TheISA::TLB::Execute) { - inst->fetchMemReq = new Request(inst->readTid(), aligned_addr, - acc_size, flags, inst->readPC(), - cpu->readCpuId(), inst->readTid()); - cache_req->memReq = inst->fetchMemReq; + inst->fetchMemReq = + new Request(inst->readTid(), aligned_addr, acc_size, flags, + inst->instAddr(), cpu->readCpuId(), inst->readTid()); + cache_req->memReq = inst->fetchMemReq; } else { if (!cache_req->is2ndSplit()) { - inst->dataMemReq = new Request(cpu->asid[tid], aligned_addr, - acc_size, flags, inst->readPC(), - cpu->readCpuId(), inst->readTid()); + inst->dataMemReq = + new Request(cpu->asid[tid], aligned_addr, acc_size, flags, + inst->instAddr(), cpu->readCpuId(), + inst->readTid()); cache_req->memReq = inst->dataMemReq; } else { assert(inst->splitInst); @@ -409,7 +410,7 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size, inst->split2ndAddr, acc_size, flags, - inst->readPC(), + inst->instAddr(), cpu->readCpuId(), tid); cache_req->memReq = inst->splitMemReq; @@ -754,7 +755,8 @@ CacheUnit::execute(int slot_num) DPRINTF(InOrderCachePort, "[tid:%i]: Instruction [sn:%i] is: %s\n", - tid, seq_num, inst->staticInst->disassemble(inst->PC)); + tid, seq_num, + inst->staticInst->disassemble(inst->instAddr())); removeAddrDependency(inst); @@ -771,7 +773,7 @@ CacheUnit::execute(int slot_num) tid, inst->seqNum); DPRINTF(InOrderStall, "STALL: [tid:%i]: Fetch miss from %08p\n", - tid, cache_req->inst->readPC()); + tid, cache_req->inst->instAddr()); cache_req->setCompleted(false); //cache_req->setMemStall(true); } @@ -1046,21 +1048,22 @@ CacheUnit::processCacheCompletion(PacketPtr pkt) // @todo: update thsi ExtMachInst ext_inst; StaticInstPtr staticInst = NULL; - Addr inst_pc = inst->readPC(); + TheISA::PCState instPC = inst->pcState(); MachInst mach_inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *> (cache_pkt->getPtr<uint8_t>())); predecoder.setTC(cpu->thread[tid]->getTC()); - predecoder.moreBytes(inst_pc, inst_pc, mach_inst); - ext_inst = predecoder.getExtMachInst(); + predecoder.moreBytes(instPC, inst->instAddr(), mach_inst); + ext_inst = predecoder.getExtMachInst(instPC); + inst->pcState(instPC); inst->setMachInst(ext_inst); // Set Up More TraceData info if (inst->traceData) { inst->traceData->setStaticInst(inst->staticInst); - inst->traceData->setPC(inst->readPC()); + inst->traceData->setPC(instPC); } } else if (inst->staticInst && inst->isMemRef()) { @@ -1149,7 +1152,7 @@ CacheUnit::processCacheCompletion(PacketPtr pkt) } else { DPRINTF(InOrderCachePort, "[tid:%u] Miss on block @ %08p completed, but squashed\n", - tid, cache_req->inst->readPC()); + tid, cache_req->inst->instAddr()); cache_req->setMemAccCompleted(); } } diff --git a/src/cpu/inorder/resources/execution_unit.cc b/src/cpu/inorder/resources/execution_unit.cc index 91e788fbc..4342042e9 100644 --- a/src/cpu/inorder/resources/execution_unit.cc +++ b/src/cpu/inorder/resources/execution_unit.cc @@ -91,8 +91,8 @@ ExecutionUnit::execute(int slot_num) exec_req->fault = NoFault; - DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%#x] %s.\n", - tid, seq_num, inst->readPC(), inst->instName()); + DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%s] %s.\n", + tid, seq_num, inst->pcState(), inst->instName()); switch (exec_req->cmd) { @@ -124,58 +124,61 @@ ExecutionUnit::execute(int slot_num) if (inst->isDirectCtrl()) { assert(!inst->isIndirectCtrl()); + TheISA::PCState pc = inst->pcState(); + TheISA::advancePC(pc, inst->staticInst); + inst->setPredTarg(pc); + if (inst->predTaken() && inst->isCondDelaySlot()) { inst->bdelaySeqNum = seq_num; - inst->setPredTarg(inst->nextPC); DPRINTF(InOrderExecute, "[tid:%i]: Conditional" - " branch inst [sn:%i] PC %#x mis" + " branch inst [sn:%i] PC %s mis" "predicted as taken.\n", tid, - seq_num, inst->PC); + seq_num, inst->pcState()); } else if (!inst->predTaken() && inst->isCondDelaySlot()) { inst->bdelaySeqNum = seq_num; - inst->setPredTarg(inst->nextPC); inst->procDelaySlotOnMispred = true; DPRINTF(InOrderExecute, "[tid:%i]: Conditional" - " branch inst [sn:%i] PC %#x mis" + " branch inst [sn:%i] PC %s mis" "predicted as not taken.\n", tid, - seq_num, inst->PC); + seq_num, inst->pcState()); } else { #if ISA_HAS_DELAY_SLOT inst->bdelaySeqNum = seq_num + 1; - inst->setPredTarg(inst->nextNPC); #else inst->bdelaySeqNum = seq_num; - inst->setPredTarg(inst->nextPC); #endif DPRINTF(InOrderExecute, "[tid:%i]: " "Misprediction detected at " - "[sn:%i] PC %#x,\n\t squashing after " + "[sn:%i] PC %s,\n\t squashing after " "delay slot instruction [sn:%i].\n", - tid, seq_num, inst->PC, + tid, seq_num, inst->pcState(), inst->bdelaySeqNum); DPRINTF(InOrderStall, "STALL: [tid:%i]: Branch" - " misprediction at %#x\n", - tid, inst->PC); + " misprediction at %s\n", + tid, inst->pcState()); } DPRINTF(InOrderExecute, "[tid:%i] Redirecting " - "fetch to %#x.\n", tid, + "fetch to %s.\n", tid, inst->readPredTarg()); - } else if(inst->isIndirectCtrl()){ + } else if (inst->isIndirectCtrl()){ + TheISA::PCState pc = inst->pcState(); + TheISA::advancePC(pc, inst->staticInst); + inst->seqNum = seq_num; + inst->setPredTarg(pc); + #if ISA_HAS_DELAY_SLOT - inst->setPredTarg(inst->nextNPC); inst->bdelaySeqNum = seq_num + 1; #else - inst->setPredTarg(inst->nextPC); inst->bdelaySeqNum = seq_num; #endif DPRINTF(InOrderExecute, "[tid:%i] Redirecting" - " fetch to %#x.\n", tid, + " fetch to %s.\n", tid, inst->readPredTarg()); } else { panic("Non-control instruction (%s) mispredict" @@ -197,14 +200,20 @@ ExecutionUnit::execute(int slot_num) if (inst->predTaken()) { predictedTakenIncorrect++; - DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ... PC%#x ... Mispredicts! (Taken)\n", - tid, inst->seqNum, inst->staticInst->disassemble(inst->PC), - inst->readPC()); + DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..." + "PC %s ... Mispredicts! (Taken)\n", + tid, inst->seqNum, + inst->staticInst->disassemble( + inst->instAddr()), + inst->pcState()); } else { predictedNotTakenIncorrect++; - DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ... PC%#x ... Mispredicts! (Not Taken)\n", - tid, inst->seqNum, inst->staticInst->disassemble(inst->PC), - inst->readPC()); + DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..." + "PC %s ... Mispredicts! (Not Taken)\n", + tid, inst->seqNum, + inst->staticInst->disassemble( + inst->instAddr()), + inst->pcState()); } predictedIncorrect++; } else { diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc b/src/cpu/inorder/resources/fetch_seq_unit.cc index 8a1ec3ce5..3bfe912e7 100644 --- a/src/cpu/inorder/resources/fetch_seq_unit.cc +++ b/src/cpu/inorder/resources/fetch_seq_unit.cc @@ -44,9 +44,6 @@ FetchSeqUnit::FetchSeqUnit(std::string res_name, int res_id, int res_width, instSize(sizeof(MachInst)) { for (ThreadID tid = 0; tid < ThePipeline::MaxThreads; tid++) { - delaySlotInfo[tid].numInsts = 0; - delaySlotInfo[tid].targetReady = false; - pcValid[tid] = false; pcBlockStage[tid] = 0; @@ -86,53 +83,17 @@ FetchSeqUnit::execute(int slot_num) case AssignNextPC: { if (pcValid[tid]) { + inst->pcState(pc[tid]); + inst->setMemAddr(pc[tid].instAddr()); - if (delaySlotInfo[tid].targetReady && - delaySlotInfo[tid].numInsts == 0) { - // Set PC to target - PC[tid] = delaySlotInfo[tid].targetAddr; //next_PC - nextPC[tid] = PC[tid] + instSize; //next_NPC - nextNPC[tid] = PC[tid] + (2 * instSize); - - delaySlotInfo[tid].targetReady = false; - - DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to delay " - "slot target\n",tid); - } + pc[tid].advance(); //XXX HACK! + inst->setPredTarg(pc[tid]); - inst->setPC(PC[tid]); - inst->setNextPC(PC[tid] + instSize); - inst->setNextNPC(PC[tid] + (instSize * 2)); - -#if ISA_HAS_DELAY_SLOT - inst->setPredTarg(inst->readNextNPC()); -#else - inst->setPredTarg(inst->readNextPC()); -#endif - inst->setMemAddr(PC[tid]); inst->setSeqNum(cpu->getAndIncrementInstSeq(tid)); DPRINTF(InOrderFetchSeq, "[tid:%i]: Assigning [sn:%i] to " - "PC %08p, NPC %08p, NNPC %08p\n", tid, - inst->seqNum, inst->readPC(), inst->readNextPC(), - inst->readNextNPC()); - - if (delaySlotInfo[tid].numInsts > 0) { - --delaySlotInfo[tid].numInsts; - - // It's OK to set PC to target of branch - if (delaySlotInfo[tid].numInsts == 0) { - delaySlotInfo[tid].targetReady = true; - } - - DPRINTF(InOrderFetchSeq, "[tid:%i]: %i delay slot inst(s) " - "left to process.\n", tid, - delaySlotInfo[tid].numInsts); - } - - PC[tid] = nextPC[tid]; - nextPC[tid] = nextNPC[tid]; - nextNPC[tid] += instSize; + "PC %s\n", tid, inst->seqNum, + inst->pcState()); fs_req->done(); } else { @@ -147,18 +108,21 @@ FetchSeqUnit::execute(int slot_num) if (inst->isControl()) { // If it's a return, then we must wait for resolved address. if (inst->isReturn() && !inst->predTaken()) { - cpu->pipelineStage[stage_num]->toPrevStages->stageBlock[stage_num][tid] = true; + cpu->pipelineStage[stage_num]-> + toPrevStages->stageBlock[stage_num][tid] = true; pcValid[tid] = false; pcBlockStage[tid] = stage_num; } else if (inst->isCondDelaySlot() && !inst->predTaken()) { // Not-Taken AND Conditional Control - DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: [PC:%08p] " - "Predicted Not-Taken Cond. " - "Delay inst. Skipping delay slot and Updating PC to %08p\n", - tid, inst->seqNum, inst->readPC(), inst->readPredTarg()); + DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: [PC:%s] " + "Predicted Not-Taken Cond. Delay inst. Skipping " + "delay slot and Updating PC to %s\n", + tid, inst->seqNum, inst->pcState(), + inst->readPredTarg()); - DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to start from stage %i, after [sn:%i].\n", - tid, stage_num, seq_num); + DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to " + "start from stage %i, after [sn:%i].\n", tid, + stage_num, seq_num); inst->bdelaySeqNum = seq_num; inst->squashingStage = stage_num; @@ -168,33 +132,26 @@ FetchSeqUnit::execute(int slot_num) // Not-Taken Control DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: Predicted " "Not-Taken Control " - "inst. updating PC to %08p\n", tid, inst->seqNum, - inst->readNextPC()); + "inst. updating PC to %s\n", tid, inst->seqNum, + inst->readPredTarg()); #if ISA_HAS_DELAY_SLOT - ++delaySlotInfo[tid].numInsts; - delaySlotInfo[tid].targetReady = false; - delaySlotInfo[tid].targetAddr = inst->readNextNPC(); -#else - assert(delaySlotInfo[tid].numInsts == 0); + pc[tid] = inst->pcState(); + advancePC(pc[tid], inst->staticInst); #endif } else if (inst->predTaken()) { // Taken Control #if ISA_HAS_DELAY_SLOT - ++delaySlotInfo[tid].numInsts; - delaySlotInfo[tid].targetReady = false; - delaySlotInfo[tid].targetAddr = inst->readPredTarg(); + pc[tid] = inst->readPredTarg(); DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i] Updating delay" - " slot target to PC %08p\n", tid, inst->seqNum, + " slot target to PC %s\n", tid, inst->seqNum, inst->readPredTarg()); inst->bdelaySeqNum = seq_num + 1; #else inst->bdelaySeqNum = seq_num; - assert(delaySlotInfo[tid].numInsts == 0); #endif inst->squashingStage = stage_num; - DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to " "start from stage %i, after [sn:%i].\n", tid, stage_num, inst->bdelaySeqNum); @@ -225,11 +182,12 @@ FetchSeqUnit::squashAfterInst(DynInstPtr inst, int stage_num, ThreadID tid) // Squash inside current resource, so if there needs to be fetching on // same cycle the fetch information will be correct. - // squash(inst, stage_num, inst->bdelaySeqNum, tid); // Schedule Squash Through-out Resource Pool - cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0); + cpu->resPool->scheduleEvent( + (InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0); } + void FetchSeqUnit::squash(DynInstPtr inst, int squash_stage, InstSeqNum squash_seq_num, ThreadID tid) @@ -241,8 +199,15 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage, // Handles the case where we are squashing because of something that is // not a branch...like a memory stall - Addr new_PC = (inst->isControl()) ? - inst->readPredTarg() : inst->readPC() + instSize; + TheISA::PCState newPC; + if (inst->isControl()) { + newPC = inst->readPredTarg(); + } else { + TheISA::PCState thisPC = inst->pcState(); + assert(inst->staticInst); + advancePC(thisPC, inst->staticInst); + newPC = thisPC; + } if (squashSeqNum[tid] <= done_seq_num && lastSquashCycle[tid] == curTick) { @@ -258,31 +223,25 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage, // the last done_seq_num then this is the delay slot inst. if (cpu->nextInstSeqNum(tid) != done_seq_num && !inst->procDelaySlotOnMispred) { - delaySlotInfo[tid].numInsts = 0; - delaySlotInfo[tid].targetReady = false; // Reset PC - PC[tid] = new_PC; - nextPC[tid] = new_PC + instSize; - nextNPC[tid] = new_PC + (2 * instSize); + pc[tid] = newPC; +#if ISA_HAS_DELAY_SLOT + TheISA::advancePC(pc[tid], inst->staticInst); +#endif - DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %08p.\n", - tid, PC[tid]); + DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %s.\n", + tid, newPC); } else { -#if !ISA_HAS_DELAY_SLOT - assert(0); -#endif + assert(ISA_HAS_DELAY_SLOT); - delaySlotInfo[tid].numInsts = 1; - delaySlotInfo[tid].targetReady = false; - delaySlotInfo[tid].targetAddr = (inst->procDelaySlotOnMispred) ? - inst->branchTarget() : new_PC; + pc[tid] = (inst->procDelaySlotOnMispred) ? + inst->branchTarget() : newPC; // Reset PC to Delay Slot Instruction if (inst->procDelaySlotOnMispred) { - PC[tid] = new_PC; - nextPC[tid] = new_PC + instSize; - nextNPC[tid] = new_PC + (2 * instSize); + // Reset PC + pc[tid] = newPC; } } @@ -309,18 +268,13 @@ FetchSeqUnit::FetchSeqEvent::process() FetchSeqUnit* fs_res = dynamic_cast<FetchSeqUnit*>(resource); assert(fs_res); - for (int i=0; i < MaxThreads; i++) { - fs_res->PC[i] = fs_res->cpu->readPC(i); - fs_res->nextPC[i] = fs_res->cpu->readNextPC(i); - fs_res->nextNPC[i] = fs_res->cpu->readNextNPC(i); - DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC:%08p NPC:%08p " - "NNPC:%08p.\n", fs_res->PC[i], fs_res->nextPC[i], - fs_res->nextNPC[i]); + for (int i = 0; i < MaxThreads; i++) { + fs_res->pc[i] = fs_res->cpu->pcState(i); + DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC: %s.\n", + fs_res->pc[i]); fs_res->pcValid[i] = true; } - - //cpu->fetchPriorityList.push_back(tid); } @@ -329,22 +283,17 @@ FetchSeqUnit::activateThread(ThreadID tid) { pcValid[tid] = true; - PC[tid] = cpu->readPC(tid); - nextPC[tid] = cpu->readNextPC(tid); - nextNPC[tid] = cpu->readNextNPC(tid); + pc[tid] = cpu->pcState(tid); cpu->fetchPriorityList.push_back(tid); - DPRINTF(InOrderFetchSeq, "[tid:%i]: Reading PC:%08p NPC:%08p " - "NNPC:%08p.\n", tid, PC[tid], nextPC[tid], nextNPC[tid]); + DPRINTF(InOrderFetchSeq, "[tid:%i]: Reading PC: %s.\n", + tid, pc[tid]); } void FetchSeqUnit::deactivateThread(ThreadID tid) { - delaySlotInfo[tid].numInsts = 0; - delaySlotInfo[tid].targetReady = false; - pcValid[tid] = false; pcBlockStage[tid] = 0; @@ -375,18 +324,14 @@ FetchSeqUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid) * switch was right after the branch. Thus, if it's not, then * we are updating incorrectly here */ - assert(cpu->thread[tid]->lastBranchNextPC == inst->readPC()); - - PC[tid] = cpu->thread[tid]->lastBranchNextNPC; - nextPC[tid] = PC[tid] + instSize; - nextNPC[tid] = nextPC[tid] + instSize; + assert(cpu->nextInstAddr(tid) == inst->instAddr()); + pc[tid] = cpu->thread[tid]->lastBranchPC; } else { - PC[tid] = inst->readNextPC(); - nextPC[tid] = inst->readNextNPC(); - nextNPC[tid] = inst->readNextNPC() + instSize; + pc[tid] = inst->pcState(); } + assert(inst->staticInst); + advancePC(pc[tid], inst->staticInst); DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating PCs due to Context Switch." - "Assigning PC:%08p NPC:%08p NNPC:%08p.\n", tid, PC[tid], - nextPC[tid], nextNPC[tid]); + "Assigning PC: %s.\n", tid, pc[tid]); } diff --git a/src/cpu/inorder/resources/fetch_seq_unit.hh b/src/cpu/inorder/resources/fetch_seq_unit.hh index aab462224..a258dc0e5 100644 --- a/src/cpu/inorder/resources/fetch_seq_unit.hh +++ b/src/cpu/inorder/resources/fetch_seq_unit.hh @@ -80,22 +80,7 @@ class FetchSeqUnit : public Resource { bool pcValid[ThePipeline::MaxThreads]; int pcBlockStage[ThePipeline::MaxThreads]; - TheISA::IntReg PC[ThePipeline::MaxThreads]; - TheISA::IntReg nextPC[ThePipeline::MaxThreads]; - TheISA::IntReg nextNPC[ThePipeline::MaxThreads]; - - /** Tracks delay slot information for threads in ISAs which use - * delay slots; - */ - struct DelaySlotInfo { - InstSeqNum delaySlotSeqNum; - InstSeqNum branchSeqNum; - int numInsts; - Addr targetAddr; - bool targetReady; - }; - - DelaySlotInfo delaySlotInfo[ThePipeline::MaxThreads]; + TheISA::PCState pc[ThePipeline::MaxThreads]; /** Squash Seq. Nums*/ InstSeqNum squashSeqNum[ThePipeline::MaxThreads]; diff --git a/src/cpu/inorder/resources/tlb_unit.hh b/src/cpu/inorder/resources/tlb_unit.hh index 5c62c7751..eb1bf55f0 100644 --- a/src/cpu/inorder/resources/tlb_unit.hh +++ b/src/cpu/inorder/resources/tlb_unit.hh @@ -111,8 +111,10 @@ class TLBUnitRequest : public ResourceRequest { aligned_addr = inst->getMemAddr(); req_size = sizeof(TheISA::MachInst); flags = 0; - inst->fetchMemReq = new Request(inst->readTid(), aligned_addr, req_size, - flags, inst->readPC(), res->cpu->readCpuId(), inst->readTid()); + inst->fetchMemReq = new Request(inst->readTid(), aligned_addr, + req_size, flags, inst->instAddr(), + res->cpu->readCpuId(), + inst->readTid()); memReq = inst->fetchMemReq; } else { aligned_addr = inst->getMemAddr();; @@ -123,8 +125,10 @@ class TLBUnitRequest : public ResourceRequest { req_size = 8; } - inst->dataMemReq = new Request(inst->readTid(), aligned_addr, req_size, - flags, inst->readPC(), res->cpu->readCpuId(), inst->readTid()); + inst->dataMemReq = new Request(inst->readTid(), aligned_addr, + req_size, flags, inst->instAddr(), + res->cpu->readCpuId(), + inst->readTid()); memReq = inst->dataMemReq; } } diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc index e6d0af2cc..bbccf626a 100644 --- a/src/cpu/inorder/thread_context.cc +++ b/src/cpu/inorder/thread_context.cc @@ -234,30 +234,6 @@ InOrderThreadContext::setRegOtherThread(int misc_reg, const MiscReg &val, } void -InOrderThreadContext::setPC(uint64_t val) -{ - DPRINTF(InOrderCPU, "[tid:%i] Setting PC to %08p\n", - thread->readTid(), val); - cpu->setPC(val, thread->readTid()); -} - -void -InOrderThreadContext::setNextPC(uint64_t val) -{ - DPRINTF(InOrderCPU, "[tid:%i] Setting NPC to %08p\n", - thread->readTid(), val); - cpu->setNextPC(val, thread->readTid()); -} - -void -InOrderThreadContext::setNextNPC(uint64_t val) -{ - DPRINTF(InOrderCPU, "[tid:%i] Setting NNPC to %08p\n", - thread->readTid(), val); - cpu->setNextNPC(val, thread->readTid()); -} - -void InOrderThreadContext::setMiscRegNoEffect(int misc_reg, const MiscReg &val) { cpu->setMiscRegNoEffect(misc_reg, val, thread->readTid()); diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index 0c0f563c0..21f1e5835 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -204,23 +204,21 @@ class InOrderThreadContext : public ThreadContext ThreadID tid); /** Reads this thread's PC. */ - uint64_t readPC() - { return cpu->readPC(thread->readTid()); } + TheISA::PCState pcState() + { return cpu->pcState(thread->readTid()); } /** Sets this thread's PC. */ - void setPC(uint64_t val); + void pcState(const TheISA::PCState &val) + { cpu->pcState(val, thread->readTid()); } - /** Reads this thread's next PC. */ - uint64_t readNextPC() - { return cpu->readNextPC(thread->readTid()); } + Addr instAddr() + { return cpu->instAddr(thread->readTid()); } - /** Sets this thread's next PC. */ - void setNextPC(uint64_t val); + Addr nextInstAddr() + { return cpu->nextInstAddr(thread->readTid()); } - uint64_t readNextNPC() - { return cpu->readNextNPC(thread->readTid()); } - - void setNextNPC(uint64_t val); + MicroPC microPC() + { return cpu->microPC(thread->readTid()); } /** Reads a miscellaneous register. */ MiscReg readMiscRegNoEffect(int misc_reg) diff --git a/src/cpu/inorder/thread_state.hh b/src/cpu/inorder/thread_state.hh index 0a171a99f..20ace6659 100644 --- a/src/cpu/inorder/thread_state.hh +++ b/src/cpu/inorder/thread_state.hh @@ -111,9 +111,7 @@ class InOrderThreadState : public ThreadState { /** Is last instruction graduated a branch? */ bool lastGradIsBranch; - Addr lastBranchPC; - Addr lastBranchNextPC; - Addr lastBranchNextNPC; + TheISA::PCState lastBranchPC; }; #endif // __CPU_INORDER_THREAD_STATE_HH__ diff --git a/src/cpu/inteltrace.cc b/src/cpu/inteltrace.cc index ec51b80e7..ee148c50f 100644 --- a/src/cpu/inteltrace.cc +++ b/src/cpu/inteltrace.cc @@ -48,7 +48,7 @@ Trace::IntelTraceRecord::dump() { ostream &outs = Trace::output(); ccprintf(outs, "%7d ) ", when); - outs << "0x" << hex << PC << ":\t"; + outs << "0x" << hex << pc.instAddr() << ":\t"; if (staticInst->isLoad()) { ccprintf(outs, "<RD %#x>", addr); } else if (staticInst->isStore()) { diff --git a/src/cpu/inteltrace.hh b/src/cpu/inteltrace.hh index c4ace4f4b..234b173e9 100644 --- a/src/cpu/inteltrace.hh +++ b/src/cpu/inteltrace.hh @@ -46,10 +46,10 @@ class IntelTraceRecord : public InstRecord { public: IntelTraceRecord(Tick _when, ThreadContext *_thread, - const StaticInstPtr _staticInst, Addr _pc, bool spec, - const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0) + const StaticInstPtr _staticInst, TheISA::PCState _pc, + bool spec, const StaticInstPtr _macroStaticInst = NULL) : InstRecord(_when, _thread, _staticInst, _pc, spec, - _macroStaticInst, _upc) + _macroStaticInst) { } @@ -65,8 +65,8 @@ class IntelTrace : public InstTracer IntelTraceRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc, - const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0) + const StaticInstPtr staticInst, TheISA::PCState pc, + const StaticInstPtr macroStaticInst = NULL) { if (!IsOn(ExecEnable)) return NULL; @@ -78,7 +78,7 @@ class IntelTrace : public InstTracer return NULL; return new IntelTraceRecord(when, tc, - staticInst, pc, tc->misspeculating(), macroStaticInst, upc); + staticInst, pc, tc->misspeculating(), macroStaticInst); } }; diff --git a/src/cpu/legiontrace.cc b/src/cpu/legiontrace.cc index 1390d0807..8750e56e5 100644 --- a/src/cpu/legiontrace.cc +++ b/src/cpu/legiontrace.cc @@ -211,7 +211,7 @@ Trace::LegionTraceRecord::dump() if(!staticInst->isMicroop() || staticInst->isLastMicroop()) { while (!compared) { if (shared_data->flags == OWN_M5) { - m5Pc = PC & SparcISA::PAddrImplMask; + m5Pc = pc.instAddr() & SparcISA::PAddrImplMask; if (bits(shared_data->pstate,3,3)) { m5Pc &= mask(32); } @@ -432,13 +432,14 @@ Trace::LegionTraceRecord::dump() << endl; predecoder.setTC(thread); - predecoder.moreBytes(m5Pc, m5Pc, - shared_data->instruction); + predecoder.moreBytes(m5Pc, m5Pc, shared_data->instruction); assert(predecoder.extMachInstReady()); + PCState tempPC = pc; StaticInstPtr legionInst = - StaticInst::decode(predecoder.getExtMachInst(), lgnPc); + StaticInst::decode(predecoder.getExtMachInst(tempPC), + lgnPc); outs << setfill(' ') << setw(15) << " Legion Inst: " << "0x" << setw(8) << setfill('0') << hex diff --git a/src/cpu/legiontrace.hh b/src/cpu/legiontrace.hh index 829941d4b..a60b9ad10 100644 --- a/src/cpu/legiontrace.hh +++ b/src/cpu/legiontrace.hh @@ -46,10 +46,10 @@ class LegionTraceRecord : public InstRecord { public: LegionTraceRecord(Tick _when, ThreadContext *_thread, - const StaticInstPtr _staticInst, Addr _pc, bool spec, - const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0) + const StaticInstPtr _staticInst, TheISA::PCState _pc, + bool spec, const StaticInstPtr _macroStaticInst = NULL) : InstRecord(_when, _thread, _staticInst, _pc, spec, - _macroStaticInst, _upc) + _macroStaticInst) { } @@ -65,14 +65,14 @@ class LegionTrace : public InstTracer LegionTraceRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc, - const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0) + const StaticInstPtr staticInst, TheISA::PCState pc, + const StaticInstPtr macroStaticInst = NULL) { if (tc->misspeculating()) return NULL; return new LegionTraceRecord(when, tc, - staticInst, pc, tc->misspeculating(), macroStaticInst, upc); + staticInst, pc, tc->misspeculating(), macroStaticInst); } }; diff --git a/src/cpu/nativetrace.hh b/src/cpu/nativetrace.hh index 6ad6b0242..5c5b9a66d 100644 --- a/src/cpu/nativetrace.hh +++ b/src/cpu/nativetrace.hh @@ -54,10 +54,10 @@ class NativeTraceRecord : public ExeTracerRecord public: NativeTraceRecord(NativeTrace * _parent, Tick _when, ThreadContext *_thread, - const StaticInstPtr _staticInst, Addr _pc, bool spec, - const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0) + const StaticInstPtr _staticInst, TheISA::PCState _pc, + bool spec, const StaticInstPtr _macroStaticInst = NULL) : ExeTracerRecord(_when, _thread, _staticInst, _pc, spec, - _macroStaticInst, _upc), + _macroStaticInst), parent(_parent) { } @@ -79,14 +79,14 @@ class NativeTrace : public ExeTracer NativeTraceRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc, - const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0) + const StaticInstPtr staticInst, TheISA::PCState pc, + const StaticInstPtr macroStaticInst = NULL) { if (tc->misspeculating()) return NULL; return new NativeTraceRecord(this, when, tc, - staticInst, pc, tc->misspeculating(), macroStaticInst, upc); + staticInst, pc, tc->misspeculating(), macroStaticInst); } template<class T> diff --git a/src/cpu/o3/bpred_unit.hh b/src/cpu/o3/bpred_unit.hh index f199bdd75..58b1147c9 100644 --- a/src/cpu/o3/bpred_unit.hh +++ b/src/cpu/o3/bpred_unit.hh @@ -88,7 +88,7 @@ class BPredUnit * @param tid The thread id. * @return Returns if the branch is taken or not. */ - bool predict(DynInstPtr &inst, Addr &PC, ThreadID tid); + bool predict(DynInstPtr &inst, TheISA::PCState &pc, ThreadID tid); // @todo: Rename this function. void BPUncond(void * &bp_history); @@ -118,7 +118,8 @@ class BPredUnit * @param actually_taken The correct branch direction. * @param tid The thread id. */ - void squash(const InstSeqNum &squashed_sn, const Addr &corr_target, + void squash(const InstSeqNum &squashed_sn, + const TheISA::PCState &corr_target, bool actually_taken, ThreadID tid); /** @@ -134,23 +135,23 @@ class BPredUnit * has the branch predictor state associated with the lookup. * @return Whether the branch is taken or not taken. */ - bool BPLookup(Addr &inst_PC, void * &bp_history); + bool BPLookup(Addr instPC, void * &bp_history); /** * Looks up a given PC in the BTB to see if a matching entry exists. * @param inst_PC The PC to look up. * @return Whether the BTB contains the given PC. */ - bool BTBValid(Addr &inst_PC) - { return BTB.valid(inst_PC, 0); } + bool BTBValid(Addr instPC) + { return BTB.valid(instPC, 0); } /** * Looks up a given PC in the BTB to get the predicted target. * @param inst_PC The PC to look up. * @return The address of the target of the branch. */ - Addr BTBLookup(Addr &inst_PC) - { return BTB.lookup(inst_PC, 0); } + TheISA::PCState BTBLookup(Addr instPC) + { return BTB.lookup(instPC, 0); } /** * Updates the BP with taken/not taken information. @@ -160,15 +161,15 @@ class BPredUnit * associated with the branch lookup that is being updated. * @todo Make this update flexible enough to handle a global predictor. */ - void BPUpdate(Addr &inst_PC, bool taken, void *bp_history); + void BPUpdate(Addr instPC, bool taken, void *bp_history); /** * Updates the BTB with the target of a branch. * @param inst_PC The branch's PC that will be updated. * @param target_PC The branch's target that will be added to the BTB. */ - void BTBUpdate(Addr &inst_PC, Addr &target_PC) - { BTB.update(inst_PC, target_PC,0); } + void BTBUpdate(Addr instPC, const TheISA::PCState &target) + { BTB.update(instPC, target, 0); } void dump(); @@ -178,13 +179,13 @@ class BPredUnit * Makes a predictor history struct that contains any * information needed to update the predictor, BTB, and RAS. */ - PredictorHistory(const InstSeqNum &seq_num, const Addr &inst_PC, + PredictorHistory(const InstSeqNum &seq_num, Addr instPC, bool pred_taken, void *bp_history, ThreadID _tid) - : seqNum(seq_num), PC(inst_PC), RASTarget(0), - RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0), + : seqNum(seq_num), pc(instPC), RASTarget(0), RASIndex(0), + tid(_tid), predTaken(pred_taken), usedRAS(0), wasCall(0), bpHistory(bp_history) - { } + {} bool operator==(const PredictorHistory &entry) const { return this->seqNum == entry.seqNum; @@ -194,10 +195,10 @@ class BPredUnit InstSeqNum seqNum; /** The PC associated with the sequence number. */ - Addr PC; + Addr pc; /** The RAS target (only valid if a return). */ - Addr RASTarget; + TheISA::PCState RASTarget; /** The RAS index of the instruction (only valid if a call). */ unsigned RASIndex; diff --git a/src/cpu/o3/bpred_unit_impl.hh b/src/cpu/o3/bpred_unit_impl.hh index ed3471761..14d47df9f 100644 --- a/src/cpu/o3/bpred_unit_impl.hh +++ b/src/cpu/o3/bpred_unit_impl.hh @@ -31,6 +31,7 @@ #include <algorithm> #include "arch/types.hh" +#include "arch/utility.hh" #include "arch/isa_traits.hh" #include "base/trace.hh" #include "base/traceflags.hh" @@ -144,17 +145,15 @@ BPredUnit<Impl>::takeOverFrom() template <class Impl> bool -BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, ThreadID tid) +BPredUnit<Impl>::predict(DynInstPtr &inst, TheISA::PCState &pc, ThreadID tid) { // See if branch predictor predicts taken. // If so, get its target addr either from the BTB or the RAS. // Save off record of branch stuff so the RAS can be fixed // up once it's done. - using TheISA::MachInst; - bool pred_taken = false; - Addr target = PC; + TheISA::PCState target = pc; ++lookups; @@ -168,19 +167,19 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, ThreadID tid) } else { ++condPredicted; - pred_taken = BPLookup(PC, bp_history); + pred_taken = BPLookup(pc.instAddr(), bp_history); DPRINTF(Fetch, "BranchPred: [tid:%i]: Branch predictor predicted %i " - "for PC %#x\n", - tid, pred_taken, inst->readPC()); + "for PC %s\n", + tid, pred_taken, inst->pcState()); } DPRINTF(Fetch, "BranchPred: [tid:%i]: [sn:%i] Creating prediction history " - "for PC %#x\n", - tid, inst->seqNum, inst->readPC()); + "for PC %s\n", + tid, inst->seqNum, inst->pcState()); - PredictorHistory predict_record(inst->seqNum, PC, pred_taken, - bp_history, tid); + PredictorHistory predict_record(inst->seqNum, pc.instAddr(), + pred_taken, bp_history, tid); // Now lookup in the BTB or RAS. if (pred_taken) { @@ -189,60 +188,58 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, ThreadID tid) // If it's a function return call, then look up the address // in the RAS. - target = RAS[tid].top(); + TheISA::PCState rasTop = RAS[tid].top(); + target = TheISA::buildRetPC(pc, rasTop); // Record the top entry of the RAS, and its index. predict_record.usedRAS = true; predict_record.RASIndex = RAS[tid].topIdx(); - predict_record.RASTarget = target; + predict_record.RASTarget = rasTop; assert(predict_record.RASIndex < 16); RAS[tid].pop(); - DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x is a return, " - "RAS predicted target: %#x, RAS index: %i.\n", - tid, inst->readPC(), target, predict_record.RASIndex); + DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %s is a return, " + "RAS predicted target: %s, RAS index: %i.\n", + tid, inst->pcState(), target, predict_record.RASIndex); } else { ++BTBLookups; if (inst->isCall()) { -#if ISA_HAS_DELAY_SLOT - Addr ras_pc = PC + (2 * sizeof(MachInst)); // Next Next PC -#else - Addr ras_pc = PC + sizeof(MachInst); // Next PC -#endif - RAS[tid].push(ras_pc); + RAS[tid].push(pc); // Record that it was a call so that the top RAS entry can // be popped off if the speculation is incorrect. predict_record.wasCall = true; - DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x was a call" - ", adding %#x to the RAS index: %i.\n", - tid, inst->readPC(), ras_pc, RAS[tid].topIdx()); + DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %s was a " + "call, adding %s to the RAS index: %i.\n", + tid, inst->pcState(), pc, RAS[tid].topIdx()); } - if (BTB.valid(PC, tid)) { + if (BTB.valid(pc.instAddr(), tid)) { ++BTBHits; // If it's not a return, use the BTB to get the target addr. - target = BTB.lookup(PC, tid); + target = BTB.lookup(pc.instAddr(), tid); - DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x predicted" - " target is %#x.\n", - tid, inst->readPC(), target); + DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %s predicted" + " target is %s.\n", tid, inst->pcState(), target); } else { DPRINTF(Fetch, "BranchPred: [tid:%i]: BTB doesn't have a " "valid entry.\n",tid); pred_taken = false; + TheISA::advancePC(target, inst->staticInst); } } + } else { + TheISA::advancePC(target, inst->staticInst); } - PC = target; + pc = target; predHist[tid].push_front(predict_record); @@ -262,7 +259,7 @@ BPredUnit<Impl>::update(const InstSeqNum &done_sn, ThreadID tid) while (!predHist[tid].empty() && predHist[tid].back().seqNum <= done_sn) { // Update the branch predictor with the correct results. - BPUpdate(predHist[tid].back().PC, + BPUpdate(predHist[tid].back().pc, predHist[tid].back().predTaken, predHist[tid].back().bpHistory); @@ -280,10 +277,8 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ThreadID tid) pred_hist.front().seqNum > squashed_sn) { if (pred_hist.front().usedRAS) { DPRINTF(Fetch, "BranchPred: [tid:%i]: Restoring top of RAS to: %i," - " target: %#x.\n", - tid, - pred_hist.front().RASIndex, - pred_hist.front().RASTarget); + " target: %s.\n", tid, + pred_hist.front().RASIndex, pred_hist.front().RASTarget); RAS[tid].restore(pred_hist.front().RASIndex, pred_hist.front().RASTarget); @@ -298,11 +293,13 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ThreadID tid) BPSquash(pred_hist.front().bpHistory); DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing history for [sn:%i] " - "PC %#x.\n", tid, pred_hist.front().seqNum, pred_hist.front().PC); + "PC %s.\n", tid, pred_hist.front().seqNum, + pred_hist.front().pc); pred_hist.pop_front(); - DPRINTF(Fetch, "[tid:%i]: predHist.size(): %i\n", tid, predHist[tid].size()); + DPRINTF(Fetch, "[tid:%i]: predHist.size(): %i\n", + tid, predHist[tid].size()); } } @@ -310,7 +307,7 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ThreadID tid) template <class Impl> void BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, - const Addr &corr_target, + const TheISA::PCState &corrTarget, bool actually_taken, ThreadID tid) { @@ -330,8 +327,8 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ++condIncorrect; DPRINTF(Fetch, "BranchPred: [tid:%i]: Squashing from sequence number %i, " - "setting target to %#x.\n", - tid, squashed_sn, corr_target); + "setting target to %s.\n", + tid, squashed_sn, corrTarget); // Squash All Branches AFTER this mispredicted branch squash(squashed_sn, tid); @@ -358,13 +355,13 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ++RASIncorrect; } - BPUpdate((*hist_it).PC, actually_taken, + BPUpdate((*hist_it).pc, actually_taken, pred_hist.front().bpHistory); - BTB.update((*hist_it).PC, corr_target, tid); + BTB.update((*hist_it).pc, corrTarget, tid); DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing history for [sn:%i] " - "PC %#x.\n", tid, (*hist_it).seqNum, (*hist_it).PC); + "PC %s.\n", tid, (*hist_it).seqNum, (*hist_it).pc); pred_hist.erase(hist_it); @@ -397,12 +394,12 @@ BPredUnit<Impl>::BPSquash(void *bp_history) template <class Impl> bool -BPredUnit<Impl>::BPLookup(Addr &inst_PC, void * &bp_history) +BPredUnit<Impl>::BPLookup(Addr instPC, void * &bp_history) { if (predictor == Local) { - return localBP->lookup(inst_PC, bp_history); + return localBP->lookup(instPC, bp_history); } else if (predictor == Tournament) { - return tournamentBP->lookup(inst_PC, bp_history); + return tournamentBP->lookup(instPC, bp_history); } else { panic("Predictor type is unexpected value!"); } @@ -410,12 +407,12 @@ BPredUnit<Impl>::BPLookup(Addr &inst_PC, void * &bp_history) template <class Impl> void -BPredUnit<Impl>::BPUpdate(Addr &inst_PC, bool taken, void *bp_history) +BPredUnit<Impl>::BPUpdate(Addr instPC, bool taken, void *bp_history) { if (predictor == Local) { - localBP->update(inst_PC, taken, bp_history); + localBP->update(instPC, taken, bp_history); } else if (predictor == Tournament) { - tournamentBP->update(inst_PC, taken, bp_history); + tournamentBP->update(instPC, taken, bp_history); } else { panic("Predictor type is unexpected value!"); } @@ -436,9 +433,9 @@ BPredUnit<Impl>::dump() while (pred_hist_it != predHist[i].end()) { cprintf("[sn:%lli], PC:%#x, tid:%i, predTaken:%i, " "bpHistory:%#x\n", - (*pred_hist_it).seqNum, (*pred_hist_it).PC, - (*pred_hist_it).tid, (*pred_hist_it).predTaken, - (*pred_hist_it).bpHistory); + pred_hist_it->seqNum, pred_hist_it->pc, + pred_hist_it->tid, pred_hist_it->predTaken, + pred_hist_it->bpHistory); pred_hist_it++; } diff --git a/src/cpu/o3/comm.hh b/src/cpu/o3/comm.hh index 23b836f73..c9fb3319b 100644 --- a/src/cpu/o3/comm.hh +++ b/src/cpu/o3/comm.hh @@ -33,6 +33,7 @@ #include <vector> +#include "arch/types.hh" #include "base/types.hh" #include "cpu/inst_seq.hh" #include "sim/faults.hh" @@ -88,9 +89,7 @@ struct DefaultIEWDefaultCommit { bool branchMispredict[Impl::MaxThreads]; bool branchTaken[Impl::MaxThreads]; Addr mispredPC[Impl::MaxThreads]; - Addr nextPC[Impl::MaxThreads]; - Addr nextNPC[Impl::MaxThreads]; - Addr nextMicroPC[Impl::MaxThreads]; + TheISA::PCState pc[Impl::MaxThreads]; InstSeqNum squashedSeqNum[Impl::MaxThreads]; bool includeSquashInst[Impl::MaxThreads]; @@ -120,9 +119,7 @@ struct TimeBufStruct { bool branchMispredict; bool branchTaken; Addr mispredPC; - Addr nextPC; - Addr nextNPC; - Addr nextMicroPC; + TheISA::PCState nextPC; unsigned branchCount; }; @@ -161,9 +158,7 @@ struct TimeBufStruct { bool branchMispredict; bool branchTaken; Addr mispredPC; - Addr nextPC; - Addr nextNPC; - Addr nextMicroPC; + TheISA::PCState pc; // Represents the instruction that has either been retired or // squashed. Similar to having a single bus that broadcasts the diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh index d93b85984..326f3a1d3 100644 --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.hh @@ -277,40 +277,21 @@ class DefaultCommit ThreadID oldestReady(); public: - /** Returns the PC of the head instruction of the ROB. - * @todo: Probably remove this function as it returns only thread 0. - */ - Addr readPC() { return PC[0]; } - - /** Returns the PC of a specific thread. */ - Addr readPC(ThreadID tid) { return PC[tid]; } + /** Reads the PC of a specific thread. */ + TheISA::PCState pcState(ThreadID tid) { return pc[tid]; } /** Sets the PC of a specific thread. */ - void setPC(Addr val, ThreadID tid) { PC[tid] = val; } - - /** Reads the micro PC of a specific thread. */ - Addr readMicroPC(ThreadID tid) { return microPC[tid]; } - - /** Sets the micro PC of a specific thread */ - void setMicroPC(Addr val, ThreadID tid) { microPC[tid] = val; } - - /** Reads the next PC of a specific thread. */ - Addr readNextPC(ThreadID tid) { return nextPC[tid]; } - - /** Sets the next PC of a specific thread. */ - void setNextPC(Addr val, ThreadID tid) { nextPC[tid] = val; } + void pcState(const TheISA::PCState &val, ThreadID tid) + { pc[tid] = val; } - /** Reads the next NPC of a specific thread. */ - Addr readNextNPC(ThreadID tid) { return nextNPC[tid]; } + /** Returns the PC of a specific thread. */ + Addr instAddr(ThreadID tid) { return pc[tid].instAddr(); } - /** Sets the next NPC of a specific thread. */ - void setNextNPC(Addr val, ThreadID tid) { nextNPC[tid] = val; } + /** Returns the next PC of a specific thread. */ + Addr nextInstAddr(ThreadID tid) { return pc[tid].nextInstAddr(); } /** Reads the micro PC of a specific thread. */ - Addr readNextMicroPC(ThreadID tid) { return nextMicroPC[tid]; } - - /** Sets the micro PC of a specific thread */ - void setNextMicroPC(Addr val, ThreadID tid) { nextMicroPC[tid] = val; } + Addr microPC(ThreadID tid) { return pc[tid].microPC(); } private: /** Time buffer interface. */ @@ -410,24 +391,10 @@ class DefaultCommit /** The interrupt fault. */ Fault interrupt; - /** The commit PC of each thread. Refers to the instruction that - * is currently being processed/committed. - */ - Addr PC[Impl::MaxThreads]; - - /** The commit micro PC of each thread. Refers to the instruction that + /** The commit PC state of each thread. Refers to the instruction that * is currently being processed/committed. */ - Addr microPC[Impl::MaxThreads]; - - /** The next PC of each thread. */ - Addr nextPC[Impl::MaxThreads]; - - /** The next NPC of each thread. */ - Addr nextNPC[Impl::MaxThreads]; - - /** The next micro PC of each thread. */ - Addr nextMicroPC[Impl::MaxThreads]; + TheISA::PCState pc[Impl::MaxThreads]; /** The sequence number of the youngest valid instruction in the ROB. */ InstSeqNum youngestSeqNum[Impl::MaxThreads]; diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 98c7b49c8..8d3edfb19 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -128,11 +128,7 @@ DefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params) committedStores[tid] = false; trapSquash[tid] = false; tcSquash[tid] = false; - microPC[tid] = 0; - nextMicroPC[tid] = 0; - PC[tid] = 0; - nextPC[tid] = 0; - nextNPC[tid] = 0; + pc[tid].set(0); } #if FULL_SYSTEM interrupt = NoFault; @@ -513,9 +509,7 @@ DefaultCommit<Impl>::squashAll(ThreadID tid) toIEW->commitInfo[tid].branchMispredict = false; - toIEW->commitInfo[tid].nextPC = PC[tid]; - toIEW->commitInfo[tid].nextNPC = nextPC[tid]; - toIEW->commitInfo[tid].nextMicroPC = nextMicroPC[tid]; + toIEW->commitInfo[tid].pc = pc[tid]; } template <class Impl> @@ -524,7 +518,7 @@ DefaultCommit<Impl>::squashFromTrap(ThreadID tid) { squashAll(tid); - DPRINTF(Commit, "Squashing from trap, restarting at PC %#x\n", PC[tid]); + DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]); thread[tid]->trapPending = false; thread[tid]->inSyscall = false; @@ -542,7 +536,7 @@ DefaultCommit<Impl>::squashFromTC(ThreadID tid) { squashAll(tid); - DPRINTF(Commit, "Squashing from TC, restarting at PC %#x\n", PC[tid]); + DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]); thread[tid]->inSyscall = false; assert(!thread[tid]->trapPending); @@ -611,16 +605,16 @@ DefaultCommit<Impl>::tick() DynInstPtr inst = rob->readHeadInst(tid); - DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %#x is head of" + DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %s is head of" " ROB and ready to commit\n", - tid, inst->seqNum, inst->readPC()); + tid, inst->seqNum, inst->pcState()); } else if (!rob->isEmpty(tid)) { DynInstPtr inst = rob->readHeadInst(tid); DPRINTF(Commit,"[tid:%i]: Can't commit, Instruction [sn:%lli] PC " - "%#x is head of ROB and not ready\n", - tid, inst->seqNum, inst->readPC()); + "%s is head of ROB and not ready\n", + tid, inst->seqNum, inst->pcState()); } DPRINTF(Commit, "[tid:%i]: ROB has %d insts & %d free entries.\n", @@ -738,7 +732,7 @@ DefaultCommit<Impl>::commit() DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n", tid, - fromIEW->nextPC[tid]); + fromIEW->pc[tid].nextInstAddr()); commitStatus[tid] = ROBSquashing; @@ -771,9 +765,7 @@ DefaultCommit<Impl>::commit() toIEW->commitInfo[tid].branchTaken = fromIEW->branchTaken[tid]; - toIEW->commitInfo[tid].nextPC = fromIEW->nextPC[tid]; - toIEW->commitInfo[tid].nextNPC = fromIEW->nextNPC[tid]; - toIEW->commitInfo[tid].nextMicroPC = fromIEW->nextMicroPC[tid]; + toIEW->commitInfo[tid].pc = fromIEW->pc[tid]; toIEW->commitInfo[tid].mispredPC = fromIEW->mispredPC[tid]; @@ -880,10 +872,7 @@ DefaultCommit<Impl>::commitInsts() // Record that the number of ROB entries has changed. changedROBNumEntries[tid] = true; } else { - PC[tid] = head_inst->readPC(); - nextPC[tid] = head_inst->readNextPC(); - nextNPC[tid] = head_inst->readNextNPC(); - nextMicroPC[tid] = head_inst->readNextMicroPC(); + pc[tid] = head_inst->pcState(); // Increment the total number of non-speculative instructions // executed. @@ -911,11 +900,7 @@ DefaultCommit<Impl>::commitInsts() cpu->instDone(tid); } - PC[tid] = nextPC[tid]; - nextPC[tid] = nextNPC[tid]; - nextNPC[tid] = nextNPC[tid] + sizeof(TheISA::MachInst); - microPC[tid] = nextMicroPC[tid]; - nextMicroPC[tid] = microPC[tid] + 1; + TheISA::advancePC(pc[tid], head_inst->staticInst); int count = 0; Addr oldpc; @@ -923,19 +908,19 @@ DefaultCommit<Impl>::commitInsts() // currently updating state while handling PC events. assert(!thread[tid]->inSyscall && !thread[tid]->trapPending); do { - oldpc = PC[tid]; + oldpc = pc[tid].instAddr(); cpu->system->pcEventQueue.service(thread[tid]->getTC()); count++; - } while (oldpc != PC[tid]); + } while (oldpc != pc[tid].instAddr()); if (count > 1) { DPRINTF(Commit, "PC skip function event, stopping commit\n"); break; } } else { - DPRINTF(Commit, "Unable to commit head instruction PC:%#x " + DPRINTF(Commit, "Unable to commit head instruction PC:%s " "[tid:%i] [sn:%i].\n", - head_inst->readPC(), tid ,head_inst->seqNum); + head_inst->pcState(), tid ,head_inst->seqNum); break; } } @@ -970,8 +955,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) head_inst->isWriteBarrier()) { DPRINTF(Commit, "Encountered a barrier or non-speculative " - "instruction [sn:%lli] at the head of the ROB, PC %#x.\n", - head_inst->seqNum, head_inst->readPC()); + "instruction [sn:%lli] at the head of the ROB, PC %s.\n", + head_inst->seqNum, head_inst->pcState()); if (inst_num > 0 || iewStage->hasStoresToWB(tid)) { DPRINTF(Commit, "Waiting for all stores to writeback.\n"); @@ -994,8 +979,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) } assert(head_inst->uncacheable()); - DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %#x.\n", - head_inst->seqNum, head_inst->readPC()); + DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %s.\n", + head_inst->seqNum, head_inst->pcState()); // Send back the non-speculative instruction's sequence // number. Tell the lsq to re-execute the load. @@ -1034,8 +1019,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) #endif if (inst_fault != NoFault) { - DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n", - head_inst->seqNum, head_inst->readPC()); + DPRINTF(Commit, "Inst [sn:%lli] PC %s has a fault\n", + head_inst->seqNum, head_inst->pcState()); if (iewStage->hasStoresToWB(tid) || inst_num > 0) { DPRINTF(Commit, "Stores outstanding, fault must wait.\n"); @@ -1081,7 +1066,6 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) // Generate trap squash event. generateTrapEvent(tid); -// warn("%lli fault (%d) handled @ PC %08p", curTick, inst_fault->name(), head_inst->readPC()); return false; } @@ -1089,9 +1073,7 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) #if FULL_SYSTEM if (thread[tid]->profile) { -// bool usermode = TheISA::inUserMode(thread[tid]->getTC()); -// thread[tid]->profilePC = usermode ? 1 : head_inst->readPC(); - thread[tid]->profilePC = head_inst->readPC(); + thread[tid]->profilePC = head_inst->instAddr(); ProfileNode *node = thread[tid]->profile->consume(thread[tid]->getTC(), head_inst->staticInst); @@ -1101,7 +1083,7 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) if (CPA::available()) { if (head_inst->isControl()) { ThreadContext *tc = thread[tid]->getTC(); - CPA::cpa()->swAutoBegin(tc, head_inst->readNextPC()); + CPA::cpa()->swAutoBegin(tc, head_inst->nextInstAddr()); } } #endif @@ -1154,8 +1136,8 @@ DefaultCommit<Impl>::getInsts() commitStatus[tid] != TrapPending) { changedROBNumEntries[tid] = true; - DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ROB.\n", - inst->readPC(), inst->seqNum, tid); + DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ROB.\n", + inst->pcState(), inst->seqNum, tid); rob->insertInst(inst); @@ -1163,9 +1145,9 @@ DefaultCommit<Impl>::getInsts() youngestSeqNum[tid] = inst->seqNum; } else { - DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was " + DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was " "squashed, skipping.\n", - inst->readPC(), inst->seqNum, tid); + inst->pcState(), inst->seqNum, tid); } } } @@ -1181,14 +1163,14 @@ DefaultCommit<Impl>::skidInsert() DynInstPtr inst = fromRename->insts[inst_num]; if (!inst->isSquashed()) { - DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ", - "skidBuffer.\n", inst->readPC(), inst->seqNum, + DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ", + "skidBuffer.\n", inst->pcState(), inst->seqNum, inst->threadNumber); skidBuffer.push(inst); } else { - DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was " + DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was " "squashed, skipping.\n", - inst->readPC(), inst->seqNum, inst->threadNumber); + inst->pcState(), inst->seqNum, inst->threadNumber); } } } @@ -1204,10 +1186,10 @@ DefaultCommit<Impl>::markCompletedInsts() ++inst_num) { if (!fromIEW->insts[inst_num]->isSquashed()) { - DPRINTF(Commit, "[tid:%i]: Marking PC %#x, [sn:%lli] ready " + DPRINTF(Commit, "[tid:%i]: Marking PC %s, [sn:%lli] ready " "within ROB.\n", fromIEW->insts[inst_num]->threadNumber, - fromIEW->insts[inst_num]->readPC(), + fromIEW->insts[inst_num]->pcState(), fromIEW->insts[inst_num]->seqNum); // Mark the instruction as ready to commit. diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 8e9f3ef5d..21c5cc706 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -732,9 +732,7 @@ FullO3CPU<Impl>::insertThread(ThreadID tid) //this->copyFromTC(tid); //Set PC/NPC/NNPC - setPC(src_tc->readPC(), tid); - setNextPC(src_tc->readNextPC(), tid); - setNextNPC(src_tc->readNextNPC(), tid); + pcState(src_tc->pcState(), tid); src_tc->setStatus(ThreadContext::Active); @@ -778,7 +776,7 @@ FullO3CPU<Impl>::removeThread(ThreadID tid) // Squash Throughout Pipeline InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum; - fetch.squash(0, sizeof(TheISA::MachInst), 0, squash_seq_num, tid); + fetch.squash(0, squash_seq_num, tid); decode.squash(tid); rename.squash(squash_seq_num, tid); iew.squash(tid); @@ -1306,73 +1304,38 @@ FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid) } template <class Impl> -uint64_t -FullO3CPU<Impl>::readPC(ThreadID tid) +TheISA::PCState +FullO3CPU<Impl>::pcState(ThreadID tid) { - return commit.readPC(tid); + return commit.pcState(tid); } template <class Impl> void -FullO3CPU<Impl>::setPC(Addr new_PC, ThreadID tid) -{ - commit.setPC(new_PC, tid); -} - -template <class Impl> -uint64_t -FullO3CPU<Impl>::readMicroPC(ThreadID tid) +FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid) { - return commit.readMicroPC(tid); + commit.pcState(val, tid); } template <class Impl> -void -FullO3CPU<Impl>::setMicroPC(Addr new_PC, ThreadID tid) +Addr +FullO3CPU<Impl>::instAddr(ThreadID tid) { - commit.setMicroPC(new_PC, tid); + return commit.instAddr(tid); } template <class Impl> -uint64_t -FullO3CPU<Impl>::readNextPC(ThreadID tid) +Addr +FullO3CPU<Impl>::nextInstAddr(ThreadID tid) { - return commit.readNextPC(tid); + return commit.nextInstAddr(tid); } template <class Impl> -void -FullO3CPU<Impl>::setNextPC(uint64_t val, ThreadID tid) -{ - commit.setNextPC(val, tid); -} - -template <class Impl> -uint64_t -FullO3CPU<Impl>::readNextNPC(ThreadID tid) -{ - return commit.readNextNPC(tid); -} - -template <class Impl> -void -FullO3CPU<Impl>::setNextNPC(uint64_t val, ThreadID tid) -{ - commit.setNextNPC(val, tid); -} - -template <class Impl> -uint64_t -FullO3CPU<Impl>::readNextMicroPC(ThreadID tid) -{ - return commit.readNextMicroPC(tid); -} - -template <class Impl> -void -FullO3CPU<Impl>::setNextMicroPC(Addr new_PC, ThreadID tid) +MicroPC +FullO3CPU<Impl>::microPC(ThreadID tid) { - commit.setNextMicroPC(new_PC, tid); + return commit.microPC(tid); } template <class Impl> @@ -1419,9 +1382,9 @@ template <class Impl> void FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) { - DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x " + DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s " "[sn:%lli]\n", - inst->threadNumber, inst->readPC(), inst->seqNum); + inst->threadNumber, inst->pcState(), inst->seqNum); removeInstsThisCycle = true; @@ -1509,10 +1472,10 @@ FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid) { if ((*instIt)->threadNumber == tid) { DPRINTF(O3CPU, "Squashing instruction, " - "[tid:%i] [sn:%lli] PC %#x\n", + "[tid:%i] [sn:%lli] PC %s\n", (*instIt)->threadNumber, (*instIt)->seqNum, - (*instIt)->readPC()); + (*instIt)->pcState()); // Mark it as squashed. (*instIt)->setSquashed(); @@ -1530,10 +1493,10 @@ FullO3CPU<Impl>::cleanUpRemovedInsts() { while (!removeList.empty()) { DPRINTF(O3CPU, "Removing instruction, " - "[tid:%i] [sn:%lli] PC %#x\n", + "[tid:%i] [sn:%lli] PC %s\n", (*removeList.front())->threadNumber, (*removeList.front())->seqNum, - (*removeList.front())->readPC()); + (*removeList.front())->pcState()); instList.erase(removeList.front()); @@ -1563,7 +1526,7 @@ FullO3CPU<Impl>::dumpInsts() while (inst_list_it != instList.end()) { cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" "Squashed:%i\n\n", - num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, + num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber, (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), (*inst_list_it)->isSquashed()); inst_list_it++; diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 57c07a9ec..2669016ff 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -444,35 +444,20 @@ class FullO3CPU : public BaseO3CPU void setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid); - /** Reads the commit PC of a specific thread. */ - Addr readPC(ThreadID tid); + /** Sets the commit PC state of a specific thread. */ + void pcState(const TheISA::PCState &newPCState, ThreadID tid); - /** Sets the commit PC of a specific thread. */ - void setPC(Addr new_PC, ThreadID tid); + /** Reads the commit PC state of a specific thread. */ + TheISA::PCState pcState(ThreadID tid); - /** Reads the commit micro PC of a specific thread. */ - Addr readMicroPC(ThreadID tid); + /** Reads the commit PC of a specific thread. */ + Addr instAddr(ThreadID tid); - /** Sets the commmit micro PC of a specific thread. */ - void setMicroPC(Addr new_microPC, ThreadID tid); + /** Reads the commit micro PC of a specific thread. */ + MicroPC microPC(ThreadID tid); /** Reads the next PC of a specific thread. */ - Addr readNextPC(ThreadID tid); - - /** Sets the next PC of a specific thread. */ - void setNextPC(Addr val, ThreadID tid); - - /** Reads the next NPC of a specific thread. */ - Addr readNextNPC(ThreadID tid); - - /** Sets the next NPC of a specific thread. */ - void setNextNPC(Addr val, ThreadID tid); - - /** Reads the commit next micro PC of a specific thread. */ - Addr readNextMicroPC(ThreadID tid); - - /** Sets the commit next micro PC of a specific thread. */ - void setNextMicroPC(Addr val, ThreadID tid); + Addr nextInstAddr(ThreadID tid); /** Initiates a squash of all in-flight instructions for a given * thread. The source of the squash is an external update of diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh index 1b76de132..5063e0f07 100644 --- a/src/cpu/o3/decode_impl.hh +++ b/src/cpu/o3/decode_impl.hh @@ -264,29 +264,16 @@ template<class Impl> void DefaultDecode<Impl>::squash(DynInstPtr &inst, ThreadID tid) { - DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch prediction " - "detected at decode.\n", tid, inst->seqNum); + DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch " + "prediction detected at decode.\n", tid, inst->seqNum); // Send back mispredict information. toFetch->decodeInfo[tid].branchMispredict = true; toFetch->decodeInfo[tid].predIncorrect = true; toFetch->decodeInfo[tid].squash = true; toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum; - toFetch->decodeInfo[tid].nextMicroPC = inst->readMicroPC(); - -#if ISA_HAS_DELAY_SLOT - toFetch->decodeInfo[tid].nextPC = inst->readPC() + sizeof(TheISA::MachInst); - toFetch->decodeInfo[tid].nextNPC = inst->branchTarget(); - toFetch->decodeInfo[tid].branchTaken = inst->readNextNPC() != - (inst->readNextPC() + sizeof(TheISA::MachInst)); -#else toFetch->decodeInfo[tid].nextPC = inst->branchTarget(); - toFetch->decodeInfo[tid].nextNPC = - inst->branchTarget() + sizeof(TheISA::MachInst); - toFetch->decodeInfo[tid].branchTaken = - inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst)); -#endif - + toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching(); InstSeqNum squash_seq_num = inst->seqNum; @@ -382,8 +369,8 @@ DefaultDecode<Impl>::skidInsert(ThreadID tid) assert(tid == inst->threadNumber); - DPRINTF(Decode,"Inserting [sn:%lli] PC:%#x into decode skidBuffer %i\n", - inst->seqNum, inst->readPC(), inst->threadNumber); + DPRINTF(Decode,"Inserting [sn:%lli] PC: %s into decode skidBuffer %i\n", + inst->seqNum, inst->pcState(), inst->threadNumber); skidBuffer[tid].push(inst); } @@ -681,13 +668,12 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid) insts_to_decode.pop(); DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with " - "PC %#x\n", - tid, inst->seqNum, inst->readPC()); + "PC %s\n", tid, inst->seqNum, inst->pcState()); if (inst->isSquashed()) { - DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %#x is " + DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %s is " "squashed, skipping.\n", - tid, inst->seqNum, inst->readPC()); + tid, inst->seqNum, inst->pcState()); ++decodeSquashedInsts; @@ -717,9 +703,6 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid) // Ensure that if it was predicted as a branch, it really is a // branch. if (inst->readPredTaken() && !inst->isControl()) { - DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n", - inst->readPredPC(), inst->readNextPC() + 4); - panic("Instruction predicted as a branch!"); ++decodeControlMispred; @@ -735,26 +718,18 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid) if (inst->isDirectCtrl() && inst->isUncondCtrl()) { ++decodeBranchResolved; - if (inst->branchTarget() != inst->readPredPC()) { + if (!(inst->branchTarget() == inst->readPredTarg())) { ++decodeBranchMispred; // Might want to set some sort of boolean and just do // a check at the end squash(inst, inst->threadNumber); - Addr target = inst->branchTarget(); + TheISA::PCState target = inst->branchTarget(); -#if ISA_HAS_DELAY_SLOT - DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %#x PredNextPC: %#x\n", - inst->seqNum, inst->readPC() + sizeof(TheISA::MachInst), target); - - //The micro pc after an instruction level branch should be 0 - inst->setPredTarg(inst->readPC() + sizeof(TheISA::MachInst), target, 0); -#else - DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %#x PredNextPC: %#x\n", - inst->seqNum, target, target + sizeof(TheISA::MachInst)); + DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %s\n", + inst->seqNum, target); //The micro pc after an instruction level branch should be 0 - inst->setPredTarg(target, target + sizeof(TheISA::MachInst), 0); -#endif + inst->setPredTarg(target); break; } } diff --git a/src/cpu/o3/dep_graph.hh b/src/cpu/o3/dep_graph.hh index c19fd0abf..804b3f9cd 100644 --- a/src/cpu/o3/dep_graph.hh +++ b/src/cpu/o3/dep_graph.hh @@ -251,8 +251,8 @@ DependencyGraph<DynInstPtr>::dump() curr = &dependGraph[i]; if (curr->inst) { - cprintf("dependGraph[%i]: producer: %#x [sn:%lli] consumer: ", - i, curr->inst->readPC(), curr->inst->seqNum); + cprintf("dependGraph[%i]: producer: %s [sn:%lli] consumer: ", + i, curr->inst->pcState(), curr->inst->seqNum); } else { cprintf("dependGraph[%i]: No producer. consumer: ", i); } @@ -260,8 +260,8 @@ DependencyGraph<DynInstPtr>::dump() while (curr->next != NULL) { curr = curr->next; - cprintf("%#x [sn:%lli] ", - curr->inst->readPC(), curr->inst->seqNum); + cprintf("%s [sn:%lli] ", + curr->inst->pcState(), curr->inst->seqNum); } cprintf("\n"); diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index e1279f82b..6bd1f9fad 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -74,14 +74,14 @@ class BaseO3DynInst : public BaseDynInst<Impl> public: /** BaseDynInst constructor given a binary instruction. */ - BaseO3DynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu); + BaseO3DynInst(StaticInstPtr staticInst, + TheISA::PCState pc, TheISA::PCState predPC, + InstSeqNum seq_num, O3CPU *cpu); /** BaseDynInst constructor given a binary instruction. */ - BaseO3DynInst(ExtMachInst inst, Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu); + BaseO3DynInst(ExtMachInst inst, + TheISA::PCState pc, TheISA::PCState predPC, + InstSeqNum seq_num, O3CPU *cpu); /** BaseDynInst constructor given a static inst pointer. */ BaseO3DynInst(StaticInstPtr &_staticInst); diff --git a/src/cpu/o3/dyn_inst_impl.hh b/src/cpu/o3/dyn_inst_impl.hh index 3e015d962..6f7c23b2f 100644 --- a/src/cpu/o3/dyn_inst_impl.hh +++ b/src/cpu/o3/dyn_inst_impl.hh @@ -33,24 +33,18 @@ template <class Impl> BaseO3DynInst<Impl>::BaseO3DynInst(StaticInstPtr staticInst, - Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, - Addr Pred_MicroPC, + TheISA::PCState pc, TheISA::PCState predPC, InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst<Impl>(staticInst, PC, NPC, microPC, - Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu) + : BaseDynInst<Impl>(staticInst, pc, predPC, seq_num, cpu) { initVars(); } template <class Impl> BaseO3DynInst<Impl>::BaseO3DynInst(ExtMachInst inst, - Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, - Addr Pred_MicroPC, + TheISA::PCState pc, TheISA::PCState predPC, InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst<Impl>(inst, PC, NPC, microPC, - Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu) + : BaseDynInst<Impl>(inst, pc, predPC, seq_num, cpu) { initVars(); } @@ -131,15 +125,17 @@ BaseO3DynInst<Impl>::hwrei() { #if THE_ISA == ALPHA_ISA // Can only do a hwrei when in pal mode. - if (!(this->readPC() & 0x3)) + if (!(this->instAddr() & 0x3)) return new AlphaISA::UnimplementedOpcodeFault; // Set the next PC based on the value of the EXC_ADDR IPR. - this->setNextPC(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, - this->threadNumber)); + AlphaISA::PCState pc = this->pcState(); + pc.npc(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, + this->threadNumber)); + this->pcState(pc); if (CPA::available()) { ThreadContext *tc = this->cpu->tcBase(this->threadNumber); - CPA::cpa()->swAutoBegin(tc, this->readNextPC()); + CPA::cpa()->swAutoBegin(tc, this->nextInstAddr()); } // Tell CPU to clear any state it needs to if a hwrei is taken. @@ -175,11 +171,11 @@ BaseO3DynInst<Impl>::syscall(int64_t callnum) // HACK: check CPU's nextPC before and after syscall. If it // changes, update this instruction's nextPC because the syscall // must have changed the nextPC. - Addr cpu_next_pc = this->cpu->readNextPC(this->threadNumber); + TheISA::PCState curPC = this->cpu->pcState(this->threadNumber); this->cpu->syscall(callnum, this->threadNumber); - Addr new_next_pc = this->cpu->readNextPC(this->threadNumber); - if (cpu_next_pc != new_next_pc) { - this->setNextPC(new_next_pc); + TheISA::PCState newPC = this->cpu->pcState(this->threadNumber); + if (!(curPC == newPC)) { + this->pcState(newPC); } } #endif diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index d881c291f..22e9e51b4 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -229,7 +229,7 @@ class DefaultFetch * @param next_NPC Used for ISAs which use delay slots. * @return Whether or not a branch was predicted as taken. */ - bool lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, Addr &next_NPC, Addr &next_MicroPC); + bool lookupAndUpdateNextPC(DynInstPtr &inst, TheISA::PCState &pc); /** * Fetches the cache line that contains fetch_PC. Returns any @@ -244,14 +244,12 @@ class DefaultFetch bool fetchCacheLine(Addr fetch_PC, Fault &ret_fault, ThreadID tid); /** Squashes a specific thread and resets the PC. */ - inline void doSquash(const Addr &new_PC, const Addr &new_NPC, - const Addr &new_MicroPC, ThreadID tid); + inline void doSquash(const TheISA::PCState &newPC, ThreadID tid); /** Squashes a specific thread and resets the PC. Also tells the CPU to * remove any instructions between fetch and decode that should be sqaushed. */ - void squashFromDecode(const Addr &new_PC, const Addr &new_NPC, - const Addr &new_MicroPC, + void squashFromDecode(const TheISA::PCState &newPC, const InstSeqNum &seq_num, ThreadID tid); /** Checks if a thread is stalled. */ @@ -266,8 +264,7 @@ class DefaultFetch * remove any instructions that are not in the ROB. The source of this * squash should be the commit stage. */ - void squash(const Addr &new_PC, const Addr &new_NPC, - const Addr &new_MicroPC, + void squash(const TheISA::PCState &newPC, const InstSeqNum &seq_num, ThreadID tid); /** Ticks the fetch stage, processing all inputs signals and fetching @@ -348,14 +345,7 @@ class DefaultFetch /** Predecoder. */ TheISA::Predecoder predecoder; - /** Per-thread fetch PC. */ - Addr PC[Impl::MaxThreads]; - - /** Per-thread fetch micro PC. */ - Addr microPC[Impl::MaxThreads]; - - /** Per-thread next PC. */ - Addr nextPC[Impl::MaxThreads]; + TheISA::PCState pc[Impl::MaxThreads]; /** Memory request used to access cache. */ RequestPtr memReq[Impl::MaxThreads]; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 3f8f84cab..bbd9ce4a2 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -316,9 +316,7 @@ DefaultFetch<Impl>::initStage() { // Setup PC and nextPC with initial state. for (ThreadID tid = 0; tid < numThreads; tid++) { - PC[tid] = cpu->readPC(tid); - nextPC[tid] = cpu->readNextPC(tid); - microPC[tid] = cpu->readMicroPC(tid); + pc[tid] = cpu->pcState(tid); } for (ThreadID tid = 0; tid < numThreads; tid++) { @@ -445,9 +443,7 @@ DefaultFetch<Impl>::takeOverFrom() stalls[i].rename = 0; stalls[i].iew = 0; stalls[i].commit = 0; - PC[i] = cpu->readPC(i); - nextPC[i] = cpu->readNextPC(i); - microPC[i] = cpu->readMicroPC(i); + pc[i] = cpu->pcState(i); fetchStatus[i] = Running; } numInst = 0; @@ -496,8 +492,8 @@ DefaultFetch<Impl>::switchToInactive() template <class Impl> bool -DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, - Addr &next_NPC, Addr &next_MicroPC) +DefaultFetch<Impl>::lookupAndUpdateNextPC( + DynInstPtr &inst, TheISA::PCState &nextPC) { // Do branch prediction check here. // A bit of a misnomer...next_PC is actually the current PC until @@ -505,51 +501,26 @@ DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, bool predict_taken; if (!inst->isControl()) { - if (inst->isMicroop() && !inst->isLastMicroop()) { - next_MicroPC++; - } else { - next_PC = next_NPC; - next_NPC = next_NPC + instSize; - next_MicroPC = 0; - } - inst->setPredTarg(next_PC, next_NPC, next_MicroPC); + TheISA::advancePC(nextPC, inst->staticInst); + inst->setPredTarg(nextPC); inst->setPredTaken(false); return false; } - //Assume for now that all control flow is to a different macroop which - //would reset the micro pc to 0. - next_MicroPC = 0; - ThreadID tid = inst->threadNumber; - Addr pred_PC = next_PC; - predict_taken = branchPred.predict(inst, pred_PC, tid); + predict_taken = branchPred.predict(inst, nextPC, tid); if (predict_taken) { - DPRINTF(Fetch, "[tid:%i]: [sn:%i]: Branch predicted to be taken to %#x.\n", - tid, inst->seqNum, pred_PC); + DPRINTF(Fetch, "[tid:%i]: [sn:%i]: Branch predicted to be taken to %s.\n", + tid, inst->seqNum, nextPC); } else { DPRINTF(Fetch, "[tid:%i]: [sn:%i]:Branch predicted to be not taken.\n", tid, inst->seqNum); } -#if ISA_HAS_DELAY_SLOT - next_PC = next_NPC; - if (predict_taken) - next_NPC = pred_PC; - else - next_NPC += instSize; -#else - if (predict_taken) - next_PC = pred_PC; - else - next_PC += instSize; - next_NPC = next_PC + instSize; -#endif - - DPRINTF(Fetch, "[tid:%i]: [sn:%i] Branch predicted to go to %#x and then %#x.\n", - tid, inst->seqNum, next_PC, next_NPC); - inst->setPredTarg(next_PC, next_NPC, next_MicroPC); + DPRINTF(Fetch, "[tid:%i]: [sn:%i] Branch predicted to go to %s.\n", + tid, inst->seqNum, nextPC); + inst->setPredTarg(nextPC); inst->setPredTaken(predict_taken); ++fetchedBranches; @@ -668,15 +639,12 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, ThreadID tid template <class Impl> inline void -DefaultFetch<Impl>::doSquash(const Addr &new_PC, - const Addr &new_NPC, const Addr &new_microPC, ThreadID tid) +DefaultFetch<Impl>::doSquash(const TheISA::PCState &newPC, ThreadID tid) { - DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %#x, NPC to: %#x.\n", - tid, new_PC, new_NPC); + DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %s.\n", + tid, newPC); - PC[tid] = new_PC; - nextPC[tid] = new_NPC; - microPC[tid] = new_microPC; + pc[tid] = newPC; // Clear the icache miss if it's outstanding. if (fetchStatus[tid] == IcacheWaitResponse) { @@ -703,13 +671,12 @@ DefaultFetch<Impl>::doSquash(const Addr &new_PC, template<class Impl> void -DefaultFetch<Impl>::squashFromDecode(const Addr &new_PC, const Addr &new_NPC, - const Addr &new_MicroPC, +DefaultFetch<Impl>::squashFromDecode(const TheISA::PCState &newPC, const InstSeqNum &seq_num, ThreadID tid) { - DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n",tid); + DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n", tid); - doSquash(new_PC, new_NPC, new_MicroPC, tid); + doSquash(newPC, tid); // Tell the CPU to remove any instructions that are in flight between // fetch and decode. @@ -784,13 +751,12 @@ DefaultFetch<Impl>::updateFetchStatus() template <class Impl> void -DefaultFetch<Impl>::squash(const Addr &new_PC, const Addr &new_NPC, - const Addr &new_MicroPC, +DefaultFetch<Impl>::squash(const TheISA::PCState &newPC, const InstSeqNum &seq_num, ThreadID tid) { - DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n",tid); + DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n", tid); - doSquash(new_PC, new_NPC, new_MicroPC, tid); + doSquash(newPC, tid); // Tell the CPU to remove any instructions that are not in the ROB. cpu->removeInstsNotInROB(tid); @@ -903,16 +869,14 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(ThreadID tid) DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash " "from commit.\n",tid); // In any case, squash. - squash(fromCommit->commitInfo[tid].nextPC, - fromCommit->commitInfo[tid].nextNPC, - fromCommit->commitInfo[tid].nextMicroPC, + squash(fromCommit->commitInfo[tid].pc, fromCommit->commitInfo[tid].doneSeqNum, tid); // Also check if there's a mispredict that happened. if (fromCommit->commitInfo[tid].branchMispredict) { branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum, - fromCommit->commitInfo[tid].nextPC, + fromCommit->commitInfo[tid].pc, fromCommit->commitInfo[tid].branchTaken, tid); } else { @@ -955,13 +919,10 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(ThreadID tid) if (fetchStatus[tid] != Squashing) { - DPRINTF(Fetch, "Squashing from decode with PC = %#x, NPC = %#x\n", - fromDecode->decodeInfo[tid].nextPC, - fromDecode->decodeInfo[tid].nextNPC); + TheISA::PCState nextPC = fromDecode->decodeInfo[tid].nextPC; + DPRINTF(Fetch, "Squashing from decode with PC = %s\n", nextPC); // Squash unless we're already squashing squashFromDecode(fromDecode->decodeInfo[tid].nextPC, - fromDecode->decodeInfo[tid].nextNPC, - fromDecode->decodeInfo[tid].nextMicroPC, fromDecode->decodeInfo[tid].doneSeqNum, tid); @@ -1016,9 +977,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) DPRINTF(Fetch, "Attempting to fetch from [tid:%i]\n", tid); // The current PC. - Addr fetch_PC = PC[tid]; - Addr fetch_NPC = nextPC[tid]; - Addr fetch_MicroPC = microPC[tid]; + TheISA::PCState fetchPC = pc[tid]; // Fault code for memory access. Fault fault = NoFault; @@ -1034,10 +993,9 @@ DefaultFetch<Impl>::fetch(bool &status_change) status_change = true; } else if (fetchStatus[tid] == Running) { DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read " - "instruction, starting at PC %08p.\n", - tid, fetch_PC); + "instruction, starting at PC %s.\n", tid, fetchPC); - bool fetch_success = fetchCacheLine(fetch_PC, fault, tid); + bool fetch_success = fetchCacheLine(fetchPC.instAddr(), fault, tid); if (!fetch_success) { if (cacheBlocked) { ++icacheStallCycles; @@ -1075,20 +1033,21 @@ DefaultFetch<Impl>::fetch(bool &status_change) return; } - Addr next_PC = fetch_PC; - Addr next_NPC = fetch_NPC; - Addr next_MicroPC = fetch_MicroPC; + TheISA::PCState nextPC = fetchPC; InstSeqNum inst_seq; MachInst inst; ExtMachInst ext_inst; - // @todo: Fix this hack. - unsigned offset = (fetch_PC & cacheBlkMask) & ~3; StaticInstPtr staticInst = NULL; StaticInstPtr macroop = NULL; if (fault == NoFault) { + //XXX Masking out pal mode bit. This will break x86. Alpha needs + //to pull the pal mode bit ouf ot the instruction address. + unsigned offset = (fetchPC.instAddr() & ~1) - cacheDataPC[tid]; + assert(offset < cacheBlkSize); + // If the read of the first instruction was successful, then grab the // instructions from the rest of the cache line and put them into the // queue heading to decode. @@ -1104,15 +1063,6 @@ DefaultFetch<Impl>::fetch(bool &status_change) numInst < fetchWidth && !predicted_branch) { - // If we're branching after this instruction, quite fetching - // from the same block then. - predicted_branch = - (fetch_PC + sizeof(TheISA::MachInst) != fetch_NPC); - if (predicted_branch) { - DPRINTF(Fetch, "Branch detected with PC = %#x, NPC = %#x\n", - fetch_PC, fetch_NPC); - } - // Make sure this is a valid index. assert(offset <= cacheBlkSize - instSize); @@ -1122,16 +1072,16 @@ DefaultFetch<Impl>::fetch(bool &status_change) (&cacheData[tid][offset])); predecoder.setTC(cpu->thread[tid]->getTC()); - predecoder.moreBytes(fetch_PC, fetch_PC, inst); + predecoder.moreBytes(fetchPC, fetchPC.instAddr(), inst); - ext_inst = predecoder.getExtMachInst(); - staticInst = StaticInstPtr(ext_inst, fetch_PC); + ext_inst = predecoder.getExtMachInst(fetchPC); + staticInst = StaticInstPtr(ext_inst, fetchPC.instAddr()); if (staticInst->isMacroop()) macroop = staticInst; } do { if (macroop) { - staticInst = macroop->fetchMicroop(fetch_MicroPC); + staticInst = macroop->fetchMicroop(fetchPC.microPC()); if (staticInst->isLastMicroop()) macroop = NULL; } @@ -1141,8 +1091,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) // Create a new DynInst from the instruction fetched. DynInstPtr instruction = new DynInst(staticInst, - fetch_PC, fetch_NPC, fetch_MicroPC, - next_PC, next_NPC, next_MicroPC, + fetchPC, nextPC, inst_seq, cpu); instruction->setTid(tid); @@ -1150,27 +1099,32 @@ DefaultFetch<Impl>::fetch(bool &status_change) instruction->setThreadState(cpu->thread[tid]); - DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x (%d) created " - "[sn:%lli]\n", tid, instruction->readPC(), - instruction->readMicroPC(), inst_seq); + DPRINTF(Fetch, "[tid:%i]: Instruction PC %s (%d) created " + "[sn:%lli]\n", tid, instruction->pcState(), + instruction->microPC(), inst_seq); //DPRINTF(Fetch, "[tid:%i]: MachInst is %#x\n", tid, ext_inst); - DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", - tid, instruction->staticInst->disassemble(fetch_PC)); + DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", tid, + instruction->staticInst-> + disassemble(fetchPC.instAddr())); #if TRACING_ON instruction->traceData = cpu->getTracer()->getInstRecord(curTick, cpu->tcBase(tid), - instruction->staticInst, instruction->readPC(), - macroop, instruction->readMicroPC()); + instruction->staticInst, fetchPC, macroop); #else instruction->traceData = NULL; #endif - ///FIXME This needs to be more robust in dealing with delay slots + // If we're branching after this instruction, quite fetching + // from the same block then. + predicted_branch = fetchPC.branching(); predicted_branch |= - lookupAndUpdateNextPC(instruction, next_PC, next_NPC, next_MicroPC); + lookupAndUpdateNextPC(instruction, nextPC); + if (predicted_branch) { + DPRINTF(Fetch, "Branch detected with PC = %s\n", fetchPC); + } // Add instruction to the CPU's list of instructions. instruction->setInstListIt(cpu->addInst(instruction)); @@ -1185,9 +1139,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) ++fetchedInsts; // Move to the next instruction, unless we have a branch. - fetch_PC = next_PC; - fetch_NPC = next_NPC; - fetch_MicroPC = next_MicroPC; + fetchPC = nextPC; if (instruction->isQuiesce()) { DPRINTF(Fetch, "Quiesce instruction encountered, halting fetch!", @@ -1202,7 +1154,8 @@ DefaultFetch<Impl>::fetch(bool &status_change) } while (staticInst->isMicroop() && !staticInst->isLastMicroop() && numInst < fetchWidth); - offset += instSize; + //XXX Masking out pal mode bit. + offset = (fetchPC.instAddr() & ~1) - cacheDataPC[tid]; } if (predicted_branch) { @@ -1224,10 +1177,8 @@ DefaultFetch<Impl>::fetch(bool &status_change) // Now that fetching is completed, update the PC to signify what the next // cycle will be. if (fault == NoFault) { - PC[tid] = next_PC; - nextPC[tid] = next_NPC; - microPC[tid] = next_MicroPC; - DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n", tid, next_PC); + pc[tid] = nextPC; + DPRINTF(Fetch, "[tid:%i]: Setting PC to %s.\n", tid, nextPC); } else { // We shouldn't be in an icache miss and also have a fault (an ITB // miss) @@ -1245,11 +1196,10 @@ DefaultFetch<Impl>::fetch(bool &status_change) ext_inst = TheISA::NoopMachInst; // Create a new DynInst from the dummy nop. - DynInstPtr instruction = new DynInst(ext_inst, - fetch_PC, fetch_NPC, fetch_MicroPC, - next_PC, next_NPC, next_MicroPC, + DynInstPtr instruction = new DynInst(ext_inst, fetchPC, nextPC, inst_seq, cpu); - instruction->setPredTarg(next_NPC, next_NPC + instSize, 0); + TheISA::advancePC(nextPC, instruction->staticInst); + instruction->setPredTarg(nextPC); instruction->setTid(tid); instruction->setASID(tid); @@ -1272,8 +1222,8 @@ DefaultFetch<Impl>::fetch(bool &status_change) fetchStatus[tid] = TrapPending; status_change = true; - DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %08p", - tid, fault->name(), PC[tid]); + DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %s", + tid, fault->name(), pc[tid]); } } diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index 2089913ef..608e70cde 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -449,27 +449,18 @@ template<class Impl> void DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, ThreadID tid) { - DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %#x " - "[sn:%i].\n", tid, inst->readPC(), inst->seqNum); + DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %s " + "[sn:%i].\n", tid, inst->pcState(), inst->seqNum); toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; - toCommit->mispredPC[tid] = inst->readPC(); + toCommit->mispredPC[tid] = inst->instAddr(); toCommit->branchMispredict[tid] = true; -#if ISA_HAS_DELAY_SLOT - int instSize = sizeof(TheISA::MachInst); - toCommit->branchTaken[tid] = - !(inst->readNextPC() + instSize == inst->readNextNPC() && - (inst->readNextPC() == inst->readPC() + instSize || - inst->readNextPC() == inst->readPC() + 2 * instSize)); -#else - toCommit->branchTaken[tid] = inst->readNextPC() != - (inst->readPC() + sizeof(TheISA::MachInst)); -#endif - toCommit->nextPC[tid] = inst->readNextPC(); - toCommit->nextNPC[tid] = inst->readNextNPC(); - toCommit->nextMicroPC[tid] = inst->readNextMicroPC(); + toCommit->branchTaken[tid] = inst->pcState().branching(); + TheISA::PCState pc = inst->pcState(); + TheISA::advancePC(pc, inst->staticInst); + toCommit->pc[tid] = pc; toCommit->includeSquashInst[tid] = false; @@ -481,12 +472,13 @@ void DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, ThreadID tid) { DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, " - "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum); + "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum); toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; - toCommit->nextPC[tid] = inst->readNextPC(); - toCommit->nextNPC[tid] = inst->readNextNPC(); + TheISA::PCState pc = inst->pcState(); + TheISA::advancePC(pc, inst->staticInst); + toCommit->pc[tid] = pc; toCommit->branchMispredict[tid] = false; toCommit->includeSquashInst[tid] = false; @@ -499,12 +491,11 @@ void DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, ThreadID tid) { DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, " - "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum); + "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum); toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; - toCommit->nextPC[tid] = inst->readPC(); - toCommit->nextNPC[tid] = inst->readNextPC(); + toCommit->pc[tid] = inst->pcState(); toCommit->branchMispredict[tid] = false; // Must include the broadcasted SN in the squash. @@ -628,9 +619,9 @@ DefaultIEW<Impl>::skidInsert(ThreadID tid) insts[tid].pop(); - DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%#x into " + DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%s into " "dispatch skidBuffer %i\n",tid, inst->seqNum, - inst->readPC(),tid); + inst->pcState(),tid); skidBuffer[tid].push(inst); } @@ -986,9 +977,9 @@ DefaultIEW<Impl>::dispatchInsts(ThreadID tid) // Make sure there's a valid instruction there. assert(inst); - DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %#x [sn:%lli] [tid:%i] to " + DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %s [sn:%lli] [tid:%i] to " "IQ.\n", - tid, inst->readPC(), inst->seqNum, inst->threadNumber); + tid, inst->pcState(), inst->seqNum, inst->threadNumber); // Be sure to mark these instructions as ready so that the // commit stage can go ahead and execute them, and mark @@ -1165,7 +1156,7 @@ DefaultIEW<Impl>::printAvailableInsts() if (inst%3==0) std::cout << "\n\t"; - std::cout << "PC: " << fromIssue->insts[inst]->readPC() + std::cout << "PC: " << fromIssue->insts[inst]->pcState() << " TN: " << fromIssue->insts[inst]->threadNumber << " SN: " << fromIssue->insts[inst]->seqNum << " | "; @@ -1205,8 +1196,8 @@ DefaultIEW<Impl>::executeInsts() DynInstPtr inst = instQueue.getInstToExecute(); - DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n", - inst->readPC(), inst->threadNumber,inst->seqNum); + DPRINTF(IEW, "Execute: Processing PC %s, [tid:%i] [sn:%i].\n", + inst->pcState(), inst->threadNumber,inst->seqNum); // Check if the instruction is squashed; if so then skip it if (inst->isSquashed()) { @@ -1298,10 +1289,9 @@ DefaultIEW<Impl>::executeInsts() DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n", - inst->readPredPC(), inst->readPredNPC()); - DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x," - " NPC: %#x.\n", inst->readNextPC(), - inst->readNextNPC()); + inst->predInstAddr(), inst->predNextInstAddr()); + DPRINTF(IEW, "Execute: Redirecting fetch to PC: %s.\n", + inst->pcState(), inst->nextInstAddr()); // If incorrect, then signal the ROB that it must be squashed. squashDueToBranch(inst, tid); @@ -1318,16 +1308,11 @@ DefaultIEW<Impl>::executeInsts() DynInstPtr violator; violator = ldstQueue.getMemDepViolator(tid); - DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %#x " - "[sn:%lli], inst PC: %#x [sn:%lli]. Addr is: %#x.\n", - violator->readPC(), violator->seqNum, - inst->readPC(), inst->seqNum, inst->physEffAddr); - // Ensure the violating instruction is older than - // current squash -/* if (fetchRedirect[tid] && - violator->seqNum >= toCommit->squashedSeqNum[tid] + 1) - continue; -*/ + DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %s " + "[sn:%lli], inst PC: %s [sn:%lli]. Addr is: %#x.\n", + violator->pcState(), violator->seqNum, + inst->pcState(), inst->seqNum, inst->physEffAddr); + fetchRedirect[tid] = true; // Tell the instruction queue that a violation has occured. @@ -1342,8 +1327,8 @@ DefaultIEW<Impl>::executeInsts() fetchRedirect[tid] = true; DPRINTF(IEW, "Load operation couldn't execute because the " - "memory system is blocked. PC: %#x [sn:%lli]\n", - inst->readPC(), inst->seqNum); + "memory system is blocked. PC: %s [sn:%lli]\n", + inst->pcState(), inst->seqNum); squashDueToMemBlocked(inst, tid); } @@ -1356,8 +1341,9 @@ DefaultIEW<Impl>::executeInsts() DynInstPtr violator = ldstQueue.getMemDepViolator(tid); DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: " - "%#x, inst PC: %#x. Addr is: %#x.\n", - violator->readPC(), inst->readPC(), inst->physEffAddr); + "%s, inst PC: %s. Addr is: %#x.\n", + violator->pcState(), inst->pcState(), + inst->physEffAddr); DPRINTF(IEW, "Violation will not be handled because " "already squashing\n"); @@ -1366,8 +1352,8 @@ DefaultIEW<Impl>::executeInsts() if (ldstQueue.loadBlocked(tid) && !ldstQueue.isLoadBlockedHandled(tid)) { DPRINTF(IEW, "Load operation couldn't execute because the " - "memory system is blocked. PC: %#x [sn:%lli]\n", - inst->readPC(), inst->seqNum); + "memory system is blocked. PC: %s [sn:%lli]\n", + inst->pcState(), inst->seqNum); DPRINTF(IEW, "Blocked load will not be handled because " "already squashing\n"); @@ -1408,8 +1394,8 @@ DefaultIEW<Impl>::writebackInsts() DynInstPtr inst = toCommit->insts[inst_num]; ThreadID tid = inst->threadNumber; - DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %#x.\n", - inst->seqNum, inst->readPC()); + DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %s.\n", + inst->seqNum, inst->pcState()); iewInstsToCommit[tid]++; @@ -1613,10 +1599,10 @@ DefaultIEW<Impl>::checkMisprediction(DynInstPtr &inst) DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n", - inst->readPredPC(), inst->readPredNPC()); + inst->predInstAddr(), inst->predNextInstAddr()); DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x," - " NPC: %#x.\n", inst->readNextPC(), - inst->readNextNPC()); + " NPC: %#x.\n", inst->nextInstAddr(), + inst->nextInstAddr()); // If incorrect, then signal the ROB that it must be squashed. squashDueToBranch(inst, tid); diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index 3d5eadf84..b944979f2 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -504,8 +504,8 @@ InstructionQueue<Impl>::insert(DynInstPtr &new_inst) // Make sure the instruction is valid assert(new_inst); - DPRINTF(IQ, "Adding instruction [sn:%lli] PC %#x to the IQ.\n", - new_inst->seqNum, new_inst->readPC()); + DPRINTF(IQ, "Adding instruction [sn:%lli] PC %s to the IQ.\n", + new_inst->seqNum, new_inst->pcState()); assert(freeEntries != 0); @@ -547,9 +547,9 @@ InstructionQueue<Impl>::insertNonSpec(DynInstPtr &new_inst) nonSpecInsts[new_inst->seqNum] = new_inst; - DPRINTF(IQ, "Adding non-speculative instruction [sn:%lli] PC %#x " + DPRINTF(IQ, "Adding non-speculative instruction [sn:%lli] PC %s " "to the IQ.\n", - new_inst->seqNum, new_inst->readPC()); + new_inst->seqNum, new_inst->pcState()); assert(freeEntries != 0); @@ -767,9 +767,9 @@ InstructionQueue<Impl>::scheduleReadyInsts() } } - DPRINTF(IQ, "Thread %i: Issuing instruction PC %#x " + DPRINTF(IQ, "Thread %i: Issuing instruction PC %s " "[sn:%lli]\n", - tid, issuing_inst->readPC(), + tid, issuing_inst->pcState(), issuing_inst->seqNum); readyInsts[op_class].pop(); @@ -910,7 +910,7 @@ InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst) while (dep_inst) { DPRINTF(IQ, "Waking up a dependent instruction, [sn:%lli] " - "PC%#x.\n", dep_inst->seqNum, dep_inst->readPC()); + "PC %s.\n", dep_inst->seqNum, dep_inst->pcState()); // Might want to give more information to the instruction // so that it knows which of its source registers is @@ -955,8 +955,8 @@ InstructionQueue<Impl>::addReadyMemInst(DynInstPtr &ready_inst) } DPRINTF(IQ, "Instruction is ready to issue, putting it onto " - "the ready list, PC %#x opclass:%i [sn:%lli].\n", - ready_inst->readPC(), op_class, ready_inst->seqNum); + "the ready list, PC %s opclass:%i [sn:%lli].\n", + ready_inst->pcState(), op_class, ready_inst->seqNum); } template <class Impl> @@ -981,8 +981,8 @@ InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst) { ThreadID tid = completed_inst->threadNumber; - DPRINTF(IQ, "Completing mem instruction PC:%#x [sn:%lli]\n", - completed_inst->readPC(), completed_inst->seqNum); + DPRINTF(IQ, "Completing mem instruction PC: %s [sn:%lli]\n", + completed_inst->pcState(), completed_inst->seqNum); ++freeEntries; @@ -1050,9 +1050,8 @@ InstructionQueue<Impl>::doSquash(ThreadID tid) (squashed_inst->isMemRef() && !squashed_inst->memOpDone)) { - DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %#x " - "squashed.\n", - tid, squashed_inst->seqNum, squashed_inst->readPC()); + DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %s squashed.\n", + tid, squashed_inst->seqNum, squashed_inst->pcState()); // Remove the instruction from the dependency list. if (!squashed_inst->isNonSpeculative() && @@ -1147,9 +1146,9 @@ InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst) if (src_reg >= numPhysRegs) { continue; } else if (regScoreboard[src_reg] == false) { - DPRINTF(IQ, "Instruction PC %#x has src reg %i that " + DPRINTF(IQ, "Instruction PC %s has src reg %i that " "is being added to the dependency chain.\n", - new_inst->readPC(), src_reg); + new_inst->pcState(), src_reg); dependGraph.insert(src_reg, new_inst); @@ -1157,9 +1156,9 @@ InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst) // was added to the dependency graph. return_val = true; } else { - DPRINTF(IQ, "Instruction PC %#x has src reg %i that " + DPRINTF(IQ, "Instruction PC %s has src reg %i that " "became ready before it reached the IQ.\n", - new_inst->readPC(), src_reg); + new_inst->pcState(), src_reg); // Mark a register ready within the instruction. new_inst->markSrcRegReady(src_reg_idx); } @@ -1228,8 +1227,8 @@ InstructionQueue<Impl>::addIfReady(DynInstPtr &inst) OpClass op_class = inst->opClass(); DPRINTF(IQ, "Instruction is ready to issue, putting it onto " - "the ready list, PC %#x opclass:%i [sn:%lli].\n", - inst->readPC(), op_class, inst->seqNum); + "the ready list, PC %s opclass:%i [sn:%lli].\n", + inst->pcState(), op_class, inst->seqNum); readyInsts[op_class].push(inst); @@ -1299,7 +1298,7 @@ InstructionQueue<Impl>::dumpLists() cprintf("Non speculative list: "); while (non_spec_it != non_spec_end_it) { - cprintf("%#x [sn:%lli]", (*non_spec_it).second->readPC(), + cprintf("%s [sn:%lli]", (*non_spec_it).second->pcState(), (*non_spec_it).second->seqNum); ++non_spec_it; } @@ -1348,9 +1347,9 @@ InstructionQueue<Impl>::dumpInsts() } } - cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" + cprintf("PC: %s\n[sn:%lli]\n[tid:%i]\n" "Issued:%i\nSquashed:%i\n", - (*inst_list_it)->readPC(), + (*inst_list_it)->pcState(), (*inst_list_it)->seqNum, (*inst_list_it)->threadNumber, (*inst_list_it)->isIssued(), @@ -1390,9 +1389,9 @@ InstructionQueue<Impl>::dumpInsts() } } - cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" + cprintf("PC: %s\n[sn:%lli]\n[tid:%i]\n" "Issued:%i\nSquashed:%i\n", - (*inst_list_it)->readPC(), + (*inst_list_it)->pcState(), (*inst_list_it)->seqNum, (*inst_list_it)->threadNumber, (*inst_list_it)->isIssued(), diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index a9047558d..372e76b71 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -530,8 +530,8 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh, (load_idx != loadHead || !load_inst->isAtCommit())) { iewStage->rescheduleMemInst(load_inst); ++lsqRescheduledLoads; - DPRINTF(LSQUnit, "Uncachable load [sn:%lli] PC %#x\n", - load_inst->seqNum, load_inst->readPC()); + DPRINTF(LSQUnit, "Uncachable load [sn:%lli] PC %s\n", + load_inst->seqNum, load_inst->pcState()); // Must delete request now that it wasn't handed off to // memory. This is quite ugly. @todo: Figure out the proper @@ -687,8 +687,8 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh, } // If there's no forwarding case, then go access memory - DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n", - load_inst->seqNum, load_inst->readPC()); + DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %s\n", + load_inst->seqNum, load_inst->pcState()); assert(!load_inst->memData); load_inst->memData = new uint8_t[64]; diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index 8aa7fe397..345d3ea69 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -352,8 +352,8 @@ LSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) assert((loadTail + 1) % LQEntries != loadHead); assert(loads < LQEntries); - DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n", - load_inst->readPC(), loadTail, load_inst->seqNum); + DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n", + load_inst->pcState(), loadTail, load_inst->seqNum); load_inst->lqIdx = loadTail; @@ -378,8 +378,8 @@ LSQUnit<Impl>::insertStore(DynInstPtr &store_inst) assert((storeTail + 1) % SQEntries != storeHead); assert(stores < SQEntries); - DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n", - store_inst->readPC(), storeTail, store_inst->seqNum); + DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n", + store_inst->pcState(), storeTail, store_inst->seqNum); store_inst->sqIdx = storeTail; store_inst->lqIdx = loadTail; @@ -444,8 +444,8 @@ LSQUnit<Impl>::executeLoad(DynInstPtr &inst) // Execute a specific load. Fault load_fault = NoFault; - DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n", - inst->readPC(),inst->seqNum); + DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n", + inst->pcState(),inst->seqNum); assert(!inst->isSquashed()); @@ -519,8 +519,8 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst) int store_idx = store_inst->sqIdx; - DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n", - store_inst->readPC(), store_inst->seqNum); + DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n", + store_inst->pcState(), store_inst->seqNum); assert(!store_inst->isSquashed()); @@ -531,8 +531,8 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst) Fault store_fault = store_inst->initiateAcc(); if (storeQueue[store_idx].size == 0) { - DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n", - store_inst->readPC(),store_inst->seqNum); + DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli],Size = 0\n", + store_inst->pcState(), store_inst->seqNum); return store_fault; } @@ -593,8 +593,8 @@ LSQUnit<Impl>::commitLoad() { assert(loadQueue[loadHead]); - DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n", - loadQueue[loadHead]->readPC()); + DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n", + loadQueue[loadHead]->pcState()); loadQueue[loadHead] = NULL; @@ -631,8 +631,8 @@ LSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) break; } DPRINTF(LSQUnit, "Marking store as able to write back, PC " - "%#x [sn:%lli]\n", - storeQueue[store_idx].inst->readPC(), + "%s [sn:%lli]\n", + storeQueue[store_idx].inst->pcState(), storeQueue[store_idx].inst->seqNum); storeQueue[store_idx].canWB = true; @@ -757,9 +757,9 @@ LSQUnit<Impl>::writebackStores() req = sreqLow; } - DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " + DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s " "to Addr:%#x, data:%#x [sn:%lli]\n", - storeWBIdx, inst->readPC(), + storeWBIdx, inst->pcState(), req->getPaddr(), (int)*(inst->memData), inst->seqNum); @@ -861,9 +861,9 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num) decrLdIdx(load_idx); while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { - DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, " + DPRINTF(LSQUnit,"Load Instruction PC %s squashed, " "[sn:%lli]\n", - loadQueue[load_idx]->readPC(), + loadQueue[load_idx]->pcState(), loadQueue[load_idx]->seqNum); if (isStalled() && load_idx == stallingLoadIdx) { @@ -906,9 +906,9 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num) break; } - DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, " + DPRINTF(LSQUnit,"Store Instruction PC %s squashed, " "idx:%i [sn:%lli]\n", - storeQueue[store_idx].inst->readPC(), + storeQueue[store_idx].inst->pcState(), store_idx, storeQueue[store_idx].inst->seqNum); // I don't think this can happen. It should have been cleared @@ -1156,7 +1156,7 @@ LSQUnit<Impl>::dumpInsts() int load_idx = loadHead; while (load_idx != loadTail && loadQueue[load_idx]) { - cprintf("%#x ", loadQueue[load_idx]->readPC()); + cprintf("%s ", loadQueue[load_idx]->pcState()); incrLdIdx(load_idx); } @@ -1167,7 +1167,7 @@ LSQUnit<Impl>::dumpInsts() int store_idx = storeHead; while (store_idx != storeTail && storeQueue[store_idx].inst) { - cprintf("%#x ", storeQueue[store_idx].inst->readPC()); + cprintf("%s ", storeQueue[store_idx].inst->pcState()); incrStIdx(store_idx); } diff --git a/src/cpu/o3/mem_dep_unit_impl.hh b/src/cpu/o3/mem_dep_unit_impl.hh index 5f5e71624..fdea84ed5 100644 --- a/src/cpu/o3/mem_dep_unit_impl.hh +++ b/src/cpu/o3/mem_dep_unit_impl.hh @@ -171,7 +171,7 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst) storeBarrierSN); producing_store = storeBarrierSN; } else { - producing_store = depPred.checkInst(inst->readPC()); + producing_store = depPred.checkInst(inst->instAddr()); } MemDepEntryPtr store_entry = NULL; @@ -191,7 +191,7 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst) // are ready. if (!store_entry) { DPRINTF(MemDepUnit, "No dependency for inst PC " - "%#x [sn:%lli].\n", inst->readPC(), inst->seqNum); + "%s [sn:%lli].\n", inst->pcState(), inst->seqNum); inst_entry->memDepReady = true; @@ -203,8 +203,8 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst) } else { // Otherwise make the instruction dependent on the store/barrier. DPRINTF(MemDepUnit, "Adding to dependency list; " - "inst PC %#x is dependent on [sn:%lli].\n", - inst->readPC(), producing_store); + "inst PC %s is dependent on [sn:%lli].\n", + inst->pcState(), producing_store); if (inst->readyToIssue()) { inst_entry->regsReady = true; @@ -224,10 +224,10 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst) } if (inst->isStore()) { - DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n", - inst->readPC(), inst->seqNum); + DPRINTF(MemDepUnit, "Inserting store PC %s [sn:%lli].\n", + inst->pcState(), inst->seqNum); - depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber); + depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber); ++insertedStores; } else if (inst->isLoad()) { @@ -260,10 +260,10 @@ MemDepUnit<MemDepPred, Impl>::insertNonSpec(DynInstPtr &inst) // Might want to turn this part into an inline function or something. // It's shared between both insert functions. if (inst->isStore()) { - DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n", - inst->readPC(), inst->seqNum); + DPRINTF(MemDepUnit, "Inserting store PC %s [sn:%lli].\n", + inst->pcState(), inst->seqNum); - depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber); + depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber); ++insertedStores; } else if (inst->isLoad()) { @@ -313,8 +313,8 @@ void MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst) { DPRINTF(MemDepUnit, "Marking registers as ready for " - "instruction PC %#x [sn:%lli].\n", - inst->readPC(), inst->seqNum); + "instruction PC %s [sn:%lli].\n", + inst->pcState(), inst->seqNum); MemDepEntryPtr inst_entry = findInHash(inst); @@ -336,8 +336,8 @@ void MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst) { DPRINTF(MemDepUnit, "Marking non speculative " - "instruction PC %#x as ready [sn:%lli].\n", - inst->readPC(), inst->seqNum); + "instruction PC %s as ready [sn:%lli].\n", + inst->pcState(), inst->seqNum); MemDepEntryPtr inst_entry = findInHash(inst); @@ -363,9 +363,8 @@ MemDepUnit<MemDepPred, Impl>::replay(DynInstPtr &inst) MemDepEntryPtr inst_entry = findInHash(temp_inst); - DPRINTF(MemDepUnit, "Replaying mem instruction PC %#x " - "[sn:%lli].\n", - temp_inst->readPC(), temp_inst->seqNum); + DPRINTF(MemDepUnit, "Replaying mem instruction PC %s [sn:%lli].\n", + temp_inst->pcState(), temp_inst->seqNum); moveToReady(inst_entry); @@ -377,9 +376,8 @@ template <class MemDepPred, class Impl> void MemDepUnit<MemDepPred, Impl>::completed(DynInstPtr &inst) { - DPRINTF(MemDepUnit, "Completed mem instruction PC %#x " - "[sn:%lli].\n", - inst->readPC(), inst->seqNum); + DPRINTF(MemDepUnit, "Completed mem instruction PC %s [sn:%lli].\n", + inst->pcState(), inst->seqNum); ThreadID tid = inst->threadNumber; @@ -507,10 +505,10 @@ MemDepUnit<MemDepPred, Impl>::violation(DynInstPtr &store_inst, DynInstPtr &violating_load) { DPRINTF(MemDepUnit, "Passing violating PCs to store sets," - " load: %#x, store: %#x\n", violating_load->readPC(), - store_inst->readPC()); + " load: %#x, store: %#x\n", violating_load->instAddr(), + store_inst->instAddr()); // Tell the memory dependence unit of the violation. - depPred.violation(violating_load->readPC(), store_inst->readPC()); + depPred.violation(violating_load->instAddr(), store_inst->instAddr()); } template <class MemDepPred, class Impl> @@ -518,9 +516,9 @@ void MemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst) { DPRINTF(MemDepUnit, "Issuing instruction PC %#x [sn:%lli].\n", - inst->readPC(), inst->seqNum); + inst->instAddr(), inst->seqNum); - depPred.issued(inst->readPC(), inst->seqNum, inst->isStore()); + depPred.issued(inst->instAddr(), inst->seqNum, inst->isStore()); } template <class MemDepPred, class Impl> @@ -559,9 +557,9 @@ MemDepUnit<MemDepPred, Impl>::dumpLists() int num = 0; while (inst_list_it != instList[tid].end()) { - cprintf("Instruction:%i\nPC:%#x\n[sn:%i]\n[tid:%i]\nIssued:%i\n" + cprintf("Instruction:%i\nPC: %s\n[sn:%i]\n[tid:%i]\nIssued:%i\n" "Squashed:%i\n\n", - num, (*inst_list_it)->readPC(), + num, (*inst_list_it)->pcState(), (*inst_list_it)->seqNum, (*inst_list_it)->threadNumber, (*inst_list_it)->isIssued(), diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index 7f796c4c8..4b321d099 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -591,15 +591,14 @@ DefaultRename<Impl>::renameInsts(ThreadID tid) insts_to_rename.pop_front(); if (renameStatus[tid] == Unblocking) { - DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%#x from rename " - "skidBuffer\n", - tid, inst->seqNum, inst->readPC()); + DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%s from rename " + "skidBuffer\n", tid, inst->seqNum, inst->pcState()); } if (inst->isSquashed()) { - DPRINTF(Rename, "[tid:%u]: instruction %i with PC %#x is " - "squashed, skipping.\n", - tid, inst->seqNum, inst->readPC()); + DPRINTF(Rename, "[tid:%u]: instruction %i with PC %s is " + "squashed, skipping.\n", tid, inst->seqNum, + inst->pcState()); ++renameSquashedInsts; @@ -610,8 +609,7 @@ DefaultRename<Impl>::renameInsts(ThreadID tid) } DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with " - "PC %#x.\n", - tid, inst->seqNum, inst->readPC()); + "PC %s.\n", tid, inst->seqNum, inst->pcState()); // Handle serializeAfter/serializeBefore instructions. // serializeAfter marks the next instruction as serializeBefore. @@ -716,8 +714,8 @@ DefaultRename<Impl>::skidInsert(ThreadID tid) assert(tid == inst->threadNumber); - DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC:%#x into Rename " - "skidBuffer\n", tid, inst->seqNum, inst->readPC()); + DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC: %s into Rename " + "skidBuffer\n", tid, inst->seqNum, inst->pcState()); ++renameSkidInsts; @@ -731,7 +729,7 @@ DefaultRename<Impl>::skidInsert(ThreadID tid) for(it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++) { warn("[tid:%u]: %s [sn:%i].\n", tid, - (*it)->staticInst->disassemble(inst->readPC()), + (*it)->staticInst->disassemble(inst->instAddr()), (*it)->seqNum); } panic("Skidbuffer Exceeded Max Size"); @@ -1287,8 +1285,7 @@ DefaultRename<Impl>::checkSignalsAndUpdate(ThreadID tid) unblock(tid); DPRINTF(Rename, "[tid:%u]: Processing instruction [%lli] with " - "PC %#x.\n", - tid, serial_inst->seqNum, serial_inst->readPC()); + "PC %s.\n", tid, serial_inst->seqNum, serial_inst->pcState()); // Put instruction into queue here. serial_inst->clearSerializeBefore(); diff --git a/src/cpu/o3/rob_impl.hh b/src/cpu/o3/rob_impl.hh index cf0080b48..37f1c5504 100644 --- a/src/cpu/o3/rob_impl.hh +++ b/src/cpu/o3/rob_impl.hh @@ -204,7 +204,7 @@ ROB<Impl>::insertInst(DynInstPtr &inst) { assert(inst); - DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC()); + DPRINTF(ROB, "Adding inst PC %s to the ROB.\n", inst->pcState()); assert(numInstsInROB != numEntries); @@ -247,7 +247,7 @@ ROB<Impl>::retireHead(ThreadID tid) assert(head_inst->readyToCommit()); DPRINTF(ROB, "[tid:%u]: Retiring head instruction, " - "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(), + "instruction PC %s, [sn:%lli]\n", tid, head_inst->pcState(), head_inst->seqNum); --numInstsInROB; @@ -338,9 +338,9 @@ ROB<Impl>::doSquash(ThreadID tid) (*squashIt[tid])->seqNum > squashedSeqNum[tid]; ++numSquashed) { - DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n", + DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %s, seq num %i.\n", (*squashIt[tid])->threadNumber, - (*squashIt[tid])->readPC(), + (*squashIt[tid])->pcState(), (*squashIt[tid])->seqNum); // Mark the instruction as squashed, and ready to commit so that diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index b7790cfda..4e559000b 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -172,29 +172,24 @@ class O3ThreadContext : public ThreadContext virtual void setFloatRegBits(int reg_idx, FloatRegBits val); - /** Reads this thread's PC. */ - virtual uint64_t readPC() - { return cpu->readPC(thread->threadId()); } - - /** Sets this thread's PC. */ - virtual void setPC(uint64_t val); - - /** Reads this thread's next PC. */ - virtual uint64_t readNextPC() - { return cpu->readNextPC(thread->threadId()); } + /** Reads this thread's PC state. */ + virtual TheISA::PCState pcState() + { return cpu->pcState(thread->threadId()); } - /** Sets this thread's next PC. */ - virtual void setNextPC(uint64_t val); + /** Sets this thread's PC state. */ + virtual void pcState(const TheISA::PCState &val); - virtual uint64_t readMicroPC() - { return cpu->readMicroPC(thread->threadId()); } - - virtual void setMicroPC(uint64_t val); + /** Reads this thread's PC. */ + virtual Addr instAddr() + { return cpu->instAddr(thread->threadId()); } - virtual uint64_t readNextMicroPC() - { return cpu->readNextMicroPC(thread->threadId()); } + /** Reads this thread's next PC. */ + virtual Addr nextInstAddr() + { return cpu->nextInstAddr(thread->threadId()); } - virtual void setNextMicroPC(uint64_t val); + /** Reads this thread's next PC. */ + virtual MicroPC microPC() + { return cpu->microPC(thread->threadId()); } /** Reads a miscellaneous register. */ virtual MiscReg readMiscRegNoEffect(int misc_reg) @@ -247,15 +242,6 @@ class O3ThreadContext : public ThreadContext } #endif - virtual uint64_t readNextNPC() - { - return this->cpu->readNextNPC(this->thread->threadId()); - } - - virtual void setNextNPC(uint64_t val) - { - this->cpu->setNextNPC(val, this->thread->threadId()); - } }; #endif diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 0b7a2b172..367442830 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -248,11 +248,7 @@ O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc) // Then finally set the PC, the next PC, the nextNPC, the micropc, and the // next micropc. - cpu->setPC(tc->readPC(), tid); - cpu->setNextPC(tc->readNextPC(), tid); - cpu->setNextNPC(tc->readNextNPC(), tid); - cpu->setMicroPC(tc->readMicroPC(), tid); - cpu->setNextMicroPC(tc->readNextMicroPC(), tid); + cpu->pcState(tc->pcState(), tid); #if !FULL_SYSTEM this->thread->funcExeInst = tc->readFuncExeInst(); #endif @@ -327,45 +323,9 @@ O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) template <class Impl> void -O3ThreadContext<Impl>::setPC(uint64_t val) +O3ThreadContext<Impl>::pcState(const TheISA::PCState &val) { - cpu->setPC(val, thread->threadId()); - - // Squash if we're not already in a state update mode. - if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->threadId()); - } -} - -template <class Impl> -void -O3ThreadContext<Impl>::setNextPC(uint64_t val) -{ - cpu->setNextPC(val, thread->threadId()); - - // Squash if we're not already in a state update mode. - if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->threadId()); - } -} - -template <class Impl> -void -O3ThreadContext<Impl>::setMicroPC(uint64_t val) -{ - cpu->setMicroPC(val, thread->threadId()); - - // Squash if we're not already in a state update mode. - if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->threadId()); - } -} - -template <class Impl> -void -O3ThreadContext<Impl>::setNextMicroPC(uint64_t val) -{ - cpu->setNextMicroPC(val, thread->threadId()); + cpu->pcState(val, thread->threadId()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { diff --git a/src/cpu/pc_event.cc b/src/cpu/pc_event.cc index 79f5277d5..533d61498 100644 --- a/src/cpu/pc_event.cc +++ b/src/cpu/pc_event.cc @@ -83,7 +83,7 @@ PCEventQueue::schedule(PCEvent *event) bool PCEventQueue::doService(ThreadContext *tc) { - Addr pc = tc->readPC() & ~0x3; + Addr pc = tc->instAddr() & ~0x3; int serviced = 0; range_t range = equal_range(pc); for (iterator i = range.first; i != range.second; ++i) { @@ -91,7 +91,7 @@ PCEventQueue::doService(ThreadContext *tc) // another event. This for example, prevents two invocations // of the SkipFuncEvent. Maybe we should have separate PC // event queues for each processor? - if (pc != (tc->readPC() & ~0x3)) + if (pc != (tc->instAddr() & ~0x3)) continue; DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n", diff --git a/src/cpu/pred/btb.cc b/src/cpu/pred/btb.cc index c6a5e23f9..e87cc6dc2 100644 --- a/src/cpu/pred/btb.cc +++ b/src/cpu/pred/btb.cc @@ -68,25 +68,25 @@ DefaultBTB::reset() inline unsigned -DefaultBTB::getIndex(const Addr &inst_PC) +DefaultBTB::getIndex(Addr instPC) { // Need to shift PC over by the word offset. - return (inst_PC >> instShiftAmt) & idxMask; + return (instPC >> instShiftAmt) & idxMask; } inline Addr -DefaultBTB::getTag(const Addr &inst_PC) +DefaultBTB::getTag(Addr instPC) { - return (inst_PC >> tagShiftAmt) & tagMask; + return (instPC >> tagShiftAmt) & tagMask; } bool -DefaultBTB::valid(const Addr &inst_PC, ThreadID tid) +DefaultBTB::valid(Addr instPC, ThreadID tid) { - unsigned btb_idx = getIndex(inst_PC); + unsigned btb_idx = getIndex(instPC); - Addr inst_tag = getTag(inst_PC); + Addr inst_tag = getTag(instPC); assert(btb_idx < numEntries); @@ -102,12 +102,12 @@ DefaultBTB::valid(const Addr &inst_PC, ThreadID tid) // @todo Create some sort of return struct that has both whether or not the // address is valid, and also the address. For now will just use addr = 0 to // represent invalid entry. -Addr -DefaultBTB::lookup(const Addr &inst_PC, ThreadID tid) +TheISA::PCState +DefaultBTB::lookup(Addr instPC, ThreadID tid) { - unsigned btb_idx = getIndex(inst_PC); + unsigned btb_idx = getIndex(instPC); - Addr inst_tag = getTag(inst_PC); + Addr inst_tag = getTag(instPC); assert(btb_idx < numEntries); @@ -121,14 +121,14 @@ DefaultBTB::lookup(const Addr &inst_PC, ThreadID tid) } void -DefaultBTB::update(const Addr &inst_PC, const Addr &target, ThreadID tid) +DefaultBTB::update(Addr instPC, const TheISA::PCState &target, ThreadID tid) { - unsigned btb_idx = getIndex(inst_PC); + unsigned btb_idx = getIndex(instPC); assert(btb_idx < numEntries); btb[btb_idx].tid = tid; btb[btb_idx].valid = true; btb[btb_idx].target = target; - btb[btb_idx].tag = getTag(inst_PC); + btb[btb_idx].tag = getTag(instPC); } diff --git a/src/cpu/pred/btb.hh b/src/cpu/pred/btb.hh index 6557522e0..814b23872 100644 --- a/src/cpu/pred/btb.hh +++ b/src/cpu/pred/btb.hh @@ -31,8 +31,10 @@ #ifndef __CPU_O3_BTB_HH__ #define __CPU_O3_BTB_HH__ +#include "arch/types.hh" #include "base/misc.hh" #include "base/types.hh" +#include "config/the_isa.hh" class DefaultBTB { @@ -41,14 +43,13 @@ class DefaultBTB { BTBEntry() : tag(0), target(0), valid(false) - { - } + {} /** The entry's tag. */ Addr tag; /** The entry's target. */ - Addr target; + TheISA::PCState target; /** The entry's thread id. */ ThreadID tid; @@ -74,21 +75,21 @@ class DefaultBTB * @param tid The thread id. * @return Returns the target of the branch. */ - Addr lookup(const Addr &inst_PC, ThreadID tid); + TheISA::PCState lookup(Addr instPC, ThreadID tid); /** Checks if a branch is in the BTB. * @param inst_PC The address of the branch to look up. * @param tid The thread id. * @return Whether or not the branch exists in the BTB. */ - bool valid(const Addr &inst_PC, ThreadID tid); + bool valid(Addr instPC, ThreadID tid); /** Updates the BTB with the target of a branch. * @param inst_PC The address of the branch being updated. * @param target_PC The target address of the branch. * @param tid The thread id. */ - void update(const Addr &inst_PC, const Addr &target_PC, + void update(Addr instPC, const TheISA::PCState &targetPC, ThreadID tid); private: @@ -96,13 +97,13 @@ class DefaultBTB * @param inst_PC The branch to look up. * @return Returns the index into the BTB. */ - inline unsigned getIndex(const Addr &inst_PC); + inline unsigned getIndex(Addr instPC); /** Returns the tag bits of a given address. * @param inst_PC The branch's address. * @return Returns the tag bits. */ - inline Addr getTag(const Addr &inst_PC); + inline Addr getTag(Addr instPC); /** The actual BTB. */ std::vector<BTBEntry> btb; diff --git a/src/cpu/pred/ras.cc b/src/cpu/pred/ras.cc index 6373e5de3..0ba09bfae 100644 --- a/src/cpu/pred/ras.cc +++ b/src/cpu/pred/ras.cc @@ -34,13 +34,8 @@ void ReturnAddrStack::init(unsigned _numEntries) { numEntries = _numEntries; - usedEntries = 0; - tos = 0; - addrStack.resize(numEntries); - - for (unsigned i = 0; i < numEntries; ++i) - addrStack[i] = 0; + reset(); } void @@ -49,11 +44,11 @@ ReturnAddrStack::reset() usedEntries = 0; tos = 0; for (unsigned i = 0; i < numEntries; ++i) - addrStack[i] = 0; + addrStack[i].set(0); } void -ReturnAddrStack::push(const Addr &return_addr) +ReturnAddrStack::push(const TheISA::PCState &return_addr) { incrTos(); @@ -76,9 +71,9 @@ ReturnAddrStack::pop() void ReturnAddrStack::restore(unsigned top_entry_idx, - const Addr &restored_target) + const TheISA::PCState &restored) { tos = top_entry_idx; - addrStack[tos] = restored_target; + addrStack[tos] = restored; } diff --git a/src/cpu/pred/ras.hh b/src/cpu/pred/ras.hh index a36faf79a..ab92b34c2 100644 --- a/src/cpu/pred/ras.hh +++ b/src/cpu/pred/ras.hh @@ -33,7 +33,9 @@ #include <vector> +#include "arch/types.hh" #include "base/types.hh" +#include "config/the_isa.hh" /** Return address stack class, implements a simple RAS. */ class ReturnAddrStack @@ -52,7 +54,7 @@ class ReturnAddrStack void reset(); /** Returns the top address on the RAS. */ - Addr top() + TheISA::PCState top() { return addrStack[tos]; } /** Returns the index of the top of the RAS. */ @@ -60,7 +62,7 @@ class ReturnAddrStack { return tos; } /** Pushes an address onto the RAS. */ - void push(const Addr &return_addr); + void push(const TheISA::PCState &return_addr); /** Pops the top address from the RAS. */ void pop(); @@ -68,9 +70,9 @@ class ReturnAddrStack /** Changes index to the top of the RAS, and replaces the top address with * a new target. * @param top_entry_idx The index of the RAS that will now be the top. - * @param restored_target The new target address of the new top of the RAS. + * @param restored The new target address of the new top of the RAS. */ - void restore(unsigned top_entry_idx, const Addr &restored_target); + void restore(unsigned top_entry_idx, const TheISA::PCState &restored); bool empty() { return usedEntries == 0; } @@ -85,7 +87,7 @@ class ReturnAddrStack { tos = (tos == 0 ? numEntries - 1 : tos - 1); } /** The RAS itself. */ - std::vector<Addr> addrStack; + std::vector<TheISA::PCState> addrStack; /** The number of entries in the RAS. */ unsigned numEntries; diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index d97e7aeec..de26ca2f8 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -321,7 +321,7 @@ AtomicSimpleCPU::readBytes(Addr addr, uint8_t * data, dcache_latency = 0; while (1) { - req->setVirt(0, addr, size, flags, thread->readPC()); + req->setVirt(0, addr, size, flags, thread->pcState().instAddr()); // translate to physical address Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read); @@ -475,7 +475,7 @@ AtomicSimpleCPU::writeBytes(uint8_t *data, unsigned size, dcache_latency = 0; while(1) { - req->setVirt(0, addr, size, flags, thread->readPC()); + req->setVirt(0, addr, size, flags, thread->pcState().instAddr()); // translate to physical address Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write); @@ -643,8 +643,11 @@ AtomicSimpleCPU::tick() Fault fault = NoFault; - bool fromRom = isRomMicroPC(thread->readMicroPC()); - if (!fromRom && !curMacroStaticInst) { + TheISA::PCState pcState = thread->pcState(); + + bool needToFetch = !isRomMicroPC(pcState.microPC()) && + !curMacroStaticInst; + if (needToFetch) { setupFetchRequest(&ifetch_req); fault = thread->itb->translateAtomic(&ifetch_req, tc, BaseTLB::Execute); @@ -655,7 +658,7 @@ AtomicSimpleCPU::tick() bool icache_access = false; dcache_access = false; // assume no dcache access - if (!fromRom && !curMacroStaticInst) { + if (needToFetch) { // This is commented out because the predecoder would act like // a tiny cache otherwise. It wouldn't be flushed when needed // like the I cache. It should be flushed, and when that works diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 088d5ff16..196b72cc0 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -368,19 +368,13 @@ BaseSimpleCPU::checkForInterrupts() void BaseSimpleCPU::setupFetchRequest(Request *req) { - Addr threadPC = thread->readPC(); + Addr instAddr = thread->instAddr(); // set up memory request for instruction fetch -#if ISA_HAS_DELAY_SLOT - DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",threadPC, - thread->readNextPC(),thread->readNextNPC()); -#else - DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p\n",threadPC, - thread->readNextPC()); -#endif + DPRINTF(Fetch, "Fetch: PC:%08p\n", instAddr); - Addr fetchPC = (threadPC & PCMask) + fetchOffset; - req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH, threadPC); + Addr fetchPC = (instAddr & PCMask) + fetchOffset; + req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH, instAddr); } @@ -399,11 +393,12 @@ BaseSimpleCPU::preExecute() // decode the instruction inst = gtoh(inst); - MicroPC upc = thread->readMicroPC(); + TheISA::PCState pcState = thread->pcState(); - if (isRomMicroPC(upc)) { + if (isRomMicroPC(pcState.microPC())) { stayAtPC = false; - curStaticInst = microcodeRom.fetchMicroop(upc, curMacroStaticInst); + curStaticInst = microcodeRom.fetchMicroop(pcState.microPC(), + curMacroStaticInst); } else if (!curMacroStaticInst) { //We're not in the middle of a macro instruction StaticInstPtr instPtr = NULL; @@ -412,21 +407,19 @@ BaseSimpleCPU::preExecute() //This should go away once the constructor can be set up properly predecoder.setTC(thread->getTC()); //If more fetch data is needed, pass it in. - Addr fetchPC = (thread->readPC() & PCMask) + fetchOffset; + Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset; //if(predecoder.needMoreBytes()) - predecoder.moreBytes(thread->readPC(), fetchPC, inst); + predecoder.moreBytes(pcState, fetchPC, inst); //else // predecoder.process(); //If an instruction is ready, decode it. Otherwise, we'll have to //fetch beyond the MachInst at the current pc. if (predecoder.extMachInstReady()) { -#if THE_ISA == X86_ISA || THE_ISA == ARM_ISA - thread->setNextPC(thread->readPC() + predecoder.getInstSize()); -#endif // X86_ISA stayAtPC = false; - instPtr = StaticInst::decode(predecoder.getExtMachInst(), - thread->readPC()); + ExtMachInst machInst = predecoder.getExtMachInst(pcState); + thread->pcState(pcState); + instPtr = StaticInst::decode(machInst, pcState.instAddr()); } else { stayAtPC = true; fetchOffset += sizeof(MachInst); @@ -436,13 +429,13 @@ BaseSimpleCPU::preExecute() //out micro ops if (instPtr && instPtr->isMacroop()) { curMacroStaticInst = instPtr; - curStaticInst = curMacroStaticInst->fetchMicroop(upc); + curStaticInst = curMacroStaticInst->fetchMicroop(pcState.microPC()); } else { curStaticInst = instPtr; } } else { //Read the next micro op from the macro op - curStaticInst = curMacroStaticInst->fetchMicroop(upc); + curStaticInst = curMacroStaticInst->fetchMicroop(pcState.microPC()); } //If we decoded an instruction this "tick", record information about it. @@ -450,8 +443,7 @@ BaseSimpleCPU::preExecute() { #if TRACING_ON traceData = tracer->getInstRecord(curTick, tc, - curStaticInst, thread->readPC(), - curMacroStaticInst, thread->readMicroPC()); + curStaticInst, thread->pcState(), curMacroStaticInst); DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n", curStaticInst->getName(), curStaticInst->machInst); @@ -462,10 +454,14 @@ BaseSimpleCPU::preExecute() void BaseSimpleCPU::postExecute() { + assert(curStaticInst); + + TheISA::PCState pc = tc->pcState(); + Addr instAddr = pc.instAddr(); #if FULL_SYSTEM - if (thread->profile && curStaticInst) { + if (thread->profile) { bool usermode = TheISA::inUserMode(tc); - thread->profilePC = usermode ? 1 : thread->readPC(); + thread->profilePC = usermode ? 1 : instAddr; ProfileNode *node = thread->profile->consume(tc, curStaticInst); if (node) thread->profileNode = node; @@ -482,10 +478,10 @@ BaseSimpleCPU::postExecute() } if (CPA::available()) { - CPA::cpa()->swAutoBegin(tc, thread->readNextPC()); + CPA::cpa()->swAutoBegin(tc, pc.nextInstAddr()); } - traceFunctions(thread->readPC()); + traceFunctions(instAddr); if (traceData) { traceData->dump(); @@ -505,30 +501,12 @@ BaseSimpleCPU::advancePC(Fault fault) fault->invoke(tc, curStaticInst); predecoder.reset(); } else { - //If we're at the last micro op for this instruction - if (curStaticInst && curStaticInst->isLastMicroop()) { - //We should be working with a macro op or be in the ROM - assert(curMacroStaticInst || - isRomMicroPC(thread->readMicroPC())); - //Close out this macro op, and clean up the - //microcode state - curMacroStaticInst = StaticInst::nullStaticInstPtr; - thread->setMicroPC(normalMicroPC(0)); - thread->setNextMicroPC(normalMicroPC(1)); - } - //If we're still in a macro op - if (curMacroStaticInst || isRomMicroPC(thread->readMicroPC())) { - //Advance the micro pc - thread->setMicroPC(thread->readNextMicroPC()); - //Advance the "next" micro pc. Note that there are no delay - //slots, and micro ops are "word" addressed. - thread->setNextMicroPC(thread->readNextMicroPC() + 1); - } else { - // go to the next instruction - thread->setPC(thread->readNextPC()); - thread->setNextPC(thread->readNextNPC()); - thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); - assert(thread->readNextPC() != thread->readNextNPC()); + if (curStaticInst) { + if (curStaticInst->isLastMicroop()) + curMacroStaticInst = StaticInst::nullStaticInstPtr; + TheISA::PCState pcState = thread->pcState(); + TheISA::advancePC(pcState, curStaticInst); + thread->pcState(pcState); } } } diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 0aa0a295c..a713533fc 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -88,11 +88,12 @@ class BaseSimpleCPU : public BaseCPU Trace::InstRecord *traceData; inline void checkPcEventQueue() { - Addr oldpc; + Addr oldpc, pc = thread->instAddr(); do { - oldpc = thread->readPC(); + oldpc = pc; system->pcEventQueue.service(tc); - } while (oldpc != thread->readPC()); + pc = thread->instAddr(); + } while (oldpc != pc); } public: @@ -282,18 +283,7 @@ class BaseSimpleCPU : public BaseCPU thread->setFloatRegBits(reg_idx, val); } - uint64_t readPC() { return thread->readPC(); } - uint64_t readMicroPC() { return thread->readMicroPC(); } - uint64_t readNextPC() { return thread->readNextPC(); } - uint64_t readNextMicroPC() { return thread->readNextMicroPC(); } - uint64_t readNextNPC() { return thread->readNextNPC(); } bool readPredicate() { return thread->readPredicate(); } - - void setPC(uint64_t val) { thread->setPC(val); } - void setMicroPC(uint64_t val) { thread->setMicroPC(val); } - void setNextPC(uint64_t val) { thread->setNextPC(val); } - void setNextMicroPC(uint64_t val) { thread->setNextMicroPC(val); } - void setNextNPC(uint64_t val) { thread->setNextNPC(val); } void setPredicate(bool val) { thread->setPredicate(val); @@ -301,6 +291,11 @@ class BaseSimpleCPU : public BaseCPU traceData->setPredicate(val); } } + TheISA::PCState pcState() { return thread->pcState(); } + void pcState(const TheISA::PCState &val) { thread->pcState(val); } + Addr instAddr() { return thread->instAddr(); } + Addr nextInstAddr() { return thread->nextInstAddr(); } + MicroPC microPC() { return thread->microPC(); } MiscReg readMiscRegNoEffect(int misc_reg) { diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 2eb5b432b..863c28be2 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -422,7 +422,7 @@ TimingSimpleCPU::readBytes(Addr addr, uint8_t *data, Fault fault; const int asid = 0; const ThreadID tid = 0; - const Addr pc = thread->readPC(); + const Addr pc = thread->instAddr(); unsigned block_size = dcachePort.peerBlockSize(); BaseTLB::Mode mode = BaseTLB::Read; @@ -545,7 +545,7 @@ TimingSimpleCPU::writeTheseBytes(uint8_t *data, unsigned size, { const int asid = 0; const ThreadID tid = 0; - const Addr pc = thread->readPC(); + const Addr pc = thread->instAddr(); unsigned block_size = dcachePort.peerBlockSize(); BaseTLB::Mode mode = BaseTLB::Write; @@ -701,9 +701,10 @@ TimingSimpleCPU::fetch() checkPcEventQueue(); - bool fromRom = isRomMicroPC(thread->readMicroPC()); + TheISA::PCState pcState = thread->pcState(); + bool needToFetch = !isRomMicroPC(pcState.microPC()) && !curMacroStaticInst; - if (!fromRom && !curMacroStaticInst) { + if (needToFetch) { Request *ifetch_req = new Request(); ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0); setupFetchRequest(ifetch_req); diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index bd796428a..15fac8677 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -193,11 +193,7 @@ SimpleThread::serialize(ostream &os) ThreadState::serialize(os); SERIALIZE_ARRAY(floatRegs.i, TheISA::NumFloatRegs); SERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs); - SERIALIZE_SCALAR(microPC); - SERIALIZE_SCALAR(nextMicroPC); - SERIALIZE_SCALAR(PC); - SERIALIZE_SCALAR(nextPC); - SERIALIZE_SCALAR(nextNPC); + _pcState.serialize(os); // thread_num and cpu_id are deterministic from the config // @@ -213,11 +209,7 @@ SimpleThread::unserialize(Checkpoint *cp, const std::string §ion) ThreadState::unserialize(cp, section); UNSERIALIZE_ARRAY(floatRegs.i, TheISA::NumFloatRegs); UNSERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs); - UNSERIALIZE_SCALAR(microPC); - UNSERIALIZE_SCALAR(nextMicroPC); - UNSERIALIZE_SCALAR(PC); - UNSERIALIZE_SCALAR(nextPC); - UNSERIALIZE_SCALAR(nextNPC); + _pcState.unserialize(cp, section); // thread_num and cpu_id are deterministic from the config // diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index e4a7b7a77..48077a9b9 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -106,27 +106,7 @@ class SimpleThread : public ThreadState TheISA::IntReg intRegs[TheISA::NumIntRegs]; TheISA::ISA isa; // one "instance" of the current ISA. - /** The current microcode pc for the currently executing macro - * operation. - */ - MicroPC microPC; - - /** The next microcode pc for the currently executing macro - * operation. - */ - MicroPC nextMicroPC; - - /** The current pc. - */ - Addr PC; - - /** The next pc. - */ - Addr nextPC; - - /** The next next pc. - */ - Addr nextNPC; + TheISA::PCState _pcState; /** Did this instruction execute or is it predicated false */ bool predicate; @@ -245,9 +225,7 @@ class SimpleThread : public ThreadState void clearArchRegs() { - microPC = 0; - nextMicroPC = 1; - PC = nextPC = nextNPC = 0; + _pcState = 0; memset(intRegs, 0, sizeof(intRegs)); memset(floatRegs.i, 0, sizeof(floatRegs.i)); isa.clear(); @@ -313,60 +291,34 @@ class SimpleThread : public ThreadState reg_idx, flatIndex, val, floatRegs.f[flatIndex]); } - uint64_t readPC() - { - return PC; - } - - void setPC(uint64_t val) - { - PC = val; - } - - uint64_t readMicroPC() - { - return microPC; - } - - void setMicroPC(uint64_t val) - { - microPC = val; - } - - uint64_t readNextPC() + TheISA::PCState + pcState() { - return nextPC; + return _pcState; } - void setNextPC(uint64_t val) + void + pcState(const TheISA::PCState &val) { - nextPC = val; + _pcState = val; } - uint64_t readNextMicroPC() + Addr + instAddr() { - return nextMicroPC; + return _pcState.instAddr(); } - void setNextMicroPC(uint64_t val) + Addr + nextInstAddr() { - nextMicroPC = val; + return _pcState.nextInstAddr(); } - uint64_t readNextNPC() + MicroPC + microPC() { -#if ISA_HAS_DELAY_SLOT - return nextNPC; -#else - return nextPC + sizeof(TheISA::MachInst); -#endif - } - - void setNextNPC(uint64_t val) - { -#if ISA_HAS_DELAY_SLOT - nextNPC = val; -#endif + return _pcState.microPC(); } bool readPredicate() diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc index 2c4fc8ab9..f2a72c96a 100644 --- a/src/cpu/static_inst.cc +++ b/src/cpu/static_inst.cc @@ -68,7 +68,8 @@ StaticInst::dumpDecodeCacheStats() } bool -StaticInst::hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const +StaticInst::hasBranchTarget(const TheISA::PCState &pc, ThreadContext *tc, + TheISA::PCState &tgt) const { if (isDirectCtrl()) { tgt = branchTarget(pc); @@ -84,21 +85,21 @@ StaticInst::hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const } StaticInstPtr -StaticInst::fetchMicroop(MicroPC micropc) +StaticInst::fetchMicroop(MicroPC upc) const { panic("StaticInst::fetchMicroop() called on instruction " "that is not microcoded."); } -Addr -StaticInst::branchTarget(Addr branchPC) const +TheISA::PCState +StaticInst::branchTarget(const TheISA::PCState &pc) const { panic("StaticInst::branchTarget() called on instruction " "that is not a PC-relative branch."); M5_DUMMY_RETURN; } -Addr +TheISA::PCState StaticInst::branchTarget(ThreadContext *tc) const { panic("StaticInst::branchTarget() called on instruction " diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 6474bbf9c..b219fafd6 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -35,6 +35,7 @@ #include <string> #include "arch/isa_traits.hh" +#include "arch/types.hh" #include "arch/registers.hh" #include "config/the_isa.hh" #include "base/hashmap.hh" @@ -70,28 +71,6 @@ namespace Trace { class InstRecord; } -typedef uint16_t MicroPC; - -static const MicroPC MicroPCRomBit = 1 << (sizeof(MicroPC) * 8 - 1); - -static inline MicroPC -romMicroPC(MicroPC upc) -{ - return upc | MicroPCRomBit; -} - -static inline MicroPC -normalMicroPC(MicroPC upc) -{ - return upc & ~MicroPCRomBit; -} - -static inline bool -isRomMicroPC(MicroPC upc) -{ - return MicroPCRomBit & upc; -} - /** * Base, ISA-independent static instruction class. * @@ -392,18 +371,20 @@ class StaticInst : public StaticInstBase */ #include "cpu/static_inst_exec_sigs.hh" + virtual void advancePC(TheISA::PCState &pcState) const = 0; + /** * Return the microop that goes with a particular micropc. This should * only be defined/used in macroops which will contain microops */ - virtual StaticInstPtr fetchMicroop(MicroPC micropc); + virtual StaticInstPtr fetchMicroop(MicroPC upc) const; /** * Return the target address for a PC-relative branch. * Invalid if not a PC-relative branch (i.e. isDirectCtrl() * should be true). */ - virtual Addr branchTarget(Addr branchPC) const; + virtual TheISA::PCState branchTarget(const TheISA::PCState &pc) const; /** * Return the target address for an indirect branch (jump). The @@ -412,13 +393,14 @@ class StaticInst : public StaticInstBase * execute the branch in question. Invalid if not an indirect * branch (i.e. isIndirectCtrl() should be true). */ - virtual Addr branchTarget(ThreadContext *tc) const; + virtual TheISA::PCState branchTarget(ThreadContext *tc) const; /** * Return true if the instruction is a control transfer, and if so, * return the target address as well. */ - bool hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const; + bool hasBranchTarget(const TheISA::PCState &pc, ThreadContext *tc, + TheISA::PCState &tgt) const; /** * Return string representation of disassembled instruction. diff --git a/src/cpu/thread_context.cc b/src/cpu/thread_context.cc index f2083ef08..c4960ea30 100644 --- a/src/cpu/thread_context.cc +++ b/src/cpu/thread_context.cc @@ -65,16 +65,8 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two) } #endif - Addr pc1 = one->readPC(); - Addr pc2 = two->readPC(); - if (pc1 != pc2) - panic("PCs doesn't match, one: %#x, two: %#x", pc1, pc2); - - Addr npc1 = one->readNextPC(); - Addr npc2 = two->readNextPC(); - if (npc1 != npc2) - panic("NPCs doesn't match, one: %#x, two: %#x", npc1, npc2); - + if (!(one->pcState() == two->pcState())) + panic("PC state doesn't match."); int id1 = one->cpuId(); int id2 = two->cpuId(); if (id1 != id2) diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index 753fa2146..1c70ef59a 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -192,25 +192,15 @@ class ThreadContext virtual void setFloatRegBits(int reg_idx, FloatRegBits val) = 0; - virtual uint64_t readPC() = 0; + virtual TheISA::PCState pcState() = 0; - virtual void setPC(uint64_t val) = 0; + virtual void pcState(const TheISA::PCState &val) = 0; - virtual uint64_t readNextPC() = 0; + virtual Addr instAddr() = 0; - virtual void setNextPC(uint64_t val) = 0; + virtual Addr nextInstAddr() = 0; - virtual uint64_t readNextNPC() = 0; - - virtual void setNextNPC(uint64_t val) = 0; - - virtual uint64_t readMicroPC() = 0; - - virtual void setMicroPC(uint64_t val) = 0; - - virtual uint64_t readNextMicroPC() = 0; - - virtual void setNextMicroPC(uint64_t val) = 0; + virtual MicroPC microPC() = 0; virtual MiscReg readMiscRegNoEffect(int misc_reg) = 0; @@ -377,25 +367,13 @@ class ProxyThreadContext : public ThreadContext void setFloatRegBits(int reg_idx, FloatRegBits val) { actualTC->setFloatRegBits(reg_idx, val); } - uint64_t readPC() { return actualTC->readPC(); } - - void setPC(uint64_t val) { actualTC->setPC(val); } - - uint64_t readNextPC() { return actualTC->readNextPC(); } - - void setNextPC(uint64_t val) { actualTC->setNextPC(val); } - - uint64_t readNextNPC() { return actualTC->readNextNPC(); } - - void setNextNPC(uint64_t val) { actualTC->setNextNPC(val); } - - uint64_t readMicroPC() { return actualTC->readMicroPC(); } - - void setMicroPC(uint64_t val) { actualTC->setMicroPC(val); } + TheISA::PCState pcState() { return actualTC->pcState(); } - uint64_t readNextMicroPC() { return actualTC->readMicroPC(); } + void pcState(const TheISA::PCState &val) { actualTC->pcState(val); } - void setNextMicroPC(uint64_t val) { actualTC->setNextMicroPC(val); } + Addr instAddr() { return actualTC->instAddr(); } + Addr nextInstAddr() { return actualTC->nextInstAddr(); } + MicroPC microPC() { return actualTC->microPC(); } bool readPredicate() { return actualTC->readPredicate(); } diff --git a/src/kern/system_events.cc b/src/kern/system_events.cc index 25856e466..612aabc0b 100644 --- a/src/kern/system_events.cc +++ b/src/kern/system_events.cc @@ -41,9 +41,10 @@ using namespace TheISA; void SkipFuncEvent::process(ThreadContext *tc) { - DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description, - tc->readPC(), tc->readIntReg(ReturnAddressReg)); + TheISA::PCState oldPC M5_VAR_USED = tc->pcState(); // Call ISA specific code to do the skipping TheISA::skipFunction(tc); + DPRINTF(PCEvent, "skipping %s: pc = %s, newpc = %s\n", description, + oldPC, tc->pcState()); } diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh index d3348fe89..aa3c4bb50 100644 --- a/src/kern/tru64/tru64.hh +++ b/src/kern/tru64/tru64.hh @@ -509,7 +509,9 @@ class Tru64 : public OperatingSystem // Note that we'll advance PC <- NPC before the end of the cycle, // so we need to restore the desired PC into NPC. // The current regs->pc will get clobbered. - tc->setNextPC(htog(sc->sc_pc)); + PCState pc = tc->pcState(); + pc.npc(htog(sc->sc_pc)); + tc->pcState(pc); for (int i = 0; i < 31; ++i) { tc->setIntReg(i, htog(sc->sc_regs[i])); @@ -703,8 +705,7 @@ class Tru64 : public OperatingSystem tc->setIntReg(TheISA::StackPointerReg, gtoh(attrp->registers.sp)); tc->setMiscRegNoEffect(AlphaISA::MISCREG_UNIQ, uniq_val); - tc->setPC(gtoh(attrp->registers.pc)); - tc->setNextPC(gtoh(attrp->registers.pc) + sizeof(TheISA::MachInst)); + tc->pcState(gtoh(attrp->registers.pc)); tc->activate(); } diff --git a/src/sim/faults.cc b/src/sim/faults.cc index 78b9fb0a4..fbe8fb32a 100644 --- a/src/sim/faults.cc +++ b/src/sim/faults.cc @@ -40,13 +40,12 @@ #if !FULL_SYSTEM void FaultBase::invoke(ThreadContext * tc, StaticInstPtr inst) { - panic("fault (%s) detected @ PC %p", name(), tc->readPC()); + panic("fault (%s) detected @ PC %s", name(), tc->pcState()); } #else void FaultBase::invoke(ThreadContext * tc, StaticInstPtr inst) { - DPRINTF(Fault, "Fault %s at PC: %#x\n", name(), tc->readPC()); - + DPRINTF(Fault, "Fault %s at PC: %s\n", name(), tc->pcState()); assert(!tc->misspeculating()); } #endif diff --git a/src/sim/insttracer.hh b/src/sim/insttracer.hh index 845f4ed99..1ff67d2cb 100644 --- a/src/sim/insttracer.hh +++ b/src/sim/insttracer.hh @@ -54,9 +54,8 @@ class InstRecord // need to make this ref-counted so it doesn't go away before we // dump the record StaticInstPtr staticInst; - Addr PC; + TheISA::PCState pc; StaticInstPtr macroStaticInst; - MicroPC upc; bool misspeculating; bool predicate; @@ -90,12 +89,11 @@ class InstRecord public: InstRecord(Tick _when, ThreadContext *_thread, const StaticInstPtr _staticInst, - Addr _pc, bool spec, - const StaticInstPtr _macroStaticInst = NULL, - MicroPC _upc = 0) + TheISA::PCState _pc, bool spec, + const StaticInstPtr _macroStaticInst = NULL) : when(_when), thread(_thread), - staticInst(_staticInst), PC(_pc), - macroStaticInst(_macroStaticInst), upc(_upc), + staticInst(_staticInst), pc(_pc), + macroStaticInst(_macroStaticInst), misspeculating(spec), predicate(true) { data_status = DataInvalid; @@ -137,9 +135,8 @@ class InstRecord Tick getWhen() { return when; } ThreadContext *getThread() { return thread; } StaticInstPtr getStaticInst() { return staticInst; } - Addr getPC() { return PC; } + TheISA::PCState getPCState() { return pc; } StaticInstPtr getMacroStaticInst() { return macroStaticInst; } - MicroPC getUPC() { return upc; } bool getMisspeculating() { return misspeculating; } Addr getAddr() { return addr; } @@ -167,9 +164,8 @@ class InstTracer : public SimObject virtual InstRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc, - const StaticInstPtr macroStaticInst = NULL, - MicroPC _upc = 0) = 0; + const StaticInstPtr staticInst, TheISA::PCState pc, + const StaticInstPtr macroStaticInst = NULL) = 0; }; diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 207c07309..60bb59790 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -824,9 +824,7 @@ cloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ctc->setIntReg(TheISA::SyscallPseudoReturnReg, 1); #endif - ctc->setPC(tc->readNextPC()); - ctc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst)); - ctc->setNextNPC(tc->readNextNPC() + sizeof(TheISA::MachInst)); + ctc->pcState(tc->nextInstAddr()); ctc->activate(); diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index eaec57ef5..f2847b2e5 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -512,8 +512,8 @@ ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, return -ENOTTY; default: - fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n", - fd, req, tc->readPC()); + fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n", + fd, req, tc->pcState()); } } |