1 //===-- RegisterContextDarwin_arm.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_arm.h"
13 
14 // C Includes
15 #include <mach/mach_types.h>
16 #include <mach/thread_act.h>
17 
18 // C++ Includes
19 // Other libraries and framework includes
20 #include "lldb/Core/DataBufferHeap.h"
21 #include "lldb/Core/DataExtractor.h"
22 #include "lldb/Core/Log.h"
23 #include "lldb/Core/RegisterValue.h"
24 #include "lldb/Core/Scalar.h"
25 #include "lldb/Host/Endian.h"
26 
27 // Project includes
28 #include "ARM_GCC_Registers.h"
29 #include "ARM_DWARF_Registers.h"
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 
34 enum
35 {
36     gpr_r0 = 0,
37     gpr_r1,
38     gpr_r2,
39     gpr_r3,
40     gpr_r4,
41     gpr_r5,
42     gpr_r6,
43     gpr_r7,
44     gpr_r8,
45     gpr_r9,
46     gpr_r10,
47     gpr_r11,
48     gpr_r12,
49     gpr_r13, gpr_sp = gpr_r13,
50     gpr_r14, gpr_lr = gpr_r14,
51     gpr_r15, gpr_pc = gpr_r15,
52     gpr_cpsr,
53 
54     fpu_s0,
55     fpu_s1,
56     fpu_s2,
57     fpu_s3,
58     fpu_s4,
59     fpu_s5,
60     fpu_s6,
61     fpu_s7,
62     fpu_s8,
63     fpu_s9,
64     fpu_s10,
65     fpu_s11,
66     fpu_s12,
67     fpu_s13,
68     fpu_s14,
69     fpu_s15,
70     fpu_s16,
71     fpu_s17,
72     fpu_s18,
73     fpu_s19,
74     fpu_s20,
75     fpu_s21,
76     fpu_s22,
77     fpu_s23,
78     fpu_s24,
79     fpu_s25,
80     fpu_s26,
81     fpu_s27,
82     fpu_s28,
83     fpu_s29,
84     fpu_s30,
85     fpu_s31,
86     fpu_fpscr,
87 
88     exc_exception,
89     exc_fsr,
90     exc_far,
91 
92     dbg_bvr0,
93     dbg_bvr1,
94     dbg_bvr2,
95     dbg_bvr3,
96     dbg_bvr4,
97     dbg_bvr5,
98     dbg_bvr6,
99     dbg_bvr7,
100     dbg_bvr8,
101     dbg_bvr9,
102     dbg_bvr10,
103     dbg_bvr11,
104     dbg_bvr12,
105     dbg_bvr13,
106     dbg_bvr14,
107     dbg_bvr15,
108 
109     dbg_bcr0,
110     dbg_bcr1,
111     dbg_bcr2,
112     dbg_bcr3,
113     dbg_bcr4,
114     dbg_bcr5,
115     dbg_bcr6,
116     dbg_bcr7,
117     dbg_bcr8,
118     dbg_bcr9,
119     dbg_bcr10,
120     dbg_bcr11,
121     dbg_bcr12,
122     dbg_bcr13,
123     dbg_bcr14,
124     dbg_bcr15,
125 
126     dbg_wvr0,
127     dbg_wvr1,
128     dbg_wvr2,
129     dbg_wvr3,
130     dbg_wvr4,
131     dbg_wvr5,
132     dbg_wvr6,
133     dbg_wvr7,
134     dbg_wvr8,
135     dbg_wvr9,
136     dbg_wvr10,
137     dbg_wvr11,
138     dbg_wvr12,
139     dbg_wvr13,
140     dbg_wvr14,
141     dbg_wvr15,
142 
143     dbg_wcr0,
144     dbg_wcr1,
145     dbg_wcr2,
146     dbg_wcr3,
147     dbg_wcr4,
148     dbg_wcr5,
149     dbg_wcr6,
150     dbg_wcr7,
151     dbg_wcr8,
152     dbg_wcr9,
153     dbg_wcr10,
154     dbg_wcr11,
155     dbg_wcr12,
156     dbg_wcr13,
157     dbg_wcr14,
158     dbg_wcr15,
159 
160     k_num_registers
161 };
162 
163 
164 RegisterContextDarwin_arm::RegisterContextDarwin_arm(Thread &thread, uint32_t concrete_frame_idx) :
165     RegisterContext(thread, concrete_frame_idx),
166     gpr(),
167     fpu(),
168     exc()
169 {
170     uint32_t i;
171     for (i=0; i<kNumErrors; i++)
172     {
173         gpr_errs[i] = -1;
174         fpu_errs[i] = -1;
175         exc_errs[i] = -1;
176     }
177 }
178 
179 RegisterContextDarwin_arm::~RegisterContextDarwin_arm()
180 {
181 }
182 
183 
184 #define GPR_OFFSET(idx) ((idx) * 4)
185 #define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR))
186 #define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU))
187 #define DBG_OFFSET(reg) (offsetof (RegisterContextDarwin_arm::DBG, reg) + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC))
188 
189 #define DEFINE_DBG(reg, i)  #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }
190 #define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC))
191 
192 static RegisterInfo g_register_infos[] = {
193 // General purpose registers
194 //  NAME        ALT     SZ  OFFSET              ENCODING        FORMAT          COMPILER                DWARF               GENERIC                     GDB                     LLDB NATIVE
195 //  ======      ======= ==  =============       =============   ============    ===============         ===============     =========================   =====================   =============
196 {   "r0",       NULL,   4,  GPR_OFFSET(0),      eEncodingUint,  eFormatHex,     { gcc_r0,               dwarf_r0,           LLDB_INVALID_REGNUM,        gdb_arm_r0,             gpr_r0      }},
197 {   "r1",       NULL,   4,  GPR_OFFSET(1),      eEncodingUint,  eFormatHex,     { gcc_r1,               dwarf_r1,           LLDB_INVALID_REGNUM,        gdb_arm_r1,             gpr_r1      }},
198 {   "r2",       NULL,   4,  GPR_OFFSET(2),      eEncodingUint,  eFormatHex,     { gcc_r2,               dwarf_r2,           LLDB_INVALID_REGNUM,        gdb_arm_r2,             gpr_r2      }},
199 {   "r3",       NULL,   4,  GPR_OFFSET(3),      eEncodingUint,  eFormatHex,     { gcc_r3,               dwarf_r3,           LLDB_INVALID_REGNUM,        gdb_arm_r3,             gpr_r3      }},
200 {   "r4",       NULL,   4,  GPR_OFFSET(4),      eEncodingUint,  eFormatHex,     { gcc_r4,               dwarf_r4,           LLDB_INVALID_REGNUM,        gdb_arm_r4,             gpr_r4      }},
201 {   "r5",       NULL,   4,  GPR_OFFSET(5),      eEncodingUint,  eFormatHex,     { gcc_r5,               dwarf_r5,           LLDB_INVALID_REGNUM,        gdb_arm_r5,             gpr_r5      }},
202 {   "r6",       NULL,   4,  GPR_OFFSET(6),      eEncodingUint,  eFormatHex,     { gcc_r6,               dwarf_r6,           LLDB_INVALID_REGNUM,        gdb_arm_r6,             gpr_r6      }},
203 {   "r7",       NULL,   4,  GPR_OFFSET(7),      eEncodingUint,  eFormatHex,     { gcc_r7,               dwarf_r7,           LLDB_REGNUM_GENERIC_FP,     gdb_arm_r7,             gpr_r7      }},
204 {   "r8",       NULL,   4,  GPR_OFFSET(8),      eEncodingUint,  eFormatHex,     { gcc_r8,               dwarf_r8,           LLDB_INVALID_REGNUM,        gdb_arm_r8,             gpr_r8      }},
205 {   "r9",       NULL,   4,  GPR_OFFSET(9),      eEncodingUint,  eFormatHex,     { gcc_r9,               dwarf_r9,           LLDB_INVALID_REGNUM,        gdb_arm_r9,             gpr_r9      }},
206 {   "r10",      NULL,   4,  GPR_OFFSET(10),     eEncodingUint,  eFormatHex,     { gcc_r10,              dwarf_r10,          LLDB_INVALID_REGNUM,        gdb_arm_r10,            gpr_r10     }},
207 {   "r11",      NULL,   4,  GPR_OFFSET(11),     eEncodingUint,  eFormatHex,     { gcc_r11,              dwarf_r11,          LLDB_INVALID_REGNUM,        gdb_arm_r11,            gpr_r11     }},
208 {   "r12",      NULL,   4,  GPR_OFFSET(12),     eEncodingUint,  eFormatHex,     { gcc_r12,              dwarf_r12,          LLDB_INVALID_REGNUM,        gdb_arm_r12,            gpr_r12     }},
209 {   "sp",       "r13",  4,  GPR_OFFSET(13),     eEncodingUint,  eFormatHex,     { gcc_sp,               dwarf_sp,           LLDB_REGNUM_GENERIC_SP,     gdb_arm_sp,             gpr_sp      }},
210 {   "lr",       "r14",  4,  GPR_OFFSET(14),     eEncodingUint,  eFormatHex,     { gcc_lr,               dwarf_lr,           LLDB_REGNUM_GENERIC_RA,     gdb_arm_lr,             gpr_lr      }},
211 {   "pc",       "r15",  4,  GPR_OFFSET(15),     eEncodingUint,  eFormatHex,     { gcc_pc,               dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     gdb_arm_pc,             gpr_pc      }},
212 {   "cpsr",     "psr",  4,  GPR_OFFSET(16),     eEncodingUint,  eFormatHex,     { gcc_cpsr,             dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  gdb_arm_cpsr,           gpr_cpsr    }},
213 
214 {   "s0",       NULL,   4,  FPU_OFFSET(0),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM,        gdb_arm_s0,             fpu_s0      }},
215 {   "s1",       NULL,   4,  FPU_OFFSET(1),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM,        gdb_arm_s1,             fpu_s1      }},
216 {   "s2",       NULL,   4,  FPU_OFFSET(2),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM,        gdb_arm_s2,             fpu_s2      }},
217 {   "s3",       NULL,   4,  FPU_OFFSET(3),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM,        gdb_arm_s3,             fpu_s3      }},
218 {   "s4",       NULL,   4,  FPU_OFFSET(4),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM,        gdb_arm_s4,             fpu_s4      }},
219 {   "s5",       NULL,   4,  FPU_OFFSET(5),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM,        gdb_arm_s5,             fpu_s5      }},
220 {   "s6",       NULL,   4,  FPU_OFFSET(6),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM,        gdb_arm_s6,             fpu_s6      }},
221 {   "s7",       NULL,   4,  FPU_OFFSET(7),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM,        gdb_arm_s7,             fpu_s7      }},
222 {   "s8",       NULL,   4,  FPU_OFFSET(8),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM,        gdb_arm_s8,             fpu_s8      }},
223 {   "s9",       NULL,   4,  FPU_OFFSET(9),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM,        gdb_arm_s9,             fpu_s9      }},
224 {   "s10",      NULL,   4,  FPU_OFFSET(10),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM,        gdb_arm_s10,            fpu_s10     }},
225 {   "s11",      NULL,   4,  FPU_OFFSET(11),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM,        gdb_arm_s11,            fpu_s11     }},
226 {   "s12",      NULL,   4,  FPU_OFFSET(12),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM,        gdb_arm_s12,            fpu_s12     }},
227 {   "s13",      NULL,   4,  FPU_OFFSET(13),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM,        gdb_arm_s13,            fpu_s13     }},
228 {   "s14",      NULL,   4,  FPU_OFFSET(14),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM,        gdb_arm_s14,            fpu_s14     }},
229 {   "s15",      NULL,   4,  FPU_OFFSET(15),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM,        gdb_arm_s15,            fpu_s15     }},
230 {   "s16",      NULL,   4,  FPU_OFFSET(16),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM,        gdb_arm_s16,            fpu_s16     }},
231 {   "s17",      NULL,   4,  FPU_OFFSET(17),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM,        gdb_arm_s17,            fpu_s17     }},
232 {   "s18",      NULL,   4,  FPU_OFFSET(18),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM,        gdb_arm_s18,            fpu_s18     }},
233 {   "s19",      NULL,   4,  FPU_OFFSET(19),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM,        gdb_arm_s19,            fpu_s19     }},
234 {   "s20",      NULL,   4,  FPU_OFFSET(20),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM,        gdb_arm_s20,            fpu_s20     }},
235 {   "s21",      NULL,   4,  FPU_OFFSET(21),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM,        gdb_arm_s21,            fpu_s21     }},
236 {   "s22",      NULL,   4,  FPU_OFFSET(22),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM,        gdb_arm_s22,            fpu_s22     }},
237 {   "s23",      NULL,   4,  FPU_OFFSET(23),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM,        gdb_arm_s23,            fpu_s23     }},
238 {   "s24",      NULL,   4,  FPU_OFFSET(24),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM,        gdb_arm_s24,            fpu_s24     }},
239 {   "s25",      NULL,   4,  FPU_OFFSET(25),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM,        gdb_arm_s25,            fpu_s25     }},
240 {   "s26",      NULL,   4,  FPU_OFFSET(26),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM,        gdb_arm_s26,            fpu_s26     }},
241 {   "s27",      NULL,   4,  FPU_OFFSET(27),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM,        gdb_arm_s27,            fpu_s27     }},
242 {   "s28",      NULL,   4,  FPU_OFFSET(28),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM,        gdb_arm_s28,            fpu_s28     }},
243 {   "s29",      NULL,   4,  FPU_OFFSET(29),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM,        gdb_arm_s29,            fpu_s29     }},
244 {   "s30",      NULL,   4,  FPU_OFFSET(30),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM,        gdb_arm_s30,            fpu_s30     }},
245 {   "s31",      NULL,   4,  FPU_OFFSET(31),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM,        gdb_arm_s31,            fpu_s31     }},
246 {   "fpscr",    NULL,   4,  FPU_OFFSET(32),     eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        gdb_arm_fpscr,          fpu_fpscr   }},
247 
248 {   "exception",NULL,   4,  EXC_OFFSET(0),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_exception }},
249 {   "fsr",      NULL,   4,  EXC_OFFSET(1),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_fsr       }},
250 {   "far",      NULL,   4,  EXC_OFFSET(2),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_far       }},
251 
252 {   DEFINE_DBG (bvr, 0) },
253 {   DEFINE_DBG (bvr, 1) },
254 {   DEFINE_DBG (bvr, 2) },
255 {   DEFINE_DBG (bvr, 3) },
256 {   DEFINE_DBG (bvr, 4) },
257 {   DEFINE_DBG (bvr, 5) },
258 {   DEFINE_DBG (bvr, 6) },
259 {   DEFINE_DBG (bvr, 7) },
260 {   DEFINE_DBG (bvr, 8) },
261 {   DEFINE_DBG (bvr, 9) },
262 {   DEFINE_DBG (bvr, 10) },
263 {   DEFINE_DBG (bvr, 11) },
264 {   DEFINE_DBG (bvr, 12) },
265 {   DEFINE_DBG (bvr, 13) },
266 {   DEFINE_DBG (bvr, 14) },
267 {   DEFINE_DBG (bvr, 15) },
268 
269 {   DEFINE_DBG (bcr, 0) },
270 {   DEFINE_DBG (bcr, 1) },
271 {   DEFINE_DBG (bcr, 2) },
272 {   DEFINE_DBG (bcr, 3) },
273 {   DEFINE_DBG (bcr, 4) },
274 {   DEFINE_DBG (bcr, 5) },
275 {   DEFINE_DBG (bcr, 6) },
276 {   DEFINE_DBG (bcr, 7) },
277 {   DEFINE_DBG (bcr, 8) },
278 {   DEFINE_DBG (bcr, 9) },
279 {   DEFINE_DBG (bcr, 10) },
280 {   DEFINE_DBG (bcr, 11) },
281 {   DEFINE_DBG (bcr, 12) },
282 {   DEFINE_DBG (bcr, 13) },
283 {   DEFINE_DBG (bcr, 14) },
284 {   DEFINE_DBG (bcr, 15) },
285 
286 {   DEFINE_DBG (wvr, 0) },
287 {   DEFINE_DBG (wvr, 1) },
288 {   DEFINE_DBG (wvr, 2) },
289 {   DEFINE_DBG (wvr, 3) },
290 {   DEFINE_DBG (wvr, 4) },
291 {   DEFINE_DBG (wvr, 5) },
292 {   DEFINE_DBG (wvr, 6) },
293 {   DEFINE_DBG (wvr, 7) },
294 {   DEFINE_DBG (wvr, 8) },
295 {   DEFINE_DBG (wvr, 9) },
296 {   DEFINE_DBG (wvr, 10) },
297 {   DEFINE_DBG (wvr, 11) },
298 {   DEFINE_DBG (wvr, 12) },
299 {   DEFINE_DBG (wvr, 13) },
300 {   DEFINE_DBG (wvr, 14) },
301 {   DEFINE_DBG (wvr, 15) },
302 
303 {   DEFINE_DBG (wcr, 0) },
304 {   DEFINE_DBG (wcr, 1) },
305 {   DEFINE_DBG (wcr, 2) },
306 {   DEFINE_DBG (wcr, 3) },
307 {   DEFINE_DBG (wcr, 4) },
308 {   DEFINE_DBG (wcr, 5) },
309 {   DEFINE_DBG (wcr, 6) },
310 {   DEFINE_DBG (wcr, 7) },
311 {   DEFINE_DBG (wcr, 8) },
312 {   DEFINE_DBG (wcr, 9) },
313 {   DEFINE_DBG (wcr, 10) },
314 {   DEFINE_DBG (wcr, 11) },
315 {   DEFINE_DBG (wcr, 12) },
316 {   DEFINE_DBG (wcr, 13) },
317 {   DEFINE_DBG (wcr, 14) },
318 {   DEFINE_DBG (wcr, 15) }
319 };
320 
321 // General purpose registers
322 static uint32_t
323 g_gpr_regnums[] =
324 {
325     gpr_r0,
326     gpr_r1,
327     gpr_r2,
328     gpr_r3,
329     gpr_r4,
330     gpr_r5,
331     gpr_r6,
332     gpr_r7,
333     gpr_r8,
334     gpr_r9,
335     gpr_r10,
336     gpr_r11,
337     gpr_r12,
338     gpr_sp,
339     gpr_lr,
340     gpr_pc,
341     gpr_cpsr
342 };
343 
344 // Floating point registers
345 static uint32_t
346 g_fpu_regnums[] =
347 {
348     fpu_s0,
349     fpu_s1,
350     fpu_s2,
351     fpu_s3,
352     fpu_s4,
353     fpu_s5,
354     fpu_s6,
355     fpu_s7,
356     fpu_s8,
357     fpu_s9,
358     fpu_s10,
359     fpu_s11,
360     fpu_s12,
361     fpu_s13,
362     fpu_s14,
363     fpu_s15,
364     fpu_s16,
365     fpu_s17,
366     fpu_s18,
367     fpu_s19,
368     fpu_s20,
369     fpu_s21,
370     fpu_s22,
371     fpu_s23,
372     fpu_s24,
373     fpu_s25,
374     fpu_s26,
375     fpu_s27,
376     fpu_s28,
377     fpu_s29,
378     fpu_s30,
379     fpu_s31,
380     fpu_fpscr,
381 };
382 
383 // Exception registers
384 
385 static uint32_t
386 g_exc_regnums[] =
387 {
388     exc_exception,
389     exc_fsr,
390     exc_far,
391 };
392 
393 static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
394 
395 void
396 RegisterContextDarwin_arm::InvalidateAllRegisters ()
397 {
398     InvalidateAllRegisterStates();
399 }
400 
401 
402 size_t
403 RegisterContextDarwin_arm::GetRegisterCount ()
404 {
405     assert(k_num_register_infos == k_num_registers);
406     return k_num_registers;
407 }
408 
409 const RegisterInfo *
410 RegisterContextDarwin_arm::GetRegisterInfoAtIndex (uint32_t reg)
411 {
412     assert(k_num_register_infos == k_num_registers);
413     if (reg < k_num_registers)
414         return &g_register_infos[reg];
415     return NULL;
416 }
417 
418 size_t
419 RegisterContextDarwin_arm::GetRegisterInfosCount ()
420 {
421     return k_num_register_infos;
422 }
423 
424 const RegisterInfo *
425 RegisterContextDarwin_arm::GetRegisterInfos ()
426 {
427     return g_register_infos;
428 }
429 
430 
431 // Number of registers in each register set
432 const size_t k_num_gpr_registers = sizeof(g_gpr_regnums) / sizeof(uint32_t);
433 const size_t k_num_fpu_registers = sizeof(g_fpu_regnums) / sizeof(uint32_t);
434 const size_t k_num_exc_registers = sizeof(g_exc_regnums) / sizeof(uint32_t);
435 
436 //----------------------------------------------------------------------
437 // Register set definitions. The first definitions at register set index
438 // of zero is for all registers, followed by other registers sets. The
439 // register information for the all register set need not be filled in.
440 //----------------------------------------------------------------------
441 static const RegisterSet g_reg_sets[] =
442 {
443     { "General Purpose Registers",  "gpr",  k_num_gpr_registers,    g_gpr_regnums,      },
444     { "Floating Point Registers",   "fpu",  k_num_fpu_registers,    g_fpu_regnums       },
445     { "Exception State Registers",  "exc",  k_num_exc_registers,    g_exc_regnums       }
446 };
447 
448 const size_t k_num_regsets = sizeof(g_reg_sets) / sizeof(RegisterSet);
449 
450 
451 size_t
452 RegisterContextDarwin_arm::GetRegisterSetCount ()
453 {
454     return k_num_regsets;
455 }
456 
457 const RegisterSet *
458 RegisterContextDarwin_arm::GetRegisterSet (uint32_t reg_set)
459 {
460     if (reg_set < k_num_regsets)
461         return &g_reg_sets[reg_set];
462     return NULL;
463 }
464 
465 
466 //----------------------------------------------------------------------
467 // Register information defintions for 32 bit i386.
468 //----------------------------------------------------------------------
469 int
470 RegisterContextDarwin_arm::GetSetForNativeRegNum (int reg)
471 {
472     if (reg < fpu_s0)
473         return GPRRegSet;
474     else if (reg < exc_exception)
475         return FPURegSet;
476     else if (reg < k_num_registers)
477         return EXCRegSet;
478     return -1;
479 }
480 
481 int
482 RegisterContextDarwin_arm::ReadGPR (bool force)
483 {
484     int set = GPRRegSet;
485     if (force || !RegisterSetIsCached(set))
486     {
487         SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
488     }
489     return GetError(GPRRegSet, Read);
490 }
491 
492 int
493 RegisterContextDarwin_arm::ReadFPU (bool force)
494 {
495     int set = FPURegSet;
496     if (force || !RegisterSetIsCached(set))
497     {
498         SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
499     }
500     return GetError(FPURegSet, Read);
501 }
502 
503 int
504 RegisterContextDarwin_arm::ReadEXC (bool force)
505 {
506     int set = EXCRegSet;
507     if (force || !RegisterSetIsCached(set))
508     {
509         SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
510     }
511     return GetError(EXCRegSet, Read);
512 }
513 
514 int
515 RegisterContextDarwin_arm::ReadDBG (bool force)
516 {
517     int set = DBGRegSet;
518     if (force || !RegisterSetIsCached(set))
519     {
520         SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));
521     }
522     return GetError(DBGRegSet, Read);
523 }
524 
525 int
526 RegisterContextDarwin_arm::WriteGPR ()
527 {
528     int set = GPRRegSet;
529     if (!RegisterSetIsCached(set))
530     {
531         SetError (set, Write, -1);
532         return KERN_INVALID_ARGUMENT;
533     }
534     SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr));
535     SetError (set, Read, -1);
536     return GetError(GPRRegSet, Write);
537 }
538 
539 int
540 RegisterContextDarwin_arm::WriteFPU ()
541 {
542     int set = FPURegSet;
543     if (!RegisterSetIsCached(set))
544     {
545         SetError (set, Write, -1);
546         return KERN_INVALID_ARGUMENT;
547     }
548     SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu));
549     SetError (set, Read, -1);
550     return GetError(FPURegSet, Write);
551 }
552 
553 int
554 RegisterContextDarwin_arm::WriteEXC ()
555 {
556     int set = EXCRegSet;
557     if (!RegisterSetIsCached(set))
558     {
559         SetError (set, Write, -1);
560         return KERN_INVALID_ARGUMENT;
561     }
562     SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc));
563     SetError (set, Read, -1);
564     return GetError(EXCRegSet, Write);
565 }
566 
567 int
568 RegisterContextDarwin_arm::WriteDBG ()
569 {
570     int set = DBGRegSet;
571     if (!RegisterSetIsCached(set))
572     {
573         SetError (set, Write, -1);
574         return KERN_INVALID_ARGUMENT;
575     }
576     SetError (set, Write, DoWriteDBG(GetThreadID(), set, dbg));
577     SetError (set, Read, -1);
578     return GetError(DBGRegSet, Write);
579 }
580 
581 
582 int
583 RegisterContextDarwin_arm::ReadRegisterSet (uint32_t set, bool force)
584 {
585     switch (set)
586     {
587     case GPRRegSet:    return ReadGPR(force);
588     case FPURegSet:    return ReadFPU(force);
589     case EXCRegSet:    return ReadEXC(force);
590     case DBGRegSet:    return ReadDBG(force);
591     default: break;
592     }
593     return KERN_INVALID_ARGUMENT;
594 }
595 
596 int
597 RegisterContextDarwin_arm::WriteRegisterSet (uint32_t set)
598 {
599     // Make sure we have a valid context to set.
600     if (RegisterSetIsCached(set))
601     {
602         switch (set)
603         {
604         case GPRRegSet:    return WriteGPR();
605         case FPURegSet:    return WriteFPU();
606         case EXCRegSet:    return WriteEXC();
607         case DBGRegSet:    return WriteDBG();
608         default: break;
609         }
610     }
611     return KERN_INVALID_ARGUMENT;
612 }
613 
614 void
615 RegisterContextDarwin_arm::LogDBGRegisters (Log *log, const DBG& dbg)
616 {
617     if (log)
618     {
619         for (uint32_t i=0; i<16; i++)
620             log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }",
621                 i, i, dbg.bvr[i], dbg.bcr[i],
622                 i, i, dbg.wvr[i], dbg.wcr[i]);
623     }
624 }
625 
626 
627 bool
628 RegisterContextDarwin_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
629 {
630     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
631     int set = RegisterContextDarwin_arm::GetSetForNativeRegNum (reg);
632 
633     if (set == -1)
634         return false;
635 
636     if (ReadRegisterSet(set, false) != KERN_SUCCESS)
637         return false;
638 
639     switch (reg)
640     {
641     case gpr_r0:
642     case gpr_r1:
643     case gpr_r2:
644     case gpr_r3:
645     case gpr_r4:
646     case gpr_r5:
647     case gpr_r6:
648     case gpr_r7:
649     case gpr_r8:
650     case gpr_r9:
651     case gpr_r10:
652     case gpr_r11:
653     case gpr_r12:
654     case gpr_sp:
655     case gpr_lr:
656     case gpr_pc:
657     case gpr_cpsr:
658         value.SetUInt32 (gpr.r[reg - gpr_r0]);
659         break;
660 
661     case fpu_s0:
662     case fpu_s1:
663     case fpu_s2:
664     case fpu_s3:
665     case fpu_s4:
666     case fpu_s5:
667     case fpu_s6:
668     case fpu_s7:
669     case fpu_s8:
670     case fpu_s9:
671     case fpu_s10:
672     case fpu_s11:
673     case fpu_s12:
674     case fpu_s13:
675     case fpu_s14:
676     case fpu_s15:
677     case fpu_s16:
678     case fpu_s17:
679     case fpu_s18:
680     case fpu_s19:
681     case fpu_s20:
682     case fpu_s21:
683     case fpu_s22:
684     case fpu_s23:
685     case fpu_s24:
686     case fpu_s25:
687     case fpu_s26:
688     case fpu_s27:
689     case fpu_s28:
690     case fpu_s29:
691     case fpu_s30:
692     case fpu_s31:
693         value.SetUInt32 (fpu.floats.s[reg], RegisterValue::eTypeFloat);
694         break;
695 
696     case fpu_fpscr:
697         value.SetUInt32 (fpu.fpscr);
698         break;
699 
700     case exc_exception:
701         value.SetUInt32 (exc.exception);
702         break;
703     case exc_fsr:
704         value.SetUInt32 (exc.fsr);
705         break;
706     case exc_far:
707         value.SetUInt32 (exc.far);
708         break;
709 
710     default:
711         value.SetValueToInvalid();
712         return false;
713 
714     }
715     return true;
716 }
717 
718 
719 bool
720 RegisterContextDarwin_arm::WriteRegister (const RegisterInfo *reg_info,
721                                         const RegisterValue &value)
722 {
723     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
724     int set = GetSetForNativeRegNum (reg);
725 
726     if (set == -1)
727         return false;
728 
729     if (ReadRegisterSet(set, false) != KERN_SUCCESS)
730         return false;
731 
732     switch (reg)
733     {
734     case gpr_r0:
735     case gpr_r1:
736     case gpr_r2:
737     case gpr_r3:
738     case gpr_r4:
739     case gpr_r5:
740     case gpr_r6:
741     case gpr_r7:
742     case gpr_r8:
743     case gpr_r9:
744     case gpr_r10:
745     case gpr_r11:
746     case gpr_r12:
747     case gpr_sp:
748     case gpr_lr:
749     case gpr_pc:
750     case gpr_cpsr:
751             gpr.r[reg - gpr_r0] = value.GetAsUInt32();
752         break;
753 
754     case fpu_s0:
755     case fpu_s1:
756     case fpu_s2:
757     case fpu_s3:
758     case fpu_s4:
759     case fpu_s5:
760     case fpu_s6:
761     case fpu_s7:
762     case fpu_s8:
763     case fpu_s9:
764     case fpu_s10:
765     case fpu_s11:
766     case fpu_s12:
767     case fpu_s13:
768     case fpu_s14:
769     case fpu_s15:
770     case fpu_s16:
771     case fpu_s17:
772     case fpu_s18:
773     case fpu_s19:
774     case fpu_s20:
775     case fpu_s21:
776     case fpu_s22:
777     case fpu_s23:
778     case fpu_s24:
779     case fpu_s25:
780     case fpu_s26:
781     case fpu_s27:
782     case fpu_s28:
783     case fpu_s29:
784     case fpu_s30:
785     case fpu_s31:
786         fpu.floats.s[reg] = value.GetAsUInt32();
787         break;
788 
789     case fpu_fpscr:
790         fpu.fpscr = value.GetAsUInt32();
791         break;
792 
793     case exc_exception:
794         exc.exception = value.GetAsUInt32();
795         break;
796     case exc_fsr:
797         exc.fsr = value.GetAsUInt32();
798         break;
799     case exc_far:
800         exc.far = value.GetAsUInt32();
801         break;
802 
803     default:
804         return false;
805 
806     }
807     return WriteRegisterSet(set) == KERN_SUCCESS;
808 }
809 
810 bool
811 RegisterContextDarwin_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
812 {
813     data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
814     if (data_sp &&
815         ReadGPR (false) == KERN_SUCCESS &&
816         ReadFPU (false) == KERN_SUCCESS &&
817         ReadEXC (false) == KERN_SUCCESS)
818     {
819         uint8_t *dst = data_sp->GetBytes();
820         ::memcpy (dst, &gpr, sizeof(gpr));
821         dst += sizeof(gpr);
822 
823         ::memcpy (dst, &fpu, sizeof(fpu));
824         dst += sizeof(gpr);
825 
826         ::memcpy (dst, &exc, sizeof(exc));
827         return true;
828     }
829     return false;
830 }
831 
832 bool
833 RegisterContextDarwin_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
834 {
835     if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
836     {
837         const uint8_t *src = data_sp->GetBytes();
838         ::memcpy (&gpr, src, sizeof(gpr));
839         src += sizeof(gpr);
840 
841         ::memcpy (&fpu, src, sizeof(fpu));
842         src += sizeof(gpr);
843 
844         ::memcpy (&exc, src, sizeof(exc));
845         uint32_t success_count = 0;
846         if (WriteGPR() == KERN_SUCCESS)
847             ++success_count;
848         if (WriteFPU() == KERN_SUCCESS)
849             ++success_count;
850         if (WriteEXC() == KERN_SUCCESS)
851             ++success_count;
852         return success_count == 3;
853     }
854     return false;
855 }
856 
857 uint32_t
858 RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg)
859 {
860     if (kind == eRegisterKindGeneric)
861     {
862         switch (reg)
863         {
864         case LLDB_REGNUM_GENERIC_PC: return gpr_pc;
865         case LLDB_REGNUM_GENERIC_SP: return gpr_sp;
866         case LLDB_REGNUM_GENERIC_FP: return gpr_r7;
867         case LLDB_REGNUM_GENERIC_RA: return gpr_lr;
868         case LLDB_REGNUM_GENERIC_FLAGS: return gpr_cpsr;
869         default:
870             break;
871         }
872     }
873     else if (kind == eRegisterKindDWARF)
874     {
875         switch (reg)
876         {
877         case dwarf_r0:  return gpr_r0;
878         case dwarf_r1:  return gpr_r1;
879         case dwarf_r2:  return gpr_r2;
880         case dwarf_r3:  return gpr_r3;
881         case dwarf_r4:  return gpr_r4;
882         case dwarf_r5:  return gpr_r5;
883         case dwarf_r6:  return gpr_r6;
884         case dwarf_r7:  return gpr_r7;
885         case dwarf_r8:  return gpr_r8;
886         case dwarf_r9:  return gpr_r9;
887         case dwarf_r10: return gpr_r10;
888         case dwarf_r11: return gpr_r11;
889         case dwarf_r12: return gpr_r12;
890         case dwarf_sp:  return gpr_sp;
891         case dwarf_lr:  return gpr_lr;
892         case dwarf_pc:  return gpr_pc;
893         case dwarf_spsr: return gpr_cpsr;
894 
895         case dwarf_s0:  return fpu_s0;
896         case dwarf_s1:  return fpu_s1;
897         case dwarf_s2:  return fpu_s2;
898         case dwarf_s3:  return fpu_s3;
899         case dwarf_s4:  return fpu_s4;
900         case dwarf_s5:  return fpu_s5;
901         case dwarf_s6:  return fpu_s6;
902         case dwarf_s7:  return fpu_s7;
903         case dwarf_s8:  return fpu_s8;
904         case dwarf_s9:  return fpu_s9;
905         case dwarf_s10: return fpu_s10;
906         case dwarf_s11: return fpu_s11;
907         case dwarf_s12: return fpu_s12;
908         case dwarf_s13: return fpu_s13;
909         case dwarf_s14: return fpu_s14;
910         case dwarf_s15: return fpu_s15;
911         case dwarf_s16: return fpu_s16;
912         case dwarf_s17: return fpu_s17;
913         case dwarf_s18: return fpu_s18;
914         case dwarf_s19: return fpu_s19;
915         case dwarf_s20: return fpu_s20;
916         case dwarf_s21: return fpu_s21;
917         case dwarf_s22: return fpu_s22;
918         case dwarf_s23: return fpu_s23;
919         case dwarf_s24: return fpu_s24;
920         case dwarf_s25: return fpu_s25;
921         case dwarf_s26: return fpu_s26;
922         case dwarf_s27: return fpu_s27;
923         case dwarf_s28: return fpu_s28;
924         case dwarf_s29: return fpu_s29;
925         case dwarf_s30: return fpu_s30;
926         case dwarf_s31: return fpu_s31;
927 
928         default:
929             break;
930         }
931     }
932     else if (kind == eRegisterKindGCC)
933     {
934         switch (reg)
935         {
936         case gcc_r0:    return gpr_r0;
937         case gcc_r1:    return gpr_r1;
938         case gcc_r2:    return gpr_r2;
939         case gcc_r3:    return gpr_r3;
940         case gcc_r4:    return gpr_r4;
941         case gcc_r5:    return gpr_r5;
942         case gcc_r6:    return gpr_r6;
943         case gcc_r7:    return gpr_r7;
944         case gcc_r8:    return gpr_r8;
945         case gcc_r9:    return gpr_r9;
946         case gcc_r10:   return gpr_r10;
947         case gcc_r11:   return gpr_r11;
948         case gcc_r12:   return gpr_r12;
949         case gcc_sp:    return gpr_sp;
950         case gcc_lr:    return gpr_lr;
951         case gcc_pc:    return gpr_pc;
952         case gcc_cpsr:  return gpr_cpsr;
953         }
954     }
955     else if (kind == eRegisterKindLLDB)
956     {
957         return reg;
958     }
959     return LLDB_INVALID_REGNUM;
960 }
961 
962 
963 uint32_t
964 RegisterContextDarwin_arm::NumSupportedHardwareBreakpoints ()
965 {
966 #if defined (__arm__)
967     // Set the init value to something that will let us know that we need to
968     // autodetect how many breakpoints are supported dynamically...
969     static uint32_t g_num_supported_hw_breakpoints = UINT32_MAX;
970     if (g_num_supported_hw_breakpoints == UINT32_MAX)
971     {
972         // Set this to zero in case we can't tell if there are any HW breakpoints
973         g_num_supported_hw_breakpoints = 0;
974 
975         uint32_t register_DBGDIDR;
976 
977         asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
978         g_num_supported_hw_breakpoints = bits(register_DBGDIDR, 27, 24);
979         // Zero is reserved for the BRP count, so don't increment it if it is zero
980         if (g_num_supported_hw_breakpoints > 0)
981             g_num_supported_hw_breakpoints++;
982 //        if (log) log->Printf ("DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, g_num_supported_hw_breakpoints);
983 
984     }
985     return g_num_supported_hw_breakpoints;
986 #else
987     // TODO: figure out remote case here!
988     return 6;
989 #endif
990 }
991 
992 uint32_t
993 RegisterContextDarwin_arm::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
994 {
995     // Make sure our address isn't bogus
996     if (addr & 1)
997         return LLDB_INVALID_INDEX32;
998 
999     int kret = ReadDBG (false);
1000 
1001     if (kret == KERN_SUCCESS)
1002     {
1003         const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints();
1004         uint32_t i;
1005         for (i=0; i<num_hw_breakpoints; ++i)
1006         {
1007             if ((dbg.bcr[i] & BCR_ENABLE) == 0)
1008                 break; // We found an available hw breakpoint slot (in i)
1009         }
1010 
1011         // See if we found an available hw breakpoint slot above
1012         if (i < num_hw_breakpoints)
1013         {
1014             // Make sure bits 1:0 are clear in our address
1015             dbg.bvr[i] = addr & ~((lldb::addr_t)3);
1016 
1017             if (size == 2 || addr & 2)
1018             {
1019                 uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1;
1020 
1021                 // We have a thumb breakpoint
1022                 // We have an ARM breakpoint
1023                 dbg.bcr[i] =  BCR_M_IMVA_MATCH |    // Stop on address mismatch
1024                                         byte_addr_select |  // Set the correct byte address select so we only trigger on the correct opcode
1025                                         S_USER |            // Which modes should this breakpoint stop in?
1026                                         BCR_ENABLE;         // Enable this hardware breakpoint
1027 //                if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)",
1028 //                        addr,
1029 //                        size,
1030 //                        i,
1031 //                        i,
1032 //                        dbg.bvr[i],
1033 //                        dbg.bcr[i]);
1034             }
1035             else if (size == 4)
1036             {
1037                 // We have an ARM breakpoint
1038                 dbg.bcr[i] =  BCR_M_IMVA_MATCH |    // Stop on address mismatch
1039                                         BAS_IMVA_ALL |      // Stop on any of the four bytes following the IMVA
1040                                         S_USER |            // Which modes should this breakpoint stop in?
1041                                         BCR_ENABLE;         // Enable this hardware breakpoint
1042 //                if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)",
1043 //                        addr,
1044 //                        size,
1045 //                        i,
1046 //                        i,
1047 //                        dbg.bvr[i],
1048 //                        dbg.bcr[i]);
1049             }
1050 
1051             kret = WriteDBG();
1052 //            if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint() WriteDBG() => 0x%8.8x.", kret);
1053 
1054             if (kret == KERN_SUCCESS)
1055                 return i;
1056         }
1057 //        else
1058 //        {
1059 //            if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint(addr = %8.8p, size = %u) => all hardware breakpoint resources are being used.", addr, size);
1060 //        }
1061     }
1062 
1063     return LLDB_INVALID_INDEX32;
1064 }
1065 
1066 bool
1067 RegisterContextDarwin_arm::ClearHardwareBreakpoint (uint32_t hw_index)
1068 {
1069     int kret = ReadDBG (false);
1070 
1071     const uint32_t num_hw_points = NumSupportedHardwareBreakpoints();
1072     if (kret == KERN_SUCCESS)
1073     {
1074         if (hw_index < num_hw_points)
1075         {
1076             dbg.bcr[hw_index] = 0;
1077 //            if (log) log->Printf ("RegisterContextDarwin_arm::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x  BCR%u = 0x%8.8x",
1078 //                    hw_index,
1079 //                    hw_index,
1080 //                    dbg.bvr[hw_index],
1081 //                    hw_index,
1082 //                    dbg.bcr[hw_index]);
1083 
1084             kret = WriteDBG();
1085 
1086             if (kret == KERN_SUCCESS)
1087                 return true;
1088         }
1089     }
1090     return false;
1091 }
1092 
1093 uint32_t
1094 RegisterContextDarwin_arm::NumSupportedHardwareWatchpoints ()
1095 {
1096 #if defined (__arm__)
1097     // Set the init value to something that will let us know that we need to
1098     // autodetect how many watchpoints are supported dynamically...
1099     static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
1100     if (g_num_supported_hw_watchpoints == UINT32_MAX)
1101     {
1102         // Set this to zero in case we can't tell if there are any HW breakpoints
1103         g_num_supported_hw_watchpoints = 0;
1104 
1105         uint32_t register_DBGDIDR;
1106         asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
1107         g_num_supported_hw_watchpoints = bits(register_DBGDIDR, 31, 28) + 1;
1108 //        if (log) log->Printf ("DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, g_num_supported_hw_watchpoints);
1109     }
1110     return g_num_supported_hw_watchpoints;
1111 #else
1112     // TODO: figure out remote case here!
1113     return 2;
1114 #endif
1115 }
1116 
1117 
1118 uint32_t
1119 RegisterContextDarwin_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write)
1120 {
1121 //    if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write);
1122 
1123     const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
1124 
1125     // Can't watch zero bytes
1126     if (size == 0)
1127         return LLDB_INVALID_INDEX32;
1128 
1129     // We must watch for either read or write
1130     if (read == false && write == false)
1131         return LLDB_INVALID_INDEX32;
1132 
1133     // Can't watch more than 4 bytes per WVR/WCR pair
1134     if (size > 4)
1135         return LLDB_INVALID_INDEX32;
1136 
1137     // We can only watch up to four bytes that follow a 4 byte aligned address
1138     // per watchpoint register pair. Since we have at most so we can only watch
1139     // until the next 4 byte boundary and we need to make sure we can properly
1140     // encode this.
1141     uint32_t addr_word_offset = addr % 4;
1142 //    if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset);
1143 
1144     uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
1145 //    if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask);
1146     if (byte_mask > 0xfu)
1147         return LLDB_INVALID_INDEX32;
1148 
1149     // Read the debug state
1150     int kret = ReadDBG (false);
1151 
1152     if (kret == KERN_SUCCESS)
1153     {
1154         // Check to make sure we have the needed hardware support
1155         uint32_t i = 0;
1156 
1157         for (i=0; i<num_hw_watchpoints; ++i)
1158         {
1159             if ((dbg.wcr[i] & WCR_ENABLE) == 0)
1160                 break; // We found an available hw breakpoint slot (in i)
1161         }
1162 
1163         // See if we found an available hw breakpoint slot above
1164         if (i < num_hw_watchpoints)
1165         {
1166             // Make the byte_mask into a valid Byte Address Select mask
1167             uint32_t byte_address_select = byte_mask << 5;
1168             // Make sure bits 1:0 are clear in our address
1169             dbg.wvr[i] = addr & ~((lldb::addr_t)3);
1170             dbg.wcr[i] =  byte_address_select |       // Which bytes that follow the IMVA that we will watch
1171                                     S_USER |                    // Stop only in user mode
1172                                     (read ? WCR_LOAD : 0) |     // Stop on read access?
1173                                     (write ? WCR_STORE : 0) |   // Stop on write access?
1174                                     WCR_ENABLE;                 // Enable this watchpoint;
1175 
1176             kret = WriteDBG();
1177 //            if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() WriteDBG() => 0x%8.8x.", kret);
1178 
1179             if (kret == KERN_SUCCESS)
1180                 return i;
1181         }
1182         else
1183         {
1184 //            if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
1185         }
1186     }
1187     return LLDB_INVALID_INDEX32;
1188 }
1189 
1190 bool
1191 RegisterContextDarwin_arm::ClearHardwareWatchpoint (uint32_t hw_index)
1192 {
1193     int kret = ReadDBG (false);
1194 
1195     const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
1196     if (kret == KERN_SUCCESS)
1197     {
1198         if (hw_index < num_hw_points)
1199         {
1200             dbg.wcr[hw_index] = 0;
1201 //            if (log) log->Printf ("RegisterContextDarwin_arm::ClearHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
1202 //                    hw_index,
1203 //                    hw_index,
1204 //                    dbg.wvr[hw_index],
1205 //                    hw_index,
1206 //                    dbg.wcr[hw_index]);
1207 
1208             kret = WriteDBG();
1209 
1210             if (kret == KERN_SUCCESS)
1211                 return true;
1212         }
1213     }
1214     return false;
1215 }
1216 
1217 #endif
1218