Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	(revision 216300)
+++ gcc/config/sh/sh.c	(working copy)
@@ -2281,20 +2281,20 @@
   return t ^ (cmpval == cmpop);
 }
 
-/* Emit INSN, possibly in a PARALLEL with an USE of fpscr for SH4.  */
-
+/* Emit INSN, possibly in a PARALLEL with an USE/CLOBBER of FPSCR bits in case
+   of floating-point comparisons.  */
 static void
 sh_emit_set_t_insn (rtx insn, enum machine_mode mode)
 {
-  if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT)
+  if (TARGET_FPU_ANY && GET_MODE_CLASS (mode) == MODE_FLOAT
+      && GET_CODE (insn) != PARALLEL)
     {
       insn = gen_rtx_PARALLEL (VOIDmode,
-		       gen_rtvec (2, insn,
-			          gen_rtx_USE (VOIDmode, get_fpscr_rtx ())));
-      (mode == SFmode ? emit_sf_insn : emit_df_insn) (insn);
+	  gen_rtvec (3, insn,
+	      gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, FPSCR_STAT_REG)),
+	      gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, FPSCR_MODES_REG))));
     }
-  else
-    emit_insn (insn);
+  emit_insn (insn);
 }
 
 /* Prepare the operands for an scc instruction; make sure that the
@@ -7250,6 +7250,7 @@
 	     && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM
 	     && reg != RETURN_ADDRESS_POINTER_REGNUM
 	     && reg != T_REG && reg != GBR_REG
+	     && reg != FPSCR_MODES_REG && reg != FPSCR_STAT_REG
 	     /* Push fpscr only on targets which have FPU */
 	     && (reg != FPSCR_REG || TARGET_FPU_ANY))
 	  : (/* Only push those regs which are used and need to be saved.  */
@@ -10070,44 +10071,6 @@
   dst = get_fpscr_rtx ();
   emit_move_insn (dst, src);
 }
-
-void
-emit_sf_insn (rtx pat)
-{
-  emit_insn (pat);
-}
-
-void
-emit_df_insn (rtx pat)
-{
-  emit_insn (pat);
-}
-
-void
-expand_sf_unop (rtx (*fun) (rtx, rtx, rtx), rtx *operands)
-{
-  emit_sf_insn ((*fun) (operands[0], operands[1], get_fpscr_rtx ()));
-}
-
-void
-expand_sf_binop (rtx (*fun) (rtx, rtx, rtx, rtx), rtx *operands)
-{
-  emit_sf_insn ((*fun) (operands[0], operands[1], operands[2],
-			 get_fpscr_rtx ()));
-}
-
-void
-expand_df_unop (rtx (*fun) (rtx, rtx, rtx), rtx *operands)
-{
-  emit_df_insn ((*fun) (operands[0], operands[1], get_fpscr_rtx ()));
-}
-
-void
-expand_df_binop (rtx (*fun) (rtx, rtx, rtx, rtx), rtx *operands)
-{
-  emit_df_insn ((*fun) (operands[0], operands[1], operands[2],
-			get_fpscr_rtx ()));
-}
 
 static rtx get_free_reg (HARD_REG_SET);
 
@@ -13308,6 +13271,9 @@
     for (regno = FIRST_GENERAL_REG; regno <= LAST_GENERAL_REG; regno++)
       if (! fixed_regs[regno] && call_really_used_regs[regno])
 	SET_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);
+
+  call_really_used_regs[FPSCR_MODES_REG] = 0;
+  call_really_used_regs[FPSCR_STAT_REG] = 0;
 }
 
 /* Implement TARGET_LEGITIMATE_CONSTANT_P
@@ -13659,7 +13625,7 @@
 
 static void
 sh_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode,
-		  int prev_mode, HARD_REG_SET regs_live)
+		  int prev_mode, HARD_REG_SET regs_live ATTRIBUTE_UNUSED)
 {
   if ((TARGET_SH4A_FP || TARGET_SH4_300)
       && prev_mode != FP_MODE_NONE && prev_mode != mode)
@@ -13668,8 +13634,36 @@
       if (TARGET_FMOVD)
 	emit_insn (gen_toggle_sz ());
     }
-  else
-    fpscr_set_from_mem (mode, regs_live);
+  else if (mode != FP_MODE_NONE)
+    {
+      rtx tmp0 = gen_reg_rtx (PSImode);
+      rtx tmp1 = gen_reg_rtx (SImode);
+
+      emit_move_insn (tmp0, get_fpscr_rtx ());
+      emit_insn (gen_extend_psi_si (tmp1, tmp0));
+
+      rtx i = NULL;
+
+      const unsigned HOST_WIDE_INT fpbits =
+	  TARGET_FMOVD ? (FPSCR_PR | FPSCR_SZ) : FPSCR_PR;
+
+      if (prev_mode != FP_MODE_NONE && prev_mode != mode)
+	i = gen_xorsi3 (tmp1, tmp1,
+			force_reg (SImode, GEN_INT (fpbits)));
+      else if (mode == FP_MODE_SINGLE)
+	i = gen_andsi3 (tmp1, tmp1,
+			force_reg (SImode, GEN_INT (~fpbits)));
+      else if (mode == FP_MODE_DOUBLE)
+	i = gen_iorsi3 (tmp1, tmp1,
+			force_reg (SImode, GEN_INT (fpbits)));
+      else
+	gcc_unreachable ();
+
+      emit_insn (i);
+
+      emit_insn (gen_truncate_si_psi (tmp0, tmp1));
+      emit_move_insn (get_fpscr_rtx (), tmp0);
+    }
 }
 
 static int
Index: gcc/config/sh/sh.h
===================================================================
--- gcc/config/sh/sh.h	(revision 216300)
+++ gcc/config/sh/sh.h	(working copy)
@@ -574,7 +574,7 @@
 	fr4..fr11	fp args in
 	fr12..fr15	call saved floating point registers  */
 
-#define MAX_REGISTER_NAME_LENGTH 5
+#define MAX_REGISTER_NAME_LENGTH 6
 extern char sh_register_names[][MAX_REGISTER_NAME_LENGTH + 1];
 
 #define SH_REGISTER_NAMES_INITIALIZER					\
@@ -598,7 +598,7 @@
   "tr0",  "tr1",  "tr2",  "tr3",  "tr4",  "tr5",  "tr6",  "tr7", 	\
   "xd0",  "xd2",  "xd4",  "xd6",  "xd8",  "xd10", "xd12", "xd14",	\
   "gbr",  "ap",	  "pr",   "t",    "mach", "macl", "fpul", "fpscr",	\
-  "rap",  "sfp"								\
+  "rap",  "sfp", "fpscr0", "fpscr1"					\
 }
 
 #define REGNAMES_ARR_INDEX_1(index) \
@@ -623,7 +623,7 @@
   REGNAMES_ARR_INDEX_8 (128), \
   REGNAMES_ARR_INDEX_8 (136), \
   REGNAMES_ARR_INDEX_8 (144), \
-  REGNAMES_ARR_INDEX_2 (152) \
+  REGNAMES_ARR_INDEX_4 (152) \
 }
 
 #define ADDREGNAMES_SIZE 32
@@ -711,7 +711,8 @@
 
 #define SPECIAL_REGISTER_P(REGNO) \
   ((REGNO) == GBR_REG || (REGNO) == T_REG \
-   || (REGNO) == MACH_REG || (REGNO) == MACL_REG)
+   || (REGNO) == MACH_REG || (REGNO) == MACL_REG \
+   || (REGNO) == FPSCR_MODES_REG || (REGNO) == FPSCR_STAT_REG)
 
 #define TARGET_REGISTER_P(REGNO) \
   ((int) (REGNO) >= FIRST_TARGET_REG && (int) (REGNO) <= LAST_TARGET_REG)
@@ -738,10 +739,10 @@
    ? DImode \
    : SImode)
 
-#define FIRST_PSEUDO_REGISTER 154
+#define FIRST_PSEUDO_REGISTER 156
 
 /* Don't count soft frame pointer.  */
-#define DWARF_FRAME_REGISTERS (FIRST_PSEUDO_REGISTER - 1)
+#define DWARF_FRAME_REGISTERS (153)
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
@@ -777,8 +778,8 @@
   0,      0,      0,      0,      0,      0,      0,      0,		\
 /*"gbr",  "ap",	  "pr",   "t",    "mach", "macl", "fpul", "fpscr", */	\
   1,      1,      1,      1,      1,      1,      0,      1,		\
-/*"rap",  "sfp" */							\
-  1,	  1,								\
+/*"rap",  "sfp","fpscr0","fpscr1"  */					\
+  1,      1,      1,      1,						\
 }
 
 /* 1 for registers not available across function calls.
@@ -816,8 +817,8 @@
   1,      1,      1,      1,      1,      1,      0,      0,		\
 /*"gbr",  "ap",	  "pr",   "t",    "mach", "macl", "fpul", "fpscr", */	\
   1,      1,      1,      1,      1,      1,      1,      1,		\
-/*"rap",  "sfp" */							\
-  1,	  1,								\
+/*"rap",  "sfp","fpscr0","fpscr1"  */					\
+  1,      1,      1,      1,						\
 }
 
 /* TARGET_CONDITIONAL_REGISTER_USAGE might want to make a register
@@ -1072,7 +1073,7 @@
 /* TARGET_REGS:  */							\
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000ff },	\
 /* ALL_REGS:  */							\
-  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x03ffffff },	\
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0fffffff },	\
 }
 
 /* The same information, inverted:
@@ -1122,7 +1123,7 @@
    128,129,130,131,132,133,134,135, \
    /* Fixed registers */ \
     15, 16, 24, 25, 26, 27, 63,144, \
-   145,146,147,148,149,152,153 }
+   145,146,147,148,149,152,153,154,155  }
 
 /* The class value for index registers, and the one for base regs.  */
 #define INDEX_REG_CLASS \
Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md	(revision 216300)
+++ gcc/config/sh/sh.md	(working copy)
@@ -76,6 +76,12 @@
 
   (FPSCR_REG	151)
 
+  ;; Virtual FPSCR - bits that are used by FP ops.
+  (FPSCR_MODES_REG 154)
+
+  ;; Virtual FPSCR - bits that are updated by FP ops.
+  (FPSCR_STAT_REG 155)
+
   (PIC_REG	12)
   (FP_REG	14)
   (SP_REG	15)
@@ -109,6 +115,9 @@
   (TR2_REG	130)
 
   (XD0_REG	136)
+
+  (FPSCR_PR	524288)
+  (FPSCR_SZ	1048576)
 ])
 
 (define_c_enum "unspec" [
@@ -176,6 +185,9 @@
   UNSPECV_GBR
   UNSPECV_SP_SWITCH_B
   UNSPECV_SP_SWITCH_E
+
+  UNSPECV_FPSCR_MODES
+  UNSPECV_FPSCR_STAT
 ])
 
 ;; -------------------------------------------------------------------------
@@ -2395,7 +2407,8 @@
    (clobber (reg:SI R1_REG))
    (clobber (reg:SI R4_REG))
    (clobber (reg:SI R5_REG))
-   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
   "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
   "jsr	@%1%#"
@@ -2666,7 +2679,8 @@
    (clobber (reg:SI PR_REG))
    (clobber (reg:DF DR0_REG))
    (clobber (reg:DF DR2_REG))
-   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
   "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE"
   "jsr	@%1%#"
@@ -6444,7 +6458,7 @@
 (define_expand "push_e"
   [(parallel [(set (mem:SF (pre_dec:SI (reg:SI SP_REG)))
 		   (match_operand:SF 0 "" ""))
-	      (use (reg:PSI FPSCR_REG))
+	      (use (reg:SI FPSCR_MODES_REG))
 	      (clobber (scratch:SI))])]
   "TARGET_SH1 && ! TARGET_SH5"
   "")
@@ -6462,7 +6476,7 @@
 (define_expand "push_4"
   [(parallel [(set (mem:DF (pre_dec:SI (reg:SI SP_REG)))
 		   (match_operand:DF 0 "" ""))
-	      (use (reg:PSI FPSCR_REG))
+	      (use (reg:SI FPSCR_MODES_REG))
 	      (clobber (scratch:SI))])]
   "TARGET_SH1 && ! TARGET_SH5"
   "")
@@ -6470,7 +6484,7 @@
 (define_expand "pop_e"
   [(parallel [(set (match_operand:SF 0 "" "")
 	      (mem:SF (post_inc:SI (reg:SI SP_REG))))
-	      (use (reg:PSI FPSCR_REG))
+	      (use (reg:SI FPSCR_MODES_REG))
 	      (clobber (scratch:SI))])]
   "TARGET_SH1 && ! TARGET_SH5"
   "")
@@ -6485,7 +6499,7 @@
 (define_expand "pop_4"
   [(parallel [(set (match_operand:DF 0 "" "")
 		   (mem:DF (post_inc:SI (reg:SI SP_REG))))
-	      (use (reg:PSI FPSCR_REG))
+	      (use (reg:SI FPSCR_MODES_REG))
 	      (clobber (scratch:SI))])]
   "TARGET_SH1 && ! TARGET_SH5"
   "")
@@ -7655,8 +7669,8 @@
 (define_insn "movdf_i4"
   [(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
 	(match_operand:DF 1 "general_movsrc_operand"  "d,r,F,m,d,FQ,m,r,d,r"))
-   (use (match_operand:PSI 2 "fpscr_operand"          "c,c,c,c,c,c,c,c,c,c"))
-   (clobber (match_scratch:SI 3                      "=X,X,&z,X,X,X,X,X,X,X"))]
+   (use (reg:SI FPSCR_MODES_REG))
+   (clobber (match_scratch:SI 2                      "=X,X,&z,X,X,X,X,X,X,X"))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
    && (arith_reg_operand (operands[0], DFmode)
        || arith_reg_operand (operands[1], DFmode))"
@@ -7711,8 +7725,8 @@
 (define_split
   [(set (match_operand:DF 0 "register_operand")
 	(match_operand:DF 1 "register_operand"))
-   (use (match_operand:PSI 2 "fpscr_operand"))
-   (clobber (match_scratch:SI 3))]
+   (use (reg:SI FPSCR_MODES_REG))
+   (clobber (match_scratch:SI 2))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed
    && (true_regnum (operands[0]) < 16) != (true_regnum (operands[1]) < 16)"
   [(const_int 0)]
@@ -7728,7 +7742,7 @@
   else
     tos = gen_tmp_stack_mem (DFmode,
 			     gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
-  insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
+  insn = emit_insn (gen_movdf_i4 (tos, operands[1]));
   if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
     add_reg_note (insn, REG_INC, stack_pointer_rtx);
   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
@@ -7736,7 +7750,7 @@
   else
     tos = gen_tmp_stack_mem (DFmode,
 			     gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
-  insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
+  insn = emit_insn (gen_movdf_i4 (operands[0], tos));
   if (TARGET_SH5 && true_regnum (operands[0]) < 16)
     emit_move_insn (stack_pointer_rtx,
 		    plus_constant (Pmode, stack_pointer_rtx, 8));
@@ -7752,8 +7766,8 @@
 (define_split
   [(set (match_operand:DF 0 "general_movdst_operand" "")
 	(match_operand:DF 1 "general_movsrc_operand"  ""))
-   (use (match_operand:PSI 2 "fpscr_operand" ""))
-   (clobber (match_scratch:SI 3 ""))]
+   (use (reg:SI FPSCR_MODES_REG))
+   (clobber (match_scratch:SI 2))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
    && reload_completed
    && true_regnum (operands[0]) < 16
@@ -7824,18 +7838,18 @@
 (define_split
   [(set (match_operand:DF 0 "register_operand" "")
 	(match_operand:DF 1 "memory_operand"  ""))
-   (use (match_operand:PSI 2 "fpscr_operand" ""))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI R0_REG))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && reload_completed"
   [(parallel [(set (match_dup 0) (match_dup 1))
-	      (use (match_dup 2))
+	      (use (reg:SI FPSCR_MODES_REG))
 	      (clobber (scratch:SI))])]
   "")
 
 (define_expand "reload_indf__frn"
   [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
 		   (match_operand:DF 1 "immediate_operand" "FQ"))
-	      (use (reg:PSI FPSCR_REG))
+	      (use (reg:SI FPSCR_MODES_REG))
 	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
   "TARGET_SH1"
   "")
@@ -7851,8 +7865,8 @@
 (define_split
   [(set (match_operand:SF 0 "register_operand" "")
 	(match_operand:SF 1 "register_operand" ""))
-   (use (match_operand:PSI 2 "fpscr_operand" ""))
-   (clobber (match_scratch:SI 3 ""))]
+   (use (reg:SI FPSCR_MODES_REG))
+   (clobber (match_scratch:SI 2))]
   "TARGET_SH2E && reload_completed
    && true_regnum (operands[0]) == true_regnum (operands[1])"
   [(set (match_dup 0) (match_dup 0))]
@@ -7862,8 +7876,8 @@
 (define_split
   [(set (match_operand:DF 0 "register_operand" "")
 	(match_operand:DF 1 "register_operand" ""))
-   (use (match_operand:PSI 2 "fpscr_operand" ""))
-   (clobber (match_scratch:SI 3 ""))]
+   (use (reg:SI FPSCR_MODES_REG))
+   (clobber (match_scratch:SI 2))]
   "TARGET_SH4 && ! TARGET_FMOVD && reload_completed
    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
@@ -7871,17 +7885,17 @@
 {
   int dst = true_regnum (operands[0]), src = true_regnum (operands[1]);
   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst),
-			   gen_rtx_REG (SFmode, src), operands[2]));
+			   gen_rtx_REG (SFmode, src)));
   emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, dst + 1),
-			   gen_rtx_REG (SFmode, src + 1), operands[2]));
+			   gen_rtx_REG (SFmode, src + 1)));
   DONE;
 })
 
 (define_split
   [(set (match_operand:DF 0 "register_operand" "")
 	(mem:DF (match_operand:SI 1 "register_operand" "")))
-   (use (match_operand:PSI 2 "fpscr_operand" ""))
-   (clobber (match_scratch:SI 3 ""))]
+   (use (reg:SI FPSCR_MODES_REG))
+   (clobber (match_scratch:SI 2))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))
    && find_regno_note (insn, REG_DEAD, true_regnum (operands[1]))"
@@ -7894,20 +7908,19 @@
     = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
 					       regno + SH_REG_MSW_OFFSET),
-				  mem2, operands[2]));
+				  mem2));
   add_reg_note (insn, REG_INC, operands[1]);
   insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
 					       regno + SH_REG_LSW_OFFSET),
-				  change_address (mem, SFmode, NULL_RTX),
-				  operands[2]));
+				  change_address (mem, SFmode, NULL_RTX)));
   DONE;
 })
 
 (define_split
   [(set (match_operand:DF 0 "register_operand" "")
 	(match_operand:DF 1 "memory_operand" ""))
-   (use (match_operand:PSI 2 "fpscr_operand" ""))
-   (clobber (match_scratch:SI 3 ""))]
+   (use (reg:SI FPSCR_MODES_REG))
+   (clobber (match_scratch:SI 2))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
    && FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
   [(const_int 0)]
@@ -7930,10 +7943,10 @@
       if (! arith_reg_operand (operands[1], SFmode))
 	{
 	  XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
-	  insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
+	  insn = emit_insn (gen_movsf_ie (reg0, mem2));
 	  add_reg_note (insn, REG_INC, XEXP (addr, 0));
 	  
-	  emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
+	  emit_insn (gen_movsf_ie (reg1, operands[1]));
 
 	  /* If we have modified the stack pointer, the value that we have
 	     read with post-increment might be modified by an interrupt,
@@ -7948,17 +7961,17 @@
       /* Fall through.  */
 
     case PLUS:
-      emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
+      emit_insn (gen_movsf_ie (reg0, operands[1]));
       operands[1] = copy_rtx (operands[1]);
       XEXP (operands[1], 0) = plus_constant (Pmode, addr, 4);
-      emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
+      emit_insn (gen_movsf_ie (reg1, operands[1]));
       break;
 
     case POST_INC:
-      insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
+      insn = emit_insn (gen_movsf_ie (reg0, operands[1]));
       add_reg_note (insn, REG_INC, XEXP (addr, 0));
 
-      insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
+      insn = emit_insn (gen_movsf_ie (reg1, operands[1]));
       add_reg_note (insn, REG_INC, XEXP (addr, 0));
       break;
 
@@ -7973,8 +7986,8 @@
 (define_split
   [(set (match_operand:DF 0 "memory_operand" "")
 	(match_operand:DF 1 "register_operand" ""))
-   (use (match_operand:PSI 2 "fpscr_operand" ""))
-   (clobber (match_scratch:SI 3 ""))]
+   (use (reg:SI FPSCR_MODES_REG))
+   (clobber (match_scratch:SI 2))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
    && FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
   [(const_int 0)]
@@ -7997,12 +8010,12 @@
       if (! arith_reg_operand (operands[0], SFmode))
 	{
 	  emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
-	  emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
+	  emit_insn (gen_movsf_ie (operands[0], reg1));
 
 	  operands[0] = copy_rtx (operands[0]);
 	  XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
 	  
-	  insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
+	  insn = emit_insn (gen_movsf_ie (operands[0], reg0));
 	  add_reg_note (insn, REG_INC, XEXP (addr, 0));
 	  break;
 	}
@@ -8014,12 +8027,12 @@
 	 register component of the address.  Just emit the lower numbered
 	 register first, to the lower address, then the higher numbered
 	 register to the higher address.  */
-      emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
+      emit_insn (gen_movsf_ie (operands[0], reg0));
 
       operands[0] = copy_rtx (operands[0]);
       XEXP (operands[0], 0) = plus_constant (Pmode, addr, 4);
 
-      emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
+      emit_insn (gen_movsf_ie (operands[0], reg1));
       break;
 
     case PRE_DEC:
@@ -8027,10 +8040,10 @@
          first (ie the word in the higher numbered register) then the
 	 word to go to the lower address.  */
 
-      insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
+      insn = emit_insn (gen_movsf_ie (operands[0], reg1));
       add_reg_note (insn, REG_INC, XEXP (addr, 0));
 
-      insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
+      insn = emit_insn (gen_movsf_ie (operands[0], reg0));
       add_reg_note (insn, REG_INC, XEXP (addr, 0));
       break;
 
@@ -8112,7 +8125,7 @@
     }
   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
     {
-      emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
+      emit_insn (gen_movdf_i4 (operands[0], operands[1]));
       DONE;
     }
 })
@@ -8357,12 +8370,12 @@
 	 "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
 	(match_operand:SF 1 "general_movsrc_operand"
 	  "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
-   (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c"))
-   (clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
+   (use (reg:SI FPSCR_MODES_REG))
+   (clobber (match_scratch:SI 2 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
   "TARGET_SH2E
    && (arith_reg_operand (operands[0], SFmode) || fpul_operand (operands[0], SFmode)
        || arith_reg_operand (operands[1], SFmode) || fpul_operand (operands[1], SFmode)
-       || arith_reg_operand (operands[3], SImode))"
+       || arith_reg_operand (operands[2], SImode))"
   "@
 	fmov	%1,%0
 	mov	%1,%0
@@ -8441,14 +8454,14 @@
 (define_split
   [(set (match_operand:SF 0 "register_operand" "")
 	(match_operand:SF 1 "register_operand" ""))
-   (use (match_operand:PSI 2 "fpscr_operand" ""))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI FPUL_REG))]
   "TARGET_SH1"
   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
-	      (use (match_dup 2))
+	      (use (reg:SI FPSCR_MODES_REG))
 	      (clobber (scratch:SI))])
    (parallel [(set (match_dup 0) (reg:SF FPUL_REG))
-	      (use (match_dup 2))
+	      (use (reg:SI FPSCR_MODES_REG))
 	      (clobber (scratch:SI))])]
   "")
 
@@ -8468,7 +8481,7 @@
     }
   if (TARGET_SH2E)
     {
-      emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
+      emit_insn (gen_movsf_ie (operands[0], operands[1]));
       DONE;
     }
 })
@@ -8483,7 +8496,7 @@
 (define_expand "reload_insf__frn"
   [(parallel [(set (match_operand:SF 0 "register_operand" "=a")
 		   (match_operand:SF 1 "immediate_operand" "FQ"))
-	      (use (reg:PSI FPSCR_REG))
+	      (use (reg:SI FPSCR_MODES_REG))
 	      (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
   "TARGET_SH1"
   "")
@@ -8929,7 +8942,7 @@
 })
 
 (define_insn "force_mode_for_call"
-  [(use (reg:PSI FPSCR_REG))]
+  [(use (reg:SI FPSCR_MODES_REG))]
   "TARGET_SHCOMPACT"
   ""
   [(set_attr "length" "0")
@@ -8940,7 +8953,7 @@
 (define_insn "calli"
   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
 	 (match_operand 1 "" ""))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SH1"
 {
@@ -8962,7 +8975,7 @@
 (define_insn "calli_tbr_rel"
   [(call (mem (match_operand:SI 0 "symbol_ref_operand" ""))
 	 (match_operand 1 "" ""))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SH2A && sh2a_is_function_vector_call (operands[0])"
 {
@@ -8983,7 +8996,7 @@
 (define_insn "calli_pcrel"
   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
 	 (match_operand 1 "" ""))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (use (reg:SI PIC_REG))
    (use (match_operand 2 "" ""))
    (clobber (reg:SI PR_REG))]
@@ -9002,7 +9015,7 @@
 (define_insn_and_split "call_pcrel"
   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
 	 (match_operand 1 "" ""))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (use (reg:SI PIC_REG))
    (clobber (reg:SI PR_REG))
    (clobber (match_scratch:SI 2 "=r"))]
@@ -9033,7 +9046,7 @@
    (match_operand 2 "immediate_operand" "n")
    (use (reg:SI R0_REG))
    (use (reg:SI R1_REG))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
   "jsr	@%0%#"
@@ -9049,7 +9062,7 @@
    (match_operand 2 "immediate_operand" "n")
    (use (reg:SI R0_REG))
    (use (reg:SI R1_REG))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI R10_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
@@ -9072,7 +9085,7 @@
   [(set (match_operand 0 "" "=rf")
 	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
 	      (match_operand 2 "" "")))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SH1"
 {
@@ -9095,7 +9108,7 @@
   [(set (match_operand 0 "" "=rf")
 	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
 	      (match_operand 2 "" "")))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SH2A && sh2a_is_function_vector_call (operands[1])"
 {
@@ -9116,7 +9129,7 @@
   [(set (match_operand 0 "" "=rf")
 	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
 	      (match_operand 2 "" "")))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (use (reg:SI PIC_REG))
    (use (match_operand 3 "" ""))
    (clobber (reg:SI PR_REG))]
@@ -9136,7 +9149,7 @@
   [(set (match_operand 0 "" "=rf")
 	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
 	      (match_operand 2 "" "")))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (use (reg:SI PIC_REG))
    (clobber (reg:SI PR_REG))
    (clobber (match_scratch:SI 3 "=r"))]
@@ -9169,7 +9182,7 @@
    (match_operand 3 "immediate_operand" "n")
    (use (reg:SI R0_REG))
    (use (reg:SI R1_REG))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
   "jsr	@%1%#"
@@ -9186,7 +9199,7 @@
    (match_operand 3 "immediate_operand" "n")
    (use (reg:SI R0_REG))
    (use (reg:SI R1_REG))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI R10_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
@@ -9210,7 +9223,7 @@
   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
 			    (match_operand 1 "" ""))
 	      (match_operand 2 "" "")
-	      (use (reg:PSI FPSCR_REG))
+	      (use (reg:SI FPSCR_MODES_REG))
 	      (clobber (reg:SI PR_REG))])]
   ""
 {
@@ -9309,7 +9322,7 @@
 				 (match_operand 3 "immediate_operand" "n")))
    (use (reg:SI R0_REG))
    (use (reg:SI R1_REG))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
   "jsr	@%0%#"
@@ -9327,7 +9340,7 @@
 				 (match_operand 3 "immediate_operand" "n")))
    (use (reg:SI R0_REG))
    (use (reg:SI R1_REG))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI R10_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
@@ -9398,7 +9411,7 @@
 		   (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
 				 (match_operand 2 "" "")))
 	      (match_operand 3 "" "")
-	      (use (reg:PSI FPSCR_REG))
+	      (use (reg:SI FPSCR_MODES_REG))
 	      (clobber (reg:SI PR_REG))])]
   ""
 {
@@ -9493,7 +9506,7 @@
 (define_insn "sibcalli"
   [(call (mem:SI (match_operand:SI 0 "register_operand" "k"))
 	 (match_operand 1 "" ""))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (return)]
   "TARGET_SH1"
   "jmp	@%0%#"
@@ -9507,7 +9520,7 @@
   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k"))
 	 (match_operand 1 "" ""))
    (use (match_operand 2 "" ""))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (return)]
   "TARGET_SH2"
 {
@@ -9525,7 +9538,7 @@
   [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")]
 			     UNSPEC_THUNK))
 	 (match_operand 1 "" ""))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (return)]
   "TARGET_SH1"
   "bra	%O0"
@@ -9539,7 +9552,7 @@
 (define_insn_and_split "sibcall_pcrel"
   [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
 	 (match_operand 1 "" ""))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (match_scratch:SI 2 "=k"))
    (return)]
   "TARGET_SH2"
@@ -9568,7 +9581,7 @@
    (return)
    (use (match_operand:SI 2 "register_operand" "z,x"))
    (use (reg:SI R1_REG))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    ;; We want to make sure the `x' above will only match MACH_REG
    ;; because sibcall_epilogue may clobber MACL_REG.
    (clobber (reg:SI MACL_REG))]
@@ -9602,7 +9615,7 @@
     [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
 	   (match_operand 1 "" ""))
      (match_operand 2 "" "")
-     (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
      (return)])]
   ""
 {
@@ -9699,7 +9712,7 @@
   [(set (match_operand 0 "" "=rf")
 	(call (mem:SI (match_operand:SI 1 "register_operand" "k"))
 	      (match_operand 2 "" "")))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (return)]
   "TARGET_SH1"
   "jmp	@%1%#"
@@ -9714,7 +9727,7 @@
 	(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k"))
 	      (match_operand 2 "" "")))
    (use (match_operand 3 "" ""))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (return)]
   "TARGET_SH2"
 {
@@ -9731,7 +9744,7 @@
   [(set (match_operand 0 "" "=rf")
 	(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
 	      (match_operand 2 "" "")))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (match_scratch:SI 3 "=k"))
    (return)]
   "TARGET_SH2"
@@ -9763,7 +9776,7 @@
    (return)
    (use (match_operand:SI 3 "register_operand" "z,x"))
    (use (reg:SI R1_REG))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    ;; We want to make sure the `x' above will only match MACH_REG
    ;; because sibcall_epilogue may clobber MACL_REG.
    (clobber (reg:SI MACL_REG))]
@@ -9799,7 +9812,7 @@
 	  (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
 	  	(match_operand 2 "" "")))
      (match_operand 3 "" "")
-     (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
      (return)])]
   ""
 {
@@ -9905,7 +9918,7 @@
    (match_operand 3 "immediate_operand" "n")
    (use (reg:SI R0_REG))
    (use (reg:SI R1_REG))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
   "jsr	@%1%#"
@@ -9924,7 +9937,7 @@
    (match_operand 3 "immediate_operand" "n")
    (use (reg:SI R0_REG))
    (use (reg:SI R1_REG))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (clobber (reg:SI R10_REG))
    (clobber (reg:SI PR_REG))]
   "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
@@ -10430,7 +10443,7 @@
 	(call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
 				  UNSPEC_TLSGD))
 	      (const_int 0)))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (use (reg:SI PIC_REG))
    (clobber (reg:SI PR_REG))
    (clobber (scratch:SI))]
@@ -10457,7 +10470,7 @@
 	(call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")]
 				  UNSPEC_TLSLDM))
 	      (const_int 0)))
-   (use (reg:PSI FPSCR_REG))
+   (use (reg:SI FPSCR_MODES_REG))
    (use (reg:SI PIC_REG))
    (clobber (reg:SI PR_REG))
    (clobber (scratch:SI))]
@@ -12199,8 +12212,11 @@
 (define_expand "movpsi"
   [(set (match_operand:PSI 0 "register_operand" "")
 	(match_operand:PSI 1 "general_movsrc_operand" ""))]
-  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
-  "")
+  "TARGET_FPU_ANY"
+{
+  emit_insn (gen_fpu_switch (operands[0], operands[1]));
+  DONE;
+})
 
 ;; The c / m alternative is a fake to guide reload to load directly into
 ;; fpscr, since reload doesn't know how to use post-increment.
@@ -12211,8 +12227,14 @@
 ;; like a mac -> gpr move.
 (define_insn "fpu_switch"
   [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<")
-	(match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))]
-  "TARGET_SH2E
+	(match_operand:PSI 1 "general_movsrc_operand" " c,>,m,m,r,r,r,!c,c"))
+   (use (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))
+   (set (reg:SI FPSCR_STAT_REG)
+	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_STAT))
+   (set (reg:SI FPSCR_MODES_REG)
+	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
+  "TARGET_FPU_ANY
    && (! reload_completed
        || true_regnum (operands[0]) != FPSCR_REG
        || !MEM_P (operands[1])
@@ -12231,44 +12253,52 @@
    (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,
 		     mac_gp,fstore")])
 
-(define_peephole2
+(define_split
   [(set (reg:PSI FPSCR_REG)
-	(mem:PSI (match_operand:SI 0 "register_operand" "")))]
-  "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
+        (match_operand:PSI 0 "simple_mem_operand"))
+   (use (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))
+   (set (reg:SI FPSCR_STAT_REG)
+	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_STAT))
+   (set (reg:SI FPSCR_MODES_REG)
+	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
+  "TARGET_FPU_ANY && reload_completed"
   [(const_int 0)]
 {
-  rtx fpscr, mem, new_insn;
+  rtx addrreg = XEXP (operands[0], 0);
+  rtx mem = replace_equiv_address (operands[0],
+				   gen_rtx_POST_INC (Pmode, addrreg));
 
-  fpscr = SET_DEST (PATTERN (curr_insn));
-  mem = SET_SRC (PATTERN (curr_insn));
-  mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
+  add_reg_note (emit_insn (gen_fpu_switch (get_fpscr_rtx (), mem)),
+		REG_INC, addrreg);
 
-  new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
-  add_reg_note (new_insn, REG_INC, operands[0]);
-  DONE;
+  /* Modify the address reg to compensate for the forced post-inc mode.
+     If the address reg becomes dead afterwards, the add will be eliminated
+     automatically.  */
+  emit_insn (gen_addsi3 (addrreg, addrreg, GEN_INT (-4)));
 })
 
-(define_split
-  [(set (reg:PSI FPSCR_REG)
-	(mem:PSI (match_operand:SI 0 "register_operand" "")))]
-  "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
-   && (flag_peephole2 ? epilogue_completed : reload_completed)"
-  [(const_int 0)]
-{
-  rtx fpscr, mem, new_insn;
+;; The 'extend_psi_si' and 'truncate_si_psi' insns are needed since we can't
+;; do logic on PSImode.  Adding PSImode logic patterns works, but loading
+;; a PSImode constant causes a double indirection, since the SH constant pool
+;; is not aware of it.
+;; FIXME: We could treat the FPSCR reg as SImode, but currently this causes
+;; additional troubles.
+(define_insn "extend_psi_si"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+	(zero_extend:SI (match_operand:PSI 1 "arith_reg_operand" "0")))]
+  "TARGET_SH1"
+  ""
+  [(set_attr "length" "0")])
 
-  fpscr = SET_DEST (PATTERN (curr_insn));
-  mem = SET_SRC (PATTERN (curr_insn));
-  mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
+(define_insn "truncate_si_psi"
+  [(set (match_operand:PSI 0 "arith_reg_dest" "=r")
+	(truncate:PSI (match_operand:SI 1 "arith_reg_operand" "0")))]
+  "TARGET_SH1"
+  ""
+  [(set_attr "length" "0")])
 
-  new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
-  add_reg_note (new_insn, REG_INC, operands[0]);
 
-  if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
-    emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
-  DONE;
-})
-
 ;; ??? This uses the fp unit, but has no type indicating that.
 ;; If we did that, this would either give a bogus latency or introduce
 ;; a bogus FIFO constraint.
@@ -12277,7 +12307,9 @@
 ;; current setting.
 (define_insn "toggle_sz"
   [(set (reg:PSI FPSCR_REG)
-	(xor:PSI (reg:PSI FPSCR_REG) (const_int 1048576)))]
+	(xor:PSI (reg:PSI FPSCR_REG) (const_int FPSCR_SZ)))
+   (set (reg:SI FPSCR_MODES_REG)
+	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "fschg"
   [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
@@ -12286,7 +12318,9 @@
 
 (define_insn "toggle_pr"
   [(set (reg:PSI FPSCR_REG)
-	(xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
+	(xor:PSI (reg:PSI FPSCR_REG) (const_int FPSCR_PR)))
+   (set (reg:SI FPSCR_MODES_REG)
+	(unspec_volatile:SI [(const_int 0)] UNSPECV_FPSCR_MODES))]
   "TARGET_SH4A_FP"
   "fpchg"
   [(set_attr "type" "fpscr_toggle")])
@@ -12299,7 +12333,7 @@
 {
   if (TARGET_SH2E)
     {
-      expand_sf_binop (&gen_addsf3_i, operands);
+      emit_insn (gen_addsf3_i (operands[0], operands[1], operands[2]));
       DONE;
     }
 })
@@ -12398,7 +12432,8 @@
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
 	(plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
 		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "TARGET_SH2E"
   "fadd	%2,%0"
   [(set_attr "type" "fp")
@@ -12412,7 +12447,7 @@
 {
   if (TARGET_SH2E)
     {
-      expand_sf_binop (&gen_subsf3_i, operands);
+      emit_insn (gen_subsf3_i (operands[0], operands[1], operands[2]));
       DONE;
     }
 })
@@ -12429,7 +12464,8 @@
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
 	(minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
 		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "TARGET_SH2E"
   "fsub	%2,%0"
   [(set_attr "type" "fp")
@@ -12443,8 +12479,7 @@
 {
   if (TARGET_SH2E)
     {
-      emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2],
-		 get_fpscr_rtx ()));
+      emit_insn (gen_mulsf3_i (operands[0], operands[1], operands[2]));
       DONE;
     }
 })
@@ -12461,7 +12496,8 @@
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
 	(mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
 		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "TARGET_SH2E"
   "fmul	%2,%0"
   [(set_attr "type" "fp")
@@ -12477,8 +12513,8 @@
 {
   if (TARGET_SH2E)
     {
-      emit_sf_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
-				  operands[3], get_fpscr_rtx ()));
+      emit_insn (gen_fmasf4_i (operands[0], operands[1], operands[2],
+			       operands[3]));
       DONE;
     }
 })
@@ -12488,7 +12524,8 @@
 	(fma:SF (match_operand:SF 1 "fp_arith_reg_operand" "w")
 		(match_operand:SF 2 "fp_arith_reg_operand" "f")
 		(match_operand:SF 3 "fp_arith_reg_operand" "0")))
-   (use (match_operand:PSI 4 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "TARGET_SH2E"
   "fmac	%1,%2,%0"
   [(set_attr "type" "fp")
@@ -12511,13 +12548,15 @@
 	(plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
 			  (match_operand:SF 2 "fp_arith_reg_operand" "f"))
 		 (match_operand:SF 3 "arith_reg_operand" "0")))
-   (use (match_operand:PSI 4 "fpscr_operand"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF"
   "fmac	%1,%2,%0"
   "&& can_create_pseudo_p ()"
   [(parallel [(set (match_dup 0)
 		   (fma:SF (match_dup 1) (match_dup 2) (match_dup 3)))
-	      (use (match_dup 4))])]
+	      (clobber (reg:SI FPSCR_STAT_REG))
+	      (use (reg:SI FPSCR_MODES_REG))])]
 {
   /* Change 'b * a + a' into 'a * b + a'.
      This is better for register allocation.  */
@@ -12548,7 +12587,7 @@
 {
   if (TARGET_SH2E)
     {
-      expand_sf_binop (&gen_divsf3_i, operands);
+      emit_insn (gen_divsf3_i (operands[0], operands[1], operands[2]));
       DONE;
     }
 })
@@ -12565,7 +12604,8 @@
   [(set (match_operand:SF 0 "fp_arith_reg_dest" "=f")
 	(div:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
 		 (match_operand:SF 2 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "TARGET_SH2E"
   "fdiv	%2,%0"
   [(set_attr "type" "fdiv")
@@ -12583,10 +12623,9 @@
 	(float:SF (match_operand:SI 1 "fpul_operand" "")))]
   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
 {
-  if (TARGET_SH4 || TARGET_SH2A_SINGLE)
+  if (!TARGET_SHMEDIA_FPU)
     {
-      emit_sf_insn (gen_floatsisf2_i4 (operands[0], operands[1],
-				       get_fpscr_rtx ()));
+      emit_insn (gen_floatsisf2_i4 (operands[0], operands[1]));
       DONE;
     }
 })
@@ -12601,19 +12640,13 @@
 (define_insn "floatsisf2_i4"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
 	(float:SF (match_operand:SI 1 "fpul_operand" "y")))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
-  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
+  "TARGET_SH2E"
   "float	%1,%0"
   [(set_attr "type" "fp")
    (set_attr "fp_mode" "single")])
 
-(define_insn "*floatsisf2_ie"
-  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
-	(float:SF (match_operand:SI 1 "fpul_operand" "y")))]
-  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
-  "float	%1,%0"
-  [(set_attr "type" "fp")])
-
 (define_insn "fix_truncsfdi2"
   [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f")
 	(fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
@@ -12626,10 +12659,9 @@
 	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
   "TARGET_SH2E || TARGET_SHMEDIA_FPU"
 {
-  if (TARGET_SH4 || TARGET_SH2A_SINGLE)
+  if (!TARGET_SHMEDIA_FPU)
     {
-      emit_sf_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1],
-					   get_fpscr_rtx ()));
+      emit_insn (gen_fix_truncsfsi2_i4 (operands[0], operands[1]));
       DONE;
     }
 })
@@ -12644,46 +12676,20 @@
 (define_insn "fix_truncsfsi2_i4"
   [(set (match_operand:SI 0 "fpul_operand" "=y")
 	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
-  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
+  "TARGET_SH2E"
   "ftrc	%1,%0"
   [(set_attr "type" "ftrc_s")
    (set_attr "fp_mode" "single")])
 
-;; ??? This pattern is used nowhere.  fix_truncsfsi2 always expands to
-;; fix_truncsfsi2_i4.
-;; (define_insn "fix_truncsfsi2_i4_2"
-;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
-;;	(fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
-;;   (use (reg:PSI FPSCR_REG))
-;;   (clobber (reg:SI FPUL_REG))]
-;;  "TARGET_SH4"
-;;  "#"
-;;  [(set_attr "length" "4")
-;;   (set_attr "fp_mode" "single")])
-
-;;(define_split
-;;  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
-;;	(fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
-;;   (use (match_operand:PSI 2 "fpscr_operand" "c"))
-;;   (clobber (reg:SI FPUL_REG))]
-;;  "TARGET_SH4"
-;;  [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
-;;	      (use (match_dup 2))])
-;;   (set (match_dup 0) (reg:SI FPUL_REG))])
-
-(define_insn "*fixsfsi"
-  [(set (match_operand:SI 0 "fpul_operand" "=y")
-	(fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
-  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
-  "ftrc	%1,%0"
-  [(set_attr "type" "fp")])
-
 (define_insn "cmpgtsf_t"
   [(set (reg:SI T_REG)
 	(gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
-	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
-  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
+	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
+  "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE"
   "fcmp/gt	%1,%0"
   [(set_attr "type" "fp_cmp")
    (set_attr "fp_mode" "single")])
@@ -12691,8 +12697,10 @@
 (define_insn "cmpeqsf_t"
   [(set (reg:SI T_REG)
 	(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
-	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
-  "TARGET_SH2E && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
+	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
+  "TARGET_SH2E || TARGET_SH4 || TARGET_SH2A_SINGLE"
   "fcmp/eq	%1,%0"
   [(set_attr "type" "fp_cmp")
    (set_attr "fp_mode" "single")])
@@ -12701,41 +12709,10 @@
   [(set (reg:SI T_REG)
 	(ior:SI (reg:SI T_REG)
 		(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
-		       (match_operand:SF 1 "fp_arith_reg_operand" "f"))))]
-  "TARGET_SH2E && TARGET_IEEE && ! (TARGET_SH4 || TARGET_SH2A_SINGLE)"
-{
-  return output_ieee_ccmpeq (insn, operands);
-}
-  [(set_attr "length" "4")])
-
-
-(define_insn "cmpgtsf_t_i4"
-  [(set (reg:SI T_REG)
-	(gt:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
-	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
-  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
-  "fcmp/gt	%1,%0"
-  [(set_attr "type" "fp_cmp")
-   (set_attr "fp_mode" "single")])
-
-(define_insn "cmpeqsf_t_i4"
-  [(set (reg:SI T_REG)
-	(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
-	       (match_operand:SF 1 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
-  "(TARGET_SH4 || TARGET_SH2A_SINGLE)"
-  "fcmp/eq	%1,%0"
-  [(set_attr "type" "fp_cmp")
-   (set_attr "fp_mode" "single")])
-
-(define_insn "*ieee_ccmpeqsf_t_4"
-  [(set (reg:SI T_REG)
-	(ior:SI (reg:SI T_REG)
-		(eq:SI (match_operand:SF 0 "fp_arith_reg_operand" "f")
 		       (match_operand:SF 1 "fp_arith_reg_operand" "f"))))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
-  "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_SINGLE)"
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
+  "TARGET_IEEE && TARGET_SH2E"
 {
   return output_ieee_ccmpeq (insn, operands);
 }
@@ -12817,7 +12794,7 @@
 {
   if (TARGET_SH3E)
     {
-      expand_sf_unop (&gen_sqrtsf2_i, operands);
+      emit_insn (gen_sqrtsf2_i (operands[0], operands[1]));
       DONE;
     }
 })
@@ -12832,7 +12809,8 @@
 (define_insn "sqrtsf2_i"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
 	(sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "TARGET_SH3E"
   "fsqrt	%0"
   [(set_attr "type" "fdiv")
@@ -12842,7 +12820,8 @@
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
 	(div:SF (match_operand:SF 1 "immediate_operand" "i")
 		(sqrt:SF (match_operand:SF 2 "fp_arith_reg_operand" "0"))))
-   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "TARGET_FPU_ANY && TARGET_FSRRA
    && operands[1] == CONST1_RTX (SFmode)"
   "fsrra	%0"
@@ -12864,10 +12843,9 @@
   rtx fsca = gen_reg_rtx (V2SFmode);
   rtx scale_reg = force_reg (SFmode, sh_fsca_sf2int ());
 
-  emit_sf_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
-  emit_sf_insn (gen_fix_truncsfsi2 (truncated, scaled));
-  emit_sf_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf (),
-			  get_fpscr_rtx ()));
+  emit_insn (gen_mulsf3 (scaled, operands[2], scale_reg));
+  emit_insn (gen_fix_truncsfsi2 (truncated, scaled));
+  emit_insn (gen_fsca (fsca, truncated, sh_fsca_int2sf ()));
 
   emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, fsca, 4));
   emit_move_insn (operands[1], gen_rtx_SUBREG (SFmode, fsca, 0));
@@ -12883,7 +12861,8 @@
 		    ] UNSPEC_FSINA)
 	 (unspec:SF [(mult:SF (float:SF (match_dup 1)) (match_dup 2))
 		    ] UNSPEC_FCOSA)))
-   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "TARGET_FPU_ANY && TARGET_FSCA"
   "fsca	fpul,%d0"
   "&& !fpul_operand (operands[1], SImode)"
@@ -12898,9 +12877,8 @@
       gcc_assert (GET_CODE (x) == FIX || GET_CODE (x) == FLOAT);
       x = XEXP (x, 0);
     }
-
   gcc_assert (x != NULL_RTX && fpul_operand (x, SImode));
-  emit_insn (gen_fsca (operands[0], x, operands[2], operands[3]));
+  emit_insn (gen_fsca (operands[0], x, operands[2]));
   DONE;
 }
   [(set_attr "type" "fsca")
@@ -12933,7 +12911,7 @@
 {
   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
     {
-      expand_df_binop (&gen_adddf3_i, operands);
+      emit_insn (gen_adddf3_i (operands[0], operands[1], operands[2]));
       DONE;
     }
 })
@@ -12950,7 +12928,8 @@
   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
 	(plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
 		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "fadd	%2,%0"
   [(set_attr "type" "dfp_arith")
@@ -12964,7 +12943,7 @@
 {
   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
     {
-      expand_df_binop (&gen_subdf3_i, operands);
+      emit_insn (gen_subdf3_i (operands[0], operands[1], operands[2]));
       DONE;
     }
 })
@@ -12981,7 +12960,8 @@
   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
 	(minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
 		  (match_operand:DF 2 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "fsub	%2,%0"
   [(set_attr "type" "dfp_arith")
@@ -12995,7 +12975,7 @@
 {
   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
     {
-      expand_df_binop (&gen_muldf3_i, operands);
+      emit_insn (gen_muldf3_i (operands[0], operands[1], operands[2]));
       DONE;
     }
 })
@@ -13012,7 +12992,8 @@
   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
 	(mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%0")
 		 (match_operand:DF 2 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "fmul	%2,%0"
   [(set_attr "type" "dfp_mul")
@@ -13026,7 +13007,7 @@
 {
   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
     {
-      expand_df_binop (&gen_divdf3_i, operands);
+      emit_insn (gen_divdf3_i (operands[0], operands[1], operands[2]));
       DONE;
     }
 })
@@ -13043,7 +13024,8 @@
   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
 	(div:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")
 		(match_operand:DF 2 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 3 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "fdiv	%2,%0"
   [(set_attr "type" "dfdiv")
@@ -13063,8 +13045,7 @@
 {
   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
     {
-      emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
-				      get_fpscr_rtx ()));
+      emit_insn (gen_floatsidf2_i (operands[0], operands[1]));
       DONE;
     }
 })
@@ -13079,7 +13060,8 @@
 (define_insn "floatsidf2_i"
   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
 	(float:DF (match_operand:SI 1 "fpul_operand" "y")))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "float	%1,%0"
   [(set_attr "type" "dfp_conv")
@@ -13099,8 +13081,7 @@
 {
   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
     {
-      emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
-					  get_fpscr_rtx ()));
+      emit_insn (gen_fix_truncdfsi2_i (operands[0], operands[1]));
       DONE;
     }
 })
@@ -13115,40 +13096,20 @@
 (define_insn "fix_truncdfsi2_i"
   [(set (match_operand:SI 0 "fpul_operand" "=y")
 	(fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "ftrc	%1,%0"
   [(set_attr "type" "dfp_conv")
    (set_attr "dfp_comp" "no")
    (set_attr "fp_mode" "double")])
 
-;; ??? This pattern is used nowhere.  fix_truncdfsi2 always expands to
-;; fix_truncdfsi2_i.
-;; (define_insn "fix_truncdfsi2_i4"
-;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
-;; 	(fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
-;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
-;;    (clobber (reg:SI FPUL_REG))]
-;;   "TARGET_SH4"
-;;   "#"
-;;   [(set_attr "length" "4")
-;;    (set_attr "fp_mode" "double")])
-;;
-;; (define_split
-;;   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
-;; 	(fix:SI (match_operand:DF 1 "arith_reg_operand" "f")))
-;;    (use (match_operand:PSI 2 "fpscr_operand" "c"))
-;;    (clobber (reg:SI FPUL_REG))]
-;;   "TARGET_SH4"
-;;   [(parallel [(set (reg:SI FPUL_REG) (fix:SI (match_dup 1)))
-;; 	      (use (match_dup 2))])
-;;    (set (match_dup 0) (reg:SI FPUL_REG))])
-
 (define_insn "cmpgtdf_t"
   [(set (reg:SI T_REG)
 	(gt:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
 	       (match_operand:DF 1 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "fcmp/gt	%1,%0"
   [(set_attr "type" "dfp_cmp")
@@ -13158,7 +13119,8 @@
   [(set (reg:SI T_REG)
 	(eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
 	       (match_operand:DF 1 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "fcmp/eq	%1,%0"
   [(set_attr "type" "dfp_cmp")
@@ -13169,7 +13131,8 @@
 	(ior:SI (reg:SI T_REG)
 		(eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
 		       (match_operand:DF 1 "fp_arith_reg_operand" "f"))))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
 {
   return output_ieee_ccmpeq (insn, operands);
@@ -13252,7 +13215,7 @@
 {
   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
     {
-      expand_df_unop (&gen_sqrtdf2_i, operands);
+      emit_insn (gen_sqrtdf2_i (operands[0], operands[1]));
       DONE;
     }
 })
@@ -13267,7 +13230,8 @@
 (define_insn "sqrtdf2_i"
   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
 	(sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0")))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "fsqrt	%0"
   [(set_attr "type" "dfdiv")
@@ -13299,8 +13263,7 @@
 {
   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
     {
-      emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
-					get_fpscr_rtx ()));
+      emit_insn (gen_extendsfdf2_i4 (operands[0], operands[1]));
       DONE;
     }
 })
@@ -13315,7 +13278,8 @@
 (define_insn "extendsfdf2_i4"
   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
 	(float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "fcnvsd  %1,%0"
   [(set_attr "type" "fp")
@@ -13328,8 +13292,7 @@
 {
   if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
     {
-      emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
-				       get_fpscr_rtx ()));
+      emit_insn (gen_truncdfsf2_i4 (operands[0], operands[1]));
       DONE;
     }
 })
@@ -13344,7 +13307,8 @@
 (define_insn "truncdfsf2_i4"
   [(set (match_operand:SF 0 "fpul_operand" "=y")
 	(float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
-   (use (match_operand:PSI 2 "fpscr_operand" "c"))]
+   (clobber (reg:SI FPSCR_STAT_REG))
+   (use (reg:SI FPSCR_MODES_REG))]
   "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
   "fcnvds  %1,%0"
   [(set_attr "type" "fp")
Index: gcc/config/sh/sh-protos.h
===================================================================
--- gcc/config/sh/sh-protos.h	(revision 216300)
+++ gcc/config/sh/sh-protos.h	(working copy)
@@ -112,8 +112,6 @@
 extern bool sh_legitimize_reload_address (rtx *, enum machine_mode, int, int);
 extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
 extern bool nonpic_symbol_mentioned_p (rtx);
-extern void emit_sf_insn (rtx);
-extern void emit_df_insn (rtx);
 extern void output_pic_addr_const (FILE *, rtx);
 extern bool expand_block_move (rtx *);
 extern void prepare_move_operands (rtx[], enum machine_mode mode);
@@ -150,10 +148,6 @@
 extern enum tls_model tls_symbolic_operand (rtx, enum machine_mode);
 extern bool system_reg_operand (rtx, enum machine_mode);
 extern bool reg_unused_after (rtx, rtx_insn *);
-extern void expand_sf_unop (rtx (*)(rtx, rtx, rtx), rtx *);
-extern void expand_sf_binop (rtx (*)(rtx, rtx, rtx, rtx), rtx *);
-extern void expand_df_unop (rtx (*)(rtx, rtx, rtx), rtx *);
-extern void expand_df_binop (rtx (*)(rtx, rtx, rtx, rtx), rtx *);
 extern int sh_insn_length_adjustment (rtx_insn *);
 extern bool sh_can_redirect_branch (rtx_insn *, rtx_insn *);
 extern void sh_expand_unop_v2sf (enum rtx_code, rtx, rtx);
Index: gcc/testsuite/gcc.target/sh/pr54680.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr54680.c	(revision 216300)
+++ gcc/testsuite/gcc.target/sh/pr54680.c	(working copy)
@@ -6,7 +6,7 @@
 /* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2*" "-m3*" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } }  */
 /* { dg-final { scan-assembler-times "fsca" 7 } } */
 /* { dg-final { scan-assembler-times "shad" 1 } } */
-/* { dg-final { scan-assembler-times "lds\t" 6 } } */
+/* { dg-final { scan-assembler-times "lds\tr\[0-9\],fpul" 6 } } */
 /* { dg-final { scan-assembler-times "fmul" 2 } } */
 /* { dg-final { scan-assembler-times "ftrc" 1 } } */
 
