diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index d00e0ba..edd64ff 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -409,6 +409,9 @@ ix86_target_macros (void)
       builtin_define_std ("i386");
     }
 
+  if (TARGET_LONG_DOUBLE_64)
+    cpp_define (parse_in, "__LONG_DOUBLE_64__");
+
   cpp_define_formatted (parse_in, "__ATOMIC_HLE_ACQUIRE=%d", IX86_HLE_ACQUIRE);
   cpp_define_formatted (parse_in, "__ATOMIC_HLE_RELEASE=%d", IX86_HLE_RELEASE);
 
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index a6fc45b..da931ee 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2786,6 +2786,7 @@ ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch,
   static struct ix86_target_opts flag_opts[] =
   {
     { "-m128bit-long-double",		MASK_128BIT_LONG_DOUBLE },
+    { "-mlong-double-64",		MASK_LONG_DOUBLE_64 },
     { "-m80387",			MASK_80387 },
     { "-maccumulate-outgoing-args",	MASK_ACCUMULATE_OUTGOING_ARGS },
     { "-malign-double",			MASK_ALIGN_DOUBLE },
@@ -4084,6 +4085,11 @@ ix86_option_override_internal (bool main_args_p)
   else if (target_flags_explicit & MASK_RECIP)
     recip_mask &= ~(RECIP_MASK_ALL & ~recip_mask_explicit);
 
+  /* Default long double to 64-bit for Bionic.  */
+  if (TARGET_HAS_BIONIC
+      && !(target_flags_explicit & MASK_LONG_DOUBLE_64))
+    target_flags |= MASK_LONG_DOUBLE_64;
+
   /* Save the initial options in case the user does function specific
      options.  */
   if (main_args_p)
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 11f79e3..3a41a43 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -671,9 +671,17 @@ enum target_cpu_default
 #define LONG_LONG_TYPE_SIZE 64
 #define FLOAT_TYPE_SIZE 32
 #define DOUBLE_TYPE_SIZE 64
-#define LONG_DOUBLE_TYPE_SIZE 80
+#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_64 ? 64 : 80)
 
-#define WIDEST_HARDWARE_FP_SIZE LONG_DOUBLE_TYPE_SIZE
+/* Define this to set long double type size to use in libgcc2.c, which can
+   not depend on target_flags.  */
+#ifdef __LONG_DOUBLE_64__
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
+#else
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 80
+#endif
+
+#define WIDEST_HARDWARE_FP_SIZE 80
 
 #if defined (TARGET_BI_ARCH) || TARGET_64BIT_DEFAULT
 #define MAX_BITS_PER_WORD 64
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index e4f78f3..6a38994 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -86,6 +86,14 @@ m96bit-long-double
 Target RejectNegative Report InverseMask(128BIT_LONG_DOUBLE) Save
 sizeof(long double) is 12
 
+mlong-double-80
+Target Report RejectNegative InverseMask(LONG_DOUBLE_64) Save
+Use 80-bit long double
+
+mlong-double-64
+Target Report RejectNegative Mask(LONG_DOUBLE_64) Save
+Use 64-bit long double
+
 maccumulate-outgoing-args
 Target Report Mask(ACCUMULATE_OUTGOING_ARGS) Save
 Reserve space for outgoing arguments in the function prologue
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ae22ca9..0957979 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -636,7 +636,8 @@ Objective-C and Objective-C++ Dialects}.
 -mno-align-stringops  -minline-all-stringops @gol
 -minline-stringops-dynamically -mstringop-strategy=@var{alg} @gol
 -mpush-args  -maccumulate-outgoing-args  -m128bit-long-double @gol
--m96bit-long-double  -mregparm=@var{num}  -msseregparm @gol
+-m96bit-long-double -mlong-double-64 -mlong-double-80 @gol
+-mregparm=@var{num}  -msseregparm @gol
 -mveclibabi=@var{type} -mvect8-ret-in-mem @gol
 -mpc32 -mpc64 -mpc80 -mstackrealign @gol
 -momit-leaf-frame-pointer  -mno-red-zone -mno-tls-direct-seg-refs @gol
@@ -13509,6 +13510,21 @@ as well as modifying the function calling convention for functions taking
 @code{long double}.  Hence they are not binary-compatible
 with code compiled without that switch.
 
+@item -mlong-double-64
+@itemx -mlong-double-80
+@opindex mlong-double-64
+@opindex mlong-double-80
+These switches control the size of @code{long double} type. A size
+of 64 bits makes the @code{long double} type equivalent to the @code{double}
+type. This is the default for Bionic C library.
+
+@strong{Warning:} if you override the default value for your target ABI, this
+changes the size of
+structures and arrays containing @code{long double} variables,
+as well as modifying the function calling convention for functions taking
+@code{long double}.  Hence they are not binary-compatible
+with code compiled without that switch.
+
 @item -mlarge-data-threshold=@var{threshold}
 @opindex mlarge-data-threshold
 When @option{-mcmodel=medium} is specified, data objects larger than
diff --git a/gcc/testsuite/gcc.target/i386/long-double-64-1.c b/gcc/testsuite/gcc.target/i386/long-double-64-1.c
new file mode 100644
index 0000000..cf93379
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/long-double-64-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlong-double-64" } */
+
+long double
+foo (long double x)
+{
+  return x * x;
+}
+
+/* { dg-final { scan-assembler-not "fldt" } } */
diff --git a/gcc/testsuite/gcc.target/i386/long-double-64-2.c b/gcc/testsuite/gcc.target/i386/long-double-64-2.c
new file mode 100644
index 0000000..ddf4fe6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/long-double-64-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mbionic" } */
+
+long double
+foo (long double x)
+{
+  return x * x;
+}
+
+/* { dg-final { scan-assembler-not "fldt" } } */
diff --git a/gcc/testsuite/gcc.target/i386/long-double-64-3.c b/gcc/testsuite/gcc.target/i386/long-double-64-3.c
new file mode 100644
index 0000000..e748fab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/long-double-64-3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mandroid" } */
+
+long double
+foo (long double x)
+{
+  return x * x;
+}
+
+/* { dg-final { scan-assembler-not "fldt" } } */
diff --git a/gcc/testsuite/gcc.target/i386/long-double-64-4.c b/gcc/testsuite/gcc.target/i386/long-double-64-4.c
new file mode 100644
index 0000000..d9c25aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/long-double-64-4.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlong-double-80 -mlong-double-64" } */
+
+long double
+foo (long double x)
+{
+  return x * x;
+}
+
+/* { dg-final { scan-assembler-not "fldt" } } */
diff --git a/gcc/testsuite/gcc.target/i386/long-double-80-1.c b/gcc/testsuite/gcc.target/i386/long-double-80-1.c
new file mode 100644
index 0000000..d3b75a0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/long-double-80-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlong-double-80" } */
+
+long double
+foo (long double x)
+{
+  return x * x;
+}
+
+/* { dg-final { scan-assembler "fldt" } } */
diff --git a/gcc/testsuite/gcc.target/i386/long-double-80-2.c b/gcc/testsuite/gcc.target/i386/long-double-80-2.c
new file mode 100644
index 0000000..954dfd1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/long-double-80-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mlong-double-80 -mbionic" } */
+
+long double
+foo (long double x)
+{
+  return x * x;
+}
+
+/* { dg-final { scan-assembler "fldt" } } */
diff --git a/gcc/testsuite/gcc.target/i386/long-double-80-3.c b/gcc/testsuite/gcc.target/i386/long-double-80-3.c
new file mode 100644
index 0000000..e0e8365
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/long-double-80-3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mlong-double-80 -mandroid" } */
+
+long double
+foo (long double x)
+{
+  return x * x;
+}
+
+/* { dg-final { scan-assembler "fldt" } } */
diff --git a/gcc/testsuite/gcc.target/i386/long-double-80-4.c b/gcc/testsuite/gcc.target/i386/long-double-80-4.c
new file mode 100644
index 0000000..cac2d55
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/long-double-80-4.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlong-double-64 -mlong-double-80" } */
+
+long double
+foo (long double x)
+{
+  return x * x;
+}
+
+/* { dg-final { scan-assembler "fldt" } } */
diff --git a/gcc/testsuite/gcc.target/i386/long-double-80-5.c b/gcc/testsuite/gcc.target/i386/long-double-80-5.c
new file mode 100644
index 0000000..4aa606f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/long-double-80-5.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlong-double-64" } */
+
+__float80
+foo (__float80 x)
+{
+  return x * x;
+}
+
+/* { dg-final { scan-assembler "fldt" } } */
diff --git a/gcc/testsuite/gcc.target/i386/long-double-80-6.c b/gcc/testsuite/gcc.target/i386/long-double-80-6.c
new file mode 100644
index 0000000..a395a26
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/long-double-80-6.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-options "-O0 -mlong-double-64 -mfpmath=387" } */
+
+int
+main ()
+{
+  __float80 a = -0.23456789;
+  if ((double) a >= 0)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/long-double-80-7.c b/gcc/testsuite/gcc.target/i386/long-double-80-7.c
new file mode 100644
index 0000000..9b30fe8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/long-double-80-7.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-O0 -mlong-double-64 -mfpmath=sse" } */
+/* { dg-require-effective-target sse2 } */
+
+#include "sse2-check.h"
+
+static void
+sse2_test (void)
+{
+  __float80 a = -0.23456789;
+  if ((double) a >= 0)
+    __builtin_abort ();
+}
diff --git a/libgcc/config/i386/t-linux b/libgcc/config/i386/t-linux
index 29b4c22..4f47f7b 100644
--- a/libgcc/config/i386/t-linux
+++ b/libgcc/config/i386/t-linux
@@ -2,3 +2,5 @@
 # Need to support TImode for x86.  Override the settings from
 # t-slibgcc-elf-ver and t-linux
 SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/i386/libgcc-glibc.ver
+
+HOST_LIBGCC2_CFLAGS += -mlong-double-80
