ISA,CPU,etc: Create an ISA defined PC type that abstracts out ISA behaviors.
authorGabe Black <gblack@eecs.umich.edu>
Sun, 31 Oct 2010 07:07:20 +0000 (00:07 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Sun, 31 Oct 2010 07:07:20 +0000 (00:07 -0700)
This change is a low level and pervasive reorganization of how PCs are managed
in M5. Back when Alpha was the only ISA, there were only 2 PCs to worry about,
the PC and the NPC, and the lsb of the PC signaled whether or not you were in
PAL mode. As other ISAs were added, we had to add an NNPC, micro PC and next
micropc, x86 and ARM introduced variable length instruction sets, and ARM
started to keep track of mode bits in the PC. Each CPU model handled PCs in
its own custom way that needed to be updated individually to handle the new
dimensions of variability, or, in the case of ARMs mode-bit-in-the-pc hack,
the complexity could be hidden in the ISA at the ISA implementation's expense.
Areas like the branch predictor hadn't been updated to handle branch delay
slots or micropcs, and it turns out that had introduced a significant (10s of
percent) performance bug in SPARC and to a lesser extend MIPS. Rather than
perpetuate the problem by reworking O3 again to handle the PC features needed
by x86, this change was introduced to rework PC handling in a more modular,
transparent, and hopefully efficient way.

PC type:

Rather than having the superset of all possible elements of PC state declared
in each of the CPU models, each ISA defines its own PCState type which has
exactly the elements it needs. A cross product of canned PCState classes are
defined in the new "generic" ISA directory for ISAs with/without delay slots
and microcode. These are either typedef-ed or subclassed by each ISA. To read
or write this structure through a *Context, you use the new pcState() accessor
which reads or writes depending on whether it has an argument. If you just
want the address of the current or next instruction or the current micro PC,
you can get those through read-only accessors on either the PCState type or
the *Contexts. These are instAddr(), nextInstAddr(), and microPC(). Note the
move away from readPC. That name is ambiguous since it's not clear whether or
not it should be the actual address to fetch from, or if it should have extra
bits in it like the PAL mode bit. Each class is free to define its own
functions to get at whatever values it needs however it needs to to be used in
ISA specific code. Eventually Alpha's PAL mode bit could be moved out of the
PC and into a separate field like ARM.

These types can be reset to a particular pc (where npc = pc +
sizeof(MachInst), nnpc = npc + sizeof(MachInst), upc = 0, nupc = 1 as
appropriate), printed, serialized, and compared. There is a branching()
function which encapsulates code in the CPU models that checked if an
instruction branched or not. Exactly what that means in the context of branch
delay slots which can skip an instruction when not taken is ambiguous, and
ideally this function and its uses can be eliminated. PCStates also generally
know how to advance themselves in various ways depending on if they point at
an instruction, a microop, or the last microop of a macroop. More on that
later.

Ideally, accessing all the PCs at once when setting them will improve
performance of M5 even though more data needs to be moved around. This is
because often all the PCs need to be manipulated together, and by getting them
all at once you avoid multiple function calls. Also, the PCs of a particular
thread will have spatial locality in the cache. Previously they were grouped
by element in arrays which spread out accesses.

Advancing the PC:

The PCs were previously managed entirely by the CPU which had to know about PC
semantics, try to figure out which dimension to increment the PC in, what to
set NPC/NNPC, etc. These decisions are best left to the ISA in conjunction
with the PC type itself. Because most of the information about how to
increment the PC (mainly what type of instruction it refers to) is contained
in the instruction object, a new advancePC virtual function was added to the
StaticInst class. Subclasses provide an implementation that moves around the
right element of the PC with a minimal amount of decision making. In ISAs like
Alpha, the instructions always simply assign NPC to PC without having to worry
about micropcs, nnpcs, etc. The added cost of a virtual function call should
be outweighed by not having to figure out as much about what to do with the
PCs and mucking around with the extra elements.

One drawback of making the StaticInsts advance the PC is that you have to
actually have one to advance the PC. This would, superficially, seem to
require decoding an instruction before fetch could advance. This is, as far as
I can tell, realistic. fetch would advance through memory addresses, not PCs,
perhaps predicting new memory addresses using existing ones. More
sophisticated decisions about control flow would be made later on, after the
instruction was decoded, and handed back to fetch. If branching needs to
happen, some amount of decoding needs to happen to see that it's a branch,
what the target is, etc. This could get a little more complicated if that gets
done by the predecoder, but I'm choosing to ignore that for now.

Variable length instructions:

To handle variable length instructions in x86 and ARM, the predecoder now
takes in the current PC by reference to the getExtMachInst function. It can
modify the PC however it needs to (by setting NPC to be the PC + instruction
length, for instance). This could be improved since the CPU doesn't know if
the PC was modified and always has to write it back.

ISA parser:

To support the new API, all PC related operand types were removed from the
parser and replaced with a PCState type. There are two warts on this
implementation. First, as with all the other operand types, the PCState still
has to have a valid operand type even though it doesn't use it. Second, using
syntax like PCS.npc(target) doesn't work for two reasons, this looks like the
syntax for operand type overriding, and the parser can't figure out if you're
reading or writing. Instructions that use the PCS operand (which I've
consistently called it) need to first read it into a local variable,
manipulate it, and then write it back out.

Return address stack:

The return address stack needed a little extra help because, in the presence
of branch delay slots, it has to merge together elements of the return PC and
the call PC. To handle that, a buildRetPC utility function was added. There
are basically only two versions in all the ISAs, but it didn't seem short
enough to put into the generic ISA directory. Also, the branch predictor code
in O3 and InOrder were adjusted so that they always store the PC of the actual
call instruction in the RAS, not the next PC. If the call instruction is a
microop, the next PC refers to the next microop in the same macroop which is
probably not desirable. The buildRetPC function advances the PC intelligently
to the next macroop (in an ISA specific way) so that that case works.

Change in stats:

There were no change in stats except in MIPS and SPARC in the O3 model. MIPS
runs in about 9% fewer ticks. SPARC runs with 30%-50% fewer ticks, which could
likely be improved further by setting call/return instruction flags and taking
advantage of the RAS.

TODO:

Add != operators to the PCState classes, defined trivially to be !(a==b).
Smooth out places where PCs are split apart, passed around, and put back
together later. I think this might happen in SPARC's fault code. Add ISA
specific constructors that allow setting PC elements without calling a bunch
of accessors. Try to eliminate the need for the branching() function. Factor
out Alpha's PAL mode pc bit into a separate flag field, and eliminate places
where it's blindly masked out or tested in the PC.

171 files changed:
src/arch/alpha/ev5.cc
src/arch/alpha/faults.cc
src/arch/alpha/interrupts.hh
src/arch/alpha/isa/branch.isa
src/arch/alpha/isa/decoder.isa
src/arch/alpha/isa/main.isa
src/arch/alpha/predecoder.hh
src/arch/alpha/process.cc
src/arch/alpha/remote_gdb.cc
src/arch/alpha/stacktrace.cc
src/arch/alpha/tlb.cc
src/arch/alpha/types.hh
src/arch/alpha/utility.cc
src/arch/alpha/utility.hh
src/arch/arm/faults.cc
src/arch/arm/insts/macromem.hh
src/arch/arm/insts/mem.hh
src/arch/arm/insts/pred_inst.hh
src/arch/arm/insts/static_inst.hh
src/arch/arm/insts/vfp.hh
src/arch/arm/isa.cc
src/arch/arm/isa/formats/breakpoint.isa
src/arch/arm/isa/insts/branch.isa
src/arch/arm/isa/insts/data.isa
src/arch/arm/isa/insts/ldr.isa
src/arch/arm/isa/insts/macromem.isa
src/arch/arm/isa/insts/misc.isa
src/arch/arm/isa/operands.isa
src/arch/arm/isa_traits.hh
src/arch/arm/linux/system.cc
src/arch/arm/nativetrace.cc
src/arch/arm/predecoder.cc
src/arch/arm/predecoder.hh
src/arch/arm/process.cc
src/arch/arm/system.hh
src/arch/arm/table_walker.cc
src/arch/arm/tlb.cc
src/arch/arm/types.hh
src/arch/arm/utility.cc
src/arch/arm/utility.hh
src/arch/generic/types.hh [new file with mode: 0644]
src/arch/isa_parser.py
src/arch/mips/isa/base.isa
src/arch/mips/isa/decoder.isa
src/arch/mips/isa/formats/branch.isa
src/arch/mips/isa/includes.isa
src/arch/mips/isa/operands.isa
src/arch/mips/mt.hh
src/arch/mips/predecoder.hh
src/arch/mips/process.cc
src/arch/mips/types.hh
src/arch/mips/utility.cc
src/arch/mips/utility.hh
src/arch/power/insts/branch.cc
src/arch/power/insts/branch.hh
src/arch/power/insts/static_inst.hh
src/arch/power/isa/decoder.isa
src/arch/power/isa/formats/branch.isa
src/arch/power/isa/formats/unknown.isa
src/arch/power/isa/operands.isa
src/arch/power/predecoder.hh
src/arch/power/process.cc
src/arch/power/types.hh
src/arch/power/utility.cc
src/arch/power/utility.hh
src/arch/sparc/faults.cc
src/arch/sparc/isa/base.isa
src/arch/sparc/isa/decoder.isa
src/arch/sparc/isa/formats/branch.isa
src/arch/sparc/isa/formats/micro.isa
src/arch/sparc/isa/operands.isa
src/arch/sparc/nativetrace.cc
src/arch/sparc/predecoder.hh
src/arch/sparc/process.cc
src/arch/sparc/remote_gdb.cc
src/arch/sparc/types.hh
src/arch/sparc/utility.cc
src/arch/sparc/utility.hh
src/arch/x86/faults.cc
src/arch/x86/insts/macroop.hh
src/arch/x86/insts/microop.hh
src/arch/x86/insts/static_inst.hh
src/arch/x86/isa/decoder/two_byte_opcodes.isa
src/arch/x86/isa/formats/unknown.isa
src/arch/x86/isa/microops/regop.isa
src/arch/x86/isa/microops/seqop.isa
src/arch/x86/isa/operands.isa
src/arch/x86/nativetrace.cc
src/arch/x86/predecoder.hh
src/arch/x86/process.cc
src/arch/x86/system.cc
src/arch/x86/tlb.cc
src/arch/x86/types.hh
src/arch/x86/utility.cc
src/arch/x86/utility.hh
src/base/remote_gdb.cc
src/base/types.hh
src/cpu/base_dyn_inst.hh
src/cpu/base_dyn_inst_impl.hh
src/cpu/checker/cpu.hh
src/cpu/exetrace.cc
src/cpu/exetrace.hh
src/cpu/inorder/comm.hh
src/cpu/inorder/cpu.cc
src/cpu/inorder/cpu.hh
src/cpu/inorder/first_stage.cc
src/cpu/inorder/inorder_dyn_inst.cc
src/cpu/inorder/inorder_dyn_inst.hh
src/cpu/inorder/inorder_trace.cc
src/cpu/inorder/inorder_trace.hh
src/cpu/inorder/pipeline_stage.cc
src/cpu/inorder/pipeline_stage.hh
src/cpu/inorder/resources/bpred_unit.cc
src/cpu/inorder/resources/bpred_unit.hh
src/cpu/inorder/resources/branch_predictor.cc
src/cpu/inorder/resources/cache_unit.cc
src/cpu/inorder/resources/execution_unit.cc
src/cpu/inorder/resources/fetch_seq_unit.cc
src/cpu/inorder/resources/fetch_seq_unit.hh
src/cpu/inorder/resources/tlb_unit.hh
src/cpu/inorder/thread_context.cc
src/cpu/inorder/thread_context.hh
src/cpu/inorder/thread_state.hh
src/cpu/inteltrace.cc
src/cpu/inteltrace.hh
src/cpu/legiontrace.cc
src/cpu/legiontrace.hh
src/cpu/nativetrace.hh
src/cpu/o3/bpred_unit.hh
src/cpu/o3/bpred_unit_impl.hh
src/cpu/o3/comm.hh
src/cpu/o3/commit.hh
src/cpu/o3/commit_impl.hh
src/cpu/o3/cpu.cc
src/cpu/o3/cpu.hh
src/cpu/o3/decode_impl.hh
src/cpu/o3/dep_graph.hh
src/cpu/o3/dyn_inst.hh
src/cpu/o3/dyn_inst_impl.hh
src/cpu/o3/fetch.hh
src/cpu/o3/fetch_impl.hh
src/cpu/o3/iew_impl.hh
src/cpu/o3/inst_queue_impl.hh
src/cpu/o3/lsq_unit.hh
src/cpu/o3/lsq_unit_impl.hh
src/cpu/o3/mem_dep_unit_impl.hh
src/cpu/o3/rename_impl.hh
src/cpu/o3/rob_impl.hh
src/cpu/o3/thread_context.hh
src/cpu/o3/thread_context_impl.hh
src/cpu/pc_event.cc
src/cpu/pred/btb.cc
src/cpu/pred/btb.hh
src/cpu/pred/ras.cc
src/cpu/pred/ras.hh
src/cpu/simple/atomic.cc
src/cpu/simple/base.cc
src/cpu/simple/base.hh
src/cpu/simple/timing.cc
src/cpu/simple_thread.cc
src/cpu/simple_thread.hh
src/cpu/static_inst.cc
src/cpu/static_inst.hh
src/cpu/thread_context.cc
src/cpu/thread_context.hh
src/kern/system_events.cc
src/kern/tru64/tru64.hh
src/sim/faults.cc
src/sim/insttracer.hh
src/sim/syscall_emul.cc
src/sim/syscall_emul.hh

index 0db75df461c89f644c1a0525e09dee4cfc5211d7..f97244260518c82e52d5e34eda2e1672ddba5bdc 100644 (file)
@@ -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)
index 9d4eeda8afde7f4ce6992bb86d7ed35eb38b330c..38386cce1a66f83f809285416e29359e462ac354 100644 (file)
@@ -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
index 3200201dbed3210e0b36b7448be857376cbae673..cbaa8e9bf4cfafd8bcf980c84b83ddb7e51d7776 100644 (file)
@@ -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
index 974193efd938b1a6bff6b3a550513c135745aee2..feb15b1589074620b47af557fd2b10bc4f3eabdc 100644 (file)
@@ -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)
 }};
 
 
index fe70e4d1621826def72b28e86aeb66e485b9efe1..e2947cf4a993d6378f9ef2a626c51d4291680419 100644 (file)
@@ -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);
index 2a0699354815212a6562ce149ef791b19cf38d5e..ffc267cd23d87d3d7b6970cf55974fbe2f566241 100644 (file)
@@ -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();
+        }
     };
 }};
 
index 913bd876460f6e3fb275b72af4b4ea57ecb5f63d..f9a716b7f573de50060336b7eb7ba76062cc7a22 100644 (file)
@@ -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;
     }
index f68a53a6f1f43a6687de305c915b5bcae431097c..3c3fd9b2533d5d9ee3c1b1b3f6fc871acd2b66cb 100644 (file)
@@ -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
index 5391d20560eba7011c310012a8ed0b074892b639..9a2a5f23f31722946274c83adb4de98bf3eee0fe 100644 (file)
@@ -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.
index 1b5a9be349f17739c50df88430659230cb52aa70..9c6b3cff0b8d1831601f555a1960e46862e0e563 100644 (file)
@@ -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) {
index b578741d9316a2818973598454c0593b68381e32..614061dddb91f49f8d1954d6b04703951d1974f8 100644 (file)
@@ -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))
index 0d285c3b23502e632454a2ef4fe9787b86c968dd..06c0168cff677889236b4356f89f9d987388bb97 100644 (file)
 #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
index 11560259f41250ca5c084316b989e53dae800798..2d56ca9b8e0977359691771c7b80c7d1fd153bf1 100644 (file)
@@ -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);
 }
 
 
index 6d5b8baf63106cd7abd31b81728d9e28ff68c8a2..fdac8b8d1c84efd6872010a25e77ccdd894a08d2 100644 (file)
 #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__
index 6e138119c0cf62789f99a26a41a1c5424a429a3b..54cf5cfe575174e9804c72a2bc3319b6e739cf25 100644 (file)
@@ -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,
index c1c8383dabc1c028c343d7e9806c53953d689642..018cb1de5d315906813d7ff9df53dbbad328f6aa 100644 (file)
@@ -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();
+        }
+    }
 };
 
 /**
index 1baba51128f36af080558164cbf62d38050e27a9..2aa4de1d710aa1ab906f36626d6a25da12f5022b 100644 (file)
@@ -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];
index b7d4c470943d9ab03a95ec825a20aeb03e5c09b8..f779b46f5542061d0b8fb25e2ea9b3abd5612b1d 100644 (file)
@@ -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();
+    }
 };
 }
 
index ad89a1a79bd158ac392d8c646a50ac73c9a9cc3a..fa850190faf2c79e742af775de5a5e2f2b98afc8 100644 (file)
@@ -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
index 964b62673ae2574127ee19706112637b4e8e308f..e962704e04111f380a94010f25a7b47d20663aae 100644 (file)
@@ -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
index d557cecbbede9ef9f8f6f7883fdcd07093dbdada..0ba62f08ddfe2433e95a34df9c18181bf23fc0ee 100644 (file)
@@ -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] =
index d59f6a71207dfcb54319c74fdc37d85a484e4a13..1825d0878e1927b80541d71abcf954e6eb3ed74b 100644 (file)
@@ -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);
     }
 }};
 
index e9ddd77b79672c6b3eeb7781fdd2694ce7ff7bd5..3ff9042e6b848fa6f3a12097b3b0db820575da43 100644 (file)
@@ -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,
index 74eeee3b2eff0c3b91dd3c381421a361eabac22b..4d368e18166c451ddf286a9bf2d0a6e99bc3d36d 100644 (file)
@@ -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")
index dc043ed8e64ba06d7ff8e6dfc3469d77e4b2519e..92ad52a6d70b65e876e90670d5058d33842e96f9 100644 (file)
@@ -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
index 6bf789efd0be546ec47dfdfa3d8df8651fb94a70..a81050b1e050b65ef9a05736a8627acf2448aac5 100644 (file)
@@ -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',
index 5742f84ab63efee1dffd74b9b61b0bf7d15da86f..1abbc3de14b29f888ba9968227398ab74eaded0f 100644 (file)
@@ -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,
index 4f1b7f6107e2325c2ed092226164c44b9847ca77..8e856e74d5754501f443f4d861b0a5675e6e4d19 100644 (file)
@@ -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)
 }};
index 8d3f0ffe3e7193854ec34b0194a7239ab2d005f2..f6aa7fcf055a27297210c61ffbbd3a4077164e33 100644 (file)
@@ -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;
index 7c4e009210a011d35def68ad6d77353181627888..40658976bbd0a2d36ca085ffb90378034f90a5f2 100644 (file)
@@ -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);
index d97be88a25d36784d05b43bc21d261a1263d051c..75546f8de5459c59053c19e8e7ab09734352c37e 100644 (file)
@@ -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);
index 04cec59b91fe0f933167293df971ab3819cd048b..456b9e4c4ea5b6f1535557e1adf1b96cc70fd4c2 100644 (file)
@@ -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;
index 2db55002438ab8648598441cfe7d5286bcf02fba..47242b8fff4aa9338155aaaa2741168d607c9f42 100644 (file)
@@ -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;
         }
index bc2aee4c89ad4bbd740e8f45b18ec71b87f47153..a5460ac195e23662c6e85791a996b58f30238de5 100644 (file)
@@ -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);
index fe5ba64476670e888b58f09c51ca1b555a06ab17..c64673df53bc1def8c2ce41f573d1f4d9e6cd82e 100644 (file)
@@ -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;
     }
 };
index 73dd24e1c09839f9883e93eba3d45a38d89c1d00..06bb102190e700ba56b0c420322e1ac32a91cbae 100644 (file)
@@ -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);
index c0ebb52b2143b5f496625bbbab48e278141a81e5..239d5d8a2e56c373fa42c65328d1634b303c5f2e 100644 (file)
@@ -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();
index 3c3b29494ee72fb322f14029c9d580e480850b05..57f34e3c2cfa23d53dcb558d21c4e0b4c88adc5c 100644 (file)
 #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,
index 7609b39918404da795601a78c48d1582e077b0a8..a114ec5e0705e8dfa9a82ebc067409cb9959ca68 100644 (file)
@@ -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);
 }
 
 
index 571a74ef8b55b861899ea4979e6f44669b2cafde..a92ab072c74d283d6ef87a5dd9d33a5752e8f079 100644 (file)
 #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 (file)
index 0000000..214b019
--- /dev/null
@@ -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
index 4e06c2ded836a425e0fb6cb4781e5f428b90dc30..8e13b6a6a8879ece9473f3c05946f337ceff955a 100755 (executable)
@@ -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
index 4e2b12fc4409b86c6cbecd8dada1461b6fb54d31..cd6faf0f3786c039a16564c58edf0446f4e1fec4 100644 (file)
@@ -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();
+        }
     };
 
 }};
index 9832937b54a7251a90ef382bdc7fa30c29081a3c..3f3bd370a5af56c55e545f8a185d36ab131d1e1b 100644 (file)
@@ -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);
                 }
index 78f973a70caced27653de6607729c4a4d4537786..232a743a718d55312dce345ce16848066eb5457b 100644 (file)
@@ -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)
index 22eb3bf130d9689b920c7a74441ea4eca78666db..d5e1448ac3a9cff5d69593fa2eaac0a791ccb635 100644 (file)
@@ -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"
 }};
index 27cb4357a27e2582f99f1aa3614e7b5c33be4f26..1bb5ae5b3a1c1927695ecda97f5b41f4f5a85361 100644 (file)
@@ -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)
 }};
index 7217c335e843265ea0d461c2bf2c2a8511be757b..3ec6cbe7056f66c396618b4c766af3e171cab126 100755 (executable)
@@ -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);
     }
 }
 
index c20fe1f5fc2c223961d526c8e47995c4c4e1bb89..f059710e5792584a52c78778a7a9998fb3695b1d 100644 (file)
@@ -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;
     }
index fa3e3bff9a2586071e7bff2ccc8b0293144bf4b8..26a2a0ddb1bff0a70288eb5b5a3927f6b1ffcb89 100644 (file)
@@ -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());
 }
 
 
index c7ef6afe148a5975c2bac7ea3b4241fda82a2281..f21db51b1b2fa120b2d2c5e5a0eac32efe39da67 100644 (file)
@@ -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
index faae1e937e3f31fa77342bfab2c1c7bd7ab5f0c0..0859eb80f06835459f20de2155ae0bc29954ae4a 100644 (file)
@@ -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);
 }
 
 
index bc50027c0df0e9ba20d724005284aad21a2943b9..2f6726c59a8f463b3c2b7bbe5342e778064541eb 100644 (file)
 #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();
+}
+
 };
 
 
index c10f7c99697458ff4926f4c7efb3204b2b2e199d..352c4ea572ebbb4010496a46cf0dc76266d9f541 100644 (file)
@@ -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
index dd00e42c3fb3db3d01d1ecb50d9c9360d43dad54..7b9e78dee3639ec1b3cfb42a34ca6bb863d9ded9 100644 (file)
@@ -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;
 };
index 399e753716c376813d19a378c4e2eddc3047aa79..91eca6fb0fedde8ace5fa24cfa38f40854db0c69 100644 (file)
@@ -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
index 3252ff14a400d2fd06f9f6f2a0572d988338b2b2..671f5738931ef2b1965434e11313c966718e19a6 100644 (file)
@@ -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.
index d51ed5c259db4b71a5cbb7534c4b76dcc193e3e3..da1579ea8086aa7a240314a1e71f89f266440f29 100644 (file)
@@ -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
index 06e6ece262839626e5bde95db0aa02b0936dd56b..8914cf9a61d27fe219d377aad5f57c27e1bcc049 100644 (file)
@@ -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;
     }
 }};
index fc6c326859b1d9b5258aad3caa9e0a1a19d1565e..908e6e0e744fe02165c4433b3fea79a84d09fd25 100644 (file)
@@ -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),
index 1f3ac41cb3ff9d01f595a9f2973437cc5d81a28b..b1f2b6e389dacdb522fec0d8f85a508f96ec3e04 100644 (file)
@@ -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;
     }
index 9fb69b9f8f85dea6927a2ff8c29f6aa605143d3b..a34a874bcc8a2a03df6526b160d4ce60f749a414 100644 (file)
@@ -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);
index 6a8d1e9d37eebbcbae0b975b875877aaf1fc8bf2..d049cdec1bbe2cc79beff26e3cf1b9e539253a75 100644 (file)
@@ -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
 
index d48d4870aaf8ad396025ea15832dcd20b39dc0f5..399ec1f56dc222c4fe46e87b46a03552f2224ce9 100644 (file)
@@ -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
index c8cd441ba33a98eafc0b388a7a1c0b7b8f3faddb..a47fcdc46710e886727a900637c650d4ae2fbcb0 100644 (file)
 #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__
index df0a283b951b89e6999bad91fd1279a4d5be0d88..28ee64321dd201f8a82887805af7fcb4fe8d7268 100644 (file)
@@ -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
index ce063bcdc1fe6e1c7ac449cb68bf67df864fdba6..c6055b3a3ac8402bdbc74c4626517b4ff8d94f3d 100644 (file)
@@ -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);
@@ -260,6 +262,12 @@ output decoder {{
             }
         }
 
+        void
+        SparcStaticInst::advancePC(SparcISA::PCState &pcState) const
+        {
+            pcState.advance();
+        }
+
         void
         SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
         {
index b9b38b56952f75be1019361b87fda77491949684..80b29398c561c34914ae6830060a13e3353ce488 100644 (file)
@@ -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);
             }
index faaee8842873b28f64445fb6e9f7618adcaa7f14..e62e0035a2416c1f3f676b953135c314699f1ea5 100644 (file)
@@ -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:
index c1d0c4f3683f77c07edf6ff71a998ebc5e0f97a5..b5a53a68b705f44b8057f47ffb38bdd0f472147b 100644 (file)
@@ -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
index a627a2e6f34da737c773520c36182c148c3d145e..8bf6450be990dc60998e826c6ba0b73b36cb4638 100644 (file)
@@ -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),
index 8a1eb7a58671e44f21cbdc63cb14da53a7da5f9d..9bccaaf7deff4dc9e38aa9fcb9d260e91089fc9d 100644 (file)
@@ -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
index c4ab4fe7952d087716c6b20c37ce01920837f886..8a25879294072cfc4a95739314fb419a2365917f 100644 (file)
@@ -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;
         }
index 0cd8889a988f23b6611f535c5cd4ea2cda4851fe..a6e21977af20878d424ebb7ba7112715710b9bd0 100644 (file)
@@ -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);
index 4eea0c0774e6acc5412e440d038158e85130ca80..aea40ea22eddef2993683fd8365d38c41ee0253e 100644 (file)
@@ -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);
 }
index 70558ec6d3a63e7e51283f009a166ffae5e85ffe..122fd808f3b7803d452b0c7bcf52c8cce56c963a 100644 (file)
 
 #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 {
index be4dfac84ca136a08fef6e6a2b79e03eacc3bef8..6de44d8a331001f477d8134593b21983707c306b 100644 (file)
@@ -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);
 }
 
 
index f6a585e2399a97e73619f39137b00b765517a776..0d5a4bb93277df902ae171cd1ce3d4e707d28cc4 100644 (file)
 #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
index 4f2d97f90b17db0f94f7cf27d87ef77af7ad7aa0..7fb677c69be9f271287573b158bee29476faf549 100644 (file)
@@ -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
index 7ead7bdc24fa2aa3698ec2162043847e05e5c8b9..fcf051a371d007bf1f7828fd6be504062a7ab9e1 100644 (file)
@@ -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];
index 9b0497efcdf039a89692f51984ac1a051542320f..6fc21545285e1b0f8da40154ea489a38b834f377 100644 (file)
@@ -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();
+        }
     };
 }
 
index 2df5df092fe1fb5e372c57f67cc6369fbcceee1b..8813f216c4a77ee4fa62be08748f340541225482 100644 (file)
@@ -158,6 +158,12 @@ namespace X86ISA
                 panic("Tried to pick with unrecognized size %d.\n", size);
             }
         }
+
+        void
+        advancePC(PCState &pcState) const
+        {
+            pcState.advance();
+        }
     };
 }
 
index de167d1c1df845511e99c2ad1f440e14b654e131..def9b7f9dd060a83f5a8997eab7b1397f47b9e15 100644 (file)
 #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");
index 11751e86163fa8eb2ceefec5c9a4dc614d544bce..1108fd4a453b711e56ea394ae2a3f13f7fb4078f 100644 (file)
@@ -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)
             {
             }
 
index 9ccea82dda0e156c2679f84e48b28f84b05c8575..86ebac174b01c6ab596edfe8a3676f8ac10f334b 100644 (file)
@@ -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'
index 57c44d48c69acc184e73d487574ca60f35de073c..a3e22b0aa19e1989260c828944f4f395ca1f482d 100644 (file)
@@ -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)
index d4140e414243ab816f5c125fd24222e2bf4ed2b0..25b73a8f2a1c5aeeac7fa1f5a2c940a65e602f5b 100644 (file)
@@ -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),
index c5c891be9f6aa5b75148429b1e9dd241ad33b181..6f92cfacfe197c74fee02dc4a93e3ffcf9d3e7d5 100644 (file)
@@ -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));
index 5b38402e0518901f2c4607fbc4482921255220e3..c06ec18bcc5e1e9ad94d8b9823e4dc356b3329f8 100644 (file)
@@ -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;
-        }
     };
 };
 
index 946a7cbe10128b13135587edc39590a926538e51..bb875686e7c98cec9a174ffffa5d3c658278f27c 100644 (file)
@@ -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);
index ae47b14fd77d91f41151503d2d26a16c9e976ee2..3fc16e72947538a572bb637866c1394c8e0aba4b 100644 (file)
@@ -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!
 
index 71e0b3adb7a2efc1e93e8bc92e42fc8f54670c9b..dbba52af0e11965bb0e87102e051c44ca6d020b3 100644 (file)
@@ -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;
index 2a0da7d65f4720c50795d6498477f729cd5bee5b..5a208446a5dd157524bc8b933e319237ce12f6d5 100644 (file)
@@ -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;
     };
index 624e8132f8b346ac210c39c2f7c77f00703ba368..88d5bfe58c48d0b676b5e3d24dfd55b40a0ef161 100644 (file)
@@ -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
index 05ce53347a74dd37078ee163ee8d0110aece42f2..143fde00c05df1396f28a2dbc15bdb8776c29883 100644 (file)
 #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__
index 68747b3d1ddb0dba2417dbcdbe2f692b19c1db95..4a06ff30793664d7c578dcaa6b587e8fa476e223 100644 (file)
@@ -645,8 +645,8 @@ BaseRemoteGDB::trap(int type)
     bufferSize = gdbregs.bytes() * 2 + 256;
     buffer = (char*)malloc(bufferSize);
 
-    DPRINTF(GDBMisc, "trap: PC=%#x NPC=%#x\n",
-            context->readPC(), context->readNextPC());
+    TheISA::PCState pc = context->pcState();
+    DPRINTF(GDBMisc, "trap: PC=%s\n", pc);
 
     clearSingleStep();
 
@@ -806,8 +806,7 @@ BaseRemoteGDB::trap(int type)
             subcmd = hex2i(&p);
             if (*p++ == ';') {
                 val = hex2i(&p);
-                context->setPC(val);
-                context->setNextPC(val + sizeof(MachInst));
+                context->pcState(val);
             }
             clearSingleStep();
             goto out;
@@ -815,8 +814,7 @@ BaseRemoteGDB::trap(int type)
           case GDBCont:
             if (p - data < (ptrdiff_t)datalen) {
                 val = hex2i(&p);
-                context->setPC(val);
-                context->setNextPC(val + sizeof(MachInst));
+                context->pcState(val);
             }
             clearSingleStep();
             goto out;
@@ -825,8 +823,7 @@ BaseRemoteGDB::trap(int type)
             subcmd = hex2i(&p);
             if (*p++ == ';') {
                 val = hex2i(&p);
-                context->setPC(val);
-                context->setNextPC(val + sizeof(MachInst));
+                context->pcState(val);
             }
             setSingleStep();
             goto out;
@@ -834,8 +831,7 @@ BaseRemoteGDB::trap(int type)
           case GDBStep:
             if (p - data < (ptrdiff_t)datalen) {
                 val = hex2i(&p);
-                context->setPC(val);
-                context->setNextPC(val + sizeof(MachInst));
+                context->pcState(val);
             }
             setSingleStep();
             goto out;
index 30b2d9258a14d1a647bd617377bfbc65c97735b7..5ce77857221d82df161320e5183b88c74bb25613 100644 (file)
@@ -67,6 +67,28 @@ const Tick MaxTick = LL(0x7fffffffffffffff);
  */
 typedef uint64_t Addr;
 
+typedef uint16_t MicroPC;
+
+static const MicroPC MicroPCRomBit = 1 << (sizeof(MicroPC) * 8 - 1);
+
+static inline MicroPC
+romMicroPC(MicroPC upc)
+{
+    return upc | MicroPCRomBit;
+}
+
+static inline MicroPC
+normalMicroPC(MicroPC upc)
+{
+    return upc & ~MicroPCRomBit;
+}
+
+static inline bool
+isRomMicroPC(MicroPC upc)
+{
+    return MicroPCRomBit & upc;
+}
+
 const Addr MaxAddr = (Addr)-1;
 
 /**
index e9b7daa4a03b068d3ebebce2958a400e01991ec7..bc6f594076f39e67cc1754b42d3fa36a115eb5e2 100644 (file)
@@ -38,6 +38,7 @@
 #include <string>
 
 #include "arch/faults.hh"
+#include "arch/utility.hh"
 #include "base/fast_alloc.hh"
 #include "base/trace.hh"
 #include "config/full_system.hh"
@@ -241,36 +242,15 @@ class BaseDynInst : public FastAlloc, public RefCounted
     /** Records changes to result? */
     bool recordResult;
 
-    /** PC of this instruction. */
-    Addr PC;
-
-    /** Micro PC of this instruction. */
-    Addr microPC;
-
     /** Did this instruction execute, or is it predicated false */
     bool predicate;
 
   protected:
-    /** Next non-speculative PC.  It is not filled in at fetch, but rather
-     *  once the target of the branch is truly known (either decode or
-     *  execute).
-     */
-    Addr nextPC;
-
-    /** Next non-speculative NPC. Target PC for Mips or Sparc. */
-    Addr nextNPC;
+    /** PC state for this instruction. */
+    TheISA::PCState pc;
 
-    /** Next non-speculative micro PC. */
-    Addr nextMicroPC;
-
-    /** Predicted next PC. */
-    Addr predPC;
-
-    /** Predicted next NPC. */
-    Addr predNPC;
-
-    /** Predicted next microPC */
-    Addr predMicroPC;
+    /** Predicted PC state after this instruction. */
+    TheISA::PCState predPC;
 
     /** If this is a branch that was predicted taken */
     bool predTaken;
@@ -386,27 +366,23 @@ class BaseDynInst : public FastAlloc, public RefCounted
     }
     /** BaseDynInst constructor given a binary instruction.
      *  @param staticInst A StaticInstPtr to the underlying instruction.
-     *  @param PC The PC of the instruction.
-     *  @param pred_PC The predicted next PC.
-     *  @param pred_NPC The predicted next NPC.
+     *  @param pc The PC state for the instruction.
+     *  @param predPC The predicted next PC state for the instruction.
      *  @param seq_num The sequence number of the instruction.
      *  @param cpu Pointer to the instruction's CPU.
      */
-    BaseDynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC,
-            Addr pred_PC, Addr pred_NPC, Addr pred_MicroPC,
-            InstSeqNum seq_num, ImplCPU *cpu);
+    BaseDynInst(StaticInstPtr staticInst, TheISA::PCState pc,
+                TheISA::PCState predPC, InstSeqNum seq_num, ImplCPU *cpu);
 
     /** BaseDynInst constructor given a binary instruction.
      *  @param inst The binary instruction.
-     *  @param PC The PC of the instruction.
-     *  @param pred_PC The predicted next PC.
-     *  @param pred_NPC The predicted next NPC.
+     *  @param _pc The PC state for the instruction.
+     *  @param _predPC The predicted next PC state for the instruction.
      *  @param seq_num The sequence number of the instruction.
      *  @param cpu Pointer to the instruction's CPU.
      */
-    BaseDynInst(TheISA::ExtMachInst inst, Addr PC, Addr NPC, Addr microPC,
-            Addr pred_PC, Addr pred_NPC, Addr pred_MicroPC,
-            InstSeqNum seq_num, ImplCPU *cpu);
+    BaseDynInst(TheISA::ExtMachInst inst, TheISA::PCState pc,
+                TheISA::PCState predPC, InstSeqNum seq_num, ImplCPU *cpu);
 
     /** BaseDynInst constructor given a StaticInst pointer.
      *  @param _staticInst The StaticInst for this BaseDynInst.
@@ -443,45 +419,22 @@ class BaseDynInst : public FastAlloc, public RefCounted
      */
     bool doneTargCalc() { return false; }
 
-    /** Returns the next PC.  This could be the speculative next PC if it is
-     *  called prior to the actual branch target being calculated.
-     */
-    Addr readNextPC() { return nextPC; }
-
-    /** Returns the next NPC.  This could be the speculative next NPC if it is
-     *  called prior to the actual branch target being calculated.
-     */
-    Addr readNextNPC()
-    {
-#if ISA_HAS_DELAY_SLOT
-        return nextNPC;
-#else
-        return nextPC + sizeof(TheISA::MachInst);
-#endif
-    }
-
-    Addr readNextMicroPC()
-    {
-        return nextMicroPC;
-    }
-
     /** Set the predicted target of this current instruction. */
-    void setPredTarg(Addr predicted_PC, Addr predicted_NPC,
-            Addr predicted_MicroPC)
+    void setPredTarg(const TheISA::PCState &_predPC)
     {
-        predPC = predicted_PC;
-        predNPC = predicted_NPC;
-        predMicroPC = predicted_MicroPC;
+        predPC = _predPC;
     }
 
+    const TheISA::PCState &readPredTarg() { return predPC; }
+
     /** Returns the predicted PC immediately after the branch. */
-    Addr readPredPC() { return predPC; }
+    Addr predInstAddr() { return predPC.instAddr(); }
 
     /** Returns the predicted PC two instructions after the branch */
-    Addr readPredNPC() { return predNPC; }
+    Addr predNextInstAddr() { return predPC.nextInstAddr(); }
 
     /** Returns the predicted micro PC after the branch */
-    Addr readPredMicroPC() { return predMicroPC; }
+    Addr predMicroPC() { return predPC.microPC(); }
 
     /** Returns whether the instruction was predicted taken or not. */
     bool readPredTaken()
@@ -497,9 +450,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
     /** Returns whether the instruction mispredicted. */
     bool mispredicted()
     {
-        return readPredPC() != readNextPC() ||
-            readPredNPC() != readNextNPC() ||
-            readPredMicroPC() != readNextMicroPC();
+        TheISA::PCState tempPC = pc;
+        TheISA::advancePC(tempPC, staticInst);
+        return !(tempPC == predPC);
     }
 
     //
@@ -576,7 +529,8 @@ class BaseDynInst : public FastAlloc, public RefCounted
     OpClass opClass() const { return staticInst->opClass(); }
 
     /** Returns the branch target address. */
-    Addr branchTarget() const { return staticInst->branchTarget(PC); }
+    TheISA::PCState branchTarget() const
+    { return staticInst->branchTarget(pc); }
 
     /** Returns the number of source registers. */
     int8_t numSrcRegs() const { return staticInst->numSrcRegs(); }
@@ -773,30 +727,20 @@ class BaseDynInst : public FastAlloc, public RefCounted
     /** Returns whether or not this instruction is squashed in the ROB. */
     bool isSquashedInROB() const { return status[SquashedInROB]; }
 
-    /** Read the PC of this instruction. */
-    const Addr readPC() const { return PC; }
+    /** Read the PC state of this instruction. */
+    const TheISA::PCState pcState() const { return pc; }
 
-    /**Read the micro PC of this instruction. */
-    const Addr readMicroPC() const { return microPC; }
+    /** Set the PC state of this instruction. */
+    const void pcState(const TheISA::PCState &val) { pc = val; }
 
-    /** Set the next PC of this instruction (its actual target). */
-    void setNextPC(Addr val)
-    {
-        nextPC = val;
-    }
+    /** Read the PC of this instruction. */
+    const Addr instAddr() const { return pc.instAddr(); }
 
-    /** Set the next NPC of this instruction (the target in Mips or Sparc).*/
-    void setNextNPC(Addr val)
-    {
-#if ISA_HAS_DELAY_SLOT
-        nextNPC = val;
-#endif
-    }
+    /** Read the PC of the next instruction. */
+    const Addr nextInstAddr() const { return pc.nextInstAddr(); }
 
-    void setNextMicroPC(Addr val)
-    {
-        nextMicroPC = val;
-    }
+    /**Read the micro PC of this instruction. */
+    const Addr microPC() const { return pc.microPC(); }
 
     bool readPredicate()
     {
@@ -895,7 +839,7 @@ BaseDynInst<Impl>::readBytes(Addr addr, uint8_t *data,
                              unsigned size, unsigned flags)
 {
     reqMade = true;
-    Request *req = new Request(asid, addr, size, flags, this->PC,
+    Request *req = new Request(asid, addr, size, flags, this->pc.instAddr(),
                                thread->contextId(), threadNumber);
 
     Request *sreqLow = NULL;
@@ -956,7 +900,7 @@ BaseDynInst<Impl>::writeBytes(uint8_t *data, unsigned size,
     }
 
     reqMade = true;
-    Request *req = new Request(asid, addr, size, flags, this->PC,
+    Request *req = new Request(asid, addr, size, flags, this->pc.instAddr(),
                                thread->contextId(), threadNumber);
 
     Request *sreqLow = NULL;
index 4fb8490c163605bc5a16c58791c9728e5ccf715f..923b204ceec979a93fa587d294605e22dc02f919 100644 (file)
@@ -62,32 +62,14 @@ my_hash_t thishash;
 
 template <class Impl>
 BaseDynInst<Impl>::BaseDynInst(StaticInstPtr _staticInst,
-                               Addr inst_PC, Addr inst_NPC,
-                               Addr inst_MicroPC,
-                               Addr pred_PC, Addr pred_NPC,
-                               Addr pred_MicroPC,
+                               TheISA::PCState _pc, TheISA::PCState _predPC,
                                InstSeqNum seq_num, ImplCPU *cpu)
   : staticInst(_staticInst), traceData(NULL), cpu(cpu)
 {
     seqNum = seq_num;
 
-    bool nextIsMicro =
-        staticInst->isMicroop() && !staticInst->isLastMicroop();
-
-    PC = inst_PC;
-    microPC = inst_MicroPC;
-    if (nextIsMicro) {
-        nextPC = inst_PC;
-        nextNPC = inst_NPC;
-        nextMicroPC = microPC + 1;
-    } else {
-        nextPC = inst_NPC;
-        nextNPC = nextPC + sizeof(TheISA::MachInst);
-        nextMicroPC = 0;
-    }
-    predPC = pred_PC;
-    predNPC = pred_NPC;
-    predMicroPC = pred_MicroPC;
+    pc = _pc;
+    predPC = _predPC;
     predTaken = false;
 
     initVars();
@@ -95,32 +77,14 @@ BaseDynInst<Impl>::BaseDynInst(StaticInstPtr _staticInst,
 
 template <class Impl>
 BaseDynInst<Impl>::BaseDynInst(TheISA::ExtMachInst inst,
-                               Addr inst_PC, Addr inst_NPC,
-                               Addr inst_MicroPC,
-                               Addr pred_PC, Addr pred_NPC,
-                               Addr pred_MicroPC,
+                               TheISA::PCState _pc, TheISA::PCState _predPC,
                                InstSeqNum seq_num, ImplCPU *cpu)
-  : staticInst(inst, inst_PC), traceData(NULL), cpu(cpu)
+  : staticInst(inst, _pc.instAddr()), traceData(NULL), cpu(cpu)
 {
     seqNum = seq_num;
 
-    bool nextIsMicro =
-        staticInst->isMicroop() && !staticInst->isLastMicroop();
-
-    PC = inst_PC;
-    microPC = inst_MicroPC;
-    if (nextIsMicro) {
-        nextPC = inst_PC;
-        nextNPC = inst_NPC;
-        nextMicroPC = microPC + 1;
-    } else {
-        nextPC = inst_NPC;
-        nextNPC = nextPC + sizeof(TheISA::MachInst);
-        nextMicroPC = 0;
-    }
-    predPC = pred_PC;
-    predNPC = pred_NPC;
-    predMicroPC = pred_MicroPC;
+    pc = _pc;
+    predPC = _predPC;
     predTaken = false;
 
     initVars();
@@ -301,8 +265,8 @@ template <class Impl>
 void
 BaseDynInst<Impl>::dump()
 {
-    cprintf("T%d : %#08d `", threadNumber, PC);
-    std::cout << staticInst->disassemble(PC);
+    cprintf("T%d : %#08d `", threadNumber, pc.instAddr());
+    std::cout << staticInst->disassemble(pc.instAddr());
     cprintf("'\n");
 }
 
@@ -311,8 +275,8 @@ void
 BaseDynInst<Impl>::dump(std::string &outstring)
 {
     std::ostringstream s;
-    s << "T" << threadNumber << " : 0x" << PC << " "
-      << staticInst->disassemble(PC);
+    s << "T" << threadNumber << " : 0x" << pc.instAddr() << " "
+      << staticInst->disassemble(pc.instAddr());
 
     outstring = s.str();
 }
index a2f44106d64c6c392be3d7e7d3eb2b00fb7ea0ae..df5d8209bda9d425b0601f35373f14fd424b4b56 100644 (file)
@@ -241,13 +241,9 @@ class CheckerCPU : public BaseCPU
         result.integer = val;
     }
 
-    uint64_t readPC() { return thread->readPC(); }
+    uint64_t instAddr() { return thread->instAddr(); }
 
-    uint64_t readNextPC() { return thread->readNextPC(); }
-
-    void setNextPC(uint64_t val) {
-        thread->setNextPC(val);
-    }
+    uint64_t nextInstAddr() { return thread->nextInstAddr(); }
 
     MiscReg readMiscRegNoEffect(int misc_reg)
     {
index 4bab778ba125d26fbcc8c847c00e8a867d6772d7..f8b25ef73ee63284f7838fd33c3f5248b66c1c51 100644 (file)
@@ -72,10 +72,7 @@ Trace::ExeTracerRecord::traceInst(StaticInstPtr inst, bool ran)
 
     std::string sym_str;
     Addr sym_addr;
-    Addr cur_pc = PC;
-#if THE_ISA == ARM_ISA
-    cur_pc &= ~PcModeMask;
-#endif
+    Addr cur_pc = pc.instAddr();
     if (debugSymbolTable
         && IsOn(ExecSymbol)
 #if FULL_SYSTEM
@@ -85,13 +82,12 @@ Trace::ExeTracerRecord::traceInst(StaticInstPtr inst, bool ran)
         if (cur_pc != sym_addr)
             sym_str += csprintf("+%d",cur_pc - sym_addr);
         outs << "@" << sym_str;
-    }
-    else {
+    } else {
         outs << "0x" << hex << cur_pc;
     }
 
     if (inst->isMicroop()) {
-        outs << "." << setw(2) << dec << upc;
+        outs << "." << setw(2) << dec << pc.microPC();
     } else {
         outs << "   ";
     }
index 1982595eb27e1b07797b15723858f302e449d01e..65950728bb368b0bccce19f8a8f767efe7390c31 100644 (file)
@@ -47,10 +47,10 @@ class ExeTracerRecord : public InstRecord
 {
   public:
     ExeTracerRecord(Tick _when, ThreadContext *_thread,
-               const StaticInstPtr _staticInst, Addr _pc, bool spec,
-               const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0)
+               const StaticInstPtr _staticInst, TheISA::PCState _pc,
+               bool spec, const StaticInstPtr _macroStaticInst = NULL)
         : InstRecord(_when, _thread, _staticInst, _pc, spec,
-                _macroStaticInst, _upc)
+                _macroStaticInst)
     {
     }
 
@@ -69,8 +69,8 @@ class ExeTracer : public InstTracer
 
     InstRecord *
     getInstRecord(Tick when, ThreadContext *tc,
-            const StaticInstPtr staticInst, Addr pc,
-            const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0)
+            const StaticInstPtr staticInst, TheISA::PCState pc,
+            const StaticInstPtr macroStaticInst = NULL)
     {
         if (!IsOn(ExecEnable))
             return NULL;
@@ -82,7 +82,7 @@ class ExeTracer : public InstTracer
             return NULL;
 
         return new ExeTracerRecord(when, tc,
-                staticInst, pc, tc->misspeculating(), macroStaticInst, upc);
+                staticInst, pc, tc->misspeculating(), macroStaticInst);
     }
 };
 
index f1b3cacacaf03482e67afa0254116f73a582d29f..386046d1cc283293e498c581d6e014ebcd02756b 100644 (file)
@@ -75,8 +75,8 @@ struct TimeStruct {
         // struct as it is used pretty frequently.
         bool branchMispredict;
         bool branchTaken;
-        uint64_t mispredPC;
-        uint64_t nextPC;
+        Addr mispredPC;
+        TheISA::PCState nextPC;
 
         unsigned branchCount;
 
index 5d42ba5594479237e80aeff5d33beafb6cf16edf..6cd938dc6e457ebf7134f1fcf8f4aa69fe7f0a37 100644 (file)
@@ -987,47 +987,6 @@ InOrderCPU::getPipeStage(int stage_num)
     return pipelineStage[stage_num];
 }
 
-uint64_t
-InOrderCPU::readPC(ThreadID tid)
-{
-    return PC[tid];
-}
-
-
-void
-InOrderCPU::setPC(Addr new_PC, ThreadID tid)
-{
-    PC[tid] = new_PC;
-}
-
-
-uint64_t
-InOrderCPU::readNextPC(ThreadID tid)
-{
-    return nextPC[tid];
-}
-
-
-void
-InOrderCPU::setNextPC(uint64_t new_NPC, ThreadID tid)
-{
-    nextPC[tid] = new_NPC;
-}
-
-
-uint64_t
-InOrderCPU::readNextNPC(ThreadID tid)
-{
-    return nextNPC[tid];
-}
-
-
-void
-InOrderCPU::setNextNPC(uint64_t new_NNPC, ThreadID tid)
-{
-    nextNPC[tid] = new_NNPC;
-}
-
 uint64_t
 InOrderCPU::readIntReg(int reg_idx, ThreadID tid)
 {
@@ -1156,15 +1115,12 @@ InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
     // Set the CPU's PCs - This contributes to the precise state of the CPU 
     // which can be used when restoring a thread to the CPU after after any
     // type of context switching activity (fork, exception, etc.)
-    setPC(inst->readPC(), tid);
-    setNextPC(inst->readNextPC(), tid);
-    setNextNPC(inst->readNextNPC(), tid);
+    pcState(inst->pcState(), tid);
 
     if (inst->isControl()) {
         thread[tid]->lastGradIsBranch = true;
-        thread[tid]->lastBranchPC = inst->readPC();
-        thread[tid]->lastBranchNextPC = inst->readNextPC();
-        thread[tid]->lastBranchNextNPC = inst->readNextNPC();        
+        thread[tid]->lastBranchPC = inst->pcState();
+        TheISA::advancePC(thread[tid]->lastBranchPC, inst->staticInst);
     } else {
         thread[tid]->lastGradIsBranch = false;
     }
@@ -1236,15 +1192,15 @@ InOrderCPU::addToRemoveList(DynInstPtr &inst)
 {
     removeInstsThisCycle = true;
     if (!inst->isRemoveList()) {            
-        DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %#x "
+        DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s "
                 "[sn:%lli] to remove list\n",
-                inst->threadNumber, inst->readPC(), inst->seqNum);
+                inst->threadNumber, inst->pcState(), inst->seqNum);
         inst->setRemoveList();        
         removeList.push(inst->getInstListIt());
     }  else {
-        DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %#x "
+        DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %s "
                 "[sn:%lli], already remove list\n",
-                inst->threadNumber, inst->readPC(), inst->seqNum);
+                inst->threadNumber, inst->pcState(), inst->seqNum);
     }
     
 }
@@ -1252,23 +1208,23 @@ InOrderCPU::addToRemoveList(DynInstPtr &inst)
 void
 InOrderCPU::removeInst(DynInstPtr &inst)
 {
-    DPRINTF(InOrderCPU, "Removing graduated instruction [tid:%i] PC %#x "
+    DPRINTF(InOrderCPU, "Removing graduated instruction [tid:%i] PC %s "
             "[sn:%lli]\n",
-            inst->threadNumber, inst->readPC(), inst->seqNum);
+            inst->threadNumber, inst->pcState(), inst->seqNum);
 
     removeInstsThisCycle = true;
 
     // Remove the instruction.
     if (!inst->isRemoveList()) {            
-        DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %#x "
+        DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s "
                 "[sn:%lli] to remove list\n",
-                inst->threadNumber, inst->readPC(), inst->seqNum);
+                inst->threadNumber, inst->pcState(), inst->seqNum);
         inst->setRemoveList();        
         removeList.push(inst->getInstListIt());
     } else {
-        DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %#x "
+        DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %s "
                 "[sn:%lli], already on remove list\n",
-                inst->threadNumber, inst->readPC(), inst->seqNum);
+                inst->threadNumber, inst->pcState(), inst->seqNum);
     }
 
 }
@@ -1307,24 +1263,24 @@ InOrderCPU::squashInstIt(const ListIt &instIt, ThreadID tid)
 {
     if ((*instIt)->threadNumber == tid) {
         DPRINTF(InOrderCPU, "Squashing instruction, "
-                "[tid:%i] [sn:%lli] PC %#x\n",
+                "[tid:%i] [sn:%lli] PC %s\n",
                 (*instIt)->threadNumber,
                 (*instIt)->seqNum,
-                (*instIt)->readPC());
+                (*instIt)->pcState());
 
         (*instIt)->setSquashed();
 
         if (!(*instIt)->isRemoveList()) {            
-            DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %#x "
+            DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s "
                     "[sn:%lli] to remove list\n",
-                    (*instIt)->threadNumber, (*instIt)->readPC(), 
+                    (*instIt)->threadNumber, (*instIt)->pcState(),
                     (*instIt)->seqNum);
             (*instIt)->setRemoveList();        
             removeList.push(instIt);
         } else {
             DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i]"
-                    " PC %#x [sn:%lli], already on remove list\n",
-                    (*instIt)->threadNumber, (*instIt)->readPC(), 
+                    " PC %s [sn:%lli], already on remove list\n",
+                    (*instIt)->threadNumber, (*instIt)->pcState(),
                     (*instIt)->seqNum);
         }
     
@@ -1338,10 +1294,10 @@ InOrderCPU::cleanUpRemovedInsts()
 {
     while (!removeList.empty()) {
         DPRINTF(InOrderCPU, "Removing instruction, "
-                "[tid:%i] [sn:%lli] PC %#x\n",
+                "[tid:%i] [sn:%lli] PC %s\n",
                 (*removeList.front())->threadNumber,
                 (*removeList.front())->seqNum,
-               (*removeList.front())->readPC());
+               (*removeList.front())->pcState());
 
         DynInstPtr inst = *removeList.front();
         ThreadID tid = inst->threadNumber;
@@ -1417,9 +1373,10 @@ InOrderCPU::dumpInsts()
     cprintf("Dumping Instruction List\n");
 
     while (inst_list_it != instList[0].end()) {
-        cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
+        cprintf("Instruction:%i\nPC:%s\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
                 "Squashed:%i\n\n",
-                num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
+                num, (*inst_list_it)->pcState(),
+                (*inst_list_it)->threadNumber,
                 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
                 (*inst_list_it)->isSquashed());
         inst_list_it++;
index abe24d6ed927452bc31df2a15dacbf861f680d64..df6617d56466d5615d70a2dfea284f7175b33e32 100644 (file)
@@ -273,9 +273,7 @@ class InOrderCPU : public BaseCPU
     PipelineStage *pipelineStage[ThePipeline::NumStages];
 
     /** Program Counters */
-    TheISA::IntReg PC[ThePipeline::MaxThreads];
-    TheISA::IntReg nextPC[ThePipeline::MaxThreads];
-    TheISA::IntReg nextNPC[ThePipeline::MaxThreads];
+    TheISA::PCState pc[ThePipeline::MaxThreads];
 
     /** The Register File for the CPU */
     union {
@@ -471,22 +469,22 @@ class InOrderCPU : public BaseCPU
                            ThreadID tid);
 
     /** Reads the commit PC of a specific thread. */
-    uint64_t readPC(ThreadID tid);
+    TheISA::PCState
+    pcState(ThreadID tid)
+    {
+        return pc[tid];
+    }
 
     /** Sets the commit PC of a specific thread. */
-    void setPC(Addr new_PC, ThreadID tid);
-
-    /** Reads the next PC of a specific thread. */
-    uint64_t readNextPC(ThreadID tid);
-
-    /** Sets the next PC of a specific thread. */
-    void setNextPC(uint64_t val, ThreadID tid);
-
-    /** Reads the next NPC of a specific thread. */
-    uint64_t readNextNPC(ThreadID tid);
+    void
+    pcState(const TheISA::PCState &newPC, ThreadID tid)
+    {
+        pc[tid] = newPC;
+    }
 
-    /** Sets the next NPC of a specific thread. */
-    void setNextNPC(uint64_t val, ThreadID tid);
+    Addr instAddr(ThreadID tid) { return pc[tid].instAddr(); }
+    Addr nextInstAddr(ThreadID tid) { return pc[tid].nextInstAddr(); }
+    MicroPC microPC(ThreadID tid) { return pc[tid].microPC(); }
 
     /** Function to add instruction onto the head of the list of the
      *  instructions.  Used when new instructions are fetched.
index 658ce37d39ef11c252a98a50a1b68c672f8b90dd..ae458c604c2dfbc3da7b6c6531970cdc25d63409 100644 (file)
@@ -84,8 +84,8 @@ FirstStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
             break;
         }
         DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] "
-                "PC %08p.\n", tid, insts[tid].front()->seqNum, 
-                insts[tid].front()->PC);
+                "PC %s.\n", tid, insts[tid].front()->seqNum,
+                insts[tid].front()->pc);
         insts[tid].pop();
     }
 
index 2465744e508fec0346b8d34323c77b832a0284f4..f672082f301780ffe4bef34a3bb7c44716e57af0 100644 (file)
@@ -47,17 +47,16 @@ using namespace std;
 using namespace TheISA;
 using namespace ThePipeline;
 
-InOrderDynInst::InOrderDynInst(TheISA::ExtMachInst machInst, Addr inst_PC,
-                               Addr pred_PC, InstSeqNum seq_num,
-                               InOrderCPU *cpu)
-  : staticInst(machInst, inst_PC), traceData(NULL), cpu(cpu)
+InOrderDynInst::InOrderDynInst(TheISA::ExtMachInst machInst,
+                               const TheISA::PCState &instPC,
+                               const TheISA::PCState &_predPC,
+                               InstSeqNum seq_num, InOrderCPU *cpu)
+  : staticInst(machInst, instPC.instAddr()), traceData(NULL), cpu(cpu)
 {
     seqNum = seq_num;
 
-    PC = inst_PC;
-    nextPC = PC + sizeof(MachInst);
-    nextNPC = nextPC + sizeof(MachInst);
-    predPC = pred_PC;
+    pc = instPC;
+    predPC = _predPC;
 
     initVars();
 }
@@ -94,7 +93,7 @@ int InOrderDynInst::instcount = 0;
 void
 InOrderDynInst::setMachInst(ExtMachInst machInst)
 {
-    staticInst = StaticInst::decode(machInst, PC);
+    staticInst = StaticInst::decode(machInst, pc.instAddr());
 
     for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
         _destRegIdx[i] = this->staticInst->destRegIdx(i);
@@ -747,8 +746,8 @@ InOrderDynInst::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
 void
 InOrderDynInst::dump()
 {
-    cprintf("T%d : %#08d `", threadNumber, PC);
-    cout << staticInst->disassemble(PC);
+    cprintf("T%d : %#08d `", threadNumber, pc.instAddr());
+    cout << staticInst->disassemble(pc.instAddr());
     cprintf("'\n");
 }
 
@@ -756,8 +755,8 @@ void
 InOrderDynInst::dump(std::string &outstring)
 {
     std::ostringstream s;
-    s << "T" << threadNumber << " : 0x" << PC << " "
-      << staticInst->disassemble(PC);
+    s << "T" << threadNumber << " : " << pc << " "
+      << staticInst->disassemble(pc.instAddr());
 
     outstring = s.str();
 }
index 0d42f46963120e37430ac507d466208ae57fa5e6..105e3765722a350f78261c9aa41a9553b829cb21 100644 (file)
@@ -41,6 +41,7 @@
 #include "arch/isa_traits.hh"
 #include "arch/mt.hh"
 #include "arch/types.hh"
+#include "arch/utility.hh"
 #include "base/fast_alloc.hh"
 #include "base/trace.hh"
 #include "base/types.hh"
@@ -108,12 +109,13 @@ class InOrderDynInst : public FastAlloc, public RefCounted
     /** BaseDynInst constructor given a binary instruction.
      *  @param inst The binary instruction.
      *  @param PC The PC of the instruction.
-     *  @param pred_PC The predicted next PC.
+     *  @param predPC The predicted next PC.
      *  @param seq_num The sequence number of the instruction.
      *  @param cpu Pointer to the instruction's CPU.
      */
-    InOrderDynInst(ExtMachInst inst, Addr PC, Addr pred_PC, InstSeqNum seq_num,
-                 InOrderCPU *cpu);
+    InOrderDynInst(ExtMachInst inst, const TheISA::PCState &PC,
+                   const TheISA::PCState &predPC, InstSeqNum seq_num,
+                   InOrderCPU *cpu);
 
     /** BaseDynInst constructor given a binary instruction.
      *  @param seq_num The sequence number of the instruction.
@@ -269,28 +271,10 @@ class InOrderDynInst : public FastAlloc, public RefCounted
     InstResult instResult[MaxInstDestRegs];
 
     /** PC of this instruction. */
-    Addr PC;
-
-    /** Next non-speculative PC.  It is not filled in at fetch, but rather
-     *  once the target of the branch is truly known (either decode or
-     *  execute).
-     */
-    Addr nextPC;
-
-    /** Next next non-speculative PC.  It is not filled in at fetch, but rather
-     *  once the target of the branch is truly known (either decode or
-     *  execute).
-     */
-    Addr nextNPC;
+    TheISA::PCState pc;
 
     /** Predicted next PC. */
-    Addr predPC;
-
-    /** Predicted next NPC. */
-    Addr predNPC;
-
-    /** Predicted next microPC */
-    Addr predMicroPC;
+    TheISA::PCState predPC;
 
     /** Address to fetch from */
     Addr fetchAddr;
@@ -540,33 +524,14 @@ class InOrderDynInst : public FastAlloc, public RefCounted
     //
     ////////////////////////////////////////////////////////////
     /** Read the PC of this instruction. */
-    const Addr readPC() const { return PC; }
+    const TheISA::PCState &pcState() const { return pc; }
 
     /** Sets the PC of this instruction. */
-    void setPC(Addr pc) { PC = pc; }
-
-    /** Returns the next PC.  This could be the speculative next PC if it is
-     *  called prior to the actual branch target being calculated.
-     */
-    Addr readNextPC() { return nextPC; }
+    void pcState(const TheISA::PCState &_pc) { pc = _pc; }
 
-    /** Set the next PC of this instruction (its actual target). */
-    void setNextPC(uint64_t val) { nextPC = val; }
-
-    /** Returns the next NPC.  This could be the speculative next NPC if it is
-     *  called prior to the actual branch target being calculated.
-     */
-    Addr readNextNPC()
-    {
-#if ISA_HAS_DELAY_SLOT
-        return nextNPC;
-#else
-        return nextPC + sizeof(TheISA::MachInst);
-#endif
-    }
-
-    /** Set the next PC of this instruction (its actual target). */
-    void setNextNPC(uint64_t val) { nextNPC = val; }
+    const Addr instAddr() { return pc.instAddr(); }
+    const Addr nextInstAddr() { return pc.nextInstAddr(); }
+    const MicroPC microPC() { return pc.microPC(); }
 
     ////////////////////////////////////////////////////////////
     //
@@ -574,38 +539,36 @@ class InOrderDynInst : public FastAlloc, public RefCounted
     //
     ////////////////////////////////////////////////////////////
     /** Set the predicted target of this current instruction. */
-    void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; }
+    void setPredTarg(const TheISA::PCState &predictedPC)
+    { predPC = predictedPC; }
 
     /** Returns the predicted target of the branch. */
-    Addr readPredTarg() { return predPC; }
+    TheISA::PCState readPredTarg() { return predPC; }
 
     /** Returns the predicted PC immediately after the branch. */
-    Addr readPredPC() { return predPC; }
+    Addr predInstAddr() { return predPC.instAddr(); }
 
     /** Returns the predicted PC two instructions after the branch */
-    Addr readPredNPC() { return predNPC; }
+    Addr predNextInstAddr() { return predPC.nextInstAddr(); }
 
     /** Returns the predicted micro PC after the branch */
-    Addr readPredMicroPC() { return predMicroPC; }
+    Addr readPredMicroPC() { return predPC.microPC(); }
 
     /** Returns whether the instruction was predicted taken or not. */
     bool predTaken() { return predictTaken; }
 
     /** Returns whether the instruction mispredicted. */
-    bool mispredicted()
+    bool
+    mispredicted()
     {
-#if ISA_HAS_DELAY_SLOT
-        return predPC != nextNPC;
-#else
-        return predPC != nextPC;
-#endif
+        TheISA::PCState nextPC = pc;
+        TheISA::advancePC(nextPC, staticInst);
+        return !(nextPC == predPC);
     }
 
-    /** Returns whether the instruction mispredicted. */
-    bool mistargeted() { return predPC != nextNPC; }
-
     /** Returns the branch target address. */
-    Addr branchTarget() const { return staticInst->branchTarget(PC); }
+    TheISA::PCState branchTarget() const
+    { return staticInst->branchTarget(pc); }
 
     /** Checks whether or not this instruction has had its branch target
      *  calculated yet.  For now it is not utilized and is hacked to be
index 90c94a4f567c29be7b1dec20f5526254efcc5742..70a94767119a6b925b33beda3936e35e42e289da 100644 (file)
@@ -70,15 +70,15 @@ InOrderTrace::getInstRecord(unsigned num_stages, bool stage_tracing,
     if (!Trace::enabled)
         return NULL;
 
-    return new InOrderTraceRecord(num_stages, stage_tracing, tc);
+    return new InOrderTraceRecord(num_stages, stage_tracing, tc, 0);
 }
 
 InOrderTraceRecord *
 InOrderTrace::getInstRecord(Tick when, ThreadContext *tc,
-        const StaticInstPtr staticInst, Addr pc,
-        const StaticInstPtr macroStaticInst, MicroPC upc)
+        const StaticInstPtr staticInst, TheISA::PCState _pc,
+        const StaticInstPtr macroStaticInst)
 {
-    return new InOrderTraceRecord(ThePipeline::NumStages, true, tc);
+    return new InOrderTraceRecord(ThePipeline::NumStages, true, tc, _pc);
 }
 
 /* namespace Trace */ }
index ccc868f15f792602e8b59e6e3a834375867d4768..fd142750015b94af5df0f0d4fdcf329db78cc94a 100644 (file)
@@ -47,8 +47,8 @@ class InOrderTraceRecord : public ExeTracerRecord
 {
   public:
     InOrderTraceRecord(unsigned num_stages, bool _stage_tracing,
-           ThreadContext *_thread, bool spec = false)
-        : ExeTracerRecord(0, _thread, NULL, 0, spec)
+           ThreadContext *_thread, TheISA::PCState _pc, bool spec = false)
+        : ExeTracerRecord(0, _thread, NULL, _pc, spec)
     {
         stageTrace = _stage_tracing;
         stageCycle.resize(num_stages);
@@ -75,7 +75,8 @@ class InOrderTraceRecord : public ExeTracerRecord
     {
         staticInst = _staticInst;
     }
-    void setPC(Addr _pc) { PC = _pc; }
+
+    void setPC(TheISA::PCState _pc) { pc = _pc; }
 };
 
 class InOrderTrace : public InstTracer
@@ -87,9 +88,9 @@ class InOrderTrace : public InstTracer
     InOrderTraceRecord *
     getInstRecord(unsigned num_stages, bool stage_tracing, ThreadContext *tc);
 
-    virtual InOrderTraceRecord *getInstRecord(Tick when, ThreadContext *tc,
-            const StaticInstPtr staticInst, Addr pc,
-            const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0);
+    InOrderTraceRecord *getInstRecord(Tick when, ThreadContext *tc,
+            const StaticInstPtr staticInst, TheISA::PCState pc,
+            const StaticInstPtr macroStaticInst = NULL);
 };
 
 /* namespace Trace */ }
index f0b48d6f61efe2b33066a20f4cc900313fe403f0..dc36965b07e683b5a36f8d3c06e688ad023cec11 100644 (file)
@@ -350,27 +350,21 @@ PipelineStage::squashDueToBranch(DynInstPtr &inst, ThreadID tid)
         toPrevStages->stageInfo[stageNum][tid].squash = true;
         toPrevStages->stageInfo[stageNum][tid].nextPC = inst->readPredTarg();
 
+        toPrevStages->stageInfo[stageNum][tid].branchTaken =
+            inst->pcState().branching();
 
 #if ISA_HAS_DELAY_SLOT
-        toPrevStages->stageInfo[stageNum][tid].branchTaken = 
-            inst->readNextNPC() !=
-            (inst->readNextPC() + sizeof(TheISA::MachInst));
-
-        toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = 
+        toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum =
             inst->bdelaySeqNum;
 
         InstSeqNum squash_seq_num = inst->bdelaySeqNum;
 #else
-        toPrevStages->stageInfo[stageNum][tid].branchTaken = 
-            inst->readNextPC() !=
-            (inst->readPC() + sizeof(TheISA::MachInst));
-
         toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = inst->seqNum;
         InstSeqNum squash_seq_num = inst->seqNum;
 #endif
 
         DPRINTF(InOrderStage, "Target being re-set to %08p\n", 
-                inst->readPredTarg());
+                inst->predInstAddr());
         DPRINTF(InOrderStage, "[tid:%i]: Squashing after [sn:%i], "
                 "due to [sn:%i] branch.\n", tid, squash_seq_num, 
                 inst->seqNum);
@@ -398,10 +392,10 @@ PipelineStage::squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid)
             prevStage->insts[i]->seqNum > squash_seq_num) {
             // Change Comment to Annulling previous instruction
             DPRINTF(InOrderStage, "[tid:%i]: Squashing instruction, "
-                    "[sn:%i] PC %08p.\n",
+                    "[sn:%i] PC %s.\n",
                     tid,
                     prevStage->insts[i]->seqNum,
-                    prevStage->insts[i]->readPC());
+                    prevStage->insts[i]->pcState());
             prevStage->insts[i]->setSquashed();
 
             prevStage->insts[i] = cpu->dummyBufferInst;
@@ -429,8 +423,8 @@ PipelineStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
             break;
         }
         DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] "
-                " PC %08p.\n", tid, skidBuffer[tid].front()->seqNum, 
-                skidBuffer[tid].front()->PC);
+                " PC %s.\n", tid, skidBuffer[tid].front()->seqNum,
+                skidBuffer[tid].front()->pc);
         skidBuffer[tid].pop();
     }
 
@@ -488,8 +482,8 @@ PipelineStage::skidInsert(ThreadID tid)
 
         assert(tid == inst->threadNumber);
 
-        DPRINTF(InOrderStage,"[tid:%i]: Inserting [sn:%lli] PC:%#x into stage "
-                "skidBuffer %i\n", tid, inst->seqNum, inst->readPC(), 
+        DPRINTF(InOrderStage,"[tid:%i]: Inserting [sn:%lli] PC:%s into stage "
+                "skidBuffer %i\n", tid, inst->seqNum, inst->pcState(),
                 inst->threadNumber);
 
         skidBuffer[tid].push(inst);
@@ -571,9 +565,9 @@ PipelineStage::activateThread(ThreadID tid)
         } else {
             DynInstPtr inst = switchedOutBuffer[tid];
 
-            DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%#x into"
+            DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%s into"
                     " stage skidBuffer %i\n", tid, inst->seqNum,
-                    inst->readPC(), inst->threadNumber);
+                    inst->pcState(), inst->threadNumber);
 
             // Make instruction available for pipeline processing
             skidBuffer[tid].push(inst);            
@@ -895,13 +889,12 @@ PipelineStage::processInsts(ThreadID tid)
         inst = insts_to_stage.front();
 
         DPRINTF(InOrderStage, "[tid:%u]: Processing instruction [sn:%lli] "
-                "with PC %#x\n",
-                tid, inst->seqNum, inst->readPC());
+                "with PC %s\n", tid, inst->seqNum, inst->pcState());
 
         if (inst->isSquashed()) {
-            DPRINTF(InOrderStage, "[tid:%u]: Instruction %i with PC %#x is "
+            DPRINTF(InOrderStage, "[tid:%u]: Instruction %i with PC %s is "
                     "squashed, skipping.\n",
-                    tid, inst->seqNum, inst->readPC());
+                    tid, inst->seqNum, inst->pcState());
 
             insts_to_stage.pop();
 
@@ -1001,8 +994,8 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed)
                     switchedOutValid[tid] = true;
                     
                     // Remove Thread From Pipeline & Resource Pool
-                    inst->squashingStage = stageNum;         
-                    inst->bdelaySeqNum = inst->seqNum;                               
+                    inst->squashingStage = stageNum;
+                    inst->bdelaySeqNum = inst->seqNum;
                     cpu->squashFromMemStall(inst, tid);  
 
                     // Switch On Cache Miss
@@ -1038,9 +1031,9 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed)
             res_stage_num = inst->nextResStage();
         }
     } else {
-        DPRINTF(InOrderStage, "[tid:%u]: Instruction [sn:%i] with PC %#x "
+        DPRINTF(InOrderStage, "[tid:%u]: Instruction [sn:%i] with PC %s "
                 " needed no resources in stage %i.\n",
-                tid, inst->seqNum, inst->readPC(), stageNum);
+                tid, inst->seqNum, inst->pcState(), stageNum);
     }
 
     return last_req_completed;
@@ -1134,8 +1127,8 @@ PipelineStage::dumpInsts()
         while (!copy_buff.empty()) {
             DynInstPtr inst = copy_buff.front();
 
-            cprintf("Inst. PC:%#x\n[tid:%i]\n[sn:%i]\n\n",
-                    inst->readPC(), inst->threadNumber, inst->seqNum);
+            cprintf("Inst. PC:%s\n[tid:%i]\n[sn:%i]\n\n",
+                    inst->pcState(), inst->threadNumber, inst->seqNum);
 
             copy_buff.pop();
         }
index c971e400e6952df63f0096b7b51715e36385eb21..6df104e6cfdbc938b0408f52f17864349994d5e1 100644 (file)
@@ -293,15 +293,15 @@ class PipelineStage
     /** SeqNum of Squashing Branch Delay Instruction (used for MIPS) */
     Addr bdelayDoneSeqNum[ThePipeline::MaxThreads];
 
-    /** Instruction used for squashing branch (used for MIPS) */
-    DynInstPtr squashInst[ThePipeline::MaxThreads];
-
     /** Tells when their is a pending delay slot inst. to send
      *  to rename. If there is, then wait squash after the next
      *  instruction (used for MIPS).
      */
     bool squashAfterDelaySlot[ThePipeline::MaxThreads];
 
+    /** Instruction used for squashing branch (used for MIPS) */
+    DynInstPtr squashInst[ThePipeline::MaxThreads];
+
     /** Maximum size of the inter-stage buffer connecting the previous stage to
      *  this stage (which we call a skid buffer) */
     unsigned stageBufferMax;
index b08a393f7f200ce7b32e05a7308b24cd1f7e0b1c..31005340927845c40fddd01a3e2661ce995c057a 100644 (file)
@@ -31,6 +31,7 @@
 #include <list>
 #include <vector>
 
+#include "arch/utility.hh"
 #include "base/trace.hh"
 #include "base/traceflags.hh"
 #include "config/the_isa.hh"
@@ -149,7 +150,7 @@ BPredUnit::takeOverFrom()
 
 
 bool
-BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid)
+BPredUnit::predict(DynInstPtr &inst, TheISA::PCState &predPC, ThreadID tid)
 {
     // See if branch predictor predicts taken.
     // If so, get its target addr either from the BTB or the RAS.
@@ -160,12 +161,13 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid)
     
     int asid = inst->asid;
     bool pred_taken = false;
-    Addr target;
+    TheISA::PCState target;
 
     ++lookups;
-    DPRINTF(InOrderBPred, "[tid:%i] [sn:%i] %s ... PC%#x doing branch "
+    DPRINTF(InOrderBPred, "[tid:%i] [sn:%i] %s ... PC %s doing branch "
             "prediction\n", tid, inst->seqNum,
-            inst->staticInst->disassemble(inst->PC), inst->readPC());
+            inst->staticInst->disassemble(inst->instAddr()),
+            inst->pcState());
 
 
     void *bp_history = NULL;
@@ -185,14 +187,14 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid)
     } else {
         ++condPredicted;
 
-        pred_taken = BPLookup(pred_PC, bp_history);
+        pred_taken = BPLookup(predPC.instAddr(), bp_history);
 
         DPRINTF(InOrderBPred, "[tid:%i]: Branch predictor predicted %i "
-                "for PC %#x\n",
-                tid, pred_taken, inst->readPC());
+                "for PC %s\n",
+                tid, pred_taken, inst->pcState());
     }
 
-    PredictorHistory predict_record(inst->seqNum, pred_PC, pred_taken,
+    PredictorHistory predict_record(inst->seqNum, predPC, pred_taken,
                                     bp_history, tid);
 
     // Now lookup in the BTB or RAS.
@@ -202,40 +204,37 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid)
 
             // If it's a function return call, then look up the address
             // in the RAS.
-            target = RAS[tid].top();
+            TheISA::PCState rasTop = RAS[tid].top();
+            target = TheISA::buildRetPC(inst->pcState(), rasTop);
 
             // Record the top entry of the RAS, and its index.
             predict_record.usedRAS = true;
             predict_record.RASIndex = RAS[tid].topIdx();
-            predict_record.RASTarget = target;
+            predict_record.rasTarget = rasTop;
 
             assert(predict_record.RASIndex < 16);
 
             RAS[tid].pop();
 
-            DPRINTF(InOrderBPred, "[tid:%i]: Instruction %#x is a return, "
-                    "RAS predicted target: %#x, RAS index: %i.\n",
-                    tid, inst->readPC(), target, predict_record.RASIndex);
+            DPRINTF(InOrderBPred, "[tid:%i]: Instruction %s is a return, "
+                    "RAS predicted target: %s, RAS index: %i.\n",
+                    tid, inst->pcState(), target,
+                    predict_record.RASIndex);
         } else {
             ++BTBLookups;
 
             if (inst->isCall()) {
 
-#if ISA_HAS_DELAY_SLOT
-                Addr ras_pc = pred_PC + instSize; // Next Next PC
-#else
-                Addr ras_pc = pred_PC; // Next PC
-#endif
-
-                RAS[tid].push(ras_pc);
+                RAS[tid].push(inst->pcState());
 
                 // Record that it was a call so that the top RAS entry can
                 // be popped off if the speculation is incorrect.
                 predict_record.wasCall = true;
 
-                DPRINTF(InOrderBPred, "[tid:%i]: Instruction %#x was a call"
-                        ", adding %#x to the RAS index: %i.\n",
-                        tid, inst->readPC(), ras_pc, RAS[tid].topIdx());
+                DPRINTF(InOrderBPred, "[tid:%i]: Instruction %s was a call"
+                        ", adding %s to the RAS index: %i.\n",
+                        tid, inst->pcState(), predPC,
+                        RAS[tid].topIdx());
             }
 
             if (inst->isCall() &&
@@ -243,18 +242,18 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid)
                 inst->isDirectCtrl()) {
                 target = inst->branchTarget();
 
-                DPRINTF(InOrderBPred, "[tid:%i]: Setting %#x predicted"
-                        " target to %#x.\n",
-                        tid, inst->readPC(), target);
-            } else if (BTB.valid(pred_PC, asid)) {
+                DPRINTF(InOrderBPred, "[tid:%i]: Setting %s predicted"
+                        " target to %s.\n",
+                        tid, inst->pcState(), target);
+            } else if (BTB.valid(predPC.instAddr(), asid)) {
                 ++BTBHits;
 
                 // If it's not a return, use the BTB to get the target addr.
-                target = BTB.lookup(pred_PC, asid);
+                target = BTB.lookup(predPC.instAddr(), asid);
 
-                DPRINTF(InOrderBPred, "[tid:%i]: [asid:%i] Instruction %#x "
-                        "predicted target is %#x.\n",
-                        tid, asid, inst->readPC(), target);
+                DPRINTF(InOrderBPred, "[tid:%i]: [asid:%i] Instruction %s "
+                        "predicted target is %s.\n",
+                        tid, asid, inst->pcState(), target);
             } else {
                 DPRINTF(InOrderBPred, "[tid:%i]: BTB doesn't have a "
                         "valid entry.\n",tid);
@@ -265,14 +264,7 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid)
 
     if (pred_taken) {
         // Set the PC and the instruction's predicted target.
-        pred_PC = target;
-    } else {
-#if ISA_HAS_DELAY_SLOT
-        // This value will be inst->PC + 4 (nextPC)
-        // Delay Slot archs need this to be inst->PC + 8 (nextNPC)
-        // so we increment one more time here.
-        pred_PC = pred_PC + instSize;
-#endif
+        predPC = target;
     }
 
     predHist[tid].push_front(predict_record);
@@ -296,7 +288,7 @@ BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid)
     while (!predHist[tid].empty() &&
            predHist[tid].back().seqNum <= done_sn) {
         // Update the branch predictor with the correct results.
-        BPUpdate(predHist[tid].back().PC,
+        BPUpdate(predHist[tid].back().pc.instAddr(),
                  predHist[tid].back().predTaken,
                  predHist[tid].back().bpHistory);
 
@@ -314,13 +306,13 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid, ThreadID asid)
            pred_hist.front().seqNum > squashed_sn) {
         if (pred_hist.front().usedRAS) {
             DPRINTF(InOrderBPred, "BranchPred: [tid:%i]: Restoring top of RAS "
-                    "to: %i, target: %#x.\n",
+                    "to: %i, target: %s.\n",
                     tid,
                     pred_hist.front().RASIndex,
-                    pred_hist.front().RASTarget);
+                    pred_hist.front().rasTarget);
 
             RAS[tid].restore(pred_hist.front().RASIndex,
-                             pred_hist.front().RASTarget);
+                             pred_hist.front().rasTarget);
 
         } else if (pred_hist.front().wasCall) {
             DPRINTF(InOrderBPred, "BranchPred: [tid:%i]: Removing speculative "
@@ -340,7 +332,7 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid, ThreadID asid)
 
 void
 BPredUnit::squash(const InstSeqNum &squashed_sn,
-                  const Addr &corr_target,
+                  const TheISA::PCState &corrTarget,
                   bool actually_taken,
                   ThreadID tid,
                   ThreadID asid)
@@ -354,8 +346,8 @@ BPredUnit::squash(const InstSeqNum &squashed_sn,
     ++condIncorrect;
 
     DPRINTF(InOrderBPred, "[tid:%i]: Squashing from sequence number %i, "
-            "setting target to %#x.\n",
-            tid, squashed_sn, corr_target);
+            "setting target to %s.\n",
+            tid, squashed_sn, corrTarget);
 
     squash(squashed_sn, tid);
 
@@ -380,13 +372,13 @@ BPredUnit::squash(const InstSeqNum &squashed_sn,
             ++RASIncorrect;
         }
 
-        BPUpdate((*hist_it).PC, actually_taken,
+        BPUpdate((*hist_it).pc.instAddr(), actually_taken,
                  pred_hist.front().bpHistory);
 
-        BTB.update((*hist_it).PC, corr_target, asid);
+        BTB.update((*hist_it).pc.instAddr(), corrTarget, asid);
 
         DPRINTF(InOrderBPred, "[tid:%i]: Removing history for [sn:%i] "
-                "PC %#x.\n", tid, (*hist_it).seqNum, (*hist_it).PC);
+                "PC %s.\n", tid, (*hist_it).seqNum, (*hist_it).pc);
 
         pred_hist.erase(hist_it);
 
@@ -424,7 +416,7 @@ BPredUnit::BPSquash(void *bp_history)
 
 
 bool
-BPredUnit::BPLookup(Addr &inst_PC, void * &bp_history)
+BPredUnit::BPLookup(Addr inst_PC, void * &bp_history)
 {
     if (predictor == Local) {
         return localBP->lookup(inst_PC, bp_history);
@@ -437,7 +429,7 @@ BPredUnit::BPLookup(Addr &inst_PC, void * &bp_history)
 
 
 void
-BPredUnit::BPUpdate(Addr &inst_PC, bool taken, void *bp_history)
+BPredUnit::BPUpdate(Addr inst_PC, bool taken, void *bp_history)
 {
     if (predictor == Local) {
         localBP->update(inst_PC, taken, bp_history);
index 881bfcc95b0d435fdf299d781cd3d8ad287fb763..3b1c0f4efcc0758bc1bbf75fbb25f5d6cbb2d3df 100644 (file)
@@ -83,11 +83,12 @@ class BPredUnit
      * Predicts whether or not the instruction is a taken branch, and the
      * target of the branch if it is taken.
      * @param inst The branch instruction.
-     * @param pred_PC The predicted PC is passed back through this parameter.
+     * @param predPC The predicted PC is passed back through this parameter.
      * @param tid The thread id.
      * @return Returns if the branch is taken or not.
      */
-    bool predict(ThePipeline::DynInstPtr &inst, Addr &pred_PC, ThreadID tid);
+    bool predict(ThePipeline::DynInstPtr &inst,
+            TheISA::PCState &predPC, ThreadID tid);
 
     // @todo: Rename this function.
     void BPUncond(void * &bp_history);
@@ -114,12 +115,13 @@ class BPredUnit
      * corrects that sn's update with the proper address and taken/not taken.
      * @param squashed_sn The sequence number to squash any younger updates up
      * until.
-     * @param corr_target The correct branch target.
+     * @param corrTarget The correct branch target.
      * @param actually_taken The correct branch direction.
      * @param tid The thread id.
      */
-    void squash(const InstSeqNum &squashed_sn, const Addr &corr_target,
-                bool actually_taken, ThreadID tid, ThreadID asid = 0);
+    void squash(const InstSeqNum &squashed_sn,
+                const TheISA::PCState &corrTarget, bool actually_taken,
+                ThreadID tid, ThreadID asid = 0);
 
     /**
      * @param bp_history Pointer to the history object.  The predictor
@@ -134,7 +136,7 @@ class BPredUnit
      * has the branch predictor state associated with the lookup.
      * @return Whether the branch is taken or not taken.
      */
-    bool BPLookup(Addr &inst_PC, void * &bp_history);
+    bool BPLookup(Addr instPC, void * &bp_history);
 
     /**
      * Looks up a given PC in the BTB to see if a matching entry exists.
@@ -149,26 +151,26 @@ class BPredUnit
      * @param inst_PC The PC to look up.
      * @return The address of the target of the branch.
      */
-    Addr BTBLookup(Addr &inst_PC)
-    { return BTB.lookup(inst_PC, 0); }
+    TheISA::PCState BTBLookup(Addr instPC)
+    { return BTB.lookup(instPC, 0); }
 
     /**
      * Updates the BP with taken/not taken information.
-     * @param inst_PC The branch's PC that will be updated.
+     * @param instPC The branch's PC that will be updated.
      * @param taken Whether the branch was taken or not taken.
      * @param bp_history Pointer to the branch predictor state that is
      * associated with the branch lookup that is being updated.
      * @todo Make this update flexible enough to handle a global predictor.
      */
-    void BPUpdate(Addr &inst_PC, bool taken, void *bp_history);
+    void BPUpdate(Addr instPC, bool taken, void *bp_history);
 
     /**
      * Updates the BTB with the target of a branch.
      * @param inst_PC The branch's PC that will be updated.
      * @param target_PC The branch's target that will be added to the BTB.
      */
-    void BTBUpdate(Addr &inst_PC, Addr &target_PC)
-    { BTB.update(inst_PC, target_PC,0); }
+    void BTBUpdate(Addr instPC, const TheISA::PCState &targetPC)
+    { BTB.update(instPC, targetPC, 0); }
 
     void dump();
 
@@ -181,22 +183,22 @@ class BPredUnit
          * Makes a predictor history struct that contains any
          * information needed to update the predictor, BTB, and RAS.
          */
-        PredictorHistory(const InstSeqNum &seq_num, const Addr &inst_PC,
-                         bool pred_taken, void *bp_history,
-                         ThreadID _tid)
-            : seqNum(seq_num), PC(inst_PC), RASTarget(0),
-              RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0),
-              wasCall(0), bpHistory(bp_history)
-        { }
+        PredictorHistory(const InstSeqNum &seq_num,
+                         const TheISA::PCState &instPC, bool pred_taken,
+                         void *bp_history, ThreadID _tid)
+            : seqNum(seq_num), pc(instPC), rasTarget(0), RASIndex(0),
+              tid(_tid), predTaken(pred_taken), usedRAS(0), wasCall(0),
+              bpHistory(bp_history)
+        {}
 
         /** The sequence number for the predictor history entry. */
         InstSeqNum seqNum;
 
         /** The PC associated with the sequence number. */
-        Addr PC;
+        TheISA::PCState pc;
 
         /** The RAS target (only valid if a return). */
-        Addr RASTarget;
+        TheISA::PCState rasTarget;
 
         /** The RAS index of the instruction (only valid if a call). */
         unsigned RASIndex;
index b971d959a1dbc5d0d738a1978c79ab3e66f83790..33b67ce4aec7c23bbceb18c847768cd5b7acbb26 100644 (file)
@@ -84,41 +84,34 @@ BranchPredictor::execute(int slot_num)
                 DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: squashed, "
                         "skipping prediction \n", tid, inst->seqNum);
             } else {
-                Addr pred_PC = inst->readNextPC();
+                TheISA::PCState predPC = inst->pcState();
+                TheISA::advancePC(predPC, inst->staticInst);
 
                 if (inst->isControl()) {
                     // If not, the pred_PC be updated to pc+8
                     // If predicted, the pred_PC will be updated to new target
                     // value
-                    bool predict_taken = branchPred.predict(inst, pred_PC, tid);
+                    bool predict_taken = branchPred.predict(inst, predPC, tid);
 
                     if (predict_taken) {
                         DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch "
                                 "predicted true.\n", tid, seq_num);
-
-                        inst->setPredTarg(pred_PC);
-
                         predictedTaken++;
                     } else {
                         DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch "
                                 "predicted false.\n", tid, seq_num);
-
-                        if (inst->isCondDelaySlot())
-                        {
-                            inst->setPredTarg(inst->readPC() + (2 * instSize));
-                        } else {
-                            inst->setPredTarg(pred_PC);
-                        }
-
                         predictedNotTaken++;
                     }
 
+                    inst->setPredTarg(predPC);
+
                     inst->setBranchPred(predict_taken);
 
                     DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Predicted PC is "
-                            "%08p.\n", tid, seq_num, pred_PC);
+                            "%s.\n", tid, seq_num, predPC);
 
                 } else {
+                    inst->setPredTarg(predPC);
                     //DPRINTF(InOrderBPred, "[tid:%i]: Ignoring [sn:%i] "
                     //      "because this isn't "
                     //      "a control instruction.\n", tid, seq_num);
@@ -166,10 +159,9 @@ BranchPredictor::squash(DynInstPtr inst, int squash_stage,
     squash_seq_num = squash_seq_num - 1;
 #endif
 
-    if(squash_stage>=ThePipeline::BackEndStartStage) {
-        Addr corr_targ=inst->readPredPC();
-        bool taken=inst->predTaken();
-        branchPred.squash(squash_seq_num,corr_targ,taken,tid);
+    if (squash_stage >= ThePipeline::BackEndStartStage) {
+        bool taken = inst->predTaken();
+        branchPred.squash(squash_seq_num, inst->readPredTarg(), taken, tid);
     } else {
         branchPred.squash(squash_seq_num, tid);
     }
index 73deacb12a98b6a7dd872162778d9d9c2f1ae521..e7f689ffa8fdf2336f7397828c1fb1eb3ec21a9f 100644 (file)
@@ -392,15 +392,16 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
     unsigned slot_idx = cache_req->getSlot();
 
     if (tlb_mode == TheISA::TLB::Execute) {
-            inst->fetchMemReq = new Request(inst->readTid(), aligned_addr,
-                                            acc_size, flags, inst->readPC(),
-                                            cpu->readCpuId(), inst->readTid());
-            cache_req->memReq = inst->fetchMemReq;
+        inst->fetchMemReq =
+            new Request(inst->readTid(), aligned_addr, acc_size, flags,
+                        inst->instAddr(), cpu->readCpuId(), inst->readTid());
+        cache_req->memReq = inst->fetchMemReq;
     } else {
         if (!cache_req->is2ndSplit()) {            
-            inst->dataMemReq = new Request(cpu->asid[tid], aligned_addr,
-                                           acc_size, flags, inst->readPC(),
-                                           cpu->readCpuId(), inst->readTid());
+            inst->dataMemReq =
+                new Request(cpu->asid[tid], aligned_addr, acc_size, flags,
+                            inst->instAddr(), cpu->readCpuId(),
+                            inst->readTid());
             cache_req->memReq = inst->dataMemReq;
         } else {
             assert(inst->splitInst);
@@ -409,7 +410,7 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
                                             inst->split2ndAddr,
                                             acc_size, 
                                             flags, 
-                                            inst->readPC(),
+                                            inst->instAddr(),
                                             cpu->readCpuId(), 
                                             tid);
             cache_req->memReq = inst->splitMemReq;            
@@ -754,7 +755,8 @@ CacheUnit::execute(int slot_num)
 
 
             DPRINTF(InOrderCachePort, "[tid:%i]: Instruction [sn:%i] is: %s\n",
-                    tid, seq_num, inst->staticInst->disassemble(inst->PC));
+                    tid, seq_num,
+                    inst->staticInst->disassemble(inst->instAddr()));
 
             removeAddrDependency(inst);
             
@@ -771,7 +773,7 @@ CacheUnit::execute(int slot_num)
                     tid, inst->seqNum);
             DPRINTF(InOrderStall,
                     "STALL: [tid:%i]: Fetch miss from %08p\n",
-                    tid, cache_req->inst->readPC());
+                    tid, cache_req->inst->instAddr());
             cache_req->setCompleted(false);
             //cache_req->setMemStall(true);            
         }
@@ -1046,21 +1048,22 @@ CacheUnit::processCacheCompletion(PacketPtr pkt)
             // @todo: update thsi
             ExtMachInst ext_inst;
             StaticInstPtr staticInst = NULL;
-            Addr inst_pc = inst->readPC();
+            TheISA::PCState instPC = inst->pcState();
             MachInst mach_inst = 
                 TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *>
                              (cache_pkt->getPtr<uint8_t>()));
 
             predecoder.setTC(cpu->thread[tid]->getTC());
-            predecoder.moreBytes(inst_pc, inst_pc, mach_inst);
-            ext_inst = predecoder.getExtMachInst();
+            predecoder.moreBytes(instPC, inst->instAddr(), mach_inst);
+            ext_inst = predecoder.getExtMachInst(instPC);
+            inst->pcState(instPC);
 
             inst->setMachInst(ext_inst);
 
             // Set Up More TraceData info
             if (inst->traceData) {
                 inst->traceData->setStaticInst(inst->staticInst);
-                inst->traceData->setPC(inst->readPC());
+                inst->traceData->setPC(instPC);
             }
 
         } else if (inst->staticInst && inst->isMemRef()) {
@@ -1149,7 +1152,7 @@ CacheUnit::processCacheCompletion(PacketPtr pkt)
     } else {
         DPRINTF(InOrderCachePort,
                 "[tid:%u] Miss on block @ %08p completed, but squashed\n",
-                tid, cache_req->inst->readPC());
+                tid, cache_req->inst->instAddr());
         cache_req->setMemAccCompleted();
     }
 }
index 91e788fbc75166c350239efa14631027601d56d3..4342042e9f896d8a00957747b3cc93d35f2999ef 100644 (file)
@@ -91,8 +91,8 @@ ExecutionUnit::execute(int slot_num)
 
     exec_req->fault = NoFault;
 
-    DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%#x] %s.\n",
-            tid, seq_num, inst->readPC(), inst->instName());
+    DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%s] %s.\n",
+            tid, seq_num, inst->pcState(), inst->instName());
 
     switch (exec_req->cmd)
     {
@@ -124,58 +124,61 @@ ExecutionUnit::execute(int slot_num)
                         if (inst->isDirectCtrl()) {
                             assert(!inst->isIndirectCtrl());
 
+                            TheISA::PCState pc = inst->pcState();
+                            TheISA::advancePC(pc, inst->staticInst);
+                            inst->setPredTarg(pc);
+
                             if (inst->predTaken() && inst->isCondDelaySlot()) {
                                 inst->bdelaySeqNum = seq_num;
-                                inst->setPredTarg(inst->nextPC);
 
                                 DPRINTF(InOrderExecute, "[tid:%i]: Conditional"
-                                        " branch inst [sn:%i] PC %#x mis"
+                                        " branch inst [sn:%i] PC %s mis"
                                         "predicted as taken.\n", tid,
-                                        seq_num, inst->PC);
+                                        seq_num, inst->pcState());
                             } else if (!inst->predTaken() &&
                                        inst->isCondDelaySlot()) {
                                 inst->bdelaySeqNum = seq_num;
-                                inst->setPredTarg(inst->nextPC);
                                 inst->procDelaySlotOnMispred = true;
 
                                 DPRINTF(InOrderExecute, "[tid:%i]: Conditional"
-                                        " branch inst [sn:%i] PC %#x mis"
+                                        " branch inst [sn:%i] PC %s mis"
                                         "predicted as not taken.\n", tid,
-                                        seq_num, inst->PC);
+                                        seq_num, inst->pcState());
                             } else {
 #if ISA_HAS_DELAY_SLOT
                                 inst->bdelaySeqNum = seq_num + 1;
-                                inst->setPredTarg(inst->nextNPC);
 #else
                                 inst->bdelaySeqNum = seq_num;
-                                inst->setPredTarg(inst->nextPC);
 #endif
                                 DPRINTF(InOrderExecute, "[tid:%i]: "
                                         "Misprediction detected at "
-                                        "[sn:%i] PC %#x,\n\t squashing after "
+                                        "[sn:%i] PC %s,\n\t squashing after "
                                         "delay slot instruction [sn:%i].\n",
-                                        tid, seq_num, inst->PC,
+                                        tid, seq_num, inst->pcState(),
                                         inst->bdelaySeqNum);
                                 DPRINTF(InOrderStall, "STALL: [tid:%i]: Branch"
-                                        " misprediction at %#x\n",
-                                        tid, inst->PC);
+                                        " misprediction at %s\n",
+                                        tid, inst->pcState());
                             }
 
                             DPRINTF(InOrderExecute, "[tid:%i] Redirecting "
-                                    "fetch to %#x.\n", tid,
+                                    "fetch to %s.\n", tid,
                                     inst->readPredTarg());
 
-                        } else if(inst->isIndirectCtrl()){
+                        } else if (inst->isIndirectCtrl()){
+                            TheISA::PCState pc = inst->pcState();
+                            TheISA::advancePC(pc, inst->staticInst);
+                            inst->seqNum = seq_num;
+                            inst->setPredTarg(pc);
+
 #if ISA_HAS_DELAY_SLOT
-                            inst->setPredTarg(inst->nextNPC);
                             inst->bdelaySeqNum = seq_num + 1;
 #else
-                            inst->setPredTarg(inst->nextPC);
                             inst->bdelaySeqNum = seq_num;
 #endif
 
                             DPRINTF(InOrderExecute, "[tid:%i] Redirecting"
-                                    " fetch to %#x.\n", tid,
+                                    " fetch to %s.\n", tid,
                                     inst->readPredTarg());
                         } else {
                             panic("Non-control instruction (%s) mispredict"
@@ -197,14 +200,20 @@ ExecutionUnit::execute(int slot_num)
 
                         if (inst->predTaken()) {
                             predictedTakenIncorrect++;
-                            DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ... PC%#x ... Mispredicts! (Taken)\n",
-                                    tid, inst->seqNum, inst->staticInst->disassemble(inst->PC),
-                                    inst->readPC());
+                            DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..."
+                                    "PC %s ... Mispredicts! (Taken)\n",
+                                    tid, inst->seqNum,
+                                    inst->staticInst->disassemble(
+                                        inst->instAddr()),
+                                    inst->pcState());
                         } else {
                             predictedNotTakenIncorrect++;
-                            DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ... PC%#x ... Mispredicts! (Not Taken)\n",
-                                    tid, inst->seqNum, inst->staticInst->disassemble(inst->PC),
-                                    inst->readPC());
+                            DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..."
+                                    "PC %s ... Mispredicts! (Not Taken)\n",
+                                    tid, inst->seqNum,
+                                    inst->staticInst->disassemble(
+                                        inst->instAddr()),
+                                    inst->pcState());
                         }
                         predictedIncorrect++;
                     } else {
index 8a1ec3ce5be7fd84969e7feeefb9cf094735edd2..3bfe912e78392198f6c362afd5fa2fc0780eaa43 100644 (file)
@@ -44,9 +44,6 @@ FetchSeqUnit::FetchSeqUnit(std::string res_name, int res_id, int res_width,
       instSize(sizeof(MachInst))
 {
     for (ThreadID tid = 0; tid < ThePipeline::MaxThreads; tid++) {
-        delaySlotInfo[tid].numInsts = 0;
-        delaySlotInfo[tid].targetReady = false;
-
         pcValid[tid] = false;
         pcBlockStage[tid] = 0;
 
@@ -86,53 +83,17 @@ FetchSeqUnit::execute(int slot_num)
       case AssignNextPC:
         {
             if (pcValid[tid]) {
+                inst->pcState(pc[tid]);
+                inst->setMemAddr(pc[tid].instAddr());
 
-                if (delaySlotInfo[tid].targetReady &&
-                    delaySlotInfo[tid].numInsts == 0) {
-                    // Set PC to target
-                    PC[tid] = delaySlotInfo[tid].targetAddr; //next_PC
-                    nextPC[tid] = PC[tid] + instSize;        //next_NPC
-                    nextNPC[tid] = PC[tid] + (2 * instSize);
-
-                    delaySlotInfo[tid].targetReady = false;
-
-                    DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to delay "
-                            "slot target\n",tid);
-                }
+                pc[tid].advance(); //XXX HACK!
+                inst->setPredTarg(pc[tid]);
 
-                inst->setPC(PC[tid]);
-                inst->setNextPC(PC[tid] + instSize);
-                inst->setNextNPC(PC[tid] + (instSize * 2));
-
-#if ISA_HAS_DELAY_SLOT
-                inst->setPredTarg(inst->readNextNPC());
-#else
-                inst->setPredTarg(inst->readNextPC());
-#endif
-                inst->setMemAddr(PC[tid]);
                 inst->setSeqNum(cpu->getAndIncrementInstSeq(tid));
 
                 DPRINTF(InOrderFetchSeq, "[tid:%i]: Assigning [sn:%i] to "
-                        "PC %08p, NPC %08p, NNPC %08p\n", tid,
-                        inst->seqNum, inst->readPC(), inst->readNextPC(),
-                        inst->readNextNPC());
-
-                if (delaySlotInfo[tid].numInsts > 0) {
-                    --delaySlotInfo[tid].numInsts;
-
-                    // It's OK to set PC to target of branch
-                    if (delaySlotInfo[tid].numInsts == 0) {
-                        delaySlotInfo[tid].targetReady = true;
-                    }
-
-                    DPRINTF(InOrderFetchSeq, "[tid:%i]: %i delay slot inst(s) "
-                            "left to process.\n", tid,
-                            delaySlotInfo[tid].numInsts);
-                }
-
-                PC[tid] = nextPC[tid];
-                nextPC[tid] = nextNPC[tid];
-                nextNPC[tid] += instSize;
+                        "PC %s\n", tid, inst->seqNum,
+                        inst->pcState());
 
                 fs_req->done();
             } else {
@@ -147,18 +108,21 @@ FetchSeqUnit::execute(int slot_num)
             if (inst->isControl()) {
                 // If it's a return, then we must wait for resolved address.
                 if (inst->isReturn() && !inst->predTaken()) {
-                    cpu->pipelineStage[stage_num]->toPrevStages->stageBlock[stage_num][tid] = true;
+                    cpu->pipelineStage[stage_num]->
+                        toPrevStages->stageBlock[stage_num][tid] = true;
                     pcValid[tid] = false;
                     pcBlockStage[tid] = stage_num;
                 } else if (inst->isCondDelaySlot() && !inst->predTaken()) {
                 // Not-Taken AND Conditional Control
-                    DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: [PC:%08p] "
-                            "Predicted Not-Taken Cond. "
-                            "Delay inst. Skipping delay slot and  Updating PC to %08p\n",
-                            tid, inst->seqNum, inst->readPC(), inst->readPredTarg());
+                    DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: [PC:%s] "
+                            "Predicted Not-Taken Cond. Delay inst. Skipping "
+                            "delay slot and  Updating PC to %s\n",
+                            tid, inst->seqNum, inst->pcState(),
+                            inst->readPredTarg());
 
-                    DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to start from stage %i, after [sn:%i].\n",
-                            tid, stage_num, seq_num);
+                    DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to "
+                            "start from stage %i, after [sn:%i].\n", tid,
+                            stage_num, seq_num);
 
                     inst->bdelaySeqNum = seq_num;
                     inst->squashingStage = stage_num;
@@ -168,33 +132,26 @@ FetchSeqUnit::execute(int slot_num)
                     // Not-Taken Control
                     DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: Predicted "
                             "Not-Taken Control "
-                            "inst. updating PC to %08p\n", tid, inst->seqNum,
-                            inst->readNextPC());
+                            "inst. updating PC to %s\n", tid, inst->seqNum,
+                            inst->readPredTarg());
 #if ISA_HAS_DELAY_SLOT
-                    ++delaySlotInfo[tid].numInsts;
-                    delaySlotInfo[tid].targetReady = false;
-                    delaySlotInfo[tid].targetAddr = inst->readNextNPC();
-#else
-                    assert(delaySlotInfo[tid].numInsts == 0);
+                    pc[tid] = inst->pcState();
+                    advancePC(pc[tid], inst->staticInst);
 #endif
                 } else if (inst->predTaken()) {
                     // Taken Control
 #if ISA_HAS_DELAY_SLOT
-                    ++delaySlotInfo[tid].numInsts;
-                    delaySlotInfo[tid].targetReady = false;
-                    delaySlotInfo[tid].targetAddr = inst->readPredTarg();
+                    pc[tid] = inst->readPredTarg();
 
                     DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i] Updating delay"
-                            " slot target to PC %08p\n", tid, inst->seqNum,
+                            " slot target to PC %s\n", tid, inst->seqNum,
                             inst->readPredTarg());
                     inst->bdelaySeqNum = seq_num + 1;
 #else
                     inst->bdelaySeqNum = seq_num;
-                    assert(delaySlotInfo[tid].numInsts == 0);
 #endif
 
                     inst->squashingStage = stage_num;
-
                     DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to "
                             "start from stage %i, after [sn:%i].\n",
                             tid, stage_num, inst->bdelaySeqNum);
@@ -225,11 +182,12 @@ FetchSeqUnit::squashAfterInst(DynInstPtr inst, int stage_num, ThreadID tid)
 
     // Squash inside current resource, so if there needs to be fetching on
     // same cycle the fetch information will be correct.
-    // squash(inst, stage_num, inst->bdelaySeqNum, tid);
 
     // Schedule Squash Through-out Resource Pool
-    cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0);
+    cpu->resPool->scheduleEvent(
+            (InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0);
 }
+
 void
 FetchSeqUnit::squash(DynInstPtr inst, int squash_stage,
                      InstSeqNum squash_seq_num, ThreadID tid)
@@ -241,8 +199,15 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage,
 
     // Handles the case where we are squashing because of something that is
     // not a branch...like a memory stall
-    Addr new_PC = (inst->isControl()) ?
-        inst->readPredTarg() : inst->readPC() + instSize;
+    TheISA::PCState newPC;
+    if (inst->isControl()) {
+        newPC = inst->readPredTarg();
+    } else {
+        TheISA::PCState thisPC = inst->pcState();
+        assert(inst->staticInst);
+        advancePC(thisPC, inst->staticInst);
+        newPC = thisPC;
+    }
 
     if (squashSeqNum[tid] <= done_seq_num &&
         lastSquashCycle[tid] == curTick) {
@@ -258,31 +223,25 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage,
         // the last done_seq_num then this is the delay slot inst.
         if (cpu->nextInstSeqNum(tid) != done_seq_num &&
             !inst->procDelaySlotOnMispred) {
-            delaySlotInfo[tid].numInsts = 0;
-            delaySlotInfo[tid].targetReady = false;
 
             // Reset PC
-            PC[tid] = new_PC;
-            nextPC[tid] = new_PC + instSize;
-            nextNPC[tid] = new_PC + (2 * instSize);
+            pc[tid] = newPC;
+#if ISA_HAS_DELAY_SLOT
+            TheISA::advancePC(pc[tid], inst->staticInst);
+#endif
 
-            DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %08p.\n",
-                    tid, PC[tid]);
+            DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %s.\n",
+                    tid, newPC);
         } else {
-#if !ISA_HAS_DELAY_SLOT
-            assert(0);
-#endif
+            assert(ISA_HAS_DELAY_SLOT);
 
-            delaySlotInfo[tid].numInsts = 1;
-            delaySlotInfo[tid].targetReady = false;
-            delaySlotInfo[tid].targetAddr = (inst->procDelaySlotOnMispred) ?
-                inst->branchTarget() : new_PC;
+            pc[tid] = (inst->procDelaySlotOnMispred) ?
+                inst->branchTarget() : newPC;
 
             // Reset PC to Delay Slot Instruction
             if (inst->procDelaySlotOnMispred) {
-                PC[tid] = new_PC;
-                nextPC[tid] = new_PC + instSize;
-                nextNPC[tid] = new_PC + (2 * instSize);
+                // Reset PC
+                pc[tid] = newPC;
             }
 
         }
@@ -309,18 +268,13 @@ FetchSeqUnit::FetchSeqEvent::process()
     FetchSeqUnit* fs_res = dynamic_cast<FetchSeqUnit*>(resource);
     assert(fs_res);
 
-    for (int i=0; i < MaxThreads; i++) {
-        fs_res->PC[i] = fs_res->cpu->readPC(i);
-        fs_res->nextPC[i] = fs_res->cpu->readNextPC(i);
-        fs_res->nextNPC[i] = fs_res->cpu->readNextNPC(i);
-        DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC:%08p NPC:%08p "
-                "NNPC:%08p.\n", fs_res->PC[i], fs_res->nextPC[i],
-                fs_res->nextNPC[i]);
+    for (int i = 0; i < MaxThreads; i++) {
+        fs_res->pc[i] = fs_res->cpu->pcState(i);
+        DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC: %s.\n",
+                fs_res->pc[i]);
 
         fs_res->pcValid[i] = true;
     }
-
-    //cpu->fetchPriorityList.push_back(tid);
 }
 
 
@@ -329,22 +283,17 @@ FetchSeqUnit::activateThread(ThreadID tid)
 {
     pcValid[tid] = true;
 
-    PC[tid] = cpu->readPC(tid);
-    nextPC[tid] = cpu->readNextPC(tid);
-    nextNPC[tid] = cpu->readNextNPC(tid);
+    pc[tid] = cpu->pcState(tid);
 
     cpu->fetchPriorityList.push_back(tid);
 
-    DPRINTF(InOrderFetchSeq, "[tid:%i]: Reading PC:%08p NPC:%08p "
-            "NNPC:%08p.\n", tid, PC[tid], nextPC[tid], nextNPC[tid]);
+    DPRINTF(InOrderFetchSeq, "[tid:%i]: Reading PC: %s.\n",
+            tid, pc[tid]);
 }
 
 void
 FetchSeqUnit::deactivateThread(ThreadID tid)
 {
-    delaySlotInfo[tid].numInsts = 0;
-    delaySlotInfo[tid].targetReady = false;
-
     pcValid[tid] = false;
     pcBlockStage[tid] = 0;
 
@@ -375,18 +324,14 @@ FetchSeqUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid)
          *  switch was right after the branch. Thus, if it's not, then
          *  we are updating incorrectly here
          */
-        assert(cpu->thread[tid]->lastBranchNextPC == inst->readPC());
-        
-        PC[tid] = cpu->thread[tid]->lastBranchNextNPC;
-        nextPC[tid] = PC[tid] + instSize;
-        nextNPC[tid] = nextPC[tid] + instSize;
+        assert(cpu->nextInstAddr(tid) == inst->instAddr());
+        pc[tid] = cpu->thread[tid]->lastBranchPC;
     } else {
-        PC[tid] = inst->readNextPC();
-        nextPC[tid] = inst->readNextNPC();
-        nextNPC[tid] = inst->readNextNPC() + instSize;        
+        pc[tid] = inst->pcState();
     }
+    assert(inst->staticInst);
+    advancePC(pc[tid], inst->staticInst);
     
     DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating PCs due to Context Switch."
-            "Assigning  PC:%08p NPC:%08p NNPC:%08p.\n", tid, PC[tid], 
-            nextPC[tid], nextNPC[tid]);
+            "Assigning  PC: %s.\n", tid, pc[tid]);
 }
index aab462224d0fc43d4b655f12c123cdded3ccd36a..a258dc0e55570e5b6bbc1c9ecee7e5a5e18346f3 100644 (file)
@@ -80,22 +80,7 @@ class FetchSeqUnit : public Resource {
     bool pcValid[ThePipeline::MaxThreads];
     int pcBlockStage[ThePipeline::MaxThreads];
 
-    TheISA::IntReg PC[ThePipeline::MaxThreads];
-    TheISA::IntReg nextPC[ThePipeline::MaxThreads];
-    TheISA::IntReg nextNPC[ThePipeline::MaxThreads];
-
-    /** Tracks delay slot information for threads in ISAs which use
-     * delay slots;
-     */
-    struct DelaySlotInfo {
-        InstSeqNum delaySlotSeqNum;
-        InstSeqNum branchSeqNum;
-        int numInsts;
-        Addr targetAddr;
-        bool targetReady;
-    };
-
-    DelaySlotInfo delaySlotInfo[ThePipeline::MaxThreads];
+    TheISA::PCState pc[ThePipeline::MaxThreads];
 
     /** Squash Seq. Nums*/
     InstSeqNum squashSeqNum[ThePipeline::MaxThreads];
index 5c62c7751f9aa4ca342b6703c7d4c673daf9744e..eb1bf55f0869745a1d425dd53f170b82542d0c74 100644 (file)
@@ -111,8 +111,10 @@ class TLBUnitRequest : public ResourceRequest {
             aligned_addr = inst->getMemAddr();
             req_size = sizeof(TheISA::MachInst);
             flags = 0;
-            inst->fetchMemReq = new Request(inst->readTid(), aligned_addr, req_size,
-                                            flags, inst->readPC(), res->cpu->readCpuId(), inst->readTid());
+            inst->fetchMemReq = new Request(inst->readTid(), aligned_addr,
+                                            req_size, flags, inst->instAddr(),
+                                            res->cpu->readCpuId(),
+                                            inst->readTid());
             memReq = inst->fetchMemReq;
         } else {
             aligned_addr = inst->getMemAddr();;
@@ -123,8 +125,10 @@ class TLBUnitRequest : public ResourceRequest {
                 req_size = 8;
             }
 
-            inst->dataMemReq = new Request(inst->readTid(), aligned_addr, req_size,
-                                   flags, inst->readPC(), res->cpu->readCpuId(), inst->readTid());
+            inst->dataMemReq = new Request(inst->readTid(), aligned_addr,
+                                           req_size, flags, inst->instAddr(),
+                                           res->cpu->readCpuId(),
+                                           inst->readTid());
             memReq = inst->dataMemReq;
         }
     }
index e6d0af2cc90fa36986f4d03c35681aa98de7b47c..bbccf626a1417c674f30af0592b3e09cde9e9934 100644 (file)
@@ -233,30 +233,6 @@ InOrderThreadContext::setRegOtherThread(int misc_reg, const MiscReg &val,
     cpu->setRegOtherThread(misc_reg, val, tid);
 }
 
-void
-InOrderThreadContext::setPC(uint64_t val)
-{
-    DPRINTF(InOrderCPU, "[tid:%i] Setting PC to %08p\n",
-            thread->readTid(), val);
-    cpu->setPC(val, thread->readTid());
-}
-
-void
-InOrderThreadContext::setNextPC(uint64_t val)
-{
-    DPRINTF(InOrderCPU, "[tid:%i] Setting NPC to %08p\n",
-            thread->readTid(), val);
-    cpu->setNextPC(val, thread->readTid());
-}
-
-void
-InOrderThreadContext::setNextNPC(uint64_t val)
-{
-    DPRINTF(InOrderCPU, "[tid:%i] Setting NNPC to %08p\n",
-            thread->readTid(), val);
-    cpu->setNextNPC(val, thread->readTid());
-}
-
 void
 InOrderThreadContext::setMiscRegNoEffect(int misc_reg, const MiscReg &val)
 {
index 0c0f563c076ba0b582987513d7d190ef5392e0be..21f1e58358b72813b7ed8da7b5ff7f7c03513c45 100644 (file)
@@ -204,23 +204,21 @@ class InOrderThreadContext : public ThreadContext
                                    ThreadID tid);
 
     /** Reads this thread's PC. */
-    uint64_t readPC()
-    { return cpu->readPC(thread->readTid()); }
+    TheISA::PCState pcState()
+    { return cpu->pcState(thread->readTid()); }
 
     /** Sets this thread's PC. */
-    void setPC(uint64_t val);
+    void pcState(const TheISA::PCState &val)
+    { cpu->pcState(val, thread->readTid()); }
 
-    /** Reads this thread's next PC. */
-    uint64_t readNextPC()
-    { return cpu->readNextPC(thread->readTid()); }
+    Addr instAddr()
+    { return cpu->instAddr(thread->readTid()); }
 
-    /** Sets this thread's next PC. */
-    void setNextPC(uint64_t val);
+    Addr nextInstAddr()
+    { return cpu->nextInstAddr(thread->readTid()); }
 
-    uint64_t readNextNPC()
-    { return cpu->readNextNPC(thread->readTid()); }
-
-    void setNextNPC(uint64_t val);
+    MicroPC microPC()
+    { return cpu->microPC(thread->readTid()); }
 
     /** Reads a miscellaneous register. */
     MiscReg readMiscRegNoEffect(int misc_reg)
index 0a171a99f26a7470952143ce2f547da88ed1c924..20ace66592a5faf32c588d46e3801a9819c30585 100644 (file)
@@ -111,9 +111,7 @@ class InOrderThreadState : public ThreadState {
     
     /** Is last instruction graduated a branch? */
     bool lastGradIsBranch;
-    Addr lastBranchPC;    
-    Addr lastBranchNextPC;    
-    Addr lastBranchNextNPC;    
+    TheISA::PCState lastBranchPC;
 };
 
 #endif // __CPU_INORDER_THREAD_STATE_HH__
index ec51b80e773ddbcb4c17c3055d210d8bcc80f9cb..ee148c50fd59cfe72e281a7f655052524705bfe3 100644 (file)
@@ -48,7 +48,7 @@ Trace::IntelTraceRecord::dump()
 {
     ostream &outs = Trace::output();
     ccprintf(outs, "%7d ) ", when);
-    outs << "0x" << hex << PC << ":\t";
+    outs << "0x" << hex << pc.instAddr() << ":\t";
     if (staticInst->isLoad()) {
         ccprintf(outs, "<RD %#x>", addr);
     } else if (staticInst->isStore()) {
index c4ace4f4b0108191fd4a126c696c83c5040309fb..234b173e9907eaf69cc71cd86cf6e97ed39edadb 100644 (file)
@@ -46,10 +46,10 @@ class IntelTraceRecord : public InstRecord
 {
   public:
     IntelTraceRecord(Tick _when, ThreadContext *_thread,
-               const StaticInstPtr _staticInst, Addr _pc, bool spec,
-               const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0)
+               const StaticInstPtr _staticInst, TheISA::PCState _pc,
+               bool spec, const StaticInstPtr _macroStaticInst = NULL)
         : InstRecord(_when, _thread, _staticInst, _pc, spec,
-                _macroStaticInst, _upc)
+                _macroStaticInst)
     {
     }
 
@@ -65,8 +65,8 @@ class IntelTrace : public InstTracer
 
     IntelTraceRecord *
     getInstRecord(Tick when, ThreadContext *tc,
-            const StaticInstPtr staticInst, Addr pc,
-            const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0)
+            const StaticInstPtr staticInst, TheISA::PCState pc,
+            const StaticInstPtr macroStaticInst = NULL)
     {
         if (!IsOn(ExecEnable))
             return NULL;
@@ -78,7 +78,7 @@ class IntelTrace : public InstTracer
             return NULL;
 
         return new IntelTraceRecord(when, tc,
-                staticInst, pc, tc->misspeculating(), macroStaticInst, upc);
+                staticInst, pc, tc->misspeculating(), macroStaticInst);
     }
 };
 
index 1390d0807fad07624d8514f0cfe22836e7e46f83..8750e56e51671778be8c55e1ecdd28a8f4dca708 100644 (file)
@@ -211,7 +211,7 @@ Trace::LegionTraceRecord::dump()
     if(!staticInst->isMicroop() || staticInst->isLastMicroop()) {
         while (!compared) {
             if (shared_data->flags == OWN_M5) {
-                m5Pc = PC & SparcISA::PAddrImplMask;
+                m5Pc = pc.instAddr() & SparcISA::PAddrImplMask;
                 if (bits(shared_data->pstate,3,3)) {
                     m5Pc &= mask(32);
                 }
@@ -432,13 +432,14 @@ Trace::LegionTraceRecord::dump()
                          << endl;
 
                     predecoder.setTC(thread);
-                    predecoder.moreBytes(m5Pc, m5Pc,
-                            shared_data->instruction);
+                    predecoder.moreBytes(m5Pc, m5Pc, shared_data->instruction);
 
                     assert(predecoder.extMachInstReady());
 
+                    PCState tempPC = pc;
                     StaticInstPtr legionInst =
-                        StaticInst::decode(predecoder.getExtMachInst(), lgnPc);
+                        StaticInst::decode(predecoder.getExtMachInst(tempPC),
+                                           lgnPc);
                     outs << setfill(' ') << setw(15)
                          << " Legion Inst: "
                          << "0x" << setw(8) << setfill('0') << hex
index 829941d4bc208c5ee994828c797943bf50223676..a60b9ad10bbd896beb3da04160e8472e05d25aa2 100644 (file)
@@ -46,10 +46,10 @@ class LegionTraceRecord : public InstRecord
 {
   public:
     LegionTraceRecord(Tick _when, ThreadContext *_thread,
-               const StaticInstPtr _staticInst, Addr _pc, bool spec,
-               const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0)
+               const StaticInstPtr _staticInst, TheISA::PCState _pc,
+               bool spec, const StaticInstPtr _macroStaticInst = NULL)
         : InstRecord(_when, _thread, _staticInst, _pc, spec,
-                _macroStaticInst, _upc)
+                _macroStaticInst)
     {
     }
 
@@ -65,14 +65,14 @@ class LegionTrace : public InstTracer
 
     LegionTraceRecord *
     getInstRecord(Tick when, ThreadContext *tc,
-            const StaticInstPtr staticInst, Addr pc,
-            const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0)
+            const StaticInstPtr staticInst, TheISA::PCState pc,
+            const StaticInstPtr macroStaticInst = NULL)
     {
         if (tc->misspeculating())
             return NULL;
 
         return new LegionTraceRecord(when, tc,
-                staticInst, pc, tc->misspeculating(), macroStaticInst, upc);
+                staticInst, pc, tc->misspeculating(), macroStaticInst);
     }
 };
 
index 6ad6b0242a897505aa30d97704352e3bc3979218..5c5b9a66d2b83a0758a4cdc821e478c930e19a09 100644 (file)
@@ -54,10 +54,10 @@ class NativeTraceRecord : public ExeTracerRecord
   public:
     NativeTraceRecord(NativeTrace * _parent,
                Tick _when, ThreadContext *_thread,
-               const StaticInstPtr _staticInst, Addr _pc, bool spec,
-               const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0)
+               const StaticInstPtr _staticInst, TheISA::PCState _pc,
+               bool spec, const StaticInstPtr _macroStaticInst = NULL)
         : ExeTracerRecord(_when, _thread, _staticInst, _pc, spec,
-                _macroStaticInst, _upc),
+                _macroStaticInst),
         parent(_parent)
     {
     }
@@ -79,14 +79,14 @@ class NativeTrace : public ExeTracer
 
     NativeTraceRecord *
     getInstRecord(Tick when, ThreadContext *tc,
-            const StaticInstPtr staticInst, Addr pc,
-            const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0)
+            const StaticInstPtr staticInst, TheISA::PCState pc,
+            const StaticInstPtr macroStaticInst = NULL)
     {
         if (tc->misspeculating())
             return NULL;
 
         return new NativeTraceRecord(this, when, tc,
-                staticInst, pc, tc->misspeculating(), macroStaticInst, upc);
+                staticInst, pc, tc->misspeculating(), macroStaticInst);
     }
 
     template<class T>
index f199bdd752ea65c0ad0a2708d83a21869f9a6901..58b1147c931b5452bb9714d4544a88bc681f497a 100644 (file)
@@ -88,7 +88,7 @@ class BPredUnit
      * @param tid The thread id.
      * @return Returns if the branch is taken or not.
      */
-    bool predict(DynInstPtr &inst, Addr &PC, ThreadID tid);
+    bool predict(DynInstPtr &inst, TheISA::PCState &pc, ThreadID tid);
 
     // @todo: Rename this function.
     void BPUncond(void * &bp_history);
@@ -118,7 +118,8 @@ class BPredUnit
      * @param actually_taken The correct branch direction.
      * @param tid The thread id.
      */
-    void squash(const InstSeqNum &squashed_sn, const Addr &corr_target,
+    void squash(const InstSeqNum &squashed_sn,
+                const TheISA::PCState &corr_target,
                 bool actually_taken, ThreadID tid);
 
     /**
@@ -134,23 +135,23 @@ class BPredUnit
      * has the branch predictor state associated with the lookup.
      * @return Whether the branch is taken or not taken.
      */
-    bool BPLookup(Addr &inst_PC, void * &bp_history);
+    bool BPLookup(Addr instPC, void * &bp_history);
 
     /**
      * Looks up a given PC in the BTB to see if a matching entry exists.
      * @param inst_PC The PC to look up.
      * @return Whether the BTB contains the given PC.
      */
-    bool BTBValid(Addr &inst_PC)
-    { return BTB.valid(inst_PC, 0); }
+    bool BTBValid(Addr instPC)
+    { return BTB.valid(instPC, 0); }
 
     /**
      * Looks up a given PC in the BTB to get the predicted target.
      * @param inst_PC The PC to look up.
      * @return The address of the target of the branch.
      */
-    Addr BTBLookup(Addr &inst_PC)
-    { return BTB.lookup(inst_PC, 0); }
+    TheISA::PCState BTBLookup(Addr instPC)
+    { return BTB.lookup(instPC, 0); }
 
     /**
      * Updates the BP with taken/not taken information.
@@ -160,15 +161,15 @@ class BPredUnit
      * associated with the branch lookup that is being updated.
      * @todo Make this update flexible enough to handle a global predictor.
      */
-    void BPUpdate(Addr &inst_PC, bool taken, void *bp_history);
+    void BPUpdate(Addr instPC, bool taken, void *bp_history);
 
     /**
      * Updates the BTB with the target of a branch.
      * @param inst_PC The branch's PC that will be updated.
      * @param target_PC The branch's target that will be added to the BTB.
      */
-    void BTBUpdate(Addr &inst_PC, Addr &target_PC)
-    { BTB.update(inst_PC, target_PC,0); }
+    void BTBUpdate(Addr instPC, const TheISA::PCState &target)
+    { BTB.update(instPC, target, 0); }
 
     void dump();
 
@@ -178,13 +179,13 @@ class BPredUnit
          * Makes a predictor history struct that contains any
          * information needed to update the predictor, BTB, and RAS.
          */
-        PredictorHistory(const InstSeqNum &seq_num, const Addr &inst_PC,
+        PredictorHistory(const InstSeqNum &seq_num, Addr instPC,
                          bool pred_taken, void *bp_history,
                          ThreadID _tid)
-            : seqNum(seq_num), PC(inst_PC), RASTarget(0),
-              RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0),
+            : seqNum(seq_num), pc(instPC), RASTarget(0), RASIndex(0),
+              tid(_tid), predTaken(pred_taken), usedRAS(0),
               wasCall(0), bpHistory(bp_history)
-        { }
+        {}
 
         bool operator==(const PredictorHistory &entry) const {
             return this->seqNum == entry.seqNum;
@@ -194,10 +195,10 @@ class BPredUnit
         InstSeqNum seqNum;
 
         /** The PC associated with the sequence number. */
-        Addr PC;
+        Addr pc;
 
         /** The RAS target (only valid if a return). */
-        Addr RASTarget;
+        TheISA::PCState RASTarget;
 
         /** The RAS index of the instruction (only valid if a call). */
         unsigned RASIndex;
index ed347176196f80eb7023f0ee564de10aeb2b9346..14d47df9fb7bde6da4792bfa71acb9243b9efc04 100644 (file)
@@ -31,6 +31,7 @@
 #include <algorithm>
 
 #include "arch/types.hh"
+#include "arch/utility.hh"
 #include "arch/isa_traits.hh"
 #include "base/trace.hh"
 #include "base/traceflags.hh"
@@ -144,17 +145,15 @@ BPredUnit<Impl>::takeOverFrom()
 
 template <class Impl>
 bool
-BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, ThreadID tid)
+BPredUnit<Impl>::predict(DynInstPtr &inst, TheISA::PCState &pc, ThreadID tid)
 {
     // See if branch predictor predicts taken.
     // If so, get its target addr either from the BTB or the RAS.
     // Save off record of branch stuff so the RAS can be fixed
     // up once it's done.
 
-    using TheISA::MachInst;
-
     bool pred_taken = false;
-    Addr target = PC;
+    TheISA::PCState target = pc;
 
     ++lookups;
 
@@ -168,19 +167,19 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, ThreadID tid)
     } else {
         ++condPredicted;
 
-        pred_taken = BPLookup(PC, bp_history);
+        pred_taken = BPLookup(pc.instAddr(), bp_history);
 
         DPRINTF(Fetch, "BranchPred: [tid:%i]: Branch predictor predicted %i "
-                "for PC %#x\n",
-                tid, pred_taken, inst->readPC());
+                "for PC %s\n",
+                tid, pred_taken, inst->pcState());
     }
 
     DPRINTF(Fetch, "BranchPred: [tid:%i]: [sn:%i] Creating prediction history "
-                "for PC %#x\n",
-            tid, inst->seqNum, inst->readPC());
+                "for PC %s\n",
+            tid, inst->seqNum, inst->pcState());
 
-    PredictorHistory predict_record(inst->seqNum, PC, pred_taken,
-                                    bp_history, tid);
+    PredictorHistory predict_record(inst->seqNum, pc.instAddr(),
+                                    pred_taken, bp_history, tid);
 
     // Now lookup in the BTB or RAS.
     if (pred_taken) {
@@ -189,60 +188,58 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, ThreadID tid)
 
             // If it's a function return call, then look up the address
             // in the RAS.
-            target = RAS[tid].top();
+            TheISA::PCState rasTop = RAS[tid].top();
+            target = TheISA::buildRetPC(pc, rasTop);
 
             // Record the top entry of the RAS, and its index.
             predict_record.usedRAS = true;
             predict_record.RASIndex = RAS[tid].topIdx();
-            predict_record.RASTarget = target;
+            predict_record.RASTarget = rasTop;
 
             assert(predict_record.RASIndex < 16);
 
             RAS[tid].pop();
 
-            DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x is a return, "
-                    "RAS predicted target: %#x, RAS index: %i.\n",
-                    tid, inst->readPC(), target, predict_record.RASIndex);
+            DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %s is a return, "
+                    "RAS predicted target: %s, RAS index: %i.\n",
+                    tid, inst->pcState(), target, predict_record.RASIndex);
         } else {
             ++BTBLookups;
 
             if (inst->isCall()) {
-#if ISA_HAS_DELAY_SLOT
-                Addr ras_pc = PC + (2 * sizeof(MachInst)); // Next Next PC
-#else
-                Addr ras_pc = PC + sizeof(MachInst); // Next PC
-#endif
-                RAS[tid].push(ras_pc);
+                RAS[tid].push(pc);
 
                 // Record that it was a call so that the top RAS entry can
                 // be popped off if the speculation is incorrect.
                 predict_record.wasCall = true;
 
-                DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x was a call"
-                        ", adding %#x to the RAS index: %i.\n",
-                        tid, inst->readPC(), ras_pc, RAS[tid].topIdx());
+                DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %s was a "
+                        "call, adding %s to the RAS index: %i.\n",
+                        tid, inst->pcState(), pc, RAS[tid].topIdx());
             }
 
-            if (BTB.valid(PC, tid)) {
+            if (BTB.valid(pc.instAddr(), tid)) {
                 ++BTBHits;
 
                 // If it's not a return, use the BTB to get the target addr.
-                target = BTB.lookup(PC, tid);
+                target = BTB.lookup(pc.instAddr(), tid);
 
-                DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x predicted"
-                        " target is %#x.\n",
-                        tid, inst->readPC(), target);
+                DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %s predicted"
+                        " target is %s.\n", tid, inst->pcState(), target);
 
             } else {
                 DPRINTF(Fetch, "BranchPred: [tid:%i]: BTB doesn't have a "
                         "valid entry.\n",tid);
                 pred_taken = false;
+                TheISA::advancePC(target, inst->staticInst);
             }
 
         }
+    } else {
+        TheISA::advancePC(target, inst->staticInst);
     }
 
-    PC = target;
+    pc = target;
 
     predHist[tid].push_front(predict_record);
 
@@ -262,7 +259,7 @@ BPredUnit<Impl>::update(const InstSeqNum &done_sn, ThreadID tid)
     while (!predHist[tid].empty() &&
            predHist[tid].back().seqNum <= done_sn) {
         // Update the branch predictor with the correct results.
-        BPUpdate(predHist[tid].back().PC,
+        BPUpdate(predHist[tid].back().pc,
                  predHist[tid].back().predTaken,
                  predHist[tid].back().bpHistory);
 
@@ -280,10 +277,8 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ThreadID tid)
            pred_hist.front().seqNum > squashed_sn) {
         if (pred_hist.front().usedRAS) {
             DPRINTF(Fetch, "BranchPred: [tid:%i]: Restoring top of RAS to: %i,"
-                    " target: %#x.\n",
-                    tid,
-                    pred_hist.front().RASIndex,
-                    pred_hist.front().RASTarget);
+                    " target: %s.\n", tid,
+                    pred_hist.front().RASIndex, pred_hist.front().RASTarget);
 
             RAS[tid].restore(pred_hist.front().RASIndex,
                              pred_hist.front().RASTarget);
@@ -298,11 +293,13 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ThreadID tid)
         BPSquash(pred_hist.front().bpHistory);
 
         DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing history for [sn:%i] "
-                "PC %#x.\n", tid, pred_hist.front().seqNum, pred_hist.front().PC);
+                "PC %s.\n", tid, pred_hist.front().seqNum,
+                pred_hist.front().pc);
 
         pred_hist.pop_front();
 
-        DPRINTF(Fetch, "[tid:%i]: predHist.size(): %i\n", tid, predHist[tid].size());
+        DPRINTF(Fetch, "[tid:%i]: predHist.size(): %i\n",
+                tid, predHist[tid].size());
     }
 
 }
@@ -310,7 +307,7 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ThreadID tid)
 template <class Impl>
 void
 BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn,
-                        const Addr &corr_target,
+                        const TheISA::PCState &corrTarget,
                         bool actually_taken,
                         ThreadID tid)
 {
@@ -330,8 +327,8 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn,
     ++condIncorrect;
 
     DPRINTF(Fetch, "BranchPred: [tid:%i]: Squashing from sequence number %i, "
-            "setting target to %#x.\n",
-            tid, squashed_sn, corr_target);
+            "setting target to %s.\n",
+            tid, squashed_sn, corrTarget);
 
     // Squash All Branches AFTER this mispredicted branch
     squash(squashed_sn, tid);
@@ -358,13 +355,13 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn,
             ++RASIncorrect;
         }
 
-        BPUpdate((*hist_it).PC, actually_taken,
+        BPUpdate((*hist_it).pc, actually_taken,
                  pred_hist.front().bpHistory);
 
-        BTB.update((*hist_it).PC, corr_target, tid);
+        BTB.update((*hist_it).pc, corrTarget, tid);
 
         DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing history for [sn:%i] "
-                "PC %#x.\n", tid, (*hist_it).seqNum, (*hist_it).PC);
+                "PC %s.\n", tid, (*hist_it).seqNum, (*hist_it).pc);
 
         pred_hist.erase(hist_it);
 
@@ -397,12 +394,12 @@ BPredUnit<Impl>::BPSquash(void *bp_history)
 
 template <class Impl>
 bool
-BPredUnit<Impl>::BPLookup(Addr &inst_PC, void * &bp_history)
+BPredUnit<Impl>::BPLookup(Addr instPC, void * &bp_history)
 {
     if (predictor == Local) {
-        return localBP->lookup(inst_PC, bp_history);
+        return localBP->lookup(instPC, bp_history);
     } else if (predictor == Tournament) {
-        return tournamentBP->lookup(inst_PC, bp_history);
+        return tournamentBP->lookup(instPC, bp_history);
     } else {
         panic("Predictor type is unexpected value!");
     }
@@ -410,12 +407,12 @@ BPredUnit<Impl>::BPLookup(Addr &inst_PC, void * &bp_history)
 
 template <class Impl>
 void
-BPredUnit<Impl>::BPUpdate(Addr &inst_PC, bool taken, void *bp_history)
+BPredUnit<Impl>::BPUpdate(Addr instPC, bool taken, void *bp_history)
 {
     if (predictor == Local) {
-        localBP->update(inst_PC, taken, bp_history);
+        localBP->update(instPC, taken, bp_history);
     } else if (predictor == Tournament) {
-        tournamentBP->update(inst_PC, taken, bp_history);
+        tournamentBP->update(instPC, taken, bp_history);
     } else {
         panic("Predictor type is unexpected value!");
     }
@@ -436,9 +433,9 @@ BPredUnit<Impl>::dump()
             while (pred_hist_it != predHist[i].end()) {
                 cprintf("[sn:%lli], PC:%#x, tid:%i, predTaken:%i, "
                         "bpHistory:%#x\n",
-                        (*pred_hist_it).seqNum, (*pred_hist_it).PC,
-                        (*pred_hist_it).tid, (*pred_hist_it).predTaken,
-                        (*pred_hist_it).bpHistory);
+                        pred_hist_it->seqNum, pred_hist_it->pc,
+                        pred_hist_it->tid, pred_hist_it->predTaken,
+                        pred_hist_it->bpHistory);
                 pred_hist_it++;
             }
 
index 23b836f73d1b6e6c90f5d8efcddbbad36982a491..c9fb3319bf1228d02883f24660e48ab08f94ed8e 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <vector>
 
+#include "arch/types.hh"
 #include "base/types.hh"
 #include "cpu/inst_seq.hh"
 #include "sim/faults.hh"
@@ -88,9 +89,7 @@ struct DefaultIEWDefaultCommit {
     bool branchMispredict[Impl::MaxThreads];
     bool branchTaken[Impl::MaxThreads];
     Addr mispredPC[Impl::MaxThreads];
-    Addr nextPC[Impl::MaxThreads];
-    Addr nextNPC[Impl::MaxThreads];
-    Addr nextMicroPC[Impl::MaxThreads];
+    TheISA::PCState pc[Impl::MaxThreads];
     InstSeqNum squashedSeqNum[Impl::MaxThreads];
 
     bool includeSquashInst[Impl::MaxThreads];
@@ -120,9 +119,7 @@ struct TimeBufStruct {
         bool branchMispredict;
         bool branchTaken;
         Addr mispredPC;
-        Addr nextPC;
-        Addr nextNPC;
-        Addr nextMicroPC;
+        TheISA::PCState nextPC;
 
         unsigned branchCount;
     };
@@ -161,9 +158,7 @@ struct TimeBufStruct {
         bool branchMispredict;
         bool branchTaken;
         Addr mispredPC;
-        Addr nextPC;
-        Addr nextNPC;
-        Addr nextMicroPC;
+        TheISA::PCState pc;
 
         // Represents the instruction that has either been retired or
         // squashed.  Similar to having a single bus that broadcasts the
index d93b85984fbfdbfbf8ebab05ea3898723286a7e7..326f3a1d3c2f672a8d58f1d0ad9c3678dcbdb3cb 100644 (file)
@@ -277,40 +277,21 @@ class DefaultCommit
     ThreadID oldestReady();
 
   public:
-    /** Returns the PC of the head instruction of the ROB.
-     * @todo: Probably remove this function as it returns only thread 0.
-     */
-    Addr readPC() { return PC[0]; }
-
-    /** Returns the PC of a specific thread. */
-    Addr readPC(ThreadID tid) { return PC[tid]; }
+    /** Reads the PC of a specific thread. */
+    TheISA::PCState pcState(ThreadID tid) { return pc[tid]; }
 
     /** Sets the PC of a specific thread. */
-    void setPC(Addr val, ThreadID tid) { PC[tid] = val; }
-
-    /** Reads the micro PC of a specific thread. */
-    Addr readMicroPC(ThreadID tid) { return microPC[tid]; }
-
-    /** Sets the micro PC of a specific thread */
-    void setMicroPC(Addr val, ThreadID tid) { microPC[tid] = val; }
-
-    /** Reads the next PC of a specific thread. */
-    Addr readNextPC(ThreadID tid) { return nextPC[tid]; }
-
-    /** Sets the next PC of a specific thread. */
-    void setNextPC(Addr val, ThreadID tid) { nextPC[tid] = val; }
+    void pcState(const TheISA::PCState &val, ThreadID tid)
+    { pc[tid] = val; }
 
-    /** Reads the next NPC of a specific thread. */
-    Addr readNextNPC(ThreadID tid) { return nextNPC[tid]; }
+    /** Returns the PC of a specific thread. */
+    Addr instAddr(ThreadID tid) { return pc[tid].instAddr(); }
 
-    /** Sets the next NPC of a specific thread. */
-    void setNextNPC(Addr val, ThreadID tid) { nextNPC[tid] = val; }
+    /** Returns the next PC of a specific thread. */
+    Addr nextInstAddr(ThreadID tid) { return pc[tid].nextInstAddr(); }
 
     /** Reads the micro PC of a specific thread. */
-    Addr readNextMicroPC(ThreadID tid) { return nextMicroPC[tid]; }
-
-    /** Sets the micro PC of a specific thread */
-    void setNextMicroPC(Addr val, ThreadID tid) { nextMicroPC[tid] = val; }
+    Addr microPC(ThreadID tid) { return pc[tid].microPC(); }
 
   private:
     /** Time buffer interface. */
@@ -410,24 +391,10 @@ class DefaultCommit
     /** The interrupt fault. */
     Fault interrupt;
 
-    /** The commit PC of each thread.  Refers to the instruction that
-     * is currently being processed/committed.
-     */
-    Addr PC[Impl::MaxThreads];
-
-    /** The commit micro PC of each thread.  Refers to the instruction that
+    /** The commit PC state of each thread.  Refers to the instruction that
      * is currently being processed/committed.
      */
-    Addr microPC[Impl::MaxThreads];
-
-    /** The next PC of each thread. */
-    Addr nextPC[Impl::MaxThreads];
-
-    /** The next NPC of each thread. */
-    Addr nextNPC[Impl::MaxThreads];
-
-    /** The next micro PC of each thread. */
-    Addr nextMicroPC[Impl::MaxThreads];
+    TheISA::PCState pc[Impl::MaxThreads];
 
     /** The sequence number of the youngest valid instruction in the ROB. */
     InstSeqNum youngestSeqNum[Impl::MaxThreads];
index 98c7b49c891faccc8b2d69f4af3e476d2e64163e..8d3edfb19c23f98b71e4f82463811ff582a446d3 100644 (file)
@@ -128,11 +128,7 @@ DefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
         committedStores[tid] = false;
         trapSquash[tid] = false;
         tcSquash[tid] = false;
-        microPC[tid] = 0;
-        nextMicroPC[tid] = 0;
-        PC[tid] = 0;
-        nextPC[tid] = 0;
-        nextNPC[tid] = 0;
+        pc[tid].set(0);
     }
 #if FULL_SYSTEM
     interrupt = NoFault;
@@ -513,9 +509,7 @@ DefaultCommit<Impl>::squashAll(ThreadID tid)
 
     toIEW->commitInfo[tid].branchMispredict = false;
 
-    toIEW->commitInfo[tid].nextPC = PC[tid];
-    toIEW->commitInfo[tid].nextNPC = nextPC[tid];
-    toIEW->commitInfo[tid].nextMicroPC = nextMicroPC[tid];
+    toIEW->commitInfo[tid].pc = pc[tid];
 }
 
 template <class Impl>
@@ -524,7 +518,7 @@ DefaultCommit<Impl>::squashFromTrap(ThreadID tid)
 {
     squashAll(tid);
 
-    DPRINTF(Commit, "Squashing from trap, restarting at PC %#x\n", PC[tid]);
+    DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]);
 
     thread[tid]->trapPending = false;
     thread[tid]->inSyscall = false;
@@ -542,7 +536,7 @@ DefaultCommit<Impl>::squashFromTC(ThreadID tid)
 {
     squashAll(tid);
 
-    DPRINTF(Commit, "Squashing from TC, restarting at PC %#x\n", PC[tid]);
+    DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]);
 
     thread[tid]->inSyscall = false;
     assert(!thread[tid]->trapPending);
@@ -611,16 +605,16 @@ DefaultCommit<Impl>::tick()
 
             DynInstPtr inst = rob->readHeadInst(tid);
 
-            DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %#x is head of"
+            DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %s is head of"
                     " ROB and ready to commit\n",
-                    tid, inst->seqNum, inst->readPC());
+                    tid, inst->seqNum, inst->pcState());
 
         } else if (!rob->isEmpty(tid)) {
             DynInstPtr inst = rob->readHeadInst(tid);
 
             DPRINTF(Commit,"[tid:%i]: Can't commit, Instruction [sn:%lli] PC "
-                    "%#x is head of ROB and not ready\n",
-                    tid, inst->seqNum, inst->readPC());
+                    "%s is head of ROB and not ready\n",
+                    tid, inst->seqNum, inst->pcState());
         }
 
         DPRINTF(Commit, "[tid:%i]: ROB has %d insts & %d free entries.\n",
@@ -738,7 +732,7 @@ DefaultCommit<Impl>::commit()
 
             DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n",
                     tid,
-                    fromIEW->nextPC[tid]);
+                    fromIEW->pc[tid].nextInstAddr());
 
             commitStatus[tid] = ROBSquashing;
 
@@ -771,9 +765,7 @@ DefaultCommit<Impl>::commit()
             toIEW->commitInfo[tid].branchTaken =
                 fromIEW->branchTaken[tid];
 
-            toIEW->commitInfo[tid].nextPC = fromIEW->nextPC[tid];
-            toIEW->commitInfo[tid].nextNPC = fromIEW->nextNPC[tid];
-            toIEW->commitInfo[tid].nextMicroPC = fromIEW->nextMicroPC[tid];
+            toIEW->commitInfo[tid].pc = fromIEW->pc[tid];
 
             toIEW->commitInfo[tid].mispredPC = fromIEW->mispredPC[tid];
 
@@ -880,10 +872,7 @@ DefaultCommit<Impl>::commitInsts()
             // Record that the number of ROB entries has changed.
             changedROBNumEntries[tid] = true;
         } else {
-            PC[tid] = head_inst->readPC();
-            nextPC[tid] = head_inst->readNextPC();
-            nextNPC[tid] = head_inst->readNextNPC();
-            nextMicroPC[tid] = head_inst->readNextMicroPC();
+            pc[tid] = head_inst->pcState();
 
             // Increment the total number of non-speculative instructions
             // executed.
@@ -911,11 +900,7 @@ DefaultCommit<Impl>::commitInsts()
                     cpu->instDone(tid);
                 }
 
-                PC[tid] = nextPC[tid];
-                nextPC[tid] = nextNPC[tid];
-                nextNPC[tid] = nextNPC[tid] + sizeof(TheISA::MachInst);
-                microPC[tid] = nextMicroPC[tid];
-                nextMicroPC[tid] = microPC[tid] + 1;
+                TheISA::advancePC(pc[tid], head_inst->staticInst);
 
                 int count = 0;
                 Addr oldpc;
@@ -923,19 +908,19 @@ DefaultCommit<Impl>::commitInsts()
                 // currently updating state while handling PC events.
                 assert(!thread[tid]->inSyscall && !thread[tid]->trapPending);
                 do {
-                    oldpc = PC[tid];
+                    oldpc = pc[tid].instAddr();
                     cpu->system->pcEventQueue.service(thread[tid]->getTC());
                     count++;
-                } while (oldpc != PC[tid]);
+                } while (oldpc != pc[tid].instAddr());
                 if (count > 1) {
                     DPRINTF(Commit,
                             "PC skip function event, stopping commit\n");
                     break;
                 }
             } else {
-                DPRINTF(Commit, "Unable to commit head instruction PC:%#x "
+                DPRINTF(Commit, "Unable to commit head instruction PC:%s "
                         "[tid:%i] [sn:%i].\n",
-                        head_inst->readPC(), tid ,head_inst->seqNum);
+                        head_inst->pcState(), tid ,head_inst->seqNum);
                 break;
             }
         }
@@ -970,8 +955,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
             head_inst->isWriteBarrier()) {
 
             DPRINTF(Commit, "Encountered a barrier or non-speculative "
-                    "instruction [sn:%lli] at the head of the ROB, PC %#x.\n",
-                    head_inst->seqNum, head_inst->readPC());
+                    "instruction [sn:%lli] at the head of the ROB, PC %s.\n",
+                    head_inst->seqNum, head_inst->pcState());
 
             if (inst_num > 0 || iewStage->hasStoresToWB(tid)) {
                 DPRINTF(Commit, "Waiting for all stores to writeback.\n");
@@ -994,8 +979,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
             }
 
             assert(head_inst->uncacheable());
-            DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %#x.\n",
-                    head_inst->seqNum, head_inst->readPC());
+            DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %s.\n",
+                    head_inst->seqNum, head_inst->pcState());
 
             // Send back the non-speculative instruction's sequence
             // number.  Tell the lsq to re-execute the load.
@@ -1034,8 +1019,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
 #endif
 
     if (inst_fault != NoFault) {
-        DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n",
-                head_inst->seqNum, head_inst->readPC());
+        DPRINTF(Commit, "Inst [sn:%lli] PC %s has a fault\n",
+                head_inst->seqNum, head_inst->pcState());
 
         if (iewStage->hasStoresToWB(tid) || inst_num > 0) {
             DPRINTF(Commit, "Stores outstanding, fault must wait.\n");
@@ -1081,7 +1066,6 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
 
         // Generate trap squash event.
         generateTrapEvent(tid);
-//        warn("%lli fault (%d) handled @ PC %08p", curTick, inst_fault->name(), head_inst->readPC());
         return false;
     }
 
@@ -1089,9 +1073,7 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
 
 #if FULL_SYSTEM
     if (thread[tid]->profile) {
-//        bool usermode = TheISA::inUserMode(thread[tid]->getTC());
-//        thread[tid]->profilePC = usermode ? 1 : head_inst->readPC();
-        thread[tid]->profilePC = head_inst->readPC();
+        thread[tid]->profilePC = head_inst->instAddr();
         ProfileNode *node = thread[tid]->profile->consume(thread[tid]->getTC(),
                                                           head_inst->staticInst);
 
@@ -1101,7 +1083,7 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
     if (CPA::available()) {
         if (head_inst->isControl()) {
             ThreadContext *tc = thread[tid]->getTC();
-            CPA::cpa()->swAutoBegin(tc, head_inst->readNextPC());
+            CPA::cpa()->swAutoBegin(tc, head_inst->nextInstAddr());
         }
     }
 #endif
@@ -1154,8 +1136,8 @@ DefaultCommit<Impl>::getInsts()
             commitStatus[tid] != TrapPending) {
             changedROBNumEntries[tid] = true;
 
-            DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ROB.\n",
-                    inst->readPC(), inst->seqNum, tid);
+            DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ROB.\n",
+                    inst->pcState(), inst->seqNum, tid);
 
             rob->insertInst(inst);
 
@@ -1163,9 +1145,9 @@ DefaultCommit<Impl>::getInsts()
 
             youngestSeqNum[tid] = inst->seqNum;
         } else {
-            DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "
+            DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was "
                     "squashed, skipping.\n",
-                    inst->readPC(), inst->seqNum, tid);
+                    inst->pcState(), inst->seqNum, tid);
         }
     }
 }
@@ -1181,14 +1163,14 @@ DefaultCommit<Impl>::skidInsert()
         DynInstPtr inst = fromRename->insts[inst_num];
 
         if (!inst->isSquashed()) {
-            DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ",
-                    "skidBuffer.\n", inst->readPC(), inst->seqNum,
+            DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ",
+                    "skidBuffer.\n", inst->pcState(), inst->seqNum,
                     inst->threadNumber);
             skidBuffer.push(inst);
         } else {
-            DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "
+            DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was "
                     "squashed, skipping.\n",
-                    inst->readPC(), inst->seqNum, inst->threadNumber);
+                    inst->pcState(), inst->seqNum, inst->threadNumber);
         }
     }
 }
@@ -1204,10 +1186,10 @@ DefaultCommit<Impl>::markCompletedInsts()
          ++inst_num)
     {
         if (!fromIEW->insts[inst_num]->isSquashed()) {
-            DPRINTF(Commit, "[tid:%i]: Marking PC %#x, [sn:%lli] ready "
+            DPRINTF(Commit, "[tid:%i]: Marking PC %s, [sn:%lli] ready "
                     "within ROB.\n",
                     fromIEW->insts[inst_num]->threadNumber,
-                    fromIEW->insts[inst_num]->readPC(),
+                    fromIEW->insts[inst_num]->pcState(),
                     fromIEW->insts[inst_num]->seqNum);
 
             // Mark the instruction as ready to commit.
index 8e9f3ef5d077a5880aea52c9d23d438f89d0c1d9..21c5cc706f7af3d6359a26ea46f5f68164b0ead2 100644 (file)
@@ -732,9 +732,7 @@ FullO3CPU<Impl>::insertThread(ThreadID tid)
     //this->copyFromTC(tid);
 
     //Set PC/NPC/NNPC
-    setPC(src_tc->readPC(), tid);
-    setNextPC(src_tc->readNextPC(), tid);
-    setNextNPC(src_tc->readNextNPC(), tid);
+    pcState(src_tc->pcState(), tid);
 
     src_tc->setStatus(ThreadContext::Active);
 
@@ -778,7 +776,7 @@ FullO3CPU<Impl>::removeThread(ThreadID tid)
 
     // Squash Throughout Pipeline
     InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum;
-    fetch.squash(0, sizeof(TheISA::MachInst), 0, squash_seq_num, tid);
+    fetch.squash(0, squash_seq_num, tid);
     decode.squash(tid);
     rename.squash(squash_seq_num, tid);
     iew.squash(tid);
@@ -1306,73 +1304,38 @@ FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid)
 }
 
 template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readPC(ThreadID tid)
+TheISA::PCState
+FullO3CPU<Impl>::pcState(ThreadID tid)
 {
-    return commit.readPC(tid);
+    return commit.pcState(tid);
 }
 
 template <class Impl>
 void
-FullO3CPU<Impl>::setPC(Addr new_PC, ThreadID tid)
-{
-    commit.setPC(new_PC, tid);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readMicroPC(ThreadID tid)
+FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid)
 {
-    return commit.readMicroPC(tid);
+    commit.pcState(val, tid);
 }
 
 template <class Impl>
-void
-FullO3CPU<Impl>::setMicroPC(Addr new_PC, ThreadID tid)
+Addr
+FullO3CPU<Impl>::instAddr(ThreadID tid)
 {
-    commit.setMicroPC(new_PC, tid);
+    return commit.instAddr(tid);
 }
 
 template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readNextPC(ThreadID tid)
+Addr
+FullO3CPU<Impl>::nextInstAddr(ThreadID tid)
 {
-    return commit.readNextPC(tid);
+    return commit.nextInstAddr(tid);
 }
 
 template <class Impl>
-void
-FullO3CPU<Impl>::setNextPC(uint64_t val, ThreadID tid)
-{
-    commit.setNextPC(val, tid);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readNextNPC(ThreadID tid)
-{
-    return commit.readNextNPC(tid);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setNextNPC(uint64_t val, ThreadID tid)
-{
-    commit.setNextNPC(val, tid);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readNextMicroPC(ThreadID tid)
-{
-    return commit.readNextMicroPC(tid);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setNextMicroPC(Addr new_PC, ThreadID tid)
+MicroPC
+FullO3CPU<Impl>::microPC(ThreadID tid)
 {
-    commit.setNextMicroPC(new_PC, tid);
+    return commit.microPC(tid);
 }
 
 template <class Impl>
@@ -1419,9 +1382,9 @@ template <class Impl>
 void
 FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
 {
-    DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x "
+    DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s "
             "[sn:%lli]\n",
-            inst->threadNumber, inst->readPC(), inst->seqNum);
+            inst->threadNumber, inst->pcState(), inst->seqNum);
 
     removeInstsThisCycle = true;
 
@@ -1509,10 +1472,10 @@ FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid)
 {
     if ((*instIt)->threadNumber == tid) {
         DPRINTF(O3CPU, "Squashing instruction, "
-                "[tid:%i] [sn:%lli] PC %#x\n",
+                "[tid:%i] [sn:%lli] PC %s\n",
                 (*instIt)->threadNumber,
                 (*instIt)->seqNum,
-                (*instIt)->readPC());
+                (*instIt)->pcState());
 
         // Mark it as squashed.
         (*instIt)->setSquashed();
@@ -1530,10 +1493,10 @@ FullO3CPU<Impl>::cleanUpRemovedInsts()
 {
     while (!removeList.empty()) {
         DPRINTF(O3CPU, "Removing instruction, "
-                "[tid:%i] [sn:%lli] PC %#x\n",
+                "[tid:%i] [sn:%lli] PC %s\n",
                 (*removeList.front())->threadNumber,
                 (*removeList.front())->seqNum,
-                (*removeList.front())->readPC());
+                (*removeList.front())->pcState());
 
         instList.erase(removeList.front());
 
@@ -1563,7 +1526,7 @@ FullO3CPU<Impl>::dumpInsts()
     while (inst_list_it != instList.end()) {
         cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
                 "Squashed:%i\n\n",
-                num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
+                num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber,
                 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
                 (*inst_list_it)->isSquashed());
         inst_list_it++;
index 57c07a9ecafd4ce7820cf570dc56dfae50ae55f1..2669016ff8d6dc68846659edd83430f75bc1a7c4 100644 (file)
@@ -444,35 +444,20 @@ class FullO3CPU : public BaseO3CPU
 
     void setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid);
 
-    /** Reads the commit PC of a specific thread. */
-    Addr readPC(ThreadID tid);
+    /** Sets the commit PC state of a specific thread. */
+    void pcState(const TheISA::PCState &newPCState, ThreadID tid);
 
-    /** Sets the commit PC of a specific thread. */
-    void setPC(Addr new_PC, ThreadID tid);
+    /** Reads the commit PC state of a specific thread. */
+    TheISA::PCState pcState(ThreadID tid);
 
-    /** Reads the commit micro PC of a specific thread. */
-    Addr readMicroPC(ThreadID tid);
+    /** Reads the commit PC of a specific thread. */
+    Addr instAddr(ThreadID tid);
 
-    /** Sets the commmit micro PC of a specific thread. */
-    void setMicroPC(Addr new_microPC, ThreadID tid);
+    /** Reads the commit micro PC of a specific thread. */
+    MicroPC microPC(ThreadID tid);
 
     /** Reads the next PC of a specific thread. */
-    Addr readNextPC(ThreadID tid);
-
-    /** Sets the next PC of a specific thread. */
-    void setNextPC(Addr val, ThreadID tid);
-
-    /** Reads the next NPC of a specific thread. */
-    Addr readNextNPC(ThreadID tid);
-
-    /** Sets the next NPC of a specific thread. */
-    void setNextNPC(Addr val, ThreadID tid);
-
-    /** Reads the commit next micro PC of a specific thread. */
-    Addr readNextMicroPC(ThreadID tid);
-
-    /** Sets the commit next micro PC of a specific thread. */
-    void setNextMicroPC(Addr val, ThreadID tid);
+    Addr nextInstAddr(ThreadID tid);
 
     /** Initiates a squash of all in-flight instructions for a given
      * thread.  The source of the squash is an external update of
index 1b76de1320e632cd00626d6985e253510d970865..5063e0f0721d3d85e6357d95abdaec359b6a756c 100644 (file)
@@ -264,29 +264,16 @@ template<class Impl>
 void
 DefaultDecode<Impl>::squash(DynInstPtr &inst, ThreadID tid)
 {
-    DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch prediction "
-            "detected at decode.\n", tid, inst->seqNum);
+    DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch "
+            "prediction detected at decode.\n", tid, inst->seqNum);
 
     // Send back mispredict information.
     toFetch->decodeInfo[tid].branchMispredict = true;
     toFetch->decodeInfo[tid].predIncorrect = true;
     toFetch->decodeInfo[tid].squash = true;
     toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
-    toFetch->decodeInfo[tid].nextMicroPC = inst->readMicroPC();
-
-#if ISA_HAS_DELAY_SLOT
-    toFetch->decodeInfo[tid].nextPC = inst->readPC() + sizeof(TheISA::MachInst);
-    toFetch->decodeInfo[tid].nextNPC = inst->branchTarget();
-    toFetch->decodeInfo[tid].branchTaken = inst->readNextNPC() !=
-        (inst->readNextPC() + sizeof(TheISA::MachInst));
-#else
     toFetch->decodeInfo[tid].nextPC = inst->branchTarget();
-    toFetch->decodeInfo[tid].nextNPC =
-        inst->branchTarget() + sizeof(TheISA::MachInst);
-    toFetch->decodeInfo[tid].branchTaken =
-        inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst));
-#endif
-
+    toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching();
 
     InstSeqNum squash_seq_num = inst->seqNum;
 
@@ -382,8 +369,8 @@ DefaultDecode<Impl>::skidInsert(ThreadID tid)
 
         assert(tid == inst->threadNumber);
 
-        DPRINTF(Decode,"Inserting [sn:%lli] PC:%#x into decode skidBuffer %i\n",
-                inst->seqNum, inst->readPC(), inst->threadNumber);
+        DPRINTF(Decode,"Inserting [sn:%lli] PC: %s into decode skidBuffer %i\n",
+                inst->seqNum, inst->pcState(), inst->threadNumber);
 
         skidBuffer[tid].push(inst);
     }
@@ -681,13 +668,12 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid)
         insts_to_decode.pop();
 
         DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with "
-                "PC %#x\n",
-                tid, inst->seqNum, inst->readPC());
+                "PC %s\n", tid, inst->seqNum, inst->pcState());
 
         if (inst->isSquashed()) {
-            DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %#x is "
+            DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %s is "
                     "squashed, skipping.\n",
-                    tid, inst->seqNum, inst->readPC());
+                    tid, inst->seqNum, inst->pcState());
 
             ++decodeSquashedInsts;
 
@@ -717,9 +703,6 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid)
         // Ensure that if it was predicted as a branch, it really is a
         // branch.
         if (inst->readPredTaken() && !inst->isControl()) {
-            DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n",
-                    inst->readPredPC(), inst->readNextPC() + 4);
-
             panic("Instruction predicted as a branch!");
 
             ++decodeControlMispred;
@@ -735,26 +718,18 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid)
         if (inst->isDirectCtrl() && inst->isUncondCtrl()) {
             ++decodeBranchResolved;
 
-            if (inst->branchTarget() != inst->readPredPC()) {
+            if (!(inst->branchTarget() == inst->readPredTarg())) {
                 ++decodeBranchMispred;
 
                 // Might want to set some sort of boolean and just do
                 // a check at the end
                 squash(inst, inst->threadNumber);
-                Addr target = inst->branchTarget();
+                TheISA::PCState target = inst->branchTarget();
 
-#if ISA_HAS_DELAY_SLOT
-                DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %#x  PredNextPC: %#x\n",
-                        inst->seqNum, inst->readPC() + sizeof(TheISA::MachInst), target);
-
-                //The micro pc after an instruction level branch should be 0
-                inst->setPredTarg(inst->readPC() + sizeof(TheISA::MachInst), target, 0);
-#else
-                DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %#x  PredNextPC: %#x\n",
-                        inst->seqNum, target, target + sizeof(TheISA::MachInst));
+                DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %s\n",
+                        inst->seqNum, target);
                 //The micro pc after an instruction level branch should be 0
-                inst->setPredTarg(target, target + sizeof(TheISA::MachInst), 0);
-#endif
+                inst->setPredTarg(target);
                 break;
             }
         }
index c19fd0abff4a9fcc8683191e25fd54c33b59f1d4..804b3f9cd4f5be1787a2c85f346211490fc33f3b 100644 (file)
@@ -251,8 +251,8 @@ DependencyGraph<DynInstPtr>::dump()
         curr = &dependGraph[i];
 
         if (curr->inst) {
-            cprintf("dependGraph[%i]: producer: %#x [sn:%lli] consumer: ",
-                    i, curr->inst->readPC(), curr->inst->seqNum);
+            cprintf("dependGraph[%i]: producer: %s [sn:%lli] consumer: ",
+                    i, curr->inst->pcState(), curr->inst->seqNum);
         } else {
             cprintf("dependGraph[%i]: No producer. consumer: ", i);
         }
@@ -260,8 +260,8 @@ DependencyGraph<DynInstPtr>::dump()
         while (curr->next != NULL) {
             curr = curr->next;
 
-            cprintf("%#x [sn:%lli] ",
-                    curr->inst->readPC(), curr->inst->seqNum);
+            cprintf("%s [sn:%lli] ",
+                    curr->inst->pcState(), curr->inst->seqNum);
         }
 
         cprintf("\n");
index e1279f82b5a77695cef613fd0d4887027e309680..6bd1f9fad9bd26f06d75b5df81131505327ee491 100644 (file)
@@ -74,14 +74,14 @@ class BaseO3DynInst : public BaseDynInst<Impl>
 
   public:
     /** BaseDynInst constructor given a binary instruction. */
-    BaseO3DynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC,
-                 Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
-                 InstSeqNum seq_num, O3CPU *cpu);
+    BaseO3DynInst(StaticInstPtr staticInst,
+                  TheISA::PCState pc, TheISA::PCState predPC,
+                  InstSeqNum seq_num, O3CPU *cpu);
 
     /** BaseDynInst constructor given a binary instruction. */
-    BaseO3DynInst(ExtMachInst inst, Addr PC, Addr NPC, Addr microPC,
-                 Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC,
-                 InstSeqNum seq_num, O3CPU *cpu);
+    BaseO3DynInst(ExtMachInst inst,
+                  TheISA::PCState pc, TheISA::PCState predPC,
+                  InstSeqNum seq_num, O3CPU *cpu);
 
     /** BaseDynInst constructor given a static inst pointer. */
     BaseO3DynInst(StaticInstPtr &_staticInst);
index 3e015d9626763f32eabbf3796c8b459e06064016..6f7c23b2fb7a80c0e0b641e79c5a634cce0b41be 100644 (file)
 
 template <class Impl>
 BaseO3DynInst<Impl>::BaseO3DynInst(StaticInstPtr staticInst,
-                                   Addr PC, Addr NPC, Addr microPC,
-                                   Addr Pred_PC, Addr Pred_NPC,
-                                   Addr Pred_MicroPC,
+                                   TheISA::PCState pc, TheISA::PCState predPC,
                                    InstSeqNum seq_num, O3CPU *cpu)
-    : BaseDynInst<Impl>(staticInst, PC, NPC, microPC,
-                        Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu)
+    : BaseDynInst<Impl>(staticInst, pc, predPC, seq_num, cpu)
 {
     initVars();
 }
 
 template <class Impl>
 BaseO3DynInst<Impl>::BaseO3DynInst(ExtMachInst inst,
-                                   Addr PC, Addr NPC, Addr microPC,
-                                   Addr Pred_PC, Addr Pred_NPC,
-                                   Addr Pred_MicroPC,
+                                   TheISA::PCState pc, TheISA::PCState predPC,
                                    InstSeqNum seq_num, O3CPU *cpu)
-    : BaseDynInst<Impl>(inst, PC, NPC, microPC,
-                        Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu)
+    : BaseDynInst<Impl>(inst, pc, predPC, seq_num, cpu)
 {
     initVars();
 }
@@ -131,15 +125,17 @@ BaseO3DynInst<Impl>::hwrei()
 {
 #if THE_ISA == ALPHA_ISA
     // Can only do a hwrei when in pal mode.
-    if (!(this->readPC() & 0x3))
+    if (!(this->instAddr() & 0x3))
         return new AlphaISA::UnimplementedOpcodeFault;
 
     // Set the next PC based on the value of the EXC_ADDR IPR.
-    this->setNextPC(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR,
-                                           this->threadNumber));
+    AlphaISA::PCState pc = this->pcState();
+    pc.npc(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR,
+                                          this->threadNumber));
+    this->pcState(pc);
     if (CPA::available()) {
         ThreadContext *tc = this->cpu->tcBase(this->threadNumber);
-        CPA::cpa()->swAutoBegin(tc, this->readNextPC());
+        CPA::cpa()->swAutoBegin(tc, this->nextInstAddr());
     }
 
     // Tell CPU to clear any state it needs to if a hwrei is taken.
@@ -175,11 +171,11 @@ BaseO3DynInst<Impl>::syscall(int64_t callnum)
     // HACK: check CPU's nextPC before and after syscall. If it
     // changes, update this instruction's nextPC because the syscall
     // must have changed the nextPC.
-    Addr cpu_next_pc = this->cpu->readNextPC(this->threadNumber);
+    TheISA::PCState curPC = this->cpu->pcState(this->threadNumber);
     this->cpu->syscall(callnum, this->threadNumber);
-    Addr new_next_pc = this->cpu->readNextPC(this->threadNumber);
-    if (cpu_next_pc != new_next_pc) {
-        this->setNextPC(new_next_pc);
+    TheISA::PCState newPC = this->cpu->pcState(this->threadNumber);
+    if (!(curPC == newPC)) {
+        this->pcState(newPC);
     }
 }
 #endif
index d881c291fc73757a78b637653ba470ff6ac0e0a9..22e9e51b4c2a417b6b6b14c84e556fff20a31020 100644 (file)
@@ -229,7 +229,7 @@ class DefaultFetch
      * @param next_NPC Used for ISAs which use delay slots.
      * @return Whether or not a branch was predicted as taken.
      */
-    bool lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, Addr &next_NPC, Addr &next_MicroPC);
+    bool lookupAndUpdateNextPC(DynInstPtr &inst, TheISA::PCState &pc);
 
     /**
      * Fetches the cache line that contains fetch_PC.  Returns any
@@ -244,14 +244,12 @@ class DefaultFetch
     bool fetchCacheLine(Addr fetch_PC, Fault &ret_fault, ThreadID tid);
 
     /** Squashes a specific thread and resets the PC. */
-    inline void doSquash(const Addr &new_PC, const Addr &new_NPC,
-                         const Addr &new_MicroPC, ThreadID tid);
+    inline void doSquash(const TheISA::PCState &newPC, ThreadID tid);
 
     /** Squashes a specific thread and resets the PC. Also tells the CPU to
      * remove any instructions between fetch and decode that should be sqaushed.
      */
-    void squashFromDecode(const Addr &new_PC, const Addr &new_NPC,
-                          const Addr &new_MicroPC,
+    void squashFromDecode(const TheISA::PCState &newPC,
                           const InstSeqNum &seq_num, ThreadID tid);
 
     /** Checks if a thread is stalled. */
@@ -266,8 +264,7 @@ class DefaultFetch
      * remove any instructions that are not in the ROB. The source of this
      * squash should be the commit stage.
      */
-    void squash(const Addr &new_PC, const Addr &new_NPC,
-                const Addr &new_MicroPC,
+    void squash(const TheISA::PCState &newPC,
                 const InstSeqNum &seq_num, ThreadID tid);
 
     /** Ticks the fetch stage, processing all inputs signals and fetching
@@ -348,14 +345,7 @@ class DefaultFetch
     /** Predecoder. */
     TheISA::Predecoder predecoder;
 
-    /** Per-thread fetch PC. */
-    Addr PC[Impl::MaxThreads];
-
-    /** Per-thread fetch micro PC. */
-    Addr microPC[Impl::MaxThreads];
-
-    /** Per-thread next PC. */
-    Addr nextPC[Impl::MaxThreads];
+    TheISA::PCState pc[Impl::MaxThreads];
 
     /** Memory request used to access cache. */
     RequestPtr memReq[Impl::MaxThreads];
index 3f8f84cab126e10d82eacb2070fd30e6d0d18cbd..bbd9ce4a2330b682f2c1c267af63ecdb95783c50 100644 (file)
@@ -316,9 +316,7 @@ DefaultFetch<Impl>::initStage()
 {
     // Setup PC and nextPC with initial state.
     for (ThreadID tid = 0; tid < numThreads; tid++) {
-        PC[tid] = cpu->readPC(tid);
-        nextPC[tid] = cpu->readNextPC(tid);
-        microPC[tid] = cpu->readMicroPC(tid);
+        pc[tid] = cpu->pcState(tid);
     }
 
     for (ThreadID tid = 0; tid < numThreads; tid++) {
@@ -445,9 +443,7 @@ DefaultFetch<Impl>::takeOverFrom()
         stalls[i].rename = 0;
         stalls[i].iew = 0;
         stalls[i].commit = 0;
-        PC[i] = cpu->readPC(i);
-        nextPC[i] = cpu->readNextPC(i);
-        microPC[i] = cpu->readMicroPC(i);
+        pc[i] = cpu->pcState(i);
         fetchStatus[i] = Running;
     }
     numInst = 0;
@@ -496,8 +492,8 @@ DefaultFetch<Impl>::switchToInactive()
 
 template <class Impl>
 bool
-DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC,
-                                          Addr &next_NPC, Addr &next_MicroPC)
+DefaultFetch<Impl>::lookupAndUpdateNextPC(
+        DynInstPtr &inst, TheISA::PCState &nextPC)
 {
     // Do branch prediction check here.
     // A bit of a misnomer...next_PC is actually the current PC until
@@ -505,51 +501,26 @@ DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC,
     bool predict_taken;
 
     if (!inst->isControl()) {
-        if (inst->isMicroop() && !inst->isLastMicroop()) {
-            next_MicroPC++;
-        } else {
-            next_PC  = next_NPC;
-            next_NPC = next_NPC + instSize;
-            next_MicroPC = 0;
-        }
-        inst->setPredTarg(next_PC, next_NPC, next_MicroPC);
+        TheISA::advancePC(nextPC, inst->staticInst);
+        inst->setPredTarg(nextPC);
         inst->setPredTaken(false);
         return false;
     }
 
-    //Assume for now that all control flow is to a different macroop which
-    //would reset the micro pc to 0.
-    next_MicroPC = 0;
-
     ThreadID tid = inst->threadNumber;
-    Addr pred_PC = next_PC;
-    predict_taken = branchPred.predict(inst, pred_PC, tid);
+    predict_taken = branchPred.predict(inst, nextPC, tid);
 
     if (predict_taken) {
-        DPRINTF(Fetch, "[tid:%i]: [sn:%i]:  Branch predicted to be taken to %#x.\n",
-                tid, inst->seqNum, pred_PC);
+        DPRINTF(Fetch, "[tid:%i]: [sn:%i]:  Branch predicted to be taken to %s.\n",
+                tid, inst->seqNum, nextPC);
     } else {
         DPRINTF(Fetch, "[tid:%i]: [sn:%i]:Branch predicted to be not taken.\n",
                 tid, inst->seqNum);
     }
 
-#if ISA_HAS_DELAY_SLOT
-    next_PC = next_NPC;
-    if (predict_taken)
-        next_NPC = pred_PC;
-    else
-        next_NPC += instSize;
-#else
-    if (predict_taken)
-        next_PC = pred_PC;
-    else
-        next_PC += instSize;
-    next_NPC = next_PC + instSize;
-#endif
-
-    DPRINTF(Fetch, "[tid:%i]: [sn:%i] Branch predicted to go to %#x and then %#x.\n",
-            tid, inst->seqNum, next_PC, next_NPC);
-    inst->setPredTarg(next_PC, next_NPC, next_MicroPC);
+    DPRINTF(Fetch, "[tid:%i]: [sn:%i] Branch predicted to go to %s.\n",
+            tid, inst->seqNum, nextPC);
+    inst->setPredTarg(nextPC);
     inst->setPredTaken(predict_taken);
 
     ++fetchedBranches;
@@ -668,15 +639,12 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, ThreadID tid
 
 template <class Impl>
 inline void
-DefaultFetch<Impl>::doSquash(const Addr &new_PC,
-        const Addr &new_NPC, const Addr &new_microPC, ThreadID tid)
+DefaultFetch<Impl>::doSquash(const TheISA::PCState &newPC, ThreadID tid)
 {
-    DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %#x, NPC to: %#x.\n",
-            tid, new_PC, new_NPC);
+    DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %s.\n",
+            tid, newPC);
 
-    PC[tid] = new_PC;
-    nextPC[tid] = new_NPC;
-    microPC[tid] = new_microPC;
+    pc[tid] = newPC;
 
     // Clear the icache miss if it's outstanding.
     if (fetchStatus[tid] == IcacheWaitResponse) {
@@ -703,13 +671,12 @@ DefaultFetch<Impl>::doSquash(const Addr &new_PC,
 
 template<class Impl>
 void
-DefaultFetch<Impl>::squashFromDecode(const Addr &new_PC, const Addr &new_NPC,
-                                     const Addr &new_MicroPC,
+DefaultFetch<Impl>::squashFromDecode(const TheISA::PCState &newPC,
                                      const InstSeqNum &seq_num, ThreadID tid)
 {
-    DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n",tid);
+    DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n", tid);
 
-    doSquash(new_PC, new_NPC, new_MicroPC, tid);
+    doSquash(newPC, tid);
 
     // Tell the CPU to remove any instructions that are in flight between
     // fetch and decode.
@@ -784,13 +751,12 @@ DefaultFetch<Impl>::updateFetchStatus()
 
 template <class Impl>
 void
-DefaultFetch<Impl>::squash(const Addr &new_PC, const Addr &new_NPC,
-                           const Addr &new_MicroPC,
+DefaultFetch<Impl>::squash(const TheISA::PCState &newPC,
                            const InstSeqNum &seq_num, ThreadID tid)
 {
-    DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n",tid);
+    DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n", tid);
 
-    doSquash(new_PC, new_NPC, new_MicroPC, tid);
+    doSquash(newPC, tid);
 
     // Tell the CPU to remove any instructions that are not in the ROB.
     cpu->removeInstsNotInROB(tid);
@@ -903,16 +869,14 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(ThreadID tid)
         DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash "
                 "from commit.\n",tid);
         // In any case, squash.
-        squash(fromCommit->commitInfo[tid].nextPC,
-               fromCommit->commitInfo[tid].nextNPC,
-               fromCommit->commitInfo[tid].nextMicroPC,
+        squash(fromCommit->commitInfo[tid].pc,
                fromCommit->commitInfo[tid].doneSeqNum,
                tid);
 
         // Also check if there's a mispredict that happened.
         if (fromCommit->commitInfo[tid].branchMispredict) {
             branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum,
-                              fromCommit->commitInfo[tid].nextPC,
+                              fromCommit->commitInfo[tid].pc,
                               fromCommit->commitInfo[tid].branchTaken,
                               tid);
         } else {
@@ -955,13 +919,10 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(ThreadID tid)
 
         if (fetchStatus[tid] != Squashing) {
 
-            DPRINTF(Fetch, "Squashing from decode with PC = %#x, NPC = %#x\n",
-                    fromDecode->decodeInfo[tid].nextPC,
-                    fromDecode->decodeInfo[tid].nextNPC);
+            TheISA::PCState nextPC = fromDecode->decodeInfo[tid].nextPC;
+            DPRINTF(Fetch, "Squashing from decode with PC = %s\n", nextPC);
             // Squash unless we're already squashing
             squashFromDecode(fromDecode->decodeInfo[tid].nextPC,
-                             fromDecode->decodeInfo[tid].nextNPC,
-                             fromDecode->decodeInfo[tid].nextMicroPC,
                              fromDecode->decodeInfo[tid].doneSeqNum,
                              tid);
 
@@ -1016,9 +977,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
     DPRINTF(Fetch, "Attempting to fetch from [tid:%i]\n", tid);
 
     // The current PC.
-    Addr fetch_PC = PC[tid];
-    Addr fetch_NPC = nextPC[tid];
-    Addr fetch_MicroPC = microPC[tid];
+    TheISA::PCState fetchPC = pc[tid];
 
     // Fault code for memory access.
     Fault fault = NoFault;
@@ -1034,10 +993,9 @@ DefaultFetch<Impl>::fetch(bool &status_change)
         status_change = true;
     } else if (fetchStatus[tid] == Running) {
         DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read "
-                "instruction, starting at PC %08p.\n",
-                tid, fetch_PC);
+                "instruction, starting at PC %s.\n", tid, fetchPC);
 
-        bool fetch_success = fetchCacheLine(fetch_PC, fault, tid);
+        bool fetch_success = fetchCacheLine(fetchPC.instAddr(), fault, tid);
         if (!fetch_success) {
             if (cacheBlocked) {
                 ++icacheStallCycles;
@@ -1075,20 +1033,21 @@ DefaultFetch<Impl>::fetch(bool &status_change)
         return;
     }
 
-    Addr next_PC = fetch_PC;
-    Addr next_NPC = fetch_NPC;
-    Addr next_MicroPC = fetch_MicroPC;
+    TheISA::PCState nextPC = fetchPC;
 
     InstSeqNum inst_seq;
     MachInst inst;
     ExtMachInst ext_inst;
-    // @todo: Fix this hack.
-    unsigned offset = (fetch_PC & cacheBlkMask) & ~3;
 
     StaticInstPtr staticInst = NULL;
     StaticInstPtr macroop = NULL;
 
     if (fault == NoFault) {
+        //XXX Masking out pal mode bit. This will break x86. Alpha needs
+        //to pull the pal mode bit ouf ot the instruction address.
+        unsigned offset = (fetchPC.instAddr() & ~1) - cacheDataPC[tid];
+        assert(offset < cacheBlkSize);
+
         // If the read of the first instruction was successful, then grab the
         // instructions from the rest of the cache line and put them into the
         // queue heading to decode.
@@ -1104,15 +1063,6 @@ DefaultFetch<Impl>::fetch(bool &status_change)
                numInst < fetchWidth &&
                !predicted_branch) {
 
-            // If we're branching after this instruction, quite fetching
-            // from the same block then.
-            predicted_branch =
-                (fetch_PC + sizeof(TheISA::MachInst) != fetch_NPC);
-            if (predicted_branch) {
-                DPRINTF(Fetch, "Branch detected with PC = %#x, NPC = %#x\n",
-                        fetch_PC, fetch_NPC);
-            }
-
             // Make sure this is a valid index.
             assert(offset <= cacheBlkSize - instSize);
 
@@ -1122,16 +1072,16 @@ DefaultFetch<Impl>::fetch(bool &status_change)
                             (&cacheData[tid][offset]));
 
                 predecoder.setTC(cpu->thread[tid]->getTC());
-                predecoder.moreBytes(fetch_PC, fetch_PC, inst);
+                predecoder.moreBytes(fetchPC, fetchPC.instAddr(), inst);
 
-                ext_inst = predecoder.getExtMachInst();
-                staticInst = StaticInstPtr(ext_inst, fetch_PC);
+                ext_inst = predecoder.getExtMachInst(fetchPC);
+                staticInst = StaticInstPtr(ext_inst, fetchPC.instAddr());
                 if (staticInst->isMacroop())
                     macroop = staticInst;
             }
             do {
                 if (macroop) {
-                    staticInst = macroop->fetchMicroop(fetch_MicroPC);
+                    staticInst = macroop->fetchMicroop(fetchPC.microPC());
                     if (staticInst->isLastMicroop())
                         macroop = NULL;
                 }
@@ -1141,8 +1091,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
 
                 // Create a new DynInst from the instruction fetched.
                 DynInstPtr instruction = new DynInst(staticInst,
-                                                     fetch_PC, fetch_NPC, fetch_MicroPC,
-                                                     next_PC, next_NPC, next_MicroPC,
+                                                     fetchPC, nextPC,
                                                      inst_seq, cpu);
                 instruction->setTid(tid);
 
@@ -1150,27 +1099,32 @@ DefaultFetch<Impl>::fetch(bool &status_change)
 
                 instruction->setThreadState(cpu->thread[tid]);
 
-                DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x (%d) created "
-                        "[sn:%lli]\n", tid, instruction->readPC(),
-                        instruction->readMicroPC(), inst_seq);
+                DPRINTF(Fetch, "[tid:%i]: Instruction PC %s (%d) created "
+                        "[sn:%lli]\n", tid, instruction->pcState(),
+                        instruction->microPC(), inst_seq);
 
                 //DPRINTF(Fetch, "[tid:%i]: MachInst is %#x\n", tid, ext_inst);
 
-                DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n",
-                        tid, instruction->staticInst->disassemble(fetch_PC));
+                DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", tid,
+                        instruction->staticInst->
+                        disassemble(fetchPC.instAddr()));
 
 #if TRACING_ON
                 instruction->traceData =
                     cpu->getTracer()->getInstRecord(curTick, cpu->tcBase(tid),
-                            instruction->staticInst, instruction->readPC(),
-                            macroop, instruction->readMicroPC());
+                            instruction->staticInst, fetchPC, macroop);
 #else
                 instruction->traceData = NULL;
 #endif
 
-                ///FIXME This needs to be more robust in dealing with delay slots
+                // If we're branching after this instruction, quite fetching
+                // from the same block then.
+                predicted_branch = fetchPC.branching();
                 predicted_branch |=
-                    lookupAndUpdateNextPC(instruction, next_PC, next_NPC, next_MicroPC);
+                    lookupAndUpdateNextPC(instruction, nextPC);
+                if (predicted_branch) {
+                    DPRINTF(Fetch, "Branch detected with PC = %s\n", fetchPC);
+                }
 
                 // Add instruction to the CPU's list of instructions.
                 instruction->setInstListIt(cpu->addInst(instruction));
@@ -1185,9 +1139,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
                 ++fetchedInsts;
 
                 // Move to the next instruction, unless we have a branch.
-                fetch_PC = next_PC;
-                fetch_NPC = next_NPC;
-                fetch_MicroPC = next_MicroPC;
+                fetchPC = nextPC;
 
                 if (instruction->isQuiesce()) {
                     DPRINTF(Fetch, "Quiesce instruction encountered, halting fetch!",
@@ -1202,7 +1154,8 @@ DefaultFetch<Impl>::fetch(bool &status_change)
             } while (staticInst->isMicroop() &&
                      !staticInst->isLastMicroop() &&
                      numInst < fetchWidth);
-            offset += instSize;
+            //XXX Masking out pal mode bit.
+            offset = (fetchPC.instAddr() & ~1) - cacheDataPC[tid];
         }
 
         if (predicted_branch) {
@@ -1224,10 +1177,8 @@ DefaultFetch<Impl>::fetch(bool &status_change)
     // Now that fetching is completed, update the PC to signify what the next
     // cycle will be.
     if (fault == NoFault) {
-        PC[tid] = next_PC;
-        nextPC[tid] = next_NPC;
-        microPC[tid] = next_MicroPC;
-        DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n", tid, next_PC);
+        pc[tid] = nextPC;
+        DPRINTF(Fetch, "[tid:%i]: Setting PC to %s.\n", tid, nextPC);
     } else {
         // We shouldn't be in an icache miss and also have a fault (an ITB
         // miss)
@@ -1245,11 +1196,10 @@ DefaultFetch<Impl>::fetch(bool &status_change)
         ext_inst = TheISA::NoopMachInst;
 
         // Create a new DynInst from the dummy nop.
-        DynInstPtr instruction = new DynInst(ext_inst,
-                                             fetch_PC, fetch_NPC, fetch_MicroPC,
-                                             next_PC, next_NPC, next_MicroPC,
+        DynInstPtr instruction = new DynInst(ext_inst, fetchPC, nextPC,
                                              inst_seq, cpu);
-        instruction->setPredTarg(next_NPC, next_NPC + instSize, 0);
+        TheISA::advancePC(nextPC, instruction->staticInst);
+        instruction->setPredTarg(nextPC);
         instruction->setTid(tid);
 
         instruction->setASID(tid);
@@ -1272,8 +1222,8 @@ DefaultFetch<Impl>::fetch(bool &status_change)
         fetchStatus[tid] = TrapPending;
         status_change = true;
 
-        DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %08p",
-                tid, fault->name(), PC[tid]);
+        DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %s",
+                tid, fault->name(), pc[tid]);
     }
 }
 
index 2089913efd503f362acb49963a69067965b7582c..608e70cde9894f9f7a3a1189cb27b8491d32bfe1 100644 (file)
@@ -449,27 +449,18 @@ template<class Impl>
 void
 DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, ThreadID tid)
 {
-    DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %#x "
-            "[sn:%i].\n", tid, inst->readPC(), inst->seqNum);
+    DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %s "
+            "[sn:%i].\n", tid, inst->pcState(), inst->seqNum);
 
     toCommit->squash[tid] = true;
     toCommit->squashedSeqNum[tid] = inst->seqNum;
-    toCommit->mispredPC[tid] = inst->readPC();
+    toCommit->mispredPC[tid] = inst->instAddr();
     toCommit->branchMispredict[tid] = true;
 
-#if ISA_HAS_DELAY_SLOT
-    int instSize = sizeof(TheISA::MachInst);
-    toCommit->branchTaken[tid] =
-        !(inst->readNextPC() + instSize == inst->readNextNPC() &&
-          (inst->readNextPC() == inst->readPC() + instSize ||
-           inst->readNextPC() == inst->readPC() + 2 * instSize));
-#else
-    toCommit->branchTaken[tid] = inst->readNextPC() !=
-        (inst->readPC() + sizeof(TheISA::MachInst));
-#endif
-    toCommit->nextPC[tid] = inst->readNextPC();
-    toCommit->nextNPC[tid] = inst->readNextNPC();
-    toCommit->nextMicroPC[tid] = inst->readNextMicroPC();
+    toCommit->branchTaken[tid] = inst->pcState().branching();
+    TheISA::PCState pc = inst->pcState();
+    TheISA::advancePC(pc, inst->staticInst);
+    toCommit->pc[tid] = pc;
 
     toCommit->includeSquashInst[tid] = false;
 
@@ -481,12 +472,13 @@ void
 DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, ThreadID tid)
 {
     DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, "
-            "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
+            "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum);
 
     toCommit->squash[tid] = true;
     toCommit->squashedSeqNum[tid] = inst->seqNum;
-    toCommit->nextPC[tid] = inst->readNextPC();
-    toCommit->nextNPC[tid] = inst->readNextNPC();
+    TheISA::PCState pc = inst->pcState();
+    TheISA::advancePC(pc, inst->staticInst);
+    toCommit->pc[tid] = pc;
     toCommit->branchMispredict[tid] = false;
 
     toCommit->includeSquashInst[tid] = false;
@@ -499,12 +491,11 @@ void
 DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, ThreadID tid)
 {
     DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, "
-            "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
+            "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum);
 
     toCommit->squash[tid] = true;
     toCommit->squashedSeqNum[tid] = inst->seqNum;
-    toCommit->nextPC[tid] = inst->readPC();
-    toCommit->nextNPC[tid] = inst->readNextPC();
+    toCommit->pc[tid] = inst->pcState();
     toCommit->branchMispredict[tid] = false;
 
     // Must include the broadcasted SN in the squash.
@@ -628,9 +619,9 @@ DefaultIEW<Impl>::skidInsert(ThreadID tid)
 
         insts[tid].pop();
 
-        DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%#x into "
+        DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%s into "
                 "dispatch skidBuffer %i\n",tid, inst->seqNum,
-                inst->readPC(),tid);
+                inst->pcState(),tid);
 
         skidBuffer[tid].push(inst);
     }
@@ -986,9 +977,9 @@ DefaultIEW<Impl>::dispatchInsts(ThreadID tid)
         // Make sure there's a valid instruction there.
         assert(inst);
 
-        DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %#x [sn:%lli] [tid:%i] to "
+        DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %s [sn:%lli] [tid:%i] to "
                 "IQ.\n",
-                tid, inst->readPC(), inst->seqNum, inst->threadNumber);
+                tid, inst->pcState(), inst->seqNum, inst->threadNumber);
 
         // Be sure to mark these instructions as ready so that the
         // commit stage can go ahead and execute them, and mark
@@ -1165,7 +1156,7 @@ DefaultIEW<Impl>::printAvailableInsts()
 
         if (inst%3==0) std::cout << "\n\t";
 
-        std::cout << "PC: " << fromIssue->insts[inst]->readPC()
+        std::cout << "PC: " << fromIssue->insts[inst]->pcState()
              << " TN: " << fromIssue->insts[inst]->threadNumber
              << " SN: " << fromIssue->insts[inst]->seqNum << " | ";
 
@@ -1205,8 +1196,8 @@ DefaultIEW<Impl>::executeInsts()
 
         DynInstPtr inst = instQueue.getInstToExecute();
 
-        DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n",
-                inst->readPC(), inst->threadNumber,inst->seqNum);
+        DPRINTF(IEW, "Execute: Processing PC %s, [tid:%i] [sn:%i].\n",
+                inst->pcState(), inst->threadNumber,inst->seqNum);
 
         // Check if the instruction is squashed; if so then skip it
         if (inst->isSquashed()) {
@@ -1298,10 +1289,9 @@ DefaultIEW<Impl>::executeInsts()
 
                 DPRINTF(IEW, "Execute: Branch mispredict detected.\n");
                 DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n",
-                        inst->readPredPC(), inst->readPredNPC());
-                DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x,"
-                        " NPC: %#x.\n", inst->readNextPC(),
-                        inst->readNextNPC());
+                        inst->predInstAddr(), inst->predNextInstAddr());
+                DPRINTF(IEW, "Execute: Redirecting fetch to PC: %s.\n",
+                        inst->pcState(), inst->nextInstAddr());
                 // If incorrect, then signal the ROB that it must be squashed.
                 squashDueToBranch(inst, tid);
 
@@ -1318,16 +1308,11 @@ DefaultIEW<Impl>::executeInsts()
                 DynInstPtr violator;
                 violator = ldstQueue.getMemDepViolator(tid);
 
-                DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %#x "
-                        "[sn:%lli], inst PC: %#x [sn:%lli]. Addr is: %#x.\n",
-                        violator->readPC(), violator->seqNum,
-                        inst->readPC(), inst->seqNum, inst->physEffAddr);
-                // Ensure the violating instruction is older than
-                // current squash
-/*                if (fetchRedirect[tid] &&
-                    violator->seqNum >= toCommit->squashedSeqNum[tid] + 1)
-                    continue;
-*/
+                DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %s "
+                        "[sn:%lli], inst PC: %s [sn:%lli]. Addr is: %#x.\n",
+                        violator->pcState(), violator->seqNum,
+                        inst->pcState(), inst->seqNum, inst->physEffAddr);
+
                 fetchRedirect[tid] = true;
 
                 // Tell the instruction queue that a violation has occured.
@@ -1342,8 +1327,8 @@ DefaultIEW<Impl>::executeInsts()
                 fetchRedirect[tid] = true;
 
                 DPRINTF(IEW, "Load operation couldn't execute because the "
-                        "memory system is blocked.  PC: %#x [sn:%lli]\n",
-                        inst->readPC(), inst->seqNum);
+                        "memory system is blocked.  PC: %s [sn:%lli]\n",
+                        inst->pcState(), inst->seqNum);
 
                 squashDueToMemBlocked(inst, tid);
             }
@@ -1356,8 +1341,9 @@ DefaultIEW<Impl>::executeInsts()
                 DynInstPtr violator = ldstQueue.getMemDepViolator(tid);
 
                 DPRINTF(IEW, "LDSTQ detected a violation.  Violator PC: "
-                        "%#x, inst PC: %#x.  Addr is: %#x.\n",
-                        violator->readPC(), inst->readPC(), inst->physEffAddr);
+                        "%s, inst PC: %s.  Addr is: %#x.\n",
+                        violator->pcState(), inst->pcState(),
+                        inst->physEffAddr);
                 DPRINTF(IEW, "Violation will not be handled because "
                         "already squashing\n");
 
@@ -1366,8 +1352,8 @@ DefaultIEW<Impl>::executeInsts()
             if (ldstQueue.loadBlocked(tid) &&
                 !ldstQueue.isLoadBlockedHandled(tid)) {
                 DPRINTF(IEW, "Load operation couldn't execute because the "
-                        "memory system is blocked.  PC: %#x [sn:%lli]\n",
-                        inst->readPC(), inst->seqNum);
+                        "memory system is blocked.  PC: %s [sn:%lli]\n",
+                        inst->pcState(), inst->seqNum);
                 DPRINTF(IEW, "Blocked load will not be handled because "
                         "already squashing\n");
 
@@ -1408,8 +1394,8 @@ DefaultIEW<Impl>::writebackInsts()
         DynInstPtr inst = toCommit->insts[inst_num];
         ThreadID tid = inst->threadNumber;
 
-        DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %#x.\n",
-                inst->seqNum, inst->readPC());
+        DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %s.\n",
+                inst->seqNum, inst->pcState());
 
         iewInstsToCommit[tid]++;
 
@@ -1613,10 +1599,10 @@ DefaultIEW<Impl>::checkMisprediction(DynInstPtr &inst)
 
             DPRINTF(IEW, "Execute: Branch mispredict detected.\n");
             DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n",
-                    inst->readPredPC(), inst->readPredNPC());
+                    inst->predInstAddr(), inst->predNextInstAddr());
             DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x,"
-                    " NPC: %#x.\n", inst->readNextPC(),
-                    inst->readNextNPC());
+                    " NPC: %#x.\n", inst->nextInstAddr(),
+                    inst->nextInstAddr());
             // If incorrect, then signal the ROB that it must be squashed.
             squashDueToBranch(inst, tid);
 
index 3d5eadf84a9952ed8c7321cbf32fdedf902a922e..b944979f2f47aaefb1f5aa962c35936482c85451 100644 (file)
@@ -504,8 +504,8 @@ InstructionQueue<Impl>::insert(DynInstPtr &new_inst)
     // Make sure the instruction is valid
     assert(new_inst);
 
-    DPRINTF(IQ, "Adding instruction [sn:%lli] PC %#x to the IQ.\n",
-            new_inst->seqNum, new_inst->readPC());
+    DPRINTF(IQ, "Adding instruction [sn:%lli] PC %s to the IQ.\n",
+            new_inst->seqNum, new_inst->pcState());
 
     assert(freeEntries != 0);
 
@@ -547,9 +547,9 @@ InstructionQueue<Impl>::insertNonSpec(DynInstPtr &new_inst)
 
     nonSpecInsts[new_inst->seqNum] = new_inst;
 
-    DPRINTF(IQ, "Adding non-speculative instruction [sn:%lli] PC %#x "
+    DPRINTF(IQ, "Adding non-speculative instruction [sn:%lli] PC %s "
             "to the IQ.\n",
-            new_inst->seqNum, new_inst->readPC());
+            new_inst->seqNum, new_inst->pcState());
 
     assert(freeEntries != 0);
 
@@ -767,9 +767,9 @@ InstructionQueue<Impl>::scheduleReadyInsts()
                 }
             }
 
-            DPRINTF(IQ, "Thread %i: Issuing instruction PC %#x "
+            DPRINTF(IQ, "Thread %i: Issuing instruction PC %s "
                     "[sn:%lli]\n",
-                    tid, issuing_inst->readPC(),
+                    tid, issuing_inst->pcState(),
                     issuing_inst->seqNum);
 
             readyInsts[op_class].pop();
@@ -910,7 +910,7 @@ InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
 
         while (dep_inst) {
             DPRINTF(IQ, "Waking up a dependent instruction, [sn:%lli] "
-                    "PC%#x.\n", dep_inst->seqNum, dep_inst->readPC());
+                    "PC %s.\n", dep_inst->seqNum, dep_inst->pcState());
 
             // Might want to give more information to the instruction
             // so that it knows which of its source registers is
@@ -955,8 +955,8 @@ InstructionQueue<Impl>::addReadyMemInst(DynInstPtr &ready_inst)
     }
 
     DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
-            "the ready list, PC %#x opclass:%i [sn:%lli].\n",
-            ready_inst->readPC(), op_class, ready_inst->seqNum);
+            "the ready list, PC %s opclass:%i [sn:%lli].\n",
+            ready_inst->pcState(), op_class, ready_inst->seqNum);
 }
 
 template <class Impl>
@@ -981,8 +981,8 @@ InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst)
 {
     ThreadID tid = completed_inst->threadNumber;
 
-    DPRINTF(IQ, "Completing mem instruction PC:%#x [sn:%lli]\n",
-            completed_inst->readPC(), completed_inst->seqNum);
+    DPRINTF(IQ, "Completing mem instruction PC: %s [sn:%lli]\n",
+            completed_inst->pcState(), completed_inst->seqNum);
 
     ++freeEntries;
 
@@ -1050,9 +1050,8 @@ InstructionQueue<Impl>::doSquash(ThreadID tid)
             (squashed_inst->isMemRef() &&
              !squashed_inst->memOpDone)) {
 
-            DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %#x "
-                    "squashed.\n",
-                    tid, squashed_inst->seqNum, squashed_inst->readPC());
+            DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %s squashed.\n",
+                    tid, squashed_inst->seqNum, squashed_inst->pcState());
 
             // Remove the instruction from the dependency list.
             if (!squashed_inst->isNonSpeculative() &&
@@ -1147,9 +1146,9 @@ InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
             if (src_reg >= numPhysRegs) {
                 continue;
             } else if (regScoreboard[src_reg] == false) {
-                DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
+                DPRINTF(IQ, "Instruction PC %s has src reg %i that "
                         "is being added to the dependency chain.\n",
-                        new_inst->readPC(), src_reg);
+                        new_inst->pcState(), src_reg);
 
                 dependGraph.insert(src_reg, new_inst);
 
@@ -1157,9 +1156,9 @@ InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
                 // was added to the dependency graph.
                 return_val = true;
             } else {
-                DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
+                DPRINTF(IQ, "Instruction PC %s has src reg %i that "
                         "became ready before it reached the IQ.\n",
-                        new_inst->readPC(), src_reg);
+                        new_inst->pcState(), src_reg);
                 // Mark a register ready within the instruction.
                 new_inst->markSrcRegReady(src_reg_idx);
             }
@@ -1228,8 +1227,8 @@ InstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
         OpClass op_class = inst->opClass();
 
         DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
-                "the ready list, PC %#x opclass:%i [sn:%lli].\n",
-                inst->readPC(), op_class, inst->seqNum);
+                "the ready list, PC %s opclass:%i [sn:%lli].\n",
+                inst->pcState(), op_class, inst->seqNum);
 
         readyInsts[op_class].push(inst);
 
@@ -1299,7 +1298,7 @@ InstructionQueue<Impl>::dumpLists()
     cprintf("Non speculative list: ");
 
     while (non_spec_it != non_spec_end_it) {
-        cprintf("%#x [sn:%lli]", (*non_spec_it).second->readPC(),
+        cprintf("%s [sn:%lli]", (*non_spec_it).second->pcState(),
                 (*non_spec_it).second->seqNum);
         ++non_spec_it;
     }
@@ -1348,9 +1347,9 @@ InstructionQueue<Impl>::dumpInsts()
                 }
             }
 
-            cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
+            cprintf("PC: %s\n[sn:%lli]\n[tid:%i]\n"
                     "Issued:%i\nSquashed:%i\n",
-                    (*inst_list_it)->readPC(),
+                    (*inst_list_it)->pcState(),
                     (*inst_list_it)->seqNum,
                     (*inst_list_it)->threadNumber,
                     (*inst_list_it)->isIssued(),
@@ -1390,9 +1389,9 @@ InstructionQueue<Impl>::dumpInsts()
             }
         }
 
-        cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
+        cprintf("PC: %s\n[sn:%lli]\n[tid:%i]\n"
                 "Issued:%i\nSquashed:%i\n",
-                (*inst_list_it)->readPC(),
+                (*inst_list_it)->pcState(),
                 (*inst_list_it)->seqNum,
                 (*inst_list_it)->threadNumber,
                 (*inst_list_it)->isIssued(),
index a9047558d28c489d266e8ce36eed061ab858ab85..372e76b71c014c35f18704380aa6b2f57bbd464d 100644 (file)
@@ -530,8 +530,8 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh,
         (load_idx != loadHead || !load_inst->isAtCommit())) {
         iewStage->rescheduleMemInst(load_inst);
         ++lsqRescheduledLoads;
-        DPRINTF(LSQUnit, "Uncachable load [sn:%lli] PC %#x\n",
-                load_inst->seqNum, load_inst->readPC());
+        DPRINTF(LSQUnit, "Uncachable load [sn:%lli] PC %s\n",
+                load_inst->seqNum, load_inst->pcState());
 
         // Must delete request now that it wasn't handed off to
         // memory.  This is quite ugly.  @todo: Figure out the proper
@@ -687,8 +687,8 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh,
     }
 
     // If there's no forwarding case, then go access memory
-    DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n",
-            load_inst->seqNum, load_inst->readPC());
+    DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %s\n",
+            load_inst->seqNum, load_inst->pcState());
 
     assert(!load_inst->memData);
     load_inst->memData = new uint8_t[64];
index 8aa7fe3971a68ea1572ba78fab5070f3bd649d44..345d3ea696793bd1e23c498a517fef87257dabb4 100644 (file)
@@ -352,8 +352,8 @@ LSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
     assert((loadTail + 1) % LQEntries != loadHead);
     assert(loads < LQEntries);
 
-    DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n",
-            load_inst->readPC(), loadTail, load_inst->seqNum);
+    DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n",
+            load_inst->pcState(), loadTail, load_inst->seqNum);
 
     load_inst->lqIdx = loadTail;
 
@@ -378,8 +378,8 @@ LSQUnit<Impl>::insertStore(DynInstPtr &store_inst)
     assert((storeTail + 1) % SQEntries != storeHead);
     assert(stores < SQEntries);
 
-    DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n",
-            store_inst->readPC(), storeTail, store_inst->seqNum);
+    DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n",
+            store_inst->pcState(), storeTail, store_inst->seqNum);
 
     store_inst->sqIdx = storeTail;
     store_inst->lqIdx = loadTail;
@@ -444,8 +444,8 @@ LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
     // Execute a specific load.
     Fault load_fault = NoFault;
 
-    DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
-            inst->readPC(),inst->seqNum);
+    DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n",
+            inst->pcState(),inst->seqNum);
 
     assert(!inst->isSquashed());
 
@@ -519,8 +519,8 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
 
     int store_idx = store_inst->sqIdx;
 
-    DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
-            store_inst->readPC(), store_inst->seqNum);
+    DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n",
+            store_inst->pcState(), store_inst->seqNum);
 
     assert(!store_inst->isSquashed());
 
@@ -531,8 +531,8 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
     Fault store_fault = store_inst->initiateAcc();
 
     if (storeQueue[store_idx].size == 0) {
-        DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n",
-                store_inst->readPC(),store_inst->seqNum);
+        DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli],Size = 0\n",
+                store_inst->pcState(), store_inst->seqNum);
 
         return store_fault;
     }
@@ -593,8 +593,8 @@ LSQUnit<Impl>::commitLoad()
 {
     assert(loadQueue[loadHead]);
 
-    DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n",
-            loadQueue[loadHead]->readPC());
+    DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n",
+            loadQueue[loadHead]->pcState());
 
     loadQueue[loadHead] = NULL;
 
@@ -631,8 +631,8 @@ LSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst)
                 break;
             }
             DPRINTF(LSQUnit, "Marking store as able to write back, PC "
-                    "%#x [sn:%lli]\n",
-                    storeQueue[store_idx].inst->readPC(),
+                    "%s [sn:%lli]\n",
+                    storeQueue[store_idx].inst->pcState(),
                     storeQueue[store_idx].inst->seqNum);
 
             storeQueue[store_idx].canWB = true;
@@ -757,9 +757,9 @@ LSQUnit<Impl>::writebackStores()
             req = sreqLow;
         }
 
-        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x "
+        DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s "
                 "to Addr:%#x, data:%#x [sn:%lli]\n",
-                storeWBIdx, inst->readPC(),
+                storeWBIdx, inst->pcState(),
                 req->getPaddr(), (int)*(inst->memData),
                 inst->seqNum);
 
@@ -861,9 +861,9 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
     decrLdIdx(load_idx);
 
     while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
-        DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, "
+        DPRINTF(LSQUnit,"Load Instruction PC %s squashed, "
                 "[sn:%lli]\n",
-                loadQueue[load_idx]->readPC(),
+                loadQueue[load_idx]->pcState(),
                 loadQueue[load_idx]->seqNum);
 
         if (isStalled() && load_idx == stallingLoadIdx) {
@@ -906,9 +906,9 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
             break;
         }
 
-        DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, "
+        DPRINTF(LSQUnit,"Store Instruction PC %s squashed, "
                 "idx:%i [sn:%lli]\n",
-                storeQueue[store_idx].inst->readPC(),
+                storeQueue[store_idx].inst->pcState(),
                 store_idx, storeQueue[store_idx].inst->seqNum);
 
         // I don't think this can happen.  It should have been cleared
@@ -1156,7 +1156,7 @@ LSQUnit<Impl>::dumpInsts()
     int load_idx = loadHead;
 
     while (load_idx != loadTail && loadQueue[load_idx]) {
-        cprintf("%#x ", loadQueue[load_idx]->readPC());
+        cprintf("%s ", loadQueue[load_idx]->pcState());
 
         incrLdIdx(load_idx);
     }
@@ -1167,7 +1167,7 @@ LSQUnit<Impl>::dumpInsts()
     int store_idx = storeHead;
 
     while (store_idx != storeTail && storeQueue[store_idx].inst) {
-        cprintf("%#x ", storeQueue[store_idx].inst->readPC());
+        cprintf("%s ", storeQueue[store_idx].inst->pcState());
 
         incrStIdx(store_idx);
     }
index 5f5e71624a1fadb1c9cef41d112af473520f6c8e..fdea84ed52de6de2e37693a901c56ade7cf11aab 100644 (file)
@@ -171,7 +171,7 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
                 storeBarrierSN);
         producing_store = storeBarrierSN;
     } else {
-        producing_store = depPred.checkInst(inst->readPC());
+        producing_store = depPred.checkInst(inst->instAddr());
     }
 
     MemDepEntryPtr store_entry = NULL;
@@ -191,7 +191,7 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
     // are ready.
     if (!store_entry) {
         DPRINTF(MemDepUnit, "No dependency for inst PC "
-                "%#x [sn:%lli].\n", inst->readPC(), inst->seqNum);
+                "%s [sn:%lli].\n", inst->pcState(), inst->seqNum);
 
         inst_entry->memDepReady = true;
 
@@ -203,8 +203,8 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
     } else {
         // Otherwise make the instruction dependent on the store/barrier.
         DPRINTF(MemDepUnit, "Adding to dependency list; "
-                "inst PC %#x is dependent on [sn:%lli].\n",
-                inst->readPC(), producing_store);
+                "inst PC %s is dependent on [sn:%lli].\n",
+                inst->pcState(), producing_store);
 
         if (inst->readyToIssue()) {
             inst_entry->regsReady = true;
@@ -224,10 +224,10 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
     }
 
     if (inst->isStore()) {
-        DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n",
-                inst->readPC(), inst->seqNum);
+        DPRINTF(MemDepUnit, "Inserting store PC %s [sn:%lli].\n",
+                inst->pcState(), inst->seqNum);
 
-        depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber);
+        depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
 
         ++insertedStores;
     } else if (inst->isLoad()) {
@@ -260,10 +260,10 @@ MemDepUnit<MemDepPred, Impl>::insertNonSpec(DynInstPtr &inst)
     // Might want to turn this part into an inline function or something.
     // It's shared between both insert functions.
     if (inst->isStore()) {
-        DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n",
-                inst->readPC(), inst->seqNum);
+        DPRINTF(MemDepUnit, "Inserting store PC %s [sn:%lli].\n",
+                inst->pcState(), inst->seqNum);
 
-        depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber);
+        depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
 
         ++insertedStores;
     } else if (inst->isLoad()) {
@@ -313,8 +313,8 @@ void
 MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst)
 {
     DPRINTF(MemDepUnit, "Marking registers as ready for "
-            "instruction PC %#x [sn:%lli].\n",
-            inst->readPC(), inst->seqNum);
+            "instruction PC %s [sn:%lli].\n",
+            inst->pcState(), inst->seqNum);
 
     MemDepEntryPtr inst_entry = findInHash(inst);
 
@@ -336,8 +336,8 @@ void
 MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst)
 {
     DPRINTF(MemDepUnit, "Marking non speculative "
-            "instruction PC %#x as ready [sn:%lli].\n",
-            inst->readPC(), inst->seqNum);
+            "instruction PC %s as ready [sn:%lli].\n",
+            inst->pcState(), inst->seqNum);
 
     MemDepEntryPtr inst_entry = findInHash(inst);
 
@@ -363,9 +363,8 @@ MemDepUnit<MemDepPred, Impl>::replay(DynInstPtr &inst)
 
         MemDepEntryPtr inst_entry = findInHash(temp_inst);
 
-        DPRINTF(MemDepUnit, "Replaying mem instruction PC %#x "
-                "[sn:%lli].\n",
-                temp_inst->readPC(), temp_inst->seqNum);
+        DPRINTF(MemDepUnit, "Replaying mem instruction PC %s [sn:%lli].\n",
+                temp_inst->pcState(), temp_inst->seqNum);
 
         moveToReady(inst_entry);
 
@@ -377,9 +376,8 @@ template <class MemDepPred, class Impl>
 void
 MemDepUnit<MemDepPred, Impl>::completed(DynInstPtr &inst)
 {
-    DPRINTF(MemDepUnit, "Completed mem instruction PC %#x "
-            "[sn:%lli].\n",
-            inst->readPC(), inst->seqNum);
+    DPRINTF(MemDepUnit, "Completed mem instruction PC %s [sn:%lli].\n",
+            inst->pcState(), inst->seqNum);
 
     ThreadID tid = inst->threadNumber;
 
@@ -507,10 +505,10 @@ MemDepUnit<MemDepPred, Impl>::violation(DynInstPtr &store_inst,
                                         DynInstPtr &violating_load)
 {
     DPRINTF(MemDepUnit, "Passing violating PCs to store sets,"
-            " load: %#x, store: %#x\n", violating_load->readPC(),
-            store_inst->readPC());
+            " load: %#x, store: %#x\n", violating_load->instAddr(),
+            store_inst->instAddr());
     // Tell the memory dependence unit of the violation.
-    depPred.violation(violating_load->readPC(), store_inst->readPC());
+    depPred.violation(violating_load->instAddr(), store_inst->instAddr());
 }
 
 template <class MemDepPred, class Impl>
@@ -518,9 +516,9 @@ void
 MemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst)
 {
     DPRINTF(MemDepUnit, "Issuing instruction PC %#x [sn:%lli].\n",
-            inst->readPC(), inst->seqNum);
+            inst->instAddr(), inst->seqNum);
 
-    depPred.issued(inst->readPC(), inst->seqNum, inst->isStore());
+    depPred.issued(inst->instAddr(), inst->seqNum, inst->isStore());
 }
 
 template <class MemDepPred, class Impl>
@@ -559,9 +557,9 @@ MemDepUnit<MemDepPred, Impl>::dumpLists()
         int num = 0;
 
         while (inst_list_it != instList[tid].end()) {
-            cprintf("Instruction:%i\nPC:%#x\n[sn:%i]\n[tid:%i]\nIssued:%i\n"
+            cprintf("Instruction:%i\nPC: %s\n[sn:%i]\n[tid:%i]\nIssued:%i\n"
                     "Squashed:%i\n\n",
-                    num, (*inst_list_it)->readPC(),
+                    num, (*inst_list_it)->pcState(),
                     (*inst_list_it)->seqNum,
                     (*inst_list_it)->threadNumber,
                     (*inst_list_it)->isIssued(),
index 7f796c4c8ec0d6026015ad8ae9fdae999b663287..4b321d09949a37e70e52800a4003540190087db1 100644 (file)
@@ -591,15 +591,14 @@ DefaultRename<Impl>::renameInsts(ThreadID tid)
         insts_to_rename.pop_front();
 
         if (renameStatus[tid] == Unblocking) {
-            DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%#x from rename "
-                    "skidBuffer\n",
-                    tid, inst->seqNum, inst->readPC());
+            DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%s from rename "
+                    "skidBuffer\n", tid, inst->seqNum, inst->pcState());
         }
 
         if (inst->isSquashed()) {
-            DPRINTF(Rename, "[tid:%u]: instruction %i with PC %#x is "
-                    "squashed, skipping.\n",
-                    tid, inst->seqNum, inst->readPC());
+            DPRINTF(Rename, "[tid:%u]: instruction %i with PC %s is "
+                    "squashed, skipping.\n", tid, inst->seqNum,
+                    inst->pcState());
 
             ++renameSquashedInsts;
 
@@ -610,8 +609,7 @@ DefaultRename<Impl>::renameInsts(ThreadID tid)
         }
 
         DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with "
-                "PC %#x.\n",
-                tid, inst->seqNum, inst->readPC());
+                "PC %s.\n", tid, inst->seqNum, inst->pcState());
 
         // Handle serializeAfter/serializeBefore instructions.
         // serializeAfter marks the next instruction as serializeBefore.
@@ -716,8 +714,8 @@ DefaultRename<Impl>::skidInsert(ThreadID tid)
 
         assert(tid == inst->threadNumber);
 
-        DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC:%#x into Rename "
-                "skidBuffer\n", tid, inst->seqNum, inst->readPC());
+        DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC: %s into Rename "
+                "skidBuffer\n", tid, inst->seqNum, inst->pcState());
 
         ++renameSkidInsts;
 
@@ -731,7 +729,7 @@ DefaultRename<Impl>::skidInsert(ThreadID tid)
         for(it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++)
         {
             warn("[tid:%u]: %s [sn:%i].\n", tid,
-                    (*it)->staticInst->disassemble(inst->readPC()),
+                    (*it)->staticInst->disassemble(inst->instAddr()),
                     (*it)->seqNum);
         }
         panic("Skidbuffer Exceeded Max Size");
@@ -1287,8 +1285,7 @@ DefaultRename<Impl>::checkSignalsAndUpdate(ThreadID tid)
         unblock(tid);
 
         DPRINTF(Rename, "[tid:%u]: Processing instruction [%lli] with "
-                "PC %#x.\n",
-                tid, serial_inst->seqNum, serial_inst->readPC());
+                "PC %s.\n", tid, serial_inst->seqNum, serial_inst->pcState());
 
         // Put instruction into queue here.
         serial_inst->clearSerializeBefore();
index cf0080b48ae22f861bb7edacc56edd3df0e76f73..37f1c55046761f5b5d53321299126209db1201b5 100644 (file)
@@ -204,7 +204,7 @@ ROB<Impl>::insertInst(DynInstPtr &inst)
 {
     assert(inst);
 
-    DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC());
+    DPRINTF(ROB, "Adding inst PC %s to the ROB.\n", inst->pcState());
 
     assert(numInstsInROB != numEntries);
 
@@ -247,7 +247,7 @@ ROB<Impl>::retireHead(ThreadID tid)
     assert(head_inst->readyToCommit());
 
     DPRINTF(ROB, "[tid:%u]: Retiring head instruction, "
-            "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(),
+            "instruction PC %s, [sn:%lli]\n", tid, head_inst->pcState(),
             head_inst->seqNum);
 
     --numInstsInROB;
@@ -338,9 +338,9 @@ ROB<Impl>::doSquash(ThreadID tid)
          (*squashIt[tid])->seqNum > squashedSeqNum[tid];
          ++numSquashed)
     {
-        DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n",
+        DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %s, seq num %i.\n",
                 (*squashIt[tid])->threadNumber,
-                (*squashIt[tid])->readPC(),
+                (*squashIt[tid])->pcState(),
                 (*squashIt[tid])->seqNum);
 
         // Mark the instruction as squashed, and ready to commit so that
index b7790cfda49af04ff53655267868a43ab1bd1c6b..4e559000b2148f52922681eb2af5e99bec349f9a 100755 (executable)
@@ -172,29 +172,24 @@ class O3ThreadContext : public ThreadContext
 
     virtual void setFloatRegBits(int reg_idx, FloatRegBits val);
 
-    /** Reads this thread's PC. */
-    virtual uint64_t readPC()
-    { return cpu->readPC(thread->threadId()); }
-
-    /** Sets this thread's PC. */
-    virtual void setPC(uint64_t val);
-
-    /** Reads this thread's next PC. */
-    virtual uint64_t readNextPC()
-    { return cpu->readNextPC(thread->threadId()); }
+    /** Reads this thread's PC state. */
+    virtual TheISA::PCState pcState()
+    { return cpu->pcState(thread->threadId()); }
 
-    /** Sets this thread's next PC. */
-    virtual void setNextPC(uint64_t val);
+    /** Sets this thread's PC state. */
+    virtual void pcState(const TheISA::PCState &val);
 
-    virtual uint64_t readMicroPC()
-    { return cpu->readMicroPC(thread->threadId()); }
-
-    virtual void setMicroPC(uint64_t val);
+    /** Reads this thread's PC. */
+    virtual Addr instAddr()
+    { return cpu->instAddr(thread->threadId()); }
 
-    virtual uint64_t readNextMicroPC()
-    { return cpu->readNextMicroPC(thread->threadId()); }
+    /** Reads this thread's next PC. */
+    virtual Addr nextInstAddr()
+    { return cpu->nextInstAddr(thread->threadId()); }
 
-    virtual void setNextMicroPC(uint64_t val);
+    /** Reads this thread's next PC. */
+    virtual MicroPC microPC()
+    { return cpu->microPC(thread->threadId()); }
 
     /** Reads a miscellaneous register. */
     virtual MiscReg readMiscRegNoEffect(int misc_reg)
@@ -247,15 +242,6 @@ class O3ThreadContext : public ThreadContext
     }
 #endif
 
-    virtual uint64_t readNextNPC()
-    {
-        return this->cpu->readNextNPC(this->thread->threadId());
-    }
-
-    virtual void setNextNPC(uint64_t val)
-    {
-        this->cpu->setNextNPC(val, this->thread->threadId());
-    }
 };
 
 #endif
index 0b7a2b1727e802bc2e26b273864501b44716099d..3674428304575ce6953b63c744a63ba7d5a441d3 100755 (executable)
@@ -248,11 +248,7 @@ O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc)
 
     // Then finally set the PC, the next PC, the nextNPC, the micropc, and the
     // next micropc.
-    cpu->setPC(tc->readPC(), tid);
-    cpu->setNextPC(tc->readNextPC(), tid);
-    cpu->setNextNPC(tc->readNextNPC(), tid);
-    cpu->setMicroPC(tc->readMicroPC(), tid);
-    cpu->setNextMicroPC(tc->readNextMicroPC(), tid);
+    cpu->pcState(tc->pcState(), tid);
 #if !FULL_SYSTEM
     this->thread->funcExeInst = tc->readFuncExeInst();
 #endif
@@ -327,45 +323,9 @@ O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
 
 template <class Impl>
 void
-O3ThreadContext<Impl>::setPC(uint64_t val)
+O3ThreadContext<Impl>::pcState(const TheISA::PCState &val)
 {
-    cpu->setPC(val, thread->threadId());
-
-    // Squash if we're not already in a state update mode.
-    if (!thread->trapPending && !thread->inSyscall) {
-        cpu->squashFromTC(thread->threadId());
-    }
-}
-
-template <class Impl>
-void
-O3ThreadContext<Impl>::setNextPC(uint64_t val)
-{
-    cpu->setNextPC(val, thread->threadId());
-
-    // Squash if we're not already in a state update mode.
-    if (!thread->trapPending && !thread->inSyscall) {
-        cpu->squashFromTC(thread->threadId());
-    }
-}
-
-template <class Impl>
-void
-O3ThreadContext<Impl>::setMicroPC(uint64_t val)
-{
-    cpu->setMicroPC(val, thread->threadId());
-
-    // Squash if we're not already in a state update mode.
-    if (!thread->trapPending && !thread->inSyscall) {
-        cpu->squashFromTC(thread->threadId());
-    }
-}
-
-template <class Impl>
-void
-O3ThreadContext<Impl>::setNextMicroPC(uint64_t val)
-{
-    cpu->setNextMicroPC(val, thread->threadId());
+    cpu->pcState(val, thread->threadId());
 
     // Squash if we're not already in a state update mode.
     if (!thread->trapPending && !thread->inSyscall) {
index 79f5277d5f3a5c21c9fce10f01298678991c93c1..533d6149892a0dae00590e95d2c88040c753182c 100644 (file)
@@ -83,7 +83,7 @@ PCEventQueue::schedule(PCEvent *event)
 bool
 PCEventQueue::doService(ThreadContext *tc)
 {
-    Addr pc = tc->readPC() & ~0x3;
+    Addr pc = tc->instAddr() & ~0x3;
     int serviced = 0;
     range_t range = equal_range(pc);
     for (iterator i = range.first; i != range.second; ++i) {
@@ -91,7 +91,7 @@ PCEventQueue::doService(ThreadContext *tc)
         // another event.  This for example, prevents two invocations
         // of the SkipFuncEvent.  Maybe we should have separate PC
         // event queues for each processor?
-        if (pc != (tc->readPC() & ~0x3))
+        if (pc != (tc->instAddr() & ~0x3))
             continue;
 
         DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n",
index c6a5e23f922cf718a145978bd3b121af97ed9485..e87cc6dc21874346bf7e4932f0dea869f50722f8 100644 (file)
@@ -68,25 +68,25 @@ DefaultBTB::reset()
 
 inline
 unsigned
-DefaultBTB::getIndex(const Addr &inst_PC)
+DefaultBTB::getIndex(Addr instPC)
 {
     // Need to shift PC over by the word offset.
-    return (inst_PC >> instShiftAmt) & idxMask;
+    return (instPC >> instShiftAmt) & idxMask;
 }
 
 inline
 Addr
-DefaultBTB::getTag(const Addr &inst_PC)
+DefaultBTB::getTag(Addr instPC)
 {
-    return (inst_PC >> tagShiftAmt) & tagMask;
+    return (instPC >> tagShiftAmt) & tagMask;
 }
 
 bool
-DefaultBTB::valid(const Addr &inst_PC, ThreadID tid)
+DefaultBTB::valid(Addr instPC, ThreadID tid)
 {
-    unsigned btb_idx = getIndex(inst_PC);
+    unsigned btb_idx = getIndex(instPC);
 
-    Addr inst_tag = getTag(inst_PC);
+    Addr inst_tag = getTag(instPC);
 
     assert(btb_idx < numEntries);
 
@@ -102,12 +102,12 @@ DefaultBTB::valid(const Addr &inst_PC, ThreadID tid)
 // @todo Create some sort of return struct that has both whether or not the
 // address is valid, and also the address.  For now will just use addr = 0 to
 // represent invalid entry.
-Addr
-DefaultBTB::lookup(const Addr &inst_PC, ThreadID tid)
+TheISA::PCState
+DefaultBTB::lookup(Addr instPC, ThreadID tid)
 {
-    unsigned btb_idx = getIndex(inst_PC);
+    unsigned btb_idx = getIndex(instPC);
 
-    Addr inst_tag = getTag(inst_PC);
+    Addr inst_tag = getTag(instPC);
 
     assert(btb_idx < numEntries);
 
@@ -121,14 +121,14 @@ DefaultBTB::lookup(const Addr &inst_PC, ThreadID tid)
 }
 
 void
-DefaultBTB::update(const Addr &inst_PC, const Addr &target, ThreadID tid)
+DefaultBTB::update(Addr instPC, const TheISA::PCState &target, ThreadID tid)
 {
-    unsigned btb_idx = getIndex(inst_PC);
+    unsigned btb_idx = getIndex(instPC);
 
     assert(btb_idx < numEntries);
 
     btb[btb_idx].tid = tid;
     btb[btb_idx].valid = true;
     btb[btb_idx].target = target;
-    btb[btb_idx].tag = getTag(inst_PC);
+    btb[btb_idx].tag = getTag(instPC);
 }
index 6557522e0c901b50d0d4687cebd6a08e33cebfb7..814b2387220ad5f249c124b39a3a54bc2e3e2438 100644 (file)
 #ifndef __CPU_O3_BTB_HH__
 #define __CPU_O3_BTB_HH__
 
+#include "arch/types.hh"
 #include "base/misc.hh"
 #include "base/types.hh"
+#include "config/the_isa.hh"
 
 class DefaultBTB
 {
@@ -41,14 +43,13 @@ class DefaultBTB
     {
         BTBEntry()
             : tag(0), target(0), valid(false)
-        {
-        }
+        {}
 
         /** The entry's tag. */
         Addr tag;
 
         /** The entry's target. */
-        Addr target;
+        TheISA::PCState target;
 
         /** The entry's thread id. */
         ThreadID tid;
@@ -74,21 +75,21 @@ class DefaultBTB
      *  @param tid The thread id.
      *  @return Returns the target of the branch.
      */
-    Addr lookup(const Addr &inst_PC, ThreadID tid);
+    TheISA::PCState lookup(Addr instPC, ThreadID tid);
 
     /** Checks if a branch is in the BTB.
      *  @param inst_PC The address of the branch to look up.
      *  @param tid The thread id.
      *  @return Whether or not the branch exists in the BTB.
      */
-    bool valid(const Addr &inst_PC, ThreadID tid);
+    bool valid(Addr instPC, ThreadID tid);
 
     /** Updates the BTB with the target of a branch.
      *  @param inst_PC The address of the branch being updated.
      *  @param target_PC The target address of the branch.
      *  @param tid The thread id.
      */
-    void update(const Addr &inst_PC, const Addr &target_PC,
+    void update(Addr instPC, const TheISA::PCState &targetPC,
                 ThreadID tid);
 
   private:
@@ -96,13 +97,13 @@ class DefaultBTB
      *  @param inst_PC The branch to look up.
      *  @return Returns the index into the BTB.
      */
-    inline unsigned getIndex(const Addr &inst_PC);
+    inline unsigned getIndex(Addr instPC);
 
     /** Returns the tag bits of a given address.
      *  @param inst_PC The branch's address.
      *  @return Returns the tag bits.
      */
-    inline Addr getTag(const Addr &inst_PC);
+    inline Addr getTag(Addr instPC);
 
     /** The actual BTB. */
     std::vector<BTBEntry> btb;
index 6373e5de3559a691506cc1379f3b600db31e9f70..0ba09bfae7e4c2013ce0065d8803007dcb610cf5 100644 (file)
@@ -34,13 +34,8 @@ void
 ReturnAddrStack::init(unsigned _numEntries)
 {
      numEntries  = _numEntries;
-     usedEntries = 0;
-     tos = 0;
-
      addrStack.resize(numEntries);
-
-     for (unsigned i = 0; i < numEntries; ++i)
-         addrStack[i] = 0;
+     reset();
 }
 
 void
@@ -49,11 +44,11 @@ ReturnAddrStack::reset()
     usedEntries = 0;
     tos = 0;
     for (unsigned i = 0; i < numEntries; ++i)
-        addrStack[i] = 0;
+        addrStack[i].set(0);
 }
 
 void
-ReturnAddrStack::push(const Addr &return_addr)
+ReturnAddrStack::push(const TheISA::PCState &return_addr)
 {
     incrTos();
 
@@ -76,9 +71,9 @@ ReturnAddrStack::pop()
 
 void
 ReturnAddrStack::restore(unsigned top_entry_idx,
-                         const Addr &restored_target)
+                         const TheISA::PCState &restored)
 {
     tos = top_entry_idx;
 
-    addrStack[tos] = restored_target;
+    addrStack[tos] = restored;
 }
index a36faf79a694cb1e02d1e2a2175afbd8d7c657d4..ab92b34c2c264a99735d676e2f20138016fb541c 100644 (file)
@@ -33,7 +33,9 @@
 
 #include <vector>
 
+#include "arch/types.hh"
 #include "base/types.hh"
+#include "config/the_isa.hh"
 
 /** Return address stack class, implements a simple RAS. */
 class ReturnAddrStack
@@ -52,7 +54,7 @@ class ReturnAddrStack
     void reset();
 
     /** Returns the top address on the RAS. */
-    Addr top()
+    TheISA::PCState top()
     { return addrStack[tos]; }
 
     /** Returns the index of the top of the RAS. */
@@ -60,7 +62,7 @@ class ReturnAddrStack
     { return tos; }
 
     /** Pushes an address onto the RAS. */
-    void push(const Addr &return_addr);
+    void push(const TheISA::PCState &return_addr);
 
     /** Pops the top address from the RAS. */
     void pop();
@@ -68,9 +70,9 @@ class ReturnAddrStack
     /** Changes index to the top of the RAS, and replaces the top address with
      *  a new target.
      *  @param top_entry_idx The index of the RAS that will now be the top.
-     *  @param restored_target The new target address of the new top of the RAS.
+     *  @param restored The new target address of the new top of the RAS.
      */
-    void restore(unsigned top_entry_idx, const Addr &restored_target);
+    void restore(unsigned top_entry_idx, const TheISA::PCState &restored);
 
      bool empty() { return usedEntries == 0; }
 
@@ -85,7 +87,7 @@ class ReturnAddrStack
     { tos = (tos == 0 ? numEntries - 1 : tos - 1); }
 
     /** The RAS itself. */
-    std::vector<Addr> addrStack;
+    std::vector<TheISA::PCState> addrStack;
 
     /** The number of entries in the RAS. */
     unsigned numEntries;
index d97e7aeecf4791cce2f8b6c8ab354ff249f15e83..de26ca2f8d0f1b5dc9d682097d29937659214b11 100644 (file)
@@ -321,7 +321,7 @@ AtomicSimpleCPU::readBytes(Addr addr, uint8_t * data,
     dcache_latency = 0;
 
     while (1) {
-        req->setVirt(0, addr, size, flags, thread->readPC());
+        req->setVirt(0, addr, size, flags, thread->pcState().instAddr());
 
         // translate to physical address
         Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read);
@@ -475,7 +475,7 @@ AtomicSimpleCPU::writeBytes(uint8_t *data, unsigned size,
     dcache_latency = 0;
 
     while(1) {
-        req->setVirt(0, addr, size, flags, thread->readPC());
+        req->setVirt(0, addr, size, flags, thread->pcState().instAddr());
 
         // translate to physical address
         Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write);
@@ -643,8 +643,11 @@ AtomicSimpleCPU::tick()
 
         Fault fault = NoFault;
 
-        bool fromRom = isRomMicroPC(thread->readMicroPC());
-        if (!fromRom && !curMacroStaticInst) {
+        TheISA::PCState pcState = thread->pcState();
+
+        bool needToFetch = !isRomMicroPC(pcState.microPC()) &&
+                           !curMacroStaticInst;
+        if (needToFetch) {
             setupFetchRequest(&ifetch_req);
             fault = thread->itb->translateAtomic(&ifetch_req, tc,
                                                  BaseTLB::Execute);
@@ -655,7 +658,7 @@ AtomicSimpleCPU::tick()
             bool icache_access = false;
             dcache_access = false; // assume no dcache access
 
-            if (!fromRom && !curMacroStaticInst) {
+            if (needToFetch) {
                 // This is commented out because the predecoder would act like
                 // a tiny cache otherwise. It wouldn't be flushed when needed
                 // like the I cache. It should be flushed, and when that works
index 088d5ff16f8b1fc547e1afaef3c0a669f3970fae..196b72cc008c913e4f75bf2ae7b25bd5c858e63d 100644 (file)
@@ -368,19 +368,13 @@ BaseSimpleCPU::checkForInterrupts()
 void
 BaseSimpleCPU::setupFetchRequest(Request *req)
 {
-    Addr threadPC = thread->readPC();
+    Addr instAddr = thread->instAddr();
 
     // set up memory request for instruction fetch
-#if ISA_HAS_DELAY_SLOT
-    DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",threadPC,
-            thread->readNextPC(),thread->readNextNPC());
-#else
-    DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p\n",threadPC,
-            thread->readNextPC());
-#endif
+    DPRINTF(Fetch, "Fetch: PC:%08p\n", instAddr);
 
-    Addr fetchPC = (threadPC & PCMask) + fetchOffset;
-    req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH, threadPC);
+    Addr fetchPC = (instAddr & PCMask) + fetchOffset;
+    req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH, instAddr);
 }
 
 
@@ -399,11 +393,12 @@ BaseSimpleCPU::preExecute()
     // decode the instruction
     inst = gtoh(inst);
 
-    MicroPC upc = thread->readMicroPC();
+    TheISA::PCState pcState = thread->pcState();
 
-    if (isRomMicroPC(upc)) {
+    if (isRomMicroPC(pcState.microPC())) {
         stayAtPC = false;
-        curStaticInst = microcodeRom.fetchMicroop(upc, curMacroStaticInst);
+        curStaticInst = microcodeRom.fetchMicroop(pcState.microPC(),
+                                                  curMacroStaticInst);
     } else if (!curMacroStaticInst) {
         //We're not in the middle of a macro instruction
         StaticInstPtr instPtr = NULL;
@@ -412,21 +407,19 @@ BaseSimpleCPU::preExecute()
         //This should go away once the constructor can be set up properly
         predecoder.setTC(thread->getTC());
         //If more fetch data is needed, pass it in.
-        Addr fetchPC = (thread->readPC() & PCMask) + fetchOffset;
+        Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset;
         //if(predecoder.needMoreBytes())
-            predecoder.moreBytes(thread->readPC(), fetchPC, inst);
+            predecoder.moreBytes(pcState, fetchPC, inst);
         //else
         //    predecoder.process();
 
         //If an instruction is ready, decode it. Otherwise, we'll have to
         //fetch beyond the MachInst at the current pc.
         if (predecoder.extMachInstReady()) {
-#if THE_ISA == X86_ISA || THE_ISA == ARM_ISA
-            thread->setNextPC(thread->readPC() + predecoder.getInstSize());
-#endif // X86_ISA
             stayAtPC = false;
-            instPtr = StaticInst::decode(predecoder.getExtMachInst(),
-                                         thread->readPC());
+            ExtMachInst machInst = predecoder.getExtMachInst(pcState);
+            thread->pcState(pcState);
+            instPtr = StaticInst::decode(machInst, pcState.instAddr());
         } else {
             stayAtPC = true;
             fetchOffset += sizeof(MachInst);
@@ -436,13 +429,13 @@ BaseSimpleCPU::preExecute()
         //out micro ops
         if (instPtr && instPtr->isMacroop()) {
             curMacroStaticInst = instPtr;
-            curStaticInst = curMacroStaticInst->fetchMicroop(upc);
+            curStaticInst = curMacroStaticInst->fetchMicroop(pcState.microPC());
         } else {
             curStaticInst = instPtr;
         }
     } else {
         //Read the next micro op from the macro op
-        curStaticInst = curMacroStaticInst->fetchMicroop(upc);
+        curStaticInst = curMacroStaticInst->fetchMicroop(pcState.microPC());
     }
 
     //If we decoded an instruction this "tick", record information about it.
@@ -450,8 +443,7 @@ BaseSimpleCPU::preExecute()
     {
 #if TRACING_ON
         traceData = tracer->getInstRecord(curTick, tc,
-                curStaticInst, thread->readPC(),
-                curMacroStaticInst, thread->readMicroPC());
+                curStaticInst, thread->pcState(), curMacroStaticInst);
 
         DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n",
                 curStaticInst->getName(), curStaticInst->machInst);
@@ -462,10 +454,14 @@ BaseSimpleCPU::preExecute()
 void
 BaseSimpleCPU::postExecute()
 {
+    assert(curStaticInst);
+
+    TheISA::PCState pc = tc->pcState();
+    Addr instAddr = pc.instAddr();
 #if FULL_SYSTEM
-    if (thread->profile && curStaticInst) {
+    if (thread->profile) {
         bool usermode = TheISA::inUserMode(tc);
-        thread->profilePC = usermode ? 1 : thread->readPC();
+        thread->profilePC = usermode ? 1 : instAddr;
         ProfileNode *node = thread->profile->consume(tc, curStaticInst);
         if (node)
             thread->profileNode = node;
@@ -482,10 +478,10 @@ BaseSimpleCPU::postExecute()
     }
 
     if (CPA::available()) {
-        CPA::cpa()->swAutoBegin(tc, thread->readNextPC());
+        CPA::cpa()->swAutoBegin(tc, pc.nextInstAddr());
     }
 
-    traceFunctions(thread->readPC());
+    traceFunctions(instAddr);
 
     if (traceData) {
         traceData->dump();
@@ -505,30 +501,12 @@ BaseSimpleCPU::advancePC(Fault fault)
         fault->invoke(tc, curStaticInst);
         predecoder.reset();
     } else {
-        //If we're at the last micro op for this instruction
-        if (curStaticInst && curStaticInst->isLastMicroop()) {
-            //We should be working with a macro op or be in the ROM
-            assert(curMacroStaticInst ||
-                    isRomMicroPC(thread->readMicroPC()));
-            //Close out this macro op, and clean up the
-            //microcode state
-            curMacroStaticInst = StaticInst::nullStaticInstPtr;
-            thread->setMicroPC(normalMicroPC(0));
-            thread->setNextMicroPC(normalMicroPC(1));
-        }
-        //If we're still in a macro op
-        if (curMacroStaticInst || isRomMicroPC(thread->readMicroPC())) {
-            //Advance the micro pc
-            thread->setMicroPC(thread->readNextMicroPC());
-            //Advance the "next" micro pc. Note that there are no delay
-            //slots, and micro ops are "word" addressed.
-            thread->setNextMicroPC(thread->readNextMicroPC() + 1);
-        } else {
-            // go to the next instruction
-            thread->setPC(thread->readNextPC());
-            thread->setNextPC(thread->readNextNPC());
-            thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
-            assert(thread->readNextPC() != thread->readNextNPC());
+        if (curStaticInst) {
+            if (curStaticInst->isLastMicroop())
+                curMacroStaticInst = StaticInst::nullStaticInstPtr;
+            TheISA::PCState pcState = thread->pcState();
+            TheISA::advancePC(pcState, curStaticInst);
+            thread->pcState(pcState);
         }
     }
 }
index 0aa0a295c03e683d68e5c405f73d76593b5acb84..a713533fc1190b9fd5a01f21be2623d0d27817bc 100644 (file)
@@ -88,11 +88,12 @@ class BaseSimpleCPU : public BaseCPU
     Trace::InstRecord *traceData;
 
     inline void checkPcEventQueue() {
-        Addr oldpc;
+        Addr oldpc, pc = thread->instAddr();
         do {
-            oldpc = thread->readPC();
+            oldpc = pc;
             system->pcEventQueue.service(tc);
-        } while (oldpc != thread->readPC());
+            pc = thread->instAddr();
+        } while (oldpc != pc);
     }
 
   public:
@@ -282,18 +283,7 @@ class BaseSimpleCPU : public BaseCPU
         thread->setFloatRegBits(reg_idx, val);
     }
 
-    uint64_t readPC() { return thread->readPC(); }
-    uint64_t readMicroPC() { return thread->readMicroPC(); }
-    uint64_t readNextPC() { return thread->readNextPC(); }
-    uint64_t readNextMicroPC() { return thread->readNextMicroPC(); }
-    uint64_t readNextNPC() { return thread->readNextNPC(); }
     bool readPredicate() { return thread->readPredicate(); }
-
-    void setPC(uint64_t val) { thread->setPC(val); }
-    void setMicroPC(uint64_t val) { thread->setMicroPC(val); }
-    void setNextPC(uint64_t val) { thread->setNextPC(val); }
-    void setNextMicroPC(uint64_t val) { thread->setNextMicroPC(val); }
-    void setNextNPC(uint64_t val) { thread->setNextNPC(val); }
     void setPredicate(bool val)
     {
         thread->setPredicate(val);
@@ -301,6 +291,11 @@ class BaseSimpleCPU : public BaseCPU
             traceData->setPredicate(val);
         }
     }
+    TheISA::PCState pcState() { return thread->pcState(); }
+    void pcState(const TheISA::PCState &val) { thread->pcState(val); }
+    Addr instAddr() { return thread->instAddr(); }
+    Addr nextInstAddr() { return thread->nextInstAddr(); }
+    MicroPC microPC() { return thread->microPC(); }
 
     MiscReg readMiscRegNoEffect(int misc_reg)
     {
index 2eb5b432bfdd832c2202167563cd20623fcdc065..863c28be203a1bfeadbca1dceace7bcc07385b94 100644 (file)
@@ -422,7 +422,7 @@ TimingSimpleCPU::readBytes(Addr addr, uint8_t *data,
     Fault fault;
     const int asid = 0;
     const ThreadID tid = 0;
-    const Addr pc = thread->readPC();
+    const Addr pc = thread->instAddr();
     unsigned block_size = dcachePort.peerBlockSize();
     BaseTLB::Mode mode = BaseTLB::Read;
 
@@ -545,7 +545,7 @@ TimingSimpleCPU::writeTheseBytes(uint8_t *data, unsigned size,
 {
     const int asid = 0;
     const ThreadID tid = 0;
-    const Addr pc = thread->readPC();
+    const Addr pc = thread->instAddr();
     unsigned block_size = dcachePort.peerBlockSize();
     BaseTLB::Mode mode = BaseTLB::Write;
 
@@ -701,9 +701,10 @@ TimingSimpleCPU::fetch()
 
     checkPcEventQueue();
 
-    bool fromRom = isRomMicroPC(thread->readMicroPC());
+    TheISA::PCState pcState = thread->pcState();
+    bool needToFetch = !isRomMicroPC(pcState.microPC()) && !curMacroStaticInst;
 
-    if (!fromRom && !curMacroStaticInst) {
+    if (needToFetch) {
         Request *ifetch_req = new Request();
         ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0);
         setupFetchRequest(ifetch_req);
index bd796428aaf21d05611e08198f965650096d34e4..15fac86779ef515ccfd112172d8c4aff3896483f 100644 (file)
@@ -193,11 +193,7 @@ SimpleThread::serialize(ostream &os)
     ThreadState::serialize(os);
     SERIALIZE_ARRAY(floatRegs.i, TheISA::NumFloatRegs);
     SERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs);
-    SERIALIZE_SCALAR(microPC);
-    SERIALIZE_SCALAR(nextMicroPC);
-    SERIALIZE_SCALAR(PC);
-    SERIALIZE_SCALAR(nextPC);
-    SERIALIZE_SCALAR(nextNPC);
+    _pcState.serialize(os);
     // thread_num and cpu_id are deterministic from the config
 
     // 
@@ -213,11 +209,7 @@ SimpleThread::unserialize(Checkpoint *cp, const std::string &section)
     ThreadState::unserialize(cp, section);
     UNSERIALIZE_ARRAY(floatRegs.i, TheISA::NumFloatRegs);
     UNSERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs);
-    UNSERIALIZE_SCALAR(microPC);
-    UNSERIALIZE_SCALAR(nextMicroPC);
-    UNSERIALIZE_SCALAR(PC);
-    UNSERIALIZE_SCALAR(nextPC);
-    UNSERIALIZE_SCALAR(nextNPC);
+    _pcState.unserialize(cp, section);
     // thread_num and cpu_id are deterministic from the config
 
     // 
index e4a7b7a77ed1190669ad9e6dc8257425facee4a7..48077a9b92bdf39070ea19bd4cb84bfafeaa5285 100644 (file)
@@ -106,27 +106,7 @@ class SimpleThread : public ThreadState
     TheISA::IntReg intRegs[TheISA::NumIntRegs];
     TheISA::ISA isa;    // one "instance" of the current ISA.
 
-    /** The current microcode pc for the currently executing macro
-     * operation.
-     */
-    MicroPC microPC;
-
-    /** The next microcode pc for the currently executing macro
-     * operation.
-     */
-    MicroPC nextMicroPC;
-
-    /** The current pc.
-     */
-    Addr PC;
-
-    /** The next pc.
-     */
-    Addr nextPC;
-
-    /** The next next pc.
-     */
-    Addr nextNPC;
+    TheISA::PCState _pcState;
 
     /** Did this instruction execute or is it predicated false */
     bool predicate;
@@ -245,9 +225,7 @@ class SimpleThread : public ThreadState
 
     void clearArchRegs()
     {
-        microPC = 0;
-        nextMicroPC = 1;
-        PC = nextPC = nextNPC = 0;
+        _pcState = 0;
         memset(intRegs, 0, sizeof(intRegs));
         memset(floatRegs.i, 0, sizeof(floatRegs.i));
         isa.clear();
@@ -313,60 +291,34 @@ class SimpleThread : public ThreadState
                 reg_idx, flatIndex, val, floatRegs.f[flatIndex]);
     }
 
-    uint64_t readPC()
-    {
-        return PC;
-    }
-
-    void setPC(uint64_t val)
-    {
-        PC = val;
-    }
-
-    uint64_t readMicroPC()
-    {
-        return microPC;
-    }
-
-    void setMicroPC(uint64_t val)
-    {
-        microPC = val;
-    }
-
-    uint64_t readNextPC()
+    TheISA::PCState
+    pcState()
     {
-        return nextPC;
+        return _pcState;
     }
 
-    void setNextPC(uint64_t val)
+    void
+    pcState(const TheISA::PCState &val)
     {
-        nextPC = val;
+        _pcState = val;
     }
 
-    uint64_t readNextMicroPC()
+    Addr
+    instAddr()
     {
-        return nextMicroPC;
+        return _pcState.instAddr();
     }
 
-    void setNextMicroPC(uint64_t val)
+    Addr
+    nextInstAddr()
     {
-        nextMicroPC = val;
+        return _pcState.nextInstAddr();
     }
 
-    uint64_t readNextNPC()
+    MicroPC
+    microPC()
     {
-#if ISA_HAS_DELAY_SLOT
-        return nextNPC;
-#else
-        return nextPC + sizeof(TheISA::MachInst);
-#endif
-    }
-
-    void setNextNPC(uint64_t val)
-    {
-#if ISA_HAS_DELAY_SLOT
-        nextNPC = val;
-#endif
+        return _pcState.microPC();
     }
 
     bool readPredicate()
index 2c4fc8ab9bd6b258e2aba010b1c3c809523ac031..f2a72c96af26bddd73af857aa19bea00e9a1230f 100644 (file)
@@ -68,7 +68,8 @@ StaticInst::dumpDecodeCacheStats()
 }
 
 bool
-StaticInst::hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const
+StaticInst::hasBranchTarget(const TheISA::PCState &pc, ThreadContext *tc,
+                            TheISA::PCState &tgt) const
 {
     if (isDirectCtrl()) {
         tgt = branchTarget(pc);
@@ -84,21 +85,21 @@ StaticInst::hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const
 }
 
 StaticInstPtr
-StaticInst::fetchMicroop(MicroPC micropc)
+StaticInst::fetchMicroop(MicroPC upc) const
 {
     panic("StaticInst::fetchMicroop() called on instruction "
           "that is not microcoded.");
 }
 
-Addr
-StaticInst::branchTarget(Addr branchPC) const
+TheISA::PCState
+StaticInst::branchTarget(const TheISA::PCState &pc) const
 {
     panic("StaticInst::branchTarget() called on instruction "
           "that is not a PC-relative branch.");
     M5_DUMMY_RETURN;
 }
 
-Addr
+TheISA::PCState
 StaticInst::branchTarget(ThreadContext *tc) const
 {
     panic("StaticInst::branchTarget() called on instruction "
index 6474bbf9cbb9dbdade52132e8774eb029294097a..b219fafd66da96a736da5e4f821e40accd27c88e 100644 (file)
@@ -35,6 +35,7 @@
 #include <string>
 
 #include "arch/isa_traits.hh"
+#include "arch/types.hh"
 #include "arch/registers.hh"
 #include "config/the_isa.hh"
 #include "base/hashmap.hh"
@@ -70,28 +71,6 @@ namespace Trace {
     class InstRecord;
 }
 
-typedef uint16_t MicroPC;
-
-static const MicroPC MicroPCRomBit = 1 << (sizeof(MicroPC) * 8 - 1);
-
-static inline MicroPC
-romMicroPC(MicroPC upc)
-{
-    return upc | MicroPCRomBit;
-}
-
-static inline MicroPC
-normalMicroPC(MicroPC upc)
-{
-    return upc & ~MicroPCRomBit;
-}
-
-static inline bool
-isRomMicroPC(MicroPC upc)
-{
-    return MicroPCRomBit & upc;
-}
-
 /**
  * Base, ISA-independent static instruction class.
  *
@@ -392,18 +371,20 @@ class StaticInst : public StaticInstBase
  */
 #include "cpu/static_inst_exec_sigs.hh"
 
+    virtual void advancePC(TheISA::PCState &pcState) const = 0;
+
     /**
      * Return the microop that goes with a particular micropc. This should
      * only be defined/used in macroops which will contain microops
      */
-    virtual StaticInstPtr fetchMicroop(MicroPC micropc);
+    virtual StaticInstPtr fetchMicroop(MicroPC upc) const;
 
     /**
      * Return the target address for a PC-relative branch.
      * Invalid if not a PC-relative branch (i.e. isDirectCtrl()
      * should be true).
      */
-    virtual Addr branchTarget(Addr branchPC) const;
+    virtual TheISA::PCState branchTarget(const TheISA::PCState &pc) const;
 
     /**
      * Return the target address for an indirect branch (jump).  The
@@ -412,13 +393,14 @@ class StaticInst : public StaticInstBase
      * execute the branch in question.  Invalid if not an indirect
      * branch (i.e. isIndirectCtrl() should be true).
      */
-    virtual Addr branchTarget(ThreadContext *tc) const;
+    virtual TheISA::PCState branchTarget(ThreadContext *tc) const;
 
     /**
      * Return true if the instruction is a control transfer, and if so,
      * return the target address as well.
      */
-    bool hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const;
+    bool hasBranchTarget(const TheISA::PCState &pc, ThreadContext *tc,
+                         TheISA::PCState &tgt) const;
 
     /**
      * Return string representation of disassembled instruction.
index f2083ef081e0d287b36b5bb7dddc4d9da66cfac9..c4960ea308eae2252e146c84f46276b0f6fd21b1 100644 (file)
@@ -65,16 +65,8 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two)
     }
 #endif
 
-    Addr pc1 = one->readPC();
-    Addr pc2 = two->readPC();
-    if (pc1 != pc2)
-        panic("PCs doesn't match, one: %#x, two: %#x", pc1, pc2);
-
-    Addr npc1 = one->readNextPC();
-    Addr npc2 = two->readNextPC();
-    if (npc1 != npc2)
-        panic("NPCs doesn't match, one: %#x, two: %#x", npc1, npc2);
-
+    if (!(one->pcState() == two->pcState()))
+        panic("PC state doesn't match.");
     int id1 = one->cpuId();
     int id2 = two->cpuId();
     if (id1 != id2)
index 753fa2146b6bf08344445e0f023ca5a879ea33cd..1c70ef59a0fe3d70f1b7c3a5c2becd2d5a0410f6 100644 (file)
@@ -192,25 +192,15 @@ class ThreadContext
 
     virtual void setFloatRegBits(int reg_idx, FloatRegBits val) = 0;
 
-    virtual uint64_t readPC() = 0;
+    virtual TheISA::PCState pcState() = 0;
 
-    virtual void setPC(uint64_t val) = 0;
+    virtual void pcState(const TheISA::PCState &val) = 0;
 
-    virtual uint64_t readNextPC() = 0;
+    virtual Addr instAddr() = 0;
 
-    virtual void setNextPC(uint64_t val) = 0;
+    virtual Addr nextInstAddr() = 0;
 
-    virtual uint64_t readNextNPC() = 0;
-
-    virtual void setNextNPC(uint64_t val) = 0;
-
-    virtual uint64_t readMicroPC() = 0;
-
-    virtual void setMicroPC(uint64_t val) = 0;
-
-    virtual uint64_t readNextMicroPC() = 0;
-
-    virtual void setNextMicroPC(uint64_t val) = 0;
+    virtual MicroPC microPC() = 0;
 
     virtual MiscReg readMiscRegNoEffect(int misc_reg) = 0;
 
@@ -377,25 +367,13 @@ class ProxyThreadContext : public ThreadContext
     void setFloatRegBits(int reg_idx, FloatRegBits val)
     { actualTC->setFloatRegBits(reg_idx, val); }
 
-    uint64_t readPC() { return actualTC->readPC(); }
-
-    void setPC(uint64_t val) { actualTC->setPC(val); }
-
-    uint64_t readNextPC() { return actualTC->readNextPC(); }
-
-    void setNextPC(uint64_t val) { actualTC->setNextPC(val); }
-
-    uint64_t readNextNPC() { return actualTC->readNextNPC(); }
-
-    void setNextNPC(uint64_t val) { actualTC->setNextNPC(val); }
-
-    uint64_t readMicroPC() { return actualTC->readMicroPC(); }
-
-    void setMicroPC(uint64_t val) { actualTC->setMicroPC(val); }
+    TheISA::PCState pcState() { return actualTC->pcState(); }
 
-    uint64_t readNextMicroPC() { return actualTC->readMicroPC(); }
+    void pcState(const TheISA::PCState &val) { actualTC->pcState(val); }
 
-    void setNextMicroPC(uint64_t val) { actualTC->setNextMicroPC(val); }
+    Addr instAddr() { return actualTC->instAddr(); }
+    Addr nextInstAddr() { return actualTC->nextInstAddr(); }
+    MicroPC microPC() { return actualTC->microPC(); }
 
     bool readPredicate() { return actualTC->readPredicate(); }
 
index 25856e4662d65ce9530b55e50a860ba0e62c6727..612aabc0b6c462c308918849624dfefef7ab533d 100644 (file)
@@ -41,9 +41,10 @@ using namespace TheISA;
 void
 SkipFuncEvent::process(ThreadContext *tc)
 {
-    DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
-            tc->readPC(), tc->readIntReg(ReturnAddressReg));
+    TheISA::PCState oldPC M5_VAR_USED = tc->pcState();
 
     // Call ISA specific code to do the skipping
     TheISA::skipFunction(tc);
+    DPRINTF(PCEvent, "skipping %s: pc = %s, newpc = %s\n", description,
+            oldPC, tc->pcState());
 }
index d3348fe89617a12a1b9b68e858923cd406624620..aa3c4bb506cacc55c143160e92ff220292a4e7a0 100644 (file)
@@ -509,7 +509,9 @@ class Tru64 : public OperatingSystem
         // Note that we'll advance PC <- NPC before the end of the cycle,
         // so we need to restore the desired PC into NPC.
         // The current regs->pc will get clobbered.
-        tc->setNextPC(htog(sc->sc_pc));
+        PCState pc = tc->pcState();
+        pc.npc(htog(sc->sc_pc));
+        tc->pcState(pc);
 
         for (int i = 0; i < 31; ++i) {
             tc->setIntReg(i, htog(sc->sc_regs[i]));
@@ -703,8 +705,7 @@ class Tru64 : public OperatingSystem
         tc->setIntReg(TheISA::StackPointerReg, gtoh(attrp->registers.sp));
         tc->setMiscRegNoEffect(AlphaISA::MISCREG_UNIQ, uniq_val);
 
-        tc->setPC(gtoh(attrp->registers.pc));
-        tc->setNextPC(gtoh(attrp->registers.pc) + sizeof(TheISA::MachInst));
+        tc->pcState(gtoh(attrp->registers.pc));
 
         tc->activate();
     }
index 78b9fb0a49d3608152e0110acaf565e8990a8bd9..fbe8fb32aecba6d4969fc634794fd00ee580937b 100644 (file)
 #if !FULL_SYSTEM
 void FaultBase::invoke(ThreadContext * tc, StaticInstPtr inst)
 {
-    panic("fault (%s) detected @ PC %p", name(), tc->readPC());
+    panic("fault (%s) detected @ PC %s", name(), tc->pcState());
 }
 #else
 void FaultBase::invoke(ThreadContext * tc, StaticInstPtr inst)
 {
-    DPRINTF(Fault, "Fault %s at PC: %#x\n", name(), tc->readPC());
-
+    DPRINTF(Fault, "Fault %s at PC: %s\n", name(), tc->pcState());
     assert(!tc->misspeculating());
 }
 #endif
index 845f4ed99f6f4fb58aab459f2a7cbd2553187f47..1ff67d2cbd6ec4fb4fce617be171923ab543e990 100644 (file)
@@ -54,9 +54,8 @@ class InstRecord
     // need to make this ref-counted so it doesn't go away before we
     // dump the record
     StaticInstPtr staticInst;
-    Addr PC;
+    TheISA::PCState pc;
     StaticInstPtr macroStaticInst;
-    MicroPC upc;
     bool misspeculating;
     bool predicate;
 
@@ -90,12 +89,11 @@ class InstRecord
   public:
     InstRecord(Tick _when, ThreadContext *_thread,
                const StaticInstPtr _staticInst,
-               Addr _pc, bool spec,
-               const StaticInstPtr _macroStaticInst = NULL,
-               MicroPC _upc = 0)
+               TheISA::PCState _pc, bool spec,
+               const StaticInstPtr _macroStaticInst = NULL)
         : when(_when), thread(_thread),
-          staticInst(_staticInst), PC(_pc),
-          macroStaticInst(_macroStaticInst), upc(_upc),
+          staticInst(_staticInst), pc(_pc),
+          macroStaticInst(_macroStaticInst),
           misspeculating(spec), predicate(true)
     {
         data_status = DataInvalid;
@@ -137,9 +135,8 @@ class InstRecord
     Tick getWhen() { return when; }
     ThreadContext *getThread() { return thread; }
     StaticInstPtr getStaticInst() { return staticInst; }
-    Addr getPC() { return PC; }
+    TheISA::PCState getPCState() { return pc; }
     StaticInstPtr getMacroStaticInst() { return macroStaticInst; }
-    MicroPC getUPC() { return upc; } 
     bool getMisspeculating() { return misspeculating; }
 
     Addr getAddr() { return addr; }
@@ -167,9 +164,8 @@ class InstTracer : public SimObject
 
     virtual InstRecord *
         getInstRecord(Tick when, ThreadContext *tc,
-                const StaticInstPtr staticInst, Addr pc,
-                const StaticInstPtr macroStaticInst = NULL,
-                MicroPC _upc = 0) = 0;
+                const StaticInstPtr staticInst, TheISA::PCState pc,
+                const StaticInstPtr macroStaticInst = NULL) = 0;
 };
 
 
index 207c07309ceb7334a243c16fd7a6466c6fe32611..60bb59790f533864df95c71d45eb338249a8c37a 100644 (file)
@@ -824,9 +824,7 @@ cloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
             ctc->setIntReg(TheISA::SyscallPseudoReturnReg, 1);
         #endif
 
-        ctc->setPC(tc->readNextPC());
-        ctc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst));
-        ctc->setNextNPC(tc->readNextNPC() + sizeof(TheISA::MachInst));
+        ctc->pcState(tc->nextInstAddr());
 
         ctc->activate();
 
index eaec57ef53628d5e72a724b251a4c3a0d96d964b..f2847b2e503f2fd619399a688781564eb39041b3 100644 (file)
@@ -512,8 +512,8 @@ ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
         return -ENOTTY;
 
       default:
-        fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n",
-              fd, req, tc->readPC());
+        fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n",
+              fd, req, tc->pcState());
     }
 }