Add Encoding T2 & T3 of the PUSH instructions to the g_arm_opcodes table.
Plus add an extra field ARMInstrSize to the table entry type 'ARMOpcode'.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@124140 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Process/Utility/EmulateInstructionARM.cpp b/source/Plugins/Process/Utility/EmulateInstructionARM.cpp
index 06a73b3..e4fa24b 100644
--- a/source/Plugins/Process/Utility/EmulateInstructionARM.cpp
+++ b/source/Plugins/Process/Utility/EmulateInstructionARM.cpp
@@ -67,7 +67,7 @@
#define ARMv8 (1u << 8)
#define ARMvAll (0xffffffffu)
-typedef enum ARMEncoding
+typedef enum
{
eEncodingA1,
eEncodingA2,
@@ -81,19 +81,26 @@
eEncodingT5,
} ARMEncoding;
+typedef enum
+{
+ eSize16,
+ eSize32
+} ARMInstrSize;
+
// Typedef for the callback function used during the emulation.
// Pass along (ARMEncoding)encoding as the callback data.
typedef bool (*EmulateCallback) (EmulateInstructionARM *emulator, ARMEncoding encoding);
-typedef struct ARMOpcode
+typedef struct
{
uint32_t mask;
uint32_t value;
uint32_t variants;
ARMEncoding encoding;
+ ARMInstrSize size;
EmulateCallback callback;
const char *name;
-};
+} ARMOpcode;
static bool
EmulateARMPushEncoding (EmulateInstructionARM *emulator, ARMEncoding encoding)
@@ -137,16 +144,31 @@
if (!success)
return false;
uint32_t registers = 0;
+ uint32_t t; // UInt(Rt)
switch (encoding) {
+ case eEncodingT2:
+ // Ignore bits 15 & 13.
+ registers = EmulateInstruction::UnsignedBits (opcode, 15, 0) & ~0xa000;
+ // if BitCount(registers) < 2 then UNPREDICTABLE;
+ if (BitCount(registers) < 2)
+ return false;
+ break;
+ case eEncodingT3:
+ t = EmulateInstruction::UnsignedBits (opcode, 15, 12);
+ // if BadReg(t) then UNPREDICTABLE;
+ if (BadReg(t))
+ return false;
+ registers = (1u << t);
+ break;
case eEncodingA1:
registers = EmulateInstruction::UnsignedBits (opcode, 15, 0);
break;
case eEncodingA2:
- const uint32_t Rt = EmulateInstruction::UnsignedBits (opcode, 15, 12);
- // if t == 13 then UNPREDICTABLE
- if (Rt == dwarf_sp)
+ t = EmulateInstruction::UnsignedBits (opcode, 15, 12);
+ // if t == 13 then UNPREDICTABLE;
+ if (t == dwarf_sp)
return false;
- registers = (1u << Rt);
+ registers = (1u << t);
break;
}
addr_t sp_offset = addr_byte_size * EmulateInstruction::BitCount (registers);
@@ -193,9 +215,13 @@
static ARMOpcode g_arm_opcodes[] =
{
- { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, EmulateARMPushEncoding,
+ { 0xffff0000, 0xe8ad0000, ARMv6T2|ARMv7, eEncodingT2, eSize32, EmulateARMPushEncoding,
"PUSH<c> <registers> ; <registers> contains more than one register" },
- { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, EmulateARMPushEncoding,
+ { 0xffff0fff, 0xf84d0d04, ARMv6T2|ARMv7, eEncodingT3, eSize32, EmulateARMPushEncoding,
+ "PUSH<c> <registers> ; <registers> contains one register, <Rt>" },
+ { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, EmulateARMPushEncoding,
+ "PUSH<c> <registers> ; <registers> contains more than one register" },
+ { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, EmulateARMPushEncoding,
"PUSH<c> <registers> ; <registers> contains one register, <Rt>" }
};