PowerPC64 little-endian fixes: 128-bit DFP parameters / registers
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Tue, 4 Feb 2014 17:34:19 +0000 (18:34 +0100)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Tue, 4 Feb 2014 17:36:54 +0000 (18:36 +0100)
The powerpc64le-linux ABI specifies that when a 128-bit DFP value is
passed in a pair of floating-point registers, the first register holds
the most-significant part of the value.  This is as opposed to the
usual rule on little-endian systems, where the first register would
hold the least-significant part.

This affects two places in GDB, the read/write routines for the
128-bit DFP pseudo-registers, and the function call / return
sequence.  For the former, current code already distinguishes
between big- and little-endian targets, but gets the latter
wrong.  This is presumably because *GCC* also got it wrong,
and GDB matches the old GCC behavior.  But GCC is now fixed:
http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02145.html
so GDB needs to be fixed too.  (Old code shouldn't really be
an issue since there is no code "out there" so far that uses
dfp128 on little-endian ...)

gdb/ChangeLog:

* ppc-sysv-tdep.c (ppc64_sysv_abi_push_freg): Use correct order
within a register pair holding a DFP 128-bit value on little-endian.
(ppc64_sysv_abi_return_value_base): Likewise.
* rs6000-tdep.c (dfp_pseudo_register_read): Likewise.
(dfp_pseudo_register_write): Likewise.

gdb/testsuite/ChangeLog:

* gdb.arch/powerpc-d128-regs.exp: Enable on powerpc64*-*.

gdb/ChangeLog
gdb/ppc-sysv-tdep.c
gdb/rs6000-tdep.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.arch/powerpc-d128-regs.exp

index e4a913bff7c632d4c703473104cd9d390a5b5010..1d2e30ccccdf9319538f7de3476a42bf56ec3b45 100644 (file)
@@ -1,3 +1,11 @@
+2014-02-04  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * ppc-sysv-tdep.c (ppc64_sysv_abi_push_freg): Use correct order
+       within a register pair holding a DFP 128-bit value on little-endian.
+       (ppc64_sysv_abi_return_value_base): Likewise.
+       * rs6000-tdep.c (dfp_pseudo_register_read): Likewise.
+       (dfp_pseudo_register_write): Likewise.
+
 2014-02-04  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * ppc-sysv-tdep.c (ppc64_sysv_abi_push_freg): Use correct
index de5a6631d1d2afffde49f4dd7d7937b90a4d0491..8e460e5f675363d9fa9c67cd1d4cf28edb4b6af7 100644 (file)
@@ -1270,9 +1270,11 @@ ppc64_sysv_abi_push_freg (struct gdbarch *gdbarch,
       if (argpos->regcache && argpos->freg <= 12)
        {
          int regnum = tdep->ppc_fp0_regnum + argpos->freg;
+         int lopart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 8 : 0;
+         int hipart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
 
-         regcache_cooked_write (argpos->regcache, regnum, val);
-         regcache_cooked_write (argpos->regcache, regnum + 1, val + 8);
+         regcache_cooked_write (argpos->regcache, regnum, val + hipart);
+         regcache_cooked_write (argpos->regcache, regnum + 1, val + lopart);
        }
 
       argpos->freg += 2;
@@ -1685,16 +1687,18 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype,
       && TYPE_CODE (valtype) == TYPE_CODE_DECFLOAT)
     {
       int regnum = tdep->ppc_fp0_regnum + 2 + 2 * index;
+      int lopart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 8 : 0;
+      int hipart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
 
       if (writebuf != NULL)
        {
-         regcache_cooked_write (regcache, regnum, writebuf);
-         regcache_cooked_write (regcache, regnum + 1, writebuf + 8);
+         regcache_cooked_write (regcache, regnum, writebuf + hipart);
+         regcache_cooked_write (regcache, regnum + 1, writebuf + lopart);
        }
       if (readbuf != NULL)
        {
-         regcache_cooked_read (regcache, regnum, readbuf);
-         regcache_cooked_read (regcache, regnum + 1, readbuf + 8);
+         regcache_cooked_read (regcache, regnum, readbuf + hipart);
+         regcache_cooked_read (regcache, regnum + 1, readbuf + lopart);
        }
       return 1;
     }
index adee085582efe21641027a89b3b48ee7869e26fa..b407bd60a66e93db22053df4e3e247fc6d457c06 100644 (file)
@@ -2672,10 +2672,10 @@ dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
   else
     {
       status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                                 2 * reg_index + 1, buffer + 8);
+                                 2 * reg_index + 1, buffer);
       if (status == REG_VALID)
        status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                                   2 * reg_index, buffer);
+                                   2 * reg_index, buffer + 8);
     }
 
   return status;
@@ -2701,9 +2701,9 @@ dfp_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
   else
     {
       regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
-                         2 * reg_index + 1, buffer + 8);
+                         2 * reg_index + 1, buffer);
       regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
-                         2 * reg_index, buffer);
+                         2 * reg_index, buffer + 8);
     }
 }
 
index 5680bc6fdd242cc9fe09fffde430663d3bf1f435..7378bb24e5405e3737232fbb01cacff61eb3bce2 100644 (file)
@@ -1,3 +1,7 @@
+2014-02-04  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * gdb.arch/powerpc-d128-regs.exp: Enable on powerpc64*-*.
+
 2014-02-04  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * gdb.arch/vsx-regs.exp: Check target endianness.  Provide variants
index 035cf12a041c90ca43b9851ed52d642a0d09c0a1..622004c93fb1471a5897d5ce59dfe8b1d752dd6c 100644 (file)
@@ -20,7 +20,7 @@
 
 # Testcase for ppc decimal128 pseudo-registers.
 
-if ![istarget "powerpc64-*"] then {
+if ![istarget "powerpc64*-*"] then {
     verbose "Skipping powerpc Decimal128 pseudo-registers testcase."
     return
 }