1314564Sdim//===-- RegisterContextDarwin_arm64.cpp ---------------------------*- C++
2314564Sdim//-*-===//
3275072Semaste//
4353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5353358Sdim// See https://llvm.org/LICENSE.txt for license information.
6353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7275072Semaste//
8275072Semaste//===----------------------------------------------------------------------===//
9275072Semaste
10275072Semaste#include "RegisterContextDarwin_arm64.h"
11341825Sdim#include "RegisterContextDarwinConstants.h"
12275072Semaste
13314564Sdim#include "lldb/Target/Process.h"
14314564Sdim#include "lldb/Target/Thread.h"
15321369Sdim#include "lldb/Utility/DataBufferHeap.h"
16321369Sdim#include "lldb/Utility/DataExtractor.h"
17321369Sdim#include "lldb/Utility/Endian.h"
18321369Sdim#include "lldb/Utility/Log.h"
19344779Sdim#include "lldb/Utility/RegisterValue.h"
20344779Sdim#include "lldb/Utility/Scalar.h"
21275072Semaste#include "llvm/ADT/STLExtras.h"
22275072Semaste#include "llvm/Support/Compiler.h"
23275072Semaste
24275072Semaste#include "Plugins/Process/Utility/InstructionUtils.h"
25275072Semaste
26353358Sdim#include <memory>
27353358Sdim
28360784Sdim#if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))
29360784Sdim#include <sys/types.h>
30360784Sdim#include <sys/sysctl.h>
31275072Semaste#endif
32275072Semaste
33341825Sdim#include "Utility/ARM64_DWARF_Registers.h"
34275072Semaste
35275072Semasteusing namespace lldb;
36275072Semasteusing namespace lldb_private;
37275072Semaste
38314564Sdim#define GPR_OFFSET(idx) ((idx)*8)
39314564Sdim#define GPR_OFFSET_NAME(reg)                                                   \
40314564Sdim  (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::GPR, reg))
41275072Semaste
42314564Sdim#define FPU_OFFSET(idx) ((idx)*16 + sizeof(RegisterContextDarwin_arm64::GPR))
43314564Sdim#define FPU_OFFSET_NAME(reg)                                                   \
44314564Sdim  (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::FPU, reg))
45275072Semaste
46314564Sdim#define EXC_OFFSET_NAME(reg)                                                   \
47314564Sdim  (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::EXC, reg) +            \
48314564Sdim   sizeof(RegisterContextDarwin_arm64::GPR) +                                  \
49314564Sdim   sizeof(RegisterContextDarwin_arm64::FPU))
50314564Sdim#define DBG_OFFSET_NAME(reg)                                                   \
51314564Sdim  (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::DBG, reg) +            \
52314564Sdim   sizeof(RegisterContextDarwin_arm64::GPR) +                                  \
53314564Sdim   sizeof(RegisterContextDarwin_arm64::FPU) +                                  \
54314564Sdim   sizeof(RegisterContextDarwin_arm64::EXC))
55275072Semaste
56314564Sdim#define DEFINE_DBG(reg, i)                                                     \
57314564Sdim  #reg, NULL,                                                                  \
58314564Sdim      sizeof(((RegisterContextDarwin_arm64::DBG *) NULL)->reg[i]),             \
59314564Sdim              DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex,              \
60314564Sdim                              {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       \
61314564Sdim                               LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       \
62314564Sdim                               LLDB_INVALID_REGNUM },                          \
63314564Sdim                               NULL, NULL, NULL, 0
64314564Sdim#define REG_CONTEXT_SIZE                                                       \
65314564Sdim  (sizeof(RegisterContextDarwin_arm64::GPR) +                                  \
66314564Sdim   sizeof(RegisterContextDarwin_arm64::FPU) +                                  \
67314564Sdim   sizeof(RegisterContextDarwin_arm64::EXC))
68275072Semaste
69275072Semaste// Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure.
70275072Semaste#define DECLARE_REGISTER_INFOS_ARM64_STRUCT
71275072Semaste#include "RegisterInfos_arm64.h"
72275072Semaste#undef DECLARE_REGISTER_INFOS_ARM64_STRUCT
73275072Semaste
74275072Semaste// General purpose registers
75314564Sdimstatic uint32_t g_gpr_regnums[] = {
76314564Sdim    gpr_x0,  gpr_x1,  gpr_x2,  gpr_x3,  gpr_x4,  gpr_x5,  gpr_x6,
77314564Sdim    gpr_x7,  gpr_x8,  gpr_x9,  gpr_x10, gpr_x11, gpr_x12, gpr_x13,
78314564Sdim    gpr_x14, gpr_x15, gpr_x16, gpr_x17, gpr_x18, gpr_x19, gpr_x20,
79314564Sdim    gpr_x21, gpr_x22, gpr_x23, gpr_x24, gpr_x25, gpr_x26, gpr_x27,
80314564Sdim    gpr_x28, gpr_fp,  gpr_lr,  gpr_sp,  gpr_pc,  gpr_cpsr};
81275072Semaste
82275072Semaste// Floating point registers
83314564Sdimstatic uint32_t g_fpu_regnums[] = {
84314564Sdim    fpu_v0,  fpu_v1,  fpu_v2,  fpu_v3,  fpu_v4,   fpu_v5,  fpu_v6,
85314564Sdim    fpu_v7,  fpu_v8,  fpu_v9,  fpu_v10, fpu_v11,  fpu_v12, fpu_v13,
86314564Sdim    fpu_v14, fpu_v15, fpu_v16, fpu_v17, fpu_v18,  fpu_v19, fpu_v20,
87314564Sdim    fpu_v21, fpu_v22, fpu_v23, fpu_v24, fpu_v25,  fpu_v26, fpu_v27,
88314564Sdim    fpu_v28, fpu_v29, fpu_v30, fpu_v31, fpu_fpsr, fpu_fpcr};
89275072Semaste
90275072Semaste// Exception registers
91275072Semaste
92314564Sdimstatic uint32_t g_exc_regnums[] = {exc_far, exc_esr, exc_exception};
93275072Semaste
94314564Sdimstatic size_t k_num_register_infos =
95314564Sdim    llvm::array_lengthof(g_register_infos_arm64_le);
96275072Semaste
97314564SdimRegisterContextDarwin_arm64::RegisterContextDarwin_arm64(
98314564Sdim    Thread &thread, uint32_t concrete_frame_idx)
99314564Sdim    : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() {
100314564Sdim  uint32_t i;
101314564Sdim  for (i = 0; i < kNumErrors; i++) {
102314564Sdim    gpr_errs[i] = -1;
103314564Sdim    fpu_errs[i] = -1;
104314564Sdim    exc_errs[i] = -1;
105314564Sdim  }
106296417Sdim}
107296417Sdim
108314564SdimRegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() {}
109296417Sdim
110314564Sdimvoid RegisterContextDarwin_arm64::InvalidateAllRegisters() {
111314564Sdim  InvalidateAllRegisterStates();
112275072Semaste}
113275072Semaste
114314564Sdimsize_t RegisterContextDarwin_arm64::GetRegisterCount() {
115314564Sdim  assert(k_num_register_infos == k_num_registers);
116314564Sdim  return k_num_registers;
117275072Semaste}
118275072Semaste
119275072Semasteconst RegisterInfo *
120314564SdimRegisterContextDarwin_arm64::GetRegisterInfoAtIndex(size_t reg) {
121314564Sdim  assert(k_num_register_infos == k_num_registers);
122314564Sdim  if (reg < k_num_registers)
123314564Sdim    return &g_register_infos_arm64_le[reg];
124353358Sdim  return nullptr;
125275072Semaste}
126275072Semaste
127314564Sdimsize_t RegisterContextDarwin_arm64::GetRegisterInfosCount() {
128314564Sdim  return k_num_register_infos;
129275072Semaste}
130275072Semaste
131314564Sdimconst RegisterInfo *RegisterContextDarwin_arm64::GetRegisterInfos() {
132314564Sdim  return g_register_infos_arm64_le;
133275072Semaste}
134275072Semaste
135275072Semaste// Number of registers in each register set
136275072Semasteconst size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
137275072Semasteconst size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
138275072Semasteconst size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
139275072Semaste
140341825Sdim// Register set definitions. The first definitions at register set index of
141341825Sdim// zero is for all registers, followed by other registers sets. The register
142341825Sdim// information for the all register set need not be filled in.
143314564Sdimstatic const RegisterSet g_reg_sets[] = {
144314564Sdim    {
145314564Sdim        "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums,
146314564Sdim    },
147314564Sdim    {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums},
148314564Sdim    {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}};
149275072Semaste
150275072Semasteconst size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
151275072Semaste
152314564Sdimsize_t RegisterContextDarwin_arm64::GetRegisterSetCount() {
153314564Sdim  return k_num_regsets;
154275072Semaste}
155275072Semaste
156314564Sdimconst RegisterSet *RegisterContextDarwin_arm64::GetRegisterSet(size_t reg_set) {
157314564Sdim  if (reg_set < k_num_regsets)
158314564Sdim    return &g_reg_sets[reg_set];
159353358Sdim  return nullptr;
160275072Semaste}
161275072Semaste
162275072Semaste// Register information definitions for arm64
163314564Sdimint RegisterContextDarwin_arm64::GetSetForNativeRegNum(int reg) {
164314564Sdim  if (reg < fpu_v0)
165314564Sdim    return GPRRegSet;
166314564Sdim  else if (reg < exc_far)
167314564Sdim    return FPURegSet;
168314564Sdim  else if (reg < k_num_registers)
169314564Sdim    return EXCRegSet;
170314564Sdim  return -1;
171275072Semaste}
172275072Semaste
173314564Sdimint RegisterContextDarwin_arm64::ReadGPR(bool force) {
174314564Sdim  int set = GPRRegSet;
175314564Sdim  if (force || !RegisterSetIsCached(set)) {
176314564Sdim    SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
177314564Sdim  }
178314564Sdim  return GetError(GPRRegSet, Read);
179275072Semaste}
180275072Semaste
181314564Sdimint RegisterContextDarwin_arm64::ReadFPU(bool force) {
182314564Sdim  int set = FPURegSet;
183314564Sdim  if (force || !RegisterSetIsCached(set)) {
184314564Sdim    SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
185314564Sdim  }
186314564Sdim  return GetError(FPURegSet, Read);
187275072Semaste}
188275072Semaste
189314564Sdimint RegisterContextDarwin_arm64::ReadEXC(bool force) {
190314564Sdim  int set = EXCRegSet;
191314564Sdim  if (force || !RegisterSetIsCached(set)) {
192314564Sdim    SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
193314564Sdim  }
194314564Sdim  return GetError(EXCRegSet, Read);
195275072Semaste}
196275072Semaste
197314564Sdimint RegisterContextDarwin_arm64::ReadDBG(bool force) {
198314564Sdim  int set = DBGRegSet;
199314564Sdim  if (force || !RegisterSetIsCached(set)) {
200314564Sdim    SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));
201314564Sdim  }
202314564Sdim  return GetError(DBGRegSet, Read);
203275072Semaste}
204275072Semaste
205314564Sdimint RegisterContextDarwin_arm64::WriteGPR() {
206314564Sdim  int set = GPRRegSet;
207314564Sdim  if (!RegisterSetIsCached(set)) {
208314564Sdim    SetError(set, Write, -1);
209314564Sdim    return KERN_INVALID_ARGUMENT;
210314564Sdim  }
211314564Sdim  SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));
212314564Sdim  SetError(set, Read, -1);
213314564Sdim  return GetError(GPRRegSet, Write);
214275072Semaste}
215275072Semaste
216314564Sdimint RegisterContextDarwin_arm64::WriteFPU() {
217314564Sdim  int set = FPURegSet;
218314564Sdim  if (!RegisterSetIsCached(set)) {
219314564Sdim    SetError(set, Write, -1);
220314564Sdim    return KERN_INVALID_ARGUMENT;
221314564Sdim  }
222314564Sdim  SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu));
223314564Sdim  SetError(set, Read, -1);
224314564Sdim  return GetError(FPURegSet, Write);
225275072Semaste}
226275072Semaste
227314564Sdimint RegisterContextDarwin_arm64::WriteEXC() {
228314564Sdim  int set = EXCRegSet;
229314564Sdim  if (!RegisterSetIsCached(set)) {
230314564Sdim    SetError(set, Write, -1);
231314564Sdim    return KERN_INVALID_ARGUMENT;
232314564Sdim  }
233314564Sdim  SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));
234314564Sdim  SetError(set, Read, -1);
235314564Sdim  return GetError(EXCRegSet, Write);
236275072Semaste}
237275072Semaste
238314564Sdimint RegisterContextDarwin_arm64::WriteDBG() {
239314564Sdim  int set = DBGRegSet;
240314564Sdim  if (!RegisterSetIsCached(set)) {
241314564Sdim    SetError(set, Write, -1);
242314564Sdim    return KERN_INVALID_ARGUMENT;
243314564Sdim  }
244314564Sdim  SetError(set, Write, DoWriteDBG(GetThreadID(), set, dbg));
245314564Sdim  SetError(set, Read, -1);
246314564Sdim  return GetError(DBGRegSet, Write);
247275072Semaste}
248275072Semaste
249314564Sdimint RegisterContextDarwin_arm64::ReadRegisterSet(uint32_t set, bool force) {
250314564Sdim  switch (set) {
251314564Sdim  case GPRRegSet:
252314564Sdim    return ReadGPR(force);
253314564Sdim  case FPURegSet:
254314564Sdim    return ReadFPU(force);
255314564Sdim  case EXCRegSet:
256314564Sdim    return ReadEXC(force);
257314564Sdim  case DBGRegSet:
258314564Sdim    return ReadDBG(force);
259314564Sdim  default:
260314564Sdim    break;
261314564Sdim  }
262314564Sdim  return KERN_INVALID_ARGUMENT;
263275072Semaste}
264275072Semaste
265314564Sdimint RegisterContextDarwin_arm64::WriteRegisterSet(uint32_t set) {
266314564Sdim  // Make sure we have a valid context to set.
267314564Sdim  if (RegisterSetIsCached(set)) {
268314564Sdim    switch (set) {
269314564Sdim    case GPRRegSet:
270314564Sdim      return WriteGPR();
271314564Sdim    case FPURegSet:
272314564Sdim      return WriteFPU();
273314564Sdim    case EXCRegSet:
274314564Sdim      return WriteEXC();
275314564Sdim    case DBGRegSet:
276314564Sdim      return WriteDBG();
277314564Sdim    default:
278314564Sdim      break;
279275072Semaste    }
280314564Sdim  }
281314564Sdim  return KERN_INVALID_ARGUMENT;
282275072Semaste}
283275072Semaste
284314564Sdimvoid RegisterContextDarwin_arm64::LogDBGRegisters(Log *log, const DBG &dbg) {
285314564Sdim  if (log) {
286314564Sdim    for (uint32_t i = 0; i < 16; i++)
287360784Sdim      LLDB_LOGF(log,
288360784Sdim                "BVR%-2u/BCR%-2u = { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64
289360784Sdim                " } WVR%-2u/WCR%-2u "
290360784Sdim                "= { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 " }",
291360784Sdim                i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]);
292314564Sdim  }
293275072Semaste}
294275072Semaste
295314564Sdimbool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info,
296314564Sdim                                               RegisterValue &value) {
297314564Sdim  const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
298314564Sdim  int set = RegisterContextDarwin_arm64::GetSetForNativeRegNum(reg);
299275072Semaste
300314564Sdim  if (set == -1)
301314564Sdim    return false;
302275072Semaste
303314564Sdim  if (ReadRegisterSet(set, false) != KERN_SUCCESS)
304314564Sdim    return false;
305275072Semaste
306314564Sdim  switch (reg) {
307314564Sdim  case gpr_x0:
308314564Sdim  case gpr_x1:
309314564Sdim  case gpr_x2:
310314564Sdim  case gpr_x3:
311314564Sdim  case gpr_x4:
312314564Sdim  case gpr_x5:
313314564Sdim  case gpr_x6:
314314564Sdim  case gpr_x7:
315314564Sdim  case gpr_x8:
316314564Sdim  case gpr_x9:
317314564Sdim  case gpr_x10:
318314564Sdim  case gpr_x11:
319314564Sdim  case gpr_x12:
320314564Sdim  case gpr_x13:
321314564Sdim  case gpr_x14:
322314564Sdim  case gpr_x15:
323314564Sdim  case gpr_x16:
324314564Sdim  case gpr_x17:
325314564Sdim  case gpr_x18:
326314564Sdim  case gpr_x19:
327314564Sdim  case gpr_x20:
328314564Sdim  case gpr_x21:
329314564Sdim  case gpr_x22:
330314564Sdim  case gpr_x23:
331314564Sdim  case gpr_x24:
332314564Sdim  case gpr_x25:
333314564Sdim  case gpr_x26:
334314564Sdim  case gpr_x27:
335314564Sdim  case gpr_x28:
336344779Sdim    value.SetUInt64(gpr.x[reg - gpr_x0]);
337344779Sdim    break;
338314564Sdim  case gpr_fp:
339344779Sdim    value.SetUInt64(gpr.fp);
340344779Sdim    break;
341314564Sdim  case gpr_sp:
342344779Sdim    value.SetUInt64(gpr.sp);
343344779Sdim    break;
344314564Sdim  case gpr_lr:
345344779Sdim    value.SetUInt64(gpr.lr);
346344779Sdim    break;
347314564Sdim  case gpr_pc:
348344779Sdim    value.SetUInt64(gpr.pc);
349344779Sdim    break;
350314564Sdim  case gpr_cpsr:
351344779Sdim    value.SetUInt64(gpr.cpsr);
352314564Sdim    break;
353275072Semaste
354314564Sdim  case gpr_w0:
355314564Sdim  case gpr_w1:
356314564Sdim  case gpr_w2:
357314564Sdim  case gpr_w3:
358314564Sdim  case gpr_w4:
359314564Sdim  case gpr_w5:
360314564Sdim  case gpr_w6:
361314564Sdim  case gpr_w7:
362314564Sdim  case gpr_w8:
363314564Sdim  case gpr_w9:
364314564Sdim  case gpr_w10:
365314564Sdim  case gpr_w11:
366314564Sdim  case gpr_w12:
367314564Sdim  case gpr_w13:
368314564Sdim  case gpr_w14:
369314564Sdim  case gpr_w15:
370314564Sdim  case gpr_w16:
371314564Sdim  case gpr_w17:
372314564Sdim  case gpr_w18:
373314564Sdim  case gpr_w19:
374314564Sdim  case gpr_w20:
375314564Sdim  case gpr_w21:
376314564Sdim  case gpr_w22:
377314564Sdim  case gpr_w23:
378314564Sdim  case gpr_w24:
379314564Sdim  case gpr_w25:
380314564Sdim  case gpr_w26:
381314564Sdim  case gpr_w27:
382314564Sdim  case gpr_w28: {
383314564Sdim    ProcessSP process_sp(m_thread.GetProcess());
384314564Sdim    if (process_sp.get()) {
385314564Sdim      DataExtractor regdata(&gpr.x[reg - gpr_w0], 8, process_sp->GetByteOrder(),
386314564Sdim                            process_sp->GetAddressByteSize());
387314564Sdim      offset_t offset = 0;
388314564Sdim      uint64_t retval = regdata.GetMaxU64(&offset, 8);
389314564Sdim      uint32_t retval_lower32 = static_cast<uint32_t>(retval & 0xffffffff);
390314564Sdim      value.SetUInt32(retval_lower32);
391314564Sdim    }
392314564Sdim  } break;
393275072Semaste
394314564Sdim  case fpu_v0:
395314564Sdim  case fpu_v1:
396314564Sdim  case fpu_v2:
397314564Sdim  case fpu_v3:
398314564Sdim  case fpu_v4:
399314564Sdim  case fpu_v5:
400314564Sdim  case fpu_v6:
401314564Sdim  case fpu_v7:
402314564Sdim  case fpu_v8:
403314564Sdim  case fpu_v9:
404314564Sdim  case fpu_v10:
405314564Sdim  case fpu_v11:
406314564Sdim  case fpu_v12:
407314564Sdim  case fpu_v13:
408314564Sdim  case fpu_v14:
409314564Sdim  case fpu_v15:
410314564Sdim  case fpu_v16:
411314564Sdim  case fpu_v17:
412314564Sdim  case fpu_v18:
413314564Sdim  case fpu_v19:
414314564Sdim  case fpu_v20:
415314564Sdim  case fpu_v21:
416314564Sdim  case fpu_v22:
417314564Sdim  case fpu_v23:
418314564Sdim  case fpu_v24:
419314564Sdim  case fpu_v25:
420314564Sdim  case fpu_v26:
421314564Sdim  case fpu_v27:
422314564Sdim  case fpu_v28:
423314564Sdim  case fpu_v29:
424314564Sdim  case fpu_v30:
425314564Sdim  case fpu_v31:
426360784Sdim    value.SetBytes(fpu.v[reg - fpu_v0].bytes, reg_info->byte_size,
427314564Sdim                   endian::InlHostByteOrder());
428314564Sdim    break;
429275072Semaste
430314564Sdim  case fpu_s0:
431314564Sdim  case fpu_s1:
432314564Sdim  case fpu_s2:
433314564Sdim  case fpu_s3:
434314564Sdim  case fpu_s4:
435314564Sdim  case fpu_s5:
436314564Sdim  case fpu_s6:
437314564Sdim  case fpu_s7:
438314564Sdim  case fpu_s8:
439314564Sdim  case fpu_s9:
440314564Sdim  case fpu_s10:
441314564Sdim  case fpu_s11:
442314564Sdim  case fpu_s12:
443314564Sdim  case fpu_s13:
444314564Sdim  case fpu_s14:
445314564Sdim  case fpu_s15:
446314564Sdim  case fpu_s16:
447314564Sdim  case fpu_s17:
448314564Sdim  case fpu_s18:
449314564Sdim  case fpu_s19:
450314564Sdim  case fpu_s20:
451314564Sdim  case fpu_s21:
452314564Sdim  case fpu_s22:
453314564Sdim  case fpu_s23:
454314564Sdim  case fpu_s24:
455314564Sdim  case fpu_s25:
456314564Sdim  case fpu_s26:
457314564Sdim  case fpu_s27:
458314564Sdim  case fpu_s28:
459314564Sdim  case fpu_s29:
460314564Sdim  case fpu_s30:
461314564Sdim  case fpu_s31: {
462314564Sdim    ProcessSP process_sp(m_thread.GetProcess());
463314564Sdim    if (process_sp.get()) {
464314564Sdim      DataExtractor regdata(&fpu.v[reg - fpu_s0], 4, process_sp->GetByteOrder(),
465314564Sdim                            process_sp->GetAddressByteSize());
466314564Sdim      offset_t offset = 0;
467314564Sdim      value.SetFloat(regdata.GetFloat(&offset));
468314564Sdim    }
469314564Sdim  } break;
470275072Semaste
471314564Sdim  case fpu_d0:
472314564Sdim  case fpu_d1:
473314564Sdim  case fpu_d2:
474314564Sdim  case fpu_d3:
475314564Sdim  case fpu_d4:
476314564Sdim  case fpu_d5:
477314564Sdim  case fpu_d6:
478314564Sdim  case fpu_d7:
479314564Sdim  case fpu_d8:
480314564Sdim  case fpu_d9:
481314564Sdim  case fpu_d10:
482314564Sdim  case fpu_d11:
483314564Sdim  case fpu_d12:
484314564Sdim  case fpu_d13:
485314564Sdim  case fpu_d14:
486314564Sdim  case fpu_d15:
487314564Sdim  case fpu_d16:
488314564Sdim  case fpu_d17:
489314564Sdim  case fpu_d18:
490314564Sdim  case fpu_d19:
491314564Sdim  case fpu_d20:
492314564Sdim  case fpu_d21:
493314564Sdim  case fpu_d22:
494314564Sdim  case fpu_d23:
495314564Sdim  case fpu_d24:
496314564Sdim  case fpu_d25:
497314564Sdim  case fpu_d26:
498314564Sdim  case fpu_d27:
499314564Sdim  case fpu_d28:
500314564Sdim  case fpu_d29:
501314564Sdim  case fpu_d30:
502314564Sdim  case fpu_d31: {
503314564Sdim    ProcessSP process_sp(m_thread.GetProcess());
504314564Sdim    if (process_sp.get()) {
505360784Sdim      DataExtractor regdata(&fpu.v[reg - fpu_d0], 8, process_sp->GetByteOrder(),
506314564Sdim                            process_sp->GetAddressByteSize());
507314564Sdim      offset_t offset = 0;
508314564Sdim      value.SetDouble(regdata.GetDouble(&offset));
509314564Sdim    }
510314564Sdim  } break;
511275072Semaste
512314564Sdim  case fpu_fpsr:
513314564Sdim    value.SetUInt32(fpu.fpsr);
514314564Sdim    break;
515275072Semaste
516314564Sdim  case fpu_fpcr:
517314564Sdim    value.SetUInt32(fpu.fpcr);
518314564Sdim    break;
519275072Semaste
520314564Sdim  case exc_exception:
521314564Sdim    value.SetUInt32(exc.exception);
522314564Sdim    break;
523314564Sdim  case exc_esr:
524314564Sdim    value.SetUInt32(exc.esr);
525314564Sdim    break;
526314564Sdim  case exc_far:
527314564Sdim    value.SetUInt64(exc.far);
528314564Sdim    break;
529314564Sdim
530314564Sdim  default:
531314564Sdim    value.SetValueToInvalid();
532314564Sdim    return false;
533314564Sdim  }
534314564Sdim  return true;
535275072Semaste}
536275072Semaste
537314564Sdimbool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info,
538314564Sdim                                                const RegisterValue &value) {
539314564Sdim  const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
540314564Sdim  int set = GetSetForNativeRegNum(reg);
541275072Semaste
542314564Sdim  if (set == -1)
543314564Sdim    return false;
544275072Semaste
545314564Sdim  if (ReadRegisterSet(set, false) != KERN_SUCCESS)
546314564Sdim    return false;
547275072Semaste
548314564Sdim  switch (reg) {
549314564Sdim  case gpr_x0:
550314564Sdim  case gpr_x1:
551314564Sdim  case gpr_x2:
552314564Sdim  case gpr_x3:
553314564Sdim  case gpr_x4:
554314564Sdim  case gpr_x5:
555314564Sdim  case gpr_x6:
556314564Sdim  case gpr_x7:
557314564Sdim  case gpr_x8:
558314564Sdim  case gpr_x9:
559314564Sdim  case gpr_x10:
560314564Sdim  case gpr_x11:
561314564Sdim  case gpr_x12:
562314564Sdim  case gpr_x13:
563314564Sdim  case gpr_x14:
564314564Sdim  case gpr_x15:
565314564Sdim  case gpr_x16:
566314564Sdim  case gpr_x17:
567314564Sdim  case gpr_x18:
568314564Sdim  case gpr_x19:
569314564Sdim  case gpr_x20:
570314564Sdim  case gpr_x21:
571314564Sdim  case gpr_x22:
572314564Sdim  case gpr_x23:
573314564Sdim  case gpr_x24:
574314564Sdim  case gpr_x25:
575314564Sdim  case gpr_x26:
576314564Sdim  case gpr_x27:
577314564Sdim  case gpr_x28:
578314564Sdim  case gpr_fp:
579314564Sdim  case gpr_sp:
580314564Sdim  case gpr_lr:
581314564Sdim  case gpr_pc:
582314564Sdim  case gpr_cpsr:
583314564Sdim    gpr.x[reg - gpr_x0] = value.GetAsUInt64();
584314564Sdim    break;
585275072Semaste
586314564Sdim  case fpu_v0:
587314564Sdim  case fpu_v1:
588314564Sdim  case fpu_v2:
589314564Sdim  case fpu_v3:
590314564Sdim  case fpu_v4:
591314564Sdim  case fpu_v5:
592314564Sdim  case fpu_v6:
593314564Sdim  case fpu_v7:
594314564Sdim  case fpu_v8:
595314564Sdim  case fpu_v9:
596314564Sdim  case fpu_v10:
597314564Sdim  case fpu_v11:
598314564Sdim  case fpu_v12:
599314564Sdim  case fpu_v13:
600314564Sdim  case fpu_v14:
601314564Sdim  case fpu_v15:
602314564Sdim  case fpu_v16:
603314564Sdim  case fpu_v17:
604314564Sdim  case fpu_v18:
605314564Sdim  case fpu_v19:
606314564Sdim  case fpu_v20:
607314564Sdim  case fpu_v21:
608314564Sdim  case fpu_v22:
609314564Sdim  case fpu_v23:
610314564Sdim  case fpu_v24:
611314564Sdim  case fpu_v25:
612314564Sdim  case fpu_v26:
613314564Sdim  case fpu_v27:
614314564Sdim  case fpu_v28:
615314564Sdim  case fpu_v29:
616314564Sdim  case fpu_v30:
617314564Sdim  case fpu_v31:
618360784Sdim    ::memcpy(fpu.v[reg - fpu_v0].bytes, value.GetBytes(),
619353358Sdim             value.GetByteSize());
620314564Sdim    break;
621275072Semaste
622314564Sdim  case fpu_fpsr:
623314564Sdim    fpu.fpsr = value.GetAsUInt32();
624314564Sdim    break;
625275072Semaste
626314564Sdim  case fpu_fpcr:
627314564Sdim    fpu.fpcr = value.GetAsUInt32();
628314564Sdim    break;
629275072Semaste
630314564Sdim  case exc_exception:
631314564Sdim    exc.exception = value.GetAsUInt32();
632314564Sdim    break;
633314564Sdim  case exc_esr:
634314564Sdim    exc.esr = value.GetAsUInt32();
635314564Sdim    break;
636314564Sdim  case exc_far:
637314564Sdim    exc.far = value.GetAsUInt64();
638314564Sdim    break;
639275072Semaste
640314564Sdim  default:
641314564Sdim    return false;
642314564Sdim  }
643314564Sdim  return WriteRegisterSet(set) == KERN_SUCCESS;
644275072Semaste}
645275072Semaste
646314564Sdimbool RegisterContextDarwin_arm64::ReadAllRegisterValues(
647314564Sdim    lldb::DataBufferSP &data_sp) {
648353358Sdim  data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
649353358Sdim  if (ReadGPR(false) == KERN_SUCCESS && ReadFPU(false) == KERN_SUCCESS &&
650353358Sdim      ReadEXC(false) == KERN_SUCCESS) {
651314564Sdim    uint8_t *dst = data_sp->GetBytes();
652314564Sdim    ::memcpy(dst, &gpr, sizeof(gpr));
653314564Sdim    dst += sizeof(gpr);
654275072Semaste
655314564Sdim    ::memcpy(dst, &fpu, sizeof(fpu));
656314564Sdim    dst += sizeof(gpr);
657275072Semaste
658314564Sdim    ::memcpy(dst, &exc, sizeof(exc));
659314564Sdim    return true;
660314564Sdim  }
661314564Sdim  return false;
662275072Semaste}
663275072Semaste
664314564Sdimbool RegisterContextDarwin_arm64::WriteAllRegisterValues(
665314564Sdim    const lldb::DataBufferSP &data_sp) {
666314564Sdim  if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
667314564Sdim    const uint8_t *src = data_sp->GetBytes();
668314564Sdim    ::memcpy(&gpr, src, sizeof(gpr));
669314564Sdim    src += sizeof(gpr);
670275072Semaste
671314564Sdim    ::memcpy(&fpu, src, sizeof(fpu));
672314564Sdim    src += sizeof(gpr);
673275072Semaste
674314564Sdim    ::memcpy(&exc, src, sizeof(exc));
675314564Sdim    uint32_t success_count = 0;
676314564Sdim    if (WriteGPR() == KERN_SUCCESS)
677314564Sdim      ++success_count;
678314564Sdim    if (WriteFPU() == KERN_SUCCESS)
679314564Sdim      ++success_count;
680314564Sdim    if (WriteEXC() == KERN_SUCCESS)
681314564Sdim      ++success_count;
682314564Sdim    return success_count == 3;
683314564Sdim  }
684314564Sdim  return false;
685275072Semaste}
686275072Semaste
687314564Sdimuint32_t RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber(
688314564Sdim    RegisterKind kind, uint32_t reg) {
689314564Sdim  if (kind == eRegisterKindGeneric) {
690314564Sdim    switch (reg) {
691314564Sdim    case LLDB_REGNUM_GENERIC_PC:
692314564Sdim      return gpr_pc;
693314564Sdim    case LLDB_REGNUM_GENERIC_SP:
694314564Sdim      return gpr_sp;
695314564Sdim    case LLDB_REGNUM_GENERIC_FP:
696314564Sdim      return gpr_fp;
697314564Sdim    case LLDB_REGNUM_GENERIC_RA:
698314564Sdim      return gpr_lr;
699314564Sdim    case LLDB_REGNUM_GENERIC_FLAGS:
700314564Sdim      return gpr_cpsr;
701314564Sdim    default:
702314564Sdim      break;
703275072Semaste    }
704314564Sdim  } else if (kind == eRegisterKindDWARF) {
705314564Sdim    switch (reg) {
706314564Sdim    case arm64_dwarf::x0:
707314564Sdim      return gpr_x0;
708314564Sdim    case arm64_dwarf::x1:
709314564Sdim      return gpr_x1;
710314564Sdim    case arm64_dwarf::x2:
711314564Sdim      return gpr_x2;
712314564Sdim    case arm64_dwarf::x3:
713314564Sdim      return gpr_x3;
714314564Sdim    case arm64_dwarf::x4:
715314564Sdim      return gpr_x4;
716314564Sdim    case arm64_dwarf::x5:
717314564Sdim      return gpr_x5;
718314564Sdim    case arm64_dwarf::x6:
719314564Sdim      return gpr_x6;
720314564Sdim    case arm64_dwarf::x7:
721314564Sdim      return gpr_x7;
722314564Sdim    case arm64_dwarf::x8:
723314564Sdim      return gpr_x8;
724314564Sdim    case arm64_dwarf::x9:
725314564Sdim      return gpr_x9;
726314564Sdim    case arm64_dwarf::x10:
727314564Sdim      return gpr_x10;
728314564Sdim    case arm64_dwarf::x11:
729314564Sdim      return gpr_x11;
730314564Sdim    case arm64_dwarf::x12:
731314564Sdim      return gpr_x12;
732314564Sdim    case arm64_dwarf::x13:
733314564Sdim      return gpr_x13;
734314564Sdim    case arm64_dwarf::x14:
735314564Sdim      return gpr_x14;
736314564Sdim    case arm64_dwarf::x15:
737314564Sdim      return gpr_x15;
738314564Sdim    case arm64_dwarf::x16:
739314564Sdim      return gpr_x16;
740314564Sdim    case arm64_dwarf::x17:
741314564Sdim      return gpr_x17;
742314564Sdim    case arm64_dwarf::x18:
743314564Sdim      return gpr_x18;
744314564Sdim    case arm64_dwarf::x19:
745314564Sdim      return gpr_x19;
746314564Sdim    case arm64_dwarf::x20:
747314564Sdim      return gpr_x20;
748314564Sdim    case arm64_dwarf::x21:
749314564Sdim      return gpr_x21;
750314564Sdim    case arm64_dwarf::x22:
751314564Sdim      return gpr_x22;
752314564Sdim    case arm64_dwarf::x23:
753314564Sdim      return gpr_x23;
754314564Sdim    case arm64_dwarf::x24:
755314564Sdim      return gpr_x24;
756314564Sdim    case arm64_dwarf::x25:
757314564Sdim      return gpr_x25;
758314564Sdim    case arm64_dwarf::x26:
759314564Sdim      return gpr_x26;
760314564Sdim    case arm64_dwarf::x27:
761314564Sdim      return gpr_x27;
762314564Sdim    case arm64_dwarf::x28:
763314564Sdim      return gpr_x28;
764275072Semaste
765314564Sdim    case arm64_dwarf::fp:
766314564Sdim      return gpr_fp;
767314564Sdim    case arm64_dwarf::sp:
768314564Sdim      return gpr_sp;
769314564Sdim    case arm64_dwarf::lr:
770314564Sdim      return gpr_lr;
771314564Sdim    case arm64_dwarf::pc:
772314564Sdim      return gpr_pc;
773314564Sdim    case arm64_dwarf::cpsr:
774314564Sdim      return gpr_cpsr;
775275072Semaste
776314564Sdim    case arm64_dwarf::v0:
777314564Sdim      return fpu_v0;
778314564Sdim    case arm64_dwarf::v1:
779314564Sdim      return fpu_v1;
780314564Sdim    case arm64_dwarf::v2:
781314564Sdim      return fpu_v2;
782314564Sdim    case arm64_dwarf::v3:
783314564Sdim      return fpu_v3;
784314564Sdim    case arm64_dwarf::v4:
785314564Sdim      return fpu_v4;
786314564Sdim    case arm64_dwarf::v5:
787314564Sdim      return fpu_v5;
788314564Sdim    case arm64_dwarf::v6:
789314564Sdim      return fpu_v6;
790314564Sdim    case arm64_dwarf::v7:
791314564Sdim      return fpu_v7;
792314564Sdim    case arm64_dwarf::v8:
793314564Sdim      return fpu_v8;
794314564Sdim    case arm64_dwarf::v9:
795314564Sdim      return fpu_v9;
796314564Sdim    case arm64_dwarf::v10:
797314564Sdim      return fpu_v10;
798314564Sdim    case arm64_dwarf::v11:
799314564Sdim      return fpu_v11;
800314564Sdim    case arm64_dwarf::v12:
801314564Sdim      return fpu_v12;
802314564Sdim    case arm64_dwarf::v13:
803314564Sdim      return fpu_v13;
804314564Sdim    case arm64_dwarf::v14:
805314564Sdim      return fpu_v14;
806314564Sdim    case arm64_dwarf::v15:
807314564Sdim      return fpu_v15;
808314564Sdim    case arm64_dwarf::v16:
809314564Sdim      return fpu_v16;
810314564Sdim    case arm64_dwarf::v17:
811314564Sdim      return fpu_v17;
812314564Sdim    case arm64_dwarf::v18:
813314564Sdim      return fpu_v18;
814314564Sdim    case arm64_dwarf::v19:
815314564Sdim      return fpu_v19;
816314564Sdim    case arm64_dwarf::v20:
817314564Sdim      return fpu_v20;
818314564Sdim    case arm64_dwarf::v21:
819314564Sdim      return fpu_v21;
820314564Sdim    case arm64_dwarf::v22:
821314564Sdim      return fpu_v22;
822314564Sdim    case arm64_dwarf::v23:
823314564Sdim      return fpu_v23;
824314564Sdim    case arm64_dwarf::v24:
825314564Sdim      return fpu_v24;
826314564Sdim    case arm64_dwarf::v25:
827314564Sdim      return fpu_v25;
828314564Sdim    case arm64_dwarf::v26:
829314564Sdim      return fpu_v26;
830314564Sdim    case arm64_dwarf::v27:
831314564Sdim      return fpu_v27;
832314564Sdim    case arm64_dwarf::v28:
833314564Sdim      return fpu_v28;
834314564Sdim    case arm64_dwarf::v29:
835314564Sdim      return fpu_v29;
836314564Sdim    case arm64_dwarf::v30:
837314564Sdim      return fpu_v30;
838314564Sdim    case arm64_dwarf::v31:
839314564Sdim      return fpu_v31;
840275072Semaste
841314564Sdim    default:
842314564Sdim      break;
843275072Semaste    }
844314564Sdim  } else if (kind == eRegisterKindEHFrame) {
845314564Sdim    switch (reg) {
846314564Sdim    case arm64_ehframe::x0:
847314564Sdim      return gpr_x0;
848314564Sdim    case arm64_ehframe::x1:
849314564Sdim      return gpr_x1;
850314564Sdim    case arm64_ehframe::x2:
851314564Sdim      return gpr_x2;
852314564Sdim    case arm64_ehframe::x3:
853314564Sdim      return gpr_x3;
854314564Sdim    case arm64_ehframe::x4:
855314564Sdim      return gpr_x4;
856314564Sdim    case arm64_ehframe::x5:
857314564Sdim      return gpr_x5;
858314564Sdim    case arm64_ehframe::x6:
859314564Sdim      return gpr_x6;
860314564Sdim    case arm64_ehframe::x7:
861314564Sdim      return gpr_x7;
862314564Sdim    case arm64_ehframe::x8:
863314564Sdim      return gpr_x8;
864314564Sdim    case arm64_ehframe::x9:
865314564Sdim      return gpr_x9;
866314564Sdim    case arm64_ehframe::x10:
867314564Sdim      return gpr_x10;
868314564Sdim    case arm64_ehframe::x11:
869314564Sdim      return gpr_x11;
870314564Sdim    case arm64_ehframe::x12:
871314564Sdim      return gpr_x12;
872314564Sdim    case arm64_ehframe::x13:
873314564Sdim      return gpr_x13;
874314564Sdim    case arm64_ehframe::x14:
875314564Sdim      return gpr_x14;
876314564Sdim    case arm64_ehframe::x15:
877314564Sdim      return gpr_x15;
878314564Sdim    case arm64_ehframe::x16:
879314564Sdim      return gpr_x16;
880314564Sdim    case arm64_ehframe::x17:
881314564Sdim      return gpr_x17;
882314564Sdim    case arm64_ehframe::x18:
883314564Sdim      return gpr_x18;
884314564Sdim    case arm64_ehframe::x19:
885314564Sdim      return gpr_x19;
886314564Sdim    case arm64_ehframe::x20:
887314564Sdim      return gpr_x20;
888314564Sdim    case arm64_ehframe::x21:
889314564Sdim      return gpr_x21;
890314564Sdim    case arm64_ehframe::x22:
891314564Sdim      return gpr_x22;
892314564Sdim    case arm64_ehframe::x23:
893314564Sdim      return gpr_x23;
894314564Sdim    case arm64_ehframe::x24:
895314564Sdim      return gpr_x24;
896314564Sdim    case arm64_ehframe::x25:
897314564Sdim      return gpr_x25;
898314564Sdim    case arm64_ehframe::x26:
899314564Sdim      return gpr_x26;
900314564Sdim    case arm64_ehframe::x27:
901314564Sdim      return gpr_x27;
902314564Sdim    case arm64_ehframe::x28:
903314564Sdim      return gpr_x28;
904314564Sdim    case arm64_ehframe::fp:
905314564Sdim      return gpr_fp;
906314564Sdim    case arm64_ehframe::sp:
907314564Sdim      return gpr_sp;
908314564Sdim    case arm64_ehframe::lr:
909314564Sdim      return gpr_lr;
910314564Sdim    case arm64_ehframe::pc:
911314564Sdim      return gpr_pc;
912314564Sdim    case arm64_ehframe::cpsr:
913314564Sdim      return gpr_cpsr;
914275072Semaste    }
915314564Sdim  } else if (kind == eRegisterKindLLDB) {
916314564Sdim    return reg;
917314564Sdim  }
918314564Sdim  return LLDB_INVALID_REGNUM;
919275072Semaste}
920275072Semaste
921314564Sdimuint32_t RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints() {
922341825Sdim#if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))
923314564Sdim  // autodetect how many watchpoints are supported dynamically...
924314564Sdim  static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
925314564Sdim  if (g_num_supported_hw_watchpoints == UINT32_MAX) {
926314564Sdim    size_t len;
927314564Sdim    uint32_t n = 0;
928314564Sdim    len = sizeof(n);
929314564Sdim    if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) {
930314564Sdim      g_num_supported_hw_watchpoints = n;
931275072Semaste    }
932314564Sdim  }
933314564Sdim  return g_num_supported_hw_watchpoints;
934275072Semaste#else
935314564Sdim  // TODO: figure out remote case here!
936314564Sdim  return 2;
937275072Semaste#endif
938275072Semaste}
939275072Semaste
940314564Sdimuint32_t RegisterContextDarwin_arm64::SetHardwareWatchpoint(lldb::addr_t addr,
941314564Sdim                                                            size_t size,
942314564Sdim                                                            bool read,
943314564Sdim                                                            bool write) {
944314564Sdim  //    if (log) log->Printf
945314564Sdim  //    ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(addr = %8.8p,
946314564Sdim  //    size = %u, read = %u, write = %u)", addr, size, read, write);
947275072Semaste
948314564Sdim  const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
949275072Semaste
950314564Sdim  // Can't watch zero bytes
951314564Sdim  if (size == 0)
952314564Sdim    return LLDB_INVALID_INDEX32;
953275072Semaste
954314564Sdim  // We must watch for either read or write
955344779Sdim  if (!read && !write)
956314564Sdim    return LLDB_INVALID_INDEX32;
957275072Semaste
958314564Sdim  // Can't watch more than 4 bytes per WVR/WCR pair
959314564Sdim  if (size > 4)
960314564Sdim    return LLDB_INVALID_INDEX32;
961275072Semaste
962314564Sdim  // We can only watch up to four bytes that follow a 4 byte aligned address
963314564Sdim  // per watchpoint register pair. Since we have at most so we can only watch
964314564Sdim  // until the next 4 byte boundary and we need to make sure we can properly
965314564Sdim  // encode this.
966314564Sdim  uint32_t addr_word_offset = addr % 4;
967314564Sdim  //    if (log) log->Printf
968314564Sdim  //    ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() -
969314564Sdim  //    addr_word_offset = 0x%8.8x", addr_word_offset);
970275072Semaste
971314564Sdim  uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
972314564Sdim  //    if (log) log->Printf
973314564Sdim  //    ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - byte_mask =
974314564Sdim  //    0x%8.8x", byte_mask);
975314564Sdim  if (byte_mask > 0xfu)
976314564Sdim    return LLDB_INVALID_INDEX32;
977275072Semaste
978314564Sdim  // Read the debug state
979314564Sdim  int kret = ReadDBG(false);
980275072Semaste
981314564Sdim  if (kret == KERN_SUCCESS) {
982314564Sdim    // Check to make sure we have the needed hardware support
983314564Sdim    uint32_t i = 0;
984275072Semaste
985314564Sdim    for (i = 0; i < num_hw_watchpoints; ++i) {
986314564Sdim      if ((dbg.wcr[i] & WCR_ENABLE) == 0)
987314564Sdim        break; // We found an available hw breakpoint slot (in i)
988314564Sdim    }
989275072Semaste
990314564Sdim    // See if we found an available hw breakpoint slot above
991314564Sdim    if (i < num_hw_watchpoints) {
992314564Sdim      // Make the byte_mask into a valid Byte Address Select mask
993314564Sdim      uint32_t byte_address_select = byte_mask << 5;
994314564Sdim      // Make sure bits 1:0 are clear in our address
995314564Sdim      dbg.wvr[i] = addr & ~((lldb::addr_t)3);
996314564Sdim      dbg.wcr[i] = byte_address_select |     // Which bytes that follow the IMVA
997314564Sdim                                             // that we will watch
998314564Sdim                   S_USER |                  // Stop only in user mode
999314564Sdim                   (read ? WCR_LOAD : 0) |   // Stop on read access?
1000314564Sdim                   (write ? WCR_STORE : 0) | // Stop on write access?
1001314564Sdim                   WCR_ENABLE;               // Enable this watchpoint;
1002275072Semaste
1003314564Sdim      kret = WriteDBG();
1004314564Sdim      //            if (log) log->Printf
1005314564Sdim      //            ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint()
1006314564Sdim      //            WriteDBG() => 0x%8.8x.", kret);
1007275072Semaste
1008314564Sdim      if (kret == KERN_SUCCESS)
1009314564Sdim        return i;
1010314564Sdim    } else {
1011314564Sdim      //            if (log) log->Printf
1012314564Sdim      //            ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint():
1013314564Sdim      //            All hardware resources (%u) are in use.",
1014314564Sdim      //            num_hw_watchpoints);
1015275072Semaste    }
1016314564Sdim  }
1017314564Sdim  return LLDB_INVALID_INDEX32;
1018275072Semaste}
1019275072Semaste
1020314564Sdimbool RegisterContextDarwin_arm64::ClearHardwareWatchpoint(uint32_t hw_index) {
1021314564Sdim  int kret = ReadDBG(false);
1022275072Semaste
1023314564Sdim  const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
1024314564Sdim  if (kret == KERN_SUCCESS) {
1025314564Sdim    if (hw_index < num_hw_points) {
1026314564Sdim      dbg.wcr[hw_index] = 0;
1027314564Sdim      //            if (log) log->Printf
1028314564Sdim      //            ("RegisterContextDarwin_arm64::ClearHardwareWatchpoint( %u )
1029314564Sdim      //            - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
1030314564Sdim      //                    hw_index,
1031314564Sdim      //                    hw_index,
1032314564Sdim      //                    dbg.wvr[hw_index],
1033314564Sdim      //                    hw_index,
1034314564Sdim      //                    dbg.wcr[hw_index]);
1035275072Semaste
1036314564Sdim      kret = WriteDBG();
1037275072Semaste
1038314564Sdim      if (kret == KERN_SUCCESS)
1039314564Sdim        return true;
1040275072Semaste    }
1041314564Sdim  }
1042314564Sdim  return false;
1043275072Semaste}
1044