aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2007-08-22 15:13:04 +0000
committerDaniel Jacobowitz <drow@false.org>2007-08-22 15:13:04 +0000
commit8d26208a1e22d9720c1423625c7e15f1bc7d237c (patch)
tree865c53dc061875f491071df2a55cd1fafcf97391 /gdb
parent65728c26984bf8b45c0f473d96443186b5c4ebab (diff)
downloadbinutils-8d26208a1e22d9720c1423625c7e15f1bc7d237c.zip
binutils-8d26208a1e22d9720c1423625c7e15f1bc7d237c.tar.gz
binutils-8d26208a1e22d9720c1423625c7e15f1bc7d237c.tar.bz2
gdb/testsuite/
* 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.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/mips-tdep.c87
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.base/callfuncs.c23
-rw-r--r--gdb/testsuite/gdb.base/callfuncs.exp5
5 files changed, 116 insertions, 11 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 17adcac..cde1d09 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 531d936..68621e1 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -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++;
}
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 8f95b3f..89b7a10 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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
diff --git a/gdb/testsuite/gdb.base/callfuncs.c b/gdb/testsuite/gdb.base/callfuncs.c
index 5a2bde2..3eeebe5 100644
--- a/gdb/testsuite/gdb.base/callfuncs.c
+++ b/gdb/testsuite/gdb.base/callfuncs.c
@@ -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
diff --git a/gdb/testsuite/gdb.base/callfuncs.exp b/gdb/testsuite/gdb.base/callfuncs.exp
index 6839abf..7d53e98 100644
--- a/gdb/testsuite/gdb.base/callfuncs.exp
+++ b/gdb/testsuite/gdb.base/callfuncs.exp
@@ -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"