(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 <gingold@adacore.com>
This commit is contained in:
Joel Brobecker 2021-10-21 13:22:40 -06:00 committed by Tom Tromey
parent 0abb4049fb
commit 9a73e1cafe

View File

@ -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<LONGEST> ();
}
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)
{