summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp')
-rw-r--r--lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp271
1 files changed, 128 insertions, 143 deletions
diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 702ca061da3..f6c52c0d8be 100644
--- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -181,21 +181,24 @@ EmulateInstructionARM::GetPluginDescriptionStatic ()
}
EmulateInstruction *
-EmulateInstructionARM::CreateInstance (const ArchSpec &arch)
+EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
{
- if (arch.GetTriple().getArch() == llvm::Triple::arm)
- {
- std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
-
- if (emulate_insn_ap.get())
- return emulate_insn_ap.release();
- }
- else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
+ if (EmulateInstructionARM::SupportsEmulatingIntructionsOfTypeStatic(inst_type))
{
- std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
-
- if (emulate_insn_ap.get())
- return emulate_insn_ap.release();
+ if (arch.GetTriple().getArch() == llvm::Triple::arm)
+ {
+ std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
+
+ if (emulate_insn_ap.get())
+ return emulate_insn_ap.release();
+ }
+ else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
+ {
+ std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
+
+ if (emulate_insn_ap.get())
+ return emulate_insn_ap.release();
+ }
}
return NULL;
@@ -340,7 +343,7 @@ EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding enc
Register dwarf_reg;
dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Register sp_reg;
- sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
+ sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
for (i=0; i<15; ++i)
{
if (BitIsSet (registers, i))
@@ -1247,7 +1250,7 @@ EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding
EmulateInstruction::Context context;
context.type = EmulateInstruction::eContextAdjustStackPointer;
Register sp_reg;
- sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
+ sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
context.SetRegisterPlusOffset (sp_reg, sp_offset);
if (d == 15)
@@ -1312,7 +1315,7 @@ EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding
EmulateInstruction::Context context;
context.type = EmulateInstruction::eContextAddition;
Register sp_reg;
- sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
+ sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Register other_reg;
other_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
context.SetRegisterRegisterOperands (sp_reg, other_reg);
@@ -1849,7 +1852,7 @@ EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding
EmulateInstruction::Context context;
context.type = EmulateInstruction::eContextPushRegisterOnStack;
Register sp_reg;
- sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
+ sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
context.SetRegisterPlusOffset (sp_reg, addr - sp);
if (Rt != 15)
{
@@ -1952,7 +1955,7 @@ EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding en
Register dwarf_reg;
dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Register sp_reg;
- sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
+ sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
for (i=0; i<regs; ++i)
{
dwarf_reg.num = start_reg + d + i;
@@ -2047,7 +2050,7 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc
Register dwarf_reg;
dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Register sp_reg;
- sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
+ sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
for (i=0; i<regs; ++i)
{
dwarf_reg.num = start_reg + d + i;
@@ -9330,7 +9333,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding
EmulateInstruction::Context context;
context.type = eContextSubtraction;
Register sp_reg;
- sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
+ sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Register dwarf_reg;
dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
@@ -10604,7 +10607,7 @@ EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding enc
// // Combine the word-aligned words in the correct order for current endianness.
// D[d+r] = if BigEndian() then word1:word2 else word2:word1;
uint64_t data;
- if (m_byte_order == eByteOrderBig)
+ if (GetByteOrder() == eByteOrderBig)
{
data = word1;
data = (data << 32) | word2;
@@ -10791,7 +10794,7 @@ EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding enc
data_reg.num = start_reg + d + r;
- if (m_byte_order == eByteOrderBig)
+ if (GetByteOrder() == eByteOrderBig)
{
context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
@@ -10931,7 +10934,7 @@ EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
// // Combine the word-aligned words in the correct order for current endianness.
// D[d] = if BigEndian() then word1:word2 else word2:word1;
uint64_t data64;
- if (m_byte_order == eByteOrderBig)
+ if (GetByteOrder() == eByteOrderBig)
{
data64 = word1;
data64 = (data64 << 32) | word2;
@@ -11059,7 +11062,7 @@ EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
if (!success)
return false;
- if (m_byte_order == eByteOrderBig)
+ if (GetByteOrder() == eByteOrderBig)
{
if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
return false;
@@ -12064,7 +12067,7 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod
}
EmulateInstructionARM::ARMOpcode*
-EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
+EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
{
static ARMOpcode
g_arm_opcodes[] =
@@ -12289,7 +12292,8 @@ EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
for (size_t i=0; i<k_num_arm_opcodes; ++i)
{
- if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
+ if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
+ (g_arm_opcodes[i].variants & arm_isa) != 0)
return &g_arm_opcodes[i];
}
return NULL;
@@ -12297,7 +12301,7 @@ EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
EmulateInstructionARM::ARMOpcode*
-EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
+EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
{
static ARMOpcode
@@ -12607,7 +12611,8 @@ EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
for (size_t i=0; i<k_num_thumb_opcodes; ++i)
{
- if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
+ if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
+ (g_thumb_opcodes[i].variants & arm_isa) != 0)
return &g_thumb_opcodes[i];
}
return NULL;
@@ -12636,24 +12641,30 @@ EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
}
bool
-EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr)
+EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
{
- m_opcode = insn_opcode;
+ if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
+ {
+ if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
+ m_opcode_mode = eModeThumb;
+ else
+ {
+ AddressClass addr_class = inst_addr.GetAddressClass();
- if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
- m_opcode_mode = eModeThumb;
- else
- {
- AddressClass addr_class = inst_addr.GetAddressClass();
-
- if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
- m_opcode_mode = eModeARM;
- else if (addr_class == eAddressClassCodeAlternateISA)
- m_opcode_mode = eModeThumb;
- else
- return false;
- }
- return true;
+ if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
+ m_opcode_mode = eModeARM;
+ else if (addr_class == eAddressClassCodeAlternateISA)
+ m_opcode_mode = eModeThumb;
+ else
+ return false;
+ }
+ if (m_opcode_mode == eModeThumb)
+ m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
+ else
+ m_opcode_cpsr = CPSR_MODE_USR;
+ return true;
+ }
+ return false;
}
bool
@@ -12711,6 +12722,12 @@ EmulateInstructionARM::ArchVersion ()
bool
EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
{
+ // If we are ignoring conditions, then always return true.
+ // this allows us to iterate over disassembly code and still
+ // emulate an instruction even if we don't have all the right
+ // bits set in the CPSR register...
+ if (m_ignore_conditions)
+ return true;
const uint32_t cond = CurrentCond (opcode);
@@ -12855,7 +12872,7 @@ EmulateInstructionARM::CurrentModeIsPrivileged ()
return false;
if (mode == 16)
- return false;
+ return false;
return true;
}
@@ -13188,123 +13205,72 @@ EmulateInstructionARM::WriteFlags (Context &context,
}
bool
-EmulateInstructionARM::EvaluateInstruction ()
+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;
+ ARMOpcode *opcode_data = NULL;
if (m_opcode_mode == eModeThumb)
- opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32());
+ opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
else if (m_opcode_mode == eModeARM)
- opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32());
- else
- return false;
+ opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
- if (!opcode_data)
+ if (opcode_data == NULL)
return false;
- // Verify that we're the right arch for this opcode
- switch (m_arm_isa)
+ const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
+ m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
+
+ bool success = false;
+ if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
{
- case ARMv4:
- if (opcode_data->variants != ARMvAll)
- return false;
- break;
-
- case ARMv4T:
- if ((opcode_data->variants!= ARMvAll)
- && (opcode_data->variants != ARMV4T_ABOVE))
- return false;
- break;
-
- case ARMv5T:
- case ARMv5TE:
- if ((opcode_data->variants != ARMvAll)
- && (opcode_data->variants != ARMV4T_ABOVE)
- && (opcode_data->variants != ARMV5_ABOVE))
- return false;
- break;
-
- case ARMv5TEJ:
- if ((opcode_data->variants != ARMvAll)
- && (opcode_data->variants != ARMV4T_ABOVE)
- && (opcode_data->variants != ARMV5_ABOVE)
- && (opcode_data->variants != ARMV5J_ABOVE))
- return false;
- break;
-
- case ARMv6:
- case ARMv6K:
- if ((opcode_data->variants != ARMvAll)
- && (opcode_data->variants != ARMV4T_ABOVE)
- && (opcode_data->variants != ARMV5_ABOVE)
- && (opcode_data->variants != ARMV5J_ABOVE)
- && (opcode_data->variants != ARMV6_ABOVE))
- return false;
- break;
-
- case ARMv6T2:
- case ARMv7:
- case ARMv8:
- if ((opcode_data->variants != ARMvAll)
- && (opcode_data->variants != ARMV4T_ABOVE)
- && (opcode_data->variants != ARMV5_ABOVE)
- && (opcode_data->variants != ARMV5J_ABOVE)
- && (opcode_data->variants != ARMV6_ABOVE)
- && (opcode_data->variants != ARMV6T2_ABOVE))
- return false;
- break;
-
- default:
-// if (opcode_data->variants != ARMvAll)
-// return false;
- break;
+ m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF,
+ dwarf_cpsr,
+ 0,
+ &success);
}
+
+ // Only return false if we are unable to read the CPSR if we care about conditions
+ if (success == false && m_ignore_conditions == false)
+ return false;
- // Just for now, for testing purposes.
- if (m_baton == NULL)
- fprintf (stdout, "\nEvaluateInstruction, opcode (0x%x), found = '%s'\n", m_opcode.GetOpcode32(),
- opcode_data->name);
-
- bool success;
- if (m_baton)
+ uint32_t orig_pc_value = 0;
+ if (auto_advance_pc)
{
- uint32_t cpsr_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
- if (success)
- m_opcode_cpsr = cpsr_value;
+ orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
+ if (!success)
+ return false;
}
- uint32_t orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
- if (!success)
- return false;
-
- success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); // Call the Emulate... function.
- if (!success)
- return false;
-
- uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
+ // Call the Emulate... function.
+ success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);
if (!success)
return false;
- if (m_advance_pc && (after_pc_value == orig_pc_value))
+ if (auto_advance_pc)
{
- if (opcode_data->size == eSize32)
- after_pc_value += 4;
- else if (opcode_data->size == eSize16)
- after_pc_value += 2;
-
- EmulateInstruction::Context context;
- context.type = eContextAdvancePC;
- context.SetNoArgs();
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
+ 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;
+
+ EmulateInstruction::Context context;
+ context.type = eContextAdvancePC;
+ context.SetNoArgs();
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
+ return false;
+
+ }
}
-
return true;
}
@@ -13331,10 +13297,6 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, Option
}
test_opcode = value_sp->GetUInt64Value ();
- // If the instruction emulation does not directly update the PC, advance the PC to the next instruction after
- // performing the emulation.
- SetAdvancePC (true);
-
if (arch.GetTriple().getArch() == llvm::Triple::arm)
{
m_opcode_mode = eModeARM;
@@ -13392,7 +13354,7 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, Option
&EmulationStateARM::ReadPseudoRegister,
&EmulationStateARM::WritePseudoRegister);
- bool success = EvaluateInstruction ();
+ bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
if (!success)
{
out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
@@ -13406,3 +13368,26 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, Option
return success;
}
+
+const char *
+EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
+{
+ if (reg_kind == eRegisterKindGeneric)
+ {
+ switch (reg_num)
+ {
+ case LLDB_REGNUM_GENERIC_PC: return "pc";
+ case LLDB_REGNUM_GENERIC_SP: return "sp";
+ case LLDB_REGNUM_GENERIC_FP: return "fp";
+ case LLDB_REGNUM_GENERIC_RA: return "lr";
+ case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
+ default: return NULL;
+ }
+ }
+ else if (reg_kind == eRegisterKindDWARF)
+ {
+ return GetARMDWARFRegisterName (reg_num);
+ }
+ return NULL;
+}
+
OpenPOWER on IntegriCloud