aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Love <cel@us.ibm.com>2022-07-15 15:30:43 +0000
committerCarl Love <cel@us.ibm.com>2022-07-15 15:30:43 +0000
commitebbac1687d0075c8666b25438fc4f35d3dd1daaa (patch)
tree4333bffaa64d011e9266c2b4abfaa38674209e33
parent72be9d6be7de305b34ac298f1466167b9aba9bc2 (diff)
downloadgdb-ebbac1687d0075c8666b25438fc4f35d3dd1daaa.zip
gdb-ebbac1687d0075c8666b25438fc4f35d3dd1daaa.tar.gz
gdb-ebbac1687d0075c8666b25438fc4f35d3dd1daaa.tar.bz2
PowerPC: Add support for IEEE 128-bit format.
The test gdb.base/infcall-nested-structs-c.exp fails on a gdb assert in function ppc64_sysv_abi_return_value in file gdb/ppc-sysv-tdep.c. The assert is due to the missing IEEE 128-bit support in file gdb/ppc-sysv-tdep.c. The IBM long double was the initial float 128-bit support added by IBM The IEEE 128-bit support, which is similar IBM long double support, was made the default starting with GCC 12. The floating point format differences include the number of bits used to encode the exponent and significand. Also, IBM long double values are passed in a pair of floating point registers. The IEEE 128-bit value is passed in a single vector register. This patch fixes the gdb_assert (ok); in function ppc64_sysv_abi_return_value in gdb/ppc-sysv-tdep.c by adding IEEE FLOAT 128-bit type support for PowerPC. The patch has been tested on Power 10, ELFv2. It fixes the following list of regression failures on Power 10: gdb.base/infcall-nested-structs-c.exp 192 gdb.base/infcall-nested-structs-c++.exp 76 gdb.base/structs.exp 9 The patch has been tested on Power 8 BE which is ELFv1.
-rw-r--r--gdb/ppc-sysv-tdep.c87
1 files changed, 69 insertions, 18 deletions
diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c
index 6c2fd1b..91cc282 100644
--- a/gdb/ppc-sysv-tdep.c
+++ b/gdb/ppc-sysv-tdep.c
@@ -450,12 +450,17 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
}
}
else if (len == 16
- && type->code () == TYPE_CODE_ARRAY
- && type->is_vector ()
- && tdep->vector_abi == POWERPC_VEC_ALTIVEC)
+ && ((type->code () == TYPE_CODE_ARRAY
+ && type->is_vector ()
+ && tdep->vector_abi == POWERPC_VEC_ALTIVEC)
+ || (type->code () == TYPE_CODE_FLT
+ && (gdbarch_long_double_format (gdbarch)
+ == floatformats_ieee_quad))))
{
/* Vector parameter passed in an Altivec register, or
- when that runs out, 16 byte aligned stack location. */
+ when that runs out, 16 byte aligned stack location.
+ IEEE FLOAT 128-bit also passes parameters in vector
+ registers. */
if (vreg <= 13)
{
if (write_pass)
@@ -1180,7 +1185,8 @@ ppc64_aggregate_candidate (struct type *type,
static int
ppc64_elfv2_abi_homogeneous_aggregate (struct type *type,
- struct type **elt_type, int *n_elts)
+ struct type **elt_type, int *n_elts,
+ struct gdbarch *gdbarch)
{
/* Complex types at the top level are treated separately. However,
complex types can be elements of homogeneous aggregates. */
@@ -1193,9 +1199,20 @@ ppc64_elfv2_abi_homogeneous_aggregate (struct type *type,
if (field_count > 0)
{
- int n_regs = ((field_type->code () == TYPE_CODE_FLT
- || field_type->code () == TYPE_CODE_DECFLOAT)?
- (TYPE_LENGTH (field_type) + 7) >> 3 : 1);
+ int n_regs;
+
+ if (field_type->code () == TYPE_CODE_FLT
+ && (gdbarch_long_double_format (gdbarch)
+ == floatformats_ieee_quad))
+ /* IEEE Float 128-bit uses one vector register. */
+ n_regs = 1;
+
+ else if (field_type->code () == TYPE_CODE_FLT
+ || field_type->code () == TYPE_CODE_DECFLOAT)
+ n_regs = (TYPE_LENGTH (field_type) + 7) >> 3;
+
+ else
+ n_regs = 1;
/* The ELFv2 ABI allows homogeneous aggregates to occupy
up to 8 registers. */
@@ -1422,7 +1439,16 @@ ppc64_sysv_abi_push_param (struct gdbarch *gdbarch,
ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (type->code () == TYPE_CODE_FLT
- || type->code () == TYPE_CODE_DECFLOAT)
+ && TYPE_LENGTH (type) == 16
+ && (gdbarch_long_double_format (gdbarch)
+ == floatformats_ieee_quad))
+ {
+ /* IEEE FLOAT128, args in vector registers. */
+ ppc64_sysv_abi_push_val (gdbarch, val, TYPE_LENGTH (type), 0, argpos);
+ ppc64_sysv_abi_push_vreg (gdbarch, val, argpos);
+ }
+ else if (type->code () == TYPE_CODE_FLT
+ || type->code () == TYPE_CODE_DECFLOAT)
{
/* Floating-point scalars are passed in floating-point registers. */
ppc64_sysv_abi_push_val (gdbarch, val, TYPE_LENGTH (type), 0, argpos);
@@ -1494,14 +1520,22 @@ ppc64_sysv_abi_push_param (struct gdbarch *gdbarch,
single floating-point value, at any level of nesting of
single-member structs, are passed in floating-point registers. */
if (type->code () == TYPE_CODE_STRUCT
- && type->num_fields () == 1)
+ && type->num_fields () == 1 && tdep->elf_abi == POWERPC_ELF_V1)
{
while (type->code () == TYPE_CODE_STRUCT
&& type->num_fields () == 1)
type = check_typedef (type->field (0).type ());
- if (type->code () == TYPE_CODE_FLT)
- ppc64_sysv_abi_push_freg (gdbarch, type, val, argpos);
+ if (type->code () == TYPE_CODE_FLT) {
+ /* Handle the case of 128-bit floats for both IEEE and IBM long double
+ formats. */
+ if (TYPE_LENGTH (type) == 16
+ && (gdbarch_long_double_format (gdbarch)
+ == floatformats_ieee_quad))
+ ppc64_sysv_abi_push_vreg (gdbarch, val, argpos);
+ else
+ ppc64_sysv_abi_push_freg (gdbarch, type, val, argpos);
+ }
}
/* In the ELFv2 ABI, homogeneous floating-point or vector
@@ -1511,13 +1545,23 @@ ppc64_sysv_abi_push_param (struct gdbarch *gdbarch,
struct type *eltype;
int i, nelt;
- if (ppc64_elfv2_abi_homogeneous_aggregate (type, &eltype, &nelt))
+ if (ppc64_elfv2_abi_homogeneous_aggregate (type, &eltype, &nelt,
+ gdbarch))
for (i = 0; i < nelt; i++)
{
const gdb_byte *elval = val + i * TYPE_LENGTH (eltype);
if (eltype->code () == TYPE_CODE_FLT
- || eltype->code () == TYPE_CODE_DECFLOAT)
+ && TYPE_LENGTH (eltype) == 16
+ && (gdbarch_long_double_format (gdbarch)
+ == floatformats_ieee_quad))
+ /* IEEE FLOAT128, args in vector registers. */
+ ppc64_sysv_abi_push_vreg (gdbarch, elval, argpos);
+
+ else if (eltype->code () == TYPE_CODE_FLT
+ || eltype->code () == TYPE_CODE_DECFLOAT)
+ /* IBM long double and all other floats and decfloats, args
+ are in a pair of floating point registers. */
ppc64_sysv_abi_push_freg (gdbarch, eltype, elval, argpos);
else if (eltype->code () == TYPE_CODE_ARRAY
&& eltype->is_vector ()
@@ -1871,10 +1915,16 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype,
return 1;
}
- /* AltiVec vectors are returned in VRs starting at v2. */
+ /* AltiVec vectors are returned in VRs starting at v2.
+ IEEE FLOAT 128-bit are stored in vector register. */
+
if (TYPE_LENGTH (valtype) == 16
- && valtype->code () == TYPE_CODE_ARRAY && valtype->is_vector ()
- && tdep->vector_abi == POWERPC_VEC_ALTIVEC)
+ && ((valtype->code () == TYPE_CODE_ARRAY
+ && valtype->is_vector ()
+ && tdep->vector_abi == POWERPC_VEC_ALTIVEC)
+ || (valtype->code () == TYPE_CODE_FLT
+ && (gdbarch_long_double_format (gdbarch)
+ == floatformats_ieee_quad))))
{
int regnum = tdep->ppc_vr0_regnum + 2 + index;
@@ -2012,7 +2062,8 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
/* In the ELFv2 ABI, homogeneous floating-point or vector
aggregates are returned in registers. */
if (tdep->elf_abi == POWERPC_ELF_V2
- && ppc64_elfv2_abi_homogeneous_aggregate (valtype, &eltype, &nelt)
+ && ppc64_elfv2_abi_homogeneous_aggregate (valtype, &eltype, &nelt,
+ gdbarch)
&& (eltype->code () == TYPE_CODE_FLT
|| eltype->code () == TYPE_CODE_DECFLOAT
|| (eltype->code () == TYPE_CODE_ARRAY