Added the start of opcode emulation for ARM instructions. This class is designed

to be fed 4 callbacks: read/write memory, and read/write registers. After this,
you can tell the object to read an instruction. This will cause the class to read
the PC, and read and instruction. Then you can emulate the instruction by calling
EvaluateInstruction. This will cause the class to figure out exactly what an opcode
does, and call the read/write mem/regs functions with actual values which allows one
to emulate an instruction without running a process, or it allows one to watch the
context information (the memory write is a pushing register 3 onto the stack at offset
12) so it can be used for generating call frame information. This way, in the future,
we will have one class that can be used to emulate instructions and generate our
unwind info from assembly.

llvm-svn: 123998
This commit is contained in:
Greg Clayton 2011-01-21 22:02:52 +00:00
parent ef8cf45eb1
commit 6da4ca83b0
5 changed files with 712 additions and 0 deletions

View File

@ -15,6 +15,10 @@
2618D7921240116900F2B8FE /* SectionLoadList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2618D7911240116900F2B8FE /* SectionLoadList.cpp */; };
2618D9EB12406FE600F2B8FE /* NameToDIE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2618D9EA12406FE600F2B8FE /* NameToDIE.cpp */; };
261B5A5411C3F2AD00AABD0A /* SharingPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 261B5A5211C3F2AD00AABD0A /* SharingPtr.cpp */; };
2621C9CD12EA009300711A30 /* EmulateInstructionARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621C9CB12EA009300711A30 /* EmulateInstructionARM.cpp */; };
2621C9CE12EA009300711A30 /* EmulateInstruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 2621C9CC12EA009300711A30 /* EmulateInstruction.h */; };
2621C9D012EA066500711A30 /* EmulateInstructionARM.h in Headers */ = {isa = PBXBuildFile; fileRef = 2621C9CF12EA066500711A30 /* EmulateInstructionARM.h */; };
2621CA0B12EA107700711A30 /* EmulateInstruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621CA0A12EA107700711A30 /* EmulateInstruction.cpp */; };
262CFC7711A4510000946C6C /* debugserver in Resources */ = {isa = PBXBuildFile; fileRef = 26CE05A0115C31E50022F371 /* debugserver */; };
2635DA87127D0D0400675BC1 /* SharingPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 261B5A5311C3F2AD00AABD0A /* SharingPtr.h */; settings = {ATTRIBUTES = (Public, ); }; };
26368A3C126B697600E8659F /* darwin-debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26368A3B126B697600E8659F /* darwin-debug.cpp */; };
@ -540,6 +544,10 @@
261B5A5311C3F2AD00AABD0A /* SharingPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SharingPtr.h; path = include/lldb/Utility/SharingPtr.h; sourceTree = "<group>"; };
261E18CC1148966100BADCD3 /* GDBRemoteRegisterContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GDBRemoteRegisterContext.h; path = "source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h"; sourceTree = "<group>"; };
261E18CD1148966100BADCD3 /* GDBRemoteRegisterContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GDBRemoteRegisterContext.cpp; path = "source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp"; sourceTree = "<group>"; };
2621C9CB12EA009300711A30 /* EmulateInstructionARM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = EmulateInstructionARM.cpp; path = Utility/EmulateInstructionARM.cpp; sourceTree = "<group>"; };
2621C9CC12EA009300711A30 /* EmulateInstruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EmulateInstruction.h; path = Utility/EmulateInstruction.h; sourceTree = "<group>"; };
2621C9CF12EA066500711A30 /* EmulateInstructionARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EmulateInstructionARM.h; path = Utility/EmulateInstructionARM.h; sourceTree = "<group>"; };
2621CA0A12EA107700711A30 /* EmulateInstruction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = EmulateInstruction.cpp; path = Utility/EmulateInstruction.cpp; sourceTree = "<group>"; };
263664921140A4930075843B /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Debugger.cpp; path = source/Core/Debugger.cpp; sourceTree = "<group>"; };
263664941140A4C10075843B /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Debugger.h; path = include/lldb/Core/Debugger.h; sourceTree = "<group>"; };
26368A3B126B697600E8659F /* darwin-debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "darwin-debug.cpp"; path = "tools/darwin-debug/darwin-debug.cpp"; sourceTree = "<group>"; };
@ -1601,6 +1609,10 @@
26B4666E11A2080F00CF6220 /* Utility */ = {
isa = PBXGroup;
children = (
2621C9CC12EA009300711A30 /* EmulateInstruction.h */,
2621CA0A12EA107700711A30 /* EmulateInstruction.cpp */,
2621C9CF12EA066500711A30 /* EmulateInstructionARM.h */,
2621C9CB12EA009300711A30 /* EmulateInstructionARM.cpp */,
AF68D32F1255A110002FF25B /* UnwindLLDB.cpp */,
AF68D3301255A110002FF25B /* UnwindLLDB.h */,
AF68D2541255416E002FF25B /* RegisterContextLLDB.cpp */,
@ -2299,6 +2311,8 @@
266A42D8128E40040090CF7C /* ClangNamespaceDecl.h in Headers */,
26E6902F129C6BD500DDECD9 /* ClangExternalASTSourceCallbacks.h in Headers */,
4C7CF7E41295E10E00B4FBB5 /* ThreadPlanCallUserExpression.h in Headers */,
2621C9CE12EA009300711A30 /* EmulateInstruction.h in Headers */,
2621C9D012EA066500711A30 /* EmulateInstructionARM.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2800,6 +2814,8 @@
26E69031129C6BEF00DDECD9 /* ClangExternalASTSourceCallbacks.cpp in Sources */,
4C7CF7E61295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp in Sources */,
B296983712C2FB98002D92C3 /* CommandObjectVersion.cpp in Sources */,
2621C9CD12EA009300711A30 /* EmulateInstructionARM.cpp in Sources */,
2621CA0B12EA107700711A30 /* EmulateInstruction.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -0,0 +1,98 @@
//===-- EmulateInstruction.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "EmulateInstruction.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/StreamString.h"
using namespace lldb;
using namespace lldb_private;
EmulateInstruction::EmulateInstruction
(
lldb::ByteOrder byte_order,
uint32_t addr_byte_size,
void *baton,
ReadMemory read_mem_callback,
WriteMemory write_mem_callback,
ReadRegister read_reg_callback,
WriteRegister write_reg_callback
) :
m_byte_order (lldb::eByteOrderHost),
m_addr_byte_size (sizeof (void *)),
m_baton (baton),
m_read_mem_callback (read_mem_callback),
m_write_mem_callback (write_mem_callback),
m_read_reg_callback (read_reg_callback),
m_write_reg_callback (write_reg_callback),
m_inst_pc (LLDB_INVALID_ADDRESS)
{
::bzero (&m_inst, sizeof (m_inst));
}
uint64_t
EmulateInstruction::ReadRegisterUnsigned (uint32_t reg_kind, uint32_t reg_num, uint64_t fail_value, bool *success_ptr)
{
uint64_t uval64 = 0;
bool success = m_read_reg_callback (m_baton, reg_kind, reg_num, uval64);
if (success_ptr)
*success_ptr = success;
if (!success)
uval64 = fail_value;
return uval64;
}
bool
EmulateInstruction::WriteRegisterUnsigned (const Context &context, uint32_t reg_kind, uint32_t reg_num, uint64_t reg_value)
{
return m_write_reg_callback (m_baton, context, reg_kind, reg_num, reg_value);
}
uint64_t
EmulateInstruction::ReadMemoryUnsigned (const Context &context, lldb::addr_t addr, size_t byte_size, uint64_t fail_value, bool *success_ptr)
{
uint64_t uval64 = 0;
bool success = false;
if (byte_size <= 8)
{
uint8_t buf[sizeof(uint64_t)];
size_t bytes_read = m_read_mem_callback (m_baton, context, addr, buf, byte_size);
if (bytes_read == byte_size)
{
uint32_t offset = 0;
DataExtractor data (buf, byte_size, m_byte_order, m_addr_byte_size);
uval64 = data.GetMaxU64 (&offset, byte_size);
success = true;
}
}
if (success_ptr)
*success_ptr = success;
if (!success)
uval64 = fail_value;
return uval64;
}
bool
EmulateInstruction::WriteMemoryUnsigned (const Context &context,
lldb::addr_t addr,
uint64_t uval,
size_t uval_byte_size)
{
StreamString strm(Stream::eBinary, GetAddressByteSize(), GetByteOrder());
strm.PutMaxHex64 (uval, uval_byte_size);
size_t bytes_written = m_write_mem_callback (m_baton, context, addr, strm.GetData(), uval_byte_size);
if (bytes_written == uval_byte_size)
return true;
return false;
}

View File

@ -0,0 +1,234 @@
//===-- EmulateInstruction.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef lldb_EmulateInstruction_h_
#define lldb_EmulateInstruction_h_
#include "lldb/lldb-include.h"
namespace lldb_private {
class EmulateInstruction
{
public:
enum ContextType
{
eContextInvalid = 0,
eContextReadOpcode,
eContextImmediate,
eContextPushRegisterOnStack,
eContextAdjustStackPointer,
eContextRegisterPlusOffset,
};
struct Context
{
ContextType type;
lldb::addr_t arg0;
lldb::addr_t arg1;
lldb::addr_t arg2;
};
union Opcode
{
uint8_t inst8;
uint16_t inst16;
uint32_t inst32;
uint64_t inst64;
union inst
{
uint8_t bytes[16];
uint8_t length;
};
};
enum OpcodeType
{
eOpcode8,
eOpcode16,
eOpcode32,
eOpcode64,
eOpcodeBytes,
};
struct Instruction
{
OpcodeType opcode_type;
Opcode opcode;
};
typedef size_t (*ReadMemory) (void *baton,
const Context &context,
lldb::addr_t addr,
void *dst,
size_t length);
typedef size_t (*WriteMemory) (void *baton,
const Context &context,
lldb::addr_t addr,
const void *dst,
size_t length);
typedef bool (*ReadRegister) (void *baton,
uint32_t reg_kind,
uint32_t reg_num,
uint64_t &reg_value);
typedef bool (*WriteRegister) (void *baton,
const Context &context,
uint32_t reg_kind,
uint32_t reg_num,
uint64_t reg_value);
EmulateInstruction (lldb::ByteOrder byte_order,
uint32_t addr_byte_size,
void *baton,
ReadMemory read_mem_callback,
WriteMemory write_mem_callback,
ReadRegister read_reg_callback,
WriteRegister write_reg_callback);
virtual ~EmulateInstruction()
{
}
virtual bool
ReadInstruction () = 0;
virtual bool
EvaluateInstruction () = 0;
// Create a mask that starts at bit zero and includes "bit"
static uint64_t
MaskUpToBit (const uint64_t bit)
{
return (1ull << (bit + 1ull)) - 1ull;
}
static bool
BitIsSet (const uint64_t value, const uint64_t bit)
{
return (value & (1ull << bit)) != 0;
}
static bool
BitIsClear (const uint64_t value, const uint64_t bit)
{
return (value & (1ull << bit)) == 0;
}
static int64_t
SignedBits (const uint64_t value, const uint64_t msbit, const uint64_t lsbit)
{
uint64_t result = UnsignedBits (value, msbit, lsbit);
if (BitIsSet(value, msbit))
{
// Sign extend
result |= ~MaskUpToBit (msbit - lsbit);
}
return result;
}
static uint64_t
UnsignedBits (const uint64_t value, const uint64_t msbit, const uint64_t lsbit)
{
uint64_t result = value >> lsbit;
result &= MaskUpToBit (msbit - lsbit);
return result;
}
uint64_t
ReadRegisterUnsigned (uint32_t reg_kind,
uint32_t reg_num,
uint64_t fail_value,
bool *success_ptr);
bool
WriteRegisterUnsigned (const Context &context,
uint32_t reg_kind,
uint32_t reg_num,
uint64_t reg_value);
uint64_t
ReadMemoryUnsigned (const Context &context,
lldb::addr_t addr,
size_t byte_size,
uint64_t fail_value,
bool *success_ptr);
bool
WriteMemoryUnsigned (const Context &context,
lldb::addr_t addr,
uint64_t uval,
size_t uval_byte_size);
static uint32_t
BitCount (uint64_t value)
{
uint32_t set_bit_count = 0;
while (value)
{
if (value & 1)
++set_bit_count;
value >>= 1;
}
return set_bit_count;
}
uint32_t
GetAddressByteSize () const
{
return m_addr_byte_size;
}
lldb::ByteOrder
GetByteOrder () const
{
return m_byte_order;
}
uint64_t
OpcodeAsUnsigned (bool *success_ptr)
{
if (success_ptr)
*success_ptr = true;
switch (m_inst.opcode_type)
{
eOpcode8: return m_inst.opcode.inst8;
eOpcode16: return m_inst.opcode.inst16;
eOpcode32: return m_inst.opcode.inst32;
eOpcode64: return m_inst.opcode.inst64;
eOpcodeBytes:
break;
}
if (success_ptr)
*success_ptr = false;
return 0;
}
protected:
lldb::ByteOrder m_byte_order;
uint32_t m_addr_byte_size;
void * m_baton;
ReadMemory m_read_mem_callback;
WriteMemory m_write_mem_callback;
ReadRegister m_read_reg_callback;
WriteRegister m_write_reg_callback;
lldb::addr_t m_inst_pc;
Instruction m_inst;
//------------------------------------------------------------------
// For EmulateInstruction only
//------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (EmulateInstruction);
};
} // namespace lldb_private
#endif // lldb_EmulateInstruction_h_

View File

@ -0,0 +1,299 @@
//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "EmulateInstructionARM.h"
using namespace lldb;
using namespace lldb_private;
// ARM constants used during decoding
#define REG_RD 0
#define LDM_REGLIST 1
#define PC_REG 15
#define PC_REGLIST_BIT 0x8000
// ARM conditions
#define COND_EQ 0x0
#define COND_NE 0x1
#define COND_CS 0x2
#define COND_HS 0x2
#define COND_CC 0x3
#define COND_LO 0x3
#define COND_MI 0x4
#define COND_PL 0x5
#define COND_VS 0x6
#define COND_VC 0x7
#define COND_HI 0x8
#define COND_LS 0x9
#define COND_GE 0xA
#define COND_LT 0xB
#define COND_GT 0xC
#define COND_LE 0xD
#define COND_AL 0xE
#define COND_UNCOND 0xF
#define MASK_CPSR_MODE_MASK (0x0000001fu)
#define MASK_CPSR_T (1u << 5)
#define MASK_CPSR_F (1u << 6)
#define MASK_CPSR_I (1u << 7)
#define MASK_CPSR_A (1u << 8)
#define MASK_CPSR_E (1u << 9)
#define MASK_CPSR_GE_MASK (0x000f0000u)
#define MASK_CPSR_J (1u << 24)
#define MASK_CPSR_Q (1u << 27)
#define MASK_CPSR_V (1u << 28)
#define MASK_CPSR_C (1u << 29)
#define MASK_CPSR_Z (1u << 30)
#define MASK_CPSR_N (1u << 31)
#define ARMv4 (1u << 0)
#define ARMv4T (1u << 1)
#define ARMv5T (1u << 2)
#define ARMv5TE (1u << 3)
#define ARMv5TEJ (1u << 4)
#define ARMv6 (1u << 5)
#define ARMv6K (1u << 6)
#define ARMv6T2 (1u << 7)
#define ARMv7 (1u << 8)
#define ARMv8 (1u << 8)
#define ARMvAll (0xffffffffu)
typedef bool (*EmulateCallback) (EmulateInstructionARM *emulator);
typedef enum ARMEncoding
{
eEncodingA1,
eEncodingA2,
eEncodingA3,
eEncodingA4,
eEncodingA5,
eEncodingT1,
eEncodingT2,
eEncodingT3,
eEncodingT4,
eEncodingT5,
} ARMEncoding;
typedef struct ARMOpcode
{
uint32_t mask;
uint32_t value;
uint32_t variants;
ARMEncoding encoding;
const char *name;
EmulateCallback callback;
};
static bool
EmulateARMPushEncodingA1 (EmulateInstructionARM *emulator)
{
#if 0
// ARM pseudo code...
if (ConditionPassed())
{
EncodingSpecificOperations();
NullCheckIfThumbEE(13);
address = SP - 4*BitCount(registers);
for (i = 0 to 14)
{
if (registers<i> == 1)
{
if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
MemA[address,4] = bits(32) UNKNOWN;
else
MemA[address,4] = R[i];
address = address + 4;
}
}
if (registers<15> == 1) // Only possible for encoding A1 or A2
MemA[address,4] = PCStoreValue();
SP = SP - 4*BitCount(registers);
}
#endif
bool success = false;
const uint32_t opcode = emulator->OpcodeAsUnsigned (&success);
if (!success)
return false;
if (emulator->ConditionPassed())
{
const uint32_t addr_byte_size = emulator->GetAddressByteSize();
const addr_t sp = emulator->ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
if (!success)
return false;
const uint32_t registers = EmulateInstruction::UnsignedBits (opcode, 15, 0);
addr_t sp_offset = addr_byte_size * EmulateInstruction::BitCount (registers);
addr_t addr = sp - sp_offset;
uint32_t i;
EmulateInstruction::Context context = { EmulateInstruction::eContextPushRegisterOnStack, eRegisterKindDWARF, 0, 0 };
for (i=0; i<15; ++i)
{
if (EmulateInstruction::BitIsSet (registers, 1u << i))
{
context.arg1 = dwarf_r0 + i; // arg1 in the context is the DWARF register number
context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
uint32_t reg_value = emulator->ReadRegisterUnsigned(eRegisterKindDWARF, context.arg1, 0, &success);
if (!success)
return false;
if (!emulator->WriteMemoryUnsigned (context, addr, reg_value, addr_byte_size))
return false;
addr += addr_byte_size;
}
}
if (EmulateInstruction::BitIsSet (registers, 1u << 15))
{
context.arg1 = dwarf_pc; // arg1 in the context is the DWARF register number
context.arg2 = addr - sp; // arg2 in the context is the stack pointer offset
const uint32_t pc = emulator->ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
if (!success)
return false;
if (!emulator->WriteMemoryUnsigned (context, addr, pc + 8, addr_byte_size))
return false;
}
context.type = EmulateInstruction::eContextAdjustStackPointer;
context.arg0 = eRegisterKindGeneric;
context.arg1 = LLDB_REGNUM_GENERIC_SP;
context.arg2 = sp_offset;
if (!emulator->WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
return false;
}
return true;
}
static ARMOpcode g_arm_opcodes[] =
{
{ 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, "PUSH<c> <registers>", EmulateARMPushEncodingA1 }
};
static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
bool
EmulateInstructionARM::ReadInstruction ()
{
bool success = false;
m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
if (success)
{
addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
if (success)
{
Context read_inst_context = {eContextReadOpcode, 0, 0};
if (m_inst_cpsr & MASK_CPSR_T)
{
m_inst_mode = eModeThumb;
uint32_t thumb_opcode = ReadMemoryUnsigned(read_inst_context, pc, 2, 0, &success);
if (success)
{
if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
{
m_inst.opcode_type = eOpcode16;
m_inst.opcode.inst16 = thumb_opcode;
}
else
{
m_inst.opcode_type = eOpcode32;
m_inst.opcode.inst32 = (thumb_opcode << 16) | ReadMemoryUnsigned(read_inst_context, pc + 2, 2, 0, &success);
}
}
}
else
{
m_inst_mode = eModeARM;
m_inst.opcode_type = eOpcode32;
m_inst.opcode.inst32 = ReadMemoryUnsigned(read_inst_context, pc, 4, 0, &success);
}
}
}
if (!success)
{
m_inst_mode = eModeInvalid;
m_inst_pc = LLDB_INVALID_ADDRESS;
}
return success;
}
uint32_t
EmulateInstructionARM::CurrentCond ()
{
switch (m_inst_mode)
{
default:
case eModeInvalid:
break;
case eModeARM:
return UnsignedBits(m_inst.opcode.inst32, 31, 28);
case eModeThumb:
return 0x0000000Eu; // Return always for now, we need to handl IT instructions later
}
return UINT32_MAX; // Return invalid value
}
bool
EmulateInstructionARM::ConditionPassed ()
{
if (m_inst_cpsr == 0)
return false;
const uint32_t cond = CurrentCond ();
if (cond == UINT32_MAX)
return false;
bool result = false;
switch (UnsignedBits(cond, 3, 1))
{
case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
case 5:
{
bool n = (m_inst_cpsr & MASK_CPSR_N);
bool v = (m_inst_cpsr & MASK_CPSR_V);
result = n == v;
}
break;
case 6:
{
bool n = (m_inst_cpsr & MASK_CPSR_N);
bool v = (m_inst_cpsr & MASK_CPSR_V);
result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
}
break;
case 7:
result = true;
break;
}
if (cond & 1)
result = !result;
return result;
}
bool
EmulateInstructionARM::EvaluateInstruction ()
{
return false;
}

View File

@ -0,0 +1,65 @@
//===-- lldb_EmulateInstructionARM.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef lldb_EmulateInstructionARM_h_
#define lldb_EmulateInstructionARM_h_
#include "EmulateInstruction.h"
#include "ARM_DWARF_Registers.h"
namespace lldb_private {
class EmulateInstructionARM : public EmulateInstruction
{
public:
enum Mode
{
eModeInvalid,
eModeARM,
eModeThumb
};
EmulateInstructionARM (void *baton,
ReadMemory read_mem_callback,
WriteMemory write_mem_callback,
ReadRegister read_reg_callback,
WriteRegister write_reg_callback) :
EmulateInstruction (lldb::eByteOrderLittle, // Byte order for ARM
4, // Address size in byte
baton,
read_mem_callback,
write_mem_callback,
read_reg_callback,
write_reg_callback),
m_inst_mode (eModeInvalid)
{
}
virtual bool
ReadInstruction ();
virtual bool
EvaluateInstruction ();
bool
ConditionPassed ();
uint32_t
CurrentCond ();
protected:
Mode m_inst_mode;
uint32_t m_inst_cpsr;
};
} // namespace lldb_private
#endif // lldb_EmulateInstructionARM_h_