1 //===-- RegisterContextDarwin_arm64.cpp ---------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #if defined(__APPLE__)
11 
12 #include "RegisterContextDarwin_arm64.h"
13 
14 // C Includes
15 #include <mach/mach_types.h>
16 #include <mach/thread_act.h>
17 #include <sys/sysctl.h>
18 
19 // C++ Includes
20 // Other libraries and framework includes
21 #include "lldb/Core/DataBufferHeap.h"
22 #include "lldb/Core/DataExtractor.h"
23 #include "lldb/Core/Log.h"
24 #include "lldb/Core/RegisterValue.h"
25 #include "lldb/Core/Scalar.h"
26 #include "lldb/Host/Endian.h"
27 #include "llvm/ADT/STLExtras.h"
28 #include "llvm/Support/Compiler.h"
29 
30 #include "Plugins/Process/Utility/InstructionUtils.h"
31 
32 // Support building against older versions of LLVM, this macro was added
33 // recently.
34 #ifndef LLVM_EXTENSION
35 #define LLVM_EXTENSION
36 #endif
37 
38 // Project includes
39 #include "ARM64_GCC_Registers.h"
40 #include "ARM64_DWARF_Registers.h"
41 
42 using namespace lldb;
43 using namespace lldb_private;
44 
45 enum
46 {
47     gpr_x0 = 0,
48     gpr_x1,
49     gpr_x2,
50     gpr_x3,
51     gpr_x4,
52     gpr_x5,
53     gpr_x6,
54     gpr_x7,
55     gpr_x8,
56     gpr_x9,
57     gpr_x10,
58     gpr_x11,
59     gpr_x12,
60     gpr_x13,
61     gpr_x14,
62     gpr_x15,
63     gpr_x16,
64     gpr_x17,
65     gpr_x18,
66     gpr_x19,
67     gpr_x20,
68     gpr_x21,
69     gpr_x22,
70     gpr_x23,
71     gpr_x24,
72     gpr_x25,
73     gpr_x26,
74     gpr_x27,
75     gpr_x28,
76     gpr_x29 = 29,  gpr_fp = gpr_x29,
77     gpr_x30 = 30,  gpr_lr = gpr_x30,  gpr_ra = gpr_x30,
78     gpr_x31 = 31,  gpr_sp = gpr_x31,
79     gpr_pc = 32,
80     gpr_cpsr,
81 
82     fpu_v0,
83     fpu_v1,
84     fpu_v2,
85     fpu_v3,
86     fpu_v4,
87     fpu_v5,
88     fpu_v6,
89     fpu_v7,
90     fpu_v8,
91     fpu_v9,
92     fpu_v10,
93     fpu_v11,
94     fpu_v12,
95     fpu_v13,
96     fpu_v14,
97     fpu_v15,
98     fpu_v16,
99     fpu_v17,
100     fpu_v18,
101     fpu_v19,
102     fpu_v20,
103     fpu_v21,
104     fpu_v22,
105     fpu_v23,
106     fpu_v24,
107     fpu_v25,
108     fpu_v26,
109     fpu_v27,
110     fpu_v28,
111     fpu_v29,
112     fpu_v30,
113     fpu_v31,
114 
115     fpu_fpsr,
116     fpu_fpcr,
117 
118     exc_far,
119     exc_esr,
120     exc_exception,
121 
122     dbg_bvr0,
123     dbg_bvr1,
124     dbg_bvr2,
125     dbg_bvr3,
126     dbg_bvr4,
127     dbg_bvr5,
128     dbg_bvr6,
129     dbg_bvr7,
130     dbg_bvr8,
131     dbg_bvr9,
132     dbg_bvr10,
133     dbg_bvr11,
134     dbg_bvr12,
135     dbg_bvr13,
136     dbg_bvr14,
137     dbg_bvr15,
138 
139     dbg_bcr0,
140     dbg_bcr1,
141     dbg_bcr2,
142     dbg_bcr3,
143     dbg_bcr4,
144     dbg_bcr5,
145     dbg_bcr6,
146     dbg_bcr7,
147     dbg_bcr8,
148     dbg_bcr9,
149     dbg_bcr10,
150     dbg_bcr11,
151     dbg_bcr12,
152     dbg_bcr13,
153     dbg_bcr14,
154     dbg_bcr15,
155 
156     dbg_wvr0,
157     dbg_wvr1,
158     dbg_wvr2,
159     dbg_wvr3,
160     dbg_wvr4,
161     dbg_wvr5,
162     dbg_wvr6,
163     dbg_wvr7,
164     dbg_wvr8,
165     dbg_wvr9,
166     dbg_wvr10,
167     dbg_wvr11,
168     dbg_wvr12,
169     dbg_wvr13,
170     dbg_wvr14,
171     dbg_wvr15,
172 
173     dbg_wcr0,
174     dbg_wcr1,
175     dbg_wcr2,
176     dbg_wcr3,
177     dbg_wcr4,
178     dbg_wcr5,
179     dbg_wcr6,
180     dbg_wcr7,
181     dbg_wcr8,
182     dbg_wcr9,
183     dbg_wcr10,
184     dbg_wcr11,
185     dbg_wcr12,
186     dbg_wcr13,
187     dbg_wcr14,
188     dbg_wcr15,
189 
190     k_num_registers
191 };
192 
193 
194 RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(Thread &thread, uint32_t concrete_frame_idx) :
195     RegisterContext(thread, concrete_frame_idx),
196     gpr(),
197     fpu(),
198     exc()
199 {
200     uint32_t i;
201     for (i=0; i<kNumErrors; i++)
202     {
203         gpr_errs[i] = -1;
204         fpu_errs[i] = -1;
205         exc_errs[i] = -1;
206     }
207 }
208 
209 RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64()
210 {
211 }
212 
213 
214 #define GPR_OFFSET(idx) ((idx) * 8)
215 #define GPR_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::GPR, reg))
216 
217 #define FPU_OFFSET(idx) ((idx) * 16 + sizeof (RegisterContextDarwin_arm64::GPR))
218 #define FPU_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::FPU, reg))
219 
220 #define EXC_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::EXC, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU))
221 #define DBG_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::DBG, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC))
222 
223 #define DEFINE_DBG(reg, i)  #reg, NULL, sizeof(((RegisterContextDarwin_arm64::DBG *)NULL)->reg[i]), DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL
224 #define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC))
225 
226 static RegisterInfo g_register_infos[] = {
227 // General purpose registers
228 //  NAME        ALT     SZ  OFFSET              ENCODING        FORMAT          COMPILER                DWARF               GENERIC                     GDB                     LLDB NATIVE   VALUE REGS    INVALIDATE REGS
229 //  ======      ======= ==  =============       =============   ============    ===============         ===============     =========================   =====================   ============= ==========    ===============
230 {   "x0",       NULL,   8,  GPR_OFFSET(0),      eEncodingUint,  eFormatHex,     { arm64_gcc::x0,               arm64_dwarf::x0,           LLDB_INVALID_REGNUM,        arm64_gcc::x0,             gpr_x0      },      NULL,              NULL},
231 {   "x1",       NULL,   8,  GPR_OFFSET(1),      eEncodingUint,  eFormatHex,     { arm64_gcc::x1,               arm64_dwarf::x1,           LLDB_INVALID_REGNUM,        arm64_gcc::x1,             gpr_x1      },      NULL,              NULL},
232 {   "x2",       NULL,   8,  GPR_OFFSET(2),      eEncodingUint,  eFormatHex,     { arm64_gcc::x2,               arm64_dwarf::x2,           LLDB_INVALID_REGNUM,        arm64_gcc::x2,             gpr_x2      },      NULL,              NULL},
233 {   "x3",       NULL,   8,  GPR_OFFSET(3),      eEncodingUint,  eFormatHex,     { arm64_gcc::x3,               arm64_dwarf::x3,           LLDB_INVALID_REGNUM,        arm64_gcc::x3,             gpr_x3      },      NULL,              NULL},
234 {   "x4",       NULL,   8,  GPR_OFFSET(4),      eEncodingUint,  eFormatHex,     { arm64_gcc::x4,               arm64_dwarf::x4,           LLDB_INVALID_REGNUM,        arm64_gcc::x4,             gpr_x4      },      NULL,              NULL},
235 {   "x5",       NULL,   8,  GPR_OFFSET(5),      eEncodingUint,  eFormatHex,     { arm64_gcc::x5,               arm64_dwarf::x5,           LLDB_INVALID_REGNUM,        arm64_gcc::x5,             gpr_x5      },      NULL,              NULL},
236 {   "x6",       NULL,   8,  GPR_OFFSET(6),      eEncodingUint,  eFormatHex,     { arm64_gcc::x6,               arm64_dwarf::x6,           LLDB_INVALID_REGNUM,        arm64_gcc::x6,             gpr_x6      },      NULL,              NULL},
237 {   "x7",       NULL,   8,  GPR_OFFSET(7),      eEncodingUint,  eFormatHex,     { arm64_gcc::x7,               arm64_dwarf::x7,           LLDB_INVALID_REGNUM,        arm64_gcc::x7,             gpr_x7      },      NULL,              NULL},
238 {   "x8",       NULL,   8,  GPR_OFFSET(8),      eEncodingUint,  eFormatHex,     { arm64_gcc::x8,               arm64_dwarf::x8,           LLDB_INVALID_REGNUM,        arm64_gcc::x8,             gpr_x8      },      NULL,              NULL},
239 {   "x9",       NULL,   8,  GPR_OFFSET(9),      eEncodingUint,  eFormatHex,     { arm64_gcc::x9,               arm64_dwarf::x9,           LLDB_INVALID_REGNUM,        arm64_gcc::x9,             gpr_x9      },      NULL,              NULL},
240 {   "x10",      NULL,   8,  GPR_OFFSET(10),     eEncodingUint,  eFormatHex,     { arm64_gcc::x10,              arm64_dwarf::x10,          LLDB_INVALID_REGNUM,        arm64_gcc::x10,            gpr_x10     },      NULL,              NULL},
241 {   "x11",      NULL,   8,  GPR_OFFSET(11),     eEncodingUint,  eFormatHex,     { arm64_gcc::x11,              arm64_dwarf::x11,          LLDB_INVALID_REGNUM,        arm64_gcc::x11,            gpr_x11     },      NULL,              NULL},
242 {   "x12",      NULL,   8,  GPR_OFFSET(12),     eEncodingUint,  eFormatHex,     { arm64_gcc::x12,              arm64_dwarf::x12,          LLDB_INVALID_REGNUM,        arm64_gcc::x12,            gpr_x12     },      NULL,              NULL},
243 {   "x13",      NULL,   8,  GPR_OFFSET(13),     eEncodingUint,  eFormatHex,     { arm64_gcc::x13,              arm64_dwarf::x13,          LLDB_INVALID_REGNUM,        arm64_gcc::x13,            gpr_x13     },      NULL,              NULL},
244 {   "x14",      NULL,   8,  GPR_OFFSET(14),     eEncodingUint,  eFormatHex,     { arm64_gcc::x14,              arm64_dwarf::x14,          LLDB_INVALID_REGNUM,        arm64_gcc::x14,            gpr_x14     },      NULL,              NULL},
245 {   "x15",      NULL,   8,  GPR_OFFSET(15),     eEncodingUint,  eFormatHex,     { arm64_gcc::x15,              arm64_dwarf::x15,          LLDB_INVALID_REGNUM,        arm64_gcc::x15,            gpr_x15     },      NULL,              NULL},
246 {   "x16",      NULL,   8,  GPR_OFFSET(16),     eEncodingUint,  eFormatHex,     { arm64_gcc::x16,              arm64_dwarf::x16,          LLDB_INVALID_REGNUM,        arm64_gcc::x16,            gpr_x16     },      NULL,              NULL},
247 {   "x17",      NULL,   8,  GPR_OFFSET(17),     eEncodingUint,  eFormatHex,     { arm64_gcc::x17,              arm64_dwarf::x17,          LLDB_INVALID_REGNUM,        arm64_gcc::x17,            gpr_x17     },      NULL,              NULL},
248 {   "x18",      NULL,   8,  GPR_OFFSET(18),     eEncodingUint,  eFormatHex,     { arm64_gcc::x18,              arm64_dwarf::x18,          LLDB_INVALID_REGNUM,        arm64_gcc::x18,            gpr_x18     },      NULL,              NULL},
249 {   "x19",      NULL,   8,  GPR_OFFSET(19),     eEncodingUint,  eFormatHex,     { arm64_gcc::x19,              arm64_dwarf::x19,          LLDB_INVALID_REGNUM,        arm64_gcc::x19,            gpr_x19     },      NULL,              NULL},
250 {   "x20",      NULL,   8,  GPR_OFFSET(20),     eEncodingUint,  eFormatHex,     { arm64_gcc::x20,              arm64_dwarf::x20,          LLDB_INVALID_REGNUM,        arm64_gcc::x20,            gpr_x20     },      NULL,              NULL},
251 {   "x21",      NULL,   8,  GPR_OFFSET(21),     eEncodingUint,  eFormatHex,     { arm64_gcc::x21,              arm64_dwarf::x21,          LLDB_INVALID_REGNUM,        arm64_gcc::x21,            gpr_x21     },      NULL,              NULL},
252 {   "x22",      NULL,   8,  GPR_OFFSET(22),     eEncodingUint,  eFormatHex,     { arm64_gcc::x22,              arm64_dwarf::x22,          LLDB_INVALID_REGNUM,        arm64_gcc::x22,            gpr_x22     },      NULL,              NULL},
253 {   "x23",      NULL,   8,  GPR_OFFSET(23),     eEncodingUint,  eFormatHex,     { arm64_gcc::x23,              arm64_dwarf::x23,          LLDB_INVALID_REGNUM,        arm64_gcc::x23,            gpr_x23     },      NULL,              NULL},
254 {   "x24",      NULL,   8,  GPR_OFFSET(24),     eEncodingUint,  eFormatHex,     { arm64_gcc::x24,              arm64_dwarf::x24,          LLDB_INVALID_REGNUM,        arm64_gcc::x24,            gpr_x24     },      NULL,              NULL},
255 {   "x25",      NULL,   8,  GPR_OFFSET(25),     eEncodingUint,  eFormatHex,     { arm64_gcc::x25,              arm64_dwarf::x25,          LLDB_INVALID_REGNUM,        arm64_gcc::x25,            gpr_x25     },      NULL,              NULL},
256 {   "x26",      NULL,   8,  GPR_OFFSET(26),     eEncodingUint,  eFormatHex,     { arm64_gcc::x26,              arm64_dwarf::x26,          LLDB_INVALID_REGNUM,        arm64_gcc::x26,            gpr_x26     },      NULL,              NULL},
257 {   "x27",      NULL,   8,  GPR_OFFSET(27),     eEncodingUint,  eFormatHex,     { arm64_gcc::x27,              arm64_dwarf::x27,          LLDB_INVALID_REGNUM,        arm64_gcc::x27,            gpr_x27     },      NULL,              NULL},
258 {   "x28",      NULL,   8,  GPR_OFFSET(28),     eEncodingUint,  eFormatHex,     { arm64_gcc::x28,              arm64_dwarf::x28,          LLDB_INVALID_REGNUM,        arm64_gcc::x28,            gpr_x28     },      NULL,              NULL},
259 
260 {   "fp",       "x29",  8,  GPR_OFFSET(29),     eEncodingUint,  eFormatHex,     { arm64_gcc::fp,               arm64_dwarf::fp,           LLDB_REGNUM_GENERIC_FP,     arm64_gcc::fp,             gpr_fp      },      NULL,              NULL},
261 {   "lr",       "x30",  8,  GPR_OFFSET(30),     eEncodingUint,  eFormatHex,     { arm64_gcc::lr,               arm64_dwarf::lr,           LLDB_REGNUM_GENERIC_RA,     arm64_gcc::lr,             gpr_lr      },      NULL,              NULL},
262 {   "sp",       "x31",  8,  GPR_OFFSET(31),     eEncodingUint,  eFormatHex,     { arm64_gcc::sp,               arm64_dwarf::sp,           LLDB_REGNUM_GENERIC_SP,     arm64_gcc::sp,             gpr_sp      },      NULL,              NULL},
263 {   "pc",       NULL,   8,  GPR_OFFSET(32),     eEncodingUint,  eFormatHex,     { arm64_gcc::pc,               arm64_dwarf::pc,           LLDB_REGNUM_GENERIC_PC,     arm64_gcc::pc,             gpr_pc      },      NULL,              NULL},
264 
265 {   "cpsr",     NULL,   4,  GPR_OFFSET_NAME(cpsr), eEncodingUint,  eFormatHex,  { arm64_gcc::cpsr,             arm64_dwarf::cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  arm64_gcc::cpsr,           gpr_cpsr    },      NULL,              NULL},
266 
267 {   "v0",       NULL,  16,  FPU_OFFSET(0),      eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v0,           LLDB_INVALID_REGNUM,        arm64_gcc::v0,             fpu_v0      },      NULL,              NULL},
268 {   "v1",       NULL,  16,  FPU_OFFSET(1),      eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v1,           LLDB_INVALID_REGNUM,        arm64_gcc::v1,             fpu_v1      },      NULL,              NULL},
269 {   "v2",       NULL,  16,  FPU_OFFSET(2),      eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v2,           LLDB_INVALID_REGNUM,        arm64_gcc::v2,             fpu_v2      },      NULL,              NULL},
270 {   "v3",       NULL,  16,  FPU_OFFSET(3),      eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v3,           LLDB_INVALID_REGNUM,        arm64_gcc::v3,             fpu_v3      },      NULL,              NULL},
271 {   "v4",       NULL,  16,  FPU_OFFSET(4),      eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v4,           LLDB_INVALID_REGNUM,        arm64_gcc::v4,             fpu_v4      },      NULL,              NULL},
272 {   "v5",       NULL,  16,  FPU_OFFSET(5),      eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v5,           LLDB_INVALID_REGNUM,        arm64_gcc::v5,             fpu_v5      },      NULL,              NULL},
273 {   "v6",       NULL,  16,  FPU_OFFSET(6),      eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v6,           LLDB_INVALID_REGNUM,        arm64_gcc::v6,             fpu_v6      },      NULL,              NULL},
274 {   "v7",       NULL,  16,  FPU_OFFSET(7),      eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v7,           LLDB_INVALID_REGNUM,        arm64_gcc::v7,             fpu_v7      },      NULL,              NULL},
275 {   "v8",       NULL,  16,  FPU_OFFSET(8),      eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v8,           LLDB_INVALID_REGNUM,        arm64_gcc::v8,             fpu_v8      },      NULL,              NULL},
276 {   "v9",       NULL,  16,  FPU_OFFSET(9),      eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v9,           LLDB_INVALID_REGNUM,        arm64_gcc::v9,             fpu_v9      },      NULL,              NULL},
277 {   "v10",      NULL,  16,  FPU_OFFSET(10),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v10,          LLDB_INVALID_REGNUM,        arm64_gcc::v10,            fpu_v10     },      NULL,              NULL},
278 {   "v11",      NULL,  16,  FPU_OFFSET(11),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v11,          LLDB_INVALID_REGNUM,        arm64_gcc::v11,            fpu_v11     },      NULL,              NULL},
279 {   "v12",      NULL,  16,  FPU_OFFSET(12),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v12,          LLDB_INVALID_REGNUM,        arm64_gcc::v12,            fpu_v12     },      NULL,              NULL},
280 {   "v13",      NULL,  16,  FPU_OFFSET(13),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v13,          LLDB_INVALID_REGNUM,        arm64_gcc::v13,            fpu_v13     },      NULL,              NULL},
281 {   "v14",      NULL,  16,  FPU_OFFSET(14),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v14,          LLDB_INVALID_REGNUM,        arm64_gcc::v14,            fpu_v14     },      NULL,              NULL},
282 {   "v15",      NULL,  16,  FPU_OFFSET(15),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v15,          LLDB_INVALID_REGNUM,        arm64_gcc::v15,            fpu_v15     },      NULL,              NULL},
283 {   "v16",      NULL,  16,  FPU_OFFSET(16),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v16,          LLDB_INVALID_REGNUM,        arm64_gcc::v16,            fpu_v16     },      NULL,              NULL},
284 {   "v17",      NULL,  16,  FPU_OFFSET(17),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v17,          LLDB_INVALID_REGNUM,        arm64_gcc::v17,            fpu_v17     },      NULL,              NULL},
285 {   "v18",      NULL,  16,  FPU_OFFSET(18),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v18,          LLDB_INVALID_REGNUM,        arm64_gcc::v18,            fpu_v18     },      NULL,              NULL},
286 {   "v19",      NULL,  16,  FPU_OFFSET(19),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v19,          LLDB_INVALID_REGNUM,        arm64_gcc::v19,            fpu_v19     },      NULL,              NULL},
287 {   "v20",      NULL,  16,  FPU_OFFSET(20),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v20,          LLDB_INVALID_REGNUM,        arm64_gcc::v20,            fpu_v20     },      NULL,              NULL},
288 {   "v21",      NULL,  16,  FPU_OFFSET(21),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v21,          LLDB_INVALID_REGNUM,        arm64_gcc::v21,            fpu_v21     },      NULL,              NULL},
289 {   "v22",      NULL,  16,  FPU_OFFSET(22),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v22,          LLDB_INVALID_REGNUM,        arm64_gcc::v22,            fpu_v22     },      NULL,              NULL},
290 {   "v23",      NULL,  16,  FPU_OFFSET(23),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v23,          LLDB_INVALID_REGNUM,        arm64_gcc::v23,            fpu_v23     },      NULL,              NULL},
291 {   "v24",      NULL,  16,  FPU_OFFSET(24),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v24,          LLDB_INVALID_REGNUM,        arm64_gcc::v24,            fpu_v24     },      NULL,              NULL},
292 {   "v25",      NULL,  16,  FPU_OFFSET(25),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v25,          LLDB_INVALID_REGNUM,        arm64_gcc::v25,            fpu_v25     },      NULL,              NULL},
293 {   "v26",      NULL,  16,  FPU_OFFSET(26),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v26,          LLDB_INVALID_REGNUM,        arm64_gcc::v26,            fpu_v26     },      NULL,              NULL},
294 {   "v27",      NULL,  16,  FPU_OFFSET(27),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v27,          LLDB_INVALID_REGNUM,        arm64_gcc::v27,            fpu_v27     },      NULL,              NULL},
295 {   "v28",      NULL,  16,  FPU_OFFSET(28),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v28,          LLDB_INVALID_REGNUM,        arm64_gcc::v28,            fpu_v28     },      NULL,              NULL},
296 {   "v29",      NULL,  16,  FPU_OFFSET(29),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v29,          LLDB_INVALID_REGNUM,        arm64_gcc::v29,            fpu_v29     },      NULL,              NULL},
297 {   "v30",      NULL,  16,  FPU_OFFSET(30),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v30,          LLDB_INVALID_REGNUM,        arm64_gcc::v30,            fpu_v30     },      NULL,              NULL},
298 {   "v31",      NULL,  16,  FPU_OFFSET(31),     eEncodingVector, eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v31,          LLDB_INVALID_REGNUM,        arm64_gcc::v31,            fpu_v31     },      NULL,              NULL},
299 
300 {   "fpsr",    NULL,   4,  FPU_OFFSET_NAME(fpsr),     eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,  fpu_fpsr   },      NULL,              NULL},
301 {   "fpcr",    NULL,   4,  FPU_OFFSET_NAME(fpcr),     eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,  fpu_fpcr   },      NULL,              NULL},
302 
303 {   "far",      NULL,   8,  EXC_OFFSET_NAME(far),       eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_far       },    NULL,              NULL},
304 {   "esr",      NULL,   4,  EXC_OFFSET_NAME(esr),       eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_esr       },    NULL,              NULL},
305 {   "exception",NULL,   4,  EXC_OFFSET_NAME(exception), eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_exception },    NULL,              NULL},
306 
307 {   DEFINE_DBG (bvr, 0) },
308 {   DEFINE_DBG (bvr, 1) },
309 {   DEFINE_DBG (bvr, 2) },
310 {   DEFINE_DBG (bvr, 3) },
311 {   DEFINE_DBG (bvr, 4) },
312 {   DEFINE_DBG (bvr, 5) },
313 {   DEFINE_DBG (bvr, 6) },
314 {   DEFINE_DBG (bvr, 7) },
315 {   DEFINE_DBG (bvr, 8) },
316 {   DEFINE_DBG (bvr, 9) },
317 {   DEFINE_DBG (bvr, 10) },
318 {   DEFINE_DBG (bvr, 11) },
319 {   DEFINE_DBG (bvr, 12) },
320 {   DEFINE_DBG (bvr, 13) },
321 {   DEFINE_DBG (bvr, 14) },
322 {   DEFINE_DBG (bvr, 15) },
323 
324 {   DEFINE_DBG (bcr, 0) },
325 {   DEFINE_DBG (bcr, 1) },
326 {   DEFINE_DBG (bcr, 2) },
327 {   DEFINE_DBG (bcr, 3) },
328 {   DEFINE_DBG (bcr, 4) },
329 {   DEFINE_DBG (bcr, 5) },
330 {   DEFINE_DBG (bcr, 6) },
331 {   DEFINE_DBG (bcr, 7) },
332 {   DEFINE_DBG (bcr, 8) },
333 {   DEFINE_DBG (bcr, 9) },
334 {   DEFINE_DBG (bcr, 10) },
335 {   DEFINE_DBG (bcr, 11) },
336 {   DEFINE_DBG (bcr, 12) },
337 {   DEFINE_DBG (bcr, 13) },
338 {   DEFINE_DBG (bcr, 14) },
339 {   DEFINE_DBG (bcr, 15) },
340 
341 {   DEFINE_DBG (wvr, 0) },
342 {   DEFINE_DBG (wvr, 1) },
343 {   DEFINE_DBG (wvr, 2) },
344 {   DEFINE_DBG (wvr, 3) },
345 {   DEFINE_DBG (wvr, 4) },
346 {   DEFINE_DBG (wvr, 5) },
347 {   DEFINE_DBG (wvr, 6) },
348 {   DEFINE_DBG (wvr, 7) },
349 {   DEFINE_DBG (wvr, 8) },
350 {   DEFINE_DBG (wvr, 9) },
351 {   DEFINE_DBG (wvr, 10) },
352 {   DEFINE_DBG (wvr, 11) },
353 {   DEFINE_DBG (wvr, 12) },
354 {   DEFINE_DBG (wvr, 13) },
355 {   DEFINE_DBG (wvr, 14) },
356 {   DEFINE_DBG (wvr, 15) },
357 
358 {   DEFINE_DBG (wcr, 0) },
359 {   DEFINE_DBG (wcr, 1) },
360 {   DEFINE_DBG (wcr, 2) },
361 {   DEFINE_DBG (wcr, 3) },
362 {   DEFINE_DBG (wcr, 4) },
363 {   DEFINE_DBG (wcr, 5) },
364 {   DEFINE_DBG (wcr, 6) },
365 {   DEFINE_DBG (wcr, 7) },
366 {   DEFINE_DBG (wcr, 8) },
367 {   DEFINE_DBG (wcr, 9) },
368 {   DEFINE_DBG (wcr, 10) },
369 {   DEFINE_DBG (wcr, 11) },
370 {   DEFINE_DBG (wcr, 12) },
371 {   DEFINE_DBG (wcr, 13) },
372 {   DEFINE_DBG (wcr, 14) },
373 {   DEFINE_DBG (wcr, 15) }
374 };
375 
376 // General purpose registers
377 static uint32_t
378 g_gpr_regnums[] =
379 {
380     gpr_x0,
381     gpr_x1,
382     gpr_x2,
383     gpr_x3,
384     gpr_x4,
385     gpr_x5,
386     gpr_x6,
387     gpr_x7,
388     gpr_x8,
389     gpr_x9,
390     gpr_x10,
391     gpr_x11,
392     gpr_x12,
393     gpr_x13,
394     gpr_x14,
395     gpr_x15,
396     gpr_x16,
397     gpr_x17,
398     gpr_x18,
399     gpr_x19,
400     gpr_x20,
401     gpr_x21,
402     gpr_x22,
403     gpr_x23,
404     gpr_x24,
405     gpr_x25,
406     gpr_x26,
407     gpr_x27,
408     gpr_x28,
409     gpr_fp,
410     gpr_lr,
411     gpr_sp,
412     gpr_pc,
413     gpr_cpsr
414 };
415 
416 // Floating point registers
417 static uint32_t
418 g_fpu_regnums[] =
419 {
420     fpu_v0,
421     fpu_v1,
422     fpu_v2,
423     fpu_v3,
424     fpu_v4,
425     fpu_v5,
426     fpu_v6,
427     fpu_v7,
428     fpu_v8,
429     fpu_v9,
430     fpu_v10,
431     fpu_v11,
432     fpu_v12,
433     fpu_v13,
434     fpu_v14,
435     fpu_v15,
436     fpu_v16,
437     fpu_v17,
438     fpu_v18,
439     fpu_v19,
440     fpu_v20,
441     fpu_v21,
442     fpu_v22,
443     fpu_v23,
444     fpu_v24,
445     fpu_v25,
446     fpu_v26,
447     fpu_v27,
448     fpu_v28,
449     fpu_v29,
450     fpu_v30,
451     fpu_v31,
452     fpu_fpsr,
453     fpu_fpcr
454 };
455 
456 // Exception registers
457 
458 static uint32_t
459 g_exc_regnums[] =
460 {
461     exc_far,
462     exc_esr,
463     exc_exception
464 };
465 
466 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
467 
468 void
469 RegisterContextDarwin_arm64::InvalidateAllRegisters ()
470 {
471     InvalidateAllRegisterStates();
472 }
473 
474 
475 size_t
476 RegisterContextDarwin_arm64::GetRegisterCount ()
477 {
478     assert(k_num_register_infos == k_num_registers);
479     return k_num_registers;
480 }
481 
482 const RegisterInfo *
483 RegisterContextDarwin_arm64::GetRegisterInfoAtIndex (size_t reg)
484 {
485     assert(k_num_register_infos == k_num_registers);
486     if (reg < k_num_registers)
487         return &g_register_infos[reg];
488     return NULL;
489 }
490 
491 size_t
492 RegisterContextDarwin_arm64::GetRegisterInfosCount ()
493 {
494     return k_num_register_infos;
495 }
496 
497 const RegisterInfo *
498 RegisterContextDarwin_arm64::GetRegisterInfos ()
499 {
500     return g_register_infos;
501 }
502 
503 
504 // Number of registers in each register set
505 const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
506 const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
507 const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
508 
509 //----------------------------------------------------------------------
510 // Register set definitions. The first definitions at register set index
511 // of zero is for all registers, followed by other registers sets. The
512 // register information for the all register set need not be filled in.
513 //----------------------------------------------------------------------
514 static const RegisterSet g_reg_sets[] =
515 {
516     { "General Purpose Registers",  "gpr",  k_num_gpr_registers,    g_gpr_regnums,      },
517     { "Floating Point Registers",   "fpu",  k_num_fpu_registers,    g_fpu_regnums       },
518     { "Exception State Registers",  "exc",  k_num_exc_registers,    g_exc_regnums       }
519 };
520 
521 const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
522 
523 
524 size_t
525 RegisterContextDarwin_arm64::GetRegisterSetCount ()
526 {
527     return k_num_regsets;
528 }
529 
530 const RegisterSet *
531 RegisterContextDarwin_arm64::GetRegisterSet (size_t reg_set)
532 {
533     if (reg_set < k_num_regsets)
534         return &g_reg_sets[reg_set];
535     return NULL;
536 }
537 
538 
539 //----------------------------------------------------------------------
540 // Register information definitions for arm64
541 //----------------------------------------------------------------------
542 int
543 RegisterContextDarwin_arm64::GetSetForNativeRegNum (int reg)
544 {
545     if (reg < fpu_v0)
546         return GPRRegSet;
547     else if (reg < exc_far)
548         return FPURegSet;
549     else if (reg < k_num_registers)
550         return EXCRegSet;
551     return -1;
552 }
553 
554 int
555 RegisterContextDarwin_arm64::ReadGPR (bool force)
556 {
557     int set = GPRRegSet;
558     if (force || !RegisterSetIsCached(set))
559     {
560         SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
561     }
562     return GetError(GPRRegSet, Read);
563 }
564 
565 int
566 RegisterContextDarwin_arm64::ReadFPU (bool force)
567 {
568     int set = FPURegSet;
569     if (force || !RegisterSetIsCached(set))
570     {
571         SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
572     }
573     return GetError(FPURegSet, Read);
574 }
575 
576 int
577 RegisterContextDarwin_arm64::ReadEXC (bool force)
578 {
579     int set = EXCRegSet;
580     if (force || !RegisterSetIsCached(set))
581     {
582         SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
583     }
584     return GetError(EXCRegSet, Read);
585 }
586 
587 int
588 RegisterContextDarwin_arm64::ReadDBG (bool force)
589 {
590     int set = DBGRegSet;
591     if (force || !RegisterSetIsCached(set))
592     {
593         SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));
594     }
595     return GetError(DBGRegSet, Read);
596 }
597 
598 int
599 RegisterContextDarwin_arm64::WriteGPR ()
600 {
601     int set = GPRRegSet;
602     if (!RegisterSetIsCached(set))
603     {
604         SetError (set, Write, -1);
605         return KERN_INVALID_ARGUMENT;
606     }
607     SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr));
608     SetError (set, Read, -1);
609     return GetError(GPRRegSet, Write);
610 }
611 
612 int
613 RegisterContextDarwin_arm64::WriteFPU ()
614 {
615     int set = FPURegSet;
616     if (!RegisterSetIsCached(set))
617     {
618         SetError (set, Write, -1);
619         return KERN_INVALID_ARGUMENT;
620     }
621     SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu));
622     SetError (set, Read, -1);
623     return GetError(FPURegSet, Write);
624 }
625 
626 int
627 RegisterContextDarwin_arm64::WriteEXC ()
628 {
629     int set = EXCRegSet;
630     if (!RegisterSetIsCached(set))
631     {
632         SetError (set, Write, -1);
633         return KERN_INVALID_ARGUMENT;
634     }
635     SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc));
636     SetError (set, Read, -1);
637     return GetError(EXCRegSet, Write);
638 }
639 
640 int
641 RegisterContextDarwin_arm64::WriteDBG ()
642 {
643     int set = DBGRegSet;
644     if (!RegisterSetIsCached(set))
645     {
646         SetError (set, Write, -1);
647         return KERN_INVALID_ARGUMENT;
648     }
649     SetError (set, Write, DoWriteDBG(GetThreadID(), set, dbg));
650     SetError (set, Read, -1);
651     return GetError(DBGRegSet, Write);
652 }
653 
654 
655 int
656 RegisterContextDarwin_arm64::ReadRegisterSet (uint32_t set, bool force)
657 {
658     switch (set)
659     {
660     case GPRRegSet:    return ReadGPR(force);
661     case FPURegSet:    return ReadFPU(force);
662     case EXCRegSet:    return ReadEXC(force);
663     case DBGRegSet:    return ReadDBG(force);
664     default: break;
665     }
666     return KERN_INVALID_ARGUMENT;
667 }
668 
669 int
670 RegisterContextDarwin_arm64::WriteRegisterSet (uint32_t set)
671 {
672     // Make sure we have a valid context to set.
673     if (RegisterSetIsCached(set))
674     {
675         switch (set)
676         {
677         case GPRRegSet:    return WriteGPR();
678         case FPURegSet:    return WriteFPU();
679         case EXCRegSet:    return WriteEXC();
680         case DBGRegSet:    return WriteDBG();
681         default: break;
682         }
683     }
684     return KERN_INVALID_ARGUMENT;
685 }
686 
687 void
688 RegisterContextDarwin_arm64::LogDBGRegisters (Log *log, const DBG& dbg)
689 {
690     if (log)
691     {
692         for (uint32_t i=0; i<16; i++)
693             log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8llx, 0x%8.8llx } WVR%-2u/WCR%-2u = { 0x%8.8llx, 0x%8.8llx }",
694                 i, i, dbg.bvr[i], dbg.bcr[i],
695                 i, i, dbg.wvr[i], dbg.wcr[i]);
696     }
697 }
698 
699 
700 bool
701 RegisterContextDarwin_arm64::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
702 {
703     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
704     int set = RegisterContextDarwin_arm64::GetSetForNativeRegNum (reg);
705 
706     if (set == -1)
707         return false;
708 
709     if (ReadRegisterSet(set, false) != KERN_SUCCESS)
710         return false;
711 
712     switch (reg)
713     {
714     case gpr_x0:
715     case gpr_x1:
716     case gpr_x2:
717     case gpr_x3:
718     case gpr_x4:
719     case gpr_x5:
720     case gpr_x6:
721     case gpr_x7:
722     case gpr_x8:
723     case gpr_x9:
724     case gpr_x10:
725     case gpr_x11:
726     case gpr_x12:
727     case gpr_x13:
728     case gpr_x14:
729     case gpr_x15:
730     case gpr_x16:
731     case gpr_x17:
732     case gpr_x18:
733     case gpr_x19:
734     case gpr_x20:
735     case gpr_x21:
736     case gpr_x22:
737     case gpr_x23:
738     case gpr_x24:
739     case gpr_x25:
740     case gpr_x26:
741     case gpr_x27:
742     case gpr_x28:
743     case gpr_fp:
744     case gpr_sp:
745     case gpr_lr:
746     case gpr_pc:
747     case gpr_cpsr:
748         value.SetUInt64 (gpr.x[reg - gpr_x0]);
749         break;
750 
751     case fpu_v0:
752     case fpu_v1:
753     case fpu_v2:
754     case fpu_v3:
755     case fpu_v4:
756     case fpu_v5:
757     case fpu_v6:
758     case fpu_v7:
759     case fpu_v8:
760     case fpu_v9:
761     case fpu_v10:
762     case fpu_v11:
763     case fpu_v12:
764     case fpu_v13:
765     case fpu_v14:
766     case fpu_v15:
767     case fpu_v16:
768     case fpu_v17:
769     case fpu_v18:
770     case fpu_v19:
771     case fpu_v20:
772     case fpu_v21:
773     case fpu_v22:
774     case fpu_v23:
775     case fpu_v24:
776     case fpu_v25:
777     case fpu_v26:
778     case fpu_v27:
779     case fpu_v28:
780     case fpu_v29:
781     case fpu_v30:
782     case fpu_v31:
783         value.SetBytes(fpu.v[reg].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder());
784         break;
785 
786     case fpu_fpsr:
787         value.SetUInt32 (fpu.fpsr);
788         break;
789 
790     case fpu_fpcr:
791         value.SetUInt32 (fpu.fpcr);
792         break;
793 
794     case exc_exception:
795         value.SetUInt32 (exc.exception);
796         break;
797     case exc_esr:
798         value.SetUInt32 (exc.esr);
799         break;
800     case exc_far:
801         value.SetUInt64 (exc.far);
802         break;
803 
804     default:
805         value.SetValueToInvalid();
806         return false;
807 
808     }
809     return true;
810 }
811 
812 
813 bool
814 RegisterContextDarwin_arm64::WriteRegister (const RegisterInfo *reg_info,
815                                         const RegisterValue &value)
816 {
817     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
818     int set = GetSetForNativeRegNum (reg);
819 
820     if (set == -1)
821         return false;
822 
823     if (ReadRegisterSet(set, false) != KERN_SUCCESS)
824         return false;
825 
826     switch (reg)
827     {
828     case gpr_x0:
829     case gpr_x1:
830     case gpr_x2:
831     case gpr_x3:
832     case gpr_x4:
833     case gpr_x5:
834     case gpr_x6:
835     case gpr_x7:
836     case gpr_x8:
837     case gpr_x9:
838     case gpr_x10:
839     case gpr_x11:
840     case gpr_x12:
841     case gpr_x13:
842     case gpr_x14:
843     case gpr_x15:
844     case gpr_x16:
845     case gpr_x17:
846     case gpr_x18:
847     case gpr_x19:
848     case gpr_x20:
849     case gpr_x21:
850     case gpr_x22:
851     case gpr_x23:
852     case gpr_x24:
853     case gpr_x25:
854     case gpr_x26:
855     case gpr_x27:
856     case gpr_x28:
857     case gpr_fp:
858     case gpr_sp:
859     case gpr_lr:
860     case gpr_pc:
861     case gpr_cpsr:
862             gpr.x[reg - gpr_x0] = value.GetAsUInt64();
863         break;
864 
865     case fpu_v0:
866     case fpu_v1:
867     case fpu_v2:
868     case fpu_v3:
869     case fpu_v4:
870     case fpu_v5:
871     case fpu_v6:
872     case fpu_v7:
873     case fpu_v8:
874     case fpu_v9:
875     case fpu_v10:
876     case fpu_v11:
877     case fpu_v12:
878     case fpu_v13:
879     case fpu_v14:
880     case fpu_v15:
881     case fpu_v16:
882     case fpu_v17:
883     case fpu_v18:
884     case fpu_v19:
885     case fpu_v20:
886     case fpu_v21:
887     case fpu_v22:
888     case fpu_v23:
889     case fpu_v24:
890     case fpu_v25:
891     case fpu_v26:
892     case fpu_v27:
893     case fpu_v28:
894     case fpu_v29:
895     case fpu_v30:
896     case fpu_v31:
897         ::memcpy (fpu.v[reg].bytes, value.GetBytes(), value.GetByteSize());
898         break;
899 
900     case fpu_fpsr:
901         fpu.fpsr = value.GetAsUInt32();
902         break;
903 
904     case fpu_fpcr:
905         fpu.fpcr = value.GetAsUInt32();
906         break;
907 
908     case exc_exception:
909         exc.exception = value.GetAsUInt32();
910         break;
911     case exc_esr:
912         exc.esr = value.GetAsUInt32();
913         break;
914     case exc_far:
915         exc.far = value.GetAsUInt64();
916         break;
917 
918     default:
919         return false;
920 
921     }
922     return WriteRegisterSet(set) == KERN_SUCCESS;
923 }
924 
925 bool
926 RegisterContextDarwin_arm64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
927 {
928     data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
929     if (data_sp &&
930         ReadGPR (false) == KERN_SUCCESS &&
931         ReadFPU (false) == KERN_SUCCESS &&
932         ReadEXC (false) == KERN_SUCCESS)
933     {
934         uint8_t *dst = data_sp->GetBytes();
935         ::memcpy (dst, &gpr, sizeof(gpr));
936         dst += sizeof(gpr);
937 
938         ::memcpy (dst, &fpu, sizeof(fpu));
939         dst += sizeof(gpr);
940 
941         ::memcpy (dst, &exc, sizeof(exc));
942         return true;
943     }
944     return false;
945 }
946 
947 bool
948 RegisterContextDarwin_arm64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
949 {
950     if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
951     {
952         const uint8_t *src = data_sp->GetBytes();
953         ::memcpy (&gpr, src, sizeof(gpr));
954         src += sizeof(gpr);
955 
956         ::memcpy (&fpu, src, sizeof(fpu));
957         src += sizeof(gpr);
958 
959         ::memcpy (&exc, src, sizeof(exc));
960         uint32_t success_count = 0;
961         if (WriteGPR() == KERN_SUCCESS)
962             ++success_count;
963         if (WriteFPU() == KERN_SUCCESS)
964             ++success_count;
965         if (WriteEXC() == KERN_SUCCESS)
966             ++success_count;
967         return success_count == 3;
968     }
969     return false;
970 }
971 
972 uint32_t
973 RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber (RegisterKind kind, uint32_t reg)
974 {
975     if (kind == eRegisterKindGeneric)
976     {
977         switch (reg)
978         {
979         case LLDB_REGNUM_GENERIC_PC: return gpr_pc;
980         case LLDB_REGNUM_GENERIC_SP: return gpr_sp;
981         case LLDB_REGNUM_GENERIC_FP: return gpr_fp;
982         case LLDB_REGNUM_GENERIC_RA: return gpr_lr;
983         case LLDB_REGNUM_GENERIC_FLAGS: return gpr_cpsr;
984         default:
985             break;
986         }
987     }
988     else if (kind == eRegisterKindDWARF)
989     {
990         switch (reg)
991         {
992         case arm64_dwarf::x0:  return gpr_x0;
993         case arm64_dwarf::x1:  return gpr_x1;
994         case arm64_dwarf::x2:  return gpr_x2;
995         case arm64_dwarf::x3:  return gpr_x3;
996         case arm64_dwarf::x4:  return gpr_x4;
997         case arm64_dwarf::x5:  return gpr_x5;
998         case arm64_dwarf::x6:  return gpr_x6;
999         case arm64_dwarf::x7:  return gpr_x7;
1000         case arm64_dwarf::x8:  return gpr_x8;
1001         case arm64_dwarf::x9:  return gpr_x9;
1002         case arm64_dwarf::x10: return gpr_x10;
1003         case arm64_dwarf::x11: return gpr_x11;
1004         case arm64_dwarf::x12: return gpr_x12;
1005         case arm64_dwarf::x13: return gpr_x13;
1006         case arm64_dwarf::x14: return gpr_x14;
1007         case arm64_dwarf::x15: return gpr_x15;
1008         case arm64_dwarf::x16: return gpr_x16;
1009         case arm64_dwarf::x17: return gpr_x17;
1010         case arm64_dwarf::x18: return gpr_x18;
1011         case arm64_dwarf::x19: return gpr_x19;
1012         case arm64_dwarf::x20: return gpr_x20;
1013         case arm64_dwarf::x21: return gpr_x21;
1014         case arm64_dwarf::x22: return gpr_x22;
1015         case arm64_dwarf::x23: return gpr_x23;
1016         case arm64_dwarf::x24: return gpr_x24;
1017         case arm64_dwarf::x25: return gpr_x25;
1018         case arm64_dwarf::x26: return gpr_x26;
1019         case arm64_dwarf::x27: return gpr_x27;
1020         case arm64_dwarf::x28: return gpr_x28;
1021 
1022         case arm64_dwarf::fp:  return gpr_fp;
1023         case arm64_dwarf::sp:  return gpr_sp;
1024         case arm64_dwarf::lr:  return gpr_lr;
1025         case arm64_dwarf::pc:  return gpr_pc;
1026         case arm64_dwarf::cpsr: return gpr_cpsr;
1027 
1028         case arm64_dwarf::v0:  return fpu_v0;
1029         case arm64_dwarf::v1:  return fpu_v1;
1030         case arm64_dwarf::v2:  return fpu_v2;
1031         case arm64_dwarf::v3:  return fpu_v3;
1032         case arm64_dwarf::v4:  return fpu_v4;
1033         case arm64_dwarf::v5:  return fpu_v5;
1034         case arm64_dwarf::v6:  return fpu_v6;
1035         case arm64_dwarf::v7:  return fpu_v7;
1036         case arm64_dwarf::v8:  return fpu_v8;
1037         case arm64_dwarf::v9:  return fpu_v9;
1038         case arm64_dwarf::v10: return fpu_v10;
1039         case arm64_dwarf::v11: return fpu_v11;
1040         case arm64_dwarf::v12: return fpu_v12;
1041         case arm64_dwarf::v13: return fpu_v13;
1042         case arm64_dwarf::v14: return fpu_v14;
1043         case arm64_dwarf::v15: return fpu_v15;
1044         case arm64_dwarf::v16: return fpu_v16;
1045         case arm64_dwarf::v17: return fpu_v17;
1046         case arm64_dwarf::v18: return fpu_v18;
1047         case arm64_dwarf::v19: return fpu_v19;
1048         case arm64_dwarf::v20: return fpu_v20;
1049         case arm64_dwarf::v21: return fpu_v21;
1050         case arm64_dwarf::v22: return fpu_v22;
1051         case arm64_dwarf::v23: return fpu_v23;
1052         case arm64_dwarf::v24: return fpu_v24;
1053         case arm64_dwarf::v25: return fpu_v25;
1054         case arm64_dwarf::v26: return fpu_v26;
1055         case arm64_dwarf::v27: return fpu_v27;
1056         case arm64_dwarf::v28: return fpu_v28;
1057         case arm64_dwarf::v29: return fpu_v29;
1058         case arm64_dwarf::v30: return fpu_v30;
1059         case arm64_dwarf::v31: return fpu_v31;
1060 
1061         default:
1062             break;
1063         }
1064     }
1065     else if (kind == eRegisterKindGCC)
1066     {
1067         switch (reg)
1068         {
1069         case arm64_gcc::x0:  return gpr_x0;
1070         case arm64_gcc::x1:  return gpr_x1;
1071         case arm64_gcc::x2:  return gpr_x2;
1072         case arm64_gcc::x3:  return gpr_x3;
1073         case arm64_gcc::x4:  return gpr_x4;
1074         case arm64_gcc::x5:  return gpr_x5;
1075         case arm64_gcc::x6:  return gpr_x6;
1076         case arm64_gcc::x7:  return gpr_x7;
1077         case arm64_gcc::x8:  return gpr_x8;
1078         case arm64_gcc::x9:  return gpr_x9;
1079         case arm64_gcc::x10: return gpr_x10;
1080         case arm64_gcc::x11: return gpr_x11;
1081         case arm64_gcc::x12: return gpr_x12;
1082         case arm64_gcc::x13: return gpr_x13;
1083         case arm64_gcc::x14: return gpr_x14;
1084         case arm64_gcc::x15: return gpr_x15;
1085         case arm64_gcc::x16: return gpr_x16;
1086         case arm64_gcc::x17: return gpr_x17;
1087         case arm64_gcc::x18: return gpr_x18;
1088         case arm64_gcc::x19: return gpr_x19;
1089         case arm64_gcc::x20: return gpr_x20;
1090         case arm64_gcc::x21: return gpr_x21;
1091         case arm64_gcc::x22: return gpr_x22;
1092         case arm64_gcc::x23: return gpr_x23;
1093         case arm64_gcc::x24: return gpr_x24;
1094         case arm64_gcc::x25: return gpr_x25;
1095         case arm64_gcc::x26: return gpr_x26;
1096         case arm64_gcc::x27: return gpr_x27;
1097         case arm64_gcc::x28: return gpr_x28;
1098         case arm64_gcc::fp:   return gpr_fp;
1099         case arm64_gcc::sp:   return gpr_sp;
1100         case arm64_gcc::lr:   return gpr_lr;
1101         case arm64_gcc::pc:   return gpr_pc;
1102         case arm64_gcc::cpsr: return gpr_cpsr;
1103         }
1104     }
1105     else if (kind == eRegisterKindLLDB)
1106     {
1107         return reg;
1108     }
1109     return LLDB_INVALID_REGNUM;
1110 }
1111 
1112 
1113 uint32_t
1114 RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints ()
1115 {
1116 #if defined (__arm64__) || defined (__aarch64__)
1117     // autodetect how many watchpoints are supported dynamically...
1118     static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
1119     if (g_num_supported_hw_watchpoints == UINT32_MAX)
1120     {
1121         size_t len;
1122         uint32_t n = 0;
1123         len = sizeof (n);
1124         if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0)
1125         {
1126             g_num_supported_hw_watchpoints = n;
1127         }
1128     }
1129     return g_num_supported_hw_watchpoints;
1130 #else
1131     // TODO: figure out remote case here!
1132     return 2;
1133 #endif
1134 }
1135 
1136 
1137 uint32_t
1138 RegisterContextDarwin_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write)
1139 {
1140 //    if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write);
1141 
1142     const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
1143 
1144     // Can't watch zero bytes
1145     if (size == 0)
1146         return LLDB_INVALID_INDEX32;
1147 
1148     // We must watch for either read or write
1149     if (read == false && write == false)
1150         return LLDB_INVALID_INDEX32;
1151 
1152     // Can't watch more than 4 bytes per WVR/WCR pair
1153     if (size > 4)
1154         return LLDB_INVALID_INDEX32;
1155 
1156     // We can only watch up to four bytes that follow a 4 byte aligned address
1157     // per watchpoint register pair. Since we have at most so we can only watch
1158     // until the next 4 byte boundary and we need to make sure we can properly
1159     // encode this.
1160     uint32_t addr_word_offset = addr % 4;
1161 //    if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset);
1162 
1163     uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
1164 //    if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask);
1165     if (byte_mask > 0xfu)
1166         return LLDB_INVALID_INDEX32;
1167 
1168     // Read the debug state
1169     int kret = ReadDBG (false);
1170 
1171     if (kret == KERN_SUCCESS)
1172     {
1173         // Check to make sure we have the needed hardware support
1174         uint32_t i = 0;
1175 
1176         for (i=0; i<num_hw_watchpoints; ++i)
1177         {
1178             if ((dbg.wcr[i] & WCR_ENABLE) == 0)
1179                 break; // We found an available hw breakpoint slot (in i)
1180         }
1181 
1182         // See if we found an available hw breakpoint slot above
1183         if (i < num_hw_watchpoints)
1184         {
1185             // Make the byte_mask into a valid Byte Address Select mask
1186             uint32_t byte_address_select = byte_mask << 5;
1187             // Make sure bits 1:0 are clear in our address
1188             dbg.wvr[i] = addr & ~((lldb::addr_t)3);
1189             dbg.wcr[i] =  byte_address_select |       // Which bytes that follow the IMVA that we will watch
1190                                     S_USER |                    // Stop only in user mode
1191                                     (read ? WCR_LOAD : 0) |     // Stop on read access?
1192                                     (write ? WCR_STORE : 0) |   // Stop on write access?
1193                                     WCR_ENABLE;                 // Enable this watchpoint;
1194 
1195             kret = WriteDBG();
1196 //            if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() WriteDBG() => 0x%8.8x.", kret);
1197 
1198             if (kret == KERN_SUCCESS)
1199                 return i;
1200         }
1201         else
1202         {
1203 //            if (log) log->Printf ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
1204         }
1205     }
1206     return LLDB_INVALID_INDEX32;
1207 }
1208 
1209 bool
1210 RegisterContextDarwin_arm64::ClearHardwareWatchpoint (uint32_t hw_index)
1211 {
1212     int kret = ReadDBG (false);
1213 
1214     const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
1215     if (kret == KERN_SUCCESS)
1216     {
1217         if (hw_index < num_hw_points)
1218         {
1219             dbg.wcr[hw_index] = 0;
1220 //            if (log) log->Printf ("RegisterContextDarwin_arm64::ClearHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
1221 //                    hw_index,
1222 //                    hw_index,
1223 //                    dbg.wvr[hw_index],
1224 //                    hw_index,
1225 //                    dbg.wcr[hw_index]);
1226 
1227             kret = WriteDBG();
1228 
1229             if (kret == KERN_SUCCESS)
1230                 return true;
1231         }
1232     }
1233     return false;
1234 }
1235 
1236 #endif
1237