Index: gcc-4.4.7/gcc/config/arm/arm.c
===================================================================
--- gcc-4.4.7.orig/gcc/config/arm/arm.c	2013-07-10 12:44:56.000000000 +0000
+++ gcc-4.4.7/gcc/config/arm/arm.c	2013-07-14 00:08:23.000000000 +0000
@@ -7163,7 +7163,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)
 	  {
@@ -11989,9 +11992,20 @@
 	}
       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 (df_regs_ever_live_p (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,
@@ -12221,10 +12235,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 (df_regs_ever_live_p (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
 	{
@@ -12912,7 +12939,7 @@
    number of bytes pushed.  */
 
 static int
-arm_save_coproc_regs(void)
+arm_save_coproc_regs(int saved_regs)
 {
   int saved_size = 0;
   unsigned reg;
@@ -12948,6 +12975,13 @@
       for (reg = LAST_CIRRUS_FP_REGNUM; reg >= FIRST_CIRRUS_FP_REGNUM; reg--)
         if (df_regs_ever_live_p (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.
+	     * Pushing Maverick registers without pushing ARM registers is rare
+	     * but can occur, e.g.in fftw3's fftw_iestimate_cost(). */
+	    if (saved_regs == 0 && saved_size == 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,
@@ -13264,7 +13298,7 @@
     }
 
   if (! IS_VOLATILE (func_type))
-    saved_regs += arm_save_coproc_regs ();
+    saved_regs += arm_save_coproc_regs (saved_regs);
 
   if (frame_pointer_needed && TARGET_ARM)
     {
