This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH 06/11] Little-endian fixes: 128-bit DFP parameters / registers
- From: "Ulrich Weigand" <uweigand at de dot ibm dot com>
- To: gdb-patches at sourceware dot org
- Date: Tue, 28 Jan 2014 18:28:43 +0100 (CET)
- Subject: [PATCH 06/11] Little-endian fixes: 128-bit DFP parameters / registers
- Authentication-results: sourceware.org; auth=none
Hello,
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 ...)
Tested on powerpc64-linux and powerpc64le-linux.
Bye,
Ulrich
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.
testsuite/ChangeLog:
* gdb.arch/powerpc-d128-regs.exp: Enable on powerpc64*-*.
Index: binutils-gdb/gdb/ppc-sysv-tdep.c
===================================================================
--- binutils-gdb.orig/gdb/ppc-sysv-tdep.c
+++ binutils-gdb/gdb/ppc-sysv-tdep.c
@@ -1267,8 +1267,11 @@ ppc64_sysv_abi_push_freg (struct gdbarch
if (argpos->regcache && argpos->freg <= 12)
{
int regnum = tdep->ppc_fp0_regnum + argpos->freg;
- regcache_cooked_write (argpos->regcache, regnum, val);
- regcache_cooked_write (argpos->regcache, regnum + 1, val + 8);
+ 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 + hipart);
+ regcache_cooked_write (argpos->regcache, regnum + 1, val + lopart);
}
argpos->freg += 2;
@@ -1676,16 +1679,18 @@ ppc64_sysv_abi_return_value_base (struct
&& 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: binutils-gdb/gdb/rs6000-tdep.c
===================================================================
--- binutils-gdb.orig/gdb/rs6000-tdep.c
+++ binutils-gdb/gdb/rs6000-tdep.c
@@ -2672,10 +2672,10 @@ dfp_pseudo_register_read (struct gdbarch
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 gdbarc
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: binutils-gdb/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp
===================================================================
--- binutils-gdb.orig/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp
+++ binutils-gdb/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp
@@ -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
}
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com