From cdb58e12364939b53a911c582c880dd8ebb166a2 Mon Sep 17 00:00:00 2001 From: Caroline Tice Date: Tue, 8 Feb 2011 23:16:02 +0000 Subject: [PATCH] Add code to emulate LDMDB Arm instruction. llvm-svn: 125133 --- .../Instruction/ARM/EmulateInstructionARM.cpp | 142 +++++++++++++++++- .../Instruction/ARM/EmulateInstructionARM.h | 3 + 2 files changed, 143 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index 8ab253597549..1a727bf6ff27 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -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 == ’1’ then + R[i] = MemA[address,4]; address = address + 4; + if registers<15> == ’1’ then + LoadWritePC(MemA[address,4]); + + if wback && registers == ’0’ then R[n] = R[n] - 4*BitCount(registers); + if wback && registers == ’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 == ’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 == ’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 == ’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 {!} " } + { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm {!} " }, + { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb {!} " } }; 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 {!} " }, - { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm.w {!} " } + { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm.w {!} " }, + { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb {!} " } }; diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h index 0b9a2efa71fd..225b57951ebd 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h +++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h @@ -238,6 +238,9 @@ protected: bool EmulateLDM (ARMEncoding encoding); + + bool + EmulateLDMDB (ARMEncoding encoding); uint32_t m_arm_isa; Mode m_inst_mode;