diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 88c760313a..0ea3228730 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2017-11-21 Ulrich Weigand + + * ppc-tdep.h (enum powerpc_long_double_abi): New data type. + (struct gdbarch_tdep): New member long_double_abi. + * rs6000-tdep.c (rs6000_gdbarch_init): Initialize long_double_abi + member of tdep struct based on Tag_GNU_Power_ABI_FP attribute. + * ppc-linux-tdep.c (ppc_linux_init_abi): Install long double data + format depending on long_double_abi tdep member. + (ppc_floatformat_for_type): Handle __ibm128 type. + 2017-11-20 Simon Marchi * darwin-nat.c (set_enable_mach_exceptions): Constify parameter. diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index ee80a71c6b..0e43a64b69 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -1623,12 +1623,17 @@ ppc_floatformat_for_type (struct gdbarch *gdbarch, const char *name, int len) { if (len == 128 && name) - if (strcmp (name, "__float128") == 0 - || strcmp (name, "_Float128") == 0 - || strcmp (name, "_Float64x") == 0 - || strcmp (name, "complex _Float128") == 0 - || strcmp (name, "complex _Float64x") == 0) - return floatformats_ia64_quad; + { + if (strcmp (name, "__float128") == 0 + || strcmp (name, "_Float128") == 0 + || strcmp (name, "_Float64x") == 0 + || strcmp (name, "complex _Float128") == 0 + || strcmp (name, "complex _Float64x") == 0) + return floatformats_ia64_quad; + + if (strcmp (name, "__ibm128") == 0) + return floatformats_ibm_long_double; + } return default_floatformat_for_type (gdbarch, name, len); } @@ -1648,12 +1653,15 @@ ppc_linux_init_abi (struct gdbarch_info info, linux_init_abi (info, gdbarch); /* PPC GNU/Linux uses either 64-bit or 128-bit long doubles; where - 128-bit, they are IBM long double, not IEEE quad long double as - in the System V ABI PowerPC Processor Supplement. We can safely - let them default to 128-bit, since the debug info will give the - size of type actually used in each case. */ + 128-bit, they can be either IBM long double or IEEE quad long double. + The 64-bit long double case will be detected automatically using + the size specified in debug info. We use a .gnu.attribute flag + to distinguish between the IBM long double and IEEE quad cases. */ set_gdbarch_long_double_bit (gdbarch, 16 * TARGET_CHAR_BIT); - set_gdbarch_long_double_format (gdbarch, floatformats_ibm_long_double); + if (tdep->long_double_abi == POWERPC_LONG_DOUBLE_IEEE128) + set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad); + else + set_gdbarch_long_double_format (gdbarch, floatformats_ibm_long_double); /* Support for floating-point data type variants. */ set_gdbarch_floatformat_for_type (gdbarch, ppc_floatformat_for_type); diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h index 4ae5c7f66e..3d1e3279e6 100644 --- a/gdb/ppc-tdep.h +++ b/gdb/ppc-tdep.h @@ -202,6 +202,15 @@ enum powerpc_vector_abi POWERPC_VEC_LAST }; +/* long double ABI version used by the inferior. */ +enum powerpc_long_double_abi +{ + POWERPC_LONG_DOUBLE_AUTO, + POWERPC_LONG_DOUBLE_IBM128, + POWERPC_LONG_DOUBLE_IEEE128, + POWERPC_LONG_DOUBLE_LAST +}; + struct gdbarch_tdep { int wordsize; /* Size in bytes of fixed-point word. */ @@ -209,6 +218,9 @@ struct gdbarch_tdep enum powerpc_elf_abi elf_abi; /* ELF ABI version. */ + /* Format to use for the "long double" data type. */ + enum powerpc_long_double_abi long_double_abi; + /* How to pass vector arguments. Never set to AUTO or LAST. */ enum powerpc_vector_abi vector_abi; diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 6c44995957..456dbcccb1 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -5949,6 +5949,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) bfd abfd; enum auto_boolean soft_float_flag = powerpc_soft_float_global; int soft_float; + enum powerpc_long_double_abi long_double_abi = POWERPC_LONG_DOUBLE_AUTO; enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global; enum powerpc_elf_abi elf_abi = POWERPC_ELF_AUTO; int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0, @@ -6271,7 +6272,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) if (soft_float_flag == AUTO_BOOLEAN_AUTO && from_elf_exec) { switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU, - Tag_GNU_Power_ABI_FP)) + Tag_GNU_Power_ABI_FP) & 3) { case 1: soft_float_flag = AUTO_BOOLEAN_FALSE; @@ -6284,6 +6285,22 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) } } + if (long_double_abi == POWERPC_LONG_DOUBLE_AUTO && from_elf_exec) + { + switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU, + Tag_GNU_Power_ABI_FP) >> 2) + { + case 1: + long_double_abi = POWERPC_LONG_DOUBLE_IBM128; + break; + case 3: + long_double_abi = POWERPC_LONG_DOUBLE_IEEE128; + break; + default: + break; + } + } + if (vector_abi == POWERPC_VEC_AUTO && from_elf_exec) { switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU, @@ -6365,6 +6382,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) continue; if (tdep && tdep->soft_float != soft_float) continue; + if (tdep && tdep->long_double_abi != long_double_abi) + continue; if (tdep && tdep->vector_abi != vector_abi) continue; if (tdep && tdep->wordsize == wordsize) @@ -6387,6 +6406,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->wordsize = wordsize; tdep->elf_abi = elf_abi; tdep->soft_float = soft_float; + tdep->long_double_abi = long_double_abi; tdep->vector_abi = vector_abi; gdbarch = gdbarch_alloc (&info, tdep); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 16d2801984..74341059fe 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-11-21 Ulrich Weigand + + * gdb.arch/ppc-longdouble.exp: New file. + * gdb.arch/ppc-longdouble.c: Likewise. + 2017-11-21 Pedro Alves * gdb.ada/minsyms.exp: Accept any address for 'some_minsym'. diff --git a/gdb/testsuite/gdb.arch/ppc-longdouble.c b/gdb/testsuite/gdb.arch/ppc-longdouble.c new file mode 100644 index 0000000000..17296bf3c7 --- /dev/null +++ b/gdb/testsuite/gdb.arch/ppc-longdouble.c @@ -0,0 +1,38 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2017 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include +#include + +long double ld; +__float128 float128; +__ibm128 ibm128; + +/* FIXME: GCC will only emit a .gnu.attribute section specifying the + long double ABI if long double is used in a function prototype. */ +void test (long double x) +{ +} + +int main() +{ + ld = 1.375l; + float128 = 2.375l; + ibm128 = 3.375l; + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/ppc-longdouble.exp b/gdb/testsuite/gdb.arch/ppc-longdouble.exp new file mode 100644 index 0000000000..66c8f540f9 --- /dev/null +++ b/gdb/testsuite/gdb.arch/ppc-longdouble.exp @@ -0,0 +1,58 @@ +# Copyright 2016-2017 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +if ![istarget "powerpc*"] then { + verbose "Skipping powerpc long-double floating point tests." + return +} + +standard_testfile + +proc do_test { name {opts {}} } { + global srcdir subdir srcfile binfile + set ccopts {debug quiet} + foreach opt $opts {lappend ccopts "additional_flags=$opt"} + set lines [gdb_compile "${srcdir}/${subdir}/${srcfile}" "$binfile.$name" executable $ccopts] + # We get this warning even with the nowarnings option ... + regsub -all "(^|\n)\[^\n\]*using \[^\n\]* extended precision long double" $lines "" lines + if { $lines != "" } then { + return + } + + clean_restart ${binfile}.${name} + + if ![runto_main] then { + return + } + + # Run to the breakpoint at return. + gdb_breakpoint [gdb_get_line_number "return"] + gdb_continue_to_breakpoint "return" + + # Print the value of ld + gdb_test "print ld" ".* = 1\\.375.*" "the value of ld is 1.375 ($name)" + # Print the value of float128 + gdb_test "print float128" ".* = 2\\.375.*" "the value of float128 is 2.375 ($name)" + # Print the value of ibm128 + gdb_test "print ibm128" ".* = 3\\.375.*" "the value of ibm128 is 3.375 ($name)" +} + +# Verify that we correctly detect the floating-point format used for +# long double. Re-run the test with -mabi=ieeelongdouble and mabi=ibmlongdouble + +do_test default { -mfloat128 } +do_test ieee128 { -mfloat128 -mabi=ieeelongdouble } +do_test ibm128 { -mfloat128 -mabi=ibmlongdouble } +