forked from OSchip/llvm-project
Add code to emulate LDMDB Arm instruction.
llvm-svn: 125133
This commit is contained in:
parent
f248b20d8c
commit
cdb58e1236
|
@ -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>" }
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -238,6 +238,9 @@ protected:
|
|||
|
||||
bool
|
||||
EmulateLDM (ARMEncoding encoding);
|
||||
|
||||
bool
|
||||
EmulateLDMDB (ARMEncoding encoding);
|
||||
|
||||
uint32_t m_arm_isa;
|
||||
Mode m_inst_mode;
|
||||
|
|
Loading…
Reference in New Issue