summaryrefslogtreecommitdiff
path: root/source/Plugins/Instruction/ARM
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/Instruction/ARM')
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp81
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.h4
-rw-r--r--source/Plugins/Instruction/ARM/EmulationStateARM.cpp116
-rw-r--r--source/Plugins/Instruction/ARM/EmulationStateARM.h10
-rw-r--r--source/Plugins/Instruction/ARM/Makefile14
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