summaryrefslogtreecommitdiff
path: root/src/arch/arm/insts/static_inst.hh
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2010-06-02 12:57:59 -0500
committerGabe Black <gblack@eecs.umich.edu>2010-06-02 12:57:59 -0500
commitebb273bb7b8a871c1c5c07e00593e0194985aa46 (patch)
treecbd00a3c8ccf0eb39e540e78f52157aa20dc2491 /src/arch/arm/insts/static_inst.hh
parent9ef82c0bc437a962398857dcb365a8493a9ac5c7 (diff)
downloadgem5-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.hh60
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__