2006-06-19 Pete Carr * rs6000-tdep.c (rs6000_gdbarch_init): Set the long double format for powerpc64. * configure.host : Set the host long double format for powerpc64 to be a 128-bit type defined in libiberty/floatformat.c. * gdbarch.sh (function_list): Use the default_long_double_format for the long double type. * ppc-linux-tdep.c (ppc_linux_init_abi): Remove code that sets long double size to 8 bytes. This breaks expression evaluation by overriding the default. * floatformat.c : Introduce default floatformat structs to describe the 128-bit long double found on the powerpc64. Description does not fully describe this format which is actually a pair of 64-bit doubles. However we are relying on floatformat_to_doublest() recognizing that this is also the default host floatformat. * floatformat.h : Default floatformat structs for powerpc64 128-bit long doubles. * powerpc64-ld128.c: Test program for 128-bit long doubles on powerpc64 * powerpc64-ld128.exp: Test program expect script for 128-bit long doubles on powerpc64 Index: gdb/configure.host =================================================================== RCS file: /cvs/src/src/gdb/configure.host,v retrieving revision 1.94 diff -a -u -p -r1.94 configure.host --- gdb/configure.host 10 Feb 2006 21:53:51 -0000 1.94 +++ gdb/configure.host 19 Jun 2006 21:32:07 -0000 @@ -179,6 +179,11 @@ m68*-*-*) gdb_host_double_format="&floatformat_ieee_double_big" gdb_host_long_double_format="&floatformat_m68881_ext" ;; +powerpc64-*-*-*) + gdb_host_float_format=0 + gdb_host_double_format=0 + gdb_host_long_double_format="&floatformat_ppc64_long_double_big" + ;; *) gdb_host_float_format=0 gdb_host_double_format=0 Index: gdb/gdbarch.sh =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.sh,v retrieving revision 1.364 diff -a -u -p -r1.364 gdbarch.sh --- gdb/gdbarch.sh 18 Apr 2006 19:20:06 -0000 1.364 +++ gdb/gdbarch.sh 19 Jun 2006 21:32:08 -0000 @@ -395,7 +395,7 @@ v:TARGET_FLOAT_FORMAT:const struct float v:TARGET_DOUBLE_BIT:int:double_bit:::8 * sizeof (double):8*TARGET_CHAR_BIT::0 v:TARGET_DOUBLE_FORMAT:const struct floatformat *:double_format:::::default_double_format (current_gdbarch)::pformat (current_gdbarch->double_format) v:TARGET_LONG_DOUBLE_BIT:int:long_double_bit:::8 * sizeof (long double):8*TARGET_CHAR_BIT::0 -v:TARGET_LONG_DOUBLE_FORMAT:const struct floatformat *:long_double_format:::::default_double_format (current_gdbarch)::pformat (current_gdbarch->long_double_format) +v:TARGET_LONG_DOUBLE_FORMAT:const struct floatformat *:long_double_format:::::default_long_double_format (current_gdbarch)::pformat (current_gdbarch->long_double_format) # For most targets, a pointer on the target and its representation as an # address in GDB have the same size and "look the same". For such a Index: gdb/ppc-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v retrieving revision 1.78 diff -a -u -p -r1.78 ppc-linux-tdep.c --- gdb/ppc-linux-tdep.c 18 Apr 2006 19:20:06 -0000 1.78 +++ gdb/ppc-linux-tdep.c 19 Jun 2006 21:32:08 -0000 @@ -1032,7 +1032,9 @@ ppc_linux_init_abi (struct gdbarch_info Linux[sic] Standards Base says that programs that use 'long double' on PPC GNU/Linux are non-conformant. */ /* NOTE: cagney/2005-01-25: True for both 32- and 64-bit. */ +#if 0 set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT); +#endif if (tdep->wordsize == 4) { Index: gdb/rs6000-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v retrieving revision 1.258 diff -a -u -p -r1.258 rs6000-tdep.c --- gdb/rs6000-tdep.c 23 Apr 2006 14:15:01 -0000 1.258 +++ gdb/rs6000-tdep.c 19 Jun 2006 21:32:08 -0000 @@ -3391,7 +3391,19 @@ rs6000_gdbarch_init (struct gdbarch_info set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT); set_gdbarch_double_bit (gdbarch, 8 * TARGET_CHAR_BIT); if (sysv_abi) - set_gdbarch_long_double_bit (gdbarch, 16 * TARGET_CHAR_BIT); + { + int byte_order = gdbarch_byte_order (gdbarch); + + if (byte_order == BFD_ENDIAN_BIG) + set_gdbarch_long_double_format (gdbarch, &floatformat_ppc64_long_double_big); + else if (byte_order == BFD_ENDIAN_LITTLE) + set_gdbarch_long_double_format (gdbarch, &floatformat_ppc64_long_double_little); + else + internal_error (__FILE__, __LINE__, + _("rs6000_gdbarch_init: " + "bad byte order")); + set_gdbarch_long_double_bit (gdbarch, 16 * TARGET_CHAR_BIT); + } else set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT); set_gdbarch_char_signed (gdbarch, 0); Index: include/floatformat.h =================================================================== RCS file: /cvs/src/src/include/floatformat.h,v retrieving revision 1.13 diff -a -u -p -r1.13 floatformat.h --- include/floatformat.h 31 Oct 2005 18:01:16 -0000 1.13 +++ include/floatformat.h 19 Jun 2006 21:32:09 -0000 @@ -118,6 +118,9 @@ extern const struct floatformat floatfor extern const struct floatformat floatformat_ia64_spill_little; extern const struct floatformat floatformat_ia64_quad_big; extern const struct floatformat floatformat_ia64_quad_little; +/* ppc64 long double implemented as 2 doubles */ +extern const struct floatformat floatformat_ppc64_long_double_big; +extern const struct floatformat floatformat_ppc64_long_double_little; /* Convert from FMT to a double. FROM is the address of the extended float. Index: libiberty/floatformat.c =================================================================== RCS file: /cvs/src/src/libiberty/floatformat.c,v retrieving revision 1.20 diff -a -u -p -r1.20 floatformat.c --- libiberty/floatformat.c 24 Apr 2006 21:34:41 -0000 1.20 +++ libiberty/floatformat.c 19 Jun 2006 21:32:09 -0000 @@ -106,6 +106,25 @@ const struct floatformat floatformat_iee floatformat_always_valid }; +/* floatformats for ppc64 long double, big and little endian. */ +/* The layout is a pair of doubles. Don't use this description to pass */ +/* information to get_field(). The bit size is the important thing. */ +const struct floatformat floatformat_ppc64_long_double_big = +{ + floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52, + floatformat_intbit_no, + "floatformat_ppc64_long_double_big", + floatformat_always_valid +}; + +const struct floatformat floatformat_ppc64_long_double_little = +{ + floatformat_little, 128, 0, 1, 11, 1023, 2047, 12, 52, + floatformat_intbit_no, + "floatformat_ppc64_long_double_little", + floatformat_always_valid +}; + /* floatformat for IEEE double, little endian byte order, with big endian word ordering, as on the ARM. */ Index: gdb/testsuite/gdb.arch/powerpc64-ld128.c =================================================================== /* This testcase is part of GDB, the GNU debugger. Copyright 2006 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include long double b1; long double b2; long double b3; long double b4; int main() { b1 = 1.2345678901234567890000000L; b2 = -1.2345678901234567890000000L; b3 = 123456789.0000000001234567890123456789L; b4 = -123456789.0000000001234567890123456789L; return 0; } Index: gdb/testsuite/gdb.arch/powerpc64-ld128.exp =================================================================== # Copyright 2006 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # This file is part of the gdb testsuite. if $tracelevel { strace $tracelevel } # Test powerpc64 128-bit long double support. set prms_id 0 set bug_id 0 if ![istarget "powerpc64-*"] then { verbose "Skipping powerpc64 128-bit long double tests." return } set testfile "powerpc64-ld128" set srcfile ${testfile}.c set binfile ${objdir}/${subdir}/${testfile} set compile_flags "debug" # "additional_flags=-mlong-double-64" if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable ${compile_flags}] != "" } { unsupported "Testcase compile failed." return -1 } gdb_exit gdb_start gdb_reinitialize_dir $srcdir/$subdir gdb_load ${binfile} if ![runto_main] then { perror "couldn't run to breakpoint" continue } # Run to the breakpoint at return. gdb_breakpoint [gdb_get_line_number "return"] gdb_continue_to_breakpoint "return" gdb_test_multiple "print sizeof(b1)" "" { -re ".*1 = 16." { pass "b1 should be 16 bytes long" } -re ".*1 = 8." { pass "b1 is 8 bytes long, test does not apply" return } } # Print the original value of b1, b2 and b3. gdb_test "print b1" ".*2 = 1\.2345678901234567890000000*.*" "The original value of b1 is 1.2345678901234567890000000 " gdb_test "print b2" ".*3 = -1\.2345678901234567890000000*.*" "The original value of b2 is -1.2345678901234567890000000" gdb_test "print b3" ".*4 = 123456789\.000000000123456789012345*.*" "The original value of b3 is 123456789.000000000123456789012345 " gdb_test "print b4" ".*5 = -123456789\.000000000123456789012345*.*" "The original value of b4 is -123456789.000000000123456789012345 " gdb_test "print sizeof(long double)" ".*6 = 16." "Long double should be 16 bytes long" # Try setting variable. gdb_test "set variable b1=1.11111111111111111111111111111111111L" gdb_test "print b1" ".*7 = 1\.11111111111111111111111111111111*.*" gdb_test "print *(long double *)&b1" ".*8 = 1\.11111111111111111111111111111111*.*" # Try some simple expressions gdb_test "set variable b1 = b1*2.0L" gdb_test "print b1" ".*9 = 2.22222222222222222222222222222222*.*" gdb_test "set variable b1 = b1/2.0L" gdb_test "print b1" ".*10 = 1\.11111111111111111111111111111111*.*" gdb_test "print *(long double *)&b1" ".*11 = 1\.11111111111111111111111111111111*.*" gdb_test "set variable b1 = b1*5.0" gdb_test "print b1" ".*12 = 5.5555555555555555555555555555555*.*" gdb_test "set variable b1 = b1/5.0" gdb_test "print b1" ".*13 = 1.11111111111111111111111111111111*.*" gdb_test "set variable b1 = 1.0e-31L" gdb_test "print b1" ".*14 = 1.000000000000000000000000000000*.*" gdb_test "set variable b1 = b1+1.0" gdb_test "print b1" ".*15 = 1.0000000000000000000000000000000*.*"