Float parameter passing in funcall on ppc-aix & ppc-lynx178.
authorJoel Brobecker <brobecker@gnat.com>
Mon, 13 May 2013 10:27:35 +0000 (10:27 +0000)
committerJoel Brobecker <brobecker@gnat.com>
Mon, 13 May 2013 10:27:35 +0000 (10:27 +0000)
Given the following code:

    float global_float = 0.0;

    void
    set_float (float f)
    {
      global_float = f;
    }

GDB incorrectly calls set_float if the set_float function is marked
as prototyped:

    (gdb) call set_float (5.0)
    (gdb) print global_float
    $1 = 2048

What happens, when the function is marked as prototyped, is that
GDB finds that the argument is a float, casts the value given in
the expression to a float, and then gives that float to ppc-aix/
ppc-lynx178's push_dummy_call gdbarch routine. The latter then blindly
copies it as is in the first floating-point register, instead of
making sure that it has the proper format first.

gdb/ChangeLog:

        * rs6000-aix-tdep.c (rs6000_push_dummy_call): Convert
        floating point registers to register type before storing
        value.
        * rs6000-lynx178-tdep.c (rs6000_lynx178_push_dummy_call):
        Likewise.

gdb/ChangeLog
gdb/rs6000-aix-tdep.c
gdb/rs6000-lynx178-tdep.c

index 84159e1dc2de297e3779c334976bb199aecd9f23..e3c2c4be846c4144298c030f6f6f1d753aae9a1c 100644 (file)
@@ -1,3 +1,11 @@
+2013-05-13  Joel Brobecker  <brobecker@adacore.com>
+
+       * rs6000-aix-tdep.c (rs6000_push_dummy_call): Convert
+       floating point registers to register type before storing
+       value.
+       * rs6000-lynx178-tdep.c (rs6000_lynx178_push_dummy_call):
+       Likewise.
+
 2013-05-10  Joel Brobecker  <brobecker@adacore.com>
            Tom Tromey  <tromey@redhat.com>
 
index 0992213f97e3a5fd412e0a705a7f32780ba1755d..0d4fec5ce0e1d390da66d527f966c337bdb0f840 100644 (file)
@@ -254,16 +254,21 @@ rs6000_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
       if (TYPE_CODE (type) == TYPE_CODE_FLT)
        {
-
          /* Floating point arguments are passed in fpr's, as well as gpr's.
             There are 13 fpr's reserved for passing parameters.  At this point
-            there is no way we would run out of them.  */
+            there is no way we would run out of them.
+
+            Always store the floating point value using the register's
+            floating-point format.  */
+         const int fp_regnum = tdep->ppc_fp0_regnum + 1 + f_argno;
+         gdb_byte reg_val[MAX_REGISTER_SIZE];
+         struct type *reg_type = register_type (gdbarch, fp_regnum);
 
          gdb_assert (len <= 8);
 
-         regcache_cooked_write (regcache,
-                                tdep->ppc_fp0_regnum + 1 + f_argno,
-                                value_contents (arg));
+         convert_typed_floating (value_contents (arg), type,
+                                 reg_val, reg_type);
+         regcache_cooked_write (regcache, fp_regnum, reg_val);
          ++f_argno;
        }
 
index 90730ab837ce140c3ca7b293cd2156135d7b6d9d..47fcc62637fa07f3f48c15a46c2002bad333464d 100644 (file)
@@ -100,13 +100,19 @@ rs6000_lynx178_push_dummy_call (struct gdbarch *gdbarch,
 
          /* Floating point arguments are passed in fpr's, as well as gpr's.
             There are 13 fpr's reserved for passing parameters.  At this point
-            there is no way we would run out of them.  */
+            there is no way we would run out of them.
+
+            Always store the floating point value using the register's
+            floating-point format.  */
+         const int fp_regnum = tdep->ppc_fp0_regnum + 1 + f_argno;
+         gdb_byte reg_val[MAX_REGISTER_SIZE];
+         struct type *reg_type = register_type (gdbarch, fp_regnum);
 
          gdb_assert (len <= 8);
 
-         regcache_cooked_write (regcache,
-                                tdep->ppc_fp0_regnum + 1 + f_argno,
-                                value_contents (arg));
+         convert_typed_floating (value_contents (arg), type,
+                                 reg_val, reg_type);
+         regcache_cooked_write (regcache, fp_regnum, reg_val);
          ++f_argno;
        }