Add _bfd_elf_ifunc_get_synthetic_symtab
[platform/upstream/binutils.git] / gdb / sparc-tdep.c
index 00e802b..7eb3b18 100644 (file)
@@ -1,12 +1,12 @@
 /* Target-dependent code for SPARC.
 
-   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -15,9 +15,7 @@
    GNU General Public License for more details.
 
    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., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "arch-utils.h"
 #include "target.h"
 #include "value.h"
 
-#include "gdb_assert.h"
-#include "gdb_string.h"
-
 #include "sparc-tdep.h"
+#include "sparc-ravenscar-thread.h"
 
 struct regset;
 
@@ -64,8 +60,8 @@ struct regset;
    sparc64-tdep.c; don't add any here.  */
 
 /* The SPARC Floating-Point Quad-Precision format is similar to
-   big-endian IA-64 Quad-recision format.  */
-#define floatformat_sparc_quad floatformat_ia64_quad_big
+   big-endian IA-64 Quad-Precision format.  */
+#define floatformats_sparc_quad floatformats_ia64_quad
 
 /* The stack pointer is offset from the stack frame by a BIAS of 2047
    (0x7ff) for 64-bit code.  BIAS is likely to be defined on SPARC
@@ -82,11 +78,16 @@ struct regset;
 #define X_IMM22(i) ((i) & 0x3fffff)
 #define X_OP3(i) (((i) >> 19) & 0x3f)
 #define X_RS1(i) (((i) >> 14) & 0x1f)
+#define X_RS2(i) ((i) & 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_DISP10(i) ((((((i) >> 11) && 0x300) | (((i) >> 5) & 0xff)) ^ 0x200) - 0x200)
 #define X_SIMM13(i) ((((i) & 0x1fff) ^ 0x1000) - 0x1000)
+/* Macros to identify some instructions.  */
+/* RETURN (RETT in V8) */
+#define X_RETTURN(i) ((X_OP (i) == 0x2) && (X_OP3 (i) == 0x39))
 
 /* Fetch the instruction at PC.  Instructions are always big-endian
    even if the processor operates in little-endian mode.  */
@@ -99,7 +100,7 @@ sparc_fetch_instruction (CORE_ADDR pc)
   int i;
 
   /* If we can't read the instruction at PC, return zero.  */
-  if (read_memory_nobpt (pc, buf, sizeof (buf)))
+  if (target_read_memory (pc, buf, sizeof (buf)))
     return 0;
 
   insn = 0;
@@ -120,6 +121,37 @@ sparc_is_unimp_insn (CORE_ADDR pc)
   return ((insn & 0xc1c00000) == 0);
 }
 
+/* Return non-zero if the instruction corresponding to PC is an
+   "annulled" branch, i.e. the annul bit is set.  */
+
+int
+sparc_is_annulled_branch_insn (CORE_ADDR pc)
+{
+  /* The branch instructions featuring an annul bit can be identified
+     by the following bit patterns:
+
+     OP=0
+      OP2=1: Branch on Integer Condition Codes with Prediction (BPcc).
+      OP2=2: Branch on Integer Condition Codes (Bcc).
+      OP2=5: Branch on FP Condition Codes with Prediction (FBfcc).
+      OP2=6: Branch on FP Condition Codes (FBcc).
+      OP2=3 && Bit28=0:
+             Branch on Integer Register with Prediction (BPr).
+
+     This leaves out ILLTRAP (OP2=0), SETHI/NOP (OP2=4) and the V8
+     coprocessor branch instructions (Op2=7).  */
+
+  const unsigned long insn = sparc_fetch_instruction (pc);
+  const unsigned op2 = X_OP2 (insn);
+
+  if ((X_OP (insn) == 0)
+      && ((op2 == 1) || (op2 == 2) || (op2 == 5) || (op2 == 6)
+         || ((op2 == 3) && ((insn & 0x10000000) == 0))))
+    return X_A (insn);
+  else
+    return 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
@@ -145,15 +177,16 @@ sparc_is_unimp_insn (CORE_ADDR pc)
 
    More information on StackGuard can be found on in:
 
-   Mike Frantzen and Mike Shuey. "StackGhost: Hardware Facilitated
+   Mike Frantzen and Mike Shuey.  "StackGhost: Hardware Facilitated
    Stack Protection."  2001.  Published in USENIX Security Symposium
    '01.  */
 
 /* Fetch StackGhost Per-Process XOR cookie.  */
 
 ULONGEST
-sparc_fetch_wcookie (void)
+sparc_fetch_wcookie (struct gdbarch *gdbarch)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct target_ops *ops = &current_target;
   gdb_byte buf[8];
   int len;
@@ -165,19 +198,7 @@ sparc_fetch_wcookie (void)
   /* We should have either an 32-bit or an 64-bit cookie.  */
   gdb_assert (len == 4 || len == 8);
 
-  return extract_unsigned_integer (buf, len);
-}
-\f
-
-/* Return the contents if register REGNUM as an address.  */
-
-CORE_ADDR
-sparc_address_from_register (int regnum)
-{
-  ULONGEST addr;
-
-  regcache_cooked_read_unsigned (current_regcache, regnum, &addr);
-  return addr;
+  return extract_unsigned_integer (buf, len, byte_order);
 }
 \f
 
@@ -232,7 +253,30 @@ sparc_floating_p (const struct type *type)
   return 0;
 }
 
-/* Check whether TYPE is "Structure or Union".  */
+/* Check whether TYPE is "Complex Floating".  */
+
+static int
+sparc_complex_floating_p (const struct type *type)
+{
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_COMPLEX:
+      {
+       int len = TYPE_LENGTH (type);
+       return (len == 8 || len == 16 || len == 32);
+      }
+    default:
+      break;
+    }
+
+  return 0;
+}
+
+/* Check whether TYPE is "Structure or Union".
+
+   In terms of Ada subprogram calls, arrays are treated the same as
+   struct and union types.  So this function also returns non-zero
+   for array types.  */
 
 static int
 sparc_structure_or_union_p (const struct type *type)
@@ -241,6 +285,7 @@ sparc_structure_or_union_p (const struct type *type)
     {
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
+    case TYPE_CODE_ARRAY:
       return 1;
     default:
       break;
@@ -284,7 +329,7 @@ static const char *sparc32_pseudo_register_names[] =
 /* Return the name of register REGNUM.  */
 
 static const char *
-sparc32_register_name (int regnum)
+sparc32_register_name (struct gdbarch *gdbarch, int regnum)
 {
   if (regnum >= 0 && regnum < SPARC32_NUM_REGS)
     return sparc32_register_names[regnum];
@@ -295,85 +340,104 @@ sparc32_register_name (int regnum)
   return NULL;
 }
 \f
+/* Construct types for ISA-specific registers.  */
 
-/* Type for %psr.  */
-struct type *sparc_psr_type;
+static struct type *
+sparc_psr_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-/* Type for %fsr.  */
-struct type *sparc_fsr_type;
+  if (!tdep->sparc_psr_type)
+    {
+      struct type *type;
 
-/* Construct types for ISA-specific registers.  */
+      type = arch_flags_type (gdbarch, "builtin_type_sparc_psr", 4);
+      append_flags_type_flag (type, 5, "ET");
+      append_flags_type_flag (type, 6, "PS");
+      append_flags_type_flag (type, 7, "S");
+      append_flags_type_flag (type, 12, "EF");
+      append_flags_type_flag (type, 13, "EC");
 
-static void
-sparc_init_types (void)
+      tdep->sparc_psr_type = type;
+    }
+
+  return tdep->sparc_psr_type;
+}
+
+static struct type *
+sparc_fsr_type (struct gdbarch *gdbarch)
 {
-  struct type *type;
-
-  type = init_flags_type ("builtin_type_sparc_psr", 4);
-  append_flags_type_flag (type, 5, "ET");
-  append_flags_type_flag (type, 6, "PS");
-  append_flags_type_flag (type, 7, "S");
-  append_flags_type_flag (type, 12, "EF");
-  append_flags_type_flag (type, 13, "EC");
-  sparc_psr_type = type;
-
-  type = init_flags_type ("builtin_type_sparc_fsr", 4);
-  append_flags_type_flag (type, 0, "NXA");
-  append_flags_type_flag (type, 1, "DZA");
-  append_flags_type_flag (type, 2, "UFA");
-  append_flags_type_flag (type, 3, "OFA");
-  append_flags_type_flag (type, 4, "NVA");
-  append_flags_type_flag (type, 5, "NXC");
-  append_flags_type_flag (type, 6, "DZC");
-  append_flags_type_flag (type, 7, "UFC");
-  append_flags_type_flag (type, 8, "OFC");
-  append_flags_type_flag (type, 9, "NVC");
-  append_flags_type_flag (type, 22, "NS");
-  append_flags_type_flag (type, 23, "NXM");
-  append_flags_type_flag (type, 24, "DZM");
-  append_flags_type_flag (type, 25, "UFM");
-  append_flags_type_flag (type, 26, "OFM");
-  append_flags_type_flag (type, 27, "NVM");
-  sparc_fsr_type = type;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (!tdep->sparc_fsr_type)
+    {
+      struct type *type;
+
+      type = arch_flags_type (gdbarch, "builtin_type_sparc_fsr", 4);
+      append_flags_type_flag (type, 0, "NXA");
+      append_flags_type_flag (type, 1, "DZA");
+      append_flags_type_flag (type, 2, "UFA");
+      append_flags_type_flag (type, 3, "OFA");
+      append_flags_type_flag (type, 4, "NVA");
+      append_flags_type_flag (type, 5, "NXC");
+      append_flags_type_flag (type, 6, "DZC");
+      append_flags_type_flag (type, 7, "UFC");
+      append_flags_type_flag (type, 8, "OFC");
+      append_flags_type_flag (type, 9, "NVC");
+      append_flags_type_flag (type, 22, "NS");
+      append_flags_type_flag (type, 23, "NXM");
+      append_flags_type_flag (type, 24, "DZM");
+      append_flags_type_flag (type, 25, "UFM");
+      append_flags_type_flag (type, 26, "OFM");
+      append_flags_type_flag (type, 27, "NVM");
+
+      tdep->sparc_fsr_type = type;
+    }
+
+  return tdep->sparc_fsr_type;
 }
 
 /* Return the GDB type object for the "standard" data type of data in
-   register REGNUM. */
+   register REGNUM.  */
 
 static struct type *
 sparc32_register_type (struct gdbarch *gdbarch, int regnum)
 {
   if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
-    return builtin_type_float;
+    return builtin_type (gdbarch)->builtin_float;
 
   if (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM)
-    return builtin_type_double;
+    return builtin_type (gdbarch)->builtin_double;
 
   if (regnum == SPARC_SP_REGNUM || regnum == SPARC_FP_REGNUM)
-    return builtin_type_void_data_ptr;
+    return builtin_type (gdbarch)->builtin_data_ptr;
 
   if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM)
-    return builtin_type_void_func_ptr;
+    return builtin_type (gdbarch)->builtin_func_ptr;
 
   if (regnum == SPARC32_PSR_REGNUM)
-    return sparc_psr_type;
+    return sparc_psr_type (gdbarch);
 
   if (regnum == SPARC32_FSR_REGNUM)
-    return sparc_fsr_type;
+    return sparc_fsr_type (gdbarch);
 
-  return builtin_type_int32;
+  return builtin_type (gdbarch)->builtin_int32;
 }
 
-static void
+static enum register_status
 sparc32_pseudo_register_read (struct gdbarch *gdbarch,
                              struct regcache *regcache,
                              int regnum, gdb_byte *buf)
 {
+  enum register_status status;
+
   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, buf + 4);
+  status = regcache_raw_read (regcache, regnum, buf);
+  if (status == REG_VALID)
+    status = regcache_raw_read (regcache, regnum + 1, buf + 4);
+  return status;
 }
 
 static void
@@ -388,23 +452,57 @@ sparc32_pseudo_register_write (struct gdbarch *gdbarch,
   regcache_raw_write (regcache, regnum + 1, buf + 4);
 }
 \f
+/* Implement "in_function_epilogue_p".  */
+
+int
+sparc_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  /* This function must return true if we are one instruction after an
+     instruction that destroyed the stack frame of the current
+     function.  The SPARC instructions used to restore the callers
+     stack frame are RESTORE and RETURN/RETT.
+
+     Of these RETURN/RETT is a branch instruction and thus we return
+     true if we are in its delay slot.
+
+     RESTORE is almost always found in the delay slot of a branch
+     instruction that transfers control to the caller, such as JMPL.
+     Thus the next instruction is in the caller frame and we don't
+     need to do anything about it.  */
+
+  unsigned int insn = sparc_fetch_instruction (pc - 4);
+
+  return X_RETTURN (insn);
+}
+\f
+
+static CORE_ADDR
+sparc32_frame_align (struct gdbarch *gdbarch, CORE_ADDR address)
+{
+  /* The ABI requires double-word alignment.  */
+  return address & ~0x7;
+}
 
 static CORE_ADDR
 sparc32_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
-                        CORE_ADDR funcaddr, int using_gcc,
+                        CORE_ADDR funcaddr,
                         struct value **args, int nargs,
                         struct type *value_type,
-                        CORE_ADDR *real_pc, CORE_ADDR *bp_addr)
+                        CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
+                        struct regcache *regcache)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
   *bp_addr = sp - 4;
   *real_pc = funcaddr;
 
-  if (using_struct_return (value_type, using_gcc))
+  if (using_struct_return (gdbarch, NULL, value_type))
     {
       gdb_byte buf[4];
 
       /* This is an UNIMP instruction.  */
-      store_unsigned_integer (buf, 4, TYPE_LENGTH (value_type) & 0x1fff);
+      store_unsigned_integer (buf, 4, byte_order,
+                             TYPE_LENGTH (value_type) & 0x1fff);
       write_memory (sp - 8, buf, 4);
       return sp - 8;
     }
@@ -417,6 +515,8 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
                         struct value **args, CORE_ADDR sp,
                         int struct_return, CORE_ADDR struct_addr)
 {
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   /* Number of words in the "parameter array".  */
   int num_elements = 0;
   int element = 0;
@@ -428,7 +528,8 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
       int len = TYPE_LENGTH (type);
 
       if (sparc_structure_or_union_p (type)
-         || (sparc_floating_p (type) && len == 16))
+         || (sparc_floating_p (type) && len == 16)
+         || sparc_complex_floating_p (type))
        {
          /* Structure, Union and Quad-Precision Arguments.  */
          sp -= len;
@@ -453,7 +554,8 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
          gdb_assert (sparc_integral_or_pointer_p (type));
 
          if (len < 4)
-           args[i] = value_cast (builtin_type_int32, args[i]);
+           args[i] = value_cast (builtin_type (gdbarch)->builtin_int32,
+                                 args[i]);
          num_elements += ((len + 3) / 4);
        }
     }
@@ -498,7 +600,7 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
     {
       gdb_byte buf[4];
 
-      store_unsigned_integer (buf, 4, struct_addr);
+      store_unsigned_integer (buf, 4, byte_order, struct_addr);
       write_memory (sp, buf, 4);
     }
 
@@ -540,7 +642,7 @@ sparc32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
    location for inserting the breakpoint.  */
    
 static const gdb_byte *
-sparc_breakpoint_from_pc (CORE_ADDR *pc, int *len)
+sparc_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc, int *len)
 {
   static const gdb_byte break_insn[] = { 0x91, 0xd0, 0x20, 0x01 };
 
@@ -555,7 +657,6 @@ static struct sparc_frame_cache *
 sparc_alloc_frame_cache (void)
 {
   struct sparc_frame_cache *cache;
-  int i;
 
   cache = FRAME_OBSTACK_ZALLOC (struct sparc_frame_cache);
 
@@ -565,21 +666,236 @@ sparc_alloc_frame_cache (void)
 
   /* Frameless until proven otherwise.  */
   cache->frameless_p = 1;
-
+  cache->frame_offset = 0;
+  cache->saved_regs_mask = 0;
+  cache->copied_regs_mask = 0;
   cache->struct_return_p = 0;
 
   return cache;
 }
 
+/* GCC generates several well-known sequences of instructions at the begining
+   of each function prologue when compiling with -fstack-check.  If one of
+   such sequences starts at START_PC, then return the address of the
+   instruction immediately past this sequence.  Otherwise, return START_PC.  */
+   
+static CORE_ADDR
+sparc_skip_stack_check (const CORE_ADDR start_pc)
+{
+  CORE_ADDR pc = start_pc;
+  unsigned long insn;
+  int offset_stack_checking_sequence = 0;
+  int probing_loop = 0;
+
+  /* With GCC, all stack checking sequences begin with the same two
+     instructions, plus an optional one in the case of a probing loop:
+
+         sethi <some immediate>, %g1
+         sub %sp, %g1, %g1
+
+     or:
+
+         sethi <some immediate>, %g1
+         sethi <some immediate>, %g4
+         sub %sp, %g1, %g1
+
+     or:
+
+         sethi <some immediate>, %g1
+         sub %sp, %g1, %g1
+         sethi <some immediate>, %g4
+
+     If the optional instruction is found (setting g4), assume that a
+     probing loop will follow.  */
+
+  /* sethi <some immediate>, %g1 */
+  insn = sparc_fetch_instruction (pc);
+  pc = pc + 4;
+  if (!(X_OP (insn) == 0 && X_OP2 (insn) == 0x4 && X_RD (insn) == 1))
+    return start_pc;
+
+  /* optional: sethi <some immediate>, %g4 */
+  insn = sparc_fetch_instruction (pc);
+  pc = pc + 4;
+  if (X_OP (insn) == 0 && X_OP2 (insn) == 0x4 && X_RD (insn) == 4)
+    {
+      probing_loop = 1;
+      insn = sparc_fetch_instruction (pc);
+      pc = pc + 4;
+    }
+
+  /* sub %sp, %g1, %g1 */
+  if (!(X_OP (insn) == 2 && X_OP3 (insn) == 0x4 && !X_I(insn)
+        && X_RD (insn) == 1 && X_RS1 (insn) == 14 && X_RS2 (insn) == 1))
+    return start_pc;
+
+  insn = sparc_fetch_instruction (pc);
+  pc = pc + 4;
+
+  /* optional: sethi <some immediate>, %g4 */
+  if (X_OP (insn) == 0 && X_OP2 (insn) == 0x4 && X_RD (insn) == 4)
+    {
+      probing_loop = 1;
+      insn = sparc_fetch_instruction (pc);
+      pc = pc + 4;
+    }
+
+  /* First possible sequence:
+         [first two instructions above]
+         clr [%g1 - some immediate]  */
+
+  /* clr [%g1 - some immediate]  */
+  if (X_OP (insn) == 3 && X_OP3(insn) == 0x4 && X_I(insn)
+      && X_RS1 (insn) == 1 && X_RD (insn) == 0)
+    {
+      /* Valid stack-check sequence, return the new PC.  */
+      return pc;
+    }
+
+  /* Second possible sequence: A small number of probes.
+         [first two instructions above]
+         clr [%g1]
+         add   %g1, -<some immediate>, %g1
+         clr [%g1]
+         [repeat the two instructions above any (small) number of times]
+         clr [%g1 - some immediate]  */
+
+  /* clr [%g1] */
+  else if (X_OP (insn) == 3 && X_OP3(insn) == 0x4 && !X_I(insn)
+      && X_RS1 (insn) == 1 && X_RD (insn) == 0)
+    {
+      while (1)
+        {
+          /* add %g1, -<some immediate>, %g1 */
+          insn = sparc_fetch_instruction (pc);
+          pc = pc + 4;
+          if (!(X_OP (insn) == 2  && X_OP3(insn) == 0 && X_I(insn)
+                && X_RS1 (insn) == 1 && X_RD (insn) == 1))
+            break;
+
+          /* clr [%g1] */
+          insn = sparc_fetch_instruction (pc);
+          pc = pc + 4;
+          if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && !X_I(insn)
+                && X_RD (insn) == 0 && X_RS1 (insn) == 1))
+            return start_pc;
+        }
+
+      /* clr [%g1 - some immediate] */
+      if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && X_I(insn)
+            && X_RS1 (insn) == 1 && X_RD (insn) == 0))
+        return start_pc;
+
+      /* We found a valid stack-check sequence, return the new PC.  */
+      return pc;
+    }
+  
+  /* Third sequence: A probing loop.
+         [first three instructions above]
+         sub  %g1, %g4, %g4
+         cmp  %g1, %g4
+         be  <disp>
+         add  %g1, -<some immediate>, %g1
+         ba  <disp>
+         clr  [%g1]
+
+     And an optional last probe for the remainder:
+
+         clr [%g4 - some immediate]  */
+
+  if (probing_loop)
+    {
+      /* sub  %g1, %g4, %g4 */
+      if (!(X_OP (insn) == 2 && X_OP3 (insn) == 0x4 && !X_I(insn)
+            && X_RD (insn) == 4 && X_RS1 (insn) == 1 && X_RS2 (insn) == 4))
+        return start_pc;
+
+      /* cmp  %g1, %g4 */
+      insn = sparc_fetch_instruction (pc);
+      pc = pc + 4;
+      if (!(X_OP (insn) == 2 && X_OP3 (insn) == 0x14 && !X_I(insn)
+            && X_RD (insn) == 0 && X_RS1 (insn) == 1 && X_RS2 (insn) == 4))
+        return start_pc;
+
+      /* be  <disp> */
+      insn = sparc_fetch_instruction (pc);
+      pc = pc + 4;
+      if (!(X_OP (insn) == 0 && X_COND (insn) == 0x1))
+        return start_pc;
+
+      /* add  %g1, -<some immediate>, %g1 */
+      insn = sparc_fetch_instruction (pc);
+      pc = pc + 4;
+      if (!(X_OP (insn) == 2  && X_OP3(insn) == 0 && X_I(insn)
+            && X_RS1 (insn) == 1 && X_RD (insn) == 1))
+        return start_pc;
+
+      /* ba  <disp> */
+      insn = sparc_fetch_instruction (pc);
+      pc = pc + 4;
+      if (!(X_OP (insn) == 0 && X_COND (insn) == 0x8))
+        return start_pc;
+
+      /* clr  [%g1] (st %g0, [%g1] or st %g0, [%g1+0]) */
+      insn = sparc_fetch_instruction (pc);
+      pc = pc + 4;
+      if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4
+            && X_RD (insn) == 0 && X_RS1 (insn) == 1
+           && (!X_I(insn) || X_SIMM13 (insn) == 0)))
+        return start_pc;
+
+      /* We found a valid stack-check sequence, return the new PC.  */
+
+      /* optional: clr [%g4 - some immediate]  */
+      insn = sparc_fetch_instruction (pc);
+      pc = pc + 4;
+      if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && X_I(insn)
+            && X_RS1 (insn) == 4 && X_RD (insn) == 0))
+        return pc - 4;
+      else
+       return pc;
+    }
+
+  /* No stack check code in our prologue, return the start_pc.  */
+  return start_pc;
+}
+
+/* Record the effect of a SAVE instruction on CACHE.  */
+
+void
+sparc_record_save_insn (struct sparc_frame_cache *cache)
+{
+  /* The frame is set up.  */
+  cache->frameless_p = 0;
+
+  /* The frame pointer contains the CFA.  */
+  cache->frame_offset = 0;
+
+  /* The `local' and `in' registers are all saved.  */
+  cache->saved_regs_mask = 0xffff;
+
+  /* The `out' registers are all renamed.  */
+  cache->copied_regs_mask = 0xff;
+}
+
+/* Do a full analysis of the prologue at PC and update CACHE accordingly.
+   Bail out early if CURRENT_PC is reached.  Return the address where
+   the analysis stopped.
+
+   We handle both the traditional register window model and the single
+   register window (aka flat) model.  */
+
 CORE_ADDR
-sparc_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
-                       struct sparc_frame_cache *cache)
+sparc_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
+                       CORE_ADDR current_pc, struct sparc_frame_cache *cache)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   unsigned long insn;
   int offset = 0;
   int dest = -1;
 
+  pc = sparc_skip_stack_check (pc);
+
   if (current_pc <= pc)
     return current_pc;
 
@@ -593,18 +909,45 @@ sparc_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
      dynamic linker patches up the first PLT with some code that
      starts with a SAVE instruction.  Patch up PC such that it points
      at the start of our PLT entry.  */
-  if (tdep->plt_entry_size > 0 && in_plt_section (current_pc, NULL))
+  if (tdep->plt_entry_size > 0 && in_plt_section (current_pc))
     pc = current_pc - ((current_pc - pc) % tdep->plt_entry_size);
 
   insn = sparc_fetch_instruction (pc);
 
+  /* Recognize store insns and record their sources.  */
+  while (X_OP (insn) == 3
+        && (X_OP3 (insn) == 0x4     /* stw */
+            || X_OP3 (insn) == 0x7  /* std */
+            || X_OP3 (insn) == 0xe) /* stx */
+        && X_RS1 (insn) == SPARC_SP_REGNUM)
+    {
+      int regnum = X_RD (insn);
+
+      /* Recognize stores into the corresponding stack slots.  */
+      if (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM
+         && ((X_I (insn)
+              && X_SIMM13 (insn) == (X_OP3 (insn) == 0xe
+                                     ? (regnum - SPARC_L0_REGNUM) * 8 + BIAS
+                                     : (regnum - SPARC_L0_REGNUM) * 4))
+             || (!X_I (insn) && regnum == SPARC_L0_REGNUM)))
+       {
+         cache->saved_regs_mask |= (1 << (regnum - SPARC_L0_REGNUM));
+         if (X_OP3 (insn) == 0x7)
+           cache->saved_regs_mask |= (1 << (regnum + 1 - SPARC_L0_REGNUM));
+       }
+
+      offset += 4;
+
+      insn = sparc_fetch_instruction (pc + offset);
+    }
+
   /* Recognize a SETHI insn and record its destination.  */
   if (X_OP (insn) == 0 && X_OP2 (insn) == 0x04)
     {
       dest = X_RD (insn);
       offset += 4;
 
-      insn = sparc_fetch_instruction (pc + 4);
+      insn = sparc_fetch_instruction (pc + offset);
     }
 
   /* Allow for an arithmetic operation on DEST or %g1.  */
@@ -613,31 +956,79 @@ sparc_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
     {
       offset += 4;
 
-      insn = sparc_fetch_instruction (pc + 8);
+      insn = sparc_fetch_instruction (pc + offset);
     }
 
   /* Check for the SAVE instruction that sets up the frame.  */
   if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3c)
     {
-      cache->frameless_p = 0;
-      return pc + offset + 4;
+      sparc_record_save_insn (cache);
+      offset += 4;
+      return pc + offset;
+    }
+
+  /* Check for an arithmetic operation on %sp.  */
+  if (X_OP (insn) == 2
+      && (X_OP3 (insn) == 0 || X_OP3 (insn) == 0x4)
+      && X_RS1 (insn) == SPARC_SP_REGNUM
+      && X_RD (insn) == SPARC_SP_REGNUM)
+    {
+      if (X_I (insn))
+       {
+         cache->frame_offset = X_SIMM13 (insn);
+         if (X_OP3 (insn) == 0)
+           cache->frame_offset = -cache->frame_offset;
+       }
+      offset += 4;
+
+      insn = sparc_fetch_instruction (pc + offset);
+
+      /* Check for an arithmetic operation that sets up the frame.  */
+      if (X_OP (insn) == 2
+         && (X_OP3 (insn) == 0 || X_OP3 (insn) == 0x4)
+         && X_RS1 (insn) == SPARC_SP_REGNUM
+         && X_RD (insn) == SPARC_FP_REGNUM)
+       {
+         cache->frameless_p = 0;
+         cache->frame_offset = 0;
+         /* We could check that the amount subtracted to %sp above is the
+            same as the one added here, but this seems superfluous.  */
+         cache->copied_regs_mask |= 0x40;
+         offset += 4;
+
+         insn = sparc_fetch_instruction (pc + offset);
+       }
+
+      /* Check for a move (or) operation that copies the return register.  */
+      if (X_OP (insn) == 2
+         && X_OP3 (insn) == 0x2
+         && !X_I (insn)
+         && X_RS1 (insn) == SPARC_G0_REGNUM
+         && X_RS2 (insn) == SPARC_O7_REGNUM
+         && X_RD (insn) == SPARC_I7_REGNUM)
+       {
+          cache->copied_regs_mask |= 0x80;
+          offset += 4;
+       }
+
+      return pc + offset;
     }
 
   return pc;
 }
 
 static CORE_ADDR
-sparc_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+sparc_unwind_pc (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  return frame_unwind_register_unsigned (next_frame, tdep->pc_regnum);
+  return frame_unwind_register_unsigned (this_frame, tdep->pc_regnum);
 }
 
 /* Return PC of first real instruction of the function starting at
    START_PC.  */
 
 static CORE_ADDR
-sparc32_skip_prologue (CORE_ADDR start_pc)
+sparc32_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
 {
   struct symtab_and_line sal;
   CORE_ADDR func_start, func_end;
@@ -654,7 +1045,7 @@ sparc32_skip_prologue (CORE_ADDR start_pc)
        return sal.end;
     }
 
-  start_pc = sparc_analyze_prologue (start_pc, 0xffffffffUL, &cache);
+  start_pc = sparc_analyze_prologue (gdbarch, 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
@@ -663,21 +1054,36 @@ sparc32_skip_prologue (CORE_ADDR start_pc)
      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.  */
+     write out these incoming arguments onto the stack.  */
 
-  while (!cache.frameless_p)
+  while (1)
     {
       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)
+      /* Recognize instructions that store incoming arguments into the
+        corresponding stack slots.  */
+      if (X_OP (insn) == 3 && (X_OP3 (insn) & 0x3c) == 0x04
+         && X_I (insn) && X_RS1 (insn) == SPARC_FP_REGNUM)
        {
-         start_pc += 4;
-         continue;
+         int regnum = X_RD (insn);
+
+         /* Case of arguments still in %o[0..5].  */
+         if (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O5_REGNUM
+             && !(cache.copied_regs_mask & (1 << (regnum - SPARC_O0_REGNUM)))
+             && X_SIMM13 (insn) == 68 + (regnum - SPARC_O0_REGNUM) * 4)
+           {
+             start_pc += 4;
+             continue;
+           }
+
+         /* Case of arguments copied into %i[0..5].  */
+         if (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I5_REGNUM
+             && (cache.copied_regs_mask & (1 << (regnum - SPARC_I0_REGNUM)))
+             && X_SIMM13 (insn) == 68 + (regnum - SPARC_I0_REGNUM) * 4)
+           {
+             start_pc += 4;
+             continue;
+           }
        }
 
       break;
@@ -689,7 +1095,7 @@ sparc32_skip_prologue (CORE_ADDR start_pc)
 /* Normal frames.  */
 
 struct sparc_frame_cache *
-sparc_frame_cache (struct frame_info *next_frame, void **this_cache)
+sparc_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
   struct sparc_frame_cache *cache;
 
@@ -699,12 +1105,10 @@ sparc_frame_cache (struct frame_info *next_frame, void **this_cache)
   cache = sparc_alloc_frame_cache ();
   *this_cache = cache;
 
-  cache->pc = frame_func_unwind (next_frame);
+  cache->pc = get_frame_func (this_frame);
   if (cache->pc != 0)
-    {
-      CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame);
-      sparc_analyze_prologue (cache->pc, addr_in_block, cache);
-    }
+    sparc_analyze_prologue (get_frame_arch (this_frame), cache->pc,
+                           get_frame_pc (this_frame), cache);
 
   if (cache->frameless_p)
     {
@@ -712,16 +1116,18 @@ sparc_frame_cache (struct frame_info *next_frame, void **this_cache)
          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);
+        get_frame_register_unsigned (this_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);
+       get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
     }
 
+  cache->base += cache->frame_offset;
+
   if (cache->base & 1)
     cache->base += BIAS;
 
@@ -746,7 +1152,7 @@ sparc32_struct_return_from_sym (struct symbol *sym)
 }
 
 struct sparc_frame_cache *
-sparc32_frame_cache (struct frame_info *next_frame, void **this_cache)
+sparc32_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
   struct sparc_frame_cache *cache;
   struct symbol *sym;
@@ -754,7 +1160,7 @@ sparc32_frame_cache (struct frame_info *next_frame, void **this_cache)
   if (*this_cache)
     return *this_cache;
 
-  cache = sparc_frame_cache (next_frame, this_cache);
+  cache = sparc_frame_cache (this_frame, this_cache);
 
   sym = find_pc_function (cache->pc);
   if (sym)
@@ -770,9 +1176,10 @@ sparc32_frame_cache (struct frame_info *next_frame, void **this_cache)
          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;
+      int regnum =
+       (cache->copied_regs_mask & 0x80) ? SPARC_I7_REGNUM : SPARC_O7_REGNUM;
 
-      pc = frame_unwind_register_unsigned (next_frame, regnum) + 8;
+      pc = get_frame_register_unsigned (this_frame, regnum) + 8;
       if (sparc_is_unimp_insn (pc))
         cache->struct_return_p = 1;
     }
@@ -781,11 +1188,11 @@ sparc32_frame_cache (struct frame_info *next_frame, void **this_cache)
 }
 
 static void
-sparc32_frame_this_id (struct frame_info *next_frame, void **this_cache,
+sparc32_frame_this_id (struct frame_info *this_frame, void **this_cache,
                       struct frame_id *this_id)
 {
   struct sparc_frame_cache *cache =
-    sparc32_frame_cache (next_frame, this_cache);
+    sparc32_frame_cache (this_frame, this_cache);
 
   /* This marks the outermost frame.  */
   if (cache->base == 0)
@@ -794,113 +1201,80 @@ sparc32_frame_this_id (struct frame_info *next_frame, void **this_cache,
   (*this_id) = frame_id_build (cache->base, cache->pc);
 }
 
-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, gdb_byte *valuep)
+static struct value *
+sparc32_frame_prev_register (struct frame_info *this_frame,
+                            void **this_cache, int regnum)
 {
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct sparc_frame_cache *cache =
-    sparc32_frame_cache (next_frame, this_cache);
+    sparc32_frame_cache (this_frame, this_cache);
 
   if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM)
     {
-      *optimizedp = 0;
-      *lvalp = not_lval;
-      *addrp = 0;
-      *realnump = -1;
-      if (valuep)
-       {
-         CORE_ADDR pc = (regnum == SPARC32_NPC_REGNUM) ? 4 : 0;
-
-         /* If this functions has a Structure, Union or
-             Quad-Precision return value, we have to skip the UNIMP
-             instruction that encodes the size of the structure.  */
-         if (cache->struct_return_p)
-           pc += 4;
-
-         regnum = cache->frameless_p ? SPARC_O7_REGNUM : SPARC_I7_REGNUM;
-         pc += frame_unwind_register_unsigned (next_frame, regnum) + 8;
-         store_unsigned_integer (valuep, 4, pc);
-       }
-      return;
+      CORE_ADDR pc = (regnum == SPARC32_NPC_REGNUM) ? 4 : 0;
+
+      /* If this functions has a Structure, Union or Quad-Precision
+        return value, we have to skip the UNIMP instruction that encodes
+        the size of the structure.  */
+      if (cache->struct_return_p)
+       pc += 4;
+
+      regnum =
+       (cache->copied_regs_mask & 0x80) ? SPARC_I7_REGNUM : SPARC_O7_REGNUM;
+      pc += get_frame_register_unsigned (this_frame, regnum) + 8;
+      return frame_unwind_got_constant (this_frame, regnum, pc);
     }
 
   /* Handle StackGhost.  */
   {
-    ULONGEST wcookie = sparc_fetch_wcookie ();
+    ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
 
     if (wcookie != 0 && !cache->frameless_p && regnum == SPARC_I7_REGNUM)
       {
-       *optimizedp = 0;
-       *lvalp = not_lval;
-       *addrp = 0;
-       *realnump = -1;
-       if (valuep)
-         {
-           CORE_ADDR addr = cache->base + (regnum - SPARC_L0_REGNUM) * 4;
-           ULONGEST i7;
-
-           /* Read the value in from memory.  */
-           i7 = get_frame_memory_unsigned (next_frame, addr, 4);
-           store_unsigned_integer (valuep, 4, i7 ^ wcookie);
-         }
-       return;
+        CORE_ADDR addr = cache->base + (regnum - SPARC_L0_REGNUM) * 4;
+        ULONGEST i7;
+
+        /* Read the value in from memory.  */
+        i7 = get_frame_memory_unsigned (this_frame, addr, 4);
+        return frame_unwind_got_constant (this_frame, regnum, i7 ^ wcookie);
       }
   }
 
-  /* The previous frame's `local' and `in' registers have been saved
+  /* The previous frame's `local' and `in' registers may have been saved
      in the register save area.  */
-  if (!cache->frameless_p
-      && regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM)
+  if (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM
+      && (cache->saved_regs_mask & (1 << (regnum - SPARC_L0_REGNUM))))
     {
-      *optimizedp = 0;
-      *lvalp = lval_memory;
-      *addrp = cache->base + (regnum - SPARC_L0_REGNUM) * 4;
-      *realnump = -1;
-      if (valuep)
-       {
-         struct gdbarch *gdbarch = get_frame_arch (next_frame);
+      CORE_ADDR addr = cache->base + (regnum - SPARC_L0_REGNUM) * 4;
 
-         /* Read the value in from memory.  */
-         read_memory (*addrp, valuep, register_size (gdbarch, regnum));
-       }
-      return;
+      return frame_unwind_got_memory (this_frame, regnum, addr);
     }
 
-  /* The previous frame's `out' registers are accessable as the
-     current frame's `in' registers.  */
-  if (!cache->frameless_p
-      && regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
+  /* The previous frame's `out' registers may be accessible as the current
+     frame's `in' registers.  */
+  if (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM
+      && (cache->copied_regs_mask & (1 << (regnum - SPARC_O0_REGNUM))))
     regnum += (SPARC_I0_REGNUM - SPARC_O0_REGNUM);
 
-  *optimizedp = 0;
-  *lvalp = lval_register;
-  *addrp = 0;
-  *realnump = regnum;
-  if (valuep)
-    frame_unwind_register (next_frame, (*realnump), valuep);
+  return frame_unwind_got_register (this_frame, regnum, regnum);
 }
 
 static const struct frame_unwind sparc32_frame_unwind =
 {
   NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
   sparc32_frame_this_id,
-  sparc32_frame_prev_register
+  sparc32_frame_prev_register,
+  NULL,
+  default_frame_sniffer
 };
-
-static const struct frame_unwind *
-sparc32_frame_sniffer (struct frame_info *next_frame)
-{
-  return &sparc32_frame_unwind;
-}
 \f
 
 static CORE_ADDR
-sparc32_frame_base_address (struct frame_info *next_frame, void **this_cache)
+sparc32_frame_base_address (struct frame_info *this_frame, void **this_cache)
 {
   struct sparc_frame_cache *cache =
-    sparc32_frame_cache (next_frame, this_cache);
+    sparc32_frame_cache (this_frame, this_cache);
 
   return cache->base;
 }
@@ -914,36 +1288,48 @@ static const struct frame_base sparc32_frame_base =
 };
 
 static struct frame_id
-sparc_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+sparc_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
   CORE_ADDR sp;
 
-  sp = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
+  sp = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM);
   if (sp & 1)
     sp += BIAS;
-  return frame_id_build (sp, frame_pc_unwind (next_frame));
+  return frame_id_build (sp, get_frame_pc (this_frame));
 }
 \f
 
-/* Extract from an array REGBUF containing the (raw) register state, a
-   function return value of TYPE, and copy that into VALBUF.  */
+/* Extract a function return value of TYPE from REGCACHE, and copy
+   that into VALBUF.  */
 
 static void
 sparc32_extract_return_value (struct type *type, struct regcache *regcache,
                              gdb_byte *valbuf)
 {
   int len = TYPE_LENGTH (type);
-  gdb_byte buf[8];
+  gdb_byte buf[32];
 
   gdb_assert (!sparc_structure_or_union_p (type));
   gdb_assert (!(sparc_floating_p (type) && len == 16));
 
-  if (sparc_floating_p (type))
+  if (sparc_floating_p (type) || sparc_complex_floating_p (type))
     {
       /* Floating return values.  */
       regcache_cooked_read (regcache, SPARC_F0_REGNUM, buf);
       if (len > 4)
        regcache_cooked_read (regcache, SPARC_F1_REGNUM, buf + 4);
+      if (len > 8)
+       {
+         regcache_cooked_read (regcache, SPARC_F2_REGNUM, buf + 8);
+         regcache_cooked_read (regcache, SPARC_F3_REGNUM, buf + 12);
+       }
+      if (len > 16)
+       {
+         regcache_cooked_read (regcache, SPARC_F4_REGNUM, buf + 16);
+         regcache_cooked_read (regcache, SPARC_F5_REGNUM, buf + 20);
+         regcache_cooked_read (regcache, SPARC_F6_REGNUM, buf + 24);
+         regcache_cooked_read (regcache, SPARC_F7_REGNUM, buf + 28);
+       }
       memcpy (valbuf, buf, len);
     }
   else
@@ -967,8 +1353,8 @@ sparc32_extract_return_value (struct type *type, struct regcache *regcache,
     }
 }
 
-/* Write into the appropriate registers a function return value stored
-   in VALBUF of type TYPE.  */
+/* Store the function return value of type TYPE from VALBUF into
+   REGCACHE.  */
 
 static void
 sparc32_store_return_value (struct type *type, struct regcache *regcache,
@@ -979,14 +1365,27 @@ sparc32_store_return_value (struct type *type, struct regcache *regcache,
 
   gdb_assert (!sparc_structure_or_union_p (type));
   gdb_assert (!(sparc_floating_p (type) && len == 16));
+  gdb_assert (len <= 8);
 
-  if (sparc_floating_p (type))
+  if (sparc_floating_p (type) || sparc_complex_floating_p (type))
     {
       /* Floating return values.  */
       memcpy (buf, valbuf, len);
       regcache_cooked_write (regcache, SPARC_F0_REGNUM, buf);
       if (len > 4)
        regcache_cooked_write (regcache, SPARC_F1_REGNUM, buf + 4);
+      if (len > 8)
+       {
+         regcache_cooked_write (regcache, SPARC_F2_REGNUM, buf + 8);
+         regcache_cooked_write (regcache, SPARC_F3_REGNUM, buf + 12);
+       }
+      if (len > 16)
+       {
+         regcache_cooked_write (regcache, SPARC_F4_REGNUM, buf + 16);
+         regcache_cooked_write (regcache, SPARC_F5_REGNUM, buf + 20);
+         regcache_cooked_write (regcache, SPARC_F6_REGNUM, buf + 24);
+         regcache_cooked_write (regcache, SPARC_F7_REGNUM, buf + 28);
+       }
     }
   else
     {
@@ -1009,10 +1408,12 @@ 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, gdb_byte *readbuf,
-                     const gdb_byte *writebuf)
+sparc32_return_value (struct gdbarch *gdbarch, struct value *function,
+                     struct type *type, struct regcache *regcache,
+                     gdb_byte *readbuf, const gdb_byte *writebuf)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
   /* 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
@@ -1023,15 +1424,21 @@ sparc32_return_value (struct gdbarch *gdbarch, struct type *type,
   if (sparc_structure_or_union_p (type)
       || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
     {
+      ULONGEST sp;
+      CORE_ADDR addr;
+
       if (readbuf)
        {
-         ULONGEST sp;
-         CORE_ADDR addr;
-
          regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
-         addr = read_memory_unsigned_integer (sp + 64, 4);
+         addr = read_memory_unsigned_integer (sp + 64, 4, byte_order);
          read_memory (addr, readbuf, TYPE_LENGTH (type));
        }
+      if (writebuf)
+       {
+         regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
+         addr = read_memory_unsigned_integer (sp + 64, 4, byte_order);
+         write_memory (addr, writebuf, TYPE_LENGTH (type));
+       }
 
       return RETURN_VALUE_ABI_PRESERVES_ADDRESS;
     }
@@ -1048,13 +1455,14 @@ 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));
+         || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16)
+         || sparc_complex_floating_p (type));
 }
 
 static int
-sparc32_dwarf2_struct_return_p (struct frame_info *next_frame)
+sparc32_dwarf2_struct_return_p (struct frame_info *this_frame)
 {
-  CORE_ADDR pc = frame_unwind_address_in_block (next_frame);
+  CORE_ADDR pc = get_frame_address_in_block (this_frame);
   struct symbol *sym = find_pc_function (pc);
 
   if (sym)
@@ -1065,7 +1473,7 @@ sparc32_dwarf2_struct_return_p (struct frame_info *next_frame)
 static void
 sparc32_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
                               struct dwarf2_frame_state_reg *reg,
-                              struct frame_info *next_frame)
+                              struct frame_info *this_frame)
 {
   int off;
 
@@ -1084,7 +1492,7 @@ sparc32_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
     case SPARC32_NPC_REGNUM:
       reg->how = DWARF2_FRAME_REG_RA_OFFSET;
       off = 8;
-      if (sparc32_dwarf2_struct_return_p (next_frame))
+      if (sparc32_dwarf2_struct_return_p (this_frame))
        off += 4;
       if (regnum == SPARC32_NPC_REGNUM)
        off += 4;
@@ -1099,19 +1507,29 @@ sparc32_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
    software single-step mechanism.  */
 
 static CORE_ADDR
-sparc_analyze_control_transfer (struct gdbarch *arch,
+sparc_analyze_control_transfer (struct frame_info *frame,
                                CORE_ADDR pc, CORE_ADDR *npc)
 {
   unsigned long insn = sparc_fetch_instruction (pc);
   int conditional_p = X_COND (insn) & 0x7;
-  int branch_p = 0;
+  int branch_p = 0, fused_p = 0;
   long offset = 0;                     /* Must be signed for sign-extend.  */
 
-  if (X_OP (insn) == 0 && X_OP2 (insn) == 3 && (insn & 0x1000000) == 0)
+  if (X_OP (insn) == 0 && X_OP2 (insn) == 3)
     {
-      /* Branch on Integer Register with Prediction (BPr).  */
-      branch_p = 1;
-      conditional_p = 1;
+      if ((insn & 0x10000000) == 0)
+       {
+         /* Branch on Integer Register with Prediction (BPr).  */
+         branch_p = 1;
+         conditional_p = 1;
+       }
+      else
+       {
+         /* Compare and Branch  */
+         branch_p = 1;
+         fused_p = 1;
+         offset = 4 * X_DISP10 (insn);
+       }
     }
   else if (X_OP (insn) == 0 && X_OP2 (insn) == 6)
     {
@@ -1141,14 +1559,23 @@ sparc_analyze_control_transfer (struct gdbarch *arch,
   else if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3a)
     {
       /* Trap instruction (TRAP).  */
-      return gdbarch_tdep (arch)->step_trap (insn);
+      return gdbarch_tdep (get_frame_arch (frame))->step_trap (frame, insn);
     }
 
   /* FIXME: Handle DONE and RETRY instructions.  */
 
   if (branch_p)
     {
-      if (conditional_p)
+      if (fused_p)
+       {
+         /* Fused compare-and-branch instructions are non-delayed,
+            and do not have an annuling capability.  So we need to
+            always set a breakpoint on both the NPC and the branch
+            target address.  */
+         gdb_assert (offset != 0);
+         return pc + offset;
+       }
+      else if (conditional_p)
        {
          /* For conditional branches, return nPC + 4 iff the annul
             bit is 1.  */
@@ -1165,7 +1592,6 @@ sparc_analyze_control_transfer (struct gdbarch *arch,
          if (X_A (insn))
            *npc = 0;
 
-         gdb_assert (offset != 0);
          return pc + offset;
        }
     }
@@ -1174,100 +1600,63 @@ sparc_analyze_control_transfer (struct gdbarch *arch,
 }
 
 static CORE_ADDR
-sparc_step_trap (unsigned long insn)
+sparc_step_trap (struct frame_info *frame, unsigned long insn)
 {
   return 0;
 }
 
-void
-sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p)
+int
+sparc_software_single_step (struct frame_info *frame)
 {
-  struct gdbarch *arch = current_gdbarch;
+  struct gdbarch *arch = get_frame_arch (frame);
   struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+  struct address_space *aspace = get_frame_address_space (frame);
   CORE_ADDR npc, nnpc;
 
-  if (insert_breakpoints_p)
-    {
-      CORE_ADDR pc, orig_npc;
+  CORE_ADDR pc, orig_npc;
 
-      pc = sparc_address_from_register (tdep->pc_regnum);
-      orig_npc = npc = sparc_address_from_register (tdep->npc_regnum);
+  pc = get_frame_register_unsigned (frame, tdep->pc_regnum);
+  orig_npc = npc = get_frame_register_unsigned (frame, tdep->npc_regnum);
 
-      /* Analyze the instruction at PC.  */
-      nnpc = sparc_analyze_control_transfer (arch, pc, &npc);
-      if (npc != 0)
-       insert_single_step_breakpoint (npc);
+  /* Analyze the instruction at PC.  */
+  nnpc = sparc_analyze_control_transfer (frame, pc, &npc);
+  if (npc != 0)
+    insert_single_step_breakpoint (arch, aspace, npc);
 
-      if (nnpc != 0)
-       insert_single_step_breakpoint (nnpc);
+  if (nnpc != 0)
+    insert_single_step_breakpoint (arch, aspace, nnpc);
 
-      /* Assert that we have set at least one breakpoint, and that
-        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
-    remove_single_step_breakpoints ();
+  /* Assert that we have set at least one breakpoint, and that
+     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);
+
+  return 1;
 }
 
 static void
-sparc_write_pc (CORE_ADDR pc, ptid_t ptid)
+sparc_write_pc (struct regcache *regcache, CORE_ADDR pc)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
 
-  write_register_pid (tdep->pc_regnum, pc, ptid);
-  write_register_pid (tdep->npc_regnum, pc + 4, ptid);
+  regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc);
+  regcache_cooked_write_unsigned (regcache, tdep->npc_regnum, pc + 4);
 }
 \f
-/* Unglobalize NAME.  */
 
-char *
-sparc_stabs_unglobalize_name (char *name)
-{
-  /* The Sun compilers (Sun ONE Studio, Forte Developer, Sun WorkShop,
-     SunPRO) convert file static variables into global values, a
-     process known as globalization.  In order to do this, the
-     compiler will create a unique prefix and prepend it to each file
-     static variable.  For static variables within a function, this
-     globalization prefix is followed by the function name (nested
-     static variables within a function are supposed to generate a
-     warning message, and are left alone).  The procedure is
-     documented in the Stabs Interface Manual, which is distrubuted
-     with the compilers, although version 4.0 of the manual seems to
-     be incorrect in some places, at least for SPARC.  The
-     globalization prefix is encoded into an N_OPT stab, with the form
-     "G=<prefix>".  The globalization prefix always seems to start
-     with a dollar sign '$'; a dot '.' is used as a seperator.  So we
-     simply strip everything up until the last dot.  */
-
-  if (name[0] == '$')
-    {
-      char *p = strrchr (name, '.');
-      if (p)
-       return p + 1;
-    }
-
-  return name;
-}
-\f
+/* Iterate over core file register note sections.  */
 
-/* Return the appropriate register set for the core section identified
-   by SECT_NAME and SECT_SIZE.  */
-
-const struct regset *
-sparc_regset_from_core_section (struct gdbarch *gdbarch,
-                               const char *sect_name, size_t sect_size)
+static void
+sparc_iterate_over_regset_sections (struct gdbarch *gdbarch,
+                                   iterate_over_regset_sections_cb *cb,
+                                   void *cb_data,
+                                   const struct regcache *regcache)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  if (strcmp (sect_name, ".reg") == 0 && sect_size >= tdep->sizeof_gregset)
-    return tdep->gregset;
-
-  if (strcmp (sect_name, ".reg2") == 0 && sect_size >= tdep->sizeof_fpregset)
-    return tdep->fpregset;
-
-  return NULL;
+  cb (".reg", tdep->sizeof_gregset, tdep->gregset, NULL, cb_data);
+  cb (".reg2", tdep->sizeof_fpregset, tdep->fpregset, NULL, cb_data);
 }
 \f
 
@@ -1283,20 +1672,15 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     return arches->gdbarch;
 
   /* Allocate space for the new architecture.  */
-  tdep = XMALLOC (struct gdbarch_tdep);
+  tdep = XCNEW (struct gdbarch_tdep);
   gdbarch = gdbarch_alloc (&info, tdep);
 
   tdep->pc_regnum = SPARC32_PC_REGNUM;
   tdep->npc_regnum = SPARC32_NPC_REGNUM;
-  tdep->gregset = NULL;
-  tdep->sizeof_gregset = 0;
-  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);
+  set_gdbarch_long_double_format (gdbarch, floatformats_sparc_quad);
 
   set_gdbarch_num_regs (gdbarch, SPARC32_NUM_REGS);
   set_gdbarch_register_name (gdbarch, sparc32_register_name);
@@ -1311,6 +1695,7 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_fp0_regnum (gdbarch, SPARC_F0_REGNUM); /* %f0 */
 
   /* Call dummy code.  */
+  set_gdbarch_frame_align (gdbarch, sparc32_frame_align);
   set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
   set_gdbarch_push_dummy_code (gdbarch, sparc32_push_dummy_code);
   set_gdbarch_push_dummy_call (gdbarch, sparc32_push_dummy_call);
@@ -1333,7 +1718,7 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_software_single_step (gdbarch, sparc_software_single_step);
   set_gdbarch_write_pc (gdbarch, sparc_write_pc);
 
-  set_gdbarch_unwind_dummy_id (gdbarch, sparc_unwind_dummy_id);
+  set_gdbarch_dummy_id (gdbarch, sparc_dummy_id);
 
   set_gdbarch_unwind_pc (gdbarch, sparc_unwind_pc);
 
@@ -1347,12 +1732,14 @@ 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);
 
-  frame_unwind_append_sniffer (gdbarch, sparc32_frame_sniffer);
+  frame_unwind_append_unwinder (gdbarch, &sparc32_frame_unwind);
 
   /* If we have register sets, enable the generic core file support.  */
   if (tdep->gregset)
-    set_gdbarch_regset_from_core_section (gdbarch,
-                                         sparc_regset_from_core_section);
+    set_gdbarch_iterate_over_regset_sections
+      (gdbarch, sparc_iterate_over_regset_sections);
+
+  register_sparc_ravenscar_ops (gdbarch);
 
   return gdbarch;
 }
@@ -1362,6 +1749,8 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 void
 sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum)
 {
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int offset = 0;
   gdb_byte buf[8];
   int i;
@@ -1380,10 +1769,12 @@ sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum)
              /* Handle StackGhost.  */
              if (i == SPARC_I7_REGNUM)
                {
-                 ULONGEST wcookie = sparc_fetch_wcookie ();
-                 ULONGEST i7 = extract_unsigned_integer (buf + offset, 8);
+                 ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
+                 ULONGEST i7;
 
-                 store_unsigned_integer (buf + offset, 8, i7 ^ wcookie);
+                 i7 = extract_unsigned_integer (buf + offset, 8, byte_order);
+                 store_unsigned_integer (buf + offset, 8, byte_order,
+                                         i7 ^ wcookie);
                }
 
              regcache_raw_supply (regcache, i, buf);
@@ -1398,7 +1789,7 @@ sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum)
 
       /* Clear out the top half of the temporary buffer, and put the
         register value in the bottom half if we're in 64-bit mode.  */
-      if (gdbarch_ptr_bit (current_gdbarch) == 64)
+      if (gdbarch_ptr_bit (get_regcache_arch (regcache)) == 64)
        {
          memset (buf, 0, 4);
          offset = 4;
@@ -1414,10 +1805,12 @@ sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum)
              /* Handle StackGhost.  */
              if (i == SPARC_I7_REGNUM)
                {
-                 ULONGEST wcookie = sparc_fetch_wcookie ();
-                 ULONGEST i7 = extract_unsigned_integer (buf + offset, 4);
+                 ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
+                 ULONGEST i7;
 
-                 store_unsigned_integer (buf + offset, 4, i7 ^ wcookie);
+                 i7 = extract_unsigned_integer (buf + offset, 4, byte_order);
+                 store_unsigned_integer (buf + offset, 4, byte_order,
+                                         i7 ^ wcookie);
                }
 
              regcache_raw_supply (regcache, i, buf);
@@ -1430,6 +1823,8 @@ void
 sparc_collect_rwindow (const struct regcache *regcache,
                       CORE_ADDR sp, int regnum)
 {
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int offset = 0;
   gdb_byte buf[8];
   int i;
@@ -1448,10 +1843,11 @@ sparc_collect_rwindow (const struct regcache *regcache,
              /* Handle StackGhost.  */
              if (i == SPARC_I7_REGNUM)
                {
-                 ULONGEST wcookie = sparc_fetch_wcookie ();
-                 ULONGEST i7 = extract_unsigned_integer (buf + offset, 8);
+                 ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
+                 ULONGEST i7;
 
-                 store_unsigned_integer (buf, 8, i7 ^ wcookie);
+                 i7 = extract_unsigned_integer (buf + offset, 8, byte_order);
+                 store_unsigned_integer (buf, 8, byte_order, i7 ^ wcookie);
                }
 
              target_write_memory (sp + ((i - SPARC_L0_REGNUM) * 8), buf, 8);
@@ -1465,7 +1861,7 @@ sparc_collect_rwindow (const struct regcache *regcache,
       sp &= 0xffffffffUL;
 
       /* Only use the bottom half if we're in 64-bit mode.  */
-      if (gdbarch_ptr_bit (current_gdbarch) == 64)
+      if (gdbarch_ptr_bit (get_regcache_arch (regcache)) == 64)
        offset = 4;
 
       for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
@@ -1477,10 +1873,12 @@ sparc_collect_rwindow (const struct regcache *regcache,
              /* Handle StackGhost.  */
              if (i == SPARC_I7_REGNUM)
                {
-                 ULONGEST wcookie = sparc_fetch_wcookie ();
-                 ULONGEST i7 = extract_unsigned_integer (buf + offset, 4);
+                 ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
+                 ULONGEST i7;
 
-                 store_unsigned_integer (buf + offset, 4, i7 ^ wcookie);
+                 i7 = extract_unsigned_integer (buf + offset, 4, byte_order);
+                 store_unsigned_integer (buf + offset, 4, byte_order,
+                                         i7 ^ wcookie);
                }
 
              target_write_memory (sp + ((i - SPARC_L0_REGNUM) * 4),
@@ -1493,35 +1891,36 @@ sparc_collect_rwindow (const struct regcache *regcache,
 /* Helper functions for dealing with register sets.  */
 
 void
-sparc32_supply_gregset (const struct sparc_gregset *gregset,
+sparc32_supply_gregset (const struct sparc_gregmap *gregmap,
                        struct regcache *regcache,
                        int regnum, const void *gregs)
 {
   const gdb_byte *regs = gregs;
+  gdb_byte zero[4] = { 0 };
   int i;
 
   if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
     regcache_raw_supply (regcache, SPARC32_PSR_REGNUM,
-                        regs + gregset->r_psr_offset);
+                        regs + gregmap->r_psr_offset);
 
   if (regnum == SPARC32_PC_REGNUM || regnum == -1)
     regcache_raw_supply (regcache, SPARC32_PC_REGNUM,
-                        regs + gregset->r_pc_offset);
+                        regs + gregmap->r_pc_offset);
 
   if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
     regcache_raw_supply (regcache, SPARC32_NPC_REGNUM,
-                        regs + gregset->r_npc_offset);
+                        regs + gregmap->r_npc_offset);
 
   if (regnum == SPARC32_Y_REGNUM || regnum == -1)
     regcache_raw_supply (regcache, SPARC32_Y_REGNUM,
-                        regs + gregset->r_y_offset);
+                        regs + gregmap->r_y_offset);
 
   if (regnum == SPARC_G0_REGNUM || regnum == -1)
-    regcache_raw_supply (regcache, SPARC_G0_REGNUM, NULL);
+    regcache_raw_supply (regcache, SPARC_G0_REGNUM, &zero);
 
   if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
     {
-      int offset = gregset->r_g1_offset;
+      int offset = gregmap->r_g1_offset;
 
       for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
        {
@@ -1535,7 +1934,7 @@ sparc32_supply_gregset (const struct sparc_gregset *gregset,
     {
       /* Not all of the register set variants include Locals and
          Inputs.  For those that don't, we read them off the stack.  */
-      if (gregset->r_l0_offset == -1)
+      if (gregmap->r_l0_offset == -1)
        {
          ULONGEST sp;
 
@@ -1544,7 +1943,7 @@ sparc32_supply_gregset (const struct sparc_gregset *gregset,
        }
       else
        {
-         int offset = gregset->r_l0_offset;
+         int offset = gregmap->r_l0_offset;
 
          for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
            {
@@ -1557,7 +1956,7 @@ sparc32_supply_gregset (const struct sparc_gregset *gregset,
 }
 
 void
-sparc32_collect_gregset (const struct sparc_gregset *gregset,
+sparc32_collect_gregset (const struct sparc_gregmap *gregmap,
                         const struct regcache *regcache,
                         int regnum, void *gregs)
 {
@@ -1566,23 +1965,23 @@ sparc32_collect_gregset (const struct sparc_gregset *gregset,
 
   if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
     regcache_raw_collect (regcache, SPARC32_PSR_REGNUM,
-                         regs + gregset->r_psr_offset);
+                         regs + gregmap->r_psr_offset);
 
   if (regnum == SPARC32_PC_REGNUM || regnum == -1)
     regcache_raw_collect (regcache, SPARC32_PC_REGNUM,
-                         regs + gregset->r_pc_offset);
+                         regs + gregmap->r_pc_offset);
 
   if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
     regcache_raw_collect (regcache, SPARC32_NPC_REGNUM,
-                         regs + gregset->r_npc_offset);
+                         regs + gregmap->r_npc_offset);
 
   if (regnum == SPARC32_Y_REGNUM || regnum == -1)
     regcache_raw_collect (regcache, SPARC32_Y_REGNUM,
-                         regs + gregset->r_y_offset);
+                         regs + gregmap->r_y_offset);
 
   if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
     {
-      int offset = gregset->r_g1_offset;
+      int offset = gregmap->r_g1_offset;
 
       /* %g0 is always zero.  */
       for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
@@ -1597,9 +1996,9 @@ sparc32_collect_gregset (const struct sparc_gregset *gregset,
     {
       /* Not all of the register set variants include Locals and
          Inputs.  For those that don't, we read them off the stack.  */
-      if (gregset->r_l0_offset != -1)
+      if (gregmap->r_l0_offset != -1)
        {
-         int offset = gregset->r_l0_offset;
+         int offset = gregmap->r_l0_offset;
 
          for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
            {
@@ -1612,7 +2011,8 @@ sparc32_collect_gregset (const struct sparc_gregset *gregset,
 }
 
 void
-sparc32_supply_fpregset (struct regcache *regcache,
+sparc32_supply_fpregset (const struct sparc_fpregmap *fpregmap,
+                        struct regcache *regcache,
                         int regnum, const void *fpregs)
 {
   const gdb_byte *regs = fpregs;
@@ -1621,15 +2021,18 @@ sparc32_supply_fpregset (struct regcache *regcache,
   for (i = 0; i < 32; i++)
     {
       if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
-       regcache_raw_supply (regcache, SPARC_F0_REGNUM + i, regs + (i * 4));
+       regcache_raw_supply (regcache, SPARC_F0_REGNUM + i,
+                            regs + fpregmap->r_f0_offset + (i * 4));
     }
 
   if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
-    regcache_raw_supply (regcache, SPARC32_FSR_REGNUM, regs + (32 * 4) + 4);
+    regcache_raw_supply (regcache, SPARC32_FSR_REGNUM,
+                        regs + fpregmap->r_fsr_offset);
 }
 
 void
-sparc32_collect_fpregset (const struct regcache *regcache,
+sparc32_collect_fpregset (const struct sparc_fpregmap *fpregmap,
+                         const struct regcache *regcache,
                          int regnum, void *fpregs)
 {
   gdb_byte *regs = fpregs;
@@ -1638,18 +2041,20 @@ sparc32_collect_fpregset (const struct regcache *regcache,
   for (i = 0; i < 32; i++)
     {
       if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
-       regcache_raw_collect (regcache, SPARC_F0_REGNUM + i, regs + (i * 4));
+       regcache_raw_collect (regcache, SPARC_F0_REGNUM + i,
+                             regs + fpregmap->r_f0_offset + (i * 4));
     }
 
   if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
-    regcache_raw_collect (regcache, SPARC32_FSR_REGNUM, regs + (32 * 4) + 4);
+    regcache_raw_collect (regcache, SPARC32_FSR_REGNUM,
+                         regs + fpregmap->r_fsr_offset);
 }
 \f
 
 /* SunOS 4.  */
 
 /* From <machine/reg.h>.  */
-const struct sparc_gregset sparc32_sunos4_gregset =
+const struct sparc_gregmap sparc32_sunos4_gregmap =
 {
   0 * 4,                       /* %psr */
   1 * 4,                       /* %pc */
@@ -1660,6 +2065,18 @@ const struct sparc_gregset sparc32_sunos4_gregset =
   4 * 4,                       /* %g1 */
   -1                           /* %l0 */
 };
+
+const struct sparc_fpregmap sparc32_sunos4_fpregmap =
+{
+  0 * 4,                       /* %f0 */
+  33 * 4,                      /* %fsr */
+};
+
+const struct sparc_fpregmap sparc32_bsd_fpregmap =
+{
+  0 * 4,                       /* %f0 */
+  32 * 4,                      /* %fsr */
+};
 \f
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
@@ -1669,7 +2086,4 @@ void
 _initialize_sparc_tdep (void)
 {
   register_gdbarch_init (bfd_arch_sparc, sparc32_gdbarch_init);
-
-  /* Initialize the SPARC-specific register types.  */
-  sparc_init_types();
 }