*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / armnbsd-nat.c
1 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
2
3 Copyright (C) 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002, 2004, 2007
4 Free Software Foundation, Inc.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
22
23 #include "defs.h"
24 #include "gdbcore.h"
25 #include "inferior.h"
26 #include "regcache.h"
27 #include "target.h"
28
29 #include "gdb_string.h"
30 #include <sys/types.h>
31 #include <sys/ptrace.h>
32 #include <machine/reg.h>
33 #include <machine/frame.h>
34
35 #include "arm-tdep.h"
36 #include "inf-ptrace.h"
37
38 extern int arm_apcs_32;
39
40 static void
41 arm_supply_gregset (struct regcache *regcache, struct reg *gregset)
42 {
43 int regno;
44 CORE_ADDR r_pc;
45
46 /* Integer registers. */
47 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
48 regcache_raw_supply (regcache, regno, (char *) &gregset->r[regno]);
49
50 regcache_raw_supply (regcache, ARM_SP_REGNUM,
51 (char *) &gregset->r_sp);
52 regcache_raw_supply (regcache, ARM_LR_REGNUM,
53 (char *) &gregset->r_lr);
54 /* This is ok: we're running native... */
55 r_pc = gdbarch_addr_bits_remove (current_gdbarch, gregset->r_pc);
56 regcache_raw_supply (regcache, ARM_PC_REGNUM, (char *) &r_pc);
57
58 if (arm_apcs_32)
59 regcache_raw_supply (regcache, ARM_PS_REGNUM,
60 (char *) &gregset->r_cpsr);
61 else
62 regcache_raw_supply (regcache, ARM_PS_REGNUM,
63 (char *) &gregset->r_pc);
64 }
65
66 static void
67 arm_supply_fparegset (struct regcache *regcache, struct fpreg *fparegset)
68 {
69 int regno;
70
71 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
72 regcache_raw_supply (regcache, regno,
73 (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]);
74
75 regcache_raw_supply (regcache, ARM_FPS_REGNUM,
76 (char *) &fparegset->fpr_fpsr);
77 }
78
79 static void
80 fetch_register (struct regcache *regcache, int regno)
81 {
82 struct reg inferior_registers;
83 int ret;
84
85 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
86 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
87
88 if (ret < 0)
89 {
90 warning (_("unable to fetch general register"));
91 return;
92 }
93
94 switch (regno)
95 {
96 case ARM_SP_REGNUM:
97 regcache_raw_supply (regcache, ARM_SP_REGNUM,
98 (char *) &inferior_registers.r_sp);
99 break;
100
101 case ARM_LR_REGNUM:
102 regcache_raw_supply (regcache, ARM_LR_REGNUM,
103 (char *) &inferior_registers.r_lr);
104 break;
105
106 case ARM_PC_REGNUM:
107 /* This is ok: we're running native... */
108 inferior_registers.r_pc = gdbarch_addr_bits_remove
109 (current_gdbarch, inferior_registers.r_pc);
110 regcache_raw_supply (regcache, ARM_PC_REGNUM,
111 (char *) &inferior_registers.r_pc);
112 break;
113
114 case ARM_PS_REGNUM:
115 if (arm_apcs_32)
116 regcache_raw_supply (regcache, ARM_PS_REGNUM,
117 (char *) &inferior_registers.r_cpsr);
118 else
119 regcache_raw_supply (regcache, ARM_PS_REGNUM,
120 (char *) &inferior_registers.r_pc);
121 break;
122
123 default:
124 regcache_raw_supply (regcache, regno,
125 (char *) &inferior_registers.r[regno]);
126 break;
127 }
128 }
129
130 static void
131 fetch_regs (struct regcache *regcache)
132 {
133 struct reg inferior_registers;
134 int ret;
135 int regno;
136
137 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
138 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
139
140 if (ret < 0)
141 {
142 warning (_("unable to fetch general registers"));
143 return;
144 }
145
146 arm_supply_gregset (regcache, &inferior_registers);
147 }
148
149 static void
150 fetch_fp_register (struct regcache *regcache, int regno)
151 {
152 struct fpreg inferior_fp_registers;
153 int ret;
154
155 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
156 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
157
158 if (ret < 0)
159 {
160 warning (_("unable to fetch floating-point register"));
161 return;
162 }
163
164 switch (regno)
165 {
166 case ARM_FPS_REGNUM:
167 regcache_raw_supply (regcache, ARM_FPS_REGNUM,
168 (char *) &inferior_fp_registers.fpr_fpsr);
169 break;
170
171 default:
172 regcache_raw_supply (regcache, regno,
173 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
174 break;
175 }
176 }
177
178 static void
179 fetch_fp_regs (struct regcache *regcache)
180 {
181 struct fpreg inferior_fp_registers;
182 int ret;
183 int regno;
184
185 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
186 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
187
188 if (ret < 0)
189 {
190 warning (_("unable to fetch general registers"));
191 return;
192 }
193
194 arm_supply_fparegset (regcache, &inferior_fp_registers);
195 }
196
197 static void
198 armnbsd_fetch_registers (struct regcache *regcache, int regno)
199 {
200 if (regno >= 0)
201 {
202 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
203 fetch_register (regcache, regno);
204 else
205 fetch_fp_register (regcache, regno);
206 }
207 else
208 {
209 fetch_regs (regcache);
210 fetch_fp_regs (regcache);
211 }
212 }
213
214
215 static void
216 store_register (const struct regcache *regcache, int regno)
217 {
218 struct reg inferior_registers;
219 int ret;
220
221 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
222 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
223
224 if (ret < 0)
225 {
226 warning (_("unable to fetch general registers"));
227 return;
228 }
229
230 switch (regno)
231 {
232 case ARM_SP_REGNUM:
233 regcache_raw_collect (regcache, ARM_SP_REGNUM,
234 (char *) &inferior_registers.r_sp);
235 break;
236
237 case ARM_LR_REGNUM:
238 regcache_raw_collect (regcache, ARM_LR_REGNUM,
239 (char *) &inferior_registers.r_lr);
240 break;
241
242 case ARM_PC_REGNUM:
243 if (arm_apcs_32)
244 regcache_raw_collect (regcache, ARM_PC_REGNUM,
245 (char *) &inferior_registers.r_pc);
246 else
247 {
248 unsigned pc_val;
249
250 regcache_raw_collect (regcache, ARM_PC_REGNUM,
251 (char *) &pc_val);
252
253 pc_val = gdbarch_addr_bits_remove (current_gdbarch, pc_val);
254 inferior_registers.r_pc ^= gdbarch_addr_bits_remove
255 (current_gdbarch,
256 inferior_registers.r_pc);
257 inferior_registers.r_pc |= pc_val;
258 }
259 break;
260
261 case ARM_PS_REGNUM:
262 if (arm_apcs_32)
263 regcache_raw_collect (regcache, ARM_PS_REGNUM,
264 (char *) &inferior_registers.r_cpsr);
265 else
266 {
267 unsigned psr_val;
268
269 regcache_raw_collect (regcache, ARM_PS_REGNUM,
270 (char *) &psr_val);
271
272 psr_val ^= gdbarch_addr_bits_remove (current_gdbarch, psr_val);
273 inferior_registers.r_pc = gdbarch_addr_bits_remove
274 (current_gdbarch,
275 inferior_registers.r_pc);
276 inferior_registers.r_pc |= psr_val;
277 }
278 break;
279
280 default:
281 regcache_raw_collect (regcache, regno,
282 (char *) &inferior_registers.r[regno]);
283 break;
284 }
285
286 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
287 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
288
289 if (ret < 0)
290 warning (_("unable to write register %d to inferior"), regno);
291 }
292
293 static void
294 store_regs (const struct regcache *regcache)
295 {
296 struct reg inferior_registers;
297 int ret;
298 int regno;
299
300
301 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
302 regcache_raw_collect (regcache, regno,
303 (char *) &inferior_registers.r[regno]);
304
305 regcache_raw_collect (regcache, ARM_SP_REGNUM,
306 (char *) &inferior_registers.r_sp);
307 regcache_raw_collect (regcache, ARM_LR_REGNUM,
308 (char *) &inferior_registers.r_lr);
309
310 if (arm_apcs_32)
311 {
312 regcache_raw_collect (regcache, ARM_PC_REGNUM,
313 (char *) &inferior_registers.r_pc);
314 regcache_raw_collect (regcache, ARM_PS_REGNUM,
315 (char *) &inferior_registers.r_cpsr);
316 }
317 else
318 {
319 unsigned pc_val;
320 unsigned psr_val;
321
322 regcache_raw_collect (regcache, ARM_PC_REGNUM,
323 (char *) &pc_val);
324 regcache_raw_collect (regcache, ARM_PS_REGNUM,
325 (char *) &psr_val);
326
327 pc_val = gdbarch_addr_bits_remove (current_gdbarch, pc_val);
328 psr_val ^= gdbarch_addr_bits_remove (current_gdbarch, psr_val);
329
330 inferior_registers.r_pc = pc_val | psr_val;
331 }
332
333 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
334 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
335
336 if (ret < 0)
337 warning (_("unable to store general registers"));
338 }
339
340 static void
341 store_fp_register (const struct regcache *regcache, int regno)
342 {
343 struct fpreg inferior_fp_registers;
344 int ret;
345
346 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
347 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
348
349 if (ret < 0)
350 {
351 warning (_("unable to fetch floating-point registers"));
352 return;
353 }
354
355 switch (regno)
356 {
357 case ARM_FPS_REGNUM:
358 regcache_raw_collect (regcache, ARM_FPS_REGNUM,
359 (char *) &inferior_fp_registers.fpr_fpsr);
360 break;
361
362 default:
363 regcache_raw_collect (regcache, regno,
364 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
365 break;
366 }
367
368 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
369 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
370
371 if (ret < 0)
372 warning (_("unable to write register %d to inferior"), regno);
373 }
374
375 static void
376 store_fp_regs (const struct regcache *regcache)
377 {
378 struct fpreg inferior_fp_registers;
379 int ret;
380 int regno;
381
382
383 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
384 regcache_raw_collect (regcache, regno,
385 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
386
387 regcache_raw_collect (regcache, ARM_FPS_REGNUM,
388 (char *) &inferior_fp_registers.fpr_fpsr);
389
390 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
391 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
392
393 if (ret < 0)
394 warning (_("unable to store floating-point registers"));
395 }
396
397 static void
398 armnbsd_store_registers (struct regcache *regcache, int regno)
399 {
400 if (regno >= 0)
401 {
402 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
403 store_register (regcache, regno);
404 else
405 store_fp_register (regcache, regno);
406 }
407 else
408 {
409 store_regs (regcache);
410 store_fp_regs (regcache);
411 }
412 }
413
414 struct md_core
415 {
416 struct reg intreg;
417 struct fpreg freg;
418 };
419
420 static void
421 fetch_core_registers (struct regcache *regcache,
422 char *core_reg_sect, unsigned core_reg_size,
423 int which, CORE_ADDR ignore)
424 {
425 struct md_core *core_reg = (struct md_core *) core_reg_sect;
426 int regno;
427 CORE_ADDR r_pc;
428
429 arm_supply_gregset (regcache, &core_reg->intreg);
430 arm_supply_fparegset (regcache, &core_reg->freg);
431 }
432
433 static void
434 fetch_elfcore_registers (struct regcache *regcache,
435 char *core_reg_sect, unsigned core_reg_size,
436 int which, CORE_ADDR ignore)
437 {
438 struct reg gregset;
439 struct fpreg fparegset;
440
441 switch (which)
442 {
443 case 0: /* Integer registers. */
444 if (core_reg_size != sizeof (struct reg))
445 warning (_("wrong size of register set in core file"));
446 else
447 {
448 /* The memcpy may be unnecessary, but we can't really be sure
449 of the alignment of the data in the core file. */
450 memcpy (&gregset, core_reg_sect, sizeof (gregset));
451 arm_supply_gregset (regcache, &gregset);
452 }
453 break;
454
455 case 2:
456 if (core_reg_size != sizeof (struct fpreg))
457 warning (_("wrong size of FPA register set in core file"));
458 else
459 {
460 /* The memcpy may be unnecessary, but we can't really be sure
461 of the alignment of the data in the core file. */
462 memcpy (&fparegset, core_reg_sect, sizeof (fparegset));
463 arm_supply_fparegset (regcache, &fparegset);
464 }
465 break;
466
467 default:
468 /* Don't know what kind of register request this is; just ignore it. */
469 break;
470 }
471 }
472
473 static struct core_fns arm_netbsd_core_fns =
474 {
475 bfd_target_unknown_flavour, /* core_flovour. */
476 default_check_format, /* check_format. */
477 default_core_sniffer, /* core_sniffer. */
478 fetch_core_registers, /* core_read_registers. */
479 NULL
480 };
481
482 static struct core_fns arm_netbsd_elfcore_fns =
483 {
484 bfd_target_elf_flavour, /* core_flovour. */
485 default_check_format, /* check_format. */
486 default_core_sniffer, /* core_sniffer. */
487 fetch_elfcore_registers, /* core_read_registers. */
488 NULL
489 };
490
491 void
492 _initialize_arm_netbsd_nat (void)
493 {
494 struct target_ops *t;
495
496 t = inf_ptrace_target ();
497 t->to_fetch_registers = armnbsd_fetch_registers;
498 t->to_store_registers = armnbsd_store_registers;
499 add_target (t);
500
501 deprecated_add_core_fns (&arm_netbsd_core_fns);
502 deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
503 }
This page took 0.043453 seconds and 4 git commands to generate.