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