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