xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- RegisterContextDarwin_arm.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_arm.h"
10061da546Spatrick #include "RegisterContextDarwinConstants.h"
11061da546Spatrick 
12061da546Spatrick #include "lldb/Utility/DataBufferHeap.h"
13061da546Spatrick #include "lldb/Utility/DataExtractor.h"
14061da546Spatrick #include "lldb/Utility/Endian.h"
15061da546Spatrick #include "lldb/Utility/Log.h"
16061da546Spatrick #include "lldb/Utility/RegisterValue.h"
17061da546Spatrick #include "lldb/Utility/Scalar.h"
18061da546Spatrick #include "llvm/Support/Compiler.h"
19061da546Spatrick 
20061da546Spatrick #include "Plugins/Process/Utility/InstructionUtils.h"
21061da546Spatrick 
22061da546Spatrick #include <memory>
23061da546Spatrick 
24061da546Spatrick #include "Utility/ARM_DWARF_Registers.h"
25061da546Spatrick #include "Utility/ARM_ehframe_Registers.h"
26061da546Spatrick 
27061da546Spatrick #include "llvm/ADT/STLExtras.h"
28061da546Spatrick 
29061da546Spatrick using namespace lldb;
30061da546Spatrick using namespace lldb_private;
31061da546Spatrick 
32061da546Spatrick enum {
33061da546Spatrick   gpr_r0 = 0,
34061da546Spatrick   gpr_r1,
35061da546Spatrick   gpr_r2,
36061da546Spatrick   gpr_r3,
37061da546Spatrick   gpr_r4,
38061da546Spatrick   gpr_r5,
39061da546Spatrick   gpr_r6,
40061da546Spatrick   gpr_r7,
41061da546Spatrick   gpr_r8,
42061da546Spatrick   gpr_r9,
43061da546Spatrick   gpr_r10,
44061da546Spatrick   gpr_r11,
45061da546Spatrick   gpr_r12,
46061da546Spatrick   gpr_r13,
47061da546Spatrick   gpr_sp = gpr_r13,
48061da546Spatrick   gpr_r14,
49061da546Spatrick   gpr_lr = gpr_r14,
50061da546Spatrick   gpr_r15,
51061da546Spatrick   gpr_pc = gpr_r15,
52061da546Spatrick   gpr_cpsr,
53061da546Spatrick 
54061da546Spatrick   fpu_s0,
55061da546Spatrick   fpu_s1,
56061da546Spatrick   fpu_s2,
57061da546Spatrick   fpu_s3,
58061da546Spatrick   fpu_s4,
59061da546Spatrick   fpu_s5,
60061da546Spatrick   fpu_s6,
61061da546Spatrick   fpu_s7,
62061da546Spatrick   fpu_s8,
63061da546Spatrick   fpu_s9,
64061da546Spatrick   fpu_s10,
65061da546Spatrick   fpu_s11,
66061da546Spatrick   fpu_s12,
67061da546Spatrick   fpu_s13,
68061da546Spatrick   fpu_s14,
69061da546Spatrick   fpu_s15,
70061da546Spatrick   fpu_s16,
71061da546Spatrick   fpu_s17,
72061da546Spatrick   fpu_s18,
73061da546Spatrick   fpu_s19,
74061da546Spatrick   fpu_s20,
75061da546Spatrick   fpu_s21,
76061da546Spatrick   fpu_s22,
77061da546Spatrick   fpu_s23,
78061da546Spatrick   fpu_s24,
79061da546Spatrick   fpu_s25,
80061da546Spatrick   fpu_s26,
81061da546Spatrick   fpu_s27,
82061da546Spatrick   fpu_s28,
83061da546Spatrick   fpu_s29,
84061da546Spatrick   fpu_s30,
85061da546Spatrick   fpu_s31,
86061da546Spatrick   fpu_fpscr,
87061da546Spatrick 
88061da546Spatrick   exc_exception,
89061da546Spatrick   exc_fsr,
90061da546Spatrick   exc_far,
91061da546Spatrick 
92061da546Spatrick   dbg_bvr0,
93061da546Spatrick   dbg_bvr1,
94061da546Spatrick   dbg_bvr2,
95061da546Spatrick   dbg_bvr3,
96061da546Spatrick   dbg_bvr4,
97061da546Spatrick   dbg_bvr5,
98061da546Spatrick   dbg_bvr6,
99061da546Spatrick   dbg_bvr7,
100061da546Spatrick   dbg_bvr8,
101061da546Spatrick   dbg_bvr9,
102061da546Spatrick   dbg_bvr10,
103061da546Spatrick   dbg_bvr11,
104061da546Spatrick   dbg_bvr12,
105061da546Spatrick   dbg_bvr13,
106061da546Spatrick   dbg_bvr14,
107061da546Spatrick   dbg_bvr15,
108061da546Spatrick 
109061da546Spatrick   dbg_bcr0,
110061da546Spatrick   dbg_bcr1,
111061da546Spatrick   dbg_bcr2,
112061da546Spatrick   dbg_bcr3,
113061da546Spatrick   dbg_bcr4,
114061da546Spatrick   dbg_bcr5,
115061da546Spatrick   dbg_bcr6,
116061da546Spatrick   dbg_bcr7,
117061da546Spatrick   dbg_bcr8,
118061da546Spatrick   dbg_bcr9,
119061da546Spatrick   dbg_bcr10,
120061da546Spatrick   dbg_bcr11,
121061da546Spatrick   dbg_bcr12,
122061da546Spatrick   dbg_bcr13,
123061da546Spatrick   dbg_bcr14,
124061da546Spatrick   dbg_bcr15,
125061da546Spatrick 
126061da546Spatrick   dbg_wvr0,
127061da546Spatrick   dbg_wvr1,
128061da546Spatrick   dbg_wvr2,
129061da546Spatrick   dbg_wvr3,
130061da546Spatrick   dbg_wvr4,
131061da546Spatrick   dbg_wvr5,
132061da546Spatrick   dbg_wvr6,
133061da546Spatrick   dbg_wvr7,
134061da546Spatrick   dbg_wvr8,
135061da546Spatrick   dbg_wvr9,
136061da546Spatrick   dbg_wvr10,
137061da546Spatrick   dbg_wvr11,
138061da546Spatrick   dbg_wvr12,
139061da546Spatrick   dbg_wvr13,
140061da546Spatrick   dbg_wvr14,
141061da546Spatrick   dbg_wvr15,
142061da546Spatrick 
143061da546Spatrick   dbg_wcr0,
144061da546Spatrick   dbg_wcr1,
145061da546Spatrick   dbg_wcr2,
146061da546Spatrick   dbg_wcr3,
147061da546Spatrick   dbg_wcr4,
148061da546Spatrick   dbg_wcr5,
149061da546Spatrick   dbg_wcr6,
150061da546Spatrick   dbg_wcr7,
151061da546Spatrick   dbg_wcr8,
152061da546Spatrick   dbg_wcr9,
153061da546Spatrick   dbg_wcr10,
154061da546Spatrick   dbg_wcr11,
155061da546Spatrick   dbg_wcr12,
156061da546Spatrick   dbg_wcr13,
157061da546Spatrick   dbg_wcr14,
158061da546Spatrick   dbg_wcr15,
159061da546Spatrick 
160061da546Spatrick   k_num_registers
161061da546Spatrick };
162061da546Spatrick 
163061da546Spatrick #define GPR_OFFSET(idx) ((idx)*4)
164061da546Spatrick #define FPU_OFFSET(idx) ((idx)*4 + sizeof(RegisterContextDarwin_arm::GPR))
165061da546Spatrick #define EXC_OFFSET(idx)                                                        \
166061da546Spatrick   ((idx)*4 + sizeof(RegisterContextDarwin_arm::GPR) +                          \
167061da546Spatrick    sizeof(RegisterContextDarwin_arm::FPU))
168061da546Spatrick #define DBG_OFFSET(reg)                                                        \
169061da546Spatrick   ((LLVM_EXTENSION offsetof(RegisterContextDarwin_arm::DBG, reg) +             \
170061da546Spatrick     sizeof(RegisterContextDarwin_arm::GPR) +                                   \
171061da546Spatrick     sizeof(RegisterContextDarwin_arm::FPU) +                                   \
172061da546Spatrick     sizeof(RegisterContextDarwin_arm::EXC)))
173061da546Spatrick 
174061da546Spatrick #define DEFINE_DBG(reg, i)                                                     \
175061da546Spatrick   #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *) NULL)->reg[i]),       \
176061da546Spatrick                       DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex,           \
177061da546Spatrick                                  {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    \
178061da546Spatrick                                   LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    \
179061da546Spatrick                                   LLDB_INVALID_REGNUM },                       \
180*f6aab3d8Srobert                                   nullptr, nullptr,
181061da546Spatrick #define REG_CONTEXT_SIZE                                                       \
182061da546Spatrick   (sizeof(RegisterContextDarwin_arm::GPR) +                                    \
183061da546Spatrick    sizeof(RegisterContextDarwin_arm::FPU) +                                    \
184061da546Spatrick    sizeof(RegisterContextDarwin_arm::EXC))
185061da546Spatrick 
186061da546Spatrick static RegisterInfo g_register_infos[] = {
187061da546Spatrick     // General purpose registers
188061da546Spatrick     //  NAME        ALT     SZ  OFFSET              ENCODING        FORMAT
189061da546Spatrick     //  EH_FRAME                DWARF               GENERIC
190061da546Spatrick     //  PROCESS PLUGIN          LLDB NATIVE
191061da546Spatrick     //  ======      ======= ==  =============       =============   ============
192061da546Spatrick     //  ===============         ===============     =========================
193061da546Spatrick     //  =====================   =============
194061da546Spatrick     {"r0",
195061da546Spatrick      nullptr,
196061da546Spatrick      4,
197061da546Spatrick      GPR_OFFSET(0),
198061da546Spatrick      eEncodingUint,
199061da546Spatrick      eFormatHex,
200061da546Spatrick      {ehframe_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r0},
201061da546Spatrick      nullptr,
202061da546Spatrick      nullptr,
203*f6aab3d8Srobert     },
204061da546Spatrick     {"r1",
205061da546Spatrick      nullptr,
206061da546Spatrick      4,
207061da546Spatrick      GPR_OFFSET(1),
208061da546Spatrick      eEncodingUint,
209061da546Spatrick      eFormatHex,
210061da546Spatrick      {ehframe_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r1},
211061da546Spatrick      nullptr,
212061da546Spatrick      nullptr,
213*f6aab3d8Srobert     },
214061da546Spatrick     {"r2",
215061da546Spatrick      nullptr,
216061da546Spatrick      4,
217061da546Spatrick      GPR_OFFSET(2),
218061da546Spatrick      eEncodingUint,
219061da546Spatrick      eFormatHex,
220061da546Spatrick      {ehframe_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r2},
221061da546Spatrick      nullptr,
222061da546Spatrick      nullptr,
223*f6aab3d8Srobert     },
224061da546Spatrick     {"r3",
225061da546Spatrick      nullptr,
226061da546Spatrick      4,
227061da546Spatrick      GPR_OFFSET(3),
228061da546Spatrick      eEncodingUint,
229061da546Spatrick      eFormatHex,
230061da546Spatrick      {ehframe_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r3},
231061da546Spatrick      nullptr,
232061da546Spatrick      nullptr,
233*f6aab3d8Srobert     },
234061da546Spatrick     {"r4",
235061da546Spatrick      nullptr,
236061da546Spatrick      4,
237061da546Spatrick      GPR_OFFSET(4),
238061da546Spatrick      eEncodingUint,
239061da546Spatrick      eFormatHex,
240061da546Spatrick      {ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r4},
241061da546Spatrick      nullptr,
242061da546Spatrick      nullptr,
243*f6aab3d8Srobert     },
244061da546Spatrick     {"r5",
245061da546Spatrick      nullptr,
246061da546Spatrick      4,
247061da546Spatrick      GPR_OFFSET(5),
248061da546Spatrick      eEncodingUint,
249061da546Spatrick      eFormatHex,
250061da546Spatrick      {ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r5},
251061da546Spatrick      nullptr,
252061da546Spatrick      nullptr,
253*f6aab3d8Srobert     },
254061da546Spatrick     {"r6",
255061da546Spatrick      nullptr,
256061da546Spatrick      4,
257061da546Spatrick      GPR_OFFSET(6),
258061da546Spatrick      eEncodingUint,
259061da546Spatrick      eFormatHex,
260061da546Spatrick      {ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r6},
261061da546Spatrick      nullptr,
262061da546Spatrick      nullptr,
263*f6aab3d8Srobert     },
264061da546Spatrick     {"r7",
265061da546Spatrick      nullptr,
266061da546Spatrick      4,
267061da546Spatrick      GPR_OFFSET(7),
268061da546Spatrick      eEncodingUint,
269061da546Spatrick      eFormatHex,
270061da546Spatrick      {ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
271061da546Spatrick       gpr_r7},
272061da546Spatrick      nullptr,
273061da546Spatrick      nullptr,
274*f6aab3d8Srobert     },
275061da546Spatrick     {"r8",
276061da546Spatrick      nullptr,
277061da546Spatrick      4,
278061da546Spatrick      GPR_OFFSET(8),
279061da546Spatrick      eEncodingUint,
280061da546Spatrick      eFormatHex,
281061da546Spatrick      {ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r8},
282061da546Spatrick      nullptr,
283061da546Spatrick      nullptr,
284*f6aab3d8Srobert     },
285061da546Spatrick     {"r9",
286061da546Spatrick      nullptr,
287061da546Spatrick      4,
288061da546Spatrick      GPR_OFFSET(9),
289061da546Spatrick      eEncodingUint,
290061da546Spatrick      eFormatHex,
291061da546Spatrick      {ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r9},
292061da546Spatrick      nullptr,
293061da546Spatrick      nullptr,
294*f6aab3d8Srobert     },
295061da546Spatrick     {"r10",
296061da546Spatrick      nullptr,
297061da546Spatrick      4,
298061da546Spatrick      GPR_OFFSET(10),
299061da546Spatrick      eEncodingUint,
300061da546Spatrick      eFormatHex,
301061da546Spatrick      {ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
302061da546Spatrick       gpr_r10},
303061da546Spatrick      nullptr,
304061da546Spatrick      nullptr,
305*f6aab3d8Srobert     },
306061da546Spatrick     {"r11",
307061da546Spatrick      nullptr,
308061da546Spatrick      4,
309061da546Spatrick      GPR_OFFSET(11),
310061da546Spatrick      eEncodingUint,
311061da546Spatrick      eFormatHex,
312061da546Spatrick      {ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
313061da546Spatrick       gpr_r11},
314061da546Spatrick      nullptr,
315061da546Spatrick      nullptr,
316*f6aab3d8Srobert     },
317061da546Spatrick     {"r12",
318061da546Spatrick      nullptr,
319061da546Spatrick      4,
320061da546Spatrick      GPR_OFFSET(12),
321061da546Spatrick      eEncodingUint,
322061da546Spatrick      eFormatHex,
323061da546Spatrick      {ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
324061da546Spatrick       gpr_r12},
325061da546Spatrick      nullptr,
326061da546Spatrick      nullptr,
327*f6aab3d8Srobert     },
328061da546Spatrick     {"sp",
329061da546Spatrick      "r13",
330061da546Spatrick      4,
331061da546Spatrick      GPR_OFFSET(13),
332061da546Spatrick      eEncodingUint,
333061da546Spatrick      eFormatHex,
334061da546Spatrick      {ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
335061da546Spatrick       gpr_sp},
336061da546Spatrick      nullptr,
337061da546Spatrick      nullptr,
338*f6aab3d8Srobert     },
339061da546Spatrick     {"lr",
340061da546Spatrick      "r14",
341061da546Spatrick      4,
342061da546Spatrick      GPR_OFFSET(14),
343061da546Spatrick      eEncodingUint,
344061da546Spatrick      eFormatHex,
345061da546Spatrick      {ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
346061da546Spatrick       gpr_lr},
347061da546Spatrick      nullptr,
348061da546Spatrick      nullptr,
349*f6aab3d8Srobert     },
350061da546Spatrick     {"pc",
351061da546Spatrick      "r15",
352061da546Spatrick      4,
353061da546Spatrick      GPR_OFFSET(15),
354061da546Spatrick      eEncodingUint,
355061da546Spatrick      eFormatHex,
356061da546Spatrick      {ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
357061da546Spatrick       gpr_pc},
358061da546Spatrick      nullptr,
359061da546Spatrick      nullptr,
360*f6aab3d8Srobert     },
361061da546Spatrick     {"cpsr",
362061da546Spatrick      "psr",
363061da546Spatrick      4,
364061da546Spatrick      GPR_OFFSET(16),
365061da546Spatrick      eEncodingUint,
366061da546Spatrick      eFormatHex,
367061da546Spatrick      {ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
368061da546Spatrick       gpr_cpsr},
369061da546Spatrick      nullptr,
370061da546Spatrick      nullptr,
371*f6aab3d8Srobert     },
372061da546Spatrick 
373061da546Spatrick     {"s0",
374061da546Spatrick      nullptr,
375061da546Spatrick      4,
376061da546Spatrick      FPU_OFFSET(0),
377061da546Spatrick      eEncodingIEEE754,
378061da546Spatrick      eFormatFloat,
379061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
380061da546Spatrick       fpu_s0},
381061da546Spatrick      nullptr,
382061da546Spatrick      nullptr,
383*f6aab3d8Srobert     },
384061da546Spatrick     {"s1",
385061da546Spatrick      nullptr,
386061da546Spatrick      4,
387061da546Spatrick      FPU_OFFSET(1),
388061da546Spatrick      eEncodingIEEE754,
389061da546Spatrick      eFormatFloat,
390061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
391061da546Spatrick       fpu_s1},
392061da546Spatrick      nullptr,
393061da546Spatrick      nullptr,
394*f6aab3d8Srobert     },
395061da546Spatrick     {"s2",
396061da546Spatrick      nullptr,
397061da546Spatrick      4,
398061da546Spatrick      FPU_OFFSET(2),
399061da546Spatrick      eEncodingIEEE754,
400061da546Spatrick      eFormatFloat,
401061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
402061da546Spatrick       fpu_s2},
403061da546Spatrick      nullptr,
404061da546Spatrick      nullptr,
405*f6aab3d8Srobert     },
406061da546Spatrick     {"s3",
407061da546Spatrick      nullptr,
408061da546Spatrick      4,
409061da546Spatrick      FPU_OFFSET(3),
410061da546Spatrick      eEncodingIEEE754,
411061da546Spatrick      eFormatFloat,
412061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
413061da546Spatrick       fpu_s3},
414061da546Spatrick      nullptr,
415061da546Spatrick      nullptr,
416*f6aab3d8Srobert     },
417061da546Spatrick     {"s4",
418061da546Spatrick      nullptr,
419061da546Spatrick      4,
420061da546Spatrick      FPU_OFFSET(4),
421061da546Spatrick      eEncodingIEEE754,
422061da546Spatrick      eFormatFloat,
423061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
424061da546Spatrick       fpu_s4},
425061da546Spatrick      nullptr,
426061da546Spatrick      nullptr,
427*f6aab3d8Srobert     },
428061da546Spatrick     {"s5",
429061da546Spatrick      nullptr,
430061da546Spatrick      4,
431061da546Spatrick      FPU_OFFSET(5),
432061da546Spatrick      eEncodingIEEE754,
433061da546Spatrick      eFormatFloat,
434061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
435061da546Spatrick       fpu_s5},
436061da546Spatrick      nullptr,
437061da546Spatrick      nullptr,
438*f6aab3d8Srobert     },
439061da546Spatrick     {"s6",
440061da546Spatrick      nullptr,
441061da546Spatrick      4,
442061da546Spatrick      FPU_OFFSET(6),
443061da546Spatrick      eEncodingIEEE754,
444061da546Spatrick      eFormatFloat,
445061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
446061da546Spatrick       fpu_s6},
447061da546Spatrick      nullptr,
448061da546Spatrick      nullptr,
449*f6aab3d8Srobert     },
450061da546Spatrick     {"s7",
451061da546Spatrick      nullptr,
452061da546Spatrick      4,
453061da546Spatrick      FPU_OFFSET(7),
454061da546Spatrick      eEncodingIEEE754,
455061da546Spatrick      eFormatFloat,
456061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
457061da546Spatrick       fpu_s7},
458061da546Spatrick      nullptr,
459061da546Spatrick      nullptr,
460*f6aab3d8Srobert     },
461061da546Spatrick     {"s8",
462061da546Spatrick      nullptr,
463061da546Spatrick      4,
464061da546Spatrick      FPU_OFFSET(8),
465061da546Spatrick      eEncodingIEEE754,
466061da546Spatrick      eFormatFloat,
467061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
468061da546Spatrick       fpu_s8},
469061da546Spatrick      nullptr,
470061da546Spatrick      nullptr,
471*f6aab3d8Srobert     },
472061da546Spatrick     {"s9",
473061da546Spatrick      nullptr,
474061da546Spatrick      4,
475061da546Spatrick      FPU_OFFSET(9),
476061da546Spatrick      eEncodingIEEE754,
477061da546Spatrick      eFormatFloat,
478061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
479061da546Spatrick       fpu_s9},
480061da546Spatrick      nullptr,
481061da546Spatrick      nullptr,
482*f6aab3d8Srobert     },
483061da546Spatrick     {"s10",
484061da546Spatrick      nullptr,
485061da546Spatrick      4,
486061da546Spatrick      FPU_OFFSET(10),
487061da546Spatrick      eEncodingIEEE754,
488061da546Spatrick      eFormatFloat,
489061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
490061da546Spatrick       fpu_s10},
491061da546Spatrick      nullptr,
492061da546Spatrick      nullptr,
493*f6aab3d8Srobert     },
494061da546Spatrick     {"s11",
495061da546Spatrick      nullptr,
496061da546Spatrick      4,
497061da546Spatrick      FPU_OFFSET(11),
498061da546Spatrick      eEncodingIEEE754,
499061da546Spatrick      eFormatFloat,
500061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
501061da546Spatrick       fpu_s11},
502061da546Spatrick      nullptr,
503061da546Spatrick      nullptr,
504*f6aab3d8Srobert     },
505061da546Spatrick     {"s12",
506061da546Spatrick      nullptr,
507061da546Spatrick      4,
508061da546Spatrick      FPU_OFFSET(12),
509061da546Spatrick      eEncodingIEEE754,
510061da546Spatrick      eFormatFloat,
511061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
512061da546Spatrick       fpu_s12},
513061da546Spatrick      nullptr,
514061da546Spatrick      nullptr,
515*f6aab3d8Srobert     },
516061da546Spatrick     {"s13",
517061da546Spatrick      nullptr,
518061da546Spatrick      4,
519061da546Spatrick      FPU_OFFSET(13),
520061da546Spatrick      eEncodingIEEE754,
521061da546Spatrick      eFormatFloat,
522061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
523061da546Spatrick       fpu_s13},
524061da546Spatrick      nullptr,
525061da546Spatrick      nullptr,
526*f6aab3d8Srobert     },
527061da546Spatrick     {"s14",
528061da546Spatrick      nullptr,
529061da546Spatrick      4,
530061da546Spatrick      FPU_OFFSET(14),
531061da546Spatrick      eEncodingIEEE754,
532061da546Spatrick      eFormatFloat,
533061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
534061da546Spatrick       fpu_s14},
535061da546Spatrick      nullptr,
536061da546Spatrick      nullptr,
537*f6aab3d8Srobert     },
538061da546Spatrick     {"s15",
539061da546Spatrick      nullptr,
540061da546Spatrick      4,
541061da546Spatrick      FPU_OFFSET(15),
542061da546Spatrick      eEncodingIEEE754,
543061da546Spatrick      eFormatFloat,
544061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
545061da546Spatrick       fpu_s15},
546061da546Spatrick      nullptr,
547061da546Spatrick      nullptr,
548*f6aab3d8Srobert     },
549061da546Spatrick     {"s16",
550061da546Spatrick      nullptr,
551061da546Spatrick      4,
552061da546Spatrick      FPU_OFFSET(16),
553061da546Spatrick      eEncodingIEEE754,
554061da546Spatrick      eFormatFloat,
555061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
556061da546Spatrick       fpu_s16},
557061da546Spatrick      nullptr,
558061da546Spatrick      nullptr,
559*f6aab3d8Srobert     },
560061da546Spatrick     {"s17",
561061da546Spatrick      nullptr,
562061da546Spatrick      4,
563061da546Spatrick      FPU_OFFSET(17),
564061da546Spatrick      eEncodingIEEE754,
565061da546Spatrick      eFormatFloat,
566061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
567061da546Spatrick       fpu_s17},
568061da546Spatrick      nullptr,
569061da546Spatrick      nullptr,
570*f6aab3d8Srobert     },
571061da546Spatrick     {"s18",
572061da546Spatrick      nullptr,
573061da546Spatrick      4,
574061da546Spatrick      FPU_OFFSET(18),
575061da546Spatrick      eEncodingIEEE754,
576061da546Spatrick      eFormatFloat,
577061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
578061da546Spatrick       fpu_s18},
579061da546Spatrick      nullptr,
580061da546Spatrick      nullptr,
581*f6aab3d8Srobert     },
582061da546Spatrick     {"s19",
583061da546Spatrick      nullptr,
584061da546Spatrick      4,
585061da546Spatrick      FPU_OFFSET(19),
586061da546Spatrick      eEncodingIEEE754,
587061da546Spatrick      eFormatFloat,
588061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
589061da546Spatrick       fpu_s19},
590061da546Spatrick      nullptr,
591061da546Spatrick      nullptr,
592*f6aab3d8Srobert     },
593061da546Spatrick     {"s20",
594061da546Spatrick      nullptr,
595061da546Spatrick      4,
596061da546Spatrick      FPU_OFFSET(20),
597061da546Spatrick      eEncodingIEEE754,
598061da546Spatrick      eFormatFloat,
599061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
600061da546Spatrick       fpu_s20},
601061da546Spatrick      nullptr,
602061da546Spatrick      nullptr,
603*f6aab3d8Srobert     },
604061da546Spatrick     {"s21",
605061da546Spatrick      nullptr,
606061da546Spatrick      4,
607061da546Spatrick      FPU_OFFSET(21),
608061da546Spatrick      eEncodingIEEE754,
609061da546Spatrick      eFormatFloat,
610061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
611061da546Spatrick       fpu_s21},
612061da546Spatrick      nullptr,
613061da546Spatrick      nullptr,
614*f6aab3d8Srobert     },
615061da546Spatrick     {"s22",
616061da546Spatrick      nullptr,
617061da546Spatrick      4,
618061da546Spatrick      FPU_OFFSET(22),
619061da546Spatrick      eEncodingIEEE754,
620061da546Spatrick      eFormatFloat,
621061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
622061da546Spatrick       fpu_s22},
623061da546Spatrick      nullptr,
624061da546Spatrick      nullptr,
625*f6aab3d8Srobert     },
626061da546Spatrick     {"s23",
627061da546Spatrick      nullptr,
628061da546Spatrick      4,
629061da546Spatrick      FPU_OFFSET(23),
630061da546Spatrick      eEncodingIEEE754,
631061da546Spatrick      eFormatFloat,
632061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
633061da546Spatrick       fpu_s23},
634061da546Spatrick      nullptr,
635061da546Spatrick      nullptr,
636*f6aab3d8Srobert     },
637061da546Spatrick     {"s24",
638061da546Spatrick      nullptr,
639061da546Spatrick      4,
640061da546Spatrick      FPU_OFFSET(24),
641061da546Spatrick      eEncodingIEEE754,
642061da546Spatrick      eFormatFloat,
643061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
644061da546Spatrick       fpu_s24},
645061da546Spatrick      nullptr,
646061da546Spatrick      nullptr,
647*f6aab3d8Srobert     },
648061da546Spatrick     {"s25",
649061da546Spatrick      nullptr,
650061da546Spatrick      4,
651061da546Spatrick      FPU_OFFSET(25),
652061da546Spatrick      eEncodingIEEE754,
653061da546Spatrick      eFormatFloat,
654061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
655061da546Spatrick       fpu_s25},
656061da546Spatrick      nullptr,
657061da546Spatrick      nullptr,
658*f6aab3d8Srobert     },
659061da546Spatrick     {"s26",
660061da546Spatrick      nullptr,
661061da546Spatrick      4,
662061da546Spatrick      FPU_OFFSET(26),
663061da546Spatrick      eEncodingIEEE754,
664061da546Spatrick      eFormatFloat,
665061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
666061da546Spatrick       fpu_s26},
667061da546Spatrick      nullptr,
668061da546Spatrick      nullptr,
669*f6aab3d8Srobert     },
670061da546Spatrick     {"s27",
671061da546Spatrick      nullptr,
672061da546Spatrick      4,
673061da546Spatrick      FPU_OFFSET(27),
674061da546Spatrick      eEncodingIEEE754,
675061da546Spatrick      eFormatFloat,
676061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
677061da546Spatrick       fpu_s27},
678061da546Spatrick      nullptr,
679061da546Spatrick      nullptr,
680*f6aab3d8Srobert     },
681061da546Spatrick     {"s28",
682061da546Spatrick      nullptr,
683061da546Spatrick      4,
684061da546Spatrick      FPU_OFFSET(28),
685061da546Spatrick      eEncodingIEEE754,
686061da546Spatrick      eFormatFloat,
687061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
688061da546Spatrick       fpu_s28},
689061da546Spatrick      nullptr,
690061da546Spatrick      nullptr,
691*f6aab3d8Srobert     },
692061da546Spatrick     {"s29",
693061da546Spatrick      nullptr,
694061da546Spatrick      4,
695061da546Spatrick      FPU_OFFSET(29),
696061da546Spatrick      eEncodingIEEE754,
697061da546Spatrick      eFormatFloat,
698061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
699061da546Spatrick       fpu_s29},
700061da546Spatrick      nullptr,
701061da546Spatrick      nullptr,
702*f6aab3d8Srobert     },
703061da546Spatrick     {"s30",
704061da546Spatrick      nullptr,
705061da546Spatrick      4,
706061da546Spatrick      FPU_OFFSET(30),
707061da546Spatrick      eEncodingIEEE754,
708061da546Spatrick      eFormatFloat,
709061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
710061da546Spatrick       fpu_s30},
711061da546Spatrick      nullptr,
712061da546Spatrick      nullptr,
713*f6aab3d8Srobert     },
714061da546Spatrick     {"s31",
715061da546Spatrick      nullptr,
716061da546Spatrick      4,
717061da546Spatrick      FPU_OFFSET(31),
718061da546Spatrick      eEncodingIEEE754,
719061da546Spatrick      eFormatFloat,
720061da546Spatrick      {LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
721061da546Spatrick       fpu_s31},
722061da546Spatrick      nullptr,
723061da546Spatrick      nullptr,
724*f6aab3d8Srobert     },
725061da546Spatrick     {"fpscr",
726061da546Spatrick      nullptr,
727061da546Spatrick      4,
728061da546Spatrick      FPU_OFFSET(32),
729061da546Spatrick      eEncodingUint,
730061da546Spatrick      eFormatHex,
731061da546Spatrick      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
732061da546Spatrick       LLDB_INVALID_REGNUM, fpu_fpscr},
733061da546Spatrick      nullptr,
734061da546Spatrick      nullptr,
735*f6aab3d8Srobert     },
736061da546Spatrick 
737061da546Spatrick     {"exception",
738061da546Spatrick      nullptr,
739061da546Spatrick      4,
740061da546Spatrick      EXC_OFFSET(0),
741061da546Spatrick      eEncodingUint,
742061da546Spatrick      eFormatHex,
743061da546Spatrick      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
744061da546Spatrick       LLDB_INVALID_REGNUM, exc_exception},
745061da546Spatrick      nullptr,
746061da546Spatrick      nullptr,
747*f6aab3d8Srobert     },
748061da546Spatrick     {"fsr",
749061da546Spatrick      nullptr,
750061da546Spatrick      4,
751061da546Spatrick      EXC_OFFSET(1),
752061da546Spatrick      eEncodingUint,
753061da546Spatrick      eFormatHex,
754061da546Spatrick      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
755061da546Spatrick       LLDB_INVALID_REGNUM, exc_fsr},
756061da546Spatrick      nullptr,
757061da546Spatrick      nullptr,
758*f6aab3d8Srobert     },
759061da546Spatrick     {"far",
760061da546Spatrick      nullptr,
761061da546Spatrick      4,
762061da546Spatrick      EXC_OFFSET(2),
763061da546Spatrick      eEncodingUint,
764061da546Spatrick      eFormatHex,
765061da546Spatrick      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
766061da546Spatrick       LLDB_INVALID_REGNUM, exc_far},
767061da546Spatrick      nullptr,
768061da546Spatrick      nullptr,
769*f6aab3d8Srobert     },
770061da546Spatrick 
771061da546Spatrick     {DEFINE_DBG(bvr, 0)},
772061da546Spatrick     {DEFINE_DBG(bvr, 1)},
773061da546Spatrick     {DEFINE_DBG(bvr, 2)},
774061da546Spatrick     {DEFINE_DBG(bvr, 3)},
775061da546Spatrick     {DEFINE_DBG(bvr, 4)},
776061da546Spatrick     {DEFINE_DBG(bvr, 5)},
777061da546Spatrick     {DEFINE_DBG(bvr, 6)},
778061da546Spatrick     {DEFINE_DBG(bvr, 7)},
779061da546Spatrick     {DEFINE_DBG(bvr, 8)},
780061da546Spatrick     {DEFINE_DBG(bvr, 9)},
781061da546Spatrick     {DEFINE_DBG(bvr, 10)},
782061da546Spatrick     {DEFINE_DBG(bvr, 11)},
783061da546Spatrick     {DEFINE_DBG(bvr, 12)},
784061da546Spatrick     {DEFINE_DBG(bvr, 13)},
785061da546Spatrick     {DEFINE_DBG(bvr, 14)},
786061da546Spatrick     {DEFINE_DBG(bvr, 15)},
787061da546Spatrick 
788061da546Spatrick     {DEFINE_DBG(bcr, 0)},
789061da546Spatrick     {DEFINE_DBG(bcr, 1)},
790061da546Spatrick     {DEFINE_DBG(bcr, 2)},
791061da546Spatrick     {DEFINE_DBG(bcr, 3)},
792061da546Spatrick     {DEFINE_DBG(bcr, 4)},
793061da546Spatrick     {DEFINE_DBG(bcr, 5)},
794061da546Spatrick     {DEFINE_DBG(bcr, 6)},
795061da546Spatrick     {DEFINE_DBG(bcr, 7)},
796061da546Spatrick     {DEFINE_DBG(bcr, 8)},
797061da546Spatrick     {DEFINE_DBG(bcr, 9)},
798061da546Spatrick     {DEFINE_DBG(bcr, 10)},
799061da546Spatrick     {DEFINE_DBG(bcr, 11)},
800061da546Spatrick     {DEFINE_DBG(bcr, 12)},
801061da546Spatrick     {DEFINE_DBG(bcr, 13)},
802061da546Spatrick     {DEFINE_DBG(bcr, 14)},
803061da546Spatrick     {DEFINE_DBG(bcr, 15)},
804061da546Spatrick 
805061da546Spatrick     {DEFINE_DBG(wvr, 0)},
806061da546Spatrick     {DEFINE_DBG(wvr, 1)},
807061da546Spatrick     {DEFINE_DBG(wvr, 2)},
808061da546Spatrick     {DEFINE_DBG(wvr, 3)},
809061da546Spatrick     {DEFINE_DBG(wvr, 4)},
810061da546Spatrick     {DEFINE_DBG(wvr, 5)},
811061da546Spatrick     {DEFINE_DBG(wvr, 6)},
812061da546Spatrick     {DEFINE_DBG(wvr, 7)},
813061da546Spatrick     {DEFINE_DBG(wvr, 8)},
814061da546Spatrick     {DEFINE_DBG(wvr, 9)},
815061da546Spatrick     {DEFINE_DBG(wvr, 10)},
816061da546Spatrick     {DEFINE_DBG(wvr, 11)},
817061da546Spatrick     {DEFINE_DBG(wvr, 12)},
818061da546Spatrick     {DEFINE_DBG(wvr, 13)},
819061da546Spatrick     {DEFINE_DBG(wvr, 14)},
820061da546Spatrick     {DEFINE_DBG(wvr, 15)},
821061da546Spatrick 
822061da546Spatrick     {DEFINE_DBG(wcr, 0)},
823061da546Spatrick     {DEFINE_DBG(wcr, 1)},
824061da546Spatrick     {DEFINE_DBG(wcr, 2)},
825061da546Spatrick     {DEFINE_DBG(wcr, 3)},
826061da546Spatrick     {DEFINE_DBG(wcr, 4)},
827061da546Spatrick     {DEFINE_DBG(wcr, 5)},
828061da546Spatrick     {DEFINE_DBG(wcr, 6)},
829061da546Spatrick     {DEFINE_DBG(wcr, 7)},
830061da546Spatrick     {DEFINE_DBG(wcr, 8)},
831061da546Spatrick     {DEFINE_DBG(wcr, 9)},
832061da546Spatrick     {DEFINE_DBG(wcr, 10)},
833061da546Spatrick     {DEFINE_DBG(wcr, 11)},
834061da546Spatrick     {DEFINE_DBG(wcr, 12)},
835061da546Spatrick     {DEFINE_DBG(wcr, 13)},
836061da546Spatrick     {DEFINE_DBG(wcr, 14)},
837061da546Spatrick     {DEFINE_DBG(wcr, 15)}};
838061da546Spatrick 
839061da546Spatrick // General purpose registers
840061da546Spatrick static uint32_t g_gpr_regnums[] = {
841061da546Spatrick     gpr_r0, gpr_r1,  gpr_r2,  gpr_r3,  gpr_r4, gpr_r5, gpr_r6, gpr_r7,  gpr_r8,
842061da546Spatrick     gpr_r9, gpr_r10, gpr_r11, gpr_r12, gpr_sp, gpr_lr, gpr_pc, gpr_cpsr};
843061da546Spatrick 
844061da546Spatrick // Floating point registers
845061da546Spatrick static uint32_t g_fpu_regnums[] = {
846061da546Spatrick     fpu_s0,  fpu_s1,  fpu_s2,  fpu_s3,  fpu_s4,    fpu_s5,  fpu_s6,
847061da546Spatrick     fpu_s7,  fpu_s8,  fpu_s9,  fpu_s10, fpu_s11,   fpu_s12, fpu_s13,
848061da546Spatrick     fpu_s14, fpu_s15, fpu_s16, fpu_s17, fpu_s18,   fpu_s19, fpu_s20,
849061da546Spatrick     fpu_s21, fpu_s22, fpu_s23, fpu_s24, fpu_s25,   fpu_s26, fpu_s27,
850061da546Spatrick     fpu_s28, fpu_s29, fpu_s30, fpu_s31, fpu_fpscr,
851061da546Spatrick };
852061da546Spatrick 
853061da546Spatrick // Exception registers
854061da546Spatrick 
855061da546Spatrick static uint32_t g_exc_regnums[] = {
856061da546Spatrick     exc_exception, exc_fsr, exc_far,
857061da546Spatrick };
858061da546Spatrick 
859*f6aab3d8Srobert static size_t k_num_register_infos = std::size(g_register_infos);
860061da546Spatrick 
RegisterContextDarwin_arm(Thread & thread,uint32_t concrete_frame_idx)861061da546Spatrick RegisterContextDarwin_arm::RegisterContextDarwin_arm(
862061da546Spatrick     Thread &thread, uint32_t concrete_frame_idx)
863061da546Spatrick     : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() {
864061da546Spatrick   uint32_t i;
865061da546Spatrick   for (i = 0; i < kNumErrors; i++) {
866061da546Spatrick     gpr_errs[i] = -1;
867061da546Spatrick     fpu_errs[i] = -1;
868061da546Spatrick     exc_errs[i] = -1;
869061da546Spatrick   }
870061da546Spatrick }
871061da546Spatrick 
872be691f3bSpatrick RegisterContextDarwin_arm::~RegisterContextDarwin_arm() = default;
873061da546Spatrick 
InvalidateAllRegisters()874061da546Spatrick void RegisterContextDarwin_arm::InvalidateAllRegisters() {
875061da546Spatrick   InvalidateAllRegisterStates();
876061da546Spatrick }
877061da546Spatrick 
GetRegisterCount()878061da546Spatrick size_t RegisterContextDarwin_arm::GetRegisterCount() {
879061da546Spatrick   assert(k_num_register_infos == k_num_registers);
880061da546Spatrick   return k_num_registers;
881061da546Spatrick }
882061da546Spatrick 
883061da546Spatrick const RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)884061da546Spatrick RegisterContextDarwin_arm::GetRegisterInfoAtIndex(size_t reg) {
885061da546Spatrick   assert(k_num_register_infos == k_num_registers);
886061da546Spatrick   if (reg < k_num_registers)
887061da546Spatrick     return &g_register_infos[reg];
888061da546Spatrick   return nullptr;
889061da546Spatrick }
890061da546Spatrick 
GetRegisterInfosCount()891061da546Spatrick size_t RegisterContextDarwin_arm::GetRegisterInfosCount() {
892061da546Spatrick   return k_num_register_infos;
893061da546Spatrick }
894061da546Spatrick 
GetRegisterInfos()895061da546Spatrick const RegisterInfo *RegisterContextDarwin_arm::GetRegisterInfos() {
896061da546Spatrick   return g_register_infos;
897061da546Spatrick }
898061da546Spatrick 
899061da546Spatrick // Number of registers in each register set
900*f6aab3d8Srobert const size_t k_num_gpr_registers = std::size(g_gpr_regnums);
901*f6aab3d8Srobert const size_t k_num_fpu_registers = std::size(g_fpu_regnums);
902*f6aab3d8Srobert const size_t k_num_exc_registers = std::size(g_exc_regnums);
903061da546Spatrick 
904061da546Spatrick // Register set definitions. The first definitions at register set index of
905061da546Spatrick // zero is for all registers, followed by other registers sets. The register
906061da546Spatrick // information for the all register set need not be filled in.
907061da546Spatrick static const RegisterSet g_reg_sets[] = {
908061da546Spatrick     {
909061da546Spatrick         "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums,
910061da546Spatrick     },
911061da546Spatrick     {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums},
912061da546Spatrick     {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}};
913061da546Spatrick 
914*f6aab3d8Srobert const size_t k_num_regsets = std::size(g_reg_sets);
915061da546Spatrick 
GetRegisterSetCount()916061da546Spatrick size_t RegisterContextDarwin_arm::GetRegisterSetCount() {
917061da546Spatrick   return k_num_regsets;
918061da546Spatrick }
919061da546Spatrick 
GetRegisterSet(size_t reg_set)920061da546Spatrick const RegisterSet *RegisterContextDarwin_arm::GetRegisterSet(size_t reg_set) {
921061da546Spatrick   if (reg_set < k_num_regsets)
922061da546Spatrick     return &g_reg_sets[reg_set];
923061da546Spatrick   return nullptr;
924061da546Spatrick }
925061da546Spatrick 
926061da546Spatrick // Register information definitions for 32 bit i386.
GetSetForNativeRegNum(int reg)927061da546Spatrick int RegisterContextDarwin_arm::GetSetForNativeRegNum(int reg) {
928061da546Spatrick   if (reg < fpu_s0)
929061da546Spatrick     return GPRRegSet;
930061da546Spatrick   else if (reg < exc_exception)
931061da546Spatrick     return FPURegSet;
932061da546Spatrick   else if (reg < k_num_registers)
933061da546Spatrick     return EXCRegSet;
934061da546Spatrick   return -1;
935061da546Spatrick }
936061da546Spatrick 
ReadGPR(bool force)937061da546Spatrick int RegisterContextDarwin_arm::ReadGPR(bool force) {
938061da546Spatrick   int set = GPRRegSet;
939061da546Spatrick   if (force || !RegisterSetIsCached(set)) {
940061da546Spatrick     SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
941061da546Spatrick   }
942061da546Spatrick   return GetError(GPRRegSet, Read);
943061da546Spatrick }
944061da546Spatrick 
ReadFPU(bool force)945061da546Spatrick int RegisterContextDarwin_arm::ReadFPU(bool force) {
946061da546Spatrick   int set = FPURegSet;
947061da546Spatrick   if (force || !RegisterSetIsCached(set)) {
948061da546Spatrick     SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
949061da546Spatrick   }
950061da546Spatrick   return GetError(FPURegSet, Read);
951061da546Spatrick }
952061da546Spatrick 
ReadEXC(bool force)953061da546Spatrick int RegisterContextDarwin_arm::ReadEXC(bool force) {
954061da546Spatrick   int set = EXCRegSet;
955061da546Spatrick   if (force || !RegisterSetIsCached(set)) {
956061da546Spatrick     SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
957061da546Spatrick   }
958061da546Spatrick   return GetError(EXCRegSet, Read);
959061da546Spatrick }
960061da546Spatrick 
ReadDBG(bool force)961061da546Spatrick int RegisterContextDarwin_arm::ReadDBG(bool force) {
962061da546Spatrick   int set = DBGRegSet;
963061da546Spatrick   if (force || !RegisterSetIsCached(set)) {
964061da546Spatrick     SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));
965061da546Spatrick   }
966061da546Spatrick   return GetError(DBGRegSet, Read);
967061da546Spatrick }
968061da546Spatrick 
WriteGPR()969061da546Spatrick int RegisterContextDarwin_arm::WriteGPR() {
970061da546Spatrick   int set = GPRRegSet;
971061da546Spatrick   if (!RegisterSetIsCached(set)) {
972061da546Spatrick     SetError(set, Write, -1);
973061da546Spatrick     return KERN_INVALID_ARGUMENT;
974061da546Spatrick   }
975061da546Spatrick   SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));
976061da546Spatrick   SetError(set, Read, -1);
977061da546Spatrick   return GetError(GPRRegSet, Write);
978061da546Spatrick }
979061da546Spatrick 
WriteFPU()980061da546Spatrick int RegisterContextDarwin_arm::WriteFPU() {
981061da546Spatrick   int set = FPURegSet;
982061da546Spatrick   if (!RegisterSetIsCached(set)) {
983061da546Spatrick     SetError(set, Write, -1);
984061da546Spatrick     return KERN_INVALID_ARGUMENT;
985061da546Spatrick   }
986061da546Spatrick   SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu));
987061da546Spatrick   SetError(set, Read, -1);
988061da546Spatrick   return GetError(FPURegSet, Write);
989061da546Spatrick }
990061da546Spatrick 
WriteEXC()991061da546Spatrick int RegisterContextDarwin_arm::WriteEXC() {
992061da546Spatrick   int set = EXCRegSet;
993061da546Spatrick   if (!RegisterSetIsCached(set)) {
994061da546Spatrick     SetError(set, Write, -1);
995061da546Spatrick     return KERN_INVALID_ARGUMENT;
996061da546Spatrick   }
997061da546Spatrick   SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));
998061da546Spatrick   SetError(set, Read, -1);
999061da546Spatrick   return GetError(EXCRegSet, Write);
1000061da546Spatrick }
1001061da546Spatrick 
WriteDBG()1002061da546Spatrick int RegisterContextDarwin_arm::WriteDBG() {
1003061da546Spatrick   int set = DBGRegSet;
1004061da546Spatrick   if (!RegisterSetIsCached(set)) {
1005061da546Spatrick     SetError(set, Write, -1);
1006061da546Spatrick     return KERN_INVALID_ARGUMENT;
1007061da546Spatrick   }
1008061da546Spatrick   SetError(set, Write, DoWriteDBG(GetThreadID(), set, dbg));
1009061da546Spatrick   SetError(set, Read, -1);
1010061da546Spatrick   return GetError(DBGRegSet, Write);
1011061da546Spatrick }
1012061da546Spatrick 
ReadRegisterSet(uint32_t set,bool force)1013061da546Spatrick int RegisterContextDarwin_arm::ReadRegisterSet(uint32_t set, bool force) {
1014061da546Spatrick   switch (set) {
1015061da546Spatrick   case GPRRegSet:
1016061da546Spatrick     return ReadGPR(force);
1017061da546Spatrick   case GPRAltRegSet:
1018061da546Spatrick     return ReadGPR(force);
1019061da546Spatrick   case FPURegSet:
1020061da546Spatrick     return ReadFPU(force);
1021061da546Spatrick   case EXCRegSet:
1022061da546Spatrick     return ReadEXC(force);
1023061da546Spatrick   case DBGRegSet:
1024061da546Spatrick     return ReadDBG(force);
1025061da546Spatrick   default:
1026061da546Spatrick     break;
1027061da546Spatrick   }
1028061da546Spatrick   return KERN_INVALID_ARGUMENT;
1029061da546Spatrick }
1030061da546Spatrick 
WriteRegisterSet(uint32_t set)1031061da546Spatrick int RegisterContextDarwin_arm::WriteRegisterSet(uint32_t set) {
1032061da546Spatrick   // Make sure we have a valid context to set.
1033061da546Spatrick   if (RegisterSetIsCached(set)) {
1034061da546Spatrick     switch (set) {
1035061da546Spatrick     case GPRRegSet:
1036061da546Spatrick       return WriteGPR();
1037061da546Spatrick     case GPRAltRegSet:
1038061da546Spatrick       return WriteGPR();
1039061da546Spatrick     case FPURegSet:
1040061da546Spatrick       return WriteFPU();
1041061da546Spatrick     case EXCRegSet:
1042061da546Spatrick       return WriteEXC();
1043061da546Spatrick     case DBGRegSet:
1044061da546Spatrick       return WriteDBG();
1045061da546Spatrick     default:
1046061da546Spatrick       break;
1047061da546Spatrick     }
1048061da546Spatrick   }
1049061da546Spatrick   return KERN_INVALID_ARGUMENT;
1050061da546Spatrick }
1051061da546Spatrick 
LogDBGRegisters(Log * log,const DBG & dbg)1052061da546Spatrick void RegisterContextDarwin_arm::LogDBGRegisters(Log *log, const DBG &dbg) {
1053061da546Spatrick   if (log) {
1054061da546Spatrick     for (uint32_t i = 0; i < 16; i++)
1055061da546Spatrick       LLDB_LOGF(log,
1056061da546Spatrick                 "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { "
1057061da546Spatrick                 "0x%8.8x, 0x%8.8x }",
1058061da546Spatrick                 i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]);
1059061da546Spatrick   }
1060061da546Spatrick }
1061061da546Spatrick 
ReadRegister(const RegisterInfo * reg_info,RegisterValue & value)1062061da546Spatrick bool RegisterContextDarwin_arm::ReadRegister(const RegisterInfo *reg_info,
1063061da546Spatrick                                              RegisterValue &value) {
1064061da546Spatrick   const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
1065061da546Spatrick   int set = RegisterContextDarwin_arm::GetSetForNativeRegNum(reg);
1066061da546Spatrick 
1067061da546Spatrick   if (set == -1)
1068061da546Spatrick     return false;
1069061da546Spatrick 
1070061da546Spatrick   if (ReadRegisterSet(set, false) != KERN_SUCCESS)
1071061da546Spatrick     return false;
1072061da546Spatrick 
1073061da546Spatrick   switch (reg) {
1074061da546Spatrick   case gpr_r0:
1075061da546Spatrick   case gpr_r1:
1076061da546Spatrick   case gpr_r2:
1077061da546Spatrick   case gpr_r3:
1078061da546Spatrick   case gpr_r4:
1079061da546Spatrick   case gpr_r5:
1080061da546Spatrick   case gpr_r6:
1081061da546Spatrick   case gpr_r7:
1082061da546Spatrick   case gpr_r8:
1083061da546Spatrick   case gpr_r9:
1084061da546Spatrick   case gpr_r10:
1085061da546Spatrick   case gpr_r11:
1086061da546Spatrick   case gpr_r12:
1087061da546Spatrick   case gpr_sp:
1088061da546Spatrick   case gpr_lr:
1089061da546Spatrick   case gpr_pc:
1090061da546Spatrick     value.SetUInt32(gpr.r[reg - gpr_r0]);
1091061da546Spatrick     break;
1092061da546Spatrick   case gpr_cpsr:
1093061da546Spatrick     value.SetUInt32(gpr.cpsr);
1094061da546Spatrick     break;
1095061da546Spatrick   case fpu_s0:
1096061da546Spatrick   case fpu_s1:
1097061da546Spatrick   case fpu_s2:
1098061da546Spatrick   case fpu_s3:
1099061da546Spatrick   case fpu_s4:
1100061da546Spatrick   case fpu_s5:
1101061da546Spatrick   case fpu_s6:
1102061da546Spatrick   case fpu_s7:
1103061da546Spatrick   case fpu_s8:
1104061da546Spatrick   case fpu_s9:
1105061da546Spatrick   case fpu_s10:
1106061da546Spatrick   case fpu_s11:
1107061da546Spatrick   case fpu_s12:
1108061da546Spatrick   case fpu_s13:
1109061da546Spatrick   case fpu_s14:
1110061da546Spatrick   case fpu_s15:
1111061da546Spatrick   case fpu_s16:
1112061da546Spatrick   case fpu_s17:
1113061da546Spatrick   case fpu_s18:
1114061da546Spatrick   case fpu_s19:
1115061da546Spatrick   case fpu_s20:
1116061da546Spatrick   case fpu_s21:
1117061da546Spatrick   case fpu_s22:
1118061da546Spatrick   case fpu_s23:
1119061da546Spatrick   case fpu_s24:
1120061da546Spatrick   case fpu_s25:
1121061da546Spatrick   case fpu_s26:
1122061da546Spatrick   case fpu_s27:
1123061da546Spatrick   case fpu_s28:
1124061da546Spatrick   case fpu_s29:
1125061da546Spatrick   case fpu_s30:
1126061da546Spatrick   case fpu_s31:
1127061da546Spatrick     value.SetUInt32(fpu.floats.s[reg], RegisterValue::eTypeFloat);
1128061da546Spatrick     break;
1129061da546Spatrick 
1130061da546Spatrick   case fpu_fpscr:
1131061da546Spatrick     value.SetUInt32(fpu.fpscr);
1132061da546Spatrick     break;
1133061da546Spatrick 
1134061da546Spatrick   case exc_exception:
1135061da546Spatrick     value.SetUInt32(exc.exception);
1136061da546Spatrick     break;
1137061da546Spatrick   case exc_fsr:
1138061da546Spatrick     value.SetUInt32(exc.fsr);
1139061da546Spatrick     break;
1140061da546Spatrick   case exc_far:
1141061da546Spatrick     value.SetUInt32(exc.far);
1142061da546Spatrick     break;
1143061da546Spatrick 
1144061da546Spatrick   default:
1145061da546Spatrick     value.SetValueToInvalid();
1146061da546Spatrick     return false;
1147061da546Spatrick   }
1148061da546Spatrick   return true;
1149061da546Spatrick }
1150061da546Spatrick 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & value)1151061da546Spatrick bool RegisterContextDarwin_arm::WriteRegister(const RegisterInfo *reg_info,
1152061da546Spatrick                                               const RegisterValue &value) {
1153061da546Spatrick   const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
1154061da546Spatrick   int set = GetSetForNativeRegNum(reg);
1155061da546Spatrick 
1156061da546Spatrick   if (set == -1)
1157061da546Spatrick     return false;
1158061da546Spatrick 
1159061da546Spatrick   if (ReadRegisterSet(set, false) != KERN_SUCCESS)
1160061da546Spatrick     return false;
1161061da546Spatrick 
1162061da546Spatrick   switch (reg) {
1163061da546Spatrick   case gpr_r0:
1164061da546Spatrick   case gpr_r1:
1165061da546Spatrick   case gpr_r2:
1166061da546Spatrick   case gpr_r3:
1167061da546Spatrick   case gpr_r4:
1168061da546Spatrick   case gpr_r5:
1169061da546Spatrick   case gpr_r6:
1170061da546Spatrick   case gpr_r7:
1171061da546Spatrick   case gpr_r8:
1172061da546Spatrick   case gpr_r9:
1173061da546Spatrick   case gpr_r10:
1174061da546Spatrick   case gpr_r11:
1175061da546Spatrick   case gpr_r12:
1176061da546Spatrick   case gpr_sp:
1177061da546Spatrick   case gpr_lr:
1178061da546Spatrick   case gpr_pc:
1179061da546Spatrick   case gpr_cpsr:
1180061da546Spatrick     gpr.r[reg - gpr_r0] = value.GetAsUInt32();
1181061da546Spatrick     break;
1182061da546Spatrick 
1183061da546Spatrick   case fpu_s0:
1184061da546Spatrick   case fpu_s1:
1185061da546Spatrick   case fpu_s2:
1186061da546Spatrick   case fpu_s3:
1187061da546Spatrick   case fpu_s4:
1188061da546Spatrick   case fpu_s5:
1189061da546Spatrick   case fpu_s6:
1190061da546Spatrick   case fpu_s7:
1191061da546Spatrick   case fpu_s8:
1192061da546Spatrick   case fpu_s9:
1193061da546Spatrick   case fpu_s10:
1194061da546Spatrick   case fpu_s11:
1195061da546Spatrick   case fpu_s12:
1196061da546Spatrick   case fpu_s13:
1197061da546Spatrick   case fpu_s14:
1198061da546Spatrick   case fpu_s15:
1199061da546Spatrick   case fpu_s16:
1200061da546Spatrick   case fpu_s17:
1201061da546Spatrick   case fpu_s18:
1202061da546Spatrick   case fpu_s19:
1203061da546Spatrick   case fpu_s20:
1204061da546Spatrick   case fpu_s21:
1205061da546Spatrick   case fpu_s22:
1206061da546Spatrick   case fpu_s23:
1207061da546Spatrick   case fpu_s24:
1208061da546Spatrick   case fpu_s25:
1209061da546Spatrick   case fpu_s26:
1210061da546Spatrick   case fpu_s27:
1211061da546Spatrick   case fpu_s28:
1212061da546Spatrick   case fpu_s29:
1213061da546Spatrick   case fpu_s30:
1214061da546Spatrick   case fpu_s31:
1215061da546Spatrick     fpu.floats.s[reg] = value.GetAsUInt32();
1216061da546Spatrick     break;
1217061da546Spatrick 
1218061da546Spatrick   case fpu_fpscr:
1219061da546Spatrick     fpu.fpscr = value.GetAsUInt32();
1220061da546Spatrick     break;
1221061da546Spatrick 
1222061da546Spatrick   case exc_exception:
1223061da546Spatrick     exc.exception = value.GetAsUInt32();
1224061da546Spatrick     break;
1225061da546Spatrick   case exc_fsr:
1226061da546Spatrick     exc.fsr = value.GetAsUInt32();
1227061da546Spatrick     break;
1228061da546Spatrick   case exc_far:
1229061da546Spatrick     exc.far = value.GetAsUInt32();
1230061da546Spatrick     break;
1231061da546Spatrick 
1232061da546Spatrick   default:
1233061da546Spatrick     return false;
1234061da546Spatrick   }
1235061da546Spatrick   return WriteRegisterSet(set) == KERN_SUCCESS;
1236061da546Spatrick }
1237061da546Spatrick 
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)1238061da546Spatrick bool RegisterContextDarwin_arm::ReadAllRegisterValues(
1239*f6aab3d8Srobert     lldb::WritableDataBufferSP &data_sp) {
1240061da546Spatrick   data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
1241061da546Spatrick   if (data_sp && ReadGPR(false) == KERN_SUCCESS &&
1242061da546Spatrick       ReadFPU(false) == KERN_SUCCESS && ReadEXC(false) == KERN_SUCCESS) {
1243061da546Spatrick     uint8_t *dst = data_sp->GetBytes();
1244061da546Spatrick     ::memcpy(dst, &gpr, sizeof(gpr));
1245061da546Spatrick     dst += sizeof(gpr);
1246061da546Spatrick 
1247061da546Spatrick     ::memcpy(dst, &fpu, sizeof(fpu));
1248061da546Spatrick     dst += sizeof(gpr);
1249061da546Spatrick 
1250061da546Spatrick     ::memcpy(dst, &exc, sizeof(exc));
1251061da546Spatrick     return true;
1252061da546Spatrick   }
1253061da546Spatrick   return false;
1254061da546Spatrick }
1255061da546Spatrick 
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)1256061da546Spatrick bool RegisterContextDarwin_arm::WriteAllRegisterValues(
1257061da546Spatrick     const lldb::DataBufferSP &data_sp) {
1258061da546Spatrick   if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
1259061da546Spatrick     const uint8_t *src = data_sp->GetBytes();
1260061da546Spatrick     ::memcpy(&gpr, src, sizeof(gpr));
1261061da546Spatrick     src += sizeof(gpr);
1262061da546Spatrick 
1263061da546Spatrick     ::memcpy(&fpu, src, sizeof(fpu));
1264061da546Spatrick     src += sizeof(gpr);
1265061da546Spatrick 
1266061da546Spatrick     ::memcpy(&exc, src, sizeof(exc));
1267061da546Spatrick     uint32_t success_count = 0;
1268061da546Spatrick     if (WriteGPR() == KERN_SUCCESS)
1269061da546Spatrick       ++success_count;
1270061da546Spatrick     if (WriteFPU() == KERN_SUCCESS)
1271061da546Spatrick       ++success_count;
1272061da546Spatrick     if (WriteEXC() == KERN_SUCCESS)
1273061da546Spatrick       ++success_count;
1274061da546Spatrick     return success_count == 3;
1275061da546Spatrick   }
1276061da546Spatrick   return false;
1277061da546Spatrick }
1278061da546Spatrick 
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t reg)1279061da546Spatrick uint32_t RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber(
1280061da546Spatrick     lldb::RegisterKind kind, uint32_t reg) {
1281061da546Spatrick   if (kind == eRegisterKindGeneric) {
1282061da546Spatrick     switch (reg) {
1283061da546Spatrick     case LLDB_REGNUM_GENERIC_PC:
1284061da546Spatrick       return gpr_pc;
1285061da546Spatrick     case LLDB_REGNUM_GENERIC_SP:
1286061da546Spatrick       return gpr_sp;
1287061da546Spatrick     case LLDB_REGNUM_GENERIC_FP:
1288061da546Spatrick       return gpr_r7;
1289061da546Spatrick     case LLDB_REGNUM_GENERIC_RA:
1290061da546Spatrick       return gpr_lr;
1291061da546Spatrick     case LLDB_REGNUM_GENERIC_FLAGS:
1292061da546Spatrick       return gpr_cpsr;
1293061da546Spatrick     default:
1294061da546Spatrick       break;
1295061da546Spatrick     }
1296061da546Spatrick   } else if (kind == eRegisterKindDWARF) {
1297061da546Spatrick     switch (reg) {
1298061da546Spatrick     case dwarf_r0:
1299061da546Spatrick       return gpr_r0;
1300061da546Spatrick     case dwarf_r1:
1301061da546Spatrick       return gpr_r1;
1302061da546Spatrick     case dwarf_r2:
1303061da546Spatrick       return gpr_r2;
1304061da546Spatrick     case dwarf_r3:
1305061da546Spatrick       return gpr_r3;
1306061da546Spatrick     case dwarf_r4:
1307061da546Spatrick       return gpr_r4;
1308061da546Spatrick     case dwarf_r5:
1309061da546Spatrick       return gpr_r5;
1310061da546Spatrick     case dwarf_r6:
1311061da546Spatrick       return gpr_r6;
1312061da546Spatrick     case dwarf_r7:
1313061da546Spatrick       return gpr_r7;
1314061da546Spatrick     case dwarf_r8:
1315061da546Spatrick       return gpr_r8;
1316061da546Spatrick     case dwarf_r9:
1317061da546Spatrick       return gpr_r9;
1318061da546Spatrick     case dwarf_r10:
1319061da546Spatrick       return gpr_r10;
1320061da546Spatrick     case dwarf_r11:
1321061da546Spatrick       return gpr_r11;
1322061da546Spatrick     case dwarf_r12:
1323061da546Spatrick       return gpr_r12;
1324061da546Spatrick     case dwarf_sp:
1325061da546Spatrick       return gpr_sp;
1326061da546Spatrick     case dwarf_lr:
1327061da546Spatrick       return gpr_lr;
1328061da546Spatrick     case dwarf_pc:
1329061da546Spatrick       return gpr_pc;
1330061da546Spatrick     case dwarf_spsr:
1331061da546Spatrick       return gpr_cpsr;
1332061da546Spatrick 
1333061da546Spatrick     case dwarf_s0:
1334061da546Spatrick       return fpu_s0;
1335061da546Spatrick     case dwarf_s1:
1336061da546Spatrick       return fpu_s1;
1337061da546Spatrick     case dwarf_s2:
1338061da546Spatrick       return fpu_s2;
1339061da546Spatrick     case dwarf_s3:
1340061da546Spatrick       return fpu_s3;
1341061da546Spatrick     case dwarf_s4:
1342061da546Spatrick       return fpu_s4;
1343061da546Spatrick     case dwarf_s5:
1344061da546Spatrick       return fpu_s5;
1345061da546Spatrick     case dwarf_s6:
1346061da546Spatrick       return fpu_s6;
1347061da546Spatrick     case dwarf_s7:
1348061da546Spatrick       return fpu_s7;
1349061da546Spatrick     case dwarf_s8:
1350061da546Spatrick       return fpu_s8;
1351061da546Spatrick     case dwarf_s9:
1352061da546Spatrick       return fpu_s9;
1353061da546Spatrick     case dwarf_s10:
1354061da546Spatrick       return fpu_s10;
1355061da546Spatrick     case dwarf_s11:
1356061da546Spatrick       return fpu_s11;
1357061da546Spatrick     case dwarf_s12:
1358061da546Spatrick       return fpu_s12;
1359061da546Spatrick     case dwarf_s13:
1360061da546Spatrick       return fpu_s13;
1361061da546Spatrick     case dwarf_s14:
1362061da546Spatrick       return fpu_s14;
1363061da546Spatrick     case dwarf_s15:
1364061da546Spatrick       return fpu_s15;
1365061da546Spatrick     case dwarf_s16:
1366061da546Spatrick       return fpu_s16;
1367061da546Spatrick     case dwarf_s17:
1368061da546Spatrick       return fpu_s17;
1369061da546Spatrick     case dwarf_s18:
1370061da546Spatrick       return fpu_s18;
1371061da546Spatrick     case dwarf_s19:
1372061da546Spatrick       return fpu_s19;
1373061da546Spatrick     case dwarf_s20:
1374061da546Spatrick       return fpu_s20;
1375061da546Spatrick     case dwarf_s21:
1376061da546Spatrick       return fpu_s21;
1377061da546Spatrick     case dwarf_s22:
1378061da546Spatrick       return fpu_s22;
1379061da546Spatrick     case dwarf_s23:
1380061da546Spatrick       return fpu_s23;
1381061da546Spatrick     case dwarf_s24:
1382061da546Spatrick       return fpu_s24;
1383061da546Spatrick     case dwarf_s25:
1384061da546Spatrick       return fpu_s25;
1385061da546Spatrick     case dwarf_s26:
1386061da546Spatrick       return fpu_s26;
1387061da546Spatrick     case dwarf_s27:
1388061da546Spatrick       return fpu_s27;
1389061da546Spatrick     case dwarf_s28:
1390061da546Spatrick       return fpu_s28;
1391061da546Spatrick     case dwarf_s29:
1392061da546Spatrick       return fpu_s29;
1393061da546Spatrick     case dwarf_s30:
1394061da546Spatrick       return fpu_s30;
1395061da546Spatrick     case dwarf_s31:
1396061da546Spatrick       return fpu_s31;
1397061da546Spatrick 
1398061da546Spatrick     default:
1399061da546Spatrick       break;
1400061da546Spatrick     }
1401061da546Spatrick   } else if (kind == eRegisterKindEHFrame) {
1402061da546Spatrick     switch (reg) {
1403061da546Spatrick     case ehframe_r0:
1404061da546Spatrick       return gpr_r0;
1405061da546Spatrick     case ehframe_r1:
1406061da546Spatrick       return gpr_r1;
1407061da546Spatrick     case ehframe_r2:
1408061da546Spatrick       return gpr_r2;
1409061da546Spatrick     case ehframe_r3:
1410061da546Spatrick       return gpr_r3;
1411061da546Spatrick     case ehframe_r4:
1412061da546Spatrick       return gpr_r4;
1413061da546Spatrick     case ehframe_r5:
1414061da546Spatrick       return gpr_r5;
1415061da546Spatrick     case ehframe_r6:
1416061da546Spatrick       return gpr_r6;
1417061da546Spatrick     case ehframe_r7:
1418061da546Spatrick       return gpr_r7;
1419061da546Spatrick     case ehframe_r8:
1420061da546Spatrick       return gpr_r8;
1421061da546Spatrick     case ehframe_r9:
1422061da546Spatrick       return gpr_r9;
1423061da546Spatrick     case ehframe_r10:
1424061da546Spatrick       return gpr_r10;
1425061da546Spatrick     case ehframe_r11:
1426061da546Spatrick       return gpr_r11;
1427061da546Spatrick     case ehframe_r12:
1428061da546Spatrick       return gpr_r12;
1429061da546Spatrick     case ehframe_sp:
1430061da546Spatrick       return gpr_sp;
1431061da546Spatrick     case ehframe_lr:
1432061da546Spatrick       return gpr_lr;
1433061da546Spatrick     case ehframe_pc:
1434061da546Spatrick       return gpr_pc;
1435061da546Spatrick     case ehframe_cpsr:
1436061da546Spatrick       return gpr_cpsr;
1437061da546Spatrick     }
1438061da546Spatrick   } else if (kind == eRegisterKindLLDB) {
1439061da546Spatrick     return reg;
1440061da546Spatrick   }
1441061da546Spatrick   return LLDB_INVALID_REGNUM;
1442061da546Spatrick }
1443061da546Spatrick 
NumSupportedHardwareBreakpoints()1444061da546Spatrick uint32_t RegisterContextDarwin_arm::NumSupportedHardwareBreakpoints() {
1445061da546Spatrick #if defined(__APPLE__) && defined(__arm__)
1446061da546Spatrick   // Set the init value to something that will let us know that we need to
1447061da546Spatrick   // autodetect how many breakpoints are supported dynamically...
1448061da546Spatrick   static uint32_t g_num_supported_hw_breakpoints = UINT32_MAX;
1449061da546Spatrick   if (g_num_supported_hw_breakpoints == UINT32_MAX) {
1450061da546Spatrick     // Set this to zero in case we can't tell if there are any HW breakpoints
1451061da546Spatrick     g_num_supported_hw_breakpoints = 0;
1452061da546Spatrick 
1453061da546Spatrick     uint32_t register_DBGDIDR;
1454061da546Spatrick 
1455061da546Spatrick     asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR));
1456061da546Spatrick     g_num_supported_hw_breakpoints = Bits32(register_DBGDIDR, 27, 24);
1457061da546Spatrick     // Zero is reserved for the BRP count, so don't increment it if it is zero
1458061da546Spatrick     if (g_num_supported_hw_breakpoints > 0)
1459061da546Spatrick       g_num_supported_hw_breakpoints++;
1460061da546Spatrick   }
1461061da546Spatrick   return g_num_supported_hw_breakpoints;
1462061da546Spatrick #else
1463061da546Spatrick   // TODO: figure out remote case here!
1464061da546Spatrick   return 6;
1465061da546Spatrick #endif
1466061da546Spatrick }
1467061da546Spatrick 
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)1468061da546Spatrick uint32_t RegisterContextDarwin_arm::SetHardwareBreakpoint(lldb::addr_t addr,
1469061da546Spatrick                                                           size_t size) {
1470061da546Spatrick   // Make sure our address isn't bogus
1471061da546Spatrick   if (addr & 1)
1472061da546Spatrick     return LLDB_INVALID_INDEX32;
1473061da546Spatrick 
1474061da546Spatrick   int kret = ReadDBG(false);
1475061da546Spatrick 
1476061da546Spatrick   if (kret == KERN_SUCCESS) {
1477061da546Spatrick     const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints();
1478061da546Spatrick     uint32_t i;
1479061da546Spatrick     for (i = 0; i < num_hw_breakpoints; ++i) {
1480061da546Spatrick       if ((dbg.bcr[i] & BCR_ENABLE) == 0)
1481061da546Spatrick         break; // We found an available hw breakpoint slot (in i)
1482061da546Spatrick     }
1483061da546Spatrick 
1484061da546Spatrick     // See if we found an available hw breakpoint slot above
1485061da546Spatrick     if (i < num_hw_breakpoints) {
1486061da546Spatrick       // Make sure bits 1:0 are clear in our address
1487061da546Spatrick       dbg.bvr[i] = addr & ~((lldb::addr_t)3);
1488061da546Spatrick 
1489061da546Spatrick       if (size == 2 || addr & 2) {
1490061da546Spatrick         uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1;
1491061da546Spatrick 
1492061da546Spatrick         // We have a thumb breakpoint
1493061da546Spatrick         // We have an ARM breakpoint
1494*f6aab3d8Srobert         dbg.bcr[i] = BCR_M_IMVA_MATCH | // Stop on address match
1495061da546Spatrick                      byte_addr_select | // Set the correct byte address select
1496061da546Spatrick                                         // so we only trigger on the correct
1497061da546Spatrick                                         // opcode
1498061da546Spatrick                      S_USER |    // Which modes should this breakpoint stop in?
1499061da546Spatrick                      BCR_ENABLE; // Enable this hardware breakpoint
1500061da546Spatrick                                  //                if (log) log->Printf
1501061da546Spatrick         //                ("RegisterContextDarwin_arm::EnableHardwareBreakpoint(
1502061da546Spatrick         //                addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x /
1503061da546Spatrick         //                0x%8.8x (Thumb)",
1504061da546Spatrick         //                        addr,
1505061da546Spatrick         //                        size,
1506061da546Spatrick         //                        i,
1507061da546Spatrick         //                        i,
1508061da546Spatrick         //                        dbg.bvr[i],
1509061da546Spatrick         //                        dbg.bcr[i]);
1510061da546Spatrick       } else if (size == 4) {
1511061da546Spatrick         // We have an ARM breakpoint
1512061da546Spatrick         dbg.bcr[i] =
1513*f6aab3d8Srobert             BCR_M_IMVA_MATCH | // Stop on address match
1514061da546Spatrick             BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA
1515061da546Spatrick             S_USER |       // Which modes should this breakpoint stop in?
1516061da546Spatrick             BCR_ENABLE;    // Enable this hardware breakpoint
1517061da546Spatrick                            //                if (log) log->Printf
1518061da546Spatrick         //                ("RegisterContextDarwin_arm::EnableHardwareBreakpoint(
1519061da546Spatrick         //                addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x /
1520061da546Spatrick         //                0x%8.8x (ARM)",
1521061da546Spatrick         //                        addr,
1522061da546Spatrick         //                        size,
1523061da546Spatrick         //                        i,
1524061da546Spatrick         //                        i,
1525061da546Spatrick         //                        dbg.bvr[i],
1526061da546Spatrick         //                        dbg.bcr[i]);
1527061da546Spatrick       }
1528061da546Spatrick 
1529061da546Spatrick       kret = WriteDBG();
1530061da546Spatrick       //            if (log) log->Printf
1531061da546Spatrick       //            ("RegisterContextDarwin_arm::EnableHardwareBreakpoint()
1532061da546Spatrick       //            WriteDBG() => 0x%8.8x.", kret);
1533061da546Spatrick 
1534061da546Spatrick       if (kret == KERN_SUCCESS)
1535061da546Spatrick         return i;
1536061da546Spatrick     }
1537061da546Spatrick     //        else
1538061da546Spatrick     //        {
1539061da546Spatrick     //            if (log) log->Printf
1540061da546Spatrick     //            ("RegisterContextDarwin_arm::EnableHardwareBreakpoint(addr =
1541061da546Spatrick     //            %8.8p, size = %u) => all hardware breakpoint resources are
1542061da546Spatrick     //            being used.", addr, size);
1543061da546Spatrick     //        }
1544061da546Spatrick   }
1545061da546Spatrick 
1546061da546Spatrick   return LLDB_INVALID_INDEX32;
1547061da546Spatrick }
1548061da546Spatrick 
ClearHardwareBreakpoint(uint32_t hw_index)1549061da546Spatrick bool RegisterContextDarwin_arm::ClearHardwareBreakpoint(uint32_t hw_index) {
1550061da546Spatrick   int kret = ReadDBG(false);
1551061da546Spatrick 
1552061da546Spatrick   const uint32_t num_hw_points = NumSupportedHardwareBreakpoints();
1553061da546Spatrick   if (kret == KERN_SUCCESS) {
1554061da546Spatrick     if (hw_index < num_hw_points) {
1555061da546Spatrick       dbg.bcr[hw_index] = 0;
1556061da546Spatrick       //            if (log) log->Printf
1557061da546Spatrick       //            ("RegisterContextDarwin_arm::SetHardwareBreakpoint( %u ) -
1558061da546Spatrick       //            BVR%u = 0x%8.8x  BCR%u = 0x%8.8x",
1559061da546Spatrick       //                    hw_index,
1560061da546Spatrick       //                    hw_index,
1561061da546Spatrick       //                    dbg.bvr[hw_index],
1562061da546Spatrick       //                    hw_index,
1563061da546Spatrick       //                    dbg.bcr[hw_index]);
1564061da546Spatrick 
1565061da546Spatrick       kret = WriteDBG();
1566061da546Spatrick 
1567061da546Spatrick       if (kret == KERN_SUCCESS)
1568061da546Spatrick         return true;
1569061da546Spatrick     }
1570061da546Spatrick   }
1571061da546Spatrick   return false;
1572061da546Spatrick }
1573061da546Spatrick 
NumSupportedHardwareWatchpoints()1574061da546Spatrick uint32_t RegisterContextDarwin_arm::NumSupportedHardwareWatchpoints() {
1575061da546Spatrick #if defined(__APPLE__) && defined(__arm__)
1576061da546Spatrick   // Set the init value to something that will let us know that we need to
1577061da546Spatrick   // autodetect how many watchpoints are supported dynamically...
1578061da546Spatrick   static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
1579061da546Spatrick   if (g_num_supported_hw_watchpoints == UINT32_MAX) {
1580061da546Spatrick     // Set this to zero in case we can't tell if there are any HW breakpoints
1581061da546Spatrick     g_num_supported_hw_watchpoints = 0;
1582061da546Spatrick 
1583061da546Spatrick     uint32_t register_DBGDIDR;
1584061da546Spatrick     asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR));
1585061da546Spatrick     g_num_supported_hw_watchpoints = Bits32(register_DBGDIDR, 31, 28) + 1;
1586061da546Spatrick   }
1587061da546Spatrick   return g_num_supported_hw_watchpoints;
1588061da546Spatrick #else
1589061da546Spatrick   // TODO: figure out remote case here!
1590061da546Spatrick   return 2;
1591061da546Spatrick #endif
1592061da546Spatrick }
1593061da546Spatrick 
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,bool read,bool write)1594061da546Spatrick uint32_t RegisterContextDarwin_arm::SetHardwareWatchpoint(lldb::addr_t addr,
1595061da546Spatrick                                                           size_t size,
1596061da546Spatrick                                                           bool read,
1597061da546Spatrick                                                           bool write) {
1598061da546Spatrick   const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
1599061da546Spatrick 
1600061da546Spatrick   // Can't watch zero bytes
1601061da546Spatrick   if (size == 0)
1602061da546Spatrick     return LLDB_INVALID_INDEX32;
1603061da546Spatrick 
1604061da546Spatrick   // We must watch for either read or write
1605061da546Spatrick   if (!read && !write)
1606061da546Spatrick     return LLDB_INVALID_INDEX32;
1607061da546Spatrick 
1608061da546Spatrick   // Can't watch more than 4 bytes per WVR/WCR pair
1609061da546Spatrick   if (size > 4)
1610061da546Spatrick     return LLDB_INVALID_INDEX32;
1611061da546Spatrick 
1612061da546Spatrick   // We can only watch up to four bytes that follow a 4 byte aligned address
1613061da546Spatrick   // per watchpoint register pair. Since we have at most so we can only watch
1614061da546Spatrick   // until the next 4 byte boundary and we need to make sure we can properly
1615061da546Spatrick   // encode this.
1616061da546Spatrick   uint32_t addr_word_offset = addr % 4;
1617061da546Spatrick   //    if (log) log->Printf
1618061da546Spatrick   //    ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() -
1619061da546Spatrick   //    addr_word_offset = 0x%8.8x", addr_word_offset);
1620061da546Spatrick 
1621061da546Spatrick   uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
1622061da546Spatrick   //    if (log) log->Printf
1623061da546Spatrick   //    ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - byte_mask =
1624061da546Spatrick   //    0x%8.8x", byte_mask);
1625061da546Spatrick   if (byte_mask > 0xfu)
1626061da546Spatrick     return LLDB_INVALID_INDEX32;
1627061da546Spatrick 
1628061da546Spatrick   // Read the debug state
1629061da546Spatrick   int kret = ReadDBG(false);
1630061da546Spatrick 
1631061da546Spatrick   if (kret == KERN_SUCCESS) {
1632061da546Spatrick     // Check to make sure we have the needed hardware support
1633061da546Spatrick     uint32_t i = 0;
1634061da546Spatrick 
1635061da546Spatrick     for (i = 0; i < num_hw_watchpoints; ++i) {
1636061da546Spatrick       if ((dbg.wcr[i] & WCR_ENABLE) == 0)
1637061da546Spatrick         break; // We found an available hw breakpoint slot (in i)
1638061da546Spatrick     }
1639061da546Spatrick 
1640061da546Spatrick     // See if we found an available hw breakpoint slot above
1641061da546Spatrick     if (i < num_hw_watchpoints) {
1642061da546Spatrick       // Make the byte_mask into a valid Byte Address Select mask
1643061da546Spatrick       uint32_t byte_address_select = byte_mask << 5;
1644061da546Spatrick       // Make sure bits 1:0 are clear in our address
1645061da546Spatrick       dbg.wvr[i] = addr & ~((lldb::addr_t)3);
1646061da546Spatrick       dbg.wcr[i] = byte_address_select |     // Which bytes that follow the IMVA
1647061da546Spatrick                                              // that we will watch
1648061da546Spatrick                    S_USER |                  // Stop only in user mode
1649061da546Spatrick                    (read ? WCR_LOAD : 0) |   // Stop on read access?
1650061da546Spatrick                    (write ? WCR_STORE : 0) | // Stop on write access?
1651061da546Spatrick                    WCR_ENABLE;               // Enable this watchpoint;
1652061da546Spatrick 
1653061da546Spatrick       kret = WriteDBG();
1654061da546Spatrick       //            if (log) log->Printf
1655061da546Spatrick       //            ("RegisterContextDarwin_arm::EnableHardwareWatchpoint()
1656061da546Spatrick       //            WriteDBG() => 0x%8.8x.", kret);
1657061da546Spatrick 
1658061da546Spatrick       if (kret == KERN_SUCCESS)
1659061da546Spatrick         return i;
1660061da546Spatrick     } else {
1661061da546Spatrick       //            if (log) log->Printf
1662061da546Spatrick       //            ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(): All
1663061da546Spatrick       //            hardware resources (%u) are in use.", num_hw_watchpoints);
1664061da546Spatrick     }
1665061da546Spatrick   }
1666061da546Spatrick   return LLDB_INVALID_INDEX32;
1667061da546Spatrick }
1668061da546Spatrick 
ClearHardwareWatchpoint(uint32_t hw_index)1669061da546Spatrick bool RegisterContextDarwin_arm::ClearHardwareWatchpoint(uint32_t hw_index) {
1670061da546Spatrick   int kret = ReadDBG(false);
1671061da546Spatrick 
1672061da546Spatrick   const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
1673061da546Spatrick   if (kret == KERN_SUCCESS) {
1674061da546Spatrick     if (hw_index < num_hw_points) {
1675061da546Spatrick       dbg.wcr[hw_index] = 0;
1676061da546Spatrick       //            if (log) log->Printf
1677061da546Spatrick       //            ("RegisterContextDarwin_arm::ClearHardwareWatchpoint( %u ) -
1678061da546Spatrick       //            WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
1679061da546Spatrick       //                    hw_index,
1680061da546Spatrick       //                    hw_index,
1681061da546Spatrick       //                    dbg.wvr[hw_index],
1682061da546Spatrick       //                    hw_index,
1683061da546Spatrick       //                    dbg.wcr[hw_index]);
1684061da546Spatrick 
1685061da546Spatrick       kret = WriteDBG();
1686061da546Spatrick 
1687061da546Spatrick       if (kret == KERN_SUCCESS)
1688061da546Spatrick         return true;
1689061da546Spatrick     }
1690061da546Spatrick   }
1691061da546Spatrick   return false;
1692061da546Spatrick }
1693