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