Index: gcc/gcc/config.gcc
===================================================================
--- gcc.orig/gcc/config.gcc
+++ gcc/gcc/config.gcc
@@ -3805,7 +3805,7 @@ case "${target}" in
 		;;
 
 	powerpc*-*-* | rs6000-*-*)
-		supported_defaults="cpu cpu_32 cpu_64 float tune tune_32 tune_64"
+		supported_defaults="abi cpu cpu_32 cpu_64 float tune tune_32 tune_64"
 
 		for which in cpu cpu_32 cpu_64 tune tune_32 tune_64; do
 			eval "val=\$with_$which"
@@ -3842,6 +3842,16 @@ case "${target}" in
 				;;
 			esac
 		done
+
+		case "$with_abi" in
+		"" | elfv1 | elfv2 )
+			#OK
+			;;
+		*)
+			echo "Unknown ABI used in --with-abi=$with_abi"
+			exit 1
+			;;
+		esac
 		;;
 
 	s390*-*-*)
Index: gcc/gcc/config/rs6000/option-defaults.h
===================================================================
--- gcc.orig/gcc/config/rs6000/option-defaults.h
+++ gcc/gcc/config/rs6000/option-defaults.h
@@ -54,6 +54,7 @@
    --with-float is ignored if -mhard-float or -msoft-float are
      specified.  */
 #define OPTION_DEFAULT_SPECS \
+  {"abi", "%{!mabi=elfv*:-mabi=%(VALUE)}" }, \
   {"tune", "%{!mtune=*:%{!mcpu=*:-mtune=%(VALUE)}}" }, \
   {"tune_32", "%{" OPT_ARCH32 ":%{!mtune=*:%{!mcpu=*:-mtune=%(VALUE)}}}" }, \
   {"tune_64", "%{" OPT_ARCH64 ":%{!mtune=*:%{!mcpu=*:-mtune=%(VALUE)}}}" }, \
Index: gcc/gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc.orig/gcc/config/rs6000/rs6000.opt
+++ gcc/gcc/config/rs6000/rs6000.opt
@@ -369,6 +369,14 @@ mabi=no-spe
 Target RejectNegative Var(rs6000_spe_abi, 0)
 Do not use the SPE ABI extensions
 
+mabi=elfv1
+Target RejectNegative Var(rs6000_elf_abi, 1) Save
+Use the ELFv1 ABI
+
+mabi=elfv2
+Target RejectNegative Var(rs6000_elf_abi, 2)
+Use the ELFv2 ABI
+
 ; These are here for testing during development only, do not document
 ; in the manual please.
 
Index: gcc/gcc/config/rs6000/rs6000-opts.h
===================================================================
--- gcc.orig/gcc/config/rs6000/rs6000-opts.h
+++ gcc/gcc/config/rs6000/rs6000-opts.h
@@ -107,7 +107,8 @@ enum group_termination
 /* Enumeration to give which calling sequence to use.  */
 enum rs6000_abi {
   ABI_NONE,
-  ABI_AIX,			/* IBM's AIX */
+  ABI_AIX,			/* IBM's AIX, or Linux ELFv1 */
+  ABI_ELFv2,			/* Linux ELFv2 ABI */
   ABI_V4,			/* System V.4/eabi */
   ABI_DARWIN			/* Apple's Darwin (OS X kernel) */
 };
Index: gcc/gcc/config/rs6000/linux64.h
===================================================================
--- gcc.orig/gcc/config/rs6000/linux64.h
+++ gcc/gcc/config/rs6000/linux64.h
@@ -25,9 +25,6 @@
 
 #ifndef RS6000_BI_ARCH
 
-#undef	DEFAULT_ABI
-#define	DEFAULT_ABI ABI_AIX
-
 #undef	TARGET_64BIT
 #define	TARGET_64BIT 1
 
@@ -88,6 +85,12 @@ extern int dot_symbols;
 #define INVALID_64BIT "-m%s not supported in this configuration"
 #define INVALID_32BIT INVALID_64BIT
 
+#ifdef LINUX64_DEFAULT_ABI_ELFv2
+#define ELFv2_ABI_CHECK (rs6000_elf_abi != 1)
+#else
+#define ELFv2_ABI_CHECK (rs6000_elf_abi == 2)
+#endif
+
 #undef	SUBSUBTARGET_OVERRIDE_OPTIONS
 #define	SUBSUBTARGET_OVERRIDE_OPTIONS				\
   do								\
@@ -102,6 +105,12 @@ extern int dot_symbols;
 	      error (INVALID_64BIT, "call");			\
 	    }							\
 	  dot_symbols = !strcmp (rs6000_abi_name, "aixdesc");	\
+	  if (ELFv2_ABI_CHECK)					\
+	    {							\
+	      rs6000_current_abi = ABI_ELFv2;			\
+	      if (dot_symbols)					\
+		error ("-mcall-aixdesc incompatible with -mabi=elfv2"); \
+	    }							\
 	  if (rs6000_isa_flags & OPTION_MASK_RELOCATABLE)	\
 	    {							\
 	      rs6000_isa_flags &= ~OPTION_MASK_RELOCATABLE;	\
@@ -355,7 +364,11 @@ extern int dot_symbols;
 #define LINK_OS_DEFAULT_SPEC "%(link_os_linux)"
 
 #define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1"
-#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld64.so.1"
+#ifdef LINUX64_DEFAULT_ABI_ELFv2
+#define GLIBC_DYNAMIC_LINKER64 "%{mabi=elfv1:/lib64/ld64.so.1;:/lib64/ld64.so.2}"
+#else
+#define GLIBC_DYNAMIC_LINKER64 "%{mabi=elfv2:/lib64/ld64.so.2;:/lib64/ld64.so.1}"
+#endif
 #define UCLIBC_DYNAMIC_LINKER32 "/lib/ld-uClibc.so.0"
 #define UCLIBC_DYNAMIC_LINKER64 "/lib/ld64-uClibc.so.0"
 #if DEFAULT_LIBC == LIBC_UCLIBC
Index: gcc/gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc.orig/gcc/config/rs6000/rs6000-c.c
+++ gcc/gcc/config/rs6000/rs6000-c.c
@@ -461,6 +461,10 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
     case ABI_AIX:
       builtin_define ("_CALL_AIXDESC");
       builtin_define ("_CALL_AIX");
+      builtin_define ("_CALL_ELF=1");
+      break;
+    case ABI_ELFv2:
+      builtin_define ("_CALL_ELF=2");
       break;
     case ABI_DARWIN:
       builtin_define ("_CALL_DARWIN");
@@ -473,6 +477,13 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
   if (TARGET_SOFT_FLOAT || !TARGET_FPRS)
     builtin_define ("__NO_FPRS__");
 
+  /* Whether aggregates passed by value are aligned to a 16 byte boundary
+     if their alignment is 16 bytes or larger.  */
+  if ((TARGET_MACHO && rs6000_darwin64_abi)
+      || DEFAULT_ABI == ABI_ELFv2
+      || (DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm))
+    builtin_define ("__STRUCT_PARM_ALIGN__=16");
+
   /* Generate defines for Xilinx FPU. */
   if (rs6000_xilinx_fpu) 
     {
Index: gcc/gcc/config/rs6000/rs6000.c
===================================================================
--- gcc.orig/gcc/config/rs6000/rs6000.c
+++ gcc/gcc/config/rs6000/rs6000.c
@@ -2231,6 +2231,7 @@ rs6000_debug_reg_global (void)
     {
     case ABI_NONE:	abi_str = "none";	break;
     case ABI_AIX:	abi_str = "aix";	break;
+    case ABI_ELFv2:	abi_str = "ELFv2";	break;
     case ABI_V4:	abi_str = "V4";		break;
     case ABI_DARWIN:	abi_str = "darwin";	break;
     default:		abi_str = "unknown";	break;
@@ -4761,7 +4762,8 @@ rs6000_file_start (void)
 	putc ('\n', file);
     }
 
-  if (DEFAULT_ABI == ABI_AIX || (TARGET_ELF && flag_pic == 2))
+  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2
+      || (TARGET_ELF && flag_pic == 2))
     {
       switch_to_section (toc_section);
       switch_to_section (text_section);
@@ -6971,10 +6973,13 @@ rs6000_legitimize_tls_address (rtx addr,
 				   1, const0_rtx, Pmode);
 
 	  r3 = gen_rtx_REG (Pmode, 3);
-	  if (DEFAULT_ABI == ABI_AIX && TARGET_64BIT)
-	    insn = gen_tls_gd_aix64 (r3, got, addr, tga, const0_rtx);
-	  else if (DEFAULT_ABI == ABI_AIX && !TARGET_64BIT)
-	    insn = gen_tls_gd_aix32 (r3, got, addr, tga, const0_rtx);
+	  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+	    {
+	      if (TARGET_64BIT)
+		insn = gen_tls_gd_aix64 (r3, got, addr, tga, const0_rtx);
+	      else
+		insn = gen_tls_gd_aix32 (r3, got, addr, tga, const0_rtx);
+	    }
 	  else if (DEFAULT_ABI == ABI_V4)
 	    insn = gen_tls_gd_sysvsi (r3, got, addr, tga, const0_rtx);
 	  else
@@ -6993,10 +6998,13 @@ rs6000_legitimize_tls_address (rtx addr,
 				   1, const0_rtx, Pmode);
 
 	  r3 = gen_rtx_REG (Pmode, 3);
-	  if (DEFAULT_ABI == ABI_AIX && TARGET_64BIT)
-	    insn = gen_tls_ld_aix64 (r3, got, tga, const0_rtx);
-	  else if (DEFAULT_ABI == ABI_AIX && !TARGET_64BIT)
-	    insn = gen_tls_ld_aix32 (r3, got, tga, const0_rtx);
+	  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+	    {
+	      if (TARGET_64BIT)
+		insn = gen_tls_ld_aix64 (r3, got, tga, const0_rtx);
+	      else
+		insn = gen_tls_ld_aix32 (r3, got, tga, const0_rtx);
+	    }
 	  else if (DEFAULT_ABI == ABI_V4)
 	    insn = gen_tls_ld_sysvsi (r3, got, tga, const0_rtx);
 	  else
@@ -7623,7 +7631,7 @@ rs6000_conditional_register_usage (void)
 
   /* The TOC register is not killed across calls in a way that is
      visible to the compiler.  */
-  if (DEFAULT_ABI == ABI_AIX)
+  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     call_really_used_regs[2] = 0;
 
   if (DEFAULT_ABI == ABI_V4
@@ -8274,7 +8282,7 @@ rs6000_emit_move (rtx dest, rtx source, 
 
 	  /* If this is a function address on -mcall-aixdesc,
 	     convert it to the address of the descriptor.  */
-	  if (DEFAULT_ABI == ABI_AIX
+	  if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
 	      && GET_CODE (operands[1]) == SYMBOL_REF
 	      && XSTR (operands[1], 0)[0] == '.')
 	    {
@@ -8665,7 +8673,7 @@ init_cumulative_args (CUMULATIVE_ARGS *c
 static bool
 rs6000_must_pass_in_stack (enum machine_mode mode, const_tree type)
 {
-  if (DEFAULT_ABI == ABI_AIX || TARGET_64BIT)
+  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2 || TARGET_64BIT)
     return must_pass_in_stack_var_size (mode, type);
   else
     return must_pass_in_stack_var_size_or_pad (mode, type);
@@ -8762,6 +8770,7 @@ rs6000_function_arg_boundary (enum machi
 	       && int_size_in_bytes (type) >= 16))
     return 128;
   else if (((TARGET_MACHO && rs6000_darwin64_abi)
+	    || DEFAULT_ABI == ABI_ELFv2
             || (DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm))
  	   && mode == BLKmode
 	   && type && TYPE_ALIGN (type) > 64)
@@ -9004,7 +9013,8 @@ rs6000_function_arg_advance_1 (CUMULATIV
 	  /* PowerPC64 Linux and AIX allocate GPRs for a vector argument
 	     even if it is going to be passed in a vector register.
 	     Darwin does the same for variable-argument functions.  */
-	  if ((DEFAULT_ABI == ABI_AIX && TARGET_64BIT)
+	  if (((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+	       && TARGET_64BIT)
 	      || (cum->stdarg && DEFAULT_ABI != ABI_V4))
 	    stack = true;
 	}
@@ -9787,7 +9797,7 @@ rs6000_function_arg (cumulative_args_t c
 	  /* Do we also need to pass this argument in the parameter
 	     save area?  */
 	  if (type && (cum->nargs_prototype <= 0
-		       || (DEFAULT_ABI == ABI_AIX
+		       || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
 			   && TARGET_XL_COMPAT
 			   && align_words >= GP_ARG_NUM_REG)))
 	    k = rs6000_psave_function_arg (mode, type, align_words, rvec);
@@ -9871,7 +9881,7 @@ rs6000_arg_partial_bytes (cumulative_arg
 	 PARALLEL including a memory element as necessary.  */
       if (type
 	  && (cum->nargs_prototype <= 0
-	      || (DEFAULT_ABI == ABI_AIX
+	      || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
 		  && TARGET_XL_COMPAT
 		  && align_words >= GP_ARG_NUM_REG)))
 	return 0;
@@ -10343,6 +10353,7 @@ rs6000_gimplify_va_arg (tree valist, tre
 
   if (((TARGET_MACHO
         && rs6000_darwin64_abi)
+       || DEFAULT_ABI == ABI_ELFv2
        || (DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm))
       && integer_zerop (TYPE_SIZE (type)))
     {
@@ -16667,6 +16678,7 @@ rs6000_output_function_entry (FILE *file
 	  gcc_unreachable ();
 
 	case ABI_AIX:
+	case ABI_ELFv2:
 	  if (DOT_SYMBOLS)
 	    putc ('.', file);
 	  else
@@ -17470,7 +17482,7 @@ rs6000_assemble_integer (rtx x, unsigned
 	 itself.  */
       else if (GET_CODE (x) == SYMBOL_REF
 	       && XSTR (x, 0)[0] == '.'
-	       && DEFAULT_ABI == ABI_AIX)
+	       && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2))
 	{
 	  const char *name = XSTR (x, 0);
 	  while (*name == '.')
@@ -19625,7 +19637,7 @@ rs6000_savres_strategy (rs6000_stack_t *
     }
   else
     {
-      gcc_checking_assert (DEFAULT_ABI == ABI_AIX);
+      gcc_checking_assert (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2);
       if (info->first_fp_reg_save > 61)
 	strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
       strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
@@ -19962,6 +19974,7 @@ rs6000_stack_info (void)
       gcc_unreachable ();
 
     case ABI_AIX:
+    case ABI_ELFv2:
     case ABI_DARWIN:
       info_ptr->fp_save_offset   = - info_ptr->fp_size;
       info_ptr->gp_save_offset   = info_ptr->fp_save_offset - info_ptr->gp_size;
@@ -20066,7 +20079,7 @@ rs6000_stack_info (void)
 
   /* Determine if we need to save the link register.  */
   if (info_ptr->calls_p
-      || (DEFAULT_ABI == ABI_AIX
+      || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
 	  && crtl->profile
 	  && !TARGET_PROFILE_KERNEL)
       || (DEFAULT_ABI == ABI_V4 && cfun->calls_alloca)
@@ -20212,6 +20225,7 @@ debug_stack_info (rs6000_stack_t *info)
     default:		 abi_string = "Unknown";	break;
     case ABI_NONE:	 abi_string = "NONE";		break;
     case ABI_AIX:	 abi_string = "AIX";		break;
+    case ABI_ELFv2:	 abi_string = "ELFv2";		break;
     case ABI_DARWIN:	 abi_string = "Darwin";		break;
     case ABI_V4:	 abi_string = "V.4";		break;
     }
@@ -20393,13 +20407,13 @@ rs6000_function_ok_for_sibcall (tree dec
 	return false;
     }
 
-  /* Under the AIX ABI we can't allow calls to non-local functions,
-     because the callee may have a different TOC pointer to the
-     caller and there's no way to ensure we restore the TOC when we
-     return.  With the secure-plt SYSV ABI we can't make non-local
+  /* Under the AIX or ELFv2 ABIs we can't allow calls to non-local
+     functions, because the callee may have a different TOC pointer to
+     the caller and there's no way to ensure we restore the TOC when
+     we return.  With the secure-plt SYSV ABI we can't make non-local
      calls when -fpic/PIC because the plt call stubs use r30.  */
   if (DEFAULT_ABI == ABI_DARWIN
-      || (DEFAULT_ABI == ABI_AIX
+      || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
 	  && decl
 	  && !DECL_EXTERNAL (decl)
 	  && (*targetm.binds_local_p) (decl))
@@ -20558,7 +20572,7 @@ rs6000_emit_load_toc_table (int fromprol
     }
   else
     {
-      gcc_assert (DEFAULT_ABI == ABI_AIX);
+      gcc_assert (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2);
 
       if (TARGET_32BIT)
 	emit_insn (gen_load_toc_aix_si (dest));
@@ -21277,7 +21291,7 @@ rs6000_savres_routine_name (rs6000_stack
       if ((sel & SAVRES_LR))
 	suffix = "_x";
     }
-  else if (DEFAULT_ABI == ABI_AIX)
+  else if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     {
 #if !defined (POWERPC_LINUX) && !defined (POWERPC_FREEBSD)
       /* No out-of-line save/restore routines for GPRs on AIX.  */
@@ -21418,7 +21432,7 @@ rs6000_emit_stack_reset (rs6000_stack_t 
 static inline unsigned
 ptr_regno_for_savres (int sel)
 {
-  if (DEFAULT_ABI == ABI_AIX)
+  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     return (sel & SAVRES_REG) == SAVRES_FPR || (sel & SAVRES_LR) ? 1 : 12;
   return DEFAULT_ABI == ABI_DARWIN && (sel & SAVRES_REG) == SAVRES_FPR ? 1 : 11;
 }
@@ -21785,7 +21799,7 @@ rs6000_emit_prologue (void)
 
   /* If we need to save CR, put it into r12 or r11.  Choose r12 except when
      r12 will be needed by out-of-line gpr restore.  */
-  cr_save_regno = (DEFAULT_ABI == ABI_AIX
+  cr_save_regno = ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
 		   && !(strategy & (SAVE_INLINE_GPRS
 				    | SAVE_NOINLINE_GPRS_SAVES_LR))
 		   ? 11 : 12);
@@ -22301,7 +22315,8 @@ rs6000_emit_prologue (void)
 	 be using r12 as frame_reg_rtx and r11 as the static chain
 	 pointer for nested functions.  */
       save_regno = 12;
-      if (DEFAULT_ABI == ABI_AIX && !using_static_chain_p)
+      if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+	  && !using_static_chain_p)
 	save_regno = 11;
       else if (REGNO (frame_reg_rtx) == 12)
 	{
@@ -23392,6 +23407,7 @@ rs6000_emit_epilogue (int sibcall)
       if (! restoring_FPRs_inline)
 	{
 	  int i;
+	  int reg;
 	  rtx sym;
 
 	  if (flag_shrink_wrap)
@@ -23400,10 +23416,9 @@ rs6000_emit_epilogue (int sibcall)
 	  sym = rs6000_savres_routine_sym (info,
 					   SAVRES_FPR | (lr ? SAVRES_LR : 0));
 	  RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode, sym);
-	  RTVEC_ELT (p, 3) = gen_rtx_USE (VOIDmode,
-					  gen_rtx_REG (Pmode,
-						       DEFAULT_ABI == ABI_AIX
-						       ? 1 : 11));
+	  reg = (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)? 1 : 11;
+	  RTVEC_ELT (p, 3) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, reg));
+
 	  for (i = 0; i < 64 - info->first_fp_reg_save; i++)
 	    {
 	      rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
@@ -23481,7 +23496,8 @@ rs6000_output_function_epilogue (FILE *f
 
      System V.4 Powerpc's (and the embedded ABI derived from it) use a
      different traceback table.  */
-  if (DEFAULT_ABI == ABI_AIX && ! flag_inhibit_size_directive
+  if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+      && ! flag_inhibit_size_directive
       && rs6000_traceback != traceback_none && !cfun->is_thunk)
     {
       const char *fname = NULL;
@@ -24484,7 +24500,7 @@ output_profile_hook (int labelno ATTRIBU
   if (TARGET_PROFILE_KERNEL)
     return;
 
-  if (DEFAULT_ABI == ABI_AIX)
+  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     {
 #ifndef NO_PROFILE_COUNTERS
 # define NO_PROFILE_COUNTERS 0
@@ -24628,6 +24644,7 @@ output_function_profiler (FILE *file, in
       break;
 
     case ABI_AIX:
+    case ABI_ELFv2:
     case ABI_DARWIN:
       if (!TARGET_PROFILE_KERNEL)
 	{
@@ -26583,6 +26600,7 @@ rs6000_trampoline_size (void)
       gcc_unreachable ();
 
     case ABI_AIX:
+    case ABI_ELFv2:
       ret = (TARGET_32BIT) ? 12 : 24;
       break;
 
@@ -26614,6 +26632,7 @@ rs6000_trampoline_init (rtx m_tramp, tre
 
     /* Under AIX, just build the 3 word function descriptor */
     case ABI_AIX:
+    case ABI_ELFv2:
       {
 	rtx fnmem, fn_reg, toc_reg;
 
@@ -26935,7 +26954,7 @@ rs6000_ms_bitfield_layout_p (const_tree 
 static void
 rs6000_elf_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED)
 {
-  if (DEFAULT_ABI == ABI_AIX
+  if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
       && TARGET_MINIMAL_TOC
       && !TARGET_RELOCATABLE)
     {
@@ -26956,7 +26975,8 @@ rs6000_elf_output_toc_section_asm_op (co
       else
 	fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);
     }
-  else if (DEFAULT_ABI == ABI_AIX && !TARGET_RELOCATABLE)
+  else if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+	   && !TARGET_RELOCATABLE)
     fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP);
   else
     {
@@ -27012,7 +27032,7 @@ rs6000_elf_encode_section_info (tree dec
   if (first
       && TREE_CODE (decl) == FUNCTION_DECL
       && !TARGET_AIX
-      && DEFAULT_ABI == ABI_AIX)
+      && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2))
     {
       rtx sym_ref = XEXP (rtl, 0);
       size_t len = strlen (XSTR (sym_ref, 0));
@@ -27506,7 +27526,7 @@ rs6000_elf_reloc_rw_mask (void)
 {
   if (flag_pic)
     return 3;
-  else if (DEFAULT_ABI == ABI_AIX)
+  else if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     return 2;
   else
     return 0;
@@ -27632,7 +27652,7 @@ rs6000_elf_declare_function_name (FILE *
   ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
   ASM_DECLARE_RESULT (file, DECL_RESULT (decl));
 
-  if (DEFAULT_ABI == ABI_AIX)
+  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     {
       const char *desc_name, *orig_name;
 
@@ -30632,7 +30652,7 @@ rs6000_legitimate_constant_p (enum machi
 
 
 
-/* Expand code to perform a call under the AIX ABI.  */
+/* Expand code to perform a call under the AIX or ELFv2 ABI.  */
 
 void
 rs6000_call_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
@@ -30738,7 +30758,7 @@ rs6000_call_aix (rtx value, rtx func_des
     use_reg (&CALL_INSN_FUNCTION_USAGE (insn), abi_reg);
 }
 
-/* Expand code to perform a sibling call under the AIX ABI.  */
+/* Expand code to perform a sibling call under the AIX or ELFv2 ABI.  */
 
 void
 rs6000_sibcall_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
Index: gcc/gcc/config/rs6000/rs6000.md
===================================================================
--- gcc.orig/gcc/config/rs6000/rs6000.md
+++ gcc/gcc/config/rs6000/rs6000.md
@@ -11201,7 +11201,7 @@
 	 	    (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
 		   UNSPEC_TLSGD)
    (clobber (reg:SI LR_REGNO))]
-  "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX"
+  "HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
 {
   if (TARGET_CMODEL != CMODEL_SMALL)
     return "addis %0,%1,%2@got@tlsgd@ha\;addi %0,%0,%2@got@tlsgd@l\;"
@@ -11310,7 +11310,8 @@
    (unspec:TLSmode [(match_operand:TLSmode 3 "rs6000_tls_symbol_ref" "")]
 		   UNSPEC_TLSGD)
    (clobber (reg:SI LR_REGNO))]
-  "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX && TARGET_TLS_MARKERS"
+  "HAVE_AS_TLS && TARGET_TLS_MARKERS
+   && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
   "bl %z1(%3@tlsgd)\;nop"
   [(set_attr "type" "branch")
    (set_attr "length" "8")])
@@ -11342,7 +11343,7 @@
    (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")]
 		   UNSPEC_TLSLD)
    (clobber (reg:SI LR_REGNO))]
-  "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX"
+  "HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
 {
   if (TARGET_CMODEL != CMODEL_SMALL)
     return "addis %0,%1,%&@got@tlsld@ha\;addi %0,%0,%&@got@tlsld@l\;"
@@ -11445,7 +11446,8 @@
 	      (match_operand 2 "" "g")))
    (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)
    (clobber (reg:SI LR_REGNO))]
-  "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX && TARGET_TLS_MARKERS"
+  "HAVE_AS_TLS && TARGET_TLS_MARKERS
+   && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
   "bl %z1(%&@tlsld)\;nop"
   [(set_attr "type" "branch")
    (set_attr "length" "8")])
@@ -11816,7 +11818,7 @@
   [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
 		   (unspec:SI [(const_int 0)] UNSPEC_TOC))
 	      (use (reg:SI 2))])]
-  "DEFAULT_ABI == ABI_AIX && TARGET_32BIT"
+  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) && TARGET_32BIT"
   "*
 {
   char buf[30];
@@ -11831,7 +11833,7 @@
   [(parallel [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
 		   (unspec:DI [(const_int 0)] UNSPEC_TOC))
 	      (use (reg:DI 2))])]
-  "DEFAULT_ABI == ABI_AIX && TARGET_64BIT"
+  "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) && TARGET_64BIT"
   "*
 {
   char buf[30];
@@ -12097,7 +12099,7 @@
 
   operands[0] = XEXP (operands[0], 0);
 
-  if (DEFAULT_ABI == ABI_AIX)
+  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     {
       rs6000_call_aix (NULL_RTX, operands[0], operands[1], operands[2]);
       DONE;
@@ -12141,7 +12143,7 @@
 
   operands[1] = XEXP (operands[1], 0);
 
-  if (DEFAULT_ABI == ABI_AIX)
+  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     {
       rs6000_call_aix (operands[0], operands[1], operands[2], operands[3]);
       DONE;
@@ -12440,7 +12442,7 @@
   [(call (mem:SI (match_operand:P 0 "current_file_function_operand" "s"))
 	 (match_operand 1 "" "g"))
    (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_AIX"
+  "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
   "bl %z0"
   [(set_attr "type" "branch")
    (set_attr "length" "4")])
@@ -12450,7 +12452,7 @@
 	(call (mem:SI (match_operand:P 1 "current_file_function_operand" "s"))
 	      (match_operand 2 "" "g")))
    (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_AIX"
+  "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
   "bl %z1"
   [(set_attr "type" "branch")
    (set_attr "length" "4")])
@@ -12462,7 +12464,7 @@
   [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s"))
 	 (match_operand 1 "" "g"))
    (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_AIX"
+  "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
   "bl %z0\;nop"
   [(set_attr "type" "branch")
    (set_attr "length" "8")])
@@ -12472,7 +12474,7 @@
 	(call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s"))
 	      (match_operand 2 "" "g")))
    (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_AIX"
+  "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
   "bl %z1\;nop"
   [(set_attr "type" "branch")
    (set_attr "length" "8")])
@@ -12488,7 +12490,7 @@
    (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
    (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
    (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_AIX"
+  "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
   "<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3"
   [(set_attr "type" "jmpreg")
    (set_attr "length" "12")])
@@ -12500,7 +12502,7 @@
    (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
    (set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>"))
    (clobber (reg:P LR_REGNO))]
-  "DEFAULT_ABI == ABI_AIX"
+  "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
   "<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4"
   [(set_attr "type" "jmpreg")
    (set_attr "length" "12")])
@@ -12554,7 +12556,7 @@
 
   operands[0] = XEXP (operands[0], 0);
 
-  if (DEFAULT_ABI == ABI_AIX)
+  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     {
       rs6000_sibcall_aix (NULL_RTX, operands[0], operands[1], operands[2]);
       DONE;
@@ -12581,7 +12583,7 @@
 
   operands[1] = XEXP (operands[1], 0);
 
-  if (DEFAULT_ABI == ABI_AIX)
+  if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
     {
       rs6000_sibcall_aix (operands[0], operands[1], operands[2], operands[3]);
       DONE;
@@ -12741,7 +12743,7 @@
   [(call (mem:SI (match_operand:P 0 "call_operand" "s,c"))
 	 (match_operand 1 "" "g,g"))
    (simple_return)]
-  "DEFAULT_ABI == ABI_AIX"
+  "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
   "@
    b %z0
    b%T0"
@@ -12753,7 +12755,7 @@
 	(call (mem:SI (match_operand:P 1 "call_operand" "s,c"))
 	      (match_operand 2 "" "g,g")))
    (simple_return)]
-  "DEFAULT_ABI == ABI_AIX"
+  "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
   "@
    b %z1
    b%T1"
Index: gcc/gcc/config/rs6000/predicates.md
===================================================================
--- gcc.orig/gcc/config/rs6000/predicates.md
+++ gcc/gcc/config/rs6000/predicates.md
@@ -1018,7 +1018,8 @@
 (define_predicate "symbol_ref_operand"
   (and (match_code "symbol_ref")
        (match_test "(mode == VOIDmode || GET_MODE (op) == mode)
-		    && (DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op))")))
+		    && ((DEFAULT_ABI != ABI_AIX && DEFAULT_ABI != ABI_ELFv2)
+			|| SYMBOL_REF_FUNCTION_P (op))")))
 
 ;; Return 1 if op is an operand that can be loaded via the GOT.
 ;; or non-special register register field no cr0
@@ -1048,9 +1049,11 @@
 ;; this file.
 (define_predicate "current_file_function_operand"
   (and (match_code "symbol_ref")
-       (match_test "(DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op))
+       (match_test "((DEFAULT_ABI != ABI_AIX && DEFAULT_ABI != ABI_ELFv2)
+		     || SYMBOL_REF_FUNCTION_P (op))
 		    && ((SYMBOL_REF_LOCAL_P (op)
-			 && (DEFAULT_ABI != ABI_AIX
+			 && ((DEFAULT_ABI != ABI_AIX
+			      && DEFAULT_ABI != ABI_ELFv2)
 			     || !SYMBOL_REF_EXTERNAL_P (op)))
 		        || (op == XEXP (DECL_RTL (current_function_decl),
 						  0)))")))
Index: gcc/libgcc/config/rs6000/linux-unwind.h
===================================================================
--- gcc.orig/libgcc/config/rs6000/linux-unwind.h
+++ gcc/libgcc/config/rs6000/linux-unwind.h
@@ -107,6 +107,8 @@ get_regs (struct _Unwind_Context *contex
     }
   else if (pc[1] == 0x380000AC)
     {
+#if _CALL_ELF != 2
+      /* These old kernel versions never supported ELFv2.  */
       /* This works for 2.4 kernels, but not for 2.6 kernels with vdso
 	 because pc isn't pointing into the stack.  Can be removed when
 	 no one is running 2.4.19 or 2.4.20, the first two ppc64
@@ -121,6 +123,7 @@ get_regs (struct _Unwind_Context *contex
       if ((long) frame24->puc != -21 * 8)
 	return frame24->puc->regs;
       else
+#endif
 	{
 	  /* This works for 2.4.21 and later kernels.  */
 	  struct rt_sigframe {
@@ -298,8 +301,12 @@ frob_update_context (struct _Unwind_Cont
 	 code that does the save/restore is generated by the linker, so
 	 we have no good way to determine at compile time what to do.  */
       if (pc[0] == 0xF8410028
+#if _CALL_ELF != 2
+	  /* The ELFv2 linker never generates the old PLT stub form.  */
 	  || ((pc[0] & 0xFFFF0000) == 0x3D820000
-	      && pc[1] == 0xF8410028))
+	      && pc[1] == 0xF8410028)
+#endif
+	  )
 	{
 	  /* We are in a plt call stub or r2 adjusting long branch stub,
 	     before r2 has been saved.  Keep REG_UNSAVED.  */
Index: gcc/gcc/testsuite/lib/target-supports.exp
===================================================================
--- gcc.orig/gcc/testsuite/lib/target-supports.exp
+++ gcc/gcc/testsuite/lib/target-supports.exp
@@ -3019,6 +3019,22 @@ proc check_effective_target_powerpc_405_
     }
 }
 
+# Return 1 if this is a PowerPC target using the ELFv2 ABI.
+
+proc check_effective_target_powerpc_elfv2 { } {
+    if { [istarget powerpc*-*-*] } {
+	return [check_no_compiler_messages powerpc_elfv2 object {
+	    #if _CALL_ELF != 2
+	    #error not ELF v2 ABI
+	    #else
+	    int dummy;
+	    #endif
+	}]
+    } else {
+	return 0
+    }
+}
+
 # Return 1 if this is a SPU target with a toolchain that
 # supports automatic overlay generation.
 
Index: gcc/gcc/testsuite/gcc.target/powerpc/pr57949-1.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/powerpc/pr57949-1.c
+++ gcc/gcc/testsuite/gcc.target/powerpc/pr57949-1.c
@@ -1,5 +1,6 @@
 /* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
 /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc_elfv2 } { "*" } { "" } } */
 /* { dg-options "-O2 -mcpu=power7" } */
 
 /* Verify that vs is 16-byte aligned in the absence of -mcompat-align-parm.  */
Index: gcc/gcc/testsuite/gcc.target/powerpc/pr57949-2.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/powerpc/pr57949-2.c
+++ gcc/gcc/testsuite/gcc.target/powerpc/pr57949-2.c
@@ -1,5 +1,6 @@
 /* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
 /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc_elfv2 } { "*" } { "" } } */
 /* { dg-options "-O2 -mcpu=power7 -mcompat-align-parm" } */
 
 /* Verify that vs is not 16-byte aligned with -mcompat-align-parm.  */
