Add a utility class ITSession to maintain the ITState for the Thumb ISA.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@124906 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 457cbaa..af81223 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -14,10 +14,74 @@
#include "ARMUtils.h"
#include "ARM_DWARF_Registers.h"
#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
+ // and CountTrailingZeros_32 function
using namespace lldb;
using namespace lldb_private;
+// A8.6.50
+// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
+static unsigned short CountITSize(unsigned ITMask) {
+ // First count the trailing zeros of the IT mask.
+ unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
+ if (TZ > 3)
+ {
+ printf("Encoding error: IT Mask '0000'\n");
+ return 0;
+ }
+ return (4 - TZ);
+}
+
+// Init ITState. Note that at least one bit is always 1 in mask.
+bool ITSession::InitIT(unsigned short bits7_0)
+{
+ ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
+ if (ITCounter == 0)
+ return false;
+
+ // A8.6.50 IT
+ unsigned short FirstCond = Bits32(bits7_0, 7, 4);
+ if (FirstCond == 0xF)
+ {
+ printf("Encoding error: IT FirstCond '1111'\n");
+ return false;
+ }
+ if (FirstCond == 0xE && ITCounter != 1)
+ {
+ printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
+ return false;
+ }
+
+ ITState = bits7_0;
+ return true;
+}
+
+// Update ITState if necessary.
+void ITSession::ITAdvance()
+{
+ assert(ITCounter);
+ --ITCounter;
+ if (ITCounter == 0)
+ ITState = 0;
+ else
+ {
+ unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
+ SetBits32(ITState, 4, 0, NewITState4_0);
+ }
+}
+
+// Return true if we're inside an IT Block.
+bool ITSession::InITBlock()
+{
+ return ITCounter != 0;
+}
+
+// Get condition bits for the current thumb instruction.
+uint32_t ITSession::GetCond()
+{
+ return Bits32(ITState, 7, 4);
+}
+
// ARM constants used during decoding
#define REG_RD 0
#define LDM_REGLIST 1
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
index dcf2fa4..dc0cf72 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -15,6 +15,30 @@
namespace lldb_private {
+// ITSession - Keep track of the IT Block progression.
+class ITSession
+{
+public:
+ ITSession() : ITCounter(0), ITState(0) {}
+ ~ITSession() {}
+
+ // InitIT - Initializes ITCounter/ITState.
+ bool InitIT(unsigned short bits7_0);
+
+ // ITAdvance - Updates ITCounter/ITState as IT Block progresses.
+ void ITAdvance();
+
+ // InITBlock - Returns true if we're inside an IT Block.
+ bool InITBlock();
+
+ // GetCond - Gets condition bits for the current thumb instruction.
+ uint32_t GetCond();
+
+private:
+ uint32_t ITCounter; // Possible values: 0, 1, 2, 3, 4.
+ uint32_t ITState; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially.
+};
+
class EmulateInstructionARM : public EmulateInstruction
{
public:
diff --git a/source/Plugins/Process/Utility/InstructionUtils.h b/source/Plugins/Process/Utility/InstructionUtils.h
index 1dc3feb..8ed2a71 100644
--- a/source/Plugins/Process/Utility/InstructionUtils.h
+++ b/source/Plugins/Process/Utility/InstructionUtils.h
@@ -21,6 +21,15 @@
return (value >> lsbit) & ((1u << (msbit - lsbit + 1)) - 1);
}
+static inline void
+SetBits32(uint32_t &bits, unsigned msbit, unsigned lsbit, unsigned val)
+{
+ assert(msbit < 32 && lsbit < 32 && msbit >= lsbit);
+ uint32_t mask = ((1 << (msbit - lsbit + 1)) - 1);
+ bits &= ~(mask << lsbit);
+ bits |= (val & mask) << lsbit;
+}
+
// Create a mask that starts at bit zero and includes "bit"
static inline uint64_t
MaskUpToBit (const uint64_t bit)