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