Index: gcc-4.2.4/gcc/config/arm/arm.c
===================================================================
--- gcc-4.2.4.orig/gcc/config/arm/arm.c	2013-07-14 07:58:33.000000000 +0000
+++ gcc-4.2.4/gcc/config/arm/arm.c	2013-07-14 07:59:44.000000000 +0000
@@ -5545,7 +5545,10 @@
     switch (GET_CODE (insn))
       {
       case JUMP_INSN:
-	/* Any branch must be followed by 2 non Cirrus instructions. */
+	/* Any branch must be followed by 2 non Cirrus instructions.
+	 * This would apply to CALL_INSN too, but that case is handled
+	 * by ensuring the 1st insn of a function is never cfstrd,
+	 * done in arm_save_coproc_regs() */
 	body = PATTERN (insn);
 	if (GET_CODE (body) != RETURN)
 	  {
@@ -9916,9 +9919,21 @@
 	}
       else if (arm_fpu_arch == FPUTYPE_MAVERICK)
 	{
+	  /* Precede cfldrd with 2 nops to avoid Erratum 1 when
+	   * the last insns of the fn are branches. Usually, but not always,
+	   * there is an "add sp,sp,#n" before this, so one nop would do,
+	   * but it's not always there. How does one know? */
+	  int have_output_nops = 0;
+
 	  for (reg = LAST_CIRRUS_FP_REGNUM; reg >= FIRST_CIRRUS_FP_REGNUM; reg--)
 	    if (regs_ever_live[reg] && !call_used_regs[reg])
 	      {
+		if (!have_output_nops)
+		  {
+		    asm_fprintf (f, "\tnop\n\tnop\n");
+		    have_output_nops = 1;
+		  }
+
 		floats_offset += 8;
 		asm_fprintf (f, "\tcfldrd\tmvd%d, [%r, #-%d]\n",
 			     reg - FIRST_CIRRUS_FP_REGNUM, FP_REGNUM,
@@ -10073,10 +10088,23 @@
 	}
       else if (arm_fpu_arch == FPUTYPE_MAVERICK)
 	{
+	  /* Precede cfldrd with 2 nops to avoid Erratum 1 when
+	   * the last insns of the fn are branches. Usually, but not always,
+	   * there is an "add sp,sp,#n" before this, so one nop would do,
+	   * but it's not always there. How does one know? */
+	  int have_output_nops = 0;
+
 	  for (reg = FIRST_CIRRUS_FP_REGNUM; reg <= LAST_CIRRUS_FP_REGNUM; reg++)
 	    if (regs_ever_live[reg] && !call_used_regs[reg])
-	      asm_fprintf (f, "\tcfldrd\tmvd%u, [%r], #8\n",
-			   reg - FIRST_CIRRUS_FP_REGNUM, SP_REGNUM);
+	      {
+		if (!have_output_nops)
+		  {
+		    asm_fprintf (f, "\tnop\n\tnop\n");
+		    have_output_nops = 1;
+		  }
+		asm_fprintf (f, "\tcfldrd\tmvd%u, [%r], #8\n",
+			     reg - FIRST_CIRRUS_FP_REGNUM, SP_REGNUM);
+	      }
 	}
       else
 	{
@@ -10890,6 +10918,14 @@
 	  for (reg = LAST_CIRRUS_FP_REGNUM; reg >= FIRST_CIRRUS_FP_REGNUM; reg--)
 	    if (regs_ever_live[reg] && !call_used_regs[reg])
 	      {
+                /* Ensure the first insn of a fn is never cfstrd to avoid Erratum 1
+		 * without having to follow every bl with two non-cirrus insns.
+		 * Saving Maverick registers without saving any ARM registers
+		 * is rare but can occur, e.g.in fftw3's fftw_iestimate_cost().
+		 */
+		if (saved_regs == 0)
+		  emit_insn(gen_nop());
+
 		insn = gen_rtx_PRE_DEC (DFmode, stack_pointer_rtx);
 		insn = gen_rtx_MEM (DFmode, insn);
 		insn = emit_insn (gen_rtx_SET (VOIDmode, insn,
