You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
4.6 KiB
118 lines
4.6 KiB
commit 0ff3e01fdc67a3842ee54224cf197e9a55f0a750 |
|
Author: Ulrich Weigand <ulrich.weigand@de.ibm.com> |
|
Date: Tue Feb 4 18:34:19 2014 +0100 |
|
|
|
PowerPC64 little-endian fixes: 128-bit DFP parameters / registers |
|
|
|
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*-*. |
|
|
|
Index: gdb-7.6.1/gdb/ppc-sysv-tdep.c |
|
=================================================================== |
|
--- gdb-7.6.1.orig/gdb/ppc-sysv-tdep.c |
|
+++ gdb-7.6.1/gdb/ppc-sysv-tdep.c |
|
@@ -1269,9 +1269,11 @@ ppc64_sysv_abi_push_freg (struct 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; |
|
@@ -1684,16 +1686,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: gdb-7.6.1/gdb/rs6000-tdep.c |
|
=================================================================== |
|
--- gdb-7.6.1.orig/gdb/rs6000-tdep.c |
|
+++ gdb-7.6.1/gdb/rs6000-tdep.c |
|
@@ -2723,10 +2723,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; |
|
@@ -2752,9 +2752,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: gdb-7.6.1/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp |
|
=================================================================== |
|
--- gdb-7.6.1.orig/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp |
|
+++ gdb-7.6.1/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 |
|
}
|
|
|