* armnbsd-nat.c: Include gdbcore.h.
[external/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 fetch_register (int regno)
42 {
43   struct reg inferior_registers;
44   int ret;
45
46   ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
47                 (PTRACE_ARG3_TYPE) &inferior_registers, 0);
48
49   if (ret < 0)
50     {
51       warning ("unable to fetch general register");
52       return;
53     }
54
55   switch (regno)
56     {
57     case ARM_SP_REGNUM:
58       supply_register (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
59       break;
60
61     case ARM_LR_REGNUM:
62       supply_register (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
63       break;
64
65     case ARM_PC_REGNUM:
66       /* This is ok: we're running native... */
67       inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc);
68       supply_register (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
69       break;
70
71     case ARM_PS_REGNUM:
72       if (arm_apcs_32)
73         supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr);
74       else
75         supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_pc);
76       break;
77
78     default:
79       supply_register (regno, (char *) &inferior_registers.r[regno]);
80       break;
81     }
82 }
83
84 static void
85 fetch_regs (void)
86 {
87   struct reg inferior_registers;
88   int ret;
89   int regno;
90
91   ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
92                 (PTRACE_ARG3_TYPE) &inferior_registers, 0);
93
94   if (ret < 0)
95     {
96       warning ("unable to fetch general registers");
97       return;
98     }
99
100   for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
101     supply_register (regno, (char *) &inferior_registers.r[regno]);
102
103   supply_register (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
104   supply_register (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
105   /* This is ok: we're running native... */
106   inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc);
107   supply_register (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
108
109   if (arm_apcs_32)
110     supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr);
111   else
112     supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_pc);
113 }
114
115 static void
116 fetch_fp_register (int regno)
117 {
118   struct fpreg inferior_fp_registers;
119   int ret;
120
121   ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
122                 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
123
124   if (ret < 0)
125     {
126       warning ("unable to fetch floating-point register");
127       return;
128     }
129
130   switch (regno)
131     {
132     case ARM_FPS_REGNUM:
133       supply_register (ARM_FPS_REGNUM,
134                        (char *) &inferior_fp_registers.fpr_fpsr);
135       break;
136
137     default:
138       supply_register
139         (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
140       break;
141     }
142 }
143
144 static void
145 fetch_fp_regs (void)
146 {
147   struct fpreg inferior_fp_registers;
148   int ret;
149   int regno;
150
151   ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
152                 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
153
154   if (ret < 0)
155     {
156       warning ("unable to fetch general registers");
157       return;
158     }
159
160   for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
161     supply_register
162       (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
163
164   supply_register (ARM_FPS_REGNUM, (char *) &inferior_fp_registers.fpr_fpsr);
165 }
166
167 void
168 fetch_inferior_registers (int regno)
169 {
170   if (regno >= 0)
171     {
172       if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
173         fetch_register (regno);
174       else
175         fetch_fp_register (regno);
176     }
177   else
178     {
179       fetch_regs ();
180       fetch_fp_regs ();
181     }
182 }
183
184
185 static void
186 store_register (int regno)
187 {
188   struct reg inferior_registers;
189   int ret;
190
191   ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
192                 (PTRACE_ARG3_TYPE) &inferior_registers, 0);
193
194   if (ret < 0)
195     {
196       warning ("unable to fetch general registers");
197       return;
198     }
199
200   switch (regno)
201     {
202     case ARM_SP_REGNUM:
203       regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
204       break;
205
206     case ARM_LR_REGNUM:
207       regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
208       break;
209
210     case ARM_PC_REGNUM:
211       if (arm_apcs_32)
212         regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
213       else
214         {
215           unsigned pc_val;
216
217           regcache_collect (ARM_PC_REGNUM, (char *) &pc_val);
218           
219           pc_val = ADDR_BITS_REMOVE (pc_val);
220           inferior_registers.r_pc
221             ^= ADDR_BITS_REMOVE (inferior_registers.r_pc);
222           inferior_registers.r_pc |= pc_val;
223         }
224       break;
225
226     case ARM_PS_REGNUM:
227       if (arm_apcs_32)
228         regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr);
229       else
230         {
231           unsigned psr_val;
232
233           regcache_collect (ARM_PS_REGNUM, (char *) &psr_val);
234
235           psr_val ^= ADDR_BITS_REMOVE (psr_val);
236           inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc);
237           inferior_registers.r_pc |= psr_val;
238         }
239       break;
240
241     default:
242       regcache_collect (regno, (char *) &inferior_registers.r[regno]);
243       break;
244     }
245
246   ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
247                 (PTRACE_ARG3_TYPE) &inferior_registers, 0);
248
249   if (ret < 0)
250     warning ("unable to write register %d to inferior", regno);
251 }
252
253 static void
254 store_regs (void)
255 {
256   struct reg inferior_registers;
257   int ret;
258   int regno;
259
260
261   for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
262     regcache_collect (regno, (char *) &inferior_registers.r[regno]);
263
264   regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
265   regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
266
267   if (arm_apcs_32)
268     {
269       regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
270       regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr);
271     }
272   else
273     {
274       unsigned pc_val;
275       unsigned psr_val;
276
277       regcache_collect (ARM_PC_REGNUM, (char *) &pc_val);
278       regcache_collect (ARM_PS_REGNUM, (char *) &psr_val);
279           
280       pc_val = ADDR_BITS_REMOVE (pc_val);
281       psr_val ^= ADDR_BITS_REMOVE (psr_val);
282
283       inferior_registers.r_pc = pc_val | psr_val;
284     }
285
286   ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
287                 (PTRACE_ARG3_TYPE) &inferior_registers, 0);
288
289   if (ret < 0)
290     warning ("unable to store general registers");
291 }
292
293 static void
294 store_fp_register (int regno)
295 {
296   struct fpreg inferior_fp_registers;
297   int ret;
298
299   ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
300                 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
301
302   if (ret < 0)
303     {
304       warning ("unable to fetch floating-point registers");
305       return;
306     }
307
308   switch (regno)
309     {
310     case ARM_FPS_REGNUM:
311       regcache_collect (ARM_FPS_REGNUM,
312                         (char *) &inferior_fp_registers.fpr_fpsr);
313       break;
314
315     default:
316       regcache_collect
317         (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
318       break;
319     }
320
321   ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
322                 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
323
324   if (ret < 0)
325     warning ("unable to write register %d to inferior", regno);
326 }
327
328 static void
329 store_fp_regs (void)
330 {
331   struct fpreg inferior_fp_registers;
332   int ret;
333   int regno;
334
335
336   for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
337     regcache_collect
338       (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
339
340   regcache_collect (ARM_FPS_REGNUM, (char *) &inferior_fp_registers.fpr_fpsr);
341
342   ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
343                 (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
344
345   if (ret < 0)
346     warning ("unable to store floating-point registers");
347 }
348
349 void
350 store_inferior_registers (int regno)
351 {
352   if (regno >= 0)
353     {
354       if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
355         store_register (regno);
356       else
357         store_fp_register (regno);
358     }
359   else
360     {
361       store_regs ();
362       store_fp_regs ();
363     }
364 }
365
366 struct md_core
367 {
368   struct reg intreg;
369   struct fpreg freg;
370 };
371
372 static void
373 fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
374                       int which, CORE_ADDR ignore)
375 {
376   struct md_core *core_reg = (struct md_core *) core_reg_sect;
377   int regno;
378   CORE_ADDR r_pc;
379   
380   /* Integer registers.  */
381   for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
382     supply_register (regno, (char *) &core_reg->intreg.r[regno]);
383
384   supply_register (ARM_SP_REGNUM, (char *) &core_reg->intreg.r_sp);
385   supply_register (ARM_LR_REGNUM, (char *) &core_reg->intreg.r_lr);
386   /* This is ok: we're running native...  */
387   r_pc = ADDR_BITS_REMOVE (core_reg->intreg.r_pc);
388   supply_register (ARM_PC_REGNUM, (char *) &r_pc);
389
390   if (arm_apcs_32)
391     supply_register (ARM_PS_REGNUM, (char *) &core_reg->intreg.r_cpsr);
392   else
393     supply_register (ARM_PS_REGNUM, (char *) &core_reg->intreg.r_pc);
394
395   /* Floating-point registers.  */
396   for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
397     supply_register
398       (regno, (char *) &core_reg->freg.fpr[regno - ARM_F0_REGNUM]);
399
400   supply_register (ARM_FPS_REGNUM, (char *) &core_reg->freg.fpr_fpsr);
401 }
402
403 static struct core_fns arm_netbsd_core_fns =
404 {
405   bfd_target_unknown_flavour,           /* core_flovour.  */
406   default_check_format,                 /* check_format.  */
407   default_core_sniffer,                 /* core_sniffer.  */
408   fetch_core_registers,                 /* core_read_registers.  */
409   NULL
410 };
411
412 void
413 _initialize_arm_netbsd_nat (void)
414 {
415   add_core_fns (&arm_netbsd_core_fns);
416 }