1 /* Target-dependent code for Motorola 68000 BSD's. 2 3 Copyright 2004 Free Software Foundation, Inc. 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 { 60 const char *regs = fpregs; 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 { 81 const char *regs = gregs; 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 } 129 130 131 /* Support for shared libraries. */ 132 133 /* Return non-zero if we are in a shared library trampoline code stub. */ 134 135 int 136 m68kbsd_aout_in_solib_call_trampoline (CORE_ADDR pc, char *name) 137 { 138 return (name && !strcmp (name, "_DYNAMIC")); 139 } 140 141 142 static void 143 m68kbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 144 { 145 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 146 147 tdep->jb_pc = 5; 148 tdep->jb_elt_size = 4; 149 150 set_gdbarch_regset_from_core_section 151 (gdbarch, m68kbsd_regset_from_core_section); 152 } 153 154 /* OpenBSD and NetBSD a.out. */ 155 156 static void 157 m68kbsd_aout_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 163 tdep->struct_return = reg_struct_return; 164 165 /* Assume SunOS-style shared libraries. */ 166 set_gdbarch_in_solib_call_trampoline 167 (gdbarch, m68kbsd_aout_in_solib_call_trampoline); 168 } 169 170 /* NetBSD/OpenBSD ELF. */ 171 172 static void 173 m68kbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 174 { 175 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 176 177 m68kbsd_init_abi (info, gdbarch); 178 179 /* NetBSD ELF uses the SVR4 ABI. */ 180 m68k_svr4_init_abi (info, gdbarch); 181 tdep->struct_return = pcc_struct_return; 182 183 /* NetBSD ELF uses SVR4-style shared libraries. */ 184 set_gdbarch_in_solib_call_trampoline 185 (gdbarch, generic_in_solib_call_trampoline); 186 set_solib_svr4_fetch_link_map_offsets 187 (gdbarch, svr4_ilp32_fetch_link_map_offsets); 188 } 189 190 191 static enum gdb_osabi 192 m68kbsd_aout_osabi_sniffer (bfd *abfd) 193 { 194 if (strcmp (bfd_get_target (abfd), "a.out-m68k-netbsd") == 0 195 || strcmp (bfd_get_target (abfd), "a.out-m68k4k-netbsd") == 0) 196 return GDB_OSABI_NETBSD_AOUT; 197 198 return GDB_OSABI_UNKNOWN; 199 } 200 201 static enum gdb_osabi 202 m68kbsd_core_osabi_sniffer (bfd *abfd) 203 { 204 if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) 205 return GDB_OSABI_NETBSD_AOUT; 206 207 return GDB_OSABI_UNKNOWN; 208 } 209 210 211 /* Provide a prototype to silence -Wmissing-prototypes. */ 212 void _initialize_m68kbsd_tdep (void); 213 214 void 215 _initialize_m68kbsd_tdep (void) 216 { 217 gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_aout_flavour, 218 m68kbsd_aout_osabi_sniffer); 219 220 /* BFD doesn't set a flavour for NetBSD style a.out core files. */ 221 gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_unknown_flavour, 222 m68kbsd_core_osabi_sniffer); 223 224 gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_AOUT, 225 m68kbsd_aout_init_abi); 226 gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_ELF, 227 m68kbsd_elf_init_abi); 228 gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_OPENBSD_ELF, 229 m68kbsd_elf_init_abi); 230 } 231