OSDN Git Service

* expr.h: Remove #ifdef FUNCTION_CONVERSION_BUG logic.
[pf3gnuchains/gcc-fork.git] / gcc / config / romp / romp.md
index 7bad21b..131e78c 100644 (file)
@@ -1,6 +1,7 @@
 ;;- Machine description for ROMP chip for GNU C compiler
-;;   Copyright (C) 1988, 1991 Free Software Foundation, Inc.
-;;   Contributed by Richard Kenner (kenner@nyu.edu)
+;;   Copyright (C) 1988, 1991, 1993, 1994, 1995, 1998, 1999, 2000
+;;   Free Software Foundation, Inc.
+;;   Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
 ;; This file is part of GNU CC.
 
@@ -16,7 +17,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU CC; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 
 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
@@ -26,7 +28,7 @@
 ;; Insn type.  Used to default other attribute values.
 
 (define_attr "type"
-  "branch,return,fp,load,loadz,store,call,address,arith,compare,multi,misc"
+  "branch,ibranch,return,fp,load,loadz,store,call,address,arith,compare,multi,misc"
   (const_string "arith"))
 
 ;; Length in bytes.
@@ -39,7 +41,7 @@
                                (const_int 254)))
                       (const_int 2)
                       (const_int 4))
-        (eq_attr "type" "return")      (const_int 2)
+        (eq_attr "type" "return,ibranch") (const_int 2)
         (eq_attr "type" "fp")          (const_int 10)
         (eq_attr "type" "call")        (const_int 4)
         (eq_attr "type" "load")
 
 (define_attr "in_delay_slot" "yes,no" 
   (cond [(eq_attr "length" "8,10,38")                  (const_string "no")
-        (eq_attr "type" "branch,return,call,multi")    (const_string "no")]
+        (eq_attr "type" "branch,ibranch,return,call,multi")
+        (const_string "no")]
        (const_string "yes")))
 
-;; Whether insn needs a delay slot.
+;; Whether insn needs a delay slot.  We have to say that two-byte
+;; branches do not need a delay slot.  Otherwise, branch shortening will
+;; try to do something with delay slot insns (we want it to on the PA).
+;; This is a kludge, which should be cleaned up at some point.
+
 (define_attr "needs_delay_slot" "yes,no"
-  (if_then_else (eq_attr "type" "branch,return,call")
+  (if_then_else (ior (and (eq_attr "type" "branch")
+                         (eq_attr "length" "4"))
+                    (eq_attr "type" "ibranch,return,call"))
                (const_string "yes") (const_string "no")))
 
 ;; What insn does to the condition code.
@@ -75,7 +84,7 @@
   (cond [(eq_attr "type" "load,loadz")         (const_string "change0")
         (eq_attr "type" "store")               (const_string "none")
         (eq_attr "type" "fp,call")             (const_string "clobber")
-        (eq_attr "type" "branch,return")       (const_string "none")
+        (eq_attr "type" "branch,ibranch,return") (const_string "none")
         (eq_attr "type" "address")             (const_string "change0")
         (eq_attr "type" "compare")             (const_string "compare")
         (eq_attr "type" "arith")               (const_string "sets")]
               || (unsigned) ((- const_val) + 0x8000) < 0x10000)
        {
          /* Can do this by loading the negative constant and then negating. */
-         emit_move_insn (operands[0],
-                         gen_rtx (CONST_INT, VOIDmode, - const_val));
+         emit_move_insn (operands[0], GEN_INT (- const_val));
          emit_insn (gen_negsi2 (operands[0], operands[0]));
          DONE;
        }
          if (low_part >= 0x10 && exact_log2 (low_part) >= 0)
            i = high_part, high_part = low_part, low_part = i;
 
-         emit_move_insn (operands[0],
-                         gen_rtx (CONST_INT, VOIDmode, low_part));
+         emit_move_insn (operands[0], GEN_INT (low_part));
          emit_insn (gen_iorsi3 (operands[0], operands[0],
-                                gen_rtx (CONST_INT, VOIDmode, high_part)));
+                                GEN_INT (high_part)));
          DONE;
        }
     }
   [(set_attr "type" "store")])
 
 (define_expand "reload_outqi"
-  [(set (match_operand:QI 0 "symbolic_memory_operand" "=m")
-       (match_operand:QI 1 "" "r"))
-   (match_operand:SI 2 "" "=&b")]
+  [(parallel [(set (match_operand:QI 0 "symbolic_memory_operand" "=m")
+                  (match_operand:QI 1 "" "r"))
+             (clobber (match_operand:SI 2 "" "=&b"))])]
   ""
   "")
 \f
   "loadha %0,%1"
   [(set_attr "type" "load")])
 
+
+;; use cal16 instead of cal for constant source because combine requires
+;; the high bits of the register to be 0 after a HImode load of a constant
+
 (define_insn ""
   [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,b,Q")
        (match_operand:HI 1 "romp_operand" "r,I,n,s,Q,m,r"))]
   "@
    cas %0,%1,r0
    lis %0,%1
-   cal %0,%L1(r0)
+   cal16 %0,%L1(r0)
    get %0,$%1
    lh%N1 %0,%1
    loadh %0,%1
   [(set_attr "type" "store")])
 
 (define_expand "reload_outhi"
-  [(set (match_operand:HI 0 "symbolic_memory_operand" "=m")
-       (match_operand:HI 1 "" "r"))
-   (match_operand:SI 2 "" "=&b")]
+  [(parallel [(set (match_operand:HI 0 "symbolic_memory_operand" "=m")
+                  (match_operand:HI 1 "" "r"))
+             (clobber (match_operand:SI 2 "" "=&b"))])]
   ""
   "")
 \f
       return \"get %O0,$%1\;ls %0,0(%O0)\;ls %O0,4(%O0)\";
     case 3:
       return \"st%M0 %1,%0\;st%M0 %O1,%O0\";
+    default:
+      abort();
     }
 }"
   [(set_attr "type" "multi")
    (set_attr "length" "8,12")])
 
 (define_expand "reload_outdi"
-  [(set (match_operand:DI 0 "symbolic_memory_operand" "=m")
-       (match_operand:DI 1 "" "r"))
-   (match_operand:SI 2 "" "=&b")]
+  [(parallel [(set (match_operand:DI 0 "symbolic_memory_operand" "=m")
+                  (match_operand:DI 1 "" "r"))
+             (clobber (match_operand:SI 2 "" "=&b"))])]
   ""
   "")
 
 { operands[2] = operand_subword (operands[0], 1, 0, DImode);
   operands[3] = XEXP (operands[1], 0);
   operands[4] = operand_subword (operands[0], 0, 0, DImode);
-  operands[5] = gen_rtx (MEM, SImode, operands[2]);
+  operands[5] = gen_rtx_MEM (SImode, operands[2]);
   operands[6] = operands[2];
-  operands[7] = gen_rtx (MEM, SImode,
-                        gen_rtx (PLUS, SImode, operands[2],
-                                 gen_rtx (CONST_INT, VOIDmode, 4)));
+  operands[7] = gen_rtx_MEM (SImode, plus_constant (operands[2], 4));
 
   if (operands[2] == 0 || operands[4] == 0)
     FAIL;
    (set (match_dup 6) (match_dup 7))]
   "
 { operands[3] = XEXP (operands[0], 0);
-  operands[4] = gen_rtx (MEM, SImode, operands[2]);
+  operands[4] = gen_rtx_MEM (SImode, operands[2]);
   operands[5] = operand_subword (operands[1], 0, 0, DImode);
-  operands[6] = gen_rtx (MEM, SImode,
-                        gen_rtx (PLUS, SImode, operands[2],
-                                 gen_rtx (CONST_INT, VOIDmode, 4)));
+  operands[6] = gen_rtx_MEM (SImode, plus_constant (operands[4], 4));
   operands[7] = operand_subword (operands[1], 1, 0, DImode);
 
   if (operands[5] == 0 || operands[7] == 0)
    && ! (GET_CODE (operands[0]) == REG
          && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
    && ! (GET_CODE (operands[1]) == REG
-         && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)"
+         && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
+   && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
+        && ! reload_completed
+        && reg_overlap_mentioned_p (operands[0], operands[1]))"
  [(parallel [(set (match_dup 2) (match_dup 3))
             (clobber (match_dup 7))])
   (parallel [(set (match_dup 4) (match_dup 5))
     operands[7] = operands[8] = operands[6];
   else
     {
-      operands[7] = gen_rtx (SCRATCH, SImode);
-      operands[8] = gen_rtx (SCRATCH, SImode);
+      operands[7] = gen_rtx_SCRATCH (SImode);
+      operands[8] = gen_rtx_SCRATCH (SImode);
     }
 }")
 
 
   if (op0 == op1)
     {
-      emit_insn (gen_rtx (SET, VOIDmode, op0, op1));
+      emit_insn (gen_rtx_SET (VOIDmode, op0, op1));
       DONE;
     }
 
       start_sequence ();
       if (GET_CODE (operands[0]) != REG
          || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-                                 operands[1]), 0)
+                                 operands[1], 0))
        {
          emit_move_insn (operand_subword (op0, 0, 1, DFmode),
                          operand_subword_force (op1, 0, DFmode));
   
   if (op0 == op1)
     {
-      emit_insn (gen_rtx (SET, VOIDmode, op0, op1));
+      emit_insn (gen_rtx_SET (VOIDmode, op0, op1));
       DONE;
     }
 
       last = emit_move_insn (operand_subword (op0, 0, 1, SFmode),
                             operand_subword_force (op1, 0, SFmode));
 
-      REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, op1, REG_NOTES (last));
+      REG_NOTES (last) = gen_rtx_EXPR_LIST (REG_EQUAL, op1, REG_NOTES (last));
       DONE;
     }
 }")
   "
 { operands[2] = XEXP (operands[1], 0);
   operands[3] = operand_subword (operands[0], 0, 0, DFmode);
-  operands[4] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 15));
-  operands[5] = operand_subword (operands[0], 0, 1, DFmode);
-  operands[6] = gen_rtx (MEM, SImode,
-                        gen_rtx (PLUS, SImode, gen_rtx (REG, SImode, 15),
-                                 gen_rtx (CONST_INT, VOIDmode, 4)));
+  operands[4] = gen_rtx_MEM (SImode, gen_rtx (REG, SImode, 15));
+  operands[5] = operand_subword (operands[0], 1, 0, DFmode);
+  operands[6] = gen_rtx_MEM (SImode,
+                            plus_constant (gen_rtx (REG, SImode, 15), 4));
 
   if (operands[3] == 0 || operands[5] == 0)
     FAIL;
    (set (match_dup 5) (match_dup 6))]
   "
 { operands[2] = XEXP (operands[0], 0);
-  operands[3] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 15));
+  operands[3] = gen_rtx_MEM (SImode, gen_rtx (REG, SImode, 15));
   operands[4] = operand_subword (operands[1], 0, 0, DFmode);
-  operands[5] = gen_rtx (MEM, SImode,
-                        gen_rtx (PLUS, SImode, gen_rtx (REG, SImode, 15),
-                                 gen_rtx (CONST_INT, VOIDmode, 4)));
+  operands[5] = gen_rtx_MEM (SImode,
+                            plus_constant (gen_rtx_REG (SImode, 15), 4));
   operands[6] = operand_subword (operands[1], 1, 0, DFmode);
 
   if (operands[4] == 0 || operands[6] == 0)
     FAIL;
 
   if (reload_completed)
-    operands[6] = operands[7] = gen_rtx (REG, SImode, 15);
+    operands[6] = operands[7] = gen_rtx_REG (SImode, 15);
   else
     {
-      operands[6] = gen_rtx (SCRATCH, SImode);
-      operands[7] = gen_rtx (SCRATCH, SImode);
+      operands[6] = gen_rtx_SCRATCH (SImode);
+      operands[7] = gen_rtx_SCRATCH (SImode);
     }
 }")
 
    && GET_CODE (operands[1]) != CONST_DOUBLE
    && (GET_CODE (operands[0]) != REG || REGNO (operands[0]) < 15)
    && (GET_CODE (operands[1]) != REG || REGNO (operands[1]) < 15)
-   && (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG)"
+   && (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG)
+   && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
+        && ! reload_completed
+        && reg_overlap_mentioned_p (operands[0], operands[1]))"
   [(set (match_dup 2) (match_dup 3))
    (set (match_dup 4) (match_dup 5))]
   "
 
 ;; Now zero extensions:
 (define_expand "zero_extendhisi2"
-  [(set (match_operand:SI 0 "register_operand" "b")
+  [(set (match_operand:SI 0 "register_operand" "")
        (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
   ""
   "")
       if (low & 0x8000)
        high++, low |= 0xffff0000;
 
-      emit_insn (gen_addsi3 (operands[0], operands[1],
-                            gen_rtx (CONST_INT, VOIDmode, high << 16)));
+      emit_insn (gen_addsi3 (operands[0], operands[1], GEN_INT (high << 16)));
       operands[1] = operands[0];
-      operands[2] = gen_rtx (CONST_INT, VOIDmode, low);
+      operands[2] = GEN_INT (low);
     }
 }")
 
   if (GET_CODE (operands [2]) == CONST_INT)
     {
       emit_insn (gen_addsi3 (operands[0], operands[1], 
-                            gen_rtx (CONST_INT,
-                                     VOIDmode, - INTVAL (operands[2]))));
+                            GEN_INT (- INTVAL (operands[2]))));
       DONE;
     }
   else
   rtx insn;
 
   emit_insn (gen_divmodsi4_doit (operands[1], operands[2]));
-  insn = emit_move_insn (operands[0], gen_rtx (REG, SImode, 2));
-  REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
-                             gen_rtx (DIV, SImode, operands[1],
-                                      operands[2]),
-                             REG_NOTES (insn));
-  insn = emit_move_insn (operands[3], gen_rtx (REG, SImode, 3));
-  REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
-                             gen_rtx (MOD, SImode, operands[1],
-                                      operands[2]),
-                             REG_NOTES (insn));
+  insn = emit_move_insn (operands[0], gen_rtx_REG (SImode, 2));
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL,
+                                       gen_rtx_DIV (SImode, operands[1],
+                                                    operands[2]),
+                                       REG_NOTES (insn));
+  insn = emit_move_insn (operands[3], gen_rtx_REG (SImode, 3));
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL,
+                                       gen_rtx_MOD (SImode, operands[1],
+                                                    operands[2]),
+                                       REG_NOTES (insn));
   DONE;
 }")
 
   rtx insn;
 
   emit_insn (gen_udivmodsi4_doit (operands[1], operands[2]));
-  insn = emit_move_insn (operands[0], gen_rtx (REG, SImode, 2));
-  REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
-                             gen_rtx (UDIV, SImode, operands[1],
-                                      operands[2]),
-                             REG_NOTES (insn));
-  insn = emit_move_insn (operands[3], gen_rtx (REG, SImode, 3));
-  REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
-                             gen_rtx (UMOD, SImode, operands[1],
-                                      operands[2]),
-                             REG_NOTES (insn));
+  insn = emit_move_insn (operands[0], gen_rtx_REG (SImode, 2));
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL,
+                                       gen_rtx_UDIV (SImode, operands[1],
+                                                     operands[2]),
+                                       REG_NOTES (insn));
+  insn = emit_move_insn (operands[3], gen_rtx_REG (SImode, 3));
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL,
+                                       gen_rtx_UMOD (SImode, operands[1],
+                                                     operands[2]),
+                                       REG_NOTES (insn));
   DONE;
 }")
 
       if (top != 0 && top != 0xffff && bottom != 0 && bottom != 0xffff)
        {
          emit_insn (gen_andsi3 (operands[0], operands[1],
-                                gen_rtx (CONST_INT, VOIDmode,
-                                         (top << 16) | 0xffff)));
+                                GEN_INT ((top << 16) | 0xffff)));
          operands[1] = operands[0];
-         operands[2] = gen_rtx (CONST_INT, VOIDmode, 0xffff0000 | bottom);
+         operands[2] = GEN_INT (0xffff0000 | bottom);
        }
     }
 }");
       if (top != 0 && bottom != 0)
        {
          emit_insn (gen_iorsi3 (operands[0], operands[1],
-                                gen_rtx (CONST_INT, VOIDmode, (top << 16))));
+                                GEN_INT (top << 16)));
          operands[1] = operands[0];
-         operands[2] = gen_rtx (CONST_INT, VOIDmode, bottom);
+         operands[2] = GEN_INT (bottom);
        }
     }
 }");
       else if (top != 0 && bottom != 0)
        {
          emit_insn (gen_xorsi3 (operands[0], operands[1],
-                                gen_rtx (CONST_INT, VOIDmode, (top << 16))));
+                                GEN_INT (top << 16)));
          operands[1] = operands[0];
-         operands[2] = gen_rtx (CONST_INT, VOIDmode, bottom);
+         operands[2] = GEN_INT (bottom);
        }
     }
 }");
 (define_insn "ashrsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
-                    (match_operand:QI 2 "reg_or_cint_operand" "r,n")))]
+                    (match_operand:SI 2 "reg_or_cint_operand" "r,n")))]
   ""
   "@
    sar %0,%2
 (define_insn "lshrsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
-                    (match_operand:QI 2 "reg_or_cint_operand" "r,n")))]
+                    (match_operand:SI 2 "reg_or_cint_operand" "r,n")))]
   ""
   "@
    sr %0,%2
 (define_insn "ashlsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
-                  (match_operand:QI 2 "reg_or_cint_operand" "r,n")))]
+                  (match_operand:SI 2 "reg_or_cint_operand" "r,n")))]
   ""
   "@
    sl %0,%2
 ;;
 ;; Operand 1 (2 for `call_value') is the number of arguments and is not used.
 (define_expand "call"
-  [(use (reg:SI 0))
-   (parallel [(call (mem:SI (match_operand:SI 0 "address_operand" ""))
-                   (match_operand 1 "" ""))
-             (clobber (reg:SI 15))])]
+  [(use (match_operand:SI 0 "address_operand" ""))
+   (use (match_operand 1 "" ""))]
   ""
   "
 {
+  rtx reg0 = gen_rtx_REG (SImode, 0);
+  rtx call_insn;
+
   if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT)
     abort();
 
   if (GET_CODE (operands[0]) == SYMBOL_REF)
     {
       extern rtx get_symref ();
-      char *real_fcnname =
-               (char *) alloca (strlen (XSTR (operands[0], 0)) + 2);
+      char *real_fcnname
+       = (char *) alloca (strlen (XSTR (operands[0], 0)) + 2);
 
       /* Copy the data area address to r0.  */
-      emit_move_insn (gen_rtx (REG, SImode, 0),
-                     force_reg (SImode, operands[0]));
+      emit_move_insn (reg0, force_reg (SImode, operands[0]));
       strcpy (real_fcnname, \".\");
       strcat (real_fcnname, XSTR (operands[0], 0));
       operands[0] = get_symref (real_fcnname);
     {
       rtx data_access;
 
-      emit_move_insn (gen_rtx (REG, SImode, 0),
-                     force_reg (SImode, operands[0]));
-      data_access = gen_rtx (MEM, SImode, operands[0]);
+      emit_move_insn (reg0, force_reg (SImode, operands[0]));
+      data_access = gen_rtx_MEM (SImode, operands[0]);
       RTX_UNCHANGING_P (data_access) = 1;
       operands[0] = copy_to_reg (data_access);
     }
+
+  call_insn = emit_call_insn (gen_call_internal (operands[0], operands[1]));
+  use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), reg0);
+  DONE;
 }")
 
-(define_insn ""
+(define_insn "call_internal"
   [(call (mem:SI (match_operand:SI 0 "register_operand" "b"))
         (match_operand 1 "" "g"))
    (clobber (reg:SI 15))]
 
 ;; Call a function and return a value.
 (define_expand "call_value"
-  [(use (reg:SI 0))
-   (parallel [(set (match_operand 0 "" "=fg")
-                  (call (mem:SI (match_operand:SI 1 "address_operand" ""))
-                        (match_operand 2 "" "")))
-             (clobber (reg:SI 15))])]
+  [(use (match_operand 0 "" ""))
+   (use (match_operand:SI 1 "address_operand" ""))
+   (use (match_operand 2 "" ""))]
   ""
   "
 {
+  rtx reg0 = gen_rtx_REG (SImode, 0);
+  rtx call_insn;
+
   if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != CONST_INT)
     abort();
 
                (char *) alloca (strlen (XSTR (operands[1], 0)) + 2);
 
       /* Copy the data area address to r0.  */
-      emit_move_insn (gen_rtx (REG, SImode, 0),
-                     force_reg (SImode, operands[1]));
+      emit_move_insn (reg0,force_reg (SImode, operands[1]));
       strcpy (real_fcnname, \".\");
       strcat (real_fcnname, XSTR (operands[1], 0));
       operands[1] = get_symref (real_fcnname);
     {
       rtx data_access;
 
-      emit_move_insn (gen_rtx (REG, SImode, 0),
-                     force_reg (SImode, operands[1]));
-      data_access = gen_rtx (MEM, SImode, operands[1]);
+      emit_move_insn (reg0,force_reg (SImode, operands[1]));
+      data_access = gen_rtx_MEM (SImode, operands[1]);
       RTX_UNCHANGING_P (data_access) = 1;
       operands[1] = copy_to_reg (data_access);
     }
+
+  call_insn = emit_call_insn (gen_call_value_internal (operands[0],
+                                                      operands[1],
+                                                      operands[2]));
+  use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), reg0);
+  DONE;
 }")
 
-(define_insn ""
+(define_insn "call_value_internal"
   [(set (match_operand 0 "" "=fg")
        (call (mem:SI (match_operand:SI 1 "register_operand" "b"))
              (match_operand 2 "" "g")))
   "bali%# r15,%1"
   [(set_attr "type" "call")])
 
+;; Call subroutine returning any type.
+
+(define_expand "untyped_call"
+  [(parallel [(call (match_operand 0 "" "")
+                   (const_int 0))
+             (match_operand 1 "" "")
+             (match_operand 2 "" "")])]
+  ""
+  "
+{
+  int i;
+
+  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+
+  for (i = 0; i < XVECLEN (operands[2], 0); i++)
+    {
+      rtx set = XVECEXP (operands[2], 0, i);
+      emit_move_insn (SET_DEST (set), SET_SRC (set));
+    }
+
+  /* The optimizer does not know that the call sets the function value
+     registers we stored in the result block.  We avoid problems by
+     claiming that all hard registers are used and clobbered at this
+     point.  */
+  emit_insn (gen_blockage ());
+
+  DONE;
+}")
+
+;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
+;; all of memory.  This blocks insns from being moved across this point.
+
+(define_insn "blockage"
+  [(unspec_volatile [(const_int 0)] 0)]
+  ""
+  "")
+
 ;; No operation insn.
 (define_insn "nop"
   [(const_int 0)]
 
       result = expand_binop (SImode, xor_optab,
                             operand_subword_force (operands[1], 0, SFmode),
-                            gen_rtx (CONST_INT, VOIDmode, 0x80000000),
-                            target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x80000000), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
       start_sequence ();
       result = expand_binop (SImode, xor_optab,
                             operand_subword_force (operands[1], 0, DFmode),
-                            gen_rtx (CONST_INT, VOIDmode, 0x80000000),
-                            target, 0, OPTAB_WIDEN);
+                            GEN_INT (0x80000000), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
   "GET_MODE (operands[0]) == SFmode || GET_MODE (operands[0]) == DFmode"
   "*
 { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
-                     operands[0], immed_real_const_1 (0, 0,
-                                                      GET_MODE (operands[0])),
+                     operands[0], CONST0_RTX (GET_MODE (operands[0])),
                      0, insn);
 }"
   [(set_attr "type" "fp")
   ""
   "*
 { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
-                     operands[1], immed_real_const_1 (0, 0,
-                                                      GET_MODE (operands[1])),
+                     operands[1], CONST0_RTX (GET_MODE (operands[1])),
                      0, insn);
 }"
   [(set_attr "type" "fp")
   [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
   ""
   "br%# %0"
-  [(set_attr "type" "branch")
-   (set_attr "length" "2")])
+  [(set_attr "type" "ibranch")])
 
 ;; Table jump for switch statements:
 (define_insn "tablejump"
    (use (label_ref (match_operand 1 "" "")))]
   ""
   "br%# %0"
-  [(set_attr "type" "branch")
-   (set_attr "length" "2")])
-\f
-;;- Local variables:
-;;- mode:emacs-lisp
-;;- comment-start: ";;- "
-;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
-;;- eval: (modify-syntax-entry ?[ "(]")
-;;- eval: (modify-syntax-entry ?] ")[")
-;;- eval: (modify-syntax-entry ?{ "(}")
-;;- eval: (modify-syntax-entry ?} "){")
-;;- End:
+  [(set_attr "type" "ibranch")])