2003-11-07 Christian Groessler <chris@groessler.org>
[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
211static int
212ppcnbsd_use_struct_convention (int gcc_p, struct type *value_type)
213{
214 if ((TYPE_LENGTH (value_type) == 16 || TYPE_LENGTH (value_type) == 8)
215 && TYPE_VECTOR (value_type))
216 return 0;
217
218 return !(TYPE_LENGTH (value_type) == 1
219 || TYPE_LENGTH (value_type) == 2
220 || TYPE_LENGTH (value_type) == 4
221 || TYPE_LENGTH (value_type) == 8);
222}
223
485721b1
JT
224static void
225ppcnbsd_init_abi (struct gdbarch_info info,
226 struct gdbarch *gdbarch)
227{
3d9b49b0 228 set_gdbarch_pc_in_sigtramp (gdbarch, ppcnbsd_pc_in_sigtramp);
e754ae69
AC
229 /* For NetBSD, this is an on again, off again thing. Some systems
230 do use the broken struct convention, and some don't. */
957e27ac 231 set_gdbarch_use_struct_convention (gdbarch, ppcnbsd_use_struct_convention);
e754ae69
AC
232 set_gdbarch_extract_return_value (gdbarch, ppc_sysv_abi_broken_extract_return_value);
233 set_gdbarch_store_return_value (gdbarch, ppc_sysv_abi_broken_store_return_value);
485721b1
JT
234 set_solib_svr4_fetch_link_map_offsets (gdbarch,
235 nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
236}
237
238void
239_initialize_ppcnbsd_tdep (void)
240{
05816f70 241 gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_NETBSD_ELF,
485721b1
JT
242 ppcnbsd_init_abi);
243
244 add_core_fns (&ppcnbsd_core_fns);
245 add_core_fns (&ppcnbsd_elfcore_fns);
246}
This page took 0.191148 seconds and 4 git commands to generate.