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'.

llvm-svn: 124140
This commit is contained in:
Johnny Chen 2011-01-24 19:46:32 +00:00
parent 78c9f78fc9
commit d8c2a48298
2 changed files with 47 additions and 9 deletions

View File

@ -18,6 +18,18 @@ namespace lldb_private {
// not permitted for many Thumb register specifiers.
static inline bool BadReg(uint32_t n) { return n == 13 || n == 15; }
// Returns an integer result equal to the number of bits of x that are ones.
static inline uint32_t BitCount(uint32_t x)
{
// c accumulates the total bits set in x
uint32_t c;
for (c = 0; x; ++c)
{
x &= x - 1; // clear the least significant bit set
}
return c;
}
} // namespace lldb_private
#endif // lldb_ARMUtils_h_

View File

@ -67,7 +67,7 @@ using namespace lldb_private;
#define ARMv8 (1u << 8)
#define ARMvAll (0xffffffffu)
typedef enum ARMEncoding
typedef enum
{
eEncodingA1,
eEncodingA2,
@ -81,19 +81,26 @@ typedef enum ARMEncoding
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 @@ EmulateARMPushEncoding (EmulateInstructionARM *emulator, ARMEncoding encoding)
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 @@ EmulateARMPushEncoding (EmulateInstructionARM *emulator, ARMEncoding encoding)
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>" }
};