diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index ee80a71..0e43a64 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 4ae5c7f..3d1e327 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 6c44995..456dbcc 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/gdb.arch/ppc-longdouble.c b/gdb/testsuite/gdb.arch/ppc-longdouble.c
new file mode 100644
index 0000000..17296bf
--- /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 <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+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 0000000..66c8f54
--- /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 <http://www.gnu.org/licenses/>.
+
+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 }
+
