2004-04-22 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / ppcnbsd-tdep.c
CommitLineData
485721b1 1/* Target-dependent code for PowerPC systems running NetBSD.
4be87837 2 Copyright 2002, 2003 Free Software Foundation, Inc.
485721b1
JT
3 Contributed by Wasabi Systems, 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#include "gdbcore.h"
24#include "regcache.h"
25#include "target.h"
26#include "breakpoint.h"
27#include "value.h"
4be87837 28#include "osabi.h"
485721b1
JT
29
30#include "ppc-tdep.h"
31#include "ppcnbsd-tdep.h"
32#include "nbsd-tdep.h"
33
34#include "solib-svr4.h"
35
36#define REG_FIXREG_OFFSET(x) ((x) * 4)
37#define REG_LR_OFFSET (32 * 4)
38#define REG_CR_OFFSET (33 * 4)
39#define REG_XER_OFFSET (34 * 4)
40#define REG_CTR_OFFSET (35 * 4)
41#define REG_PC_OFFSET (36 * 4)
42#define SIZEOF_STRUCT_REG (37 * 4)
43
44#define FPREG_FPR_OFFSET(x) ((x) * 8)
45#define FPREG_FPSCR_OFFSET (32 * 8)
46#define SIZEOF_STRUCT_FPREG (33 * 8)
47
48void
49ppcnbsd_supply_reg (char *regs, int regno)
50{
51 struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
52 int i;
53
54 for (i = 0; i <= 31; i++)
55 {
56 if (regno == i || regno == -1)
57 supply_register (i, regs + REG_FIXREG_OFFSET (i));
58 }
59
60 if (regno == tdep->ppc_lr_regnum || regno == -1)
61 supply_register (tdep->ppc_lr_regnum, regs + REG_LR_OFFSET);
62
63 if (regno == tdep->ppc_cr_regnum || regno == -1)
64 supply_register (tdep->ppc_cr_regnum, regs + REG_CR_OFFSET);
65
66 if (regno == tdep->ppc_xer_regnum || regno == -1)
67 supply_register (tdep->ppc_xer_regnum, regs + REG_XER_OFFSET);
68
69 if (regno == tdep->ppc_ctr_regnum || regno == -1)
70 supply_register (tdep->ppc_ctr_regnum, regs + REG_CTR_OFFSET);
71
72 if (regno == PC_REGNUM || regno == -1)
73 supply_register (PC_REGNUM, regs + REG_PC_OFFSET);
74}
75
76void
77ppcnbsd_fill_reg (char *regs, int regno)
78{
79 struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
80 int i;
81
82 for (i = 0; i <= 31; i++)
83 {
84 if (regno == i || regno == -1)
85 regcache_collect (i, regs + REG_FIXREG_OFFSET (i));
86 }
87
88 if (regno == tdep->ppc_lr_regnum || regno == -1)
89 regcache_collect (tdep->ppc_lr_regnum, regs + REG_LR_OFFSET);
90
91 if (regno == tdep->ppc_cr_regnum || regno == -1)
92 regcache_collect (tdep->ppc_cr_regnum, regs + REG_CR_OFFSET);
93
94 if (regno == tdep->ppc_xer_regnum || regno == -1)
95 regcache_collect (tdep->ppc_xer_regnum, regs + REG_XER_OFFSET);
96
97 if (regno == tdep->ppc_ctr_regnum || regno == -1)
98 regcache_collect (tdep->ppc_ctr_regnum, regs + REG_CTR_OFFSET);
99
100 if (regno == PC_REGNUM || regno == -1)
101 regcache_collect (PC_REGNUM, regs + REG_PC_OFFSET);
102}
103
104void
105ppcnbsd_supply_fpreg (char *fpregs, int regno)
106{
107 struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
108 int i;
109
110 for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
111 {
112 if (regno == i || regno == -1)
113 supply_register (i, fpregs + FPREG_FPR_OFFSET (i - FP0_REGNUM));
114 }
115
116 if (regno == tdep->ppc_fpscr_regnum || regno == -1)
117 supply_register (tdep->ppc_fpscr_regnum, fpregs + FPREG_FPSCR_OFFSET);
118}
119
120void
121ppcnbsd_fill_fpreg (char *fpregs, int regno)
122{
123 struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
124 int i;
125
126 for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
127 {
128 if (regno == i || regno == -1)
129 regcache_collect (i, fpregs + FPREG_FPR_OFFSET (i - FP0_REGNUM));
130 }
131
132 if (regno == tdep->ppc_fpscr_regnum || regno == -1)
133 regcache_collect (tdep->ppc_fpscr_regnum, fpregs + FPREG_FPSCR_OFFSET);
134}
135
136static void
137fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
138 CORE_ADDR ignore)
139{
140 char *regs, *fpregs;
141
142 /* We get everything from one section. */
143 if (which != 0)
144 return;
145
146 regs = core_reg_sect;
147 fpregs = core_reg_sect + SIZEOF_STRUCT_REG;
148
149 /* Integer registers. */
150 ppcnbsd_supply_reg (regs, -1);
151
152 /* Floating point registers. */
153 ppcnbsd_supply_fpreg (fpregs, -1);
154}
155
156static void
157fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, int which,
158 CORE_ADDR ignore)
159{
160 switch (which)
161 {
162 case 0: /* Integer registers. */
163 if (core_reg_size != SIZEOF_STRUCT_REG)
164 warning ("Wrong size register set in core file.");
165 else
166 ppcnbsd_supply_reg (core_reg_sect, -1);
167 break;
168
169 case 2: /* Floating point registers. */
170 if (core_reg_size != SIZEOF_STRUCT_FPREG)
171 warning ("Wrong size FP register set in core file.");
172 else
173 ppcnbsd_supply_fpreg (core_reg_sect, -1);
174 break;
175
176 default:
177 /* Don't know what kind of register request this is; just ignore it. */
178 break;
179 }
180}
181
182static struct core_fns ppcnbsd_core_fns =
183{
184 bfd_target_unknown_flavour, /* core_flavour */
185 default_check_format, /* check_format */
186 default_core_sniffer, /* core_sniffer */
187 fetch_core_registers, /* core_read_registers */
188 NULL /* next */
189};
190
191static struct core_fns ppcnbsd_elfcore_fns =
192{
193 bfd_target_elf_flavour, /* core_flavour */
194 default_check_format, /* check_format */
195 default_core_sniffer, /* core_sniffer */
196 fetch_elfcore_registers, /* core_read_registers */
197 NULL /* next */
198};
199
3d9b49b0
JT
200static int
201ppcnbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
202{
203 /* FIXME: Need to add support for kernel-provided signal trampolines. */
204 return (nbsd_pc_in_sigtramp (pc, func_name));
205}
206
957e27ac
AC
207/* NetBSD is confused. It appears that 1.5 was using the correct SVr4
208 convention but, 1.6 switched to the below broken convention. For
209 the moment use the broken convention. Ulgh!. */
210
05580c65
AC
211static enum return_value_convention
212ppcnbsd_return_value (struct gdbarch *gdbarch, struct type *valtype,
963e2bb7
AC
213 struct regcache *regcache, void *readbuf,
214 const void *writebuf)
05580c65
AC
215{
216 if ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT
217 || TYPE_CODE (valtype) == TYPE_CODE_UNION)
218 && !((TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 8)
219 && TYPE_VECTOR (valtype))
220 && !(TYPE_LENGTH (valtype) == 1
221 || TYPE_LENGTH (valtype) == 2
222 || TYPE_LENGTH (valtype) == 4
223 || TYPE_LENGTH (valtype) == 8))
224 return RETURN_VALUE_STRUCT_CONVENTION;
225 else
226 return ppc_sysv_abi_broken_return_value (gdbarch, valtype, regcache,
963e2bb7 227 readbuf, writebuf);
957e27ac
AC
228}
229
485721b1
JT
230static void
231ppcnbsd_init_abi (struct gdbarch_info info,
232 struct gdbarch *gdbarch)
233{
f561f026 234 set_gdbarch_deprecated_pc_in_sigtramp (gdbarch, ppcnbsd_pc_in_sigtramp);
e754ae69
AC
235 /* For NetBSD, this is an on again, off again thing. Some systems
236 do use the broken struct convention, and some don't. */
05580c65 237 set_gdbarch_return_value (gdbarch, ppcnbsd_return_value);
485721b1
JT
238 set_solib_svr4_fetch_link_map_offsets (gdbarch,
239 nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
240}
241
242void
243_initialize_ppcnbsd_tdep (void)
244{
05816f70 245 gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_NETBSD_ELF,
485721b1
JT
246 ppcnbsd_init_abi);
247
00e32a35
AC
248 deprecated_add_core_fns (&ppcnbsd_core_fns);
249 deprecated_add_core_fns (&ppcnbsd_elfcore_fns);
485721b1 250}
This page took 0.408227 seconds and 4 git commands to generate.