Fix various things in the instruction emulation code:
- Add ability to control whether or not the emulator advances the
PC register (in the emulation state), if the instruction itself
does not change the pc value..
- Fix a few typos in asm description strings.
- Fix bug in the carry flag calculation.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@129168 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/lldb/API/SBInstruction.h b/include/lldb/API/SBInstruction.h
index d12c8ce..6e6926c 100644
--- a/include/lldb/API/SBInstruction.h
+++ b/include/lldb/API/SBInstruction.h
@@ -53,7 +53,7 @@
GetDescription (lldb::SBStream &description);
bool
- EmulateWithFrame (lldb::SBFrame &frame);
+ EmulateWithFrame (lldb::SBFrame &frame, bool auto_advance_pc);
bool
DumpEmulation (const char * triple); // triple is to specify the architecture, e.g. 'armv6' or 'arm-apple-darwin'
diff --git a/include/lldb/Core/Disassembler.h b/include/lldb/Core/Disassembler.h
index 705d9bb..fda05bc 100644
--- a/include/lldb/Core/Disassembler.h
+++ b/include/lldb/Core/Disassembler.h
@@ -73,6 +73,7 @@
bool
Emulate (const ArchSpec &arch,
+ bool auto_advance_pc,
void *baton,
EmulateInstruction::ReadMemory read_mem_callback,
EmulateInstruction::WriteMemory write_mem_calback,
diff --git a/include/lldb/Core/EmulateInstruction.h b/include/lldb/Core/EmulateInstruction.h
index 2e8bccb..9a088c8 100644
--- a/include/lldb/Core/EmulateInstruction.h
+++ b/include/lldb/Core/EmulateInstruction.h
@@ -144,6 +144,8 @@
eContextAddition,
eContextSubtraction,
+
+ eContextAdvancePC,
eContextReturnFromException
};
@@ -412,6 +414,12 @@
virtual bool
EvaluateInstruction () = 0;
+ bool
+ GetAdvancePC () { return m_advance_pc; }
+
+ void
+ SetAdvancePC (bool value) { m_advance_pc = value; }
+
static void
TranslateRegister (uint32_t reg_kind, uint32_t reg_num, std::string ®_name);
@@ -548,6 +556,7 @@
WriteRegister m_write_reg_callback;
lldb::addr_t m_opcode_pc;
Opcode m_opcode;
+ bool m_advance_pc;
//------------------------------------------------------------------
// For EmulateInstruction only
//------------------------------------------------------------------
diff --git a/source/API/SBInstruction.cpp b/source/API/SBInstruction.cpp
index e46e869..a4ab155 100644
--- a/source/API/SBInstruction.cpp
+++ b/source/API/SBInstruction.cpp
@@ -116,7 +116,7 @@
}
bool
-SBInstruction::EmulateWithFrame (lldb::SBFrame &frame)
+SBInstruction::EmulateWithFrame (lldb::SBFrame &frame, bool auto_advance_pc)
{
if (m_opaque_sp && frame.get())
{
@@ -126,6 +126,7 @@
lldb_private::ArchSpec arch = target->GetArchitecture();
return m_opaque_sp->Emulate (arch,
+ auto_advance_pc,
(void *) frame.get(),
&lldb_private::EmulateInstruction::ReadMemoryFrame,
&lldb_private::EmulateInstruction::WriteMemoryFrame,
@@ -142,12 +143,8 @@
{
lldb_private::ArchSpec arch (triple, NULL);
- return m_opaque_sp->Emulate (arch,
- NULL,
- &lldb_private::EmulateInstruction::ReadMemoryDefault,
- &lldb_private::EmulateInstruction::WriteMemoryDefault,
- &lldb_private::EmulateInstruction::ReadRegisterDefault,
- &lldb_private::EmulateInstruction::WriteRegisterDefault);
+ return m_opaque_sp->DumpEmulation (arch);
+
}
return false;
}
diff --git a/source/Core/Disassembler.cpp b/source/Core/Disassembler.cpp
index 2318cf5..c422113 100644
--- a/source/Core/Disassembler.cpp
+++ b/source/Core/Disassembler.cpp
@@ -504,6 +504,7 @@
bool
Instruction::Emulate (const ArchSpec &arch,
+ bool auto_advance_pc,
void *baton,
EmulateInstruction::ReadMemory read_mem_callback,
EmulateInstruction::WriteMemory write_mem_callback,
@@ -516,6 +517,7 @@
insn_emulator_ap->SetBaton (baton);
insn_emulator_ap->SetCallbacks (read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback);
insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress());
+ insn_emulator_ap->SetAdvancePC (auto_advance_pc);
return insn_emulator_ap->EvaluateInstruction ();
}
diff --git a/source/Core/EmulateInstruction.cpp b/source/Core/EmulateInstruction.cpp
index 7130360..e828dbc 100644
--- a/source/Core/EmulateInstruction.cpp
+++ b/source/Core/EmulateInstruction.cpp
@@ -70,7 +70,8 @@
m_read_reg_callback (read_reg_callback),
m_write_reg_callback (write_reg_callback),
m_opcode (),
- m_opcode_pc (LLDB_INVALID_ADDRESS)
+ m_opcode_pc (LLDB_INVALID_ADDRESS),
+ m_advance_pc (false)
{
}
@@ -88,7 +89,8 @@
m_write_mem_callback (&WriteMemoryDefault),
m_read_reg_callback (&ReadRegisterDefault),
m_write_reg_callback (&WriteRegisterDefault),
- m_opcode_pc (LLDB_INVALID_ADDRESS)
+ m_opcode_pc (LLDB_INVALID_ADDRESS),
+ m_advance_pc (false)
{
::memset (&m_opcode, 0, sizeof (m_opcode));
}
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 04abfbd..1cd8440 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -11937,7 +11937,7 @@
// add (register)
{ 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
// add (register-shifted register)
- { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>m, <Rm>, <type> <RS>"},
+ { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
// adr
{ 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
{ 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
@@ -12063,7 +12063,7 @@
{ 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
{ 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
{ 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
- { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strc<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
+ { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
{ 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
{ 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
{ 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
@@ -12331,7 +12331,7 @@
{ 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
{ 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
{ 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
- { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
+ { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
{ 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
{ 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
{ 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
@@ -12351,7 +12351,7 @@
{ 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
{ 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
{ 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
- { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt?, <Rt2>, [<Rn>,#+/-<imm>]!"},
+ { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
{ 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
{ 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
{ 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
@@ -12832,8 +12832,13 @@
int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
result = UnsignedBits(unsigned_sum, 31, 0);
- carry_out = (result == unsigned_sum ? 0 : 1);
+// carry_out = (result == unsigned_sum ? 0 : 1);
overflow = ((int32_t)result == signed_sum ? 0 : 1);
+
+ if (carry_in)
+ carry_out = ((int32_t) x >= (int32_t) y) ? 1 : 0;
+ else
+ carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
AddWithCarryResult res = { result, carry_out, overflow };
return res;
@@ -13057,7 +13062,43 @@
// 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);
+ fprintf (stdout, "\nEvaluateInstruction, opcode (0x%x), found = '%s'\n", m_opcode.GetOpcode32(),
+ opcode_data->name);
+
+ bool success;
+ if (m_baton)
+ {
+ uint32_t cpsr_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
+ if (success)
+ m_opcode_cpsr = cpsr_value;
+ }
- return (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); // Call the Emulate... function.
+ 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);
+ if (!success)
+ return false;
+
+ if (m_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;
}