* inferior.h (read_sp): Remove prototype.
[deliverable/binutils-gdb.git] / gdb / sparc64-tdep.c
index da5d3571a4ce28788ecfdf4ff3a245ce718b1299..f44afaf1b6053b26ea910df03c539a42238d7f08 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for UltraSPARC.
 
-   Copyright 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006, 2007 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 "dwarf2-frame.h"
 #include "floatformat.h"
 #include "frame.h"
 #include "frame-base.h"
 #include "frame-unwind.h"
 #include "gdbcore.h"
 #include "gdbtypes.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "objfiles.h"
 #include "osabi.h"
 #include "regcache.h"
 #include "target.h"
 /* Please use the sparc32_-prefix for 32-bit specific code, the
    sparc64_-prefix for 64-bit specific code and the sparc_-prefix for
    code can handle both.  */
-
-/* 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
-   hosts, so undefine it first.  */
-#undef BIAS
-#define BIAS 2047
-
-/* Macros to extract fields from SPARC instructions.  */
-#define X_OP(i) (((i) >> 30) & 0x3)
-#define X_A(i) (((i) >> 29) & 1)
-#define X_COND(i) (((i) >> 25) & 0xf)
-#define X_OP2(i) (((i) >> 22) & 0x7)
-#define X_IMM22(i) ((i) & 0x3fffff)
-#define X_OP3(i) (((i) >> 19) & 0x3f)
-/* Sign extension macros.  */
-#define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000)
-#define X_DISP19(i) ((((i) & 0x7ffff) ^ 0x40000) - 0x40000)
-
-/* Fetch the instruction at PC.  Instructions are always big-endian
-   even if the processor operates in little-endian mode.  */
-
-static unsigned long
-sparc_fetch_instruction (CORE_ADDR pc)
-{
-  unsigned char buf[4];
-  unsigned long insn;
-  int i;
-
-  read_memory (pc, buf, sizeof (buf));
-
-  insn = 0;
-  for (i = 0; i < sizeof (buf); i++)
-    insn = (insn << 8) | buf[i];
-  return insn;
-}
 \f
 /* The functions on this page are intended to be used to classify
    function arguments.  */
 
-/* Return the contents if register REGNUM as an address.  */
-
-static CORE_ADDR
-sparc_address_from_register (int regnum)
-{
-  ULONGEST addr;
-
-  regcache_cooked_read_unsigned (current_regcache, regnum, &addr);
-  return addr;
-}
-
 /* Check whether TYPE is "Integral or Pointer".  */
 
 static int
@@ -162,14 +120,62 @@ sparc64_structure_or_union_p (const struct type *type)
 
   return 0;
 }
+\f
 
-/* UltraSPARC architecture specific information.  */
+/* Type for %pstate.  */
+struct type *sparc64_pstate_type;
 
-struct gdbarch_tdep
+/* Type for %fsr.  */
+struct type *sparc64_fsr_type;
+
+/* Type for %fprs.  */
+struct type *sparc64_fprs_type;
+
+/* Construct types for ISA-specific registers.  */
+
+static void
+sparc64_init_types (void)
 {
-  /* Offset of saved PC in jmp_buf.  */
-  int jb_pc_offset;
-};
+  struct type *type;
+
+  type = init_flags_type ("builtin_type_sparc64_pstate", 8);
+  append_flags_type_flag (type, 0, "AG");
+  append_flags_type_flag (type, 1, "IE");
+  append_flags_type_flag (type, 2, "PRIV");
+  append_flags_type_flag (type, 3, "AM");
+  append_flags_type_flag (type, 4, "PEF");
+  append_flags_type_flag (type, 5, "RED");
+  append_flags_type_flag (type, 8, "TLE");
+  append_flags_type_flag (type, 9, "CLE");
+  append_flags_type_flag (type, 10, "PID0");
+  append_flags_type_flag (type, 11, "PID1");
+  sparc64_pstate_type = type;
+
+  type = init_flags_type ("builtin_type_sparc64_fsr", 8);
+  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");
+  sparc64_fsr_type = type;
+
+  type = init_flags_type ("builtin_type_sparc64_fprs", 8);
+  append_flags_type_flag (type, 0, "DL");
+  append_flags_type_flag (type, 1, "DU");
+  append_flags_type_flag (type, 2, "FEF");
+  sparc64_fprs_type = type;
+}
 
 /* Register information.  */
 
@@ -271,10 +277,11 @@ static struct sparc64_register_info sparc64_register_info[] =
   
   /* This raw register contains the contents of %cwp, %pstate, %asi
      and %ccr as laid out in a %tstate register.  */
-  { NULL, &builtin_type_int64 },
+  /* FIXME: Give it a name until we start using register groups.  */
+  { "state", &builtin_type_int64 },
 
-  { "fsr", &builtin_type_int64 },
-  { "fprs", &builtin_type_int64 },
+  { "fsr", &sparc64_fsr_type },
+  { "fprs", &sparc64_fprs_type },
 
   /* "Although Y is a 64-bit register, its high-order 32 bits are
      reserved and always read as 0."  */
@@ -282,8 +289,7 @@ static struct sparc64_register_info sparc64_register_info[] =
 };
 
 /* Total number of registers.  */
-#define SPARC64_NUM_REGS \
-  (sizeof (sparc64_register_info) / sizeof (sparc64_register_info[0]))
+#define SPARC64_NUM_REGS ARRAY_SIZE (sparc64_register_info)
 
 /* We provide the aliases %d0..%d62 and %q0..%q60 for the floating
    registers as "psuedo" registers.  */
@@ -291,7 +297,7 @@ static struct sparc64_register_info sparc64_register_info[] =
 static struct sparc64_register_info sparc64_pseudo_register_info[] =
 {
   { "cwp", &builtin_type_int64 },
-  { "pstate", &builtin_type_int64 },
+  { "pstate", &sparc64_pstate_type },
   { "asi", &builtin_type_int64 },
   { "ccr", &builtin_type_int64 },
 
@@ -347,9 +353,7 @@ static struct sparc64_register_info sparc64_pseudo_register_info[] =
 };
 
 /* Total number of pseudo registers.  */
-#define SPARC64_NUM_PSEUDO_REGS \
-  (sizeof (sparc64_pseudo_register_info) \
-   / sizeof (sparc64_pseudo_register_info[0]))
+#define SPARC64_NUM_PSEUDO_REGS ARRAY_SIZE (sparc64_pseudo_register_info)
 
 /* Return the name of register REGNUM.  */
 
@@ -383,7 +387,7 @@ sparc64_register_type (struct gdbarch *gdbarch, int regnum)
 static void
 sparc64_pseudo_register_read (struct gdbarch *gdbarch,
                              struct regcache *regcache,
-                             int regnum, void *buf)
+                             int regnum, gdb_byte *buf)
 {
   gdb_assert (regnum >= SPARC64_NUM_REGS);
 
@@ -391,7 +395,7 @@ sparc64_pseudo_register_read (struct gdbarch *gdbarch,
     {
       regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC64_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);
     }
   else if (regnum >= SPARC64_D32_REGNUM && regnum <= SPARC64_D62_REGNUM)
     {
@@ -402,15 +406,15 @@ sparc64_pseudo_register_read (struct gdbarch *gdbarch,
     {
       regnum = SPARC_F0_REGNUM + 4 * (regnum - SPARC64_Q0_REGNUM);
       regcache_raw_read (regcache, regnum, buf);
-      regcache_raw_read (regcache, regnum + 1, ((char *)buf) + 4);
-      regcache_raw_read (regcache, regnum + 2, ((char *)buf) + 8);
-      regcache_raw_read (regcache, regnum + 3, ((char *)buf) + 12);
+      regcache_raw_read (regcache, regnum + 1, buf + 4);
+      regcache_raw_read (regcache, regnum + 2, buf + 8);
+      regcache_raw_read (regcache, regnum + 3, buf + 12);
     }
   else if (regnum >= SPARC64_Q32_REGNUM && regnum <= SPARC64_Q60_REGNUM)
     {
       regnum = SPARC64_F32_REGNUM + 2 * (regnum - SPARC64_Q32_REGNUM);
       regcache_raw_read (regcache, regnum, buf);
-      regcache_raw_read (regcache, regnum + 1, ((char *)buf) + 8);
+      regcache_raw_read (regcache, regnum + 1, buf + 8);
     }
   else if (regnum == SPARC64_CWP_REGNUM
           || regnum == SPARC64_PSTATE_REGNUM
@@ -422,16 +426,16 @@ sparc64_pseudo_register_read (struct gdbarch *gdbarch,
       regcache_raw_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state);
       switch (regnum)
        {
-       SPARC64_CWP_REGNUM:
+       case SPARC64_CWP_REGNUM:
          state = (state >> 0) & ((1 << 5) - 1);
          break;
-       SPARC64_PSTATE_REGNUM:
+       case SPARC64_PSTATE_REGNUM:
          state = (state >> 8) & ((1 << 12) - 1);
          break;
-       SPARC64_ASI_REGNUM:
+       case SPARC64_ASI_REGNUM:
          state = (state >> 24) & ((1 << 8) - 1);
          break;
-       SPARC64_CCR_REGNUM:
+       case SPARC64_CCR_REGNUM:
          state = (state >> 32) & ((1 << 8) - 1);
          break;
        }
@@ -442,7 +446,7 @@ sparc64_pseudo_register_read (struct gdbarch *gdbarch,
 static void
 sparc64_pseudo_register_write (struct gdbarch *gdbarch,
                               struct regcache *regcache,
-                              int regnum, const void *buf)
+                              int regnum, const gdb_byte *buf)
 {
   gdb_assert (regnum >= SPARC64_NUM_REGS);
 
@@ -450,7 +454,7 @@ sparc64_pseudo_register_write (struct gdbarch *gdbarch,
     {
       regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC64_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);
     }
   else if (regnum >= SPARC64_D32_REGNUM && regnum <= SPARC64_D62_REGNUM)
     {
@@ -461,89 +465,44 @@ sparc64_pseudo_register_write (struct gdbarch *gdbarch,
     {
       regnum = SPARC_F0_REGNUM + 4 * (regnum - SPARC64_Q0_REGNUM);
       regcache_raw_write (regcache, regnum, buf);
-      regcache_raw_write (regcache, regnum + 1, ((const char *)buf) + 4);
-      regcache_raw_write (regcache, regnum + 2, ((const char *)buf) + 8);
-      regcache_raw_write (regcache, regnum + 3, ((const char *)buf) + 12);
+      regcache_raw_write (regcache, regnum + 1, buf + 4);
+      regcache_raw_write (regcache, regnum + 2, buf + 8);
+      regcache_raw_write (regcache, regnum + 3, buf + 12);
     }
   else if (regnum >= SPARC64_Q32_REGNUM && regnum <= SPARC64_Q60_REGNUM)
     {
       regnum = SPARC64_F32_REGNUM + 2 * (regnum - SPARC64_Q32_REGNUM);
       regcache_raw_write (regcache, regnum, buf);
-      regcache_raw_write (regcache, regnum + 1, ((const char *)buf) + 8);
+      regcache_raw_write (regcache, regnum + 1, buf + 8);
     }
-}
-
-/* Use the program counter to determine the contents and size of a
-   breakpoint instruction.  Return a pointer to a string of bytes that
-   encode a breakpoint instruction, store the length of the string in
-   *LEN and optionally adjust *PC to point to the correct memory
-   location for inserting the breakpoint.  */
-   
-static const unsigned char *
-sparc_breakpoint_from_pc (CORE_ADDR *pc, int *len)
-{
-  static unsigned char break_insn[] = { 0x91, 0xd0, 0x20, 0x01 };
-
-  *len = sizeof (break_insn);
-  return break_insn;
-}
-\f
-
-struct sparc64_frame_cache
-{
-  /* Base address.  */
-  CORE_ADDR base;
-  CORE_ADDR pc;
-
-  /* Do we have a frame?  */
-  int frameless_p;
-};
-
-/* Allocate and initialize a frame cache.  */
-
-static struct sparc64_frame_cache *
-sparc64_alloc_frame_cache (void)
-{
-  struct sparc64_frame_cache *cache;
-  int i;
-
-  cache = FRAME_OBSTACK_ZALLOC (struct sparc64_frame_cache);
-
-  /* Base address.  */
-  cache->base = 0;
-  cache->pc = 0;
-
-  /* Frameless until proven otherwise.  */
-  cache->frameless_p = 1;
-
-  return cache;
-}
-
-static CORE_ADDR
-sparc64_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
-                         struct sparc64_frame_cache *cache)
-{
-  unsigned long insn;
-
-  if (current_pc <= pc)
-    return current_pc;
-
-  /* Check whether the function starts with a SAVE instruction.  */
-  insn = sparc_fetch_instruction (pc);
-  if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3c)
+  else if (regnum == SPARC64_CWP_REGNUM
+          || regnum == SPARC64_PSTATE_REGNUM
+          || regnum == SPARC64_ASI_REGNUM
+          || regnum == SPARC64_CCR_REGNUM)
     {
-      cache->frameless_p = 0;
-      return pc + 4;
-    }
-
-  return pc;
-}
+      ULONGEST state, bits;
 
-static CORE_ADDR
-sparc64_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, SPARC64_PC_REGNUM);
+      regcache_raw_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state);
+      bits = extract_unsigned_integer (buf, 8);
+      switch (regnum)
+       {
+       case SPARC64_CWP_REGNUM:
+         state |= ((bits & ((1 << 5) - 1)) << 0);
+         break;
+       case SPARC64_PSTATE_REGNUM:
+         state |= ((bits & ((1 << 12) - 1)) << 8);
+         break;
+       case SPARC64_ASI_REGNUM:
+         state |= ((bits & ((1 << 8) - 1)) << 24);
+         break;
+       case SPARC64_CCR_REGNUM:
+         state |= ((bits & ((1 << 8) - 1)) << 32);
+         break;
+       }
+      regcache_raw_write_unsigned (regcache, SPARC64_STATE_REGNUM, state);
+    }
 }
+\f
 
 /* Return PC of first real instruction of the function starting at
    START_PC.  */
@@ -553,7 +512,7 @@ sparc64_skip_prologue (CORE_ADDR start_pc)
 {
   struct symtab_and_line sal;
   CORE_ADDR func_start, func_end;
-  struct sparc64_frame_cache cache;
+  struct sparc_frame_cache cache;
 
   /* This is the preferred method, find the end of the prologue by
      using the debugging information.  */
@@ -566,50 +525,22 @@ sparc64_skip_prologue (CORE_ADDR start_pc)
        return sal.end;
     }
 
-  return sparc64_analyze_prologue (start_pc, 0xffffffffffffffffUL, &cache);
+  return sparc_analyze_prologue (start_pc, 0xffffffffffffffffULL, &cache);
 }
 
 /* Normal frames.  */
 
-static struct sparc64_frame_cache *
+static struct sparc_frame_cache *
 sparc64_frame_cache (struct frame_info *next_frame, void **this_cache)
 {
-  struct sparc64_frame_cache *cache;
-
-  if (*this_cache)
-    return *this_cache;
-
-  cache = sparc64_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)
-    sparc64_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), 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);
-    }
-
-  return cache;
+  return sparc_frame_cache (next_frame, this_cache);
 }
 
 static void
 sparc64_frame_this_id (struct frame_info *next_frame, void **this_cache,
                       struct frame_id *this_id)
 {
-  struct sparc64_frame_cache *cache =
+  struct sparc_frame_cache *cache =
     sparc64_frame_cache (next_frame, this_cache);
 
   /* This marks the outermost frame.  */
@@ -623,9 +554,9 @@ static void
 sparc64_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 sparc64_frame_cache *cache =
+  struct sparc_frame_cache *cache =
     sparc64_frame_cache (next_frame, this_cache);
 
   if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM)
@@ -645,6 +576,29 @@ sparc64_frame_prev_register (struct frame_info *next_frame, void **this_cache,
       return;
     }
 
+  /* Handle StackGhost.  */
+  {
+    ULONGEST wcookie = sparc_fetch_wcookie ();
+
+    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) * 8;
+           ULONGEST i7;
+
+           /* Read the value in from memory.  */
+           i7 = get_frame_memory_unsigned (next_frame, addr, 8);
+           store_unsigned_integer (valuep, 8, i7 ^ wcookie);
+         }
+       return;
+      }
+  }
+
   /* The previous frame's `local' and `in' registers have been saved
      in the register save area.  */
   if (!cache->frameless_p
@@ -652,7 +606,7 @@ sparc64_frame_prev_register (struct frame_info *next_frame, void **this_cache,
     {
       *optimizedp = 0;
       *lvalp = lval_memory;
-      *addrp = cache->base + BIAS + (regnum - SPARC_L0_REGNUM) * 8;
+      *addrp = cache->base + (regnum - SPARC_L0_REGNUM) * 8;
       *realnump = -1;
       if (valuep)
        {
@@ -670,8 +624,12 @@ sparc64_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, regnum, valuep);
 }
 
 static const struct frame_unwind sparc64_frame_unwind =
@@ -691,10 +649,9 @@ sparc64_frame_sniffer (struct frame_info *next_frame)
 static CORE_ADDR
 sparc64_frame_base_address (struct frame_info *next_frame, void **this_cache)
 {
-  struct sparc64_frame_cache *cache =
+  struct sparc_frame_cache *cache =
     sparc64_frame_cache (next_frame, this_cache);
 
-  /* ??? Should we take BIAS into account here?  */
   return cache->base;
 }
 
@@ -705,15 +662,6 @@ static const struct frame_base sparc64_frame_base =
   sparc64_frame_base_address,
   sparc64_frame_base_address
 };
-
-static struct frame_id
-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);
-  return frame_id_build (sp, frame_pc_unwind (next_frame));
-}
 \f
 /* Check whether TYPE must be 16-byte aligned.  */
 
@@ -728,8 +676,12 @@ sparc64_16_byte_align_p (struct type *type)
       int i;
 
       for (i = 0; i < TYPE_NFIELDS (type); i++)
-       if (sparc64_16_byte_align_p (TYPE_FIELD_TYPE (type, i)))
-         return 1;
+       {
+         struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i));
+
+         if (sparc64_16_byte_align_p (subtype))
+           return 1;
+       }
     }
 
   return 0;
@@ -743,7 +695,7 @@ sparc64_16_byte_align_p (struct type *type)
 
 static void
 sparc64_store_floating_fields (struct regcache *regcache, struct type *type,
-                              char *valbuf, int element, int bitpos)
+                              const gdb_byte *valbuf, int element, int bitpos)
 {
   gdb_assert (element < 16);
 
@@ -781,9 +733,30 @@ sparc64_store_floating_fields (struct regcache *regcache, struct type *type,
       int i;
 
       for (i = 0; i < TYPE_NFIELDS (type); i++)
-       sparc64_store_floating_fields (regcache, TYPE_FIELD_TYPE (type, i),
-                                      valbuf, element,
-                                      bitpos + TYPE_FIELD_BITPOS (type, i));
+       {
+         struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i));
+         int subpos = bitpos + TYPE_FIELD_BITPOS (type, i);
+
+         sparc64_store_floating_fields (regcache, subtype, valbuf,
+                                        element, subpos);
+       }
+
+      /* GCC has an interesting bug.  If TYPE is a structure that has
+         a single `float' member, GCC doesn't treat it as a structure
+         at all, but rather as an ordinary `float' argument.  This
+         argument will be stored in %f1, as required by the psABI.
+         However, as a member of a structure the psABI requires it to
+         be stored in %f0.  This bug is present in GCC 3.3.2, but
+         probably in older releases to.  To appease GCC, if a
+         structure has only a single `float' member, we store its
+         value in %f1 too (we already have stored in %f0).  */
+      if (TYPE_NFIELDS (type) == 1)
+       {
+         struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, 0));
+
+         if (sparc64_floating_p (subtype) && TYPE_LENGTH (subtype) == 4)
+           regcache_cooked_write (regcache, SPARC_F1_REGNUM, valbuf);
+       }
     }
 }
 
@@ -794,7 +767,7 @@ sparc64_store_floating_fields (struct regcache *regcache, struct type *type,
 
 static void
 sparc64_extract_floating_fields (struct regcache *regcache, struct type *type,
-                                char *valbuf, int bitpos)
+                                gdb_byte *valbuf, int bitpos)
 {
   if (sparc64_floating_p (type))
     {
@@ -829,9 +802,12 @@ sparc64_extract_floating_fields (struct regcache *regcache, struct type *type,
       int i;
 
       for (i = 0; i < TYPE_NFIELDS (type); i++)
-       sparc64_extract_floating_fields (regcache, TYPE_FIELD_TYPE (type, i),
-                                        valbuf,
-                                        bitpos + TYPE_FIELD_BITPOS (type, i));
+       {
+         struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i));
+         int subpos = bitpos + TYPE_FIELD_BITPOS (type, i);
+
+         sparc64_extract_floating_fields (regcache, subtype, valbuf, subpos);
+       }
     }
 }
 
@@ -859,7 +835,7 @@ sparc64_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 (sparc64_structure_or_union_p (type))
@@ -888,7 +864,7 @@ sparc64_store_arguments (struct regcache *regcache, int nargs,
                  a problem.  */
              sp &= ~0xf;
 
-             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++;
            }
@@ -957,11 +933,11 @@ sparc64_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 gdb_byte *valbuf = value_contents (args[i]);
+      struct type *type = value_type (args[i]);
       int len = TYPE_LENGTH (type);
       int regnum = -1;
-      char buf[16];
+      gdb_byte buf[16];
 
       if (sparc64_structure_or_union_p (type))
        {
@@ -1007,10 +983,11 @@ sparc64_store_arguments (struct regcache *regcache, int nargs,
                  undefined."  Even though the psABI says that "the
                  left half is undefined", set it to zero here.  */
              memset (buf, 0, 4);
-             valbuf = memcpy (buf + 4, valbuf, 4);
+             memcpy (buf + 4, valbuf, 4);
+             valbuf = buf;
              len = 8;
              if (element < 16)
-               regnum = SPARC64_D0_REGNUM;
+               regnum = SPARC64_D0_REGNUM + element;
            }
        }
       else
@@ -1038,11 +1015,11 @@ sparc64_store_arguments (struct regcache *regcache, int nargs,
              gdb_assert (element < 6);
              regnum = SPARC_O0_REGNUM + element;
              regcache_cooked_write (regcache, regnum, valbuf);
-             regcache_cooked_write (regcache, regnum + 1, valbuf);
+             regcache_cooked_write (regcache, regnum + 1, valbuf + 8);
            }
        }
 
-      /* Always store the argument in memeory.  */
+      /* Always store the argument in memory.  */
       write_memory (sp + element * 8, valbuf, len);
       element += ((len + 7) / 8);
     }
@@ -1055,7 +1032,7 @@ sparc64_store_arguments (struct regcache *regcache, int nargs,
 }
 
 static CORE_ADDR
-sparc64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+sparc64_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)
@@ -1071,12 +1048,12 @@ sparc64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   sp -= 16 * 8;
 
   /* Stack should be 16-byte aligned at this point.  */
-  gdb_assert (sp % 16 == 0);
+  gdb_assert ((sp + BIAS) % 16 == 0);
 
   /* Finally, update the stack pointer.  */
   regcache_cooked_write_unsigned (regcache, SPARC_SP_REGNUM, sp);
 
-  return sp;
+  return sp + BIAS;
 }
 \f
 
@@ -1085,10 +1062,10 @@ sparc64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
 
 static void
 sparc64_extract_return_value (struct type *type, struct regcache *regcache,
-                             void *valbuf)
+                             gdb_byte *valbuf)
 {
   int len = TYPE_LENGTH (type);
-  char buf[32];
+  gdb_byte buf[32];
   int i;
 
   if (sparc64_structure_or_union_p (type))
@@ -1109,6 +1086,15 @@ sparc64_extract_return_value (struct type *type, struct regcache *regcache,
        regcache_cooked_read (regcache, SPARC_F0_REGNUM + i, buf + i * 4);
       memcpy (valbuf, buf, len);
     }
+  else if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+    {
+      /* Small arrays are returned the same way as small structures.  */
+      gdb_assert (len <= 32);
+
+      for (i = 0; i < ((len + 7) / 8); i++)
+       regcache_cooked_read (regcache, SPARC_O0_REGNUM + i, buf + i * 8);
+      memcpy (valbuf, buf, len);
+    }
   else
     {
       /* Integral and pointer return values.  */
@@ -1126,10 +1112,10 @@ sparc64_extract_return_value (struct type *type, struct regcache *regcache,
 
 static void
 sparc64_store_return_value (struct type *type, struct regcache *regcache,
-                           const void *valbuf)
+                           const gdb_byte *valbuf)
 {
   int len = TYPE_LENGTH (type);
-  char buf[16];
+  gdb_byte buf[16];
   int i;
 
   if (sparc64_structure_or_union_p (type))
@@ -1143,7 +1129,7 @@ sparc64_store_return_value (struct type *type, struct regcache *regcache,
       memset (buf, 0, sizeof (buf));
       memcpy (buf, valbuf, len);
       for (i = 0; i < ((len + 7) / 8); i++)
-       regcache_cooked_write (regcache, SPARC_O0_REGNUM + i, buf + i * 4);
+       regcache_cooked_write (regcache, SPARC_O0_REGNUM + i, buf + i * 8);
       if (TYPE_CODE (type) != TYPE_CODE_UNION)
        sparc64_store_floating_fields (regcache, type, buf, 0, 0);
     }
@@ -1154,6 +1140,16 @@ sparc64_store_return_value (struct type *type, struct regcache *regcache,
       for (i = 0; i < len / 4; i++)
        regcache_cooked_write (regcache, SPARC_F0_REGNUM + i, buf + i * 4);
     }
+  else if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+    {
+      /* Small arrays are returned the same way as small structures.  */
+      gdb_assert (len <= 32);
+
+      memset (buf, 0, sizeof (buf));
+      memcpy (buf, valbuf, len);
+      for (i = 0; i < ((len + 7) / 8); i++)
+       regcache_cooked_write (regcache, SPARC_O0_REGNUM + i, buf + i * 8);
+    }
   else
     {
       /* Integral and pointer return values.  */
@@ -1166,161 +1162,62 @@ sparc64_store_return_value (struct type *type, struct regcache *regcache,
     }
 }
 
-/* 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 CORE_ADDR
-sparc_extract_struct_value_address (struct regcache *regcache)
+static enum return_value_convention
+sparc64_return_value (struct gdbarch *gdbarch, struct type *type,
+                     struct regcache *regcache, gdb_byte *readbuf,
+                     const gdb_byte *writebuf)
 {
-  ULONGEST addr;
+  if (TYPE_LENGTH (type) > 32)
+    return RETURN_VALUE_STRUCT_CONVENTION;
 
-  regcache_cooked_read_unsigned (regcache, SPARC_O0_REGNUM, &addr);
-  return addr;
-}
+  if (readbuf)
+    sparc64_extract_return_value (type, regcache, readbuf);
+  if (writebuf)
+    sparc64_store_return_value (type, regcache, writebuf);
 
-static int
-sparc64_use_struct_convention (int gcc_p, struct type *type)
-{
-  /* Structure and union types up to 32 bytes in size are returned in
-     registers.  */
-  return (TYPE_LENGTH (type) > 32);
+  return RETURN_VALUE_REGISTER_CONVENTION;
 }
-
 \f
-/* The SPARC Architecture doesn't have hardware single-step support,
-   and most operating systems don't implement it either, so we provide
-   software single-step mechanism.  */
 
-static CORE_ADDR
-sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc)
+static void
+sparc64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+                              struct dwarf2_frame_state_reg *reg,
+                              struct frame_info *next_frame)
 {
-  unsigned long insn = sparc_fetch_instruction (pc);
-  int conditional_p = X_COND (insn) & 0x7;
-  int branch_p = 0;
-  long offset = 0;                     /* Must be signed for sign-extend.  */
-
-  if (X_OP (insn) == 0 && X_OP2 (insn) == 3 && (insn & 0x1000000) == 0)
-    {
-      /* Branch on Integer Register with Prediction (BPr).  */
-      branch_p = 1;
-      conditional_p = 1;
-    }
-  else if (X_OP (insn) == 0 && X_OP2 (insn) == 6)
-    {
-      /* Branch on Floating-Point Condition Codes (FBfcc).  */
-      branch_p = 1;
-      offset = 4 * X_DISP22 (insn);
-    }
-  else if (X_OP (insn) == 0 && X_OP2 (insn) == 5)
-    {
-      /* Branch on Floating-Point Condition Codes with Prediction
-         (FBPfcc).  */
-      branch_p = 1;
-      offset = 4 * X_DISP19 (insn);
-    }
-  else if (X_OP (insn) == 0 && X_OP2 (insn) == 2)
-    {
-      /* Branch on Integer Condition Codes (Bicc).  */
-      branch_p = 1;
-      offset = 4 * X_DISP22 (insn);
-    }
-  else if (X_OP (insn) == 0 && X_OP2 (insn) == 1)
+  switch (regnum)
     {
-      /* Branch on Integer Condition Codes with Prediction (BPcc).  */
-      branch_p = 1;
-      offset = 4 * X_DISP19 (insn);
-    }
-
-  /* FIXME: Handle DONE and RETRY instructions.  */
-
-  /* FIXME: Handle the Trap instruction.  */
-
-  if (branch_p)
-    {
-      if (conditional_p)
-       {
-         /* For conditional branches, return nPC + 4 iff the annul
-            bit is 1.  */
-         return (X_A (insn) ? *npc + 4 : 0);
-       }
-      else
-       {
-         /* For unconditional branches, return the target if its
-            specified condition is "always" and return nPC + 4 if the
-            condition is "never".  If the annul bit is 1, set *NPC to
-            zero.  */
-         if (X_COND (insn) == 0x0)
-           pc = *npc, offset = 4;
-         if (X_A (insn))
-           *npc = 0;
-
-         gdb_assert (offset != 0);
-         return pc + offset;
-       }
+    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 SPARC64_PC_REGNUM:
+      reg->how = DWARF2_FRAME_REG_RA_OFFSET;
+      reg->loc.offset = 8;
+      break;
+    case SPARC64_NPC_REGNUM:
+      reg->how = DWARF2_FRAME_REG_RA_OFFSET;
+      reg->loc.offset = 12;
+      break;
     }
-
-  return 0;
 }
 
 void
-sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p)
-{
-  static CORE_ADDR npc, nnpc;
-  static char npc_save[4], nnpc_save[4];
-
-  if (insert_breakpoints_p)
-    {
-      CORE_ADDR pc;
-
-      gdb_assert (npc == 0);
-      gdb_assert (nnpc == 0);
-
-      pc = sparc_address_from_register (SPARC64_PC_REGNUM);
-      npc = sparc_address_from_register (SPARC64_NPC_REGNUM);
-
-      /* Analyze the instruction at PC.  */
-      nnpc = sparc_analyze_control_transfer (pc, &npc);
-      if (npc != 0)
-       target_insert_breakpoint (npc, npc_save);
-      if (nnpc != 0)
-       target_insert_breakpoint (nnpc, nnpc_save);
-
-      /* Assert that we have set at least one breakpoint.  */
-      gdb_assert (npc != 0 || nnpc != 0);
-    }
-  else
-    {
-      if (npc != 0)
-       target_remove_breakpoint (npc, npc_save);
-      if (nnpc != 0)
-       target_remove_breakpoint (nnpc, nnpc_save);
-
-      npc = 0;
-      nnpc = 0;
-    }
-}
-\f
-
-static struct gdbarch *
-sparc64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+sparc64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep;
-  struct gdbarch *gdbarch;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  /* If there is already a candidate, use it.  */
-  arches = gdbarch_list_lookup_by_info (arches, &info);
-  if (arches != NULL)
-    return arches->gdbarch;
-
-  /* Allocate space for the new architecture.  */
-  tdep = XMALLOC (struct gdbarch_tdep);
-  gdbarch = gdbarch_alloc (&info, tdep);
+  tdep->pc_regnum = SPARC64_PC_REGNUM;
+  tdep->npc_regnum = SPARC64_NPC_REGNUM;
 
+  /* This is what all the fuss is about.  */
   set_gdbarch_long_bit (gdbarch, 64);
   set_gdbarch_long_long_bit (gdbarch, 64);
   set_gdbarch_ptr_bit (gdbarch, 64);
-  set_gdbarch_long_double_bit (gdbarch, 128);
 
   set_gdbarch_num_regs (gdbarch, SPARC64_NUM_REGS);
   set_gdbarch_register_name (gdbarch, sparc64_register_name);
@@ -1330,156 +1227,334 @@ sparc64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_pseudo_register_write (gdbarch, sparc64_pseudo_register_write);
 
   /* Register numbers of various important registers.  */
-  set_gdbarch_sp_regnum (gdbarch, SPARC_SP_REGNUM); /* %sp */
   set_gdbarch_pc_regnum (gdbarch, SPARC64_PC_REGNUM); /* %pc */
-  set_gdbarch_npc_regnum (gdbarch, SPARC64_NPC_REGNUM);
-  set_gdbarch_fp0_regnum (gdbarch, SPARC_F0_REGNUM); /* %f0 */
 
   /* Call dummy code.  */
+  set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
+  set_gdbarch_push_dummy_code (gdbarch, NULL);
   set_gdbarch_push_dummy_call (gdbarch, sparc64_push_dummy_call);
 
-  set_gdbarch_extract_return_value (gdbarch, sparc64_extract_return_value);
-  set_gdbarch_store_return_value (gdbarch, sparc64_store_return_value);
-  set_gdbarch_extract_struct_value_address
-    (gdbarch, sparc_extract_struct_value_address);
-  set_gdbarch_use_struct_convention (gdbarch, sparc64_use_struct_convention);
+  set_gdbarch_return_value (gdbarch, sparc64_return_value);
+  set_gdbarch_stabs_argument_has_addr
+    (gdbarch, default_stabs_argument_has_addr);
 
   set_gdbarch_skip_prologue (gdbarch, sparc64_skip_prologue);
 
-  /* Stack grows downward.  */
-  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+  /* Hook in the DWARF CFI frame unwinder.  */
+  dwarf2_frame_set_init_reg (gdbarch, sparc64_dwarf2_frame_init_reg);
+  /* FIXME: kettenis/20050423: Don't enable the unwinder until the
+     StackGhost issues have been resolved.  */
+
+  frame_unwind_append_sniffer (gdbarch, sparc64_frame_sniffer);
+  frame_base_set_default (gdbarch, &sparc64_frame_base);
+}
+\f
+
+/* Helper functions for dealing with register sets.  */
 
-  set_gdbarch_breakpoint_from_pc (gdbarch, sparc_breakpoint_from_pc);
-  set_gdbarch_decr_pc_after_break (gdbarch, 0);
-  set_gdbarch_function_start_offset (gdbarch, 0);
+#define TSTATE_CWP     0x000000000000001fULL
+#define TSTATE_ICC     0x0000000f00000000ULL
+#define TSTATE_XCC     0x000000f000000000ULL
 
-  set_gdbarch_frame_args_skip (gdbarch, 8);
+#define PSR_S          0x00000080
+#define PSR_ICC                0x00f00000
+#define PSR_VERS       0x0f000000
+#define PSR_IMPL       0xf0000000
+#define PSR_V8PLUS     0xff000000
+#define PSR_XCC                0x000f0000
 
-  set_gdbarch_print_insn (gdbarch, print_insn_sparc);
+void
+sparc64_supply_gregset (const struct sparc_gregset *gregset,
+                       struct regcache *regcache,
+                       int regnum, const void *gregs)
+{
+  int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
+  const gdb_byte *regs = gregs;
+  int i;
 
-  set_gdbarch_software_single_step (gdbarch, sparc_software_single_step);
+  if (sparc32)
+    {
+      if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
+       {
+         int offset = gregset->r_tstate_offset;
+         ULONGEST tstate, psr;
+         gdb_byte buf[4];
+
+         tstate = extract_unsigned_integer (regs + offset, 8);
+         psr = ((tstate & TSTATE_CWP) | PSR_S | ((tstate & TSTATE_ICC) >> 12)
+                | ((tstate & TSTATE_XCC) >> 20) | PSR_V8PLUS);
+         store_unsigned_integer (buf, 4, psr);
+         regcache_raw_supply (regcache, SPARC32_PSR_REGNUM, buf);
+       }
 
-  set_gdbarch_unwind_dummy_id (gdbarch, sparc_unwind_dummy_id);
+      if (regnum == SPARC32_PC_REGNUM || regnum == -1)
+       regcache_raw_supply (regcache, SPARC32_PC_REGNUM,
+                            regs + gregset->r_pc_offset + 4);
 
-  set_gdbarch_unwind_pc (gdbarch, sparc64_unwind_pc);
+      if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
+       regcache_raw_supply (regcache, SPARC32_NPC_REGNUM,
+                            regs + gregset->r_npc_offset + 4);
 
-  frame_base_set_default (gdbarch, &sparc64_frame_base);
+      if (regnum == SPARC32_Y_REGNUM || regnum == -1)
+       {
+         int offset = gregset->r_y_offset + 8 - gregset->r_y_size;
+         regcache_raw_supply (regcache, SPARC32_Y_REGNUM, regs + offset);
+       }
+    }
+  else
+    {
+      if (regnum == SPARC64_STATE_REGNUM || regnum == -1)
+       regcache_raw_supply (regcache, SPARC64_STATE_REGNUM,
+                            regs + gregset->r_tstate_offset);
 
-  /* Hook in ABI-specific overrides, if they have been registered.  */
-  gdbarch_init_osabi (info, gdbarch);
+      if (regnum == SPARC64_PC_REGNUM || regnum == -1)
+       regcache_raw_supply (regcache, SPARC64_PC_REGNUM,
+                            regs + gregset->r_pc_offset);
 
-  frame_unwind_append_sniffer (gdbarch, sparc64_frame_sniffer);
+      if (regnum == SPARC64_NPC_REGNUM || regnum == -1)
+       regcache_raw_supply (regcache, SPARC64_NPC_REGNUM,
+                            regs + gregset->r_npc_offset);
 
-  return gdbarch;
-}
-\f
-/* Helper functions for dealing with register windows.  */
+      if (regnum == SPARC64_Y_REGNUM || regnum == -1)
+       {
+         gdb_byte buf[8];
 
-static void
-sparc_supply_rwindow (CORE_ADDR sp, int regnum)
-{
-  int offset = 0;
-  char buf[8];
-  int i;
+         memset (buf, 0, 8);
+         memcpy (buf + 8 - gregset->r_y_size,
+                 regs + gregset->r_y_offset, gregset->r_y_size);
+         regcache_raw_supply (regcache, SPARC64_Y_REGNUM, buf);
+       }
+
+      if ((regnum == SPARC64_FPRS_REGNUM || regnum == -1)
+         && gregset->r_fprs_offset != -1)
+       regcache_raw_supply (regcache, SPARC64_FPRS_REGNUM,
+                            regs + gregset->r_fprs_offset);
+    }
+
+  if (regnum == SPARC_G0_REGNUM || regnum == -1)
+    regcache_raw_supply (regcache, SPARC_G0_REGNUM, NULL);
 
-  /* 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 ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
     {
-      memset (buf, 0, 4);
-      offset = 4;
+      int offset = gregset->r_g1_offset;
+
+      if (sparc32)
+       offset += 4;
+
+      for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
+       {
+         if (regnum == i || regnum == -1)
+           regcache_raw_supply (regcache, i, regs + offset);
+         offset += 8;
+       }
     }
 
-  for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
+  if ((regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) || regnum == -1)
     {
-      if (regnum == i || regnum == -1)
+      /* 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)
+       {
+         ULONGEST sp;
+
+         regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
+         sparc_supply_rwindow (regcache, sp, regnum);
+       }
+      else
        {
-         target_read_memory (sp + ((i - SPARC_L0_REGNUM) * 4),
-                             buf + offset, 4);
-         supply_register (i, buf);
+         int offset = gregset->r_l0_offset;
+
+         if (sparc32)
+           offset += 4;
+
+         for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
+           {
+             if (regnum == i || regnum == -1)
+               regcache_raw_supply (regcache, i, regs + offset);
+             offset += 8;
+           }
        }
     }
 }
 
 void
-sparc64_supply_rwindow (CORE_ADDR sp, int regnum)
+sparc64_collect_gregset (const struct sparc_gregset *gregset,
+                        const struct regcache *regcache,
+                        int regnum, void *gregs)
 {
-  if (sp & 1)
+  int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
+  gdb_byte *regs = gregs;
+  int i;
+
+  if (sparc32)
     {
-      char buf[8];
-      int i;
+      if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
+       {
+         int offset = gregset->r_tstate_offset;
+         ULONGEST tstate, psr;
+         gdb_byte buf[8];
+
+         tstate = extract_unsigned_integer (regs + offset, 8);
+         regcache_raw_collect (regcache, SPARC32_PSR_REGNUM, buf);
+         psr = extract_unsigned_integer (buf, 4);
+         tstate |= (psr & PSR_ICC) << 12;
+         if ((psr & (PSR_VERS | PSR_IMPL)) == PSR_V8PLUS)
+           tstate |= (psr & PSR_XCC) << 20;
+         store_unsigned_integer (buf, 8, tstate);
+         memcpy (regs + offset, buf, 8);
+       }
 
-      /* Registers are 64-bit.  */
-      sp += BIAS;
+      if (regnum == SPARC32_PC_REGNUM || regnum == -1)
+       regcache_raw_collect (regcache, SPARC32_PC_REGNUM,
+                             regs + gregset->r_pc_offset + 4);
 
-      for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
+      if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
+       regcache_raw_collect (regcache, SPARC32_NPC_REGNUM,
+                             regs + gregset->r_npc_offset + 4);
+
+      if (regnum == SPARC32_Y_REGNUM || regnum == -1)
        {
-         if (regnum == i || regnum == -1)
-           {
-             target_read_memory (sp + ((i - SPARC_L0_REGNUM) * 8),
-                                 buf, sizeof (buf));
-             supply_register (i, buf);
-           }
+         int offset = gregset->r_y_offset + 8 - gregset->r_y_size;
+         regcache_raw_collect (regcache, SPARC32_Y_REGNUM, regs + offset);
        }
     }
   else
     {
-      /* Registers are 32-bit.  Toss any sign-extension of the stack
-        pointer.  */
-      sparc_supply_rwindow (sp & 0xffffffffUL, regnum);
+      if (regnum == SPARC64_STATE_REGNUM || regnum == -1)
+       regcache_raw_collect (regcache, SPARC64_STATE_REGNUM,
+                             regs + gregset->r_tstate_offset);
+
+      if (regnum == SPARC64_PC_REGNUM || regnum == -1)
+       regcache_raw_collect (regcache, SPARC64_PC_REGNUM,
+                             regs + gregset->r_pc_offset);
+
+      if (regnum == SPARC64_NPC_REGNUM || regnum == -1)
+       regcache_raw_collect (regcache, SPARC64_NPC_REGNUM,
+                             regs + gregset->r_npc_offset);
+
+      if (regnum == SPARC64_Y_REGNUM || regnum == -1)
+       {
+         gdb_byte buf[8];
+
+         regcache_raw_collect (regcache, SPARC64_Y_REGNUM, buf);
+         memcpy (regs + gregset->r_y_offset,
+                 buf + 8 - gregset->r_y_size, gregset->r_y_size);
+       }
+
+      if ((regnum == SPARC64_FPRS_REGNUM || regnum == -1)
+         && gregset->r_fprs_offset != -1)
+       regcache_raw_collect (regcache, SPARC64_FPRS_REGNUM,
+                             regs + gregset->r_fprs_offset);
+
+    }
+
+  if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
+    {
+      int offset = gregset->r_g1_offset;
+
+      if (sparc32)
+       offset += 4;
+
+      /* %g0 is always zero.  */
+      for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
+       {
+         if (regnum == i || regnum == -1)
+           regcache_raw_collect (regcache, i, regs + offset);
+         offset += 8;
+       }
+    }
+
+  if ((regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) || regnum == -1)
+    {
+      /* 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)
+       {
+         int offset = gregset->r_l0_offset;
+
+         if (sparc32)
+           offset += 4;
+
+         for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
+           {
+             if (regnum == i || regnum == -1)
+               regcache_raw_collect (regcache, i, regs + offset);
+             offset += 8;
+           }
+       }
     }
 }
 
-static void
-sparc_fill_rwindow (CORE_ADDR sp, int regnum)
+void
+sparc64_supply_fpregset (struct regcache *regcache,
+                        int regnum, const void *fpregs)
 {
-  int offset = 0;
-  char buf[8];
+  int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
+  const gdb_byte *regs = fpregs;
   int i;
 
-  /* Only use the bottom half if we're in 64-bit mode.  */
-  if (gdbarch_ptr_bit (current_gdbarch) == 64)
-    offset = 4;
+  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));
+    }
 
-  for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
+  if (sparc32)
+    {
+      if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
+       regcache_raw_supply (regcache, SPARC32_FSR_REGNUM,
+                            regs + (32 * 4) + (16 * 8) + 4);
+    }
+  else
     {
-      if (regnum == -1 || regnum == SPARC_SP_REGNUM || regnum == i)
+      for (i = 0; i < 16; i++)
        {
-         regcache_collect (i, buf);
-         target_write_memory (sp + ((i - SPARC_L0_REGNUM) * 4), buf, 4);
+         if (regnum == (SPARC64_F32_REGNUM + i) || regnum == -1)
+           regcache_raw_supply (regcache, SPARC64_F32_REGNUM + i,
+                                regs + (32 * 4) + (i * 8));
        }
+
+      if (regnum == SPARC64_FSR_REGNUM || regnum == -1)
+       regcache_raw_supply (regcache, SPARC64_FSR_REGNUM,
+                            regs + (32 * 4) + (16 * 8));
     }
 }
 
 void
-sparc64_fill_rwindow (CORE_ADDR sp, int regnum)
+sparc64_collect_fpregset (const struct regcache *regcache,
+                         int regnum, void *fpregs)
 {
-  if (sp & 1)
-    {
-      char buf[8];
-      int i;
+  int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
+  gdb_byte *regs = fpregs;
+  int i;
 
-      /* Registers are 64-bit.  */
-      sp += BIAS;
+  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));
+    }
 
-      for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
-       {
-         if (regnum == -1 || regnum == SPARC_SP_REGNUM || regnum == i)
-           {
-             regcache_collect (i, buf);
-             target_write_memory (sp + ((i - SPARC_L0_REGNUM) * 8),
-                                  buf, sizeof (buf));
-           }
-       }
+  if (sparc32)
+    {
+      if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
+       regcache_raw_collect (regcache, SPARC32_FSR_REGNUM,
+                             regs + (32 * 4) + (16 * 8) + 4);
     }
   else
     {
-      /* Registers are 32-bit.  Toss any sign-extension of the stack
-        pointer.  */
-      sparc_fill_rwindow (sp & 0xffffffffUL, regnum);
+      for (i = 0; i < 16; i++)
+       {
+         if (regnum == (SPARC64_F32_REGNUM + i) || regnum == -1)
+           regcache_raw_collect (regcache, SPARC64_F32_REGNUM + i,
+                                 regs + (32 * 4) + (i * 8));
+       }
+
+      if (regnum == SPARC64_FSR_REGNUM || regnum == -1)
+       regcache_raw_collect (regcache, SPARC64_FSR_REGNUM,
+                             regs + (32 * 4) + (16 * 8));
     }
 }
-\f
+
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 void _initialize_sparc64_tdep (void);
@@ -1487,5 +1562,6 @@ void _initialize_sparc64_tdep (void);
 void
 _initialize_sparc64_tdep (void)
 {
-  register_gdbarch_init (bfd_arch_sparc, sparc64_gdbarch_init);
+  /* Initialize the UltraSPARC-specific register types.  */
+  sparc64_init_types();
 }
This page took 0.038692 seconds and 4 git commands to generate.