summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTamas Berghammer <tberghammer@google.com>2016-02-02 14:32:11 +0000
committerTamas Berghammer <tberghammer@google.com>2016-02-02 14:32:11 +0000
commit8e18fe6e5423163d8f3f9b56aadc8c5b3eb2be91 (patch)
treed20764245ea183874a9293c2dca9d88604caa00a
parent926b189a813cc434beadc831fc5beca621fb8612 (diff)
downloadbcm5719-llvm-8e18fe6e5423163d8f3f9b56aadc8c5b3eb2be91.tar.gz
bcm5719-llvm-8e18fe6e5423163d8f3f9b56aadc8c5b3eb2be91.zip
Fix single stepping over the IT instruction
The ARM instruction emulator had 2 bugs related to the handling of the IT instruction causing an error in single stepping: * We haven't initialized the IT mask from the CPSR so if the last instruction of the IT block is a branch and the condition is false then the emulator evaluated the branch what resulted in an incorrect pc for the next instruction. * The ITSTATE was advanced before the execution of each instruction. As a result the emulator was using the condition of following instruction in every case. The ITSTATE should be edvanced after the execution of an instruction except after an IT instruction. Differential revision: http://reviews.llvm.org/D16772 llvm-svn: 259509
-rw-r--r--lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp21
1 files changed, 16 insertions, 5 deletions
diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index d646d4d4754..ec57eb5f1fc 100644
--- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -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,10 +13581,6 @@ 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)
@@ -13614,7 +13619,13 @@ EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
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->callback != &EmulateInstructionARM::EmulateIT)
+ m_it_session.ITAdvance();
+
if (auto_advance_pc)
{
uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
OpenPOWER on IntegriCloud