bfd/
[deliverable/binutils-gdb.git] / gdb / sparc-tdep.c
index 66dbac798c0e6e803f5bd825c791c5530fdda668..27c852f2632207bf515cb215ea874cea42b6a84e 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for SPARC.
 
-   Copyright 2003, 2004 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"
 
 struct regset;
 
-/* This file implements the The SPARC 32-bit ABI as defined by the
-   section "Low-Level System Information" of the SPARC Compliance
-   Definition (SCD) 2.4.1, which is the 32-bit System V psABI for
-   SPARC.  The SCD lists changes with respect to the origional 32-bit
-   psABI as defined in the "System V ABI, SPARC Processor
-   Supplement".
+/* This file implements the SPARC 32-bit ABI as defined by the section
+   "Low-Level System Information" of the SPARC Compliance Definition
+   (SCD) 2.4.1, which is the 32-bit System V psABI for SPARC.  The SCD
+   lists changes with respect to the original 32-bit psABI as defined
+   in the "System V ABI, SPARC Processor Supplement".
 
    Note that if we talk about SunOS, we mean SunOS 4.x, which was
    BSD-based, which is sometimes (retroactively?) referred to as
@@ -81,10 +81,12 @@ struct regset;
 #define X_OP2(i) (((i) >> 22) & 0x7)
 #define X_IMM22(i) ((i) & 0x3fffff)
 #define X_OP3(i) (((i) >> 19) & 0x3f)
+#define X_RS1(i) (((i) >> 14) & 0x1f)
 #define X_I(i) (((i) >> 13) & 1)
 /* Sign extension macros.  */
 #define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000)
 #define X_DISP19(i) ((((i) & 0x7ffff) ^ 0x40000) - 0x40000)
+#define X_SIMM13(i) ((((i) & 0x1fff) ^ 0x1000) - 0x1000)
 
 /* Fetch the instruction at PC.  Instructions are always big-endian
    even if the processor operates in little-endian mode.  */
@@ -92,12 +94,12 @@ struct regset;
 unsigned long
 sparc_fetch_instruction (CORE_ADDR pc)
 {
-  unsigned char buf[4];
+  gdb_byte buf[4];
   unsigned long insn;
   int i;
 
   /* If we can't read the instruction at PC, return zero.  */
-  if (target_read_memory (pc, buf, sizeof (buf)))
+  if (read_memory_nobpt (pc, buf, sizeof (buf)))
     return 0;
 
   insn = 0;
@@ -107,6 +109,17 @@ sparc_fetch_instruction (CORE_ADDR pc)
 }
 \f
 
+/* Return non-zero if the instruction corresponding to PC is an "unimp"
+   instruction.  */
+
+static int
+sparc_is_unimp_insn (CORE_ADDR pc)
+{
+  const unsigned long insn = sparc_fetch_instruction (pc);
+  
+  return ((insn & 0xc1c00000) == 0);
+}
+
 /* OpenBSD/sparc includes StackGhost, which according to the author's
    website http://stackghost.cerias.purdue.edu "... transparently and
    automatically protects applications' stack frames; more
@@ -142,10 +155,10 @@ 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);
+  len = target_read (ops, TARGET_OBJECT_WCOOKIE, NULL, buf, 0, 8);
   if (len == -1)
     return 0;
 
@@ -158,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;
@@ -176,6 +189,8 @@ sparc_address_from_register (int regnum)
 static int
 sparc_integral_or_pointer_p (const struct type *type)
 {
+  int len = TYPE_LENGTH (type);
+
   switch (TYPE_CODE (type))
     {
     case TYPE_CODE_INT:
@@ -183,22 +198,14 @@ sparc_integral_or_pointer_p (const struct type *type)
     case TYPE_CODE_CHAR:
     case TYPE_CODE_ENUM:
     case TYPE_CODE_RANGE:
-      {
-       /* We have byte, half-word, word and extended-word/doubleword
-           integral types.  The doubleword is an extension to the
-           origional 32-bit ABI by the SCD 2.4.x.  */
-       int len = TYPE_LENGTH (type);
-       return (len == 1 || len == 2 || len == 4 || len == 8);
-      }
-      return 1;
+      /* We have byte, half-word, word and extended-word/doubleword
+        integral types.  The doubleword is an extension to the
+        original 32-bit ABI by the SCD 2.4.x.  */
+      return (len == 1 || len == 2 || len == 4 || len == 8);
     case TYPE_CODE_PTR:
     case TYPE_CODE_REF:
-      {
-       /* Allow either 32-bit or 64-bit pointers.  */
-       int len = TYPE_LENGTH (type);
-       return (len == 4 || len == 8);
-      }
-      return 1;
+      /* Allow either 32-bit or 64-bit pointers.  */
+      return (len == 4 || len == 8);
     default:
       break;
     }
@@ -312,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
 
@@ -346,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);
@@ -369,7 +376,7 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
 
   for (i = 0; i < nargs; i++)
     {
-      struct type *type = VALUE_TYPE (args[i]);
+      struct type *type = value_type (args[i]);
       int len = TYPE_LENGTH (type);
 
       if (sparc_structure_or_union_p (type)
@@ -382,7 +389,7 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
              correct, and wasting a few bytes shouldn't be a problem.  */
          sp &= ~0x7;
 
-         write_memory (sp, VALUE_CONTENTS (args[i]), len);
+         write_memory (sp, value_contents (args[i]), len);
          args[i] = value_from_pointer (lookup_pointer_type (type), sp);
          num_elements++;
        }
@@ -417,8 +424,8 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
 
   for (i = 0; i < nargs; i++)
     {
-      char *valbuf = VALUE_CONTENTS (args[i]);
-      struct type *type = VALUE_TYPE (args[i]);
+      const bfd_byte *valbuf = value_contents (args[i]);
+      struct type *type = value_type (args[i]);
       int len = TYPE_LENGTH (type);
 
       gdb_assert (len == 4 || len == 8);
@@ -441,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);
@@ -451,7 +458,7 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
 }
 
 static CORE_ADDR
-sparc32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+sparc32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                         struct regcache *regcache, CORE_ADDR bp_addr,
                         int nargs, struct value **args, CORE_ADDR sp,
                         int struct_return, CORE_ADDR struct_addr)
@@ -484,10 +491,10 @@ sparc32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
    *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;
@@ -599,7 +606,36 @@ sparc32_skip_prologue (CORE_ADDR start_pc)
        return sal.end;
     }
 
-  return sparc_analyze_prologue (start_pc, 0xffffffffUL, &cache);
+  start_pc = sparc_analyze_prologue (start_pc, 0xffffffffUL, &cache);
+
+  /* The psABI says that "Although the first 6 words of arguments
+     reside in registers, the standard stack frame reserves space for
+     them.".  It also suggests that a function may use that space to
+     "write incoming arguments 0 to 5" into that space, and that's
+     indeed what GCC seems to be doing.  In that case GCC will
+     generate debug information that points to the stack slots instead
+     of the registers, so we should consider the instructions that
+     write out these incoming arguments onto the stack.  Of course we
+     only need to do this if we have a stack frame.  */
+
+  while (!cache.frameless_p)
+    {
+      unsigned long insn = sparc_fetch_instruction (start_pc);
+
+      /* Recognize instructions that store incoming arguments in
+         %i0...%i5 into the corresponding stack slot.  */
+      if (X_OP (insn) == 3 && (X_OP3 (insn) & 0x3c) == 0x04 && X_I (insn)
+         && (X_RD (insn) >= 24 && X_RD (insn) <= 29) && X_RS1 (insn) == 30
+         && X_SIMM13 (insn) == 68 + (X_RD (insn) - 24) * 4)
+       {
+         start_pc += 4;
+         continue;
+       }
+
+      break;
+    }
+
+  return start_pc;
 }
 
 /* Normal frames.  */
@@ -615,14 +651,6 @@ sparc_frame_cache (struct frame_info *next_frame, void **this_cache)
   cache = sparc_alloc_frame_cache ();
   *this_cache = cache;
 
-  /* In priciple, for normal frames, %fp (%i6) holds the frame
-     pointer, which holds the base address for the current stack
-     frame.  */
-
-  cache->base = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
-  if (cache->base == 0)
-    return cache;
-
   cache->pc = frame_func_unwind (next_frame);
   if (cache->pc != 0)
     {
@@ -632,15 +660,43 @@ sparc_frame_cache (struct frame_info *next_frame, void **this_cache)
 
   if (cache->frameless_p)
     {
-      /* We didn't find a valid frame, which means that CACHE->base
-        currently holds the frame pointer for our calling frame.  */
-      cache->base = frame_unwind_register_unsigned (next_frame,
-                                                   SPARC_SP_REGNUM);
+      /* This function is frameless, so %fp (%i6) holds the frame
+         pointer for our calling frame.  Use %sp (%o6) as this frame's
+         base address.  */
+      cache->base =
+       frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
+    }
+  else
+    {
+      /* For normal frames, %fp (%i6) holds the frame pointer, the
+         base address for the current stack frame.  */
+      cache->base =
+       frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
     }
 
+  if (cache->base & 1)
+    cache->base += BIAS;
+
   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)
 {
@@ -655,16 +711,22 @@ 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);
+      cache->struct_return_p = sparc32_struct_return_from_sym (sym);
+    }
+  else
+    {
+      /* There is no debugging information for this function to
+         help us determine whether this function returns a struct
+         or not.  So we rely on another heuristic which is to check
+         the instruction at the return address and see if this is
+         an "unimp" instruction.  If it is, then it is a struct-return
+         function.  */
+      CORE_ADDR pc;
+      int regnum = cache->frameless_p ? SPARC_O7_REGNUM : SPARC_I7_REGNUM;
 
-      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;
-       }
+      pc = frame_unwind_register_unsigned (next_frame, regnum) + 8;
+      if (sparc_is_unimp_insn (pc))
+        cache->struct_return_p = 1;
     }
 
   return cache;
@@ -688,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);
@@ -764,8 +826,12 @@ sparc32_frame_prev_register (struct frame_info *next_frame, void **this_cache,
       && regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
     regnum += (SPARC_I0_REGNUM - SPARC_O0_REGNUM);
 
-  frame_register_unwind (next_frame, regnum,
-                        optimizedp, lvalp, addrp, realnump, valuep);
+  *optimizedp = 0;
+  *lvalp = lval_register;
+  *addrp = 0;
+  *realnump = regnum;
+  if (valuep)
+    frame_unwind_register (next_frame, (*realnump), valuep);
 }
 
 static const struct frame_unwind sparc32_frame_unwind =
@@ -805,6 +871,8 @@ sparc_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
   CORE_ADDR sp;
 
   sp = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
+  if (sp & 1)
+    sp += BIAS;
   return frame_id_build (sp, frame_pc_unwind (next_frame));
 }
 \f
@@ -814,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));
@@ -856,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));
@@ -894,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);
@@ -909,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
@@ -948,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;
@@ -986,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)
@@ -1018,39 +1125,42 @@ 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);
-  static CORE_ADDR npc, nnpc;
-  static char npc_save[4], nnpc_save[4];
+  struct gdbarch *arch = current_gdbarch;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+  CORE_ADDR npc, nnpc;
 
   if (insert_breakpoints_p)
     {
-      CORE_ADDR pc;
+      CORE_ADDR pc, orig_npc;
 
       pc = sparc_address_from_register (tdep->pc_regnum);
-      npc = sparc_address_from_register (tdep->npc_regnum);
+      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);
+       insert_single_step_breakpoint (npc);
+
       if (nnpc != 0)
-       target_insert_breakpoint (nnpc, nnpc_save);
+       insert_single_step_breakpoint (nnpc);
 
       /* Assert that we have set at least one breakpoint, and that
-         they're not set at the same spot.  */
-      gdb_assert (npc != 0 || nnpc != 0);
-      gdb_assert (nnpc != npc);
+        they're not set at the same spot - unless we're going
+        from here straight to NULL, i.e. a call or jump to 0.  */
+      gdb_assert (npc != 0 || nnpc != 0 || orig_npc == 0);
+      gdb_assert (nnpc != npc || orig_npc == 0);
     }
   else
-    {
-      if (npc != 0)
-       target_remove_breakpoint (npc, npc_save);
-      if (nnpc != 0)
-       target_remove_breakpoint (nnpc, nnpc_save);
-    }
+    remove_single_step_breakpoints ();
 }
 
 static void
@@ -1135,6 +1245,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);
@@ -1180,6 +1291,11 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   frame_base_set_default (gdbarch, &sparc32_frame_base);
 
+  /* 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.  */
+
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
@@ -1199,7 +1315,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)
@@ -1212,6 +1328,16 @@ sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum)
          if (regnum == i || regnum == -1)
            {
              target_read_memory (sp + ((i - SPARC_L0_REGNUM) * 8), buf, 8);
+
+             /* Handle StackGhost.  */
+             if (i == SPARC_I7_REGNUM)
+               {
+                 ULONGEST wcookie = sparc_fetch_wcookie ();
+                 ULONGEST i7 = extract_unsigned_integer (buf + offset, 8);
+
+                 store_unsigned_integer (buf + offset, 8, i7 ^ wcookie);
+               }
+
              regcache_raw_supply (regcache, i, buf);
            }
        }
@@ -1257,7 +1383,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)
@@ -1270,6 +1396,16 @@ sparc_collect_rwindow (const struct regcache *regcache,
          if (regnum == -1 || regnum == SPARC_SP_REGNUM || regnum == i)
            {
              regcache_raw_collect (regcache, i, buf);
+
+             /* Handle StackGhost.  */
+             if (i == SPARC_I7_REGNUM)
+               {
+                 ULONGEST wcookie = sparc_fetch_wcookie ();
+                 ULONGEST i7 = extract_unsigned_integer (buf + offset, 8);
+
+                 store_unsigned_integer (buf, 8, i7 ^ wcookie);
+               }
+
              target_write_memory (sp + ((i - SPARC_L0_REGNUM) * 8), buf, 8);
            }
        }
@@ -1313,7 +1449,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)
@@ -1377,7 +1513,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)
@@ -1431,7 +1567,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++)
@@ -1448,7 +1584,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.034422 seconds and 4 git commands to generate.