Replace copyreloc-main.c with copyreloc-main.S
[platform/upstream/binutils.git] / gdb / armnbsd-nat.c
1 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
2
3    Copyright (C) 1988-2014 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 3 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, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21 #include "gdbcore.h"
22 #include "inferior.h"
23 #include "regcache.h"
24 #include "target.h"
25 #include <sys/types.h>
26 #include <sys/ptrace.h>
27 #include <machine/reg.h>
28 #include <machine/frame.h>
29
30 #include "arm-tdep.h"
31 #include "inf-ptrace.h"
32
33 extern int arm_apcs_32;
34
35 static void
36 arm_supply_gregset (struct regcache *regcache, struct reg *gregset)
37 {
38   int regno;
39   CORE_ADDR r_pc;
40
41   /* Integer registers.  */
42   for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
43     regcache_raw_supply (regcache, regno, (char *) &gregset->r[regno]);
44
45   regcache_raw_supply (regcache, ARM_SP_REGNUM,
46                        (char *) &gregset->r_sp);
47   regcache_raw_supply (regcache, ARM_LR_REGNUM,
48                        (char *) &gregset->r_lr);
49   /* This is ok: we're running native...  */
50   r_pc = gdbarch_addr_bits_remove (get_regcache_arch (regcache), gregset->r_pc);
51   regcache_raw_supply (regcache, ARM_PC_REGNUM, (char *) &r_pc);
52
53   if (arm_apcs_32)
54     regcache_raw_supply (regcache, ARM_PS_REGNUM,
55                          (char *) &gregset->r_cpsr);
56   else
57     regcache_raw_supply (regcache, ARM_PS_REGNUM,
58                          (char *) &gregset->r_pc);
59 }
60
61 static void
62 arm_supply_fparegset (struct regcache *regcache, struct fpreg *fparegset)
63 {
64   int regno;
65
66   for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
67     regcache_raw_supply (regcache, regno,
68                          (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]);
69
70   regcache_raw_supply (regcache, ARM_FPS_REGNUM,
71                        (char *) &fparegset->fpr_fpsr);
72 }
73
74 static void
75 fetch_register (struct regcache *regcache, int regno)
76 {
77   struct reg inferior_registers;
78   int ret;
79
80   ret = ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid),
81                 (PTRACE_TYPE_ARG3) &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       regcache_raw_supply (regcache, ARM_SP_REGNUM,
93                            (char *) &inferior_registers.r_sp);
94       break;
95
96     case ARM_LR_REGNUM:
97       regcache_raw_supply (regcache, ARM_LR_REGNUM,
98                            (char *) &inferior_registers.r_lr);
99       break;
100
101     case ARM_PC_REGNUM:
102       /* This is ok: we're running native...  */
103       inferior_registers.r_pc = gdbarch_addr_bits_remove
104                                   (get_regcache_arch (regcache),
105                                    inferior_registers.r_pc);
106       regcache_raw_supply (regcache, ARM_PC_REGNUM,
107                            (char *) &inferior_registers.r_pc);
108       break;
109
110     case ARM_PS_REGNUM:
111       if (arm_apcs_32)
112         regcache_raw_supply (regcache, ARM_PS_REGNUM,
113                              (char *) &inferior_registers.r_cpsr);
114       else
115         regcache_raw_supply (regcache, ARM_PS_REGNUM,
116                              (char *) &inferior_registers.r_pc);
117       break;
118
119     default:
120       regcache_raw_supply (regcache, regno,
121                            (char *) &inferior_registers.r[regno]);
122       break;
123     }
124 }
125
126 static void
127 fetch_regs (struct regcache *regcache)
128 {
129   struct reg inferior_registers;
130   int ret;
131   int regno;
132
133   ret = ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid),
134                 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
135
136   if (ret < 0)
137     {
138       warning (_("unable to fetch general registers"));
139       return;
140     }
141
142   arm_supply_gregset (regcache, &inferior_registers);
143 }
144
145 static void
146 fetch_fp_register (struct regcache *regcache, int regno)
147 {
148   struct fpreg inferior_fp_registers;
149   int ret;
150
151   ret = ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid),
152                 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
153
154   if (ret < 0)
155     {
156       warning (_("unable to fetch floating-point register"));
157       return;
158     }
159
160   switch (regno)
161     {
162     case ARM_FPS_REGNUM:
163       regcache_raw_supply (regcache, ARM_FPS_REGNUM,
164                            (char *) &inferior_fp_registers.fpr_fpsr);
165       break;
166
167     default:
168       regcache_raw_supply (regcache, regno,
169                            (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
170       break;
171     }
172 }
173
174 static void
175 fetch_fp_regs (struct regcache *regcache)
176 {
177   struct fpreg inferior_fp_registers;
178   int ret;
179   int regno;
180
181   ret = ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid),
182                 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
183
184   if (ret < 0)
185     {
186       warning (_("unable to fetch general registers"));
187       return;
188     }
189
190   arm_supply_fparegset (regcache, &inferior_fp_registers);
191 }
192
193 static void
194 armnbsd_fetch_registers (struct target_ops *ops,
195                          struct regcache *regcache, int regno)
196 {
197   if (regno >= 0)
198     {
199       if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
200         fetch_register (regcache, regno);
201       else
202         fetch_fp_register (regcache, regno);
203     }
204   else
205     {
206       fetch_regs (regcache);
207       fetch_fp_regs (regcache);
208     }
209 }
210
211
212 static void
213 store_register (const struct regcache *regcache, int regno)
214 {
215   struct gdbarch *gdbarch = get_regcache_arch (regcache);
216   struct reg inferior_registers;
217   int ret;
218
219   ret = ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid),
220                 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
221
222   if (ret < 0)
223     {
224       warning (_("unable to fetch general registers"));
225       return;
226     }
227
228   switch (regno)
229     {
230     case ARM_SP_REGNUM:
231       regcache_raw_collect (regcache, ARM_SP_REGNUM,
232                             (char *) &inferior_registers.r_sp);
233       break;
234
235     case ARM_LR_REGNUM:
236       regcache_raw_collect (regcache, ARM_LR_REGNUM,
237                             (char *) &inferior_registers.r_lr);
238       break;
239
240     case ARM_PC_REGNUM:
241       if (arm_apcs_32)
242         regcache_raw_collect (regcache, ARM_PC_REGNUM,
243                               (char *) &inferior_registers.r_pc);
244       else
245         {
246           unsigned pc_val;
247
248           regcache_raw_collect (regcache, ARM_PC_REGNUM,
249                                 (char *) &pc_val);
250           
251           pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
252           inferior_registers.r_pc ^= gdbarch_addr_bits_remove
253                                        (gdbarch, inferior_registers.r_pc);
254           inferior_registers.r_pc |= pc_val;
255         }
256       break;
257
258     case ARM_PS_REGNUM:
259       if (arm_apcs_32)
260         regcache_raw_collect (regcache, ARM_PS_REGNUM,
261                               (char *) &inferior_registers.r_cpsr);
262       else
263         {
264           unsigned psr_val;
265
266           regcache_raw_collect (regcache, ARM_PS_REGNUM,
267                                 (char *) &psr_val);
268
269           psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
270           inferior_registers.r_pc = gdbarch_addr_bits_remove
271                                       (gdbarch, inferior_registers.r_pc);
272           inferior_registers.r_pc |= psr_val;
273         }
274       break;
275
276     default:
277       regcache_raw_collect (regcache, regno,
278                             (char *) &inferior_registers.r[regno]);
279       break;
280     }
281
282   ret = ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid),
283                 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
284
285   if (ret < 0)
286     warning (_("unable to write register %d to inferior"), regno);
287 }
288
289 static void
290 store_regs (const struct regcache *regcache)
291 {
292   struct gdbarch *gdbarch = get_regcache_arch (regcache);
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 (regcache, regno,
300                           (char *) &inferior_registers.r[regno]);
301
302   regcache_raw_collect (regcache, ARM_SP_REGNUM,
303                         (char *) &inferior_registers.r_sp);
304   regcache_raw_collect (regcache, ARM_LR_REGNUM,
305                         (char *) &inferior_registers.r_lr);
306
307   if (arm_apcs_32)
308     {
309       regcache_raw_collect (regcache, ARM_PC_REGNUM,
310                             (char *) &inferior_registers.r_pc);
311       regcache_raw_collect (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 (regcache, ARM_PC_REGNUM,
320                             (char *) &pc_val);
321       regcache_raw_collect (regcache, ARM_PS_REGNUM,
322                             (char *) &psr_val);
323           
324       pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
325       psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
326
327       inferior_registers.r_pc = pc_val | psr_val;
328     }
329
330   ret = ptrace (PT_SETREGS, ptid_get_pid (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 (const struct regcache *regcache, int regno)
339 {
340   struct fpreg inferior_fp_registers;
341   int ret;
342
343   ret = ptrace (PT_GETFPREGS, ptid_get_pid (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 (regcache, ARM_FPS_REGNUM,
356                             (char *) &inferior_fp_registers.fpr_fpsr);
357       break;
358
359     default:
360       regcache_raw_collect (regcache, regno,
361                             (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
362       break;
363     }
364
365   ret = ptrace (PT_SETFPREGS, ptid_get_pid (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 (const struct regcache *regcache)
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 (regcache, regno,
382                           (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
383
384   regcache_raw_collect (regcache, ARM_FPS_REGNUM,
385                         (char *) &inferior_fp_registers.fpr_fpsr);
386
387   ret = ptrace (PT_SETFPREGS, ptid_get_pid (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 static void
395 armnbsd_store_registers (struct target_ops *ops,
396                          struct regcache *regcache, int regno)
397 {
398   if (regno >= 0)
399     {
400       if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
401         store_register (regcache, regno);
402       else
403         store_fp_register (regcache, regno);
404     }
405   else
406     {
407       store_regs (regcache);
408       store_fp_regs (regcache);
409     }
410 }
411
412 struct md_core
413 {
414   struct reg intreg;
415   struct fpreg freg;
416 };
417
418 static void
419 fetch_core_registers (struct regcache *regcache,
420                       char *core_reg_sect, unsigned core_reg_size,
421                       int which, CORE_ADDR ignore)
422 {
423   struct md_core *core_reg = (struct md_core *) core_reg_sect;
424   int regno;
425   CORE_ADDR r_pc;
426
427   arm_supply_gregset (regcache, &core_reg->intreg);
428   arm_supply_fparegset (regcache, &core_reg->freg);
429 }
430
431 static void
432 fetch_elfcore_registers (struct regcache *regcache,
433                          char *core_reg_sect, unsigned core_reg_size,
434                          int which, CORE_ADDR ignore)
435 {
436   struct reg gregset;
437   struct fpreg fparegset;
438
439   switch (which)
440     {
441     case 0:     /* Integer registers.  */
442       if (core_reg_size != sizeof (struct reg))
443         warning (_("wrong size of register set in core file"));
444       else
445         {
446           /* The memcpy may be unnecessary, but we can't really be sure
447              of the alignment of the data in the core file.  */
448           memcpy (&gregset, core_reg_sect, sizeof (gregset));
449           arm_supply_gregset (regcache, &gregset);
450         }
451       break;
452
453     case 2:
454       if (core_reg_size != sizeof (struct fpreg))
455         warning (_("wrong size of FPA register set in core file"));
456       else
457         {
458           /* The memcpy may be unnecessary, but we can't really be sure
459              of the alignment of the data in the core file.  */
460           memcpy (&fparegset, core_reg_sect, sizeof (fparegset));
461           arm_supply_fparegset (regcache, &fparegset);
462         }
463       break;
464
465     default:
466       /* Don't know what kind of register request this is; just ignore it.  */
467       break;
468     }
469 }
470
471 static struct core_fns arm_netbsd_core_fns =
472 {
473   bfd_target_unknown_flavour,           /* core_flovour.  */
474   default_check_format,                 /* check_format.  */
475   default_core_sniffer,                 /* core_sniffer.  */
476   fetch_core_registers,                 /* core_read_registers.  */
477   NULL
478 };
479
480 static struct core_fns arm_netbsd_elfcore_fns =
481 {
482   bfd_target_elf_flavour,               /* core_flovour.  */
483   default_check_format,                 /* check_format.  */
484   default_core_sniffer,                 /* core_sniffer.  */
485   fetch_elfcore_registers,              /* core_read_registers.  */
486   NULL
487 };
488
489 void
490 _initialize_arm_netbsd_nat (void)
491 {
492   struct target_ops *t;
493
494   t = inf_ptrace_target ();
495   t->to_fetch_registers = armnbsd_fetch_registers;
496   t->to_store_registers = armnbsd_store_registers;
497   add_target (t);
498
499   deprecated_add_core_fns (&arm_netbsd_core_fns);
500   deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
501 }