From 9a73e1cafedc2e3a466b6193a460cb8062fa0a59 Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Thu, 21 Oct 2021 13:22:40 -0600 Subject: [PATCH] (PPC64) fix handling of fixed-point values when using "return" command In the gdb.ada/fixed_points_function.exp testcase, we have the following Ada code... type FP1_Type is delta 0.1 range -1.0 .. +1.0; -- Ordinary function Call_FP1 (F : FP1_Type) return FP1_Type is begin FP1_Arg := F; return FP1_Arg; end Call_FP1; ... used as follow: F1 : FP1_Type := 1.0; F1 := Call_FP1 (F1); The testcase, among other things, verifies that "return" works properly as follow: | (gdb) return 1.0 | Make pck.call_fp1 return now? (y or n) y | [...] | 9 F1 := Call_FP1 (F1); | (gdb) next | (gdb) print f1 | $1 = 0.0625 The output of the last command shows that we returned the wrong value. The value printed gives a clue about the problem, since it is 1/16th of the value we expected, where 1/16 is FP1_Type's scaling factor. The problem, here, comes from the fact that the function handling return values for base types (ppc64_sysv_abi_return_value_base) writes the return value using unpack_long which, upon seeing that the value being unpacked is a fixed point type, applies the scaling factor, to get the integer-representation of our fixed-point value (similar to what it does with floats, for instance). So, the fix consists in teaching ppc64_sysv_abi_return_value_base about fixed-point types, and to avoid the unwanted application of the scaling factor. Note that the "finish" function, on the other hand, does not suffer from this issue, simply becaue the value returned by the function is read from register without the use of a type, thus avoiding an unwanted application of a scaling factor. No test added, as this change is already tested by gdb.ada/fixed_points_function.exp. Co-Authored-By: Tristan Gingold --- gdb/ppc-sysv-tdep.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index 0d15e427561..86f0acb0543 100644 --- a/gdb/ppc-sysv-tdep.c +++ b/gdb/ppc-sysv-tdep.c @@ -1745,16 +1745,32 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype, if ((valtype->code () == TYPE_CODE_INT || valtype->code () == TYPE_CODE_ENUM || valtype->code () == TYPE_CODE_CHAR - || valtype->code () == TYPE_CODE_BOOL) + || valtype->code () == TYPE_CODE_BOOL + || valtype->code () == TYPE_CODE_RANGE + || is_fixed_point_type (valtype)) && TYPE_LENGTH (valtype) <= 8) { int regnum = tdep->ppc_gp0_regnum + 3 + index; if (writebuf != NULL) { + LONGEST return_val; + + if (is_fixed_point_type (valtype)) + { + /* Fixed point type values need to be returned unscaled. */ + gdb_mpz unscaled; + + unscaled.read ({writebuf, TYPE_LENGTH (valtype)}, + type_byte_order (valtype), + valtype->is_unsigned ()); + return_val = unscaled.as_integer (); + } + else + return_val = unpack_long (valtype, writebuf); + /* Be careful to sign extend the value. */ - regcache_cooked_write_unsigned (regcache, regnum, - unpack_long (valtype, writebuf)); + regcache_cooked_write_unsigned (regcache, regnum, return_val); } if (readbuf != NULL) { -- 2.30.2