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