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