2005-01-19 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / gdb / armnbsd-nat.c
1 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
2
3 Copyright 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002, 2004
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., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23 #include "defs.h"
24
25 #ifndef FETCH_INFERIOR_REGISTERS
26 #error Not FETCH_INFERIOR_REGISTERS
27 #endif /* !FETCH_INFERIOR_REGISTERS */
28
29 #include "arm-tdep.h"
30
31 #include <sys/types.h>
32 #include <sys/ptrace.h>
33 #include <machine/reg.h>
34 #include <machine/frame.h>
35 #include "inferior.h"
36 #include "regcache.h"
37 #include "gdbcore.h"
38
39 extern int arm_apcs_32;
40
41 static void
42 supply_gregset (struct reg *gregset)
43 {
44 int regno;
45 CORE_ADDR r_pc;
46
47 /* Integer registers. */
48 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
49 regcache_raw_supply (current_regcache, regno, (char *) &gregset->r[regno]);
50
51 regcache_raw_supply (current_regcache, ARM_SP_REGNUM,
52 (char *) &gregset->r_sp);
53 regcache_raw_supply (current_regcache, ARM_LR_REGNUM,
54 (char *) &gregset->r_lr);
55 /* This is ok: we're running native... */
56 r_pc = ADDR_BITS_REMOVE (gregset->r_pc);
57 regcache_raw_supply (current_regcache, ARM_PC_REGNUM, (char *) &r_pc);
58
59 if (arm_apcs_32)
60 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
61 (char *) &gregset->r_cpsr);
62 else
63 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
64 (char *) &gregset->r_pc);
65 }
66
67 static void
68 supply_fparegset (struct fpreg *fparegset)
69 {
70 int regno;
71
72 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
73 regcache_raw_supply (current_regcache, regno,
74 (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]);
75
76 regcache_raw_supply (current_regcache, ARM_FPS_REGNUM,
77 (char *) &fparegset->fpr_fpsr);
78 }
79
80 static void
81 fetch_register (int regno)
82 {
83 struct reg inferior_registers;
84 int ret;
85
86 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
87 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
88
89 if (ret < 0)
90 {
91 warning (_("unable to fetch general register"));
92 return;
93 }
94
95 switch (regno)
96 {
97 case ARM_SP_REGNUM:
98 regcache_raw_supply (current_regcache, ARM_SP_REGNUM,
99 (char *) &inferior_registers.r_sp);
100 break;
101
102 case ARM_LR_REGNUM:
103 regcache_raw_supply (current_regcache, ARM_LR_REGNUM,
104 (char *) &inferior_registers.r_lr);
105 break;
106
107 case ARM_PC_REGNUM:
108 /* This is ok: we're running native... */
109 inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc);
110 regcache_raw_supply (current_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 (current_regcache, ARM_PS_REGNUM,
117 (char *) &inferior_registers.r_cpsr);
118 else
119 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
120 (char *) &inferior_registers.r_pc);
121 break;
122
123 default:
124 regcache_raw_supply (current_regcache, regno,
125 (char *) &inferior_registers.r[regno]);
126 break;
127 }
128 }
129
130 static void
131 fetch_regs (void)
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 supply_gregset (&inferior_registers);
147 }
148
149 static void
150 fetch_fp_register (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 (current_regcache, ARM_FPS_REGNUM,
168 (char *) &inferior_fp_registers.fpr_fpsr);
169 break;
170
171 default:
172 regcache_raw_supply (current_regcache, regno,
173 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
174 break;
175 }
176 }
177
178 static void
179 fetch_fp_regs (void)
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 supply_fparegset (&inferior_fp_registers);
195 }
196
197 void
198 fetch_inferior_registers (int regno)
199 {
200 if (regno >= 0)
201 {
202 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
203 fetch_register (regno);
204 else
205 fetch_fp_register (regno);
206 }
207 else
208 {
209 fetch_regs ();
210 fetch_fp_regs ();
211 }
212 }
213
214
215 static void
216 store_register (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 (current_regcache, ARM_SP_REGNUM,
234 (char *) &inferior_registers.r_sp);
235 break;
236
237 case ARM_LR_REGNUM:
238 regcache_raw_collect (current_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 (current_regcache, ARM_PC_REGNUM,
245 (char *) &inferior_registers.r_pc);
246 else
247 {
248 unsigned pc_val;
249
250 regcache_raw_collect (current_regcache, ARM_PC_REGNUM,
251 (char *) &pc_val);
252
253 pc_val = ADDR_BITS_REMOVE (pc_val);
254 inferior_registers.r_pc
255 ^= ADDR_BITS_REMOVE (inferior_registers.r_pc);
256 inferior_registers.r_pc |= pc_val;
257 }
258 break;
259
260 case ARM_PS_REGNUM:
261 if (arm_apcs_32)
262 regcache_raw_collect (current_regcache, ARM_PS_REGNUM,
263 (char *) &inferior_registers.r_cpsr);
264 else
265 {
266 unsigned psr_val;
267
268 regcache_raw_collect (current_regcache, ARM_PS_REGNUM,
269 (char *) &psr_val);
270
271 psr_val ^= ADDR_BITS_REMOVE (psr_val);
272 inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc);
273 inferior_registers.r_pc |= psr_val;
274 }
275 break;
276
277 default:
278 regcache_raw_collect (current_regcache, regno,
279 (char *) &inferior_registers.r[regno]);
280 break;
281 }
282
283 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
284 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
285
286 if (ret < 0)
287 warning (_("unable to write register %d to inferior"), regno);
288 }
289
290 static void
291 store_regs (void)
292 {
293 struct reg inferior_registers;
294 int ret;
295 int regno;
296
297
298 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
299 regcache_raw_collect (current_regcache, regno,
300 (char *) &inferior_registers.r[regno]);
301
302 regcache_raw_collect (current_regcache, ARM_SP_REGNUM,
303 (char *) &inferior_registers.r_sp);
304 regcache_raw_collect (current_regcache, ARM_LR_REGNUM,
305 (char *) &inferior_registers.r_lr);
306
307 if (arm_apcs_32)
308 {
309 regcache_raw_collect (current_regcache, ARM_PC_REGNUM,
310 (char *) &inferior_registers.r_pc);
311 regcache_raw_collect (current_regcache, ARM_PS_REGNUM,
312 (char *) &inferior_registers.r_cpsr);
313 }
314 else
315 {
316 unsigned pc_val;
317 unsigned psr_val;
318
319 regcache_raw_collect (current_regcache, ARM_PC_REGNUM,
320 (char *) &pc_val);
321 regcache_raw_collect (current_regcache, ARM_PS_REGNUM,
322 (char *) &psr_val);
323
324 pc_val = ADDR_BITS_REMOVE (pc_val);
325 psr_val ^= ADDR_BITS_REMOVE (psr_val);
326
327 inferior_registers.r_pc = pc_val | psr_val;
328 }
329
330 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
331 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
332
333 if (ret < 0)
334 warning (_("unable to store general registers"));
335 }
336
337 static void
338 store_fp_register (int regno)
339 {
340 struct fpreg inferior_fp_registers;
341 int ret;
342
343 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
344 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
345
346 if (ret < 0)
347 {
348 warning (_("unable to fetch floating-point registers"));
349 return;
350 }
351
352 switch (regno)
353 {
354 case ARM_FPS_REGNUM:
355 regcache_raw_collect (current_regcache, ARM_FPS_REGNUM,
356 (char *) &inferior_fp_registers.fpr_fpsr);
357 break;
358
359 default:
360 regcache_raw_collect (current_regcache, regno,
361 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
362 break;
363 }
364
365 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
366 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
367
368 if (ret < 0)
369 warning (_("unable to write register %d to inferior"), regno);
370 }
371
372 static void
373 store_fp_regs (void)
374 {
375 struct fpreg inferior_fp_registers;
376 int ret;
377 int regno;
378
379
380 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
381 regcache_raw_collect (current_regcache, regno,
382 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
383
384 regcache_raw_collect (current_regcache, ARM_FPS_REGNUM,
385 (char *) &inferior_fp_registers.fpr_fpsr);
386
387 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
388 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
389
390 if (ret < 0)
391 warning (_("unable to store floating-point registers"));
392 }
393
394 void
395 store_inferior_registers (int regno)
396 {
397 if (regno >= 0)
398 {
399 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
400 store_register (regno);
401 else
402 store_fp_register (regno);
403 }
404 else
405 {
406 store_regs ();
407 store_fp_regs ();
408 }
409 }
410
411 struct md_core
412 {
413 struct reg intreg;
414 struct fpreg freg;
415 };
416
417 static void
418 fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
419 int which, CORE_ADDR ignore)
420 {
421 struct md_core *core_reg = (struct md_core *) core_reg_sect;
422 int regno;
423 CORE_ADDR r_pc;
424
425 supply_gregset (&core_reg->intreg);
426 supply_fparegset (&core_reg->freg);
427 }
428
429 static void
430 fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size,
431 int which, CORE_ADDR ignore)
432 {
433 struct reg gregset;
434 struct fpreg fparegset;
435
436 switch (which)
437 {
438 case 0: /* Integer registers. */
439 if (core_reg_size != sizeof (struct reg))
440 warning (_("wrong size of register set in core file"));
441 else
442 {
443 /* The memcpy may be unnecessary, but we can't really be sure
444 of the alignment of the data in the core file. */
445 memcpy (&gregset, core_reg_sect, sizeof (gregset));
446 supply_gregset (&gregset);
447 }
448 break;
449
450 case 2:
451 if (core_reg_size != sizeof (struct fpreg))
452 warning (_("wrong size of FPA register set in core file"));
453 else
454 {
455 /* The memcpy may be unnecessary, but we can't really be sure
456 of the alignment of the data in the core file. */
457 memcpy (&fparegset, core_reg_sect, sizeof (fparegset));
458 supply_fparegset (&fparegset);
459 }
460 break;
461
462 default:
463 /* Don't know what kind of register request this is; just ignore it. */
464 break;
465 }
466 }
467
468 static struct core_fns arm_netbsd_core_fns =
469 {
470 bfd_target_unknown_flavour, /* core_flovour. */
471 default_check_format, /* check_format. */
472 default_core_sniffer, /* core_sniffer. */
473 fetch_core_registers, /* core_read_registers. */
474 NULL
475 };
476
477 static struct core_fns arm_netbsd_elfcore_fns =
478 {
479 bfd_target_elf_flavour, /* core_flovour. */
480 default_check_format, /* check_format. */
481 default_core_sniffer, /* core_sniffer. */
482 fetch_elfcore_registers, /* core_read_registers. */
483 NULL
484 };
485
486 void
487 _initialize_arm_netbsd_nat (void)
488 {
489 deprecated_add_core_fns (&arm_netbsd_core_fns);
490 deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
491 }
This page took 0.041125 seconds and 4 git commands to generate.