Commit | Line | Data |
---|---|---|
8f2d3ea0 MK |
1 | /* Target-dependent code for Motorola 68000 BSD's. |
2 | ||
f5cf7aa1 | 3 | Copyright 2004, 2005 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 | |
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 "arch-utils.h" | |
24 | #include "osabi.h" | |
25 | #include "regcache.h" | |
26 | #include "regset.h" | |
27 | ||
28 | #include "gdb_assert.h" | |
29 | #include "gdb_string.h" | |
30 | ||
31 | #include "m68k-tdep.h" | |
32 | #include "solib-svr4.h" | |
33 | ||
34 | /* Core file support. */ | |
35 | ||
36 | /* Sizeof `struct reg' in <machine/reg.h>. */ | |
37 | #define M68KBSD_SIZEOF_GREGS (18 * 4) | |
38 | ||
39 | /* Sizeof `struct fpreg' in <machine/reg.h. */ | |
40 | #define M68KBSD_SIZEOF_FPREGS (((8 * 3) + 3) * 4) | |
41 | ||
42 | int | |
43 | m68kbsd_fpreg_offset (int regnum) | |
44 | { | |
45 | if (regnum >= M68K_FPC_REGNUM) | |
46 | return 8 * 12 + (regnum - M68K_FPC_REGNUM) * 4; | |
47 | ||
48 | return (regnum - M68K_FP0_REGNUM) * 12; | |
49 | } | |
50 | ||
51 | /* Supply register REGNUM from the buffer specified by FPREGS and LEN | |
52 | in the floating-point register set REGSET to register cache | |
53 | REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ | |
54 | ||
55 | static void | |
56 | m68kbsd_supply_fpregset (const struct regset *regset, | |
57 | struct regcache *regcache, | |
58 | int regnum, const void *fpregs, size_t len) | |
59 | { | |
f5cf7aa1 | 60 | const gdb_byte *regs = fpregs; |
8f2d3ea0 MK |
61 | int i; |
62 | ||
63 | gdb_assert (len >= M68KBSD_SIZEOF_FPREGS); | |
64 | ||
65 | for (i = M68K_FP0_REGNUM; i <= M68K_PC_REGNUM; i++) | |
66 | { | |
67 | if (regnum == i || regnum == -1) | |
68 | regcache_raw_supply (regcache, i, regs + m68kbsd_fpreg_offset (i)); | |
69 | } | |
70 | } | |
71 | ||
72 | /* Supply register REGNUM from the buffer specified by GREGS and LEN | |
73 | in the general-purpose register set REGSET to register cache | |
74 | REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ | |
75 | ||
76 | static void | |
77 | m68kbsd_supply_gregset (const struct regset *regset, | |
78 | struct regcache *regcache, | |
79 | int regnum, const void *gregs, size_t len) | |
80 | { | |
f5cf7aa1 | 81 | const gdb_byte *regs = gregs; |
8f2d3ea0 MK |
82 | int i; |
83 | ||
84 | gdb_assert (len >= M68KBSD_SIZEOF_GREGS); | |
85 | ||
86 | for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++) | |
87 | { | |
88 | if (regnum == i || regnum == -1) | |
89 | regcache_raw_supply (regcache, i, regs + i * 4); | |
90 | } | |
91 | ||
92 | if (len >= M68KBSD_SIZEOF_GREGS + M68KBSD_SIZEOF_FPREGS) | |
93 | { | |
94 | regs += M68KBSD_SIZEOF_GREGS; | |
95 | len -= M68KBSD_SIZEOF_GREGS; | |
96 | m68kbsd_supply_fpregset (regset, regcache, regnum, regs, len); | |
97 | } | |
98 | } | |
99 | ||
100 | /* Motorola 68000 register sets. */ | |
101 | ||
102 | static struct regset m68kbsd_gregset = | |
103 | { | |
104 | NULL, | |
105 | m68kbsd_supply_gregset | |
106 | }; | |
107 | ||
108 | static struct regset m68kbsd_fpregset = | |
109 | { | |
110 | NULL, | |
111 | m68kbsd_supply_fpregset | |
112 | }; | |
113 | ||
114 | /* Return the appropriate register set for the core section identified | |
115 | by SECT_NAME and SECT_SIZE. */ | |
116 | ||
117 | static const struct regset * | |
118 | m68kbsd_regset_from_core_section (struct gdbarch *gdbarch, | |
119 | const char *sect_name, size_t sect_size) | |
120 | { | |
121 | if (strcmp (sect_name, ".reg") == 0 && sect_size >= M68KBSD_SIZEOF_GREGS) | |
122 | return &m68kbsd_gregset; | |
123 | ||
124 | if (strcmp (sect_name, ".reg2") == 0 && sect_size >= M68KBSD_SIZEOF_FPREGS) | |
125 | return &m68kbsd_fpregset; | |
126 | ||
127 | return NULL; | |
128 | } | |
8f2d3ea0 MK |
129 | |
130 | static void | |
131 | m68kbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | |
132 | { | |
133 | struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
134 | ||
135 | tdep->jb_pc = 5; | |
136 | tdep->jb_elt_size = 4; | |
137 | ||
138 | set_gdbarch_regset_from_core_section | |
139 | (gdbarch, m68kbsd_regset_from_core_section); | |
140 | } | |
141 | ||
142 | /* OpenBSD and NetBSD a.out. */ | |
143 | ||
144 | static void | |
145 | m68kbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | |
146 | { | |
147 | struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
148 | ||
149 | m68kbsd_init_abi (info, gdbarch); | |
150 | ||
151 | tdep->struct_return = reg_struct_return; | |
8f2d3ea0 MK |
152 | } |
153 | ||
154 | /* NetBSD ELF. */ | |
155 | ||
156 | static void | |
157 | m68kbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | |
158 | { | |
159 | struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
160 | ||
161 | m68kbsd_init_abi (info, gdbarch); | |
162 | ||
5ab5aa0f MK |
163 | /* NetBSD ELF uses the SVR4 ABI. */ |
164 | m68k_svr4_init_abi (info, gdbarch); | |
8f2d3ea0 MK |
165 | tdep->struct_return = pcc_struct_return; |
166 | ||
167 | /* NetBSD ELF uses SVR4-style shared libraries. */ | |
8f2d3ea0 MK |
168 | set_solib_svr4_fetch_link_map_offsets |
169 | (gdbarch, svr4_ilp32_fetch_link_map_offsets); | |
170 | } | |
171 | \f | |
172 | ||
173 | static enum gdb_osabi | |
174 | m68kbsd_aout_osabi_sniffer (bfd *abfd) | |
175 | { | |
176 | if (strcmp (bfd_get_target (abfd), "a.out-m68k-netbsd") == 0 | |
177 | || strcmp (bfd_get_target (abfd), "a.out-m68k4k-netbsd") == 0) | |
178 | return GDB_OSABI_NETBSD_AOUT; | |
179 | ||
180 | return GDB_OSABI_UNKNOWN; | |
181 | } | |
182 | ||
183 | static enum gdb_osabi | |
184 | m68kbsd_core_osabi_sniffer (bfd *abfd) | |
185 | { | |
186 | if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) | |
187 | return GDB_OSABI_NETBSD_AOUT; | |
188 | ||
189 | return GDB_OSABI_UNKNOWN; | |
190 | } | |
191 | \f | |
192 | ||
193 | /* Provide a prototype to silence -Wmissing-prototypes. */ | |
194 | void _initialize_m68kbsd_tdep (void); | |
195 | ||
196 | void | |
197 | _initialize_m68kbsd_tdep (void) | |
198 | { | |
199 | gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_aout_flavour, | |
200 | m68kbsd_aout_osabi_sniffer); | |
201 | ||
202 | /* BFD doesn't set a flavour for NetBSD style a.out core files. */ | |
203 | gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_unknown_flavour, | |
204 | m68kbsd_core_osabi_sniffer); | |
205 | ||
206 | gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_AOUT, | |
207 | m68kbsd_aout_init_abi); | |
208 | gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_ELF, | |
209 | m68kbsd_elf_init_abi); | |
210 | } |