summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch')
-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
95 files changed, 1518 insertions, 636 deletions
diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc
index 0db75df46..f97244260 100644
--- a/src/arch/alpha/ev5.cc
+++ b/src/arch/alpha/ev5.cc
@@ -60,8 +60,7 @@ initCPU(ThreadContext *tc, int cpuId)
AlphaFault *reset = new ResetFault;
- tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect());
- tc->setNextPC(tc->readPC() + sizeof(MachInst));
+ tc->pcState(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect());
delete reset;
}
@@ -494,12 +493,14 @@ using namespace AlphaISA;
Fault
SimpleThread::hwrei()
{
- if (!(readPC() & 0x3))
+ PCState pc = pcState();
+ if (!(pc.pc() & 0x3))
return new UnimplementedOpcodeFault;
- setNextPC(readMiscRegNoEffect(IPR_EXC_ADDR));
+ pc.npc(readMiscRegNoEffect(IPR_EXC_ADDR));
+ pcState(pc);
- CPA::cpa()->swAutoBegin(tc, readNextPC());
+ CPA::cpa()->swAutoBegin(tc, pc.npc());
if (!misspeculating()) {
if (kernelStats)
diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc
index 9d4eeda8a..38386cce1 100644
--- a/src/arch/alpha/faults.cc
+++ b/src/arch/alpha/faults.cc
@@ -115,9 +115,11 @@ AlphaFault::invoke(ThreadContext *tc, StaticInstPtr inst)
FaultBase::invoke(tc);
countStat()++;
+ PCState pc = tc->pcState();
+
// exception restart address
- if (setRestartAddress() || !(tc->readPC() & 0x3))
- tc->setMiscRegNoEffect(IPR_EXC_ADDR, tc->readPC());
+ if (setRestartAddress() || !(pc.pc() & 0x3))
+ tc->setMiscRegNoEffect(IPR_EXC_ADDR, pc.pc());
if (skipFaultingInstruction()) {
// traps... skip faulting instruction.
@@ -125,8 +127,8 @@ AlphaFault::invoke(ThreadContext *tc, StaticInstPtr inst)
tc->readMiscRegNoEffect(IPR_EXC_ADDR) + 4);
}
- tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + vect());
- tc->setNextPC(tc->readPC() + sizeof(MachInst));
+ pc.set(tc->readMiscRegNoEffect(IPR_PAL_BASE) + vect());
+ tc->pcState(pc);
}
void
diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh
index 3200201db..cbaa8e9bf 100644
--- a/src/arch/alpha/interrupts.hh
+++ b/src/arch/alpha/interrupts.hh
@@ -133,7 +133,7 @@ class Interrupts : public SimObject
bool
checkInterrupts(ThreadContext *tc) const
{
- return (intstatus != 0) && !(tc->readPC() & 0x3);
+ return (intstatus != 0) && !(tc->pcState().pc() & 0x3);
}
Fault
diff --git a/src/arch/alpha/isa/branch.isa b/src/arch/alpha/isa/branch.isa
index 974193efd..feb15b158 100644
--- a/src/arch/alpha/isa/branch.isa
+++ b/src/arch/alpha/isa/branch.isa
@@ -81,7 +81,7 @@ output header {{
{
}
- Addr branchTarget(Addr branchPC) const;
+ AlphaISA::PCState branchTarget(const AlphaISA::PCState &branchPC) const;
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
@@ -106,7 +106,7 @@ output header {{
{
}
- Addr branchTarget(ThreadContext *tc) const;
+ AlphaISA::PCState branchTarget(ThreadContext *tc) const;
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
@@ -114,18 +114,19 @@ output header {{
}};
output decoder {{
- Addr
- Branch::branchTarget(Addr branchPC) const
+ AlphaISA::PCState
+ Branch::branchTarget(const AlphaISA::PCState &branchPC) const
{
- return branchPC + 4 + disp;
+ return branchPC.pc() + 4 + disp;
}
- Addr
+ AlphaISA::PCState
Jump::branchTarget(ThreadContext *tc) const
{
- Addr NPC = tc->readPC() + 4;
+ PCState pc = tc->pcState();
uint64_t Rb = tc->readIntReg(_srcRegIdx[0]);
- return (Rb & ~3) | (NPC & 1);
+ pc.set((Rb & ~3) | (pc.pc() & 1));
+ return pc;
}
const std::string &
@@ -217,7 +218,14 @@ def template JumpOrBranchDecode {{
}};
def format CondBranch(code) {{
- code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
+ code = '''
+ bool cond;
+ %(code)s;
+ PCState pc = PCS;
+ if (cond)
+ pc.npc(pc.npc() + disp);
+ PCS = pc;
+ ''' % { "code" : code }
iop = InstObjParams(name, Name, 'Branch', code,
('IsDirectControl', 'IsCondControl'))
header_output = BasicDeclare.subst(iop)
@@ -229,16 +237,18 @@ def format CondBranch(code) {{
let {{
def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
# Declare basic control transfer w/o link (i.e. link reg is R31)
- nolink_code = 'NPC = %s;\n' % npc_expr
- nolink_iop = InstObjParams(name, Name, base_class, nolink_code, flags)
+ readpc_code = 'PCState pc = PCS;'
+ nolink_code = 'pc.npc(%s);\nPCS = pc' % npc_expr
+ nolink_iop = InstObjParams(name, Name, base_class,
+ readpc_code + nolink_code, flags)
header_output = BasicDeclare.subst(nolink_iop)
decoder_output = BasicConstructor.subst(nolink_iop)
exec_output = BasicExecute.subst(nolink_iop)
# Generate declaration of '*AndLink' version, append to decls
- link_code = 'Ra = NPC & ~3;\n' + nolink_code
+ link_code = 'Ra = pc.npc() & ~3;\n' + nolink_code
link_iop = InstObjParams(name, Name + 'AndLink', base_class,
- link_code, flags)
+ readpc_code + link_code, flags)
header_output += BasicDeclare.subst(link_iop)
decoder_output += BasicConstructor.subst(link_iop)
exec_output += BasicExecute.subst(link_iop)
@@ -253,13 +263,13 @@ def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
def format UncondBranch(*flags) {{
flags += ('IsUncondControl', 'IsDirectControl')
(header_output, decoder_output, decode_block, exec_output) = \
- UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
+ UncondCtrlBase(name, Name, 'Branch', 'pc.npc() + disp', flags)
}};
def format Jump(*flags) {{
flags += ('IsUncondControl', 'IsIndirectControl')
(header_output, decoder_output, decode_block, exec_output) = \
- UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
+ UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (pc.npc() & 1)', flags)
}};
diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa
index fe70e4d16..e2947cf4a 100644
--- a/src/arch/alpha/isa/decoder.isa
+++ b/src/arch/alpha/isa/decoder.isa
@@ -856,15 +856,16 @@ decode OPCODE default Unknown::unknown() {
// invalid pal function code, or attempt to do privileged
// PAL call in non-kernel mode
fault = new UnimplementedOpcodeFault;
- }
- else {
+ } else {
// check to see if simulator wants to do something special
// on this PAL call (including maybe suppress it)
bool dopal = xc->simPalCheck(palFunc);
if (dopal) {
- xc->setMiscReg(IPR_EXC_ADDR, NPC);
- NPC = xc->readMiscReg(IPR_PAL_BASE) + palOffset;
+ PCState pc = PCS;
+ xc->setMiscReg(IPR_EXC_ADDR, pc.npc());
+ pc.npc(xc->readMiscReg(IPR_PAL_BASE) + palOffset);
+ PCS = pc;
}
}
}}, IsNonSpeculative);
@@ -1030,13 +1031,14 @@ decode OPCODE default Unknown::unknown() {
}}, IsNonSpeculative);
#endif
0x54: m5panic({{
- panic("M5 panic instruction called at pc=%#x.", xc->readPC());
+ panic("M5 panic instruction called at pc=%#x.",
+ xc->pcState().pc());
}}, IsNonSpeculative);
#define CPANN(lbl) CPA::cpa()->lbl(xc->tcBase())
0x55: decode RA {
0x00: m5a_old({{
panic("Deprecated M5 annotate instruction executed at pc=%#x\n",
- xc->readPC());
+ xc->pcState().pc());
}}, IsNonSpeculative);
0x01: m5a_bsm({{
CPANN(swSmBegin);
diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa
index 2a0699354..ffc267cd2 100644
--- a/src/arch/alpha/isa/main.isa
+++ b/src/arch/alpha/isa/main.isa
@@ -46,6 +46,7 @@ output header {{
#include <iomanip>
#include "arch/alpha/faults.hh"
+#include "arch/alpha/types.hh"
#include "config/ss_compatible_fp.hh"
#include "cpu/static_inst.hh"
#include "mem/request.hh" // some constructors use MemReq flags
@@ -185,7 +186,7 @@ def operands {{
'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),
'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
- 'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
+ 'PCS': ('PCState', 'uq', None, ( None, None, 'IsControl' ), 4),
'Runiq': ('ControlReg', 'uq', 'MISCREG_UNIQ', None, 1),
'FPCR': ('ControlReg', 'uq', 'MISCREG_FPCR', None, 1),
'IntrFlag': ('ControlReg', 'uq', 'MISCREG_INTR', None, 1),
@@ -233,6 +234,12 @@ output header {{
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ void
+ advancePC(AlphaISA::PCState &pcState) const
+ {
+ pcState.advance();
+ }
};
}};
diff --git a/src/arch/alpha/predecoder.hh b/src/arch/alpha/predecoder.hh
index 913bd8764..f9a716b7f 100644
--- a/src/arch/alpha/predecoder.hh
+++ b/src/arch/alpha/predecoder.hh
@@ -76,11 +76,11 @@ class Predecoder
// Use this to give data to the predecoder. This should be used
// when there is control flow.
void
- moreBytes(Addr pc, Addr fetchPC, MachInst inst)
+ moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
{
ext_inst = inst;
#if FULL_SYSTEM
- ext_inst |= (static_cast<ExtMachInst>(pc & 0x1) << 32);
+ ext_inst |= (static_cast<ExtMachInst>(pc.pc() & 0x1) << 32);
#endif
}
@@ -98,7 +98,7 @@ class Predecoder
// This returns a constant reference to the ExtMachInst to avoid a copy
const ExtMachInst &
- getExtMachInst()
+ getExtMachInst(PCState &pc)
{
return ext_inst;
}
diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc
index f68a53a6f..3c3fd9b25 100644
--- a/src/arch/alpha/process.cc
+++ b/src/arch/alpha/process.cc
@@ -162,15 +162,7 @@ AlphaLiveProcess::argsInit(int intSize, int pageSize)
setSyscallArg(tc, 1, argv_array_base);
tc->setIntReg(StackPointerReg, stack_min);
- Addr prog_entry = objFile->entryPoint();
- tc->setPC(prog_entry);
- tc->setNextPC(prog_entry + sizeof(MachInst));
-
- // MIPS/Sparc need NNPC for delay slot handling, while
- // Alpha has no delay slots... However, CPU models
- // cycle PCs by PC=NPC, NPC=NNPC, etc. so setting this
- // here ensures CPU-Model Compatibility across board
- tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
+ tc->pcState(objFile->entryPoint());
}
void
diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc
index 5391d2056..9a2a5f23f 100644
--- a/src/arch/alpha/remote_gdb.cc
+++ b/src/arch/alpha/remote_gdb.cc
@@ -211,7 +211,7 @@ RemoteGDB::getregs()
{
memset(gdbregs.regs, 0, gdbregs.bytes());
- gdbregs.regs[KGDB_REG_PC] = context->readPC();
+ gdbregs.regs[KGDB_REG_PC] = context->pcState().pc();
// @todo: Currently this is very Alpha specific.
if (PcPAL(gdbregs.regs[KGDB_REG_PC])) {
@@ -254,7 +254,7 @@ RemoteGDB::setregs()
context->setFloatRegBits(i, gdbregs.regs[i + KGDB_REG_F0]);
}
#endif
- context->setPC(gdbregs.regs[KGDB_REG_PC]);
+ context->pcState(gdbregs.regs[KGDB_REG_PC]);
}
void
@@ -273,30 +273,28 @@ RemoteGDB::clearSingleStep()
void
RemoteGDB::setSingleStep()
{
- Addr pc = context->readPC();
- Addr npc, bpc;
+ PCState pc = context->pcState();
+ PCState bpc;
bool set_bt = false;
- npc = pc + sizeof(MachInst);
-
// User was stopped at pc, e.g. the instruction at pc was not
// executed.
- MachInst inst = read<MachInst>(pc);
- StaticInstPtr si(inst, pc);
+ MachInst inst = read<MachInst>(pc.pc());
+ StaticInstPtr si(inst, pc.pc());
if (si->hasBranchTarget(pc, context, bpc)) {
// Don't bother setting a breakpoint on the taken branch if it
// is the same as the next pc
- if (bpc != npc)
+ if (bpc.pc() != pc.npc())
set_bt = true;
}
DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n",
takenBkpt, notTakenBkpt);
- setTempBreakpoint(notTakenBkpt = npc);
+ setTempBreakpoint(notTakenBkpt = pc.npc());
if (set_bt)
- setTempBreakpoint(takenBkpt = bpc);
+ setTempBreakpoint(takenBkpt = bpc.pc());
}
// Write bytes to kernel address space for debugger.
diff --git a/src/arch/alpha/stacktrace.cc b/src/arch/alpha/stacktrace.cc
index 1b5a9be34..9c6b3cff0 100644
--- a/src/arch/alpha/stacktrace.cc
+++ b/src/arch/alpha/stacktrace.cc
@@ -145,7 +145,7 @@ StackTrace::trace(ThreadContext *_tc, bool is_call)
bool usermode =
(tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0;
- Addr pc = tc->readNextPC();
+ Addr pc = tc->pcState().pc();
bool kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd;
if (usermode) {
@@ -168,7 +168,7 @@ StackTrace::trace(ThreadContext *_tc, bool is_call)
panic("could not find address %#x", pc);
stack.push_back(addr);
- pc = tc->readPC();
+ pc = tc->pcState().pc();
}
while (ksp > bottom) {
diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc
index b578741d9..614061ddd 100644
--- a/src/arch/alpha/tlb.cc
+++ b/src/arch/alpha/tlb.cc
@@ -443,8 +443,6 @@ TLB::translateInst(RequestPtr req, ThreadContext *tc)
Fault
TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
{
- Addr pc = tc->readPC();
-
mode_type mode =
(mode_type)DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM));
@@ -458,7 +456,7 @@ TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags);
}
- if (PcPAL(pc)) {
+ if (PcPAL(tc->pcState().pc())) {
mode = (req->getFlags() & Request::ALTMODE) ?
(mode_type)ALT_MODE_AM(
tc->readMiscRegNoEffect(IPR_ALT_MODE))
diff --git a/src/arch/alpha/types.hh b/src/arch/alpha/types.hh
index 0d285c3b2..06c0168cf 100644
--- a/src/arch/alpha/types.hh
+++ b/src/arch/alpha/types.hh
@@ -33,12 +33,15 @@
#define __ARCH_ALPHA_TYPES_HH__
#include "base/types.hh"
+#include "arch/generic/types.hh"
namespace AlphaISA {
typedef uint32_t MachInst;
typedef uint64_t ExtMachInst;
+typedef GenericISA::SimplePCState<MachInst> PCState;
+
typedef uint64_t LargestRead;
enum annotes
diff --git a/src/arch/alpha/utility.cc b/src/arch/alpha/utility.cc
index 11560259f..2d56ca9b8 100644
--- a/src/arch/alpha/utility.cc
+++ b/src/arch/alpha/utility.cc
@@ -77,8 +77,7 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
copyMiscRegs(src, dest);
// Lastly copy PC/NPC
- dest->setPC(src->readPC());
- dest->setNextPC(src->readNextPC());
+ dest->pcState(src->pcState());
}
void
@@ -99,9 +98,9 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
void
skipFunction(ThreadContext *tc)
{
- Addr newpc = tc->readIntReg(ReturnAddressReg);
- tc->setPC(newpc);
- tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
+ TheISA::PCState newPC = tc->pcState();
+ newPC.set(tc->readIntReg(ReturnAddressReg));
+ tc->pcState(newPC);
}
diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh
index 6d5b8baf6..fdac8b8d1 100644
--- a/src/arch/alpha/utility.hh
+++ b/src/arch/alpha/utility.hh
@@ -37,10 +37,19 @@
#include "arch/alpha/registers.hh"
#include "base/misc.hh"
#include "config/full_system.hh"
+#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
namespace AlphaISA {
+inline PCState
+buildRetPC(const PCState &curPC, const PCState &callPC)
+{
+ PCState retPC = callPC;
+ retPC.advance();
+ return retPC;
+}
+
uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp);
inline bool
@@ -95,6 +104,13 @@ void copyRegs(ThreadContext *src, ThreadContext *dest);
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
void skipFunction(ThreadContext *tc);
+
+inline void
+advancePC(PCState &pc, const StaticInstPtr inst)
+{
+ pc.advance();
+}
+
} // namespace AlphaISA
#endif // __ARCH_ALPHA_UTILITY_HH__
diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc
index 6e138119c..54cf5cfe5 100644
--- a/src/arch/arm/faults.cc
+++ b/src/arch/arm/faults.cc
@@ -104,6 +104,7 @@ ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst)
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR) |
tc->readIntReg(INTREG_CONDCODES);
+ Addr curPc M5_VAR_USED = tc->pcState().pc();
cpsr.mode = nextMode();
@@ -116,7 +117,7 @@ ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst)
cpsr.i = 1;
cpsr.e = sctlr.ee;
tc->setMiscReg(MISCREG_CPSR, cpsr);
- tc->setIntReg(INTREG_LR, tc->readPC() +
+ tc->setIntReg(INTREG_LR, curPc +
(saved_cpsr.t ? thumbPcOffset() : armPcOffset()));
switch (nextMode()) {
@@ -139,14 +140,15 @@ ArmFault::invoke(ThreadContext *tc, StaticInstPtr inst)
panic("unknown Mode\n");
}
- Addr pc M5_VAR_USED = tc->readPC();
- Addr newPc = getVector(tc) | (sctlr.te ? PcTBit : 0);
+ Addr newPc = getVector(tc);
DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n",
- name(), cpsr, pc, tc->readIntReg(INTREG_LR), newPc);
- tc->setPC(newPc);
- tc->setNextPC(newPc + cpsr.t ? 2 : 4 );
- tc->setMicroPC(0);
- tc->setNextMicroPC(1);
+ name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc);
+ PCState pc(newPc);
+ pc.thumb(cpsr.t);
+ pc.nextThumb(pc.thumb());
+ pc.jazelle(cpsr.j);
+ pc.nextJazelle(pc.jazelle());
+ tc->pcState(pc);
}
void
@@ -193,10 +195,10 @@ SupervisorCall::invoke(ThreadContext *tc, StaticInstPtr inst)
tc->syscall(callNum);
// Advance the PC since that won't happen automatically.
- tc->setPC(tc->readNextPC());
- tc->setNextPC(tc->readNextNPC());
- tc->setMicroPC(0);
- tc->setNextMicroPC(1);
+ PCState pc = tc->pcState();
+ assert(inst);
+ inst->advancePC(pc);
+ tc->pcState(pc);
}
#endif // FULL_SYSTEM
@@ -223,10 +225,10 @@ FlushPipe::invoke(ThreadContext *tc, StaticInstPtr inst) {
// Set the PC to the next instruction of the faulting instruction.
// Net effect is simply squashing all instructions behind and
// start refetching from the next instruction.
- tc->setPC(tc->readNextPC());
- tc->setNextPC(tc->readNextNPC());
- tc->setMicroPC(0);
- tc->setNextMicroPC(1);
+ PCState pc = tc->pcState();
+ assert(inst);
+ inst->advancePC(pc);
+ tc->pcState(pc);
}
template void AbortFault<PrefetchAbort>::invoke(ThreadContext *tc,
diff --git a/src/arch/arm/insts/macromem.hh b/src/arch/arm/insts/macromem.hh
index c1c8383da..018cb1de5 100644
--- a/src/arch/arm/insts/macromem.hh
+++ b/src/arch/arm/insts/macromem.hh
@@ -77,6 +77,18 @@ class MicroOp : public PredOp
{
flags[IsDelayedCommit] = true;
}
+
+ void
+ advancePC(PCState &pcState) const
+ {
+ if (flags[IsLastMicroop]) {
+ pcState.uEnd();
+ } else if (flags[IsMicroop]) {
+ pcState.uAdvance();
+ } else {
+ pcState.advance();
+ }
+ }
};
/**
diff --git a/src/arch/arm/insts/mem.hh b/src/arch/arm/insts/mem.hh
index 1baba5112..2aa4de1d7 100644
--- a/src/arch/arm/insts/mem.hh
+++ b/src/arch/arm/insts/mem.hh
@@ -63,8 +63,28 @@ class Swap : public PredOp
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
+class MightBeMicro : public PredOp
+{
+ protected:
+ MightBeMicro(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
+ : PredOp(mnem, _machInst, __opClass)
+ {}
+
+ void
+ advancePC(PCState &pcState) const
+ {
+ if (flags[IsLastMicroop]) {
+ pcState.uEnd();
+ } else if (flags[IsMicroop]) {
+ pcState.uAdvance();
+ } else {
+ pcState.advance();
+ }
+ }
+};
+
// The address is a base register plus an immediate.
-class RfeOp : public PredOp
+class RfeOp : public MightBeMicro
{
public:
enum AddrMode {
@@ -83,7 +103,7 @@ class RfeOp : public PredOp
RfeOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
IntRegIndex _base, AddrMode _mode, bool _wb)
- : PredOp(mnem, _machInst, __opClass),
+ : MightBeMicro(mnem, _machInst, __opClass),
base(_base), mode(_mode), wb(_wb), uops(NULL)
{}
@@ -94,7 +114,7 @@ class RfeOp : public PredOp
}
StaticInstPtr
- fetchMicroop(MicroPC microPC)
+ fetchMicroop(MicroPC microPC) const
{
assert(uops != NULL && microPC < numMicroops);
return uops[microPC];
@@ -104,7 +124,7 @@ class RfeOp : public PredOp
};
// The address is a base register plus an immediate.
-class SrsOp : public PredOp
+class SrsOp : public MightBeMicro
{
public:
enum AddrMode {
@@ -123,7 +143,7 @@ class SrsOp : public PredOp
SrsOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
uint32_t _regMode, AddrMode _mode, bool _wb)
- : PredOp(mnem, _machInst, __opClass),
+ : MightBeMicro(mnem, _machInst, __opClass),
regMode(_regMode), mode(_mode), wb(_wb), uops(NULL)
{}
@@ -134,7 +154,7 @@ class SrsOp : public PredOp
}
StaticInstPtr
- fetchMicroop(MicroPC microPC)
+ fetchMicroop(MicroPC microPC) const
{
assert(uops != NULL && microPC < numMicroops);
return uops[microPC];
@@ -143,7 +163,7 @@ class SrsOp : public PredOp
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
-class Memory : public PredOp
+class Memory : public MightBeMicro
{
public:
enum AddrMode {
@@ -163,7 +183,7 @@ class Memory : public PredOp
Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
IntRegIndex _dest, IntRegIndex _base, bool _add)
- : PredOp(mnem, _machInst, __opClass),
+ : MightBeMicro(mnem, _machInst, __opClass),
dest(_dest), base(_base), add(_add), uops(NULL)
{}
@@ -174,7 +194,7 @@ class Memory : public PredOp
}
StaticInstPtr
- fetchMicroop(MicroPC microPC)
+ fetchMicroop(MicroPC microPC) const
{
assert(uops != NULL && microPC < numMicroops);
return uops[microPC];
diff --git a/src/arch/arm/insts/pred_inst.hh b/src/arch/arm/insts/pred_inst.hh
index b7d4c4709..f779b46f5 100644
--- a/src/arch/arm/insts/pred_inst.hh
+++ b/src/arch/arm/insts/pred_inst.hh
@@ -312,7 +312,7 @@ class PredMacroOp : public PredOp
}
StaticInstPtr
- fetchMicroop(MicroPC microPC)
+ fetchMicroop(MicroPC microPC) const
{
assert(microPC < numMicroops);
return microOps[microPC];
@@ -332,6 +332,15 @@ class PredMicroop : public PredOp
{
flags[IsMicroop] = true;
}
+
+ void
+ advancePC(PCState &pcState) const
+ {
+ if (flags[IsLastMicroop])
+ pcState.uEnd();
+ else
+ pcState.uAdvance();
+ }
};
}
diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh
index ad89a1a79..fa850190f 100644
--- a/src/arch/arm/insts/static_inst.hh
+++ b/src/arch/arm/insts/static_inst.hh
@@ -155,6 +155,12 @@ class ArmStaticInst : public StaticInst
IntRegIndex rs, uint32_t shiftAmt, ArmShiftType type,
uint32_t imm) const;
+ void
+ advancePC(PCState &pcState) const
+ {
+ pcState.advance();
+ }
+
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
static inline uint32_t
@@ -219,26 +225,16 @@ class ArmStaticInst : public StaticInst
static inline Addr
readPC(XC *xc)
{
- Addr pc = xc->readPC();
- if (isThumb(pc))
- return pc + 4;
- else
- return pc + 8;
+ return xc->pcState().instPC();
}
- // Perform an regular branch.
template<class XC>
static inline void
setNextPC(XC *xc, Addr val)
{
- Addr npc = xc->readNextPC();
- if (isThumb(npc)) {
- val &= ~mask(1);
- } else {
- val &= ~mask(2);
- }
- xc->setNextPC((npc & PcModeMask) |
- (val & ~PcModeMask));
+ PCState pc = xc->pcState();
+ pc.instNPC(val);
+ xc->pcState(pc);
}
template<class T>
@@ -279,30 +275,9 @@ class ArmStaticInst : public StaticInst
static inline void
setIWNextPC(XC *xc, Addr val)
{
- Addr stateBits = xc->readPC() & PcModeMask;
- Addr jBit = PcJBit;
- Addr tBit = PcTBit;
- bool thumbEE = (stateBits == (tBit | jBit));
-
- Addr newPc = (val & ~PcModeMask);
- if (thumbEE) {
- if (bits(newPc, 0)) {
- newPc = newPc & ~mask(1);
- } else {
- panic("Bad thumbEE interworking branch address %#x.\n", newPc);
- }
- } else {
- if (bits(newPc, 0)) {
- stateBits = tBit;
- newPc = newPc & ~mask(1);
- } else if (!bits(newPc, 1)) {
- stateBits = 0;
- } else {
- warn("Bad interworking branch address %#x.\n", newPc);
- }
- }
- newPc = newPc | stateBits;
- xc->setNextPC(newPc);
+ PCState pc = xc->pcState();
+ pc.instIWNPC(val);
+ xc->pcState(pc);
}
// Perform an interworking branch in ARM mode, a regular branch
@@ -311,14 +286,9 @@ class ArmStaticInst : public StaticInst
static inline void
setAIWNextPC(XC *xc, Addr val)
{
- Addr stateBits = xc->readPC() & PcModeMask;
- Addr jBit = PcJBit;
- Addr tBit = PcTBit;
- if (!jBit && !tBit) {
- setIWNextPC(xc, val);
- } else {
- setNextPC(xc, val);
- }
+ PCState pc = xc->pcState();
+ pc.instAIWNPC(val);
+ xc->pcState(pc);
}
inline Fault
diff --git a/src/arch/arm/insts/vfp.hh b/src/arch/arm/insts/vfp.hh
index 964b62673..e962704e0 100644
--- a/src/arch/arm/insts/vfp.hh
+++ b/src/arch/arm/insts/vfp.hh
@@ -459,6 +459,18 @@ class FpOp : public PredOp
unaryOp(FPSCR &fpscr, fpType op1,
fpType (*func)(fpType),
bool flush, uint32_t rMode) const;
+
+ void
+ advancePC(PCState &pcState) const
+ {
+ if (flags[IsLastMicroop]) {
+ pcState.uEnd();
+ } else if (flags[IsMicroop]) {
+ pcState.uAdvance();
+ } else {
+ pcState.advance();
+ }
+ }
};
class FpRegRegOp : public FpOp
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc
index d557cecbb..0ba62f08d 100644
--- a/src/arch/arm/isa.cc
+++ b/src/arch/arm/isa.cc
@@ -168,15 +168,9 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc)
{
if (misc_reg == MISCREG_CPSR) {
CPSR cpsr = miscRegs[misc_reg];
- Addr pc = tc->readPC();
- if (pc & (ULL(1) << PcJBitShift))
- cpsr.j = 1;
- else
- cpsr.j = 0;
- if (isThumb(pc))
- cpsr.t = 1;
- else
- cpsr.t = 0;
+ PCState pc = tc->pcState();
+ cpsr.j = pc.jazelle() ? 1 : 0;
+ cpsr.t = pc.thumb() ? 1 : 0;
return cpsr;
}
if (misc_reg >= MISCREG_CP15_UNIMP_START &&
@@ -239,13 +233,10 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
CPSR cpsr = val;
DPRINTF(Arm, "Updating CPSR from %#x to %#x f:%d i:%d a:%d mode:%#x\n",
miscRegs[misc_reg], cpsr, cpsr.f, cpsr.i, cpsr.a, cpsr.mode);
- Addr npc = tc->readNextPC() & ~PcModeMask;
- if (cpsr.j)
- npc = npc | PcJBit;
- if (cpsr.t)
- npc = npc | PcTBit;
-
- tc->setNextPC(npc);
+ PCState pc = tc->pcState();
+ pc.nextThumb(cpsr.t);
+ pc.nextJazelle(cpsr.j);
+ tc->pcState(pc);
} else if (misc_reg >= MISCREG_CP15_UNIMP_START &&
misc_reg < MISCREG_CP15_END) {
panic("Unimplemented CP15 register %s wrote with %#x.\n",
@@ -414,7 +405,7 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
default:
panic("Security Extensions not implemented!");
}
- req->setVirt(0, val, 1, flags, tc->readPC());
+ req->setVirt(0, val, 1, flags, tc->pcState().pc());
fault = tc->getDTBPtr()->translateAtomic(req, tc, mode);
if (fault == NoFault) {
miscRegs[MISCREG_PAR] =
diff --git a/src/arch/arm/isa/formats/breakpoint.isa b/src/arch/arm/isa/formats/breakpoint.isa
index d59f6a712..1825d0878 100644
--- a/src/arch/arm/isa/formats/breakpoint.isa
+++ b/src/arch/arm/isa/formats/breakpoint.isa
@@ -83,7 +83,7 @@ output exec {{
Breakpoint::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
- return new PrefetchAbort(xc->readPC(), ArmFault::DebugEvent);
+ return new PrefetchAbort(xc->pcState().pc(), ArmFault::DebugEvent);
}
}};
diff --git a/src/arch/arm/isa/insts/branch.isa b/src/arch/arm/isa/insts/branch.isa
index e9ddd77b7..3ff9042e6 100644
--- a/src/arch/arm/isa/insts/branch.isa
+++ b/src/arch/arm/isa/insts/branch.isa
@@ -46,15 +46,17 @@ let {{
# B, BL
for (mnem, link) in (("b", False), ("bl", True)):
bCode = '''
- Addr curPc = readPC(xc);
- NPC = ((curPc + imm) & mask(32)) | (curPc & ~mask(32));
+ ArmISA::PCState pc = PCS;
+ Addr curPc = pc.instPC();
+ pc.instNPC((uint32_t)(curPc + imm));
+ PCS = pc;
'''
if (link):
bCode += '''
- if (!isThumb(curPc))
- LR = curPc - 4;
- else
+ if (pc.thumb())
LR = curPc | 1;
+ else
+ LR = curPc - 4;
'''
bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond",
@@ -66,10 +68,12 @@ let {{
# BX, BLX
blxCode = '''
- Addr curPc M5_VAR_USED = readPC(xc);
+ ArmISA::PCState pc = PCS;
+ Addr curPc M5_VAR_USED = pc.instPC();
%(link)s
// Switch modes
%(branch)s
+ PCS = pc;
'''
blxList = (("blx", True, True),
@@ -81,8 +85,8 @@ let {{
if imm:
Name += "Imm"
# Since we're switching ISAs, the target ISA will be the opposite
- # of the current ISA. !arm is whether the target is ARM.
- newPC = '(isThumb(curPc) ? (roundDown(curPc, 4) + imm) : (curPc + imm))'
+ # of the current ISA. pc.thumb() is whether the target is ARM.
+ newPC = '(pc.thumb() ? (roundDown(curPc, 4) + imm) : (curPc + imm))'
base = "BranchImmCond"
declare = BranchImmCondDeclare
constructor = BranchImmCondConstructor
@@ -97,28 +101,28 @@ let {{
// The immediate version of the blx thumb instruction
// is 32 bits wide, but "next pc" doesn't reflect that
// so we don't want to substract 2 from it at this point
- if (!isThumb(curPc))
- LR = curPc - 4;
- else
+ if (pc.thumb())
LR = curPc | 1;
+ else
+ LR = curPc - 4;
'''
elif link:
linkStr = '''
- if (!isThumb(curPc))
- LR = curPc - 4;
- else
+ if (pc.thumb())
LR = (curPc - 2) | 1;
+ else
+ LR = curPc - 4;
'''
else:
linkStr = ""
if imm and link: #blx with imm
branchStr = '''
- Addr tempPc = ((%(newPC)s) & mask(32)) | (curPc & ~mask(32));
- FNPC = tempPc ^ PcTBit;
+ pc.nextThumb(!pc.thumb());
+ pc.instNPC(%(newPC)s);
'''
else:
- branchStr = "IWNPC = %(newPC)s;"
+ branchStr = "pc.instIWNPC(%(newPC)s);"
branchStr = branchStr % { "newPC" : newPC }
code = blxCode % {"link": linkStr,
@@ -136,8 +140,10 @@ let {{
#CBNZ, CBZ. These are always unconditional as far as predicates
for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")):
code = '''
- Addr curPc = readPC(xc);
- NPC = ((curPc + imm) & mask(32)) | (curPc & ~mask(32));
+ ArmISA::PCState pc = PCS;
+ Addr curPc = pc.instPC();
+ pc.instNPC((uint32_t)(curPc + imm));
+ PCS = pc;
'''
predTest = "Op1 %(test)s 0" % {"test": test}
iop = InstObjParams(mnem, mnem.capitalize(), "BranchImmReg",
@@ -155,7 +161,11 @@ let {{
ArmISA::TLB::MustBeOne;
EA = Op1 + Op2 * 2
'''
- accCode = "NPC = readPC(xc) + 2 * (Mem.uh);"
+ accCode = '''
+ ArmISA::PCState pc = PCS;
+ pc.instNPC(pc.instPC() + 2 * (Mem.uh));
+ PCS = pc;
+ '''
mnem = "tbh"
else:
eaCode = '''
@@ -164,7 +174,11 @@ let {{
ArmISA::TLB::MustBeOne;
EA = Op1 + Op2
'''
- accCode = "NPC = readPC(xc) + 2 * (Mem.ub);"
+ accCode = '''
+ ArmISA::PCState pc = PCS;
+ pc.instNPC(pc.instPC() + 2 * (Mem.ub));
+ PCS = pc;
+ '''
mnem = "tbb"
iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg",
{'ea_code': eaCode,
diff --git a/src/arch/arm/isa/insts/data.isa b/src/arch/arm/isa/insts/data.isa
index 74eeee3b2..4d368e181 100644
--- a/src/arch/arm/isa/insts/data.isa
+++ b/src/arch/arm/isa/insts/data.isa
@@ -239,6 +239,10 @@ let {{
cpsrWriteByInstr(Cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
+ ArmISA::PCState pc = PCS;
+ pc.nextThumb(((CPSR)newCpsr).t);
+ pc.nextJazelle(((CPSR)newCpsr).j);
+ PCS = pc;
'''
buildImmDataInst(mnem + 's', code, flagType,
suffix = "ImmPclr", buildCc = False,
@@ -253,7 +257,8 @@ let {{
buildDataInst("rsb", "Dest = resTemp = secondOp - Op1;", "rsb")
buildDataInst("add", "Dest = resTemp = Op1 + secondOp;", "add")
buildImmDataInst("adr", '''
- Dest = resTemp = (readPC(xc) & ~0x3) +
+ ArmISA::PCState pc = PCS;
+ Dest = resTemp = (pc.instPC() & ~0x3) +
(op1 ? secondOp : -secondOp);
''')
buildDataInst("adc", "Dest = resTemp = Op1 + secondOp + %s;" % oldC, "add")
diff --git a/src/arch/arm/isa/insts/ldr.isa b/src/arch/arm/isa/insts/ldr.isa
index dc043ed8e..92ad52a6d 100644
--- a/src/arch/arm/isa/insts/ldr.isa
+++ b/src/arch/arm/isa/insts/ldr.isa
@@ -105,12 +105,16 @@ let {{
accCode = '''
CPSR cpsr = Cpsr;
SCTLR sctlr = Sctlr;
- NPC = cSwap<uint32_t>(Mem.ud, cpsr.e);
+ ArmISA::PCState pc = PCS;
+ pc.instNPC(cSwap<uint32_t>(Mem.ud, cpsr.e));
uint32_t newCpsr =
cpsrWriteByInstr(cpsr | CondCodes,
cSwap<uint32_t>(Mem.ud >> 32, cpsr.e),
0xF, true, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
+ pc.nextThumb(((CPSR)newCpsr).t);
+ pc.nextJazelle(((CPSR)newCpsr).j);
+ PCS = pc;
CondCodes = CondCodesMask & newCpsr;
'''
self.codeBlobs["memacc_code"] = accCode
diff --git a/src/arch/arm/isa/insts/macromem.isa b/src/arch/arm/isa/insts/macromem.isa
index 6bf789efd..a81050b1e 100644
--- a/src/arch/arm/isa/insts/macromem.isa
+++ b/src/arch/arm/isa/insts/macromem.isa
@@ -93,7 +93,9 @@ let {{
cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr;
- IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
+ ArmISA::PCState pc = PCS;
+ pc.instIWNPC(cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0));
+ PCS = pc;
'''
microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
'MicroMemOp',
diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa
index 5742f84ab..1abbc3de1 100644
--- a/src/arch/arm/isa/insts/misc.isa
+++ b/src/arch/arm/isa/insts/misc.isa
@@ -83,6 +83,10 @@ let {{
uint32_t newCpsr =
cpsrWriteByInstr(Cpsr | CondCodes, Op1, byteMask, false, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
+ ArmISA::PCState pc = PCS;
+ pc.nextThumb(((CPSR)newCpsr).t);
+ pc.nextJazelle(((CPSR)newCpsr).j);
+ PCS = pc;
CondCodes = CondCodesMask & newCpsr;
'''
msrCpsrRegIop = InstObjParams("msr", "MsrCpsrReg", "MsrRegOp",
@@ -107,6 +111,10 @@ let {{
uint32_t newCpsr =
cpsrWriteByInstr(Cpsr | CondCodes, imm, byteMask, false, sctlr.nmfi);
Cpsr = ~CondCodesMask & newCpsr;
+ ArmISA::PCState pc = PCS;
+ pc.nextThumb(((CPSR)newCpsr).t);
+ pc.nextJazelle(((CPSR)newCpsr).j);
+ PCS = pc;
CondCodes = CondCodesMask & newCpsr;
'''
msrCpsrImmIop = InstObjParams("msr", "MsrCpsrImm", "MsrImmOp",
@@ -462,8 +470,12 @@ let {{
decoder_output += RegRegRegRegOpConstructor.subst(usada8Iop)
exec_output += PredOpExecute.subst(usada8Iop)
+ bkptCode = '''
+ ArmISA::PCState pc = PCS;
+ return new PrefetchAbort(pc.pc(), ArmFault::DebugEvent);
+ '''
bkptIop = InstObjParams("bkpt", "BkptInst", "ArmStaticInst",
- "return new PrefetchAbort(PC, ArmFault::DebugEvent);")
+ bkptCode)
header_output += BasicDeclare.subst(bkptIop)
decoder_output += BasicConstructor.subst(bkptIop)
exec_output += BasicExecute.subst(bkptIop)
@@ -638,7 +650,10 @@ let {{
exec_output += PredOpExecute.subst(mcr15UserIop)
enterxCode = '''
- FNPC = NPC | PcJBit | PcTBit;
+ ArmISA::PCState pc = PCS;
+ pc.nextThumb(true);
+ pc.nextJazelle(true);
+ PCS = pc;
'''
enterxIop = InstObjParams("enterx", "Enterx", "PredOp",
{ "code": enterxCode,
@@ -648,7 +663,10 @@ let {{
exec_output += PredOpExecute.subst(enterxIop)
leavexCode = '''
- FNPC = (NPC & ~PcJBit) | PcTBit;
+ ArmISA::PCState pc = PCS;
+ pc.nextThumb(true);
+ pc.nextJazelle(false);
+ PCS = pc;
'''
leavexIop = InstObjParams("leavex", "Leavex", "PredOp",
{ "code": leavexCode,
diff --git a/src/arch/arm/isa/operands.isa b/src/arch/arm/isa/operands.isa
index 4f1b7f610..8e856e74d 100644
--- a/src/arch/arm/isa/operands.isa
+++ b/src/arch/arm/isa/operands.isa
@@ -54,11 +54,10 @@ def operand_types {{
let {{
maybePCRead = '''
- ((%(reg_idx)s == PCReg) ? (readPC(xc) & ~PcModeMask) :
- xc->%(func)s(this, %(op_idx)s))
+ ((%(reg_idx)s == PCReg) ? readPC(xc) : xc->%(func)s(this, %(op_idx)s))
'''
maybeAlignedPCRead = '''
- ((%(reg_idx)s == PCReg) ? (roundDown(readPC(xc) & ~PcModeMask, 4)) :
+ ((%(reg_idx)s == PCReg) ? (roundDown(readPC(xc), 4)) :
xc->%(func)s(this, %(op_idx)s))
'''
maybePCWrite = '''
@@ -81,140 +80,133 @@ let {{
xc->%(func)s(this, %(op_idx)s, %(final_val)s);
}
'''
-
- readNPC = 'xc->readNextPC() & ~PcModeMask'
- writeNPC = 'setNextPC(xc, %(final_val)s)'
- writeIWNPC = 'setIWNextPC(xc, %(final_val)s)'
- forceNPC = 'xc->setNextPC(%(final_val)s)'
}};
def operands {{
#Abstracted integer reg operands
- 'Dest': ('IntReg', 'uw', 'dest', 'IsInteger', 2,
+ 'Dest': ('IntReg', 'uw', 'dest', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'FpDest': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 2),
- 'FpDestP0': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 2),
- 'FpDestP1': ('FloatReg', 'sf', '(dest + 1)', 'IsFloating', 2),
- 'FpDestP2': ('FloatReg', 'sf', '(dest + 2)', 'IsFloating', 2),
- 'FpDestP3': ('FloatReg', 'sf', '(dest + 3)', 'IsFloating', 2),
- 'FpDestP4': ('FloatReg', 'sf', '(dest + 4)', 'IsFloating', 2),
- 'FpDestP5': ('FloatReg', 'sf', '(dest + 5)', 'IsFloating', 2),
- 'FpDestP6': ('FloatReg', 'sf', '(dest + 6)', 'IsFloating', 2),
- 'FpDestP7': ('FloatReg', 'sf', '(dest + 7)', 'IsFloating', 2),
- 'FpDestS0P0': ('FloatReg', 'sf', '(dest + step * 0 + 0)', 'IsFloating', 2),
- 'FpDestS0P1': ('FloatReg', 'sf', '(dest + step * 0 + 1)', 'IsFloating', 2),
- 'FpDestS1P0': ('FloatReg', 'sf', '(dest + step * 1 + 0)', 'IsFloating', 2),
- 'FpDestS1P1': ('FloatReg', 'sf', '(dest + step * 1 + 1)', 'IsFloating', 2),
- 'FpDestS2P0': ('FloatReg', 'sf', '(dest + step * 2 + 0)', 'IsFloating', 2),
- 'FpDestS2P1': ('FloatReg', 'sf', '(dest + step * 2 + 1)', 'IsFloating', 2),
- 'FpDestS3P0': ('FloatReg', 'sf', '(dest + step * 3 + 0)', 'IsFloating', 2),
- 'FpDestS3P1': ('FloatReg', 'sf', '(dest + step * 3 + 1)', 'IsFloating', 2),
- 'Result': ('IntReg', 'uw', 'result', 'IsInteger', 2,
+ 'FpDest': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 3),
+ 'FpDestP0': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 3),
+ 'FpDestP1': ('FloatReg', 'sf', '(dest + 1)', 'IsFloating', 3),
+ 'FpDestP2': ('FloatReg', 'sf', '(dest + 2)', 'IsFloating', 3),
+ 'FpDestP3': ('FloatReg', 'sf', '(dest + 3)', 'IsFloating', 3),
+ 'FpDestP4': ('FloatReg', 'sf', '(dest + 4)', 'IsFloating', 3),
+ 'FpDestP5': ('FloatReg', 'sf', '(dest + 5)', 'IsFloating', 3),
+ 'FpDestP6': ('FloatReg', 'sf', '(dest + 6)', 'IsFloating', 3),
+ 'FpDestP7': ('FloatReg', 'sf', '(dest + 7)', 'IsFloating', 3),
+ 'FpDestS0P0': ('FloatReg', 'sf', '(dest + step * 0 + 0)', 'IsFloating', 3),
+ 'FpDestS0P1': ('FloatReg', 'sf', '(dest + step * 0 + 1)', 'IsFloating', 3),
+ 'FpDestS1P0': ('FloatReg', 'sf', '(dest + step * 1 + 0)', 'IsFloating', 3),
+ 'FpDestS1P1': ('FloatReg', 'sf', '(dest + step * 1 + 1)', 'IsFloating', 3),
+ 'FpDestS2P0': ('FloatReg', 'sf', '(dest + step * 2 + 0)', 'IsFloating', 3),
+ 'FpDestS2P1': ('FloatReg', 'sf', '(dest + step * 2 + 1)', 'IsFloating', 3),
+ 'FpDestS3P0': ('FloatReg', 'sf', '(dest + step * 3 + 0)', 'IsFloating', 3),
+ 'FpDestS3P1': ('FloatReg', 'sf', '(dest + step * 3 + 1)', 'IsFloating', 3),
+ 'Result': ('IntReg', 'uw', 'result', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Dest2': ('IntReg', 'uw', 'dest2', 'IsInteger', 2,
+ 'Dest2': ('IntReg', 'uw', 'dest2', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'FpDest2': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 2),
- 'FpDest2P0': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 2),
- 'FpDest2P1': ('FloatReg', 'sf', '(dest2 + 1)', 'IsFloating', 2),
- 'FpDest2P2': ('FloatReg', 'sf', '(dest2 + 2)', 'IsFloating', 2),
- 'FpDest2P3': ('FloatReg', 'sf', '(dest2 + 3)', 'IsFloating', 2),
- 'IWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 2,
+ 'FpDest2': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 3),
+ 'FpDest2P0': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 3),
+ 'FpDest2P1': ('FloatReg', 'sf', '(dest2 + 1)', 'IsFloating', 3),
+ 'FpDest2P2': ('FloatReg', 'sf', '(dest2 + 2)', 'IsFloating', 3),
+ 'FpDest2P3': ('FloatReg', 'sf', '(dest2 + 3)', 'IsFloating', 3),
+ 'IWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 3,
maybePCRead, maybeIWPCWrite),
- 'AIWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 2,
+ 'AIWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 3,
maybePCRead, maybeAIWPCWrite),
'SpMode': ('IntReg', 'uw',
'intRegInMode((OperatingMode)regMode, INTREG_SP)',
- 'IsInteger', 2),
- 'MiscDest': ('ControlReg', 'uw', 'dest', (None, None, 'IsControl'), 2),
- 'Base': ('IntReg', 'uw', 'base', 'IsInteger', 0,
+ 'IsInteger', 3),
+ 'MiscDest': ('ControlReg', 'uw', 'dest', (None, None, 'IsControl'), 3),
+ 'Base': ('IntReg', 'uw', 'base', 'IsInteger', 1,
maybeAlignedPCRead, maybePCWrite),
- 'Index': ('IntReg', 'uw', 'index', 'IsInteger', 2,
+ 'Index': ('IntReg', 'uw', 'index', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Op1': ('IntReg', 'uw', 'op1', 'IsInteger', 2,
+ 'Op1': ('IntReg', 'uw', 'op1', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'FpOp1': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 2),
- 'FpOp1P0': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 2),
- 'FpOp1P1': ('FloatReg', 'sf', '(op1 + 1)', 'IsFloating', 2),
- 'FpOp1P2': ('FloatReg', 'sf', '(op1 + 2)', 'IsFloating', 2),
- 'FpOp1P3': ('FloatReg', 'sf', '(op1 + 3)', 'IsFloating', 2),
- 'FpOp1P4': ('FloatReg', 'sf', '(op1 + 4)', 'IsFloating', 2),
- 'FpOp1P5': ('FloatReg', 'sf', '(op1 + 5)', 'IsFloating', 2),
- 'FpOp1P6': ('FloatReg', 'sf', '(op1 + 6)', 'IsFloating', 2),
- 'FpOp1P7': ('FloatReg', 'sf', '(op1 + 7)', 'IsFloating', 2),
- 'FpOp1S0P0': ('FloatReg', 'sf', '(op1 + step * 0 + 0)', 'IsFloating', 2),
- 'FpOp1S0P1': ('FloatReg', 'sf', '(op1 + step * 0 + 1)', 'IsFloating', 2),
- 'FpOp1S1P0': ('FloatReg', 'sf', '(op1 + step * 1 + 0)', 'IsFloating', 2),
- 'FpOp1S1P1': ('FloatReg', 'sf', '(op1 + step * 1 + 1)', 'IsFloating', 2),
- 'FpOp1S2P0': ('FloatReg', 'sf', '(op1 + step * 2 + 0)', 'IsFloating', 2),
- 'FpOp1S2P1': ('FloatReg', 'sf', '(op1 + step * 2 + 1)', 'IsFloating', 2),
- 'FpOp1S3P0': ('FloatReg', 'sf', '(op1 + step * 3 + 0)', 'IsFloating', 2),
- 'FpOp1S3P1': ('FloatReg', 'sf', '(op1 + step * 3 + 1)', 'IsFloating', 2),
- 'MiscOp1': ('ControlReg', 'uw', 'op1', (None, None, 'IsControl'), 2),
- 'Op2': ('IntReg', 'uw', 'op2', 'IsInteger', 2,
+ 'FpOp1': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 3),
+ 'FpOp1P0': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 3),
+ 'FpOp1P1': ('FloatReg', 'sf', '(op1 + 1)', 'IsFloating', 3),
+ 'FpOp1P2': ('FloatReg', 'sf', '(op1 + 2)', 'IsFloating', 3),
+ 'FpOp1P3': ('FloatReg', 'sf', '(op1 + 3)', 'IsFloating', 3),
+ 'FpOp1P4': ('FloatReg', 'sf', '(op1 + 4)', 'IsFloating', 3),
+ 'FpOp1P5': ('FloatReg', 'sf', '(op1 + 5)', 'IsFloating', 3),
+ 'FpOp1P6': ('FloatReg', 'sf', '(op1 + 6)', 'IsFloating', 3),
+ 'FpOp1P7': ('FloatReg', 'sf', '(op1 + 7)', 'IsFloating', 3),
+ 'FpOp1S0P0': ('FloatReg', 'sf', '(op1 + step * 0 + 0)', 'IsFloating', 3),
+ 'FpOp1S0P1': ('FloatReg', 'sf', '(op1 + step * 0 + 1)', 'IsFloating', 3),
+ 'FpOp1S1P0': ('FloatReg', 'sf', '(op1 + step * 1 + 0)', 'IsFloating', 3),
+ 'FpOp1S1P1': ('FloatReg', 'sf', '(op1 + step * 1 + 1)', 'IsFloating', 3),
+ 'FpOp1S2P0': ('FloatReg', 'sf', '(op1 + step * 2 + 0)', 'IsFloating', 3),
+ 'FpOp1S2P1': ('FloatReg', 'sf', '(op1 + step * 2 + 1)', 'IsFloating', 3),
+ 'FpOp1S3P0': ('FloatReg', 'sf', '(op1 + step * 3 + 0)', 'IsFloating', 3),
+ 'FpOp1S3P1': ('FloatReg', 'sf', '(op1 + step * 3 + 1)', 'IsFloating', 3),
+ 'MiscOp1': ('ControlReg', 'uw', 'op1', (None, None, 'IsControl'), 3),
+ 'Op2': ('IntReg', 'uw', 'op2', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'FpOp2': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 2),
- 'FpOp2P0': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 2),
- 'FpOp2P1': ('FloatReg', 'sf', '(op2 + 1)', 'IsFloating', 2),
- 'FpOp2P2': ('FloatReg', 'sf', '(op2 + 2)', 'IsFloating', 2),
- 'FpOp2P3': ('FloatReg', 'sf', '(op2 + 3)', 'IsFloating', 2),
- 'Op3': ('IntReg', 'uw', 'op3', 'IsInteger', 2,
+ 'FpOp2': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 3),
+ 'FpOp2P0': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 3),
+ 'FpOp2P1': ('FloatReg', 'sf', '(op2 + 1)', 'IsFloating', 3),
+ 'FpOp2P2': ('FloatReg', 'sf', '(op2 + 2)', 'IsFloating', 3),
+ 'FpOp2P3': ('FloatReg', 'sf', '(op2 + 3)', 'IsFloating', 3),
+ 'Op3': ('IntReg', 'uw', 'op3', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Shift': ('IntReg', 'uw', 'shift', 'IsInteger', 2,
+ 'Shift': ('IntReg', 'uw', 'shift', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Reg0': ('IntReg', 'uw', 'reg0', 'IsInteger', 2,
+ 'Reg0': ('IntReg', 'uw', 'reg0', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Reg1': ('IntReg', 'uw', 'reg1', 'IsInteger', 2,
+ 'Reg1': ('IntReg', 'uw', 'reg1', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Reg2': ('IntReg', 'uw', 'reg2', 'IsInteger', 2,
+ 'Reg2': ('IntReg', 'uw', 'reg2', 'IsInteger', 3,
maybePCRead, maybePCWrite),
- 'Reg3': ('IntReg', 'uw', 'reg3', 'IsInteger', 2,
+ 'Reg3': ('IntReg', 'uw', 'reg3', 'IsInteger', 3,
maybePCRead, maybePCWrite),
#General Purpose Integer Reg Operands
- 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 2, maybePCRead, maybePCWrite),
- 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 2, maybePCRead, maybePCWrite),
- 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2, maybePCRead, maybePCWrite),
- 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 2, maybePCRead, maybePCWrite),
- 'R7': ('IntReg', 'uw', '7', 'IsInteger', 2),
- 'R0': ('IntReg', 'uw', '0', 'IsInteger', 2),
+ 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 3, maybePCRead, maybePCWrite),
+ 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 3, maybePCRead, maybePCWrite),
+ 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3, maybePCRead, maybePCWrite),
+ 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 3, maybePCRead, maybePCWrite),
+ 'R7': ('IntReg', 'uw', '7', 'IsInteger', 3),
+ 'R0': ('IntReg', 'uw', '0', 'IsInteger', 3),
- 'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 2),
- 'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', None, 2),
+ 'LR': ('IntReg', 'uw', 'INTREG_LR', 'IsInteger', 3),
+ 'CondCodes': ('IntReg', 'uw', 'INTREG_CONDCODES', None, 3),
'OptCondCodes': ('IntReg', 'uw',
'''(condCode == COND_AL || condCode == COND_UC) ?
- INTREG_ZERO : INTREG_CONDCODES''', None, 2),
- 'FpCondCodes': ('IntReg', 'uw', 'INTREG_FPCONDCODES', None, 2),
+ INTREG_ZERO : INTREG_CONDCODES''', None, 3),
+ 'FpCondCodes': ('IntReg', 'uw', 'INTREG_FPCONDCODES', None, 3),
#Register fields for microops
- 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 2, maybePCRead, maybePCWrite),
- 'IWRa' : ('IntReg', 'uw', 'ura', 'IsInteger', 2,
+ 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 3, maybePCRead, maybePCWrite),
+ 'IWRa' : ('IntReg', 'uw', 'ura', 'IsInteger', 3,
maybePCRead, maybeIWPCWrite),
- 'Fa' : ('FloatReg', 'sf', 'ura', 'IsFloating', 2),
- 'Rb' : ('IntReg', 'uw', 'urb', 'IsInteger', 2, maybePCRead, maybePCWrite),
- 'Rc' : ('IntReg', 'uw', 'urc', 'IsInteger', 2, maybePCRead, maybePCWrite),
+ 'Fa' : ('FloatReg', 'sf', 'ura', 'IsFloating', 3),
+ 'Rb' : ('IntReg', 'uw', 'urb', 'IsInteger', 3, maybePCRead, maybePCWrite),
+ 'Rc' : ('IntReg', 'uw', 'urc', 'IsInteger', 3, maybePCRead, maybePCWrite),
#General Purpose Floating Point Reg Operands
- 'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 2),
- 'Fn': ('FloatReg', 'df', 'FN', 'IsFloating', 2),
- 'Fm': ('FloatReg', 'df', 'FM', 'IsFloating', 2),
+ 'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 3),
+ 'Fn': ('FloatReg', 'df', 'FN', 'IsFloating', 3),
+ 'Fm': ('FloatReg', 'df', 'FM', 'IsFloating', 3),
#Memory Operand
- 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 2),
+ 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 3),
- 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 1),
- 'Itstate': ('ControlReg', 'ub', 'MISCREG_ITSTATE', None, 2),
- 'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', None, 2),
- 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', None, 2),
- 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', None, 2),
- 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', None, 2),
- 'Cpacr': ('ControlReg', 'uw', 'MISCREG_CPACR', (None, None, 'IsControl'), 2),
- 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', None, 2),
- 'Sctlr': ('ControlReg', 'uw', 'MISCREG_SCTLR', None, 2),
- 'SevMailbox': ('ControlReg', 'uw', 'MISCREG_SEV_MAILBOX', None, 2),
- 'PC': ('PC', 'ud', None, None, 2),
- 'NPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2,
- readNPC, writeNPC),
- 'FNPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2,
- readNPC, forceNPC),
- 'IWNPC': ('NPC', 'ud', None, (None, None, 'IsControl'), 2,
- readNPC, writeIWNPC),
+ 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', (None, None, 'IsControl'), 2),
+ 'Itstate': ('ControlReg', 'ub', 'MISCREG_ITSTATE', None, 3),
+ 'Spsr': ('ControlReg', 'uw', 'MISCREG_SPSR', None, 3),
+ 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', None, 3),
+ 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', None, 3),
+ 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', None, 3),
+ 'Cpacr': ('ControlReg', 'uw', 'MISCREG_CPACR', (None, None, 'IsControl'), 3),
+ 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', None, 3),
+ 'Sctlr': ('ControlReg', 'uw', 'MISCREG_SCTLR', None, 3),
+ 'SevMailbox': ('ControlReg', 'uw', 'MISCREG_SEV_MAILBOX', None, 3),
+ #PCS needs to have a sorting index (the number at the end) less than all
+ #the integer registers which might update the PC. That way if the flag
+ #bits of the pc state are updated and a branch happens through R15, the
+ #updates are layered properly and the R15 update isn't lost.
+ 'PCS': ('PCState', 'uw', None, (None, None, 'IsControl'), 0)
}};
diff --git a/src/arch/arm/isa_traits.hh b/src/arch/arm/isa_traits.hh
index 8d3f0ffe3..f6aa7fcf0 100644
--- a/src/arch/arm/isa_traits.hh
+++ b/src/arch/arm/isa_traits.hh
@@ -123,15 +123,6 @@ namespace ArmISA
INT_FIQ,
NumInterruptTypes
};
-
- // These otherwise unused bits of the PC are used to select a mode
- // like the J and T bits of the CPSR.
- static const Addr PcJBitShift = 33;
- static const Addr PcJBit = ULL(1) << PcJBitShift;
- static const Addr PcTBitShift = 34;
- static const Addr PcTBit = ULL(1) << PcTBitShift;
- static const Addr PcModeMask = (ULL(1) << PcJBitShift) |
- (ULL(1) << PcTBitShift);
};
using namespace ArmISA;
diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc
index 7c4e00921..40658976b 100644
--- a/src/arch/arm/linux/system.cc
+++ b/src/arch/arm/linux/system.cc
@@ -103,8 +103,7 @@ LinuxArmSystem::startup()
ThreadContext *tc = threadContexts[0];
// Set the initial PC to be at start of the kernel code
- tc->setPC(tc->getSystemPtr()->kernelEntry & loadAddrMask);
- tc->setNextPC(tc->readPC() + sizeof(MachInst));
+ tc->pcState(tc->getSystemPtr()->kernelEntry & loadAddrMask);
// Setup the machine type
tc->setIntReg(0, 0);
diff --git a/src/arch/arm/nativetrace.cc b/src/arch/arm/nativetrace.cc
index d97be88a2..75546f8de 100644
--- a/src/arch/arm/nativetrace.cc
+++ b/src/arch/arm/nativetrace.cc
@@ -106,7 +106,7 @@ Trace::ArmNativeTrace::ThreadState::update(ThreadContext *tc)
}
//R15, aliased with the PC
- newState[STATE_PC] = tc->readNextPC();
+ newState[STATE_PC] = tc->pcState().npc();
changed[STATE_PC] = (newState[STATE_PC] != oldState[STATE_PC]);
//CPSR
@@ -121,7 +121,7 @@ Trace::ArmNativeTrace::check(NativeTraceRecord *record)
ThreadContext *tc = record->getThread();
// This area is read only on the target. It can't stop there to tell us
// what's going on, so we should skip over anything there also.
- if (tc->readNextPC() > 0xffff0000)
+ if (tc->nextInstAddr() > 0xffff0000)
return;
nState.update(this);
mState.update(tc);
diff --git a/src/arch/arm/predecoder.cc b/src/arch/arm/predecoder.cc
index 04cec59b9..456b9e4c4 100644
--- a/src/arch/arm/predecoder.cc
+++ b/src/arch/arm/predecoder.cc
@@ -148,11 +148,11 @@ Predecoder::process()
//Use this to give data to the predecoder. This should be used
//when there is control flow.
void
-Predecoder::moreBytes(Addr pc, Addr fetchPC, MachInst inst)
+Predecoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst)
{
data = inst;
- offset = (fetchPC >= pc) ? 0 : pc - fetchPC;
- emi.thumb = isThumb(pc);
+ offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC;
+ emi.thumb = pc.thumb();
FPSCR fpscr = tc->readMiscReg(MISCREG_FPSCR);
emi.fpscrLen = fpscr.len;
emi.fpscrStride = fpscr.stride;
diff --git a/src/arch/arm/predecoder.hh b/src/arch/arm/predecoder.hh
index 2db550024..47242b8ff 100644
--- a/src/arch/arm/predecoder.hh
+++ b/src/arch/arm/predecoder.hh
@@ -94,7 +94,7 @@ namespace ArmISA
//Use this to give data to the predecoder. This should be used
//when there is control flow.
- void moreBytes(Addr pc, Addr fetchPC, MachInst inst);
+ void moreBytes(const PCState &pc, Addr fetchPC, MachInst inst);
//Use this to give data to the predecoder. This should be used
//when instructions are executed in order.
@@ -121,9 +121,10 @@ namespace ArmISA
}
//This returns a constant reference to the ExtMachInst to avoid a copy
- ExtMachInst getExtMachInst()
+ ExtMachInst getExtMachInst(PCState &pc)
{
ExtMachInst thisEmi = emi;
+ pc.npc(pc.pc() + getInstSize());
emi = 0;
return thisEmi;
}
diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc
index bc2aee4c8..a5460ac19 100644
--- a/src/arch/arm/process.cc
+++ b/src/arch/arm/process.cc
@@ -360,11 +360,11 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
tc->setIntReg(ArgumentReg2, 0);
}
- Addr prog_entry = objFile->entryPoint();
- if (arch == ObjectFile::Thumb)
- prog_entry = (prog_entry & ~mask(1)) | PcTBit;
- tc->setPC(prog_entry);
- tc->setNextPC(prog_entry + sizeof(MachInst));
+ PCState pc;
+ pc.thumb(arch == ObjectFile::Thumb);
+ pc.nextThumb(pc.thumb());
+ pc.set(objFile->entryPoint() & ~mask(1));
+ tc->pcState(pc);
//Align the "stack_min" to a page boundary.
stack_min = roundDown(stack_min, pageSize);
diff --git a/src/arch/arm/system.hh b/src/arch/arm/system.hh
index fe5ba6447..c64673df5 100644
--- a/src/arch/arm/system.hh
+++ b/src/arch/arm/system.hh
@@ -70,7 +70,7 @@ class ArmSystem : public System
// Remove the low bit that thumb symbols have set
// but that aren't actually odd aligned
if (addr & 0x1)
- return (addr & ~1) | PcTBit;
+ return addr & ~1;
return addr;
}
};
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc
index 73dd24e1c..06bb10219 100644
--- a/src/arch/arm/table_walker.cc
+++ b/src/arch/arm/table_walker.cc
@@ -107,7 +107,7 @@ TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _
/** @todo These should be cached or grabbed from cached copies in
the TLB, all these miscreg reads are expensive */
- currState->vaddr = currState->req->getVaddr() & ~PcModeMask;
+ currState->vaddr = currState->req->getVaddr();
currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR);
sctlr = currState->sctlr;
currState->N = currState->tc->readMiscReg(MISCREG_TTBCR);
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index c0ebb52b2..239d5d8a2 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -316,7 +316,7 @@ TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode,
Translation *translation, bool &delay, bool timing)
{
// XXX Cache misc registers and have miscreg write function inv cache
- Addr vaddr = req->getVaddr() & ~PcModeMask;
+ Addr vaddr = req->getVaddr();
SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
uint32_t flags = req->getFlags();
@@ -362,7 +362,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
Translation *translation, bool &delay, bool timing)
{
// XXX Cache misc registers and have miscreg write function inv cache
- Addr vaddr = req->getVaddr() & ~PcModeMask;
+ Addr vaddr = req->getVaddr();
SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
uint32_t flags = req->getFlags();
diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh
index 3c3b29494..57f34e3c2 100644
--- a/src/arch/arm/types.hh
+++ b/src/arch/arm/types.hh
@@ -43,8 +43,10 @@
#ifndef __ARCH_ARM_TYPES_HH__
#define __ARCH_ARM_TYPES_HH__
+#include "arch/generic/types.hh"
#include "base/bitunion.hh"
#include "base/hashmap.hh"
+#include "base/misc.hh"
#include "base/types.hh"
namespace ArmISA
@@ -188,6 +190,189 @@ namespace ArmISA
Bitfield<11, 8> ltcoproc;
EndBitUnion(ExtMachInst)
+ class PCState : public GenericISA::UPCState<MachInst>
+ {
+ protected:
+
+ typedef GenericISA::UPCState<MachInst> Base;
+
+ enum FlagBits {
+ ThumbBit = (1 << 0),
+ JazelleBit = (1 << 1)
+ };
+ uint8_t flags;
+ uint8_t nextFlags;
+
+ public:
+ PCState() : flags(0), nextFlags(0)
+ {}
+
+ void
+ set(Addr val)
+ {
+ Base::set(val);
+ npc(val + (thumb() ? 2 : 4));
+ }
+
+ PCState(Addr val) : flags(0), nextFlags(0)
+ { set(val); }
+
+ bool
+ thumb() const
+ {
+ return flags & ThumbBit;
+ }
+
+ void
+ thumb(bool val)
+ {
+ if (val)
+ flags |= ThumbBit;
+ else
+ flags &= ~ThumbBit;
+ }
+
+ bool
+ nextThumb() const
+ {
+ return nextFlags & ThumbBit;
+ }
+
+ void
+ nextThumb(bool val)
+ {
+ if (val)
+ nextFlags |= ThumbBit;
+ else
+ nextFlags &= ~ThumbBit;
+ }
+
+ bool
+ jazelle() const
+ {
+ return flags & JazelleBit;
+ }
+
+ void
+ jazelle(bool val)
+ {
+ if (val)
+ flags |= JazelleBit;
+ else
+ flags &= ~JazelleBit;
+ }
+
+ bool
+ nextJazelle() const
+ {
+ return nextFlags & JazelleBit;
+ }
+
+ void
+ nextJazelle(bool val)
+ {
+ if (val)
+ nextFlags |= JazelleBit;
+ else
+ nextFlags &= ~JazelleBit;
+ }
+
+ void
+ advance()
+ {
+ Base::advance();
+ npc(pc() + (thumb() ? 2 : 4));
+ flags = nextFlags;
+ }
+
+ void
+ uEnd()
+ {
+ advance();
+ upc(0);
+ nupc(1);
+ }
+
+ Addr
+ instPC() const
+ {
+ return pc() + (thumb() ? 4 : 8);
+ }
+
+ void
+ instNPC(uint32_t val)
+ {
+ npc(val &~ mask(nextThumb() ? 1 : 2));
+ }
+
+ Addr
+ instNPC() const
+ {
+ return npc();
+ }
+
+ // Perform an interworking branch.
+ void
+ instIWNPC(uint32_t val)
+ {
+ bool thumbEE = (thumb() && jazelle());
+
+ Addr newPC = val;
+ if (thumbEE) {
+ if (bits(newPC, 0)) {
+ newPC = newPC & ~mask(1);
+ } else {
+ panic("Bad thumbEE interworking branch address %#x.\n",
+ newPC);
+ }
+ } else {
+ if (bits(newPC, 0)) {
+ nextThumb(true);
+ newPC = newPC & ~mask(1);
+ } else if (!bits(newPC, 1)) {
+ nextThumb(false);
+ } else {
+ warn("Bad interworking branch address %#x.\n", newPC);
+ }
+ }
+ npc(newPC);
+ }
+
+ // Perform an interworking branch in ARM mode, a regular branch
+ // otherwise.
+ void
+ instAIWNPC(uint32_t val)
+ {
+ if (!thumb() && !jazelle())
+ instIWNPC(val);
+ else
+ instNPC(val);
+ }
+
+ bool
+ operator == (const PCState &opc) const
+ {
+ return Base::operator == (opc) &&
+ flags == opc.flags && nextFlags == opc.nextFlags;
+ }
+
+ void
+ serialize(std::ostream &os)
+ {
+ Base::serialize(os);
+ SERIALIZE_SCALAR(flags);
+ SERIALIZE_SCALAR(nextFlags);
+ }
+
+ void
+ unserialize(Checkpoint *cp, const std::string &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__