Index: gcc/config/rs6000/rs6000-modes.def
===================================================================
--- gcc/config/rs6000/rs6000-modes.def	(revision 223458)
+++ gcc/config/rs6000/rs6000-modes.def	(working copy)
@@ -18,6 +18,13 @@
    along with GCC; see the file COPYING3.  If not see
    <http://www.gnu.org/licenses/>.  */
 
+/* IBM 128-bit floating point.  IFmode and KFmode use the fractional float
+   support in order to declare 3 128-bit floating point types.  */
+FRACTIONAL_FLOAT_MODE (IF, 106, 16, ibm_extended_format);
+
+/* Explicit IEEE 128-bit floating point.  */
+FRACTIONAL_FLOAT_MODE (KF, 113, 16, ieee_quad_format);
+
 /* 128-bit floating point.  ABI_V4 uses IEEE quad, AIX/Darwin
    adjust this in rs6000_option_override_internal.  */
 FLOAT_MODE (TF, 16, ieee_quad_format);
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(revision 223458)
+++ gcc/config/rs6000/rs6000.opt	(working copy)
@@ -600,3 +600,19 @@ Allow float/double variables in upper re
 moptimize-swaps
 Target Undocumented Var(rs6000_optimize_swaps) Init(1) Save
 Analyze and remove doubleword swaps from VSX computations.
+
+mfloat128-
+Target RejectNegative Joined Enum(float128_type_t) Var(TARGET_FLOAT128) Init(FLOAT128_UNSET) Save
+-mfloat128-{software,none} - Specify how IEEE 128-bit floating point is used.
+
+Enum
+Name(float128_type_t) Type(enum float128_type_t)
+
+EnumValue
+Enum(float128_type_t) String(none) Value(FLOAT128_NONE)
+
+EnumValue
+Enum(float128_type_t) String(software) Value(FLOAT128_SW)
+
+EnumValue
+Enum(float128_type_t) String(sw) Value(FLOAT128_SW)
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 223458)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1817,6 +1817,16 @@ rs6000_hard_regno_mode_ok (int regno, ma
 	    && IN_RANGE (last_regno, FIRST_GPR_REGNO, LAST_GPR_REGNO)
 	    && ((regno & 1) == 0));
 
+  /* If we don't allow 128-bit binary floating point, disallow the 128-bit
+     types from going in any registers.  Similarly if __float128 is not
+     supported, don't allow __float128/__ibm128 types.  */
+  if (!TARGET_LONG_DOUBLE_128
+      && (mode == TFmode || mode == KFmode || mode == IFmode))
+    return false;
+
+  if (!TARGET_FLOAT128 && (mode == KFmode || mode == IFmode))
+    return false;
+
   /* VSX registers that overlap the FPR registers are larger than for non-VSX
      implementations.  Don't allow an item to be split between a FP register
      and an Altivec register.  Allow TImode in all VSX registers if the user
@@ -2086,6 +2096,7 @@ rs6000_debug_reg_global (void)
   const char *trace_str;
   const char *abi_str;
   const char *cmodel_str;
+  const char *float128_str;
   struct cl_target_option cl_opts;
 
   /* Modes we want tieable information on.  */
@@ -2099,6 +2110,8 @@ rs6000_debug_reg_global (void)
     SFmode,
     DFmode,
     TFmode,
+    IFmode,
+    KFmode,
     SDmode,
     DDmode,
     TDmode,
@@ -2445,6 +2458,15 @@ rs6000_debug_reg_global (void)
   fprintf (stderr, DEBUG_FMT_S, "e500_double",
 	   (TARGET_E500_DOUBLE ? "true" : "false"));
 
+  switch (TARGET_FLOAT128)
+    {
+    case FLOAT128_NONE:	float128_str = "none";		break;
+    case FLOAT128_SW:	float128_str = "software";	break;
+    default:		float128_str = "unknown";	break;
+    }
+
+  fprintf (stderr, DEBUG_FMT_S, "float128", float128_str);
+
   if (TARGET_LINK_STACK)
     fprintf (stderr, DEBUG_FMT_S, "link_stack", "true");
 
@@ -3703,6 +3725,13 @@ rs6000_option_override_internal (bool gl
       && optimize >= 3)
     rs6000_isa_flags |= OPTION_MASK_P8_FUSION_SIGN;
 
+  /* Set the appropriate IEEE 128-bit floating option.  Do not enable float128
+     support by default until the libgcc support is added.  */
+  if (TARGET_FLOAT128 == FLOAT128_UNSET)
+    TARGET_FLOAT128 = FLOAT128_NONE;
+  else if (TARGET_FLOAT128 == FLOAT128_SW && !TARGET_VSX)
+    error ("-mfloat128-software requires VSX support");
+
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
     rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags);
 
@@ -14320,6 +14349,8 @@ rs6000_init_builtins (void)
   tree tdecl;
   tree ftype;
   machine_mode mode;
+  machine_mode ieee128_mode;
+  machine_mode ibm128_mode;
 
   if (TARGET_DEBUG_BUILTIN)
     fprintf (stderr, "rs6000_init_builtins%s%s%s%s\n",
@@ -14387,6 +14418,32 @@ rs6000_init_builtins (void)
   dfloat128_type_internal_node = dfloat128_type_node;
   void_type_internal_node = void_type_node;
 
+  /* 128-bit floating point support.  KFmode is IEEE 128-bit floating point.
+     IFmode is the IBM extended 128-bit format that is a pair of doubles.
+     TFmode will be either IEEE 128-bit floating point or the IBM double-double
+     format that uses a pair of doubles, depending on the switches and
+     defaults.  */
+  if (TARGET_IEEEQUAD)
+    {
+      ieee128_mode = TFmode;
+      ibm128_mode = IFmode;
+    }
+  else
+    {
+      ieee128_mode = KFmode;
+      ibm128_mode = TFmode;
+    }
+
+  ieee128_float_type_node = make_node (REAL_TYPE);
+  TYPE_PRECISION (ieee128_float_type_node) = 128;
+  layout_type (ieee128_float_type_node);
+  SET_TYPE_MODE (ieee128_float_type_node, ieee128_mode);
+
+  ibm128_float_type_node = make_node (REAL_TYPE);
+  TYPE_PRECISION (ibm128_float_type_node) = 128;
+  layout_type (ibm128_float_type_node);
+  SET_TYPE_MODE (ibm128_float_type_node, ibm128_mode);
+
   /* Initialize the modes for builtin_function_type, mapping a machine mode to
      tree type node.  */
   builtin_mode_to_type[QImode][0] = integer_type_node;
@@ -14399,6 +14456,8 @@ rs6000_init_builtins (void)
   builtin_mode_to_type[TImode][1] = unsigned_intTI_type_node;
   builtin_mode_to_type[SFmode][0] = float_type_node;
   builtin_mode_to_type[DFmode][0] = double_type_node;
+  builtin_mode_to_type[IFmode][0] = ibm128_float_type_node;
+  builtin_mode_to_type[KFmode][0] = ieee128_float_type_node;
   builtin_mode_to_type[TFmode][0] = long_double_type_node;
   builtin_mode_to_type[DDmode][0] = dfloat64_type_node;
   builtin_mode_to_type[TDmode][0] = dfloat128_type_node;
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 223458)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -2715,6 +2715,8 @@ enum rs6000_builtin_type_index
   RS6000_BTI_dfloat64,		 /* dfloat64_type_node */
   RS6000_BTI_dfloat128,		 /* dfloat128_type_node */
   RS6000_BTI_void,	         /* void_type_node */
+  RS6000_BTI_ieee128_float,	 /* ieee 128-bit floating point */
+  RS6000_BTI_ibm128_float,	 /* IBM 128-bit floating point */
   RS6000_BTI_MAX
 };
 
@@ -2769,6 +2771,8 @@ enum rs6000_builtin_type_index
 #define dfloat64_type_internal_node	 (rs6000_builtin_types[RS6000_BTI_dfloat64])
 #define dfloat128_type_internal_node	 (rs6000_builtin_types[RS6000_BTI_dfloat128])
 #define void_type_internal_node		 (rs6000_builtin_types[RS6000_BTI_void])
+#define ieee128_float_type_node		 (rs6000_builtin_types[RS6000_BTI_ieee128_float])
+#define ibm128_float_type_node		 (rs6000_builtin_types[RS6000_BTI_ibm128_float])
 
 extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
 extern GTY(()) tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
Index: gcc/config/rs6000/rs6000-opts.h
===================================================================
--- gcc/config/rs6000/rs6000-opts.h	(revision 223458)
+++ gcc/config/rs6000/rs6000-opts.h	(working copy)
@@ -79,6 +79,15 @@ enum fpu_type_t
   FPU_DF_FULL			/* Full Double Single Precision FPU */
 };
 
+
+/* Float128 support.  */
+enum float128_type_t
+{
+  FLOAT128_UNSET	= -1,	/* Initial value.  */
+  FLOAT128_NONE,		/* No __float128 support.  */
+  FLOAT128_SW			/* software __float128 support.  */
+};
+
 /* Types of costly dependences.  */
 enum rs6000_dependence_cost
 {
