summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2011-02-13 17:41:10 -0800
committerGabe Black <gblack@eecs.umich.edu>2011-02-13 17:41:10 -0800
commit5ee94f4a3dadda357c6d28b60c19b3638146f9a7 (patch)
tree788669466677be1649fb84890428159f617c9daf
parentf036fd97481081afce7f757231ab69ba212f7f2a (diff)
downloadgem5-5ee94f4a3dadda357c6d28b60c19b3638146f9a7.tar.xz
X86: Only reset npc to reflect instruction length once.
When redirecting fetch to handle branches, the npc of the current pc state needs to be left alone. This change makes the pc state record whether or not the npc already reflects a real value by making it keep track of the current instruction size, or if no size has been set.
-rw-r--r--src/arch/x86/predecoder.hh6
-rw-r--r--src/arch/x86/types.hh50
2 files changed, 54 insertions, 2 deletions
diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh
index c06ec18bc..5c67e28e1 100644
--- a/src/arch/x86/predecoder.hh
+++ b/src/arch/x86/predecoder.hh
@@ -225,7 +225,11 @@ namespace X86ISA
{
assert(emiIsReady);
emiIsReady = false;
- nextPC.npc(nextPC.pc() + getInstSize());
+ if (!nextPC.size()) {
+ Addr size = getInstSize();
+ nextPC.size(size);
+ nextPC.npc(nextPC.pc() + size);
+ }
return emi;
}
};
diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh
index 5a208446a..d78af1b81 100644
--- a/src/arch/x86/types.hh
+++ b/src/arch/x86/types.hh
@@ -222,7 +222,55 @@ namespace X86ISA
return true;
}
- typedef GenericISA::UPCState<MachInst> PCState;
+ class PCState : public GenericISA::UPCState<MachInst>
+ {
+ protected:
+ typedef GenericISA::UPCState<MachInst> Base;
+
+ uint8_t _size;
+
+ public:
+ void
+ set(Addr val)
+ {
+ Base::set(val);
+ _size = 0;
+ }
+
+ PCState() {}
+ PCState(Addr val) { set(val); }
+
+ uint8_t size() const { return _size; }
+ void size(uint8_t newSize) { _size = newSize; }
+
+ void
+ advance()
+ {
+ Base::advance();
+ _size = 0;
+ }
+
+ void
+ uEnd()
+ {
+ Base::uEnd();
+ _size = 0;
+ }
+
+ void
+ serialize(std::ostream &os)
+ {
+ Base::serialize(os);
+ SERIALIZE_SCALAR(_size);
+ }
+
+ void
+ unserialize(Checkpoint *cp, const std::string &section)
+ {
+ Base::unserialize(cp, section);
+ UNSERIALIZE_SCALAR(_size);
+ }
+ };
struct CoreSpecific {
int core_type;