Add code to emulate the LDMIB Arm instruction.
Modify code for LDM and LDMDB instructions to only create one context and to reuse it, rather than creating multiple contexts. llvm-svn: 125139
This commit is contained in:
parent
108a363318
commit
123b89b67f
|
@ -1607,16 +1607,18 @@ EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
|
|||
const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
|
||||
if (!success)
|
||||
return false;
|
||||
|
||||
EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
|
||||
eRegisterKindDWARF,
|
||||
dwarf_r0 + n,
|
||||
offset };
|
||||
|
||||
for (int i = 0; i < 14; ++i)
|
||||
{
|
||||
if (BitIsSet (registers, i))
|
||||
{
|
||||
EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
|
||||
eRegisterKindDWARF,
|
||||
dwarf_r0 + n,
|
||||
offset };
|
||||
|
||||
context.type = EmulateInstruction::eContextRegisterPlusOffset;
|
||||
context.arg2 = offset;
|
||||
if (wback && (n == 13)) // Pop Instruction
|
||||
context.type = EmulateInstruction::eContextPopRegisterOffStack;
|
||||
|
||||
|
@ -1635,11 +1637,8 @@ EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
|
|||
if (BitIsSet (registers, 15))
|
||||
{
|
||||
//LoadWritePC (MemA [address, 4]);
|
||||
EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
|
||||
eRegisterKindDWARF,
|
||||
dwarf_r0 + n,
|
||||
offset };
|
||||
|
||||
context.type = EmulateInstruction::eContextRegisterPlusOffset;
|
||||
context.arg2 = offset;
|
||||
uint32_t data = ReadMemoryUnsigned (context, base_address + offset, addr_byte_size, 0, &success);
|
||||
if (!success)
|
||||
return false;
|
||||
|
@ -1650,10 +1649,8 @@ EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
|
|||
if (wback && BitIsClear (registers, n))
|
||||
{
|
||||
addr_t offset = addr_byte_size * BitCount (registers);
|
||||
EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
|
||||
eRegisterKindDWARF,
|
||||
dwarf_r0 + n,
|
||||
offset };
|
||||
context.type = EmulateInstruction::eContextRegisterPlusOffset;
|
||||
context.arg2 = offset;
|
||||
|
||||
// R[n] = R[n] + 4 * BitCount (registers)
|
||||
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
|
||||
|
@ -1741,17 +1738,17 @@ EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
|
|||
int32_t offset = 0;
|
||||
addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success)
|
||||
- (addr_byte_size * BitCount (registers));
|
||||
EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
|
||||
eRegisterKindDWARF,
|
||||
dwarf_r0 + n,
|
||||
offset };
|
||||
|
||||
for (int i = 0; i < 14; ++i)
|
||||
{
|
||||
if (BitIsSet (registers, i))
|
||||
{
|
||||
// R[i] = MemA[address,4]; address = address + 4;
|
||||
EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
|
||||
eRegisterKindDWARF,
|
||||
dwarf_r0 + n,
|
||||
offset };
|
||||
|
||||
context.arg2 = offset;
|
||||
uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
|
||||
if (!success)
|
||||
return false;
|
||||
|
@ -1767,11 +1764,7 @@ EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
|
|||
// LoadWritePC(MemA[address,4]);
|
||||
if (BitIsSet (registers, 15))
|
||||
{
|
||||
EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
|
||||
eRegisterKindDWARF,
|
||||
dwarf_r0 + n,
|
||||
offset };
|
||||
|
||||
context.arg2 = offset;
|
||||
uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
|
||||
if (!success)
|
||||
return false;
|
||||
|
@ -1782,11 +1775,7 @@ EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
|
|||
// if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
|
||||
if (wback && BitIsClear (registers, n))
|
||||
{
|
||||
EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
|
||||
eRegisterKindDWARF,
|
||||
dwarf_r0 + n,
|
||||
offset };
|
||||
|
||||
context.arg2 = offset;
|
||||
addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
|
||||
if (!success)
|
||||
return false;
|
||||
|
@ -1801,6 +1790,110 @@ EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
|
||||
{
|
||||
#if 0
|
||||
if ConditionPassed() then
|
||||
EncodingSpecificOperations();
|
||||
address = R[n] + 4;
|
||||
|
||||
for i = 0 to 14
|
||||
if registers<i> == ’1’ then
|
||||
R[i] = MemA[address,4]; address = address + 4;
|
||||
if registers<15> == ’1’ then
|
||||
LoadWritePC(MemA[address,4]);
|
||||
|
||||
if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
|
||||
if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
|
||||
#endif
|
||||
|
||||
bool success = false;
|
||||
const uint32_t opcode = OpcodeAsUnsigned (&success);
|
||||
if (!success)
|
||||
return false;
|
||||
|
||||
if (ConditionPassed())
|
||||
{
|
||||
uint32_t n;
|
||||
uint32_t registers = 0;
|
||||
bool wback;
|
||||
const uint32_t addr_byte_size = GetAddressByteSize();
|
||||
switch (encoding)
|
||||
{
|
||||
case eEncodingA1:
|
||||
// n = UInt(Rn); registers = register_list; wback = (W == ’1’);
|
||||
n = Bits32 (opcode, 19, 16);
|
||||
registers = Bits32 (opcode, 15, 0);
|
||||
wback = BitIsSet (opcode, 21);
|
||||
|
||||
// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
|
||||
if ((n == 15) || (BitCount (registers) < 1))
|
||||
return false;
|
||||
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
// address = R[n] + 4;
|
||||
|
||||
int32_t offset = 0;
|
||||
addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success) + addr_byte_size;
|
||||
|
||||
EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
|
||||
eRegisterKindDWARF,
|
||||
dwarf_r0 + n,
|
||||
offset };
|
||||
|
||||
for (int i = 0; i < 14; ++i)
|
||||
{
|
||||
if (BitIsSet (registers, i))
|
||||
{
|
||||
// R[i] = MemA[address,4]; address = address + 4;
|
||||
|
||||
context.arg2 = offset;
|
||||
uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
|
||||
if (!success)
|
||||
return false;
|
||||
|
||||
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
|
||||
return false;
|
||||
|
||||
offset += addr_byte_size;
|
||||
}
|
||||
}
|
||||
|
||||
// if registers<15> == ’1’ then
|
||||
// LoadWritePC(MemA[address,4]);
|
||||
if (BitIsSet (registers, 15))
|
||||
{
|
||||
context.arg2 = offset;
|
||||
uint32_t data = ReadMemoryUnsigned (context, address + offset, addr_byte_size, 0, &success);
|
||||
if (!success)
|
||||
return false;
|
||||
if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, data))
|
||||
return false;
|
||||
}
|
||||
|
||||
// if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
|
||||
if (wback && BitIsClear (registers, n))
|
||||
{
|
||||
context.arg2 = offset;
|
||||
addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
|
||||
if (!success)
|
||||
return false;
|
||||
addr = addr + (addr_byte_size * BitCount (registers));
|
||||
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
|
||||
return false;
|
||||
}
|
||||
|
||||
// if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
|
||||
if (wback && BitIsSet (registers, n))
|
||||
return false; // I'm not sure this is right; how do I set R[n] to bits(32) UNKNOWN.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
EmulateInstructionARM::ARMOpcode*
|
||||
EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
|
||||
|
@ -1862,7 +1955,8 @@ EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
|
|||
// Load instructions
|
||||
//----------------------------------------------------------------------
|
||||
{ 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
|
||||
{ 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }
|
||||
{ 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
|
||||
{ 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" }
|
||||
|
||||
};
|
||||
static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
|
||||
|
|
|
@ -245,6 +245,9 @@ protected:
|
|||
|
||||
bool
|
||||
EmulateLDMDB (ARMEncoding encoding);
|
||||
|
||||
bool
|
||||
EmulateLDMIB (ARMEncoding encoding);
|
||||
|
||||
uint32_t m_arm_isa;
|
||||
Mode m_inst_mode;
|
||||
|
|
Loading…
Reference in New Issue