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