2005-07-13 Eric Christopher <echristo@redhat.com>
[deliverable/binutils-gdb.git] / gdb / ppcobsd-tdep.c
index 90381e4c412bb98264c3164cc5fc8f9c7f9605b4..c2d542e164c49bcae33af2b097b6cbd63a4667c3 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for OpenBSD/powerpc.
 
-   Copyright 2004 Free Software Foundation, Inc.
+   Copyright 2004, 2005 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
 #include "defs.h"
 #include "arch-utils.h"
+#include "floatformat.h"
 #include "osabi.h"
 #include "regcache.h"
 #include "regset.h"
+#include "trad-frame.h"
+#include "tramp-frame.h"
 
+#include "gdb_assert.h"
 #include "gdb_string.h"
 
 #include "ppc-tdep.h"
@@ -46,6 +50,18 @@ ppcobsd_supply_gregset (const struct regset *regset,
                        struct regcache *regcache, int regnum,
                        const void *gregs, size_t len)
 {
+  /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
+     point registers.  Traditionally, GDB's register set has still
+     listed the floating point registers for such machines, so this
+     code is harmless.  However, the new E500 port actually omits the
+     floating point registers entirely from the register set --- they
+     don't even have register numbers assigned to them.
+
+     It's not clear to me how best to update this code, so this assert
+     will alert the first person to encounter the OpenBSD/E500
+     combination to the problem.  */
+  gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
+
   ppc_supply_gregset (regset, regcache, regnum, gregs, len);
   ppc_supply_fpregset (regset, regcache, regnum, gregs, len);
 }
@@ -60,11 +76,23 @@ ppcobsd_collect_gregset (const struct regset *regset,
                         const struct regcache *regcache, int regnum,
                         void *gregs, size_t len)
 {
+  /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
+     point registers.  Traditionally, GDB's register set has still
+     listed the floating point registers for such machines, so this
+     code is harmless.  However, the new E500 port actually omits the
+     floating point registers entirely from the register set --- they
+     don't even have register numbers assigned to them.
+
+     It's not clear to me how best to update this code, so this assert
+     will alert the first person to encounter the OpenBSD/E500
+     combination to the problem.  */
+  gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
+
   ppc_collect_gregset (regset, regcache, regnum, gregs, len);
   ppc_collect_fpregset (regset, regcache, regnum, gregs, len);
 }
 
-/* OpenBS/powerpc register set.  */
+/* OpenBSD/powerpc register set.  */
 
 struct regset ppcobsd_gregset =
 {
@@ -86,17 +114,77 @@ ppcobsd_regset_from_core_section (struct gdbarch *gdbarch,
 }
 \f
 
+/* Signal trampolines.  */
+
+static void
+ppcobsd_sigtramp_cache_init (const struct tramp_frame *self,
+                            struct frame_info *next_frame,
+                            struct trad_frame_cache *this_cache,
+                            CORE_ADDR func)
+{
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  CORE_ADDR addr, base;
+  int i;
+
+  base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
+  addr = base + 0x18 + 2 * tdep->wordsize;
+  for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize)
+    {
+      int regnum = i + tdep->ppc_gp0_regnum;
+      trad_frame_set_reg_addr (this_cache, regnum, addr);
+    }
+  trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum, addr);
+  addr += tdep->wordsize;
+  trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum, addr);
+  addr += tdep->wordsize;
+  trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum, addr);
+  addr += tdep->wordsize;
+  trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum, addr);
+  addr += tdep->wordsize;
+  trad_frame_set_reg_addr (this_cache, PC_REGNUM, addr); /* SRR0? */
+  addr += tdep->wordsize;
+
+  /* Construct the frame ID using the function start.  */
+  trad_frame_set_id (this_cache, frame_id_build (base, func));
+}
+
+static const struct tramp_frame ppcobsd_sigtramp =
+{
+  SIGTRAMP_FRAME,
+  4,
+  {
+    { 0x3821fff0, -1 },                /* add r1,r1,-16 */
+    { 0x4e800021, -1 },                /* blrl */
+    { 0x38610018, -1 },                /* addi r3,r1,24 */
+    { 0x38000067, -1 },                /* li r0,103 */
+    { 0x44000002, -1 },                /* sc */
+    { 0x38000001, -1 },                /* li r0,1 */
+    { 0x44000002, -1 },                /* sc */
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  ppcobsd_sigtramp_cache_init
+};
+\f
+
 static void
 ppcobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
+  /* OpenBSD doesn't support the 128-bit `long double' from the psABI.  */
+  set_gdbarch_long_double_bit (gdbarch, 64);
+  set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
+
+  /* OpenBSD currently uses a broken GCC.  */
+  set_gdbarch_return_value (gdbarch, ppc_sysv_abi_broken_return_value);
+
   /* OpenBSD uses SVR4-style shared libraries.  */
-  set_gdbarch_in_solib_call_trampoline
-    (gdbarch, generic_in_solib_call_trampoline);
   set_solib_svr4_fetch_link_map_offsets
     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
 
   set_gdbarch_regset_from_core_section
     (gdbarch, ppcobsd_regset_from_core_section);
+
+  tramp_frame_prepend_unwinder (gdbarch, &ppcobsd_sigtramp);
 }
 \f
 
@@ -124,6 +212,8 @@ _initialize_ppcobsd_tdep (void)
   gdbarch_register_osabi_sniffer (bfd_arch_powerpc, bfd_target_unknown_flavour,
                                   ppcobsd_core_osabi_sniffer);
 
+  gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_OPENBSD_ELF,
+                         ppcobsd_init_abi);
   gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_OPENBSD_ELF,
                          ppcobsd_init_abi);
 
This page took 0.025158 seconds and 4 git commands to generate.