diff options
Diffstat (limited to 'source/Plugins/Instruction/ARM')
-rw-r--r-- | source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp | 81 | ||||
-rw-r--r-- | source/Plugins/Instruction/ARM/EmulateInstructionARM.h | 4 | ||||
-rw-r--r-- | source/Plugins/Instruction/ARM/EmulationStateARM.cpp | 116 | ||||
-rw-r--r-- | source/Plugins/Instruction/ARM/EmulationStateARM.h | 10 | ||||
-rw-r--r-- | source/Plugins/Instruction/ARM/Makefile | 14 |
5 files changed, 114 insertions, 111 deletions
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index d646d4d4754a1..884078b27175d 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -13004,7 +13004,7 @@ EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address { if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target)) { - if (m_arch.GetTriple().getArch() == llvm::Triple::thumb) + if (m_arch.GetTriple().getArch() == llvm::Triple::thumb || m_arch.IsAlwaysThumbInstructions ()) m_opcode_mode = eModeThumb; else { @@ -13017,7 +13017,7 @@ EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address else return false; } - if (m_opcode_mode == eModeThumb) + if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions ()) m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T; else m_opcode_cpsr = CPSR_MODE_USR; @@ -13040,7 +13040,7 @@ EmulateInstructionARM::ReadInstruction () read_inst_context.type = eContextReadOpcode; read_inst_context.SetNoArgs (); - if (m_opcode_cpsr & MASK_CPSR_T) + if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions ()) { m_opcode_mode = eModeThumb; uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success); @@ -13062,6 +13062,15 @@ EmulateInstructionARM::ReadInstruction () m_opcode_mode = eModeARM; m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success), GetByteOrder()); } + + if (!m_ignore_conditions) + { + // If we are not ignoreing the conditions then init the it session from the current + // value of cpsr. + uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) | Bits32(m_opcode_cpsr, 26, 25); + if (it != 0) + m_it_session.InitIT(it); + } } } if (!success) @@ -13572,20 +13581,13 @@ EmulateInstructionARM::WriteFlags (Context &context, bool EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options) { - // Advance the ITSTATE bits to their values for the next instruction. - if (m_opcode_mode == eModeThumb && m_it_session.InITBlock()) - m_it_session.ITAdvance(); - ARMOpcode *opcode_data = NULL; if (m_opcode_mode == eModeThumb) opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa); else if (m_opcode_mode == eModeARM) opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa); - - if (opcode_data == NULL) - return false; - + const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC; m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions; @@ -13609,41 +13611,48 @@ EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options) if (!success) return false; } - - // Call the Emulate... function. - success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); - if (!success) - return false; - + + // Call the Emulate... function if we managed to decode the opcode. + if (opcode_data) + { + success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); + if (!success) + return false; + } + + // Advance the ITSTATE bits to their values for the next instruction if we haven't just executed + // an IT instruction what initialized it. + if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() && + (opcode_data == nullptr || opcode_data->callback != &EmulateInstructionARM::EmulateIT)) + m_it_session.ITAdvance(); + if (auto_advance_pc) { uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success); if (!success) return false; - + if (auto_advance_pc && (after_pc_value == orig_pc_value)) { - if (opcode_data->size == eSize32) - after_pc_value += 4; - else if (opcode_data->size == eSize16) - after_pc_value += 2; - + after_pc_value += m_opcode.GetByteSize(); + EmulateInstruction::Context context; context.type = eContextAdvancePC; context.SetNoArgs(); if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value)) return false; - } } return true; } -bool -EmulateInstructionARM::IsInstructionConditional() +EmulateInstruction::InstructionCondition +EmulateInstructionARM::GetInstructionCondition() { const uint32_t cond = CurrentCond (m_opcode.GetOpcode32()); - return cond != 0xe && cond != 0xf && cond != UINT32_MAX; + if (cond == 0xe || cond == 0xf || cond == UINT32_MAX) + return EmulateInstruction::UnconditionalCondition; + return cond; } bool @@ -13669,19 +13678,19 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, Option } test_opcode = value_sp->GetUInt64Value (); - if (arch.GetTriple().getArch() == llvm::Triple::arm) - { - m_opcode_mode = eModeARM; - m_opcode.SetOpcode32 (test_opcode, GetByteOrder()); - } - else if (arch.GetTriple().getArch() == llvm::Triple::thumb) + + if (arch.GetTriple().getArch() == llvm::Triple::thumb || arch.IsAlwaysThumbInstructions ()) { m_opcode_mode = eModeThumb; if (test_opcode < 0x10000) - m_opcode.SetOpcode16 (test_opcode, GetByteOrder()); + m_opcode.SetOpcode16 (test_opcode, endian::InlHostByteOrder()); else - m_opcode.SetOpcode32 (test_opcode, GetByteOrder()); - + m_opcode.SetOpcode32 (test_opcode, endian::InlHostByteOrder()); + } + else if (arch.GetTriple().getArch() == llvm::Triple::arm) + { + m_opcode_mode = eModeARM; + m_opcode.SetOpcode32 (test_opcode, endian::InlHostByteOrder()); } else { diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h index 893f43f199779..6e75a3db2eb5a 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h @@ -166,8 +166,8 @@ public: bool EvaluateInstruction (uint32_t evaluate_options) override; - bool - IsInstructionConditional() override; + InstructionCondition + GetInstructionCondition() override; bool TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) override; diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp index 6072264f1efc8..547db44ebfb21 100644 --- a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp @@ -61,11 +61,15 @@ EmulationStateARM::LoadPseudoRegistersFromFrame (StackFrame &frame) if (reg_ctx->ReadRegister (reg_info, reg_value)) { + uint64_t value = reg_value.GetAsUInt64(); uint32_t idx = i - dwarf_d0; if (i < 16) - m_vfp_regs.sd_regs[idx].d_reg = reg_value.GetAsUInt64(); + { + m_vfp_regs.s_regs[idx * 2] = (uint32_t)value; + m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32); + } else - m_vfp_regs.d_regs[idx - 16] = reg_value.GetAsUInt64(); + m_vfp_regs.d_regs[idx - 16] = value; } else success = false; @@ -82,16 +86,18 @@ EmulationStateARM::StorePseudoRegisterValue (uint32_t reg_num, uint64_t value) else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) { uint32_t idx = reg_num - dwarf_s0; - m_vfp_regs.sd_regs[idx / 2].s_reg[idx % 2] = (uint32_t) value; + m_vfp_regs.s_regs[idx] = (uint32_t)value; } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) { - if ((reg_num - dwarf_d0) < 16) + uint32_t idx = reg_num - dwarf_d0; + if (idx < 16) { - m_vfp_regs.sd_regs[reg_num - dwarf_d0].d_reg = value; + m_vfp_regs.s_regs[idx * 2] = (uint32_t)value; + m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32); } else - m_vfp_regs.d_regs[reg_num - dwarf_d16] = value; + m_vfp_regs.d_regs[idx - 16] = value; } else return false; @@ -110,14 +116,15 @@ EmulationStateARM::ReadPseudoRegisterValue (uint32_t reg_num, bool &success) else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) { uint32_t idx = reg_num - dwarf_s0; - value = m_vfp_regs.sd_regs[idx / 2].s_reg[idx % 2]; + value = m_vfp_regs.d_regs[idx]; } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) { - if ((reg_num - dwarf_d0) < 16) - value = m_vfp_regs.sd_regs[reg_num - dwarf_d0].d_reg; + uint32_t idx = reg_num - dwarf_d0; + if (idx < 16) + value = (uint64_t)m_vfp_regs.s_regs[idx * 2] | ((uint64_t)m_vfp_regs.s_regs[idx * 2 + 1] >> 32); else - value = m_vfp_regs.d_regs[reg_num - dwarf_d16]; + value = m_vfp_regs.d_regs[idx - 16]; } else success = false; @@ -131,8 +138,8 @@ EmulationStateARM::ClearPseudoRegisters () for (int i = 0; i < 17; ++i) m_gpr[i] = 0; - for (int i = 0; i < 16; ++i) - m_vfp_regs.sd_regs[i].d_reg = 0; + for (int i = 0; i < 32; ++i) + m_vfp_regs.s_regs[i] = 0; for (int i = 0; i < 16; ++i) m_vfp_regs.d_regs[i] = 0; @@ -145,23 +152,14 @@ EmulationStateARM::ClearPseudoMemory () } bool -EmulationStateARM::StoreToPseudoAddress (lldb::addr_t p_address, uint64_t value, uint32_t size) +EmulationStateARM::StoreToPseudoAddress (lldb::addr_t p_address, uint32_t value) { - if (size > 8) - return false; - - if (size <= 4) - m_memory[p_address] = value; - else if (size == 8) - { - m_memory[p_address] = (value << 32) >> 32; - m_memory[p_address + 4] = value << 32; - } + m_memory[p_address] = value; return true; } uint32_t -EmulationStateARM::ReadFromPseudoAddress (lldb::addr_t p_address, uint32_t size, bool &success) +EmulationStateARM::ReadFromPseudoAddress (lldb::addr_t p_address, bool &success) { std::map<lldb::addr_t,uint32_t>::iterator pos; uint32_t ret_val = 0; @@ -191,25 +189,31 @@ EmulationStateARM::ReadPseudoMemory (EmulateInstruction *instruction, EmulationStateARM *pseudo_state = (EmulationStateARM *) baton; if (length <= 4) { - uint32_t value = pseudo_state->ReadFromPseudoAddress (addr, length, success); + uint32_t value = pseudo_state->ReadFromPseudoAddress (addr, success); if (!success) return 0; + if (endian::InlHostByteOrder() == lldb::eByteOrderBig) + value = llvm::ByteSwap_32 (value); *((uint32_t *) dst) = value; } else if (length == 8) { - uint32_t value1 = pseudo_state->ReadFromPseudoAddress (addr, 4, success); + uint32_t value1 = pseudo_state->ReadFromPseudoAddress (addr, success); if (!success) return 0; - uint32_t value2 = pseudo_state->ReadFromPseudoAddress (addr + 4, 4, success); + uint32_t value2 = pseudo_state->ReadFromPseudoAddress (addr + 4, success); if (!success) return 0; - uint64_t value64 = value2; - value64 = (value64 << 32) | value1; - *((uint64_t *) dst) = value64; + if (endian::InlHostByteOrder() == lldb::eByteOrderBig) + { + value1 = llvm::ByteSwap_32 (value1); + value2 = llvm::ByteSwap_32 (value2); + } + ((uint32_t *) dst)[0] = value1; + ((uint32_t *) dst)[1] = value2; } else success = false; @@ -231,13 +235,32 @@ EmulationStateARM::WritePseudoMemory (EmulateInstruction *instruction, if (!baton) return 0; - bool success; EmulationStateARM *pseudo_state = (EmulationStateARM *) baton; - uint64_t value = *((const uint64_t *) dst); - success = pseudo_state->StoreToPseudoAddress (addr, value, length); - if (success) + + if (length <= 4) + { + uint32_t value = *((const uint32_t *) dst); + if (endian::InlHostByteOrder() == lldb::eByteOrderBig) + value = llvm::ByteSwap_32 (value); + + pseudo_state->StoreToPseudoAddress (addr, value); return length; - + } + else if (length == 8) + { + uint32_t value1 = ((const uint32_t *) dst)[0]; + uint32_t value2 = ((const uint32_t *) dst)[1]; + if (endian::InlHostByteOrder() == lldb::eByteOrderBig) + { + value1 = llvm::ByteSwap_32 (value1); + value2 = llvm::ByteSwap_32 (value2); + } + + pseudo_state->StoreToPseudoAddress (addr, value1); + pseudo_state->StoreToPseudoAddress (addr + 4, value2); + return length; + } + return 0; } @@ -289,27 +312,16 @@ EmulationStateARM::CompareState (EmulationStateARM &other_state) match = false; } - for (int i = 0; match && i < 16; ++i) + for (int i = 0; match && i < 32; ++i) { - if (m_vfp_regs.sd_regs[i].s_reg[0] != other_state.m_vfp_regs.sd_regs[i].s_reg[0]) - match = false; - - if (m_vfp_regs.sd_regs[i].s_reg[1] != other_state.m_vfp_regs.sd_regs[i].s_reg[1]) + if (m_vfp_regs.s_regs[i] != other_state.m_vfp_regs.s_regs[i]) match = false; } - for (int i = 0; match && i < 32; ++i) + for (int i = 0; match && i < 16; ++i) { - if (i < 16) - { - if (m_vfp_regs.sd_regs[i].d_reg != other_state.m_vfp_regs.sd_regs[i].d_reg) - match = false; - } - else - { - if (m_vfp_regs.d_regs[i - 16] != other_state.m_vfp_regs.d_regs[i - 16]) - match = false; - } + if (m_vfp_regs.d_regs[i] != other_state.m_vfp_regs.d_regs[i]) + match = false; } return match; @@ -355,7 +367,7 @@ EmulationStateARM::LoadStateFromDictionary (OptionValueDictionary *test_data) if (value_sp.get() == NULL) return false; uint64_t value = value_sp->GetUInt64Value(); - StoreToPseudoAddress (address, value, 4); + StoreToPseudoAddress (address, value); address = address + 4; } } diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.h b/source/Plugins/Instruction/ARM/EmulationStateARM.h index ad596a3c2779c..e82ef94b5a013 100644 --- a/source/Plugins/Instruction/ARM/EmulationStateARM.h +++ b/source/Plugins/Instruction/ARM/EmulationStateARM.h @@ -30,10 +30,10 @@ public: ReadPseudoRegisterValue (uint32_t reg_num, bool &success); bool - StoreToPseudoAddress (lldb::addr_t p_address, uint64_t value, uint32_t size); + StoreToPseudoAddress (lldb::addr_t p_address, uint32_t value); uint32_t - ReadFromPseudoAddress (lldb::addr_t p_address, uint32_t size, bool &success); + ReadFromPseudoAddress (lldb::addr_t p_address, bool &success); void ClearPseudoRegisters (); @@ -82,11 +82,7 @@ private: uint32_t m_gpr[17]; struct _sd_regs { - union - { - uint32_t s_reg[2]; - uint64_t d_reg; - } sd_regs[16]; // sregs 0 - 31 & dregs 0 - 15 + uint32_t s_regs[32]; // sregs 0 - 31 & dregs 0 - 15 uint64_t d_regs[16]; // dregs 16-31 diff --git a/source/Plugins/Instruction/ARM/Makefile b/source/Plugins/Instruction/ARM/Makefile deleted file mode 100644 index 31a233b0b374b..0000000000000 --- a/source/Plugins/Instruction/ARM/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Instruction/ARM/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginInstructionARM -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile |