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