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