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