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