* alphabsd-nat.c (fetch_inferior_registers):
[external/binutils.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 }