diff options
Diffstat (limited to 'src/arch')
95 files changed, 1518 insertions, 636 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__ |