OSDN Git Service

* config/sh/sh.md (divsi_inv_m3): Handle zero dividend
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / sh.md
index be6294f..00221cc 100644 (file)
@@ -8,7 +8,7 @@
 
 ;; GCC is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GCC is distributed in the hope that it will be useful,
@@ -17,9 +17,8 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
 
 
 ;; ??? Should prepend a * to all pattern names which are not used.
     {
       rtx tmp;
 
-      if (no_new_pseudos)
+      if (!can_create_pseudo_p ())
        FAIL;
 
       tmp = gen_reg_rtx (DImode);
                   (match_operand:SI 3 "register_operand" "0"))
                 (match_operand:SI 4 "arith_reg_or_0_operand" "r")))
    (clobber (match_scratch:SI 5 "=&r"))]
-  "TARGET_SHMEDIA && no_new_pseudos"
+  "TARGET_SHMEDIA && !can_create_pseudo_p ()"
   "#"
   "TARGET_SHMEDIA && reload_completed"
   [(pc)]
     {
       rtx tmp;
 
-      if (no_new_pseudos)
+      if (!can_create_pseudo_p ())
        FAIL;
 
       tmp = gen_reg_rtx (SImode);
 {
   if (TARGET_SH1)
     {
-      if (no_new_pseudos && ! arith_reg_operand (operands[2], DImode))
+      if (!can_create_pseudo_p () && ! arith_reg_operand (operands[2], DImode))
         FAIL;
       operands[2] = force_reg (DImode, operands[2]);
       emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
     }
   if (TARGET_SHMEDIA)
     {
-      if (no_new_pseudos && ! arith_reg_or_0_operand (operands[1], SImode))
+      if (!can_create_pseudo_p ()
+         && ! arith_reg_or_0_operand (operands[1], SImode))
        FAIL;
       if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG)
        operands[1] = force_reg (SImode, operands[1]);
    (clobber (reg:DI TR0_REG))
    (clobber (reg:DI TR1_REG))
    (clobber (reg:DI TR2_REG))
-   (use (match_operand 1 "target_operand" "b"))]
+   (use (match_operand 1 "target_reg_operand" "b"))]
   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
   "blink       %1, r18"
   [(set_attr "type" "sfunc")
   ""
   "
 {
-  rtx first, last;
+  rtx last;
 
   operands[3] = gen_reg_rtx (Pmode);
   /* Emit the move of the address to a pseudo outside of the libcall.  */
       function_symbol (operands[3], \"__udivsi3\", SFUNC_STATIC);
       last = gen_udivsi3_i1 (operands[0], operands[3]);
     }
-  first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
+  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
-  last = emit_insn (last);
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
+  emit_insn (last);
   DONE;
 }")
 
    (clobber (reg:SI R20_REG))
    (clobber (reg:SI R21_REG))
    (clobber (reg:SI TR0_REG))
-   (use (match_operand 1 "target_operand" "b"))]
+   (use (match_operand 1 "target_reg_operand" "b"))]
   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
   "blink       %1, r18"
   [(set_attr "type" "sfunc")])
    (clobber (reg:SI R21_REG))
    (clobber (reg:SI TR0_REG))
    (use (reg:SI R20_REG))
-   (use (match_operand 1 "target_operand" "b"))]
+   (use (match_operand 1 "target_reg_operand" "b"))]
   "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)"
   "blink       %1, r18"
   [(set_attr "type" "sfunc")])
   ""
   "
 {
-  rtx first, last;
+  rtx last;
 
   operands[3] = gen_reg_rtx (Pmode);
   /* Emit the move of the address to a pseudo outside of the libcall.  */
       function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT);
       last = gen_divsi3_i1 (operands[0], operands[3]);
     }
-  first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
+  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
   emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
-  last = emit_insn (last);
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
+  emit_insn (last);
   DONE;
 }")
 
@@ -2365,7 +2357,7 @@ norm32: r25
    (clobber (match_operand:DI 8 "register_operand" "=r"))]
   "TARGET_SHMEDIA"
   "#"
-  "&& no_new_pseudos"
+  "&& !can_create_pseudo_p ()"
   [(pc)]
   "
 {
@@ -2409,7 +2401,7 @@ norm32: r25
    (clobber (match_operand:DI 4 "register_operand" "=r"))]
   "TARGET_SHMEDIA"
   "#"
-  "&& no_new_pseudos"
+  "&& !can_create_pseudo_p ()"
   [(pc)]
   "
 {
@@ -2453,7 +2445,7 @@ norm32: r25
    (clobber (match_operand:DI 13 "register_operand" "=r"))]
   "TARGET_SHMEDIA"
   "#"
-  "&& no_new_pseudos"
+  "&& !can_create_pseudo_p ()"
   [(pc)]
   "
 {
@@ -2479,6 +2471,12 @@ norm32: r25
   rtx scratch1 = operands[8];
   rtx scratch2 = operands[9];
 
+  if (satisfies_constraint_N (dividend))
+    {
+      emit_move_insn (result, dividend);
+      DONE;
+    }
+
   emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend));
   emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend));
   emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63)));
@@ -2520,7 +2518,7 @@ norm32: r25
    && (TARGET_DIVIDE_INV_MINLAT
        || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)"
   "#"
-  "&& no_new_pseudos"
+  "&& !can_create_pseudo_p ()"
   [(pc)]
   "
 {
@@ -2687,7 +2685,7 @@ label:
    (clobber (match_operand:DF 9 "fp_arith_reg_operand" ""))
    (clobber (match_operand:DF 10 "fp_arith_reg_operand" ""))
    (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))]
-  "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && no_new_pseudos"
+  "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && !can_create_pseudo_p ()"
   "#"
   "&& 1"
   [(set (match_dup 9) (float:DF (match_dup 1)))
@@ -2746,21 +2744,21 @@ label:
   "TARGET_SH1"
   "
 {
-  rtx first, last;
+  rtx insn, macl;
 
-  first = emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
-  last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
+  macl = gen_rtx_REG (SImode, MACL_REG);
+  start_sequence ();
+  emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
+  insn = get_insns ();  
+  end_sequence ();
   /* expand_binop can't find a suitable code in umul_widen_optab to
      make a REG_EQUAL note from, so make one here.
      See also smulsi3_highpart.
      ??? Alternatively, we could put this at the calling site of expand_binop,
      i.e. expand_expr.  */
-  set_unique_reg_note (last, REG_EQUAL,
-                      copy_rtx (SET_SRC (single_set (first))));
+  /* Use emit_libcall_block for loop invariant code motion and to make
+     a REG_EQUAL note.  */
+  emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
 
   DONE;
 }")
@@ -2776,21 +2774,21 @@ label:
   "TARGET_SH1"
   "
 {
-  rtx first, last;
+  rtx insn, macl;
 
-  first = emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
-  last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACL_REG));
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
+  macl = gen_rtx_REG (SImode, MACL_REG);
+  start_sequence ();
+  emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
+  insn = get_insns ();  
+  end_sequence ();
   /* expand_binop can't find a suitable code in umul_widen_optab to
      make a REG_EQUAL note from, so make one here.
      See also smulsi3_highpart.
      ??? Alternatively, we could put this at the calling site of expand_binop,
      i.e. expand_expr.  */
-  set_unique_reg_note (last, REG_EQUAL,
-                      copy_rtx (SET_SRC (single_set (first))));
+  /* Use emit_libcall_block for loop invariant code motion and to make
+     a REG_EQUAL note.  */
+  emit_libcall_block (insn, operands[0], macl, SET_SRC (single_set (insn)));
 
   DONE;
 }")
@@ -2854,8 +2852,6 @@ label:
   "TARGET_SH1"
   "
 {
-  rtx first, last;
-
   if (!TARGET_SH2)
     {
       /* The address must be set outside the libcall,
@@ -2864,23 +2860,18 @@ label:
       rtx addr = force_reg (SImode, sym);
       rtx insns = gen_mulsi3_call (operands[0], operands[1],
                                   operands[2], addr);
-      first = insns;
-      last = emit_insn (insns);
+      emit_insn (insns);
     }
   else
     {
       rtx macl = gen_rtx_REG (SImode, MACL_REG);
 
-      first = emit_insn (gen_mul_l (operands[1], operands[2]));
+      emit_insn (gen_mul_l (operands[1], operands[2]));
       /* consec_sets_giv can only recognize the first insn that sets a
         giv as the giv insn.  So we must tag this also with a REG_EQUAL
         note.  */
-      last = emit_insn (gen_movsi_i ((operands[0]), macl));
+      emit_insn (gen_movsi_i ((operands[0]), macl));
     }
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
   DONE;
 }")
 
@@ -3055,21 +3046,21 @@ label:
   "TARGET_SH2"
   "
 {
-  rtx first, last;
+  rtx insn, mach;
 
-  first = emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
-  last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
+  mach = gen_rtx_REG (SImode, MACH_REG);
+  start_sequence ();
+  emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
+  insn = get_insns ();  
+  end_sequence ();
   /* expand_binop can't find a suitable code in mul_highpart_optab to
      make a REG_EQUAL note from, so make one here.
      See also {,u}mulhisi.
      ??? Alternatively, we could put this at the calling site of expand_binop,
      i.e. expand_mult_highpart.  */
-  set_unique_reg_note (last, REG_EQUAL,
-                      copy_rtx (SET_SRC (single_set (first))));
+  /* Use emit_libcall_block for loop invariant code motion and to make
+     a REG_EQUAL note.  */
+  emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
 
   DONE;
 }")
@@ -3102,14 +3093,17 @@ label:
   "TARGET_SH2"
   "
 {
-  rtx first, last;
+  rtx insn, mach;
+
+  mach = gen_rtx_REG (SImode, MACH_REG);
+  start_sequence ();
+  emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
+  insn = get_insns ();  
+  end_sequence ();
+  /* Use emit_libcall_block for loop invariant code motion and to make
+     a REG_EQUAL note.  */
+  emit_libcall_block (insn, operands[0], mach, SET_SRC (single_set (insn)));
 
-  first = emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
-  last = emit_move_insn (operands[0], gen_rtx_REG (SImode, MACH_REG));
-  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-     invariant code motion can move it.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
   DONE;
 }")
 
@@ -5035,7 +5029,7 @@ label:
   [(set (match_dup 0) (match_dup 1))]
   "
 {
-  if (TARGET_SHCOMPACT && current_function_has_nonlocal_label)
+  if (TARGET_SHCOMPACT && current_function_saves_all_registers)
     operands[1] = gen_frame_mem (SImode, return_address_pointer_rtx);
 }")
 
@@ -8701,8 +8695,8 @@ label:
 {
   rtx insn, mem;
 
-  operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
-  operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
+  operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
+  operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
 
   if (TARGET_SHMEDIA)
     {
@@ -8801,7 +8795,9 @@ label:
   "
 {
   rtx gotoffsym, insn;
-  rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
+  rtx t = (!can_create_pseudo_p ()
+          ? operands[0]
+          : gen_reg_rtx (GET_MODE (operands[0])));
 
   gotoffsym = gen_sym2GOTOFF (operands[1]);
   PUT_MODE (gotoffsym, Pmode);
@@ -8921,7 +8917,9 @@ mov.l\\t1f,r4\\n\\
   "
 {
   rtx dtpoffsym, insn;
-  rtx t = no_new_pseudos ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
+  rtx t = (!can_create_pseudo_p ()
+          ? operands[0]
+          : gen_reg_rtx (GET_MODE (operands[0])));
 
   dtpoffsym = gen_sym2DTPOFF (operands[1]);
   PUT_MODE (dtpoffsym, Pmode);
@@ -8978,7 +8976,7 @@ mov.l\\t1f,r0\\n\\
 }")
 
 (define_insn "load_gbr"
-  [(set (match_operand:SI 0 "register_operand" "") (reg:SI GBR_REG))
+  [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))
    (use (reg:SI GBR_REG))]
   ""
   "stc gbr,%0"
@@ -9507,8 +9505,9 @@ mov.l\\t1f,r0\\n\\
 
       reg = operands[0];
       if (GET_MODE (operands[0]) != SImode)
-       reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
-                            : gen_reg_rtx (SImode);
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
 
       switch (GET_MODE (sh_compare_op0))
        {
@@ -9571,8 +9570,9 @@ mov.l\\t1f,r0\\n\\
 
       reg = operands[0];
       if (GET_MODE (operands[0]) != SImode)
-       reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
-                            : gen_reg_rtx (SImode);
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
 
       switch (GET_MODE (sh_compare_op0))
        {
@@ -9634,14 +9634,15 @@ mov.l\\t1f,r0\\n\\
 
       reg = operands[0];
       if (GET_MODE (operands[0]) != SImode)
-       reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
-                            : gen_reg_rtx (SImode);
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
 
       switch (GET_MODE (sh_compare_op0))
        {
        case SImode:
          {
-           tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
+           tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
 
            emit_insn (gen_cmpgtsi_media (tmp,
                                          sh_compare_op0, sh_compare_op1));
@@ -9651,7 +9652,7 @@ mov.l\\t1f,r0\\n\\
 
        case DImode:
          {
-           tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
+           tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
 
            emit_insn (gen_cmpgtdi_media (tmp,
                                          sh_compare_op0, sh_compare_op1));
@@ -9701,8 +9702,9 @@ mov.l\\t1f,r0\\n\\
 
       reg = operands[0];
       if (GET_MODE (operands[0]) != SImode)
-       reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
-                            : gen_reg_rtx (SImode);
+       reg = (!can_create_pseudo_p () ?
+              gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
@@ -9765,8 +9767,9 @@ mov.l\\t1f,r0\\n\\
        mode = GET_MODE (sh_compare_op1);
       reg = operands[0];
       if (GET_MODE (operands[0]) != SImode)
-       reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
-                            : gen_reg_rtx (SImode);
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       sh_compare_op0 = force_reg (mode, sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (mode, sh_compare_op1);
@@ -9775,7 +9778,7 @@ mov.l\\t1f,r0\\n\\
        {
        case SImode:
          {
-           rtx tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
+           rtx tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
 
            emit_insn (gen_cmpgtsi_media (tmp,
                                          sh_compare_op1, sh_compare_op0));
@@ -9785,7 +9788,7 @@ mov.l\\t1f,r0\\n\\
 
        case DImode:
          {
-           rtx tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
+           rtx tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
 
            emit_insn (gen_cmpgtdi_media (tmp,
                                          sh_compare_op1, sh_compare_op0));
@@ -9849,8 +9852,9 @@ mov.l\\t1f,r0\\n\\
 
       reg = operands[0];
       if (GET_MODE (operands[0]) == DImode)
-       reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
-                            : gen_reg_rtx (SImode);
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
@@ -9882,8 +9886,9 @@ mov.l\\t1f,r0\\n\\
 
       reg = operands[0];
       if (GET_MODE (operands[0]) == DImode)
-       reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
-                            : gen_reg_rtx (SImode);
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
@@ -9915,8 +9920,9 @@ mov.l\\t1f,r0\\n\\
 
       reg = operands[0];
       if (GET_MODE (operands[0]) != SImode)
-       reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
-                            : gen_reg_rtx (SImode);
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
@@ -9924,7 +9930,7 @@ mov.l\\t1f,r0\\n\\
                                    : GET_MODE (sh_compare_op1),
                                    sh_compare_op1);
 
-      tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
+      tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
 
       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1));
       emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
@@ -9950,8 +9956,9 @@ mov.l\\t1f,r0\\n\\
 
       reg = operands[0];
       if (GET_MODE (operands[0]) != SImode)
-       reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
-                            : gen_reg_rtx (SImode);
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
       if (sh_compare_op1 != const0_rtx)
        sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
@@ -9959,7 +9966,7 @@ mov.l\\t1f,r0\\n\\
                                    : GET_MODE (sh_compare_op1),
                                    sh_compare_op1);
 
-      tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode);
+      tmp = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (SImode);
 
       emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0));
       emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
@@ -9999,8 +10006,9 @@ mov.l\\t1f,r0\\n\\
 
       reg = operands[0];
       if (GET_MODE (operands[0]) != SImode)
-       reg = no_new_pseudos ? gen_rtx_SUBREG (SImode, operands[0], 0)
-                            : gen_reg_rtx (SImode);
+       reg = (!can_create_pseudo_p ()
+              ? gen_rtx_SUBREG (SImode, operands[0], 0)
+              : gen_reg_rtx (SImode));
       if (! TARGET_SHMEDIA_FPU
          && GET_MODE (sh_compare_op0) != DImode
          && GET_MODE (sh_compare_op0) != SImode)
@@ -10013,7 +10021,7 @@ mov.l\\t1f,r0\\n\\
                                    : GET_MODE (sh_compare_op1),
                                    sh_compare_op1);
 
-      tmp = no_new_pseudos ? reg : gen_reg_rtx (SImode);
+      tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode);
 
       emit_insn (gen_seq (tmp));
       emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx));
@@ -10448,39 +10456,61 @@ mov.l\\t1f,r0\\n\\
 }"
   [(set_attr "type" "fparith_media")])
 
-(define_insn_and_split "binary_sf_op"
+(define_insn_and_split "binary_sf_op0"
   [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
-       (vec_select:V2SF
-        (vec_concat:V2SF
+       (vec_concat:V2SF
+         (match_operator:SF 3 "binary_float_operator"
+           [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
+                           (parallel [(const_int 0)]))
+            (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
+                           (parallel [(const_int 0)]))])
          (vec_select:SF
           (match_dup 0)
-          (parallel [(match_operand 7 "const_int_operand" "n")]))
+          (parallel [(const_int 1)]))))]
+  "TARGET_SHMEDIA_FPU"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 4) (match_dup 5))]
+  "
+{
+  int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
+  rtx op1 = gen_rtx_REG (SFmode,
+                        true_regnum (operands[1]) + endian);
+  rtx op2 = gen_rtx_REG (SFmode,
+                        true_regnum (operands[2]) + endian);
+
+  operands[4] = gen_rtx_REG (SFmode,
+                            true_regnum (operands[0]) + endian);
+  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
+}"
+  [(set_attr "type" "fparith_media")])
+
+(define_insn_and_split "binary_sf_op1"
+  [(set (match_operand:V2SF 0 "fp_arith_reg_operand" "=f")
+       (vec_concat:V2SF
+         (vec_select:SF
+          (match_dup 0)
+          (parallel [(const_int 0)]))
          (match_operator:SF 3 "binary_float_operator"
            [(vec_select:SF (match_operand:V2SF 1 "fp_arith_reg_operand" "f")
-                           (parallel [(match_operand 5
-                                       "const_int_operand" "n")]))
+                           (parallel [(const_int 1)]))
             (vec_select:SF (match_operand:V2SF 2 "fp_arith_reg_operand" "f")
-                           (parallel [(match_operand 6
-                                       "const_int_operand" "n")]))]))
-        (parallel [(match_dup 7) (match_operand 4 "const_int_operand" "n")])))]
-  "TARGET_SHMEDIA_FPU && INTVAL (operands[4]) != INTVAL (operands[7])"
+                           (parallel [(const_int 1)]))])))]
+  "TARGET_SHMEDIA_FPU"
   "#"
   "&& reload_completed"
-  [(set (match_dup 8) (match_dup 9))]
+  [(set (match_dup 4) (match_dup 5))]
   "
 {
   int endian = TARGET_LITTLE_ENDIAN ? 0 : 1;
   rtx op1 = gen_rtx_REG (SFmode,
-                        (true_regnum (operands[1])
-                         + (INTVAL (operands[5]) ^ endian)));
+                        true_regnum (operands[1]) + (1 ^ endian));
   rtx op2 = gen_rtx_REG (SFmode,
-                        (true_regnum (operands[2])
-                         + (INTVAL (operands[6]) ^ endian)));
+                        true_regnum (operands[2]) + (1 ^ endian));
 
-  operands[8] = gen_rtx_REG (SFmode,
-                            (true_regnum (operands[0])
-                             + (INTVAL (operands[4]) ^ endian)));
-  operands[9] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
+  operands[4] = gen_rtx_REG (SFmode,
+                            true_regnum (operands[0]) + (1 ^ endian));
+  operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SFmode, op1, op2);
 }"
   [(set_attr "type" "fparith_media")])
 
@@ -13577,18 +13607,21 @@ mov.l\\t1f,r0\\n\\
   [(prefetch (match_operand:SI 0 "register_operand" "r")
              (match_operand:SI 1 "const_int_operand" "n")
              (match_operand:SI 2 "const_int_operand" "n"))]
-  "TARGET_HARD_SH4 || TARGET_SHCOMPACT"
+  "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && !TARGET_VXWORKS_RTP"
   "*
 {
   return \"pref @%0\";
 }"
   [(set_attr "type" "other")])
 
+;; In user mode, the "pref" instruction will raise a RADDERR exception
+;; for accesses to [0x80000000,0xffffffff].  This makes it an unsuitable
+;; implementation of __builtin_prefetch for VxWorks RTPs.
 (define_expand "prefetch"
   [(prefetch (match_operand 0 "address_operand" "p")
              (match_operand:SI 1 "const_int_operand" "n")
              (match_operand:SI 2 "const_int_operand" "n"))]
-  "TARGET_HARD_SH4 || TARGET_SH5"
+  "(TARGET_HARD_SH4 || TARGET_SH5) && (TARGET_SHMEDIA || !TARGET_VXWORKS_RTP)"
   "
 {
   if (GET_MODE (operands[0]) != Pmode