Fix fixed-point "return" on ARM
authorTom Tromey <tromey@adacore.com>
Wed, 20 Sep 2023 17:29:53 +0000 (11:29 -0600)
committerTom Tromey <tromey@adacore.com>
Mon, 30 Oct 2023 13:45:39 +0000 (07:45 -0600)
On a big-endian ARM machine, the "return" command resulted in the
wrong value being returned when the function had a fixed-point return
type.  This patch fixes the problem by unpacking and repacking the
fixed-point type appropriately.

Approved-By: Luis Machado <luis.machado@arm.com>
gdb/arm-tdep.c

index 62412d92f855f864a0ef28294733b96dee4d3abc..a9c43b27265e54bf5dec2a194b51f947a1e83fee 100644 (file)
@@ -9170,16 +9170,28 @@ arm_store_return_value (struct type *type, struct regcache *regs,
           || type->code () == TYPE_CODE_BOOL
           || type->code () == TYPE_CODE_PTR
           || TYPE_IS_REFERENCE (type)
-          || type->code () == TYPE_CODE_ENUM)
+          || type->code () == TYPE_CODE_ENUM
+          || is_fixed_point_type (type))
     {
       if (type->length () <= 4)
        {
          /* Values of one word or less are zero/sign-extended and
             returned in r0.  */
          bfd_byte tmpbuf[ARM_INT_REGISTER_SIZE];
-         LONGEST val = unpack_long (type, valbuf);
 
-         store_signed_integer (tmpbuf, ARM_INT_REGISTER_SIZE, byte_order, val);
+         if (is_fixed_point_type (type))
+           {
+             gdb_mpz unscaled;
+             unscaled.read (gdb::make_array_view (valbuf, type->length ()),
+                            byte_order, type->is_unsigned ());
+             unscaled.write (gdb::make_array_view (tmpbuf, sizeof (tmpbuf)),
+                             byte_order, type->is_unsigned ());
+           }
+         else
+           {
+             LONGEST val = unpack_long (type, valbuf);
+             store_signed_integer (tmpbuf, ARM_INT_REGISTER_SIZE, byte_order, val);
+           }
          regs->cooked_write (ARM_A1_REGNUM, tmpbuf);
        }
       else