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