* dwarf2-frame.c (dwarf2_frame_ops init_reg): Add "next_frame"
[deliverable/binutils-gdb.git] / gdb / sparc-tdep.c
index dcae0455885e9836ed09a6f7a74eaef886ec2355..e3b1ccfd43725a8e21a160847af2f9041ea28433 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for SPARC.
 
-   Copyright 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
 #include "arch-utils.h"
 #include "dis-asm.h"
+#include "dwarf2-frame.h"
 #include "floatformat.h"
 #include "frame.h"
 #include "frame-base.h"
@@ -93,7 +94,7 @@ struct regset;
 unsigned long
 sparc_fetch_instruction (CORE_ADDR pc)
 {
-  unsigned char buf[4];
+  gdb_byte buf[4];
   unsigned long insn;
   int i;
 
@@ -154,7 +155,7 @@ ULONGEST
 sparc_fetch_wcookie (void)
 {
   struct target_ops *ops = &current_target;
-  char buf[8];
+  gdb_byte buf[8];
   int len;
 
   len = target_read_partial (ops, TARGET_OBJECT_WCOOKIE, NULL, buf, 0, 8);
@@ -170,7 +171,7 @@ sparc_fetch_wcookie (void)
 
 /* Return the contents if register REGNUM as an address.  */
 
-static CORE_ADDR
+CORE_ADDR
 sparc_address_from_register (int regnum)
 {
   ULONGEST addr;
@@ -318,25 +319,25 @@ sparc32_register_type (struct gdbarch *gdbarch, int regnum)
 static void
 sparc32_pseudo_register_read (struct gdbarch *gdbarch,
                              struct regcache *regcache,
-                             int regnum, void *buf)
+                             int regnum, gdb_byte *buf)
 {
   gdb_assert (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM);
 
   regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC32_D0_REGNUM);
   regcache_raw_read (regcache, regnum, buf);
-  regcache_raw_read (regcache, regnum + 1, ((char *)buf) + 4);
+  regcache_raw_read (regcache, regnum + 1, buf + 4);
 }
 
 static void
 sparc32_pseudo_register_write (struct gdbarch *gdbarch,
                               struct regcache *regcache,
-                              int regnum, const void *buf)
+                              int regnum, const gdb_byte *buf)
 {
   gdb_assert (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM);
 
   regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC32_D0_REGNUM);
   regcache_raw_write (regcache, regnum, buf);
-  regcache_raw_write (regcache, regnum + 1, ((const char *)buf) + 4);
+  regcache_raw_write (regcache, regnum + 1, buf + 4);
 }
 \f
 
@@ -352,7 +353,7 @@ sparc32_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
 
   if (using_struct_return (value_type, using_gcc))
     {
-      char buf[4];
+      gdb_byte buf[4];
 
       /* This is an UNIMP instruction.  */
       store_unsigned_integer (buf, 4, TYPE_LENGTH (value_type) & 0x1fff);
@@ -447,7 +448,7 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
 
   if (struct_return)
     {
-      char buf[4];
+      gdb_byte buf[4];
 
       store_unsigned_integer (buf, 4, struct_addr);
       write_memory (sp, buf, 4);
@@ -490,10 +491,10 @@ sparc32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
    *LEN and optionally adjust *PC to point to the correct memory
    location for inserting the breakpoint.  */
    
-static const unsigned char *
+static const gdb_byte *
 sparc_breakpoint_from_pc (CORE_ADDR *pc, int *len)
 {
-  static unsigned char break_insn[] = { 0x91, 0xd0, 0x20, 0x01 };
+  static const gdb_byte break_insn[] = { 0x91, 0xd0, 0x20, 0x01 };
 
   *len = sizeof (break_insn);
   return break_insn;
@@ -679,6 +680,23 @@ sparc_frame_cache (struct frame_info *next_frame, void **this_cache)
   return cache;
 }
 
+static int
+sparc32_struct_return_from_sym (struct symbol *sym)
+{
+  struct type *type = check_typedef (SYMBOL_TYPE (sym));
+  enum type_code code = TYPE_CODE (type);
+
+  if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
+    {
+      type = check_typedef (TYPE_TARGET_TYPE (type));
+      if (sparc_structure_or_union_p (type)
+         || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
+       return 1;
+    }
+
+  return 0;
+}
+
 struct sparc_frame_cache *
 sparc32_frame_cache (struct frame_info *next_frame, void **this_cache)
 {
@@ -693,16 +711,7 @@ sparc32_frame_cache (struct frame_info *next_frame, void **this_cache)
   sym = find_pc_function (cache->pc);
   if (sym)
     {
-      struct type *type = check_typedef (SYMBOL_TYPE (sym));
-      enum type_code code = TYPE_CODE (type);
-
-      if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
-       {
-         type = check_typedef (TYPE_TARGET_TYPE (type));
-         if (sparc_structure_or_union_p (type)
-             || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
-           cache->struct_return_p = 1;
-       }
+      cache->struct_return_p = sparc32_struct_return_from_sym (sym);
     }
   else
     {
@@ -741,7 +750,7 @@ static void
 sparc32_frame_prev_register (struct frame_info *next_frame, void **this_cache,
                             int regnum, int *optimizedp,
                             enum lval_type *lvalp, CORE_ADDR *addrp,
-                            int *realnump, void *valuep)
+                            int *realnump, gdb_byte *valuep)
 {
   struct sparc_frame_cache *cache =
     sparc32_frame_cache (next_frame, this_cache);
@@ -873,10 +882,10 @@ sparc_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
 
 static void
 sparc32_extract_return_value (struct type *type, struct regcache *regcache,
-                             void *valbuf)
+                             gdb_byte *valbuf)
 {
   int len = TYPE_LENGTH (type);
-  char buf[8];
+  gdb_byte buf[8];
 
   gdb_assert (!sparc_structure_or_union_p (type));
   gdb_assert (!(sparc_floating_p (type) && len == 16));
@@ -915,10 +924,10 @@ sparc32_extract_return_value (struct type *type, struct regcache *regcache,
 
 static void
 sparc32_store_return_value (struct type *type, struct regcache *regcache,
-                           const void *valbuf)
+                           const gdb_byte *valbuf)
 {
   int len = TYPE_LENGTH (type);
-  char buf[8];
+  gdb_byte buf[8];
 
   gdb_assert (!sparc_structure_or_union_p (type));
   gdb_assert (!(sparc_floating_p (type) && len == 16));
@@ -953,12 +962,31 @@ sparc32_store_return_value (struct type *type, struct regcache *regcache,
 
 static enum return_value_convention
 sparc32_return_value (struct gdbarch *gdbarch, struct type *type,
-                     struct regcache *regcache, void *readbuf,
-                     const void *writebuf)
+                     struct regcache *regcache, gdb_byte *readbuf,
+                     const gdb_byte *writebuf)
 {
+  /* The psABI says that "...every stack frame reserves the word at
+     %fp+64.  If a function returns a structure, union, or
+     quad-precision value, this word should hold the address of the
+     object into which the return value should be copied."  This
+     guarantees that we can always find the return value, not just
+     before the function returns.  */
+
   if (sparc_structure_or_union_p (type)
       || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
-    return RETURN_VALUE_STRUCT_CONVENTION;
+    {
+      if (readbuf)
+       {
+         ULONGEST sp;
+         CORE_ADDR addr;
+
+         regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
+         addr = read_memory_unsigned_integer (sp + 64, 4);
+         read_memory (addr, readbuf, TYPE_LENGTH (type));
+       }
+
+      return RETURN_VALUE_ABI_PRESERVES_ADDRESS;
+    }
 
   if (readbuf)
     sparc32_extract_return_value (type, regcache, readbuf);
@@ -968,37 +996,53 @@ sparc32_return_value (struct gdbarch *gdbarch, struct type *type,
   return RETURN_VALUE_REGISTER_CONVENTION;
 }
 
-#if 0
-/* NOTE: cagney/2004-01-17: For the moment disable this method.  The
-   architecture and CORE-gdb will need new code (and a replacement for
-   DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS) before this can be made to
-   work robustly.  Here is a possible function signature: */
-/* NOTE: cagney/2004-01-17: So far only the 32-bit SPARC ABI has been
-   identifed as having a way to robustly recover the address of a
-   struct-convention return-value (after the function has returned).
-   For all other ABIs so far examined, the calling convention makes no
-   guarenteed that the register containing the return-value will be
-   preserved and hence that the return-value's address can be
-   recovered.  */
-/* Extract from REGCACHE, which contains the (raw) register state, the
-   address in which a function should return its structure value, as a
-   CORE_ADDR.  */
+static int
+sparc32_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type)
+{
+  return (sparc_structure_or_union_p (type)
+         || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16));
+}
 
-static CORE_ADDR
-sparc32_extract_struct_value_address (struct regcache *regcache)
+static int
+sparc32_dwarf2_struct_return_p (struct frame_info *next_frame)
 {
-  ULONGEST sp;
+  CORE_ADDR pc = frame_unwind_address_in_block (next_frame);
+  struct symbol *sym = find_pc_function (pc);
 
-  regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
-  return read_memory_unsigned_integer (sp + 64, 4);
+  if (sym)
+    return sparc32_struct_return_from_sym (sym);
+  return 0;
 }
-#endif
 
-static int
-sparc32_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type)
+static void
+sparc32_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+                              struct dwarf2_frame_state_reg *reg,
+                              struct frame_info *next_frame)
 {
-  return (sparc_structure_or_union_p (type)
-         || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16));
+  int off;
+
+  switch (regnum)
+    {
+    case SPARC_G0_REGNUM:
+      /* Since %g0 is always zero, there is no point in saving it, and
+        people will be inclined omit it from the CFI.  Make sure we
+        don't warn about that.  */
+      reg->how = DWARF2_FRAME_REG_SAME_VALUE;
+      break;
+    case SPARC_SP_REGNUM:
+      reg->how = DWARF2_FRAME_REG_CFA;
+      break;
+    case SPARC32_PC_REGNUM:
+    case SPARC32_NPC_REGNUM:
+      reg->how = DWARF2_FRAME_REG_RA_OFFSET;
+      off = 8;
+      if (sparc32_dwarf2_struct_return_p (next_frame))
+       off += 4;
+      if (regnum == SPARC32_NPC_REGNUM)
+       off += 4;
+      reg->loc.offset = off;
+      break;
+    }
 }
 
 \f
@@ -1007,7 +1051,8 @@ sparc32_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type)
    software single-step mechanism.  */
 
 static CORE_ADDR
-sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc)
+sparc_analyze_control_transfer (struct gdbarch *arch,
+                               CORE_ADDR pc, CORE_ADDR *npc)
 {
   unsigned long insn = sparc_fetch_instruction (pc);
   int conditional_p = X_COND (insn) & 0x7;
@@ -1045,11 +1090,14 @@ sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc)
       branch_p = 1;
       offset = 4 * X_DISP19 (insn);
     }
+  else if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3a)
+    {
+      /* Trap instruction (TRAP).  */
+      return gdbarch_tdep (arch)->step_trap (insn);
+    }
 
   /* FIXME: Handle DONE and RETRY instructions.  */
 
-  /* FIXME: Handle the Trap instruction.  */
-
   if (branch_p)
     {
       if (conditional_p)
@@ -1077,12 +1125,19 @@ sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc)
   return 0;
 }
 
+static CORE_ADDR
+sparc_step_trap (unsigned long insn)
+{
+  return 0;
+}
+
 void
 sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch *arch = current_gdbarch;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
   static CORE_ADDR npc, nnpc;
-  static char npc_save[4], nnpc_save[4];
+  static gdb_byte npc_save[4], nnpc_save[4];
 
   if (insert_breakpoints_p)
     {
@@ -1092,7 +1147,7 @@ sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p)
       orig_npc = npc = sparc_address_from_register (tdep->npc_regnum);
 
       /* Analyze the instruction at PC.  */
-      nnpc = sparc_analyze_control_transfer (pc, &npc);
+      nnpc = sparc_analyze_control_transfer (arch, pc, &npc);
       if (npc != 0)
        target_insert_breakpoint (npc, npc_save);
       if (nnpc != 0)
@@ -1195,6 +1250,7 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->fpregset = NULL;
   tdep->sizeof_fpregset = 0;
   tdep->plt_entry_size = 0;
+  tdep->step_trap = sparc_step_trap;
 
   set_gdbarch_long_double_bit (gdbarch, 128);
   set_gdbarch_long_double_format (gdbarch, &floatformat_sparc_quad);
@@ -1243,6 +1299,11 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
+  /* Hook in the DWARF CFI frame unwinder.  */
+  dwarf2_frame_set_init_reg (gdbarch, sparc32_dwarf2_frame_init_reg);
+  /* FIXME: kettenis/20050423: Don't enable the unwinder until the
+     StackGhost issues have been resolved.  */
+
   frame_unwind_append_sniffer (gdbarch, sparc32_frame_sniffer);
 
   /* If we have register sets, enable the generic core file support.  */
@@ -1259,7 +1320,7 @@ void
 sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum)
 {
   int offset = 0;
-  char buf[8];
+  gdb_byte buf[8];
   int i;
 
   if (sp & 1)
@@ -1327,7 +1388,7 @@ sparc_collect_rwindow (const struct regcache *regcache,
                       CORE_ADDR sp, int regnum)
 {
   int offset = 0;
-  char buf[8];
+  gdb_byte buf[8];
   int i;
 
   if (sp & 1)
@@ -1393,7 +1454,7 @@ sparc32_supply_gregset (const struct sparc_gregset *gregset,
                        struct regcache *regcache,
                        int regnum, const void *gregs)
 {
-  const char *regs = gregs;
+  const gdb_byte *regs = gregs;
   int i;
 
   if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
@@ -1457,7 +1518,7 @@ sparc32_collect_gregset (const struct sparc_gregset *gregset,
                         const struct regcache *regcache,
                         int regnum, void *gregs)
 {
-  char *regs = gregs;
+  gdb_byte *regs = gregs;
   int i;
 
   if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
@@ -1511,7 +1572,7 @@ void
 sparc32_supply_fpregset (struct regcache *regcache,
                         int regnum, const void *fpregs)
 {
-  const char *regs = fpregs;
+  const gdb_byte *regs = fpregs;
   int i;
 
   for (i = 0; i < 32; i++)
@@ -1528,7 +1589,7 @@ void
 sparc32_collect_fpregset (const struct regcache *regcache,
                          int regnum, void *fpregs)
 {
-  char *regs = fpregs;
+  gdb_byte *regs = fpregs;
   int i;
 
   for (i = 0; i < 32; i++)
This page took 0.030751 seconds and 4 git commands to generate.