brintos

brintos / llvm-project-archived public Read only

0
0
Text · 38.6 KiB · f124424 Raw
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