1 1.1 christos /* Target-dependent code for NetBSD/powerpc. 2 1.1 christos 3 1.1.1.2 christos Copyright (C) 2002-2024 Free Software Foundation, Inc. 4 1.1 christos 5 1.1 christos Contributed by Wasabi Systems, Inc. 6 1.1 christos 7 1.1 christos This file is part of GDB. 8 1.1 christos 9 1.1 christos This program is free software; you can redistribute it and/or modify 10 1.1 christos it under the terms of the GNU General Public License as published by 11 1.1 christos the Free Software Foundation; either version 3 of the License, or 12 1.1 christos (at your option) any later version. 13 1.1 christos 14 1.1 christos This program is distributed in the hope that it will be useful, 15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 1.1 christos GNU General Public License for more details. 18 1.1 christos 19 1.1 christos You should have received a copy of the GNU General Public License 20 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21 1.1 christos 22 1.1 christos #include "gdbtypes.h" 23 1.1 christos #include "osabi.h" 24 1.1 christos #include "regcache.h" 25 1.1 christos #include "regset.h" 26 1.1 christos #include "trad-frame.h" 27 1.1 christos #include "tramp-frame.h" 28 1.1 christos 29 1.1 christos #include "ppc-tdep.h" 30 1.1 christos #include "netbsd-tdep.h" 31 1.1 christos #include "ppc-netbsd-tdep.h" 32 1.1 christos #include "ppc-tdep.h" 33 1.1 christos #include "solib-svr4.h" 34 1.1 christos 35 1.1 christos /* Register offsets from <machine/reg.h>. */ 36 1.1 christos static ppc_reg_offsets ppcnbsd_reg_offsets; 37 1.1 christos 38 1.1 christos 40 1.1 christos /* Core file support. */ 41 1.1 christos 42 1.1 christos /* NetBSD/powerpc register sets. */ 43 1.1 christos 44 1.1 christos const struct regset ppcnbsd_gregset = 45 1.1 christos { 46 1.1 christos &ppcnbsd_reg_offsets, 47 1.1 christos ppc_supply_gregset 48 1.1 christos }; 49 1.1 christos 50 1.1 christos const struct regset ppcnbsd_fpregset = 51 1.1 christos { 52 1.1 christos &ppcnbsd_reg_offsets, 53 1.1 christos ppc_supply_fpregset 54 1.1 christos }; 55 1.1 christos 56 1.1 christos /* Iterate over core file register note sections. */ 57 1.1 christos 58 1.1 christos static void 59 1.1 christos ppcnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, 60 1.1 christos iterate_over_regset_sections_cb *cb, 61 1.1 christos void *cb_data, 62 1.1 christos const struct regcache *regcache) 63 1.1 christos { 64 1.1 christos cb (".reg", 148, 148, &ppcnbsd_gregset, NULL, cb_data); 65 1.1 christos cb (".reg2", 264, 264, &ppcnbsd_fpregset, NULL, cb_data); 66 1.1 christos } 67 1.1 christos 68 1.1 christos 70 1.1 christos /* NetBSD is confused. It appears that 1.5 was using the correct SVR4 71 1.1 christos convention but, 1.6 switched to the below broken convention. For 72 1.1 christos the moment use the broken convention. Ulgh! */ 73 1.1 christos 74 1.1 christos static enum return_value_convention 75 1.1 christos ppcnbsd_return_value (struct gdbarch *gdbarch, struct value *function, 76 1.1 christos struct type *valtype, struct regcache *regcache, 77 1.1 christos gdb_byte *readbuf, const gdb_byte *writebuf) 78 1.1 christos { 79 1.1 christos #if 0 80 1.1 christos if ((valtype->code () == TYPE_CODE_STRUCT 81 1.1 christos || valtype->code () == TYPE_CODE_UNION) 82 1.1 christos && !((valtype->length () == 16 || valtype->length () == 8) 83 1.1 christos && valtype->is_vector ()) 84 1.1 christos && !(valtype->length () == 1 85 1.1 christos || valtype->length () == 2 86 1.1 christos || valtype->length () == 4 87 1.1 christos || valtype->length () == 8)) 88 1.1 christos return RETURN_VALUE_STRUCT_CONVENTION; 89 1.1 christos else 90 1.1 christos #endif 91 1.1 christos return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype, 92 1.1 christos regcache, readbuf, writebuf); 93 1.1 christos } 94 1.1 christos 95 1.1 christos 97 1.1 christos /* Signal trampolines. */ 98 1.1 christos 99 1.1 christos extern const struct tramp_frame ppcnbsd2_sigtramp; 100 1.1.1.2 christos 101 1.1 christos static void 102 1.1 christos ppcnbsd_sigtramp_cache_init (const struct tramp_frame *self, 103 1.1 christos const frame_info_ptr &this_frame, 104 1.1 christos struct trad_frame_cache *this_cache, 105 1.1 christos CORE_ADDR func) 106 1.1 christos { 107 1.1 christos struct gdbarch *gdbarch = get_frame_arch (this_frame); 108 1.1 christos ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch); 109 1.1 christos CORE_ADDR addr, base; 110 1.1 christos int i; 111 1.1 christos 112 1.1 christos base = get_frame_register_unsigned (this_frame, 113 1.1 christos gdbarch_sp_regnum (gdbarch)); 114 1.1 christos if (self == &ppcnbsd2_sigtramp) 115 1.1 christos addr = base + 0x10 + 2 * tdep->wordsize; 116 1.1 christos else 117 1.1 christos addr = base + 0x18 + 2 * tdep->wordsize; 118 1.1 christos for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize) 119 1.1 christos { 120 1.1 christos int regnum = i + tdep->ppc_gp0_regnum; 121 1.1 christos trad_frame_set_reg_addr (this_cache, regnum, addr); 122 1.1 christos } 123 1.1 christos trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum, addr); 124 1.1 christos addr += tdep->wordsize; 125 1.1 christos trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum, addr); 126 1.1 christos addr += tdep->wordsize; 127 1.1 christos trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum, addr); 128 1.1 christos addr += tdep->wordsize; 129 1.1 christos trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum, addr); 130 1.1 christos addr += tdep->wordsize; 131 1.1 christos trad_frame_set_reg_addr (this_cache, gdbarch_pc_regnum (gdbarch), 132 1.1 christos addr); /* SRR0? */ 133 1.1 christos addr += tdep->wordsize; 134 1.1 christos 135 1.1 christos /* Construct the frame ID using the function start. */ 136 1.1 christos trad_frame_set_id (this_cache, frame_id_build (base, func)); 137 1.1 christos } 138 1.1 christos 139 1.1 christos static const struct tramp_frame ppcnbsd_sigtramp = 140 1.1 christos { 141 1.1 christos SIGTRAMP_FRAME, 142 1.1 christos 4, 143 1.1 christos { 144 1.1 christos { 0x3821fff0, ULONGEST_MAX }, /* add r1,r1,-16 */ 145 1.1 christos { 0x4e800021, ULONGEST_MAX }, /* blrl */ 146 1.1 christos { 0x38610018, ULONGEST_MAX }, /* addi r3,r1,24 */ 147 1.1 christos { 0x38000127, ULONGEST_MAX }, /* li r0,295 */ 148 1.1 christos { 0x44000002, ULONGEST_MAX }, /* sc */ 149 1.1 christos { 0x38000001, ULONGEST_MAX }, /* li r0,1 */ 150 1.1 christos { 0x44000002, ULONGEST_MAX }, /* sc */ 151 1.1 christos { TRAMP_SENTINEL_INSN, ULONGEST_MAX } 152 1.1 christos }, 153 1.1 christos ppcnbsd_sigtramp_cache_init 154 1.1 christos }; 155 1.1 christos 156 1.1 christos /* NetBSD 2.0 introduced a slightly different signal trampoline. */ 157 1.1 christos 158 1.1 christos const struct tramp_frame ppcnbsd2_sigtramp = 159 1.1 christos { 160 1.1 christos SIGTRAMP_FRAME, 161 1.1 christos 4, 162 1.1 christos { 163 1.1 christos { 0x3821fff0, ULONGEST_MAX }, /* add r1,r1,-16 */ 164 1.1 christos { 0x4e800021, ULONGEST_MAX }, /* blrl */ 165 1.1 christos { 0x38610010, ULONGEST_MAX }, /* addi r3,r1,16 */ 166 1.1 christos { 0x38000127, ULONGEST_MAX }, /* li r0,295 */ 167 1.1 christos { 0x44000002, ULONGEST_MAX }, /* sc */ 168 1.1 christos { 0x38000001, ULONGEST_MAX }, /* li r0,1 */ 169 1.1 christos { 0x44000002, ULONGEST_MAX }, /* sc */ 170 1.1 christos { TRAMP_SENTINEL_INSN, ULONGEST_MAX } 171 1.1 christos }, 172 1.1 christos ppcnbsd_sigtramp_cache_init 173 1.1 christos }; 174 1.1 christos 175 1.1 christos 177 1.1 christos static void 178 1.1 christos ppcnbsd_init_abi (struct gdbarch_info info, 179 1.1 christos struct gdbarch *gdbarch) 180 1.1 christos { 181 1.1 christos nbsd_init_abi (info, gdbarch); 182 1.1 christos 183 1.1 christos /* NetBSD doesn't support the 128-bit `long double' from the psABI. */ 184 1.1 christos set_gdbarch_long_double_bit (gdbarch, 64); 185 1.1 christos set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double); 186 1.1 christos 187 1.1 christos /* For NetBSD, this is an on again, off again thing. Some systems 188 1.1 christos do use the broken struct convention, and some don't. */ 189 1.1 christos set_gdbarch_return_value (gdbarch, ppcnbsd_return_value); 190 1.1 christos 191 1.1 christos /* NetBSD uses SVR4-style shared libraries. */ 192 1.1 christos set_solib_svr4_fetch_link_map_offsets 193 1.1 christos (gdbarch, svr4_ilp32_fetch_link_map_offsets); 194 1.1 christos 195 1.1 christos set_gdbarch_iterate_over_regset_sections 196 1.1 christos (gdbarch, ppcnbsd_iterate_over_regset_sections); 197 1.1 christos 198 1.1 christos tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd_sigtramp); 199 1.1 christos tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd2_sigtramp); 200 1.1 christos } 201 1.1 christos 202 1.1 christos void _initialize_ppcnbsd_tdep (); 203 1.1 christos void 204 1.1 christos _initialize_ppcnbsd_tdep () 205 1.1 christos { 206 1.1 christos gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_NETBSD, 207 1.1 christos ppcnbsd_init_abi); 208 1.1 christos 209 1.1 christos /* Register NetBSD OSABI also for rs6000, which is default target 210 1.1 christos used before any executable image is loaded. */ 211 1.1 christos gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_NETBSD, 212 1.1 christos ppcnbsd_init_abi); 213 1.1 christos 214 1.1 christos /* Avoid initializing the register offsets again if they were 215 1.1 christos already initialized by ppc-netbsd-nat.c. */ 216 1.1 christos if (ppcnbsd_reg_offsets.pc_offset == 0) 217 1.1 christos { 218 1.1 christos /* General-purpose registers. */ 219 1.1 christos ppcnbsd_reg_offsets.r0_offset = 0; 220 1.1 christos ppcnbsd_reg_offsets.gpr_size = 4; 221 1.1 christos ppcnbsd_reg_offsets.xr_size = 4; 222 1.1 christos ppcnbsd_reg_offsets.lr_offset = 128; 223 1.1 christos ppcnbsd_reg_offsets.cr_offset = 132; 224 1.1 christos ppcnbsd_reg_offsets.xer_offset = 136; 225 1.1 christos ppcnbsd_reg_offsets.ctr_offset = 140; 226 1.1 christos ppcnbsd_reg_offsets.pc_offset = 144; 227 1.1 christos ppcnbsd_reg_offsets.ps_offset = -1; 228 1.1 christos ppcnbsd_reg_offsets.mq_offset = -1; 229 1.1 christos 230 1.1 christos /* Floating-point registers. */ 231 1.1 christos ppcnbsd_reg_offsets.f0_offset = 0; 232 1.1 christos ppcnbsd_reg_offsets.fpscr_offset = 256; 233 ppcnbsd_reg_offsets.fpscr_size = 4; 234 235 } 236 } 237