* arm-tdep.c (arm_extract_return_value, arm_store_return_value):
[deliverable/binutils-gdb.git] / gdb / armnbsd-nat.c
CommitLineData
e7a42bc8 1/* Native-dependent code for BSD Unix running on ARM's, for GDB.
9f8e0089
MK
2
3 Copyright 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002, 2004
34e8f22d 4 Free Software Foundation, Inc.
e7a42bc8
FN
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
3e56fc4b
RE
25#ifndef FETCH_INFERIOR_REGISTERS
26#error Not FETCH_INFERIOR_REGISTERS
27#endif /* !FETCH_INFERIOR_REGISTERS */
28
34e8f22d
RE
29#include "arm-tdep.h"
30
e7a42bc8
FN
31#include <sys/types.h>
32#include <sys/ptrace.h>
33#include <machine/reg.h>
34#include <machine/frame.h>
35#include "inferior.h"
97e03143 36#include "regcache.h"
3e56fc4b 37#include "gdbcore.h"
e7a42bc8 38
47221191
RE
39extern int arm_apcs_32;
40
b34db576
RE
41static void
42supply_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++)
23a6d369 49 regcache_raw_supply (current_regcache, regno, (char *) &gregset->r[regno]);
b34db576 50
23a6d369
AC
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);
b34db576
RE
55 /* This is ok: we're running native... */
56 r_pc = ADDR_BITS_REMOVE (gregset->r_pc);
23a6d369 57 regcache_raw_supply (current_regcache, ARM_PC_REGNUM, (char *) &r_pc);
b34db576
RE
58
59 if (arm_apcs_32)
23a6d369
AC
60 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
61 (char *) &gregset->r_cpsr);
b34db576 62 else
23a6d369
AC
63 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
64 (char *) &gregset->r_pc);
b34db576
RE
65}
66
67static void
68supply_fparegset (struct fpreg *fparegset)
69{
70 int regno;
71
72 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
23a6d369
AC
73 regcache_raw_supply (current_regcache, regno,
74 (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]);
b34db576 75
23a6d369
AC
76 regcache_raw_supply (current_regcache, ARM_FPS_REGNUM,
77 (char *) &fparegset->fpr_fpsr);
b34db576
RE
78}
79
47221191
RE
80static void
81fetch_register (int regno)
82{
83 struct reg inferior_registers;
84 int ret;
85
86 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 87 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
88
89 if (ret < 0)
90 {
edefbb7c 91 warning (_("unable to fetch general register"));
47221191
RE
92 return;
93 }
94
95 switch (regno)
96 {
97 case ARM_SP_REGNUM:
23a6d369
AC
98 regcache_raw_supply (current_regcache, ARM_SP_REGNUM,
99 (char *) &inferior_registers.r_sp);
47221191
RE
100 break;
101
102 case ARM_LR_REGNUM:
23a6d369
AC
103 regcache_raw_supply (current_regcache, ARM_LR_REGNUM,
104 (char *) &inferior_registers.r_lr);
47221191
RE
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);
23a6d369
AC
110 regcache_raw_supply (current_regcache, ARM_PC_REGNUM,
111 (char *) &inferior_registers.r_pc);
47221191
RE
112 break;
113
114 case ARM_PS_REGNUM:
115 if (arm_apcs_32)
23a6d369
AC
116 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
117 (char *) &inferior_registers.r_cpsr);
47221191 118 else
23a6d369
AC
119 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
120 (char *) &inferior_registers.r_pc);
47221191
RE
121 break;
122
123 default:
23a6d369
AC
124 regcache_raw_supply (current_regcache, regno,
125 (char *) &inferior_registers.r[regno]);
47221191
RE
126 break;
127 }
128}
129
130static void
3e56fc4b 131fetch_regs (void)
e7a42bc8
FN
132{
133 struct reg inferior_registers;
47221191
RE
134 int ret;
135 int regno;
136
137 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 138 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
139
140 if (ret < 0)
141 {
edefbb7c 142 warning (_("unable to fetch general registers"));
47221191
RE
143 return;
144 }
145
b34db576 146 supply_gregset (&inferior_registers);
47221191
RE
147}
148
149static void
150fetch_fp_register (int regno)
151{
152 struct fpreg inferior_fp_registers;
153 int ret;
154
155 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 156 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
157
158 if (ret < 0)
159 {
edefbb7c 160 warning (_("unable to fetch floating-point register"));
47221191
RE
161 return;
162 }
163
164 switch (regno)
165 {
166 case ARM_FPS_REGNUM:
23a6d369
AC
167 regcache_raw_supply (current_regcache, ARM_FPS_REGNUM,
168 (char *) &inferior_fp_registers.fpr_fpsr);
47221191
RE
169 break;
170
171 default:
23a6d369
AC
172 regcache_raw_supply (current_regcache, regno,
173 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
47221191
RE
174 break;
175 }
176}
177
178static void
3e56fc4b 179fetch_fp_regs (void)
47221191
RE
180{
181 struct fpreg inferior_fp_registers;
182 int ret;
183 int regno;
184
185 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 186 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
187
188 if (ret < 0)
189 {
edefbb7c 190 warning (_("unable to fetch general registers"));
47221191
RE
191 return;
192 }
193
b34db576 194 supply_fparegset (&inferior_fp_registers);
e7a42bc8
FN
195}
196
197void
47221191
RE
198fetch_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
215static void
216store_register (int regno)
e7a42bc8
FN
217{
218 struct reg inferior_registers;
47221191
RE
219 int ret;
220
221 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 222 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
223
224 if (ret < 0)
225 {
edefbb7c 226 warning (_("unable to fetch general registers"));
47221191
RE
227 return;
228 }
229
230 switch (regno)
231 {
232 case ARM_SP_REGNUM:
822c9732
AC
233 regcache_raw_collect (current_regcache, ARM_SP_REGNUM,
234 (char *) &inferior_registers.r_sp);
47221191
RE
235 break;
236
237 case ARM_LR_REGNUM:
822c9732
AC
238 regcache_raw_collect (current_regcache, ARM_LR_REGNUM,
239 (char *) &inferior_registers.r_lr);
47221191 240 break;
e7a42bc8 241
47221191
RE
242 case ARM_PC_REGNUM:
243 if (arm_apcs_32)
822c9732
AC
244 regcache_raw_collect (current_regcache, ARM_PC_REGNUM,
245 (char *) &inferior_registers.r_pc);
47221191
RE
246 else
247 {
248 unsigned pc_val;
e7a42bc8 249
822c9732
AC
250 regcache_raw_collect (current_regcache, ARM_PC_REGNUM,
251 (char *) &pc_val);
47221191
RE
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)
822c9732
AC
262 regcache_raw_collect (current_regcache, ARM_PS_REGNUM,
263 (char *) &inferior_registers.r_cpsr);
47221191
RE
264 else
265 {
266 unsigned psr_val;
267
822c9732
AC
268 regcache_raw_collect (current_regcache, ARM_PS_REGNUM,
269 (char *) &psr_val);
47221191
RE
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:
822c9732
AC
278 regcache_raw_collect (current_regcache, regno,
279 (char *) &inferior_registers.r[regno]);
47221191
RE
280 break;
281 }
282
283 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
9f8e0089 284 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
285
286 if (ret < 0)
edefbb7c 287 warning (_("unable to write register %d to inferior"), regno);
47221191
RE
288}
289
290static void
3e56fc4b 291store_regs (void)
47221191
RE
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++)
822c9732
AC
299 regcache_raw_collect (current_regcache, regno,
300 (char *) &inferior_registers.r[regno]);
47221191 301
822c9732
AC
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);
47221191
RE
306
307 if (arm_apcs_32)
308 {
822c9732
AC
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);
47221191
RE
313 }
314 else
315 {
316 unsigned pc_val;
317 unsigned psr_val;
318
822c9732
AC
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);
47221191
RE
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),
9f8e0089 331 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
47221191
RE
332
333 if (ret < 0)
edefbb7c 334 warning (_("unable to store general registers"));
47221191
RE
335}
336
337static void
338store_fp_register (int regno)
339{
340 struct fpreg inferior_fp_registers;
341 int ret;
342
343 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 344 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
345
346 if (ret < 0)
347 {
edefbb7c 348 warning (_("unable to fetch floating-point registers"));
47221191
RE
349 return;
350 }
351
352 switch (regno)
353 {
354 case ARM_FPS_REGNUM:
822c9732
AC
355 regcache_raw_collect (current_regcache, ARM_FPS_REGNUM,
356 (char *) &inferior_fp_registers.fpr_fpsr);
47221191
RE
357 break;
358
359 default:
822c9732
AC
360 regcache_raw_collect (current_regcache, regno,
361 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
47221191
RE
362 break;
363 }
364
365 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
9f8e0089 366 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
367
368 if (ret < 0)
edefbb7c 369 warning (_("unable to write register %d to inferior"), regno);
47221191
RE
370}
371
372static void
3e56fc4b 373store_fp_regs (void)
47221191
RE
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++)
822c9732
AC
381 regcache_raw_collect (current_regcache, regno,
382 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
47221191 383
822c9732
AC
384 regcache_raw_collect (current_regcache, ARM_FPS_REGNUM,
385 (char *) &inferior_fp_registers.fpr_fpsr);
47221191
RE
386
387 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
9f8e0089 388 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
47221191
RE
389
390 if (ret < 0)
edefbb7c 391 warning (_("unable to store floating-point registers"));
47221191
RE
392}
393
394void
395store_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 }
e7a42bc8
FN
409}
410
411struct md_core
412{
413 struct reg intreg;
414 struct fpreg freg;
415};
416
3e56fc4b 417static void
47221191
RE
418fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
419 int which, CORE_ADDR ignore)
e7a42bc8
FN
420{
421 struct md_core *core_reg = (struct md_core *) core_reg_sect;
3e56fc4b
RE
422 int regno;
423 CORE_ADDR r_pc;
3e56fc4b 424
b34db576
RE
425 supply_gregset (&core_reg->intreg);
426 supply_fparegset (&core_reg->freg);
427}
3e56fc4b 428
b34db576
RE
429static void
430fetch_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;
e7a42bc8 435
b34db576
RE
436 switch (which)
437 {
438 case 0: /* Integer registers. */
439 if (core_reg_size != sizeof (struct reg))
edefbb7c 440 warning (_("wrong size of register set in core file"));
b34db576
RE
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))
edefbb7c 452 warning (_("wrong size of FPA register set in core file"));
b34db576
RE
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;
3e56fc4b 461
b34db576
RE
462 default:
463 /* Don't know what kind of register request this is; just ignore it. */
464 break;
465 }
e7a42bc8
FN
466}
467
3e56fc4b
RE
468static 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
b34db576
RE
477static 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
3e56fc4b
RE
486void
487_initialize_arm_netbsd_nat (void)
488{
00e32a35
AC
489 deprecated_add_core_fns (&arm_netbsd_core_fns);
490 deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
3e56fc4b 491}
This page took 0.295803 seconds and 4 git commands to generate.