gdb/testsuite/
authorDaniel Jacobowitz <drow@false.org>
Wed, 22 Aug 2007 15:13:04 +0000 (15:13 +0000)
committerDaniel Jacobowitz <drow@false.org>
Wed, 22 Aug 2007 15:13:04 +0000 (15:13 +0000)
* gdb.base/callfuncs.exp (do_function_calls): Use t_double_int
and t_int_double.
* gdb.base/callfuncs.c (t_double_int, t_int_double): New.

gdb/
* mips-tdep.c (mips_n32n64_fp_arg_chunk_p): New.
(mips_n32n64_push_dummy_call): Always increment float_argreg along
with argreg.  Use mips_n32n64_fp_arg_chunk_p.

gdb/ChangeLog
gdb/mips-tdep.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/callfuncs.c
gdb/testsuite/gdb.base/callfuncs.exp

index 17adcac..cde1d09 100644 (file)
@@ -1,5 +1,11 @@
 2007-08-22  Daniel Jacobowitz  <dan@codesourcery.com>
 
+       * mips-tdep.c (mips_n32n64_fp_arg_chunk_p): New.
+       (mips_n32n64_push_dummy_call): Always increment float_argreg along
+       with argreg.  Use mips_n32n64_fp_arg_chunk_p.
+
+2007-08-22  Daniel Jacobowitz  <dan@codesourcery.com>
+
        * solib-svr4.c (scan_dyntag): Only read target memory when necessary.
        Fix formatting.
        (elf_locate_base): Look for DT_MIPS_RLD_MAP first.  Expand comments.
index 531d936..68621e1 100644 (file)
@@ -2781,6 +2781,59 @@ mips_eabi_return_value (struct gdbarch *gdbarch,
 
 /* N32/N64 ABI stuff.  */
 
+/* Search for a naturally aligned double at OFFSET inside a struct
+   ARG_TYPE.  The N32 / N64 ABIs pass these in floating point
+   registers.  */
+
+static int
+mips_n32n64_fp_arg_chunk_p (struct type *arg_type, int offset)
+{
+  int i;
+
+  if (TYPE_CODE (arg_type) != TYPE_CODE_STRUCT)
+    return 0;
+
+  if (MIPS_FPU_TYPE != MIPS_FPU_DOUBLE)
+    return 0;
+
+  if (TYPE_LENGTH (arg_type) < offset + MIPS64_REGSIZE)
+    return 0;
+
+  for (i = 0; i < TYPE_NFIELDS (arg_type); i++)
+    {
+      int pos;
+      struct type *field_type;
+
+      /* We're only looking at normal fields.  */
+      if (TYPE_FIELD_STATIC (arg_type, i)
+         || (TYPE_FIELD_BITPOS (arg_type, i) % 8) != 0)
+       continue;
+
+      /* If we have gone past the offset, there is no double to pass.  */
+      pos = TYPE_FIELD_BITPOS (arg_type, i) / 8;
+      if (pos > offset)
+       return 0;
+
+      field_type = check_typedef (TYPE_FIELD_TYPE (arg_type, i));
+
+      /* If this field is entirely before the requested offset, go
+        on to the next one.  */
+      if (pos + TYPE_LENGTH (field_type) <= offset)
+       continue;
+
+      /* If this is our special aligned double, we can stop.  */
+      if (TYPE_CODE (field_type) == TYPE_CODE_FLT
+         && TYPE_LENGTH (field_type) == MIPS64_REGSIZE)
+       return 1;
+
+      /* This field starts at or before the requested offset, and
+        overlaps it.  If it is a structure, recurse inwards.  */
+      return mips_n32n64_fp_arg_chunk_p (field_type, offset - pos);
+    }
+
+  return 0;
+}
+
 static CORE_ADDR
 mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                             struct regcache *regcache, CORE_ADDR bp_addr,
@@ -2855,23 +2908,22 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       val = value_contents (arg);
 
       if (fp_register_arg_p (typecode, arg_type)
-         && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
+         && argreg <= MIPS_LAST_ARG_REGNUM)
        {
          /* This is a floating point value that fits entirely
             in a single register.  */
-         /* On 32 bit ABI's the float_argreg is further adjusted
-            above to ensure that it is even register aligned.  */
          LONGEST regval = extract_unsigned_integer (val, len);
          if (mips_debug)
            fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
                                float_argreg, phex (regval, len));
-         regcache_cooked_write_unsigned (regcache, float_argreg++, regval);
+         regcache_cooked_write_unsigned (regcache, float_argreg, regval);
 
          if (mips_debug)
            fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
                                argreg, phex (regval, len));
          regcache_cooked_write_unsigned (regcache, argreg, regval);
-         argreg += 1;
+         float_argreg++;
+         argreg++;
        }
       else
        {
@@ -2896,10 +2948,12 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
                                    partial_len);
 
+             if (fp_register_arg_p (typecode, arg_type))
+               gdb_assert (argreg > MIPS_LAST_ARG_REGNUM);
+
              /* Write this portion of the argument to the stack.  */
              if (argreg > MIPS_LAST_ARG_REGNUM
-                 || odd_sized_struct
-                 || fp_register_arg_p (typecode, arg_type))
+                 || odd_sized_struct)
                {
                  /* Should shorter than int integer values be
                     promoted to int before being stored? */
@@ -2940,12 +2994,10 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                }
 
              /* Note!!! This is NOT an else clause.  Odd sized
-                structs may go thru BOTH paths.  Floating point
-                arguments will not.  */
+                structs may go thru BOTH paths.  */
              /* Write this portion of the argument to a general
                 purpose register.  */
-             if (argreg <= MIPS_LAST_ARG_REGNUM
-                 && !fp_register_arg_p (typecode, arg_type))
+             if (argreg <= MIPS_LAST_ARG_REGNUM)
                {
                  LONGEST regval =
                    extract_unsigned_integer (val, partial_len);
@@ -2971,6 +3023,19 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                                      argreg,
                                      phex (regval, MIPS64_REGSIZE));
                  regcache_cooked_write_unsigned (regcache, argreg, regval);
+
+                 if (mips_n32n64_fp_arg_chunk_p (arg_type,
+                                                 TYPE_LENGTH (arg_type) - len))
+                   {
+                     if (mips_debug)
+                       fprintf_filtered (gdb_stdlog, " - fpreg=%d val=%s",
+                                         float_argreg,
+                                         phex (regval, MIPS64_REGSIZE));
+                     regcache_cooked_write_unsigned (regcache, float_argreg,
+                                                     regval);
+                   }
+
+                 float_argreg++;
                  argreg++;
                }
 
index 8f95b3f..89b7a10 100644 (file)
@@ -1,3 +1,9 @@
+2007-08-22  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * gdb.base/callfuncs.exp (do_function_calls): Use t_double_int
+       and t_int_double.
+       * gdb.base/callfuncs.c (t_double_int, t_int_double): New.
+
 2007-08-17  Joel Brobecker  <brobecker@adacore.com>
 
        * gdb.base/step-line.c: Switch license to GPL version 3, and
index 5a2bde2..3eeebe5 100644 (file)
@@ -334,6 +334,29 @@ char char_array_arg1[], char_array_arg2[];
          !strcmp (char_array_arg2, char_array_val2));
 }
 
+#ifdef PROTOTYPES
+int t_double_int (double double_arg1, int int_arg2)
+#else
+int t_double_int (double_arg1, int_arg2)
+double double_arg1;
+int int_arg2;
+#endif
+{
+  return ((double_arg1 - int_arg2) < DELTA
+         && (double_arg1 - int_arg2) > -DELTA);
+}
+
+#ifdef PROTOTYPES
+int t_int_double (int int_arg1, double double_arg2)
+#else
+int t_int_double (int_arg1, double_arg2)
+int int_arg1;
+double double_arg2;
+#endif
+{
+  return ((int_arg1 - double_arg2) < DELTA
+         && (int_arg1 - double_arg2) > -DELTA);
+}
 
 /* This used to simply compare the function pointer arguments with
    known values for func_val1 and func_val2.  Doing so is valid ANSI
index 6839abf..7d53e98 100644 (file)
@@ -163,6 +163,11 @@ proc do_function_calls {} {
        gdb_test "p t_double_values(double_val1,double_val2)" " = 1"
        gdb_test "p t_double_values(45.654,double_val2)" " = 1"
        gdb_test "p t_double_values(double_val1,-67.66)" " = 1"
+
+       gdb_test "p t_double_int(99.0, 1)" " = 0"
+       gdb_test "p t_double_int(99.0, 99)" " = 1"
+       gdb_test "p t_int_double(99, 1.0)" " = 0"
+       gdb_test "p t_int_double(99, 99.0)" " = 1"
     }
 
     gdb_test "p t_string_values(string_val2,string_val1)" " = 0"