summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/alpha/ev5.cc11
-rw-r--r--src/arch/alpha/faults.cc10
-rw-r--r--src/arch/alpha/interrupts.hh2
-rw-r--r--src/arch/alpha/isa/branch.isa40
-rw-r--r--src/arch/alpha/isa/decoder.isa14
-rw-r--r--src/arch/alpha/isa/main.isa9
-rw-r--r--src/arch/alpha/predecoder.hh6
-rw-r--r--src/arch/alpha/process.cc10
-rw-r--r--src/arch/alpha/remote_gdb.cc20
-rw-r--r--src/arch/alpha/stacktrace.cc4
-rw-r--r--src/arch/alpha/tlb.cc4
-rw-r--r--src/arch/alpha/types.hh3
-rw-r--r--src/arch/alpha/utility.cc9
-rw-r--r--src/arch/alpha/utility.hh16
-rw-r--r--src/arch/arm/faults.cc34
-rw-r--r--src/arch/arm/insts/macromem.hh12
-rw-r--r--src/arch/arm/insts/mem.hh38
-rw-r--r--src/arch/arm/insts/pred_inst.hh11
-rw-r--r--src/arch/arm/insts/static_inst.hh62
-rw-r--r--src/arch/arm/insts/vfp.hh12
-rw-r--r--src/arch/arm/isa.cc25
-rw-r--r--src/arch/arm/isa/formats/breakpoint.isa2
-rw-r--r--src/arch/arm/isa/insts/branch.isa56
-rw-r--r--src/arch/arm/isa/insts/data.isa7
-rw-r--r--src/arch/arm/isa/insts/ldr.isa6
-rw-r--r--src/arch/arm/isa/insts/macromem.isa4
-rw-r--r--src/arch/arm/isa/insts/misc.isa24
-rw-r--r--src/arch/arm/isa/operands.isa204
-rw-r--r--src/arch/arm/isa_traits.hh9
-rw-r--r--src/arch/arm/linux/system.cc3
-rw-r--r--src/arch/arm/nativetrace.cc4
-rw-r--r--src/arch/arm/predecoder.cc6
-rw-r--r--src/arch/arm/predecoder.hh5
-rw-r--r--src/arch/arm/process.cc10
-rw-r--r--src/arch/arm/system.hh2
-rw-r--r--src/arch/arm/table_walker.cc2
-rw-r--r--src/arch/arm/tlb.cc4
-rw-r--r--src/arch/arm/types.hh185
-rw-r--r--src/arch/arm/utility.cc10
-rw-r--r--src/arch/arm/utility.hh21
-rw-r--r--src/arch/generic/types.hh432
-rwxr-xr-xsrc/arch/isa_parser.py54
-rw-r--r--src/arch/mips/isa/base.isa7
-rw-r--r--src/arch/mips/isa/decoder.isa44
-rw-r--r--src/arch/mips/isa/formats/branch.isa90
-rw-r--r--src/arch/mips/isa/includes.isa1
-rw-r--r--src/arch/mips/isa/operands.isa3
-rwxr-xr-xsrc/arch/mips/mt.hh14
-rw-r--r--src/arch/mips/predecoder.hh4
-rw-r--r--src/arch/mips/process.cc5
-rw-r--r--src/arch/mips/types.hh3
-rw-r--r--src/arch/mips/utility.cc7
-rw-r--r--src/arch/mips/utility.hh16
-rw-r--r--src/arch/power/insts/branch.cc24
-rw-r--r--src/arch/power/insts/branch.hh10
-rw-r--r--src/arch/power/insts/static_inst.hh6
-rw-r--r--src/arch/power/isa/decoder.isa36
-rw-r--r--src/arch/power/isa/formats/branch.isa6
-rw-r--r--src/arch/power/isa/formats/unknown.isa2
-rw-r--r--src/arch/power/isa/operands.isa3
-rw-r--r--src/arch/power/predecoder.hh4
-rw-r--r--src/arch/power/process.cc4
-rw-r--r--src/arch/power/types.hh3
-rw-r--r--src/arch/power/utility.cc3
-rw-r--r--src/arch/power/utility.hh15
-rw-r--r--src/arch/sparc/faults.cc65
-rw-r--r--src/arch/sparc/isa/base.isa8
-rw-r--r--src/arch/sparc/isa/decoder.isa89
-rw-r--r--src/arch/sparc/isa/formats/branch.isa17
-rw-r--r--src/arch/sparc/isa/formats/micro.isa16
-rw-r--r--src/arch/sparc/isa/operands.isa3
-rw-r--r--src/arch/sparc/nativetrace.cc5
-rw-r--r--src/arch/sparc/predecoder.hh4
-rw-r--r--src/arch/sparc/process.cc25
-rw-r--r--src/arch/sparc/remote_gdb.cc21
-rw-r--r--src/arch/sparc/types.hh3
-rw-r--r--src/arch/sparc/utility.cc12
-rw-r--r--src/arch/sparc/utility.hh17
-rw-r--r--src/arch/x86/faults.cc26
-rw-r--r--src/arch/x86/insts/macroop.hh3
-rw-r--r--src/arch/x86/insts/microop.hh9
-rw-r--r--src/arch/x86/insts/static_inst.hh6
-rw-r--r--src/arch/x86/isa/decoder/two_byte_opcodes.isa2
-rw-r--r--src/arch/x86/isa/formats/unknown.isa4
-rw-r--r--src/arch/x86/isa/microops/regop.isa13
-rw-r--r--src/arch/x86/isa/microops/seqop.isa16
-rw-r--r--src/arch/x86/isa/operands.isa5
-rw-r--r--src/arch/x86/nativetrace.cc2
-rw-r--r--src/arch/x86/predecoder.hh28
-rw-r--r--src/arch/x86/process.cc10
-rw-r--r--src/arch/x86/system.cc3
-rw-r--r--src/arch/x86/tlb.cc2
-rw-r--r--src/arch/x86/types.hh3
-rw-r--r--src/arch/x86/utility.cc9
-rw-r--r--src/arch/x86/utility.hh16
-rw-r--r--src/base/remote_gdb.cc16
-rw-r--r--src/base/types.hh22
-rw-r--r--src/cpu/base_dyn_inst.hh130
-rw-r--r--src/cpu/base_dyn_inst_impl.hh58
-rw-r--r--src/cpu/checker/cpu.hh8
-rw-r--r--src/cpu/exetrace.cc10
-rw-r--r--src/cpu/exetrace.hh12
-rw-r--r--src/cpu/inorder/comm.hh4
-rw-r--r--src/cpu/inorder/cpu.cc91
-rw-r--r--src/cpu/inorder/cpu.hh30
-rw-r--r--src/cpu/inorder/first_stage.cc4
-rw-r--r--src/cpu/inorder/inorder_dyn_inst.cc25
-rw-r--r--src/cpu/inorder/inorder_dyn_inst.hh87
-rw-r--r--src/cpu/inorder/inorder_trace.cc8
-rw-r--r--src/cpu/inorder/inorder_trace.hh13
-rw-r--r--src/cpu/inorder/pipeline_stage.cc49
-rw-r--r--src/cpu/inorder/pipeline_stage.hh6
-rw-r--r--src/cpu/inorder/resources/bpred_unit.cc94
-rw-r--r--src/cpu/inorder/resources/bpred_unit.hh44
-rw-r--r--src/cpu/inorder/resources/branch_predictor.cc28
-rw-r--r--src/cpu/inorder/resources/cache_unit.cc33
-rw-r--r--src/cpu/inorder/resources/execution_unit.cc59
-rw-r--r--src/cpu/inorder/resources/fetch_seq_unit.cc171
-rw-r--r--src/cpu/inorder/resources/fetch_seq_unit.hh17
-rw-r--r--src/cpu/inorder/resources/tlb_unit.hh12
-rw-r--r--src/cpu/inorder/thread_context.cc24
-rw-r--r--src/cpu/inorder/thread_context.hh22
-rw-r--r--src/cpu/inorder/thread_state.hh4
-rw-r--r--src/cpu/inteltrace.cc2
-rw-r--r--src/cpu/inteltrace.hh12
-rw-r--r--src/cpu/legiontrace.cc9
-rw-r--r--src/cpu/legiontrace.hh12
-rw-r--r--src/cpu/nativetrace.hh12
-rw-r--r--src/cpu/o3/bpred_unit.hh33
-rw-r--r--src/cpu/o3/bpred_unit_impl.hh103
-rw-r--r--src/cpu/o3/comm.hh13
-rw-r--r--src/cpu/o3/commit.hh55
-rw-r--r--src/cpu/o3/commit_impl.hh86
-rw-r--r--src/cpu/o3/cpu.cc83
-rw-r--r--src/cpu/o3/cpu.hh33
-rw-r--r--src/cpu/o3/decode_impl.hh51
-rw-r--r--src/cpu/o3/dep_graph.hh8
-rw-r--r--src/cpu/o3/dyn_inst.hh12
-rw-r--r--src/cpu/o3/dyn_inst_impl.hh32
-rw-r--r--src/cpu/o3/fetch.hh20
-rw-r--r--src/cpu/o3/fetch_impl.hh178
-rw-r--r--src/cpu/o3/iew_impl.hh94
-rw-r--r--src/cpu/o3/inst_queue_impl.hh49
-rw-r--r--src/cpu/o3/lsq_unit.hh8
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh44
-rw-r--r--src/cpu/o3/mem_dep_unit_impl.hh52
-rw-r--r--src/cpu/o3/rename_impl.hh23
-rw-r--r--src/cpu/o3/rob_impl.hh8
-rwxr-xr-xsrc/cpu/o3/thread_context.hh42
-rwxr-xr-xsrc/cpu/o3/thread_context_impl.hh46
-rw-r--r--src/cpu/pc_event.cc4
-rw-r--r--src/cpu/pred/btb.cc28
-rw-r--r--src/cpu/pred/btb.hh17
-rw-r--r--src/cpu/pred/ras.cc15
-rw-r--r--src/cpu/pred/ras.hh12
-rw-r--r--src/cpu/simple/atomic.cc13
-rw-r--r--src/cpu/simple/base.cc82
-rw-r--r--src/cpu/simple/base.hh23
-rw-r--r--src/cpu/simple/timing.cc9
-rw-r--r--src/cpu/simple_thread.cc12
-rw-r--r--src/cpu/simple_thread.hh82
-rw-r--r--src/cpu/static_inst.cc11
-rw-r--r--src/cpu/static_inst.hh34
-rw-r--r--src/cpu/thread_context.cc12
-rw-r--r--src/cpu/thread_context.hh42
-rw-r--r--src/kern/system_events.cc5
-rw-r--r--src/kern/tru64/tru64.hh7
-rw-r--r--src/sim/faults.cc5
-rw-r--r--src/sim/insttracer.hh20
-rw-r--r--src/sim/syscall_emul.cc4
-rw-r--r--src/sim/syscall_emul.hh4
171 files changed, 2503 insertions, 2293 deletions
diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc
index 0db75df46..f97244260 100644
--- a/src/arch/alpha/ev5.cc
+++ b/src/arch/alpha/ev5.cc
@@ -60,8 +60,7 @@ initCPU(ThreadContext *tc, int cpuId)
AlphaFault *reset = new ResetFault;
- tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect());
- tc->setNextPC(tc->readPC() + sizeof(MachInst));
+ tc->pcState(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect());
delete reset;
}
@@ -494,12 +493,14 @@ using namespace AlphaISA;
Fault
SimpleThread::hwrei()
{
- if (!(readPC() & 0x3))
+ PCState pc = pcState();
+ if (!(pc.pc() & 0x3))
return new UnimplementedOpcodeFault;
- setNextPC(readMiscRegNoEffect(IPR_EXC_ADDR));
+ pc.npc(readMiscRegNoEffect(IPR_EXC_ADDR));
+ pcState(pc);
- CPA::cpa()->swAutoBegin(tc, readNextPC());
+ CPA::cpa()->swAutoBegin(tc, pc.npc());
if (!misspeculating()) {
if (kernelStats)
diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc
index 9d4eeda8a..38386cce1 100644
--- a/src/arch/alpha/faults.cc
+++ b/src/arch/alpha/faults.cc
@@ -115,9 +115,11 @@ AlphaFault::invoke(ThreadContext *tc, StaticInstPtr inst)
FaultBase::invoke(tc);
countStat()++;
+ PCState pc = tc->pcState();
+
// exception restart address
- if (setRestartAddress() || !(tc->readPC() & 0x3))
- tc->setMiscRegNoEffect(IPR_EXC_ADDR, tc->readPC());
+ if (setRestartAddress() || !(pc.pc() & 0x3))
+ tc->setMiscRegNoEffect(IPR_EXC_ADDR, pc.pc());
if (skipFaultingInstruction()) {
// traps... skip faulting instruction.
@@ -125,8 +127,8 @@ AlphaFault::invoke(ThreadContext *tc, StaticInstPtr inst)
tc->readMiscRegNoEffect(IPR_EXC_ADDR) + 4);
}
- tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + vect());
- tc->setNextPC(tc->readPC() + sizeof(MachInst));
+ pc.set(tc->readMiscRegNoEffect(IPR_PAL_BASE) + vect());
+ tc->pcState(pc);
}
void
diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh
index 3200201db..cbaa8e9bf 100644
--- a/src/arch/alpha/interrupts.hh
+++ b/src/arch/alpha/interrupts.hh
@@ -133,7 +133,7 @@ class Interrupts : public SimObject
bool
checkInterrupts(ThreadContext *tc) const
{
- return (intstatus != 0) && !(tc->readPC() & 0x3);
+ return (intstatus != 0) && !(tc->pcState().pc() & 0x3);
}
Fault
diff --git a/src/arch/alpha/isa/branch.isa b/src/arch/alpha/isa/branch.isa
index 974193efd..feb15b158 100644
--- a/src/arch/alpha/isa/branch.isa
+++ b/src/arch/alpha/isa/branch.isa
@@ -81,7 +81,7 @@ output header {{
{
}
- Addr branchTarget(Addr branchPC) const;
+ AlphaISA::PCState branchTarget(const AlphaISA::PCState &branchPC) const;
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
@@ -106,7 +106,7 @@ output header {{
{
}
- Addr branchTarget(ThreadContext *tc) const;
+ AlphaISA::PCState branchTarget(ThreadContext *tc) const;
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
@@ -114,18 +114,19 @@ output header {{
}};
output decoder {{
- Addr
- Branch::branchTarget(Addr branchPC) const
+ AlphaISA::PCState
+ Branch::branchTarget(const AlphaISA::PCState &branchPC) const
{
- return branchPC + 4 + disp;
+ return branchPC.pc() + 4 + disp;
}
- Addr
+ AlphaISA::PCState
Jump::branchTarget(ThreadContext *tc) const
{
- Addr NPC = tc->readPC() + 4;
+ PCState pc = tc->pcState();
uint64_t Rb = tc->readIntReg(_srcRegIdx[0]);
- return (Rb & ~3) | (NPC & 1);
+ pc.set((Rb & ~3) | (pc.pc() & 1));
+ return pc;
}
const std::string &
@@ -217,7 +218,14 @@ def template JumpOrBranchDecode {{
}};
def format CondBranch(code) {{
- code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
+ code = '''
+ bool cond;
+ %(code)s;
+ PCState pc = PCS;
+ if (cond)
+ pc.npc(pc.npc() + disp);
+ PCS = pc;
+ ''' % { "code" : code }
iop = InstObjParams(name, Name, 'Branch', code,
('IsDirectControl', 'IsCondControl'))
header_output = BasicDeclare.subst(iop)
@@ -229,16 +237,18 @@ def format CondBranch(code) {{
let {{
def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
# Declare basic control transfer w/o link (i.e. link reg is R31)
- nolink_code = 'NPC = %s;\n' % npc_expr
- nolink_iop = InstObjParams(name, Name, base_class, nolink_code, flags)
+ readpc_code = 'PCState pc = PCS;'
+ nolink_code = 'pc.npc(%s);\nPCS = pc' % npc_expr
+ nolink_iop = InstObjParams(name, Name, base_class,
+ readpc_code + nolink_code, flags)
header_output = BasicDeclare.subst(nolink_iop)
decoder_output = BasicConstructor.subst(nolink_iop)
exec_output = BasicExecute.subst(nolink_iop)
# Generate declaration of '*AndLink' version, append to decls
- link_code = 'Ra = NPC & ~3;\n' + nolink_code
+ link_code = 'Ra = pc.npc() & ~3;\n' + nolink_code
link_iop = InstObjParams(name, Name + 'AndLink', base_class,
- link_code, flags)
+ readpc_code + link_code, flags)
header_output += BasicDeclare.subst(link_iop)
decoder_output += BasicConstructor.subst(link_iop)
exec_output += BasicExecute.subst(link_iop)
@@ -253,13 +263,13 @@ def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
def format UncondBranch(*flags) {{
flags += ('IsUncondControl', 'IsDirectControl')
(header_output, decoder_output, decode_block, exec_output) = \
- UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
+ UncondCtrlBase(name, Name, 'Branch', 'pc.npc() + disp', flags)
}};
def format Jump(*flags) {{
flags += ('IsUncondControl', 'IsIndirectControl')
(header_output, decoder_output, decode_block, exec_output) = \
- UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
+ UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (pc.npc() & 1)', flags)
}};
diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa
index fe70e4d16..e2947cf4a 100644
--- a/src/arch/alpha/isa/decoder.isa
+++ b/src/arch/alpha/isa/decoder.isa
@@ -856,15 +856,16 @@ decode OPCODE default Unknown::unknown() {
// invalid pal function code, or attempt to do privileged
// PAL call in non-kernel mode
fault = new UnimplementedOpcodeFault;
- }
- else {
+ } else {
// check to see if simulator wants to do something special
// on this PAL call (including maybe suppress it)
bool dopal = xc->simPalCheck(palFunc);
if (dopal) {
- xc->setMiscReg(IPR_EXC_ADDR, NPC);
- NPC = xc->readMiscReg(IPR_PAL_BASE) + palOffset;
+ PCState pc = PCS;
+ xc->setMiscReg(IPR_EXC_ADDR, pc.npc());
+ pc.npc(xc->readMiscReg(IPR_PAL_BASE) + palOffset);
+ PCS = pc;
}
}
}}, IsNonSpeculative);
@@ -1030,13 +1031,14 @@ decode OPCODE default Unknown::unknown() {
}}, IsNonSpeculative);
#endif
0x54: m5panic({{
- panic("M5 panic instruction called at pc=%#x.", xc->readPC());
+ panic("M5 panic instruction called at pc=%#x.",
+ xc->pcState().pc());
}}, IsNonSpeculative);
#define CPANN(lbl) CPA::cpa()->lbl(xc->tcBase())
0x55: decode RA {
0x00: m5a_old({{
panic("Deprecated M5 annotate instruction executed at pc=%#x\n",
- xc->readPC());
+ xc->pcState().pc());
}}, IsNonSpeculative);
0x01: m5a_bsm({{
CPANN(swSmBegin);
diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa
index 2a0699354..ffc267cd2 100644
--- a/src/arch/alpha/isa/main.isa
+++ b/src/arch/alpha/isa/main.isa
@@ -46,6 +46,7 @@ output header {{
#include <iomanip>
#include "arch/alpha/faults.hh"
+#include "arch/alpha/types.hh"
#include "config/ss_compatible_fp.hh"
#include "cpu/static_inst.hh"
#include "mem/request.hh" // some constructors use MemReq flags
@@ -185,7 +186,7 @@ def operands {{
'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),
'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
- 'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
+ 'PCS': ('PCState', 'uq', None, ( None, None, 'IsControl' ), 4),
'Runiq': ('ControlReg', 'uq', 'MISCREG_UNIQ', None, 1),
'FPCR': ('ControlReg', 'uq', 'MISCREG_FPCR', None, 1),
'IntrFlag': ('ControlReg', 'uq', 'MISCREG_INTR', None, 1),
@@ -233,6 +234,12 @@ output header {{
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ void
+ advancePC(AlphaISA::PCState &pcState) const
+ {
+ pcState.advance();
+ }
};
}};
diff --git a/src/arch/alpha/predecoder.hh b/src/arch/alpha/predecoder.hh
index 913bd8764..f9a716b7f 100644
--- a/src/arch/alpha/predecoder.hh
+++ b/src/arch/alpha/predecoder.hh
@@ -76,11 +76,11 @@ class Predecoder
// Use this to give data to the predecoder. This should be used
// when there is control flow.
void
- moreBytes(Addr pc, Addr fetchPC, MachInst inst)
+ moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
{
ext_inst = inst;
#if FULL_SYSTEM
- ext_inst |= (static_cast<ExtMachInst>(pc & 0x1) << 32);
+ ext_inst |= (static_cast<ExtMachInst>(pc.pc() & 0x1) << 32);
#endif
}
@@ -98,7 +98,7 @@ class Predecoder
// This returns a constant reference to the ExtMachInst to avoid a copy
const ExtMachInst &
- getExtMachInst()
+ getExtMachInst(PCState &pc)
{
return ext_inst;
}
diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc
index f68a53a6f..3c3fd9b25 100644
--- a/src/arch/alpha/process.cc
+++ b/src/arch/alpha/process.cc
@@ -162,15 +162,7 @@ AlphaLiveProcess::argsInit(int intSize, int pageSize)
setSyscallArg(tc, 1, argv_array_base);
tc->setIntReg(StackPointerReg, stack_min);
- Addr prog_entry = objFile->entryPoint();
- tc->setPC(prog_entry);
- tc->setNextPC(prog_entry + sizeof(MachInst));
-
- // MIPS/Sparc need NNPC for delay slot handling, while
- // Alpha has no delay slots... However, CPU models
- // cycle PCs by PC=NPC, NPC=NNPC, etc. so setting this
- // here ensures CPU-Model Compatibility across board
- tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
+ tc->pcState(objFile->entryPoint());
}
void
diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc
index 5391d2056..9a2a5f23f 100644
--- a/src/arch/alpha/remote_gdb.cc
+++ b/src/arch/alpha/remote_gdb.cc
@@ -211,7 +211,7 @@ RemoteGDB::getregs()
{
memset(gdbregs.regs, 0, gdbregs.bytes());
- gdbregs.regs[KGDB_REG_PC] = context->readPC();
+ gdbregs.regs[KGDB_REG_PC] = context->pcState().pc();
// @todo: Currently this is very Alpha specific.
if (PcPAL(gdbregs.regs[KGDB_REG_PC])) {
@@ -254,7 +254,7 @@ RemoteGDB::setregs()
context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]);
}
#endif
- context->setPC(gdbregs.regs[KGDB_REG_PC]);
+ context->pcState(gdbregs.regs[KGDB_REG_PC]);
}
void
@@ -273,30 +273,28 @@ RemoteGDB::clearSingleStep()
void
RemoteGDB::setSingleStep()
{
- Addr pc = context->readPC();
- Addr npc, bpc;
+ PCState pc = context->pcState();
+ PCState bpc;
bool set_bt = false;
- npc = pc + sizeof(MachInst);
-
// User was stopped at pc, e.g. the instruction at pc was not
// executed.
- MachInst inst = read<MachInst>(pc);
- StaticInstPtr si(inst, pc);
+ MachInst inst = read<MachInst>(pc.pc());
+ StaticInstPtr si(inst, pc.pc());
if (si->hasBranchTarget(pc, context, bpc)) {
// Don't bother setting a breakpoint on the taken branch if it
// is the same as the next pc
- if (bpc != npc)
+ if (bpc.pc() != pc.npc())
set_bt = true;
}
DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n",
takenBkpt, notTakenBkpt);
- setTempBreakpoint(notTakenBkpt = npc);
+ setTempBreakpoint(notTakenBkpt = pc.npc());
if (set_bt)
- setTempBreakpoint(takenBkpt = bpc);
+ setTempBreakpoint(takenBkpt = bpc.pc());
}
// Write bytes to kernel address space for debugger.
diff --git a/src/arch/alpha/stacktrace.cc b/src/arch/alpha/stacktrace.cc
index 1b5a9be34..9c6b3cff0 100644
--- a/src/arch/alpha/stacktrace.cc
+++ b/src/arch/alpha/stacktrace.cc
@@ -145,7 +145,7 @@ StackTrace::trace(ThreadContext *_tc, bool is_call)
bool usermode =
(tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0;
- Addr pc = tc->readNextPC();
+ Addr pc = tc->pcState().pc();
bool kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd;
if (usermode) {
@@ -168,7 +168,7 @@ StackTrace::trace(ThreadContext *_tc, bool is_call)
panic("could not find address %#x", pc);
stack.push_back(addr);
- pc = tc->readPC();
+ pc = tc->pcState().pc();
}
while (ksp > bottom) {
diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc
index b578741d9..614061ddd 100644
--- a/src/arch/alpha/tlb.cc
+++ b/src/arch/alpha/tlb.cc
@@ -443,8 +443,6 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc)
Fault
TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
{
- Addr pc = tc->readPC();
-
mode_type mode =
(mode_type)DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM));
@@ -458,7 +456,7 @@ TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags);
}
- if (PcPAL(pc)) {
+ if (PcPAL(tc->pcState().pc())) {
mode = (req->getFlags() & Request::ALTMODE) ?
(mode_type)ALT_MODE_AM(
tc->readMiscRegNoEffect(IPR_ALT_MODE))
diff --git a/src/arch/alpha/types.hh b/src/arch/alpha/types.hh
index 0d285c3b2..06c0168cf 100644
--- a/src/arch/alpha/types.hh
+++ b/src/arch/alpha/types.hh
@@ -33,12 +33,15 @@
#define __ARCH_ALPHA_TYPES_HH__
#include "base/types.hh"
+#include "arch/generic/types.hh"
namespace AlphaISA {
typedef uint32_t MachInst;
typedef uint64_t ExtMachInst;
+typedef GenericISA::SimplePCState<MachInst> PCState;
+
typedef uint64_t LargestRead;
enum annotes
diff --git a/src/arch/alpha/utility.cc b/src/arch/alpha/utility.cc
index 11560259f..2d56ca9b8 100644
--- a/src/arch/alpha/utility.cc
+++ b/src/arch/alpha/utility.cc
@@ -77,8 +77,7 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
copyMiscRegs(src, dest);
// Lastly copy PC/NPC
- dest->setPC(src->readPC());
- dest->setNextPC(src->readNextPC());
+ dest->pcState(src->pcState());
}
void
@@ -99,9 +98,9 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
void
skipFunction(ThreadContext *tc)
{
- Addr newpc = tc->readIntReg(ReturnAddressReg);
- tc->setPC(newpc);
- tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
+ TheISA::PCState newPC = tc->pcState();
+ newPC.set(tc->readIntReg(ReturnAddressReg));
+ tc->pcState(newPC);
}
diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh
index 6d5b8baf6..fdac8b8d1 100644
--- a/src/arch/alpha/utility.hh
+++ b/src/arch/alpha/utility.hh
@@ -37,10 +37,19 @@
#include "arch/alpha/registers.hh"
#include "base/misc.hh"
#include "config/full_system.hh"
+#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
namespace AlphaISA {
+inline PCState
+buildRetPC(const PCState &curPC, const PCState &callPC)
+{
+ PCState retPC = callPC;
+ retPC.advance();
+ return retPC;
+}
+
uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp);
inline bool
@@ -95,6 +104,13 @@ void copyRegs(ThreadContext *src, ThreadContext *dest);
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
void skipFunction(ThreadContext *tc);
+
+inline void
+advancePC(PCState &pc, const StaticInstPtr inst)
+{
+ pc.advance();
+}
+
} // namespace AlphaISA
#endif // __ARCH_ALPHA_UTILITY_HH__
diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc
index 6e138119c..54cf5cfe5 100644
--- a/src/arch/arm/faults.cc
+++ b/src/arch/arm/faults.cc
@@ -104,6 +104,7 @@ ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst)
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR) |
tc->readIntReg(INTREG_CONDCODES);
+ Addr curPc M5_VAR_USED = tc->pcState().pc();
cpsr.mode = nextMode();
@@ -116,7 +117,7 @@ ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst)
cpsr.i = 1;
cpsr.e = sctlr.ee;
tc->setMiscReg(MISCREG_CPSR, cpsr);
- tc->setIntReg(INTREG_LR, tc->readPC() +
+ tc->setIntReg(INTREG_LR, curPc +
(saved_cpsr.t ? thumbPcOffset() : armPcOffset()));
switch (nextMode()) {
@@ -139,14 +140,15 @@ ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst)
panic("unknown Mode\n");
}
- Addr pc M5_VAR_USED = tc->readPC();
- Addr newPc = getVector(tc) | (sctlr.te ? PcTBit : 0);
+ Addr newPc = getVector(tc);
DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n",
- name(), cpsr, pc, tc->readIntReg(INTREG_LR), newPc);
- tc->setPC(newPc);
- tc->setNextPC(newPc + cpsr.t ? 2 : 4 );
- tc->setMicroPC(0);
- tc->setNextMicroPC(1);
+ name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc);
+ PCState pc(newPc);
+ pc.thumb(cpsr.t);
+ pc.nextThumb(pc.thumb());
+ pc.jazelle(cpsr.j);
+ pc.nextJazelle(pc.jazelle());
+ tc->pcState(pc);
}
void
@@ -193,10 +195,10 @@ SupervisorCall::invoke(ThreadContext *tc, StaticInstPtr inst)
tc->syscall(callNum);
// Advance the PC since that won't happen automatically.
- tc->setPC(tc->readNextPC());
- tc->setNextPC(tc->readNextNPC());
- tc->setMicroPC(0);
- tc->setNextMicroPC(1);
+ PCState pc = tc->pcState();
+ assert(inst);
+ inst->advancePC(pc);
+ tc->pcState(pc);
}
#endif // FULL_SYSTEM
@@ -223,10 +225,10 @@ FlushPipe::invoke(ThreadContext *tc, StaticInstPtr inst) {
// Set the PC to the next instruction of the faulting instruction.
// Net effect is simply squashing all instructions behind and
// start refetching from the next instruction.
- tc->setPC(tc->readNextPC());
- tc->setNextPC(tc->readNextNPC());
- tc->setMicroPC(0);
- tc->setNextMicroPC(1);
+ PCState pc = tc->pcState();
+ assert(inst);
+ inst->advancePC(pc);
+ tc->pcState(pc);
}
template void AbortFault<PrefetchAbort>::invoke(ThreadContext *tc,
diff --git a/src/arch/arm/insts/macromem.hh b/src/arch/arm/insts/macromem.hh
index c1c8383da..018cb1de5 100644
--- a/src/arch/arm/insts/macromem.hh
+++ b/src/arch/arm/insts/macromem.hh
@@ -77,6 +77,18 @@ class MicroOp : public PredOp
{
flags[IsDelayedCommit] = true;
}
+
+ void
+ advancePC(PCState &pcState) const
+ {
+ if (flags[IsLastMicroop]) {
+ pcState.uEnd();
+ } else if (flags[IsMicroop]) {
+ pcState.uAdvance();
+ } else {
+ pcState.advance();
+ }
+ }
};
/**
diff --git a/src/arch/arm/insts/mem.hh b/src/arch/arm/insts/mem.hh
index 1baba5112..2aa4de1d7 100644
--- a/src/arch/arm/insts/mem.hh
+++ b/src/arch/arm/insts/mem.hh
@@ -63,8 +63,28 @@ class Swap : public PredOp
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
+class MightBeMicro : public PredOp
+{
+ protected:
+ MightBeMicro(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
+ : PredOp(mnem, _machInst, __opClass)
+ {}
+
+ void
+ advancePC(PCState &pcState) const
+ {
+ if (flags[IsLastMicroop]) {
+ pcState.uEnd();
+ } else if (flags[IsMicroop]) {
+ pcState.uAdvance();
+ } else {
+ pcState.advance();
+ }
+ }
+};
+
// The address is a base register plus an immediate.
-class RfeOp : public PredOp
+class RfeOp : public MightBeMicro
{
public:
enum AddrMode {
@@ -83,7 +103,7 @@ class RfeOp : public PredOp
RfeOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
IntRegIndex _base, AddrMode _mode, bool _wb)
- : PredOp(mnem, _machInst, __opClass),
+ : MightBeMicro(mnem, _machInst, __opClass),
base(_base), mode(_mode), wb(_wb), uops(NULL)
{}
@@ -94,7 +114,7 @@ class RfeOp : public PredOp
}
StaticInstPtr
- fetchMicroop(MicroPC microPC)
+ fetchMicroop(MicroPC microPC) const
{
assert(uops != NULL && microPC < numMicroops);
return uops[microPC];
@@ -104,7 +124,7 @@ class RfeOp : public PredOp
};
// The address is a base register plus an immediate.
-class SrsOp : public PredOp
+class SrsOp : public MightBeMicro
{
public:
enum AddrMode {
@@ -123,7 +143,7 @@ class SrsOp : public PredOp
SrsOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
uint32_t _regMode, AddrMode _mode, bool _wb)
- : PredOp(mnem, _machInst, __opClass),
+ : MightBeMicro(mnem, _machInst, __opClass),
regMode(_regMode), mode(_mode), wb(_wb), uops(NULL)
{}
@@ -134,7 +154,7 @@ class SrsOp : public PredOp
}
StaticInstPtr
- fetchMicroop(MicroPC microPC)
+ fetchMicroop(MicroPC microPC) const
{
assert(uops != NULL && microPC < numMicroops);
return uops[microPC];
@@ -143,7 +163,7 @@ class SrsOp : public PredOp
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
-class Memory : public PredOp
+class Memory : public MightBeMicro
{
public:
enum AddrMode {
@@ -163,7 +183,7 @@ class Memory : public PredOp
Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
IntRegIndex _dest, IntRegIndex _base, bool _add)
- : PredOp(mnem, _machInst, __opClass),
+ : MightBeMicro(mnem, _machInst, __opClass),
dest(_dest), base(_base), add(_add), uops(NULL)
{}
@@ -174,7 +194,7 @@ class Memory : public PredOp
}
StaticInstPtr
- fetchMicroop(MicroPC microPC)
+ fetchMicroop(MicroPC microPC) const
{
assert(uops != NULL && microPC < numMicroops);
return uops[microPC];
diff --git a/src/arch/arm/insts/pred_inst.hh b/src/arch/arm/insts/pred_inst.hh
index b7d4c4709..f779b46f5 100644
--- a/src/arch/arm/insts/pred_inst.hh
+++ b/src/arch/arm/insts/pred_inst.hh
@@ -312,7 +312,7 @@ class PredMacroOp : public PredOp
}
StaticInstPtr
- fetchMicroop(MicroPC microPC)
+ fetchMicroop(MicroPC microPC) const
{
assert(microPC < numMicroops);
return microOps[microPC];
@@ -332,6 +332,15 @@ class PredMicroop : public PredOp
{
flags[IsMicroop] = true;
}
+
+ void
+ advancePC(PCState &pcState) const
+ {
+ if (flags[IsLastMicroop])
+ pcState.uEnd();
+ else
+ pcState.uAdvance();
+ }
};
}
diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh
index ad89a1a79..fa850190f 100644
--- a/src/arch/arm/insts/static_inst.hh
+++ b/src/arch/arm/insts/static_inst.hh
@@ -155,6 +155,12 @@ class ArmStaticInst : public StaticInst
IntRegIndex rs, uint32_t shiftAmt, ArmShiftType type,
uint32_t imm) const;
+ void
+ advancePC(PCState &pcState) const
+ {
+ pcState.advance();
+ }
+
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
static inline uint32_t
@@ -219,26 +225,16 @@ class ArmStaticInst : public StaticInst
static inline Addr
readPC(XC *xc)
{
- Addr pc = xc->readPC();
- if (isThumb(pc))
- return pc + 4;
- else
- return pc + 8;
+ return xc->pcState().instPC();
}
- // Perform an regular branch.
template<class XC>
static inline void
setNextPC(XC *xc, Addr val)
{
- Addr npc = xc->readNextPC();
- if (isThumb(npc)) {
- val &= ~mask(1);
- } else {
- val &= ~mask(2);
- }
- xc->setNextPC((npc & PcModeMask) |
- (val & ~PcModeMask));
+ PCState pc = xc->pcState();
+ pc.instNPC(val);
+ xc->pcState(pc);
}
template<class T>
@@ -279,30 +275,9 @@ class ArmStaticInst : public StaticInst
static inline void
setIWNextPC(XC *xc, Addr val)
{
- Addr stateBits = xc->readPC() & PcModeMask;
- Addr jBit = PcJBit;
- Addr tBit = PcTBit;
- bool thumbEE = (stateBits == (tBit | jBit));
-
- Addr newPc = (val & ~PcModeMask);
- if (thumbEE) {
- if (bits(newPc, 0)) {
- newPc = newPc & ~mask(1);
- } else {
- panic("Bad thumbEE interworking branch address %#x.\n", newPc);
- }
- } else {
- if (bits(newPc, 0)) {
- stateBits = tBit;
- newPc = newPc & ~mask(1);
- } else if (!bits(newPc, 1)) {
- stateBits = 0;
- } else {
- warn("Bad interworking branch address %#x.\n", newPc);
- }
- }
- newPc = newPc | stateBits;
- xc->setNextPC(newPc);
+ PCState pc = xc->pcState();
+ pc.instIWNPC(val);
+ xc->pcState(pc);
}
// Perform an interworking branch in ARM mode, a regular branch
@@ -311,14 +286,9 @@ class ArmStaticInst : public StaticInst
static inline void
setAIWNextPC(XC *xc, Addr val)
{
- Addr stateBits = xc->readPC() & PcModeMask;
- Addr jBit = PcJBit;
- Addr tBit = PcTBit;
- if (!jBit && !tBit) {
- setIWNextPC(xc, val);
- } else {
- setNextPC(xc, val);
- }
+ PCState pc = xc->pcState();
+ pc.instAIWNPC(val);
+ xc->pcState(pc);
}
inline Fault
diff --git a/src/arch/arm/insts/vfp.hh b/src/arch/arm/insts/vfp.hh
index 964b62673..e962704e0 100644
--- a/src/arch/arm/insts/vfp.hh
+++ b/src/arch/arm/insts/vfp.hh
@@ -459,6 +459,18 @@ class FpOp : public PredOp
unaryOp(FPSCR &fpscr, fpType op1,
fpType (*func)(fpType),
bool flush, uint32_t rMode) const;
+
+ void
+ advancePC(PCState &pcState) const
+ {
+ if (flags[IsLastMicroop]) {
+ pcState.uEnd();
+ } else if (flags[IsMicroop]) {
+ pcState.uAdvance();
+ } else {
+ pcState.advance();
+ }
+ }
};
class FpRegRegOp : public FpOp
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index d557cecbb..0ba62f08d 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -168,15 +168,9 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
{
if (misc_reg == MISCREG_CPSR) {
CPSR cpsr = miscRegs[misc_reg];
- Addr pc = tc->readPC();
- if (pc & (ULL(1) << PcJBitShift))
- cpsr.j = 1;
- else
- cpsr.j = 0;
- if (isThumb(pc))
- cpsr.t = 1;
- else
- cpsr.t = 0;
+ PCState pc = tc->pcState();
+ cpsr.j = pc.jazelle() ? 1 : 0;
+ cpsr.t = pc.thumb() ? 1 : 0;
return cpsr;
}
if (misc_reg >= MISCREG_CP15_UNIMP_START &&
@@ -239,13 +233,10 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
CPSR cpsr = val;
DPRINTF(Arm, "Updating CPSR from %#x to %#x f:%d i:%d a:%d mode:%#x\n",
miscRegs[misc_reg], cpsr, cpsr.f, cpsr.i, cpsr.a, cpsr.mode);
- Addr npc = tc->readNextPC() & ~PcModeMask;
- if (cpsr.j)
- npc = npc | PcJBit;
- if (cpsr.t)
- npc = npc | PcTBit;
-
- tc->setNextPC(npc);
+ PCState pc = tc->pcState();
+ pc.nextThumb(cpsr.t);
+ pc.nextJazelle(cpsr.j);
+ tc->pcState(pc);
} else if (misc_reg >= MISCREG_CP15_UNIMP_START &&
misc_reg < MISCREG_CP15_END) {
panic("Unimplemented CP15 register %s wrote with %#x.\n",
@@ -414,7 +405,7 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
default:
panic("Security Extensions not implemented!");
}
- req->setVirt(0, val, 1, flags, tc->readPC());
+ req->setVirt(0, val, 1, flags, tc->pcState().pc());
fault = tc->getDTBPtr()->translateAtomic(req, tc, mode);
if (fault == NoFault) {
miscRegs[MISCREG_PAR] =
diff --git a/src/arch/arm/isa/formats/breakpoint.isa b/src/arch/arm/isa/formats/breakpoint.isa
index d59f6a712..1825d0878 100644
--- a/src/arch/arm/isa/formats/breakpoint.isa
+++ b/src/arch/arm/isa/formats/breakpoint.isa
@@ -83,7 +83,7 @@ output exec {{
Breakpoint::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
- return new PrefetchAbort(xc->readPC(), ArmFault::DebugEvent);
+ return new PrefetchAbort(xc->pcState().pc(), ArmFault::DebugEvent);
}
}};
diff --git a/src/arch/arm/isa/insts/branch.isa b/src/arch/arm/isa/insts/branch.isa
index e9ddd77b7..3ff9042e6 100644
--- a/src/arch/arm/isa/insts/branch.isa
+++ b/src/arch/arm/isa/insts/branch.isa
@@ -46,15 +46,17 @@ let {{
# B, BL
for (mnem, link) in (("b", False), ("bl", True)):
bCode = '''
- Addr curPc = readPC(xc);
- NPC = ((curPc + imm) & mask(32)) | (curPc & ~mask(32));
+ ArmISA::PCState pc = PCS;
+ Addr curPc = pc.instPC();
+ pc.instNPC((uint32_t)(curPc + imm));
+ PCS = pc;
'''
if (link):
bCode += '''
- if (!isThumb(curPc))
- LR = curPc - 4;
- else
+ if (pc.thumb())
LR = curPc | 1;
+ else
+ LR = curPc - 4;
'''
bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond",
@@ -66,10 +68,12 @@ let {{
# BX, BLX
blxCode = '''
- Addr curPc M5_VAR_USED = readPC(xc);
+ ArmISA::PCState pc = PCS;
+ Addr curPc M5_VAR_USED = pc.instPC();
%(link)s
// Switch modes
%(branch)s
+ PCS = pc;
'''
blxList = (("blx", True, True),
@@ -81,8 +85,8 @@ let {{
if imm:
Name += "Imm"
# Since we're switching ISAs, the target ISA will be the opposite
- # of the current ISA. !arm is whether the target is ARM.
- newPC = '(isThumb(curPc) ? (roundDown(curPc, 4) + imm) : (curPc + imm))'
+ # of the current ISA. pc.thumb() is whether the target is ARM.
+ newPC = '(pc.thumb() ? (roundDown(curPc, 4) + imm) : (curPc + imm))'
base = "BranchImmCond"
declare = BranchImmCondDeclare
constructor = BranchImmCondConstructor
@@ -97,28 +101,28 @@ let {{
// The immediate version of the blx thumb instruction
// is 32 bits wide, but "next pc" doesn't reflect that
// so we don't want to substract 2 from it at this point
- if (!isThumb(curPc))
- LR = curPc - 4;
- else
+ if (pc.thumb())
LR = curPc | 1;
+ else
+ LR = curPc - 4;
'''
elif link:
linkStr = '''
- if (!isThumb(curPc))
- LR = curPc - 4;
- else
+ if (pc.thumb())
LR = (curPc - 2) | 1;
+ else
+ LR = curPc - 4;
'''
else:
linkStr = ""
if imm and link: #blx with imm
branchStr = '''
- Addr tempPc = ((%(newPC)s) & mask(32)) | (curPc & ~mask(32));
- FNPC = tempPc ^ PcTBit;
+ pc.nextThumb(!pc.thumb());
+ pc.instNPC(%(newPC)s);
'''
else:
- branchStr = "IWNPC = %(newPC)s;"
+ branchStr = "pc.instIWNPC(%(newPC)s);"
branchStr = branchStr % { "newPC" : newPC }
code = blxCode % {"link": linkStr,
@@ -136,8 +140,10 @@ let {{
#CBNZ, CBZ. These are always unconditional as far as predicates
for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")):
code = '''
- Addr curPc = readPC(xc);
- NPC = ((curPc + imm) & mask(32)) | (curPc & ~mask(32));
+ ArmISA::PCState pc = PCS;
+ Addr curPc = pc.instPC();
+ pc.instNPC((uint32_t)(curPc + imm));
+ PCS = pc;
'''
predTest = "Op1 %(test)s 0" % {"test": test}
iop = InstObjParams(mnem, mnem.capitalize(), "BranchImmReg",
@@ -155,7 +161,11 @@ let {{
ArmISA::TLB::MustBeOne;
EA = Op1 + Op2 * 2
'''
- accCode = "NPC = readPC(xc) + 2 * (Mem.uh);"
+ accCode = '''
+ ArmISA::PCState pc = PCS;
+ pc.instNPC(pc.instPC() + 2 * (Mem.uh));
+ PCS = pc;
+ '''
mnem = "tbh"
else:
eaCode = '''
@@ -164,7 +174,11 @@ let {{
ArmISA::TLB::MustBeOne;
EA = Op1 + Op2
'''
- accCode = "NPC = readPC(xc) + 2 * (Mem.ub);"
+ accCode = '''
+ ArmISA::PCState pc = PCS;
+ pc.instNPC(pc.instPC() + 2 * (Mem.ub));
+ PCS = pc;
+ '''
mnem = "tbb"
iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg",
{'ea_code': eaCode,
diff --git a/src/arch/arm/isa/insts/data.isa b/src/arch/arm/isa/insts/data.isa
index 74eeee3b2..4d368e181 100644
--- a/src/arch/arm/isa/insts/data.isa
+++ b/src/arch/arm/isa/insts/data.isa
@@ -239,6 +239,10 @@ let {{
cpsrWriteByInstr(Cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
+ ArmISA::PCState pc = PCS;
+ pc.nextThumb(((CPSR)newCpsr).t);
+ pc.nextJazelle(((CPSR)newCpsr).j);
+ PCS = pc;
'''
buildImmDataInst(mnem + 's', code, flagType,
suffix = "ImmPclr", buildCc = False,
@@ -253,7 +257,8 @@ let {{
buildDataInst("rsb", "Dest = resTemp = secondOp - Op1;", "rsb")
buildDataInst("add", "Dest = resTemp = Op1 + secondOp;", "add")
buildImmDataInst("adr", '''
- Dest = resTemp = (readPC(xc) & ~0x3) +
+ ArmISA::PCState pc = PCS;
+ Dest = resTemp = (pc.instPC() & ~0x3) +
(op1 ? secondOp : -secondOp);
''')
buildDataInst("adc", "Dest = resTemp = Op1 + secondOp + %s;" % oldC, "add")
diff --git a/src/arch/arm/isa/insts/ldr.isa b/src/arch/arm/isa/insts/ldr.isa
index dc043ed8e..92ad52a6d 100644
--- a/src/arch/arm/isa/insts/ldr.isa
+++ b/src/arch/arm/isa/insts/ldr.isa
@@ -105,12 +105,16 @@ let {{
accCode = '''
CPSR cpsr = Cpsr;
SCTLR sctlr = Sctlr;
- NPC = cSwap<uint32_t>(Mem.ud, cpsr.e);
+ ArmISA::PCState pc = PCS;
+ pc.instNPC(cSwap<uint32_t>(Mem.ud, cpsr.e));
uint32_t newCpsr =
cpsrWriteByInstr(cpsr | CondCodes,
cSwap<uint32_t>(Mem.ud >> 32, cpsr.e),
0xF, true, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
+ pc.nextThumb(((CPSR)newCpsr).t);
+ pc.nextJazelle(((CPSR)newCpsr).j);
+ PCS = pc;
CondCodes = CondCodesMask & newCpsr;
'''
self.codeBlobs["memacc_code"] = accCode
diff --git a/src/arch/arm/isa/insts/macromem.isa b/src/arch/arm/isa/insts/macromem.isa
index 6bf789efd..a81050b1e 100644
--- a/src/arch/arm/isa/insts/macromem.isa
+++ b/src/arch/arm/isa/insts/macromem.isa
@@ -93,7 +93,9 @@ let {{
cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
- IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
+ ArmISA::PCState pc = PCS;
+ pc.instIWNPC(cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0));
+ PCS = pc;
'''
microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
'MicroMemOp',
diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa
index 5742f84ab..1abbc3de1 100644
--- a/src/arch/arm/isa/insts/misc.isa
+++ b/src/arch/arm/isa/insts/misc.isa
@@ -83,6 +83,10 @@ let {{
uint32_t newCpsr =
cpsrWriteByInstr(Cpsr | CondCodes, Op1, byteMask, false, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
+ ArmISA::PCState pc = PCS;
+ pc.nextThumb(((CPSR)newCpsr).t);
+ pc.nextJazelle(((CPSR)newCpsr).j);
+ PCS = pc;
CondCodes = CondCodesMask & newCpsr;
'''
msrCpsrRegIop = InstObjParams("msr", "MsrCpsrReg", "MsrRegOp",
@@ -107,6 +111,10 @@ let {{
uint32_t newCpsr =
cpsrWriteByInstr(Cpsr | CondCodes, imm, byteMask, false, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
+ ArmISA::PCState pc = PCS;
+ pc.nextThumb(((CPSR)newCpsr).t);
+ pc.nextJazelle(((CPSR)newCpsr).j);
+ PCS = pc;
CondCodes = CondCodesMask & newCpsr;
'''
msrCpsrImmIop = InstObjParams("msr", "MsrCpsrImm", "MsrImmOp",
@@ -462,8 +470,12 @@ let {{
decoder_output += RegRegRegRegOpConstructor.subst(usada8Iop)
exec_output += PredOpExecute.subst(usada8Iop)
+ bkptCode = '''
+ ArmISA::PCState pc = PCS;
+ return new PrefetchAbort(pc.pc(), ArmFault::DebugEvent);
+ '''
bkptIop = InstObjParams("bkpt", "BkptInst", "ArmStaticInst",
- "return new PrefetchAbort(PC, ArmFault::DebugEvent);")
+ bkptCode)
header_output += BasicDeclare.subst(bkptIop)
decoder_output += BasicConstructor.subst(bkptIop)
exec_output += BasicExecute.subst(bkptIop)
@@ -638,7 +650,10 @@ let {{
exec_output += PredOpExecute.subst(mcr15UserIop)
enterxCode = '''
- FNPC = NPC | PcJBit | PcTBit;
+ ArmISA::PCState pc = PCS;
+ pc.nextThumb(true);
+ pc.nextJazelle(true);
+ PCS = pc;
'''
enterxIop = InstObjParams("enterx", "Enterx", "PredOp",
{ "code": enterxCode,
@@ -648,7 +663,10 @@ let {{
exec_output += PredOpExecute.subst(enterxIop)
leavexCode = '''
- FNPC = (NPC & ~PcJBit) | PcTBit;
+ ArmISA::PCState pc = PCS;
+ pc.nextThumb(true);
+ pc.nextJazelle(false);
+ PCS = pc;
'''
leavexIop = InstObjParams("leavex", "Leavex", "PredOp",
{ "code": leavexCode,
diff --git a/src/arch/arm/isa/operands.isa b/src/arch/arm/isa/operands.isa
index 4f1b7f610..8e856e74d 100644
--- a/src/arch/arm/isa/operands.isa
+++ b/src/arch/arm/isa/operands.isa
@@ -54,11 +54,10 @@ def operand_types {{
let {{
maybePCRead = '''
- ((%(reg_idx)s == PCReg) ? (readPC(xc) & ~PcModeMask) :
- xc->%(func)s(this, %(op_idx)s))
+ ((%(reg_idx)s == PCReg) ? readPC(xc) : xc->%(func)s(this, %(op_idx)s))
'''
maybeAlignedPCRead = '''
- ((%(reg_idx)s == PCReg) ? (roundDown(readPC(xc) & ~PcModeMask, 4)) :
+ ((%(reg_idx)s == PCReg) ? (roundDown(readPC(xc), 4)) :
xc->%(func)s(this, %(op_idx)s))
'''
maybePCWrite = '''
@@ -81,140 +80,133 @@ let {{
xc->%(func)s(this, %(op_idx)s, %(final_val)s);
}
'''
-
- readNPC = 'xc->readNextPC() & ~PcModeMask'
- writeNPC = 'setNextPC(xc, %(final_val)s)'
- writeIWNPC = 'setIWNextPC(xc, %(final_val)s)'
- forceNPC = 'xc->setNextPC(%(final_val)s)'
}};
def operands {{
#Abstracted integer reg operands
- 'Dest': ('IntReg', 'uw', 'dest', 'IsInteger', 2,
+ 'Dest': ('IntReg', 'uw', 'dest', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'FpDest': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 2),
- 'FpDestP0': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 2),
- 'FpDestP1': ('FloatReg', 'sf', '(dest + 1)', 'IsFloating', 2),
- 'FpDestP2': ('FloatReg', 'sf', '(dest + 2)', 'IsFloating', 2),
- 'FpDestP3': ('FloatReg', 'sf', '(dest + 3)', 'IsFloating', 2),
- 'FpDestP4': ('FloatReg', 'sf', '(dest + 4)', 'IsFloating', 2),
- 'FpDestP5': ('FloatReg', 'sf', '(dest + 5)', 'IsFloating', 2),
- 'FpDestP6': ('FloatReg', 'sf', '(dest + 6)', 'IsFloating', 2),
- 'FpDestP7': ('FloatReg', 'sf', '(dest + 7)', 'IsFloating', 2),
- 'FpDestS0P0': ('FloatReg', 'sf', '(dest + step * 0 + 0)', 'IsFloating', 2),
- 'FpDestS0P1': ('FloatReg', 'sf', '(dest + step * 0 + 1)', 'IsFloating', 2),
- 'FpDestS1P0': ('FloatReg', 'sf', '(dest + step * 1 + 0)', 'IsFloating', 2),
- 'FpDestS1P1': ('FloatReg', 'sf', '(dest + step * 1 + 1)', 'IsFloating', 2),
- 'FpDestS2P0': ('FloatReg', 'sf', '(dest + step * 2 + 0)', 'IsFloating', 2),
- 'FpDestS2P1': ('FloatReg', 'sf', '(dest + step * 2 + 1)', 'IsFloating', 2),
- 'FpDestS3P0': ('FloatReg', 'sf', '(dest + step * 3 + 0)', 'IsFloating', 2),
- 'FpDestS3P1': ('FloatReg', 'sf', '(dest + step * 3 + 1)', 'IsFloating', 2),
- 'Result': ('IntReg', 'uw', 'result', 'IsInteger', 2,
+ 'FpDest': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 3),
+ 'FpDestP0': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 3),
+ 'FpDestP1': ('FloatReg', 'sf', '(dest + 1)', 'IsFloating', 3),
+ 'FpDestP2': ('FloatReg', 'sf', '(dest + 2)', 'IsFloating', 3),
+ 'FpDestP3': ('FloatReg', 'sf', '(dest + 3)', 'IsFloating', 3),
+ 'FpDestP4': ('FloatReg', 'sf', '(dest + 4)', 'IsFloating', 3),
+ 'FpDestP5': ('FloatReg', 'sf', '(dest + 5)', 'IsFloating', 3),
+ 'FpDestP6': ('FloatReg', 'sf', '(dest + 6)', 'IsFloating', 3),
+ 'FpDestP7': ('FloatReg', 'sf', '(dest + 7)', 'IsFloating', 3),
+ 'FpDestS0P0': ('FloatReg', 'sf', '(dest + step * 0 + 0)', 'IsFloating', 3),
+ 'FpDestS0P1': ('FloatReg', 'sf', '(dest + step * 0 + 1)', 'IsFloating', 3),
+ 'FpDestS1P0': ('FloatReg', 'sf', '(dest + step * 1 + 0)', 'IsFloating', 3),
+ 'FpDestS1P1': ('FloatReg', 'sf', '(dest + step * 1 + 1)', 'IsFloating', 3),
+ 'FpDestS2P0': ('FloatReg', 'sf', '(dest + step * 2 + 0)', 'IsFloating', 3),
+ 'FpDestS2P1': ('FloatReg', 'sf', '(dest + step * 2 + 1)', 'IsFloating', 3),
+ 'FpDestS3P0': ('FloatReg', 'sf', '(dest + step * 3 + 0)', 'IsFloating', 3),
+ 'FpDestS3P1': ('FloatReg', 'sf', '(dest + step * 3 + 1)', 'IsFloating', 3),
+ 'Result': ('IntReg', 'uw', 'result', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Dest2': ('IntReg', 'uw', 'dest2', 'IsInteger', 2,
+ 'Dest2': ('IntReg', 'uw', 'dest2', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'FpDest2': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 2),
- 'FpDest2P0': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 2),
- 'FpDest2P1': ('FloatReg', 'sf', '(dest2 + 1)', 'IsFloating', 2),
- 'FpDest2P2': ('FloatReg', 'sf', '(dest2 + 2)', 'IsFloating', 2),
- 'FpDest2P3': ('FloatReg', 'sf', '(dest2 + 3)', 'IsFloating', 2),
- 'IWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 2,
+ 'FpDest2': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 3),
+ 'FpDest2P0': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 3),
+ 'FpDest2P1': ('FloatReg', 'sf', '(dest2 + 1)', 'IsFloating', 3),
+ 'FpDest2P2': ('FloatReg', 'sf', '(dest2 + 2)', 'IsFloating', 3),
+ 'FpDest2P3': ('FloatReg', 'sf', '(dest2 + 3)', 'IsFloating', 3),
+ 'IWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 3,
maybePCRead, maybeIWPCWrite),
- 'AIWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 2,
+ 'AIWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 3,
maybePCRead, maybeAIWPCWrite),
'SpMode': ('IntReg', 'uw',
'intRegInMode((OperatingMode)regMode, INTREG_SP)',
- 'IsInteger', 2),
- 'MiscDest': ('ControlReg', 'uw', 'dest', (None, None, 'IsControl'), 2),
- 'Base': ('IntReg', 'uw', 'base', 'IsInteger', 0,
+ 'IsInteger', 3),
+ 'MiscDest': ('ControlReg', 'uw', 'dest', (None, None, 'IsControl'), 3),
+ 'Base': ('IntReg', 'uw', 'base', 'IsInteger', 1,
maybeAlignedPCRead, maybePCWrite),
- 'Index': ('IntReg', 'uw', 'index', 'IsInteger', 2,
+ 'Index': ('IntReg', 'uw', 'index', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Op1': ('IntReg', 'uw', 'op1', 'IsInteger', 2,
+ 'Op1': ('IntReg', 'uw', 'op1', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'FpOp1': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 2),
- 'FpOp1P0': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 2),
- 'FpOp1P1': ('FloatReg', 'sf', '(op1 + 1)', 'IsFloating', 2),
- 'FpOp1P2': ('FloatReg', 'sf', '(op1 + 2)', 'IsFloating', 2),
- 'FpOp1P3': ('FloatReg', 'sf', '(op1 + 3)', 'IsFloating', 2),
- 'FpOp1P4': ('FloatReg', 'sf', '(op1 + 4)', 'IsFloating', 2),
- 'FpOp1P5': ('FloatReg', 'sf', '(op1 + 5)', 'IsFloating', 2),
- 'FpOp1P6': ('FloatReg', 'sf', '(op1 + 6)', 'IsFloating', 2),
- 'FpOp1P7': ('FloatReg', 'sf', '(op1 + 7)', 'IsFloating', 2),
- 'FpOp1S0P0': ('FloatReg', 'sf', '(op1 + step * 0 + 0)', 'IsFloating', 2),
- 'FpOp1S0P1': ('FloatReg', 'sf', '(op1 + step * 0 + 1)', 'IsFloating', 2),
- 'FpOp1S1P0': ('FloatReg', 'sf', '(op1 + step * 1 + 0)', 'IsFloating', 2),
- 'FpOp1S1P1': ('FloatReg', 'sf', '(op1 + step * 1 + 1)', 'IsFloating', 2),
- 'FpOp1S2P0': ('FloatReg', 'sf', '(op1 + step * 2 + 0)', 'IsFloating', 2),
- 'FpOp1S2P1': ('FloatReg', 'sf', '(op1 + step * 2 + 1)', 'IsFloating', 2),
- 'FpOp1S3P0': ('FloatReg', 'sf', '(op1 + step * 3 + 0)', 'IsFloating', 2),
- 'FpOp1S3P1': ('FloatReg', 'sf', '(op1 + step * 3 + 1)', 'IsFloating', 2),
- 'MiscOp1': ('ControlReg', 'uw', 'op1', (None, None, 'IsControl'), 2),
- 'Op2': ('IntReg', 'uw', 'op2', 'IsInteger', 2,
+ 'FpOp1': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 3),
+ 'FpOp1P0': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 3),
+ 'FpOp1P1': ('FloatReg', 'sf', '(op1 + 1)', 'IsFloating', 3),
+ 'FpOp1P2': ('FloatReg', 'sf', '(op1 + 2)', 'IsFloating', 3),
+ 'FpOp1P3': ('FloatReg', 'sf', '(op1 + 3)', 'IsFloating', 3),
+ 'FpOp1P4': ('FloatReg', 'sf', '(op1 + 4)', 'IsFloating', 3),
+ 'FpOp1P5': ('FloatReg', 'sf', '(op1 + 5)', 'IsFloating', 3),
+ 'FpOp1P6': ('FloatReg', 'sf', '(op1 + 6)', 'IsFloating', 3),
+ 'FpOp1P7': ('FloatReg', 'sf', '(op1 + 7)', 'IsFloating', 3),
+ 'FpOp1S0P0': ('FloatReg', 'sf', '(op1 + step * 0 + 0)', 'IsFloating', 3),
+ 'FpOp1S0P1': ('FloatReg', 'sf', '(op1 + step * 0 + 1)', 'IsFloating', 3),
+ 'FpOp1S1P0': ('FloatReg', 'sf', '(op1 + step * 1 + 0)', 'IsFloating', 3),
+ 'FpOp1S1P1': ('FloatReg', 'sf', '(op1 + step * 1 + 1)', 'IsFloating', 3),
+ 'FpOp1S2P0': ('FloatReg', 'sf', '(op1 + step * 2 + 0)', 'IsFloating', 3),
+ 'FpOp1S2P1': ('FloatReg', 'sf', '(op1 + step * 2 + 1)', 'IsFloating', 3),
+ 'FpOp1S3P0': ('FloatReg', 'sf', '(op1 + step * 3 + 0)', 'IsFloating', 3),
+ 'FpOp1S3P1': ('FloatReg', 'sf', '(op1 + step * 3 + 1)', 'IsFloating', 3),
+ 'MiscOp1': ('ControlReg', 'uw', 'op1', (None, None, 'IsControl'), 3),
+ 'Op2': ('IntReg', 'uw', 'op2', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'FpOp2': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 2),
- 'FpOp2P0': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 2),
- 'FpOp2P1': ('FloatReg', 'sf', '(op2 + 1)', 'IsFloating', 2),
- 'FpOp2P2': ('FloatReg', 'sf', '(op2 + 2)', 'IsFloating', 2),
- 'FpOp2P3': ('FloatReg', 'sf', '(op2 + 3)', 'IsFloating', 2),
- 'Op3': ('IntReg', 'uw', 'op3', 'IsInteger', 2,
+ 'FpOp2': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 3),
+ 'FpOp2P0': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 3),
+ 'FpOp2P1': ('FloatReg', 'sf', '(op2 + 1)', 'IsFloating', 3),
+ 'FpOp2P2': ('FloatReg', 'sf', '(op2 + 2)', 'IsFloating', 3),
+ 'FpOp2P3': ('FloatReg', 'sf', '(op2 + 3)', 'IsFloating', 3),
+ 'Op3': ('IntReg', 'uw', 'op3', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Shift': ('IntReg', 'uw', 'shift', 'IsInteger', 2,
+ 'Shift': ('IntReg', 'uw', 'shift', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Reg0': ('IntReg', 'uw', 'reg0', 'IsInteger', 2,
+ 'Reg0': ('IntReg', 'uw', 'reg0', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Reg1': ('IntReg', 'uw', 'reg1', 'IsInteger', 2,
+ 'Reg1': ('IntReg', 'uw', 'reg1', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Reg2': ('IntReg', 'uw', 'reg2', 'IsInteger', 2,
+ 'Reg2': ('IntReg', 'uw', 'reg2', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Reg3': ('IntReg', 'uw', 'reg3', 'IsInteger', 2,
+ 'Reg3': ('IntReg', 'uw', 'reg3', 'IsInteger', 3,
maybePCRead, maybePCWrite),
#General Purpose Integer Reg Operands
- 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 2, maybePCRead, maybePCWrite),
- 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 2, maybePCRead, maybePCWrite),
- 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2, maybePCRead, maybePCWrite),
- 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 2, maybePCRead, maybePCWrite),
- 'R7': ('IntReg', 'uw', '7', 'IsInteger', 2),
- 'R0': ('IntReg', 'uw', '0', 'IsInteger', 2),
+ 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 3, maybePCRead, maybePCWrite),
+ 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 3, maybePCRead, maybePCWrite),
+ 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3, maybePCRead, maybePCWrite),
+ 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 3, maybePCRead, maybePCWrite),
+ 'R7': ('IntReg', 'uw', '7', 'IsInteger', 3),
+ 'R0': ('IntReg', 'uw', '0', 'IsInteger', 3),
- 'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 2),
- 'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', None, 2),
+ 'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 3),
+ 'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', None, 3),
'OptCondCodes': ('IntReg', 'uw',
'''(condCode == COND_AL || condCode == COND_UC) ?
- INTREG_ZERO : INTREG_CONDCODES''', None, 2),
- 'FpCondCodes': ('IntReg', 'uw', 'INTREG_FPCONDCODES', None, 2),
+ INTREG_ZERO : INTREG_CONDCODES''', None, 3),
+ 'FpCondCodes': ('IntReg', 'uw', 'INTREG_FPCONDCODES', None, 3),
#Register fields for microops
- 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 2, maybePCRead, maybePCWrite),
- 'IWRa' : ('IntReg', 'uw', 'ura', 'IsInteger', 2,
+ 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 3, maybePCRead, maybePCWrite),
+ 'IWRa' : ('IntReg', 'uw', 'ura', 'IsInteger', 3,
maybePCRead, maybeIWPCWrite),
- 'Fa' : ('FloatReg', 'sf', 'ura', 'IsFloating', 2),
- 'Rb' : ('IntReg', 'uw', 'urb', 'IsInteger', 2, maybePCRead, maybePCWrite),
- 'Rc' : ('IntReg', 'uw', 'urc', 'IsInteger', 2, maybePCRead, maybePCWrite),
+ 'Fa' : ('FloatReg', 'sf', 'ura', 'IsFloating', 3),
+ 'Rb' : ('IntReg', 'uw', 'urb', 'IsInteger', 3, maybePCRead, maybePCWrite),
+ 'Rc' : ('IntReg', 'uw', 'urc', 'IsInteger', 3, maybePCRead, maybePCWrite),
#General Purpose Floating Point Reg Operands
- 'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 2),
- 'Fn': ('FloatReg', 'df', 'FN', 'IsFloating', 2),
- 'Fm': ('FloatReg', 'df', 'FM', 'IsFloating', 2),
+ 'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 3),
+ 'Fn': ('FloatReg', 'df', 'FN', 'IsFloating', 3),
+ 'Fm': ('FloatReg', 'df', 'FM', 'IsFloating', 3),
#Memory Operand
- 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 2),
+ 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 3),
- 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 1),
- 'Itstate': ('ControlReg', 'ub', 'MISCREG_ITSTATE', None, 2),
- 'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', None, 2),
- 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', None, 2),
- 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', None, 2),
- 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', None, 2),
- 'Cpacr': ('ControlReg', 'uw', 'MISCREG_CPACR', (None, None, 'IsControl'), 2),
- 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', None, 2),
- 'Sctlr': ('ControlReg', 'uw', 'MISCREG_SCTLR', None, 2),
- 'SevMailbox': ('ControlReg', 'uw', 'MISCREG_SEV_MAILBOX', None, 2),
- 'PC': ('PC', 'ud', None, None, 2),
- 'NPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2,
- readNPC, writeNPC),
- 'FNPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2,
- readNPC, forceNPC),
- 'IWNPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2,
- readNPC, writeIWNPC),
+ 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 2),
+ 'Itstate': ('ControlReg', 'ub', 'MISCREG_ITSTATE', None, 3),
+ 'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', None, 3),
+ 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', None, 3),
+ 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', None, 3),
+ 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', None, 3),
+ 'Cpacr': ('ControlReg', 'uw', 'MISCREG_CPACR', (None, None, 'IsControl'), 3),
+ 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', None, 3),
+ 'Sctlr': ('ControlReg', 'uw', 'MISCREG_SCTLR', None, 3),
+ 'SevMailbox': ('ControlReg', 'uw', 'MISCREG_SEV_MAILBOX', None, 3),
+ #PCS needs to have a sorting index (the number at the end) less than all
+ #the integer registers which might update the PC. That way if the flag
+ #bits of the pc state are updated and a branch happens through R15, the
+ #updates are layered properly and the R15 update isn't lost.
+ 'PCS': ('PCState', 'uw', None, (None, None, 'IsControl'), 0)
}};
diff --git a/src/arch/arm/isa_traits.hh b/src/arch/arm/isa_traits.hh
index 8d3f0ffe3..f6aa7fcf0 100644
--- a/src/arch/arm/isa_traits.hh
+++ b/src/arch/arm/isa_traits.hh
@@ -123,15 +123,6 @@ namespace ArmISA
INT_FIQ,
NumInterruptTypes
};
-
- // These otherwise unused bits of the PC are used to select a mode
- // like the J and T bits of the CPSR.
- static const Addr PcJBitShift = 33;
- static const Addr PcJBit = ULL(1) << PcJBitShift;
- static const Addr PcTBitShift = 34;
- static const Addr PcTBit = ULL(1) << PcTBitShift;
- static const Addr PcModeMask = (ULL(1) << PcJBitShift) |
- (ULL(1) << PcTBitShift);
};
using namespace ArmISA;
diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc
index 7c4e00921..40658976b 100644
--- a/src/arch/arm/linux/system.cc
+++ b/src/arch/arm/linux/system.cc
@@ -103,8 +103,7 @@ LinuxArmSystem::startup()
ThreadContext *tc = threadContexts[0];
// Set the initial PC to be at start of the kernel code
- tc->setPC(tc->getSystemPtr()->kernelEntry & loadAddrMask);
- tc->setNextPC(tc->readPC() + sizeof(MachInst));
+ tc->pcState(tc->getSystemPtr()->kernelEntry & loadAddrMask);
// Setup the machine type
tc->setIntReg(0, 0);
diff --git a/src/arch/arm/nativetrace.cc b/src/arch/arm/nativetrace.cc
index d97be88a2..75546f8de 100644
--- a/src/arch/arm/nativetrace.cc
+++ b/src/arch/arm/nativetrace.cc
@@ -106,7 +106,7 @@ Trace::ArmNativeTrace::ThreadState::update(ThreadContext *tc)
}
//R15, aliased with the PC
- newState[STATE_PC] = tc->readNextPC();
+ newState[STATE_PC] = tc->pcState().npc();
changed[STATE_PC] = (newState[STATE_PC] != oldState[STATE_PC]);
//CPSR
@@ -121,7 +121,7 @@ Trace::ArmNativeTrace::check(NativeTraceRecord *record)
ThreadContext *tc = record->getThread();
// This area is read only on the target. It can't stop there to tell us
// what's going on, so we should skip over anything there also.
- if (tc->readNextPC() > 0xffff0000)
+ if (tc->nextInstAddr() > 0xffff0000)
return;
nState.update(this);
mState.update(tc);
diff --git a/src/arch/arm/predecoder.cc b/src/arch/arm/predecoder.cc
index 04cec59b9..456b9e4c4 100644
--- a/src/arch/arm/predecoder.cc
+++ b/src/arch/arm/predecoder.cc
@@ -148,11 +148,11 @@ Predecoder::process()
//Use this to give data to the predecoder. This should be used
//when there is control flow.
void
-Predecoder::moreBytes(Addr pc, Addr fetchPC, MachInst inst)
+Predecoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
{
data = inst;
- offset = (fetchPC >= pc) ? 0 : pc - fetchPC;
- emi.thumb = isThumb(pc);
+ offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC;
+ emi.thumb = pc.thumb();
FPSCR fpscr = tc->readMiscReg(MISCREG_FPSCR);
emi.fpscrLen = fpscr.len;
emi.fpscrStride = fpscr.stride;
diff --git a/src/arch/arm/predecoder.hh b/src/arch/arm/predecoder.hh
index 2db550024..47242b8ff 100644
--- a/src/arch/arm/predecoder.hh
+++ b/src/arch/arm/predecoder.hh
@@ -94,7 +94,7 @@ namespace ArmISA
//Use this to give data to the predecoder. This should be used
//when there is control flow.
- void moreBytes(Addr pc, Addr fetchPC, MachInst inst);
+ void moreBytes(const PCState &pc, Addr fetchPC, MachInst inst);
//Use this to give data to the predecoder. This should be used
//when instructions are executed in order.
@@ -121,9 +121,10 @@ namespace ArmISA
}
//This returns a constant reference to the ExtMachInst to avoid a copy
- ExtMachInst getExtMachInst()
+ ExtMachInst getExtMachInst(PCState &pc)
{
ExtMachInst thisEmi = emi;
+ pc.npc(pc.pc() + getInstSize());
emi = 0;
return thisEmi;
}
diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc
index bc2aee4c8..a5460ac19 100644
--- a/src/arch/arm/process.cc
+++ b/src/arch/arm/process.cc
@@ -360,11 +360,11 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
tc->setIntReg(ArgumentReg2, 0);
}
- Addr prog_entry = objFile->entryPoint();
- if (arch == ObjectFile::Thumb)
- prog_entry = (prog_entry & ~mask(1)) | PcTBit;
- tc->setPC(prog_entry);
- tc->setNextPC(prog_entry + sizeof(MachInst));
+ PCState pc;
+ pc.thumb(arch == ObjectFile::Thumb);
+ pc.nextThumb(pc.thumb());
+ pc.set(objFile->entryPoint() & ~mask(1));
+ tc->pcState(pc);
//Align the "stack_min" to a page boundary.
stack_min = roundDown(stack_min, pageSize);
diff --git a/src/arch/arm/system.hh b/src/arch/arm/system.hh
index fe5ba6447..c64673df5 100644
--- a/src/arch/arm/system.hh
+++ b/src/arch/arm/system.hh
@@ -70,7 +70,7 @@ class ArmSystem : public System
// Remove the low bit that thumb symbols have set
// but that aren't actually odd aligned
if (addr & 0x1)
- return (addr & ~1) | PcTBit;
+ return addr & ~1;
return addr;
}
};
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc
index 73dd24e1c..06bb10219 100644
--- a/src/arch/arm/table_walker.cc
+++ b/src/arch/arm/table_walker.cc
@@ -107,7 +107,7 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _
/** @todo These should be cached or grabbed from cached copies in
the TLB, all these miscreg reads are expensive */
- currState->vaddr = currState->req->getVaddr() & ~PcModeMask;
+ currState->vaddr = currState->req->getVaddr();
currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR);
sctlr = currState->sctlr;
currState->N = currState->tc->readMiscReg(MISCREG_TTBCR);
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index c0ebb52b2..239d5d8a2 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -316,7 +316,7 @@ TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode,
Translation *translation, bool &delay, bool timing)
{
// XXX Cache misc registers and have miscreg write function inv cache
- Addr vaddr = req->getVaddr() & ~PcModeMask;
+ Addr vaddr = req->getVaddr();
SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
uint32_t flags = req->getFlags();
@@ -362,7 +362,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
Translation *translation, bool &delay, bool timing)
{
// XXX Cache misc registers and have miscreg write function inv cache
- Addr vaddr = req->getVaddr() & ~PcModeMask;
+ Addr vaddr = req->getVaddr();
SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
uint32_t flags = req->getFlags();
diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh
index 3c3b29494..57f34e3c2 100644
--- a/src/arch/arm/types.hh
+++ b/src/arch/arm/types.hh
@@ -43,8 +43,10 @@
#ifndef __ARCH_ARM_TYPES_HH__
#define __ARCH_ARM_TYPES_HH__
+#include "arch/generic/types.hh"
#include "base/bitunion.hh"
#include "base/hashmap.hh"
+#include "base/misc.hh"
#include "base/types.hh"
namespace ArmISA
@@ -188,6 +190,189 @@ namespace ArmISA
Bitfield<11, 8> ltcoproc;
EndBitUnion(ExtMachInst)
+ class PCState : public GenericISA::UPCState<MachInst>
+ {
+ protected:
+
+ typedef GenericISA::UPCState<MachInst> Base;
+
+ enum FlagBits {
+ ThumbBit = (1 << 0),
+ JazelleBit = (1 << 1)
+ };
+ uint8_t flags;
+ uint8_t nextFlags;
+
+ public:
+ PCState() : flags(0), nextFlags(0)
+ {}
+
+ void
+ set(Addr val)
+ {
+ Base::set(val);
+ npc(val + (thumb() ? 2 : 4));
+ }
+
+ PCState(Addr val) : flags(0), nextFlags(0)
+ { set(val); }
+
+ bool
+ thumb() const
+ {
+ return flags & ThumbBit;
+ }
+
+ void
+ thumb(bool val)
+ {
+ if (val)
+ flags |= ThumbBit;
+ else
+ flags &= ~ThumbBit;
+ }
+
+ bool
+ nextThumb() const
+ {
+ return nextFlags & ThumbBit;
+ }
+
+ void
+ nextThumb(bool val)
+ {
+ if (val)
+ nextFlags |= ThumbBit;
+ else
+ nextFlags &= ~ThumbBit;
+ }
+
+ bool
+ jazelle() const
+ {
+ return flags & JazelleBit;
+ }
+
+ void
+ jazelle(bool val)
+ {
+ if (val)
+ flags |= JazelleBit;
+ else
+ flags &= ~JazelleBit;
+ }
+
+ bool
+ nextJazelle() const
+ {
+ return nextFlags & JazelleBit;
+ }
+
+ void
+ nextJazelle(bool val)
+ {
+ if (val)
+ nextFlags |= JazelleBit;
+ else
+ nextFlags &= ~JazelleBit;
+ }
+
+ void
+ advance()
+ {
+ Base::advance();
+ npc(pc() + (thumb() ? 2 : 4));
+ flags = nextFlags;
+ }
+
+ void
+ uEnd()
+ {
+ advance();
+ upc(0);
+ nupc(1);
+ }
+
+ Addr
+ instPC() const
+ {
+ return pc() + (thumb() ? 4 : 8);
+ }
+
+ void
+ instNPC(uint32_t val)
+ {
+ npc(val &~ mask(nextThumb() ? 1 : 2));
+ }
+
+ Addr
+ instNPC() const
+ {
+ return npc();
+ }
+
+ // Perform an interworking branch.
+ void
+ instIWNPC(uint32_t val)
+ {
+ bool thumbEE = (thumb() && jazelle());
+
+ Addr newPC = val;
+ if (thumbEE) {
+ if (bits(newPC, 0)) {
+ newPC = newPC & ~mask(1);
+ } else {
+ panic("Bad thumbEE interworking branch address %#x.\n",
+ newPC);
+ }
+ } else {
+ if (bits(newPC, 0)) {
+ nextThumb(true);
+ newPC = newPC & ~mask(1);
+ } else if (!bits(newPC, 1)) {
+ nextThumb(false);
+ } else {
+ warn("Bad interworking branch address %#x.\n", newPC);
+ }
+ }
+ npc(newPC);
+ }
+
+ // Perform an interworking branch in ARM mode, a regular branch
+ // otherwise.
+ void
+ instAIWNPC(uint32_t val)
+ {
+ if (!thumb() && !jazelle())
+ instIWNPC(val);
+ else
+ instNPC(val);
+ }
+
+ bool
+ operator == (const PCState &opc) const
+ {
+ return Base::operator == (opc) &&
+ flags == opc.flags && nextFlags == opc.nextFlags;
+ }
+
+ void
+ serialize(std::ostream &os)
+ {
+ Base::serialize(os);
+ SERIALIZE_SCALAR(flags);
+ SERIALIZE_SCALAR(nextFlags);
+ }
+
+ void
+ unserialize(Checkpoint *cp, const std::string &section)
+ {
+ 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 &section)
+ {
+ 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 &section)
+ {
+ 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 &section)
+ {
+ 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 &section)
+ {
+ Base::unserialize(cp, section);
+ UNSERIALIZE_SCALAR(_upc);
+ UNSERIALIZE_SCALAR(_nupc);
+ }
+};
+
+template <class MachInst>
+std::ostream &
+operator<<(std::ostream & os, const DelaySlotUPCState<MachInst> &pc)
+{
+ ccprintf(os, "(%#x=>%#x=>%#x).(%d=>%d)",
+ pc.pc(), pc.npc(), pc.nnpc(), pc.upc(), pc.nupc());
+ return os;
+}
+
+}
+
+#endif
diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py
index 4e06c2ded..8e13b6a6a 100755
--- a/src/arch/isa_parser.py
+++ b/src/arch/isa_parser.py
@@ -681,71 +681,43 @@ class MemOperand(Operand):
def makeAccSize(self):
return self.size
-class PCOperand(Operand):
+class PCStateOperand(Operand):
def makeConstructor(self):
return ''
def makeRead(self):
- return '%s = xc->readPC();\n' % self.base_name
+ return '%s = xc->pcState();\n' % self.base_name
def makeWrite(self):
- return 'xc->setPC(%s);\n' % self.base_name
+ return 'xc->pcState(%s);\n' % self.base_name
-class UPCOperand(Operand):
- def makeConstructor(self):
- return ''
-
- def makeRead(self):
- if self.read_code != None:
- return self.buildReadCode('readMicroPC')
- return '%s = xc->readMicroPC();\n' % self.base_name
-
- def makeWrite(self):
- if self.write_code != None:
- return self.buildWriteCode('setMicroPC')
- return 'xc->setMicroPC(%s);\n' % self.base_name
+ def makeDecl(self):
+ return 'TheISA::PCState ' + self.base_name + ' M5_VAR_USED;\n';
-class NUPCOperand(Operand):
+class PCOperand(Operand):
def makeConstructor(self):
return ''
def makeRead(self):
- if self.read_code != None:
- return self.buildReadCode('readNextMicroPC')
- return '%s = xc->readNextMicroPC();\n' % self.base_name
+ return '%s = xc->instAddr();\n' % self.base_name
- def makeWrite(self):
- if self.write_code != None:
- return self.buildWriteCode('setNextMicroPC')
- return 'xc->setNextMicroPC(%s);\n' % self.base_name
-
-class NPCOperand(Operand):
+class UPCOperand(Operand):
def makeConstructor(self):
return ''
def makeRead(self):
if self.read_code != None:
- return self.buildReadCode('readNextPC')
- return '%s = xc->readNextPC();\n' % self.base_name
-
- def makeWrite(self):
- if self.write_code != None:
- return self.buildWriteCode('setNextPC')
- return 'xc->setNextPC(%s);\n' % self.base_name
+ return self.buildReadCode('microPC')
+ return '%s = xc->microPC();\n' % self.base_name
-class NNPCOperand(Operand):
+class NPCOperand(Operand):
def makeConstructor(self):
return ''
def makeRead(self):
if self.read_code != None:
- return self.buildReadCode('readNextNPC')
- return '%s = xc->readNextNPC();\n' % self.base_name
-
- def makeWrite(self):
- if self.write_code != None:
- return self.buildWriteCode('setNextNPC')
- return 'xc->setNextNPC(%s);\n' % self.base_name
+ return self.buildReadCode('nextInstAddr')
+ return '%s = xc->nextInstAddr();\n' % self.base_name
class OperandList(object):
'''Find all the operands in the given code block. Returns an operand
diff --git a/src/arch/mips/isa/base.isa b/src/arch/mips/isa/base.isa
index 4e2b12fc4..cd6faf0f3 100644
--- a/src/arch/mips/isa/base.isa
+++ b/src/arch/mips/isa/base.isa
@@ -56,6 +56,13 @@ output header {{
void printReg(std::ostream &os, int reg) const;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ public:
+ void
+ advancePC(MipsISA::PCState &pc) const
+ {
+ pc.advance();
+ }
};
}};
diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa
index 9832937b5..3f3bd370a 100644
--- a/src/arch/mips/isa/decoder.isa
+++ b/src/arch/mips/isa/decoder.isa
@@ -133,25 +133,34 @@ decode OPCODE_HI default Unknown::unknown() {
0x1: jr_hb({{
Config1Reg config1 = Config1;
if (config1.ca == 0) {
- NNPC = Rs;
+ pc.nnpc(Rs);
} else {
panic("MIPS16e not supported\n");
}
+ PCS = pc;
}}, IsReturn, ClearHazards);
default: jr({{
Config1Reg config1 = Config1;
if (config1.ca == 0) {
- NNPC = Rs;
+ pc.nnpc(Rs);
} else {
panic("MIPS16e not supported\n");
}
+ PCS = pc;
}}, IsReturn);
}
0x1: decode HINT {
- 0x1: jalr_hb({{ Rd = NNPC; NNPC = Rs; }}, IsCall
- , ClearHazards);
- default: jalr({{ Rd = NNPC; NNPC = Rs; }}, IsCall);
+ 0x1: jalr_hb({{
+ Rd = pc.nnpc();
+ pc.nnpc(Rs);
+ PCS = pc;
+ }}, IsCall, ClearHazards);
+ default: jalr({{
+ Rd = pc.nnpc();
+ pc.nnpc(Rs);
+ PCS = pc;
+ }}, IsCall);
}
}
@@ -323,9 +332,14 @@ decode OPCODE_HI default Unknown::unknown() {
}
format Jump {
- 0x2: j({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2); }});
- 0x3: jal({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2); }},
- IsCall, Link);
+ 0x2: j({{
+ pc.nnpc((pc.npc() & 0xF0000000) | (JMPTARG << 2));
+ PCS = pc;
+ }});
+ 0x3: jal({{
+ pc.nnpc((pc.npc() & 0xF0000000) | (JMPTARG << 2));
+ PCS = pc;
+ }}, IsCall, Link);
}
format Branch {
@@ -694,15 +708,16 @@ decode OPCODE_HI default Unknown::unknown() {
ConfigReg config = Config;
SRSCtlReg srsCtl = SRSCtl;
DPRINTF(MipsPRA,"Restoring PC - %x\n",EPC);
+ MipsISA::PCState pc = PCS;
if (status.erl == 1) {
status.erl = 0;
- NPC = ErrorEPC;
+ pc.npc(ErrorEPC);
// Need to adjust NNPC, otherwise things break
- NNPC = ErrorEPC + sizeof(MachInst);
+ pc.nnpc(ErrorEPC + sizeof(MachInst));
} else {
- NPC = EPC;
+ pc.npc(EPC);
// Need to adjust NNPC, otherwise things break
- NNPC = EPC + sizeof(MachInst);
+ pc.nnpc(EPC + sizeof(MachInst));
status.exl = 0;
if (config.ar >=1 &&
srsCtl.hss > 0 &&
@@ -711,6 +726,7 @@ decode OPCODE_HI default Unknown::unknown() {
//xc->setShadowSet(srsCtl.pss);
}
}
+ PCS = pc;
LLFlag = 0;
Status = status;
SRSCtl = srsCtl;
@@ -718,13 +734,15 @@ decode OPCODE_HI default Unknown::unknown() {
0x1F: deret({{
DebugReg debug = Debug;
+ MipsISA::PCState pc = PCS;
if (debug.dm == 1) {
debug.dm = 1;
debug.iexi = 0;
- NPC = DEPC;
+ pc.npc(DEPC);
} else {
// Undefined;
}
+ PCS = pc;
Debug = debug;
}}, IsReturn, IsSerializing, IsERET);
}
diff --git a/src/arch/mips/isa/formats/branch.isa b/src/arch/mips/isa/formats/branch.isa
index 78f973a70..232a743a7 100644
--- a/src/arch/mips/isa/formats/branch.isa
+++ b/src/arch/mips/isa/formats/branch.isa
@@ -89,7 +89,7 @@ output header {{
}
}
- Addr branchTarget(Addr branchPC) const;
+ MipsISA::PCState branchTarget(const MipsISA::PCState &branchPC) const;
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
@@ -116,7 +116,7 @@ output header {{
{
}
- Addr branchTarget(ThreadContext *tc) const;
+ MipsISA::PCState branchTarget(ThreadContext *tc) const;
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
@@ -124,17 +124,25 @@ output header {{
}};
output decoder {{
- Addr
- Branch::branchTarget(Addr branchPC) const
+ MipsISA::PCState
+ Branch::branchTarget(const MipsISA::PCState &branchPC) const
{
- return branchPC + 4 + disp;
+ MipsISA::PCState target = branchPC;
+ target.advance();
+ target.npc(branchPC.pc() + sizeof(MachInst) + disp);
+ target.nnpc(target.npc() + sizeof(MachInst));
+ return target;
}
- Addr
+ MipsISA::PCState
Jump::branchTarget(ThreadContext *tc) const
{
- Addr NPC = tc->readNextPC();
- return (NPC & 0xF0000000) | (disp);
+ MipsISA::PCState target = tc->pcState();
+ Addr pc = target.pc();
+ target.advance();
+ target.npc((pc & 0xF0000000) | disp);
+ target.nnpc(target.npc() + sizeof(MachInst));
+ return target;
}
const std::string &
@@ -217,19 +225,16 @@ output decoder {{
}};
def format Branch(code, *opt_flags) {{
- not_taken_code = ' NNPC = NNPC;\n'
- not_taken_code += '} \n'
+ not_taken_code = ''
#Build Instruction Flags
#Use Link & Likely Flags to Add Link/Condition Code
inst_flags = ('IsDirectControl', )
for x in opt_flags:
if x == 'Link':
- code += 'R31 = NNPC;\n'
+ code += 'R31 = pc.nnpc();\n'
elif x == 'Likely':
- not_taken_code = ' NPC = NNPC;\n'
- not_taken_code += ' NNPC = NNPC + 4;\n'
- not_taken_code += '} \n'
+ not_taken_code = 'pc.advance();'
inst_flags += ('IsCondDelaySlot', )
else:
inst_flags += (x, )
@@ -241,11 +246,17 @@ def format Branch(code, *opt_flags) {{
inst_flags += ('IsCondControl', )
#Condition code
- code = 'bool cond;\n' + code
- code += 'if (cond) {\n'
- code += ' NNPC = NPC + disp;\n'
- code += '} else {\n'
- code += not_taken_code
+ code = '''
+ bool cond;
+ MipsISA::PCState pc = PCS;
+ %(code)s
+ if (cond) {
+ pc.nnpc(pc.npc() + disp);
+ } else {
+ %(not_taken_code)s
+ }
+ PCS = pc;
+ ''' % { "code" : code, "not_taken_code" : not_taken_code }
iop = InstObjParams(name, Name, 'Branch', code, inst_flags)
header_output = BasicDeclare.subst(iop)
@@ -255,19 +266,16 @@ def format Branch(code, *opt_flags) {{
}};
def format DspBranch(code, *opt_flags) {{
- not_taken_code = ' NNPC = NNPC;\n'
- not_taken_code += '} \n'
+ not_taken_code = ''
#Build Instruction Flags
#Use Link & Likely Flags to Add Link/Condition Code
inst_flags = ('IsDirectControl', )
for x in opt_flags:
if x == 'Link':
- code += 'R31 = NNPC;\n'
+ code += 'R32 = pc.nnpc();'
elif x == 'Likely':
- not_taken_code = ' NPC = NNPC;\n'
- not_taken_code += ' NNPC = NNPC + 4;\n'
- not_taken_code += '} \n'
+ not_taken_code = 'pc.advance();'
inst_flags += ('IsCondDelaySlot', )
else:
inst_flags += (x, )
@@ -278,19 +286,19 @@ def format DspBranch(code, *opt_flags) {{
else:
inst_flags += ('IsCondControl', )
- #Declaration code
- decl_code = 'bool cond;\n'
- decl_code += 'uint32_t dspctl;\n'
-
- #Fetch code
- fetch_code = 'dspctl = DSPControl;\n'
-
#Condition code
- code = decl_code + fetch_code + code
- code += 'if (cond) {\n'
- code += ' NNPC = NPC + disp;\n'
- code += '} else {\n'
- code += not_taken_code
+ code = '''
+ MipsISA::PCState pc = PCS;
+ bool cond;
+ uint32_t dspctl = DSPControl;
+ %(code)s
+ if (cond) {
+ pc.nnpc(pc.npc() + disp);
+ } else {
+ %(not_taken_code)s
+ }
+ PCS = pc;
+ ''' % { "code" : code, "not_taken_code" : not_taken_code }
iop = InstObjParams(name, Name, 'Branch', code, inst_flags)
header_output = BasicDeclare.subst(iop)
@@ -305,12 +313,18 @@ def format Jump(code, *opt_flags) {{
inst_flags = ('IsIndirectControl', 'IsUncondControl')
for x in opt_flags:
if x == 'Link':
- code = 'R31 = NNPC;\n' + code
+ code = '''
+ R31 = pc.nnpc();
+ ''' + code
elif x == 'ClearHazards':
code += '/* Code Needed to Clear Execute & Inst Hazards */\n'
else:
inst_flags += (x, )
+ code = '''
+ MipsISA::PCState pc = PCS;
+ ''' + code
+
iop = InstObjParams(name, Name, 'Jump', code, inst_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
diff --git a/src/arch/mips/isa/includes.isa b/src/arch/mips/isa/includes.isa
index 22eb3bf13..d5e1448ac 100644
--- a/src/arch/mips/isa/includes.isa
+++ b/src/arch/mips/isa/includes.isa
@@ -39,6 +39,7 @@ output header {{
#include <iomanip>
#include "arch/mips/isa_traits.hh"
+#include "arch/mips/types.hh"
#include "cpu/static_inst.hh"
#include "mem/packet.hh"
}};
diff --git a/src/arch/mips/isa/operands.isa b/src/arch/mips/isa/operands.isa
index 27cb4357a..1bb5ae5b3 100644
--- a/src/arch/mips/isa/operands.isa
+++ b/src/arch/mips/isa/operands.isa
@@ -151,6 +151,5 @@ def operands {{
'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
#Program Counter Operands
- 'NPC': ('NPC', 'uw', None, 'IsControl', 4),
- 'NNPC':('NNPC', 'uw', None, 'IsControl', 4)
+ 'PCS': ('PCState', 'uw', None, (None, None, 'IsControl'), 4)
}};
diff --git a/src/arch/mips/mt.hh b/src/arch/mips/mt.hh
index 7217c335e..3ec6cbe70 100755
--- a/src/arch/mips/mt.hh
+++ b/src/arch/mips/mt.hh
@@ -77,11 +77,12 @@ haltThread(TC *tc)
// Save last known PC in TCRestart
// @TODO: Needs to check if this is a branch and if so,
// take previous instruction
- tc->setMiscReg(MISCREG_TC_RESTART, tc->readNextPC());
+ PCState pc = tc->pcState();
+ tc->setMiscReg(MISCREG_TC_RESTART, pc.npc());
warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x",
curTick, tc->threadId(), tc->getCpuPtr()->name(),
- tc->readPC(), tc->readNextPC());
+ pc.pc(), pc.npc());
}
}
@@ -91,17 +92,14 @@ restoreThread(TC *tc)
{
if (tc->status() != TC::Active) {
// Restore PC from TCRestart
- IntReg pc = tc->readMiscRegNoEffect(MISCREG_TC_RESTART);
+ Addr restartPC = tc->readMiscRegNoEffect(MISCREG_TC_RESTART);
// TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY
- tc->setPC(pc);
- tc->setNextPC(pc + 4);
- tc->setNextNPC(pc + 8);
+ tc->pcState(restartPC);
tc->activate(0);
warn("%i: Restoring thread %i in %s @ PC %x",
- curTick, tc->threadId(), tc->getCpuPtr()->name(),
- tc->readPC());
+ curTick, tc->threadId(), tc->getCpuPtr()->name(), restartPC);
}
}
diff --git a/src/arch/mips/predecoder.hh b/src/arch/mips/predecoder.hh
index c20fe1f5f..f059710e5 100644
--- a/src/arch/mips/predecoder.hh
+++ b/src/arch/mips/predecoder.hh
@@ -75,7 +75,7 @@ class Predecoder
//Use this to give data to the predecoder. This should be used
//when there is control flow.
void
- moreBytes(Addr pc, Addr fetchPC, MachInst inst)
+ moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
{
emi = inst;
}
@@ -94,7 +94,7 @@ class Predecoder
//This returns a constant reference to the ExtMachInst to avoid a copy
const ExtMachInst &
- getExtMachInst()
+ getExtMachInst(PCState &pc)
{
return emi;
}
diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc
index fa3e3bff9..26a2a0ddb 100644
--- a/src/arch/mips/process.cc
+++ b/src/arch/mips/process.cc
@@ -176,10 +176,7 @@ MipsLiveProcess::argsInit(int pageSize)
setSyscallArg(tc, 1, argv_array_base);
tc->setIntReg(StackPointerReg, stack_min);
- Addr prog_entry = objFile->entryPoint();
- tc->setPC(prog_entry);
- tc->setNextPC(prog_entry + sizeof(MachInst));
- tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
+ tc->pcState(objFile->entryPoint());
}
diff --git a/src/arch/mips/types.hh b/src/arch/mips/types.hh
index c7ef6afe1..f21db51b1 100644
--- a/src/arch/mips/types.hh
+++ b/src/arch/mips/types.hh
@@ -31,6 +31,7 @@
#ifndef __ARCH_MIPS_TYPES_HH__
#define __ARCH_MIPS_TYPES_HH__
+#include "arch/generic/types.hh"
#include "base/types.hh"
namespace MipsISA
@@ -39,6 +40,8 @@ namespace MipsISA
typedef uint32_t MachInst;
typedef uint64_t ExtMachInst;
+typedef GenericISA::DelaySlotPCState<MachInst> PCState;
+
typedef uint64_t LargestRead;
//used in FP convert & round function
diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc
index faae1e937..0859eb80f 100644
--- a/src/arch/mips/utility.cc
+++ b/src/arch/mips/utility.cc
@@ -267,10 +267,9 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
void
skipFunction(ThreadContext *tc)
{
- Addr newpc = tc->readIntReg(ReturnAddressReg);
- tc->setPC(newpc);
- tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
- tc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst));
+ TheISA::PCState newPC = tc->pcState();
+ newPC.set(tc->readIntReg(ReturnAddressReg));
+ tc->pcState(newPC);
}
diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh
index bc50027c0..2f6726c59 100644
--- a/src/arch/mips/utility.hh
+++ b/src/arch/mips/utility.hh
@@ -39,12 +39,22 @@
#include "base/misc.hh"
#include "base/types.hh"
#include "config/full_system.hh"
+#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
class ThreadContext;
namespace MipsISA {
+inline PCState
+buildRetPC(const PCState &curPC, const PCState &callPC)
+{
+ PCState ret = callPC;
+ ret.advance();
+ ret.pc(curPC.npc());
+ return ret;
+}
+
uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp);
////////////////////////////////////////////////////////////////////////
@@ -105,6 +115,12 @@ void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
void skipFunction(ThreadContext *tc);
+inline void
+advancePC(PCState &pc, const StaticInstPtr inst)
+{
+ pc.advance();
+}
+
};
diff --git a/src/arch/power/insts/branch.cc b/src/arch/power/insts/branch.cc
index c10f7c996..352c4ea57 100644
--- a/src/arch/power/insts/branch.cc
+++ b/src/arch/power/insts/branch.cc
@@ -52,10 +52,10 @@ PCDependentDisassembly::disassemble(Addr pc, const SymbolTable *symtab) const
return *cachedDisassembly;
}
-Addr
-BranchPCRel::branchTarget(Addr pc) const
+PowerISA::PCState
+BranchPCRel::branchTarget(const PowerISA::PCState &pc) const
{
- return (uint32_t)(pc + disp);
+ return (uint32_t)(pc.pc() + disp);
}
std::string
@@ -76,8 +76,8 @@ BranchPCRel::generateDisassembly(Addr pc, const SymbolTable *symtab) const
return ss.str();
}
-Addr
-BranchNonPCRel::branchTarget(Addr pc) const
+PowerISA::PCState
+BranchNonPCRel::branchTarget(const PowerISA::PCState &pc) const
{
return targetAddr;
}
@@ -98,10 +98,10 @@ BranchNonPCRel::generateDisassembly(Addr pc, const SymbolTable *symtab) const
return ss.str();
}
-Addr
-BranchPCRelCond::branchTarget(Addr pc) const
+PowerISA::PCState
+BranchPCRelCond::branchTarget(const PowerISA::PCState &pc) const
{
- return (uint32_t)(pc + disp);
+ return (uint32_t)(pc.pc() + disp);
}
std::string
@@ -124,8 +124,8 @@ BranchPCRelCond::generateDisassembly(Addr pc, const SymbolTable *symtab) const
return ss.str();
}
-Addr
-BranchNonPCRelCond::branchTarget(Addr pc) const
+PowerISA::PCState
+BranchNonPCRelCond::branchTarget(const PowerISA::PCState &pc) const
{
return targetAddr;
}
@@ -149,11 +149,11 @@ BranchNonPCRelCond::generateDisassembly(Addr pc,
return ss.str();
}
-Addr
+PowerISA::PCState
BranchRegCond::branchTarget(ThreadContext *tc) const
{
uint32_t regVal = tc->readIntReg(_srcRegIdx[_numSrcRegs - 1]);
- return (regVal & 0xfffffffc);
+ return regVal & 0xfffffffc;
}
std::string
diff --git a/src/arch/power/insts/branch.hh b/src/arch/power/insts/branch.hh
index dd00e42c3..7b9e78dee 100644
--- a/src/arch/power/insts/branch.hh
+++ b/src/arch/power/insts/branch.hh
@@ -86,7 +86,7 @@ class BranchPCRel : public PCDependentDisassembly
}
}
- Addr branchTarget(Addr pc) const;
+ PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
@@ -112,7 +112,7 @@ class BranchNonPCRel : public PCDependentDisassembly
}
}
- Addr branchTarget(Addr pc) const;
+ PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
@@ -187,7 +187,7 @@ class BranchPCRelCond : public BranchCond
}
}
- Addr branchTarget(Addr pc) const;
+ PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
@@ -213,7 +213,7 @@ class BranchNonPCRelCond : public BranchCond
}
}
- Addr branchTarget(Addr pc) const;
+ PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
@@ -231,7 +231,7 @@ class BranchRegCond : public BranchCond
{
}
- Addr branchTarget(ThreadContext *tc) const;
+ PowerISA::PCState branchTarget(ThreadContext *tc) const;
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
diff --git a/src/arch/power/insts/static_inst.hh b/src/arch/power/insts/static_inst.hh
index 399e75371..91eca6fb0 100644
--- a/src/arch/power/insts/static_inst.hh
+++ b/src/arch/power/insts/static_inst.hh
@@ -63,6 +63,12 @@ class PowerStaticInst : public StaticInst
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ void
+ advancePC(PowerISA::PCState &pcState) const
+ {
+ pcState.advance();
+ }
};
} // PowerISA namespace
diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa
index 3252ff14a..671f57389 100644
--- a/src/arch/power/isa/decoder.isa
+++ b/src/arch/power/isa/decoder.isa
@@ -381,12 +381,20 @@ decode OPCODE default Unknown::unknown() {
// Conditionally branch relative to PC based on CR and CTR.
format BranchPCRelCondCtr {
- 0: bc({{ NPC = PC + disp; }});
+ 0: bc({{
+ PowerISA::PCState pc = PCS;
+ pc.npc((uint32_t)(pc.pc() + disp));
+ PCS = pc;
+ }});
}
// Conditionally branch to fixed address based on CR and CTR.
format BranchNonPCRelCondCtr {
- 1: bca({{ NPC = targetAddr; }});
+ 1: bca({{
+ PowerISA::PCState pc = PCS;
+ pc.npc(targetAddr);
+ PCS = pc;
+ }});
}
}
@@ -394,12 +402,20 @@ decode OPCODE default Unknown::unknown() {
// Unconditionally branch relative to PC.
format BranchPCRel {
- 0: b({{ NPC = PC + disp; }});
+ 0: b({{
+ PowerISA::PCState pc = PCS;
+ pc.npc((uint32_t)(pc.pc() + disp));
+ PCS = pc;
+ }});
}
// Unconditionally branch to fixed address.
format BranchNonPCRel {
- 1: ba({{ NPC = targetAddr; }});
+ 1: ba({{
+ PowerISA::PCState pc = PCS;
+ pc.npc(targetAddr);
+ PCS = pc;
+ }});
}
}
@@ -407,12 +423,20 @@ decode OPCODE default Unknown::unknown() {
// Conditionally branch to address in LR based on CR and CTR.
format BranchLrCondCtr {
- 16: bclr({{ NPC = LR & 0xfffffffc; }});
+ 16: bclr({{
+ PowerISA::PCState pc = PCS;
+ pc.npc(LR & 0xfffffffc);
+ PCS = pc;
+ }});
}
// Conditionally branch to address in CTR based on CR.
format BranchCtrCond {
- 528: bcctr({{ NPC = CTR & 0xfffffffc; }});
+ 528: bcctr({{
+ PowerISA::PCState pc = PCS;
+ pc.npc(CTR & 0xfffffffc);
+ PCS = pc;
+ }});
}
// Condition register manipulation instructions.
diff --git a/src/arch/power/isa/formats/branch.isa b/src/arch/power/isa/formats/branch.isa
index d51ed5c25..da1579ea8 100644
--- a/src/arch/power/isa/formats/branch.isa
+++ b/src/arch/power/isa/formats/branch.isa
@@ -48,7 +48,7 @@
let {{
# Simple code to update link register (LR).
-updateLrCode = 'LR = PC + 4;'
+updateLrCode = 'PowerISA::PCState lrpc = PCS; LR = lrpc.pc() + 4;'
}};
@@ -105,7 +105,7 @@ def GetCondCode(br_code):
cond_code = 'if(condOk(CR)) {\n'
cond_code += ' ' + br_code + '\n'
cond_code += '} else {\n'
- cond_code += ' NPC = NPC;\n'
+ cond_code += ' PCS = PCS;\n'
cond_code += '}\n'
return cond_code
@@ -119,7 +119,7 @@ def GetCtrCondCode(br_code):
cond_code += 'if(ctr_ok && cond_ok) {\n'
cond_code += ' ' + br_code + '\n'
cond_code += '} else {\n'
- cond_code += ' NPC = NPC;\n'
+ cond_code += ' PCS = PCS;\n'
cond_code += '}\n'
cond_code += 'CTR = ctr;\n'
return cond_code
diff --git a/src/arch/power/isa/formats/unknown.isa b/src/arch/power/isa/formats/unknown.isa
index 06e6ece26..8914cf9a6 100644
--- a/src/arch/power/isa/formats/unknown.isa
+++ b/src/arch/power/isa/formats/unknown.isa
@@ -76,7 +76,7 @@ output exec {{
{
panic("attempt to execute unknown instruction at %#x"
"(inst 0x%08x, opcode 0x%x, binary: %s)",
- xc->readPC(), machInst, OPCODE, inst2string(machInst));
+ xc->pcState().pc(), machInst, OPCODE, inst2string(machInst));
return new UnimplementedOpcodeFault;
}
}};
diff --git a/src/arch/power/isa/operands.isa b/src/arch/power/isa/operands.isa
index fc6c32685..908e6e0e7 100644
--- a/src/arch/power/isa/operands.isa
+++ b/src/arch/power/isa/operands.isa
@@ -59,8 +59,7 @@ def operands {{
'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 8),
# Program counter and next
- 'PC': ('PC', 'uw', None, (None, None, 'IsControl'), 9),
- 'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 9),
+ 'PCS': ('PCState', 'uq', None, (None, None, 'IsControl'), 9),
# Control registers
'CR': ('IntReg', 'uw', 'INTREG_CR', 'IsInteger', 9),
diff --git a/src/arch/power/predecoder.hh b/src/arch/power/predecoder.hh
index 1f3ac41cb..b1f2b6e38 100644
--- a/src/arch/power/predecoder.hh
+++ b/src/arch/power/predecoder.hh
@@ -83,7 +83,7 @@ class Predecoder
// Use this to give data to the predecoder. This should be used
// when there is control flow.
void
- moreBytes(Addr pc, Addr fetchPC, MachInst inst)
+ moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
{
emi = inst;
}
@@ -110,7 +110,7 @@ class Predecoder
// This returns a constant reference to the ExtMachInst to avoid a copy
const ExtMachInst &
- getExtMachInst()
+ getExtMachInst(PCState &pcState)
{
return emi;
}
diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc
index 9fb69b9f8..a34a874bc 100644
--- a/src/arch/power/process.cc
+++ b/src/arch/power/process.cc
@@ -256,9 +256,7 @@ PowerLiveProcess::argsInit(int intSize, int pageSize)
//Set the stack pointer register
tc->setIntReg(StackPointerReg, stack_min);
- Addr prog_entry = objFile->entryPoint();
- tc->setPC(prog_entry);
- tc->setNextPC(prog_entry + sizeof(MachInst));
+ tc->pcState(objFile->entryPoint());
//Align the "stack_min" to a page boundary.
stack_min = roundDown(stack_min, pageSize);
diff --git a/src/arch/power/types.hh b/src/arch/power/types.hh
index 6a8d1e9d3..d049cdec1 100644
--- a/src/arch/power/types.hh
+++ b/src/arch/power/types.hh
@@ -31,6 +31,7 @@
#ifndef __ARCH_POWER_TYPES_HH__
#define __ARCH_POWER_TYPES_HH__
+#include "arch/generic/types.hh"
#include "base/bitunion.hh"
#include "base/hashmap.hh"
#include "base/types.hh"
@@ -78,6 +79,8 @@ BitUnion32(ExtMachInst)
Bitfield<19, 12> fxm;
EndBitUnion(ExtMachInst)
+typedef GenericISA::SimplePCState<MachInst> PCState;
+
// typedef uint64_t LargestRead;
// // Need to use 64 bits to make sure that read requests get handled properly
diff --git a/src/arch/power/utility.cc b/src/arch/power/utility.cc
index d48d4870a..399ec1f56 100644
--- a/src/arch/power/utility.cc
+++ b/src/arch/power/utility.cc
@@ -52,8 +52,7 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
copyMiscRegs(src, dest);
// Lastly copy PC/NPC
- dest->setPC(src->readPC());
- dest->setNextPC(src->readNextPC());
+ dest->pcState(src->pcState());
}
void
diff --git a/src/arch/power/utility.hh b/src/arch/power/utility.hh
index c8cd441ba..a47fcdc46 100644
--- a/src/arch/power/utility.hh
+++ b/src/arch/power/utility.hh
@@ -36,10 +36,19 @@
#define __ARCH_POWER_UTILITY_HH__
#include "base/types.hh"
+#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
namespace PowerISA {
+inline PCState
+buildRetPC(const PCState &curPC, const PCState &callPC)
+{
+ PCState retPC = callPC;
+ retPC.advance();
+ return retPC;
+}
+
/**
* Function to ensure ISA semantics about 0 registers.
* @param tc The thread context.
@@ -63,6 +72,12 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
void skipFunction(ThreadContext *tc);
+inline void
+advancePC(PCState &pc, const StaticInstPtr inst)
+{
+ pc.advance();
+}
+
} // PowerISA namespace
#endif // __ARCH_POWER_UTILITY_HH__
diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc
index df0a283b9..28ee64321 100644
--- a/src/arch/sparc/faults.cc
+++ b/src/arch/sparc/faults.cc
@@ -307,15 +307,11 @@ void doREDFault(ThreadContext *tc, TrapType tt)
//MiscReg CANSAVE = tc->readMiscRegNoEffect(MISCREG_CANSAVE);
MiscReg CANSAVE = tc->readMiscRegNoEffect(NumIntArchRegs + 3);
MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL);
- MiscReg PC = tc->readPC();
- MiscReg NPC = tc->readNextPC();
+ PCState pc = tc->pcState();
TL++;
- if (bits(PSTATE, 3,3)) {
- PC &= mask(32);
- NPC &= mask(32);
- }
+ Addr pcMask = bits(PSTATE, 3) ? mask(32) : mask(64);
//set TSTATE.gl to gl
replaceBits(TSTATE, 42, 40, GL);
@@ -332,9 +328,9 @@ void doREDFault(ThreadContext *tc, TrapType tt)
tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE);
//set TPC to PC
- tc->setMiscRegNoEffect(MISCREG_TPC, PC);
+ tc->setMiscRegNoEffect(MISCREG_TPC, pc.pc() & pcMask);
//set TNPC to NPC
- tc->setMiscRegNoEffect(MISCREG_TNPC, NPC);
+ tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask);
//set HTSTATE.hpstate to hpstate
tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE);
@@ -394,18 +390,14 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
//MiscReg CANSAVE = tc->readMiscRegNoEffect(MISCREG_CANSAVE);
MiscReg CANSAVE = tc->readIntReg(NumIntArchRegs + 3);
MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL);
- MiscReg PC = tc->readPC();
- MiscReg NPC = tc->readNextPC();
-
- if (bits(PSTATE, 3,3)) {
- PC &= mask(32);
- NPC &= mask(32);
- }
+ PCState pc = tc->pcState();
//Increment the trap level
TL++;
tc->setMiscRegNoEffect(MISCREG_TL, TL);
+ Addr pcMask = bits(PSTATE, 3) ? mask(32) : mask(64);
+
//Save off state
//set TSTATE.gl to gl
@@ -423,9 +415,9 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE);
//set TPC to PC
- tc->setMiscRegNoEffect(MISCREG_TPC, PC);
+ tc->setMiscRegNoEffect(MISCREG_TPC, pc.pc() & pcMask);
//set TNPC to NPC
- tc->setMiscRegNoEffect(MISCREG_TNPC, NPC);
+ tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask);
//set HTSTATE.hpstate to hpstate
tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE);
@@ -479,7 +471,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
}
}
-void getREDVector(MiscReg TT, Addr & PC, Addr & NPC)
+void getREDVector(MiscReg TT, Addr &PC, Addr &NPC)
{
//XXX The following constant might belong in a header file.
const Addr RSTVAddr = 0xFFF0000000ULL;
@@ -554,9 +546,13 @@ void SparcFaultBase::invoke(ThreadContext * tc, StaticInstPtr inst)
getPrivVector(tc, PC, NPC, trapType(), tl+1);
}
- tc->setPC(PC);
- tc->setNextPC(NPC);
- tc->setNextNPC(NPC + sizeof(MachInst));
+ PCState pc;
+ pc.pc(PC);
+ pc.npc(NPC);
+ pc.nnpc(NPC + sizeof(MachInst));
+ pc.upc(0);
+ pc.nupc(1);
+ tc->pcState(pc);
}
void PowerOnReset::invoke(ThreadContext * tc, StaticInstPtr inst)
@@ -593,9 +589,14 @@ void PowerOnReset::invoke(ThreadContext * tc, StaticInstPtr inst)
Addr PC, NPC;
getREDVector(trapType(), PC, NPC);
- tc->setPC(PC);
- tc->setNextPC(NPC);
- tc->setNextNPC(NPC + sizeof(MachInst));
+
+ PCState pc;
+ pc.pc(PC);
+ pc.npc(NPC);
+ pc.nnpc(NPC + sizeof(MachInst));
+ pc.upc(0);
+ pc.nupc(1);
+ tc->pcState(pc);
//These registers are specified as "undefined" after a POR, and they
//should have reasonable values after the miscregfile is reset
@@ -664,10 +665,7 @@ void SpillNNormal::invoke(ThreadContext *tc, StaticInstPtr inst)
assert(lp);
//Then adjust the PC and NPC
- Addr spillStart = lp->readSpillStart();
- tc->setPC(spillStart);
- tc->setNextPC(spillStart + sizeof(MachInst));
- tc->setNextNPC(spillStart + 2*sizeof(MachInst));
+ tc->pcState(lp->readSpillStart());
}
void FillNNormal::invoke(ThreadContext *tc, StaticInstPtr inst)
@@ -681,10 +679,7 @@ void FillNNormal::invoke(ThreadContext *tc, StaticInstPtr inst)
assert(lp);
//Then adjust the PC and NPC
- Addr fillStart = lp->readFillStart();
- tc->setPC(fillStart);
- tc->setNextPC(fillStart + sizeof(MachInst));
- tc->setNextNPC(fillStart + 2*sizeof(MachInst));
+ tc->pcState(lp->readFillStart());
}
void TrapInstruction::invoke(ThreadContext *tc, StaticInstPtr inst)
@@ -702,9 +697,9 @@ void TrapInstruction::invoke(ThreadContext *tc, StaticInstPtr inst)
//We need to explicitly advance the pc, since that's not done for us
//on a faulting instruction
- tc->setPC(tc->readNextPC());
- tc->setNextPC(tc->readNextNPC());
- tc->setNextNPC(tc->readNextNPC() + sizeof(MachInst));
+ PCState pc = tc->pcState();
+ pc.advance();
+ tc->pcState(pc);
}
#endif
diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa
index ce063bcdc..c6055b3a3 100644
--- a/src/arch/sparc/isa/base.isa
+++ b/src/arch/sparc/isa/base.isa
@@ -111,6 +111,8 @@ output header {{
void printRegArray(std::ostream &os,
const RegIndex indexArray[], int num) const;
+
+ void advancePC(SparcISA::PCState &pcState) const;
};
bool passesFpCondition(uint32_t fcc, uint32_t condition);
@@ -261,6 +263,12 @@ output decoder {{
}
void
+ SparcStaticInst::advancePC(SparcISA::PCState &pcState) const
+ {
+ pcState.advance();
+ }
+
+ void
SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
{
if(_numSrcRegs > reg)
diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa
index b9b38b569..80b29398c 100644
--- a/src/arch/sparc/isa/decoder.isa
+++ b/src/arch/sparc/isa/decoder.isa
@@ -46,14 +46,18 @@ decode OP default Unknown::unknown()
{
//Branch Always
0x8: bpa(19, annul_code={{
- NPC = xc->readPC() + disp;
- NNPC = NPC + 4;
+ SparcISA::PCState pc = PCS;
+ pc.npc(pc.pc() + disp);
+ pc.nnpc(pc.npc() + 4);
+ PCS = pc;
}});
//Branch Never
0x0: bpn(19, {{;}},
annul_code={{
- NNPC = NPC + 8;
- NPC = NPC + 4;
+ SparcISA::PCState pc = PCS;
+ pc.nnpc(pc.npc() + 8);
+ pc.npc(pc.npc() + 4);
+ PCS = pc;
}});
default: decode BPCC
{
@@ -66,14 +70,18 @@ decode OP default Unknown::unknown()
{
//Branch Always
0x8: ba(22, annul_code={{
- NPC = xc->readPC() + disp;
- NNPC = NPC + 4;
+ SparcISA::PCState pc = PCS;
+ pc.npc(pc.pc() + disp);
+ pc.nnpc(pc.npc() + 4);
+ PCS = pc;
}});
//Branch Never
0x0: bn(22, {{;}},
annul_code={{
- NNPC = NPC + 8;
- NPC = NPC + 4;
+ SparcISA::PCState pc = PCS;
+ pc.nnpc(pc.npc() + 8);
+ pc.npc(pc.npc() + 4);
+ PCS = pc;
}});
default: bicc(22, test={{passesCondition(Ccr<3:0>, COND2)}});
}
@@ -97,14 +105,18 @@ decode OP default Unknown::unknown()
format BranchN {
//Branch Always
0x8: fbpa(22, annul_code={{
- NPC = xc->readPC() + disp;
- NNPC = NPC + 4;
+ SparcISA::PCState pc = PCS;
+ pc.npc(pc.pc() + disp);
+ pc.nnpc(pc.npc() + 4);
+ PCS = pc;
}});
//Branch Never
0x0: fbpn(22, {{;}},
annul_code={{
- NNPC = NPC + 8;
- NPC = NPC + 4;
+ SparcISA::PCState pc = PCS;
+ pc.nnpc(pc.npc() + 8);
+ pc.npc(pc.npc() + 4);
+ PCS = pc;
}});
default: decode BPCC {
0x0: fbpfcc0(19, test=
@@ -123,14 +135,18 @@ decode OP default Unknown::unknown()
format BranchN {
//Branch Always
0x8: fba(22, annul_code={{
- NPC = xc->readPC() + disp;
- NNPC = NPC + 4;
+ SparcISA::PCState pc = PCS;
+ pc.npc(pc.pc() + disp);
+ pc.nnpc(pc.npc() + 4);
+ PCS = pc;
}});
//Branch Never
0x0: fbn(22, {{;}},
annul_code={{
- NNPC = NPC + 8;
- NPC = NPC + 4;
+ SparcISA::PCState pc = PCS;
+ pc.nnpc(pc.npc() + 8);
+ pc.npc(pc.npc() + 4);
+ PCS = pc;
}});
default: fbfcc(22, test=
{{passesFpCondition(Fsr<11:10>, COND2)}});
@@ -138,11 +154,13 @@ decode OP default Unknown::unknown()
}
}
0x1: BranchN::call(30, {{
+ SparcISA::PCState pc = PCS;
if (Pstate<3:>)
- R15 = (xc->readPC())<31:0>;
+ R15 = (pc.pc())<31:0>;
else
- R15 = xc->readPC();
- NNPC = R15 + disp;
+ R15 = pc.pc();
+ pc.nnpc(R15 + disp);
+ PCS = pc;
}});
0x2: decode OP3 {
format IntOp {
@@ -316,10 +334,12 @@ decode OP default Unknown::unknown()
0x03: NoPriv::rdasi({{Rd = Asi;}});
0x04: Priv::rdtick({{Rd = Tick;}}, {{Tick<63:>}});
0x05: NoPriv::rdpc({{
+ SparcISA::PCState pc = PCS;
if(Pstate<3:>)
- Rd = (xc->readPC())<31:0>;
+ Rd = (pc.pc())<31:0>;
else
- Rd = xc->readPC();}});
+ Rd = pc.pc();
+ }});
0x06: NoPriv::rdfprs({{
//Wait for all fpops to finish.
Rd = Fprs;
@@ -973,7 +993,8 @@ decode OP default Unknown::unknown()
0x51: m5break({{PseudoInst::debugbreak(xc->tcBase());
}}, IsNonSpeculative);
0x54: m5panic({{
- panic("M5 panic instruction called at pc=%#x.", xc->readPC());
+ SparcISA::PCState pc = PCS;
+ panic("M5 panic instruction called at pc=%#x.", pc.pc());
}}, No_OpClass, IsNonSpeculative);
}
#endif
@@ -985,11 +1006,13 @@ decode OP default Unknown::unknown()
fault = new MemAddressNotAligned;
else
{
+ SparcISA::PCState pc = PCS;
if (Pstate<3:>)
- Rd = (xc->readPC())<31:0>;
+ Rd = (pc.pc())<31:0>;
else
- Rd = xc->readPC();
- NNPC = target;
+ Rd = pc.pc();
+ pc.nnpc(target);
+ PCS = pc;
}
}});
0x39: Branch::return({{
@@ -1010,7 +1033,9 @@ decode OP default Unknown::unknown()
fault = new MemAddressNotAligned;
else
{
- NNPC = target;
+ SparcISA::PCState pc = PCS;
+ pc.nnpc(target);
+ PCS = pc;
Cwp = (Cwp - 1 + NWindows) % NWindows;
Cansave = Cansave + 1;
Canrestore = Canrestore - 1;
@@ -1082,8 +1107,10 @@ decode OP default Unknown::unknown()
Ccr = Tstate<39:32>;
Gl = Tstate<42:40>;
Hpstate = Htstate;
- NPC = Tnpc;
- NNPC = Tnpc + 4;
+ SparcISA::PCState pc = PCS;
+ pc.npc(Tnpc);
+ pc.nnpc(Tnpc + 4);
+ PCS = pc;
Tl = Tl - 1;
}}, checkTl=true);
0x1: Priv::retry({{
@@ -1093,8 +1120,10 @@ decode OP default Unknown::unknown()
Ccr = Tstate<39:32>;
Gl = Tstate<42:40>;
Hpstate = Htstate;
- NPC = Tpc;
- NNPC = Tnpc;
+ SparcISA::PCState pc = PCS;
+ pc.npc(Tpc);
+ pc.nnpc(Tnpc);
+ PCS = pc;
Tl = Tl - 1;
}}, checkTl=true);
}
diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa
index faaee8842..e62e0035a 100644
--- a/src/arch/sparc/isa/formats/branch.isa
+++ b/src/arch/sparc/isa/formats/branch.isa
@@ -193,7 +193,7 @@ def template JumpExecute {{
%(op_decl)s;
%(op_rd)s;
- NNPC = xc->readNextNPC();
+ PCS = PCS;
%(code)s;
if(fault == NoFault)
@@ -289,15 +289,24 @@ let {{
def doCondBranch(name, Name, base, cond, code, opt_flags):
return doBranch(name, Name, base, cond, code, code,
- 'NPC = NPC; NNPC = NNPC;',
- 'NNPC = NPC + 8; NPC = NPC + 4',
+ 'PCS = PCS;',
+ '''
+ SparcISA::PCState pc = PCS;
+ pc.nnpc(pc.npc() + 8);
+ pc.npc(pc.npc() + 4);
+ PCS = pc;
+ ''',
opt_flags)
def doUncondBranch(name, Name, base, code, annul_code, opt_flags):
return doBranch(name, Name, base, "true", code, annul_code,
";", ";", opt_flags)
- default_branch_code = "NNPC = xc->readPC() + disp;"
+ default_branch_code = '''
+ SparcISA::PCState pc = PCS;
+ pc.nnpc(pc.pc() + disp);
+ PCS = pc;
+ '''
}};
// Format for branch instructions with n bit displacements:
diff --git a/src/arch/sparc/isa/formats/micro.isa b/src/arch/sparc/isa/formats/micro.isa
index c1d0c4f36..b5a53a68b 100644
--- a/src/arch/sparc/isa/formats/micro.isa
+++ b/src/arch/sparc/isa/formats/micro.isa
@@ -81,10 +81,11 @@ output header {{
StaticInstPtr * microops;
- StaticInstPtr fetchMicroop(MicroPC microPC)
+ StaticInstPtr
+ fetchMicroop(MicroPC upc) const
{
- assert(microPC < numMicroops);
- return microops[microPC];
+ assert(upc < numMicroops);
+ return microops[upc];
}
%(MacroExecute)s
@@ -102,6 +103,15 @@ output header {{
{
flags[IsMicroop] = true;
}
+
+ void
+ advancePC(SparcISA::PCState &pcState) const
+ {
+ if (flags[IsLastMicroop])
+ pcState.uEnd();
+ else
+ pcState.uAdvance();
+ }
};
class SparcDelayedMicroInst : public SparcMicroInst
diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa
index a627a2e6f..8bf6450be 100644
--- a/src/arch/sparc/isa/operands.isa
+++ b/src/arch/sparc/isa/operands.isa
@@ -126,8 +126,7 @@ def operands {{
#'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12),
'Frs2_low': ('FloatReg', 'uw', 'dfprl(RS2)', 'IsFloating', 12),
'Frs2_high': ('FloatReg', 'uw', 'dfprh(RS2)', 'IsFloating', 12),
- 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31),
- 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32),
+ 'PCS': ('PCState', 'udw', None, (None, None, 'IsControl'), 30),
# Registers which are used explicitly in instructions
'R0': ('IntReg', 'udw', '0', None, 6),
'R1': ('IntReg', 'udw', '1', None, 7),
diff --git a/src/arch/sparc/nativetrace.cc b/src/arch/sparc/nativetrace.cc
index 8a1eb7a58..9bccaaf7d 100644
--- a/src/arch/sparc/nativetrace.cc
+++ b/src/arch/sparc/nativetrace.cc
@@ -67,16 +67,17 @@ Trace::SparcNativeTrace::check(NativeTraceRecord *record)
checkReg(*(regName++), regVal, realRegVal);
}
+ SparcISA::PCState pc = tc->pcState();
// PC
read(&realRegVal, sizeof(realRegVal));
realRegVal = SparcISA::gtoh(realRegVal);
- regVal = tc->readNextPC();
+ regVal = pc.npc();
checkReg("pc", regVal, realRegVal);
// NPC
read(&realRegVal, sizeof(realRegVal));
realRegVal = SparcISA::gtoh(realRegVal);
- regVal = tc->readNextNPC();
+ pc.nnpc();
checkReg("npc", regVal, realRegVal);
// CCR
diff --git a/src/arch/sparc/predecoder.hh b/src/arch/sparc/predecoder.hh
index c4ab4fe79..8a2587929 100644
--- a/src/arch/sparc/predecoder.hh
+++ b/src/arch/sparc/predecoder.hh
@@ -72,7 +72,7 @@ namespace SparcISA
//Use this to give data to the predecoder. This should be used
//when there is control flow.
- void moreBytes(Addr pc, Addr fetchPC, MachInst inst)
+ void moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
{
emi = inst;
//The I bit, bit 13, is used to figure out where the ASI
@@ -99,7 +99,7 @@ namespace SparcISA
}
//This returns a constant reference to the ExtMachInst to avoid a copy
- const ExtMachInst & getExtMachInst()
+ const ExtMachInst & getExtMachInst(PCState &pcState)
{
return emi;
}
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
index 0cd8889a9..a6e21977a 100644
--- a/src/arch/sparc/process.cc
+++ b/src/arch/sparc/process.cc
@@ -69,41 +69,39 @@ SparcLiveProcess::SparcLiveProcess(LiveProcessParams * params,
void SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc)
{
+ PCState pc = tc->pcState();
switch(trapNum)
{
case 0x01: //Software breakpoint
- warn("Software breakpoint encountered at pc %#x.\n", tc->readPC());
+ warn("Software breakpoint encountered at pc %#x.\n", pc.pc());
break;
case 0x02: //Division by zero
- warn("Software signaled a division by zero at pc %#x.\n",
- tc->readPC());
+ warn("Software signaled a division by zero at pc %#x.\n", pc.pc());
break;
case 0x03: //Flush window trap
flushWindows(tc);
break;
case 0x04: //Clean windows
warn("Ignoring process request for clean register "
- "windows at pc %#x.\n", tc->readPC());
+ "windows at pc %#x.\n", pc.pc());
break;
case 0x05: //Range check
- warn("Software signaled a range check at pc %#x.\n",
- tc->readPC());
+ warn("Software signaled a range check at pc %#x.\n", pc.pc());
break;
case 0x06: //Fix alignment
warn("Ignoring process request for os assisted unaligned accesses "
- "at pc %#x.\n", tc->readPC());
+ "at pc %#x.\n", pc.pc());
break;
case 0x07: //Integer overflow
- warn("Software signaled an integer overflow at pc %#x.\n",
- tc->readPC());
+ warn("Software signaled an integer overflow at pc %#x.\n", pc.pc());
break;
case 0x32: //Get integer condition codes
warn("Ignoring process request to get the integer condition codes "
- "at pc %#x.\n", tc->readPC());
+ "at pc %#x.\n", pc.pc());
break;
case 0x33: //Set integer condition codes
warn("Ignoring process request to set the integer condition codes "
- "at pc %#x.\n", tc->readPC());
+ "at pc %#x.\n", pc.pc());
break;
default:
panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum);
@@ -402,10 +400,7 @@ SparcLiveProcess::argsInit(int pageSize)
// don't have anything like that, it should be set to 0.
tc->setIntReg(1, 0);
- Addr prog_entry = objFile->entryPoint();
- tc->setPC(prog_entry);
- tc->setNextPC(prog_entry + sizeof(MachInst));
- tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
+ tc->pcState(objFile->entryPoint());
//Align the "stack_min" to a page boundary.
stack_min = roundDown(stack_min, pageSize);
diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc
index 4eea0c077..aea40ea22 100644
--- a/src/arch/sparc/remote_gdb.cc
+++ b/src/arch/sparc/remote_gdb.cc
@@ -179,12 +179,14 @@ RemoteGDB::getregs()
{
memset(gdbregs.regs, 0, gdbregs.size);
+ PCState pc = context->pcState();
+
if (context->readMiscReg(MISCREG_PSTATE) &
PSTATE::am) {
uint32_t *regs;
regs = (uint32_t*)gdbregs.regs;
- regs[Reg32Pc] = htobe((uint32_t)context->readPC());
- regs[Reg32Npc] = htobe((uint32_t)context->readNextPC());
+ regs[Reg32Pc] = htobe((uint32_t)pc.pc());
+ regs[Reg32Npc] = htobe((uint32_t)pc.npc());
for(int x = RegG0; x <= RegI0 + 7; x++)
regs[x] = htobe((uint32_t)context->readIntReg(x - RegG0));
@@ -193,8 +195,8 @@ RemoteGDB::getregs()
regs[Reg32Fsr] = htobe((uint32_t)context->readMiscReg(MISCREG_FSR));
regs[Reg32Csr] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 2));
} else {
- gdbregs.regs[RegPc] = htobe(context->readPC());
- gdbregs.regs[RegNpc] = htobe(context->readNextPC());
+ gdbregs.regs[RegPc] = htobe(pc.pc());
+ gdbregs.regs[RegNpc] = htobe(pc.npc());
for(int x = RegG0; x <= RegI0 + 7; x++)
gdbregs.regs[x] = htobe(context->readIntReg(x - RegG0));
@@ -224,8 +226,13 @@ RemoteGDB::getregs()
void
RemoteGDB::setregs()
{
- context->setPC(gdbregs.regs[RegPc]);
- context->setNextPC(gdbregs.regs[RegNpc]);
+ PCState pc;
+ pc.pc(gdbregs.regs[RegPc]);
+ pc.npc(gdbregs.regs[RegNpc]);
+ pc.nnpc(pc.npc() + sizeof(MachInst));
+ pc.upc(0);
+ pc.nupc(1);
+ context->pcState(pc);
for(int x = RegG0; x <= RegI0 + 7; x++)
context->setIntReg(x - RegG0, gdbregs.regs[x]);
//Only the integer registers, pc and npc are set in netbsd
@@ -241,6 +248,6 @@ RemoteGDB::clearSingleStep()
void
RemoteGDB::setSingleStep()
{
- nextBkpt = context->readNextPC();
+ nextBkpt = context->pcState().npc();
setTempBreakpoint(nextBkpt);
}
diff --git a/src/arch/sparc/types.hh b/src/arch/sparc/types.hh
index 70558ec6d..122fd808f 100644
--- a/src/arch/sparc/types.hh
+++ b/src/arch/sparc/types.hh
@@ -33,12 +33,15 @@
#include "base/bigint.hh"
#include "base/types.hh"
+#include "arch/generic/types.hh"
namespace SparcISA
{
typedef uint32_t MachInst;
typedef uint64_t ExtMachInst;
+ typedef GenericISA::DelaySlotUPCState<MachInst> PCState;
+
typedef Twin64_t LargestRead;
struct CoreSpecific {
diff --git a/src/arch/sparc/utility.cc b/src/arch/sparc/utility.cc
index be4dfac84..6de44d8a3 100644
--- a/src/arch/sparc/utility.cc
+++ b/src/arch/sparc/utility.cc
@@ -213,20 +213,16 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
// Copy misc. registers
copyMiscRegs(src, dest);
-
// Lastly copy PC/NPC
- dest->setPC(src->readPC());
- dest->setNextPC(src->readNextPC());
- dest->setNextNPC(src->readNextNPC());
+ dest->pcState(src->pcState());
}
void
skipFunction(ThreadContext *tc)
{
- Addr newpc = tc->readIntReg(ReturnAddressReg);
- tc->setPC(newpc);
- tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
- tc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst));
+ TheISA::PCState newPC = tc->pcState();
+ newPC.set(tc->readIntReg(ReturnAddressReg));
+ tc->pcState(newPC);
}
diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh
index f6a585e23..0d5a4bb93 100644
--- a/src/arch/sparc/utility.hh
+++ b/src/arch/sparc/utility.hh
@@ -36,11 +36,22 @@
#include "arch/sparc/tlb.hh"
#include "base/misc.hh"
#include "base/bitfield.hh"
+#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
#include "sim/fault.hh"
namespace SparcISA
{
+
+ inline PCState
+ buildRetPC(const PCState &curPC, const PCState &callPC)
+ {
+ PCState ret = callPC;
+ ret.uEnd();
+ ret.pc(curPC.npc());
+ return ret;
+ }
+
uint64_t
getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp);
@@ -78,6 +89,12 @@ namespace SparcISA
void skipFunction(ThreadContext *tc);
+ inline void
+ advancePC(PCState &pc, const StaticInstPtr inst)
+ {
+ inst->advancePC(pc);
+ }
+
} // namespace SparcISA
#endif
diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc
index 4f2d97f90..7fb677c69 100644
--- a/src/arch/x86/faults.cc
+++ b/src/arch/x86/faults.cc
@@ -58,7 +58,8 @@ namespace X86ISA
#if FULL_SYSTEM
void X86FaultBase::invoke(ThreadContext * tc, StaticInstPtr inst)
{
- Addr pc = tc->readPC();
+ PCState pcState = tc->pcState();
+ Addr pc = pcState.pc();
DPRINTF(Faults, "RIP %#x: vector %d: %s\n", pc, vector, describe());
using namespace X86ISAInst::RomLabels;
HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
@@ -86,8 +87,9 @@ namespace X86ISA
assert(!isSoft());
tc->setIntReg(INTREG_MICRO(15), errorCode);
}
- tc->setMicroPC(romMicroPC(entry));
- tc->setNextMicroPC(romMicroPC(entry) + 1);
+ pcState.upc(romMicroPC(entry));
+ pcState.nupc(romMicroPC(entry) + 1);
+ tc->pcState(pcState);
}
std::string
@@ -106,9 +108,8 @@ namespace X86ISA
{
X86FaultBase::invoke(tc);
// This is the same as a fault, but it happens -after- the instruction.
- tc->setPC(tc->readNextPC());
- tc->setNextPC(tc->readNextNPC());
- tc->setNextNPC(tc->readNextNPC() + sizeof(MachInst));
+ PCState pc = tc->pcState();
+ pc.uEnd();
}
void X86Abort::invoke(ThreadContext * tc, StaticInstPtr inst)
@@ -207,9 +208,8 @@ namespace X86ISA
tc->setMiscReg(MISCREG_CS_LIMIT, 0xffffffff);
tc->setMiscReg(MISCREG_CS_ATTR, codeAttr);
- tc->setPC(0x000000000000fff0ULL +
- tc->readMiscReg(MISCREG_CS_BASE));
- tc->setNextPC(tc->readPC() + sizeof(MachInst));
+ PCState pc(0x000000000000fff0ULL + tc->readMiscReg(MISCREG_CS_BASE));
+ tc->pcState(pc);
tc->setMiscReg(MISCREG_TSG_BASE, 0);
tc->setMiscReg(MISCREG_TSG_LIMIT, 0xffff);
@@ -243,8 +243,9 @@ namespace X86ISA
// Update the handy M5 Reg.
tc->setMiscReg(MISCREG_M5_REG, 0);
MicroPC entry = X86ISAInst::RomLabels::extern_label_initIntHalt;
- tc->setMicroPC(romMicroPC(entry));
- tc->setNextMicroPC(romMicroPC(entry) + 1);
+ pc.upc(romMicroPC(entry));
+ pc.nupc(romMicroPC(entry) + 1);
+ tc->pcState(pc);
}
void
@@ -263,8 +264,7 @@ namespace X86ISA
// This has the base value pre-added.
tc->setMiscReg(MISCREG_CS_LIMIT, 0xffff);
- tc->setPC(tc->readMiscReg(MISCREG_CS_BASE));
- tc->setNextPC(tc->readPC() + sizeof(MachInst));
+ tc->pcState(tc->readMiscReg(MISCREG_CS_BASE));
}
#else
diff --git a/src/arch/x86/insts/macroop.hh b/src/arch/x86/insts/macroop.hh
index 7ead7bdc2..fcf051a37 100644
--- a/src/arch/x86/insts/macroop.hh
+++ b/src/arch/x86/insts/macroop.hh
@@ -73,7 +73,8 @@ class MacroopBase : public X86StaticInst
StaticInstPtr * microops;
- StaticInstPtr fetchMicroop(MicroPC microPC)
+ StaticInstPtr
+ fetchMicroop(MicroPC microPC) const
{
assert(microPC < numMicroops);
return microops[microPC];
diff --git a/src/arch/x86/insts/microop.hh b/src/arch/x86/insts/microop.hh
index 9b0497efc..6fc215452 100644
--- a/src/arch/x86/insts/microop.hh
+++ b/src/arch/x86/insts/microop.hh
@@ -114,6 +114,15 @@ namespace X86ISA
}
bool checkCondition(uint64_t flags, int condition) const;
+
+ void
+ advancePC(PCState &pcState) const
+ {
+ if (flags[IsLastMicroop])
+ pcState.uEnd();
+ else
+ pcState.uAdvance();
+ }
};
}
diff --git a/src/arch/x86/insts/static_inst.hh b/src/arch/x86/insts/static_inst.hh
index 2df5df092..8813f216c 100644
--- a/src/arch/x86/insts/static_inst.hh
+++ b/src/arch/x86/insts/static_inst.hh
@@ -158,6 +158,12 @@ namespace X86ISA
panic("Tried to pick with unrecognized size %d.\n", size);
}
}
+
+ void
+ advancePC(PCState &pcState) const
+ {
+ pcState.advance();
+ }
};
}
diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa
index de167d1c1..def9b7f9d 100644
--- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa
+++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa
@@ -199,7 +199,7 @@
#endif
0x54: m5panic({{
panic("M5 panic instruction called at pc=%#x.\n",
- xc->readPC());
+ xc->pcState().pc());
}}, IsNonSpeculative);
0x55: m5reserved1({{
warn("M5 reserved opcode 1 ignored.\n");
diff --git a/src/arch/x86/isa/formats/unknown.isa b/src/arch/x86/isa/formats/unknown.isa
index 11751e861..1108fd4a4 100644
--- a/src/arch/x86/isa/formats/unknown.isa
+++ b/src/arch/x86/isa/formats/unknown.isa
@@ -47,13 +47,13 @@ output header {{
/**
* Class for Unknown/Illegal instructions
*/
- class Unknown : public StaticInst
+ class Unknown : public X86ISA::X86StaticInst
{
public:
// Constructor
Unknown(ExtMachInst _machInst) :
- StaticInst("unknown", _machInst, No_OpClass)
+ X86ISA::X86StaticInst("unknown", _machInst, No_OpClass)
{
}
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
index 9ccea82dd..86ebac174 100644
--- a/src/arch/x86/isa/microops/regop.isa
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -944,8 +944,12 @@ let {{
code = 'DoubleBits = psrc1 ^ op2;'
class Wrip(WrRegOp, CondRegOp):
- code = 'RIP = psrc1 + sop2 + CSBase'
- else_code="RIP = RIP;"
+ code = '''
+ X86ISA::PCState pc = PCS;
+ pc.npc(psrc1 + sop2 + CSBase);
+ PCS = pc;
+ '''
+ else_code = "PCS = PCS;"
class Wruflags(WrRegOp):
code = 'ccFlagBits = psrc1 ^ op2'
@@ -961,7 +965,10 @@ let {{
'''
class Rdip(RdRegOp):
- code = 'DestReg = RIP - CSBase'
+ code = '''
+ X86ISA::PCState pc = PCS;
+ DestReg = pc.npc() - CSBase;
+ '''
class Ruflags(RdRegOp):
code = 'DestReg = ccFlagBits'
diff --git a/src/arch/x86/isa/microops/seqop.isa b/src/arch/x86/isa/microops/seqop.isa
index 57c44d48c..a3e22b0aa 100644
--- a/src/arch/x86/isa/microops/seqop.isa
+++ b/src/arch/x86/isa/microops/seqop.isa
@@ -169,15 +169,23 @@ let {{
return super(Eret, self).getAllocator(microFlags)
iop = InstObjParams("br", "MicroBranchFlags", "SeqOpBase",
- {"code": "nuIP = target",
- "else_code": "nuIP = nuIP",
+ {"code": '''
+ X86ISA::PCState pc = PCS;
+ pc.nupc(target);
+ PCS = pc;
+ ''',
+ "else_code": "PCS = PCS",
"cond_test": "checkCondition(ccFlagBits, cc)"})
exec_output += SeqOpExecute.subst(iop)
header_output += SeqOpDeclare.subst(iop)
decoder_output += SeqOpConstructor.subst(iop)
iop = InstObjParams("br", "MicroBranch", "SeqOpBase",
- {"code": "nuIP = target",
- "else_code": "nuIP = nuIP",
+ {"code": '''
+ X86ISA::PCState pc = PCS;
+ pc.nupc(target);
+ PCS = pc;
+ ''',
+ "else_code": "PCS = PCS",
"cond_test": "true"})
exec_output += SeqOpExecute.subst(iop)
header_output += SeqOpDeclare.subst(iop)
diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa
index d4140e414..25b73a8f2 100644
--- a/src/arch/x86/isa/operands.isa
+++ b/src/arch/x86/isa/operands.isa
@@ -97,9 +97,8 @@ def operands {{
'FpSrcReg2': floatReg('src2', 21),
'FpDestReg': floatReg('dest', 22),
'FpData': floatReg('data', 23),
- 'RIP': ('NPC', 'uqw', None, (None, None, 'IsControl'), 50),
- 'uIP': ('UPC', 'uqw', None, (None, None, 'IsControl'), 51),
- 'nuIP': ('NUPC', 'uqw', None, (None, None, 'IsControl'), 52),
+ 'PCS': ('PCState', 'udw', None,
+ (None, None, 'IsControl'), 50),
# This holds the condition code portion of the flag register. The
# nccFlagBits version holds the rest.
'ccFlagBits': intReg('INTREG_PSEUDO(0)', 60),
diff --git a/src/arch/x86/nativetrace.cc b/src/arch/x86/nativetrace.cc
index c5c891be9..6f92cfacf 100644
--- a/src/arch/x86/nativetrace.cc
+++ b/src/arch/x86/nativetrace.cc
@@ -85,7 +85,7 @@ X86NativeTrace::ThreadState::update(ThreadContext *tc)
r13 = tc->readIntReg(X86ISA::INTREG_R13);
r14 = tc->readIntReg(X86ISA::INTREG_R14);
r15 = tc->readIntReg(X86ISA::INTREG_R15);
- rip = tc->readNextPC();
+ rip = tc->pcState().pc();
//This should be expanded if x87 registers are considered
for (int i = 0; i < 8; i++)
mmx[i] = tc->readFloatRegBits(X86ISA::FLOATREG_MMX(i));
diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh
index 5b38402e0..c06ec18bc 100644
--- a/src/arch/x86/predecoder.hh
+++ b/src/arch/x86/predecoder.hh
@@ -188,11 +188,11 @@ namespace X86ISA
//Use this to give data to the predecoder. This should be used
//when there is control flow.
- void moreBytes(Addr pc, Addr fetchPC, MachInst data)
+ void moreBytes(const PCState &pc, Addr fetchPC, MachInst data)
{
DPRINTF(Predecoder, "Getting more bytes.\n");
basePC = fetchPC;
- offset = (fetchPC >= pc) ? 0 : pc - fetchPC;
+ offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC;
fetchChunk = data;
outOfBytes = false;
process();
@@ -208,22 +208,26 @@ namespace X86ISA
return emiIsReady;
}
+ int
+ getInstSize()
+ {
+ int size = basePC + offset - origPC;
+ DPRINTF(Predecoder,
+ "Calculating the instruction size: "
+ "basePC: %#x offset: %#x origPC: %#x size: %d\n",
+ basePC, offset, origPC, size);
+ return size;
+ }
+
//This returns a constant reference to the ExtMachInst to avoid a copy
- const ExtMachInst & getExtMachInst()
+ const ExtMachInst &
+ getExtMachInst(X86ISA::PCState &nextPC)
{
assert(emiIsReady);
emiIsReady = false;
+ nextPC.npc(nextPC.pc() + getInstSize());
return emi;
}
-
- int getInstSize()
- {
- DPRINTF(Predecoder,
- "Calculating the instruction size: "
- "basePC: %#x offset: %#x origPC: %#x\n",
- basePC, offset, origPC);
- return basePC + offset - origPC;
- }
};
};
diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc
index 946a7cbe1..bb875686e 100644
--- a/src/arch/x86/process.cc
+++ b/src/arch/x86/process.cc
@@ -116,10 +116,12 @@ X86_64LiveProcess::X86_64LiveProcess(LiveProcessParams *params,
void
I386LiveProcess::syscall(int64_t callnum, ThreadContext *tc)
{
- Addr eip = tc->readPC();
+ TheISA::PCState pc = tc->pcState();
+ Addr eip = pc.pc();
if (eip >= vsyscallPage.base &&
eip < vsyscallPage.base + vsyscallPage.size) {
- tc->setNextPC(vsyscallPage.base + vsyscallPage.vsysexitOffset);
+ pc.npc(vsyscallPage.base + vsyscallPage.vsysexitOffset);
+ tc->pcState(pc);
}
X86LiveProcess::syscall(callnum, tc);
}
@@ -645,11 +647,9 @@ X86LiveProcess::argsInit(int pageSize,
//Set the stack pointer register
tc->setIntReg(StackPointerReg, stack_min);
- Addr prog_entry = objFile->entryPoint();
// There doesn't need to be any segment base added in since we're dealing
// with the flat segmentation model.
- tc->setPC(prog_entry);
- tc->setNextPC(prog_entry + sizeof(MachInst));
+ tc->pcState(objFile->entryPoint());
//Align the "stack_min" to a page boundary.
stack_min = roundDown(stack_min, pageSize);
diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc
index ae47b14fd..3fc16e729 100644
--- a/src/arch/x86/system.cc
+++ b/src/arch/x86/system.cc
@@ -320,8 +320,7 @@ X86System::initState()
cr0.pg = 1;
tc->setMiscReg(MISCREG_CR0, cr0);
- tc->setPC(tc->getSystemPtr()->kernelEntry);
- tc->setNextPC(tc->readPC());
+ tc->pcState(tc->getSystemPtr()->kernelEntry);
// We should now be in long mode. Yay!
diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc
index 71e0b3adb..dbba52af0 100644
--- a/src/arch/x86/tlb.cc
+++ b/src/arch/x86/tlb.cc
@@ -609,7 +609,7 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation,
#else
DPRINTF(TLB, "Handling a TLB miss for "
"address %#x at pc %#x.\n",
- vaddr, tc->readPC());
+ vaddr, tc->instAddr());
Process *p = tc->getProcessPtr();
TlbEntry newEntry;
diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh
index 2a0da7d65..5a208446a 100644
--- a/src/arch/x86/types.hh
+++ b/src/arch/x86/types.hh
@@ -42,6 +42,7 @@
#include <iostream>
+#include "arch/generic/types.hh"
#include "base/bitunion.hh"
#include "base/cprintf.hh"
#include "base/hashmap.hh"
@@ -221,6 +222,8 @@ namespace X86ISA
return true;
}
+ typedef GenericISA::UPCState<MachInst> PCState;
+
struct CoreSpecific {
int core_type;
};
diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc
index 624e8132f..88d5bfe58 100644
--- a/src/arch/x86/utility.cc
+++ b/src/arch/x86/utility.cc
@@ -72,8 +72,10 @@ void initCPU(ThreadContext *tc, int cpuId)
InitInterrupt init(0);
init.invoke(tc);
- tc->setMicroPC(0);
- tc->setNextMicroPC(1);
+ PCState pc = tc->pcState();
+ pc.upc(0);
+ pc.nupc(1);
+ tc->pcState(pc);
// These next two loops zero internal microcode and implicit registers.
// They aren't specified by the ISA but are used internally by M5's
@@ -231,8 +233,7 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
//copy float regs
copyMiscRegs(src, dest);
- dest->setPC(src->readPC());
- dest->setNextPC(src->readNextPC());
+ dest->pcState(src->pcState());
}
void
diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh
index 05ce53347..143fde00c 100644
--- a/src/arch/x86/utility.hh
+++ b/src/arch/x86/utility.hh
@@ -46,12 +46,22 @@
#include "base/misc.hh"
#include "base/types.hh"
#include "config/full_system.hh"
+#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
class ThreadContext;
namespace X86ISA
{
+
+ inline PCState
+ buildRetPC(const PCState &curPC, const PCState &callPC)
+ {
+ PCState retPC = callPC;
+ retPC.uEnd();
+ return retPC;
+ }
+
uint64_t
getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp);
@@ -86,6 +96,12 @@ namespace X86ISA
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
void skipFunction(ThreadContext *tc);
+
+ inline void
+ advancePC(PCState &pc, const StaticInstPtr inst)
+ {
+ inst->advancePC(pc);
+ }
};
#endif // __ARCH_X86_UTILITY_HH__
diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc
index 68747b3d1..4a06ff307 100644
--- a/src/base/remote_gdb.cc
+++ b/src/base/remote_gdb.cc
@@ -645,8 +645,8 @@ BaseRemoteGDB::trap(int type)
bufferSize = gdbregs.bytes() * 2 + 256;
buffer = (char*)malloc(bufferSize);
- DPRINTF(GDBMisc, "trap: PC=%#x NPC=%#x\n",
- context->readPC(), context->readNextPC());
+ TheISA::PCState pc = context->pcState();
+ DPRINTF(GDBMisc, "trap: PC=%s\n", pc);
clearSingleStep();
@@ -806,8 +806,7 @@ BaseRemoteGDB::trap(int type)
subcmd = hex2i(&p);
if (*p++ == ';') {
val = hex2i(&p);
- context->setPC(val);
- context->setNextPC(val + sizeof(MachInst));
+ context->pcState(val);
}
clearSingleStep();
goto out;
@@ -815,8 +814,7 @@ BaseRemoteGDB::trap(int type)
case GDBCont:
if (p - data < (ptrdiff_t)datalen) {
val = hex2i(&p);
- context->setPC(val);
- context->setNextPC(val + sizeof(MachInst));
+ context->pcState(val);
}
clearSingleStep();
goto out;
@@ -825,8 +823,7 @@ BaseRemoteGDB::trap(int type)
subcmd = hex2i(&p);
if (*p++ == ';') {
val = hex2i(&p);
- context->setPC(val);
- context->setNextPC(val + sizeof(MachInst));
+ context->pcState(val);
}
setSingleStep();
goto out;
@@ -834,8 +831,7 @@ BaseRemoteGDB::trap(int type)
case GDBStep:
if (p - data < (ptrdiff_t)datalen) {
val = hex2i(&p);
- context->setPC(val);
- context->setNextPC(val + sizeof(MachInst));
+ context->pcState(val);
}
setSingleStep();
goto out;
diff --git a/src/base/types.hh b/src/base/types.hh
index 30b2d9258..5ce778572 100644
--- a/src/base/types.hh
+++ b/src/base/types.hh
@@ -67,6 +67,28 @@ const Tick MaxTick = LL(0x7fffffffffffffff);
*/
typedef uint64_t Addr;
+typedef uint16_t MicroPC;
+
+static const MicroPC MicroPCRomBit = 1 << (sizeof(MicroPC) * 8 - 1);
+
+static inline MicroPC
+romMicroPC(MicroPC upc)
+{
+ return upc | MicroPCRomBit;
+}
+
+static inline MicroPC
+normalMicroPC(MicroPC upc)
+{
+ return upc & ~MicroPCRomBit;
+}
+
+static inline bool
+isRomMicroPC(MicroPC upc)
+{
+ return MicroPCRomBit & upc;
+}
+
const Addr MaxAddr = (Addr)-1;
/**
diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh
index e9b7daa4a..bc6f59407 100644
--- a/src/cpu/base_dyn_inst.hh
+++ b/src/cpu/base_dyn_inst.hh
@@ -38,6 +38,7 @@
#include <string>
#include "arch/faults.hh"
+#include "arch/utility.hh"
#include "base/fast_alloc.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
@@ -241,36 +242,15 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** Records changes to result? */
bool recordResult;
- /** PC of this instruction. */
- Addr PC;
-
- /** Micro PC of this instruction. */
- Addr microPC;
-
/** Did this instruction execute, or is it predicated false */
bool predicate;
protected:
- /** Next non-speculative PC. It is not filled in at fetch, but rather
- * once the target of the branch is truly known (either decode or
- * execute).
- */
- Addr nextPC;
-
- /** Next non-speculative NPC. Target PC for Mips or Sparc. */
- Addr nextNPC;
+ /** PC state for this instruction. */
+ TheISA::PCState pc;
- /** Next non-speculative micro PC. */
- Addr nextMicroPC;
-
- /** Predicted next PC. */
- Addr predPC;
-
- /** Predicted next NPC. */
- Addr predNPC;
-
- /** Predicted next microPC */
- Addr predMicroPC;
+ /** Predicted PC state after this instruction. */
+ TheISA::PCState predPC;
/** If this is a branch that was predicted taken */
bool predTaken;
@@ -386,27 +366,23 @@ class BaseDynInst : public FastAlloc, public RefCounted
}
/** BaseDynInst constructor given a binary instruction.
* @param staticInst A StaticInstPtr to the underlying instruction.
- * @param PC The PC of the instruction.
- * @param pred_PC The predicted next PC.
- * @param pred_NPC The predicted next NPC.
+ * @param pc The PC state for the instruction.
+ * @param predPC The predicted next PC state for the instruction.
* @param seq_num The sequence number of the instruction.
* @param cpu Pointer to the instruction's CPU.
*/
- BaseDynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC,
- Addr pred_PC, Addr pred_NPC, Addr pred_MicroPC,
- InstSeqNum seq_num, ImplCPU *cpu);
+ BaseDynInst(StaticInstPtr staticInst, TheISA::PCState pc,
+ TheISA::PCState predPC, InstSeqNum seq_num, ImplCPU *cpu);
/** BaseDynInst constructor given a binary instruction.
* @param inst The binary instruction.
- * @param PC The PC of the instruction.
- * @param pred_PC The predicted next PC.
- * @param pred_NPC The predicted next NPC.
+ * @param _pc The PC state for the instruction.
+ * @param _predPC The predicted next PC state for the instruction.
* @param seq_num The sequence number of the instruction.
* @param cpu Pointer to the instruction's CPU.
*/
- BaseDynInst(TheISA::ExtMachInst inst, Addr PC, Addr NPC, Addr microPC,
- Addr pred_PC, Addr pred_NPC, Addr pred_MicroPC,
- InstSeqNum seq_num, ImplCPU *cpu);
+ BaseDynInst(TheISA::ExtMachInst inst, TheISA::PCState pc,
+ TheISA::PCState predPC, InstSeqNum seq_num, ImplCPU *cpu);
/** BaseDynInst constructor given a StaticInst pointer.
* @param _staticInst The StaticInst for this BaseDynInst.
@@ -443,45 +419,22 @@ class BaseDynInst : public FastAlloc, public RefCounted
*/
bool doneTargCalc() { return false; }
- /** Returns the next PC. This could be the speculative next PC if it is
- * called prior to the actual branch target being calculated.
- */
- Addr readNextPC() { return nextPC; }
-
- /** Returns the next NPC. This could be the speculative next NPC if it is
- * called prior to the actual branch target being calculated.
- */
- Addr readNextNPC()
- {
-#if ISA_HAS_DELAY_SLOT
- return nextNPC;
-#else
- return nextPC + sizeof(TheISA::MachInst);
-#endif
- }
-
- Addr readNextMicroPC()
- {
- return nextMicroPC;
- }
-
/** Set the predicted target of this current instruction. */
- void setPredTarg(Addr predicted_PC, Addr predicted_NPC,
- Addr predicted_MicroPC)
+ void setPredTarg(const TheISA::PCState &_predPC)
{
- predPC = predicted_PC;
- predNPC = predicted_NPC;
- predMicroPC = predicted_MicroPC;
+ predPC = _predPC;
}
+ const TheISA::PCState &readPredTarg() { return predPC; }
+
/** Returns the predicted PC immediately after the branch. */
- Addr readPredPC() { return predPC; }
+ Addr predInstAddr() { return predPC.instAddr(); }
/** Returns the predicted PC two instructions after the branch */
- Addr readPredNPC() { return predNPC; }
+ Addr predNextInstAddr() { return predPC.nextInstAddr(); }
/** Returns the predicted micro PC after the branch */
- Addr readPredMicroPC() { return predMicroPC; }
+ Addr predMicroPC() { return predPC.microPC(); }
/** Returns whether the instruction was predicted taken or not. */
bool readPredTaken()
@@ -497,9 +450,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** Returns whether the instruction mispredicted. */
bool mispredicted()
{
- return readPredPC() != readNextPC() ||
- readPredNPC() != readNextNPC() ||
- readPredMicroPC() != readNextMicroPC();
+ TheISA::PCState tempPC = pc;
+ TheISA::advancePC(tempPC, staticInst);
+ return !(tempPC == predPC);
}
//
@@ -576,7 +529,8 @@ class BaseDynInst : public FastAlloc, public RefCounted
OpClass opClass() const { return staticInst->opClass(); }
/** Returns the branch target address. */
- Addr branchTarget() const { return staticInst->branchTarget(PC); }
+ TheISA::PCState branchTarget() const
+ { return staticInst->branchTarget(pc); }
/** Returns the number of source registers. */
int8_t numSrcRegs() const { return staticInst->numSrcRegs(); }
@@ -773,30 +727,20 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** Returns whether or not this instruction is squashed in the ROB. */
bool isSquashedInROB() const { return status[SquashedInROB]; }
- /** Read the PC of this instruction. */
- const Addr readPC() const { return PC; }
+ /** Read the PC state of this instruction. */
+ const TheISA::PCState pcState() const { return pc; }
- /**Read the micro PC of this instruction. */
- const Addr readMicroPC() const { return microPC; }
+ /** Set the PC state of this instruction. */
+ const void pcState(const TheISA::PCState &val) { pc = val; }
- /** Set the next PC of this instruction (its actual target). */
- void setNextPC(Addr val)
- {
- nextPC = val;
- }
+ /** Read the PC of this instruction. */
+ const Addr instAddr() const { return pc.instAddr(); }
- /** Set the next NPC of this instruction (the target in Mips or Sparc).*/
- void setNextNPC(Addr val)
- {
-#if ISA_HAS_DELAY_SLOT
- nextNPC = val;
-#endif
- }
+ /** Read the PC of the next instruction. */
+ const Addr nextInstAddr() const { return pc.nextInstAddr(); }
- void setNextMicroPC(Addr val)
- {
- nextMicroPC = val;
- }
+ /**Read the micro PC of this instruction. */
+ const Addr microPC() const { return pc.microPC(); }
bool readPredicate()
{
@@ -895,7 +839,7 @@ BaseDynInst<Impl>::readBytes(Addr addr, uint8_t *data,
unsigned size, unsigned flags)
{
reqMade = true;
- Request *req = new Request(asid, addr, size, flags, this->PC,
+ Request *req = new Request(asid, addr, size, flags, this->pc.instAddr(),
thread->contextId(), threadNumber);
Request *sreqLow = NULL;
@@ -956,7 +900,7 @@ BaseDynInst<Impl>::writeBytes(uint8_t *data, unsigned size,
}
reqMade = true;
- Request *req = new Request(asid, addr, size, flags, this->PC,
+ Request *req = new Request(asid, addr, size, flags, this->pc.instAddr(),
thread->contextId(), threadNumber);
Request *sreqLow = NULL;
diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh
index 4fb8490c1..923b204ce 100644
--- a/src/cpu/base_dyn_inst_impl.hh
+++ b/src/cpu/base_dyn_inst_impl.hh
@@ -62,32 +62,14 @@ my_hash_t thishash;
template <class Impl>
BaseDynInst<Impl>::BaseDynInst(StaticInstPtr _staticInst,
- Addr inst_PC, Addr inst_NPC,
- Addr inst_MicroPC,
- Addr pred_PC, Addr pred_NPC,
- Addr pred_MicroPC,
+ TheISA::PCState _pc, TheISA::PCState _predPC,
InstSeqNum seq_num, ImplCPU *cpu)
: staticInst(_staticInst), traceData(NULL), cpu(cpu)
{
seqNum = seq_num;
- bool nextIsMicro =
- staticInst->isMicroop() && !staticInst->isLastMicroop();
-
- PC = inst_PC;
- microPC = inst_MicroPC;
- if (nextIsMicro) {
- nextPC = inst_PC;
- nextNPC = inst_NPC;
- nextMicroPC = microPC + 1;
- } else {
- nextPC = inst_NPC;
- nextNPC = nextPC + sizeof(TheISA::MachInst);
- nextMicroPC = 0;
- }
- predPC = pred_PC;
- predNPC = pred_NPC;
- predMicroPC = pred_MicroPC;
+ pc = _pc;
+ predPC = _predPC;
predTaken = false;
initVars();
@@ -95,32 +77,14 @@ BaseDynInst<Impl>::BaseDynInst(StaticInstPtr _staticInst,
template <class Impl>
BaseDynInst<Impl>::BaseDynInst(TheISA::ExtMachInst inst,
- Addr inst_PC, Addr inst_NPC,
- Addr inst_MicroPC,
- Addr pred_PC, Addr pred_NPC,
- Addr pred_MicroPC,
+ TheISA::PCState _pc, TheISA::PCState _predPC,
InstSeqNum seq_num, ImplCPU *cpu)
- : staticInst(inst, inst_PC), traceData(NULL), cpu(cpu)
+ : staticInst(inst, _pc.instAddr()), traceData(NULL), cpu(cpu)
{
seqNum = seq_num;
- bool nextIsMicro =
- staticInst->isMicroop() && !staticInst->isLastMicroop();
-
- PC = inst_PC;
- microPC = inst_MicroPC;
- if (nextIsMicro) {
- nextPC = inst_PC;
- nextNPC = inst_NPC;
- nextMicroPC = microPC + 1;
- } else {
- nextPC = inst_NPC;
- nextNPC = nextPC + sizeof(TheISA::MachInst);
- nextMicroPC = 0;
- }
- predPC = pred_PC;
- predNPC = pred_NPC;
- predMicroPC = pred_MicroPC;
+ pc = _pc;
+ predPC = _predPC;
predTaken = false;
initVars();
@@ -301,8 +265,8 @@ template <class Impl>
void
BaseDynInst<Impl>::dump()
{
- cprintf("T%d : %#08d `", threadNumber, PC);
- std::cout << staticInst->disassemble(PC);
+ cprintf("T%d : %#08d `", threadNumber, pc.instAddr());
+ std::cout << staticInst->disassemble(pc.instAddr());
cprintf("'\n");
}
@@ -311,8 +275,8 @@ void
BaseDynInst<Impl>::dump(std::string &outstring)
{
std::ostringstream s;
- s << "T" << threadNumber << " : 0x" << PC << " "
- << staticInst->disassemble(PC);
+ s << "T" << threadNumber << " : 0x" << pc.instAddr() << " "
+ << staticInst->disassemble(pc.instAddr());
outstring = s.str();
}
diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh
index a2f44106d..df5d8209b 100644
--- a/src/cpu/checker/cpu.hh
+++ b/src/cpu/checker/cpu.hh
@@ -241,13 +241,9 @@ class CheckerCPU : public BaseCPU
result.integer = val;
}
- uint64_t readPC() { return thread->readPC(); }
+ uint64_t instAddr() { return thread->instAddr(); }
- uint64_t readNextPC() { return thread->readNextPC(); }
-
- void setNextPC(uint64_t val) {
- thread->setNextPC(val);
- }
+ uint64_t nextInstAddr() { return thread->nextInstAddr(); }
MiscReg readMiscRegNoEffect(int misc_reg)
{
diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc
index 4bab778ba..f8b25ef73 100644
--- a/src/cpu/exetrace.cc
+++ b/src/cpu/exetrace.cc
@@ -72,10 +72,7 @@ Trace::ExeTracerRecord::traceInst(StaticInstPtr inst, bool ran)
std::string sym_str;
Addr sym_addr;
- Addr cur_pc = PC;
-#if THE_ISA == ARM_ISA
- cur_pc &= ~PcModeMask;
-#endif
+ Addr cur_pc = pc.instAddr();
if (debugSymbolTable
&& IsOn(ExecSymbol)
#if FULL_SYSTEM
@@ -85,13 +82,12 @@ Trace::ExeTracerRecord::traceInst(StaticInstPtr inst, bool ran)
if (cur_pc != sym_addr)
sym_str += csprintf("+%d",cur_pc - sym_addr);
outs << "@" << sym_str;
- }
- else {
+ } else {
outs << "0x" << hex << cur_pc;
}
if (inst->isMicroop()) {
- outs << "." << setw(2) << dec << upc;
+ outs << "." << setw(2) << dec << pc.microPC();
} else {
outs << " ";
}
diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh
index 1982595eb..65950728b 100644
--- a/src/cpu/exetrace.hh
+++ b/src/cpu/exetrace.hh
@@ -47,10 +47,10 @@ class ExeTracerRecord : public InstRecord
{
public:
ExeTracerRecord(Tick _when, ThreadContext *_thread,
- const StaticInstPtr _staticInst, Addr _pc, bool spec,
- const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0)
+ const StaticInstPtr _staticInst, TheISA::PCState _pc,
+ bool spec, const StaticInstPtr _macroStaticInst = NULL)
: InstRecord(_when, _thread, _staticInst, _pc, spec,
- _macroStaticInst, _upc)
+ _macroStaticInst)
{
}
@@ -69,8 +69,8 @@ class ExeTracer : public InstTracer
InstRecord *
getInstRecord(Tick when, ThreadContext *tc,
- const StaticInstPtr staticInst, Addr pc,
- const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0)
+ const StaticInstPtr staticInst, TheISA::PCState pc,
+ const StaticInstPtr macroStaticInst = NULL)
{
if (!IsOn(ExecEnable))
return NULL;
@@ -82,7 +82,7 @@ class ExeTracer : public InstTracer
return NULL;
return new ExeTracerRecord(when, tc,
- staticInst, pc, tc->misspeculating(), macroStaticInst, upc);
+ staticInst, pc, tc->misspeculating(), macroStaticInst);
}
};
diff --git a/src/cpu/inorder/comm.hh b/src/cpu/inorder/comm.hh
index f1b3cacac..386046d1c 100644
--- a/src/cpu/inorder/comm.hh
+++ b/src/cpu/inorder/comm.hh
@@ -75,8 +75,8 @@ struct TimeStruct {
// struct as it is used pretty frequently.
bool branchMispredict;
bool branchTaken;
- uint64_t mispredPC;
- uint64_t nextPC;
+ Addr mispredPC;
+ TheISA::PCState nextPC;
unsigned branchCount;
diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc
index 5d42ba559..6cd938dc6 100644
--- a/src/cpu/inorder/cpu.cc
+++ b/src/cpu/inorder/cpu.cc
@@ -988,47 +988,6 @@ InOrderCPU::getPipeStage(int stage_num)
}
uint64_t
-InOrderCPU::readPC(ThreadID tid)
-{
- return PC[tid];
-}
-
-
-void
-InOrderCPU::setPC(Addr new_PC, ThreadID tid)
-{
- PC[tid] = new_PC;
-}
-
-
-uint64_t
-InOrderCPU::readNextPC(ThreadID tid)
-{
- return nextPC[tid];
-}
-
-
-void
-InOrderCPU::setNextPC(uint64_t new_NPC, ThreadID tid)
-{
- nextPC[tid] = new_NPC;
-}
-
-
-uint64_t
-InOrderCPU::readNextNPC(ThreadID tid)
-{
- return nextNPC[tid];
-}
-
-
-void
-InOrderCPU::setNextNPC(uint64_t new_NNPC, ThreadID tid)
-{
- nextNPC[tid] = new_NNPC;
-}
-
-uint64_t
InOrderCPU::readIntReg(int reg_idx, ThreadID tid)
{
return intRegs[tid][reg_idx];
@@ -1156,15 +1115,12 @@ InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
// Set the CPU's PCs - This contributes to the precise state of the CPU
// which can be used when restoring a thread to the CPU after after any
// type of context switching activity (fork, exception, etc.)
- setPC(inst->readPC(), tid);
- setNextPC(inst->readNextPC(), tid);
- setNextNPC(inst->readNextNPC(), tid);
+ pcState(inst->pcState(), tid);
if (inst->isControl()) {
thread[tid]->lastGradIsBranch = true;
- thread[tid]->lastBranchPC = inst->readPC();
- thread[tid]->lastBranchNextPC = inst->readNextPC();
- thread[tid]->lastBranchNextNPC = inst->readNextNPC();
+ thread[tid]->lastBranchPC = inst->pcState();
+ TheISA::advancePC(thread[tid]->lastBranchPC, inst->staticInst);
} else {
thread[tid]->lastGradIsBranch = false;
}
@@ -1236,15 +1192,15 @@ InOrderCPU::addToRemoveList(DynInstPtr &inst)
{
removeInstsThisCycle = true;
if (!inst->isRemoveList()) {
- DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %#x "
+ DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s "
"[sn:%lli] to remove list\n",
- inst->threadNumber, inst->readPC(), inst->seqNum);
+ inst->threadNumber, inst->pcState(), inst->seqNum);
inst->setRemoveList();
removeList.push(inst->getInstListIt());
} else {
- DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %#x "
+ DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %s "
"[sn:%lli], already remove list\n",
- inst->threadNumber, inst->readPC(), inst->seqNum);
+ inst->threadNumber, inst->pcState(), inst->seqNum);
}
}
@@ -1252,23 +1208,23 @@ InOrderCPU::addToRemoveList(DynInstPtr &inst)
void
InOrderCPU::removeInst(DynInstPtr &inst)
{
- DPRINTF(InOrderCPU, "Removing graduated instruction [tid:%i] PC %#x "
+ DPRINTF(InOrderCPU, "Removing graduated instruction [tid:%i] PC %s "
"[sn:%lli]\n",
- inst->threadNumber, inst->readPC(), inst->seqNum);
+ inst->threadNumber, inst->pcState(), inst->seqNum);
removeInstsThisCycle = true;
// Remove the instruction.
if (!inst->isRemoveList()) {
- DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %#x "
+ DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s "
"[sn:%lli] to remove list\n",
- inst->threadNumber, inst->readPC(), inst->seqNum);
+ inst->threadNumber, inst->pcState(), inst->seqNum);
inst->setRemoveList();
removeList.push(inst->getInstListIt());
} else {
- DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %#x "
+ DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %s "
"[sn:%lli], already on remove list\n",
- inst->threadNumber, inst->readPC(), inst->seqNum);
+ inst->threadNumber, inst->pcState(), inst->seqNum);
}
}
@@ -1307,24 +1263,24 @@ InOrderCPU::squashInstIt(const ListIt &instIt, ThreadID tid)
{
if ((*instIt)->threadNumber == tid) {
DPRINTF(InOrderCPU, "Squashing instruction, "
- "[tid:%i] [sn:%lli] PC %#x\n",
+ "[tid:%i] [sn:%lli] PC %s\n",
(*instIt)->threadNumber,
(*instIt)->seqNum,
- (*instIt)->readPC());
+ (*instIt)->pcState());
(*instIt)->setSquashed();
if (!(*instIt)->isRemoveList()) {
- DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %#x "
+ DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s "
"[sn:%lli] to remove list\n",
- (*instIt)->threadNumber, (*instIt)->readPC(),
+ (*instIt)->threadNumber, (*instIt)->pcState(),
(*instIt)->seqNum);
(*instIt)->setRemoveList();
removeList.push(instIt);
} else {
DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i]"
- " PC %#x [sn:%lli], already on remove list\n",
- (*instIt)->threadNumber, (*instIt)->readPC(),
+ " PC %s [sn:%lli], already on remove list\n",
+ (*instIt)->threadNumber, (*instIt)->pcState(),
(*instIt)->seqNum);
}
@@ -1338,10 +1294,10 @@ InOrderCPU::cleanUpRemovedInsts()
{
while (!removeList.empty()) {
DPRINTF(InOrderCPU, "Removing instruction, "
- "[tid:%i] [sn:%lli] PC %#x\n",
+ "[tid:%i] [sn:%lli] PC %s\n",
(*removeList.front())->threadNumber,
(*removeList.front())->seqNum,
- (*removeList.front())->readPC());
+ (*removeList.front())->pcState());
DynInstPtr inst = *removeList.front();
ThreadID tid = inst->threadNumber;
@@ -1417,9 +1373,10 @@ InOrderCPU::dumpInsts()
cprintf("Dumping Instruction List\n");
while (inst_list_it != instList[0].end()) {
- cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
+ cprintf("Instruction:%i\nPC:%s\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
"Squashed:%i\n\n",
- num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
+ num, (*inst_list_it)->pcState(),
+ (*inst_list_it)->threadNumber,
(*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
(*inst_list_it)->isSquashed());
inst_list_it++;
diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh
index abe24d6ed..df6617d56 100644
--- a/src/cpu/inorder/cpu.hh
+++ b/src/cpu/inorder/cpu.hh
@@ -273,9 +273,7 @@ class InOrderCPU : public BaseCPU
PipelineStage *pipelineStage[ThePipeline::NumStages];
/** Program Counters */
- TheISA::IntReg PC[ThePipeline::MaxThreads];
- TheISA::IntReg nextPC[ThePipeline::MaxThreads];
- TheISA::IntReg nextNPC[ThePipeline::MaxThreads];
+ TheISA::PCState pc[ThePipeline::MaxThreads];
/** The Register File for the CPU */
union {
@@ -471,22 +469,22 @@ class InOrderCPU : public BaseCPU
ThreadID tid);
/** Reads the commit PC of a specific thread. */
- uint64_t readPC(ThreadID tid);
+ TheISA::PCState
+ pcState(ThreadID tid)
+ {
+ return pc[tid];
+ }
/** Sets the commit PC of a specific thread. */
- void setPC(Addr new_PC, ThreadID tid);
-
- /** Reads the next PC of a specific thread. */
- uint64_t readNextPC(ThreadID tid);
-
- /** Sets the next PC of a specific thread. */
- void setNextPC(uint64_t val, ThreadID tid);
-
- /** Reads the next NPC of a specific thread. */
- uint64_t readNextNPC(ThreadID tid);
+ void
+ pcState(const TheISA::PCState &newPC, ThreadID tid)
+ {
+ pc[tid] = newPC;
+ }
- /** Sets the next NPC of a specific thread. */
- void setNextNPC(uint64_t val, ThreadID tid);
+ Addr instAddr(ThreadID tid) { return pc[tid].instAddr(); }
+ Addr nextInstAddr(ThreadID tid) { return pc[tid].nextInstAddr(); }
+ MicroPC microPC(ThreadID tid) { return pc[tid].microPC(); }
/** Function to add instruction onto the head of the list of the
* instructions. Used when new instructions are fetched.
diff --git a/src/cpu/inorder/first_stage.cc b/src/cpu/inorder/first_stage.cc
index 658ce37d3..ae458c604 100644
--- a/src/cpu/inorder/first_stage.cc
+++ b/src/cpu/inorder/first_stage.cc
@@ -84,8 +84,8 @@ FirstStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
break;
}
DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] "
- "PC %08p.\n", tid, insts[tid].front()->seqNum,
- insts[tid].front()->PC);
+ "PC %s.\n", tid, insts[tid].front()->seqNum,
+ insts[tid].front()->pc);
insts[tid].pop();
}
diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc
index 2465744e5..f672082f3 100644
--- a/src/cpu/inorder/inorder_dyn_inst.cc
+++ b/src/cpu/inorder/inorder_dyn_inst.cc
@@ -47,17 +47,16 @@ using namespace std;
using namespace TheISA;
using namespace ThePipeline;
-InOrderDynInst::InOrderDynInst(TheISA::ExtMachInst machInst, Addr inst_PC,
- Addr pred_PC, InstSeqNum seq_num,
- InOrderCPU *cpu)
- : staticInst(machInst, inst_PC), traceData(NULL), cpu(cpu)
+InOrderDynInst::InOrderDynInst(TheISA::ExtMachInst machInst,
+ const TheISA::PCState &instPC,
+ const TheISA::PCState &_predPC,
+ InstSeqNum seq_num, InOrderCPU *cpu)
+ : staticInst(machInst, instPC.instAddr()), traceData(NULL), cpu(cpu)
{
seqNum = seq_num;
- PC = inst_PC;
- nextPC = PC + sizeof(MachInst);
- nextNPC = nextPC + sizeof(MachInst);
- predPC = pred_PC;
+ pc = instPC;
+ predPC = _predPC;
initVars();
}
@@ -94,7 +93,7 @@ int InOrderDynInst::instcount = 0;
void
InOrderDynInst::setMachInst(ExtMachInst machInst)
{
- staticInst = StaticInst::decode(machInst, PC);
+ staticInst = StaticInst::decode(machInst, pc.instAddr());
for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
_destRegIdx[i] = this->staticInst->destRegIdx(i);
@@ -747,8 +746,8 @@ InOrderDynInst::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
void
InOrderDynInst::dump()
{
- cprintf("T%d : %#08d `", threadNumber, PC);
- cout << staticInst->disassemble(PC);
+ cprintf("T%d : %#08d `", threadNumber, pc.instAddr());
+ cout << staticInst->disassemble(pc.instAddr());
cprintf("'\n");
}
@@ -756,8 +755,8 @@ void
InOrderDynInst::dump(std::string &outstring)
{
std::ostringstream s;
- s << "T" << threadNumber << " : 0x" << PC << " "
- << staticInst->disassemble(PC);
+ s << "T" << threadNumber << " : " << pc << " "
+ << staticInst->disassemble(pc.instAddr());
outstring = s.str();
}
diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh
index 0d42f4696..105e37657 100644
--- a/src/cpu/inorder/inorder_dyn_inst.hh
+++ b/src/cpu/inorder/inorder_dyn_inst.hh
@@ -41,6 +41,7 @@
#include "arch/isa_traits.hh"
#include "arch/mt.hh"
#include "arch/types.hh"
+#include "arch/utility.hh"
#include "base/fast_alloc.hh"
#include "base/trace.hh"
#include "base/types.hh"
@@ -108,12 +109,13 @@ class InOrderDynInst : public FastAlloc, public RefCounted
/** BaseDynInst constructor given a binary instruction.
* @param inst The binary instruction.
* @param PC The PC of the instruction.
- * @param pred_PC The predicted next PC.
+ * @param predPC The predicted next PC.
* @param seq_num The sequence number of the instruction.
* @param cpu Pointer to the instruction's CPU.
*/
- InOrderDynInst(ExtMachInst inst, Addr PC, Addr pred_PC, InstSeqNum seq_num,
- InOrderCPU *cpu);
+ InOrderDynInst(ExtMachInst inst, const TheISA::PCState &PC,
+ const TheISA::PCState &predPC, InstSeqNum seq_num,
+ InOrderCPU *cpu);
/** BaseDynInst constructor given a binary instruction.
* @param seq_num The sequence number of the instruction.
@@ -269,28 +271,10 @@ class InOrderDynInst : public FastAlloc, public RefCounted
InstResult instResult[MaxInstDestRegs];
/** PC of this instruction. */
- Addr PC;
-
- /** Next non-speculative PC. It is not filled in at fetch, but rather
- * once the target of the branch is truly known (either decode or
- * execute).
- */
- Addr nextPC;
-
- /** Next next non-speculative PC. It is not filled in at fetch, but rather
- * once the target of the branch is truly known (either decode or
- * execute).
- */
- Addr nextNPC;
+ TheISA::PCState pc;
/** Predicted next PC. */
- Addr predPC;
-
- /** Predicted next NPC. */
- Addr predNPC;
-
- /** Predicted next microPC */
- Addr predMicroPC;
+ TheISA::PCState predPC;
/** Address to fetch from */
Addr fetchAddr;
@@ -540,33 +524,14 @@ class InOrderDynInst : public FastAlloc, public RefCounted
//
////////////////////////////////////////////////////////////
/** Read the PC of this instruction. */
- const Addr readPC() const { return PC; }
+ const TheISA::PCState &pcState() const { return pc; }
/** Sets the PC of this instruction. */
- void setPC(Addr pc) { PC = pc; }
-
- /** Returns the next PC. This could be the speculative next PC if it is
- * called prior to the actual branch target being calculated.
- */
- Addr readNextPC() { return nextPC; }
+ void pcState(const TheISA::PCState &_pc) { pc = _pc; }
- /** Set the next PC of this instruction (its actual target). */
- void setNextPC(uint64_t val) { nextPC = val; }
-
- /** Returns the next NPC. This could be the speculative next NPC if it is
- * called prior to the actual branch target being calculated.
- */
- Addr readNextNPC()
- {
-#if ISA_HAS_DELAY_SLOT
- return nextNPC;
-#else
- return nextPC + sizeof(TheISA::MachInst);
-#endif
- }
-
- /** Set the next PC of this instruction (its actual target). */
- void setNextNPC(uint64_t val) { nextNPC = val; }
+ const Addr instAddr() { return pc.instAddr(); }
+ const Addr nextInstAddr() { return pc.nextInstAddr(); }
+ const MicroPC microPC() { return pc.microPC(); }
////////////////////////////////////////////////////////////
//
@@ -574,38 +539,36 @@ class InOrderDynInst : public FastAlloc, public RefCounted
//
////////////////////////////////////////////////////////////
/** Set the predicted target of this current instruction. */
- void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; }
+ void setPredTarg(const TheISA::PCState &predictedPC)
+ { predPC = predictedPC; }
/** Returns the predicted target of the branch. */
- Addr readPredTarg() { return predPC; }
+ TheISA::PCState readPredTarg() { return predPC; }
/** Returns the predicted PC immediately after the branch. */
- Addr readPredPC() { return predPC; }
+ Addr predInstAddr() { return predPC.instAddr(); }
/** Returns the predicted PC two instructions after the branch */
- Addr readPredNPC() { return predNPC; }
+ Addr predNextInstAddr() { return predPC.nextInstAddr(); }
/** Returns the predicted micro PC after the branch */
- Addr readPredMicroPC() { return predMicroPC; }
+ Addr readPredMicroPC() { return predPC.microPC(); }
/** Returns whether the instruction was predicted taken or not. */
bool predTaken() { return predictTaken; }
/** Returns whether the instruction mispredicted. */
- bool mispredicted()
+ bool
+ mispredicted()
{
-#if ISA_HAS_DELAY_SLOT
- return predPC != nextNPC;
-#else
- return predPC != nextPC;
-#endif
+ TheISA::PCState nextPC = pc;
+ TheISA::advancePC(nextPC, staticInst);
+ return !(nextPC == predPC);
}
- /** Returns whether the instruction mispredicted. */
- bool mistargeted() { return predPC != nextNPC; }
-
/** Returns the branch target address. */
- Addr branchTarget() const { return staticInst->branchTarget(PC); }
+ TheISA::PCState branchTarget() const
+ { return staticInst->branchTarget(pc); }
/** Checks whether or not this instruction has had its branch target
* calculated yet. For now it is not utilized and is hacked to be
diff --git a/src/cpu/inorder/inorder_trace.cc b/src/cpu/inorder/inorder_trace.cc
index 90c94a4f5..70a947671 100644
--- a/src/cpu/inorder/inorder_trace.cc
+++ b/src/cpu/inorder/inorder_trace.cc
@@ -70,15 +70,15 @@ InOrderTrace::getInstRecord(unsigned num_stages, bool stage_tracing,
if (!Trace::enabled)
return NULL;
- return new InOrderTraceRecord(num_stages, stage_tracing, tc);
+ return new InOrderTraceRecord(num_stages, stage_tracing, tc, 0);
}
InOrderTraceRecord *
InOrderTrace::getInstRecord(Tick when, ThreadContext *tc,
- const StaticInstPtr staticInst, Addr pc,
- const StaticInstPtr macroStaticInst, MicroPC upc)
+ const StaticInstPtr staticInst, TheISA::PCState _pc,
+ const StaticInstPtr macroStaticInst)
{
- return new InOrderTraceRecord(ThePipeline::NumStages, true, tc);
+ return new InOrderTraceRecord(ThePipeline::NumStages, true, tc, _pc);
}
/* namespace Trace */ }
diff --git a/src/cpu/inorder/inorder_trace.hh b/src/cpu/inorder/inorder_trace.hh
index ccc868f15..fd1427500 100644
--- a/src/cpu/inorder/inorder_trace.hh
+++ b/src/cpu/inorder/inorder_trace.hh
@@ -47,8 +47,8 @@ class InOrderTraceRecord : public ExeTracerRecord
{
public:
InOrderTraceRecord(unsigned num_stages, bool _stage_tracing,
- ThreadContext *_thread, bool spec = false)
- : ExeTracerRecord(0, _thread, NULL, 0, spec)
+ ThreadContext *_thread, TheISA::PCState _pc, bool spec = false)
+ : ExeTracerRecord(0, _thread, NULL, _pc, spec)
{
stageTrace = _stage_tracing;
stageCycle.resize(num_stages);
@@ -75,7 +75,8 @@ class InOrderTraceRecord : public ExeTracerRecord
{
staticInst = _staticInst;
}
- void setPC(Addr _pc) { PC = _pc; }
+
+ void setPC(TheISA::PCState _pc) { pc = _pc; }
};
class InOrderTrace : public InstTracer
@@ -87,9 +88,9 @@ class InOrderTrace : public InstTracer
InOrderTraceRecord *
getInstRecord(unsigned num_stages, bool stage_tracing, ThreadContext *tc);
- virtual InOrderTraceRecord *getInstRecord(Tick when, ThreadContext *tc,
- const StaticInstPtr staticInst, Addr pc,
- const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0);
+ InOrderTraceRecord *getInstRecord(Tick when, ThreadContext *tc,
+ const StaticInstPtr staticInst, TheISA::PCState pc,
+ const StaticInstPtr macroStaticInst = NULL);
};
/* namespace Trace */ }
diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc
index f0b48d6f6..dc36965b0 100644
--- a/src/cpu/inorder/pipeline_stage.cc
+++ b/src/cpu/inorder/pipeline_stage.cc
@@ -350,27 +350,21 @@ PipelineStage::squashDueToBranch(DynInstPtr &inst, ThreadID tid)
toPrevStages->stageInfo[stageNum][tid].squash = true;
toPrevStages->stageInfo[stageNum][tid].nextPC = inst->readPredTarg();
+ toPrevStages->stageInfo[stageNum][tid].branchTaken =
+ inst->pcState().branching();
#if ISA_HAS_DELAY_SLOT
- toPrevStages->stageInfo[stageNum][tid].branchTaken =
- inst->readNextNPC() !=
- (inst->readNextPC() + sizeof(TheISA::MachInst));
-
- toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum =
+ toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum =
inst->bdelaySeqNum;
InstSeqNum squash_seq_num = inst->bdelaySeqNum;
#else
- toPrevStages->stageInfo[stageNum][tid].branchTaken =
- inst->readNextPC() !=
- (inst->readPC() + sizeof(TheISA::MachInst));
-
toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = inst->seqNum;
InstSeqNum squash_seq_num = inst->seqNum;
#endif
DPRINTF(InOrderStage, "Target being re-set to %08p\n",
- inst->readPredTarg());
+ inst->predInstAddr());
DPRINTF(InOrderStage, "[tid:%i]: Squashing after [sn:%i], "
"due to [sn:%i] branch.\n", tid, squash_seq_num,
inst->seqNum);
@@ -398,10 +392,10 @@ PipelineStage::squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid)
prevStage->insts[i]->seqNum > squash_seq_num) {
// Change Comment to Annulling previous instruction
DPRINTF(InOrderStage, "[tid:%i]: Squashing instruction, "
- "[sn:%i] PC %08p.\n",
+ "[sn:%i] PC %s.\n",
tid,
prevStage->insts[i]->seqNum,
- prevStage->insts[i]->readPC());
+ prevStage->insts[i]->pcState());
prevStage->insts[i]->setSquashed();
prevStage->insts[i] = cpu->dummyBufferInst;
@@ -429,8 +423,8 @@ PipelineStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
break;
}
DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] "
- " PC %08p.\n", tid, skidBuffer[tid].front()->seqNum,
- skidBuffer[tid].front()->PC);
+ " PC %s.\n", tid, skidBuffer[tid].front()->seqNum,
+ skidBuffer[tid].front()->pc);
skidBuffer[tid].pop();
}
@@ -488,8 +482,8 @@ PipelineStage::skidInsert(ThreadID tid)
assert(tid == inst->threadNumber);
- DPRINTF(InOrderStage,"[tid:%i]: Inserting [sn:%lli] PC:%#x into stage "
- "skidBuffer %i\n", tid, inst->seqNum, inst->readPC(),
+ DPRINTF(InOrderStage,"[tid:%i]: Inserting [sn:%lli] PC:%s into stage "
+ "skidBuffer %i\n", tid, inst->seqNum, inst->pcState(),
inst->threadNumber);
skidBuffer[tid].push(inst);
@@ -571,9 +565,9 @@ PipelineStage::activateThread(ThreadID tid)
} else {
DynInstPtr inst = switchedOutBuffer[tid];
- DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%#x into"
+ DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%s into"
" stage skidBuffer %i\n", tid, inst->seqNum,
- inst->readPC(), inst->threadNumber);
+ inst->pcState(), inst->threadNumber);
// Make instruction available for pipeline processing
skidBuffer[tid].push(inst);
@@ -895,13 +889,12 @@ PipelineStage::processInsts(ThreadID tid)
inst = insts_to_stage.front();
DPRINTF(InOrderStage, "[tid:%u]: Processing instruction [sn:%lli] "
- "with PC %#x\n",
- tid, inst->seqNum, inst->readPC());
+ "with PC %s\n", tid, inst->seqNum, inst->pcState());
if (inst->isSquashed()) {
- DPRINTF(InOrderStage, "[tid:%u]: Instruction %i with PC %#x is "
+ DPRINTF(InOrderStage, "[tid:%u]: Instruction %i with PC %s is "
"squashed, skipping.\n",
- tid, inst->seqNum, inst->readPC());
+ tid, inst->seqNum, inst->pcState());
insts_to_stage.pop();
@@ -1001,8 +994,8 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed)
switchedOutValid[tid] = true;
// Remove Thread From Pipeline & Resource Pool
- inst->squashingStage = stageNum;
- inst->bdelaySeqNum = inst->seqNum;
+ inst->squashingStage = stageNum;
+ inst->bdelaySeqNum = inst->seqNum;
cpu->squashFromMemStall(inst, tid);
// Switch On Cache Miss
@@ -1038,9 +1031,9 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed)
res_stage_num = inst->nextResStage();
}
} else {
- DPRINTF(InOrderStage, "[tid:%u]: Instruction [sn:%i] with PC %#x "
+ DPRINTF(InOrderStage, "[tid:%u]: Instruction [sn:%i] with PC %s "
" needed no resources in stage %i.\n",
- tid, inst->seqNum, inst->readPC(), stageNum);
+ tid, inst->seqNum, inst->pcState(), stageNum);
}
return last_req_completed;
@@ -1134,8 +1127,8 @@ PipelineStage::dumpInsts()
while (!copy_buff.empty()) {
DynInstPtr inst = copy_buff.front();
- cprintf("Inst. PC:%#x\n[tid:%i]\n[sn:%i]\n\n",
- inst->readPC(), inst->threadNumber, inst->seqNum);
+ cprintf("Inst. PC:%s\n[tid:%i]\n[sn:%i]\n\n",
+ inst->pcState(), inst->threadNumber, inst->seqNum);
copy_buff.pop();
}
diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh
index c971e400e..6df104e6c 100644
--- a/src/cpu/inorder/pipeline_stage.hh
+++ b/src/cpu/inorder/pipeline_stage.hh
@@ -293,15 +293,15 @@ class PipelineStage
/** SeqNum of Squashing Branch Delay Instruction (used for MIPS) */
Addr bdelayDoneSeqNum[ThePipeline::MaxThreads];
- /** Instruction used for squashing branch (used for MIPS) */
- DynInstPtr squashInst[ThePipeline::MaxThreads];
-
/** Tells when their is a pending delay slot inst. to send
* to rename. If there is, then wait squash after the next
* instruction (used for MIPS).
*/
bool squashAfterDelaySlot[ThePipeline::MaxThreads];
+ /** Instruction used for squashing branch (used for MIPS) */
+ DynInstPtr squashInst[ThePipeline::MaxThreads];
+
/** Maximum size of the inter-stage buffer connecting the previous stage to
* this stage (which we call a skid buffer) */
unsigned stageBufferMax;
diff --git a/src/cpu/inorder/resources/bpred_unit.cc b/src/cpu/inorder/resources/bpred_unit.cc
index b08a393f7..310053409 100644
--- a/src/cpu/inorder/resources/bpred_unit.cc
+++ b/src/cpu/inorder/resources/bpred_unit.cc
@@ -31,6 +31,7 @@
#include <list>
#include <vector>
+#include "arch/utility.hh"
#include "base/trace.hh"
#include "base/traceflags.hh"
#include "config/the_isa.hh"
@@ -149,7 +150,7 @@ BPredUnit::takeOverFrom()
bool
-BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid)
+BPredUnit::predict(DynInstPtr &inst, TheISA::PCState &predPC, ThreadID tid)
{
// See if branch predictor predicts taken.
// If so, get its target addr either from the BTB or the RAS.
@@ -160,12 +161,13 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid)
int asid = inst->asid;
bool pred_taken = false;
- Addr target;
+ TheISA::PCState target;
++lookups;
- DPRINTF(InOrderBPred, "[tid:%i] [sn:%i] %s ... PC%#x doing branch "
+ DPRINTF(InOrderBPred, "[tid:%i] [sn:%i] %s ... PC %s doing branch "
"prediction\n", tid, inst->seqNum,
- inst->staticInst->disassemble(inst->PC), inst->readPC());
+ inst->staticInst->disassemble(inst->instAddr()),
+ inst->pcState());
void *bp_history = NULL;
@@ -185,14 +187,14 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid)
} else {
++condPredicted;
- pred_taken = BPLookup(pred_PC, bp_history);
+ pred_taken = BPLookup(predPC.instAddr(), bp_history);
DPRINTF(InOrderBPred, "[tid:%i]: Branch predictor predicted %i "
- "for PC %#x\n",
- tid, pred_taken, inst->readPC());
+ "for PC %s\n",
+ tid, pred_taken, inst->pcState());
}
- PredictorHistory predict_record(inst->seqNum, pred_PC, pred_taken,
+ PredictorHistory predict_record(inst->seqNum, predPC, pred_taken,
bp_history, tid);
// Now lookup in the BTB or RAS.
@@ -202,40 +204,37 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid)
// If it's a function return call, then look up the address
// in the RAS.
- target = RAS[tid].top();
+ TheISA::PCState rasTop = RAS[tid].top();
+ target = TheISA::buildRetPC(inst->pcState(), rasTop);
// Record the top entry of the RAS, and its index.
predict_record.usedRAS = true;
predict_record.RASIndex = RAS[tid].topIdx();
- predict_record.RASTarget = target;
+ predict_record.rasTarget = rasTop;
assert(predict_record.RASIndex < 16);
RAS[tid].pop();
- DPRINTF(InOrderBPred, "[tid:%i]: Instruction %#x is a return, "
- "RAS predicted target: %#x, RAS index: %i.\n",
- tid, inst->readPC(), target, predict_record.RASIndex);
+ DPRINTF(InOrderBPred, "[tid:%i]: Instruction %s is a return, "
+ "RAS predicted target: %s, RAS index: %i.\n",
+ tid, inst->pcState(), target,
+ predict_record.RASIndex);
} else {
++BTBLookups;
if (inst->isCall()) {
-#if ISA_HAS_DELAY_SLOT
- Addr ras_pc = pred_PC + instSize; // Next Next PC
-#else
- Addr ras_pc = pred_PC; // Next PC
-#endif
-
- RAS[tid].push(ras_pc);
+ RAS[tid].push(inst->pcState());
// Record that it was a call so that the top RAS entry can
// be popped off if the speculation is incorrect.
predict_record.wasCall = true;
- DPRINTF(InOrderBPred, "[tid:%i]: Instruction %#x was a call"
- ", adding %#x to the RAS index: %i.\n",
- tid, inst->readPC(), ras_pc, RAS[tid].topIdx());
+ DPRINTF(InOrderBPred, "[tid:%i]: Instruction %s was a call"
+ ", adding %s to the RAS index: %i.\n",
+ tid, inst->pcState(), predPC,
+ RAS[tid].topIdx());
}
if (inst->isCall() &&
@@ -243,18 +242,18 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid)
inst->isDirectCtrl()) {
target = inst->branchTarget();
- DPRINTF(InOrderBPred, "[tid:%i]: Setting %#x predicted"
- " target to %#x.\n",
- tid, inst->readPC(), target);
- } else if (BTB.valid(pred_PC, asid)) {
+ DPRINTF(InOrderBPred, "[tid:%i]: Setting %s predicted"
+ " target to %s.\n",
+ tid, inst->pcState(), target);
+ } else if (BTB.valid(predPC.instAddr(), asid)) {
++BTBHits;
// If it's not a return, use the BTB to get the target addr.
- target = BTB.lookup(pred_PC, asid);
+ target = BTB.lookup(predPC.instAddr(), asid);
- DPRINTF(InOrderBPred, "[tid:%i]: [asid:%i] Instruction %#x "
- "predicted target is %#x.\n",
- tid, asid, inst->readPC(), target);
+ DPRINTF(InOrderBPred, "[tid:%i]: [asid:%i] Instruction %s "
+ "predicted target is %s.\n",
+ tid, asid, inst->pcState(), target);
} else {
DPRINTF(InOrderBPred, "[tid:%i]: BTB doesn't have a "
"valid entry.\n",tid);
@@ -265,14 +264,7 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid)
if (pred_taken) {
// Set the PC and the instruction's predicted target.
- pred_PC = target;
- } else {
-#if ISA_HAS_DELAY_SLOT
- // This value will be inst->PC + 4 (nextPC)
- // Delay Slot archs need this to be inst->PC + 8 (nextNPC)
- // so we increment one more time here.
- pred_PC = pred_PC + instSize;
-#endif
+ predPC = target;
}
predHist[tid].push_front(predict_record);
@@ -296,7 +288,7 @@ BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid)
while (!predHist[tid].empty() &&
predHist[tid].back().seqNum <= done_sn) {
// Update the branch predictor with the correct results.
- BPUpdate(predHist[tid].back().PC,
+ BPUpdate(predHist[tid].back().pc.instAddr(),
predHist[tid].back().predTaken,
predHist[tid].back().bpHistory);
@@ -314,13 +306,13 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid, ThreadID asid)
pred_hist.front().seqNum > squashed_sn) {
if (pred_hist.front().usedRAS) {
DPRINTF(InOrderBPred, "BranchPred: [tid:%i]: Restoring top of RAS "
- "to: %i, target: %#x.\n",
+ "to: %i, target: %s.\n",
tid,
pred_hist.front().RASIndex,
- pred_hist.front().RASTarget);
+ pred_hist.front().rasTarget);
RAS[tid].restore(pred_hist.front().RASIndex,
- pred_hist.front().RASTarget);
+ pred_hist.front().rasTarget);
} else if (pred_hist.front().wasCall) {
DPRINTF(InOrderBPred, "BranchPred: [tid:%i]: Removing speculative "
@@ -340,7 +332,7 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid, ThreadID asid)
void
BPredUnit::squash(const InstSeqNum &squashed_sn,
- const Addr &corr_target,
+ const TheISA::PCState &corrTarget,
bool actually_taken,
ThreadID tid,
ThreadID asid)
@@ -354,8 +346,8 @@ BPredUnit::squash(const InstSeqNum &squashed_sn,
++condIncorrect;
DPRINTF(InOrderBPred, "[tid:%i]: Squashing from sequence number %i, "
- "setting target to %#x.\n",
- tid, squashed_sn, corr_target);
+ "setting target to %s.\n",
+ tid, squashed_sn, corrTarget);
squash(squashed_sn, tid);
@@ -380,13 +372,13 @@ BPredUnit::squash(const InstSeqNum &squashed_sn,
++RASIncorrect;
}
- BPUpdate((*hist_it).PC, actually_taken,
+ BPUpdate((*hist_it).pc.instAddr(), actually_taken,
pred_hist.front().bpHistory);
- BTB.update((*hist_it).PC, corr_target, asid);
+ BTB.update((*hist_it).pc.instAddr(), corrTarget, asid);
DPRINTF(InOrderBPred, "[tid:%i]: Removing history for [sn:%i] "
- "PC %#x.\n", tid, (*hist_it).seqNum, (*hist_it).PC);
+ "PC %s.\n", tid, (*hist_it).seqNum, (*hist_it).pc);
pred_hist.erase(hist_it);
@@ -424,7 +416,7 @@ BPredUnit::BPSquash(void *bp_history)
bool
-BPredUnit::BPLookup(Addr &inst_PC, void * &bp_history)
+BPredUnit::BPLookup(Addr inst_PC, void * &bp_history)
{
if (predictor == Local) {
return localBP->lookup(inst_PC, bp_history);
@@ -437,7 +429,7 @@ BPredUnit::BPLookup(Addr &inst_PC, void * &bp_history)
void
-BPredUnit::BPUpdate(Addr &inst_PC, bool taken, void *bp_history)
+BPredUnit::BPUpdate(Addr inst_PC, bool taken, void *bp_history)
{
if (predictor == Local) {
localBP->update(inst_PC, taken, bp_history);
diff --git a/src/cpu/inorder/resources/bpred_unit.hh b/src/cpu/inorder/resources/bpred_unit.hh
index 881bfcc95..3b1c0f4ef 100644
--- a/src/cpu/inorder/resources/bpred_unit.hh
+++ b/src/cpu/inorder/resources/bpred_unit.hh
@@ -83,11 +83,12 @@ class BPredUnit
* Predicts whether or not the instruction is a taken branch, and the
* target of the branch if it is taken.
* @param inst The branch instruction.
- * @param pred_PC The predicted PC is passed back through this parameter.
+ * @param predPC The predicted PC is passed back through this parameter.
* @param tid The thread id.
* @return Returns if the branch is taken or not.
*/
- bool predict(ThePipeline::DynInstPtr &inst, Addr &pred_PC, ThreadID tid);
+ bool predict(ThePipeline::DynInstPtr &inst,
+ TheISA::PCState &predPC, ThreadID tid);
// @todo: Rename this function.
void BPUncond(void * &bp_history);
@@ -114,12 +115,13 @@ class BPredUnit
* corrects that sn's update with the proper address and taken/not taken.
* @param squashed_sn The sequence number to squash any younger updates up
* until.
- * @param corr_target The correct branch target.
+ * @param corrTarget The correct branch target.
* @param actually_taken The correct branch direction.
* @param tid The thread id.
*/
- void squash(const InstSeqNum &squashed_sn, const Addr &corr_target,
- bool actually_taken, ThreadID tid, ThreadID asid = 0);
+ void squash(const InstSeqNum &squashed_sn,
+ const TheISA::PCState &corrTarget, bool actually_taken,
+ ThreadID tid, ThreadID asid = 0);
/**
* @param bp_history Pointer to the history object. The predictor
@@ -134,7 +136,7 @@ class BPredUnit
* has the branch predictor state associated with the lookup.
* @return Whether the branch is taken or not taken.
*/
- bool BPLookup(Addr &inst_PC, void * &bp_history);
+ bool BPLookup(Addr instPC, void * &bp_history);
/**
* Looks up a given PC in the BTB to see if a matching entry exists.
@@ -149,26 +151,26 @@ class BPredUnit
* @param inst_PC The PC to look up.
* @return The address of the target of the branch.
*/
- Addr BTBLookup(Addr &inst_PC)
- { return BTB.lookup(inst_PC, 0); }
+ TheISA::PCState BTBLookup(Addr instPC)
+ { return BTB.lookup(instPC, 0); }
/**
* Updates the BP with taken/not taken information.
- * @param inst_PC The branch's PC that will be updated.
+ * @param instPC The branch's PC that will be updated.
* @param taken Whether the branch was taken or not taken.
* @param bp_history Pointer to the branch predictor state that is
* associated with the branch lookup that is being updated.
* @todo Make this update flexible enough to handle a global predictor.
*/
- void BPUpdate(Addr &inst_PC, bool taken, void *bp_history);
+ void BPUpdate(Addr instPC, bool taken, void *bp_history);
/**
* Updates the BTB with the target of a branch.
* @param inst_PC The branch's PC that will be updated.
* @param target_PC The branch's target that will be added to the BTB.
*/
- void BTBUpdate(Addr &inst_PC, Addr &target_PC)
- { BTB.update(inst_PC, target_PC,0); }
+ void BTBUpdate(Addr instPC, const TheISA::PCState &targetPC)
+ { BTB.update(instPC, targetPC, 0); }
void dump();
@@ -181,22 +183,22 @@ class BPredUnit
* Makes a predictor history struct that contains any
* information needed to update the predictor, BTB, and RAS.
*/
- PredictorHistory(const InstSeqNum &seq_num, const Addr &inst_PC,
- bool pred_taken, void *bp_history,
- ThreadID _tid)
- : seqNum(seq_num), PC(inst_PC), RASTarget(0),
- RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0),
- wasCall(0), bpHistory(bp_history)
- { }
+ PredictorHistory(const InstSeqNum &seq_num,
+ const TheISA::PCState &instPC, bool pred_taken,
+ void *bp_history, ThreadID _tid)
+ : seqNum(seq_num), pc(instPC), rasTarget(0), RASIndex(0),
+ tid(_tid), predTaken(pred_taken), usedRAS(0), wasCall(0),
+ bpHistory(bp_history)
+ {}
/** The sequence number for the predictor history entry. */
InstSeqNum seqNum;
/** The PC associated with the sequence number. */
- Addr PC;
+ TheISA::PCState pc;
/** The RAS target (only valid if a return). */
- Addr RASTarget;
+ TheISA::PCState rasTarget;
/** The RAS index of the instruction (only valid if a call). */
unsigned RASIndex;
diff --git a/src/cpu/inorder/resources/branch_predictor.cc b/src/cpu/inorder/resources/branch_predictor.cc
index b971d959a..33b67ce4a 100644
--- a/src/cpu/inorder/resources/branch_predictor.cc
+++ b/src/cpu/inorder/resources/branch_predictor.cc
@@ -84,41 +84,34 @@ BranchPredictor::execute(int slot_num)
DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: squashed, "
"skipping prediction \n", tid, inst->seqNum);
} else {
- Addr pred_PC = inst->readNextPC();
+ TheISA::PCState predPC = inst->pcState();
+ TheISA::advancePC(predPC, inst->staticInst);
if (inst->isControl()) {
// If not, the pred_PC be updated to pc+8
// If predicted, the pred_PC will be updated to new target
// value
- bool predict_taken = branchPred.predict(inst, pred_PC, tid);
+ bool predict_taken = branchPred.predict(inst, predPC, tid);
if (predict_taken) {
DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch "
"predicted true.\n", tid, seq_num);
-
- inst->setPredTarg(pred_PC);
-
predictedTaken++;
} else {
DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch "
"predicted false.\n", tid, seq_num);
-
- if (inst->isCondDelaySlot())
- {
- inst->setPredTarg(inst->readPC() + (2 * instSize));
- } else {
- inst->setPredTarg(pred_PC);
- }
-
predictedNotTaken++;
}
+ inst->setPredTarg(predPC);
+
inst->setBranchPred(predict_taken);
DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Predicted PC is "
- "%08p.\n", tid, seq_num, pred_PC);
+ "%s.\n", tid, seq_num, predPC);
} else {
+ inst->setPredTarg(predPC);
//DPRINTF(InOrderBPred, "[tid:%i]: Ignoring [sn:%i] "
// "because this isn't "
// "a control instruction.\n", tid, seq_num);
@@ -166,10 +159,9 @@ BranchPredictor::squash(DynInstPtr inst, int squash_stage,
squash_seq_num = squash_seq_num - 1;
#endif
- if(squash_stage>=ThePipeline::BackEndStartStage) {
- Addr corr_targ=inst->readPredPC();
- bool taken=inst->predTaken();
- branchPred.squash(squash_seq_num,corr_targ,taken,tid);
+ if (squash_stage >= ThePipeline::BackEndStartStage) {
+ bool taken = inst->predTaken();
+ branchPred.squash(squash_seq_num, inst->readPredTarg(), taken, tid);
} else {
branchPred.squash(squash_seq_num, tid);
}
diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc
index 73deacb12..e7f689ffa 100644
--- a/src/cpu/inorder/resources/cache_unit.cc
+++ b/src/cpu/inorder/resources/cache_unit.cc
@@ -392,15 +392,16 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
unsigned slot_idx = cache_req->getSlot();
if (tlb_mode == TheISA::TLB::Execute) {
- inst->fetchMemReq = new Request(inst->readTid(), aligned_addr,
- acc_size, flags, inst->readPC(),
- cpu->readCpuId(), inst->readTid());
- cache_req->memReq = inst->fetchMemReq;
+ inst->fetchMemReq =
+ new Request(inst->readTid(), aligned_addr, acc_size, flags,
+ inst->instAddr(), cpu->readCpuId(), inst->readTid());
+ cache_req->memReq = inst->fetchMemReq;
} else {
if (!cache_req->is2ndSplit()) {
- inst->dataMemReq = new Request(cpu->asid[tid], aligned_addr,
- acc_size, flags, inst->readPC(),
- cpu->readCpuId(), inst->readTid());
+ inst->dataMemReq =
+ new Request(cpu->asid[tid], aligned_addr, acc_size, flags,
+ inst->instAddr(), cpu->readCpuId(),
+ inst->readTid());
cache_req->memReq = inst->dataMemReq;
} else {
assert(inst->splitInst);
@@ -409,7 +410,7 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
inst->split2ndAddr,
acc_size,
flags,
- inst->readPC(),
+ inst->instAddr(),
cpu->readCpuId(),
tid);
cache_req->memReq = inst->splitMemReq;
@@ -754,7 +755,8 @@ CacheUnit::execute(int slot_num)
DPRINTF(InOrderCachePort, "[tid:%i]: Instruction [sn:%i] is: %s\n",
- tid, seq_num, inst->staticInst->disassemble(inst->PC));
+ tid, seq_num,
+ inst->staticInst->disassemble(inst->instAddr()));
removeAddrDependency(inst);
@@ -771,7 +773,7 @@ CacheUnit::execute(int slot_num)
tid, inst->seqNum);
DPRINTF(InOrderStall,
"STALL: [tid:%i]: Fetch miss from %08p\n",
- tid, cache_req->inst->readPC());
+ tid, cache_req->inst->instAddr());
cache_req->setCompleted(false);
//cache_req->setMemStall(true);
}
@@ -1046,21 +1048,22 @@ CacheUnit::processCacheCompletion(PacketPtr pkt)
// @todo: update thsi
ExtMachInst ext_inst;
StaticInstPtr staticInst = NULL;
- Addr inst_pc = inst->readPC();
+ TheISA::PCState instPC = inst->pcState();
MachInst mach_inst =
TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *>
(cache_pkt->getPtr<uint8_t>()));
predecoder.setTC(cpu->thread[tid]->getTC());
- predecoder.moreBytes(inst_pc, inst_pc, mach_inst);
- ext_inst = predecoder.getExtMachInst();
+ predecoder.moreBytes(instPC, inst->instAddr(), mach_inst);
+ ext_inst = predecoder.getExtMachInst(instPC);
+ inst->pcState(instPC);
inst->setMachInst(ext_inst);
// Set Up More TraceData info
if (inst->traceData) {
inst->traceData->setStaticInst(inst->staticInst);
- inst->traceData->setPC(inst->readPC());
+ inst->traceData->setPC(instPC);
}
} else if (inst->staticInst && inst->isMemRef()) {
@@ -1149,7 +1152,7 @@ CacheUnit::processCacheCompletion(PacketPtr pkt)
} else {
DPRINTF(InOrderCachePort,
"[tid:%u] Miss on block @ %08p completed, but squashed\n",
- tid, cache_req->inst->readPC());
+ tid, cache_req->inst->instAddr());
cache_req->setMemAccCompleted();
}
}
diff --git a/src/cpu/inorder/resources/execution_unit.cc b/src/cpu/inorder/resources/execution_unit.cc
index 91e788fbc..4342042e9 100644
--- a/src/cpu/inorder/resources/execution_unit.cc
+++ b/src/cpu/inorder/resources/execution_unit.cc
@@ -91,8 +91,8 @@ ExecutionUnit::execute(int slot_num)
exec_req->fault = NoFault;
- DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%#x] %s.\n",
- tid, seq_num, inst->readPC(), inst->instName());
+ DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%s] %s.\n",
+ tid, seq_num, inst->pcState(), inst->instName());
switch (exec_req->cmd)
{
@@ -124,58 +124,61 @@ ExecutionUnit::execute(int slot_num)
if (inst->isDirectCtrl()) {
assert(!inst->isIndirectCtrl());
+ TheISA::PCState pc = inst->pcState();
+ TheISA::advancePC(pc, inst->staticInst);
+ inst->setPredTarg(pc);
+
if (inst->predTaken() && inst->isCondDelaySlot()) {
inst->bdelaySeqNum = seq_num;
- inst->setPredTarg(inst->nextPC);
DPRINTF(InOrderExecute, "[tid:%i]: Conditional"
- " branch inst [sn:%i] PC %#x mis"
+ " branch inst [sn:%i] PC %s mis"
"predicted as taken.\n", tid,
- seq_num, inst->PC);
+ seq_num, inst->pcState());
} else if (!inst->predTaken() &&
inst->isCondDelaySlot()) {
inst->bdelaySeqNum = seq_num;
- inst->setPredTarg(inst->nextPC);
inst->procDelaySlotOnMispred = true;
DPRINTF(InOrderExecute, "[tid:%i]: Conditional"
- " branch inst [sn:%i] PC %#x mis"
+ " branch inst [sn:%i] PC %s mis"
"predicted as not taken.\n", tid,
- seq_num, inst->PC);
+ seq_num, inst->pcState());
} else {
#if ISA_HAS_DELAY_SLOT
inst->bdelaySeqNum = seq_num + 1;
- inst->setPredTarg(inst->nextNPC);
#else
inst->bdelaySeqNum = seq_num;
- inst->setPredTarg(inst->nextPC);
#endif
DPRINTF(InOrderExecute, "[tid:%i]: "
"Misprediction detected at "
- "[sn:%i] PC %#x,\n\t squashing after "
+ "[sn:%i] PC %s,\n\t squashing after "
"delay slot instruction [sn:%i].\n",
- tid, seq_num, inst->PC,
+ tid, seq_num, inst->pcState(),
inst->bdelaySeqNum);
DPRINTF(InOrderStall, "STALL: [tid:%i]: Branch"
- " misprediction at %#x\n",
- tid, inst->PC);
+ " misprediction at %s\n",
+ tid, inst->pcState());
}
DPRINTF(InOrderExecute, "[tid:%i] Redirecting "
- "fetch to %#x.\n", tid,
+ "fetch to %s.\n", tid,
inst->readPredTarg());
- } else if(inst->isIndirectCtrl()){
+ } else if (inst->isIndirectCtrl()){
+ TheISA::PCState pc = inst->pcState();
+ TheISA::advancePC(pc, inst->staticInst);
+ inst->seqNum = seq_num;
+ inst->setPredTarg(pc);
+
#if ISA_HAS_DELAY_SLOT
- inst->setPredTarg(inst->nextNPC);
inst->bdelaySeqNum = seq_num + 1;
#else
- inst->setPredTarg(inst->nextPC);
inst->bdelaySeqNum = seq_num;
#endif
DPRINTF(InOrderExecute, "[tid:%i] Redirecting"
- " fetch to %#x.\n", tid,
+ " fetch to %s.\n", tid,
inst->readPredTarg());
} else {
panic("Non-control instruction (%s) mispredict"
@@ -197,14 +200,20 @@ ExecutionUnit::execute(int slot_num)
if (inst->predTaken()) {
predictedTakenIncorrect++;
- DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ... PC%#x ... Mispredicts! (Taken)\n",
- tid, inst->seqNum, inst->staticInst->disassemble(inst->PC),
- inst->readPC());
+ DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..."
+ "PC %s ... Mispredicts! (Taken)\n",
+ tid, inst->seqNum,
+ inst->staticInst->disassemble(
+ inst->instAddr()),
+ inst->pcState());
} else {
predictedNotTakenIncorrect++;
- DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ... PC%#x ... Mispredicts! (Not Taken)\n",
- tid, inst->seqNum, inst->staticInst->disassemble(inst->PC),
- inst->readPC());
+ DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..."
+ "PC %s ... Mispredicts! (Not Taken)\n",
+ tid, inst->seqNum,
+ inst->staticInst->disassemble(
+ inst->instAddr()),
+ inst->pcState());
}
predictedIncorrect++;
} else {
diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc b/src/cpu/inorder/resources/fetch_seq_unit.cc
index 8a1ec3ce5..3bfe912e7 100644
--- a/src/cpu/inorder/resources/fetch_seq_unit.cc
+++ b/src/cpu/inorder/resources/fetch_seq_unit.cc
@@ -44,9 +44,6 @@ FetchSeqUnit::FetchSeqUnit(std::string res_name, int res_id, int res_width,
instSize(sizeof(MachInst))
{
for (ThreadID tid = 0; tid < ThePipeline::MaxThreads; tid++) {
- delaySlotInfo[tid].numInsts = 0;
- delaySlotInfo[tid].targetReady = false;
-
pcValid[tid] = false;
pcBlockStage[tid] = 0;
@@ -86,53 +83,17 @@ FetchSeqUnit::execute(int slot_num)
case AssignNextPC:
{
if (pcValid[tid]) {
+ inst->pcState(pc[tid]);
+ inst->setMemAddr(pc[tid].instAddr());
- if (delaySlotInfo[tid].targetReady &&
- delaySlotInfo[tid].numInsts == 0) {
- // Set PC to target
- PC[tid] = delaySlotInfo[tid].targetAddr; //next_PC
- nextPC[tid] = PC[tid] + instSize; //next_NPC
- nextNPC[tid] = PC[tid] + (2 * instSize);
-
- delaySlotInfo[tid].targetReady = false;
-
- DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to delay "
- "slot target\n",tid);
- }
+ pc[tid].advance(); //XXX HACK!
+ inst->setPredTarg(pc[tid]);
- inst->setPC(PC[tid]);
- inst->setNextPC(PC[tid] + instSize);
- inst->setNextNPC(PC[tid] + (instSize * 2));
-
-#if ISA_HAS_DELAY_SLOT
- inst->setPredTarg(inst->readNextNPC());
-#else
- inst->setPredTarg(inst->readNextPC());
-#endif
- inst->setMemAddr(PC[tid]);
inst->setSeqNum(cpu->getAndIncrementInstSeq(tid));
DPRINTF(InOrderFetchSeq, "[tid:%i]: Assigning [sn:%i] to "
- "PC %08p, NPC %08p, NNPC %08p\n", tid,
- inst->seqNum, inst->readPC(), inst->readNextPC(),
- inst->readNextNPC());
-
- if (delaySlotInfo[tid].numInsts > 0) {
- --delaySlotInfo[tid].numInsts;
-
- // It's OK to set PC to target of branch
- if (delaySlotInfo[tid].numInsts == 0) {
- delaySlotInfo[tid].targetReady = true;
- }
-
- DPRINTF(InOrderFetchSeq, "[tid:%i]: %i delay slot inst(s) "
- "left to process.\n", tid,
- delaySlotInfo[tid].numInsts);
- }
-
- PC[tid] = nextPC[tid];
- nextPC[tid] = nextNPC[tid];
- nextNPC[tid] += instSize;
+ "PC %s\n", tid, inst->seqNum,
+ inst->pcState());
fs_req->done();
} else {
@@ -147,18 +108,21 @@ FetchSeqUnit::execute(int slot_num)
if (inst->isControl()) {
// If it's a return, then we must wait for resolved address.
if (inst->isReturn() && !inst->predTaken()) {
- cpu->pipelineStage[stage_num]->toPrevStages->stageBlock[stage_num][tid] = true;
+ cpu->pipelineStage[stage_num]->
+ toPrevStages->stageBlock[stage_num][tid] = true;
pcValid[tid] = false;
pcBlockStage[tid] = stage_num;
} else if (inst->isCondDelaySlot() && !inst->predTaken()) {
// Not-Taken AND Conditional Control
- DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: [PC:%08p] "
- "Predicted Not-Taken Cond. "
- "Delay inst. Skipping delay slot and Updating PC to %08p\n",
- tid, inst->seqNum, inst->readPC(), inst->readPredTarg());
+ DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: [PC:%s] "
+ "Predicted Not-Taken Cond. Delay inst. Skipping "
+ "delay slot and Updating PC to %s\n",
+ tid, inst->seqNum, inst->pcState(),
+ inst->readPredTarg());
- DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to start from stage %i, after [sn:%i].\n",
- tid, stage_num, seq_num);
+ DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to "
+ "start from stage %i, after [sn:%i].\n", tid,
+ stage_num, seq_num);
inst->bdelaySeqNum = seq_num;
inst->squashingStage = stage_num;
@@ -168,33 +132,26 @@ FetchSeqUnit::execute(int slot_num)
// Not-Taken Control
DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: Predicted "
"Not-Taken Control "
- "inst. updating PC to %08p\n", tid, inst->seqNum,
- inst->readNextPC());
+ "inst. updating PC to %s\n", tid, inst->seqNum,
+ inst->readPredTarg());
#if ISA_HAS_DELAY_SLOT
- ++delaySlotInfo[tid].numInsts;
- delaySlotInfo[tid].targetReady = false;
- delaySlotInfo[tid].targetAddr = inst->readNextNPC();
-#else
- assert(delaySlotInfo[tid].numInsts == 0);
+ pc[tid] = inst->pcState();
+ advancePC(pc[tid], inst->staticInst);
#endif
} else if (inst->predTaken()) {
// Taken Control
#if ISA_HAS_DELAY_SLOT
- ++delaySlotInfo[tid].numInsts;
- delaySlotInfo[tid].targetReady = false;
- delaySlotInfo[tid].targetAddr = inst->readPredTarg();
+ pc[tid] = inst->readPredTarg();
DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i] Updating delay"
- " slot target to PC %08p\n", tid, inst->seqNum,
+ " slot target to PC %s\n", tid, inst->seqNum,
inst->readPredTarg());
inst->bdelaySeqNum = seq_num + 1;
#else
inst->bdelaySeqNum = seq_num;
- assert(delaySlotInfo[tid].numInsts == 0);
#endif
inst->squashingStage = stage_num;
-
DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to "
"start from stage %i, after [sn:%i].\n",
tid, stage_num, inst->bdelaySeqNum);
@@ -225,11 +182,12 @@ FetchSeqUnit::squashAfterInst(DynInstPtr inst, int stage_num, ThreadID tid)
// Squash inside current resource, so if there needs to be fetching on
// same cycle the fetch information will be correct.
- // squash(inst, stage_num, inst->bdelaySeqNum, tid);
// Schedule Squash Through-out Resource Pool
- cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0);
+ cpu->resPool->scheduleEvent(
+ (InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0);
}
+
void
FetchSeqUnit::squash(DynInstPtr inst, int squash_stage,
InstSeqNum squash_seq_num, ThreadID tid)
@@ -241,8 +199,15 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage,
// Handles the case where we are squashing because of something that is
// not a branch...like a memory stall
- Addr new_PC = (inst->isControl()) ?
- inst->readPredTarg() : inst->readPC() + instSize;
+ TheISA::PCState newPC;
+ if (inst->isControl()) {
+ newPC = inst->readPredTarg();
+ } else {
+ TheISA::PCState thisPC = inst->pcState();
+ assert(inst->staticInst);
+ advancePC(thisPC, inst->staticInst);
+ newPC = thisPC;
+ }
if (squashSeqNum[tid] <= done_seq_num &&
lastSquashCycle[tid] == curTick) {
@@ -258,31 +223,25 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage,
// the last done_seq_num then this is the delay slot inst.
if (cpu->nextInstSeqNum(tid) != done_seq_num &&
!inst->procDelaySlotOnMispred) {
- delaySlotInfo[tid].numInsts = 0;
- delaySlotInfo[tid].targetReady = false;
// Reset PC
- PC[tid] = new_PC;
- nextPC[tid] = new_PC + instSize;
- nextNPC[tid] = new_PC + (2 * instSize);
+ pc[tid] = newPC;
+#if ISA_HAS_DELAY_SLOT
+ TheISA::advancePC(pc[tid], inst->staticInst);
+#endif
- DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %08p.\n",
- tid, PC[tid]);
+ DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %s.\n",
+ tid, newPC);
} else {
-#if !ISA_HAS_DELAY_SLOT
- assert(0);
-#endif
+ assert(ISA_HAS_DELAY_SLOT);
- delaySlotInfo[tid].numInsts = 1;
- delaySlotInfo[tid].targetReady = false;
- delaySlotInfo[tid].targetAddr = (inst->procDelaySlotOnMispred) ?
- inst->branchTarget() : new_PC;
+ pc[tid] = (inst->procDelaySlotOnMispred) ?
+ inst->branchTarget() : newPC;
// Reset PC to Delay Slot Instruction
if (inst->procDelaySlotOnMispred) {
- PC[tid] = new_PC;
- nextPC[tid] = new_PC + instSize;
- nextNPC[tid] = new_PC + (2 * instSize);
+ // Reset PC
+ pc[tid] = newPC;
}
}
@@ -309,18 +268,13 @@ FetchSeqUnit::FetchSeqEvent::process()
FetchSeqUnit* fs_res = dynamic_cast<FetchSeqUnit*>(resource);
assert(fs_res);
- for (int i=0; i < MaxThreads; i++) {
- fs_res->PC[i] = fs_res->cpu->readPC(i);
- fs_res->nextPC[i] = fs_res->cpu->readNextPC(i);
- fs_res->nextNPC[i] = fs_res->cpu->readNextNPC(i);
- DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC:%08p NPC:%08p "
- "NNPC:%08p.\n", fs_res->PC[i], fs_res->nextPC[i],
- fs_res->nextNPC[i]);
+ for (int i = 0; i < MaxThreads; i++) {
+ fs_res->pc[i] = fs_res->cpu->pcState(i);
+ DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC: %s.\n",
+ fs_res->pc[i]);
fs_res->pcValid[i] = true;
}
-
- //cpu->fetchPriorityList.push_back(tid);
}
@@ -329,22 +283,17 @@ FetchSeqUnit::activateThread(ThreadID tid)
{
pcValid[tid] = true;
- PC[tid] = cpu->readPC(tid);
- nextPC[tid] = cpu->readNextPC(tid);
- nextNPC[tid] = cpu->readNextNPC(tid);
+ pc[tid] = cpu->pcState(tid);
cpu->fetchPriorityList.push_back(tid);
- DPRINTF(InOrderFetchSeq, "[tid:%i]: Reading PC:%08p NPC:%08p "
- "NNPC:%08p.\n", tid, PC[tid], nextPC[tid], nextNPC[tid]);
+ DPRINTF(InOrderFetchSeq, "[tid:%i]: Reading PC: %s.\n",
+ tid, pc[tid]);
}
void
FetchSeqUnit::deactivateThread(ThreadID tid)
{
- delaySlotInfo[tid].numInsts = 0;
- delaySlotInfo[tid].targetReady = false;
-
pcValid[tid] = false;
pcBlockStage[tid] = 0;
@@ -375,18 +324,14 @@ FetchSeqUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid)
* switch was right after the branch. Thus, if it's not, then
* we are updating incorrectly here
*/
- assert(cpu->thread[tid]->lastBranchNextPC == inst->readPC());
-
- PC[tid] = cpu->thread[tid]->lastBranchNextNPC;
- nextPC[tid] = PC[tid] + instSize;
- nextNPC[tid] = nextPC[tid] + instSize;
+ assert(cpu->nextInstAddr(tid) == inst->instAddr());
+ pc[tid] = cpu->thread[tid]->lastBranchPC;
} else {
- PC[tid] = inst->readNextPC();
- nextPC[tid] = inst->readNextNPC();
- nextNPC[tid] = inst->readNextNPC() + instSize;
+ pc[tid] = inst->pcState();
}
+ assert(inst->staticInst);
+ advancePC(pc[tid], inst->staticInst);
DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating PCs due to Context Switch."
- "Assigning PC:%08p NPC:%08p NNPC:%08p.\n", tid, PC[tid],
- nextPC[tid], nextNPC[tid]);
+ "Assigning PC: %s.\n", tid, pc[tid]);
}
diff --git a/src/cpu/inorder/resources/fetch_seq_unit.hh b/src/cpu/inorder/resources/fetch_seq_unit.hh
index aab462224..a258dc0e5 100644
--- a/src/cpu/inorder/resources/fetch_seq_unit.hh
+++ b/src/cpu/inorder/resources/fetch_seq_unit.hh
@@ -80,22 +80,7 @@ class FetchSeqUnit : public Resource {
bool pcValid[ThePipeline::MaxThreads];
int pcBlockStage[ThePipeline::MaxThreads];
- TheISA::IntReg PC[ThePipeline::MaxThreads];
- TheISA::IntReg nextPC[ThePipeline::MaxThreads];
- TheISA::IntReg nextNPC[ThePipeline::MaxThreads];
-
- /** Tracks delay slot information for threads in ISAs which use
- * delay slots;
- */
- struct DelaySlotInfo {
- InstSeqNum delaySlotSeqNum;
- InstSeqNum branchSeqNum;
- int numInsts;
- Addr targetAddr;
- bool targetReady;
- };
-
- DelaySlotInfo delaySlotInfo[ThePipeline::MaxThreads];
+ TheISA::PCState pc[ThePipeline::MaxThreads];
/** Squash Seq. Nums*/
InstSeqNum squashSeqNum[ThePipeline::MaxThreads];
diff --git a/src/cpu/inorder/resources/tlb_unit.hh b/src/cpu/inorder/resources/tlb_unit.hh
index 5c62c7751..eb1bf55f0 100644
--- a/src/cpu/inorder/resources/tlb_unit.hh
+++ b/src/cpu/inorder/resources/tlb_unit.hh
@@ -111,8 +111,10 @@ class TLBUnitRequest : public ResourceRequest {
aligned_addr = inst->getMemAddr();
req_size = sizeof(TheISA::MachInst);
flags = 0;
- inst->fetchMemReq = new Request(inst->readTid(), aligned_addr, req_size,
- flags, inst->readPC(), res->cpu->readCpuId(), inst->readTid());
+ inst->fetchMemReq = new Request(inst->readTid(), aligned_addr,
+ req_size, flags, inst->instAddr(),
+ res->cpu->readCpuId(),
+ inst->readTid());
memReq = inst->fetchMemReq;
} else {
aligned_addr = inst->getMemAddr();;
@@ -123,8 +125,10 @@ class TLBUnitRequest : public ResourceRequest {
req_size = 8;
}
- inst->dataMemReq = new Request(inst->readTid(), aligned_addr, req_size,
- flags, inst->readPC(), res->cpu->readCpuId(), inst->readTid());
+ inst->dataMemReq = new Request(inst->readTid(), aligned_addr,
+ req_size, flags, inst->instAddr(),
+ res->cpu->readCpuId(),
+ inst->readTid());
memReq = inst->dataMemReq;
}
}
diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc
index e6d0af2cc..bbccf626a 100644
--- a/src/cpu/inorder/thread_context.cc
+++ b/src/cpu/inorder/thread_context.cc
@@ -234,30 +234,6 @@ InOrderThreadContext::setRegOtherThread(int misc_reg, const MiscReg &val,
}
void
-InOrderThreadContext::setPC(uint64_t val)
-{
- DPRINTF(InOrderCPU, "[tid:%i] Setting PC to %08p\n",
- thread->readTid(), val);
- cpu->setPC(val, thread->readTid());
-}
-
-void
-InOrderThreadContext::setNextPC(uint64_t val)
-{
- DPRINTF(InOrderCPU, "[tid:%i] Setting NPC to %08p\n",
- thread->readTid(), val);
- cpu->setNextPC(val, thread->readTid());
-}
-
-void
-InOrderThreadContext::setNextNPC(uint64_t val)
-{
- DPRINTF(InOrderCPU, "[tid:%i] Setting NNPC to %08p\n",
- thread->readTid(), val);
- cpu->setNextNPC(val, thread->readTid());
-}
-
-void
InOrderThreadContext::setMiscRegNoEffect(int misc_reg, const MiscReg &val)
{
cpu->setMiscRegNoEffect(misc_reg, val, thread->readTid());
diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh
index 0c0f563c0..21f1e5835 100644
--- a/src/cpu/inorder/thread_context.hh
+++ b/src/cpu/inorder/thread_context.hh
@@ -204,23 +204,21 @@ class InOrderThreadContext : public ThreadContext
ThreadID tid);
/** Reads this thread's PC. */
- uint64_t readPC()
- { return cpu->readPC(thread->readTid()); }
+ TheISA::PCState pcState()
+ { return cpu->pcState(thread->readTid()); }
/** Sets this thread's PC. */
- void setPC(uint64_t val);
+ void pcState(const TheISA::PCState &val)
+ { cpu->pcState(val, thread->readTid()); }
- /** Reads this thread's next PC. */
- uint64_t readNextPC()
- { return cpu->readNextPC(thread->readTid()); }
+ Addr instAddr()
+ { return cpu->instAddr(thread->readTid()); }
- /** Sets this thread's next PC. */
- void setNextPC(uint64_t val);
+ Addr nextInstAddr()
+ { return cpu->nextInstAddr(thread->readTid()); }
- uint64_t readNextNPC()
- { return cpu->readNextNPC(thread->readTid()); }
-
- void setNextNPC(uint64_t val);
+ MicroPC microPC()
+ { return cpu->microPC(thread->readTid()); }
/** Reads a miscellaneous register. */
MiscReg readMiscRegNoEffect(int misc_reg)
diff --git a/src/cpu/inorder/thread_state.hh b/src/cpu/inorder/thread_state.hh
index 0a171a99f..20ace6659 100644
--- a/src/cpu/inorder/thread_state.hh
+++ b/src/cpu/inorder/thread_state.hh
@@ -111,9 +111,7 @@ class InOrderThreadState : public ThreadState {
/** Is last instruction graduated a branch? */
bool lastGradIsBranch;
- Addr lastBranchPC;
- Addr lastBranchNextPC;
- Addr lastBranchNextNPC;
+ TheISA::PCState lastBranchPC;
};
#endif // __CPU_INORDER_THREAD_STATE_HH__
diff --git a/src/cpu/inteltrace.cc b/src/cpu/inteltrace.cc
index ec51b80e7..ee148c50f 100644
--- a/src/cpu/inteltrace.cc
+++ b/src/cpu/inteltrace.cc
@@ -48,7 +48,7 @@ Trace::IntelTraceRecord::dump()
{
ostream &outs = Trace::output();
ccprintf(outs, "%7d ) ", when);
- outs << "0x" << hex << PC << ":\t";
+ outs << "0x" << hex << pc.instAddr() << ":\t";
if (staticInst->isLoad()) {
ccprintf(outs, "<RD %#x>", addr);
} else if (staticInst->isStore()) {
diff --git a/src/cpu/inteltrace.hh b/src/cpu/inteltrace.hh
index c4ace4f4b..234b173e9 100644
--- a/src/cpu/inteltrace.hh
+++ b/src/cpu/inteltrace.hh
@@ -46,10 +46,10 @@ class IntelTraceRecord : public InstRecord
{
public:
IntelTraceRecord(Tick _when, ThreadContext *_thread,
- const StaticInstPtr _staticInst, Addr _pc, bool spec,
- const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0)
+ const StaticInstPtr _staticInst, TheISA::PCState _pc,
+ bool spec, const StaticInstPtr _macroStaticInst = NULL)
: InstRecord(_when, _thread, _staticInst, _pc, spec,
- _macroStaticInst, _upc)
+ _macroStaticInst)
{
}
@@ -65,8 +65,8 @@ class IntelTrace : public InstTracer
IntelTraceRecord *
getInstRecord(Tick when, ThreadContext *tc,
- const StaticInstPtr staticInst, Addr pc,
- const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0)
+ const StaticInstPtr staticInst, TheISA::PCState pc,
+ const StaticInstPtr macroStaticInst = NULL)
{
if (!IsOn(ExecEnable))
return NULL;
@@ -78,7 +78,7 @@ class IntelTrace : public InstTracer
return NULL;
return new IntelTraceRecord(when, tc,
- staticInst, pc, tc->misspeculating(), macroStaticInst, upc);
+ staticInst, pc, tc->misspeculating(), macroStaticInst);
}
};
diff --git a/src/cpu/legiontrace.cc b/src/cpu/legiontrace.cc
index 1390d0807..8750e56e5 100644
--- a/src/cpu/legiontrace.cc
+++ b/src/cpu/legiontrace.cc
@@ -211,7 +211,7 @@ Trace::LegionTraceRecord::dump()
if(!staticInst->isMicroop() || staticInst->isLastMicroop()) {
while (!compared) {
if (shared_data->flags == OWN_M5) {
- m5Pc = PC & SparcISA::PAddrImplMask;
+ m5Pc = pc.instAddr() & SparcISA::PAddrImplMask;
if (bits(shared_data->pstate,3,3)) {
m5Pc &= mask(32);
}
@@ -432,13 +432,14 @@ Trace::LegionTraceRecord::dump()
<< endl;
predecoder.setTC(thread);
- predecoder.moreBytes(m5Pc, m5Pc,
- shared_data->instruction);
+ predecoder.moreBytes(m5Pc, m5Pc, shared_data->instruction);
assert(predecoder.extMachInstReady());
+ PCState tempPC = pc;
StaticInstPtr legionInst =
- StaticInst::decode(predecoder.getExtMachInst(), lgnPc);
+ StaticInst::decode(predecoder.getExtMachInst(tempPC),
+ lgnPc);
outs << setfill(' ') << setw(15)
<< " Legion Inst: "
<< "0x" << setw(8) << setfill('0') << hex
diff --git a/src/cpu/legiontrace.hh b/src/cpu/legiontrace.hh
index 829941d4b..a60b9ad10 100644
--- a/src/cpu/legiontrace.hh
+++ b/src/cpu/legiontrace.hh
@@ -46,10 +46,10 @@ class LegionTraceRecord : public InstRecord
{
public:
LegionTraceRecord(Tick _when, ThreadContext *_thread,
- const StaticInstPtr _staticInst, Addr _pc, bool spec,
- const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0)
+ const StaticInstPtr _staticInst, TheISA::PCState _pc,
+ bool spec, const StaticInstPtr _macroStaticInst = NULL)
: InstRecord(_when, _thread, _staticInst, _pc, spec,
- _macroStaticInst, _upc)
+ _macroStaticInst)
{
}
@@ -65,14 +65,14 @@ class LegionTrace : public InstTracer
LegionTraceRecord *
getInstRecord(Tick when, ThreadContext *tc,
- const StaticInstPtr staticInst, Addr pc,
- const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0)
+ const StaticInstPtr staticInst, TheISA::PCState pc,
+ const StaticInstPtr macroStaticInst = NULL)
{
if (tc->misspeculating())
return NULL;
return new LegionTraceRecord(when, tc,
- staticInst, pc, tc->misspeculating(), macroStaticInst, upc);
+ staticInst, pc, tc->misspeculating(), macroStaticInst);
}
};
diff --git a/src/cpu/nativetrace.hh b/src/cpu/nativetrace.hh
index 6ad6b0242..5c5b9a66d 100644
--- a/src/cpu/nativetrace.hh
+++ b/src/cpu/nativetrace.hh
@@ -54,10 +54,10 @@ class NativeTraceRecord : public ExeTracerRecord
public:
NativeTraceRecord(NativeTrace * _parent,
Tick _when, ThreadContext *_thread,
- const StaticInstPtr _staticInst, Addr _pc, bool spec,
- const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0)
+ const StaticInstPtr _staticInst, TheISA::PCState _pc,
+ bool spec, const StaticInstPtr _macroStaticInst = NULL)
: ExeTracerRecord(_when, _thread, _staticInst, _pc, spec,
- _macroStaticInst, _upc),
+ _macroStaticInst),
parent(_parent)
{
}
@@ -79,14 +79,14 @@ class NativeTrace : public ExeTracer
NativeTraceRecord *
getInstRecord(Tick when, ThreadContext *tc,
- const StaticInstPtr staticInst, Addr pc,
- const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0)
+ const StaticInstPtr staticInst, TheISA::PCState pc,
+ const StaticInstPtr macroStaticInst = NULL)
{
if (tc->misspeculating())
return NULL;
return new NativeTraceRecord(this, when, tc,
- staticInst, pc, tc->misspeculating(), macroStaticInst, upc);
+ staticInst, pc, tc->misspeculating(), macroStaticInst);
}
template<class T>
diff --git a/src/cpu/o3/bpred_unit.hh b/src/cpu/o3/bpred_unit.hh
index f199bdd75..58b1147c9 100644
--- a/src/cpu/o3/bpred_unit.hh
+++ b/src/cpu/o3/bpred_unit.hh
@@ -88,7 +88,7 @@ class BPredUnit
* @param tid The thread id.
* @return Returns if the branch is taken or not.
*/
- bool predict(DynInstPtr &inst, Addr &PC, ThreadID tid);
+ bool predict(DynInstPtr &inst, TheISA::PCState &pc, ThreadID tid);
// @todo: Rename this function.
void BPUncond(void * &bp_history);
@@ -118,7 +118,8 @@ class BPredUnit
* @param actually_taken The correct branch direction.
* @param tid The thread id.
*/
- void squash(const InstSeqNum &squashed_sn, const Addr &corr_target,
+ void squash(const InstSeqNum &squashed_sn,
+ const TheISA::PCState &corr_target,
bool actually_taken, ThreadID tid);
/**
@@ -134,23 +135,23 @@ class BPredUnit
* has the branch predictor state associated with the lookup.
* @return Whether the branch is taken or not taken.
*/
- bool BPLookup(Addr &inst_PC, void * &bp_history);
+ bool BPLookup(Addr instPC, void * &bp_history);
/**
* Looks up a given PC in the BTB to see if a matching entry exists.
* @param inst_PC The PC to look up.
* @return Whether the BTB contains the given PC.
*/
- bool BTBValid(Addr &inst_PC)
- { return BTB.valid(inst_PC, 0); }
+ bool BTBValid(Addr instPC)
+ { return BTB.valid(instPC, 0); }
/**
* Looks up a given PC in the BTB to get the predicted target.
* @param inst_PC The PC to look up.
* @return The address of the target of the branch.
*/
- Addr BTBLookup(Addr &inst_PC)
- { return BTB.lookup(inst_PC, 0); }
+ TheISA::PCState BTBLookup(Addr instPC)
+ { return BTB.lookup(instPC, 0); }
/**
* Updates the BP with taken/not taken information.
@@ -160,15 +161,15 @@ class BPredUnit
* associated with the branch lookup that is being updated.
* @todo Make this update flexible enough to handle a global predictor.
*/
- void BPUpdate(Addr &inst_PC, bool taken, void *bp_history);
+ void BPUpdate(Addr instPC, bool taken, void *bp_history);
/**
* Updates the BTB with the target of a branch.
* @param inst_PC The branch's PC that will be updated.
* @param target_PC The branch's target that will be added to the BTB.
*/
- void BTBUpdate(Addr &inst_PC, Addr &target_PC)
- { BTB.update(inst_PC, target_PC,0); }
+ void BTBUpdate(Addr instPC, const TheISA::PCState &target)
+ { BTB.update(instPC, target, 0); }
void dump();
@@ -178,13 +179,13 @@ class BPredUnit
* Makes a predictor history struct that contains any
* information needed to update the predictor, BTB, and RAS.
*/
- PredictorHistory(const InstSeqNum &seq_num, const Addr &inst_PC,
+ PredictorHistory(const InstSeqNum &seq_num, Addr instPC,
bool pred_taken, void *bp_history,
ThreadID _tid)
- : seqNum(seq_num), PC(inst_PC), RASTarget(0),
- RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0),
+ : seqNum(seq_num), pc(instPC), RASTarget(0), RASIndex(0),
+ tid(_tid), predTaken(pred_taken), usedRAS(0),
wasCall(0), bpHistory(bp_history)
- { }
+ {}
bool operator==(const PredictorHistory &entry) const {
return this->seqNum == entry.seqNum;
@@ -194,10 +195,10 @@ class BPredUnit
InstSeqNum seqNum;
/** The PC associated with the sequence number. */
- Addr PC;
+ Addr pc;
/** The RAS target (only valid if a return). */
- Addr RASTarget;
+ TheISA::PCState RASTarget;
/** The RAS index of the instruction (only valid if a call). */
unsigned RASIndex;
diff --git a/src/cpu/o3/bpred_unit_impl.hh b/src/cpu/o3/bpred_unit_impl.hh
index ed3471761..14d47df9f 100644
--- a/src/cpu/o3/bpred_unit_impl.hh
+++ b/src/cpu/o3/bpred_unit_impl.hh
@@ -31,6 +31,7 @@
#include <algorithm>
#include "arch/types.hh"
+#include "arch/utility.hh"
#include "arch/isa_traits.hh"
#include "base/trace.hh"
#include "base/traceflags.hh"
@@ -144,17 +145,15 @@ BPredUnit<Impl>::takeOverFrom()
template <class Impl>
bool
-BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, ThreadID tid)
+BPredUnit<Impl>::predict(DynInstPtr &inst, TheISA::PCState &pc, ThreadID tid)
{
// See if branch predictor predicts taken.
// If so, get its target addr either from the BTB or the RAS.
// Save off record of branch stuff so the RAS can be fixed
// up once it's done.
- using TheISA::MachInst;
-
bool pred_taken = false;
- Addr target = PC;
+ TheISA::PCState target = pc;
++lookups;
@@ -168,19 +167,19 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, ThreadID tid)
} else {
++condPredicted;
- pred_taken = BPLookup(PC, bp_history);
+ pred_taken = BPLookup(pc.instAddr(), bp_history);
DPRINTF(Fetch, "BranchPred: [tid:%i]: Branch predictor predicted %i "
- "for PC %#x\n",
- tid, pred_taken, inst->readPC());
+ "for PC %s\n",
+ tid, pred_taken, inst->pcState());
}
DPRINTF(Fetch, "BranchPred: [tid:%i]: [sn:%i] Creating prediction history "
- "for PC %#x\n",
- tid, inst->seqNum, inst->readPC());
+ "for PC %s\n",
+ tid, inst->seqNum, inst->pcState());
- PredictorHistory predict_record(inst->seqNum, PC, pred_taken,
- bp_history, tid);
+ PredictorHistory predict_record(inst->seqNum, pc.instAddr(),
+ pred_taken, bp_history, tid);
// Now lookup in the BTB or RAS.
if (pred_taken) {
@@ -189,60 +188,58 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, ThreadID tid)
// If it's a function return call, then look up the address
// in the RAS.
- target = RAS[tid].top();
+ TheISA::PCState rasTop = RAS[tid].top();
+ target = TheISA::buildRetPC(pc, rasTop);
// Record the top entry of the RAS, and its index.
predict_record.usedRAS = true;
predict_record.RASIndex = RAS[tid].topIdx();
- predict_record.RASTarget = target;
+ predict_record.RASTarget = rasTop;
assert(predict_record.RASIndex < 16);
RAS[tid].pop();
- DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x is a return, "
- "RAS predicted target: %#x, RAS index: %i.\n",
- tid, inst->readPC(), target, predict_record.RASIndex);
+ DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %s is a return, "
+ "RAS predicted target: %s, RAS index: %i.\n",
+ tid, inst->pcState(), target, predict_record.RASIndex);
} else {
++BTBLookups;
if (inst->isCall()) {
-#if ISA_HAS_DELAY_SLOT
- Addr ras_pc = PC + (2 * sizeof(MachInst)); // Next Next PC
-#else
- Addr ras_pc = PC + sizeof(MachInst); // Next PC
-#endif
- RAS[tid].push(ras_pc);
+ RAS[tid].push(pc);
// Record that it was a call so that the top RAS entry can
// be popped off if the speculation is incorrect.
predict_record.wasCall = true;
- DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x was a call"
- ", adding %#x to the RAS index: %i.\n",
- tid, inst->readPC(), ras_pc, RAS[tid].topIdx());
+ DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %s was a "
+ "call, adding %s to the RAS index: %i.\n",
+ tid, inst->pcState(), pc, RAS[tid].topIdx());
}
- if (BTB.valid(PC, tid)) {
+ if (BTB.valid(pc.instAddr(), tid)) {
++BTBHits;
// If it's not a return, use the BTB to get the target addr.
- target = BTB.lookup(PC, tid);
+ target = BTB.lookup(pc.instAddr(), tid);
- DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x predicted"
- " target is %#x.\n",
- tid, inst->readPC(), target);
+ DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %s predicted"
+ " target is %s.\n", tid, inst->pcState(), target);
} else {
DPRINTF(Fetch, "BranchPred: [tid:%i]: BTB doesn't have a "
"valid entry.\n",tid);
pred_taken = false;
+ TheISA::advancePC(target, inst->staticInst);
}
}
+ } else {
+ TheISA::advancePC(target, inst->staticInst);
}
- PC = target;
+ pc = target;
predHist[tid].push_front(predict_record);
@@ -262,7 +259,7 @@ BPredUnit<Impl>::update(const InstSeqNum &done_sn, ThreadID tid)
while (!predHist[tid].empty() &&
predHist[tid].back().seqNum <= done_sn) {
// Update the branch predictor with the correct results.
- BPUpdate(predHist[tid].back().PC,
+ BPUpdate(predHist[tid].back().pc,
predHist[tid].back().predTaken,
predHist[tid].back().bpHistory);
@@ -280,10 +277,8 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ThreadID tid)
pred_hist.front().seqNum > squashed_sn) {
if (pred_hist.front().usedRAS) {
DPRINTF(Fetch, "BranchPred: [tid:%i]: Restoring top of RAS to: %i,"
- " target: %#x.\n",
- tid,
- pred_hist.front().RASIndex,
- pred_hist.front().RASTarget);
+ " target: %s.\n", tid,
+ pred_hist.front().RASIndex, pred_hist.front().RASTarget);
RAS[tid].restore(pred_hist.front().RASIndex,
pred_hist.front().RASTarget);
@@ -298,11 +293,13 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ThreadID tid)
BPSquash(pred_hist.front().bpHistory);
DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing history for [sn:%i] "
- "PC %#x.\n", tid, pred_hist.front().seqNum, pred_hist.front().PC);
+ "PC %s.\n", tid, pred_hist.front().seqNum,
+ pred_hist.front().pc);
pred_hist.pop_front();
- DPRINTF(Fetch, "[tid:%i]: predHist.size(): %i\n", tid, predHist[tid].size());
+ DPRINTF(Fetch, "[tid:%i]: predHist.size(): %i\n",
+ tid, predHist[tid].size());
}
}
@@ -310,7 +307,7 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ThreadID tid)
template <class Impl>
void
BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn,
- const Addr &corr_target,
+ const TheISA::PCState &corrTarget,
bool actually_taken,
ThreadID tid)
{
@@ -330,8 +327,8 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn,
++condIncorrect;
DPRINTF(Fetch, "BranchPred: [tid:%i]: Squashing from sequence number %i, "
- "setting target to %#x.\n",
- tid, squashed_sn, corr_target);
+ "setting target to %s.\n",
+ tid, squashed_sn, corrTarget);
// Squash All Branches AFTER this mispredicted branch
squash(squashed_sn, tid);
@@ -358,13 +355,13 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn,
++RASIncorrect;
}
- BPUpdate((*hist_it).PC, actually_taken,
+ BPUpdate((*hist_it).pc, actually_taken,
pred_hist.front().bpHistory);
- BTB.update((*hist_it).PC, corr_target, tid);
+ BTB.update((*hist_it).pc, corrTarget, tid);
DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing history for [sn:%i] "
- "PC %#x.\n", tid, (*hist_it).seqNum, (*hist_it).PC);
+ "PC %s.\n", tid, (*hist_it).seqNum, (*hist_it).pc);
pred_hist.erase(hist_it);
@@ -397,12 +394,12 @@ BPredUnit<Impl>::BPSquash(void *bp_history)
template <class Impl>
bool
-BPredUnit<Impl>::BPLookup(Addr &inst_PC, void * &bp_history)
+BPredUnit<Impl>::BPLookup(Addr instPC, void * &bp_history)
{
if (predictor == Local) {
- return localBP->lookup(inst_PC, bp_history);
+ return localBP->lookup(instPC, bp_history);
} else if (predictor == Tournament) {
- return tournamentBP->lookup(inst_PC, bp_history);
+ return tournamentBP->lookup(instPC, bp_history);
} else {
panic("Predictor type is unexpected value!");
}
@@ -410,12 +407,12 @@ BPredUnit<Impl>::BPLookup(Addr &inst_PC, void * &bp_history)
template <class Impl>
void
-BPredUnit<Impl>::BPUpdate(Addr &inst_PC, bool taken, void *bp_history)
+BPredUnit<Impl>::BPUpdate(Addr instPC, bool taken, void *bp_history)
{
if (predictor == Local) {
- localBP->update(inst_PC, taken, bp_history);
+ localBP->update(instPC, taken, bp_history);
} else if (predictor == Tournament) {
- tournamentBP->update(inst_PC, taken, bp_history);
+ tournamentBP->update(instPC, taken, bp_history);
} else {
panic("Predictor type is unexpected value!");
}
@@ -436,9 +433,9 @@ BPredUnit<Impl>::dump()
while (pred_hist_it != predHist[i].end()) {
cprintf("[sn:%lli], PC:%#x, tid:%i, predTaken:%i, "
"bpHistory:%#x\n",
- (*pred_hist_it).seqNum, (*pred_hist_it).PC,
- (*pred_hist_it).tid, (*pred_hist_it).predTaken,
- (*pred_hist_it).bpHistory);
+ pred_hist_it->seqNum, pred_hist_it->pc,
+ pred_hist_it->tid, pred_hist_it->predTaken,
+ pred_hist_it->bpHistory);
pred_hist_it++;
}
diff --git a/src/cpu/o3/comm.hh b/src/cpu/o3/comm.hh
index 23b836f73..c9fb3319b 100644
--- a/src/cpu/o3/comm.hh
+++ b/src/cpu/o3/comm.hh
@@ -33,6 +33,7 @@
#include <vector>
+#include "arch/types.hh"
#include "base/types.hh"
#include "cpu/inst_seq.hh"
#include "sim/faults.hh"
@@ -88,9 +89,7 @@ struct DefaultIEWDefaultCommit {
bool branchMispredict[Impl::MaxThreads];
bool branchTaken[Impl::MaxThreads];
Addr mispredPC[Impl::MaxThreads];
- Addr nextPC[Impl::MaxThreads];
- Addr nextNPC[Impl::MaxThreads];
- Addr nextMicroPC[Impl::MaxThreads];
+ TheISA::PCState pc[Impl::MaxThreads];
InstSeqNum squashedSeqNum[Impl::MaxThreads];
bool includeSquashInst[Impl::MaxThreads];
@@ -120,9 +119,7 @@ struct TimeBufStruct {
bool branchMispredict;
bool branchTaken;
Addr mispredPC;
- Addr nextPC;
- Addr nextNPC;
- Addr nextMicroPC;
+ TheISA::PCState nextPC;
unsigned branchCount;
};
@@ -161,9 +158,7 @@ struct TimeBufStruct {
bool branchMispredict;
bool branchTaken;
Addr mispredPC;
- Addr nextPC;
- Addr nextNPC;
- Addr nextMicroPC;
+ TheISA::PCState pc;
// Represents the instruction that has either been retired or
// squashed. Similar to having a single bus that broadcasts the
diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh
index d93b85984..326f3a1d3 100644
--- a/src/cpu/o3/commit.hh
+++ b/src/cpu/o3/commit.hh
@@ -277,40 +277,21 @@ class DefaultCommit
ThreadID oldestReady();
public:
- /** Returns the PC of the head instruction of the ROB.
- * @todo: Probably remove this function as it returns only thread 0.
- */
- Addr readPC() { return PC[0]; }
-
- /** Returns the PC of a specific thread. */
- Addr readPC(ThreadID tid) { return PC[tid]; }
+ /** Reads the PC of a specific thread. */
+ TheISA::PCState pcState(ThreadID tid) { return pc[tid]; }
/** Sets the PC of a specific thread. */
- void setPC(Addr val, ThreadID tid) { PC[tid] = val; }
-
- /** Reads the micro PC of a specific thread. */
- Addr readMicroPC(ThreadID tid) { return microPC[tid]; }
-
- /** Sets the micro PC of a specific thread */
- void setMicroPC(Addr val, ThreadID tid) { microPC[tid] = val; }
-
- /** Reads the next PC of a specific thread. */
- Addr readNextPC(ThreadID tid) { return nextPC[tid]; }
-
- /** Sets the next PC of a specific thread. */
- void setNextPC(Addr val, ThreadID tid) { nextPC[tid] = val; }
+ void pcState(const TheISA::PCState &val, ThreadID tid)
+ { pc[tid] = val; }
- /** Reads the next NPC of a specific thread. */
- Addr readNextNPC(ThreadID tid) { return nextNPC[tid]; }
+ /** Returns the PC of a specific thread. */
+ Addr instAddr(ThreadID tid) { return pc[tid].instAddr(); }
- /** Sets the next NPC of a specific thread. */
- void setNextNPC(Addr val, ThreadID tid) { nextNPC[tid] = val; }
+ /** Returns the next PC of a specific thread. */
+ Addr nextInstAddr(ThreadID tid) { return pc[tid].nextInstAddr(); }
/** Reads the micro PC of a specific thread. */
- Addr readNextMicroPC(ThreadID tid) { return nextMicroPC[tid]; }
-
- /** Sets the micro PC of a specific thread */
- void setNextMicroPC(Addr val, ThreadID tid) { nextMicroPC[tid] = val; }
+ Addr microPC(ThreadID tid) { return pc[tid].microPC(); }
private:
/** Time buffer interface. */
@@ -410,24 +391,10 @@ class DefaultCommit
/** The interrupt fault. */
Fault interrupt;
- /** The commit PC of each thread. Refers to the instruction that
- * is currently being processed/committed.
- */
- Addr PC[Impl::MaxThreads];
-
- /** The commit micro PC of each thread. Refers to the instruction that
+ /** The commit PC state of each thread. Refers to the instruction that
* is currently being processed/committed.
*/
- Addr microPC[Impl::MaxThreads];
-
- /** The next PC of each thread. */
- Addr nextPC[Impl::MaxThreads];
-
- /** The next NPC of each thread. */
- Addr nextNPC[Impl::MaxThreads];
-
- /** The next micro PC of each thread. */
- Addr nextMicroPC[Impl::MaxThreads];
+ TheISA::PCState pc[Impl::MaxThreads];
/** The sequence number of the youngest valid instruction in the ROB. */
InstSeqNum youngestSeqNum[Impl::MaxThreads];
diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh
index 98c7b49c8..8d3edfb19 100644
--- a/src/cpu/o3/commit_impl.hh
+++ b/src/cpu/o3/commit_impl.hh
@@ -128,11 +128,7 @@ DefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
committedStores[tid] = false;
trapSquash[tid] = false;
tcSquash[tid] = false;
- microPC[tid] = 0;
- nextMicroPC[tid] = 0;
- PC[tid] = 0;
- nextPC[tid] = 0;
- nextNPC[tid] = 0;
+ pc[tid].set(0);
}
#if FULL_SYSTEM
interrupt = NoFault;
@@ -513,9 +509,7 @@ DefaultCommit<Impl>::squashAll(ThreadID tid)
toIEW->commitInfo[tid].branchMispredict = false;
- toIEW->commitInfo[tid].nextPC = PC[tid];
- toIEW->commitInfo[tid].nextNPC = nextPC[tid];
- toIEW->commitInfo[tid].nextMicroPC = nextMicroPC[tid];
+ toIEW->commitInfo[tid].pc = pc[tid];
}
template <class Impl>
@@ -524,7 +518,7 @@ DefaultCommit<Impl>::squashFromTrap(ThreadID tid)
{
squashAll(tid);
- DPRINTF(Commit, "Squashing from trap, restarting at PC %#x\n", PC[tid]);
+ DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]);
thread[tid]->trapPending = false;
thread[tid]->inSyscall = false;
@@ -542,7 +536,7 @@ DefaultCommit<Impl>::squashFromTC(ThreadID tid)
{
squashAll(tid);
- DPRINTF(Commit, "Squashing from TC, restarting at PC %#x\n", PC[tid]);
+ DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]);
thread[tid]->inSyscall = false;
assert(!thread[tid]->trapPending);
@@ -611,16 +605,16 @@ DefaultCommit<Impl>::tick()
DynInstPtr inst = rob->readHeadInst(tid);
- DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %#x is head of"
+ DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %s is head of"
" ROB and ready to commit\n",
- tid, inst->seqNum, inst->readPC());
+ tid, inst->seqNum, inst->pcState());
} else if (!rob->isEmpty(tid)) {
DynInstPtr inst = rob->readHeadInst(tid);
DPRINTF(Commit,"[tid:%i]: Can't commit, Instruction [sn:%lli] PC "
- "%#x is head of ROB and not ready\n",
- tid, inst->seqNum, inst->readPC());
+ "%s is head of ROB and not ready\n",
+ tid, inst->seqNum, inst->pcState());
}
DPRINTF(Commit, "[tid:%i]: ROB has %d insts & %d free entries.\n",
@@ -738,7 +732,7 @@ DefaultCommit<Impl>::commit()
DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n",
tid,
- fromIEW->nextPC[tid]);
+ fromIEW->pc[tid].nextInstAddr());
commitStatus[tid] = ROBSquashing;
@@ -771,9 +765,7 @@ DefaultCommit<Impl>::commit()
toIEW->commitInfo[tid].branchTaken =
fromIEW->branchTaken[tid];
- toIEW->commitInfo[tid].nextPC = fromIEW->nextPC[tid];
- toIEW->commitInfo[tid].nextNPC = fromIEW->nextNPC[tid];
- toIEW->commitInfo[tid].nextMicroPC = fromIEW->nextMicroPC[tid];
+ toIEW->commitInfo[tid].pc = fromIEW->pc[tid];
toIEW->commitInfo[tid].mispredPC = fromIEW->mispredPC[tid];
@@ -880,10 +872,7 @@ DefaultCommit<Impl>::commitInsts()
// Record that the number of ROB entries has changed.
changedROBNumEntries[tid] = true;
} else {
- PC[tid] = head_inst->readPC();
- nextPC[tid] = head_inst->readNextPC();
- nextNPC[tid] = head_inst->readNextNPC();
- nextMicroPC[tid] = head_inst->readNextMicroPC();
+ pc[tid] = head_inst->pcState();
// Increment the total number of non-speculative instructions
// executed.
@@ -911,11 +900,7 @@ DefaultCommit<Impl>::commitInsts()
cpu->instDone(tid);
}
- PC[tid] = nextPC[tid];
- nextPC[tid] = nextNPC[tid];
- nextNPC[tid] = nextNPC[tid] + sizeof(TheISA::MachInst);
- microPC[tid] = nextMicroPC[tid];
- nextMicroPC[tid] = microPC[tid] + 1;
+ TheISA::advancePC(pc[tid], head_inst->staticInst);
int count = 0;
Addr oldpc;
@@ -923,19 +908,19 @@ DefaultCommit<Impl>::commitInsts()
// currently updating state while handling PC events.
assert(!thread[tid]->inSyscall && !thread[tid]->trapPending);
do {
- oldpc = PC[tid];
+ oldpc = pc[tid].instAddr();
cpu->system->pcEventQueue.service(thread[tid]->getTC());
count++;
- } while (oldpc != PC[tid]);
+ } while (oldpc != pc[tid].instAddr());
if (count > 1) {
DPRINTF(Commit,
"PC skip function event, stopping commit\n");
break;
}
} else {
- DPRINTF(Commit, "Unable to commit head instruction PC:%#x "
+ DPRINTF(Commit, "Unable to commit head instruction PC:%s "
"[tid:%i] [sn:%i].\n",
- head_inst->readPC(), tid ,head_inst->seqNum);
+ head_inst->pcState(), tid ,head_inst->seqNum);
break;
}
}
@@ -970,8 +955,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
head_inst->isWriteBarrier()) {
DPRINTF(Commit, "Encountered a barrier or non-speculative "
- "instruction [sn:%lli] at the head of the ROB, PC %#x.\n",
- head_inst->seqNum, head_inst->readPC());
+ "instruction [sn:%lli] at the head of the ROB, PC %s.\n",
+ head_inst->seqNum, head_inst->pcState());
if (inst_num > 0 || iewStage->hasStoresToWB(tid)) {
DPRINTF(Commit, "Waiting for all stores to writeback.\n");
@@ -994,8 +979,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
}
assert(head_inst->uncacheable());
- DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %#x.\n",
- head_inst->seqNum, head_inst->readPC());
+ DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %s.\n",
+ head_inst->seqNum, head_inst->pcState());
// Send back the non-speculative instruction's sequence
// number. Tell the lsq to re-execute the load.
@@ -1034,8 +1019,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
#endif
if (inst_fault != NoFault) {
- DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n",
- head_inst->seqNum, head_inst->readPC());
+ DPRINTF(Commit, "Inst [sn:%lli] PC %s has a fault\n",
+ head_inst->seqNum, head_inst->pcState());
if (iewStage->hasStoresToWB(tid) || inst_num > 0) {
DPRINTF(Commit, "Stores outstanding, fault must wait.\n");
@@ -1081,7 +1066,6 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
// Generate trap squash event.
generateTrapEvent(tid);
-// warn("%lli fault (%d) handled @ PC %08p", curTick, inst_fault->name(), head_inst->readPC());
return false;
}
@@ -1089,9 +1073,7 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
#if FULL_SYSTEM
if (thread[tid]->profile) {
-// bool usermode = TheISA::inUserMode(thread[tid]->getTC());
-// thread[tid]->profilePC = usermode ? 1 : head_inst->readPC();
- thread[tid]->profilePC = head_inst->readPC();
+ thread[tid]->profilePC = head_inst->instAddr();
ProfileNode *node = thread[tid]->profile->consume(thread[tid]->getTC(),
head_inst->staticInst);
@@ -1101,7 +1083,7 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
if (CPA::available()) {
if (head_inst->isControl()) {
ThreadContext *tc = thread[tid]->getTC();
- CPA::cpa()->swAutoBegin(tc, head_inst->readNextPC());
+ CPA::cpa()->swAutoBegin(tc, head_inst->nextInstAddr());
}
}
#endif
@@ -1154,8 +1136,8 @@ DefaultCommit<Impl>::getInsts()
commitStatus[tid] != TrapPending) {
changedROBNumEntries[tid] = true;
- DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ROB.\n",
- inst->readPC(), inst->seqNum, tid);
+ DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ROB.\n",
+ inst->pcState(), inst->seqNum, tid);
rob->insertInst(inst);
@@ -1163,9 +1145,9 @@ DefaultCommit<Impl>::getInsts()
youngestSeqNum[tid] = inst->seqNum;
} else {
- DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "
+ DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was "
"squashed, skipping.\n",
- inst->readPC(), inst->seqNum, tid);
+ inst->pcState(), inst->seqNum, tid);
}
}
}
@@ -1181,14 +1163,14 @@ DefaultCommit<Impl>::skidInsert()
DynInstPtr inst = fromRename->insts[inst_num];
if (!inst->isSquashed()) {
- DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ",
- "skidBuffer.\n", inst->readPC(), inst->seqNum,
+ DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ",
+ "skidBuffer.\n", inst->pcState(), inst->seqNum,
inst->threadNumber);
skidBuffer.push(inst);
} else {
- DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "
+ DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was "
"squashed, skipping.\n",
- inst->readPC(), inst->seqNum, inst->threadNumber);
+ inst->pcState(), inst->seqNum, inst->threadNumber);
}
}
}
@@ -1204,10 +1186,10 @@ DefaultCommit<Impl>::markCompletedInsts()
++inst_num)
{
if (!fromIEW->insts[inst_num]->isSquashed()) {
- DPRINTF(Commit, "[tid:%i]: Marking PC %#x, [sn:%lli] ready "
+ DPRINTF(Commit, "[tid:%i]: Marking PC %s, [sn:%lli] ready "
"within ROB.\n",
fromIEW->insts[inst_num]->threadNumber,
- fromIEW->insts[inst_num]->readPC(),
+ fromIEW->insts[inst_num]->pcState(),
fromIEW->insts[inst_num]->seqNum);
// Mark the instruction as ready to commit.
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc
index 8e9f3ef5d..21c5cc706 100644
--- a/src/cpu/o3/cpu.cc
+++ b/src/cpu/o3/cpu.cc
@@ -732,9 +732,7 @@ FullO3CPU<Impl>::insertThread(ThreadID tid)
//this->copyFromTC(tid);
//Set PC/NPC/NNPC
- setPC(src_tc->readPC(), tid);
- setNextPC(src_tc->readNextPC(), tid);
- setNextNPC(src_tc->readNextNPC(), tid);
+ pcState(src_tc->pcState(), tid);
src_tc->setStatus(ThreadContext::Active);
@@ -778,7 +776,7 @@ FullO3CPU<Impl>::removeThread(ThreadID tid)
// Squash Throughout Pipeline
InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum;
- fetch.squash(0, sizeof(TheISA::MachInst), 0, squash_seq_num, tid);
+ fetch.squash(0, squash_seq_num, tid);
decode.squash(tid);
rename.squash(squash_seq_num, tid);
iew.squash(tid);
@@ -1306,73 +1304,38 @@ FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid)
}
template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readPC(ThreadID tid)
+TheISA::PCState
+FullO3CPU<Impl>::pcState(ThreadID tid)
{
- return commit.readPC(tid);
+ return commit.pcState(tid);
}
template <class Impl>
void
-FullO3CPU<Impl>::setPC(Addr new_PC, ThreadID tid)
-{
- commit.setPC(new_PC, tid);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readMicroPC(ThreadID tid)
+FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid)
{
- return commit.readMicroPC(tid);
+ commit.pcState(val, tid);
}
template <class Impl>
-void
-FullO3CPU<Impl>::setMicroPC(Addr new_PC, ThreadID tid)
+Addr
+FullO3CPU<Impl>::instAddr(ThreadID tid)
{
- commit.setMicroPC(new_PC, tid);
+ return commit.instAddr(tid);
}
template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readNextPC(ThreadID tid)
+Addr
+FullO3CPU<Impl>::nextInstAddr(ThreadID tid)
{
- return commit.readNextPC(tid);
+ return commit.nextInstAddr(tid);
}
template <class Impl>
-void
-FullO3CPU<Impl>::setNextPC(uint64_t val, ThreadID tid)
-{
- commit.setNextPC(val, tid);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readNextNPC(ThreadID tid)
-{
- return commit.readNextNPC(tid);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setNextNPC(uint64_t val, ThreadID tid)
-{
- commit.setNextNPC(val, tid);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readNextMicroPC(ThreadID tid)
-{
- return commit.readNextMicroPC(tid);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setNextMicroPC(Addr new_PC, ThreadID tid)
+MicroPC
+FullO3CPU<Impl>::microPC(ThreadID tid)
{
- commit.setNextMicroPC(new_PC, tid);
+ return commit.microPC(tid);
}
template <class Impl>
@@ -1419,9 +1382,9 @@ template <class Impl>
void
FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
{
- DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x "
+ DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s "
"[sn:%lli]\n",
- inst->threadNumber, inst->readPC(), inst->seqNum);
+ inst->threadNumber, inst->pcState(), inst->seqNum);
removeInstsThisCycle = true;
@@ -1509,10 +1472,10 @@ FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid)
{
if ((*instIt)->threadNumber == tid) {
DPRINTF(O3CPU, "Squashing instruction, "
- "[tid:%i] [sn:%lli] PC %#x\n",
+ "[tid:%i] [sn:%lli] PC %s\n",
(*instIt)->threadNumber,
(*instIt)->seqNum,
- (*instIt)->readPC());
+ (*instIt)->pcState());
// Mark it as squashed.
(*instIt)->setSquashed();
@@ -1530,10 +1493,10 @@ FullO3CPU<Impl>::cleanUpRemovedInsts()
{
while (!removeList.empty()) {
DPRINTF(O3CPU, "Removing instruction, "
- "[tid:%i] [sn:%lli] PC %#x\n",
+ "[tid:%i] [sn:%lli] PC %s\n",
(*removeList.front())->threadNumber,
(*removeList.front())->seqNum,
- (*removeList.front())->readPC());
+ (*removeList.front())->pcState());
instList.erase(removeList.front());
@@ -1563,7 +1526,7 @@ FullO3CPU<Impl>::dumpInsts()
while (inst_list_it != instList.end()) {
cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
"Squashed:%i\n\n",
- num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
+ num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber,
(*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
(*inst_list_it)->isSquashed());
inst_list_it++;
diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh
index 57c07a9ec..2669016ff 100644
--- a/src/cpu/o3/cpu.hh
+++ b/src/cpu/o3/cpu.hh
@@ -444,35 +444,20 @@ class FullO3CPU : public BaseO3CPU
void setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid);
- /** Reads the commit PC of a specific thread. */
- Addr readPC(ThreadID tid);
+ /** Sets the commit PC state of a specific thread. */
+ void pcState(const TheISA::PCState &newPCState, ThreadID tid);
- /** Sets the commit PC of a specific thread. */
- void setPC(Addr new_PC, ThreadID tid);
+ /** Reads the commit PC state of a specific thread. */
+ TheISA::PCState pcState(ThreadID tid);
- /** Reads the commit micro PC of a specific thread. */
- Addr readMicroPC(ThreadID tid);
+ /** Reads the commit PC of a specific thread. */
+ Addr instAddr(ThreadID tid);
- /** Sets the commmit micro PC of a specific thread. */
- void setMicroPC(Addr new_microPC, ThreadID tid);
+ /** Reads the commit micro PC of a specific thread. */
+ MicroPC microPC(ThreadID tid);
/** Reads the next PC of a specific thread. */
- Addr readNextPC(ThreadID tid);
-
- /** Sets the next PC of a specific thread. */
- void setNextPC(Addr val, ThreadID tid);
-
- /** Reads the next NPC of a specific thread. */
- Addr readNextNPC(ThreadID tid);
-
- /** Sets the next NPC of a specific thread. */
- void setNextNPC(Addr val, ThreadID tid);
-
- /** Reads the commit next micro PC of a specific thread. */
- Addr readNextMicroPC(ThreadID tid);
-
- /** Sets the commit next micro PC of a specific thread. */
- void setNextMicroPC(Addr val, ThreadID tid);
+ Addr nextInstAddr(ThreadID tid);
/** Initiates a squash of all in-flight instructions for a given
* thread. The source of the squash is an external update of
diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh
index 1b76de132..5063e0f07 100644
--- a/src/cpu/o3/decode_impl.hh
+++ b/src/cpu/o3/decode_impl.hh
@@ -264,29 +264,16 @@ template<class Impl>
void
DefaultDecode<Impl>::squash(DynInstPtr &inst, ThreadID tid)
{
- DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch prediction "
- "detected at decode.\n", tid, inst->seqNum);
+ DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch "
+ "prediction detected at decode.\n", tid, inst->seqNum);
// Send back mispredict information.
toFetch->decodeInfo[tid].branchMispredict = true;
toFetch->decodeInfo[tid].predIncorrect = true;
toFetch->decodeInfo[tid].squash = true;
toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
- toFetch->decodeInfo[tid].nextMicroPC = inst->readMicroPC();
-
-#if ISA_HAS_DELAY_SLOT
- toFetch->decodeInfo[tid].nextPC = inst->readPC() + sizeof(TheISA::MachInst);
- toFetch->decodeInfo[tid].nextNPC = inst->branchTarget();
- toFetch->decodeInfo[tid].branchTaken = inst->readNextNPC() !=
- (inst->readNextPC() + sizeof(TheISA::MachInst));
-#else
toFetch->decodeInfo[tid].nextPC = inst->branchTarget();
- toFetch->decodeInfo[tid].nextNPC =
- inst->branchTarget() + sizeof(TheISA::MachInst);
- toFetch->decodeInfo[tid].branchTaken =
- inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst));
-#endif
-
+ toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching();
InstSeqNum squash_seq_num = inst->seqNum;
@@ -382,8 +369,8 @@ DefaultDecode<Impl>::skidInsert(ThreadID tid)
assert(tid == inst->threadNumber);
- DPRINTF(Decode,"Inserting [sn:%lli] PC:%#x into decode skidBuffer %i\n",
- inst->seqNum, inst->readPC(), inst->threadNumber);
+ DPRINTF(Decode,"Inserting [sn:%lli] PC: %s into decode skidBuffer %i\n",
+ inst->seqNum, inst->pcState(), inst->threadNumber);
skidBuffer[tid].push(inst);
}
@@ -681,13 +668,12 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid)
insts_to_decode.pop();
DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with "
- "PC %#x\n",
- tid, inst->seqNum, inst->readPC());
+ "PC %s\n", tid, inst->seqNum, inst->pcState());
if (inst->isSquashed()) {
- DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %#x is "
+ DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %s is "
"squashed, skipping.\n",
- tid, inst->seqNum, inst->readPC());
+ tid, inst->seqNum, inst->pcState());
++decodeSquashedInsts;
@@ -717,9 +703,6 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid)
// Ensure that if it was predicted as a branch, it really is a
// branch.
if (inst->readPredTaken() && !inst->isControl()) {
- DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n",
- inst->readPredPC(), inst->readNextPC() + 4);
-
panic("Instruction predicted as a branch!");
++decodeControlMispred;
@@ -735,26 +718,18 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid)
if (inst->isDirectCtrl() && inst->isUncondCtrl()) {
++decodeBranchResolved;
- if (inst->branchTarget() != inst->readPredPC()) {
+ if (!(inst->branchTarget() == inst->readPredTarg())) {
++decodeBranchMispred;
// Might want to set some sort of boolean and just do
// a check at the end
squash(inst, inst->threadNumber);
- Addr target = inst->branchTarget();
+ TheISA::PCState target = inst->branchTarget();
-#if ISA_HAS_DELAY_SLOT
- DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %#x PredNextPC: %#x\n",
- inst->seqNum, inst->readPC() + sizeof(TheISA::MachInst), target);
-
- //The micro pc after an instruction level branch should be 0
- inst->setPredTarg(inst->readPC() + sizeof(TheISA::MachInst), target, 0);
-#else
- DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %#x PredNextPC: %#x\n",
- inst->seqNum, target, target + sizeof(TheISA::MachInst));
+ DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %s\n",
+ inst->seqNum, target);
//The micro pc after an instruction level branch should be 0
- inst->setPredTarg(target, target + sizeof(TheISA::MachInst), 0);
-#endif
+ inst->setPredTarg(target);
break;
}
}
diff --git a/src/cpu/o3/dep_graph.hh b/src/cpu/o3/dep_graph.hh
index c19fd0abf..804b3f9cd 100644
--- a/src/cpu/o3/dep_graph.hh
+++ b/src/cpu/o3/dep_graph.hh
@@ -251,8 +251,8 @@ DependencyGraph<DynInstPtr>::dump()
curr = &dependGraph[i];
if (curr->inst) {
- cprintf("dependGraph[%i]: producer: %#x [sn:%lli] consumer: ",
- i, curr->inst->readPC(), curr->inst->seqNum);
+ cprintf("dependGraph[%i]: producer: %s [sn:%lli] consumer: ",
+ i, curr->inst->pcState(), curr->inst->seqNum);
} else {
cprintf("dependGraph[%i]: No producer. consumer: ", i);
}
@@ -260,8 +260,8 @@ DependencyGraph<DynInstPtr>::dump()
while (curr->next != NULL) {
curr = curr->next;
- cprintf("%#x [sn:%lli] ",
- curr->inst->readPC(), curr->inst->seqNum);
+ cprintf("%s [sn:%lli] ",
+ curr->inst->pcState(), curr->inst->seqNum);
}
cprintf("\n");
diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh
index e1279f82b..6bd1f9fad 100644
--- a/src/cpu/o3/dyn_inst.hh
+++ b/src/cpu/o3/dyn_inst.hh
@@ -74,14 +74,14 @@ class BaseO3DynInst : public BaseDynInst<Impl>
public:
/** BaseDynInst constructor given a binary instruction. */
- BaseO3DynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC,
- Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
- InstSeqNum seq_num, O3CPU *cpu);
+ BaseO3DynInst(StaticInstPtr staticInst,
+ TheISA::PCState pc, TheISA::PCState predPC,
+ InstSeqNum seq_num, O3CPU *cpu);
/** BaseDynInst constructor given a binary instruction. */
- BaseO3DynInst(ExtMachInst inst, Addr PC, Addr NPC, Addr microPC,
- Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
- InstSeqNum seq_num, O3CPU *cpu);
+ BaseO3DynInst(ExtMachInst inst,
+ TheISA::PCState pc, TheISA::PCState predPC,
+ InstSeqNum seq_num, O3CPU *cpu);
/** BaseDynInst constructor given a static inst pointer. */
BaseO3DynInst(StaticInstPtr &_staticInst);
diff --git a/src/cpu/o3/dyn_inst_impl.hh b/src/cpu/o3/dyn_inst_impl.hh
index 3e015d962..6f7c23b2f 100644
--- a/src/cpu/o3/dyn_inst_impl.hh
+++ b/src/cpu/o3/dyn_inst_impl.hh
@@ -33,24 +33,18 @@
template <class Impl>
BaseO3DynInst<Impl>::BaseO3DynInst(StaticInstPtr staticInst,
- Addr PC, Addr NPC, Addr microPC,
- Addr Pred_PC, Addr Pred_NPC,
- Addr Pred_MicroPC,
+ TheISA::PCState pc, TheISA::PCState predPC,
InstSeqNum seq_num, O3CPU *cpu)
- : BaseDynInst<Impl>(staticInst, PC, NPC, microPC,
- Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu)
+ : BaseDynInst<Impl>(staticInst, pc, predPC, seq_num, cpu)
{
initVars();
}
template <class Impl>
BaseO3DynInst<Impl>::BaseO3DynInst(ExtMachInst inst,
- Addr PC, Addr NPC, Addr microPC,
- Addr Pred_PC, Addr Pred_NPC,
- Addr Pred_MicroPC,
+ TheISA::PCState pc, TheISA::PCState predPC,
InstSeqNum seq_num, O3CPU *cpu)
- : BaseDynInst<Impl>(inst, PC, NPC, microPC,
- Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu)
+ : BaseDynInst<Impl>(inst, pc, predPC, seq_num, cpu)
{
initVars();
}
@@ -131,15 +125,17 @@ BaseO3DynInst<Impl>::hwrei()
{
#if THE_ISA == ALPHA_ISA
// Can only do a hwrei when in pal mode.
- if (!(this->readPC() & 0x3))
+ if (!(this->instAddr() & 0x3))
return new AlphaISA::UnimplementedOpcodeFault;
// Set the next PC based on the value of the EXC_ADDR IPR.
- this->setNextPC(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR,
- this->threadNumber));
+ AlphaISA::PCState pc = this->pcState();
+ pc.npc(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR,
+ this->threadNumber));
+ this->pcState(pc);
if (CPA::available()) {
ThreadContext *tc = this->cpu->tcBase(this->threadNumber);
- CPA::cpa()->swAutoBegin(tc, this->readNextPC());
+ CPA::cpa()->swAutoBegin(tc, this->nextInstAddr());
}
// Tell CPU to clear any state it needs to if a hwrei is taken.
@@ -175,11 +171,11 @@ BaseO3DynInst<Impl>::syscall(int64_t callnum)
// HACK: check CPU's nextPC before and after syscall. If it
// changes, update this instruction's nextPC because the syscall
// must have changed the nextPC.
- Addr cpu_next_pc = this->cpu->readNextPC(this->threadNumber);
+ TheISA::PCState curPC = this->cpu->pcState(this->threadNumber);
this->cpu->syscall(callnum, this->threadNumber);
- Addr new_next_pc = this->cpu->readNextPC(this->threadNumber);
- if (cpu_next_pc != new_next_pc) {
- this->setNextPC(new_next_pc);
+ TheISA::PCState newPC = this->cpu->pcState(this->threadNumber);
+ if (!(curPC == newPC)) {
+ this->pcState(newPC);
}
}
#endif
diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh
index d881c291f..22e9e51b4 100644
--- a/src/cpu/o3/fetch.hh
+++ b/src/cpu/o3/fetch.hh
@@ -229,7 +229,7 @@ class DefaultFetch
* @param next_NPC Used for ISAs which use delay slots.
* @return Whether or not a branch was predicted as taken.
*/
- bool lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, Addr &next_NPC, Addr &next_MicroPC);
+ bool lookupAndUpdateNextPC(DynInstPtr &inst, TheISA::PCState &pc);
/**
* Fetches the cache line that contains fetch_PC. Returns any
@@ -244,14 +244,12 @@ class DefaultFetch
bool fetchCacheLine(Addr fetch_PC, Fault &ret_fault, ThreadID tid);
/** Squashes a specific thread and resets the PC. */
- inline void doSquash(const Addr &new_PC, const Addr &new_NPC,
- const Addr &new_MicroPC, ThreadID tid);
+ inline void doSquash(const TheISA::PCState &newPC, ThreadID tid);
/** Squashes a specific thread and resets the PC. Also tells the CPU to
* remove any instructions between fetch and decode that should be sqaushed.
*/
- void squashFromDecode(const Addr &new_PC, const Addr &new_NPC,
- const Addr &new_MicroPC,
+ void squashFromDecode(const TheISA::PCState &newPC,
const InstSeqNum &seq_num, ThreadID tid);
/** Checks if a thread is stalled. */
@@ -266,8 +264,7 @@ class DefaultFetch
* remove any instructions that are not in the ROB. The source of this
* squash should be the commit stage.
*/
- void squash(const Addr &new_PC, const Addr &new_NPC,
- const Addr &new_MicroPC,
+ void squash(const TheISA::PCState &newPC,
const InstSeqNum &seq_num, ThreadID tid);
/** Ticks the fetch stage, processing all inputs signals and fetching
@@ -348,14 +345,7 @@ class DefaultFetch
/** Predecoder. */
TheISA::Predecoder predecoder;
- /** Per-thread fetch PC. */
- Addr PC[Impl::MaxThreads];
-
- /** Per-thread fetch micro PC. */
- Addr microPC[Impl::MaxThreads];
-
- /** Per-thread next PC. */
- Addr nextPC[Impl::MaxThreads];
+ TheISA::PCState pc[Impl::MaxThreads];
/** Memory request used to access cache. */
RequestPtr memReq[Impl::MaxThreads];
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index 3f8f84cab..bbd9ce4a2 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -316,9 +316,7 @@ DefaultFetch<Impl>::initStage()
{
// Setup PC and nextPC with initial state.
for (ThreadID tid = 0; tid < numThreads; tid++) {
- PC[tid] = cpu->readPC(tid);
- nextPC[tid] = cpu->readNextPC(tid);
- microPC[tid] = cpu->readMicroPC(tid);
+ pc[tid] = cpu->pcState(tid);
}
for (ThreadID tid = 0; tid < numThreads; tid++) {
@@ -445,9 +443,7 @@ DefaultFetch<Impl>::takeOverFrom()
stalls[i].rename = 0;
stalls[i].iew = 0;
stalls[i].commit = 0;
- PC[i] = cpu->readPC(i);
- nextPC[i] = cpu->readNextPC(i);
- microPC[i] = cpu->readMicroPC(i);
+ pc[i] = cpu->pcState(i);
fetchStatus[i] = Running;
}
numInst = 0;
@@ -496,8 +492,8 @@ DefaultFetch<Impl>::switchToInactive()
template <class Impl>
bool
-DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC,
- Addr &next_NPC, Addr &next_MicroPC)
+DefaultFetch<Impl>::lookupAndUpdateNextPC(
+ DynInstPtr &inst, TheISA::PCState &nextPC)
{
// Do branch prediction check here.
// A bit of a misnomer...next_PC is actually the current PC until
@@ -505,51 +501,26 @@ DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC,
bool predict_taken;
if (!inst->isControl()) {
- if (inst->isMicroop() && !inst->isLastMicroop()) {
- next_MicroPC++;
- } else {
- next_PC = next_NPC;
- next_NPC = next_NPC + instSize;
- next_MicroPC = 0;
- }
- inst->setPredTarg(next_PC, next_NPC, next_MicroPC);
+ TheISA::advancePC(nextPC, inst->staticInst);
+ inst->setPredTarg(nextPC);
inst->setPredTaken(false);
return false;
}
- //Assume for now that all control flow is to a different macroop which
- //would reset the micro pc to 0.
- next_MicroPC = 0;
-
ThreadID tid = inst->threadNumber;
- Addr pred_PC = next_PC;
- predict_taken = branchPred.predict(inst, pred_PC, tid);
+ predict_taken = branchPred.predict(inst, nextPC, tid);
if (predict_taken) {
- DPRINTF(Fetch, "[tid:%i]: [sn:%i]: Branch predicted to be taken to %#x.\n",
- tid, inst->seqNum, pred_PC);
+ DPRINTF(Fetch, "[tid:%i]: [sn:%i]: Branch predicted to be taken to %s.\n",
+ tid, inst->seqNum, nextPC);
} else {
DPRINTF(Fetch, "[tid:%i]: [sn:%i]:Branch predicted to be not taken.\n",
tid, inst->seqNum);
}
-#if ISA_HAS_DELAY_SLOT
- next_PC = next_NPC;
- if (predict_taken)
- next_NPC = pred_PC;
- else
- next_NPC += instSize;
-#else
- if (predict_taken)
- next_PC = pred_PC;
- else
- next_PC += instSize;
- next_NPC = next_PC + instSize;
-#endif
-
- DPRINTF(Fetch, "[tid:%i]: [sn:%i] Branch predicted to go to %#x and then %#x.\n",
- tid, inst->seqNum, next_PC, next_NPC);
- inst->setPredTarg(next_PC, next_NPC, next_MicroPC);
+ DPRINTF(Fetch, "[tid:%i]: [sn:%i] Branch predicted to go to %s.\n",
+ tid, inst->seqNum, nextPC);
+ inst->setPredTarg(nextPC);
inst->setPredTaken(predict_taken);
++fetchedBranches;
@@ -668,15 +639,12 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, ThreadID tid
template <class Impl>
inline void
-DefaultFetch<Impl>::doSquash(const Addr &new_PC,
- const Addr &new_NPC, const Addr &new_microPC, ThreadID tid)
+DefaultFetch<Impl>::doSquash(const TheISA::PCState &newPC, ThreadID tid)
{
- DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %#x, NPC to: %#x.\n",
- tid, new_PC, new_NPC);
+ DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %s.\n",
+ tid, newPC);
- PC[tid] = new_PC;
- nextPC[tid] = new_NPC;
- microPC[tid] = new_microPC;
+ pc[tid] = newPC;
// Clear the icache miss if it's outstanding.
if (fetchStatus[tid] == IcacheWaitResponse) {
@@ -703,13 +671,12 @@ DefaultFetch<Impl>::doSquash(const Addr &new_PC,
template<class Impl>
void
-DefaultFetch<Impl>::squashFromDecode(const Addr &new_PC, const Addr &new_NPC,
- const Addr &new_MicroPC,
+DefaultFetch<Impl>::squashFromDecode(const TheISA::PCState &newPC,
const InstSeqNum &seq_num, ThreadID tid)
{
- DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n",tid);
+ DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n", tid);
- doSquash(new_PC, new_NPC, new_MicroPC, tid);
+ doSquash(newPC, tid);
// Tell the CPU to remove any instructions that are in flight between
// fetch and decode.
@@ -784,13 +751,12 @@ DefaultFetch<Impl>::updateFetchStatus()
template <class Impl>
void
-DefaultFetch<Impl>::squash(const Addr &new_PC, const Addr &new_NPC,
- const Addr &new_MicroPC,
+DefaultFetch<Impl>::squash(const TheISA::PCState &newPC,
const InstSeqNum &seq_num, ThreadID tid)
{
- DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n",tid);
+ DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n", tid);
- doSquash(new_PC, new_NPC, new_MicroPC, tid);
+ doSquash(newPC, tid);
// Tell the CPU to remove any instructions that are not in the ROB.
cpu->removeInstsNotInROB(tid);
@@ -903,16 +869,14 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(ThreadID tid)
DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash "
"from commit.\n",tid);
// In any case, squash.
- squash(fromCommit->commitInfo[tid].nextPC,
- fromCommit->commitInfo[tid].nextNPC,
- fromCommit->commitInfo[tid].nextMicroPC,
+ squash(fromCommit->commitInfo[tid].pc,
fromCommit->commitInfo[tid].doneSeqNum,
tid);
// Also check if there's a mispredict that happened.
if (fromCommit->commitInfo[tid].branchMispredict) {
branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum,
- fromCommit->commitInfo[tid].nextPC,
+ fromCommit->commitInfo[tid].pc,
fromCommit->commitInfo[tid].branchTaken,
tid);
} else {
@@ -955,13 +919,10 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(ThreadID tid)
if (fetchStatus[tid] != Squashing) {
- DPRINTF(Fetch, "Squashing from decode with PC = %#x, NPC = %#x\n",
- fromDecode->decodeInfo[tid].nextPC,
- fromDecode->decodeInfo[tid].nextNPC);
+ TheISA::PCState nextPC = fromDecode->decodeInfo[tid].nextPC;
+ DPRINTF(Fetch, "Squashing from decode with PC = %s\n", nextPC);
// Squash unless we're already squashing
squashFromDecode(fromDecode->decodeInfo[tid].nextPC,
- fromDecode->decodeInfo[tid].nextNPC,
- fromDecode->decodeInfo[tid].nextMicroPC,
fromDecode->decodeInfo[tid].doneSeqNum,
tid);
@@ -1016,9 +977,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
DPRINTF(Fetch, "Attempting to fetch from [tid:%i]\n", tid);
// The current PC.
- Addr fetch_PC = PC[tid];
- Addr fetch_NPC = nextPC[tid];
- Addr fetch_MicroPC = microPC[tid];
+ TheISA::PCState fetchPC = pc[tid];
// Fault code for memory access.
Fault fault = NoFault;
@@ -1034,10 +993,9 @@ DefaultFetch<Impl>::fetch(bool &status_change)
status_change = true;
} else if (fetchStatus[tid] == Running) {
DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read "
- "instruction, starting at PC %08p.\n",
- tid, fetch_PC);
+ "instruction, starting at PC %s.\n", tid, fetchPC);
- bool fetch_success = fetchCacheLine(fetch_PC, fault, tid);
+ bool fetch_success = fetchCacheLine(fetchPC.instAddr(), fault, tid);
if (!fetch_success) {
if (cacheBlocked) {
++icacheStallCycles;
@@ -1075,20 +1033,21 @@ DefaultFetch<Impl>::fetch(bool &status_change)
return;
}
- Addr next_PC = fetch_PC;
- Addr next_NPC = fetch_NPC;
- Addr next_MicroPC = fetch_MicroPC;
+ TheISA::PCState nextPC = fetchPC;
InstSeqNum inst_seq;
MachInst inst;
ExtMachInst ext_inst;
- // @todo: Fix this hack.
- unsigned offset = (fetch_PC & cacheBlkMask) & ~3;
StaticInstPtr staticInst = NULL;
StaticInstPtr macroop = NULL;
if (fault == NoFault) {
+ //XXX Masking out pal mode bit. This will break x86. Alpha needs
+ //to pull the pal mode bit ouf ot the instruction address.
+ unsigned offset = (fetchPC.instAddr() & ~1) - cacheDataPC[tid];
+ assert(offset < cacheBlkSize);
+
// If the read of the first instruction was successful, then grab the
// instructions from the rest of the cache line and put them into the
// queue heading to decode.
@@ -1104,15 +1063,6 @@ DefaultFetch<Impl>::fetch(bool &status_change)
numInst < fetchWidth &&
!predicted_branch) {
- // If we're branching after this instruction, quite fetching
- // from the same block then.
- predicted_branch =
- (fetch_PC + sizeof(TheISA::MachInst) != fetch_NPC);
- if (predicted_branch) {
- DPRINTF(Fetch, "Branch detected with PC = %#x, NPC = %#x\n",
- fetch_PC, fetch_NPC);
- }
-
// Make sure this is a valid index.
assert(offset <= cacheBlkSize - instSize);
@@ -1122,16 +1072,16 @@ DefaultFetch<Impl>::fetch(bool &status_change)
(&cacheData[tid][offset]));
predecoder.setTC(cpu->thread[tid]->getTC());
- predecoder.moreBytes(fetch_PC, fetch_PC, inst);
+ predecoder.moreBytes(fetchPC, fetchPC.instAddr(), inst);
- ext_inst = predecoder.getExtMachInst();
- staticInst = StaticInstPtr(ext_inst, fetch_PC);
+ ext_inst = predecoder.getExtMachInst(fetchPC);
+ staticInst = StaticInstPtr(ext_inst, fetchPC.instAddr());
if (staticInst->isMacroop())
macroop = staticInst;
}
do {
if (macroop) {
- staticInst = macroop->fetchMicroop(fetch_MicroPC);
+ staticInst = macroop->fetchMicroop(fetchPC.microPC());
if (staticInst->isLastMicroop())
macroop = NULL;
}
@@ -1141,8 +1091,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
// Create a new DynInst from the instruction fetched.
DynInstPtr instruction = new DynInst(staticInst,
- fetch_PC, fetch_NPC, fetch_MicroPC,
- next_PC, next_NPC, next_MicroPC,
+ fetchPC, nextPC,
inst_seq, cpu);
instruction->setTid(tid);
@@ -1150,27 +1099,32 @@ DefaultFetch<Impl>::fetch(bool &status_change)
instruction->setThreadState(cpu->thread[tid]);
- DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x (%d) created "
- "[sn:%lli]\n", tid, instruction->readPC(),
- instruction->readMicroPC(), inst_seq);
+ DPRINTF(Fetch, "[tid:%i]: Instruction PC %s (%d) created "
+ "[sn:%lli]\n", tid, instruction->pcState(),
+ instruction->microPC(), inst_seq);
//DPRINTF(Fetch, "[tid:%i]: MachInst is %#x\n", tid, ext_inst);
- DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n",
- tid, instruction->staticInst->disassemble(fetch_PC));
+ DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", tid,
+ instruction->staticInst->
+ disassemble(fetchPC.instAddr()));
#if TRACING_ON
instruction->traceData =
cpu->getTracer()->getInstRecord(curTick, cpu->tcBase(tid),
- instruction->staticInst, instruction->readPC(),
- macroop, instruction->readMicroPC());
+ instruction->staticInst, fetchPC, macroop);
#else
instruction->traceData = NULL;
#endif
- ///FIXME This needs to be more robust in dealing with delay slots
+ // If we're branching after this instruction, quite fetching
+ // from the same block then.
+ predicted_branch = fetchPC.branching();
predicted_branch |=
- lookupAndUpdateNextPC(instruction, next_PC, next_NPC, next_MicroPC);
+ lookupAndUpdateNextPC(instruction, nextPC);
+ if (predicted_branch) {
+ DPRINTF(Fetch, "Branch detected with PC = %s\n", fetchPC);
+ }
// Add instruction to the CPU's list of instructions.
instruction->setInstListIt(cpu->addInst(instruction));
@@ -1185,9 +1139,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
++fetchedInsts;
// Move to the next instruction, unless we have a branch.
- fetch_PC = next_PC;
- fetch_NPC = next_NPC;
- fetch_MicroPC = next_MicroPC;
+ fetchPC = nextPC;
if (instruction->isQuiesce()) {
DPRINTF(Fetch, "Quiesce instruction encountered, halting fetch!",
@@ -1202,7 +1154,8 @@ DefaultFetch<Impl>::fetch(bool &status_change)
} while (staticInst->isMicroop() &&
!staticInst->isLastMicroop() &&
numInst < fetchWidth);
- offset += instSize;
+ //XXX Masking out pal mode bit.
+ offset = (fetchPC.instAddr() & ~1) - cacheDataPC[tid];
}
if (predicted_branch) {
@@ -1224,10 +1177,8 @@ DefaultFetch<Impl>::fetch(bool &status_change)
// Now that fetching is completed, update the PC to signify what the next
// cycle will be.
if (fault == NoFault) {
- PC[tid] = next_PC;
- nextPC[tid] = next_NPC;
- microPC[tid] = next_MicroPC;
- DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n", tid, next_PC);
+ pc[tid] = nextPC;
+ DPRINTF(Fetch, "[tid:%i]: Setting PC to %s.\n", tid, nextPC);
} else {
// We shouldn't be in an icache miss and also have a fault (an ITB
// miss)
@@ -1245,11 +1196,10 @@ DefaultFetch<Impl>::fetch(bool &status_change)
ext_inst = TheISA::NoopMachInst;
// Create a new DynInst from the dummy nop.
- DynInstPtr instruction = new DynInst(ext_inst,
- fetch_PC, fetch_NPC, fetch_MicroPC,
- next_PC, next_NPC, next_MicroPC,
+ DynInstPtr instruction = new DynInst(ext_inst, fetchPC, nextPC,
inst_seq, cpu);
- instruction->setPredTarg(next_NPC, next_NPC + instSize, 0);
+ TheISA::advancePC(nextPC, instruction->staticInst);
+ instruction->setPredTarg(nextPC);
instruction->setTid(tid);
instruction->setASID(tid);
@@ -1272,8 +1222,8 @@ DefaultFetch<Impl>::fetch(bool &status_change)
fetchStatus[tid] = TrapPending;
status_change = true;
- DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %08p",
- tid, fault->name(), PC[tid]);
+ DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %s",
+ tid, fault->name(), pc[tid]);
}
}
diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh
index 2089913ef..608e70cde 100644
--- a/src/cpu/o3/iew_impl.hh
+++ b/src/cpu/o3/iew_impl.hh
@@ -449,27 +449,18 @@ template<class Impl>
void
DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, ThreadID tid)
{
- DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %#x "
- "[sn:%i].\n", tid, inst->readPC(), inst->seqNum);
+ DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %s "
+ "[sn:%i].\n", tid, inst->pcState(), inst->seqNum);
toCommit->squash[tid] = true;
toCommit->squashedSeqNum[tid] = inst->seqNum;
- toCommit->mispredPC[tid] = inst->readPC();
+ toCommit->mispredPC[tid] = inst->instAddr();
toCommit->branchMispredict[tid] = true;
-#if ISA_HAS_DELAY_SLOT
- int instSize = sizeof(TheISA::MachInst);
- toCommit->branchTaken[tid] =
- !(inst->readNextPC() + instSize == inst->readNextNPC() &&
- (inst->readNextPC() == inst->readPC() + instSize ||
- inst->readNextPC() == inst->readPC() + 2 * instSize));
-#else
- toCommit->branchTaken[tid] = inst->readNextPC() !=
- (inst->readPC() + sizeof(TheISA::MachInst));
-#endif
- toCommit->nextPC[tid] = inst->readNextPC();
- toCommit->nextNPC[tid] = inst->readNextNPC();
- toCommit->nextMicroPC[tid] = inst->readNextMicroPC();
+ toCommit->branchTaken[tid] = inst->pcState().branching();
+ TheISA::PCState pc = inst->pcState();
+ TheISA::advancePC(pc, inst->staticInst);
+ toCommit->pc[tid] = pc;
toCommit->includeSquashInst[tid] = false;
@@ -481,12 +472,13 @@ void
DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, ThreadID tid)
{
DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, "
- "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
+ "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum);
toCommit->squash[tid] = true;
toCommit->squashedSeqNum[tid] = inst->seqNum;
- toCommit->nextPC[tid] = inst->readNextPC();
- toCommit->nextNPC[tid] = inst->readNextNPC();
+ TheISA::PCState pc = inst->pcState();
+ TheISA::advancePC(pc, inst->staticInst);
+ toCommit->pc[tid] = pc;
toCommit->branchMispredict[tid] = false;
toCommit->includeSquashInst[tid] = false;
@@ -499,12 +491,11 @@ void
DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, ThreadID tid)
{
DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, "
- "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
+ "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum);
toCommit->squash[tid] = true;
toCommit->squashedSeqNum[tid] = inst->seqNum;
- toCommit->nextPC[tid] = inst->readPC();
- toCommit->nextNPC[tid] = inst->readNextPC();
+ toCommit->pc[tid] = inst->pcState();
toCommit->branchMispredict[tid] = false;
// Must include the broadcasted SN in the squash.
@@ -628,9 +619,9 @@ DefaultIEW<Impl>::skidInsert(ThreadID tid)
insts[tid].pop();
- DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%#x into "
+ DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%s into "
"dispatch skidBuffer %i\n",tid, inst->seqNum,
- inst->readPC(),tid);
+ inst->pcState(),tid);
skidBuffer[tid].push(inst);
}
@@ -986,9 +977,9 @@ DefaultIEW<Impl>::dispatchInsts(ThreadID tid)
// Make sure there's a valid instruction there.
assert(inst);
- DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %#x [sn:%lli] [tid:%i] to "
+ DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %s [sn:%lli] [tid:%i] to "
"IQ.\n",
- tid, inst->readPC(), inst->seqNum, inst->threadNumber);
+ tid, inst->pcState(), inst->seqNum, inst->threadNumber);
// Be sure to mark these instructions as ready so that the
// commit stage can go ahead and execute them, and mark
@@ -1165,7 +1156,7 @@ DefaultIEW<Impl>::printAvailableInsts()
if (inst%3==0) std::cout << "\n\t";
- std::cout << "PC: " << fromIssue->insts[inst]->readPC()
+ std::cout << "PC: " << fromIssue->insts[inst]->pcState()
<< " TN: " << fromIssue->insts[inst]->threadNumber
<< " SN: " << fromIssue->insts[inst]->seqNum << " | ";
@@ -1205,8 +1196,8 @@ DefaultIEW<Impl>::executeInsts()
DynInstPtr inst = instQueue.getInstToExecute();
- DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n",
- inst->readPC(), inst->threadNumber,inst->seqNum);
+ DPRINTF(IEW, "Execute: Processing PC %s, [tid:%i] [sn:%i].\n",
+ inst->pcState(), inst->threadNumber,inst->seqNum);
// Check if the instruction is squashed; if so then skip it
if (inst->isSquashed()) {
@@ -1298,10 +1289,9 @@ DefaultIEW<Impl>::executeInsts()
DPRINTF(IEW, "Execute: Branch mispredict detected.\n");
DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n",
- inst->readPredPC(), inst->readPredNPC());
- DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x,"
- " NPC: %#x.\n", inst->readNextPC(),
- inst->readNextNPC());
+ inst->predInstAddr(), inst->predNextInstAddr());
+ DPRINTF(IEW, "Execute: Redirecting fetch to PC: %s.\n",
+ inst->pcState(), inst->nextInstAddr());
// If incorrect, then signal the ROB that it must be squashed.
squashDueToBranch(inst, tid);
@@ -1318,16 +1308,11 @@ DefaultIEW<Impl>::executeInsts()
DynInstPtr violator;
violator = ldstQueue.getMemDepViolator(tid);
- DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %#x "
- "[sn:%lli], inst PC: %#x [sn:%lli]. Addr is: %#x.\n",
- violator->readPC(), violator->seqNum,
- inst->readPC(), inst->seqNum, inst->physEffAddr);
- // Ensure the violating instruction is older than
- // current squash
-/* if (fetchRedirect[tid] &&
- violator->seqNum >= toCommit->squashedSeqNum[tid] + 1)
- continue;
-*/
+ DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %s "
+ "[sn:%lli], inst PC: %s [sn:%lli]. Addr is: %#x.\n",
+ violator->pcState(), violator->seqNum,
+ inst->pcState(), inst->seqNum, inst->physEffAddr);
+
fetchRedirect[tid] = true;
// Tell the instruction queue that a violation has occured.
@@ -1342,8 +1327,8 @@ DefaultIEW<Impl>::executeInsts()
fetchRedirect[tid] = true;
DPRINTF(IEW, "Load operation couldn't execute because the "
- "memory system is blocked. PC: %#x [sn:%lli]\n",
- inst->readPC(), inst->seqNum);
+ "memory system is blocked. PC: %s [sn:%lli]\n",
+ inst->pcState(), inst->seqNum);
squashDueToMemBlocked(inst, tid);
}
@@ -1356,8 +1341,9 @@ DefaultIEW<Impl>::executeInsts()
DynInstPtr violator = ldstQueue.getMemDepViolator(tid);
DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: "
- "%#x, inst PC: %#x. Addr is: %#x.\n",
- violator->readPC(), inst->readPC(), inst->physEffAddr);
+ "%s, inst PC: %s. Addr is: %#x.\n",
+ violator->pcState(), inst->pcState(),
+ inst->physEffAddr);
DPRINTF(IEW, "Violation will not be handled because "
"already squashing\n");
@@ -1366,8 +1352,8 @@ DefaultIEW<Impl>::executeInsts()
if (ldstQueue.loadBlocked(tid) &&
!ldstQueue.isLoadBlockedHandled(tid)) {
DPRINTF(IEW, "Load operation couldn't execute because the "
- "memory system is blocked. PC: %#x [sn:%lli]\n",
- inst->readPC(), inst->seqNum);
+ "memory system is blocked. PC: %s [sn:%lli]\n",
+ inst->pcState(), inst->seqNum);
DPRINTF(IEW, "Blocked load will not be handled because "
"already squashing\n");
@@ -1408,8 +1394,8 @@ DefaultIEW<Impl>::writebackInsts()
DynInstPtr inst = toCommit->insts[inst_num];
ThreadID tid = inst->threadNumber;
- DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %#x.\n",
- inst->seqNum, inst->readPC());
+ DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %s.\n",
+ inst->seqNum, inst->pcState());
iewInstsToCommit[tid]++;
@@ -1613,10 +1599,10 @@ DefaultIEW<Impl>::checkMisprediction(DynInstPtr &inst)
DPRINTF(IEW, "Execute: Branch mispredict detected.\n");
DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n",
- inst->readPredPC(), inst->readPredNPC());
+ inst->predInstAddr(), inst->predNextInstAddr());
DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x,"
- " NPC: %#x.\n", inst->readNextPC(),
- inst->readNextNPC());
+ " NPC: %#x.\n", inst->nextInstAddr(),
+ inst->nextInstAddr());
// If incorrect, then signal the ROB that it must be squashed.
squashDueToBranch(inst, tid);
diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh
index 3d5eadf84..b944979f2 100644
--- a/src/cpu/o3/inst_queue_impl.hh
+++ b/src/cpu/o3/inst_queue_impl.hh
@@ -504,8 +504,8 @@ InstructionQueue<Impl>::insert(DynInstPtr &new_inst)
// Make sure the instruction is valid
assert(new_inst);
- DPRINTF(IQ, "Adding instruction [sn:%lli] PC %#x to the IQ.\n",
- new_inst->seqNum, new_inst->readPC());
+ DPRINTF(IQ, "Adding instruction [sn:%lli] PC %s to the IQ.\n",
+ new_inst->seqNum, new_inst->pcState());
assert(freeEntries != 0);
@@ -547,9 +547,9 @@ InstructionQueue<Impl>::insertNonSpec(DynInstPtr &new_inst)
nonSpecInsts[new_inst->seqNum] = new_inst;
- DPRINTF(IQ, "Adding non-speculative instruction [sn:%lli] PC %#x "
+ DPRINTF(IQ, "Adding non-speculative instruction [sn:%lli] PC %s "
"to the IQ.\n",
- new_inst->seqNum, new_inst->readPC());
+ new_inst->seqNum, new_inst->pcState());
assert(freeEntries != 0);
@@ -767,9 +767,9 @@ InstructionQueue<Impl>::scheduleReadyInsts()
}
}
- DPRINTF(IQ, "Thread %i: Issuing instruction PC %#x "
+ DPRINTF(IQ, "Thread %i: Issuing instruction PC %s "
"[sn:%lli]\n",
- tid, issuing_inst->readPC(),
+ tid, issuing_inst->pcState(),
issuing_inst->seqNum);
readyInsts[op_class].pop();
@@ -910,7 +910,7 @@ InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
while (dep_inst) {
DPRINTF(IQ, "Waking up a dependent instruction, [sn:%lli] "
- "PC%#x.\n", dep_inst->seqNum, dep_inst->readPC());
+ "PC %s.\n", dep_inst->seqNum, dep_inst->pcState());
// Might want to give more information to the instruction
// so that it knows which of its source registers is
@@ -955,8 +955,8 @@ InstructionQueue<Impl>::addReadyMemInst(DynInstPtr &ready_inst)
}
DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
- "the ready list, PC %#x opclass:%i [sn:%lli].\n",
- ready_inst->readPC(), op_class, ready_inst->seqNum);
+ "the ready list, PC %s opclass:%i [sn:%lli].\n",
+ ready_inst->pcState(), op_class, ready_inst->seqNum);
}
template <class Impl>
@@ -981,8 +981,8 @@ InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst)
{
ThreadID tid = completed_inst->threadNumber;
- DPRINTF(IQ, "Completing mem instruction PC:%#x [sn:%lli]\n",
- completed_inst->readPC(), completed_inst->seqNum);
+ DPRINTF(IQ, "Completing mem instruction PC: %s [sn:%lli]\n",
+ completed_inst->pcState(), completed_inst->seqNum);
++freeEntries;
@@ -1050,9 +1050,8 @@ InstructionQueue<Impl>::doSquash(ThreadID tid)
(squashed_inst->isMemRef() &&
!squashed_inst->memOpDone)) {
- DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %#x "
- "squashed.\n",
- tid, squashed_inst->seqNum, squashed_inst->readPC());
+ DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %s squashed.\n",
+ tid, squashed_inst->seqNum, squashed_inst->pcState());
// Remove the instruction from the dependency list.
if (!squashed_inst->isNonSpeculative() &&
@@ -1147,9 +1146,9 @@ InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
if (src_reg >= numPhysRegs) {
continue;
} else if (regScoreboard[src_reg] == false) {
- DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
+ DPRINTF(IQ, "Instruction PC %s has src reg %i that "
"is being added to the dependency chain.\n",
- new_inst->readPC(), src_reg);
+ new_inst->pcState(), src_reg);
dependGraph.insert(src_reg, new_inst);
@@ -1157,9 +1156,9 @@ InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
// was added to the dependency graph.
return_val = true;
} else {
- DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
+ DPRINTF(IQ, "Instruction PC %s has src reg %i that "
"became ready before it reached the IQ.\n",
- new_inst->readPC(), src_reg);
+ new_inst->pcState(), src_reg);
// Mark a register ready within the instruction.
new_inst->markSrcRegReady(src_reg_idx);
}
@@ -1228,8 +1227,8 @@ InstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
OpClass op_class = inst->opClass();
DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
- "the ready list, PC %#x opclass:%i [sn:%lli].\n",
- inst->readPC(), op_class, inst->seqNum);
+ "the ready list, PC %s opclass:%i [sn:%lli].\n",
+ inst->pcState(), op_class, inst->seqNum);
readyInsts[op_class].push(inst);
@@ -1299,7 +1298,7 @@ InstructionQueue<Impl>::dumpLists()
cprintf("Non speculative list: ");
while (non_spec_it != non_spec_end_it) {
- cprintf("%#x [sn:%lli]", (*non_spec_it).second->readPC(),
+ cprintf("%s [sn:%lli]", (*non_spec_it).second->pcState(),
(*non_spec_it).second->seqNum);
++non_spec_it;
}
@@ -1348,9 +1347,9 @@ InstructionQueue<Impl>::dumpInsts()
}
}
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
+ cprintf("PC: %s\n[sn:%lli]\n[tid:%i]\n"
"Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
+ (*inst_list_it)->pcState(),
(*inst_list_it)->seqNum,
(*inst_list_it)->threadNumber,
(*inst_list_it)->isIssued(),
@@ -1390,9 +1389,9 @@ InstructionQueue<Impl>::dumpInsts()
}
}
- cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
+ cprintf("PC: %s\n[sn:%lli]\n[tid:%i]\n"
"Issued:%i\nSquashed:%i\n",
- (*inst_list_it)->readPC(),
+ (*inst_list_it)->pcState(),
(*inst_list_it)->seqNum,
(*inst_list_it)->threadNumber,
(*inst_list_it)->isIssued(),
diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh
index a9047558d..372e76b71 100644
--- a/src/cpu/o3/lsq_unit.hh
+++ b/src/cpu/o3/lsq_unit.hh
@@ -530,8 +530,8 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh,
(load_idx != loadHead || !load_inst->isAtCommit())) {
iewStage->rescheduleMemInst(load_inst);
++lsqRescheduledLoads;
- DPRINTF(LSQUnit, "Uncachable load [sn:%lli] PC %#x\n",
- load_inst->seqNum, load_inst->readPC());
+ DPRINTF(LSQUnit, "Uncachable load [sn:%lli] PC %s\n",
+ load_inst->seqNum, load_inst->pcState());
// Must delete request now that it wasn't handed off to
// memory. This is quite ugly. @todo: Figure out the proper
@@ -687,8 +687,8 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh,
}
// If there's no forwarding case, then go access memory
- DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n",
- load_inst->seqNum, load_inst->readPC());
+ DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %s\n",
+ load_inst->seqNum, load_inst->pcState());
assert(!load_inst->memData);
load_inst->memData = new uint8_t[64];
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index 8aa7fe397..345d3ea69 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -352,8 +352,8 @@ LSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
assert((loadTail + 1) % LQEntries != loadHead);
assert(loads < LQEntries);
- DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n",
- load_inst->readPC(), loadTail, load_inst->seqNum);
+ DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n",
+ load_inst->pcState(), loadTail, load_inst->seqNum);
load_inst->lqIdx = loadTail;
@@ -378,8 +378,8 @@ LSQUnit<Impl>::insertStore(DynInstPtr &store_inst)
assert((storeTail + 1) % SQEntries != storeHead);
assert(stores < SQEntries);
- DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n",
- store_inst->readPC(), storeTail, store_inst->seqNum);
+ DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n",
+ store_inst->pcState(), storeTail, store_inst->seqNum);
store_inst->sqIdx = storeTail;
store_inst->lqIdx = loadTail;
@@ -444,8 +444,8 @@ LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
// Execute a specific load.
Fault load_fault = NoFault;
- DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
- inst->readPC(),inst->seqNum);
+ DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n",
+ inst->pcState(),inst->seqNum);
assert(!inst->isSquashed());
@@ -519,8 +519,8 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
int store_idx = store_inst->sqIdx;
- DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
- store_inst->readPC(), store_inst->seqNum);
+ DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n",
+ store_inst->pcState(), store_inst->seqNum);
assert(!store_inst->isSquashed());
@@ -531,8 +531,8 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
Fault store_fault = store_inst->initiateAcc();
if (storeQueue[store_idx].size == 0) {
- DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n",
- store_inst->readPC(),store_inst->seqNum);
+ DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli],Size = 0\n",
+ store_inst->pcState(), store_inst->seqNum);
return store_fault;
}
@@ -593,8 +593,8 @@ LSQUnit<Impl>::commitLoad()
{
assert(loadQueue[loadHead]);
- DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n",
- loadQueue[loadHead]->readPC());
+ DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n",
+ loadQueue[loadHead]->pcState());
loadQueue[loadHead] = NULL;
@@ -631,8 +631,8 @@ LSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst)
break;
}
DPRINTF(LSQUnit, "Marking store as able to write back, PC "
- "%#x [sn:%lli]\n",
- storeQueue[store_idx].inst->readPC(),
+ "%s [sn:%lli]\n",
+ storeQueue[store_idx].inst->pcState(),
storeQueue[store_idx].inst->seqNum);
storeQueue[store_idx].canWB = true;
@@ -757,9 +757,9 @@ LSQUnit<Impl>::writebackStores()
req = sreqLow;
}
- DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
+ DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s "
"to Addr:%#x, data:%#x [sn:%lli]\n",
- storeWBIdx, inst->readPC(),
+ storeWBIdx, inst->pcState(),
req->getPaddr(), (int)*(inst->memData),
inst->seqNum);
@@ -861,9 +861,9 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
decrLdIdx(load_idx);
while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
- DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, "
+ DPRINTF(LSQUnit,"Load Instruction PC %s squashed, "
"[sn:%lli]\n",
- loadQueue[load_idx]->readPC(),
+ loadQueue[load_idx]->pcState(),
loadQueue[load_idx]->seqNum);
if (isStalled() && load_idx == stallingLoadIdx) {
@@ -906,9 +906,9 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
break;
}
- DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, "
+ DPRINTF(LSQUnit,"Store Instruction PC %s squashed, "
"idx:%i [sn:%lli]\n",
- storeQueue[store_idx].inst->readPC(),
+ storeQueue[store_idx].inst->pcState(),
store_idx, storeQueue[store_idx].inst->seqNum);
// I don't think this can happen. It should have been cleared
@@ -1156,7 +1156,7 @@ LSQUnit<Impl>::dumpInsts()
int load_idx = loadHead;
while (load_idx != loadTail && loadQueue[load_idx]) {
- cprintf("%#x ", loadQueue[load_idx]->readPC());
+ cprintf("%s ", loadQueue[load_idx]->pcState());
incrLdIdx(load_idx);
}
@@ -1167,7 +1167,7 @@ LSQUnit<Impl>::dumpInsts()
int store_idx = storeHead;
while (store_idx != storeTail && storeQueue[store_idx].inst) {
- cprintf("%#x ", storeQueue[store_idx].inst->readPC());
+ cprintf("%s ", storeQueue[store_idx].inst->pcState());
incrStIdx(store_idx);
}
diff --git a/src/cpu/o3/mem_dep_unit_impl.hh b/src/cpu/o3/mem_dep_unit_impl.hh
index 5f5e71624..fdea84ed5 100644
--- a/src/cpu/o3/mem_dep_unit_impl.hh
+++ b/src/cpu/o3/mem_dep_unit_impl.hh
@@ -171,7 +171,7 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
storeBarrierSN);
producing_store = storeBarrierSN;
} else {
- producing_store = depPred.checkInst(inst->readPC());
+ producing_store = depPred.checkInst(inst->instAddr());
}
MemDepEntryPtr store_entry = NULL;
@@ -191,7 +191,7 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
// are ready.
if (!store_entry) {
DPRINTF(MemDepUnit, "No dependency for inst PC "
- "%#x [sn:%lli].\n", inst->readPC(), inst->seqNum);
+ "%s [sn:%lli].\n", inst->pcState(), inst->seqNum);
inst_entry->memDepReady = true;
@@ -203,8 +203,8 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
} else {
// Otherwise make the instruction dependent on the store/barrier.
DPRINTF(MemDepUnit, "Adding to dependency list; "
- "inst PC %#x is dependent on [sn:%lli].\n",
- inst->readPC(), producing_store);
+ "inst PC %s is dependent on [sn:%lli].\n",
+ inst->pcState(), producing_store);
if (inst->readyToIssue()) {
inst_entry->regsReady = true;
@@ -224,10 +224,10 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
}
if (inst->isStore()) {
- DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n",
- inst->readPC(), inst->seqNum);
+ DPRINTF(MemDepUnit, "Inserting store PC %s [sn:%lli].\n",
+ inst->pcState(), inst->seqNum);
- depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber);
+ depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
++insertedStores;
} else if (inst->isLoad()) {
@@ -260,10 +260,10 @@ MemDepUnit<MemDepPred, Impl>::insertNonSpec(DynInstPtr &inst)
// Might want to turn this part into an inline function or something.
// It's shared between both insert functions.
if (inst->isStore()) {
- DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n",
- inst->readPC(), inst->seqNum);
+ DPRINTF(MemDepUnit, "Inserting store PC %s [sn:%lli].\n",
+ inst->pcState(), inst->seqNum);
- depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber);
+ depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
++insertedStores;
} else if (inst->isLoad()) {
@@ -313,8 +313,8 @@ void
MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst)
{
DPRINTF(MemDepUnit, "Marking registers as ready for "
- "instruction PC %#x [sn:%lli].\n",
- inst->readPC(), inst->seqNum);
+ "instruction PC %s [sn:%lli].\n",
+ inst->pcState(), inst->seqNum);
MemDepEntryPtr inst_entry = findInHash(inst);
@@ -336,8 +336,8 @@ void
MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst)
{
DPRINTF(MemDepUnit, "Marking non speculative "
- "instruction PC %#x as ready [sn:%lli].\n",
- inst->readPC(), inst->seqNum);
+ "instruction PC %s as ready [sn:%lli].\n",
+ inst->pcState(), inst->seqNum);
MemDepEntryPtr inst_entry = findInHash(inst);
@@ -363,9 +363,8 @@ MemDepUnit<MemDepPred, Impl>::replay(DynInstPtr &inst)
MemDepEntryPtr inst_entry = findInHash(temp_inst);
- DPRINTF(MemDepUnit, "Replaying mem instruction PC %#x "
- "[sn:%lli].\n",
- temp_inst->readPC(), temp_inst->seqNum);
+ DPRINTF(MemDepUnit, "Replaying mem instruction PC %s [sn:%lli].\n",
+ temp_inst->pcState(), temp_inst->seqNum);
moveToReady(inst_entry);
@@ -377,9 +376,8 @@ template <class MemDepPred, class Impl>
void
MemDepUnit<MemDepPred, Impl>::completed(DynInstPtr &inst)
{
- DPRINTF(MemDepUnit, "Completed mem instruction PC %#x "
- "[sn:%lli].\n",
- inst->readPC(), inst->seqNum);
+ DPRINTF(MemDepUnit, "Completed mem instruction PC %s [sn:%lli].\n",
+ inst->pcState(), inst->seqNum);
ThreadID tid = inst->threadNumber;
@@ -507,10 +505,10 @@ MemDepUnit<MemDepPred, Impl>::violation(DynInstPtr &store_inst,
DynInstPtr &violating_load)
{
DPRINTF(MemDepUnit, "Passing violating PCs to store sets,"
- " load: %#x, store: %#x\n", violating_load->readPC(),
- store_inst->readPC());
+ " load: %#x, store: %#x\n", violating_load->instAddr(),
+ store_inst->instAddr());
// Tell the memory dependence unit of the violation.
- depPred.violation(violating_load->readPC(), store_inst->readPC());
+ depPred.violation(violating_load->instAddr(), store_inst->instAddr());
}
template <class MemDepPred, class Impl>
@@ -518,9 +516,9 @@ void
MemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst)
{
DPRINTF(MemDepUnit, "Issuing instruction PC %#x [sn:%lli].\n",
- inst->readPC(), inst->seqNum);
+ inst->instAddr(), inst->seqNum);
- depPred.issued(inst->readPC(), inst->seqNum, inst->isStore());
+ depPred.issued(inst->instAddr(), inst->seqNum, inst->isStore());
}
template <class MemDepPred, class Impl>
@@ -559,9 +557,9 @@ MemDepUnit<MemDepPred, Impl>::dumpLists()
int num = 0;
while (inst_list_it != instList[tid].end()) {
- cprintf("Instruction:%i\nPC:%#x\n[sn:%i]\n[tid:%i]\nIssued:%i\n"
+ cprintf("Instruction:%i\nPC: %s\n[sn:%i]\n[tid:%i]\nIssued:%i\n"
"Squashed:%i\n\n",
- num, (*inst_list_it)->readPC(),
+ num, (*inst_list_it)->pcState(),
(*inst_list_it)->seqNum,
(*inst_list_it)->threadNumber,
(*inst_list_it)->isIssued(),
diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh
index 7f796c4c8..4b321d099 100644
--- a/src/cpu/o3/rename_impl.hh
+++ b/src/cpu/o3/rename_impl.hh
@@ -591,15 +591,14 @@ DefaultRename<Impl>::renameInsts(ThreadID tid)
insts_to_rename.pop_front();
if (renameStatus[tid] == Unblocking) {
- DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%#x from rename "
- "skidBuffer\n",
- tid, inst->seqNum, inst->readPC());
+ DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%s from rename "
+ "skidBuffer\n", tid, inst->seqNum, inst->pcState());
}
if (inst->isSquashed()) {
- DPRINTF(Rename, "[tid:%u]: instruction %i with PC %#x is "
- "squashed, skipping.\n",
- tid, inst->seqNum, inst->readPC());
+ DPRINTF(Rename, "[tid:%u]: instruction %i with PC %s is "
+ "squashed, skipping.\n", tid, inst->seqNum,
+ inst->pcState());
++renameSquashedInsts;
@@ -610,8 +609,7 @@ DefaultRename<Impl>::renameInsts(ThreadID tid)
}
DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with "
- "PC %#x.\n",
- tid, inst->seqNum, inst->readPC());
+ "PC %s.\n", tid, inst->seqNum, inst->pcState());
// Handle serializeAfter/serializeBefore instructions.
// serializeAfter marks the next instruction as serializeBefore.
@@ -716,8 +714,8 @@ DefaultRename<Impl>::skidInsert(ThreadID tid)
assert(tid == inst->threadNumber);
- DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC:%#x into Rename "
- "skidBuffer\n", tid, inst->seqNum, inst->readPC());
+ DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC: %s into Rename "
+ "skidBuffer\n", tid, inst->seqNum, inst->pcState());
++renameSkidInsts;
@@ -731,7 +729,7 @@ DefaultRename<Impl>::skidInsert(ThreadID tid)
for(it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++)
{
warn("[tid:%u]: %s [sn:%i].\n", tid,
- (*it)->staticInst->disassemble(inst->readPC()),
+ (*it)->staticInst->disassemble(inst->instAddr()),
(*it)->seqNum);
}
panic("Skidbuffer Exceeded Max Size");
@@ -1287,8 +1285,7 @@ DefaultRename<Impl>::checkSignalsAndUpdate(ThreadID tid)
unblock(tid);
DPRINTF(Rename, "[tid:%u]: Processing instruction [%lli] with "
- "PC %#x.\n",
- tid, serial_inst->seqNum, serial_inst->readPC());
+ "PC %s.\n", tid, serial_inst->seqNum, serial_inst->pcState());
// Put instruction into queue here.
serial_inst->clearSerializeBefore();
diff --git a/src/cpu/o3/rob_impl.hh b/src/cpu/o3/rob_impl.hh
index cf0080b48..37f1c5504 100644
--- a/src/cpu/o3/rob_impl.hh
+++ b/src/cpu/o3/rob_impl.hh
@@ -204,7 +204,7 @@ ROB<Impl>::insertInst(DynInstPtr &inst)
{
assert(inst);
- DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC());
+ DPRINTF(ROB, "Adding inst PC %s to the ROB.\n", inst->pcState());
assert(numInstsInROB != numEntries);
@@ -247,7 +247,7 @@ ROB<Impl>::retireHead(ThreadID tid)
assert(head_inst->readyToCommit());
DPRINTF(ROB, "[tid:%u]: Retiring head instruction, "
- "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(),
+ "instruction PC %s, [sn:%lli]\n", tid, head_inst->pcState(),
head_inst->seqNum);
--numInstsInROB;
@@ -338,9 +338,9 @@ ROB<Impl>::doSquash(ThreadID tid)
(*squashIt[tid])->seqNum > squashedSeqNum[tid];
++numSquashed)
{
- DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n",
+ DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %s, seq num %i.\n",
(*squashIt[tid])->threadNumber,
- (*squashIt[tid])->readPC(),
+ (*squashIt[tid])->pcState(),
(*squashIt[tid])->seqNum);
// Mark the instruction as squashed, and ready to commit so that
diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh
index b7790cfda..4e559000b 100755
--- a/src/cpu/o3/thread_context.hh
+++ b/src/cpu/o3/thread_context.hh
@@ -172,29 +172,24 @@ class O3ThreadContext : public ThreadContext
virtual void setFloatRegBits(int reg_idx, FloatRegBits val);
- /** Reads this thread's PC. */
- virtual uint64_t readPC()
- { return cpu->readPC(thread->threadId()); }
-
- /** Sets this thread's PC. */
- virtual void setPC(uint64_t val);
-
- /** Reads this thread's next PC. */
- virtual uint64_t readNextPC()
- { return cpu->readNextPC(thread->threadId()); }
+ /** Reads this thread's PC state. */
+ virtual TheISA::PCState pcState()
+ { return cpu->pcState(thread->threadId()); }
- /** Sets this thread's next PC. */
- virtual void setNextPC(uint64_t val);
+ /** Sets this thread's PC state. */
+ virtual void pcState(const TheISA::PCState &val);
- virtual uint64_t readMicroPC()
- { return cpu->readMicroPC(thread->threadId()); }
-
- virtual void setMicroPC(uint64_t val);
+ /** Reads this thread's PC. */
+ virtual Addr instAddr()
+ { return cpu->instAddr(thread->threadId()); }
- virtual uint64_t readNextMicroPC()
- { return cpu->readNextMicroPC(thread->threadId()); }
+ /** Reads this thread's next PC. */
+ virtual Addr nextInstAddr()
+ { return cpu->nextInstAddr(thread->threadId()); }
- virtual void setNextMicroPC(uint64_t val);
+ /** Reads this thread's next PC. */
+ virtual MicroPC microPC()
+ { return cpu->microPC(thread->threadId()); }
/** Reads a miscellaneous register. */
virtual MiscReg readMiscRegNoEffect(int misc_reg)
@@ -247,15 +242,6 @@ class O3ThreadContext : public ThreadContext
}
#endif
- virtual uint64_t readNextNPC()
- {
- return this->cpu->readNextNPC(this->thread->threadId());
- }
-
- virtual void setNextNPC(uint64_t val)
- {
- this->cpu->setNextNPC(val, this->thread->threadId());
- }
};
#endif
diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh
index 0b7a2b172..367442830 100755
--- a/src/cpu/o3/thread_context_impl.hh
+++ b/src/cpu/o3/thread_context_impl.hh
@@ -248,11 +248,7 @@ O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc)
// Then finally set the PC, the next PC, the nextNPC, the micropc, and the
// next micropc.
- cpu->setPC(tc->readPC(), tid);
- cpu->setNextPC(tc->readNextPC(), tid);
- cpu->setNextNPC(tc->readNextNPC(), tid);
- cpu->setMicroPC(tc->readMicroPC(), tid);
- cpu->setNextMicroPC(tc->readNextMicroPC(), tid);
+ cpu->pcState(tc->pcState(), tid);
#if !FULL_SYSTEM
this->thread->funcExeInst = tc->readFuncExeInst();
#endif
@@ -327,45 +323,9 @@ O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
template <class Impl>
void
-O3ThreadContext<Impl>::setPC(uint64_t val)
+O3ThreadContext<Impl>::pcState(const TheISA::PCState &val)
{
- cpu->setPC(val, thread->threadId());
-
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
-}
-
-template <class Impl>
-void
-O3ThreadContext<Impl>::setNextPC(uint64_t val)
-{
- cpu->setNextPC(val, thread->threadId());
-
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
-}
-
-template <class Impl>
-void
-O3ThreadContext<Impl>::setMicroPC(uint64_t val)
-{
- cpu->setMicroPC(val, thread->threadId());
-
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
-}
-
-template <class Impl>
-void
-O3ThreadContext<Impl>::setNextMicroPC(uint64_t val)
-{
- cpu->setNextMicroPC(val, thread->threadId());
+ cpu->pcState(val, thread->threadId());
// Squash if we're not already in a state update mode.
if (!thread->trapPending && !thread->inSyscall) {
diff --git a/src/cpu/pc_event.cc b/src/cpu/pc_event.cc
index 79f5277d5..533d61498 100644
--- a/src/cpu/pc_event.cc
+++ b/src/cpu/pc_event.cc
@@ -83,7 +83,7 @@ PCEventQueue::schedule(PCEvent *event)
bool
PCEventQueue::doService(ThreadContext *tc)
{
- Addr pc = tc->readPC() & ~0x3;
+ Addr pc = tc->instAddr() & ~0x3;
int serviced = 0;
range_t range = equal_range(pc);
for (iterator i = range.first; i != range.second; ++i) {
@@ -91,7 +91,7 @@ PCEventQueue::doService(ThreadContext *tc)
// another event. This for example, prevents two invocations
// of the SkipFuncEvent. Maybe we should have separate PC
// event queues for each processor?
- if (pc != (tc->readPC() & ~0x3))
+ if (pc != (tc->instAddr() & ~0x3))
continue;
DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n",
diff --git a/src/cpu/pred/btb.cc b/src/cpu/pred/btb.cc
index c6a5e23f9..e87cc6dc2 100644
--- a/src/cpu/pred/btb.cc
+++ b/src/cpu/pred/btb.cc
@@ -68,25 +68,25 @@ DefaultBTB::reset()
inline
unsigned
-DefaultBTB::getIndex(const Addr &inst_PC)
+DefaultBTB::getIndex(Addr instPC)
{
// Need to shift PC over by the word offset.
- return (inst_PC >> instShiftAmt) & idxMask;
+ return (instPC >> instShiftAmt) & idxMask;
}
inline
Addr
-DefaultBTB::getTag(const Addr &inst_PC)
+DefaultBTB::getTag(Addr instPC)
{
- return (inst_PC >> tagShiftAmt) & tagMask;
+ return (instPC >> tagShiftAmt) & tagMask;
}
bool
-DefaultBTB::valid(const Addr &inst_PC, ThreadID tid)
+DefaultBTB::valid(Addr instPC, ThreadID tid)
{
- unsigned btb_idx = getIndex(inst_PC);
+ unsigned btb_idx = getIndex(instPC);
- Addr inst_tag = getTag(inst_PC);
+ Addr inst_tag = getTag(instPC);
assert(btb_idx < numEntries);
@@ -102,12 +102,12 @@ DefaultBTB::valid(const Addr &inst_PC, ThreadID tid)
// @todo Create some sort of return struct that has both whether or not the
// address is valid, and also the address. For now will just use addr = 0 to
// represent invalid entry.
-Addr
-DefaultBTB::lookup(const Addr &inst_PC, ThreadID tid)
+TheISA::PCState
+DefaultBTB::lookup(Addr instPC, ThreadID tid)
{
- unsigned btb_idx = getIndex(inst_PC);
+ unsigned btb_idx = getIndex(instPC);
- Addr inst_tag = getTag(inst_PC);
+ Addr inst_tag = getTag(instPC);
assert(btb_idx < numEntries);
@@ -121,14 +121,14 @@ DefaultBTB::lookup(const Addr &inst_PC, ThreadID tid)
}
void
-DefaultBTB::update(const Addr &inst_PC, const Addr &target, ThreadID tid)
+DefaultBTB::update(Addr instPC, const TheISA::PCState &target, ThreadID tid)
{
- unsigned btb_idx = getIndex(inst_PC);
+ unsigned btb_idx = getIndex(instPC);
assert(btb_idx < numEntries);
btb[btb_idx].tid = tid;
btb[btb_idx].valid = true;
btb[btb_idx].target = target;
- btb[btb_idx].tag = getTag(inst_PC);
+ btb[btb_idx].tag = getTag(instPC);
}
diff --git a/src/cpu/pred/btb.hh b/src/cpu/pred/btb.hh
index 6557522e0..814b23872 100644
--- a/src/cpu/pred/btb.hh
+++ b/src/cpu/pred/btb.hh
@@ -31,8 +31,10 @@
#ifndef __CPU_O3_BTB_HH__
#define __CPU_O3_BTB_HH__
+#include "arch/types.hh"
#include "base/misc.hh"
#include "base/types.hh"
+#include "config/the_isa.hh"
class DefaultBTB
{
@@ -41,14 +43,13 @@ class DefaultBTB
{
BTBEntry()
: tag(0), target(0), valid(false)
- {
- }
+ {}
/** The entry's tag. */
Addr tag;
/** The entry's target. */
- Addr target;
+ TheISA::PCState target;
/** The entry's thread id. */
ThreadID tid;
@@ -74,21 +75,21 @@ class DefaultBTB
* @param tid The thread id.
* @return Returns the target of the branch.
*/
- Addr lookup(const Addr &inst_PC, ThreadID tid);
+ TheISA::PCState lookup(Addr instPC, ThreadID tid);
/** Checks if a branch is in the BTB.
* @param inst_PC The address of the branch to look up.
* @param tid The thread id.
* @return Whether or not the branch exists in the BTB.
*/
- bool valid(const Addr &inst_PC, ThreadID tid);
+ bool valid(Addr instPC, ThreadID tid);
/** Updates the BTB with the target of a branch.
* @param inst_PC The address of the branch being updated.
* @param target_PC The target address of the branch.
* @param tid The thread id.
*/
- void update(const Addr &inst_PC, const Addr &target_PC,
+ void update(Addr instPC, const TheISA::PCState &targetPC,
ThreadID tid);
private:
@@ -96,13 +97,13 @@ class DefaultBTB
* @param inst_PC The branch to look up.
* @return Returns the index into the BTB.
*/
- inline unsigned getIndex(const Addr &inst_PC);
+ inline unsigned getIndex(Addr instPC);
/** Returns the tag bits of a given address.
* @param inst_PC The branch's address.
* @return Returns the tag bits.
*/
- inline Addr getTag(const Addr &inst_PC);
+ inline Addr getTag(Addr instPC);
/** The actual BTB. */
std::vector<BTBEntry> btb;
diff --git a/src/cpu/pred/ras.cc b/src/cpu/pred/ras.cc
index 6373e5de3..0ba09bfae 100644
--- a/src/cpu/pred/ras.cc
+++ b/src/cpu/pred/ras.cc
@@ -34,13 +34,8 @@ void
ReturnAddrStack::init(unsigned _numEntries)
{
numEntries = _numEntries;
- usedEntries = 0;
- tos = 0;
-
addrStack.resize(numEntries);
-
- for (unsigned i = 0; i < numEntries; ++i)
- addrStack[i] = 0;
+ reset();
}
void
@@ -49,11 +44,11 @@ ReturnAddrStack::reset()
usedEntries = 0;
tos = 0;
for (unsigned i = 0; i < numEntries; ++i)
- addrStack[i] = 0;
+ addrStack[i].set(0);
}
void
-ReturnAddrStack::push(const Addr &return_addr)
+ReturnAddrStack::push(const TheISA::PCState &return_addr)
{
incrTos();
@@ -76,9 +71,9 @@ ReturnAddrStack::pop()
void
ReturnAddrStack::restore(unsigned top_entry_idx,
- const Addr &restored_target)
+ const TheISA::PCState &restored)
{
tos = top_entry_idx;
- addrStack[tos] = restored_target;
+ addrStack[tos] = restored;
}
diff --git a/src/cpu/pred/ras.hh b/src/cpu/pred/ras.hh
index a36faf79a..ab92b34c2 100644
--- a/src/cpu/pred/ras.hh
+++ b/src/cpu/pred/ras.hh
@@ -33,7 +33,9 @@
#include <vector>
+#include "arch/types.hh"
#include "base/types.hh"
+#include "config/the_isa.hh"
/** Return address stack class, implements a simple RAS. */
class ReturnAddrStack
@@ -52,7 +54,7 @@ class ReturnAddrStack
void reset();
/** Returns the top address on the RAS. */
- Addr top()
+ TheISA::PCState top()
{ return addrStack[tos]; }
/** Returns the index of the top of the RAS. */
@@ -60,7 +62,7 @@ class ReturnAddrStack
{ return tos; }
/** Pushes an address onto the RAS. */
- void push(const Addr &return_addr);
+ void push(const TheISA::PCState &return_addr);
/** Pops the top address from the RAS. */
void pop();
@@ -68,9 +70,9 @@ class ReturnAddrStack
/** Changes index to the top of the RAS, and replaces the top address with
* a new target.
* @param top_entry_idx The index of the RAS that will now be the top.
- * @param restored_target The new target address of the new top of the RAS.
+ * @param restored The new target address of the new top of the RAS.
*/
- void restore(unsigned top_entry_idx, const Addr &restored_target);
+ void restore(unsigned top_entry_idx, const TheISA::PCState &restored);
bool empty() { return usedEntries == 0; }
@@ -85,7 +87,7 @@ class ReturnAddrStack
{ tos = (tos == 0 ? numEntries - 1 : tos - 1); }
/** The RAS itself. */
- std::vector<Addr> addrStack;
+ std::vector<TheISA::PCState> addrStack;
/** The number of entries in the RAS. */
unsigned numEntries;
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index d97e7aeec..de26ca2f8 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -321,7 +321,7 @@ AtomicSimpleCPU::readBytes(Addr addr, uint8_t * data,
dcache_latency = 0;
while (1) {
- req->setVirt(0, addr, size, flags, thread->readPC());
+ req->setVirt(0, addr, size, flags, thread->pcState().instAddr());
// translate to physical address
Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read);
@@ -475,7 +475,7 @@ AtomicSimpleCPU::writeBytes(uint8_t *data, unsigned size,
dcache_latency = 0;
while(1) {
- req->setVirt(0, addr, size, flags, thread->readPC());
+ req->setVirt(0, addr, size, flags, thread->pcState().instAddr());
// translate to physical address
Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write);
@@ -643,8 +643,11 @@ AtomicSimpleCPU::tick()
Fault fault = NoFault;
- bool fromRom = isRomMicroPC(thread->readMicroPC());
- if (!fromRom && !curMacroStaticInst) {
+ TheISA::PCState pcState = thread->pcState();
+
+ bool needToFetch = !isRomMicroPC(pcState.microPC()) &&
+ !curMacroStaticInst;
+ if (needToFetch) {
setupFetchRequest(&ifetch_req);
fault = thread->itb->translateAtomic(&ifetch_req, tc,
BaseTLB::Execute);
@@ -655,7 +658,7 @@ AtomicSimpleCPU::tick()
bool icache_access = false;
dcache_access = false; // assume no dcache access
- if (!fromRom && !curMacroStaticInst) {
+ if (needToFetch) {
// This is commented out because the predecoder would act like
// a tiny cache otherwise. It wouldn't be flushed when needed
// like the I cache. It should be flushed, and when that works
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index 088d5ff16..196b72cc0 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -368,19 +368,13 @@ BaseSimpleCPU::checkForInterrupts()
void
BaseSimpleCPU::setupFetchRequest(Request *req)
{
- Addr threadPC = thread->readPC();
+ Addr instAddr = thread->instAddr();
// set up memory request for instruction fetch
-#if ISA_HAS_DELAY_SLOT
- DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",threadPC,
- thread->readNextPC(),thread->readNextNPC());
-#else
- DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p\n",threadPC,
- thread->readNextPC());
-#endif
+ DPRINTF(Fetch, "Fetch: PC:%08p\n", instAddr);
- Addr fetchPC = (threadPC & PCMask) + fetchOffset;
- req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH, threadPC);
+ Addr fetchPC = (instAddr & PCMask) + fetchOffset;
+ req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH, instAddr);
}
@@ -399,11 +393,12 @@ BaseSimpleCPU::preExecute()
// decode the instruction
inst = gtoh(inst);
- MicroPC upc = thread->readMicroPC();
+ TheISA::PCState pcState = thread->pcState();
- if (isRomMicroPC(upc)) {
+ if (isRomMicroPC(pcState.microPC())) {
stayAtPC = false;
- curStaticInst = microcodeRom.fetchMicroop(upc, curMacroStaticInst);
+ curStaticInst = microcodeRom.fetchMicroop(pcState.microPC(),
+ curMacroStaticInst);
} else if (!curMacroStaticInst) {
//We're not in the middle of a macro instruction
StaticInstPtr instPtr = NULL;
@@ -412,21 +407,19 @@ BaseSimpleCPU::preExecute()
//This should go away once the constructor can be set up properly
predecoder.setTC(thread->getTC());
//If more fetch data is needed, pass it in.
- Addr fetchPC = (thread->readPC() & PCMask) + fetchOffset;
+ Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset;
//if(predecoder.needMoreBytes())
- predecoder.moreBytes(thread->readPC(), fetchPC, inst);
+ predecoder.moreBytes(pcState, fetchPC, inst);
//else
// predecoder.process();
//If an instruction is ready, decode it. Otherwise, we'll have to
//fetch beyond the MachInst at the current pc.
if (predecoder.extMachInstReady()) {
-#if THE_ISA == X86_ISA || THE_ISA == ARM_ISA
- thread->setNextPC(thread->readPC() + predecoder.getInstSize());
-#endif // X86_ISA
stayAtPC = false;
- instPtr = StaticInst::decode(predecoder.getExtMachInst(),
- thread->readPC());
+ ExtMachInst machInst = predecoder.getExtMachInst(pcState);
+ thread->pcState(pcState);
+ instPtr = StaticInst::decode(machInst, pcState.instAddr());
} else {
stayAtPC = true;
fetchOffset += sizeof(MachInst);
@@ -436,13 +429,13 @@ BaseSimpleCPU::preExecute()
//out micro ops
if (instPtr && instPtr->isMacroop()) {
curMacroStaticInst = instPtr;
- curStaticInst = curMacroStaticInst->fetchMicroop(upc);
+ curStaticInst = curMacroStaticInst->fetchMicroop(pcState.microPC());
} else {
curStaticInst = instPtr;
}
} else {
//Read the next micro op from the macro op
- curStaticInst = curMacroStaticInst->fetchMicroop(upc);
+ curStaticInst = curMacroStaticInst->fetchMicroop(pcState.microPC());
}
//If we decoded an instruction this "tick", record information about it.
@@ -450,8 +443,7 @@ BaseSimpleCPU::preExecute()
{
#if TRACING_ON
traceData = tracer->getInstRecord(curTick, tc,
- curStaticInst, thread->readPC(),
- curMacroStaticInst, thread->readMicroPC());
+ curStaticInst, thread->pcState(), curMacroStaticInst);
DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n",
curStaticInst->getName(), curStaticInst->machInst);
@@ -462,10 +454,14 @@ BaseSimpleCPU::preExecute()
void
BaseSimpleCPU::postExecute()
{
+ assert(curStaticInst);
+
+ TheISA::PCState pc = tc->pcState();
+ Addr instAddr = pc.instAddr();
#if FULL_SYSTEM
- if (thread->profile && curStaticInst) {
+ if (thread->profile) {
bool usermode = TheISA::inUserMode(tc);
- thread->profilePC = usermode ? 1 : thread->readPC();
+ thread->profilePC = usermode ? 1 : instAddr;
ProfileNode *node = thread->profile->consume(tc, curStaticInst);
if (node)
thread->profileNode = node;
@@ -482,10 +478,10 @@ BaseSimpleCPU::postExecute()
}
if (CPA::available()) {
- CPA::cpa()->swAutoBegin(tc, thread->readNextPC());
+ CPA::cpa()->swAutoBegin(tc, pc.nextInstAddr());
}
- traceFunctions(thread->readPC());
+ traceFunctions(instAddr);
if (traceData) {
traceData->dump();
@@ -505,30 +501,12 @@ BaseSimpleCPU::advancePC(Fault fault)
fault->invoke(tc, curStaticInst);
predecoder.reset();
} else {
- //If we're at the last micro op for this instruction
- if (curStaticInst && curStaticInst->isLastMicroop()) {
- //We should be working with a macro op or be in the ROM
- assert(curMacroStaticInst ||
- isRomMicroPC(thread->readMicroPC()));
- //Close out this macro op, and clean up the
- //microcode state
- curMacroStaticInst = StaticInst::nullStaticInstPtr;
- thread->setMicroPC(normalMicroPC(0));
- thread->setNextMicroPC(normalMicroPC(1));
- }
- //If we're still in a macro op
- if (curMacroStaticInst || isRomMicroPC(thread->readMicroPC())) {
- //Advance the micro pc
- thread->setMicroPC(thread->readNextMicroPC());
- //Advance the "next" micro pc. Note that there are no delay
- //slots, and micro ops are "word" addressed.
- thread->setNextMicroPC(thread->readNextMicroPC() + 1);
- } else {
- // go to the next instruction
- thread->setPC(thread->readNextPC());
- thread->setNextPC(thread->readNextNPC());
- thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
- assert(thread->readNextPC() != thread->readNextNPC());
+ if (curStaticInst) {
+ if (curStaticInst->isLastMicroop())
+ curMacroStaticInst = StaticInst::nullStaticInstPtr;
+ TheISA::PCState pcState = thread->pcState();
+ TheISA::advancePC(pcState, curStaticInst);
+ thread->pcState(pcState);
}
}
}
diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh
index 0aa0a295c..a713533fc 100644
--- a/src/cpu/simple/base.hh
+++ b/src/cpu/simple/base.hh
@@ -88,11 +88,12 @@ class BaseSimpleCPU : public BaseCPU
Trace::InstRecord *traceData;
inline void checkPcEventQueue() {
- Addr oldpc;
+ Addr oldpc, pc = thread->instAddr();
do {
- oldpc = thread->readPC();
+ oldpc = pc;
system->pcEventQueue.service(tc);
- } while (oldpc != thread->readPC());
+ pc = thread->instAddr();
+ } while (oldpc != pc);
}
public:
@@ -282,18 +283,7 @@ class BaseSimpleCPU : public BaseCPU
thread->setFloatRegBits(reg_idx, val);
}
- uint64_t readPC() { return thread->readPC(); }
- uint64_t readMicroPC() { return thread->readMicroPC(); }
- uint64_t readNextPC() { return thread->readNextPC(); }
- uint64_t readNextMicroPC() { return thread->readNextMicroPC(); }
- uint64_t readNextNPC() { return thread->readNextNPC(); }
bool readPredicate() { return thread->readPredicate(); }
-
- void setPC(uint64_t val) { thread->setPC(val); }
- void setMicroPC(uint64_t val) { thread->setMicroPC(val); }
- void setNextPC(uint64_t val) { thread->setNextPC(val); }
- void setNextMicroPC(uint64_t val) { thread->setNextMicroPC(val); }
- void setNextNPC(uint64_t val) { thread->setNextNPC(val); }
void setPredicate(bool val)
{
thread->setPredicate(val);
@@ -301,6 +291,11 @@ class BaseSimpleCPU : public BaseCPU
traceData->setPredicate(val);
}
}
+ TheISA::PCState pcState() { return thread->pcState(); }
+ void pcState(const TheISA::PCState &val) { thread->pcState(val); }
+ Addr instAddr() { return thread->instAddr(); }
+ Addr nextInstAddr() { return thread->nextInstAddr(); }
+ MicroPC microPC() { return thread->microPC(); }
MiscReg readMiscRegNoEffect(int misc_reg)
{
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index 2eb5b432b..863c28be2 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -422,7 +422,7 @@ TimingSimpleCPU::readBytes(Addr addr, uint8_t *data,
Fault fault;
const int asid = 0;
const ThreadID tid = 0;
- const Addr pc = thread->readPC();
+ const Addr pc = thread->instAddr();
unsigned block_size = dcachePort.peerBlockSize();
BaseTLB::Mode mode = BaseTLB::Read;
@@ -545,7 +545,7 @@ TimingSimpleCPU::writeTheseBytes(uint8_t *data, unsigned size,
{
const int asid = 0;
const ThreadID tid = 0;
- const Addr pc = thread->readPC();
+ const Addr pc = thread->instAddr();
unsigned block_size = dcachePort.peerBlockSize();
BaseTLB::Mode mode = BaseTLB::Write;
@@ -701,9 +701,10 @@ TimingSimpleCPU::fetch()
checkPcEventQueue();
- bool fromRom = isRomMicroPC(thread->readMicroPC());
+ TheISA::PCState pcState = thread->pcState();
+ bool needToFetch = !isRomMicroPC(pcState.microPC()) && !curMacroStaticInst;
- if (!fromRom && !curMacroStaticInst) {
+ if (needToFetch) {
Request *ifetch_req = new Request();
ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0);
setupFetchRequest(ifetch_req);
diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc
index bd796428a..15fac8677 100644
--- a/src/cpu/simple_thread.cc
+++ b/src/cpu/simple_thread.cc
@@ -193,11 +193,7 @@ SimpleThread::serialize(ostream &os)
ThreadState::serialize(os);
SERIALIZE_ARRAY(floatRegs.i, TheISA::NumFloatRegs);
SERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs);
- SERIALIZE_SCALAR(microPC);
- SERIALIZE_SCALAR(nextMicroPC);
- SERIALIZE_SCALAR(PC);
- SERIALIZE_SCALAR(nextPC);
- SERIALIZE_SCALAR(nextNPC);
+ _pcState.serialize(os);
// thread_num and cpu_id are deterministic from the config
//
@@ -213,11 +209,7 @@ SimpleThread::unserialize(Checkpoint *cp, const std::string &section)
ThreadState::unserialize(cp, section);
UNSERIALIZE_ARRAY(floatRegs.i, TheISA::NumFloatRegs);
UNSERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs);
- UNSERIALIZE_SCALAR(microPC);
- UNSERIALIZE_SCALAR(nextMicroPC);
- UNSERIALIZE_SCALAR(PC);
- UNSERIALIZE_SCALAR(nextPC);
- UNSERIALIZE_SCALAR(nextNPC);
+ _pcState.unserialize(cp, section);
// thread_num and cpu_id are deterministic from the config
//
diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh
index e4a7b7a77..48077a9b9 100644
--- a/src/cpu/simple_thread.hh
+++ b/src/cpu/simple_thread.hh
@@ -106,27 +106,7 @@ class SimpleThread : public ThreadState
TheISA::IntReg intRegs[TheISA::NumIntRegs];
TheISA::ISA isa; // one "instance" of the current ISA.
- /** The current microcode pc for the currently executing macro
- * operation.
- */
- MicroPC microPC;
-
- /** The next microcode pc for the currently executing macro
- * operation.
- */
- MicroPC nextMicroPC;
-
- /** The current pc.
- */
- Addr PC;
-
- /** The next pc.
- */
- Addr nextPC;
-
- /** The next next pc.
- */
- Addr nextNPC;
+ TheISA::PCState _pcState;
/** Did this instruction execute or is it predicated false */
bool predicate;
@@ -245,9 +225,7 @@ class SimpleThread : public ThreadState
void clearArchRegs()
{
- microPC = 0;
- nextMicroPC = 1;
- PC = nextPC = nextNPC = 0;
+ _pcState = 0;
memset(intRegs, 0, sizeof(intRegs));
memset(floatRegs.i, 0, sizeof(floatRegs.i));
isa.clear();
@@ -313,60 +291,34 @@ class SimpleThread : public ThreadState
reg_idx, flatIndex, val, floatRegs.f[flatIndex]);
}
- uint64_t readPC()
- {
- return PC;
- }
-
- void setPC(uint64_t val)
- {
- PC = val;
- }
-
- uint64_t readMicroPC()
- {
- return microPC;
- }
-
- void setMicroPC(uint64_t val)
- {
- microPC = val;
- }
-
- uint64_t readNextPC()
+ TheISA::PCState
+ pcState()
{
- return nextPC;
+ return _pcState;
}
- void setNextPC(uint64_t val)
+ void
+ pcState(const TheISA::PCState &val)
{
- nextPC = val;
+ _pcState = val;
}
- uint64_t readNextMicroPC()
+ Addr
+ instAddr()
{
- return nextMicroPC;
+ return _pcState.instAddr();
}
- void setNextMicroPC(uint64_t val)
+ Addr
+ nextInstAddr()
{
- nextMicroPC = val;
+ return _pcState.nextInstAddr();
}
- uint64_t readNextNPC()
+ MicroPC
+ microPC()
{
-#if ISA_HAS_DELAY_SLOT
- return nextNPC;
-#else
- return nextPC + sizeof(TheISA::MachInst);
-#endif
- }
-
- void setNextNPC(uint64_t val)
- {
-#if ISA_HAS_DELAY_SLOT
- nextNPC = val;
-#endif
+ return _pcState.microPC();
}
bool readPredicate()
diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc
index 2c4fc8ab9..f2a72c96a 100644
--- a/src/cpu/static_inst.cc
+++ b/src/cpu/static_inst.cc
@@ -68,7 +68,8 @@ StaticInst::dumpDecodeCacheStats()
}
bool
-StaticInst::hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const
+StaticInst::hasBranchTarget(const TheISA::PCState &pc, ThreadContext *tc,
+ TheISA::PCState &tgt) const
{
if (isDirectCtrl()) {
tgt = branchTarget(pc);
@@ -84,21 +85,21 @@ StaticInst::hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const
}
StaticInstPtr
-StaticInst::fetchMicroop(MicroPC micropc)
+StaticInst::fetchMicroop(MicroPC upc) const
{
panic("StaticInst::fetchMicroop() called on instruction "
"that is not microcoded.");
}
-Addr
-StaticInst::branchTarget(Addr branchPC) const
+TheISA::PCState
+StaticInst::branchTarget(const TheISA::PCState &pc) const
{
panic("StaticInst::branchTarget() called on instruction "
"that is not a PC-relative branch.");
M5_DUMMY_RETURN;
}
-Addr
+TheISA::PCState
StaticInst::branchTarget(ThreadContext *tc) const
{
panic("StaticInst::branchTarget() called on instruction "
diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh
index 6474bbf9c..b219fafd6 100644
--- a/src/cpu/static_inst.hh
+++ b/src/cpu/static_inst.hh
@@ -35,6 +35,7 @@
#include <string>
#include "arch/isa_traits.hh"
+#include "arch/types.hh"
#include "arch/registers.hh"
#include "config/the_isa.hh"
#include "base/hashmap.hh"
@@ -70,28 +71,6 @@ namespace Trace {
class InstRecord;
}
-typedef uint16_t MicroPC;
-
-static const MicroPC MicroPCRomBit = 1 << (sizeof(MicroPC) * 8 - 1);
-
-static inline MicroPC
-romMicroPC(MicroPC upc)
-{
- return upc | MicroPCRomBit;
-}
-
-static inline MicroPC
-normalMicroPC(MicroPC upc)
-{
- return upc & ~MicroPCRomBit;
-}
-
-static inline bool
-isRomMicroPC(MicroPC upc)
-{
- return MicroPCRomBit & upc;
-}
-
/**
* Base, ISA-independent static instruction class.
*
@@ -392,18 +371,20 @@ class StaticInst : public StaticInstBase
*/
#include "cpu/static_inst_exec_sigs.hh"
+ virtual void advancePC(TheISA::PCState &pcState) const = 0;
+
/**
* Return the microop that goes with a particular micropc. This should
* only be defined/used in macroops which will contain microops
*/
- virtual StaticInstPtr fetchMicroop(MicroPC micropc);
+ virtual StaticInstPtr fetchMicroop(MicroPC upc) const;
/**
* Return the target address for a PC-relative branch.
* Invalid if not a PC-relative branch (i.e. isDirectCtrl()
* should be true).
*/
- virtual Addr branchTarget(Addr branchPC) const;
+ virtual TheISA::PCState branchTarget(const TheISA::PCState &pc) const;
/**
* Return the target address for an indirect branch (jump). The
@@ -412,13 +393,14 @@ class StaticInst : public StaticInstBase
* execute the branch in question. Invalid if not an indirect
* branch (i.e. isIndirectCtrl() should be true).
*/
- virtual Addr branchTarget(ThreadContext *tc) const;
+ virtual TheISA::PCState branchTarget(ThreadContext *tc) const;
/**
* Return true if the instruction is a control transfer, and if so,
* return the target address as well.
*/
- bool hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const;
+ bool hasBranchTarget(const TheISA::PCState &pc, ThreadContext *tc,
+ TheISA::PCState &tgt) const;
/**
* Return string representation of disassembled instruction.
diff --git a/src/cpu/thread_context.cc b/src/cpu/thread_context.cc
index f2083ef08..c4960ea30 100644
--- a/src/cpu/thread_context.cc
+++ b/src/cpu/thread_context.cc
@@ -65,16 +65,8 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two)
}
#endif
- Addr pc1 = one->readPC();
- Addr pc2 = two->readPC();
- if (pc1 != pc2)
- panic("PCs doesn't match, one: %#x, two: %#x", pc1, pc2);
-
- Addr npc1 = one->readNextPC();
- Addr npc2 = two->readNextPC();
- if (npc1 != npc2)
- panic("NPCs doesn't match, one: %#x, two: %#x", npc1, npc2);
-
+ if (!(one->pcState() == two->pcState()))
+ panic("PC state doesn't match.");
int id1 = one->cpuId();
int id2 = two->cpuId();
if (id1 != id2)
diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh
index 753fa2146..1c70ef59a 100644
--- a/src/cpu/thread_context.hh
+++ b/src/cpu/thread_context.hh
@@ -192,25 +192,15 @@ class ThreadContext
virtual void setFloatRegBits(int reg_idx, FloatRegBits val) = 0;
- virtual uint64_t readPC() = 0;
+ virtual TheISA::PCState pcState() = 0;
- virtual void setPC(uint64_t val) = 0;
+ virtual void pcState(const TheISA::PCState &val) = 0;
- virtual uint64_t readNextPC() = 0;
+ virtual Addr instAddr() = 0;
- virtual void setNextPC(uint64_t val) = 0;
+ virtual Addr nextInstAddr() = 0;
- virtual uint64_t readNextNPC() = 0;
-
- virtual void setNextNPC(uint64_t val) = 0;
-
- virtual uint64_t readMicroPC() = 0;
-
- virtual void setMicroPC(uint64_t val) = 0;
-
- virtual uint64_t readNextMicroPC() = 0;
-
- virtual void setNextMicroPC(uint64_t val) = 0;
+ virtual MicroPC microPC() = 0;
virtual MiscReg readMiscRegNoEffect(int misc_reg) = 0;
@@ -377,25 +367,13 @@ class ProxyThreadContext : public ThreadContext
void setFloatRegBits(int reg_idx, FloatRegBits val)
{ actualTC->setFloatRegBits(reg_idx, val); }
- uint64_t readPC() { return actualTC->readPC(); }
-
- void setPC(uint64_t val) { actualTC->setPC(val); }
-
- uint64_t readNextPC() { return actualTC->readNextPC(); }
-
- void setNextPC(uint64_t val) { actualTC->setNextPC(val); }
-
- uint64_t readNextNPC() { return actualTC->readNextNPC(); }
-
- void setNextNPC(uint64_t val) { actualTC->setNextNPC(val); }
-
- uint64_t readMicroPC() { return actualTC->readMicroPC(); }
-
- void setMicroPC(uint64_t val) { actualTC->setMicroPC(val); }
+ TheISA::PCState pcState() { return actualTC->pcState(); }
- uint64_t readNextMicroPC() { return actualTC->readMicroPC(); }
+ void pcState(const TheISA::PCState &val) { actualTC->pcState(val); }
- void setNextMicroPC(uint64_t val) { actualTC->setNextMicroPC(val); }
+ Addr instAddr() { return actualTC->instAddr(); }
+ Addr nextInstAddr() { return actualTC->nextInstAddr(); }
+ MicroPC microPC() { return actualTC->microPC(); }
bool readPredicate() { return actualTC->readPredicate(); }
diff --git a/src/kern/system_events.cc b/src/kern/system_events.cc
index 25856e466..612aabc0b 100644
--- a/src/kern/system_events.cc
+++ b/src/kern/system_events.cc
@@ -41,9 +41,10 @@ using namespace TheISA;
void
SkipFuncEvent::process(ThreadContext *tc)
{
- DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
- tc->readPC(), tc->readIntReg(ReturnAddressReg));
+ TheISA::PCState oldPC M5_VAR_USED = tc->pcState();
// Call ISA specific code to do the skipping
TheISA::skipFunction(tc);
+ DPRINTF(PCEvent, "skipping %s: pc = %s, newpc = %s\n", description,
+ oldPC, tc->pcState());
}
diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh
index d3348fe89..aa3c4bb50 100644
--- a/src/kern/tru64/tru64.hh
+++ b/src/kern/tru64/tru64.hh
@@ -509,7 +509,9 @@ class Tru64 : public OperatingSystem
// Note that we'll advance PC <- NPC before the end of the cycle,
// so we need to restore the desired PC into NPC.
// The current regs->pc will get clobbered.
- tc->setNextPC(htog(sc->sc_pc));
+ PCState pc = tc->pcState();
+ pc.npc(htog(sc->sc_pc));
+ tc->pcState(pc);
for (int i = 0; i < 31; ++i) {
tc->setIntReg(i, htog(sc->sc_regs[i]));
@@ -703,8 +705,7 @@ class Tru64 : public OperatingSystem
tc->setIntReg(TheISA::StackPointerReg, gtoh(attrp->registers.sp));
tc->setMiscRegNoEffect(AlphaISA::MISCREG_UNIQ, uniq_val);
- tc->setPC(gtoh(attrp->registers.pc));
- tc->setNextPC(gtoh(attrp->registers.pc) + sizeof(TheISA::MachInst));
+ tc->pcState(gtoh(attrp->registers.pc));
tc->activate();
}
diff --git a/src/sim/faults.cc b/src/sim/faults.cc
index 78b9fb0a4..fbe8fb32a 100644
--- a/src/sim/faults.cc
+++ b/src/sim/faults.cc
@@ -40,13 +40,12 @@
#if !FULL_SYSTEM
void FaultBase::invoke(ThreadContext * tc, StaticInstPtr inst)
{
- panic("fault (%s) detected @ PC %p", name(), tc->readPC());
+ panic("fault (%s) detected @ PC %s", name(), tc->pcState());
}
#else
void FaultBase::invoke(ThreadContext * tc, StaticInstPtr inst)
{
- DPRINTF(Fault, "Fault %s at PC: %#x\n", name(), tc->readPC());
-
+ DPRINTF(Fault, "Fault %s at PC: %s\n", name(), tc->pcState());
assert(!tc->misspeculating());
}
#endif
diff --git a/src/sim/insttracer.hh b/src/sim/insttracer.hh
index 845f4ed99..1ff67d2cb 100644
--- a/src/sim/insttracer.hh
+++ b/src/sim/insttracer.hh
@@ -54,9 +54,8 @@ class InstRecord
// need to make this ref-counted so it doesn't go away before we
// dump the record
StaticInstPtr staticInst;
- Addr PC;
+ TheISA::PCState pc;
StaticInstPtr macroStaticInst;
- MicroPC upc;
bool misspeculating;
bool predicate;
@@ -90,12 +89,11 @@ class InstRecord
public:
InstRecord(Tick _when, ThreadContext *_thread,
const StaticInstPtr _staticInst,
- Addr _pc, bool spec,
- const StaticInstPtr _macroStaticInst = NULL,
- MicroPC _upc = 0)
+ TheISA::PCState _pc, bool spec,
+ const StaticInstPtr _macroStaticInst = NULL)
: when(_when), thread(_thread),
- staticInst(_staticInst), PC(_pc),
- macroStaticInst(_macroStaticInst), upc(_upc),
+ staticInst(_staticInst), pc(_pc),
+ macroStaticInst(_macroStaticInst),
misspeculating(spec), predicate(true)
{
data_status = DataInvalid;
@@ -137,9 +135,8 @@ class InstRecord
Tick getWhen() { return when; }
ThreadContext *getThread() { return thread; }
StaticInstPtr getStaticInst() { return staticInst; }
- Addr getPC() { return PC; }
+ TheISA::PCState getPCState() { return pc; }
StaticInstPtr getMacroStaticInst() { return macroStaticInst; }
- MicroPC getUPC() { return upc; }
bool getMisspeculating() { return misspeculating; }
Addr getAddr() { return addr; }
@@ -167,9 +164,8 @@ class InstTracer : public SimObject
virtual InstRecord *
getInstRecord(Tick when, ThreadContext *tc,
- const StaticInstPtr staticInst, Addr pc,
- const StaticInstPtr macroStaticInst = NULL,
- MicroPC _upc = 0) = 0;
+ const StaticInstPtr staticInst, TheISA::PCState pc,
+ const StaticInstPtr macroStaticInst = NULL) = 0;
};
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
index 207c07309..60bb59790 100644
--- a/src/sim/syscall_emul.cc
+++ b/src/sim/syscall_emul.cc
@@ -824,9 +824,7 @@ cloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ctc->setIntReg(TheISA::SyscallPseudoReturnReg, 1);
#endif
- ctc->setPC(tc->readNextPC());
- ctc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst));
- ctc->setNextNPC(tc->readNextNPC() + sizeof(TheISA::MachInst));
+ ctc->pcState(tc->nextInstAddr());
ctc->activate();
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index eaec57ef5..f2847b2e5 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -512,8 +512,8 @@ ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
return -ENOTTY;
default:
- fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n",
- fd, req, tc->readPC());
+ fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n",
+ fd, req, tc->pcState());
}
}