RegisterContextDarwin_arm64.cpp revision 353358
1155408Srwatson//===-- RegisterContextDarwin_arm64.cpp ---------------------------*- C++
2155408Srwatson//-*-===//
3188315Srwatson//
4155408Srwatson// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5155408Srwatson// See https://llvm.org/LICENSE.txt for license information.
6155408Srwatson// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7155408Srwatson//
8155408Srwatson//===----------------------------------------------------------------------===//
9155408Srwatson
10155408Srwatson#include "RegisterContextDarwin_arm64.h"
11155408Srwatson#include "RegisterContextDarwinConstants.h"
12155408Srwatson
13155408Srwatson#include "lldb/Target/Process.h"
14155408Srwatson#include "lldb/Target/Thread.h"
15155408Srwatson#include "lldb/Utility/DataBufferHeap.h"
16155408Srwatson#include "lldb/Utility/DataExtractor.h"
17155408Srwatson#include "lldb/Utility/Endian.h"
18155408Srwatson#include "lldb/Utility/Log.h"
19155408Srwatson#include "lldb/Utility/RegisterValue.h"
20155408Srwatson#include "lldb/Utility/Scalar.h"
21155408Srwatson#include "llvm/ADT/STLExtras.h"
22155408Srwatson#include "llvm/Support/Compiler.h"
23155408Srwatson
24155408Srwatson#include "Plugins/Process/Utility/InstructionUtils.h"
25155408Srwatson
26155408Srwatson#include <memory>
27155408Srwatson
28155408Srwatson// Support building against older versions of LLVM, this macro was added
29155408Srwatson// recently.
30178186Srwatson#ifndef LLVM_EXTENSION
31178186Srwatson#define LLVM_EXTENSION
32178186Srwatson#endif
33155408Srwatson
34155408Srwatson#include "Utility/ARM64_DWARF_Registers.h"
35155408Srwatson
36155408Srwatsonusing namespace lldb;
37155408Srwatsonusing namespace lldb_private;
38155408Srwatson
39155408Srwatson#define GPR_OFFSET(idx) ((idx)*8)
40155408Srwatson#define GPR_OFFSET_NAME(reg)                                                   \
41155408Srwatson  (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::GPR, reg))
42155408Srwatson
43155408Srwatson#define FPU_OFFSET(idx) ((idx)*16 + sizeof(RegisterContextDarwin_arm64::GPR))
44155408Srwatson#define FPU_OFFSET_NAME(reg)                                                   \
45184488Srwatson  (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::FPU, reg))
46155408Srwatson
47155408Srwatson#define EXC_OFFSET_NAME(reg)                                                   \
48155408Srwatson  (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::EXC, reg) +            \
49155408Srwatson   sizeof(RegisterContextDarwin_arm64::GPR) +                                  \
50184508Srwatson   sizeof(RegisterContextDarwin_arm64::FPU))
51155408Srwatson#define DBG_OFFSET_NAME(reg)                                                   \
52155408Srwatson  (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::DBG, reg) +            \
53155408Srwatson   sizeof(RegisterContextDarwin_arm64::GPR) +                                  \
54155408Srwatson   sizeof(RegisterContextDarwin_arm64::FPU) +                                  \
55156880Srwatson   sizeof(RegisterContextDarwin_arm64::EXC))
56155408Srwatson
57155408Srwatson#define DEFINE_DBG(reg, i)                                                     \
58155408Srwatson  #reg, NULL,                                                                  \
59155408Srwatson      sizeof(((RegisterContextDarwin_arm64::DBG *) NULL)->reg[i]),             \
60184545Srwatson              DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex,              \
61184545Srwatson                              {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       \
62184545Srwatson                               LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       \
63184545Srwatson                               LLDB_INVALID_REGNUM },                          \
64155408Srwatson                               NULL, NULL, NULL, 0
65155408Srwatson#define REG_CONTEXT_SIZE                                                       \
66155408Srwatson  (sizeof(RegisterContextDarwin_arm64::GPR) +                                  \
67155408Srwatson   sizeof(RegisterContextDarwin_arm64::FPU) +                                  \
68155408Srwatson   sizeof(RegisterContextDarwin_arm64::EXC))
69155408Srwatson
70155408Srwatson// Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure.
71155408Srwatson#define DECLARE_REGISTER_INFOS_ARM64_STRUCT
72174894Swkoszek#include "RegisterInfos_arm64.h"
73159269Srwatson#undef DECLARE_REGISTER_INFOS_ARM64_STRUCT
74155408Srwatson
75155408Srwatson// General purpose registers
76155408Srwatsonstatic uint32_t g_gpr_regnums[] = {
77155408Srwatson    gpr_x0,  gpr_x1,  gpr_x2,  gpr_x3,  gpr_x4,  gpr_x5,  gpr_x6,
78156883Srwatson    gpr_x7,  gpr_x8,  gpr_x9,  gpr_x10, gpr_x11, gpr_x12, gpr_x13,
79188315Srwatson    gpr_x14, gpr_x15, gpr_x16, gpr_x17, gpr_x18, gpr_x19, gpr_x20,
80155408Srwatson    gpr_x21, gpr_x22, gpr_x23, gpr_x24, gpr_x25, gpr_x26, gpr_x27,
81155408Srwatson    gpr_x28, gpr_fp,  gpr_lr,  gpr_sp,  gpr_pc,  gpr_cpsr};
82155408Srwatson
83155408Srwatson// Floating point registers
84155408Srwatsonstatic uint32_t g_fpu_regnums[] = {
85155408Srwatson    fpu_v0,  fpu_v1,  fpu_v2,  fpu_v3,  fpu_v4,   fpu_v5,  fpu_v6,
86155408Srwatson    fpu_v7,  fpu_v8,  fpu_v9,  fpu_v10, fpu_v11,  fpu_v12, fpu_v13,
87155408Srwatson    fpu_v14, fpu_v15, fpu_v16, fpu_v17, fpu_v18,  fpu_v19, fpu_v20,
88155408Srwatson    fpu_v21, fpu_v22, fpu_v23, fpu_v24, fpu_v25,  fpu_v26, fpu_v27,
89155408Srwatson    fpu_v28, fpu_v29, fpu_v30, fpu_v31, fpu_fpsr, fpu_fpcr};
90155408Srwatson
91155408Srwatson// Exception registers
92159269Srwatson
93159269Srwatsonstatic uint32_t g_exc_regnums[] = {exc_far, exc_esr, exc_exception};
94159269Srwatson
95159269Srwatsonstatic size_t k_num_register_infos =
96159269Srwatson    llvm::array_lengthof(g_register_infos_arm64_le);
97159269Srwatson
98159269SrwatsonRegisterContextDarwin_arm64::RegisterContextDarwin_arm64(
99159269Srwatson    Thread &thread, uint32_t concrete_frame_idx)
100159269Srwatson    : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() {
101159269Srwatson  uint32_t i;
102159269Srwatson  for (i = 0; i < kNumErrors; i++) {
103159269Srwatson    gpr_errs[i] = -1;
104159269Srwatson    fpu_errs[i] = -1;
105159269Srwatson    exc_errs[i] = -1;
106159269Srwatson  }
107159269Srwatson}
108159269Srwatson
109155408SrwatsonRegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() {}
110155408Srwatson
111155408Srwatsonvoid RegisterContextDarwin_arm64::InvalidateAllRegisters() {
112155408Srwatson  InvalidateAllRegisterStates();
113155408Srwatson}
114155408Srwatson
115155408Srwatsonsize_t RegisterContextDarwin_arm64::GetRegisterCount() {
116155408Srwatson  assert(k_num_register_infos == k_num_registers);
117155408Srwatson  return k_num_registers;
118155408Srwatson}
119155408Srwatson
120155408Srwatsonconst RegisterInfo *
121184488SrwatsonRegisterContextDarwin_arm64::GetRegisterInfoAtIndex(size_t reg) {
122184488Srwatson  assert(k_num_register_infos == k_num_registers);
123184488Srwatson  if (reg < k_num_registers)
124184508Srwatson    return &g_register_infos_arm64_le[reg];
125184488Srwatson  return nullptr;
126184488Srwatson}
127184508Srwatson
128184508Srwatsonsize_t RegisterContextDarwin_arm64::GetRegisterInfosCount() {
129184508Srwatson  return k_num_register_infos;
130184508Srwatson}
131184508Srwatson
132184508Srwatsonconst RegisterInfo *RegisterContextDarwin_arm64::GetRegisterInfos() {
133184508Srwatson  return g_register_infos_arm64_le;
134184508Srwatson}
135184488Srwatson
136184488Srwatson// Number of registers in each register set
137184488Srwatsonconst size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
138184488Srwatsonconst size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
139184488Srwatsonconst size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
140184536Srwatson
141184536Srwatson// Register set definitions. The first definitions at register set index of
142184536Srwatson// zero is for all registers, followed by other registers sets. The register
143184536Srwatson// information for the all register set need not be filled in.
144184536Srwatsonstatic const RegisterSet g_reg_sets[] = {
145184536Srwatson    {
146184536Srwatson        "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums,
147155408Srwatson    },
148155408Srwatson    {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums},
149184536Srwatson    {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}};
150184536Srwatson
151155408Srwatsonconst size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
152184540Srwatson
153184540Srwatsonsize_t RegisterContextDarwin_arm64::GetRegisterSetCount() {
154184540Srwatson  return k_num_regsets;
155155408Srwatson}
156155408Srwatson
157155408Srwatsonconst RegisterSet *RegisterContextDarwin_arm64::GetRegisterSet(size_t reg_set) {
158155408Srwatson  if (reg_set < k_num_regsets)
159159269Srwatson    return &g_reg_sets[reg_set];
160159269Srwatson  return nullptr;
161159269Srwatson}
162159269Srwatson
163159269Srwatson// Register information definitions for arm64
164159269Srwatsonint RegisterContextDarwin_arm64::GetSetForNativeRegNum(int reg) {
165159269Srwatson  if (reg < fpu_v0)
166159269Srwatson    return GPRRegSet;
167159269Srwatson  else if (reg < exc_far)
168159269Srwatson    return FPURegSet;
169159269Srwatson  else if (reg < k_num_registers)
170184508Srwatson    return EXCRegSet;
171184508Srwatson  return -1;
172186662Srwatson}
173186662Srwatson
174159269Srwatsonint RegisterContextDarwin_arm64::ReadGPR(bool force) {
175155408Srwatson  int set = GPRRegSet;
176155408Srwatson  if (force || !RegisterSetIsCached(set)) {
177159269Srwatson    SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
178159269Srwatson  }
179159269Srwatson  return GetError(GPRRegSet, Read);
180155408Srwatson}
181155408Srwatson
182155408Srwatsonint RegisterContextDarwin_arm64::ReadFPU(bool force) {
183184508Srwatson  int set = FPURegSet;
184184508Srwatson  if (force || !RegisterSetIsCached(set)) {
185184508Srwatson    SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
186184508Srwatson  }
187184508Srwatson  return GetError(FPURegSet, Read);
188184508Srwatson}
189184508Srwatson
190184488Srwatsonint RegisterContextDarwin_arm64::ReadEXC(bool force) {
191184508Srwatson  int set = EXCRegSet;
192184508Srwatson  if (force || !RegisterSetIsCached(set)) {
193184508Srwatson    SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
194184508Srwatson  }
195184508Srwatson  return GetError(EXCRegSet, Read);
196184508Srwatson}
197155408Srwatson
198184488Srwatsonint RegisterContextDarwin_arm64::ReadDBG(bool force) {
199184488Srwatson  int set = DBGRegSet;
200184488Srwatson  if (force || !RegisterSetIsCached(set)) {
201184488Srwatson    SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));
202155408Srwatson  }
203155408Srwatson  return GetError(DBGRegSet, Read);
204184488Srwatson}
205155408Srwatson
206184488Srwatsonint RegisterContextDarwin_arm64::WriteGPR() {
207184488Srwatson  int set = GPRRegSet;
208184488Srwatson  if (!RegisterSetIsCached(set)) {
209184488Srwatson    SetError(set, Write, -1);
210184488Srwatson    return KERN_INVALID_ARGUMENT;
211184488Srwatson  }
212184488Srwatson  SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));
213184488Srwatson  SetError(set, Read, -1);
214155408Srwatson  return GetError(GPRRegSet, Write);
215155408Srwatson}
216155408Srwatson
217155408Srwatsonint RegisterContextDarwin_arm64::WriteFPU() {
218155408Srwatson  int set = FPURegSet;
219155408Srwatson  if (!RegisterSetIsCached(set)) {
220155408Srwatson    SetError(set, Write, -1);
221155408Srwatson    return KERN_INVALID_ARGUMENT;
222155408Srwatson  }
223155408Srwatson  SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu));
224155408Srwatson  SetError(set, Read, -1);
225155408Srwatson  return GetError(FPURegSet, Write);
226155408Srwatson}
227155408Srwatson
228155408Srwatsonint RegisterContextDarwin_arm64::WriteEXC() {
229155408Srwatson  int set = EXCRegSet;
230161582Srwatson  if (!RegisterSetIsCached(set)) {
231155408Srwatson    SetError(set, Write, -1);
232155408Srwatson    return KERN_INVALID_ARGUMENT;
233155408Srwatson  }
234191143Srwatson  SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));
235155408Srwatson  SetError(set, Read, -1);
236155408Srwatson  return GetError(EXCRegSet, Write);
237155408Srwatson}
238155408Srwatson
239155408Srwatsonint RegisterContextDarwin_arm64::WriteDBG() {
240161582Srwatson  int set = DBGRegSet;
241155408Srwatson  if (!RegisterSetIsCached(set)) {
242155408Srwatson    SetError(set, Write, -1);
243155408Srwatson    return KERN_INVALID_ARGUMENT;
244161582Srwatson  }
245161582Srwatson  SetError(set, Write, DoWriteDBG(GetThreadID(), set, dbg));
246161582Srwatson  SetError(set, Read, -1);
247161582Srwatson  return GetError(DBGRegSet, Write);
248161582Srwatson}
249161582Srwatson
250161582Srwatsonint RegisterContextDarwin_arm64::ReadRegisterSet(uint32_t set, bool force) {
251161582Srwatson  switch (set) {
252161582Srwatson  case GPRRegSet:
253161582Srwatson    return ReadGPR(force);
254155408Srwatson  case FPURegSet:
255155408Srwatson    return ReadFPU(force);
256155408Srwatson  case EXCRegSet:
257155408Srwatson    return ReadEXC(force);
258155408Srwatson  case DBGRegSet:
259155408Srwatson    return ReadDBG(force);
260155408Srwatson  default:
261155408Srwatson    break;
262155408Srwatson  }
263155408Srwatson  return KERN_INVALID_ARGUMENT;
264155408Srwatson}
265155408Srwatson
266155408Srwatsonint RegisterContextDarwin_arm64::WriteRegisterSet(uint32_t set) {
267155408Srwatson  // Make sure we have a valid context to set.
268155408Srwatson  if (RegisterSetIsCached(set)) {
269155408Srwatson    switch (set) {
270155408Srwatson    case GPRRegSet:
271155408Srwatson      return WriteGPR();
272155408Srwatson    case FPURegSet:
273155408Srwatson      return WriteFPU();
274159269Srwatson    case EXCRegSet:
275159269Srwatson      return WriteEXC();
276159269Srwatson    case DBGRegSet:
277159269Srwatson      return WriteDBG();
278159269Srwatson    default:
279159269Srwatson      break;
280159269Srwatson    }
281184488Srwatson  }
282159269Srwatson  return KERN_INVALID_ARGUMENT;
283159269Srwatson}
284159269Srwatson
285159269Srwatsonvoid RegisterContextDarwin_arm64::LogDBGRegisters(Log *log, const DBG &dbg) {
286159269Srwatson  if (log) {
287159269Srwatson    for (uint32_t i = 0; i < 16; i++)
288159269Srwatson      log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64
289159269Srwatson                  " } WVR%-2u/WCR%-2u "
290159269Srwatson                  "= { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 " }",
291159269Srwatson                  i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]);
292159269Srwatson  }
293159269Srwatson}
294159269Srwatson
295159269Srwatsonbool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info,
296159269Srwatson                                               RegisterValue &value) {
297159269Srwatson  const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
298159269Srwatson  int set = RegisterContextDarwin_arm64::GetSetForNativeRegNum(reg);
299159269Srwatson
300184488Srwatson  if (set == -1)
301159269Srwatson    return false;
302159269Srwatson
303159269Srwatson  if (ReadRegisterSet(set, false) != KERN_SUCCESS)
304159269Srwatson    return false;
305159269Srwatson
306159269Srwatson  switch (reg) {
307184488Srwatson  case gpr_x0:
308159269Srwatson  case gpr_x1:
309159269Srwatson  case gpr_x2:
310159269Srwatson  case gpr_x3:
311159269Srwatson  case gpr_x4:
312159269Srwatson  case gpr_x5:
313159269Srwatson  case gpr_x6:
314159269Srwatson  case gpr_x7:
315159269Srwatson  case gpr_x8:
316159269Srwatson  case gpr_x9:
317159269Srwatson  case gpr_x10:
318159269Srwatson  case gpr_x11:
319159269Srwatson  case gpr_x12:
320159269Srwatson  case gpr_x13:
321159269Srwatson  case gpr_x14:
322159269Srwatson  case gpr_x15:
323159269Srwatson  case gpr_x16:
324159269Srwatson  case gpr_x17:
325184488Srwatson  case gpr_x18:
326159269Srwatson  case gpr_x19:
327159269Srwatson  case gpr_x20:
328159269Srwatson  case gpr_x21:
329159269Srwatson  case gpr_x22:
330159269Srwatson  case gpr_x23:
331159269Srwatson  case gpr_x24:
332159269Srwatson  case gpr_x25:
333159269Srwatson  case gpr_x26:
334184488Srwatson  case gpr_x27:
335159269Srwatson  case gpr_x28:
336159269Srwatson    value.SetUInt64(gpr.x[reg - gpr_x0]);
337159269Srwatson    break;
338159269Srwatson  case gpr_fp:
339159269Srwatson    value.SetUInt64(gpr.fp);
340159269Srwatson    break;
341159269Srwatson  case gpr_sp:
342159269Srwatson    value.SetUInt64(gpr.sp);
343159269Srwatson    break;
344159269Srwatson  case gpr_lr:
345159269Srwatson    value.SetUInt64(gpr.lr);
346159269Srwatson    break;
347159269Srwatson  case gpr_pc:
348184488Srwatson    value.SetUInt64(gpr.pc);
349159269Srwatson    break;
350159269Srwatson  case gpr_cpsr:
351159269Srwatson    value.SetUInt64(gpr.cpsr);
352159269Srwatson    break;
353159269Srwatson
354159269Srwatson  case gpr_w0:
355184488Srwatson  case gpr_w1:
356159269Srwatson  case gpr_w2:
357159269Srwatson  case gpr_w3:
358159269Srwatson  case gpr_w4:
359159269Srwatson  case gpr_w5:
360159269Srwatson  case gpr_w6:
361159269Srwatson  case gpr_w7:
362159269Srwatson  case gpr_w8:
363159269Srwatson  case gpr_w9:
364159269Srwatson  case gpr_w10:
365159269Srwatson  case gpr_w11:
366159269Srwatson  case gpr_w12:
367159269Srwatson  case gpr_w13:
368159269Srwatson  case gpr_w14:
369184488Srwatson  case gpr_w15:
370159269Srwatson  case gpr_w16:
371159269Srwatson  case gpr_w17:
372159269Srwatson  case gpr_w18:
373159269Srwatson  case gpr_w19:
374159269Srwatson  case gpr_w20:
375159269Srwatson  case gpr_w21:
376159269Srwatson  case gpr_w22:
377159269Srwatson  case gpr_w23:
378159269Srwatson  case gpr_w24:
379159269Srwatson  case gpr_w25:
380159269Srwatson  case gpr_w26:
381184488Srwatson  case gpr_w27:
382159269Srwatson  case gpr_w28: {
383184488Srwatson    ProcessSP process_sp(m_thread.GetProcess());
384159269Srwatson    if (process_sp.get()) {
385159269Srwatson      DataExtractor regdata(&gpr.x[reg - gpr_w0], 8, process_sp->GetByteOrder(),
386170196Srwatson                            process_sp->GetAddressByteSize());
387159269Srwatson      offset_t offset = 0;
388159269Srwatson      uint64_t retval = regdata.GetMaxU64(&offset, 8);
389159269Srwatson      uint32_t retval_lower32 = static_cast<uint32_t>(retval & 0xffffffff);
390159269Srwatson      value.SetUInt32(retval_lower32);
391159269Srwatson    }
392159269Srwatson  } break;
393159269Srwatson
394159269Srwatson  case fpu_v0:
395159269Srwatson  case fpu_v1:
396159269Srwatson  case fpu_v2:
397159269Srwatson  case fpu_v3:
398159269Srwatson  case fpu_v4:
399159269Srwatson  case fpu_v5:
400159269Srwatson  case fpu_v6:
401159269Srwatson  case fpu_v7:
402184488Srwatson  case fpu_v8:
403159269Srwatson  case fpu_v9:
404159269Srwatson  case fpu_v10:
405159269Srwatson  case fpu_v11:
406159269Srwatson  case fpu_v12:
407159269Srwatson  case fpu_v13:
408159269Srwatson  case fpu_v14:
409159269Srwatson  case fpu_v15:
410159269Srwatson  case fpu_v16:
411159269Srwatson  case fpu_v17:
412159269Srwatson  case fpu_v18:
413159269Srwatson  case fpu_v19:
414159269Srwatson  case fpu_v20:
415159269Srwatson  case fpu_v21:
416159269Srwatson  case fpu_v22:
417159269Srwatson  case fpu_v23:
418159269Srwatson  case fpu_v24:
419159269Srwatson  case fpu_v25:
420159269Srwatson  case fpu_v26:
421159269Srwatson  case fpu_v27:
422159269Srwatson  case fpu_v28:
423159269Srwatson  case fpu_v29:
424159269Srwatson  case fpu_v30:
425159269Srwatson  case fpu_v31:
426159269Srwatson    value.SetBytes(fpu.v[reg - fpu_v0].bytes.buffer, reg_info->byte_size,
427159269Srwatson                   endian::InlHostByteOrder());
428159269Srwatson    break;
429159269Srwatson
430159269Srwatson  case fpu_s0:
431159269Srwatson  case fpu_s1:
432159269Srwatson  case fpu_s2:
433159269Srwatson  case fpu_s3:
434159269Srwatson  case fpu_s4:
435159269Srwatson  case fpu_s5:
436159269Srwatson  case fpu_s6:
437159269Srwatson  case fpu_s7:
438159269Srwatson  case fpu_s8:
439186825Srwatson  case fpu_s9:
440186825Srwatson  case fpu_s10:
441186825Srwatson  case fpu_s11:
442186825Srwatson  case fpu_s12:
443184488Srwatson  case fpu_s13:
444159269Srwatson  case fpu_s14:
445184488Srwatson  case fpu_s15:
446159269Srwatson  case fpu_s16:
447159269Srwatson  case fpu_s17:
448184488Srwatson  case fpu_s18:
449184488Srwatson  case fpu_s19:
450159269Srwatson  case fpu_s20:
451159269Srwatson  case fpu_s21:
452184488Srwatson  case fpu_s22:
453159269Srwatson  case fpu_s23:
454184488Srwatson  case fpu_s24:
455159269Srwatson  case fpu_s25:
456159269Srwatson  case fpu_s26:
457159269Srwatson  case fpu_s27:
458159269Srwatson  case fpu_s28:
459159269Srwatson  case fpu_s29:
460184489Srwatson  case fpu_s30:
461184489Srwatson  case fpu_s31: {
462155408Srwatson    ProcessSP process_sp(m_thread.GetProcess());
463155408Srwatson    if (process_sp.get()) {
464155408Srwatson      DataExtractor regdata(&fpu.v[reg - fpu_s0], 4, process_sp->GetByteOrder(),
465155408Srwatson                            process_sp->GetAddressByteSize());
466184489Srwatson      offset_t offset = 0;
467155408Srwatson      value.SetFloat(regdata.GetFloat(&offset));
468184488Srwatson    }
469155408Srwatson  } break;
470184489Srwatson
471184489Srwatson  case fpu_d0:
472184489Srwatson  case fpu_d1:
473184489Srwatson  case fpu_d2:
474184489Srwatson  case fpu_d3:
475184489Srwatson  case fpu_d4:
476155408Srwatson  case fpu_d5:
477155408Srwatson  case fpu_d6:
478155408Srwatson  case fpu_d7:
479156292Srwatson  case fpu_d8:
480155408Srwatson  case fpu_d9:
481155408Srwatson  case fpu_d10:
482155408Srwatson  case fpu_d11:
483155408Srwatson  case fpu_d12:
484155408Srwatson  case fpu_d13:
485155408Srwatson  case fpu_d14:
486155408Srwatson  case fpu_d15:
487155408Srwatson  case fpu_d16:
488155408Srwatson  case fpu_d17:
489155408Srwatson  case fpu_d18:
490155408Srwatson  case fpu_d19:
491155408Srwatson  case fpu_d20:
492155408Srwatson  case fpu_d21:
493155408Srwatson  case fpu_d22:
494155408Srwatson  case fpu_d23:
495155408Srwatson  case fpu_d24:
496155408Srwatson  case fpu_d25:
497184536Srwatson  case fpu_d26:
498155408Srwatson  case fpu_d27:
499161582Srwatson  case fpu_d28:
500155408Srwatson  case fpu_d29:
501155408Srwatson  case fpu_d30:
502184488Srwatson  case fpu_d31: {
503155408Srwatson    ProcessSP process_sp(m_thread.GetProcess());
504155408Srwatson    if (process_sp.get()) {
505155408Srwatson      DataExtractor regdata(&fpu.v[reg - fpu_s0], 8, process_sp->GetByteOrder(),
506155408Srwatson                            process_sp->GetAddressByteSize());
507155408Srwatson      offset_t offset = 0;
508155408Srwatson      value.SetDouble(regdata.GetDouble(&offset));
509155408Srwatson    }
510159269Srwatson  } break;
511159269Srwatson
512155408Srwatson  case fpu_fpsr:
513155408Srwatson    value.SetUInt32(fpu.fpsr);
514155408Srwatson    break;
515155408Srwatson
516184488Srwatson  case fpu_fpcr:
517155408Srwatson    value.SetUInt32(fpu.fpcr);
518155408Srwatson    break;
519155408Srwatson
520155408Srwatson  case exc_exception:
521184488Srwatson    value.SetUInt32(exc.exception);
522159269Srwatson    break;
523184488Srwatson  case exc_esr:
524159269Srwatson    value.SetUInt32(exc.esr);
525159269Srwatson    break;
526159269Srwatson  case exc_far:
527184488Srwatson    value.SetUInt64(exc.far);
528159269Srwatson    break;
529184488Srwatson
530184488Srwatson  default:
531184488Srwatson    value.SetValueToInvalid();
532159269Srwatson    return false;
533159269Srwatson  }
534159269Srwatson  return true;
535159269Srwatson}
536159269Srwatson
537159269Srwatsonbool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info,
538159269Srwatson                                                const RegisterValue &value) {
539159269Srwatson  const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
540159269Srwatson  int set = GetSetForNativeRegNum(reg);
541159269Srwatson
542159269Srwatson  if (set == -1)
543159269Srwatson    return false;
544159269Srwatson
545159269Srwatson  if (ReadRegisterSet(set, false) != KERN_SUCCESS)
546159269Srwatson    return false;
547159269Srwatson
548159269Srwatson  switch (reg) {
549184488Srwatson  case gpr_x0:
550159269Srwatson  case gpr_x1:
551159269Srwatson  case gpr_x2:
552159269Srwatson  case gpr_x3:
553159269Srwatson  case gpr_x4:
554184488Srwatson  case gpr_x5:
555184488Srwatson  case gpr_x6:
556184488Srwatson  case gpr_x7:
557155408Srwatson  case gpr_x8:
558184488Srwatson  case gpr_x9:
559184488Srwatson  case gpr_x10:
560184488Srwatson  case gpr_x11:
561184488Srwatson  case gpr_x12:
562184488Srwatson  case gpr_x13:
563155408Srwatson  case gpr_x14:
564155408Srwatson  case gpr_x15:
565155408Srwatson  case gpr_x16:
566155408Srwatson  case gpr_x17:
567155408Srwatson  case gpr_x18:
568155408Srwatson  case gpr_x19:
569155408Srwatson  case gpr_x20:
570155408Srwatson  case gpr_x21:
571155408Srwatson  case gpr_x22:
572155408Srwatson  case gpr_x23:
573155408Srwatson  case gpr_x24:
574155408Srwatson  case gpr_x25:
575184488Srwatson  case gpr_x26:
576155408Srwatson  case gpr_x27:
577155408Srwatson  case gpr_x28:
578155408Srwatson  case gpr_fp:
579155408Srwatson  case gpr_sp:
580155408Srwatson  case gpr_lr:
581155408Srwatson  case gpr_pc:
582193951Skib  case gpr_cpsr:
583184488Srwatson    gpr.x[reg - gpr_x0] = value.GetAsUInt64();
584184508Srwatson    break;
585184488Srwatson
586159269Srwatson  case fpu_v0:
587159269Srwatson  case fpu_v1:
588159269Srwatson  case fpu_v2:
589159269Srwatson  case fpu_v3:
590159269Srwatson  case fpu_v4:
591159269Srwatson  case fpu_v5:
592159269Srwatson  case fpu_v6:
593159269Srwatson  case fpu_v7:
594159269Srwatson  case fpu_v8:
595159269Srwatson  case fpu_v9:
596159269Srwatson  case fpu_v10:
597159269Srwatson  case fpu_v11:
598159269Srwatson  case fpu_v12:
599161582Srwatson  case fpu_v13:
600161582Srwatson  case fpu_v14:
601161582Srwatson  case fpu_v15:
602155408Srwatson  case fpu_v16:
603155408Srwatson  case fpu_v17:
604155408Srwatson  case fpu_v18:
605159269Srwatson  case fpu_v19:
606155408Srwatson  case fpu_v20:
607155408Srwatson  case fpu_v21:
608155408Srwatson  case fpu_v22:
609155408Srwatson  case fpu_v23:
610159269Srwatson  case fpu_v24:
611155408Srwatson  case fpu_v25:
612155408Srwatson  case fpu_v26:
613159269Srwatson  case fpu_v27:
614155408Srwatson  case fpu_v28:
615155408Srwatson  case fpu_v29:
616155408Srwatson  case fpu_v30:
617184488Srwatson  case fpu_v31:
618155408Srwatson    ::memcpy(fpu.v[reg - fpu_v0].bytes.buffer, value.GetBytes(),
619155408Srwatson             value.GetByteSize());
620155408Srwatson    break;
621184536Srwatson
622155408Srwatson  case fpu_fpsr:
623155408Srwatson    fpu.fpsr = value.GetAsUInt32();
624155408Srwatson    break;
625184536Srwatson
626184536Srwatson  case fpu_fpcr:
627184536Srwatson    fpu.fpcr = value.GetAsUInt32();
628184536Srwatson    break;
629159269Srwatson
630159269Srwatson  case exc_exception:
631159269Srwatson    exc.exception = value.GetAsUInt32();
632159269Srwatson    break;
633184488Srwatson  case exc_esr:
634184488Srwatson    exc.esr = value.GetAsUInt32();
635184488Srwatson    break;
636159269Srwatson  case exc_far:
637159269Srwatson    exc.far = value.GetAsUInt64();
638159269Srwatson    break;
639159269Srwatson
640159269Srwatson  default:
641184488Srwatson    return false;
642184488Srwatson  }
643159269Srwatson  return WriteRegisterSet(set) == KERN_SUCCESS;
644159269Srwatson}
645159269Srwatson
646184488Srwatsonbool RegisterContextDarwin_arm64::ReadAllRegisterValues(
647184508Srwatson    lldb::DataBufferSP &data_sp) {
648184488Srwatson  data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
649225177Sattilio  if (ReadGPR(false) == KERN_SUCCESS && ReadFPU(false) == KERN_SUCCESS &&
650161582Srwatson      ReadEXC(false) == KERN_SUCCESS) {
651159269Srwatson    uint8_t *dst = data_sp->GetBytes();
652155408Srwatson    ::memcpy(dst, &gpr, sizeof(gpr));
653155408Srwatson    dst += sizeof(gpr);
654155408Srwatson
655155408Srwatson    ::memcpy(dst, &fpu, sizeof(fpu));
656155408Srwatson    dst += sizeof(gpr);
657155408Srwatson
658155408Srwatson    ::memcpy(dst, &exc, sizeof(exc));
659155408Srwatson    return true;
660155408Srwatson  }
661155408Srwatson  return false;
662155408Srwatson}
663155408Srwatson
664155408Srwatsonbool RegisterContextDarwin_arm64::WriteAllRegisterValues(
665155408Srwatson    const lldb::DataBufferSP &data_sp) {
666155408Srwatson  if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
667155408Srwatson    const uint8_t *src = data_sp->GetBytes();
668155408Srwatson    ::memcpy(&gpr, src, sizeof(gpr));
669155408Srwatson    src += sizeof(gpr);
670155408Srwatson
671155408Srwatson    ::memcpy(&fpu, src, sizeof(fpu));
672155408Srwatson    src += sizeof(gpr);
673155408Srwatson
674155408Srwatson    ::memcpy(&exc, src, sizeof(exc));
675155408Srwatson    uint32_t success_count = 0;
676183381Sed    if (WriteGPR() == KERN_SUCCESS)
677155408Srwatson      ++success_count;
678155408Srwatson    if (WriteFPU() == KERN_SUCCESS)
679155408Srwatson      ++success_count;
680155408Srwatson    if (WriteEXC() == KERN_SUCCESS)
681155408Srwatson      ++success_count;
682155408Srwatson    return success_count == 3;
683155408Srwatson  }
684155408Srwatson  return false;
685155408Srwatson}
686164033Srwatson
687164033Srwatsonuint32_t RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber(
688164033Srwatson    RegisterKind kind, uint32_t reg) {
689155408Srwatson  if (kind == eRegisterKindGeneric) {
690155408Srwatson    switch (reg) {
691155408Srwatson    case LLDB_REGNUM_GENERIC_PC:
692155408Srwatson      return gpr_pc;
693155408Srwatson    case LLDB_REGNUM_GENERIC_SP:
694155408Srwatson      return gpr_sp;
695184488Srwatson    case LLDB_REGNUM_GENERIC_FP:
696155408Srwatson      return gpr_fp;
697155408Srwatson    case LLDB_REGNUM_GENERIC_RA:
698155408Srwatson      return gpr_lr;
699155408Srwatson    case LLDB_REGNUM_GENERIC_FLAGS:
700184488Srwatson      return gpr_cpsr;
701155408Srwatson    default:
702155408Srwatson      break;
703155408Srwatson    }
704155408Srwatson  } else if (kind == eRegisterKindDWARF) {
705155408Srwatson    switch (reg) {
706184488Srwatson    case arm64_dwarf::x0:
707155408Srwatson      return gpr_x0;
708155408Srwatson    case arm64_dwarf::x1:
709184488Srwatson      return gpr_x1;
710184488Srwatson    case arm64_dwarf::x2:
711155408Srwatson      return gpr_x2;
712155408Srwatson    case arm64_dwarf::x3:
713155408Srwatson      return gpr_x3;
714155408Srwatson    case arm64_dwarf::x4:
715155408Srwatson      return gpr_x4;
716155408Srwatson    case arm64_dwarf::x5:
717155408Srwatson      return gpr_x5;
718155408Srwatson    case arm64_dwarf::x6:
719155408Srwatson      return gpr_x6;
720155408Srwatson    case arm64_dwarf::x7:
721155408Srwatson      return gpr_x7;
722155408Srwatson    case arm64_dwarf::x8:
723155408Srwatson      return gpr_x8;
724155408Srwatson    case arm64_dwarf::x9:
725155408Srwatson      return gpr_x9;
726184488Srwatson    case arm64_dwarf::x10:
727155408Srwatson      return gpr_x10;
728184488Srwatson    case arm64_dwarf::x11:
729184488Srwatson      return gpr_x11;
730155408Srwatson    case arm64_dwarf::x12:
731155408Srwatson      return gpr_x12;
732155408Srwatson    case arm64_dwarf::x13:
733184488Srwatson      return gpr_x13;
734155408Srwatson    case arm64_dwarf::x14:
735155408Srwatson      return gpr_x14;
736155408Srwatson    case arm64_dwarf::x15:
737155408Srwatson      return gpr_x15;
738156880Srwatson    case arm64_dwarf::x16:
739156880Srwatson      return gpr_x16;
740155408Srwatson    case arm64_dwarf::x17:
741155408Srwatson      return gpr_x17;
742155408Srwatson    case arm64_dwarf::x18:
743155408Srwatson      return gpr_x18;
744155408Srwatson    case arm64_dwarf::x19:
745159269Srwatson      return gpr_x19;
746155408Srwatson    case arm64_dwarf::x20:
747159269Srwatson      return gpr_x20;
748159269Srwatson    case arm64_dwarf::x21:
749159269Srwatson      return gpr_x21;
750155408Srwatson    case arm64_dwarf::x22:
751155408Srwatson      return gpr_x22;
752155408Srwatson    case arm64_dwarf::x23:
753159269Srwatson      return gpr_x23;
754159269Srwatson    case arm64_dwarf::x24:
755159269Srwatson      return gpr_x24;
756159269Srwatson    case arm64_dwarf::x25:
757159269Srwatson      return gpr_x25;
758159269Srwatson    case arm64_dwarf::x26:
759155408Srwatson      return gpr_x26;
760155408Srwatson    case arm64_dwarf::x27:
761184488Srwatson      return gpr_x27;
762155408Srwatson    case arm64_dwarf::x28:
763155408Srwatson      return gpr_x28;
764155408Srwatson
765155408Srwatson    case arm64_dwarf::fp:
766184488Srwatson      return gpr_fp;
767155408Srwatson    case arm64_dwarf::sp:
768155408Srwatson      return gpr_sp;
769155408Srwatson    case arm64_dwarf::lr:
770155408Srwatson      return gpr_lr;
771184488Srwatson    case arm64_dwarf::pc:
772184536Srwatson      return gpr_pc;
773184488Srwatson    case arm64_dwarf::cpsr:
774155408Srwatson      return gpr_cpsr;
775155408Srwatson
776155408Srwatson    case arm64_dwarf::v0:
777155408Srwatson      return fpu_v0;
778184488Srwatson    case arm64_dwarf::v1:
779155408Srwatson      return fpu_v1;
780155408Srwatson    case arm64_dwarf::v2:
781155408Srwatson      return fpu_v2;
782155408Srwatson    case arm64_dwarf::v3:
783184488Srwatson      return fpu_v3;
784155408Srwatson    case arm64_dwarf::v4:
785155408Srwatson      return fpu_v4;
786155408Srwatson    case arm64_dwarf::v5:
787155408Srwatson      return fpu_v5;
788155408Srwatson    case arm64_dwarf::v6:
789155408Srwatson      return fpu_v6;
790155408Srwatson    case arm64_dwarf::v7:
791155408Srwatson      return fpu_v7;
792155408Srwatson    case arm64_dwarf::v8:
793155408Srwatson      return fpu_v8;
794156880Srwatson    case arm64_dwarf::v9:
795155408Srwatson      return fpu_v9;
796156880Srwatson    case arm64_dwarf::v10:
797156880Srwatson      return fpu_v10;
798156880Srwatson    case arm64_dwarf::v11:
799156880Srwatson      return fpu_v11;
800156880Srwatson    case arm64_dwarf::v12:
801156880Srwatson      return fpu_v12;
802156880Srwatson    case arm64_dwarf::v13:
803156880Srwatson      return fpu_v13;
804156880Srwatson    case arm64_dwarf::v14:
805156880Srwatson      return fpu_v14;
806156880Srwatson    case arm64_dwarf::v15:
807156880Srwatson      return fpu_v15;
808156880Srwatson    case arm64_dwarf::v16:
809156880Srwatson      return fpu_v16;
810156880Srwatson    case arm64_dwarf::v17:
811156880Srwatson      return fpu_v17;
812156880Srwatson    case arm64_dwarf::v18:
813156880Srwatson      return fpu_v18;
814156880Srwatson    case arm64_dwarf::v19:
815156880Srwatson      return fpu_v19;
816156884Srwatson    case arm64_dwarf::v20:
817156884Srwatson      return fpu_v20;
818156884Srwatson    case arm64_dwarf::v21:
819156884Srwatson      return fpu_v21;
820156884Srwatson    case arm64_dwarf::v22:
821156884Srwatson      return fpu_v22;
822156884Srwatson    case arm64_dwarf::v23:
823156884Srwatson      return fpu_v23;
824156884Srwatson    case arm64_dwarf::v24:
825156884Srwatson      return fpu_v24;
826159269Srwatson    case arm64_dwarf::v25:
827184488Srwatson      return fpu_v25;
828159269Srwatson    case arm64_dwarf::v26:
829159269Srwatson      return fpu_v26;
830184488Srwatson    case arm64_dwarf::v27:
831159269Srwatson      return fpu_v27;
832159269Srwatson    case arm64_dwarf::v28:
833159269Srwatson      return fpu_v28;
834159269Srwatson    case arm64_dwarf::v29:
835184488Srwatson      return fpu_v29;
836159269Srwatson    case arm64_dwarf::v30:
837159269Srwatson      return fpu_v30;
838184488Srwatson    case arm64_dwarf::v31:
839159269Srwatson      return fpu_v31;
840159269Srwatson
841159269Srwatson    default:
842159269Srwatson      break;
843184488Srwatson    }
844159269Srwatson  } else if (kind == eRegisterKindEHFrame) {
845159269Srwatson    switch (reg) {
846184488Srwatson    case arm64_ehframe::x0:
847159269Srwatson      return gpr_x0;
848159269Srwatson    case arm64_ehframe::x1:
849159269Srwatson      return gpr_x1;
850159269Srwatson    case arm64_ehframe::x2:
851184488Srwatson      return gpr_x2;
852159269Srwatson    case arm64_ehframe::x3:
853159269Srwatson      return gpr_x3;
854184488Srwatson    case arm64_ehframe::x4:
855159269Srwatson      return gpr_x4;
856159269Srwatson    case arm64_ehframe::x5:
857159269Srwatson      return gpr_x5;
858159269Srwatson    case arm64_ehframe::x6:
859159269Srwatson      return gpr_x6;
860159269Srwatson    case arm64_ehframe::x7:
861159269Srwatson      return gpr_x7;
862159269Srwatson    case arm64_ehframe::x8:
863159269Srwatson      return gpr_x8;
864159269Srwatson    case arm64_ehframe::x9:
865159269Srwatson      return gpr_x9;
866159269Srwatson    case arm64_ehframe::x10:
867159269Srwatson      return gpr_x10;
868159269Srwatson    case arm64_ehframe::x11:
869159269Srwatson      return gpr_x11;
870159269Srwatson    case arm64_ehframe::x12:
871159269Srwatson      return gpr_x12;
872159269Srwatson    case arm64_ehframe::x13:
873159269Srwatson      return gpr_x13;
874159269Srwatson    case arm64_ehframe::x14:
875159269Srwatson      return gpr_x14;
876159269Srwatson    case arm64_ehframe::x15:
877159269Srwatson      return gpr_x15;
878159269Srwatson    case arm64_ehframe::x16:
879159269Srwatson      return gpr_x16;
880159269Srwatson    case arm64_ehframe::x17:
881184488Srwatson      return gpr_x17;
882159269Srwatson    case arm64_ehframe::x18:
883184488Srwatson      return gpr_x18;
884159269Srwatson    case arm64_ehframe::x19:
885159269Srwatson      return gpr_x19;
886159269Srwatson    case arm64_ehframe::x20:
887159269Srwatson      return gpr_x20;
888159269Srwatson    case arm64_ehframe::x21:
889159269Srwatson      return gpr_x21;
890159269Srwatson    case arm64_ehframe::x22:
891159269Srwatson      return gpr_x22;
892184488Srwatson    case arm64_ehframe::x23:
893159269Srwatson      return gpr_x23;
894184488Srwatson    case arm64_ehframe::x24:
895159269Srwatson      return gpr_x24;
896159269Srwatson    case arm64_ehframe::x25:
897159269Srwatson      return gpr_x25;
898159269Srwatson    case arm64_ehframe::x26:
899159269Srwatson      return gpr_x26;
900159269Srwatson    case arm64_ehframe::x27:
901159269Srwatson      return gpr_x27;
902159269Srwatson    case arm64_ehframe::x28:
903159269Srwatson      return gpr_x28;
904184508Srwatson    case arm64_ehframe::fp:
905184508Srwatson      return gpr_fp;
906184488Srwatson    case arm64_ehframe::sp:
907159269Srwatson      return gpr_sp;
908184488Srwatson    case arm64_ehframe::lr:
909184508Srwatson      return gpr_lr;
910159269Srwatson    case arm64_ehframe::pc:
911159269Srwatson      return gpr_pc;
912159269Srwatson    case arm64_ehframe::cpsr:
913161646Srwatson      return gpr_cpsr;
914161646Srwatson    }
915161646Srwatson  } else if (kind == eRegisterKindLLDB) {
916161646Srwatson    return reg;
917161646Srwatson  }
918156880Srwatson  return LLDB_INVALID_REGNUM;
919156880Srwatson}
920156880Srwatson
921156880Srwatsonuint32_t RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints() {
922156880Srwatson#if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))
923156880Srwatson  // autodetect how many watchpoints are supported dynamically...
924156880Srwatson  static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
925156880Srwatson  if (g_num_supported_hw_watchpoints == UINT32_MAX) {
926156880Srwatson    size_t len;
927156880Srwatson    uint32_t n = 0;
928156880Srwatson    len = sizeof(n);
929156880Srwatson    if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) {
930156880Srwatson      g_num_supported_hw_watchpoints = n;
931156880Srwatson    }
932156880Srwatson  }
933156880Srwatson  return g_num_supported_hw_watchpoints;
934184510Srwatson#else
935156880Srwatson  // TODO: figure out remote case here!
936156880Srwatson  return 2;
937156880Srwatson#endif
938155408Srwatson}
939155408Srwatson
940155408Srwatsonuint32_t RegisterContextDarwin_arm64::SetHardwareWatchpoint(lldb::addr_t addr,
941155408Srwatson                                                            size_t size,
942155408Srwatson                                                            bool read,
943155408Srwatson                                                            bool write) {
944155408Srwatson  //    if (log) log->Printf
945184534Srwatson  //    ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(addr = %8.8p,
946184534Srwatson  //    size = %u, read = %u, write = %u)", addr, size, read, write);
947155408Srwatson
948155408Srwatson  const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
949155408Srwatson
950155408Srwatson  // Can't watch zero bytes
951155408Srwatson  if (size == 0)
952155408Srwatson    return LLDB_INVALID_INDEX32;
953184508Srwatson
954155408Srwatson  // We must watch for either read or write
955155408Srwatson  if (!read && !write)
956155408Srwatson    return LLDB_INVALID_INDEX32;
957155408Srwatson
958184488Srwatson  // Can't watch more than 4 bytes per WVR/WCR pair
959184508Srwatson  if (size > 4)
960184508Srwatson    return LLDB_INVALID_INDEX32;
961184508Srwatson
962184508Srwatson  // We can only watch up to four bytes that follow a 4 byte aligned address
963184508Srwatson  // per watchpoint register pair. Since we have at most so we can only watch
964184508Srwatson  // until the next 4 byte boundary and we need to make sure we can properly
965184488Srwatson  // encode this.
966184508Srwatson  uint32_t addr_word_offset = addr % 4;
967184508Srwatson  //    if (log) log->Printf
968184508Srwatson  //    ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() -
969184508Srwatson  //    addr_word_offset = 0x%8.8x", addr_word_offset);
970184508Srwatson
971155408Srwatson  uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
972184508Srwatson  //    if (log) log->Printf
973184508Srwatson  //    ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - byte_mask =
974184508Srwatson  //    0x%8.8x", byte_mask);
975184508Srwatson  if (byte_mask > 0xfu)
976184508Srwatson    return LLDB_INVALID_INDEX32;
977184508Srwatson
978184508Srwatson  // Read the debug state
979184508Srwatson  int kret = ReadDBG(false);
980184508Srwatson
981184508Srwatson  if (kret == KERN_SUCCESS) {
982184534Srwatson    // Check to make sure we have the needed hardware support
983184534Srwatson    uint32_t i = 0;
984184508Srwatson
985184508Srwatson    for (i = 0; i < num_hw_watchpoints; ++i) {
986184508Srwatson      if ((dbg.wcr[i] & WCR_ENABLE) == 0)
987173083Scsjp        break; // We found an available hw breakpoint slot (in i)
988184534Srwatson    }
989184534Srwatson
990184534Srwatson    // See if we found an available hw breakpoint slot above
991184534Srwatson    if (i < num_hw_watchpoints) {
992184536Srwatson      // Make the byte_mask into a valid Byte Address Select mask
993184536Srwatson      uint32_t byte_address_select = byte_mask << 5;
994184536Srwatson      // Make sure bits 1:0 are clear in our address
995184534Srwatson      dbg.wvr[i] = addr & ~((lldb::addr_t)3);
996184534Srwatson      dbg.wcr[i] = byte_address_select |     // Which bytes that follow the IMVA
997184536Srwatson                                             // that we will watch
998184536Srwatson                   S_USER |                  // Stop only in user mode
999184534Srwatson                   (read ? WCR_LOAD : 0) |   // Stop on read access?
1000184534Srwatson                   (write ? WCR_STORE : 0) | // Stop on write access?
1001184534Srwatson                   WCR_ENABLE;               // Enable this watchpoint;
1002184534Srwatson
1003184534Srwatson      kret = WriteDBG();
1004184534Srwatson      //            if (log) log->Printf
1005184534Srwatson      //            ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint()
1006184534Srwatson      //            WriteDBG() => 0x%8.8x.", kret);
1007184534Srwatson
1008184534Srwatson      if (kret == KERN_SUCCESS)
1009184534Srwatson        return i;
1010184534Srwatson    } else {
1011184536Srwatson      //            if (log) log->Printf
1012184536Srwatson      //            ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint():
1013184536Srwatson      //            All hardware resources (%u) are in use.",
1014184536Srwatson      //            num_hw_watchpoints);
1015184534Srwatson    }
1016184536Srwatson  }
1017184534Srwatson  return LLDB_INVALID_INDEX32;
1018184534Srwatson}
1019184536Srwatson
1020184534Srwatsonbool RegisterContextDarwin_arm64::ClearHardwareWatchpoint(uint32_t hw_index) {
1021184508Srwatson  int kret = ReadDBG(false);
1022184508Srwatson
1023184508Srwatson  const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
1024184534Srwatson  if (kret == KERN_SUCCESS) {
1025155408Srwatson    if (hw_index < num_hw_points) {
1026155408Srwatson      dbg.wcr[hw_index] = 0;
1027155408Srwatson      //            if (log) log->Printf
1028155408Srwatson      //            ("RegisterContextDarwin_arm64::ClearHardwareWatchpoint( %u )
1029155408Srwatson      //            - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
1030155408Srwatson      //                    hw_index,
1031155408Srwatson      //                    hw_index,
1032155408Srwatson      //                    dbg.wvr[hw_index],
1033155408Srwatson      //                    hw_index,
1034155408Srwatson      //                    dbg.wcr[hw_index]);
1035155408Srwatson
1036155408Srwatson      kret = WriteDBG();
1037155408Srwatson
1038155408Srwatson      if (kret == KERN_SUCCESS)
1039184488Srwatson        return true;
1040155408Srwatson    }
1041184488Srwatson  }
1042155408Srwatson  return false;
1043155408Srwatson}
1044155408Srwatson