diff mbox

[SH,committed] PR 53513 Make FPU mode switches not use __fpscr_values

Message ID 1413457416.31394.118.camel@yam-132-YW-E178-FTW
State New
Headers show

Commit Message

Oleg Endo Oct. 16, 2014, 11:03 a.m. UTC
Hi,

As discussed in the PR, the __fpscr_values based FPU mode switching is
replaced by other means, which preserve the other FPU mode and status
bits across mode switches.  For details please refer to the coments in
the PR.

Tested on sh-sim with -m4 -ml and -m4 -mb without new failures, except
for the expected interrupt function handling breakage.  As discussed in
the PR those not so common cases will be fixed later.  Committed as
r216307.

Cheers,
Oleg

gcc/ChangeLog
	PR target/53513
	* config/sh/sh-protos.h (emit_sf_insn, emit_df_insn, expand_sf_unop,
	expand_sf_binop, expand_df_unop, expand_df_binop): Remove.

	* config/sh/sh.c (sh_emit_set_t_insn): Adjust generated insn pattern
	to match fp insn patterns.
	(calc_live_regs): Add FPSCR_MODES_REG and FPSCR_STAT_REG to the ignore
	list.
	(emit_sf_insn, emit_df_insn, expand_sf_unop, expand_sf_binop,
	expand_df_unop, expand_df_binop): Remove.
	(sh_conditional_register_usage): Mark FPSCR_MODES_REG and
	FPSCR_STAT_REG as not call clobbered.
	(sh_emit_mode_set): Emit fpscr store-modify-load sequence instead of
	invoking fpscr_set_from_mem.

	* config/sh/sh.h (MAX_REGISTER_NAME_LENGTH): Increase to 6.
	(SH_REGISTER_NAMES_INITIALIZER): Add names for FPSCR_MODES_REG and
	FPSCR_STAT_REG.
	(REGISTER_NAMES): Adjust.
	(SPECIAL_REGISTER_P): Add FPSCR_MODES_REG and FPSCR_STAT_REG.
	(FIRST_PSEUDO_REGISTER): Increase to 156.
	(DWARF_FRAME_REGISTERS): Define as 153 to keep the original value.
	(FIXED_REGISTERS, CALL_USED_REGISTERS): Add FPSCR_MODES_REG and
	FPSCR_STAT_REG.
	(REG_CLASS_CONTENTS): Adjust ALL_REGS bit mask to include
	FPSCR_MODES_REG and FPSCR_STAT_REG.
	(REG_ALLOC_ORDER): Add FPSCR_MODES_REG and FPSCR_STAT_REG.

	* config/sh/sh.md (FPSCR_MODES_REG, FPSCR_STAT_REG, FPSCR_PR,
	FPSCR_SZ): Add new constants.
	(UNSPECV_FPSCR_MODES, UNSPECV_FPSCR_STAT): Add new unspecv constants.

	(movpsi): Use TARGET_FPU_ANY condition, invoke gen_fpu_switch.
	(fpu_switch): Add use and set of FPSCR_STAT_REG and FPSCR_MODES_REG.
	Use TARGET_FPU_ANY condition.
	(fpu_switch peephole2): Remove.
	(fpu_switch split): Use simple_mem_operand to capture the mem and
	adjust split implementation.
	(extend_psi_si, truncate_si_psi): New insns.
	(toggle_sz, toggle_pr): Use FPSCR_SZ, FPSCR_PR constants.  Add
	set of FPSCR_MODES_REG.

	(push_e, push_4, pop_e, pop_4, movdf_i4, reload_indf__frn, movsf_ie,
	reload_insf__frn, force_mode_for_call, calli, calli_tbr_rel,
	calli_pcrel, call_pcrel, call_compact, call_compact_rettramp,
	call_valuei, call_valuei_tbr_rel, call_valuei_pcrel, call_value_pcrel,
	call_value_compact, call_value_compact_rettramp, call,
	call_pop_compact, call_pop_compact_rettramp, call_value, sibcalli,
	sibcalli_pcrel, sibcalli_thunk, sibcall_pcrel, sibcall_compact,
	sibcall, sibcall_valuei, sibcall_valuei_pcrel, sibcall_value_pcrel,
	sibcall_value_compact, sibcall_value, call_value_pop_compact,
	call_value_pop_compact_rettramp, various unnamed splits):
	Replace use of FPSCR_REG with use of FPSCR_MODES_REG.  Adjust gen_*
	function uses.

	(floatsisf2_i4, *floatsisf2_ie): Merge into floatsisf2_i4.
	(fix_truncsfsi2_i4, *fixsfsi): Merge into fix_truncsfsi2_i4.
	(cmpgtsf_t, cmpgtsf_t_i4): Merge into cmpgtsf_t.
	(cmpeqsf_t, cmpeqsf_t_i4): Merge into cmpeqsf_t.
	(ieee_ccmpeqsf_t, *ieee_ccmpeqsf_t_4): Merge into ieee_ccmpeqsf_t.

	(udivsi3_i4, divsi3_i4, addsf3_i, subsf3_i, mulsf3_i, fmasf4_i,
	*fmasf4, divsf3_i, floatsisf2_i4, fix_truncsfsi2_i4, cmpgtsf_t,
	cmpeqsf_t, ieee_ccmpeqsf_t, sqrtsf2_i, rsqrtsf2, fsca, adddf3_i,
	subdf3_i, muldf3_i, divdf3_i, floatsidf2_i, fix_truncdfsi2_i,
	cmpgtdf_t, cmpeqdf_t, *ieee_ccmpeqdf_t, sqrtdf2_i, extendsfdf2_i4,
	truncdfsf2_i4): Replace use of FPSCR_REG with clobber of FPSCR_STAT_REG
	and use of FPSCR_MODES_REG.  Adjust gen_* function uses.

gcc/testsuite/ChangeLog

	PR target/53513
	* gcc.target/sh/pr54680.c: Adjust matching of lds insn.
diff mbox

Patch

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