diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 |
commit | 14f1b3e8826ce43b978db93a62d1166055db5394 (patch) | |
tree | 0a00ad8d3498783fe0193f3b656bca17c4c8697d /source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp | |
parent | 4ee8c119c71a06dcad1e0fecc8c675e480e59337 (diff) | |
download | src-14f1b3e8826ce43b978db93a62d1166055db5394.tar.gz src-14f1b3e8826ce43b978db93a62d1166055db5394.zip |
Vendor import of lldb trunk r290819:vendor/lldb/lldb-trunk-r290819
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=311128
svn path=/vendor/lldb/lldb-trunk-r290819/; revision=311129; tag=vendor/lldb/lldb-trunk-r290819
Diffstat (limited to 'source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp')
-rw-r--r-- | source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp | 1896 |
1 files changed, 983 insertions, 913 deletions
diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index ea67928280d3..43f23097c0d9 100644 --- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -1,4 +1,4 @@ -//===-- EmulateInstructionARM64.cpp -------------------------------*- C++ -*-===// +//===-- EmulateInstructionARM64.cpp ------------------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // @@ -11,8 +11,8 @@ #include <stdlib.h> -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Address.h" +#include "lldb/Core/ArchSpec.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Stream.h" @@ -20,7 +20,24 @@ #include "Plugins/Process/Utility/ARMDefines.h" #include "Plugins/Process/Utility/ARMUtils.h" -#include "Utility/ARM64_DWARF_Registers.h" +#include "Plugins/Process/Utility/lldb-arm64-register-enums.h" + +#define GPR_OFFSET(idx) ((idx)*8) +#define GPR_OFFSET_NAME(reg) 0 +#define FPU_OFFSET(idx) ((idx)*16) +#define FPU_OFFSET_NAME(reg) 0 +#define EXC_OFFSET_NAME(reg) 0 +#define DBG_OFFSET_NAME(reg) 0 +#define DBG_OFFSET_NAME(reg) 0 +#define DEFINE_DBG(re, y) \ + "na", nullptr, 8, 0, lldb::eEncodingUint, lldb::eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, \ + nullptr, nullptr, nullptr, 0 + +#define DECLARE_REGISTER_INFOS_ARM64_STRUCT + +#include "Plugins/Process/Utility/RegisterInfos_arm64.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/MathExtras.h" // for SignExtend32 template function @@ -31,15 +48,22 @@ using namespace lldb; using namespace lldb_private; -#define No_VFP 0 -#define VFPv1 (1u << 1) -#define VFPv2 (1u << 2) -#define VFPv3 (1u << 3) +static bool LLDBTableGetRegisterInfo(uint32_t reg_num, RegisterInfo ®_info) { + if (reg_num >= llvm::array_lengthof(g_register_infos_arm64_le)) + return false; + reg_info = g_register_infos_arm64_le[reg_num]; + return true; +} + +#define No_VFP 0 +#define VFPv1 (1u << 1) +#define VFPv2 (1u << 2) +#define VFPv3 (1u << 3) #define AdvancedSIMD (1u << 4) #define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD) #define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD) -#define VFPv2v3 (VFPv2 | VFPv3) +#define VFPv2v3 (VFPv2 | VFPv3) #define UInt(x) ((uint64_t)x) #define SInt(x) ((int64_t)x) @@ -47,17 +71,9 @@ using namespace lldb_private; #define boolean bool #define integer int64_t -static inline bool -IsZero(uint64_t x) -{ - return x == 0; -} +static inline bool IsZero(uint64_t x) { return x == 0; } -static inline uint64_t -NOT(uint64_t x) -{ - return ~x; -} +static inline uint64_t NOT(uint64_t x) { return ~x; } #if 0 // LSL_C() @@ -75,354 +91,435 @@ LSL_C (uint64_t x, integer shift, bool &carry_out) // LSL() // ===== -static inline uint64_t -LSL(uint64_t x, integer shift) -{ - if (shift == 0) - return x; - return x << shift; +static inline uint64_t LSL(uint64_t x, integer shift) { + if (shift == 0) + return x; + return x << shift; } // AddWithCarry() // =============== static inline uint64_t -AddWithCarry (uint32_t N, uint64_t x, uint64_t y, bit carry_in, EmulateInstructionARM64::ProcState &proc_state) -{ - uint64_t unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in); - int64_t signed_sum = SInt(x) + SInt(y) + UInt(carry_in); - uint64_t result = unsigned_sum; - if (N < 64) - result = Bits64 (result, N-1, 0); - proc_state.N = Bit64(result, N-1); - proc_state.Z = IsZero(result); - proc_state.C = UInt(result) == unsigned_sum; - proc_state.V = SInt(result) == signed_sum; - return result; +AddWithCarry(uint32_t N, uint64_t x, uint64_t y, bit carry_in, + EmulateInstructionARM64::ProcState &proc_state) { + uint64_t unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in); + int64_t signed_sum = SInt(x) + SInt(y) + UInt(carry_in); + uint64_t result = unsigned_sum; + if (N < 64) + result = Bits64(result, N - 1, 0); + proc_state.N = Bit64(result, N - 1); + proc_state.Z = IsZero(result); + proc_state.C = UInt(result) == unsigned_sum; + proc_state.V = SInt(result) == signed_sum; + return result; } // ConstrainUnpredictable() // ======================== EmulateInstructionARM64::ConstraintType -ConstrainUnpredictable (EmulateInstructionARM64::Unpredictable which) -{ - EmulateInstructionARM64::ConstraintType result = EmulateInstructionARM64::Constraint_UNKNOWN; - switch (which) - { - case EmulateInstructionARM64::Unpredictable_WBOVERLAP: - case EmulateInstructionARM64::Unpredictable_LDPOVERLAP: - // TODO: don't know what to really do here? Pseudo code says: - // set result to one of above Constraint behaviours or UNDEFINED - break; - } - return result; +ConstrainUnpredictable(EmulateInstructionARM64::Unpredictable which) { + EmulateInstructionARM64::ConstraintType result = + EmulateInstructionARM64::Constraint_UNKNOWN; + switch (which) { + case EmulateInstructionARM64::Unpredictable_WBOVERLAP: + case EmulateInstructionARM64::Unpredictable_LDPOVERLAP: + // TODO: don't know what to really do here? Pseudo code says: + // set result to one of above Constraint behaviours or UNDEFINED + break; + } + return result; } - - //---------------------------------------------------------------------- // // EmulateInstructionARM implementation // //---------------------------------------------------------------------- -void -EmulateInstructionARM64::Initialize () -{ - PluginManager::RegisterPlugin (GetPluginNameStatic (), - GetPluginDescriptionStatic (), - CreateInstance); +void EmulateInstructionARM64::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); } -void -EmulateInstructionARM64::Terminate () -{ - PluginManager::UnregisterPlugin (CreateInstance); +void EmulateInstructionARM64::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); } -ConstString -EmulateInstructionARM64::GetPluginNameStatic () -{ - ConstString g_plugin_name ("lldb.emulate-instruction.arm64"); - return g_plugin_name; +ConstString EmulateInstructionARM64::GetPluginNameStatic() { + ConstString g_plugin_name("lldb.emulate-instruction.arm64"); + return g_plugin_name; } -lldb_private::ConstString -EmulateInstructionARM64::GetPluginName() -{ - static ConstString g_plugin_name ("EmulateInstructionARM64"); - return g_plugin_name; +lldb_private::ConstString EmulateInstructionARM64::GetPluginName() { + static ConstString g_plugin_name("EmulateInstructionARM64"); + return g_plugin_name; } -const char * -EmulateInstructionARM64::GetPluginDescriptionStatic () -{ - return "Emulate instructions for the ARM64 architecture."; +const char *EmulateInstructionARM64::GetPluginDescriptionStatic() { + return "Emulate instructions for the ARM64 architecture."; } EmulateInstruction * -EmulateInstructionARM64::CreateInstance (const ArchSpec &arch, InstructionType inst_type) -{ - if (EmulateInstructionARM64::SupportsEmulatingInstructionsOfTypeStatic(inst_type)) - { - if (arch.GetTriple().getArch() == llvm::Triple::aarch64) - { - std::auto_ptr<EmulateInstructionARM64> emulate_insn_ap (new EmulateInstructionARM64 (arch)); - if (emulate_insn_ap.get()) - return emulate_insn_ap.release(); - } +EmulateInstructionARM64::CreateInstance(const ArchSpec &arch, + InstructionType inst_type) { + if (EmulateInstructionARM64::SupportsEmulatingInstructionsOfTypeStatic( + inst_type)) { + if (arch.GetTriple().getArch() == llvm::Triple::aarch64) { + std::auto_ptr<EmulateInstructionARM64> emulate_insn_ap( + new EmulateInstructionARM64(arch)); + if (emulate_insn_ap.get()) + return emulate_insn_ap.release(); } - - return NULL; + } + + return NULL; } -bool -EmulateInstructionARM64::SetTargetTriple (const ArchSpec &arch) -{ - if (arch.GetTriple().getArch () == llvm::Triple::arm) - return true; - else if (arch.GetTriple().getArch () == llvm::Triple::thumb) - return true; +bool EmulateInstructionARM64::SetTargetTriple(const ArchSpec &arch) { + if (arch.GetTriple().getArch() == llvm::Triple::arm) + return true; + else if (arch.GetTriple().getArch() == llvm::Triple::thumb) + return true; - return false; + return false; } -bool -EmulateInstructionARM64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info) -{ - if (reg_kind == eRegisterKindGeneric) - { - switch (reg_num) - { - case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::pc; break; - case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::sp; break; - case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::fp; break; - case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::lr; break; - case LLDB_REGNUM_GENERIC_FLAGS: - // There is no DWARF register number for the CPSR right now... - reg_info.name = "cpsr"; - reg_info.alt_name = NULL; - reg_info.byte_size = 4; - reg_info.byte_offset = 0; - reg_info.encoding = eEncodingUint; - reg_info.format = eFormatHex; - for (uint32_t i=0; i<lldb::kNumRegisterKinds; ++i) - reg_info.kinds[reg_kind] = LLDB_INVALID_REGNUM; - reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; - return true; - - default: return false; - } +bool EmulateInstructionARM64::GetRegisterInfo(RegisterKind reg_kind, + uint32_t reg_num, + RegisterInfo ®_info) { + if (reg_kind == eRegisterKindGeneric) { + switch (reg_num) { + case LLDB_REGNUM_GENERIC_PC: + reg_kind = eRegisterKindLLDB; + reg_num = gpr_pc_arm64; + break; + case LLDB_REGNUM_GENERIC_SP: + reg_kind = eRegisterKindLLDB; + reg_num = gpr_sp_arm64; + break; + case LLDB_REGNUM_GENERIC_FP: + reg_kind = eRegisterKindLLDB; + reg_num = gpr_fp_arm64; + break; + case LLDB_REGNUM_GENERIC_RA: + reg_kind = eRegisterKindLLDB; + reg_num = gpr_lr_arm64; + break; + case LLDB_REGNUM_GENERIC_FLAGS: + reg_kind = eRegisterKindLLDB; + reg_num = gpr_cpsr_arm64; + break; + + default: + return false; } - - if (reg_kind == eRegisterKindDWARF) - return arm64_dwarf::GetRegisterInfo(reg_num, reg_info); - return false; + } + + if (reg_kind == eRegisterKindLLDB) + return LLDBTableGetRegisterInfo(reg_num, reg_info); + return false; } -EmulateInstructionARM64::Opcode* -EmulateInstructionARM64::GetOpcodeForInstruction (const uint32_t opcode) -{ - static EmulateInstructionARM64::Opcode - g_opcodes[] = - { - //---------------------------------------------------------------------- - // Prologue instructions - //---------------------------------------------------------------------- - - // push register(s) - { 0xff000000, 0xd1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUB <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" }, - { 0xff000000, 0xf1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUBS <Xd>, <Xn|SP>, #<imm> {, <shift>}" }, - { 0xff000000, 0x91000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADD <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" }, - { 0xff000000, 0xb1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADDS <Xd>, <Xn|SP>, #<imm> {, <shift>}" }, - - { 0xff000000, 0x51000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUB <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" }, - { 0xff000000, 0x71000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" }, - { 0xff000000, 0x11000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADD <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" }, - { 0xff000000, 0x31000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADDS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" }, - - { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <St>, <St2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" }, - - { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, - - { 0xffc00000, 0x28800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xa8800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x2c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x6c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xac800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, - - { 0xffc00000, 0x29400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0xa9400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0x2d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <St>, <St2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0x6d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0xad400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" }, - - { 0xffc00000, 0x29c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xa9c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x2dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x6dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xadc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, - - { 0xffc00000, 0x28c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xa8c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x2cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x6cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xacc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, - - { 0xffe00c00, 0xb8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "STR <Wt>, [<Xn|SP>], #<simm>" }, - { 0xffe00c00, 0xf8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "STR <Xt>, [<Xn|SP>], #<simm>" }, - { 0xffe00c00, 0xb8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "STR <Wt>, [<Xn|SP>, #<simm>]!" }, - { 0xffe00c00, 0xf8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "STR <Xt>, [<Xn|SP>, #<simm>]!" }, - { 0xffc00000, 0xb9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "STR <Wt>, [<Xn|SP>{, #<pimm>}]" }, - { 0xffc00000, 0xf9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "STR <Xt>, [<Xn|SP>{, #<pimm>}]" }, - - { 0xffe00c00, 0xb8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "LDR <Wt>, [<Xn|SP>], #<simm>" }, - { 0xffe00c00, 0xf8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "LDR <Xt>, [<Xn|SP>], #<simm>" }, - { 0xffe00c00, 0xb8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "LDR <Wt>, [<Xn|SP>, #<simm>]!" }, - { 0xffe00c00, 0xf8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "LDR <Xt>, [<Xn|SP>, #<simm>]!" }, - { 0xffc00000, 0xb9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "LDR <Wt>, [<Xn|SP>{, #<pimm>}]" }, - { 0xffc00000, 0xf9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "LDR <Xt>, [<Xn|SP>{, #<pimm>}]" }, - - { 0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB, "B <label>" }, - { 0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond, "B.<cond> <label>" }, - { 0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBZ <Wt>, <label>" }, - { 0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBNZ <Wt>, <label>" }, - { 0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBZ <R><t>, #<imm>, <label>" }, - { 0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBNZ <R><t>, #<imm>, <label>" }, - - }; - static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_opcodes); - - for (size_t i=0; i<k_num_arm_opcodes; ++i) - { - if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value) - return &g_opcodes[i]; - } - return nullptr; +EmulateInstructionARM64::Opcode * +EmulateInstructionARM64::GetOpcodeForInstruction(const uint32_t opcode) { + static EmulateInstructionARM64::Opcode g_opcodes[] = { + //---------------------------------------------------------------------- + // Prologue instructions + //---------------------------------------------------------------------- + + // push register(s) + {0xff000000, 0xd1000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "SUB <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}"}, + {0xff000000, 0xf1000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "SUBS <Xd>, <Xn|SP>, #<imm> {, <shift>}"}, + {0xff000000, 0x91000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "ADD <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}"}, + {0xff000000, 0xb1000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "ADDS <Xd>, <Xn|SP>, #<imm> {, <shift>}"}, + + {0xff000000, 0x51000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "SUB <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}"}, + {0xff000000, 0x71000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}"}, + {0xff000000, 0x11000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "ADD <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}"}, + {0xff000000, 0x31000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "ADDS <Wd>, <Wn|WSP>, #<imm> {, <shift>}"}, + + {0xffc00000, 0x29000000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "STP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0xa9000000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "STP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0x2d000000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "STP <St>, <St2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0x6d000000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "STP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0xad000000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "STP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]"}, + + {0xffc00000, 0x29800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xa9800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x2d800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "STP <St>, <St2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x6d800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xad800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"}, + + {0xffc00000, 0x28800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xa8800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x2c800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "STP <St>, <St2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x6c800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xac800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"}, + + {0xffc00000, 0x29400000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "LDP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0xa9400000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "LDP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0x2d400000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "LDP <St>, <St2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0x6d400000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "LDP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0xad400000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "LDP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]"}, + + {0xffc00000, 0x29c00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xa9c00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x2dc00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x6dc00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xadc00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"}, + + {0xffc00000, 0x28c00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xa8c00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x2cc00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x6cc00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xacc00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"}, + + {0xffe00c00, 0xb8000400, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, + "STR <Wt>, [<Xn|SP>], #<simm>"}, + {0xffe00c00, 0xf8000400, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, + "STR <Xt>, [<Xn|SP>], #<simm>"}, + {0xffe00c00, 0xb8000c00, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, + "STR <Wt>, [<Xn|SP>, #<simm>]!"}, + {0xffe00c00, 0xf8000c00, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, + "STR <Xt>, [<Xn|SP>, #<simm>]!"}, + {0xffc00000, 0xb9000000, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, + "STR <Wt>, [<Xn|SP>{, #<pimm>}]"}, + {0xffc00000, 0xf9000000, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, + "STR <Xt>, [<Xn|SP>{, #<pimm>}]"}, + + {0xffe00c00, 0xb8400400, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, + "LDR <Wt>, [<Xn|SP>], #<simm>"}, + {0xffe00c00, 0xf8400400, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, + "LDR <Xt>, [<Xn|SP>], #<simm>"}, + {0xffe00c00, 0xb8400c00, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, + "LDR <Wt>, [<Xn|SP>, #<simm>]!"}, + {0xffe00c00, 0xf8400c00, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, + "LDR <Xt>, [<Xn|SP>, #<simm>]!"}, + {0xffc00000, 0xb9400000, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, + "LDR <Wt>, [<Xn|SP>{, #<pimm>}]"}, + {0xffc00000, 0xf9400000, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, + "LDR <Xt>, [<Xn|SP>{, #<pimm>}]"}, + + {0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB, + "B <label>"}, + {0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond, + "B.<cond> <label>"}, + {0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, + "CBZ <Wt>, <label>"}, + {0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, + "CBNZ <Wt>, <label>"}, + {0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, + "TBZ <R><t>, #<imm>, <label>"}, + {0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, + "TBNZ <R><t>, #<imm>, <label>"}, + + }; + static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_opcodes); + + for (size_t i = 0; i < k_num_arm_opcodes; ++i) { + if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value) + return &g_opcodes[i]; + } + return nullptr; } -bool -EmulateInstructionARM64::ReadInstruction () -{ - bool success = false; - m_addr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); - if (success) - { - Context read_inst_context; - read_inst_context.type = eContextReadOpcode; - read_inst_context.SetNoArgs (); - m_opcode.SetOpcode32 (ReadMemoryUnsigned (read_inst_context, m_addr, 4, 0, &success), GetByteOrder()); - } - if (!success) - m_addr = LLDB_INVALID_ADDRESS; - return success; +bool EmulateInstructionARM64::ReadInstruction() { + bool success = false; + m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, + LLDB_INVALID_ADDRESS, &success); + if (success) { + Context read_inst_context; + read_inst_context.type = eContextReadOpcode; + read_inst_context.SetNoArgs(); + m_opcode.SetOpcode32( + ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success), + GetByteOrder()); + } + if (!success) + m_addr = LLDB_INVALID_ADDRESS; + return success; } +bool EmulateInstructionARM64::EvaluateInstruction(uint32_t evaluate_options) { + const uint32_t opcode = m_opcode.GetOpcode32(); + Opcode *opcode_data = GetOpcodeForInstruction(opcode); + if (opcode_data == NULL) + return false; -bool -EmulateInstructionARM64::EvaluateInstruction (uint32_t evaluate_options) -{ - const uint32_t opcode = m_opcode.GetOpcode32(); - Opcode *opcode_data = GetOpcodeForInstruction(opcode); - if (opcode_data == NULL) - return false; - - //printf ("opcode template for 0x%8.8x: %s\n", opcode, opcode_data->name); - 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) -// { -// m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, // use eRegisterKindDWARF is we ever get a cpsr DWARF register number -// LLDB_REGNUM_GENERIC_FLAGS, // use arm64_dwarf::cpsr if we ever get one -// 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; - - uint32_t orig_pc_value = 0; - if (auto_advance_pc) - { - orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::pc, 0, &success); - if (!success) - return false; - } - - // Call the Emulate... function. - success = (this->*opcode_data->callback) (opcode); + // printf ("opcode template for 0x%8.8x: %s\n", opcode, opcode_data->name); + 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) + // { + // m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindLLDB, + // gpr_cpsr_arm64, + // 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; + + uint32_t orig_pc_value = 0; + if (auto_advance_pc) { + orig_pc_value = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success); if (!success) + return false; + } + + // Call the Emulate... function. + success = (this->*opcode_data->callback)(opcode); + if (!success) + return false; + + if (auto_advance_pc) { + uint32_t new_pc_value = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success); + if (!success) + return false; + + if (auto_advance_pc && (new_pc_value == orig_pc_value)) { + EmulateInstruction::Context context; + context.type = eContextAdvancePC; + context.SetNoArgs(); + if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_pc_arm64, + orig_pc_value + 4)) return false; - - if (auto_advance_pc) - { - uint32_t new_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::pc, 0, &success); - if (!success) - return false; - - if (auto_advance_pc && (new_pc_value == orig_pc_value)) - { - EmulateInstruction::Context context; - context.type = eContextAdvancePC; - context.SetNoArgs(); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, arm64_dwarf::pc, orig_pc_value + 4)) - return false; - } } - return true; + } + return true; } -bool -EmulateInstructionARM64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) -{ - unwind_plan.Clear(); - unwind_plan.SetRegisterKind (eRegisterKindDWARF); +bool EmulateInstructionARM64::CreateFunctionEntryUnwind( + UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindLLDB); - UnwindPlan::RowSP row(new UnwindPlan::Row); + UnwindPlan::RowSP row(new UnwindPlan::Row); - // Our previous Call Frame Address is the stack pointer - row->GetCFAValue().SetIsRegisterPlusOffset(arm64_dwarf::sp, 0); + // Our previous Call Frame Address is the stack pointer + row->GetCFAValue().SetIsRegisterPlusOffset(gpr_sp_arm64, 0); - unwind_plan.AppendRow (row); - unwind_plan.SetSourceName ("EmulateInstructionARM64"); - unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); - unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); - unwind_plan.SetReturnAddressRegister (arm64_dwarf::lr); - return true; + unwind_plan.AppendRow(row); + unwind_plan.SetSourceName("EmulateInstructionARM64"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetReturnAddressRegister(gpr_lr_arm64); + return true; } -uint32_t -EmulateInstructionARM64::GetFramePointerRegisterNumber () const -{ - if (m_arch.GetTriple().isAndroid()) - return LLDB_INVALID_REGNUM; // Don't use frame pointer on android +uint32_t EmulateInstructionARM64::GetFramePointerRegisterNumber() const { + if (m_arch.GetTriple().isAndroid()) + return LLDB_INVALID_REGNUM; // Don't use frame pointer on android - return arm64_dwarf::sp; + return gpr_fp_arm64; } -bool -EmulateInstructionARM64::UsingAArch32() -{ - bool aarch32 = m_opcode_pstate.RW == 1; - // if !HaveAnyAArch32() then assert !aarch32; - // if HighestELUsingAArch32() then assert aarch32; - return aarch32; +bool EmulateInstructionARM64::UsingAArch32() { + bool aarch32 = m_opcode_pstate.RW == 1; + // if !HaveAnyAArch32() then assert !aarch32; + // if HighestELUsingAArch32() then assert aarch32; + return aarch32; } -bool -EmulateInstructionARM64::BranchTo (const Context &context, uint32_t N, addr_t target) -{ +bool EmulateInstructionARM64::BranchTo(const Context &context, uint32_t N, + addr_t target) { #if 0 // Set program counter to a new address, with a branch reason hint // for possible use by hardware fetching the next instruction. @@ -450,603 +547,578 @@ EmulateInstructionARM64::BranchTo (const Context &context, uint32_t N, addr_t ta return; #endif - addr_t addr; + addr_t addr; + + // Hint_Branch(branch_type); + if (N == 32) { + if (!UsingAArch32()) + return false; + addr = target; + } else if (N == 64) { + if (UsingAArch32()) + return false; + // TODO: Remove the tag bits from a tagged target + addr = target; + } else + return false; - //Hint_Branch(branch_type); - if (N == 32) - { - if (!UsingAArch32()) - return false; - addr = target; - } - else if (N == 64) - { - if (UsingAArch32()) - return false; - // TODO: Remove the tag bits from a tagged target - addr = target; - } - else - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC, addr)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, addr)) - return false; + return true; +} +bool EmulateInstructionARM64::ConditionHolds(const uint32_t cond) { + // 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; -} -bool -EmulateInstructionARM64::ConditionHolds (const uint32_t cond) -{ - // 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; - - bool result = false; - switch (UnsignedBits(cond, 3, 1)) - { - case 0: - result = (m_opcode_pstate.Z == 1); - break; - case 1: - result = (m_opcode_pstate.C == 1); - break; - case 2: - result = (m_opcode_pstate.N == 1); - break; - case 3: - result = (m_opcode_pstate.V == 1); - break; - case 4: - result = (m_opcode_pstate.C == 1 && m_opcode_pstate.Z == 0); - break; - case 5: - result = (m_opcode_pstate.N == m_opcode_pstate.V); - break; - case 6: - result = (m_opcode_pstate.N == m_opcode_pstate.V && m_opcode_pstate.Z == 0); - break; - case 7: - // Always execute (cond == 0b1110, or the special 0b1111 which gives - // opcodes different meanings, but always means execution happens. - return true; - } + bool result = false; + switch (UnsignedBits(cond, 3, 1)) { + case 0: + result = (m_opcode_pstate.Z == 1); + break; + case 1: + result = (m_opcode_pstate.C == 1); + break; + case 2: + result = (m_opcode_pstate.N == 1); + break; + case 3: + result = (m_opcode_pstate.V == 1); + break; + case 4: + result = (m_opcode_pstate.C == 1 && m_opcode_pstate.Z == 0); + break; + case 5: + result = (m_opcode_pstate.N == m_opcode_pstate.V); + break; + case 6: + result = (m_opcode_pstate.N == m_opcode_pstate.V && m_opcode_pstate.Z == 0); + break; + case 7: + // Always execute (cond == 0b1110, or the special 0b1111 which gives + // opcodes different meanings, but always means execution happens. + return true; + } - if (cond & 1) - result = !result; - return result; + if (cond & 1) + result = !result; + return result; } -bool -EmulateInstructionARM64::EmulateADDSUBImm (const uint32_t opcode) -{ - // integer d = UInt(Rd); - // integer n = UInt(Rn); - // integer datasize = if sf == 1 then 64 else 32; - // boolean sub_op = (op == 1); - // boolean setflags = (S == 1); - // bits(datasize) imm; - // - // case shift of - // when '00' imm = ZeroExtend(imm12, datasize); - // when '01' imm = ZeroExtend(imm12 : Zeros(12), datasize); - // when '1x' UNDEFINED; - // - // - // bits(datasize) result; - // bits(datasize) operand1 = if n == 31 then SP[] else X[n]; - // bits(datasize) operand2 = imm; - // bits(4) nzcv; - // bit carry_in; - // - // if sub_op then - // operand2 = NOT(operand2); - // carry_in = 1; - // else - // carry_in = 0; - // - // (result, nzcv) = AddWithCarry(operand1, operand2, carry_in); - // - // if setflags then - // PSTATE.NZCV = nzcv; - // - // if d == 31 && !setflags then - // SP[] = result; - // else - // X[d] = result; - - const uint32_t sf = Bit32(opcode, 31); - const uint32_t op = Bit32(opcode, 30); - const uint32_t S = Bit32(opcode, 29); - const uint32_t shift = Bits32(opcode, 23, 22); - const uint32_t imm12 = Bits32(opcode, 21, 10); - const uint32_t Rn = Bits32(opcode, 9, 5); - const uint32_t Rd = Bits32(opcode, 4, 0); - - bool success = false; - - const uint32_t d = UInt(Rd); - const uint32_t n = UInt(Rn); - const uint32_t datasize = (sf == 1) ? 64 : 32; - boolean sub_op = op == 1; - boolean setflags = S == 1; - uint64_t imm; - - switch (shift) - { - case 0: imm = imm12; break; - case 1: imm = imm12 << 12; break; - default: return false; // UNDEFINED; - } - uint64_t result; - uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, &success); - uint64_t operand2 = imm; - bit carry_in; - - if (sub_op) - { - operand2 = NOT(operand2); - carry_in = 1; - imm = -imm; // For the Register plug offset context below - } - else - { - carry_in = 0; - } - - ProcState proc_state; - - result = AddWithCarry (datasize, operand1, operand2, carry_in, proc_state); +bool EmulateInstructionARM64::EmulateADDSUBImm(const uint32_t opcode) { + // integer d = UInt(Rd); + // integer n = UInt(Rn); + // integer datasize = if sf == 1 then 64 else 32; + // boolean sub_op = (op == 1); + // boolean setflags = (S == 1); + // bits(datasize) imm; + // + // case shift of + // when '00' imm = ZeroExtend(imm12, datasize); + // when '01' imm = ZeroExtend(imm12 : Zeros(12), datasize); + // when '1x' UNDEFINED; + // + // + // bits(datasize) result; + // bits(datasize) operand1 = if n == 31 then SP[] else X[n]; + // bits(datasize) operand2 = imm; + // bits(4) nzcv; + // bit carry_in; + // + // if sub_op then + // operand2 = NOT(operand2); + // carry_in = 1; + // else + // carry_in = 0; + // + // (result, nzcv) = AddWithCarry(operand1, operand2, carry_in); + // + // if setflags then + // PSTATE.NZCV = nzcv; + // + // if d == 31 && !setflags then + // SP[] = result; + // else + // X[d] = result; + + const uint32_t sf = Bit32(opcode, 31); + const uint32_t op = Bit32(opcode, 30); + const uint32_t S = Bit32(opcode, 29); + const uint32_t shift = Bits32(opcode, 23, 22); + const uint32_t imm12 = Bits32(opcode, 21, 10); + const uint32_t Rn = Bits32(opcode, 9, 5); + const uint32_t Rd = Bits32(opcode, 4, 0); + + bool success = false; + + const uint32_t d = UInt(Rd); + const uint32_t n = UInt(Rn); + const uint32_t datasize = (sf == 1) ? 64 : 32; + boolean sub_op = op == 1; + boolean setflags = S == 1; + uint64_t imm; + + switch (shift) { + case 0: + imm = imm12; + break; + case 1: + imm = imm12 << 12; + break; + default: + return false; // UNDEFINED; + } + uint64_t result; + uint64_t operand1 = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success); + uint64_t operand2 = imm; + bit carry_in; + + if (sub_op) { + operand2 = NOT(operand2); + carry_in = 1; + imm = -imm; // For the Register plug offset context below + } else { + carry_in = 0; + } + + ProcState proc_state; + + result = AddWithCarry(datasize, operand1, operand2, carry_in, proc_state); + + if (setflags) { + m_emulated_pstate.N = proc_state.N; + m_emulated_pstate.Z = proc_state.Z; + m_emulated_pstate.C = proc_state.C; + m_emulated_pstate.V = proc_state.V; + } + + Context context; + RegisterInfo reg_info_Rn; + if (GetRegisterInfo(eRegisterKindLLDB, n, reg_info_Rn)) + context.SetRegisterPlusOffset(reg_info_Rn, imm); + + if (n == GetFramePointerRegisterNumber() && d == gpr_sp_arm64 && !setflags) { + // 'mov sp, fp' - common epilogue instruction, CFA is now in terms + // of the stack pointer, instead of frame pointer. + context.type = EmulateInstruction::eContextRestoreStackPointer; + } else if ((n == gpr_sp_arm64 || n == GetFramePointerRegisterNumber()) && + d == gpr_sp_arm64 && !setflags) { + context.type = EmulateInstruction::eContextAdjustStackPointer; + } else if (d == GetFramePointerRegisterNumber() && n == gpr_sp_arm64 && + !setflags) { + context.type = EmulateInstruction::eContextSetFramePointer; + } else { + context.type = EmulateInstruction::eContextImmediate; + } + + // If setflags && d == gpr_sp_arm64 then d = WZR/XZR. See CMN, CMP + if (!setflags || d != gpr_sp_arm64) + WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_x0_arm64 + d, result); + + return false; +} - if (setflags) - { - m_emulated_pstate.N = proc_state.N; - m_emulated_pstate.Z = proc_state.Z; - m_emulated_pstate.C = proc_state.C; - m_emulated_pstate.V = proc_state.V; +template <EmulateInstructionARM64::AddrMode a_mode> +bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) { + uint32_t opc = Bits32(opcode, 31, 30); + uint32_t V = Bit32(opcode, 26); + uint32_t L = Bit32(opcode, 22); + uint32_t imm7 = Bits32(opcode, 21, 15); + uint32_t Rt2 = Bits32(opcode, 14, 10); + uint32_t Rn = Bits32(opcode, 9, 5); + uint32_t Rt = Bits32(opcode, 4, 0); + + integer n = UInt(Rn); + integer t = UInt(Rt); + integer t2 = UInt(Rt2); + uint64_t idx; + + MemOp memop = L == 1 ? MemOp_LOAD : MemOp_STORE; + boolean vector = (V == 1); + // AccType acctype = AccType_NORMAL; + boolean is_signed = false; + boolean wback = a_mode != AddrMode_OFF; + boolean wb_unknown = false; + boolean rt_unknown = false; + integer scale; + integer size; + + if (opc == 3) + return false; // UNDEFINED + + if (vector) { + scale = 2 + UInt(opc); + } else { + scale = (opc & 2) ? 3 : 2; + is_signed = (opc & 1) != 0; + if (is_signed && memop == MemOp_STORE) + return false; // UNDEFINED + } + + if (!vector && wback && ((t == n) || (t2 == n))) { + switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) { + case Constraint_UNKNOWN: + wb_unknown = true; // writeback is UNKNOWN + break; + + case Constraint_SUPPRESSWB: + wback = false; // writeback is suppressed + break; + + case Constraint_NOP: + memop = MemOp_NOP; // do nothing + wback = false; + break; + + case Constraint_NONE: + break; } - - Context context; - RegisterInfo reg_info_Rn; - if (arm64_dwarf::GetRegisterInfo (n, reg_info_Rn)) - context.SetRegisterPlusOffset (reg_info_Rn, imm); + } - if ((n == arm64_dwarf::sp || n == GetFramePointerRegisterNumber()) && - d == arm64_dwarf::sp && - !setflags) - { - context.type = EmulateInstruction::eContextAdjustStackPointer; - } - else if (d == GetFramePointerRegisterNumber() && - n == arm64_dwarf::sp && - !setflags) - { - context.type = EmulateInstruction::eContextSetFramePointer; - } - else - { - context.type = EmulateInstruction::eContextImmediate; + if (memop == MemOp_LOAD && t == t2) { + switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) { + case Constraint_UNKNOWN: + rt_unknown = true; // result is UNKNOWN + break; + + case Constraint_NOP: + memop = MemOp_NOP; // do nothing + wback = false; + break; + + default: + break; } + } + + idx = LSL(llvm::SignExtend64<7>(imm7), scale); + size = (integer)1 << scale; + uint64_t datasize = size * 8; + uint64_t address; + uint64_t wb_address; - // If setflags && d == arm64_dwarf::sp then d = WZR/XZR. See CMN, CMP - if (!setflags || d != arm64_dwarf::sp) - WriteRegisterUnsigned (context, eRegisterKindDWARF, arm64_dwarf::x0 + d, result); + RegisterValue data_Rt; + RegisterValue data_Rt2; + // if (vector) + // CheckFPEnabled(false); + + RegisterInfo reg_info_base; + RegisterInfo reg_info_Rt; + RegisterInfo reg_info_Rt2; + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base)) return false; -} -template <EmulateInstructionARM64::AddrMode a_mode> bool -EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode) -{ - uint32_t opc = Bits32(opcode, 31, 30); - uint32_t V = Bit32(opcode, 26); - uint32_t L = Bit32(opcode, 22); - uint32_t imm7 = Bits32(opcode, 21, 15); - uint32_t Rt2 = Bits32(opcode, 14, 10); - uint32_t Rn = Bits32(opcode, 9, 5); - uint32_t Rt = Bits32(opcode, 4, 0); - - integer n = UInt(Rn); - integer t = UInt(Rt); - integer t2 = UInt(Rt2); - uint64_t idx; - - MemOp memop = L == 1 ? MemOp_LOAD : MemOp_STORE; - boolean vector = (V == 1); - //AccType acctype = AccType_NORMAL; - boolean is_signed = false; - boolean wback = a_mode != AddrMode_OFF; - boolean wb_unknown = false; - boolean rt_unknown = false; - integer scale; - integer size; - - if (opc == 3) - return false; // UNDEFINED - - if (vector) - { - scale = 2 + UInt(opc); - } - else + if (vector) { + if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t, reg_info_Rt)) + return false; + if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2, reg_info_Rt2)) + return false; + } else { + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt)) + return false; + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2, reg_info_Rt2)) + return false; + } + + bool success = false; + if (n == 31) { + // CheckSPAlignment(); + address = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success); + } else + address = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success); + + wb_address = address + idx; + if (a_mode != AddrMode_POST) + address = wb_address; + + Context context_t; + Context context_t2; + + uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; + Error error; + + switch (memop) { + case MemOp_STORE: { + if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is + // based off of the sp + // or fp register { - scale = (opc & 2) ? 3 : 2; - is_signed = (opc & 1) != 0; - if (is_signed && memop == MemOp_STORE) - return false; // UNDEFINED - } - - if (!vector && wback && ((t == n) || (t2 == n))) - { - switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) - { - case Constraint_UNKNOWN: - wb_unknown = true; // writeback is UNKNOWN - break; - - case Constraint_SUPPRESSWB: - wback = false; // writeback is suppressed - break; - - case Constraint_NOP: - memop = MemOp_NOP; // do nothing - wback = false; - break; - - case Constraint_NONE: - break; - } + context_t.type = eContextPushRegisterOnStack; + context_t2.type = eContextPushRegisterOnStack; + } else { + context_t.type = eContextRegisterStore; + context_t2.type = eContextRegisterStore; } + context_t.SetRegisterToRegisterPlusOffset(reg_info_Rt, reg_info_base, 0); + context_t2.SetRegisterToRegisterPlusOffset(reg_info_Rt2, reg_info_base, + size); + + if (!ReadRegister(®_info_Rt, data_Rt)) + return false; + + if (data_Rt.GetAsMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, + eByteOrderLittle, error) == 0) + return false; + + if (!WriteMemory(context_t, address + 0, buffer, reg_info_Rt.byte_size)) + return false; + + if (!ReadRegister(®_info_Rt2, data_Rt2)) + return false; + + if (data_Rt2.GetAsMemoryData(®_info_Rt2, buffer, reg_info_Rt2.byte_size, + eByteOrderLittle, error) == 0) + return false; - if (memop == MemOp_LOAD && t == t2) + if (!WriteMemory(context_t2, address + size, buffer, + reg_info_Rt2.byte_size)) + return false; + } break; + + case MemOp_LOAD: { + if (n == 31 || n == GetFramePointerRegisterNumber()) // if this load is + // based off of the sp + // or fp register { - switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) - { - case Constraint_UNKNOWN: - rt_unknown = true; // result is UNKNOWN - break; - - case Constraint_NOP: - memop = MemOp_NOP; // do nothing - wback = false; - break; - - default: - break; - } + context_t.type = eContextPopRegisterOffStack; + context_t2.type = eContextPopRegisterOffStack; + } else { + context_t.type = eContextRegisterLoad; + context_t2.type = eContextRegisterLoad; } - - idx = LSL(llvm::SignExtend64<7>(imm7), scale); - size = (integer)1 << scale; - uint64_t datasize = size * 8; - uint64_t address; - uint64_t wb_address; - - RegisterValue data_Rt; - RegisterValue data_Rt2; - - // if (vector) - // CheckFPEnabled(false); - - RegisterInfo reg_info_base; - RegisterInfo reg_info_Rt; - RegisterInfo reg_info_Rt2; - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + n, reg_info_base)) + context_t.SetAddress(address); + context_t2.SetAddress(address + size); + + if (rt_unknown) + memset(buffer, 'U', reg_info_Rt.byte_size); + else { + if (!ReadMemory(context_t, address, buffer, reg_info_Rt.byte_size)) return false; - - if (vector) - { - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::v0 + n, reg_info_Rt)) - return false; - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::v0 + n, reg_info_Rt2)) - return false; - } - else - { - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + t, reg_info_Rt)) - return false; - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + t2, reg_info_Rt2)) - return false; - } - - bool success = false; - if (n == 31) - { - //CheckSPAlignment(); - address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::sp, 0, &success); } - else - address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, &success); - - wb_address = address + idx; - if (a_mode != AddrMode_POST) - address = wb_address; - - Context context_t; - Context context_t2; - - uint8_t buffer [RegisterValue::kMaxRegisterByteSize]; - Error error; - - switch (memop) - { - case MemOp_STORE: - { - if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is based off of the sp or fp register - { - context_t.type = eContextPushRegisterOnStack; - context_t2.type = eContextPushRegisterOnStack; - } - else - { - context_t.type = eContextRegisterStore; - context_t2.type = eContextRegisterStore; - } - context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0); - context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size); - - if (!ReadRegister (®_info_Rt, data_Rt)) - return false; - - if (data_Rt.GetAsMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0) - return false; - - if (!WriteMemory(context_t, address + 0, buffer, reg_info_Rt.byte_size)) - return false; - - if (!ReadRegister (®_info_Rt2, data_Rt2)) - return false; - - if (data_Rt2.GetAsMemoryData(®_info_Rt2, buffer, reg_info_Rt2.byte_size, eByteOrderLittle, error) == 0) - return false; - - if (!WriteMemory(context_t2, address + size, buffer, reg_info_Rt2.byte_size)) - return false; - } - break; - - case MemOp_LOAD: - { - if (n == 31 || n == GetFramePointerRegisterNumber()) // if this load is based off of the sp or fp register - { - context_t.type = eContextPopRegisterOffStack; - context_t2.type = eContextPopRegisterOffStack; - } - else - { - context_t.type = eContextRegisterLoad; - context_t2.type = eContextRegisterLoad; - } - context_t.SetAddress(address); - context_t2.SetAddress(address + size); - - if (rt_unknown) - memset (buffer, 'U', reg_info_Rt.byte_size); - else - { - if (!ReadMemory (context_t, address, buffer, reg_info_Rt.byte_size)) - return false; - } - - if (data_Rt.SetFromMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0) - return false; - - if (!vector && is_signed && !data_Rt.SignExtend (datasize)) - return false; - - if (!WriteRegister (context_t, ®_info_Rt, data_Rt)) - return false; - - if (!rt_unknown) - { - if (!ReadMemory (context_t2, address + size, buffer, reg_info_Rt2.byte_size)) - return false; - } - - if (data_Rt2.SetFromMemoryData(®_info_Rt2, buffer, reg_info_Rt2.byte_size, eByteOrderLittle, error) == 0) - return false; - - if (!vector && is_signed && !data_Rt2.SignExtend (datasize)) - return false; - - if (!WriteRegister (context_t2, ®_info_Rt2, data_Rt2)) - return false; - } - break; - - default: - break; - } - - if (wback) - { - if (wb_unknown) - wb_address = LLDB_INVALID_ADDRESS; - Context context; - context.SetImmediateSigned (idx); - if (n == 31) - context.type = eContextAdjustStackPointer; - else - context.type = eContextAdjustBaseRegister; - WriteRegisterUnsigned (context, ®_info_base, wb_address); - } - return true; -} -template <EmulateInstructionARM64::AddrMode a_mode> bool -EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode) -{ - uint32_t size = Bits32(opcode, 31, 30); - uint32_t opc = Bits32(opcode, 23, 22); - uint32_t n = Bits32(opcode, 9, 5); - uint32_t t = Bits32(opcode, 4, 0); + if (data_Rt.SetFromMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, + eByteOrderLittle, error) == 0) + return false; - bool wback; - bool postindex; - uint64_t offset; + if (!vector && is_signed && !data_Rt.SignExtend(datasize)) + return false; - switch (a_mode) - { - case AddrMode_POST: - wback = true; - postindex = true; - offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12)); - break; - case AddrMode_PRE: - wback = true; - postindex = false; - offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12)); - break; - case AddrMode_OFF: - wback = false; - postindex = false; - offset = LSL(Bits32(opcode, 21, 10), size); - break; + if (!WriteRegister(context_t, ®_info_Rt, data_Rt)) + return false; + + if (!rt_unknown) { + if (!ReadMemory(context_t2, address + size, buffer, + reg_info_Rt2.byte_size)) + return false; } - MemOp memop; + if (data_Rt2.SetFromMemoryData(®_info_Rt2, buffer, + reg_info_Rt2.byte_size, eByteOrderLittle, + error) == 0) + return false; - if (Bit32(opc, 1) == 0) - { - memop = Bit32(opc, 0) == 1 ? MemOp_LOAD : MemOp_STORE; - } - else - { - memop = MemOp_LOAD; - if (size == 2 && Bit32(opc, 0) == 1) - return false; - } + if (!vector && is_signed && !data_Rt2.SignExtend(datasize)) + return false; - Error error; - bool success = false; - uint64_t address; - uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; - RegisterValue data_Rt; + if (!WriteRegister(context_t2, ®_info_Rt2, data_Rt2)) + return false; + } break; + + default: + break; + } + if (wback) { + if (wb_unknown) + wb_address = LLDB_INVALID_ADDRESS; + Context context; + context.SetImmediateSigned(idx); if (n == 31) - address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::sp, 0, &success); + context.type = eContextAdjustStackPointer; else - address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, &success); + context.type = eContextAdjustBaseRegister; + WriteRegisterUnsigned(context, ®_info_base, wb_address); + } + return true; +} - if (!success) - return false; +template <EmulateInstructionARM64::AddrMode a_mode> +bool EmulateInstructionARM64::EmulateLDRSTRImm(const uint32_t opcode) { + uint32_t size = Bits32(opcode, 31, 30); + uint32_t opc = Bits32(opcode, 23, 22); + uint32_t n = Bits32(opcode, 9, 5); + uint32_t t = Bits32(opcode, 4, 0); + + bool wback; + bool postindex; + uint64_t offset; + + switch (a_mode) { + case AddrMode_POST: + wback = true; + postindex = true; + offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12)); + break; + case AddrMode_PRE: + wback = true; + postindex = false; + offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12)); + break; + case AddrMode_OFF: + wback = false; + postindex = false; + offset = LSL(Bits32(opcode, 21, 10), size); + break; + } + + MemOp memop; + + if (Bit32(opc, 1) == 0) { + memop = Bit32(opc, 0) == 1 ? MemOp_LOAD : MemOp_STORE; + } else { + memop = MemOp_LOAD; + if (size == 2 && Bit32(opc, 0) == 1) + return false; + } + + Error error; + bool success = false; + uint64_t address; + uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; + RegisterValue data_Rt; + + if (n == 31) + address = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success); + else + address = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success); + + if (!success) + return false; - if (!postindex) - address += offset; + if (!postindex) + address += offset; - RegisterInfo reg_info_base; - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + n, reg_info_base)) - return false; + RegisterInfo reg_info_base; + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base)) + return false; - RegisterInfo reg_info_Rt; - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + t, reg_info_Rt)) - return false; + RegisterInfo reg_info_Rt; + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt)) + return false; - Context context; - switch (memop) - { - case MemOp_STORE: - if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is based off of the sp or fp register - context.type = eContextPushRegisterOnStack; - else - context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, postindex ? 0 : offset); - - if (!ReadRegister (®_info_Rt, data_Rt)) - return false; - - if (data_Rt.GetAsMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0) - return false; - - if (!WriteMemory(context, address, buffer, reg_info_Rt.byte_size)) - return false; - break; - - case MemOp_LOAD: - if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is based off of the sp or fp register - context.type = eContextPopRegisterOffStack; - else - context.type = eContextRegisterLoad; - context.SetAddress(address); - - if (!ReadMemory (context, address, buffer, reg_info_Rt.byte_size)) - return false; - - if (data_Rt.SetFromMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0) - return false; - - if (!WriteRegister (context, ®_info_Rt, data_Rt)) - return false; - break; - default: - return false; - } + Context context; + switch (memop) { + case MemOp_STORE: + if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is + // based off of the sp + // or fp register + context.type = eContextPushRegisterOnStack; + else + context.type = eContextRegisterStore; + context.SetRegisterToRegisterPlusOffset(reg_info_Rt, reg_info_base, + postindex ? 0 : offset); + + if (!ReadRegister(®_info_Rt, data_Rt)) + return false; + + if (data_Rt.GetAsMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, + eByteOrderLittle, error) == 0) + return false; + + if (!WriteMemory(context, address, buffer, reg_info_Rt.byte_size)) + return false; + break; + + case MemOp_LOAD: + if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is + // based off of the sp + // or fp register + context.type = eContextPopRegisterOffStack; + else + context.type = eContextRegisterLoad; + context.SetAddress(address); - if (wback) - { - if (postindex) - address += offset; + if (!ReadMemory(context, address, buffer, reg_info_Rt.byte_size)) + return false; - if (n == 31) - context.type = eContextAdjustStackPointer; - else - context.type = eContextAdjustBaseRegister; - context.SetImmediateSigned (offset); + if (data_Rt.SetFromMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, + eByteOrderLittle, error) == 0) + return false; - if (!WriteRegisterUnsigned (context, ®_info_base, address)) - return false; - } - return true; + if (!WriteRegister(context, ®_info_Rt, data_Rt)) + return false; + break; + default: + return false; + } + + if (wback) { + if (postindex) + address += offset; + + if (n == 31) + context.type = eContextAdjustStackPointer; + else + context.type = eContextAdjustBaseRegister; + context.SetImmediateSigned(offset); + + if (!WriteRegisterUnsigned(context, ®_info_base, address)) + return false; + } + return true; } -bool -EmulateInstructionARM64::EmulateB (const uint32_t opcode) -{ +bool EmulateInstructionARM64::EmulateB(const uint32_t opcode) { #if 0 // ARM64 pseudo code... if branch_type == BranchType_CALL then X[30] = PC[] + 4; BranchTo(PC[] + offset, branch_type); #endif - bool success = false; + bool success = false; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRelativeBranchImmediate; - const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); - if (!success) - return false; - - int64_t offset = llvm::SignExtend64<28>(Bits32(opcode, 25, 0) << 2); - BranchType branch_type = Bit32(opcode, 31) ? BranchType_CALL : BranchType_JMP; - addr_t target = pc + offset; - context.SetImmediateSigned(offset); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRelativeBranchImmediate; + const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC, 0, &success); + if (!success) + return false; - switch (branch_type) - { - case BranchType_CALL: - { - addr_t x30 = pc + 4; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, arm64_dwarf::x30, x30)) - return false; - } - break; - case BranchType_JMP: - break; - default: - return false; - } + int64_t offset = llvm::SignExtend64<28>(Bits32(opcode, 25, 0) << 2); + BranchType branch_type = Bit32(opcode, 31) ? BranchType_CALL : BranchType_JMP; + addr_t target = pc + offset; + context.SetImmediateSigned(offset); + + switch (branch_type) { + case BranchType_CALL: { + addr_t x30 = pc + 4; + if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_lr_arm64, x30)) + return false; + } break; + case BranchType_JMP: + break; + default: + return false; + } - if (!BranchTo(context, 64, target)) - return false; - return true; + if (!BranchTo(context, 64, target)) + return false; + return true; } -bool -EmulateInstructionARM64::EmulateBcond (const uint32_t opcode) -{ +bool EmulateInstructionARM64::EmulateBcond(const uint32_t opcode) { #if 0 // ARM64 pseudo code... bits(64) offset = SignExtend(imm19:'00', 64); @@ -1055,29 +1127,27 @@ EmulateInstructionARM64::EmulateBcond (const uint32_t opcode) BranchTo(PC[] + offset, BranchType_JMP); #endif - if (ConditionHolds(Bits32(opcode, 3, 0))) - { - bool success = false; - - const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); - if (!success) - return false; - - int64_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2); - addr_t target = pc + offset; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRelativeBranchImmediate; - context.SetImmediateSigned(offset); - if (!BranchTo(context, 64, target)) - return false; - } - return true; + if (ConditionHolds(Bits32(opcode, 3, 0))) { + bool success = false; + + const uint64_t pc = ReadRegisterUnsigned( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); + if (!success) + return false; + + int64_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2); + addr_t target = pc + offset; + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRelativeBranchImmediate; + context.SetImmediateSigned(offset); + if (!BranchTo(context, 64, target)) + return false; + } + return true; } -bool -EmulateInstructionARM64::EmulateCBZ (const uint32_t opcode) -{ +bool EmulateInstructionARM64::EmulateCBZ(const uint32_t opcode) { #if 0 integer t = UInt(Rt); integer datasize = if sf == '1' then 64 else 32; @@ -1089,34 +1159,33 @@ EmulateInstructionARM64::EmulateCBZ (const uint32_t opcode) BranchTo(PC[] + offset, BranchType_JMP); #endif - bool success = false; + bool success = false; + + uint32_t t = Bits32(opcode, 4, 0); + bool is_zero = Bit32(opcode, 24) == 0; + int32_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2); - uint32_t t = Bits32(opcode, 4, 0); - bool is_zero = Bit32(opcode, 24) == 0; - int32_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2); + const uint64_t operand = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success); + if (!success) + return false; - const uint64_t operand = ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::x0 + t, 0, &success); + if (m_ignore_conditions || ((operand == 0) == is_zero)) { + const uint64_t pc = ReadRegisterUnsigned( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); if (!success) - return false; + return false; - if (m_ignore_conditions || ((operand == 0) == is_zero)) - { - const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); - if (!success) - return false; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRelativeBranchImmediate; - context.SetImmediateSigned(offset); - if (!BranchTo(context, 64, pc + offset)) - return false; - } - return true; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRelativeBranchImmediate; + context.SetImmediateSigned(offset); + if (!BranchTo(context, 64, pc + offset)) + return false; + } + return true; } -bool -EmulateInstructionARM64::EmulateTBZ (const uint32_t opcode) -{ +bool EmulateInstructionARM64::EmulateTBZ(const uint32_t opcode) { #if 0 integer t = UInt(Rt); integer datasize = if b5 == '1' then 64 else 32; @@ -1125,28 +1194,29 @@ EmulateInstructionARM64::EmulateTBZ (const uint32_t opcode) bits(64) offset = SignExtend(imm14:'00', 64); #endif - bool success = false; + bool success = false; + + uint32_t t = Bits32(opcode, 4, 0); + uint32_t bit_pos = (Bit32(opcode, 31) << 6) | (Bits32(opcode, 23, 19)); + uint32_t bit_val = Bit32(opcode, 24); + int64_t offset = llvm::SignExtend64<16>(Bits32(opcode, 18, 5) << 2); - uint32_t t = Bits32(opcode, 4, 0); - uint32_t bit_pos = (Bit32(opcode, 31) << 6) | (Bits32(opcode, 23, 19)); - uint32_t bit_val = Bit32(opcode, 24); - int64_t offset = llvm::SignExtend64<16>(Bits32(opcode, 18, 5) << 2); + const uint64_t operand = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success); + if (!success) + return false; - const uint64_t operand = ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::x0 + t, 0, &success); + if (m_ignore_conditions || Bit32(operand, bit_pos) == bit_val) { + const uint64_t pc = ReadRegisterUnsigned( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); if (!success) - return false; + return false; - if (m_ignore_conditions || Bit32(operand, bit_pos) == bit_val) - { - const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); - if (!success) - return false; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRelativeBranchImmediate; - context.SetImmediateSigned(offset); - if (!BranchTo(context, 64, pc + offset)) - return false; - } - return true; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRelativeBranchImmediate; + context.SetImmediateSigned(offset); + if (!BranchTo(context, 64, pc + offset)) + return false; + } + return true; } |