* spu-tdep.c: Update for unwinder changes.
[deliverable/binutils-gdb.git] / gdb / m68kbsd-tdep.c
CommitLineData
8f2d3ea0
MK
1/* Target-dependent code for Motorola 68000 BSD's.
2
9b254dd1 3 Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
8f2d3ea0
MK
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
8f2d3ea0
MK
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
8f2d3ea0
MK
19
20#include "defs.h"
21#include "arch-utils.h"
059cb7d2 22#include "frame.h"
8f2d3ea0
MK
23#include "osabi.h"
24#include "regcache.h"
25#include "regset.h"
059cb7d2
MK
26#include "trad-frame.h"
27#include "tramp-frame.h"
ec20a626 28#include "gdbtypes.h"
8f2d3ea0
MK
29
30#include "gdb_assert.h"
31#include "gdb_string.h"
32
33#include "m68k-tdep.h"
34#include "solib-svr4.h"
35
36/* Core file support. */
37
38/* Sizeof `struct reg' in <machine/reg.h>. */
39#define M68KBSD_SIZEOF_GREGS (18 * 4)
40
41/* Sizeof `struct fpreg' in <machine/reg.h. */
42#define M68KBSD_SIZEOF_FPREGS (((8 * 3) + 3) * 4)
43
44int
45m68kbsd_fpreg_offset (int regnum)
46{
8ed86d01
VP
47 int fp_len = TYPE_LENGTH (gdbarch_register_type (current_gdbarch, regnum));
48
8f2d3ea0 49 if (regnum >= M68K_FPC_REGNUM)
8ed86d01 50 return 8 * fp_len + (regnum - M68K_FPC_REGNUM) * 4;
8f2d3ea0 51
8ed86d01 52 return (regnum - M68K_FP0_REGNUM) * fp_len;
8f2d3ea0
MK
53}
54
55/* Supply register REGNUM from the buffer specified by FPREGS and LEN
56 in the floating-point register set REGSET to register cache
57 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
58
59static void
60m68kbsd_supply_fpregset (const struct regset *regset,
61 struct regcache *regcache,
62 int regnum, const void *fpregs, size_t len)
63{
f5cf7aa1 64 const gdb_byte *regs = fpregs;
8f2d3ea0
MK
65 int i;
66
67 gdb_assert (len >= M68KBSD_SIZEOF_FPREGS);
68
69 for (i = M68K_FP0_REGNUM; i <= M68K_PC_REGNUM; i++)
70 {
71 if (regnum == i || regnum == -1)
72 regcache_raw_supply (regcache, i, regs + m68kbsd_fpreg_offset (i));
73 }
74}
75
76/* Supply register REGNUM from the buffer specified by GREGS and LEN
77 in the general-purpose register set REGSET to register cache
78 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
79
80static void
81m68kbsd_supply_gregset (const struct regset *regset,
82 struct regcache *regcache,
83 int regnum, const void *gregs, size_t len)
84{
f5cf7aa1 85 const gdb_byte *regs = gregs;
8f2d3ea0
MK
86 int i;
87
88 gdb_assert (len >= M68KBSD_SIZEOF_GREGS);
89
90 for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++)
91 {
92 if (regnum == i || regnum == -1)
93 regcache_raw_supply (regcache, i, regs + i * 4);
94 }
95
96 if (len >= M68KBSD_SIZEOF_GREGS + M68KBSD_SIZEOF_FPREGS)
97 {
98 regs += M68KBSD_SIZEOF_GREGS;
99 len -= M68KBSD_SIZEOF_GREGS;
100 m68kbsd_supply_fpregset (regset, regcache, regnum, regs, len);
101 }
102}
103
104/* Motorola 68000 register sets. */
105
106static struct regset m68kbsd_gregset =
107{
108 NULL,
109 m68kbsd_supply_gregset
110};
111
112static struct regset m68kbsd_fpregset =
113{
114 NULL,
115 m68kbsd_supply_fpregset
116};
117
118/* Return the appropriate register set for the core section identified
119 by SECT_NAME and SECT_SIZE. */
120
121static const struct regset *
122m68kbsd_regset_from_core_section (struct gdbarch *gdbarch,
123 const char *sect_name, size_t sect_size)
124{
125 if (strcmp (sect_name, ".reg") == 0 && sect_size >= M68KBSD_SIZEOF_GREGS)
126 return &m68kbsd_gregset;
127
128 if (strcmp (sect_name, ".reg2") == 0 && sect_size >= M68KBSD_SIZEOF_FPREGS)
129 return &m68kbsd_fpregset;
130
131 return NULL;
132}
059cb7d2
MK
133\f
134
135/* Signal trampolines. */
136
137static void
138m68kobsd_sigtramp_cache_init (const struct tramp_frame *self,
5366653e 139 struct frame_info *this_frame,
059cb7d2
MK
140 struct trad_frame_cache *this_cache,
141 CORE_ADDR func)
142{
143 CORE_ADDR addr, base, pc;
144 int regnum;
145
5366653e 146 base = get_frame_register_unsigned (this_frame, M68K_SP_REGNUM);
059cb7d2
MK
147
148 /* The 'addql #4,%sp' instruction at offset 8 adjusts the stack
149 pointer. Adjust the frame base accordingly. */
5366653e 150 pc = get_frame_register_unsigned (this_frame, M68K_PC_REGNUM);
059cb7d2
MK
151 if ((pc - func) > 8)
152 base -= 4;
153
154 /* Get frame pointer, stack pointer, program counter and processor
155 state from `struct sigcontext'. */
5366653e 156 addr = get_frame_memory_unsigned (this_frame, base + 8, 4);
059cb7d2
MK
157 trad_frame_set_reg_addr (this_cache, M68K_FP_REGNUM, addr + 8);
158 trad_frame_set_reg_addr (this_cache, M68K_SP_REGNUM, addr + 12);
159 trad_frame_set_reg_addr (this_cache, M68K_PC_REGNUM, addr + 20);
160 trad_frame_set_reg_addr (this_cache, M68K_PS_REGNUM, addr + 24);
161
162 /* The sc_ap member of `struct sigcontext' points to additional
163 hardware state. Here we find the missing registers. */
5366653e 164 addr = get_frame_memory_unsigned (this_frame, addr + 16, 4) + 4;
059cb7d2
MK
165 for (regnum = M68K_D0_REGNUM; regnum < M68K_FP_REGNUM; regnum++, addr += 4)
166 trad_frame_set_reg_addr (this_cache, regnum, addr);
167
168 /* Construct the frame ID using the function start. */
169 trad_frame_set_id (this_cache, frame_id_build (base, func));
170}
171
172static const struct tramp_frame m68kobsd_sigtramp = {
173 SIGTRAMP_FRAME,
174 2,
175 {
176 { 0x206f, -1 }, { 0x000c, -1}, /* moveal %sp@(12),%a0 */
177 { 0x4e90, -1 }, /* jsr %a0@ */
178 { 0x588f, -1 }, /* addql #4,%sp */
179 { 0x4e41, -1 }, /* trap #1 */
180 { 0x2f40, -1 }, { 0x0004, -1 }, /* moveal %d0,%sp@(4) */
181 { 0x7001, -1 }, /* moveq #SYS_exit,%d0 */
182 { 0x4e40, -1 }, /* trap #0 */
183 { TRAMP_SENTINEL_INSN, -1 }
184 },
185 m68kobsd_sigtramp_cache_init
186};
187\f
8f2d3ea0
MK
188
189static void
190m68kbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
191{
192 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
193
194 tdep->jb_pc = 5;
195 tdep->jb_elt_size = 4;
196
9418f048
UW
197 set_gdbarch_decr_pc_after_break (gdbarch, 2);
198
8f2d3ea0
MK
199 set_gdbarch_regset_from_core_section
200 (gdbarch, m68kbsd_regset_from_core_section);
201}
202
203/* OpenBSD and NetBSD a.out. */
204
205static void
206m68kbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
207{
208 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
209
210 m68kbsd_init_abi (info, gdbarch);
211
212 tdep->struct_return = reg_struct_return;
059cb7d2
MK
213
214 tramp_frame_prepend_unwinder (gdbarch, &m68kobsd_sigtramp);
8f2d3ea0
MK
215}
216
217/* NetBSD ELF. */
218
219static void
220m68kbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
221{
222 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
223
224 m68kbsd_init_abi (info, gdbarch);
225
5ab5aa0f
MK
226 /* NetBSD ELF uses the SVR4 ABI. */
227 m68k_svr4_init_abi (info, gdbarch);
8f2d3ea0
MK
228 tdep->struct_return = pcc_struct_return;
229
230 /* NetBSD ELF uses SVR4-style shared libraries. */
8f2d3ea0
MK
231 set_solib_svr4_fetch_link_map_offsets
232 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
233}
234\f
235
236static enum gdb_osabi
237m68kbsd_aout_osabi_sniffer (bfd *abfd)
238{
239 if (strcmp (bfd_get_target (abfd), "a.out-m68k-netbsd") == 0
240 || strcmp (bfd_get_target (abfd), "a.out-m68k4k-netbsd") == 0)
241 return GDB_OSABI_NETBSD_AOUT;
242
243 return GDB_OSABI_UNKNOWN;
244}
245
246static enum gdb_osabi
247m68kbsd_core_osabi_sniffer (bfd *abfd)
248{
249 if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
250 return GDB_OSABI_NETBSD_AOUT;
251
252 return GDB_OSABI_UNKNOWN;
253}
254\f
255
256/* Provide a prototype to silence -Wmissing-prototypes. */
257void _initialize_m68kbsd_tdep (void);
258
259void
260_initialize_m68kbsd_tdep (void)
261{
262 gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_aout_flavour,
263 m68kbsd_aout_osabi_sniffer);
264
265 /* BFD doesn't set a flavour for NetBSD style a.out core files. */
266 gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_unknown_flavour,
267 m68kbsd_core_osabi_sniffer);
268
269 gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_AOUT,
270 m68kbsd_aout_init_abi);
271 gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_ELF,
272 m68kbsd_elf_init_abi);
273}
This page took 0.355242 seconds and 4 git commands to generate.