xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- RegisterContextDarwin_arm64.cpp -----------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "RegisterContextDarwin_arm64.h"
10061da546Spatrick #include "RegisterContextDarwinConstants.h"
11061da546Spatrick 
12061da546Spatrick #include "lldb/Target/Process.h"
13061da546Spatrick #include "lldb/Target/Thread.h"
14061da546Spatrick #include "lldb/Utility/DataBufferHeap.h"
15061da546Spatrick #include "lldb/Utility/DataExtractor.h"
16061da546Spatrick #include "lldb/Utility/Endian.h"
17061da546Spatrick #include "lldb/Utility/Log.h"
18061da546Spatrick #include "lldb/Utility/RegisterValue.h"
19061da546Spatrick #include "lldb/Utility/Scalar.h"
20061da546Spatrick #include "llvm/ADT/STLExtras.h"
21061da546Spatrick #include "llvm/Support/Compiler.h"
22061da546Spatrick 
23061da546Spatrick #include "Plugins/Process/Utility/InstructionUtils.h"
24061da546Spatrick 
25061da546Spatrick #include <memory>
26061da546Spatrick 
27061da546Spatrick #if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))
28061da546Spatrick #include <sys/types.h>
29061da546Spatrick #include <sys/sysctl.h>
30061da546Spatrick #endif
31061da546Spatrick 
32061da546Spatrick #include "Utility/ARM64_DWARF_Registers.h"
33061da546Spatrick 
34061da546Spatrick using namespace lldb;
35061da546Spatrick using namespace lldb_private;
36061da546Spatrick 
37061da546Spatrick #define GPR_OFFSET(idx) ((idx)*8)
38061da546Spatrick #define GPR_OFFSET_NAME(reg)                                                   \
39061da546Spatrick   (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::GPR, reg))
40061da546Spatrick 
41061da546Spatrick #define FPU_OFFSET(idx) ((idx)*16 + sizeof(RegisterContextDarwin_arm64::GPR))
42061da546Spatrick #define FPU_OFFSET_NAME(reg)                                                   \
43061da546Spatrick   (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::FPU, reg))
44061da546Spatrick 
45061da546Spatrick #define EXC_OFFSET_NAME(reg)                                                   \
46061da546Spatrick   (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::EXC, reg) +            \
47061da546Spatrick    sizeof(RegisterContextDarwin_arm64::GPR) +                                  \
48061da546Spatrick    sizeof(RegisterContextDarwin_arm64::FPU))
49061da546Spatrick #define DBG_OFFSET_NAME(reg)                                                   \
50061da546Spatrick   (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::DBG, reg) +            \
51061da546Spatrick    sizeof(RegisterContextDarwin_arm64::GPR) +                                  \
52061da546Spatrick    sizeof(RegisterContextDarwin_arm64::FPU) +                                  \
53061da546Spatrick    sizeof(RegisterContextDarwin_arm64::EXC))
54061da546Spatrick 
55061da546Spatrick #define DEFINE_DBG(reg, i)                                                     \
56061da546Spatrick   #reg, NULL,                                                                  \
57061da546Spatrick       sizeof(((RegisterContextDarwin_arm64::DBG *) NULL)->reg[i]),             \
58061da546Spatrick               DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex,              \
59061da546Spatrick                               {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       \
60061da546Spatrick                                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       \
61061da546Spatrick                                LLDB_INVALID_REGNUM },                          \
62*f6aab3d8Srobert                                NULL, NULL
63061da546Spatrick #define REG_CONTEXT_SIZE                                                       \
64061da546Spatrick   (sizeof(RegisterContextDarwin_arm64::GPR) +                                  \
65061da546Spatrick    sizeof(RegisterContextDarwin_arm64::FPU) +                                  \
66061da546Spatrick    sizeof(RegisterContextDarwin_arm64::EXC))
67061da546Spatrick 
68061da546Spatrick // Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure.
69061da546Spatrick #define DECLARE_REGISTER_INFOS_ARM64_STRUCT
70061da546Spatrick #include "RegisterInfos_arm64.h"
71061da546Spatrick #undef DECLARE_REGISTER_INFOS_ARM64_STRUCT
72061da546Spatrick 
73061da546Spatrick // General purpose registers
74061da546Spatrick static uint32_t g_gpr_regnums[] = {
75061da546Spatrick     gpr_x0,  gpr_x1,  gpr_x2,  gpr_x3,  gpr_x4,  gpr_x5,  gpr_x6,
76061da546Spatrick     gpr_x7,  gpr_x8,  gpr_x9,  gpr_x10, gpr_x11, gpr_x12, gpr_x13,
77061da546Spatrick     gpr_x14, gpr_x15, gpr_x16, gpr_x17, gpr_x18, gpr_x19, gpr_x20,
78061da546Spatrick     gpr_x21, gpr_x22, gpr_x23, gpr_x24, gpr_x25, gpr_x26, gpr_x27,
79061da546Spatrick     gpr_x28, gpr_fp,  gpr_lr,  gpr_sp,  gpr_pc,  gpr_cpsr};
80061da546Spatrick 
81061da546Spatrick // Floating point registers
82061da546Spatrick static uint32_t g_fpu_regnums[] = {
83061da546Spatrick     fpu_v0,  fpu_v1,  fpu_v2,  fpu_v3,  fpu_v4,   fpu_v5,  fpu_v6,
84061da546Spatrick     fpu_v7,  fpu_v8,  fpu_v9,  fpu_v10, fpu_v11,  fpu_v12, fpu_v13,
85061da546Spatrick     fpu_v14, fpu_v15, fpu_v16, fpu_v17, fpu_v18,  fpu_v19, fpu_v20,
86061da546Spatrick     fpu_v21, fpu_v22, fpu_v23, fpu_v24, fpu_v25,  fpu_v26, fpu_v27,
87061da546Spatrick     fpu_v28, fpu_v29, fpu_v30, fpu_v31, fpu_fpsr, fpu_fpcr};
88061da546Spatrick 
89061da546Spatrick // Exception registers
90061da546Spatrick 
91061da546Spatrick static uint32_t g_exc_regnums[] = {exc_far, exc_esr, exc_exception};
92061da546Spatrick 
93*f6aab3d8Srobert static size_t k_num_register_infos = std::size(g_register_infos_arm64_le);
94061da546Spatrick 
RegisterContextDarwin_arm64(Thread & thread,uint32_t concrete_frame_idx)95061da546Spatrick RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(
96061da546Spatrick     Thread &thread, uint32_t concrete_frame_idx)
97*f6aab3d8Srobert     : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc(), dbg() {
98061da546Spatrick   uint32_t i;
99061da546Spatrick   for (i = 0; i < kNumErrors; i++) {
100061da546Spatrick     gpr_errs[i] = -1;
101061da546Spatrick     fpu_errs[i] = -1;
102061da546Spatrick     exc_errs[i] = -1;
103061da546Spatrick   }
104061da546Spatrick }
105061da546Spatrick 
106be691f3bSpatrick RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() = default;
107061da546Spatrick 
InvalidateAllRegisters()108061da546Spatrick void RegisterContextDarwin_arm64::InvalidateAllRegisters() {
109061da546Spatrick   InvalidateAllRegisterStates();
110061da546Spatrick }
111061da546Spatrick 
GetRegisterCount()112061da546Spatrick size_t RegisterContextDarwin_arm64::GetRegisterCount() {
113061da546Spatrick   assert(k_num_register_infos == k_num_registers);
114061da546Spatrick   return k_num_registers;
115061da546Spatrick }
116061da546Spatrick 
117061da546Spatrick const RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)118061da546Spatrick RegisterContextDarwin_arm64::GetRegisterInfoAtIndex(size_t reg) {
119061da546Spatrick   assert(k_num_register_infos == k_num_registers);
120061da546Spatrick   if (reg < k_num_registers)
121061da546Spatrick     return &g_register_infos_arm64_le[reg];
122061da546Spatrick   return nullptr;
123061da546Spatrick }
124061da546Spatrick 
GetRegisterInfosCount()125061da546Spatrick size_t RegisterContextDarwin_arm64::GetRegisterInfosCount() {
126061da546Spatrick   return k_num_register_infos;
127061da546Spatrick }
128061da546Spatrick 
GetRegisterInfos()129061da546Spatrick const RegisterInfo *RegisterContextDarwin_arm64::GetRegisterInfos() {
130061da546Spatrick   return g_register_infos_arm64_le;
131061da546Spatrick }
132061da546Spatrick 
133061da546Spatrick // Number of registers in each register set
134*f6aab3d8Srobert const size_t k_num_gpr_registers = std::size(g_gpr_regnums);
135*f6aab3d8Srobert const size_t k_num_fpu_registers = std::size(g_fpu_regnums);
136*f6aab3d8Srobert const size_t k_num_exc_registers = std::size(g_exc_regnums);
137061da546Spatrick 
138061da546Spatrick // Register set definitions. The first definitions at register set index of
139061da546Spatrick // zero is for all registers, followed by other registers sets. The register
140061da546Spatrick // information for the all register set need not be filled in.
141061da546Spatrick static const RegisterSet g_reg_sets[] = {
142061da546Spatrick     {
143061da546Spatrick         "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums,
144061da546Spatrick     },
145061da546Spatrick     {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums},
146061da546Spatrick     {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}};
147061da546Spatrick 
148*f6aab3d8Srobert const size_t k_num_regsets = std::size(g_reg_sets);
149061da546Spatrick 
GetRegisterSetCount()150061da546Spatrick size_t RegisterContextDarwin_arm64::GetRegisterSetCount() {
151061da546Spatrick   return k_num_regsets;
152061da546Spatrick }
153061da546Spatrick 
GetRegisterSet(size_t reg_set)154061da546Spatrick const RegisterSet *RegisterContextDarwin_arm64::GetRegisterSet(size_t reg_set) {
155061da546Spatrick   if (reg_set < k_num_regsets)
156061da546Spatrick     return &g_reg_sets[reg_set];
157061da546Spatrick   return nullptr;
158061da546Spatrick }
159061da546Spatrick 
160061da546Spatrick // Register information definitions for arm64
GetSetForNativeRegNum(int reg)161061da546Spatrick int RegisterContextDarwin_arm64::GetSetForNativeRegNum(int reg) {
162061da546Spatrick   if (reg < fpu_v0)
163061da546Spatrick     return GPRRegSet;
164061da546Spatrick   else if (reg < exc_far)
165061da546Spatrick     return FPURegSet;
166061da546Spatrick   else if (reg < k_num_registers)
167061da546Spatrick     return EXCRegSet;
168061da546Spatrick   return -1;
169061da546Spatrick }
170061da546Spatrick 
ReadGPR(bool force)171061da546Spatrick int RegisterContextDarwin_arm64::ReadGPR(bool force) {
172061da546Spatrick   int set = GPRRegSet;
173061da546Spatrick   if (force || !RegisterSetIsCached(set)) {
174061da546Spatrick     SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
175061da546Spatrick   }
176061da546Spatrick   return GetError(GPRRegSet, Read);
177061da546Spatrick }
178061da546Spatrick 
ReadFPU(bool force)179061da546Spatrick int RegisterContextDarwin_arm64::ReadFPU(bool force) {
180061da546Spatrick   int set = FPURegSet;
181061da546Spatrick   if (force || !RegisterSetIsCached(set)) {
182061da546Spatrick     SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
183061da546Spatrick   }
184061da546Spatrick   return GetError(FPURegSet, Read);
185061da546Spatrick }
186061da546Spatrick 
ReadEXC(bool force)187061da546Spatrick int RegisterContextDarwin_arm64::ReadEXC(bool force) {
188061da546Spatrick   int set = EXCRegSet;
189061da546Spatrick   if (force || !RegisterSetIsCached(set)) {
190061da546Spatrick     SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
191061da546Spatrick   }
192061da546Spatrick   return GetError(EXCRegSet, Read);
193061da546Spatrick }
194061da546Spatrick 
ReadDBG(bool force)195061da546Spatrick int RegisterContextDarwin_arm64::ReadDBG(bool force) {
196061da546Spatrick   int set = DBGRegSet;
197061da546Spatrick   if (force || !RegisterSetIsCached(set)) {
198061da546Spatrick     SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));
199061da546Spatrick   }
200061da546Spatrick   return GetError(DBGRegSet, Read);
201061da546Spatrick }
202061da546Spatrick 
WriteGPR()203061da546Spatrick int RegisterContextDarwin_arm64::WriteGPR() {
204061da546Spatrick   int set = GPRRegSet;
205061da546Spatrick   if (!RegisterSetIsCached(set)) {
206061da546Spatrick     SetError(set, Write, -1);
207061da546Spatrick     return KERN_INVALID_ARGUMENT;
208061da546Spatrick   }
209061da546Spatrick   SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));
210061da546Spatrick   SetError(set, Read, -1);
211061da546Spatrick   return GetError(GPRRegSet, Write);
212061da546Spatrick }
213061da546Spatrick 
WriteFPU()214061da546Spatrick int RegisterContextDarwin_arm64::WriteFPU() {
215061da546Spatrick   int set = FPURegSet;
216061da546Spatrick   if (!RegisterSetIsCached(set)) {
217061da546Spatrick     SetError(set, Write, -1);
218061da546Spatrick     return KERN_INVALID_ARGUMENT;
219061da546Spatrick   }
220061da546Spatrick   SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu));
221061da546Spatrick   SetError(set, Read, -1);
222061da546Spatrick   return GetError(FPURegSet, Write);
223061da546Spatrick }
224061da546Spatrick 
WriteEXC()225061da546Spatrick int RegisterContextDarwin_arm64::WriteEXC() {
226061da546Spatrick   int set = EXCRegSet;
227061da546Spatrick   if (!RegisterSetIsCached(set)) {
228061da546Spatrick     SetError(set, Write, -1);
229061da546Spatrick     return KERN_INVALID_ARGUMENT;
230061da546Spatrick   }
231061da546Spatrick   SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));
232061da546Spatrick   SetError(set, Read, -1);
233061da546Spatrick   return GetError(EXCRegSet, Write);
234061da546Spatrick }
235061da546Spatrick 
WriteDBG()236061da546Spatrick int RegisterContextDarwin_arm64::WriteDBG() {
237061da546Spatrick   int set = DBGRegSet;
238061da546Spatrick   if (!RegisterSetIsCached(set)) {
239061da546Spatrick     SetError(set, Write, -1);
240061da546Spatrick     return KERN_INVALID_ARGUMENT;
241061da546Spatrick   }
242061da546Spatrick   SetError(set, Write, DoWriteDBG(GetThreadID(), set, dbg));
243061da546Spatrick   SetError(set, Read, -1);
244061da546Spatrick   return GetError(DBGRegSet, Write);
245061da546Spatrick }
246061da546Spatrick 
ReadRegisterSet(uint32_t set,bool force)247061da546Spatrick int RegisterContextDarwin_arm64::ReadRegisterSet(uint32_t set, bool force) {
248061da546Spatrick   switch (set) {
249061da546Spatrick   case GPRRegSet:
250061da546Spatrick     return ReadGPR(force);
251061da546Spatrick   case FPURegSet:
252061da546Spatrick     return ReadFPU(force);
253061da546Spatrick   case EXCRegSet:
254061da546Spatrick     return ReadEXC(force);
255061da546Spatrick   case DBGRegSet:
256061da546Spatrick     return ReadDBG(force);
257061da546Spatrick   default:
258061da546Spatrick     break;
259061da546Spatrick   }
260061da546Spatrick   return KERN_INVALID_ARGUMENT;
261061da546Spatrick }
262061da546Spatrick 
WriteRegisterSet(uint32_t set)263061da546Spatrick int RegisterContextDarwin_arm64::WriteRegisterSet(uint32_t set) {
264061da546Spatrick   // Make sure we have a valid context to set.
265061da546Spatrick   if (RegisterSetIsCached(set)) {
266061da546Spatrick     switch (set) {
267061da546Spatrick     case GPRRegSet:
268061da546Spatrick       return WriteGPR();
269061da546Spatrick     case FPURegSet:
270061da546Spatrick       return WriteFPU();
271061da546Spatrick     case EXCRegSet:
272061da546Spatrick       return WriteEXC();
273061da546Spatrick     case DBGRegSet:
274061da546Spatrick       return WriteDBG();
275061da546Spatrick     default:
276061da546Spatrick       break;
277061da546Spatrick     }
278061da546Spatrick   }
279061da546Spatrick   return KERN_INVALID_ARGUMENT;
280061da546Spatrick }
281061da546Spatrick 
LogDBGRegisters(Log * log,const DBG & dbg)282061da546Spatrick void RegisterContextDarwin_arm64::LogDBGRegisters(Log *log, const DBG &dbg) {
283061da546Spatrick   if (log) {
284061da546Spatrick     for (uint32_t i = 0; i < 16; i++)
285061da546Spatrick       LLDB_LOGF(log,
286061da546Spatrick                 "BVR%-2u/BCR%-2u = { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64
287061da546Spatrick                 " } WVR%-2u/WCR%-2u "
288061da546Spatrick                 "= { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 " }",
289061da546Spatrick                 i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]);
290061da546Spatrick   }
291061da546Spatrick }
292061da546Spatrick 
ReadRegister(const RegisterInfo * reg_info,RegisterValue & value)293061da546Spatrick bool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info,
294061da546Spatrick                                                RegisterValue &value) {
295061da546Spatrick   const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
296061da546Spatrick   int set = RegisterContextDarwin_arm64::GetSetForNativeRegNum(reg);
297061da546Spatrick 
298061da546Spatrick   if (set == -1)
299061da546Spatrick     return false;
300061da546Spatrick 
301061da546Spatrick   if (ReadRegisterSet(set, false) != KERN_SUCCESS)
302061da546Spatrick     return false;
303061da546Spatrick 
304061da546Spatrick   switch (reg) {
305061da546Spatrick   case gpr_x0:
306061da546Spatrick   case gpr_x1:
307061da546Spatrick   case gpr_x2:
308061da546Spatrick   case gpr_x3:
309061da546Spatrick   case gpr_x4:
310061da546Spatrick   case gpr_x5:
311061da546Spatrick   case gpr_x6:
312061da546Spatrick   case gpr_x7:
313061da546Spatrick   case gpr_x8:
314061da546Spatrick   case gpr_x9:
315061da546Spatrick   case gpr_x10:
316061da546Spatrick   case gpr_x11:
317061da546Spatrick   case gpr_x12:
318061da546Spatrick   case gpr_x13:
319061da546Spatrick   case gpr_x14:
320061da546Spatrick   case gpr_x15:
321061da546Spatrick   case gpr_x16:
322061da546Spatrick   case gpr_x17:
323061da546Spatrick   case gpr_x18:
324061da546Spatrick   case gpr_x19:
325061da546Spatrick   case gpr_x20:
326061da546Spatrick   case gpr_x21:
327061da546Spatrick   case gpr_x22:
328061da546Spatrick   case gpr_x23:
329061da546Spatrick   case gpr_x24:
330061da546Spatrick   case gpr_x25:
331061da546Spatrick   case gpr_x26:
332061da546Spatrick   case gpr_x27:
333061da546Spatrick   case gpr_x28:
334061da546Spatrick     value.SetUInt64(gpr.x[reg - gpr_x0]);
335061da546Spatrick     break;
336061da546Spatrick   case gpr_fp:
337061da546Spatrick     value.SetUInt64(gpr.fp);
338061da546Spatrick     break;
339061da546Spatrick   case gpr_sp:
340061da546Spatrick     value.SetUInt64(gpr.sp);
341061da546Spatrick     break;
342061da546Spatrick   case gpr_lr:
343061da546Spatrick     value.SetUInt64(gpr.lr);
344061da546Spatrick     break;
345061da546Spatrick   case gpr_pc:
346061da546Spatrick     value.SetUInt64(gpr.pc);
347061da546Spatrick     break;
348061da546Spatrick   case gpr_cpsr:
349061da546Spatrick     value.SetUInt64(gpr.cpsr);
350061da546Spatrick     break;
351061da546Spatrick 
352061da546Spatrick   case gpr_w0:
353061da546Spatrick   case gpr_w1:
354061da546Spatrick   case gpr_w2:
355061da546Spatrick   case gpr_w3:
356061da546Spatrick   case gpr_w4:
357061da546Spatrick   case gpr_w5:
358061da546Spatrick   case gpr_w6:
359061da546Spatrick   case gpr_w7:
360061da546Spatrick   case gpr_w8:
361061da546Spatrick   case gpr_w9:
362061da546Spatrick   case gpr_w10:
363061da546Spatrick   case gpr_w11:
364061da546Spatrick   case gpr_w12:
365061da546Spatrick   case gpr_w13:
366061da546Spatrick   case gpr_w14:
367061da546Spatrick   case gpr_w15:
368061da546Spatrick   case gpr_w16:
369061da546Spatrick   case gpr_w17:
370061da546Spatrick   case gpr_w18:
371061da546Spatrick   case gpr_w19:
372061da546Spatrick   case gpr_w20:
373061da546Spatrick   case gpr_w21:
374061da546Spatrick   case gpr_w22:
375061da546Spatrick   case gpr_w23:
376061da546Spatrick   case gpr_w24:
377061da546Spatrick   case gpr_w25:
378061da546Spatrick   case gpr_w26:
379061da546Spatrick   case gpr_w27:
380061da546Spatrick   case gpr_w28: {
381061da546Spatrick     ProcessSP process_sp(m_thread.GetProcess());
382061da546Spatrick     if (process_sp.get()) {
383061da546Spatrick       DataExtractor regdata(&gpr.x[reg - gpr_w0], 8, process_sp->GetByteOrder(),
384061da546Spatrick                             process_sp->GetAddressByteSize());
385061da546Spatrick       offset_t offset = 0;
386061da546Spatrick       uint64_t retval = regdata.GetMaxU64(&offset, 8);
387061da546Spatrick       uint32_t retval_lower32 = static_cast<uint32_t>(retval & 0xffffffff);
388061da546Spatrick       value.SetUInt32(retval_lower32);
389061da546Spatrick     }
390061da546Spatrick   } break;
391061da546Spatrick 
392061da546Spatrick   case fpu_v0:
393061da546Spatrick   case fpu_v1:
394061da546Spatrick   case fpu_v2:
395061da546Spatrick   case fpu_v3:
396061da546Spatrick   case fpu_v4:
397061da546Spatrick   case fpu_v5:
398061da546Spatrick   case fpu_v6:
399061da546Spatrick   case fpu_v7:
400061da546Spatrick   case fpu_v8:
401061da546Spatrick   case fpu_v9:
402061da546Spatrick   case fpu_v10:
403061da546Spatrick   case fpu_v11:
404061da546Spatrick   case fpu_v12:
405061da546Spatrick   case fpu_v13:
406061da546Spatrick   case fpu_v14:
407061da546Spatrick   case fpu_v15:
408061da546Spatrick   case fpu_v16:
409061da546Spatrick   case fpu_v17:
410061da546Spatrick   case fpu_v18:
411061da546Spatrick   case fpu_v19:
412061da546Spatrick   case fpu_v20:
413061da546Spatrick   case fpu_v21:
414061da546Spatrick   case fpu_v22:
415061da546Spatrick   case fpu_v23:
416061da546Spatrick   case fpu_v24:
417061da546Spatrick   case fpu_v25:
418061da546Spatrick   case fpu_v26:
419061da546Spatrick   case fpu_v27:
420061da546Spatrick   case fpu_v28:
421061da546Spatrick   case fpu_v29:
422061da546Spatrick   case fpu_v30:
423061da546Spatrick   case fpu_v31:
424061da546Spatrick     value.SetBytes(fpu.v[reg - fpu_v0].bytes, reg_info->byte_size,
425061da546Spatrick                    endian::InlHostByteOrder());
426061da546Spatrick     break;
427061da546Spatrick 
428061da546Spatrick   case fpu_s0:
429061da546Spatrick   case fpu_s1:
430061da546Spatrick   case fpu_s2:
431061da546Spatrick   case fpu_s3:
432061da546Spatrick   case fpu_s4:
433061da546Spatrick   case fpu_s5:
434061da546Spatrick   case fpu_s6:
435061da546Spatrick   case fpu_s7:
436061da546Spatrick   case fpu_s8:
437061da546Spatrick   case fpu_s9:
438061da546Spatrick   case fpu_s10:
439061da546Spatrick   case fpu_s11:
440061da546Spatrick   case fpu_s12:
441061da546Spatrick   case fpu_s13:
442061da546Spatrick   case fpu_s14:
443061da546Spatrick   case fpu_s15:
444061da546Spatrick   case fpu_s16:
445061da546Spatrick   case fpu_s17:
446061da546Spatrick   case fpu_s18:
447061da546Spatrick   case fpu_s19:
448061da546Spatrick   case fpu_s20:
449061da546Spatrick   case fpu_s21:
450061da546Spatrick   case fpu_s22:
451061da546Spatrick   case fpu_s23:
452061da546Spatrick   case fpu_s24:
453061da546Spatrick   case fpu_s25:
454061da546Spatrick   case fpu_s26:
455061da546Spatrick   case fpu_s27:
456061da546Spatrick   case fpu_s28:
457061da546Spatrick   case fpu_s29:
458061da546Spatrick   case fpu_s30:
459061da546Spatrick   case fpu_s31: {
460061da546Spatrick     ProcessSP process_sp(m_thread.GetProcess());
461061da546Spatrick     if (process_sp.get()) {
462061da546Spatrick       DataExtractor regdata(&fpu.v[reg - fpu_s0], 4, process_sp->GetByteOrder(),
463061da546Spatrick                             process_sp->GetAddressByteSize());
464061da546Spatrick       offset_t offset = 0;
465061da546Spatrick       value.SetFloat(regdata.GetFloat(&offset));
466061da546Spatrick     }
467061da546Spatrick   } break;
468061da546Spatrick 
469061da546Spatrick   case fpu_d0:
470061da546Spatrick   case fpu_d1:
471061da546Spatrick   case fpu_d2:
472061da546Spatrick   case fpu_d3:
473061da546Spatrick   case fpu_d4:
474061da546Spatrick   case fpu_d5:
475061da546Spatrick   case fpu_d6:
476061da546Spatrick   case fpu_d7:
477061da546Spatrick   case fpu_d8:
478061da546Spatrick   case fpu_d9:
479061da546Spatrick   case fpu_d10:
480061da546Spatrick   case fpu_d11:
481061da546Spatrick   case fpu_d12:
482061da546Spatrick   case fpu_d13:
483061da546Spatrick   case fpu_d14:
484061da546Spatrick   case fpu_d15:
485061da546Spatrick   case fpu_d16:
486061da546Spatrick   case fpu_d17:
487061da546Spatrick   case fpu_d18:
488061da546Spatrick   case fpu_d19:
489061da546Spatrick   case fpu_d20:
490061da546Spatrick   case fpu_d21:
491061da546Spatrick   case fpu_d22:
492061da546Spatrick   case fpu_d23:
493061da546Spatrick   case fpu_d24:
494061da546Spatrick   case fpu_d25:
495061da546Spatrick   case fpu_d26:
496061da546Spatrick   case fpu_d27:
497061da546Spatrick   case fpu_d28:
498061da546Spatrick   case fpu_d29:
499061da546Spatrick   case fpu_d30:
500061da546Spatrick   case fpu_d31: {
501061da546Spatrick     ProcessSP process_sp(m_thread.GetProcess());
502061da546Spatrick     if (process_sp.get()) {
503061da546Spatrick       DataExtractor regdata(&fpu.v[reg - fpu_d0], 8, process_sp->GetByteOrder(),
504061da546Spatrick                             process_sp->GetAddressByteSize());
505061da546Spatrick       offset_t offset = 0;
506061da546Spatrick       value.SetDouble(regdata.GetDouble(&offset));
507061da546Spatrick     }
508061da546Spatrick   } break;
509061da546Spatrick 
510061da546Spatrick   case fpu_fpsr:
511061da546Spatrick     value.SetUInt32(fpu.fpsr);
512061da546Spatrick     break;
513061da546Spatrick 
514061da546Spatrick   case fpu_fpcr:
515061da546Spatrick     value.SetUInt32(fpu.fpcr);
516061da546Spatrick     break;
517061da546Spatrick 
518061da546Spatrick   case exc_exception:
519061da546Spatrick     value.SetUInt32(exc.exception);
520061da546Spatrick     break;
521061da546Spatrick   case exc_esr:
522061da546Spatrick     value.SetUInt32(exc.esr);
523061da546Spatrick     break;
524061da546Spatrick   case exc_far:
525061da546Spatrick     value.SetUInt64(exc.far);
526061da546Spatrick     break;
527061da546Spatrick 
528061da546Spatrick   default:
529061da546Spatrick     value.SetValueToInvalid();
530061da546Spatrick     return false;
531061da546Spatrick   }
532061da546Spatrick   return true;
533061da546Spatrick }
534061da546Spatrick 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & value)535061da546Spatrick bool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info,
536061da546Spatrick                                                 const RegisterValue &value) {
537061da546Spatrick   const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
538061da546Spatrick   int set = GetSetForNativeRegNum(reg);
539061da546Spatrick 
540061da546Spatrick   if (set == -1)
541061da546Spatrick     return false;
542061da546Spatrick 
543061da546Spatrick   if (ReadRegisterSet(set, false) != KERN_SUCCESS)
544061da546Spatrick     return false;
545061da546Spatrick 
546061da546Spatrick   switch (reg) {
547061da546Spatrick   case gpr_x0:
548061da546Spatrick   case gpr_x1:
549061da546Spatrick   case gpr_x2:
550061da546Spatrick   case gpr_x3:
551061da546Spatrick   case gpr_x4:
552061da546Spatrick   case gpr_x5:
553061da546Spatrick   case gpr_x6:
554061da546Spatrick   case gpr_x7:
555061da546Spatrick   case gpr_x8:
556061da546Spatrick   case gpr_x9:
557061da546Spatrick   case gpr_x10:
558061da546Spatrick   case gpr_x11:
559061da546Spatrick   case gpr_x12:
560061da546Spatrick   case gpr_x13:
561061da546Spatrick   case gpr_x14:
562061da546Spatrick   case gpr_x15:
563061da546Spatrick   case gpr_x16:
564061da546Spatrick   case gpr_x17:
565061da546Spatrick   case gpr_x18:
566061da546Spatrick   case gpr_x19:
567061da546Spatrick   case gpr_x20:
568061da546Spatrick   case gpr_x21:
569061da546Spatrick   case gpr_x22:
570061da546Spatrick   case gpr_x23:
571061da546Spatrick   case gpr_x24:
572061da546Spatrick   case gpr_x25:
573061da546Spatrick   case gpr_x26:
574061da546Spatrick   case gpr_x27:
575061da546Spatrick   case gpr_x28:
576061da546Spatrick   case gpr_fp:
577061da546Spatrick   case gpr_sp:
578061da546Spatrick   case gpr_lr:
579061da546Spatrick   case gpr_pc:
580061da546Spatrick   case gpr_cpsr:
581061da546Spatrick     gpr.x[reg - gpr_x0] = value.GetAsUInt64();
582061da546Spatrick     break;
583061da546Spatrick 
584061da546Spatrick   case fpu_v0:
585061da546Spatrick   case fpu_v1:
586061da546Spatrick   case fpu_v2:
587061da546Spatrick   case fpu_v3:
588061da546Spatrick   case fpu_v4:
589061da546Spatrick   case fpu_v5:
590061da546Spatrick   case fpu_v6:
591061da546Spatrick   case fpu_v7:
592061da546Spatrick   case fpu_v8:
593061da546Spatrick   case fpu_v9:
594061da546Spatrick   case fpu_v10:
595061da546Spatrick   case fpu_v11:
596061da546Spatrick   case fpu_v12:
597061da546Spatrick   case fpu_v13:
598061da546Spatrick   case fpu_v14:
599061da546Spatrick   case fpu_v15:
600061da546Spatrick   case fpu_v16:
601061da546Spatrick   case fpu_v17:
602061da546Spatrick   case fpu_v18:
603061da546Spatrick   case fpu_v19:
604061da546Spatrick   case fpu_v20:
605061da546Spatrick   case fpu_v21:
606061da546Spatrick   case fpu_v22:
607061da546Spatrick   case fpu_v23:
608061da546Spatrick   case fpu_v24:
609061da546Spatrick   case fpu_v25:
610061da546Spatrick   case fpu_v26:
611061da546Spatrick   case fpu_v27:
612061da546Spatrick   case fpu_v28:
613061da546Spatrick   case fpu_v29:
614061da546Spatrick   case fpu_v30:
615061da546Spatrick   case fpu_v31:
616061da546Spatrick     ::memcpy(fpu.v[reg - fpu_v0].bytes, value.GetBytes(),
617061da546Spatrick              value.GetByteSize());
618061da546Spatrick     break;
619061da546Spatrick 
620061da546Spatrick   case fpu_fpsr:
621061da546Spatrick     fpu.fpsr = value.GetAsUInt32();
622061da546Spatrick     break;
623061da546Spatrick 
624061da546Spatrick   case fpu_fpcr:
625061da546Spatrick     fpu.fpcr = value.GetAsUInt32();
626061da546Spatrick     break;
627061da546Spatrick 
628061da546Spatrick   case exc_exception:
629061da546Spatrick     exc.exception = value.GetAsUInt32();
630061da546Spatrick     break;
631061da546Spatrick   case exc_esr:
632061da546Spatrick     exc.esr = value.GetAsUInt32();
633061da546Spatrick     break;
634061da546Spatrick   case exc_far:
635061da546Spatrick     exc.far = value.GetAsUInt64();
636061da546Spatrick     break;
637061da546Spatrick 
638061da546Spatrick   default:
639061da546Spatrick     return false;
640061da546Spatrick   }
641061da546Spatrick   return WriteRegisterSet(set) == KERN_SUCCESS;
642061da546Spatrick }
643061da546Spatrick 
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)644061da546Spatrick bool RegisterContextDarwin_arm64::ReadAllRegisterValues(
645*f6aab3d8Srobert     lldb::WritableDataBufferSP &data_sp) {
646061da546Spatrick   data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
647061da546Spatrick   if (ReadGPR(false) == KERN_SUCCESS && ReadFPU(false) == KERN_SUCCESS &&
648061da546Spatrick       ReadEXC(false) == KERN_SUCCESS) {
649061da546Spatrick     uint8_t *dst = data_sp->GetBytes();
650061da546Spatrick     ::memcpy(dst, &gpr, sizeof(gpr));
651061da546Spatrick     dst += sizeof(gpr);
652061da546Spatrick 
653061da546Spatrick     ::memcpy(dst, &fpu, sizeof(fpu));
654061da546Spatrick     dst += sizeof(gpr);
655061da546Spatrick 
656061da546Spatrick     ::memcpy(dst, &exc, sizeof(exc));
657061da546Spatrick     return true;
658061da546Spatrick   }
659061da546Spatrick   return false;
660061da546Spatrick }
661061da546Spatrick 
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)662061da546Spatrick bool RegisterContextDarwin_arm64::WriteAllRegisterValues(
663061da546Spatrick     const lldb::DataBufferSP &data_sp) {
664061da546Spatrick   if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
665061da546Spatrick     const uint8_t *src = data_sp->GetBytes();
666061da546Spatrick     ::memcpy(&gpr, src, sizeof(gpr));
667061da546Spatrick     src += sizeof(gpr);
668061da546Spatrick 
669061da546Spatrick     ::memcpy(&fpu, src, sizeof(fpu));
670061da546Spatrick     src += sizeof(gpr);
671061da546Spatrick 
672061da546Spatrick     ::memcpy(&exc, src, sizeof(exc));
673061da546Spatrick     uint32_t success_count = 0;
674061da546Spatrick     if (WriteGPR() == KERN_SUCCESS)
675061da546Spatrick       ++success_count;
676061da546Spatrick     if (WriteFPU() == KERN_SUCCESS)
677061da546Spatrick       ++success_count;
678061da546Spatrick     if (WriteEXC() == KERN_SUCCESS)
679061da546Spatrick       ++success_count;
680061da546Spatrick     return success_count == 3;
681061da546Spatrick   }
682061da546Spatrick   return false;
683061da546Spatrick }
684061da546Spatrick 
ConvertRegisterKindToRegisterNumber(RegisterKind kind,uint32_t reg)685061da546Spatrick uint32_t RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber(
686061da546Spatrick     RegisterKind kind, uint32_t reg) {
687061da546Spatrick   if (kind == eRegisterKindGeneric) {
688061da546Spatrick     switch (reg) {
689061da546Spatrick     case LLDB_REGNUM_GENERIC_PC:
690061da546Spatrick       return gpr_pc;
691061da546Spatrick     case LLDB_REGNUM_GENERIC_SP:
692061da546Spatrick       return gpr_sp;
693061da546Spatrick     case LLDB_REGNUM_GENERIC_FP:
694061da546Spatrick       return gpr_fp;
695061da546Spatrick     case LLDB_REGNUM_GENERIC_RA:
696061da546Spatrick       return gpr_lr;
697061da546Spatrick     case LLDB_REGNUM_GENERIC_FLAGS:
698061da546Spatrick       return gpr_cpsr;
699061da546Spatrick     default:
700061da546Spatrick       break;
701061da546Spatrick     }
702061da546Spatrick   } else if (kind == eRegisterKindDWARF) {
703061da546Spatrick     switch (reg) {
704061da546Spatrick     case arm64_dwarf::x0:
705061da546Spatrick       return gpr_x0;
706061da546Spatrick     case arm64_dwarf::x1:
707061da546Spatrick       return gpr_x1;
708061da546Spatrick     case arm64_dwarf::x2:
709061da546Spatrick       return gpr_x2;
710061da546Spatrick     case arm64_dwarf::x3:
711061da546Spatrick       return gpr_x3;
712061da546Spatrick     case arm64_dwarf::x4:
713061da546Spatrick       return gpr_x4;
714061da546Spatrick     case arm64_dwarf::x5:
715061da546Spatrick       return gpr_x5;
716061da546Spatrick     case arm64_dwarf::x6:
717061da546Spatrick       return gpr_x6;
718061da546Spatrick     case arm64_dwarf::x7:
719061da546Spatrick       return gpr_x7;
720061da546Spatrick     case arm64_dwarf::x8:
721061da546Spatrick       return gpr_x8;
722061da546Spatrick     case arm64_dwarf::x9:
723061da546Spatrick       return gpr_x9;
724061da546Spatrick     case arm64_dwarf::x10:
725061da546Spatrick       return gpr_x10;
726061da546Spatrick     case arm64_dwarf::x11:
727061da546Spatrick       return gpr_x11;
728061da546Spatrick     case arm64_dwarf::x12:
729061da546Spatrick       return gpr_x12;
730061da546Spatrick     case arm64_dwarf::x13:
731061da546Spatrick       return gpr_x13;
732061da546Spatrick     case arm64_dwarf::x14:
733061da546Spatrick       return gpr_x14;
734061da546Spatrick     case arm64_dwarf::x15:
735061da546Spatrick       return gpr_x15;
736061da546Spatrick     case arm64_dwarf::x16:
737061da546Spatrick       return gpr_x16;
738061da546Spatrick     case arm64_dwarf::x17:
739061da546Spatrick       return gpr_x17;
740061da546Spatrick     case arm64_dwarf::x18:
741061da546Spatrick       return gpr_x18;
742061da546Spatrick     case arm64_dwarf::x19:
743061da546Spatrick       return gpr_x19;
744061da546Spatrick     case arm64_dwarf::x20:
745061da546Spatrick       return gpr_x20;
746061da546Spatrick     case arm64_dwarf::x21:
747061da546Spatrick       return gpr_x21;
748061da546Spatrick     case arm64_dwarf::x22:
749061da546Spatrick       return gpr_x22;
750061da546Spatrick     case arm64_dwarf::x23:
751061da546Spatrick       return gpr_x23;
752061da546Spatrick     case arm64_dwarf::x24:
753061da546Spatrick       return gpr_x24;
754061da546Spatrick     case arm64_dwarf::x25:
755061da546Spatrick       return gpr_x25;
756061da546Spatrick     case arm64_dwarf::x26:
757061da546Spatrick       return gpr_x26;
758061da546Spatrick     case arm64_dwarf::x27:
759061da546Spatrick       return gpr_x27;
760061da546Spatrick     case arm64_dwarf::x28:
761061da546Spatrick       return gpr_x28;
762061da546Spatrick 
763061da546Spatrick     case arm64_dwarf::fp:
764061da546Spatrick       return gpr_fp;
765061da546Spatrick     case arm64_dwarf::sp:
766061da546Spatrick       return gpr_sp;
767061da546Spatrick     case arm64_dwarf::lr:
768061da546Spatrick       return gpr_lr;
769061da546Spatrick     case arm64_dwarf::pc:
770061da546Spatrick       return gpr_pc;
771061da546Spatrick     case arm64_dwarf::cpsr:
772061da546Spatrick       return gpr_cpsr;
773061da546Spatrick 
774061da546Spatrick     case arm64_dwarf::v0:
775061da546Spatrick       return fpu_v0;
776061da546Spatrick     case arm64_dwarf::v1:
777061da546Spatrick       return fpu_v1;
778061da546Spatrick     case arm64_dwarf::v2:
779061da546Spatrick       return fpu_v2;
780061da546Spatrick     case arm64_dwarf::v3:
781061da546Spatrick       return fpu_v3;
782061da546Spatrick     case arm64_dwarf::v4:
783061da546Spatrick       return fpu_v4;
784061da546Spatrick     case arm64_dwarf::v5:
785061da546Spatrick       return fpu_v5;
786061da546Spatrick     case arm64_dwarf::v6:
787061da546Spatrick       return fpu_v6;
788061da546Spatrick     case arm64_dwarf::v7:
789061da546Spatrick       return fpu_v7;
790061da546Spatrick     case arm64_dwarf::v8:
791061da546Spatrick       return fpu_v8;
792061da546Spatrick     case arm64_dwarf::v9:
793061da546Spatrick       return fpu_v9;
794061da546Spatrick     case arm64_dwarf::v10:
795061da546Spatrick       return fpu_v10;
796061da546Spatrick     case arm64_dwarf::v11:
797061da546Spatrick       return fpu_v11;
798061da546Spatrick     case arm64_dwarf::v12:
799061da546Spatrick       return fpu_v12;
800061da546Spatrick     case arm64_dwarf::v13:
801061da546Spatrick       return fpu_v13;
802061da546Spatrick     case arm64_dwarf::v14:
803061da546Spatrick       return fpu_v14;
804061da546Spatrick     case arm64_dwarf::v15:
805061da546Spatrick       return fpu_v15;
806061da546Spatrick     case arm64_dwarf::v16:
807061da546Spatrick       return fpu_v16;
808061da546Spatrick     case arm64_dwarf::v17:
809061da546Spatrick       return fpu_v17;
810061da546Spatrick     case arm64_dwarf::v18:
811061da546Spatrick       return fpu_v18;
812061da546Spatrick     case arm64_dwarf::v19:
813061da546Spatrick       return fpu_v19;
814061da546Spatrick     case arm64_dwarf::v20:
815061da546Spatrick       return fpu_v20;
816061da546Spatrick     case arm64_dwarf::v21:
817061da546Spatrick       return fpu_v21;
818061da546Spatrick     case arm64_dwarf::v22:
819061da546Spatrick       return fpu_v22;
820061da546Spatrick     case arm64_dwarf::v23:
821061da546Spatrick       return fpu_v23;
822061da546Spatrick     case arm64_dwarf::v24:
823061da546Spatrick       return fpu_v24;
824061da546Spatrick     case arm64_dwarf::v25:
825061da546Spatrick       return fpu_v25;
826061da546Spatrick     case arm64_dwarf::v26:
827061da546Spatrick       return fpu_v26;
828061da546Spatrick     case arm64_dwarf::v27:
829061da546Spatrick       return fpu_v27;
830061da546Spatrick     case arm64_dwarf::v28:
831061da546Spatrick       return fpu_v28;
832061da546Spatrick     case arm64_dwarf::v29:
833061da546Spatrick       return fpu_v29;
834061da546Spatrick     case arm64_dwarf::v30:
835061da546Spatrick       return fpu_v30;
836061da546Spatrick     case arm64_dwarf::v31:
837061da546Spatrick       return fpu_v31;
838061da546Spatrick 
839061da546Spatrick     default:
840061da546Spatrick       break;
841061da546Spatrick     }
842061da546Spatrick   } else if (kind == eRegisterKindEHFrame) {
843061da546Spatrick     switch (reg) {
844061da546Spatrick     case arm64_ehframe::x0:
845061da546Spatrick       return gpr_x0;
846061da546Spatrick     case arm64_ehframe::x1:
847061da546Spatrick       return gpr_x1;
848061da546Spatrick     case arm64_ehframe::x2:
849061da546Spatrick       return gpr_x2;
850061da546Spatrick     case arm64_ehframe::x3:
851061da546Spatrick       return gpr_x3;
852061da546Spatrick     case arm64_ehframe::x4:
853061da546Spatrick       return gpr_x4;
854061da546Spatrick     case arm64_ehframe::x5:
855061da546Spatrick       return gpr_x5;
856061da546Spatrick     case arm64_ehframe::x6:
857061da546Spatrick       return gpr_x6;
858061da546Spatrick     case arm64_ehframe::x7:
859061da546Spatrick       return gpr_x7;
860061da546Spatrick     case arm64_ehframe::x8:
861061da546Spatrick       return gpr_x8;
862061da546Spatrick     case arm64_ehframe::x9:
863061da546Spatrick       return gpr_x9;
864061da546Spatrick     case arm64_ehframe::x10:
865061da546Spatrick       return gpr_x10;
866061da546Spatrick     case arm64_ehframe::x11:
867061da546Spatrick       return gpr_x11;
868061da546Spatrick     case arm64_ehframe::x12:
869061da546Spatrick       return gpr_x12;
870061da546Spatrick     case arm64_ehframe::x13:
871061da546Spatrick       return gpr_x13;
872061da546Spatrick     case arm64_ehframe::x14:
873061da546Spatrick       return gpr_x14;
874061da546Spatrick     case arm64_ehframe::x15:
875061da546Spatrick       return gpr_x15;
876061da546Spatrick     case arm64_ehframe::x16:
877061da546Spatrick       return gpr_x16;
878061da546Spatrick     case arm64_ehframe::x17:
879061da546Spatrick       return gpr_x17;
880061da546Spatrick     case arm64_ehframe::x18:
881061da546Spatrick       return gpr_x18;
882061da546Spatrick     case arm64_ehframe::x19:
883061da546Spatrick       return gpr_x19;
884061da546Spatrick     case arm64_ehframe::x20:
885061da546Spatrick       return gpr_x20;
886061da546Spatrick     case arm64_ehframe::x21:
887061da546Spatrick       return gpr_x21;
888061da546Spatrick     case arm64_ehframe::x22:
889061da546Spatrick       return gpr_x22;
890061da546Spatrick     case arm64_ehframe::x23:
891061da546Spatrick       return gpr_x23;
892061da546Spatrick     case arm64_ehframe::x24:
893061da546Spatrick       return gpr_x24;
894061da546Spatrick     case arm64_ehframe::x25:
895061da546Spatrick       return gpr_x25;
896061da546Spatrick     case arm64_ehframe::x26:
897061da546Spatrick       return gpr_x26;
898061da546Spatrick     case arm64_ehframe::x27:
899061da546Spatrick       return gpr_x27;
900061da546Spatrick     case arm64_ehframe::x28:
901061da546Spatrick       return gpr_x28;
902061da546Spatrick     case arm64_ehframe::fp:
903061da546Spatrick       return gpr_fp;
904061da546Spatrick     case arm64_ehframe::sp:
905061da546Spatrick       return gpr_sp;
906061da546Spatrick     case arm64_ehframe::lr:
907061da546Spatrick       return gpr_lr;
908061da546Spatrick     case arm64_ehframe::pc:
909061da546Spatrick       return gpr_pc;
910061da546Spatrick     case arm64_ehframe::cpsr:
911061da546Spatrick       return gpr_cpsr;
912061da546Spatrick     }
913061da546Spatrick   } else if (kind == eRegisterKindLLDB) {
914061da546Spatrick     return reg;
915061da546Spatrick   }
916061da546Spatrick   return LLDB_INVALID_REGNUM;
917061da546Spatrick }
918061da546Spatrick 
NumSupportedHardwareWatchpoints()919061da546Spatrick uint32_t RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints() {
920061da546Spatrick #if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))
921061da546Spatrick   // autodetect how many watchpoints are supported dynamically...
922061da546Spatrick   static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
923061da546Spatrick   if (g_num_supported_hw_watchpoints == UINT32_MAX) {
924061da546Spatrick     size_t len;
925061da546Spatrick     uint32_t n = 0;
926061da546Spatrick     len = sizeof(n);
927061da546Spatrick     if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) {
928061da546Spatrick       g_num_supported_hw_watchpoints = n;
929061da546Spatrick     }
930061da546Spatrick   }
931061da546Spatrick   return g_num_supported_hw_watchpoints;
932061da546Spatrick #else
933061da546Spatrick   // TODO: figure out remote case here!
934061da546Spatrick   return 2;
935061da546Spatrick #endif
936061da546Spatrick }
937061da546Spatrick 
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,bool read,bool write)938061da546Spatrick uint32_t RegisterContextDarwin_arm64::SetHardwareWatchpoint(lldb::addr_t addr,
939061da546Spatrick                                                             size_t size,
940061da546Spatrick                                                             bool read,
941061da546Spatrick                                                             bool write) {
942061da546Spatrick   //    if (log) log->Printf
943061da546Spatrick   //    ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(addr = %8.8p,
944061da546Spatrick   //    size = %u, read = %u, write = %u)", addr, size, read, write);
945061da546Spatrick 
946061da546Spatrick   const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
947061da546Spatrick 
948061da546Spatrick   // Can't watch zero bytes
949061da546Spatrick   if (size == 0)
950061da546Spatrick     return LLDB_INVALID_INDEX32;
951061da546Spatrick 
952061da546Spatrick   // We must watch for either read or write
953061da546Spatrick   if (!read && !write)
954061da546Spatrick     return LLDB_INVALID_INDEX32;
955061da546Spatrick 
956061da546Spatrick   // Can't watch more than 4 bytes per WVR/WCR pair
957061da546Spatrick   if (size > 4)
958061da546Spatrick     return LLDB_INVALID_INDEX32;
959061da546Spatrick 
960061da546Spatrick   // We can only watch up to four bytes that follow a 4 byte aligned address
961061da546Spatrick   // per watchpoint register pair. Since we have at most so we can only watch
962061da546Spatrick   // until the next 4 byte boundary and we need to make sure we can properly
963061da546Spatrick   // encode this.
964061da546Spatrick   uint32_t addr_word_offset = addr % 4;
965061da546Spatrick   //    if (log) log->Printf
966061da546Spatrick   //    ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() -
967061da546Spatrick   //    addr_word_offset = 0x%8.8x", addr_word_offset);
968061da546Spatrick 
969061da546Spatrick   uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
970061da546Spatrick   //    if (log) log->Printf
971061da546Spatrick   //    ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - byte_mask =
972061da546Spatrick   //    0x%8.8x", byte_mask);
973061da546Spatrick   if (byte_mask > 0xfu)
974061da546Spatrick     return LLDB_INVALID_INDEX32;
975061da546Spatrick 
976061da546Spatrick   // Read the debug state
977061da546Spatrick   int kret = ReadDBG(false);
978061da546Spatrick 
979061da546Spatrick   if (kret == KERN_SUCCESS) {
980061da546Spatrick     // Check to make sure we have the needed hardware support
981061da546Spatrick     uint32_t i = 0;
982061da546Spatrick 
983061da546Spatrick     for (i = 0; i < num_hw_watchpoints; ++i) {
984061da546Spatrick       if ((dbg.wcr[i] & WCR_ENABLE) == 0)
985061da546Spatrick         break; // We found an available hw breakpoint slot (in i)
986061da546Spatrick     }
987061da546Spatrick 
988061da546Spatrick     // See if we found an available hw breakpoint slot above
989061da546Spatrick     if (i < num_hw_watchpoints) {
990061da546Spatrick       // Make the byte_mask into a valid Byte Address Select mask
991061da546Spatrick       uint32_t byte_address_select = byte_mask << 5;
992061da546Spatrick       // Make sure bits 1:0 are clear in our address
993061da546Spatrick       dbg.wvr[i] = addr & ~((lldb::addr_t)3);
994061da546Spatrick       dbg.wcr[i] = byte_address_select |     // Which bytes that follow the IMVA
995061da546Spatrick                                              // that we will watch
996061da546Spatrick                    S_USER |                  // Stop only in user mode
997061da546Spatrick                    (read ? WCR_LOAD : 0) |   // Stop on read access?
998061da546Spatrick                    (write ? WCR_STORE : 0) | // Stop on write access?
999061da546Spatrick                    WCR_ENABLE;               // Enable this watchpoint;
1000061da546Spatrick 
1001061da546Spatrick       kret = WriteDBG();
1002061da546Spatrick       //            if (log) log->Printf
1003061da546Spatrick       //            ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint()
1004061da546Spatrick       //            WriteDBG() => 0x%8.8x.", kret);
1005061da546Spatrick 
1006061da546Spatrick       if (kret == KERN_SUCCESS)
1007061da546Spatrick         return i;
1008061da546Spatrick     } else {
1009061da546Spatrick       //            if (log) log->Printf
1010061da546Spatrick       //            ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint():
1011061da546Spatrick       //            All hardware resources (%u) are in use.",
1012061da546Spatrick       //            num_hw_watchpoints);
1013061da546Spatrick     }
1014061da546Spatrick   }
1015061da546Spatrick   return LLDB_INVALID_INDEX32;
1016061da546Spatrick }
1017061da546Spatrick 
ClearHardwareWatchpoint(uint32_t hw_index)1018061da546Spatrick bool RegisterContextDarwin_arm64::ClearHardwareWatchpoint(uint32_t hw_index) {
1019061da546Spatrick   int kret = ReadDBG(false);
1020061da546Spatrick 
1021061da546Spatrick   const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
1022061da546Spatrick   if (kret == KERN_SUCCESS) {
1023061da546Spatrick     if (hw_index < num_hw_points) {
1024061da546Spatrick       dbg.wcr[hw_index] = 0;
1025061da546Spatrick       //            if (log) log->Printf
1026061da546Spatrick       //            ("RegisterContextDarwin_arm64::ClearHardwareWatchpoint( %u )
1027061da546Spatrick       //            - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
1028061da546Spatrick       //                    hw_index,
1029061da546Spatrick       //                    hw_index,
1030061da546Spatrick       //                    dbg.wvr[hw_index],
1031061da546Spatrick       //                    hw_index,
1032061da546Spatrick       //                    dbg.wcr[hw_index]);
1033061da546Spatrick 
1034061da546Spatrick       kret = WriteDBG();
1035061da546Spatrick 
1036061da546Spatrick       if (kret == KERN_SUCCESS)
1037061da546Spatrick         return true;
1038061da546Spatrick     }
1039061da546Spatrick   }
1040061da546Spatrick   return false;
1041061da546Spatrick }
1042