diff mbox

[rs6000] ELFv2 ABI 1/8: Add options and infrastructure

Message ID 201311111440.rABEem5T003872@d06av02.portsmouth.uk.ibm.com
State New
Headers show

Commit Message

Ulrich Weigand Nov. 11, 2013, 2:40 p.m. UTC
Hello,

this is the first patch in the series to add support for the ELFv2 ABI.

The ELFv2 ABI is the intended ABI for the new powerpc64le-linux port.
However, it is not inherently tied to the byte order; it it possible
in principle to use the ELFv2 ABI in big-endian mode too.

Therefore, it is introduces via a new pair of options
   -mabi=elfv1 / -mabi=elfv2
where -mabi=elfv1 select the current Linux ABI, and -mabi=elfv2
selects the new one.

If neither option is given, the compiler defaults to whatever ABI
was specified at configure time using the
   --with-abi=elfv1 / --with-abi=elfv2
configure option.

If this was not specified either, every subtarget can provide a
master default by defining (or not) the LINUX64_DEFAULT_ABI_ELFv2
macro.

The patch series is structured as follows:

- This first patch adds the new enum rs6000_abi value ABI_ELFv2
  and all the configure logic needed to set it.  It is treated
  just like ABI_AIX (on a modern system) at this point; no change
  in generated code is expected yet.

- A series of follow on patches will add the various features
  defining the ELFv2 ABI.  Note that they will still not be
  active by default anywhere.

- The final patch will simply turn the switch to make ELFv2
  the default ABI on powerpc64le-linux.

The whole series was tested on:

  - powerpc64-linux with no regression, including no regression
    in an ALT_CC_UNDER_TEST/ALT_CXX_UNDER_TEST run of compat.exp
    and struct-layout-1.exp against a current compiler.

  - powerpc64-linux --with-abi=elfv2 in mock-up big-endian ELFv2
    environment running with some hacks on an existing system.

  - powerpc64le-linux, using the new default ELFv2 in a rebuilt
    small OS image using the new ABI everywhere.
 
(Of course, patches to binutils, glibc, and libffi to support the
new ELFv2 ABI are also required.)

The tests were using all languages (including Java, Go, and
Objective-C++; on powerpc64le-linux also Ada), and all target
libraries except libsanitizer (which currently seems broken
on mainline).

There is a small number of regressions on powerpc64le-linux
which seem to be due to unrelated issues:

- FAIL: g++.dg/cpp1y/vla-initlist1.C execution test
  This is an invalid assumption in the test case

- FAIL: go.test/test/fixedbugs/bug296.go execution,  -O2 -g
  The ELFv2 ABI  seems to be exposing a Go frontend bug here

- FAIL: runtime/pprof   (in libgo)
  This is due to a glibc problem with unwinding through a
  context created via makecontext

I'll address those separately.  (Of course, there are also
other pre-existing regressions on powerpc64le-linux simply
due to little-endian issues.  Those are unaffected by ELFv2.)


I'll add more detailed descriptions of the actual ABI features
with the various follow-on patches that implement those.

This patch specifically only adds the options as described above.
ABI_ELFv2 is implemented to be equivalent to ABI_AIX on a modern
system; since the ABI is new, there is no need to continue to
support legacy features.  This means specifically:
- DOT_SYMBOLS is assumed to be false
- rs6000_compat_align_parm is assumed to be false
- code in linux-unwind.h that handles old kernels/linkers is removed

The patch also adds two new pre-defined macros:
- _CALL_ELF is set to 1 or 2 to denote the ELFv1 / ELFv2 ABI
- __STRUCT_PARM_ALIGN__ is set to 16 if aggregates passed by value
  are aligned to 16 if their native alignment requires that
  (this is necessary to implement libffi, for example)

In addition, the patch adds a testsuite effective target check
for the ELFv2 ABI, and disables the pr57949 tests (these verify
the operation of the -mcompat-align-parm option, which is no
longer useful in the ELFv2 ABI).


To avoid having a partial ABI implementation in tree, it seems best
to commit this whole patch series as a single commit.

Is the series OK for mainline?

Bye,
Ulrich




gcc/ChangeLog:

2013-11-11  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>

	* config.gcc [powerpc*-*-* | rs6000-*-*]: Support --with-abi=elfv1
	and --with-abi=elfv2.
	* config/rs6000/option-defaults.h (OPTION_DEFAULT_SPECS): Add "abi".
	* config/rs6000/rs6000.opt (mabi=elfv1): New option.
	(mabi=elfv2): Likewise.
	* config/rs6000/rs6000-opts.h (enum rs6000_abi): Add ABI_ELFv2.
	* config/rs6000/linux64.h (DEFAULT_ABI): Do not hard-code to AIX_ABI
	if !RS6000_BI_ARCH.
	(ELFv2_ABI_CHECK): New macro.
	(SUBSUBTARGET_OVERRIDE_OPTIONS): Use it to decide whether to set
	rs6000_current_abi to ABI_AIX or ABI_ELFv2.
	(GLIBC_DYNAMIC_LINKER64): Support ELFv2 ld.so version.
	* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Predefine
	_CALL_ELF and __STRUCT_PARM_ALIGN__ if appropriate.

	* config/rs6000/rs6000.c (rs6000_debug_reg_global): Handle ABI_ELFv2.
	(debug_stack_info): Likewise.
	(rs6000_file_start): Treat ABI_ELFv2 the same as ABI_AIX.
	(rs6000_legitimize_tls_address): Likewise.
	(rs6000_conditional_register_usage): Likewise.
	(rs6000_emit_move): Likewise.
	(init_cumulative_args): Likewise.
	(rs6000_function_arg_advance_1): Likewise.
	(rs6000_function_arg): Likewise.
	(rs6000_arg_partial_bytes): Likewise.
	(rs6000_output_function_entry): Likewise.
	(rs6000_assemble_integer): Likewise.
	(rs6000_savres_strategy): Likewise.
	(rs6000_stack_info): Likewise.
	(rs6000_function_ok_for_sibcall): Likewise.
	(rs6000_emit_load_toc_table): Likewise.
	(rs6000_savres_routine_name): Likewise.
	(ptr_regno_for_savres): Likewise.
	(rs6000_emit_prologue): Likewise.
	(rs6000_emit_epilogue): Likewise.
	(rs6000_output_function_epilogue): Likewise.
	(output_profile_hook): Likewise.
	(output_function_profiler): Likewise.
	(rs6000_trampoline_size): Likewise.
	(rs6000_trampoline_init): Likewise.
	(rs6000_elf_output_toc_section_asm_op): Likewise.
	(rs6000_elf_encode_section_info): Likewise.
	(rs6000_elf_reloc_rw_mask): Likewise.
	(rs6000_elf_declare_function_name): Likewise.
	(rs6000_function_arg_boundary): Treat ABI_ELFv2 the same as ABI_AIX,
	except that rs6000_compat_align_parm is always assumed false.
	(rs6000_gimplify_va_arg): Likewise.
	(rs6000_call_aix): Update comment.
	(rs6000_sibcall_aix): Likewise.
	* config/rs6000/rs6000.md ("tls_gd_aix<TLSmode:tls_abi_suffix>"):
	Treat ABI_ELFv2 the same as ABI_AIX.
	("*tls_gd_call_aix<TLSmode:tls_abi_suffix>"): Likewise.
	("tls_ld_aix<TLSmode:tls_abi_suffix>"): Likewise.
	("*tls_ld_call_aix<TLSmode:tls_abi_suffix>"): Likewise.
	("load_toc_aix_si"): Likewise.
	("load_toc_aix_di"): Likewise.
	("call"): Likewise.
	("call_value"): Likewise.
	("*call_local_aix<mode>"): Likewise.
	("*call_value_local_aix<mode>"): Likewise.
	("*call_nonlocal_aix<mode>"): Likewise.
	("*call_value_nonlocal_aix<mode>"): Likewise.
	("*call_indirect_aix<mode>"): Likewise.
	("*call_value_indirect_aix<mode>"): Likewise.
	("sibcall"): Likewise.
	("sibcall_value"): Likewise.
	("*sibcall_aix<mode>"): Likewise.
	("*sibcall_value_aix<mode>"): Likewise.
	* config/rs6000/predicates.md ("symbol_ref_operand"): Likewise.
	("current_file_function_operand"): Likewise.

libgcc/ChangeLog:

2013-11-11  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
	    Alan Modra  <amodra@gmail.com>

	* config/rs6000/linux-unwind.h (get_regs): Do not support
	old kernel versions if _CALL_ELF == 2.
	(frob_update_context): Do not support PLT stub variants only
	generated by old linkers if _CALL_ELF == 2.

gcc/testsuite/ChangeLog:

2013-11-11  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>

	* lib/target-supports.exp (check_effective_target_powerpc_elfv2):
	New function.
	* gcc.target/powerpc/pr57949-1.c: Disable for powerpc_elfv2.
	* gcc.target/powerpc/pr57949-2.c: Likewise.

Comments

Joseph Myers Nov. 11, 2013, 11:04 p.m. UTC | #1
On Mon, 11 Nov 2013, Ulrich Weigand wrote:

> Hello,
> 
> this is the first patch in the series to add support for the ELFv2 ABI.
> 
> The ELFv2 ABI is the intended ABI for the new powerpc64le-linux port.
> However, it is not inherently tied to the byte order; it it possible
> in principle to use the ELFv2 ABI in big-endian mode too.

I'd rather, from a glibc perspective, keep down the number of variant ABIs 
available - and in particular, disallow the (ELFv1, little-endian 
combination) - have a compiler error given for it.  And, similarly, have 
the (ELFv2, big-endian) combination only if the plan is for it to obsolete 
the old ABI and for support for the old ABI for powerpc64-linux to be 
removed from GCC and glibc in a few years' time (similarly to how the ARM 
EABI superseded the old arm-linux-gnu ABI).  If you don't have such errors 
in GCC, then you should have configure-time errors in glibc to disallow 
the unsupported combinations.

(Any new supported glibc configuration should of course set minimum symbol 
version to GLIBC_2.19, or whatever the version is of the first release 
supporting it - and the dynamic linker / ldconfig should distinguish 
shared libraries for the two variants.)

I didn't see anything in this series regarding the ELFv1 ABI feature 
that's the greatest pain from a glibc perspective - the use of IBM long 
double.  The idea of moving to IEEE binary128 was floated in 
<https://sourceware.org/ml/libc-alpha/2013-10/msg00597.html> - have you 
abandoned that idea?  Obviously it would be bad to end up having two 
variants of ELFv2 with different long double formats.  (Though we can't 
actually eliminate IBM long double support from glibc unless all ABIs with 
it are obsoleted, including 32-bit.)  If you do move to IEEE binary128 I'd 
advise simply using soft-fp in libgcc for the functions that normally go 
in libgcc, given that 64-bit implies hard float, rather than the 
arrangements some targets have of putting their binary128 functions in 
glibc.

> Therefore, it is introduces via a new pair of options
>    -mabi=elfv1 / -mabi=elfv2
> where -mabi=elfv1 select the current Linux ABI, and -mabi=elfv2
> selects the new one.

New command-line options need invoke.texi documentation.

> (Of course, patches to binutils, glibc, and libffi to support the
> new ELFv2 ABI are also required.)

And GDB - GDB needs to know how to call functions, how to pass arguments 
to them and how to find the return value.
Jakub Jelinek Nov. 11, 2013, 11:17 p.m. UTC | #2
On Mon, Nov 11, 2013 at 03:40:48PM +0100, Ulrich Weigand wrote:
> @@ -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

I agree with Joseph that it would be nice to keep the number of supported
ABIs down, if it could be old powerpc64-linux big-endian ELFv1 and powerpc64le-linux
ELFv2 only, that would be ideal.  Can little-endian and big-endian binaries
coexist on the same kernel, or will there be big endian only kernels vs.
little endian only kernels?  If they can coexist, perhaps it would be better
to use different libQUAL suffix from lib64 (lib64be?), if they can't, using lib64
is fine.  If they can coexist, then there is certainly an issue with various
shared binary files that typically some way handle different word size these
days, but not endianity (utmp/wtmp, ld.so.cache, locale-archive, various
other files).

	Jakub
diff mbox

Patch

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.  */