Index: gcc/gcc/config/rs6000/rs6000.h
===================================================================
--- gcc.orig/gcc/config/rs6000/rs6000.h
+++ gcc/gcc/config/rs6000/rs6000.h
@@ -1529,12 +1529,12 @@ extern enum reg_class rs6000_constraints
 
 /* Size of the fixed area on the stack */
 #define RS6000_SAVE_AREA \
-  ((DEFAULT_ABI == ABI_V4 ? 8 : 24) << (TARGET_64BIT ? 1 : 0))
+  ((DEFAULT_ABI == ABI_V4 ? 8 : DEFAULT_ABI == ABI_ELFv2 ? 16 : 24)	\
+   << (TARGET_64BIT ? 1 : 0))
 
-/* MEM representing address to save the TOC register */
-#define RS6000_SAVE_TOC gen_rtx_MEM (Pmode, \
-				     plus_constant (Pmode, stack_pointer_rtx, \
-						    (TARGET_32BIT ? 20 : 40)))
+/* Stack offset for toc save slot.  */
+#define RS6000_TOC_SAVE_SLOT \
+  ((DEFAULT_ABI == ABI_ELFv2 ? 12 : 20) << (TARGET_64BIT ? 1 : 0))
 
 /* Align an address */
 #define RS6000_ALIGN(n,a) (((n) + (a) - 1) & ~((a) - 1))
Index: gcc/gcc/config/rs6000/rs6000.c
===================================================================
--- gcc.orig/gcc/config/rs6000/rs6000.c
+++ gcc/gcc/config/rs6000/rs6000.c
@@ -9029,6 +9029,16 @@ rs6000_function_arg_boundary (enum machi
     return PARM_BOUNDARY;
 }
 
+/* The offset in words to the start of the parameter save area.  */
+
+static unsigned int
+rs6000_parm_offset (void)
+{
+  return (DEFAULT_ABI == ABI_V4 ? 2
+	  : DEFAULT_ABI == ABI_ELFv2 ? 4
+	  : 6);
+}
+
 /* For a function parm of MODE and TYPE, return the starting word in
    the parameter area.  NWORDS of the parameter area are already used.  */
 
@@ -9037,11 +9047,9 @@ rs6000_parm_start (enum machine_mode mod
 		   unsigned int nwords)
 {
   unsigned int align;
-  unsigned int parm_offset;
 
   align = rs6000_function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
-  parm_offset = DEFAULT_ABI == ABI_V4 ? 2 : 6;
-  return nwords + (-(parm_offset + nwords) & align);
+  return nwords + (-(rs6000_parm_offset () + nwords) & align);
 }
 
 /* Compute the size (in words) of a function argument.  */
@@ -9281,15 +9289,13 @@ rs6000_function_arg_advance_1 (CUMULATIV
 	{
 	  int align;
 
-	  /* Vector parameters must be 16-byte aligned.  This places
-	     them at 2 mod 4 in terms of words in 32-bit mode, since
-	     the parameter save area starts at offset 24 from the
-	     stack.  In 64-bit mode, they just have to start on an
-	     even word, since the parameter save area is 16-byte
-	     aligned.  Space for GPRs is reserved even if the argument
-	     will be passed in memory.  */
+	  /* Vector parameters must be 16-byte aligned.  In 32-bit
+	     mode this means we need to take into account the offset
+	     to the parameter save area.  In 64-bit mode, they just
+	     have to start on an even word, since the parameter save
+	     area is 16-byte aligned.  */
 	  if (TARGET_32BIT)
-	    align = (2 - cum->words) & 3;
+	    align = -(rs6000_parm_offset () + cum->words) & 3;
 	  else
 	    align = cum->words & 1;
 	  cum->words += align + rs6000_arg_size (mode, type);
@@ -9965,13 +9971,13 @@ rs6000_function_arg (cumulative_args_t c
 	  int align, align_words, n_words;
 	  enum machine_mode part_mode;
 
-	  /* Vector parameters must be 16-byte aligned.  This places them at
-	     2 mod 4 in terms of words in 32-bit mode, since the parameter
-	     save area starts at offset 24 from the stack.  In 64-bit mode,
-	     they just have to start on an even word, since the parameter
-	     save area is 16-byte aligned.  */
+	  /* Vector parameters must be 16-byte aligned.  In 32-bit
+	     mode this means we need to take into account the offset
+	     to the parameter save area.  In 64-bit mode, they just
+	     have to start on an even word, since the parameter save
+	     area is 16-byte aligned.  */
 	  if (TARGET_32BIT)
-	    align = (2 - cum->words) & 3;
+	    align = -(rs6000_parm_offset () + cum->words) & 3;
 	  else
 	    align = cum->words & 1;
 	  align_words = cum->words + align;
@@ -20188,6 +20194,34 @@ rs6000_savres_strategy (rs6000_stack_t *
    The required alignment for AIX configurations is two words (i.e., 8
    or 16 bytes).
 
+   The ELFv2 ABI is a variant of the AIX ABI.  Stack frames look like:
+
+	SP---->	+---------------------------------------+
+		| Back chain to caller			|  0
+		+---------------------------------------+
+		| Save area for CR			|  8
+		+---------------------------------------+
+		| Saved LR				|  16
+		+---------------------------------------+
+		| Saved TOC pointer			|  24
+		+---------------------------------------+
+		| Parameter save area (P)		|  32
+		+---------------------------------------+
+		| Alloca space (A)			|  32+P
+		+---------------------------------------+
+		| Local variable space (L)		|  32+P+A
+		+---------------------------------------+
+		| Save area for AltiVec registers (W)	|  32+P+A+L
+		+---------------------------------------+
+		| AltiVec alignment padding (Y)		|  32+P+A+L+W
+		+---------------------------------------+
+		| Save area for GP registers (G)	|  32+P+A+L+W+Y
+		+---------------------------------------+
+		| Save area for FP registers (F)	|  32+P+A+L+W+Y+G
+		+---------------------------------------+
+	old SP->| back chain to caller's caller		|  32+P+A+L+W+Y+G+F
+		+---------------------------------------+
+
 
    V.4 stack frames look like:
 
@@ -22532,7 +22566,8 @@ rs6000_emit_prologue (void)
 	 be updated if we arrived at this function via a plt call or
 	 toc adjusting stub.  */
       emit_move_insn (tmp_reg_si, gen_rtx_MEM (SImode, tmp_reg));
-      toc_restore_insn = TARGET_32BIT ? 0x80410014 : 0xE8410028;
+      toc_restore_insn = ((TARGET_32BIT ? 0x80410000 : 0xE8410000)
+			  + RS6000_TOC_SAVE_SLOT);
       hi = gen_int_mode (toc_restore_insn & ~0xffff, SImode);
       emit_insn (gen_xorsi3 (tmp_reg_si, tmp_reg_si, hi));
       compare_result = gen_rtx_REG (CCUNSmode, CR0_REGNO);
@@ -22551,7 +22586,7 @@ rs6000_emit_prologue (void)
       LABEL_NUSES (toc_save_done) += 1;
 
       save_insn = emit_frame_save (frame_reg_rtx, reg_mode,
-				   TOC_REGNUM, frame_off + 5 * reg_size,
+				   TOC_REGNUM, frame_off + RS6000_TOC_SAVE_SLOT,
 				   sp_off - frame_off);
 
       emit_label (toc_save_done);
@@ -22946,7 +22981,7 @@ rs6000_emit_prologue (void)
   if (rs6000_save_toc_in_prologue_p ())
     {
       rtx reg = gen_rtx_REG (reg_mode, TOC_REGNUM);
-      emit_insn (gen_frame_store (reg, sp_reg_rtx, 5 * reg_size));
+      emit_insn (gen_frame_store (reg, sp_reg_rtx, RS6000_TOC_SAVE_SLOT));
     }
 }
 
@@ -23014,7 +23049,11 @@ rs6000_output_function_prologue (FILE *f
       asm_fprintf (file, "\tmflr %s\n", reg_names[0]);
       asm_fprintf (file, "\tstd %s,16(%s)\n", reg_names[0], reg_names[1]);
 
-      if (cfun->static_chain_decl != NULL)
+      /* In the ELFv2 ABI we have no compiler stack word.  It must be
+	 the resposibility of _mcount to preserve the static chain
+	 register if required.  */
+      if (DEFAULT_ABI != ABI_ELFv2
+	  && cfun->static_chain_decl != NULL)
 	{
 	  asm_fprintf (file, "\tstd %s,24(%s)\n",
 		       reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
@@ -23758,7 +23797,7 @@ rs6000_emit_epilogue (int sibcall)
 	{
 	  rtx reg = gen_rtx_REG (reg_mode, 2);
 	  emit_insn (gen_frame_load (reg, frame_reg_rtx,
-				     frame_off + 5 * reg_size));
+				     frame_off + RS6000_TOC_SAVE_SLOT));
 	}
 
       for (i = 0; ; ++i)
@@ -31335,7 +31374,7 @@ rs6000_call_aix (rtx value, rtx func_des
       /* Save the TOC into its reserved slot before the call,
 	 and prepare to restore it after the call.  */
       rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
-      rtx stack_toc_offset = GEN_INT (5 * GET_MODE_SIZE (Pmode));
+      rtx stack_toc_offset = GEN_INT (RS6000_TOC_SAVE_SLOT);
       rtx stack_toc_mem = gen_frame_mem (Pmode,
 					 gen_rtx_PLUS (Pmode, stack_ptr,
 						       stack_toc_offset));
Index: gcc/libgcc/config/rs6000/linux-unwind.h
===================================================================
--- gcc.orig/libgcc/config/rs6000/linux-unwind.h
+++ gcc/libgcc/config/rs6000/linux-unwind.h
@@ -29,6 +29,14 @@
 #define R_VR0		77
 #define R_VRSAVE	109
 
+#ifdef __powerpc64__
+#if _CALL_ELF == 2
+#define TOC_SAVE_SLOT	24
+#else
+#define TOC_SAVE_SLOT	40
+#endif
+#endif
+
 struct gcc_vregs
 {
   __attribute__ ((vector_size (16))) int vr[32];
@@ -310,11 +318,11 @@ frob_update_context (struct _Unwind_Cont
 	 figure out if it was saved.  The big problem here is that the
 	 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 (pc[0] == 0xF8410000 + TOC_SAVE_SLOT
 #if _CALL_ELF != 2
 	  /* The ELFv2 linker never generates the old PLT stub form.  */
 	  || ((pc[0] & 0xFFFF0000) == 0x3D820000
-	      && pc[1] == 0xF8410028)
+	      && pc[1] == 0xF8410000 + TOC_SAVE_SLOT)
 #endif
 	  )
 	{
@@ -325,19 +333,19 @@ frob_update_context (struct _Unwind_Cont
 	{
 	  unsigned int *insn
 	    = (unsigned int *) _Unwind_GetGR (context, R_LR);
-	  if (insn && *insn == 0xE8410028)
-	    _Unwind_SetGRPtr (context, 2, context->cfa + 40);
+	  if (insn && *insn == 0xE8410000 + TOC_SAVE_SLOT)
+	    _Unwind_SetGRPtr (context, 2, context->cfa + TOC_SAVE_SLOT);
 #if _CALL_ELF != 2
 	  /* ELFv2 does not use this function pointer call sequence.  */
 	  else if (pc[0] == 0x4E800421
-		   && pc[1] == 0xE8410028)
+		   && pc[1] == 0xE8410000 + TOC_SAVE_SLOT)
 	    {
 	      /* We are at the bctrl instruction in a call via function
 		 pointer.  gcc always emits the load of the new R2 just
 		 before the bctrl so this is the first and only place
 		 we need to use the stored R2.  */
 	      _Unwind_Word sp = _Unwind_GetGR (context, 1);
-	      _Unwind_SetGRPtr (context, 2, (void *)(sp + 40));
+	      _Unwind_SetGRPtr (context, 2, (void *)(sp + TOC_SAVE_SLOT));
 	    }
 #endif
 	}
Index: gcc/gcc/testsuite/gcc.target/powerpc/ppc64-abi-1.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/powerpc/ppc64-abi-1.c
+++ gcc/gcc/testsuite/gcc.target/powerpc/ppc64-abi-1.c
@@ -89,8 +89,10 @@ typedef struct sf
   long a1;
   long a2;
   long a3;
+#if _CALL_ELF != 2
   long a4;
   long a5;
+#endif
   parm_t slot[100];
 } stack_frame_t;
 
Index: gcc/gcc/testsuite/gcc.target/powerpc/ppc64-abi-2.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/powerpc/ppc64-abi-2.c
+++ gcc/gcc/testsuite/gcc.target/powerpc/ppc64-abi-2.c
@@ -107,8 +107,10 @@ typedef struct sf
   long a1;
   long a2;
   long a3;
+#if _CALL_ELF != 2
   long a4;
   long a5;
+#endif
   parm_t slot[100];
 } stack_frame_t;
 
Index: gcc/gcc/testsuite/gcc.target/powerpc/ppc64-abi-dfp-1.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/powerpc/ppc64-abi-dfp-1.c
+++ gcc/gcc/testsuite/gcc.target/powerpc/ppc64-abi-dfp-1.c
@@ -87,8 +87,10 @@ typedef struct sf
   long a1;
   long a2;
   long a3;
+#if _CALL_ELF != 2
   long a4;
   long a5;
+#endif
   unsigned long slot[100];
 } stack_frame_t;
 
Index: gcc/gcc/testsuite/gcc.dg/stack-usage-1.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.dg/stack-usage-1.c
+++ gcc/gcc/testsuite/gcc.dg/stack-usage-1.c
@@ -40,7 +40,11 @@
 #  endif
 #elif defined (__powerpc64__) || defined (__ppc64__) || defined (__POWERPC64__) \
       || defined (__PPC64__)
-#  define SIZE 180
+#  if _CALL_ELF == 2
+#     define SIZE 208
+#  else
+#     define SIZE 180
+#  endif
 #elif defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) \
       || defined (__POWERPC__) || defined (PPC) || defined (_IBMR2)
 #  if defined (__ALTIVEC__)
