Add code to emulate LDMDB Arm instruction.

llvm-svn: 125133
This commit is contained in:
Caroline Tice 2011-02-08 23:16:02 +00:00
parent f248b20d8c
commit cdb58e1236
2 changed files with 143 additions and 2 deletions

View File

@ -1617,6 +1617,142 @@ EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
return true;
}
bool
EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
{
#if 0
// ARM pseudo code...
if ConditionPassed() then
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
address = R[n] - 4*BitCount(registers);
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; // Only possible for encoding A1
#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 eEncodingT1:
// n = UInt(Rn); registers = P:M:0:register_list; wback = (W == 1);
n = Bits32 (opcode, 19, 16);
registers = Bits32 (opcode, 15, 0);
wback = BitIsSet (opcode, 21);
// if n == 15 || BitCount(registers) < 2 || (P == 1 && M == 1) then UNPREDICTABLE;
if ((n == 15)
|| (BitCount (registers) < 2)
|| (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
return false;
// if registers<15> == 1 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
if (BitIsSet (registers, 15)
&& m_it_session.InITBlock()
&& !m_it_session.LastInITBlock())
return false;
// if wback && registers<n> == 1 then UNPREDICTABLE;
if (wback && BitIsSet (registers, n))
return false;
break;
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;
}
int32_t offset = 0;
addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success)
- (addr_byte_size * BitCount (registers));
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 };
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))
{
EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
eRegisterKindDWARF,
dwarf_r0 + n,
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))
{
EmulateInstruction::Context context = { EmulateInstruction::eContextRegisterPlusOffset,
eRegisterKindDWARF,
dwarf_r0 + n,
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)
{
@ -1676,7 +1812,8 @@ EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
//----------------------------------------------------------------------
// Load instructions
//----------------------------------------------------------------------
{ 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }
{ 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
{ 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }
};
static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
@ -1765,7 +1902,8 @@ EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
// Load instructions
//----------------------------------------------------------------------
{ 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
{ 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" }
{ 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
{ 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }
};

View File

@ -238,6 +238,9 @@ protected:
bool
EmulateLDM (ARMEncoding encoding);
bool
EmulateLDMDB (ARMEncoding encoding);
uint32_t m_arm_isa;
Mode m_inst_mode;