From 36d1c68c70a09d38d76faa82263d16269139033c Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Mon, 13 May 2013 10:27:35 +0000 Subject: [PATCH] Float parameter passing in funcall on ppc-aix & ppc-lynx178. 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 | 8 ++++++++ gdb/rs6000-aix-tdep.c | 15 ++++++++++----- gdb/rs6000-lynx178-tdep.c | 14 ++++++++++---- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 84159e1dc2d..e3c2c4be846 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2013-05-13 Joel Brobecker + + * 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 Tom Tromey diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c index 0992213f97e..0d4fec5ce0e 100644 --- a/gdb/rs6000-aix-tdep.c +++ b/gdb/rs6000-aix-tdep.c @@ -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; } diff --git a/gdb/rs6000-lynx178-tdep.c b/gdb/rs6000-lynx178-tdep.c index 90730ab837c..47fcc62637f 100644 --- a/gdb/rs6000-lynx178-tdep.c +++ b/gdb/rs6000-lynx178-tdep.c @@ -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; } -- 2.30.2