Fix typo in ChangeLog entry.
[deliverable/binutils-gdb.git] / gdb / armnbsd-nat.c
CommitLineData
e7a42bc8 1/* Native-dependent code for BSD Unix running on ARM's, for GDB.
34e8f22d
RE
2 Copyright 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002
3 Free Software Foundation, Inc.
e7a42bc8
FN
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
3e56fc4b
RE
24#ifndef FETCH_INFERIOR_REGISTERS
25#error Not FETCH_INFERIOR_REGISTERS
26#endif /* !FETCH_INFERIOR_REGISTERS */
27
34e8f22d
RE
28#include "arm-tdep.h"
29
e7a42bc8
FN
30#include <sys/types.h>
31#include <sys/ptrace.h>
32#include <machine/reg.h>
33#include <machine/frame.h>
34#include "inferior.h"
97e03143 35#include "regcache.h"
3e56fc4b 36#include "gdbcore.h"
e7a42bc8 37
47221191
RE
38extern int arm_apcs_32;
39
b34db576
RE
40static void
41supply_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
62static void
63supply_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
47221191
RE
74static void
75fetch_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
118static void
3e56fc4b 119fetch_regs (void)
e7a42bc8
FN
120{
121 struct reg inferior_registers;
47221191
RE
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
b34db576 134 supply_gregset (&inferior_registers);
47221191
RE
135}
136
137static void
138fetch_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
166static void
3e56fc4b 167fetch_fp_regs (void)
47221191
RE
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
b34db576 182 supply_fparegset (&inferior_fp_registers);
e7a42bc8
FN
183}
184
185void
47221191
RE
186fetch_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
203static void
204store_register (int regno)
e7a42bc8
FN
205{
206 struct reg inferior_registers;
47221191
RE
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;
e7a42bc8 227
47221191
RE
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;
e7a42bc8 234
47221191
RE
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
271static void
3e56fc4b 272store_regs (void)
47221191
RE
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
311static void
312store_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
346static void
3e56fc4b 347store_fp_regs (void)
47221191
RE
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
367void
368store_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 }
e7a42bc8
FN
382}
383
384struct md_core
385{
386 struct reg intreg;
387 struct fpreg freg;
388};
389
3e56fc4b 390static void
47221191
RE
391fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
392 int which, CORE_ADDR ignore)
e7a42bc8
FN
393{
394 struct md_core *core_reg = (struct md_core *) core_reg_sect;
3e56fc4b
RE
395 int regno;
396 CORE_ADDR r_pc;
3e56fc4b 397
b34db576
RE
398 supply_gregset (&core_reg->intreg);
399 supply_fparegset (&core_reg->freg);
400}
3e56fc4b 401
b34db576
RE
402static void
403fetch_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;
e7a42bc8 408
b34db576
RE
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;
3e56fc4b 434
b34db576
RE
435 default:
436 /* Don't know what kind of register request this is; just ignore it. */
437 break;
438 }
e7a42bc8
FN
439}
440
3e56fc4b
RE
441static 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
b34db576
RE
450static 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
3e56fc4b
RE
459void
460_initialize_arm_netbsd_nat (void)
461{
462 add_core_fns (&arm_netbsd_core_fns);
b34db576 463 add_core_fns (&arm_netbsd_elfcore_fns);
3e56fc4b 464}
This page took 0.205331 seconds and 4 git commands to generate.