OSDN Git Service

* alpha.md (builtin_longjmp): Add missing "DONE".
[pf3gnuchains/gcc-fork.git] / gcc / config / alpha / alpha.md
index 7990f20..59b04f9 100644 (file)
@@ -28,6 +28,7 @@
 ;;     2       insxh
 ;;     3       mskxh
 ;;     4       cvtlq
+;;     5       cvtql
 ;;     
 ;; UNSPEC_VOLATILE:
 ;;
@@ -36,7 +37,9 @@
 ;;     2       builtin_setjmp_receiver
 ;;     3       builtin_longjmp
 ;;     4       trapb
-
+;;     5       prologue_stack_probe_loop
+;;     6       realign
+;;     7       exception_receiver
 \f
 ;; Processor type -- this attribute must exactly match the processor_type
 ;; enumeration in alpha.h.
 ;; separately.
 
 (define_attr "type"
-  "ild,fld,ldsym,ist,fst,ibr,fbr,jsr,iadd,ilog,shift,icmov,fcmov,icmp,imul,fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof"
+  "ild,fld,ldsym,ist,fst,ibr,fbr,jsr,iadd,ilog,shift,icmov,fcmov,icmp,imul,fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
   (const_string "iadd"))
 
+;; Describe a user's asm statement.
+(define_asm_attributes
+  [(set_attr "type" "multi")])
+
+;; Define the operand size an insn operates on.  Used primarily by mul
+;; and div operations that have size dependant timings.
+
 (define_attr "opsize" "si,di,udi" (const_string "di"))
 
 ;; The TRAP_TYPE attribute marks instructions that may generate traps
 ;; (which are imprecise and may need a trapb if software completion
 ;; is desired).
+
 (define_attr "trap" "no,yes" (const_string "no"))
 
+;; The length of an instruction sequence in bytes.
+
+(define_attr "length" "" (const_int 4))
 \f
 ;; On EV4 there are two classes of resources to consider: resources needed
 ;; to issue, and resources needed to execute.  IBUS[01] are in the first
    addl %1,$31,%0
    ldl %0,%1
    lds %0,%1\;cvtlq %0,%0"
-  [(set_attr "type" "iadd,ild,fld")])
+  [(set_attr "type" "iadd,ild,fld")
+   (set_attr "length" "*,*,8")])
 
 ;; Due to issues with CLASS_CANNOT_CHANGE_SIZE, we cannot use a subreg here.
 (define_split
                 (match_operand:SI 2 "add_operand" "")))]
   ""
   "
-{ emit_insn (gen_rtx_SET (VOIDmode, gen_lowpart (DImode, operands[0]),
-                         gen_rtx_PLUS (DImode,
-                                       gen_lowpart (DImode, operands[1]),
-                                       gen_lowpart (DImode, operands[2]))));
-  DONE;
-} ")
+{
+  if (optimize)
+    {
+      rtx op1 = gen_lowpart (DImode, operands[1]);
+      rtx op2 = gen_lowpart (DImode, operands[2]);
+
+      if (! cse_not_expected)
+        {
+          rtx tmp = gen_reg_rtx (DImode);
+          emit_insn (gen_adddi3 (tmp, op1, op2));
+          emit_move_insn (gen_lowpart (DImode, operands[0]), tmp);
+        }
+      else
+        emit_insn (gen_adddi3 (gen_lowpart (DImode, operands[0]), op1, op2));
+      DONE;
+    }
+}")
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
        (sign_extend:DI
         (plus:SI (match_operand:SI 1 "register_operand" "")
                  (match_operand:SI 2 "const_int_operand" ""))))
-   (clobber (match_operand:SI 3 "register_operand" ""))]
+   (clobber (match_operand:SI 3 "reg_not_elim_operand" ""))]
   "! sext_add_operand (operands[2], SImode) && INTVAL (operands[2]) > 0
    && INTVAL (operands[2]) % 4 == 0"
   [(set (match_dup 3) (match_dup 4))
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r,r")
-       (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,rJ")
+       (plus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r,r")
                          (match_operand:SI 2 "const48_operand" "I,I"))
                 (match_operand:SI 3 "sext_add_operand" "rI,O")))]
   ""
   "@
-   s%2addl %r1,%3,%0
-   s%2subl %r1,%n3,%0")
+   s%2addl %1,%3,%0
+   s%2subl %1,%n3,%0")
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r,r")
        (sign_extend:DI
-        (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,rJ")
+        (plus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r,r")
                           (match_operand:SI 2 "const48_operand" "I,I"))
                  (match_operand:SI 3 "sext_add_operand" "rI,O"))))]
   ""
   "@
-   s%2addl %r1,%3,%0
-   s%2subl %r1,%n3,%0")
+   s%2addl %1,%3,%0
+   s%2subl %1,%n3,%0")
 
 (define_split
   [(set (match_operand:DI 0 "register_operand" "")
                                               (match_operand 3 "" "")])
                           (match_operand:SI 4 "const48_operand" ""))
                  (match_operand:SI 5 "add_operand" ""))))
-   (clobber (match_operand:DI 6 "register_operand" ""))]
+   (clobber (match_operand:DI 6 "reg_not_elim_operand" ""))]
   ""
   [(set (match_dup 6) (match_dup 7))
    (set (match_dup 0)
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r,r")
-       (plus:DI (mult:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,rJ")
+       (plus:DI (mult:DI (match_operand:DI 1 "reg_not_elim_operand" "r,r")
                          (match_operand:DI 2 "const48_operand" "I,I"))
-                (match_operand:DI 3 "reg_or_8bit_operand" "rI,O")))]
+                (match_operand:DI 3 "sext_add_operand" "rI,O")))]
   ""
   "@
-   s%2addq %r1,%3,%0
+   s%2addq %1,%3,%0
    s%2subq %1,%n3,%0")
 
 ;; These variants of the above insns can occur if the third operand
   [(set (match_dup 5)
        (plus:SI (mult:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
    (set (match_dup 0) (sign_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
-  "
-{ operands[5] = gen_lowpart (SImode, operands[0]);
-}")
+  "operands[5] = gen_lowpart (SImode, operands[0]);")
 
 (define_insn ""
   [(set (match_operand:DI 0 "some_operand" "=&r")
                  (match_operand:SI 2 "reg_or_8bit_operand" "")))]
   ""
   "
-{ emit_insn (gen_rtx_SET (VOIDmode, gen_lowpart (DImode, operands[0]),
-                         gen_rtx_MINUS (DImode,
-                                        gen_lowpart (DImode, operands[1]),
-                                        gen_lowpart (DImode, operands[2]))));
-  DONE;
+{
+  if (optimize)
+    {
+      rtx op1 = gen_lowpart (DImode, operands[1]);
+      rtx op2 = gen_lowpart (DImode, operands[2]);
+
+      if (! cse_not_expected)
+        {
+          rtx tmp = gen_reg_rtx (DImode);
+          emit_insn (gen_subdi3 (tmp, op1, op2));
+          emit_move_insn (gen_lowpart (DImode, operands[0]), tmp);
+        }
+      else
+        emit_insn (gen_subdi3 (gen_lowpart (DImode, operands[0]), op1, op2));
+      DONE;
+    }
 } ")
 
 (define_insn ""
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (minus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
+       (minus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r")
                           (match_operand:SI 2 "const48_operand" "I"))
                  (match_operand:SI 3 "reg_or_8bit_operand" "rI")))]
   ""
-  "s%2subl %r1,%3,%0")
+  "s%2subl %1,%3,%0")
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (sign_extend:DI
-        (minus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
+        (minus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r")
                            (match_operand:SI 2 "const48_operand" "I"))
                   (match_operand:SI 3 "reg_or_8bit_operand" "rI"))))]
   ""
-  "s%2subl %r1,%3,%0")
+  "s%2subl %1,%3,%0")
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
-       (minus:DI (mult:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
+       (minus:DI (mult:DI (match_operand:DI 1 "reg_not_elim_operand" "r")
                           (match_operand:DI 2 "const48_operand" "I"))
                  (match_operand:DI 3 "reg_or_8bit_operand" "rI")))]
   ""
-  "s%2subq %r1,%3,%0")
+  "s%2subq %1,%3,%0")
 
 (define_insn "mulsi3"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
-                (match_operand:SI 2 "reg_or_0_operand" "rJ")))]
+                (match_operand:SI 2 "reg_or_8bit_operand" "rI")))]
   ""
-  "mull %r1,%r2,%0"
+  "mull %r1,%2,%0"
   [(set_attr "type" "imul")
    (set_attr "opsize" "si")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
-       (sign_extend:DI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
-                                (match_operand:SI 2 "reg_or_0_operand" "rJ"))))]
+       (sign_extend:DI
+         (mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
+                  (match_operand:SI 2 "reg_or_8bit_operand" "rI"))))]
   ""
-  "mull %r1,%r2,%0"
+  "mull %r1,%2,%0"
   [(set_attr "type" "imul")
    (set_attr "opsize" "si")])
 
 (define_insn "muldi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (mult:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ")
-                (match_operand:DI 2 "reg_or_0_operand" "rJ")))]
+                (match_operand:DI 2 "reg_or_8bit_operand" "rI")))]
   ""
-  "mulq %r1,%r2,%0"
+  "mulq %r1,%2,%0"
   [(set_attr "type" "imul")])
 
 (define_insn "umuldi3_highpart"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (truncate:DI
         (lshiftrt:TI
-         (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand" "r"))
-                  (zero_extend:TI (match_operand:DI 2 "register_operand" "r")))
+         (mult:TI (zero_extend:TI
+                    (match_operand:DI 1 "reg_or_0_operand" "%rJ"))
+                  (zero_extend:TI
+                    (match_operand:DI 2 "reg_or_8bit_operand" "rI")))
          (const_int 64))))]
   ""
-  "umulh %1,%2,%0"
+  "umulh %r1,%2,%0"
   [(set_attr "type" "imul")
    (set_attr "opsize" "udi")])
 
 ;; The divide and remainder operations always take their inputs from
 ;; r24 and r25, put their output in r27, and clobber r23 and r28.
 
-;; ??? comment out the divsi routines since the library functions
-;; don't seem to do the right thing with the high 32-bits of a
-;; register nonzero.
-
-;(define_expand "divsi3"
-;  [(set (reg:SI 24) (match_operand:SI 1 "input_operand" ""))
-;   (set (reg:SI 25) (match_operand:SI 2 "input_operand" ""))
-;   (parallel [(set (reg:SI 27)
-;                 (div:SI (reg:SI 24)
-;                         (reg:SI 25)))
-;            (clobber (reg:DI 23))
-;            (clobber (reg:DI 28))])
-;   (set (match_operand:SI 0 "general_operand" "")
-;      (reg:SI 27))]
-;  "!TARGET_OPEN_VMS"
-;  "")
-
-;(define_expand "udivsi3"
-;  [(set (reg:SI 24) (match_operand:SI 1 "input_operand" ""))
-;   (set (reg:SI 25) (match_operand:SI 2 "input_operand" ""))
-;   (parallel [(set (reg:SI 27)
-;                 (udiv:SI (reg:SI 24)
-;                          (reg:SI 25)))
-;            (clobber (reg:DI 23))
-;            (clobber (reg:DI 28))])
-;   (set (match_operand:SI 0 "general_operand" "")
-;      (reg:SI 27))]
-;  "!TARGET_OPEN_VMS"
-;  "")
-
-;(define_expand "modsi3"
-;  [(set (reg:SI 24) (match_operand:SI 1 "input_operand" ""))
-;   (set (reg:SI 25) (match_operand:SI 2 "input_operand" ""))
-;   (parallel [(set (reg:SI 27)
-;                 (mod:SI (reg:SI 24)
-;                         (reg:SI 25)))
-;            (clobber (reg:DI 23))
-;            (clobber (reg:DI 28))])
-;   (set (match_operand:SI 0 "general_operand" "")
-;      (reg:SI 27))]
-;  "!TARGET_OPEN_VMS"
-;  "")
-
-;(define_expand "umodsi3"
-;  [(set (reg:SI 24) (match_operand:SI 1 "input_operand" ""))
-;   (set (reg:SI 25) (match_operand:SI 2 "input_operand" ""))
-;   (parallel [(set (reg:SI 27)
-;                 (umod:SI (reg:SI 24)
-;                          (reg:SI 25)))
-;            (clobber (reg:DI 23))
-;            (clobber (reg:DI 28))])
-;   (set (match_operand:SI 0 "general_operand" "")
-;      (reg:SI 27))]
-;  "!TARGET_OPEN_VMS"
-;  "")
+;; ??? Force sign-extension here because some versions of OSF/1 don't
+;; do the right thing if the inputs are not properly sign-extended.
+;; But Linux, for instance, does not have this problem.  Is it worth
+;; the complication here to eliminate the sign extension?
+
+(define_expand "divsi3"
+  [(set (reg:DI 24)
+       (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))
+   (set (reg:DI 25)
+       (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "")))
+   (parallel [(set (reg:DI 27)
+                  (sign_extend:DI (div:SI (reg:DI 24) (reg:DI 25))))
+             (clobber (reg:DI 23))
+             (clobber (reg:DI 28))])
+   (set (match_operand:SI 0 "general_operand" "")
+       (subreg:SI (reg:DI 27) 0))]
+  "!TARGET_OPEN_VMS"
+  "")
+
+(define_expand "udivsi3"
+  [(set (reg:DI 24)
+       (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))
+   (set (reg:DI 25)
+       (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "")))
+   (parallel [(set (reg:DI 27)
+                  (sign_extend:DI (udiv:SI (reg:DI 24) (reg:DI 25))))
+             (clobber (reg:DI 23))
+             (clobber (reg:DI 28))])
+   (set (match_operand:SI 0 "general_operand" "")
+       (subreg:SI (reg:DI 27) 0))]
+  "!TARGET_OPEN_VMS"
+  "")
+
+(define_expand "modsi3"
+  [(set (reg:DI 24)
+       (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))
+   (set (reg:DI 25)
+       (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "")))
+   (parallel [(set (reg:DI 27)
+                  (sign_extend:DI (mod:SI (reg:DI 24) (reg:DI 25))))
+             (clobber (reg:DI 23))
+             (clobber (reg:DI 28))])
+   (set (match_operand:SI 0 "general_operand" "")
+       (subreg:SI (reg:DI 27) 0))]
+  "!TARGET_OPEN_VMS"
+  "")
+
+(define_expand "umodsi3"
+  [(set (reg:DI 24)
+       (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))
+   (set (reg:DI 25)
+       (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "")))
+   (parallel [(set (reg:DI 27)
+                  (sign_extend:DI (umod:SI (reg:DI 24) (reg:DI 25))))
+             (clobber (reg:DI 23))
+             (clobber (reg:DI 28))])
+   (set (match_operand:SI 0 "general_operand" "")
+       (subreg:SI (reg:DI 27) 0))]
+  "!TARGET_OPEN_VMS"
+  "")
 
 (define_expand "divdi3"
   [(set (reg:DI 24) (match_operand:DI 1 "input_operand" ""))
   "!TARGET_OPEN_VMS"
   "")
 
-;(define_insn ""
-;  [(set (reg:SI 27)
-;      (match_operator:SI 1 "divmod_operator"
-;                      [(reg:SI 24) (reg:SI 25)]))
-;   (clobber (reg:DI 23))
-;   (clobber (reg:DI 28))]
-;  "!TARGET_OPEN_VMS"
-;  "%E1 $24,$25,$27"
-;  [(set_attr "type" "jsr")])
+;; Lengths of 8 for ldq $t12,__divq($gp); jsr $t9,($t12),__divq as
+;; expanded by the assembler.
+(define_insn ""
+  [(set (reg:DI 27)
+       (sign_extend:DI (match_operator:SI 1 "divmod_operator"
+                       [(reg:DI 24) (reg:DI 25)])))
+   (clobber (reg:DI 23))
+   (clobber (reg:DI 28))]
+  "!TARGET_OPEN_VMS"
+  "%E1 $24,$25,$27"
+  [(set_attr "type" "jsr")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (reg:DI 27)
    (clobber (reg:DI 28))]
   "!TARGET_OPEN_VMS"
   "%E1 $24,$25,$27"
-  [(set_attr "type" "jsr")])
+  [(set_attr "type" "jsr")
+   (set_attr "length" "8")])
 \f
 ;; Next are the basic logical operations.  These only exist in DImode.
 
 (define_insn "ashldi3"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
        (ashift:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,rJ")
-                  (match_operand:DI 2 "reg_or_6bit_operand" "P,rI")))]
+                  (match_operand:DI 2 "reg_or_6bit_operand" "P,rS")))]
   ""
   "*
 {
        return \"s%P2addq %r1,0,%0\";
     case 1:
       return \"sll %r1,%2,%0\";
+    default:
+      abort();
     }
 }"
   [(set_attr "type" "iadd,shift")])
 (define_insn "lshrdi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
-                    (match_operand:DI 2 "reg_or_6bit_operand" "rI")))]
+                    (match_operand:DI 2 "reg_or_6bit_operand" "rS")))]
   ""
   "srl %r1,%2,%0"
   [(set_attr "type" "shift")])
 (define_insn "ashrdi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (ashiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
-                    (match_operand:DI 2 "reg_or_6bit_operand" "rI")))]
+                    (match_operand:DI 2 "reg_or_6bit_operand" "rS")))]
   ""
   "sra %r1,%2,%0"
   [(set_attr "type" "shift")])
   "ext%M2l %r1,%3,%0"
   [(set_attr "type" "shift")])
 
+;; Combine has some strange notion of preserving existing undefined behaviour
+;; in shifts larger than a word size.  So capture these patterns that it 
+;; should have turned into zero_extracts.
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (and (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
+               (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+                          (const_int 3)))
+            (match_operand:DI 3 "mode_mask_operand" "n")))]
+  ""
+  "ext%U3l %1,%2,%0"
+  [(set_attr "type" "shift")])
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
+         (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+                    (const_int 3))))]
+  ""
+  "extql %1,%2,%0"
+  [(set_attr "type" "shift")])
+
 (define_insn "extqh"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (ashift:DI
   "insql %1,%2,%0"
   [(set_attr "type" "shift")])
 
+;; Combine has this sometimes habit of moving the and outside of the
+;; shift, making life more interesting.
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
+                          (match_operand:DI 2 "mul8_operand" "I"))
+               (match_operand:DI 3 "immediate_operand" "i")))]
+  "HOST_BITS_PER_WIDE_INT == 64
+   && GET_CODE (operands[3]) == CONST_INT
+   && (((unsigned HOST_WIDE_INT) 0xff << INTVAL (operands[2])
+        == INTVAL (operands[3]))
+       || ((unsigned HOST_WIDE_INT) 0xffff << INTVAL (operands[2])
+        == INTVAL (operands[3]))
+       || ((unsigned HOST_WIDE_INT) 0xffffffff << INTVAL (operands[2])
+        == INTVAL (operands[3])))"
+  "*
+{
+#if HOST_BITS_PER_WIDE_INT == 64
+  if ((unsigned HOST_WIDE_INT) 0xff << INTVAL (operands[2])
+      == INTVAL (operands[3]))
+    return \"insbl %1,%s2,%0\";
+  if ((unsigned HOST_WIDE_INT) 0xffff << INTVAL (operands[2])
+      == INTVAL (operands[3]))
+    return \"inswl %1,%s2,%0\";
+  if ((unsigned HOST_WIDE_INT) 0xffffffff << INTVAL (operands[2])
+      == INTVAL (operands[3]))
+    return \"insll %1,%s2,%0\";
+#endif
+  abort();
+}"
+  [(set_attr "type" "shift")])
+
 ;; We do not include the insXh insns because they are complex to express
 ;; and it does not appear that we would ever want to generate them.
 ;;
 (define_insn "negsf2"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (neg:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
-  "TARGET_FP && alpha_fptm == ALPHA_FPTM_N"
+  "TARGET_FP"
   "cpysn %R1,%R1,%0"
   [(set_attr "type" "fadd")])
 
-(define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=&f")
-       (neg:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
-  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
-  "sub%,%)%& $f31,%R1,%0"
-  [(set_attr "type" "fadd")
-   (set_attr "trap" "yes")])
-
-(define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=f")
-       (neg:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
-  "TARGET_FP"
-  "sub%,%)%& $f31,%R1,%0"
-  [(set_attr "type" "fadd")
-   (set_attr "trap" "yes")])
-
 (define_insn "negdf2"
   [(set (match_operand:DF 0 "register_operand" "=f")
        (neg:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
   [(set_attr "type" "fadd")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=&f")
-       (neg:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
-  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
-  "sub%-%)%& $f31,%R1,%0"
-  [(set_attr "type" "fadd")
-   (set_attr "trap" "yes")])
-
-(define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=f")
-       (neg:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
-  "TARGET_FP"
-  "sub%-%)%& $f31,%R1,%0"
-  [(set_attr "type" "fadd")
-   (set_attr "trap" "yes")])
-
-(define_insn ""
   [(set (match_operand:SF 0 "register_operand" "=&f")
        (plus:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG")
                 (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
   [(set_attr "type" "fadd")
    (set_attr "trap" "yes")])
 
+;; Define conversion operators between DFmode and SImode, using the cvtql
+;; instruction.  To allow combine et al to do useful things, we keep the
+;; operation as a unit until after reload, at which point we split the
+;; instructions.
+;;
+;; Note that we (attempt to) only consider this optimization when the
+;; ultimate destination is memory.  If we will be doing further integer
+;; processing, it is cheaper to do the truncation in the int regs.
+
+(define_insn "*cvtql"
+  [(set (match_operand:SI 0 "register_operand" "=f")
+       (unspec:SI [(match_operand:DI 1 "reg_or_fp0_operand" "fG")] 5))]
+  "TARGET_FP"
+  "cvtql%` %R1,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_split
+  [(set (match_operand:SI 0 "memory_operand" "")
+       (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "")) 0))
+   (clobber (match_scratch:DI 2 ""))
+   (clobber (match_scratch:SI 3 ""))]
+  "TARGET_FP && reload_completed"
+  [(set (match_dup 2) (fix:DI (match_dup 1)))
+   (set (match_dup 3) (unspec:SI [(match_dup 2)] 5))
+   (set (match_dup 0) (match_dup 3))]
+  "")
+
+(define_split
+  [(set (match_operand:SI 0 "memory_operand" "")
+       (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "")) 0))
+   (clobber (match_scratch:DI 2 ""))]
+  "TARGET_FP && reload_completed"
+  [(set (match_dup 2) (fix:DI (match_dup 1)))
+   (set (match_dup 3) (unspec:SI [(match_dup 2)] 5))
+   (set (match_dup 0) (match_dup 3))]
+  ;; Due to REG_CANNOT_CHANGE_SIZE issues, we cannot simply use SUBREG.
+  "operands[3] = gen_rtx_REG (SImode, REGNO (operands[2]));")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "memory_operand" "=m")
+       (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")) 0))
+   (clobber (match_scratch:DI 2 "=&f"))
+   (clobber (match_scratch:SI 3 "=&f"))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "#"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "memory_operand" "=m")
+       (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")) 0))
+   (clobber (match_scratch:DI 2 "=f"))]
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "#"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=&f")
        (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
   [(set_attr "type" "fadd")
    (set_attr "trap" "yes")])
 
+;; Likewise between SFmode and SImode.
+
+(define_split
+  [(set (match_operand:SI 0 "memory_operand" "")
+       (subreg:SI (fix:DI (float_extend:DF
+                (match_operand:SF 1 "reg_or_fp0_operand" ""))) 0))
+   (clobber (match_scratch:DI 2 ""))
+   (clobber (match_scratch:SI 3 ""))]
+  "TARGET_FP && reload_completed"
+  [(set (match_dup 2) (fix:DI (float_extend:DF (match_dup 1))))
+   (set (match_dup 3) (unspec:SI [(match_dup 2)] 5))
+   (set (match_dup 0) (match_dup 3))]
+  "")
+
+(define_split
+  [(set (match_operand:SI 0 "memory_operand" "")
+       (subreg:SI (fix:DI (float_extend:DF
+                (match_operand:SF 1 "reg_or_fp0_operand" ""))) 0))
+   (clobber (match_scratch:DI 2 ""))]
+  "TARGET_FP && reload_completed"
+  [(set (match_dup 2) (fix:DI (float_extend:DF (match_dup 1))))
+   (set (match_dup 3) (unspec:SI [(match_dup 2)] 5))
+   (set (match_dup 0) (match_dup 3))]
+  ;; Due to REG_CANNOT_CHANGE_SIZE issues, we cannot simply use SUBREG.
+  "operands[3] = gen_rtx_REG (SImode, REGNO (operands[2]));")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "memory_operand" "=m")
+       (subreg:SI (fix:DI (float_extend:DF
+                (match_operand:SF 1 "reg_or_fp0_operand" "fG"))) 0))
+   (clobber (match_scratch:DI 2 "=&f"))
+   (clobber (match_scratch:SI 3 "=&f"))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "#"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "memory_operand" "=m")
+       (subreg:SI (fix:DI (float_extend:DF
+                (match_operand:SF 1 "reg_or_fp0_operand" "fG"))) 0))
+   (clobber (match_scratch:DI 2 "=f"))]
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "#"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=&f")
        (fix:DI (float_extend:DF
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
-       (if_then_else:DI
+       (if_then_else:SI
         (match_operator 2 "signed_comparison_operator"
                         [(match_operand:DI 3 "reg_or_0_operand" "rJ,rJ,J,J")
                          (match_operand:DI 4 "reg_or_0_operand" "J,J,rJ,rJ")])
    (clobber (match_scratch:DI 4 "=&r"))]
   ""
   "addq %0,%1,%4\;cmov%C2 %r3,%4,%0"
-  [(set_attr "type" "icmov")])
+  [(set_attr "type" "icmov")
+   (set_attr "length" "8")])
 
 (define_split
   [(set (match_operand:DI 0 "register_operand" "")
 
 (define_insn "sminqi3"
   [(set (match_operand:QI 0 "register_operand" "=r")
-       (smin:SI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
+       (smin:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
                 (match_operand:QI 2 "reg_or_8bit_operand" "rI")))]
   "TARGET_MAX"
   "minsb8 %r1,%2,%0"
 
 (define_insn "uminqi3"
   [(set (match_operand:QI 0 "register_operand" "=r")
-       (umin:SI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
+       (umin:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
                 (match_operand:QI 2 "reg_or_8bit_operand" "rI")))]
   "TARGET_MAX"
   "minub8 %r1,%2,%0"
 
 (define_insn "smaxqi3"
   [(set (match_operand:QI 0 "register_operand" "=r")
-       (smax:SI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
+       (smax:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
                 (match_operand:QI 2 "reg_or_8bit_operand" "rI")))]
   "TARGET_MAX"
   "maxsb8 %r1,%2,%0"
 
 (define_insn "umaxqi3"
   [(set (match_operand:QI 0 "register_operand" "=r")
-       (umax:SI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
+       (umax:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
                 (match_operand:QI 2 "reg_or_8bit_operand" "rI")))]
   "TARGET_MAX"
   "maxub8 %r1,%2,%0"
 
 (define_insn "sminhi3"
   [(set (match_operand:HI 0 "register_operand" "=r")
-       (smin:SI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
+       (smin:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
                 (match_operand:HI 2 "reg_or_8bit_operand" "rI")))]
   "TARGET_MAX"
   "minsw4 %r1,%2,%0"
 
 (define_insn "uminhi3"
   [(set (match_operand:HI 0 "register_operand" "=r")
-       (umin:SI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
+       (umin:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
                 (match_operand:HI 2 "reg_or_8bit_operand" "rI")))]
   "TARGET_MAX"
   "minuw4 %r1,%2,%0"
 
 (define_insn "smaxhi3"
   [(set (match_operand:HI 0 "register_operand" "=r")
-       (smax:SI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
+       (smax:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
                 (match_operand:HI 2 "reg_or_8bit_operand" "rI")))]
   "TARGET_MAX"
   "maxsw4 %r1,%2,%0"
 
 (define_insn "umaxhi3"
   [(set (match_operand:HI 0 "register_operand" "=r")
-       (umax:SI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
+       (umax:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
                 (match_operand:HI 2 "reg_or_8bit_operand" "rI")))]
   "TARGET_MAX"
   "maxuw4 %r1,%2,%0"
    (set_attr "trap" "yes")])
 
 (define_insn ""
+  [(set (match_operand:DF 0 "register_operand" "=&f")
+       (match_operator:DF 1 "alpha_comparison_operator"
+                          [(float_extend:DF
+                            (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
+                           (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "cmp%-%C1%' %R2,%R3,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
        (match_operator:DF 1 "alpha_comparison_operator"
                           [(float_extend:DF
    (set_attr "trap" "yes")])
 
 (define_insn ""
+  [(set (match_operand:DF 0 "register_operand" "=&f")
+       (match_operator:DF 1 "alpha_comparison_operator"
+                          [(match_operand:DF 2 "reg_or_fp0_operand" "fG")
+                           (float_extend:DF
+                            (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "cmp%-%C1%' %R2,%R3,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
        (match_operator:DF 1 "alpha_comparison_operator"
                           [(match_operand:DF 2 "reg_or_fp0_operand" "fG")
    (set_attr "trap" "yes")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=f")
+  [(set (match_operand:DF 0 "register_operand" "=&f")
        (match_operator:DF 1 "alpha_comparison_operator"
                           [(float_extend:DF
                             (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
                            (float_extend:DF
                             (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))]
-  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
   "cmp%-%C1%' %R2,%R3,%0"
   [(set_attr "type" "fadd")
    (set_attr "trap" "yes")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=&f,f")
-       (if_then_else:DF 
-        (match_operator 3 "signed_comparison_operator"
-                        [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG")
-                         (match_operand:DF 2 "fp0_operand" "G,G")])
-        (match_operand:DF 1 "reg_or_fp0_operand" "fG,0")
-        (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))]
-  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
-  "@
-   fcmov%C3 %R4,%R1,%0
-   fcmov%D3 %R4,%R5,%0"
-  [(set_attr "type" "fcmov")])
+  [(set (match_operand:DF 0 "register_operand" "=f")
+       (match_operator:DF 1 "alpha_comparison_operator"
+                          [(float_extend:DF
+                            (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
+                           (float_extend:DF
+                            (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))]
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "cmp%-%C1%' %R2,%R3,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f,f")
                          (match_operand:DF 2 "fp0_operand" "G,G")])
         (match_operand:DF 1 "reg_or_fp0_operand" "fG,0")
         (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))]
-  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
-  "@
-   fcmov%C3 %R4,%R1,%0
-   fcmov%D3 %R4,%R5,%0"
-  [(set_attr "type" "fcmov")])
-
-(define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=&f,f")
-       (if_then_else:SF 
-        (match_operator 3 "signed_comparison_operator"
-                        [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG")
-                         (match_operand:DF 2 "fp0_operand" "G,G")])
-        (match_operand:SF 1 "reg_or_fp0_operand" "fG,0")
-        (match_operand:SF 5 "reg_or_fp0_operand" "0,fG")))]
-  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "TARGET_FP"
   "@
    fcmov%C3 %R4,%R1,%0
    fcmov%D3 %R4,%R5,%0"
                          (match_operand:DF 2 "fp0_operand" "G,G")])
         (match_operand:SF 1 "reg_or_fp0_operand" "fG,0")
         (match_operand:SF 5 "reg_or_fp0_operand" "0,fG")))]
-  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "TARGET_FP"
   "@
    fcmov%C3 %R4,%R1,%0
    fcmov%D3 %R4,%R5,%0"
                          (match_operand:DF 2 "fp0_operand" "G,G")])
         (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG,0"))
         (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))]
-  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "TARGET_FP"
   "@
    fcmov%C3 %R4,%R1,%0
    fcmov%D3 %R4,%R5,%0"
                          (match_operand:DF 2 "fp0_operand" "G,G")])
         (match_operand:DF 1 "reg_or_fp0_operand" "fG,0")
         (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))]
-  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "TARGET_FP"
   "@
    fcmov%C3 %R4,%R1,%0
    fcmov%D3 %R4,%R5,%0"
                          (match_operand:DF 2 "fp0_operand" "G,G")])
         (match_operand:SF 1 "reg_or_fp0_operand" "fG,0")
         (match_operand:SF 5 "reg_or_fp0_operand" "0,fG")))]
-  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "TARGET_FP"
   "@
    fcmov%C3 %R4,%R1,%0
    fcmov%D3 %R4,%R5,%0"
                          (match_operand:DF 2 "fp0_operand" "G,G")])
         (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG,0"))
         (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))]
-  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "TARGET_FP"
   "@
    fcmov%C3 %R4,%R1,%0
    fcmov%D3 %R4,%R5,%0"
 
 (define_expand "movsicc"
   [(set (match_operand:SI 0 "register_operand" "")
-       (if_then_else:DI (match_operand 1 "comparison_operator" "")
+       (if_then_else:SI (match_operand 1 "comparison_operator" "")
                         (match_operand:SI 2 "reg_or_8bit_operand" "")
                         (match_operand:SI 3 "reg_or_8bit_operand" "")))]
   ""
   if (GET_CODE (operands[0]) == SYMBOL_REF)
     {
       extern char *savealloc ();
-      char *symbol = XSTR (operands[0], 0);
-      char *linksym = savealloc (strlen (symbol) + 6);
+      char *linksym, *symbol = XSTR (operands[0], 0);
       rtx linkage;
 
+      if (*symbol == '*')
+       symbol++;
+      linksym = savealloc (strlen (symbol) + 6);
+
       alpha_need_linkage (symbol, 0);
 
       linksym[0] = '$';
   if (GET_CODE (operands[1]) == SYMBOL_REF)
     {
       extern char *savealloc ();
-      char *symbol = XSTR (operands[1], 0);
-      char *linksym = savealloc (strlen (symbol) + 6);
+      char *linksym, *symbol = XSTR (operands[1], 0);
       rtx linkage;
 
+      if (*symbol == '*')
+       symbol++;
+      linksym = savealloc (strlen (symbol) + 6);
+
       alpha_need_linkage (symbol, 0);
       linksym[0] = '$';
       strcpy (linksym+1, symbol);
    jsr $26,($27),0\;ldgp $29,0($26)
    bsr $26,$%0..ng
    jsr $26,%0\;ldgp $29,0($26)"
-  [(set_attr "type" "jsr")])
+  [(set_attr "type" "jsr")
+   (set_attr "length" "12,*,16")])
       
 (define_insn ""
   [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i"))
    jsr $26,(%0)
    bsr $26,%0
    jsr $26,%0"
-  [(set_attr "type" "jsr")])
+  [(set_attr "type" "jsr")
+   (set_attr "length" "*,*,12")])
       
 (define_insn ""
   [(call (mem:DI (match_operand:DI 0 "call_operand" "r,i"))
   "@
    bis %2,%2,$27\;jsr $26,0\;ldq $27,0($29)
    ldq $27,%2\;jsr $26,%0\;ldq $27,0($29)"
-  [(set_attr "type" "jsr")])
+  [(set_attr "type" "jsr")
+   (set_attr "length" "12,16")])
 
 (define_insn ""
   [(set (match_operand 0 "register_operand" "=rf,rf,rf")
    jsr $26,($27),0\;ldgp $29,0($26)
    bsr $26,$%1..ng
    jsr $26,%1\;ldgp $29,0($26)"
-  [(set_attr "type" "jsr")])
+  [(set_attr "type" "jsr")
+   (set_attr "length" "12,*,16")])
 
 (define_insn ""
   [(set (match_operand 0 "register_operand" "=rf,rf,rf")
    jsr $26,(%1)
    bsr $26,%1
    jsr $26,%1"
-  [(set_attr "type" "jsr")])
+  [(set_attr "type" "jsr")
+   (set_attr "length" "*,*,12")])
 
 (define_insn ""
   [(set (match_operand 0 "register_operand" "")
   "@
    bis %3,%3,$27\;jsr $26,0\;ldq $27,0($29)
    ldq $27,%3\;jsr $26,%1\;ldq $27,0($29)"
-  [(set_attr "type" "jsr")])
+  [(set_attr "type" "jsr")
+   (set_attr "length" "12,16")])
 
 ;; Call subroutine returning any type.
 
 (define_insn "blockage"
   [(unspec_volatile [(const_int 0)] 1)]
   ""
-  "")
+  ""
+  [(set_attr "length" "0")])
 
 (define_insn "jump"
   [(set (pc)
   "ret $31,($26),1"
   [(set_attr "type" "ibr")])
 
+;; Use a different pattern for functions which have non-trivial
+;; epilogues so as not to confuse jump and reorg.
+(define_insn "return_internal"
+  [(use (reg:DI 26))
+   (return)]
+  ""
+  "ret $31,($26),1"
+  [(set_attr "type" "ibr")])
+
 (define_insn "indirect_jump"
   [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
   ""
   "jmp $31,(%0),0"
   [(set_attr "type" "ibr")])
 
-(define_insn "nop"
-  [(const_int 0)]
-  ""
-  "bis $31,$31,$31"
-  [(set_attr "type" "ilog")])
-
 (define_expand "tablejump"
   [(use (match_operand:SI 0 "register_operand" ""))
    (use (match_operand:SI 1 "" ""))]
   else
     return \"addq %0,$29,%2\;jmp $31,(%2),0\";
 }"
-  [(set_attr "type" "ibr")])
+  [(set_attr "type" "ibr")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (pc)
 ;; Technically the type for call_pal is jsr, but we use that for determining
 ;; if we need a GP.  Use ibr instead since it has the same EV5 scheduling
 ;; characteristics.
-(define_insn ""
+(define_insn "imb"
   [(unspec_volatile [(const_int 0)] 0)]
   ""
   "call_pal 0x86"
     {
       if (TARGET_BUILD_CONSTANTS)
        {
-#if HOST_BITS_PER_WIDE_INT == 64
-         HOST_WIDE_INT i;
+         HOST_WIDE_INT i0, i1;
 
          if (GET_CODE (operands[1]) == CONST_INT)
-           i = INTVAL (operands[1]);
+           {
+             i0 = INTVAL (operands[1]);
+             i1 = -(i0 < 0);
+           }
          else if (GET_CODE (operands[1]) == CONST_DOUBLE)
-           i = CONST_DOUBLE_LOW (operands[1]);
+           {
+#if HOST_BITS_PER_WIDE_INT >= 64
+             i0 = CONST_DOUBLE_LOW (operands[1]);
+             i1 = -(i0 < 0);
+#else
+             i0 = CONST_DOUBLE_LOW (operands[1]);
+             i1 = CONST_DOUBLE_HIGH (operands[1]);
+#endif
+           }
          else
            abort();
          
-          tem = alpha_emit_set_long_const (operands[0], i);
+          tem = alpha_emit_set_long_const (operands[0], i0, i1);
           if (rtx_equal_p (tem, operands[0]))
            DONE;
           else
            operands[1] = tem;
-#else
-          abort();
-#endif
        }
       else
        {
     }
 }")
 
+;; This is used by alpha_expand_prolog to do the same thing as above,
+;; except we cannot at that time generate new basic blocks, so we hide
+;; the loop in this one insn.
+
+(define_insn "prologue_stack_probe_loop"
+  [(unspec_volatile [(match_operand 0 "register_operand" "r")
+                    (match_operand 1 "register_operand" "r")] 5)]
+  ""
+  "*
+{
+  static int label_no;
+  int count_regno = REGNO (operands[0]);
+  int ptr_regno = REGNO (operands[1]);
+  char label[64];
+
+  /* Ho hum, output the hard way to get the label at the beginning of
+     the line.  Wish there were a magic char you could get
+     asm_output_printf to do that.  Then we could use %= as well and
+     get rid of the label_no bits here too.  */
+
+  ASM_GENERATE_INTERNAL_LABEL (label, \"LSC\", label_no);
+  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LSC\", label_no++);
+
+  fprintf (asm_out_file, \"\\tstq $31,-8192($%d)\\n\", ptr_regno);
+  fprintf (asm_out_file, \"\\tsubq $%d,1,$%d\\n\", count_regno, count_regno);
+  fprintf (asm_out_file, \"\\tlda $%d,-8192($%d)\\n\", ptr_regno, ptr_regno);
+  fprintf (asm_out_file, \"\\tbne $%d,\", count_regno);
+  assemble_name (asm_out_file, label);
+  putc ('\\n', asm_out_file);
+
+  return \"\";
+}"
+  [(set_attr "length" "16")
+   (set_attr "type" "multi")])
+
+(define_expand "prologue"
+  [(clobber (const_int 0))]
+  ""
+  "alpha_expand_prologue (); DONE;")
+
+(define_insn "init_fp"
+  [(set (match_operand:DI 0 "register_operand" "r")
+        (match_operand:DI 1 "register_operand" "r"))
+   (clobber (mem:BLK (match_operand:DI 2 "register_operand" "r")))]
+  ""
+  "bis %1,%1,%0")
+
+(define_expand "epilogue"
+  [(clobber (const_int 0))]
+  ""
+  "alpha_expand_epilogue (); DONE;")
+
+(define_expand "eh_epilogue"
+  [(use (match_operand:DI 0 "register_operand" "r"))
+   (use (match_operand:DI 1 "register_operand" "r"))
+   (use (match_operand:DI 2 "register_operand" "r"))]
+  "! TARGET_OPEN_VMS"
+  "
+{
+  alpha_eh_epilogue_sp_ofs = operands[1];
+  if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 26)
+    {
+      rtx ra = gen_rtx_REG (Pmode, 26);
+      emit_move_insn (ra, operands[2]);
+      operands[2] = ra;
+    }
+}")
+
 (define_expand "builtin_longjmp"
   [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)]
   "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
      where to look for it when we get back to setjmp's function for
      restoring the gp.  */
   emit_indirect_jump (pv);
+  DONE;
 }")
 
 (define_insn "builtin_setjmp_receiver"
   [(unspec_volatile [(match_operand 0 "" "")] 2)]
   "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT && TARGET_AS_CAN_SUBTRACT_LABELS"
-  "\\n$LSJ%=:\;ldgp $29,$LSJ%=-%l0($27)")
+  "\\n$LSJ%=:\;ldgp $29,$LSJ%=-%l0($27)"
+  [(set_attr "length" "8")
+   (set_attr "type" "multi")])
 
 (define_insn ""
   [(unspec_volatile [(match_operand 0 "" "")] 2)]
   "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
-  "br $27,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($27)")
+  "br $29,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($29)"
+  [(set_attr "length" "12")
+   (set_attr "type" "multi")])
+
+(define_insn "exception_receiver"
+  [(unspec_volatile [(const_int 0)] 7)]
+  "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
+  "br $29,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($29)"
+  [(set_attr "length" "12")
+   (set_attr "type" "multi")])
 
 (define_expand "nonlocal_goto_receiver"
   [(unspec_volatile [(const_int 0)] 1)
    (clobber (reg:DI 25))
    (clobber (reg:DI 0))]
   "TARGET_OPEN_VMS"
-  "lda $0,OTS$HOME_ARGS\;ldq $0,8($0)\;jsr $0,OTS$HOME_ARGS")
+  "lda $0,OTS$HOME_ARGS\;ldq $0,8($0)\;jsr $0,OTS$HOME_ARGS"
+  [(set_attr "length" "16")
+   (set_attr "type" "multi")])
 
 ;; Close the trap shadow of preceeding instructions.  This is generated
 ;; by alpha_reorg.
   ""
   "trapb"
   [(set_attr "type" "misc")])
+
+;; No-op instructions used by machine-dependant reorg to preserve
+;; alignment for instruction issue.
+
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  "nop"
+  [(set_attr "type" "ilog")])
+
+(define_insn "fnop"
+  [(const_int 1)]
+  "TARGET_FP"
+  "fnop"
+  [(set_attr "type" "fcpys")])
+
+(define_insn "unop"
+  [(const_int 2)]
+  ""
+  "unop")
+
+(define_insn "realign"
+  [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] 6)]
+  ""
+  ".align %0 #realign")
+\f
+;; Peepholes go at the end.
+
+;; Optimize sign-extension of SImode loads.  This shows up in the wake of
+;; reload when converting fp->int.
+;;
+;; ??? What to do now that we actually care about the packing and
+;; alignment of instructions?  Perhaps reload can be enlightened, or
+;; the peephole pass moved up after reload but before sched2?
+;
+;(define_peephole
+;  [(set (match_operand:SI 0 "register_operand" "=r")
+;        (match_operand:SI 1 "memory_operand" "m"))
+;   (set (match_operand:DI 2 "register_operand" "=r")
+;        (sign_extend:DI (match_dup 0)))]
+;  "dead_or_set_p (insn, operands[0])"
+;  "ldl %2,%1")
+;
+;(define_peephole
+;  [(set (match_operand:SI 0 "register_operand" "=r")
+;        (match_operand:SI 1 "hard_fp_register_operand" "f"))
+;   (set (match_operand:DI 2 "register_operand" "=r")
+;        (sign_extend:DI (match_dup 0)))]
+;  "TARGET_CIX && dead_or_set_p (insn, operands[0])"
+;  "ftois %1,%2")