diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 736051cab1f64d9e470c838b28cf895e93ea55c9..cd1108354622f920d6970e69b09d8f95e9cda953 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+2011-01-18  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+	* doc/extend.texi: Mention __float128 support on hppa HP-UX.
+	* config/pa/pa-hpux.h (HPUX_LONG_DOUBLE_LIBRARY): Define to 1.
+	* config/pa/pa.c (pa_expand_builtin): New.  Include "langhooks.h".
+	(pa_c_mode_for_suffix): New.
+	(TARGET_EXPAND_BUILTIN): Define.
+	(TARGET_C_MODE_FOR_SUFFIX): Define.
+	(pa_builtins): Define.
+	(pa_init_builtins): Register __float128 type and init new support
+	builtins.
+	* config/pa/pa.h (HPUX_LONG_DOUBLE_LIBRARY): Define if not defined.
+	* config/pa/quadlib.c (_U_Qfcopysign): New.
+
 2011-01-18  Eric Botcazou  <ebotcazou@adacore.com>
 
 	PR middle-end/46894
diff --git a/gcc/config/pa/pa-hpux.h b/gcc/config/pa/pa-hpux.h
index 69a9d1905f7bbb3f335ad8005ebb538d02ec02e0..f167e133eb58f20ac6beab187e098c8da6afa7fa 100644
--- a/gcc/config/pa/pa-hpux.h
+++ b/gcc/config/pa/pa-hpux.h
@@ -22,6 +22,9 @@ along with GCC; see the file COPYING3.  If not see
 #undef TARGET_HPUX
 #define TARGET_HPUX 1
 
+#undef HPUX_LONG_DOUBLE_LIBRARY
+#define HPUX_LONG_DOUBLE_LIBRARY 1
+
 #undef TARGET_DEFAULT
 #define TARGET_DEFAULT MASK_BIG_SWITCH
 
@@ -33,7 +36,6 @@ along with GCC; see the file COPYING3.  If not see
 #define PTRDIFF_TYPE "int"
 
 #define LONG_DOUBLE_TYPE_SIZE 128
-#define HPUX_LONG_DOUBLE_LIBRARY
 #define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) ((MODE) == TFmode)
 
 /* GCC always defines __STDC__.  HP C++ compilers don't define it.  This
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 89f7e500820781bb30310bd289b57379ecc11413..98267b0ca63e9a817e76f24d4c1c38580d3a41e2 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm_p.h"
 #include "target.h"
 #include "target-def.h"
+#include "langhooks.h"
 #include "df.h"
 
 /* Return nonzero if there is a bypass for the output of 
@@ -129,6 +130,7 @@ static void pa_asm_out_constructor (rtx, int);
 static void pa_asm_out_destructor (rtx, int);
 #endif
 static void pa_init_builtins (void);
+static rtx pa_expand_builtin (tree, rtx, rtx, enum machine_mode mode, int);
 static rtx hppa_builtin_saveregs (void);
 static void hppa_va_start (tree, rtx);
 static tree hppa_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
@@ -151,7 +153,7 @@ static void output_deferred_profile_counters (void) ATTRIBUTE_UNUSED;
 #ifdef ASM_OUTPUT_EXTERNAL_REAL
 static void pa_hpux_file_end (void);
 #endif
-#ifdef HPUX_LONG_DOUBLE_LIBRARY
+#if HPUX_LONG_DOUBLE_LIBRARY
 static void pa_hpux_init_libfuncs (void);
 #endif
 static rtx pa_struct_value_rtx (tree, int);
@@ -181,6 +183,7 @@ static bool pa_print_operand_punct_valid_p (unsigned char);
 static rtx pa_internal_arg_pointer (void);
 static bool pa_can_eliminate (const int, const int);
 static void pa_conditional_register_usage (void);
+static enum machine_mode pa_c_mode_for_suffix (char);
 static section *pa_function_section (tree, enum node_frequency, bool, bool);
 
 /* The following extra sections are only used for SOM.  */
@@ -317,6 +320,9 @@ static const struct default_options pa_option_optimization_table[] =
 #undef TARGET_INIT_BUILTINS
 #define TARGET_INIT_BUILTINS pa_init_builtins
 
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN pa_expand_builtin
+
 #undef TARGET_REGISTER_MOVE_COST
 #define TARGET_REGISTER_MOVE_COST hppa_register_move_cost
 #undef TARGET_RTX_COSTS
@@ -327,7 +333,7 @@ static const struct default_options pa_option_optimization_table[] =
 #undef TARGET_MACHINE_DEPENDENT_REORG
 #define TARGET_MACHINE_DEPENDENT_REORG pa_reorg
 
-#ifdef HPUX_LONG_DOUBLE_LIBRARY
+#if HPUX_LONG_DOUBLE_LIBRARY
 #undef TARGET_INIT_LIBFUNCS
 #define TARGET_INIT_LIBFUNCS pa_hpux_init_libfuncs
 #endif
@@ -389,6 +395,8 @@ static const struct default_options pa_option_optimization_table[] =
 #define TARGET_CAN_ELIMINATE pa_can_eliminate
 #undef TARGET_CONDITIONAL_REGISTER_USAGE
 #define TARGET_CONDITIONAL_REGISTER_USAGE pa_conditional_register_usage
+#undef TARGET_C_MODE_FOR_SUFFIX
+#define TARGET_C_MODE_FOR_SUFFIX pa_c_mode_for_suffix
 #undef TARGET_ASM_FUNCTION_SECTION
 #define TARGET_ASM_FUNCTION_SECTION pa_function_section
 
@@ -598,6 +606,17 @@ pa_option_override (void)
   init_machine_status = pa_init_machine_status;
 }
 
+enum pa_builtins
+{
+  PA_BUILTIN_COPYSIGNQ,
+  PA_BUILTIN_FABSQ,
+  PA_BUILTIN_INFQ,
+  PA_BUILTIN_HUGE_VALQ,
+  PA_BUILTIN_max
+};
+
+static GTY(()) tree pa_builtins[(int) PA_BUILTIN_max];
+
 static void
 pa_init_builtins (void)
 {
@@ -613,6 +632,86 @@ pa_init_builtins (void)
   if (built_in_decls [BUILT_IN_FINITEF])
     set_user_assembler_name (built_in_decls [BUILT_IN_FINITEF], "_Isfinitef");
 #endif
+
+  if (HPUX_LONG_DOUBLE_LIBRARY)
+    {
+      tree decl, ftype;
+
+      /* Under HPUX, the __float128 type is a synonym for "long double".  */
+      (*lang_hooks.types.register_builtin_type) (long_double_type_node,
+						 "__float128");
+
+      /* TFmode support builtins.  */
+      ftype = build_function_type_list (long_double_type_node,
+					long_double_type_node,
+					NULL_TREE);
+      decl = add_builtin_function ("__builtin_fabsq", ftype,
+				   PA_BUILTIN_FABSQ, BUILT_IN_MD,
+				   "_U_Qfabs", NULL_TREE);
+      TREE_READONLY (decl) = 1;
+      pa_builtins[PA_BUILTIN_FABSQ] = decl;
+
+      ftype = build_function_type_list (long_double_type_node,
+					long_double_type_node,
+					long_double_type_node,
+					NULL_TREE);
+      decl = add_builtin_function ("__builtin_copysignq", ftype,
+				   PA_BUILTIN_COPYSIGNQ, BUILT_IN_MD,
+				   "_U_Qfcopysign", NULL_TREE);
+      TREE_READONLY (decl) = 1;
+      pa_builtins[PA_BUILTIN_COPYSIGNQ] = decl;
+
+      ftype = build_function_type (long_double_type_node, void_list_node);
+      decl = add_builtin_function ("__builtin_infq", ftype,
+				   PA_BUILTIN_INFQ, BUILT_IN_MD,
+				   NULL, NULL_TREE);
+      pa_builtins[PA_BUILTIN_INFQ] = decl;
+
+      decl = add_builtin_function ("__builtin_huge_valq", ftype,
+                                   PA_BUILTIN_HUGE_VALQ, BUILT_IN_MD,
+                                   NULL, NULL_TREE);
+      pa_builtins[PA_BUILTIN_HUGE_VALQ] = decl;
+    }
+}
+
+static rtx
+pa_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
+		   enum machine_mode mode ATTRIBUTE_UNUSED,
+		   int ignore ATTRIBUTE_UNUSED)
+{
+  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+
+  switch (fcode)
+    {
+    case PA_BUILTIN_FABSQ:
+    case PA_BUILTIN_COPYSIGNQ:
+      return expand_call (exp, target, ignore);
+
+    case PA_BUILTIN_INFQ:
+    case PA_BUILTIN_HUGE_VALQ:
+      {
+	enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
+	REAL_VALUE_TYPE inf;
+	rtx tmp;
+
+	real_inf (&inf);
+	tmp = CONST_DOUBLE_FROM_REAL_VALUE (inf, target_mode);
+
+	tmp = validize_mem (force_const_mem (target_mode, tmp));
+
+	if (target == 0)
+	  target = gen_reg_rtx (target_mode);
+
+	emit_move_insn (target, tmp);
+	return target;
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+
+  return NULL_RTX;
 }
 
 /* Function to init struct machine_function.
@@ -5522,7 +5621,7 @@ output_deferred_plabels (void)
     }
 }
 
-#ifdef HPUX_LONG_DOUBLE_LIBRARY
+#if HPUX_LONG_DOUBLE_LIBRARY
 /* Initialize optabs to point to HPUX long double emulation routines.  */
 static void
 pa_hpux_init_libfuncs (void)
@@ -10243,6 +10342,20 @@ pa_conditional_register_usage (void)
     fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
 }
 
+/* Target hook for c_mode_for_suffix.  */
+
+static enum machine_mode
+pa_c_mode_for_suffix (char suffix)
+{
+  if (HPUX_LONG_DOUBLE_LIBRARY)
+    {
+      if (suffix == 'q')
+	return TFmode;
+    }
+
+  return VOIDmode;
+}
+
 /* Target hook for function_section.  */
 
 static section *
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index 0a0250ff3b9f40fec19a907f9f8afeb9ee59088f..41af1f12f6edff21c8d116c4342e2fcfc54356d1 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -86,6 +86,11 @@ extern int flag_pa_unix;
 #define TARGET_HPUX_11_11 0
 #endif
 
+/* HP-UX long double library.  */
+#ifndef HPUX_LONG_DOUBLE_LIBRARY
+#define HPUX_LONG_DOUBLE_LIBRARY 0
+#endif
+
 /* The following three defines are potential target switches.  The current
    defines are optimal given the current capabilities of GAS and GNU ld.  */
 
diff --git a/gcc/config/pa/quadlib.c b/gcc/config/pa/quadlib.c
index 06c2292b869c8cc0896f2f7125291b9b2e5201c6..2c1160015edeb29c8845c5aab3a8f76fe2d5085e 100644
--- a/gcc/config/pa/quadlib.c
+++ b/gcc/config/pa/quadlib.c
@@ -58,6 +58,7 @@ int _U_Qford (long double, long double);
 int _U_Qfcomp (long double, long double);
 
 long double _U_Qfneg (long double);
+long double _U_Qfcopysign (long double, long double);
 
 #ifdef __LP64__
 int __U_Qfcnvfxt_quad_to_sgl (long double);
@@ -160,7 +161,6 @@ _U_Qfcomp (long double a, long double b)
   return (_U_Qfcmp (a, b, QCMP_UNORD | QCMP_EQ | QCMP_GT) != 0 ? 1 : -1);
 }
 
-
 /* Negate long double A.  */
 long double
 _U_Qfneg (long double a)
@@ -176,6 +176,23 @@ _U_Qfneg (long double a)
   return u.ld;
 }
 
+/* Return long double A with sign changed to sign of long double B.  */
+long double
+_U_Qfcopysign (long double a, long double b)
+{
+  union
+   {
+     long double ld;
+     int i[4];
+   } ua, ub;
+
+  ua.ld = a;
+  ub.ld = b;
+  ua.i[0] &= 0x7fffffff;
+  ua.i[0] |= (0x80000000 & ub.i[0]);
+  return ua.ld;
+}
+
 #ifdef __LP64__
 /* This routine is only necessary for the PA64 port; for reasons unknown
    _U_Qfcnvfxt_quad_to_sgl returns the integer in the high 32bits of the
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 958541b1ee4c6196fc4ca1f16739677b6e7195ea..ab65fd6848e6a19d933e236e1aecc2b074f779b1 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -934,6 +934,7 @@ typedef _Complex float __attribute__((mode(XC))) _Complex80;
 
 Not all targets support additional floating point types.  @code{__float80}
 and @code{__float128} types are supported on i386, x86_64 and ia64 targets.
+The @code{__float128} type is supported on hppa HP-UX targets.
 
 @node Half-Precision
 @section Half-Precision Floating Point