1223 lines · cpp
1//===-- EmulateInstructionARM64.cpp ---------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "EmulateInstructionARM64.h"10 11#include "lldb/Core/Address.h"12#include "lldb/Core/PluginManager.h"13#include "lldb/Symbol/UnwindPlan.h"14#include "lldb/Utility/ArchSpec.h"15#include "lldb/Utility/RegisterValue.h"16#include "lldb/Utility/Stream.h"17 18#include "llvm/Support/CheckedArithmetic.h"19 20#include "Plugins/Process/Utility/ARMDefines.h"21#include "Plugins/Process/Utility/ARMUtils.h"22#include "Plugins/Process/Utility/lldb-arm64-register-enums.h"23 24#include <algorithm>25#include <cstdlib>26#include <optional>27 28#define GPR_OFFSET(idx) ((idx)*8)29#define GPR_OFFSET_NAME(reg) 030#define FPU_OFFSET(idx) ((idx)*16)31#define FPU_OFFSET_NAME(reg) 032#define EXC_OFFSET_NAME(reg) 033#define DBG_OFFSET_NAME(reg) 034#define DBG_OFFSET_NAME(reg) 035#define DEFINE_DBG(re, y) \36 "na", nullptr, 8, 0, lldb::eEncodingUint, lldb::eFormatHex, \37 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \38 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, \39 nullptr, nullptr, nullptr40 41#define DECLARE_REGISTER_INFOS_ARM64_STRUCT42 43#include "Plugins/Process/Utility/RegisterInfos_arm64.h"44 45#include "llvm/ADT/STLExtras.h"46#include "llvm/Support/MathExtras.h"47 48#include "Plugins/Process/Utility/InstructionUtils.h"49 50using namespace lldb;51using namespace lldb_private;52 53LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM64, InstructionARM64)54 55static std::optional<RegisterInfo> LLDBTableGetRegisterInfo(uint32_t reg_num) {56 if (reg_num >= std::size(g_register_infos_arm64_le))57 return {};58 return g_register_infos_arm64_le[reg_num];59}60 61#define No_VFP 062#define VFPv1 (1u << 1)63#define VFPv2 (1u << 2)64#define VFPv3 (1u << 3)65#define AdvancedSIMD (1u << 4)66 67#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)68#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)69#define VFPv2v3 (VFPv2 | VFPv3)70 71#define UInt(x) ((uint64_t)x)72#define SInt(x) ((int64_t)x)73#define bit bool74#define boolean bool75#define integer int64_t76 77static inline bool IsZero(uint64_t x) { return x == 0; }78 79static inline uint64_t NOT(uint64_t x) { return ~x; }80 81// LSL()82// =====83 84static inline uint64_t LSL(uint64_t x, integer shift) {85 if (shift == 0)86 return x;87 return x << shift;88}89 90// ConstrainUnpredictable()91// ========================92 93EmulateInstructionARM64::ConstraintType94ConstrainUnpredictable(EmulateInstructionARM64::Unpredictable which) {95 EmulateInstructionARM64::ConstraintType result =96 EmulateInstructionARM64::Constraint_UNKNOWN;97 switch (which) {98 case EmulateInstructionARM64::Unpredictable_WBOVERLAP:99 case EmulateInstructionARM64::Unpredictable_LDPOVERLAP:100 // TODO: don't know what to really do here? Pseudo code says:101 // set result to one of above Constraint behaviours or UNDEFINED102 break;103 }104 return result;105}106 107//108// EmulateInstructionARM implementation109//110 111void EmulateInstructionARM64::Initialize() {112 PluginManager::RegisterPlugin(GetPluginNameStatic(),113 GetPluginDescriptionStatic(), CreateInstance);114}115 116void EmulateInstructionARM64::Terminate() {117 PluginManager::UnregisterPlugin(CreateInstance);118}119 120llvm::StringRef EmulateInstructionARM64::GetPluginDescriptionStatic() {121 return "Emulate instructions for the ARM64 architecture.";122}123 124EmulateInstruction *125EmulateInstructionARM64::CreateInstance(const ArchSpec &arch,126 InstructionType inst_type) {127 if (EmulateInstructionARM64::SupportsEmulatingInstructionsOfTypeStatic(128 inst_type)) {129 if (arch.GetTriple().getArch() == llvm::Triple::aarch64 ||130 arch.GetTriple().getArch() == llvm::Triple::aarch64_32) {131 return new EmulateInstructionARM64(arch);132 }133 }134 135 return nullptr;136}137 138bool EmulateInstructionARM64::SetTargetTriple(const ArchSpec &arch) {139 if (arch.GetTriple().getArch() == llvm::Triple::arm)140 return true;141 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)142 return true;143 144 return false;145}146 147std::optional<RegisterInfo>148EmulateInstructionARM64::GetRegisterInfo(RegisterKind reg_kind,149 uint32_t reg_num) {150 if (reg_kind == eRegisterKindGeneric) {151 switch (reg_num) {152 case LLDB_REGNUM_GENERIC_PC:153 reg_kind = eRegisterKindLLDB;154 reg_num = gpr_pc_arm64;155 break;156 case LLDB_REGNUM_GENERIC_SP:157 reg_kind = eRegisterKindLLDB;158 reg_num = gpr_sp_arm64;159 break;160 case LLDB_REGNUM_GENERIC_FP:161 reg_kind = eRegisterKindLLDB;162 reg_num = gpr_fp_arm64;163 break;164 case LLDB_REGNUM_GENERIC_RA:165 reg_kind = eRegisterKindLLDB;166 reg_num = gpr_lr_arm64;167 break;168 case LLDB_REGNUM_GENERIC_FLAGS:169 reg_kind = eRegisterKindLLDB;170 reg_num = gpr_cpsr_arm64;171 break;172 173 default:174 return {};175 }176 }177 178 if (reg_kind == eRegisterKindLLDB)179 return LLDBTableGetRegisterInfo(reg_num);180 return {};181}182 183EmulateInstructionARM64::Opcode *184EmulateInstructionARM64::GetOpcodeForInstruction(const uint32_t opcode) {185 static EmulateInstructionARM64::Opcode g_opcodes[] = {186 // Prologue instructions187 188 // push register(s)189 {0xff000000, 0xd1000000, No_VFP,190 &EmulateInstructionARM64::EmulateADDSUBImm,191 "SUB <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}"},192 {0xff000000, 0xf1000000, No_VFP,193 &EmulateInstructionARM64::EmulateADDSUBImm,194 "SUBS <Xd>, <Xn|SP>, #<imm> {, <shift>}"},195 {0xff000000, 0x91000000, No_VFP,196 &EmulateInstructionARM64::EmulateADDSUBImm,197 "ADD <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}"},198 {0xff000000, 0xb1000000, No_VFP,199 &EmulateInstructionARM64::EmulateADDSUBImm,200 "ADDS <Xd>, <Xn|SP>, #<imm> {, <shift>}"},201 202 {0xff000000, 0x51000000, No_VFP,203 &EmulateInstructionARM64::EmulateADDSUBImm,204 "SUB <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}"},205 {0xff000000, 0x71000000, No_VFP,206 &EmulateInstructionARM64::EmulateADDSUBImm,207 "SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}"},208 {0xff000000, 0x11000000, No_VFP,209 &EmulateInstructionARM64::EmulateADDSUBImm,210 "ADD <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}"},211 {0xff000000, 0x31000000, No_VFP,212 &EmulateInstructionARM64::EmulateADDSUBImm,213 "ADDS <Wd>, <Wn|WSP>, #<imm> {, <shift>}"},214 215 {0xffc00000, 0x29000000, No_VFP,216 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,217 "STP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]"},218 {0xffc00000, 0xa9000000, No_VFP,219 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,220 "STP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]"},221 {0xffc00000, 0x2d000000, No_VFP,222 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,223 "STP <St>, <St2>, [<Xn|SP>{, #<imm>}]"},224 {0xffc00000, 0x6d000000, No_VFP,225 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,226 "STP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]"},227 {0xffc00000, 0xad000000, No_VFP,228 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,229 "STP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]"},230 231 {0xffc00000, 0x29800000, No_VFP,232 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,233 "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"},234 {0xffc00000, 0xa9800000, No_VFP,235 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,236 "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"},237 {0xffc00000, 0x2d800000, No_VFP,238 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,239 "STP <St>, <St2>, [<Xn|SP>, #<imm>]!"},240 {0xffc00000, 0x6d800000, No_VFP,241 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,242 "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"},243 {0xffc00000, 0xad800000, No_VFP,244 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,245 "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"},246 247 {0xffc00000, 0x28800000, No_VFP,248 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,249 "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"},250 {0xffc00000, 0xa8800000, No_VFP,251 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,252 "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"},253 {0xffc00000, 0x2c800000, No_VFP,254 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,255 "STP <St>, <St2>, [<Xn|SP>, #<imm>]!"},256 {0xffc00000, 0x6c800000, No_VFP,257 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,258 "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"},259 {0xffc00000, 0xac800000, No_VFP,260 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,261 "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"},262 263 {0xffc00000, 0x29400000, No_VFP,264 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,265 "LDP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]"},266 {0xffc00000, 0xa9400000, No_VFP,267 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,268 "LDP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]"},269 {0xffc00000, 0x2d400000, No_VFP,270 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,271 "LDP <St>, <St2>, [<Xn|SP>{, #<imm>}]"},272 {0xffc00000, 0x6d400000, No_VFP,273 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,274 "LDP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]"},275 {0xffc00000, 0xad400000, No_VFP,276 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,277 "LDP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]"},278 279 {0xffc00000, 0x29c00000, No_VFP,280 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,281 "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"},282 {0xffc00000, 0xa9c00000, No_VFP,283 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,284 "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"},285 {0xffc00000, 0x2dc00000, No_VFP,286 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,287 "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!"},288 {0xffc00000, 0x6dc00000, No_VFP,289 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,290 "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"},291 {0xffc00000, 0xadc00000, No_VFP,292 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,293 "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"},294 295 {0xffc00000, 0x28c00000, No_VFP,296 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,297 "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"},298 {0xffc00000, 0xa8c00000, No_VFP,299 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,300 "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"},301 {0xffc00000, 0x2cc00000, No_VFP,302 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,303 "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!"},304 {0xffc00000, 0x6cc00000, No_VFP,305 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,306 "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"},307 {0xffc00000, 0xacc00000, No_VFP,308 &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,309 "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"},310 311 {0xffe00c00, 0xb8000400, No_VFP,312 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>,313 "STR <Wt>, [<Xn|SP>], #<simm>"},314 {0xffe00c00, 0xf8000400, No_VFP,315 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>,316 "STR <Xt>, [<Xn|SP>], #<simm>"},317 {0xffe00c00, 0xb8000c00, No_VFP,318 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,319 "STR <Wt>, [<Xn|SP>, #<simm>]!"},320 {0xffe00c00, 0xf8000c00, No_VFP,321 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,322 "STR <Xt>, [<Xn|SP>, #<simm>]!"},323 {0xffc00000, 0xb9000000, No_VFP,324 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,325 "STR <Wt>, [<Xn|SP>{, #<pimm>}]"},326 {0xffc00000, 0xf9000000, No_VFP,327 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,328 "STR <Xt>, [<Xn|SP>{, #<pimm>}]"},329 330 {0xffe00c00, 0xb8400400, No_VFP,331 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>,332 "LDR <Wt>, [<Xn|SP>], #<simm>"},333 {0xffe00c00, 0xf8400400, No_VFP,334 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>,335 "LDR <Xt>, [<Xn|SP>], #<simm>"},336 {0xffe00c00, 0xb8400c00, No_VFP,337 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,338 "LDR <Wt>, [<Xn|SP>, #<simm>]!"},339 {0xffe00c00, 0xf8400c00, No_VFP,340 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,341 "LDR <Xt>, [<Xn|SP>, #<simm>]!"},342 {0xffc00000, 0xb9400000, No_VFP,343 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,344 "LDR <Wt>, [<Xn|SP>{, #<pimm>}]"},345 {0xffc00000, 0xf9400000, No_VFP,346 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,347 "LDR <Xt>, [<Xn|SP>{, #<pimm>}]"},348 349 {0x3f200c00, 0x3c000400, No_VFP,350 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>,351 "LDR|STR <Bt|Ht|St|Dt|Qt>, [<Xn|SP>], #<simm>"},352 {0x3f200c00, 0x3c000c00, No_VFP,353 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,354 "LDR|STR <Bt|Ht|St|Dt|Qt>, [<Xn|SP>, #<simm>]!"},355 {0x3f000000, 0x3d000000, No_VFP,356 &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,357 "LDR|STR <Bt|Ht|St|Dt|Qt>, [<Xn|SP>{, #<pimm>}]"},358 359 {0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB,360 "B <label>"},361 {0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond,362 "B.<cond> <label>"},363 {0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ,364 "CBZ <Wt>, <label>"},365 {0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ,366 "CBNZ <Wt>, <label>"},367 {0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ,368 "TBZ <R><t>, #<imm>, <label>"},369 {0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ,370 "TBNZ <R><t>, #<imm>, <label>"},371 372 };373 static const size_t k_num_arm_opcodes = std::size(g_opcodes);374 375 for (size_t i = 0; i < k_num_arm_opcodes; ++i) {376 if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value)377 return &g_opcodes[i];378 }379 return nullptr;380}381 382bool EmulateInstructionARM64::ReadInstruction() {383 bool success = false;384 m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,385 LLDB_INVALID_ADDRESS, &success);386 if (success) {387 Context read_inst_context;388 read_inst_context.type = eContextReadOpcode;389 read_inst_context.SetNoArgs();390 m_opcode.SetOpcode32(391 ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),392 GetByteOrder());393 }394 if (!success)395 m_addr = LLDB_INVALID_ADDRESS;396 return success;397}398 399bool EmulateInstructionARM64::EvaluateInstruction(uint32_t evaluate_options) {400 const uint32_t opcode = m_opcode.GetOpcode32();401 Opcode *opcode_data = GetOpcodeForInstruction(opcode);402 if (opcode_data == nullptr)403 return false;404 405 const bool auto_advance_pc =406 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;407 m_ignore_conditions =408 evaluate_options & eEmulateInstructionOptionIgnoreConditions;409 410 bool success = false;411 412 // Only return false if we are unable to read the CPSR if we care about413 // conditions414 if (!success && !m_ignore_conditions)415 return false;416 417 uint64_t orig_pc_value = 0;418 if (auto_advance_pc) {419 orig_pc_value =420 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success);421 if (!success)422 return false;423 }424 425 // Call the Emulate... function.426 success = (this->*opcode_data->callback)(opcode);427 if (!success)428 return false;429 430 if (auto_advance_pc) {431 uint64_t new_pc_value =432 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success);433 if (!success)434 return false;435 436 if (new_pc_value == orig_pc_value) {437 EmulateInstruction::Context context;438 context.type = eContextAdvancePC;439 context.SetNoArgs();440 if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_pc_arm64,441 orig_pc_value + 4))442 return false;443 }444 }445 return true;446}447 448bool EmulateInstructionARM64::CreateFunctionEntryUnwind(449 UnwindPlan &unwind_plan) {450 unwind_plan.Clear();451 unwind_plan.SetRegisterKind(eRegisterKindLLDB);452 453 UnwindPlan::Row row;454 455 // Our previous Call Frame Address is the stack pointer456 row.GetCFAValue().SetIsRegisterPlusOffset(gpr_sp_arm64, 0);457 row.SetRegisterLocationToSame(gpr_lr_arm64, /*must_replace=*/false);458 row.SetRegisterLocationToSame(gpr_fp_arm64, /*must_replace=*/false);459 460 unwind_plan.AppendRow(std::move(row));461 unwind_plan.SetSourceName("EmulateInstructionARM64");462 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);463 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);464 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);465 unwind_plan.SetReturnAddressRegister(gpr_lr_arm64);466 return true;467}468 469uint32_t EmulateInstructionARM64::GetFramePointerRegisterNumber() const {470 if (m_arch.GetTriple().isAndroid())471 return LLDB_INVALID_REGNUM; // Don't use frame pointer on android472 473 return gpr_fp_arm64;474}475 476bool EmulateInstructionARM64::UsingAArch32() {477 bool aarch32 = m_opcode_pstate.RW == 1;478 // if !HaveAnyAArch32() then assert !aarch32;479 // if HighestELUsingAArch32() then assert aarch32;480 return aarch32;481}482 483bool EmulateInstructionARM64::BranchTo(const Context &context, uint32_t N,484 addr_t target) {485#if 0486 // Set program counter to a new address, with a branch reason hint for487 // possible use by hardware fetching the next instruction.488 BranchTo(bits(N) target, BranchType branch_type)489 Hint_Branch(branch_type);490 if N == 32 then491 assert UsingAArch32();492 _PC = ZeroExtend(target);493 else494 assert N == 64 && !UsingAArch32();495 // Remove the tag bits from a tagged target496 case PSTATE.EL of497 when EL0, EL1498 if target<55> == '1' && TCR_EL1.TBI1 == '1' then499 target<63:56> = '11111111';500 if target<55> == '0' && TCR_EL1.TBI0 == '1' then501 target<63:56> = '00000000';502 when EL2503 if TCR_EL2.TBI == '1' then504 target<63:56> = '00000000';505 when EL3506 if TCR_EL3.TBI == '1' then507 target<63:56> = '00000000';508 _PC = target<63:0>;509 return;510#endif511 512 addr_t addr;513 514 // Hint_Branch(branch_type);515 if (N == 32) {516 if (!UsingAArch32())517 return false;518 addr = target;519 } else if (N == 64) {520 if (UsingAArch32())521 return false;522 // TODO: Remove the tag bits from a tagged target523 addr = target;524 } else525 return false;526 527 return WriteRegisterUnsigned(context, eRegisterKindGeneric,528 LLDB_REGNUM_GENERIC_PC, addr);529}530 531bool EmulateInstructionARM64::ConditionHolds(const uint32_t cond) {532 // If we are ignoring conditions, then always return true. this allows us to533 // iterate over disassembly code and still emulate an instruction even if we534 // don't have all the right bits set in the CPSR register...535 if (m_ignore_conditions)536 return true;537 538 bool result = false;539 switch (UnsignedBits(cond, 3, 1)) {540 case 0:541 result = (m_opcode_pstate.Z == 1);542 break;543 case 1:544 result = (m_opcode_pstate.C == 1);545 break;546 case 2:547 result = (m_opcode_pstate.N == 1);548 break;549 case 3:550 result = (m_opcode_pstate.V == 1);551 break;552 case 4:553 result = (m_opcode_pstate.C == 1 && m_opcode_pstate.Z == 0);554 break;555 case 5:556 result = (m_opcode_pstate.N == m_opcode_pstate.V);557 break;558 case 6:559 result = (m_opcode_pstate.N == m_opcode_pstate.V && m_opcode_pstate.Z == 0);560 break;561 case 7:562 // Always execute (cond == 0b1110, or the special 0b1111 which gives563 // opcodes different meanings, but always means execution happens.564 return true;565 }566 567 if (cond & 1)568 result = !result;569 return result;570}571 572uint64_t EmulateInstructionARM64::573AddWithCarry(uint32_t N, uint64_t x, uint64_t y, bit carry_in,574 EmulateInstructionARM64::ProcState &proc_state) {575 uint64_t unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in);576 std::optional<int64_t> signed_sum = llvm::checkedAdd(SInt(x), SInt(y));577 bool overflow = !signed_sum;578 if (!overflow)579 overflow |= !llvm::checkedAdd(*signed_sum, SInt(carry_in));580 uint64_t result = unsigned_sum;581 if (N < 64)582 result = Bits64(result, N - 1, 0);583 proc_state.N = Bit64(result, N - 1);584 proc_state.Z = IsZero(result);585 proc_state.C = UInt(result) != unsigned_sum;586 proc_state.V = overflow;587 return result;588}589 590bool EmulateInstructionARM64::EmulateADDSUBImm(const uint32_t opcode) {591 // integer d = UInt(Rd);592 // integer n = UInt(Rn);593 // integer datasize = if sf == 1 then 64 else 32;594 // boolean sub_op = (op == 1);595 // boolean setflags = (S == 1);596 // bits(datasize) imm;597 //598 // case shift of599 // when '00' imm = ZeroExtend(imm12, datasize);600 // when '01' imm = ZeroExtend(imm12 : Zeros(12), datasize);601 // when '1x' UNDEFINED;602 //603 //604 // bits(datasize) result;605 // bits(datasize) operand1 = if n == 31 then SP[] else X[n];606 // bits(datasize) operand2 = imm;607 // bits(4) nzcv;608 // bit carry_in;609 //610 // if sub_op then611 // operand2 = NOT(operand2);612 // carry_in = 1;613 // else614 // carry_in = 0;615 //616 // (result, nzcv) = AddWithCarry(operand1, operand2, carry_in);617 //618 // if setflags then619 // PSTATE.NZCV = nzcv;620 //621 // if d == 31 && !setflags then622 // SP[] = result;623 // else624 // X[d] = result;625 626 const uint32_t sf = Bit32(opcode, 31);627 const uint32_t op = Bit32(opcode, 30);628 const uint32_t S = Bit32(opcode, 29);629 const uint32_t shift = Bits32(opcode, 23, 22);630 const uint32_t imm12 = Bits32(opcode, 21, 10);631 const uint32_t Rn = Bits32(opcode, 9, 5);632 const uint32_t Rd = Bits32(opcode, 4, 0);633 634 bool success = false;635 636 const uint32_t d = UInt(Rd);637 const uint32_t n = UInt(Rn);638 const uint32_t datasize = (sf == 1) ? 64 : 32;639 boolean sub_op = op == 1;640 boolean setflags = S == 1;641 uint64_t imm;642 643 switch (shift) {644 case 0:645 imm = imm12;646 break;647 case 1:648 imm = static_cast<uint64_t>(imm12) << 12;649 break;650 default:651 return false; // UNDEFINED;652 }653 uint64_t result;654 uint64_t operand1 =655 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);656 uint64_t operand2 = imm;657 bit carry_in;658 659 if (sub_op) {660 operand2 = NOT(operand2);661 carry_in = true;662 imm = -imm; // For the Register plug offset context below663 } else {664 carry_in = false;665 }666 667 ProcState proc_state;668 669 result = AddWithCarry(datasize, operand1, operand2, carry_in, proc_state);670 671 if (setflags) {672 m_emulated_pstate.N = proc_state.N;673 m_emulated_pstate.Z = proc_state.Z;674 m_emulated_pstate.C = proc_state.C;675 m_emulated_pstate.V = proc_state.V;676 }677 678 Context context;679 std::optional<RegisterInfo> reg_info_Rn =680 GetRegisterInfo(eRegisterKindLLDB, n);681 if (reg_info_Rn)682 context.SetRegisterPlusOffset(*reg_info_Rn, imm);683 684 if (n == GetFramePointerRegisterNumber() && d == gpr_sp_arm64 && !setflags) {685 // 'mov sp, fp' - common epilogue instruction, CFA is now in terms of the686 // stack pointer, instead of frame pointer.687 context.type = EmulateInstruction::eContextRestoreStackPointer;688 } else if ((n == gpr_sp_arm64 || n == GetFramePointerRegisterNumber()) &&689 d == gpr_sp_arm64 && !setflags) {690 context.type = EmulateInstruction::eContextAdjustStackPointer;691 } else if (d == GetFramePointerRegisterNumber() && n == gpr_sp_arm64 &&692 !setflags) {693 context.type = EmulateInstruction::eContextSetFramePointer;694 } else {695 context.type = EmulateInstruction::eContextImmediate;696 }697 698 // If setflags && d == gpr_sp_arm64 then d = WZR/XZR. See CMN, CMP699 if (!setflags || d != gpr_sp_arm64)700 WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_x0_arm64 + d, result);701 702 return false;703}704 705template <EmulateInstructionARM64::AddrMode a_mode>706bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) {707 uint32_t opc = Bits32(opcode, 31, 30);708 uint32_t V = Bit32(opcode, 26);709 uint32_t L = Bit32(opcode, 22);710 uint32_t imm7 = Bits32(opcode, 21, 15);711 uint32_t Rt2 = Bits32(opcode, 14, 10);712 uint32_t Rn = Bits32(opcode, 9, 5);713 uint32_t Rt = Bits32(opcode, 4, 0);714 715 integer n = UInt(Rn);716 integer t = UInt(Rt);717 integer t2 = UInt(Rt2);718 uint64_t idx;719 720 MemOp memop = L == 1 ? MemOp_LOAD : MemOp_STORE;721 boolean vector = (V == 1);722 // AccType acctype = AccType_NORMAL;723 boolean is_signed = false;724 boolean wback = a_mode != AddrMode_OFF;725 boolean wb_unknown = false;726 boolean rt_unknown = false;727 integer scale;728 integer size;729 730 if (opc == 3)731 return false; // UNDEFINED732 733 if (vector) {734 scale = 2 + UInt(opc);735 } else {736 scale = (opc & 2) ? 3 : 2;737 is_signed = (opc & 1) != 0;738 if (is_signed && memop == MemOp_STORE)739 return false; // UNDEFINED740 }741 742 if (!vector && wback && ((t == n) || (t2 == n))) {743 switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) {744 case Constraint_UNKNOWN:745 wb_unknown = true; // writeback is UNKNOWN746 break;747 748 case Constraint_SUPPRESSWB:749 wback = false; // writeback is suppressed750 break;751 752 case Constraint_NOP:753 memop = MemOp_NOP; // do nothing754 wback = false;755 break;756 757 case Constraint_NONE:758 break;759 }760 }761 762 if (memop == MemOp_LOAD && t == t2) {763 switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) {764 case Constraint_UNKNOWN:765 rt_unknown = true; // result is UNKNOWN766 break;767 768 case Constraint_NOP:769 memop = MemOp_NOP; // do nothing770 wback = false;771 break;772 773 default:774 break;775 }776 }777 778 idx = LSL(llvm::SignExtend64<7>(imm7), scale);779 size = (integer)1 << scale;780 uint64_t datasize = size * 8;781 uint64_t address;782 uint64_t wb_address;783 784 std::optional<RegisterInfo> reg_info_base =785 GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n);786 if (!reg_info_base)787 return false;788 789 std::optional<RegisterInfo> reg_info_Rt;790 std::optional<RegisterInfo> reg_info_Rt2;791 792 if (vector) {793 reg_info_Rt = GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t);794 reg_info_Rt2 = GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2);795 } else {796 reg_info_Rt = GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t);797 reg_info_Rt2 = GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2);798 }799 800 if (!reg_info_Rt || !reg_info_Rt2)801 return false;802 803 bool success = false;804 if (n == 31) {805 // CheckSPAlignment();806 address =807 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);808 } else809 address =810 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);811 812 wb_address = address + idx;813 if (a_mode != AddrMode_POST)814 address = wb_address;815 816 Context context_t;817 Context context_t2;818 819 RegisterValue::BytesContainer buffer;820 Status error;821 822 switch (memop) {823 case MemOp_STORE: {824 if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is825 // based off of the sp826 // or fp register827 {828 context_t.type = eContextPushRegisterOnStack;829 context_t2.type = eContextPushRegisterOnStack;830 } else {831 context_t.type = eContextRegisterStore;832 context_t2.type = eContextRegisterStore;833 }834 context_t.SetRegisterToRegisterPlusOffset(*reg_info_Rt, *reg_info_base, 0);835 context_t2.SetRegisterToRegisterPlusOffset(*reg_info_Rt2, *reg_info_base,836 size);837 838 std::optional<RegisterValue> data_Rt = ReadRegister(*reg_info_Rt);839 if (!data_Rt)840 return false;841 842 buffer.resize(reg_info_Rt->byte_size);843 if (data_Rt->GetAsMemoryData(*reg_info_Rt, buffer.data(),844 reg_info_Rt->byte_size, eByteOrderLittle,845 error) == 0)846 return false;847 848 if (!WriteMemory(context_t, address + 0, buffer.data(),849 reg_info_Rt->byte_size))850 return false;851 852 std::optional<RegisterValue> data_Rt2 = ReadRegister(*reg_info_Rt2);853 if (!data_Rt2)854 return false;855 856 buffer.resize(reg_info_Rt2->byte_size);857 if (data_Rt2->GetAsMemoryData(*reg_info_Rt2, buffer.data(),858 reg_info_Rt2->byte_size, eByteOrderLittle,859 error) == 0)860 return false;861 862 if (!WriteMemory(context_t2, address + size, buffer.data(),863 reg_info_Rt2->byte_size))864 return false;865 } break;866 867 case MemOp_LOAD: {868 if (n == 31 || n == GetFramePointerRegisterNumber()) // if this load is869 // based off of the sp870 // or fp register871 {872 context_t.type = eContextPopRegisterOffStack;873 context_t2.type = eContextPopRegisterOffStack;874 } else {875 context_t.type = eContextRegisterLoad;876 context_t2.type = eContextRegisterLoad;877 }878 context_t.SetAddress(address);879 context_t2.SetAddress(address + size);880 881 buffer.resize(reg_info_Rt->byte_size);882 if (rt_unknown)883 std::fill(buffer.begin(), buffer.end(), 'U');884 else {885 if (!ReadMemory(context_t, address, buffer.data(),886 reg_info_Rt->byte_size))887 return false;888 }889 890 RegisterValue data_Rt;891 if (data_Rt.SetFromMemoryData(*reg_info_Rt, buffer.data(),892 reg_info_Rt->byte_size, eByteOrderLittle,893 error) == 0)894 return false;895 896 if (!vector && is_signed && !data_Rt.SignExtend(datasize))897 return false;898 899 if (!WriteRegister(context_t, *reg_info_Rt, data_Rt))900 return false;901 902 buffer.resize(reg_info_Rt2->byte_size);903 if (!rt_unknown)904 if (!ReadMemory(context_t2, address + size, buffer.data(),905 reg_info_Rt2->byte_size))906 return false;907 908 RegisterValue data_Rt2;909 if (data_Rt2.SetFromMemoryData(*reg_info_Rt2, buffer.data(),910 reg_info_Rt2->byte_size, eByteOrderLittle,911 error) == 0)912 return false;913 914 if (!vector && is_signed && !data_Rt2.SignExtend(datasize))915 return false;916 917 if (!WriteRegister(context_t2, *reg_info_Rt2, data_Rt2))918 return false;919 } break;920 921 default:922 break;923 }924 925 if (wback) {926 if (wb_unknown)927 wb_address = LLDB_INVALID_ADDRESS;928 Context context;929 context.SetImmediateSigned(idx);930 if (n == 31)931 context.type = eContextAdjustStackPointer;932 else933 context.type = eContextAdjustBaseRegister;934 WriteRegisterUnsigned(context, *reg_info_base, wb_address);935 }936 return true;937}938 939template <EmulateInstructionARM64::AddrMode a_mode>940bool EmulateInstructionARM64::EmulateLDRSTRImm(const uint32_t opcode) {941 uint32_t size = Bits32(opcode, 31, 30);942 uint32_t opc = Bits32(opcode, 23, 22);943 uint32_t vr = Bit32(opcode, 26);944 uint32_t n = Bits32(opcode, 9, 5);945 uint32_t t = Bits32(opcode, 4, 0);946 947 MemOp memop;948 if (vr) {949 // opc<1> == 1 && size != 0 is an undefined encoding.950 if (Bit32(opc, 1) == 1 && size != 0)951 return false;952 // opc<1> == 1 && size == 0 encode the 128-bit variant.953 if (Bit32(opc, 1) == 1)954 size = 4;955 memop = Bit32(opc, 0) == 1 ? MemOp_LOAD : MemOp_STORE;956 } else {957 if (Bit32(opc, 1) == 0) {958 memop = Bit32(opc, 0) == 1 ? MemOp_LOAD : MemOp_STORE;959 } else {960 memop = MemOp_LOAD;961 if (size == 2 && Bit32(opc, 0) == 1)962 return false;963 }964 }965 966 bool wback;967 bool postindex;968 uint64_t offset;969 970 switch (a_mode) {971 case AddrMode_POST:972 wback = true;973 postindex = true;974 offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));975 break;976 case AddrMode_PRE:977 wback = true;978 postindex = false;979 offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));980 break;981 case AddrMode_OFF:982 wback = false;983 postindex = false;984 offset = LSL(Bits32(opcode, 21, 10), size);985 break;986 }987 988 Status error;989 bool success = false;990 uint64_t address;991 RegisterValue::BytesContainer buffer;992 993 if (n == 31)994 address =995 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);996 else997 address =998 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);999 1000 if (!success)1001 return false;1002 1003 if (!postindex)1004 address += offset;1005 1006 std::optional<RegisterInfo> reg_info_base =1007 GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n);1008 if (!reg_info_base)1009 return false;1010 1011 std::optional<RegisterInfo> reg_info_Rt =1012 vr ? GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t)1013 : GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t);1014 if (!reg_info_Rt)1015 return false;1016 1017 Context context;1018 switch (memop) {1019 case MemOp_STORE: {1020 if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is1021 // based off of the sp1022 // or fp register1023 context.type = eContextPushRegisterOnStack;1024 else1025 context.type = eContextRegisterStore;1026 context.SetRegisterToRegisterPlusOffset(*reg_info_Rt, *reg_info_base,1027 postindex ? 0 : offset);1028 1029 std::optional<RegisterValue> data_Rt = ReadRegister(*reg_info_Rt);1030 if (!data_Rt)1031 return false;1032 1033 buffer.resize(reg_info_Rt->byte_size);1034 if (data_Rt->GetAsMemoryData(*reg_info_Rt, buffer.data(),1035 reg_info_Rt->byte_size, eByteOrderLittle,1036 error) == 0)1037 return false;1038 1039 if (!WriteMemory(context, address, buffer.data(), reg_info_Rt->byte_size))1040 return false;1041 } break;1042 1043 case MemOp_LOAD: {1044 if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is1045 // based off of the sp1046 // or fp register1047 context.type = eContextPopRegisterOffStack;1048 else1049 context.type = eContextRegisterLoad;1050 context.SetAddress(address);1051 1052 buffer.resize(reg_info_Rt->byte_size);1053 if (!ReadMemory(context, address, buffer.data(), reg_info_Rt->byte_size))1054 return false;1055 1056 RegisterValue data_Rt;1057 if (data_Rt.SetFromMemoryData(*reg_info_Rt, buffer.data(),1058 reg_info_Rt->byte_size, eByteOrderLittle,1059 error) == 0)1060 return false;1061 1062 if (!WriteRegister(context, *reg_info_Rt, data_Rt))1063 return false;1064 } break;1065 default:1066 return false;1067 }1068 1069 if (wback) {1070 if (postindex)1071 address += offset;1072 1073 if (n == 31)1074 context.type = eContextAdjustStackPointer;1075 else1076 context.type = eContextAdjustBaseRegister;1077 context.SetImmediateSigned(offset);1078 1079 if (!WriteRegisterUnsigned(context, *reg_info_base, address))1080 return false;1081 }1082 return true;1083}1084 1085bool EmulateInstructionARM64::EmulateB(const uint32_t opcode) {1086#if 01087 // ARM64 pseudo code...1088 if branch_type == BranchType_CALL then X[30] = PC[] + 4;1089 BranchTo(PC[] + offset, branch_type);1090#endif1091 1092 bool success = false;1093 1094 EmulateInstruction::Context context;1095 context.type = EmulateInstruction::eContextRelativeBranchImmediate;1096 const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric,1097 LLDB_REGNUM_GENERIC_PC, 0, &success);1098 if (!success)1099 return false;1100 1101 int64_t offset = llvm::SignExtend64<28>(Bits32(opcode, 25, 0) << 2);1102 BranchType branch_type = Bit32(opcode, 31) ? BranchType_CALL : BranchType_JMP;1103 addr_t target = pc + offset;1104 context.SetImmediateSigned(offset);1105 1106 switch (branch_type) {1107 case BranchType_CALL: {1108 addr_t x30 = pc + 4;1109 if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_lr_arm64, x30))1110 return false;1111 } break;1112 case BranchType_JMP:1113 break;1114 default:1115 return false;1116 }1117 1118 return BranchTo(context, 64, target);1119}1120 1121bool EmulateInstructionARM64::EmulateBcond(const uint32_t opcode) {1122#if 01123 // ARM64 pseudo code...1124 bits(64) offset = SignExtend(imm19:'00', 64);1125 bits(4) condition = cond;1126 if ConditionHolds(condition) then1127 BranchTo(PC[] + offset, BranchType_JMP);1128#endif1129 1130 if (ConditionHolds(Bits32(opcode, 3, 0))) {1131 bool success = false;1132 1133 const uint64_t pc = ReadRegisterUnsigned(1134 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);1135 if (!success)1136 return false;1137 1138 int64_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2);1139 addr_t target = pc + offset;1140 1141 EmulateInstruction::Context context;1142 context.type = EmulateInstruction::eContextRelativeBranchImmediate;1143 context.SetImmediateSigned(offset);1144 if (!BranchTo(context, 64, target))1145 return false;1146 }1147 return true;1148}1149 1150bool EmulateInstructionARM64::EmulateCBZ(const uint32_t opcode) {1151#if 01152 integer t = UInt(Rt);1153 integer datasize = if sf == '1' then 64 else 32;1154 boolean iszero = (op == '0');1155 bits(64) offset = SignExtend(imm19:'00', 64);1156 1157 bits(datasize) operand1 = X[t];1158 if IsZero(operand1) == iszero then1159 BranchTo(PC[] + offset, BranchType_JMP);1160#endif1161 1162 bool success = false;1163 1164 uint32_t t = Bits32(opcode, 4, 0);1165 bool is_zero = Bit32(opcode, 24) == 0;1166 int32_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2);1167 1168 const uint64_t operand =1169 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success);1170 if (!success)1171 return false;1172 1173 if (m_ignore_conditions || ((operand == 0) == is_zero)) {1174 const uint64_t pc = ReadRegisterUnsigned(1175 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);1176 if (!success)1177 return false;1178 1179 EmulateInstruction::Context context;1180 context.type = EmulateInstruction::eContextRelativeBranchImmediate;1181 context.SetImmediateSigned(offset);1182 if (!BranchTo(context, 64, pc + offset))1183 return false;1184 }1185 return true;1186}1187 1188bool EmulateInstructionARM64::EmulateTBZ(const uint32_t opcode) {1189#if 01190 integer t = UInt(Rt);1191 integer datasize = if b5 == '1' then 64 else 32;1192 integer bit_pos = UInt(b5:b40);1193 bit bit_val = op;1194 bits(64) offset = SignExtend(imm14:'00', 64);1195#endif1196 1197 bool success = false;1198 1199 uint32_t t = Bits32(opcode, 4, 0);1200 uint32_t bit_pos = (Bit32(opcode, 31) << 6) | (Bits32(opcode, 23, 19));1201 uint32_t bit_val = Bit32(opcode, 24);1202 int64_t offset = llvm::SignExtend64<16>(Bits32(opcode, 18, 5) << 2);1203 1204 const uint64_t operand =1205 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success);1206 if (!success)1207 return false;1208 1209 if (m_ignore_conditions || Bit32(operand, bit_pos) == bit_val) {1210 const uint64_t pc = ReadRegisterUnsigned(1211 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);1212 if (!success)1213 return false;1214 1215 EmulateInstruction::Context context;1216 context.type = EmulateInstruction::eContextRelativeBranchImmediate;1217 context.SetImmediateSigned(offset);1218 if (!BranchTo(context, 64, pc + offset))1219 return false;1220 }1221 return true;1222}1223