* NEWS: Mention pointer to member improvements.
[deliverable/binutils-gdb.git] / gdb / sparc64-tdep.c
index 1d925188f299a290e2c056b1b85a1d950377ab88..a3a734bff80f362d8757272b901f1b02698fbe55 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for UltraSPARC.
 
-   Copyright 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
 #include "arch-utils.h"
+#include "dwarf2-frame.h"
 #include "floatformat.h"
 #include "frame.h"
 #include "frame-base.h"
@@ -119,6 +120,62 @@ sparc64_structure_or_union_p (const struct type *type)
 
   return 0;
 }
+\f
+
+/* Type for %pstate.  */
+struct type *sparc64_pstate_type;
+
+/* 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)
+{
+  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.  */
 
@@ -223,8 +280,8 @@ static struct sparc64_register_info sparc64_register_info[] =
   /* 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."  */
@@ -240,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 },
 
@@ -330,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);
 
@@ -338,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)
     {
@@ -349,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
@@ -389,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);
 
@@ -397,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)
     {
@@ -408,15 +465,15 @@ 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);
     }
   else if (regnum == SPARC64_CWP_REGNUM
           || regnum == SPARC64_PSTATE_REGNUM
@@ -497,7 +554,7 @@ 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 sparc_frame_cache *cache =
     sparc64_frame_cache (next_frame, this_cache);
@@ -519,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
@@ -526,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)
        {
@@ -572,7 +652,7 @@ sparc64_frame_base_address (struct frame_info *next_frame, void **this_cache)
   struct sparc_frame_cache *cache =
     sparc64_frame_cache (next_frame, this_cache);
 
-  return cache->base + BIAS;
+  return cache->base;
 }
 
 static const struct frame_base sparc64_frame_base =
@@ -615,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);
 
@@ -687,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))
     {
@@ -755,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))
@@ -784,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++;
            }
@@ -853,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))
        {
@@ -939,7 +1019,7 @@ sparc64_store_arguments (struct regcache *regcache, int nargs,
            }
        }
 
-      /* Always store the argument in memeory.  */
+      /* Always store the argument in memory.  */
       write_memory (sp + element * 8, valbuf, len);
       element += ((len + 7) / 8);
     }
@@ -973,7 +1053,7 @@ sparc64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   /* Finally, update the stack pointer.  */
   regcache_cooked_write_unsigned (regcache, SPARC_SP_REGNUM, sp);
 
-  return sp;
+  return sp + BIAS;
 }
 \f
 
@@ -982,10 +1062,10 @@ sparc64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
 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))
@@ -1006,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.  */
@@ -1023,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))
@@ -1051,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.  */
@@ -1065,8 +1164,8 @@ sparc64_store_return_value (struct type *type, struct regcache *regcache,
 
 static enum return_value_convention
 sparc64_return_value (struct gdbarch *gdbarch, struct type *type,
-                     struct regcache *regcache, void *readbuf,
-                     const void *writebuf)
+                     struct regcache *regcache, gdb_byte *readbuf,
+                     const gdb_byte *writebuf)
 {
   if (TYPE_LENGTH (type) > 32)
     return RETURN_VALUE_STRUCT_CONVENTION;
@@ -1080,6 +1179,33 @@ sparc64_return_value (struct gdbarch *gdbarch, struct type *type,
 }
 \f
 
+static void
+sparc64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+                              struct dwarf2_frame_state_reg *reg,
+                              struct frame_info *next_frame)
+{
+  switch (regnum)
+    {
+    case SPARC_G0_REGNUM:
+      /* Since %g0 is always zero, there is no point in saving it, and
+        people will be inclined omit it from the CFI.  Make sure we
+        don't warn about that.  */
+      reg->how = DWARF2_FRAME_REG_SAME_VALUE;
+      break;
+    case SPARC_SP_REGNUM:
+      reg->how = DWARF2_FRAME_REG_CFA;
+      break;
+    case 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;
+    }
+}
+
 void
 sparc64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -1114,6 +1240,11 @@ sparc64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   set_gdbarch_skip_prologue (gdbarch, sparc64_skip_prologue);
 
+  /* 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);
 }
@@ -1138,7 +1269,7 @@ sparc64_supply_gregset (const struct sparc_gregset *gregset,
                        int regnum, const void *gregs)
 {
   int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
-  const char *regs = gregs;
+  const gdb_byte *regs = gregs;
   int i;
 
   if (sparc32)
@@ -1147,7 +1278,7 @@ sparc64_supply_gregset (const struct sparc_gregset *gregset,
        {
          int offset = gregset->r_tstate_offset;
          ULONGEST tstate, psr;
-         char buf[4];
+         gdb_byte buf[4];
 
          tstate = extract_unsigned_integer (regs + offset, 8);
          psr = ((tstate & TSTATE_CWP) | PSR_S | ((tstate & TSTATE_ICC) >> 12)
@@ -1186,7 +1317,7 @@ sparc64_supply_gregset (const struct sparc_gregset *gregset,
 
       if (regnum == SPARC64_Y_REGNUM || regnum == -1)
        {
-         char buf[8];
+         gdb_byte buf[8];
 
          memset (buf, 0, 8);
          memcpy (buf + 8 - gregset->r_y_size,
@@ -1252,7 +1383,7 @@ sparc64_collect_gregset (const struct sparc_gregset *gregset,
                         int regnum, void *gregs)
 {
   int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
-  char *regs = gregs;
+  gdb_byte *regs = gregs;
   int i;
 
   if (sparc32)
@@ -1261,7 +1392,7 @@ sparc64_collect_gregset (const struct sparc_gregset *gregset,
        {
          int offset = gregset->r_tstate_offset;
          ULONGEST tstate, psr;
-         char buf[8];
+         gdb_byte buf[8];
 
          tstate = extract_unsigned_integer (regs + offset, 8);
          regcache_raw_collect (regcache, SPARC32_PSR_REGNUM, buf);
@@ -1303,7 +1434,7 @@ sparc64_collect_gregset (const struct sparc_gregset *gregset,
 
       if (regnum == SPARC64_Y_REGNUM || regnum == -1)
        {
-         char buf[8];
+         gdb_byte buf[8];
 
          regcache_raw_collect (regcache, SPARC64_Y_REGNUM, buf);
          memcpy (regs + gregset->r_y_offset,
@@ -1359,7 +1490,7 @@ sparc64_supply_fpregset (struct regcache *regcache,
                         int regnum, const void *fpregs)
 {
   int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
-  const char *regs = fpregs;
+  const gdb_byte *regs = fpregs;
   int i;
 
   for (i = 0; i < 32; i++)
@@ -1394,7 +1525,7 @@ sparc64_collect_fpregset (const struct regcache *regcache,
                          int regnum, void *fpregs)
 {
   int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
-  char *regs = fpregs;
+  gdb_byte *regs = fpregs;
   int i;
 
   for (i = 0; i < 32; i++)
@@ -1423,3 +1554,14 @@ sparc64_collect_fpregset (const struct regcache *regcache,
                              regs + (32 * 4) + (16 * 8));
     }
 }
+
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_sparc64_tdep (void);
+
+void
+_initialize_sparc64_tdep (void)
+{
+  /* Initialize the UltraSPARC-specific register types.  */
+  sparc64_init_types();
+}
This page took 0.031947 seconds and 4 git commands to generate.