* configure.ac: Use AC_CHECK_DECLS instead of gcc_AC_CHECK_DECLS
[deliverable/binutils-gdb.git] / gdb / sparc64-tdep.c
index ced47a4edbe2bf3966ce10bf6ff4ba2b4c24dbfb..95562ba0b80b5fa81d7f29766b1982dddbc31561 100644 (file)
 /* 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
@@ -555,8 +544,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 =
@@ -579,8 +572,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);
 
-  /* ??? Should we take BIAS into account here?  */
-  return cache->base;
+  return cache->base + BIAS;
 }
 
 static const struct frame_base sparc64_frame_base =
@@ -604,8 +596,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;
@@ -657,9 +653,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);
+       }
     }
 }
 
@@ -705,9 +722,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);
+       }
     }
 }
 
@@ -735,7 +755,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))
@@ -834,7 +854,7 @@ 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]);
+      struct type *type = value_type (args[i]);
       int len = TYPE_LENGTH (type);
       int regnum = -1;
       char buf[16];
@@ -883,10 +903,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
@@ -914,11 +935,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);
     }
@@ -931,7 +952,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)
@@ -1019,7 +1040,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);
     }
@@ -1042,12 +1063,20 @@ sparc64_store_return_value (struct type *type, struct regcache *regcache,
     }
 }
 
-static int
-sparc64_use_struct_convention (int gcc_p, struct type *type)
+static enum return_value_convention
+sparc64_return_value (struct gdbarch *gdbarch, struct type *type,
+                     struct regcache *regcache, void *readbuf,
+                     const void *writebuf)
 {
-  /* Structure and union types up to 32 bytes in size are returned in
-     registers.  */
-  return (TYPE_LENGTH (type) > 32);
+  if (TYPE_LENGTH (type) > 32)
+    return RETURN_VALUE_STRUCT_CONVENTION;
+
+  if (readbuf)
+    sparc64_extract_return_value (type, regcache, readbuf);
+  if (writebuf)
+    sparc64_store_return_value (type, regcache, writebuf);
+
+  return RETURN_VALUE_REGISTER_CONVENTION;
 }
 \f
 
@@ -1079,11 +1108,7 @@ sparc64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   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_use_struct_convention (gdbarch, sparc64_use_struct_convention);
-  set_gdbarch_return_value_on_stack
-    (gdbarch, generic_return_value_on_stack_not);
+  set_gdbarch_return_value (gdbarch, sparc64_return_value);
   set_gdbarch_stabs_argument_has_addr
     (gdbarch, default_stabs_argument_has_addr);
 
This page took 0.025432 seconds and 4 git commands to generate.