diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2010-06-02 12:57:59 -0500 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2010-06-02 12:57:59 -0500 |
commit | ebb273bb7b8a871c1c5c07e00593e0194985aa46 (patch) | |
tree | cbd00a3c8ccf0eb39e540e78f52157aa20dc2491 /src/arch/arm/insts/static_inst.hh | |
parent | 9ef82c0bc437a962398857dcb365a8493a9ac5c7 (diff) | |
download | gem5-ebb273bb7b8a871c1c5c07e00593e0194985aa46.tar.xz |
ARM: Add a new base class for instructions that can do an interworking branch.
Diffstat (limited to 'src/arch/arm/insts/static_inst.hh')
-rw-r--r-- | src/arch/arm/insts/static_inst.hh | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh index 7a87fce2b..18ca83741 100644 --- a/src/arch/arm/insts/static_inst.hh +++ b/src/arch/arm/insts/static_inst.hh @@ -47,7 +47,7 @@ namespace ArmISA { -class ArmStaticInst : public StaticInst +class ArmStaticInstBase : public StaticInst { protected: int32_t shift_rm_imm(uint32_t base, uint32_t shamt, @@ -67,7 +67,7 @@ class ArmStaticInst : public StaticInst bool arm_sub_overflow(int32_t result, int32_t lhs, int32_t rhs) const; // Constructor - ArmStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass) + ArmStaticInstBase(const char *mnem, MachInst _machInst, OpClass __opClass) : StaticInst(mnem, _machInst, __opClass) { } @@ -146,6 +146,62 @@ class ArmStaticInst : public StaticInst (val & ~PcModeMask)); } }; + +class ArmStaticInst : public ArmStaticInstBase +{ + protected: + ArmStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass) + : ArmStaticInstBase(mnem, _machInst, __opClass) + { + } + + template<class XC> + static void + setNextPC(XC *xc, Addr val) + { + xc->setNextPC((xc->readNextPC() & PcModeMask) | + (val & ~PcModeMask)); + } +}; + +class ArmInterWorking : public ArmStaticInstBase +{ + protected: + ArmInterWorking(const char *mnem, MachInst _machInst, OpClass __opClass) + : ArmStaticInstBase(mnem, _machInst, __opClass) + { + } + + template<class XC> + static void + setNextPC(XC *xc, Addr val) + { + Addr stateBits = xc->readPC() & PcModeMask; + Addr jBit = (ULL(1) << PcJBitShift); + Addr tBit = (ULL(1) << PcTBitShift); + bool thumbEE = (stateBits == (tBit | jBit)); + + Addr newPc = (val & ~PcModeMask); + if (thumbEE) { + if (bits(newPc, 0)) { + warn("Bad thumbEE interworking branch address %#x.\n", newPc); + } else { + newPc = newPc & ~mask(1); + } + } 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); + } +}; } #endif //__ARCH_ARM_INSTS_STATICINST_HH__ |