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