OSDN Git Service

* alpha.md (builtin_longjmp): Add missing "DONE".
[pf3gnuchains/gcc-fork.git] / gcc / config / alpha / alpha.md
index 459ca66..59b04f9 100644 (file)
@@ -1,5 +1,5 @@
 ;; Machine description for DEC Alpha for GNU C compiler
-;; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
 ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
 ;; This file is part of GNU CC.
 
 ;; 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.
+
+;; Uses of UNSPEC in this file:
+;;
+;;     0       arg_home
+;;     1       cttz
+;;     2       insxh
+;;     3       mskxh
+;;     4       cvtlq
+;;     5       cvtql
+;;     
+;; UNSPEC_VOLATILE:
+;;
+;;     0       imb
+;;     1       blockage
+;;     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.
+
+(define_attr "cpu" "ev4,ev5,ev6"
+  (const (symbol_ref "alpha_cpu")))
+
 ;; Define an insn type attribute.  This is used in function unit delay
 ;; computations, among other purposes.  For the most part, we use the names
 ;; defined in the EV4 documentation, but add a few that we have to know about
 ;; separately.
 
 (define_attr "type"
-  "ld,st,ibr,fbr,jsr,iaddlog,shiftcm,icmp,imull,imulq,fpop,fdivs,fdivt,ldsym,isubr"
-  (const_string "shiftcm"))
-
-;; We include four function units: ABOX, which computes the address,
-;; BBOX, used for branches, EBOX, used for integer operations, and FBOX,
-;; used for FP operations.
-;;
-;; We assume that we have been successful in getting double issues and
-;; hence multiply all costs by two insns per cycle.  The minimum time in
-;; a function unit is 2 cycle, which will tend to produce the double
-;; issues.
-
-;; Memory delivers its result in three cycles.
-(define_function_unit "abox" 1 0 (eq_attr "type" "ld,ldsym,st") 6 2)
+  "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"))
 
-;; Branches have no delay cost, but do tie up the unit for two cycles.
-(define_function_unit "bbox" 1 1 (eq_attr "type" "ibr,fbr,jsr") 4 4)
+;; Describe a user's asm statement.
+(define_asm_attributes
+  [(set_attr "type" "multi")])
 
-;; Arithmetic insns are normally have their results available after two
-;; cycles.  There are a number of exceptions.  They are encoded in
-;; ADJUST_COST.  Some of the other insns have similar exceptions.
+;; Define the operand size an insn operates on.  Used primarily by mul
+;; and div operations that have size dependant timings.
 
-(define_function_unit "ebox" 1 0 (eq_attr "type" "iaddlog,shiftcm,icmp") 4 2)
+(define_attr "opsize" "si,di,udi" (const_string "di"))
 
-;; These really don't take up the integer pipeline, but they do occupy
-;; IBOX1; we approximate here.
+;; The TRAP_TYPE attribute marks instructions that may generate traps
+;; (which are imprecise and may need a trapb if software completion
+;; is desired).
 
-(define_function_unit "ebox" 1 0 (eq_attr "type" "imull") 42 2)
-(define_function_unit "ebox" 1 0 (eq_attr "type" "imulq") 46 2)
+(define_attr "trap" "no,yes" (const_string "no"))
 
-(define_function_unit "imult" 1 0 (eq_attr "type" "imull") 42 38)
-(define_function_unit "imult" 1 0 (eq_attr "type" "imulq") 46 42)
+;; The length of an instruction sequence in bytes.
 
-(define_function_unit "fbox" 1 0 (eq_attr "type" "fpop") 12 2)
-
-(define_function_unit "fbox" 1 0 (eq_attr "type" "fdivs") 68 0)
-(define_function_unit "fbox" 1 0 (eq_attr "type" "fdivt") 126 0)
+(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
+;; category.  ABOX, BBOX, EBOX, FBOX, IMUL & FDIV make up the second.
+;; (There are a few other register-like resources, but ...)
+
+; First, describe all of the issue constraints with single cycle delays.
+; All insns need a bus, but all except loads require one or the other.
+(define_function_unit "ev4_ibus0" 1 0
+  (and (eq_attr "cpu" "ev4")
+       (eq_attr "type" "fst,fbr,iadd,imul,ilog,shift,icmov,icmp"))
+  1 1)
+
+(define_function_unit "ev4_ibus1" 1 0
+  (and (eq_attr "cpu" "ev4")
+       (eq_attr "type" "ist,ibr,jsr,fadd,fcmov,fcpys,fmul,fdiv,misc"))
+  1 1)
+
+; Memory delivers its result in three cycles.  Actually return one and
+; take care of this in adjust_cost, since we want to handle user-defined
+; memory latencies.
+(define_function_unit "ev4_abox" 1 0
+  (and (eq_attr "cpu" "ev4")
+       (eq_attr "type" "ild,fld,ldsym,ist,fst"))
+  1 1)
+
+; Branches have no delay cost, but do tie up the unit for two cycles.
+(define_function_unit "ev4_bbox" 1 1
+  (and (eq_attr "cpu" "ev4")
+       (eq_attr "type" "ibr,fbr,jsr"))
+  2 2)
+
+; Arithmetic insns are normally have their results available after
+; two cycles.  There are a number of exceptions.  They are encoded in
+; ADJUST_COST.  Some of the other insns have similar exceptions.
+(define_function_unit "ev4_ebox" 1 0
+  (and (eq_attr "cpu" "ev4")
+       (eq_attr "type" "iadd,ilog,shift,icmov,icmp,misc"))
+  2 1)
+
+(define_function_unit "imul" 1 0
+  (and (eq_attr "cpu" "ev4")
+       (and (eq_attr "type" "imul")
+           (eq_attr "opsize" "si")))
+  21 19)
+
+(define_function_unit "imul" 1 0
+  (and (eq_attr "cpu" "ev4")
+       (and (eq_attr "type" "imul")
+           (eq_attr "opsize" "!si")))
+  23 21)
+
+(define_function_unit "ev4_fbox" 1 0
+  (and (eq_attr "cpu" "ev4")
+       (eq_attr "type" "fadd,fmul,fcpys,fcmov"))
+  6 1)
+
+(define_function_unit "fdiv" 1 0
+  (and (eq_attr "cpu" "ev4")
+       (and (eq_attr "type" "fdiv")
+           (eq_attr "opsize" "si")))
+  34 30)
+
+(define_function_unit "fdiv" 1 0
+  (and (eq_attr "cpu" "ev4")
+       (and (eq_attr "type" "fdiv")
+           (eq_attr "opsize" "di")))
+  63 59)
+\f
+;; EV5 scheduling.  EV5 can issue 4 insns per clock.
+;;
+;; EV5 has two asymetric integer units.  Model this with E0 & E1 along
+;; with the combined resource EBOX.
+
+(define_function_unit "ev5_ebox" 2 0
+  (and (eq_attr "cpu" "ev5")
+       (eq_attr "type" "!fbr,fcmov,fadd,fmul,fcpys,fdiv"))
+  1 1)
+
+; Memory takes at least 2 clocks.  Return one from here and fix up with
+; user-defined latencies in adjust_cost.
+; ??? How to: "An instruction of class LD cannot be issued in the _second_
+; cycle after an instruction of class ST is issued."
+(define_function_unit "ev5_ebox" 2 0
+  (and (eq_attr "cpu" "ev5")
+       (eq_attr "type" "ild,fld,ldsym"))
+  1 1)
+
+; Stores, shifts, multiplies can only issue to E0
+(define_function_unit "ev5_e0" 1 0
+  (and (eq_attr "cpu" "ev5")
+       (eq_attr "type" "ist,fst,shift,imul"))
+  1 1)
+
+; Motion video insns also issue only to E0, and take two ticks.
+(define_function_unit "ev5_e0" 1 0
+  (and (eq_attr "cpu" "ev5")
+       (eq_attr "type" "mvi"))
+  2 1)
+
+; Conditional moves always take 2 ticks.
+(define_function_unit "ev5_ebox" 2 0
+  (and (eq_attr "cpu" "ev5")
+       (eq_attr "type" "icmov"))
+  2 1)
+
+; Branches can only issue to E1
+(define_function_unit "ev5_e1" 1 0
+  (and (eq_attr "cpu" "ev5")
+       (eq_attr "type" "ibr,jsr"))
+  1 1)
+
+; Multiplies also use the integer multiplier.
+; ??? How to: "No instruction can be issued to pipe E0 exactly two
+; cycles before an integer multiplication completes."
+(define_function_unit "imul" 1 0
+  (and (eq_attr "cpu" "ev5")
+       (and (eq_attr "type" "imul")
+           (eq_attr "opsize" "si")))
+  8 4)
+
+(define_function_unit "imul" 1 0
+  (and (eq_attr "cpu" "ev5")
+       (and (eq_attr "type" "imul")
+           (eq_attr "opsize" "di")))
+  12 8)
+
+(define_function_unit "imul" 1 0
+  (and (eq_attr "cpu" "ev5")
+       (and (eq_attr "type" "imul")
+           (eq_attr "opsize" "udi")))
+  14 8)
+
+;; Similarly for the FPU we have two asymetric units.  But fcpys can issue
+;; on either so we have to play the game again.
+
+(define_function_unit "ev5_fbox" 2 0
+  (and (eq_attr "cpu" "ev5")
+       (eq_attr "type" "fadd,fcmov,fmul,fcpys,fbr,fdiv"))
+  4 1)
+  
+(define_function_unit "ev5_fm" 1 0
+  (and (eq_attr "cpu" "ev5")
+       (eq_attr "type" "fmul"))
+  4 1)
+
+; Add and cmov as you would expect; fbr never produces a result;
+; fdiv issues through fa to the divider, 
+(define_function_unit "ev5_fa" 1 0
+  (and (eq_attr "cpu" "ev5")
+       (eq_attr "type" "fadd,fcmov,fbr,fdiv"))
+  4 1)
+
+; ??? How to: "No instruction can be issued to pipe FA exactly five
+; cycles before a floating point divide completes."
+(define_function_unit "fdiv" 1 0
+  (and (eq_attr "cpu" "ev5")
+       (and (eq_attr "type" "fdiv")
+           (eq_attr "opsize" "si")))
+  15 15)                               ; 15 to 31 data dependant
+
+(define_function_unit "fdiv" 1 0
+  (and (eq_attr "cpu" "ev5")
+       (and (eq_attr "type" "fdiv")
+           (eq_attr "opsize" "di")))
+  22 22)                               ; 22 to 60 data dependant
+\f
+;; EV6 scheduling.  EV6 can issue 4 insns per clock.
+;;
+;; EV6 has two symmetric pairs ("clusters") of two asymetric integer units
+;; ("upper" and "lower"), yielding pipe names U0, U1, L0, L1.
+
+;; Conditional moves decompose into two independant primitives, each 
+;; taking one cycle.  Since ev6 is out-of-order, we can't see anything
+;; but two cycles.
+(define_function_unit "ev6_ebox" 4 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "icmov"))
+  2 1)
+
+(define_function_unit "ev6_ebox" 4 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "!fbr,fcmov,fadd,fmul,fcpys,fdiv,fsqrt"))
+  1 1)
+
+;; Integer loads take at least 3 clocks, and only issue to lower units.
+;; Return one from here and fix up with user-defined latencies in adjust_cost.
+(define_function_unit "ev6_l" 2 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "ild,ldsym,ist,fst"))
+  1 1)
+
+;; FP loads take at least 4 clocks.  Return two from here...
+(define_function_unit "ev6_l" 2 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "fld"))
+  2 1)
+
+;; Motion video insns also issue only to U0, and take three ticks.
+(define_function_unit "ev6_u0" 1 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "mvi"))
+  3 1)
+
+(define_function_unit "ev6_u" 2 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "mvi"))
+  3 1)
+
+;; Shifts issue to either upper pipe.
+(define_function_unit "ev6_u" 2 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "shift"))
+  1 1)
+
+;; Multiplies issue only to U1, and all take 7 ticks.
+;; Rather than create a new function unit just for U1, reuse IMUL
+(define_function_unit "imul" 1 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "imul"))
+  7 1)
+
+(define_function_unit "ev6_u" 2 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "imul"))
+  7 1)
+
+;; Branches issue to either upper pipe
+(define_function_unit "ev6_u" 2 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "ibr"))
+  3 1)
+
+;; Calls only issue to L0.
+(define_function_unit "ev6_l0" 1 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "jsr"))
+  1 1)
+
+(define_function_unit "ev6_l" 2 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "jsr"))
+  1 1)
+
+;; Ftoi/itof only issue to lower pipes
+(define_function_unit "ev6_l" 2 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "ftoi"))
+  3 1)
+
+(define_function_unit "ev6_l" 2 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "itof"))
+  4 1)
+
+;; For the FPU we are very similar to EV5, except there's no insn that
+;; can issue to fm & fa, so we get to leave that out.
+  
+(define_function_unit "ev6_fm" 1 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "fmul"))
+  4 1)
+
+(define_function_unit "ev6_fa" 1 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "fadd,fcpys,fbr,fdiv,fsqrt"))
+  4 1)
+
+(define_function_unit "ev6_fa" 1 0
+  (and (eq_attr "cpu" "ev6")
+       (eq_attr "type" "fcmov"))
+  8 1)
+
+(define_function_unit "fdiv" 1 0
+  (and (eq_attr "cpu" "ev6")
+       (and (eq_attr "type" "fdiv")
+           (eq_attr "opsize" "si")))
+  12 10)
+
+(define_function_unit "fdiv" 1 0
+  (and (eq_attr "cpu" "ev6")
+       (and (eq_attr "type" "fdiv")
+           (eq_attr "opsize" "di")))
+  15 13)
+
+(define_function_unit "fsqrt" 1 0
+  (and (eq_attr "cpu" "ev6")
+       (and (eq_attr "type" "fsqrt")
+           (eq_attr "opsize" "si")))
+  16 14)
+
+(define_function_unit "fsqrt" 1 0
+  (and (eq_attr "cpu" "ev6")
+       (and (eq_attr "type" "fsqrt")
+           (eq_attr "opsize" "di")))
+  32 30)
+
+; ??? The FPU communicates with memory and the integer register file
+; via two fp store units.  We need a slot in the fst immediately, and
+; a slot in LOW after the operand data is ready.  At which point the
+; data may be moved either to the store queue or the integer register
+; file and the insn retired.
 
-(define_function_unit "divider" 1 0 (eq_attr "type" "fdivs") 68 60)
-(define_function_unit "divider" 1 0 (eq_attr "type" "fdivt") 126 118)
 \f
 ;; First define the arithmetic insns.  Note that the 32-bit forms also
 ;; sign-extend.
 
-;; Note that we can do sign extensions in both FP and integer registers.
-;; However, the result must be in the same type of register as the input.
-;; The register preferencing code can't handle this case very well, so, for
-;; now, don't let the FP case show up here for preferencing.  Also,
-;; sign-extends in FP registers take two instructions.
+;; Handle 32-64 bit extension from memory to a floating point register
+;; specially, since this ocurrs frequently in int->double conversions.
+;; This is done with a define_split after reload converting the plain
+;; sign-extension into a load+unspec, which of course results in lds+cvtlq.
+;;
+;; Note that while we must retain the =f case in the insn for reload's
+;; benefit, it should be eliminated after reload, so we should never emit
+;; code for that case.  But we don't reject the possibility.
+
 (define_insn "extendsidi2"
-  [(set (match_operand:DI 0 "register_operand" "=r,r,*f")
-       (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,*f")))]
+  [(set (match_operand:DI 0 "register_operand" "=r,r,?f")
+       (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,m")))]
   ""
   "@
    addl %1,$31,%0
    ldl %0,%1
-   cvtql %1,%0\;cvtlq %0,%0"
-  [(set_attr "type" "iaddlog,ld,fpop")])
+   lds %0,%1\;cvtlq %0,%0"
+  [(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
+  [(set (match_operand:DI 0 "hard_fp_register_operand" "")
+       (sign_extend:DI (match_operand:SI 1 "memory_operand" "")))]
+  "reload_completed"
+  [(set (match_dup 2) (match_dup 1))
+   (set (match_dup 0) (unspec:DI [(match_dup 2)] 4))]
+  "operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]));")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=f")
+       (unspec:DI [(match_operand:SI 1 "register_operand" "f")] 4))]
+  ""
+  "cvtlq %1,%0"
+  [(set_attr "type" "fadd")])
 
 ;; Do addsi3 the way expand_binop would do if we didn't have one.  This
 ;; generates better code.  We have the anonymous addsi3 pattern below in
                 (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")
    addl %r1,%2,%0
    subl %r1,%n2,%0
    lda %0,%2(%r1)
-   ldah %0,%h2(%r1)"
-  [(set_attr "type" "iaddlog")])
+   ldah %0,%h2(%r1)")
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
   ""
   "@
    addl %r1,%2,%0
-   subl %r1,%n2,%0"
-  [(set_attr "type" "iaddlog")])
+   subl %r1,%n2,%0")
 
 (define_split
   [(set (match_operand:DI 0 "register_operand" "")
        (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))
    (set (match_dup 0) (sign_extend:DI (plus:SI (match_dup 7) (match_dup 4))))]
   "
 {
-  operands[6] = gen_rtx (GET_CODE (operands[1]), DImode,
-                        operands[2], operands[3]);
+  operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[1]), DImode,
+                               operands[2], operands[3]);
   operands[7] = gen_lowpart (SImode, operands[5]);
 }")
 
    addq %r1,%2,%0
    subq %r1,%n2,%0
    lda %0,%2(%r1)
-   ldah %0,%h2(%r1)"
-  [(set_attr "type" "iaddlog")])
+   ldah %0,%h2(%r1)")
 
 ;; Don't do this if we are adjusting SP since we don't want to do
 ;; it in two steps. 
 
 (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"
-  [(set_attr "type" "iaddlog")])
+   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"
-  [(set_attr "type" "iaddlog")])
+   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)
                                 (match_dup 5))))]
   "
 {
-  operands[7] = gen_rtx (GET_CODE (operands[1]), DImode,
-                        operands[2], operands[3]);
+  operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[1]), DImode,
+                               operands[2], operands[3]);
   operands[8] = gen_lowpart (SImode, operands[6]);
 }")
 
 (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%2subq %1,%n3,%0"
-  [(set_attr "type" "iaddlog")])
+   s%2addq %1,%3,%0
+   s%2subq %1,%n3,%0")
 
 ;; These variants of the above insns can occur if the third operand
 ;; is the frame pointer.  This is a kludge, but there doesn't
 ;; seem to be a way around it.  Only recognize them while reloading.
 
 (define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=&r")
-       (plus:DI (plus:DI (match_operand:DI 1 "register_operand" "r")
-                         (match_operand:DI 2 "register_operand" "r"))
-                (match_operand:DI 3 "add_operand" "rIOKL")))]
+  [(set (match_operand:DI 0 "some_operand" "=&r")
+       (plus:DI (plus:DI (match_operand:DI 1 "some_operand" "r")
+                         (match_operand:DI 2 "some_operand" "r"))
+                (match_operand:DI 3 "some_operand" "rIOKL")))]
   "reload_in_progress"
-  "#"
-  [(set_attr "type" "iaddlog")])
+  "#")
 
 (define_split
   [(set (match_operand:DI 0 "register_operand" "")
   "")
                                           
 (define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=&r")
+  [(set (match_operand:SI 0 "some_operand" "=&r")
        (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "some_operand" "rJ")
                                   (match_operand:SI 2 "const48_operand" "I"))
-                         (match_operand:SI 3 "register_operand" "r"))
-                (match_operand:SI 4 "add_operand" "rIOKL")))]
+                         (match_operand:SI 3 "some_operand" "r"))
+                (match_operand:SI 4 "some_operand" "rIOKL")))]
   "reload_in_progress"
-  "#"
-  [(set_attr "type" "iaddlog")])
+  "#")
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "r")
   "")
 
 (define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=&r")
+  [(set (match_operand:DI 0 "some_operand" "=&r")
        (sign_extend:DI
         (plus:SI (plus:SI
                   (mult:SI (match_operand:SI 1 "some_operand" "rJ")
                            (match_operand:SI 2 "const48_operand" "I"))
-                  (match_operand:SI 3 "register_operand" "r"))
-                 (match_operand:SI 4 "add_operand" "rIOKL"))))]
+                  (match_operand:SI 3 "some_operand" "r"))
+                 (match_operand:SI 4 "some_operand" "rIOKL"))))]
   "reload_in_progress"
-  "#"
-  [(set_attr "type" "iaddlog")])
+  "#")
 
 (define_split
   [(set (match_operand:DI 0 "register_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 "register_operand" "=&r")
+  [(set (match_operand:DI 0 "some_operand" "=&r")
        (plus:DI (plus:DI (mult:DI (match_operand:DI 1 "some_operand" "rJ")
                                   (match_operand:DI 2 "const48_operand" "I"))
-                         (match_operand:DI 3 "register_operand" "r"))
-                (match_operand:DI 4 "add_operand" "rIOKL")))]
+                         (match_operand:DI 3 "some_operand" "r"))
+                (match_operand:DI 4 "some_operand" "rIOKL")))]
   "reload_in_progress"
-  "s%2addq %r1,%3,%0\;addq %0,%4,%0"
-  [(set_attr "type" "iaddlog")])
+  "#")
 
 (define_split
   [(set (match_operand:DI 0 "register_operand" "=")
   [(set (match_operand:SI 0 "register_operand" "=r")
        (neg:SI (match_operand:SI 1 "reg_or_8bit_operand" "rI")))]
   ""
-  "subl $31,%1,%0"
-  [(set_attr "type" "iaddlog")])
+  "subl $31,%1,%0")
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (sign_extend:DI (neg:SI
                         (match_operand:SI 1 "reg_or_8bit_operand" "rI"))))]
   ""
-  "subl $31,%1,%0"
-  [(set_attr "type" "iaddlog")])
+  "subl $31,%1,%0")
 
 (define_insn "negdi2"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (neg:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")))]
   ""
-  "subq $31,%1,%0"
-  [(set_attr "type" "iaddlog")])
+  "subq $31,%1,%0")
 
 (define_expand "subsi3"
   [(set (match_operand:SI 0 "register_operand" "")
                  (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 ""
        (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
                  (match_operand:SI 2 "reg_or_8bit_operand" "rI")))]
   ""
-  "subl %r1,%2,%0"
-  [(set_attr "type" "iaddlog")])
+  "subl %r1,%2,%0")
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (sign_extend:DI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
                                  (match_operand:SI 2 "reg_or_8bit_operand" "rI"))))]
   ""
-  "subl %r1,%2,%0"
-  [(set_attr "type" "iaddlog")])
+  "subl %r1,%2,%0")
 
 (define_insn "subdi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (minus:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
                  (match_operand:DI 2 "reg_or_8bit_operand" "rI")))]
   ""
-  "subq %r1,%2,%0"
-  [(set_attr "type" "iaddlog")])
+  "subq %r1,%2,%0")
 
 (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"
-  [(set_attr "type" "iaddlog")])
+  "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"
-  [(set_attr "type" "iaddlog")])
+  "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"
-  [(set_attr "type" "iaddlog")])
+  "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"
-  [(set_attr "type" "imull")])
+  "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"
-  [(set_attr "type" "imull")])
+  "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"
-  [(set_attr "type" "imulq")])
+  "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"
-  [(set_attr "type" "imulq")])
+  "umulh %r1,%2,%0"
+  [(set_attr "type" "imul")
+   (set_attr "opsize" "udi")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
          (const_int 64))))]
   ""
   "umulh %1,%2,%0"
-  [(set_attr "type" "imulq")])
+  [(set_attr "type" "imul")
+   (set_attr "opsize" "udi")])
 \f
 ;; The divide and remainder operations always take their inputs from
 ;; r24 and r25, put their output in r27, and clobber r23 and r28.
 
+;; ??? 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: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)))
+  [(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" "")
-       (reg:SI 27))]
-  ""
+       (subreg:SI (reg:DI 27) 0))]
+  "!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)))
+  [(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" "")
-       (reg:SI 27))]
-  ""
+       (subreg:SI (reg:DI 27) 0))]
+  "!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)))
+  [(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" "")
-       (reg:SI 27))]
-  ""
+       (subreg:SI (reg:DI 27) 0))]
+  "!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)))
+  [(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" "")
-       (reg:SI 27))]
-  ""
+       (subreg:SI (reg:DI 27) 0))]
+  "!TARGET_OPEN_VMS"
   "")
 
 (define_expand "divdi3"
              (clobber (reg:DI 28))])
    (set (match_operand:DI 0 "general_operand" "")
        (reg:DI 27))]
-  ""
+  "!TARGET_OPEN_VMS"
   "")
 
 (define_expand "udivdi3"
              (clobber (reg:DI 28))])
    (set (match_operand:DI 0 "general_operand" "")
        (reg:DI 27))]
-  ""
+  "!TARGET_OPEN_VMS"
   "")
 
 (define_expand "moddi3"
              (clobber (reg:DI 28))])
    (set (match_operand:DI 0 "general_operand" "")
        (reg:DI 27))]
-  ""
+  "!TARGET_OPEN_VMS"
   "")
 
 (define_expand "umoddi3"
              (clobber (reg:DI 28))])
    (set (match_operand:DI 0 "general_operand" "")
        (reg:DI 27))]
-  ""
+  "!TARGET_OPEN_VMS"
   "")
 
+;; Lengths of 8 for ldq $t12,__divq($gp); jsr $t9,($t12),__divq as
+;; expanded by the assembler.
 (define_insn ""
-  [(set (reg:SI 27)
-       (match_operator:SI 1 "divmod_operator"
-                       [(reg:SI 24) (reg:SI 25)]))
+  [(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" "isubr")])
+  [(set_attr "type" "jsr")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (reg:DI 27)
                        [(reg:DI 24) (reg:DI 25)]))
    (clobber (reg:DI 23))
    (clobber (reg:DI 28))]
-  ""
+  "!TARGET_OPEN_VMS"
   "%E1 $24,$25,$27"
-  [(set_attr "type" "isubr")])
+  [(set_attr "type" "jsr")
+   (set_attr "length" "8")])
 \f
 ;; Next are the basic logical operations.  These only exist in DImode.
 
    and %r1,%2,%0
    bic %r1,%N2,%0
    zapnot %r1,%m2,%0"
-  [(set_attr "type" "iaddlog,iaddlog,shiftcm")])
+  [(set_attr "type" "ilog,ilog,shift")])
 
-;; There are times when we can split and AND into two AND insns.  This occurs
+;; There are times when we can split an AND into two AND insns.  This occurs
 ;; when we can first clear any bytes and then clear anything else.  For
 ;; example "I & 0xffff07" is "(I & 0xffffff) & 0xffffffffffffff07".
-;; Only to this when running on 64-bit host since the computations are
+;; Only do this when running on 64-bit host since the computations are
 ;; too messy otherwise.
 
 (define_split
   [(set (match_operand:HI 0 "register_operand" "=r")
        (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))]
   ""
-  "zapnot %1,1,%0"
-  [(set_attr "type" "iaddlog")])
+  "and %1,0xff,%0"
+  [(set_attr "type" "ilog")])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+  "TARGET_BWX"
+  "@
+   and %1,0xff,%0
+   ldbu %0,%1"
+  [(set_attr "type" "ilog,ild")])
 
-(define_insn "zero_extendqisi2"
+(define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extend:SI (match_operand:QI 1 "register_operand" "r")))]
+  "! TARGET_BWX"
+  "and %1,0xff,%0"
+  [(set_attr "type" "ilog")])
+
+(define_expand "zero_extendqisi2"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
   ""
-  "zapnot %1,1,%0"
-  [(set_attr "type" "iaddlog")])
+  "")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+  "TARGET_BWX"
+  "@
+   and %1,0xff,%0
+   ldbu %0,%1"
+  [(set_attr "type" "ilog,ild")])
 
-(define_insn "zero_extendqidi2"
+(define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI (match_operand:QI 1 "register_operand" "r")))]
+  "! TARGET_BWX"
+  "and %1,0xff,%0"
+  [(set_attr "type" "ilog")])
+  
+(define_expand "zero_extendqidi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
   ""
-  "zapnot %1,1,%0"
-  [(set_attr "type" "iaddlog")])
+  "")
+  
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+  "TARGET_BWX"
+  "@
+   zapnot %1,3,%0
+   ldwu %0,%1"
+  [(set_attr "type" "shift,ild")])
 
-(define_insn "zero_extendhisi2"
+(define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extend:SI (match_operand:HI 1 "register_operand" "r")))]
-  ""
+  "! TARGET_BWX"
   "zapnot %1,3,%0"
-  [(set_attr "type" "iaddlog")])
+  [(set_attr "type" "shift")])
+
+(define_expand "zero_extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
+  ""
+  "")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+  "TARGET_BWX"
+  "@
+   zapnot %1,3,%0
+   ldwu %0,%1"
+  [(set_attr "type" "shift,ild")])
 
-(define_insn "zero_extendhidi2"
+(define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI (match_operand:HI 1 "register_operand" "r")))]
   ""
   "zapnot %1,3,%0"
-  [(set_attr "type" "iaddlog")])
+  [(set_attr "type" "shift")])
+
+(define_expand "zero_extendhidi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
+  ""
+  "")
 
 (define_insn "zero_extendsidi2"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
   ""
   "zapnot %1,15,%0"
-  [(set_attr "type" "iaddlog")])
+  [(set_attr "type" "shift")])
 
 (define_insn  ""
   [(set (match_operand:DI 0 "register_operand" "=r")
                (match_operand:DI 2 "reg_or_0_operand" "rJ")))]
   ""
   "bic %r2,%1,%0"
-  [(set_attr "type" "iaddlog")])
+  [(set_attr "type" "ilog")])
 
 (define_insn "iordi3"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
   "@
    bis %r1,%2,%0
    ornot %r1,%N2,%0"
-  [(set_attr "type" "iaddlog")])
+  [(set_attr "type" "ilog")])
 
 (define_insn "one_cmpldi2"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")))]
   ""
   "ornot $31,%1,%0"
-  [(set_attr "type" "iaddlog")])
+  [(set_attr "type" "ilog")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
                (match_operand:DI 2 "reg_or_0_operand" "rJ")))]
   ""
   "ornot %r2,%1,%0"
-  [(set_attr "type" "iaddlog")])
+  [(set_attr "type" "ilog")])
 
 (define_insn "xordi3"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
   "@
    xor %r1,%2,%0
    eqv %r1,%N2,%0"
-  [(set_attr "type" "iaddlog")])
+  [(set_attr "type" "ilog")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
                        (match_operand:DI 2 "register_operand" "rI"))))]
   ""
   "eqv %r1,%2,%0"
-  [(set_attr "type" "iaddlog")])
+  [(set_attr "type" "ilog")])
+\f
+;; Handle the FFS insn if we support CIX. 
+
+(define_expand "ffsdi2"
+  [(set (match_dup 2)
+       (unspec [(match_operand:DI 1 "register_operand" "")] 1))
+   (set (match_dup 3)
+       (plus:DI (match_dup 2) (const_int 1)))
+   (set (match_operand:DI 0 "register_operand" "")
+       (if_then_else:DI (eq (match_dup 1) (const_int 0))
+                        (const_int 0) (match_dup 3)))]
+  "TARGET_CIX"
+  "
+{
+  operands[2] = gen_reg_rtx (DImode);
+  operands[3] = gen_reg_rtx (DImode);
+}")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec [(match_operand:DI 1 "register_operand" "r")] 1))]
+  "TARGET_CIX"
+  "cttz %1,%0"
+  ; ev6 calls all mvi and cttz/ctlz/popc class imisc, so just 
+  ; reuse the existing type name.
+  [(set_attr "type" "mvi")])
 \f
 ;; Next come the shifts and the various extract and insert operations.
 
 (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" "iaddlog,shiftcm")])
+  [(set_attr "type" "iadd,shift")])
 
 ;; ??? The following pattern is made by combine, but earlier phases
 ;; (specifically flow) can't handle it.  This occurs in jump.c.  Deal
 ;;  else
 ;;    return \"s%P2addl %r1,0,%0\";
 ;; }"
-;;  [(set_attr "type" "iaddlog")])
+;;  [(set_attr "type" "iadd")])
                          
 (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")
+  "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")
+  "sra %r1,%2,%0"
+  [(set_attr "type" "shift")])
 
 (define_expand "extendqihi2"
   [(set (match_dup 2)
-       (ashift:DI (match_operand:QI 1 "register_operand" "")
+       (ashift:DI (match_operand:QI 1 "some_operand" "")
                   (const_int 56)))
    (set (match_operand:HI 0 "register_operand" "")
        (ashiftrt:DI (match_dup 2)
                     (const_int 56)))]
   ""
   "
-{ operands[0] = gen_lowpart (DImode, operands[0]);
-  operands[1] = gen_lowpart (DImode, operands[1]);
+{
+  if (TARGET_BWX)
+    {
+      emit_insn (gen_extendqihi2x (operands[0],
+                                  force_reg (QImode, operands[1])));
+      DONE;
+    }
+ /* If we have an unaligned MEM, extend to DImode (which we do
+     specially) and then copy to the result.  */
+  if (unaligned_memory_operand (operands[1], HImode))
+    {
+      rtx temp = gen_reg_rtx (DImode);
+
+      emit_insn (gen_extendqidi2 (temp, operands[1]));
+      emit_move_insn (operands[0], gen_lowpart (HImode, temp));
+      DONE;
+    }
+
+  operands[0] = gen_lowpart (DImode, operands[0]);
+  operands[1] = gen_lowpart (DImode, force_reg (QImode, operands[1]));
   operands[2] = gen_reg_rtx (DImode);
 }")
 
+(define_insn "extendqidi2x"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (sign_extend:DI (match_operand:QI 1 "register_operand" "r")))]
+  "TARGET_BWX"
+  "sextb %1,%0"
+  [(set_attr "type" "shift")])
+
+(define_insn "extendhidi2x"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (sign_extend:DI (match_operand:HI 1 "register_operand" "r")))]
+  "TARGET_BWX"
+  "sextw %1,%0"
+  [(set_attr "type" "shift")])
+
+(define_insn "extendqisi2x"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
+  "TARGET_BWX"
+  "sextb %1,%0"
+  [(set_attr "type" "shift")])
+
+(define_insn "extendhisi2x"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
+  "TARGET_BWX"
+  "sextw %1,%0"
+  [(set_attr "type" "shift")])
+
+(define_insn "extendqihi2x"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))]
+  "TARGET_BWX"
+  "sextb %1,%0"
+  [(set_attr "type" "shift")])
+
 (define_expand "extendqisi2"
   [(set (match_dup 2)
-       (ashift:DI (match_operand:QI 1 "register_operand" "")
+       (ashift:DI (match_operand:QI 1 "some_operand" "")
                   (const_int 56)))
    (set (match_operand:SI 0 "register_operand" "")
        (ashiftrt:DI (match_dup 2)
                     (const_int 56)))]
   ""
   "
-{ operands[0] = gen_lowpart (DImode, operands[0]);
-  operands[1] = gen_lowpart (DImode, operands[1]);
+{
+  if (TARGET_BWX)
+    {
+      emit_insn (gen_extendqisi2x (operands[0],
+                                  force_reg (QImode, operands[1])));
+      DONE;
+    }
+
+  /* If we have an unaligned MEM, extend to a DImode form of
+     the result (which we do specially).  */
+  if (unaligned_memory_operand (operands[1], QImode))
+    {
+      rtx temp = gen_reg_rtx (DImode);
+
+      emit_insn (gen_extendqidi2 (temp, operands[1]));
+      emit_move_insn (operands[0], gen_lowpart (SImode, temp));
+      DONE;
+    }
+
+  operands[0] = gen_lowpart (DImode, operands[0]);
+  operands[1] = gen_lowpart (DImode, force_reg (QImode, operands[1]));
   operands[2] = gen_reg_rtx (DImode);
 }")
 
 (define_expand "extendqidi2"
   [(set (match_dup 2)
-       (ashift:DI (match_operand:QI 1 "register_operand" "")
+       (ashift:DI (match_operand:QI 1 "some_operand" "")
                   (const_int 56)))
    (set (match_operand:DI 0 "register_operand" "")
        (ashiftrt:DI (match_dup 2)
                     (const_int 56)))]
   ""
   "
-{ operands[1] = gen_lowpart (DImode, operands[1]);
+{
+  if (TARGET_BWX)
+    {
+      emit_insn (gen_extendqidi2x (operands[0],
+                                  force_reg (QImode, operands[1])));
+      DONE;
+    }
+
+  if (unaligned_memory_operand (operands[1], QImode))
+    {
+      rtx seq
+       = gen_unaligned_extendqidi (operands[0],
+                                   get_unaligned_address (operands[1], 1));
+
+      alpha_set_memflags (seq, operands[1]);
+      emit_insn (seq);
+      DONE;
+    }
+
+  operands[1] = gen_lowpart (DImode, force_reg (QImode, operands[1]));
   operands[2] = gen_reg_rtx (DImode);
 }")
 
 (define_expand "extendhisi2"
   [(set (match_dup 2)
-       (ashift:DI (match_operand:HI 1 "register_operand" "")
+       (ashift:DI (match_operand:HI 1 "some_operand" "")
                   (const_int 48)))
    (set (match_operand:SI 0 "register_operand" "")
        (ashiftrt:DI (match_dup 2)
                     (const_int 48)))]
   ""
   "
-{ operands[0] = gen_lowpart (DImode, operands[0]);
-  operands[1] = gen_lowpart (DImode, operands[1]);
+{
+  if (TARGET_BWX)
+    {
+      emit_insn (gen_extendhisi2x (operands[0],
+                                  force_reg (HImode, operands[1])));
+      DONE;
+    }
+
+  /* If we have an unaligned MEM, extend to a DImode form of
+     the result (which we do specially).  */
+  if (unaligned_memory_operand (operands[1], HImode))
+    {
+      rtx temp = gen_reg_rtx (DImode);
+
+      emit_insn (gen_extendhidi2 (temp, operands[1]));
+      emit_move_insn (operands[0], gen_lowpart (SImode, temp));
+      DONE;
+    }
+
+  operands[0] = gen_lowpart (DImode, operands[0]);
+  operands[1] = gen_lowpart (DImode, force_reg (HImode, operands[1]));
   operands[2] = gen_reg_rtx (DImode);
 }")
 
 (define_expand "extendhidi2"
   [(set (match_dup 2)
-       (ashift:DI (match_operand:HI 1 "register_operand" "")
+       (ashift:DI (match_operand:HI 1 "some_operand" "")
                   (const_int 48)))
    (set (match_operand:DI 0 "register_operand" "")
        (ashiftrt:DI (match_dup 2)
                     (const_int 48)))]
   ""
   "
-{ operands[1] = gen_lowpart (DImode, operands[1]);
+{
+  if (TARGET_BWX)
+    {
+      emit_insn (gen_extendhidi2x (operands[0],
+                                  force_reg (HImode, operands[1])));
+      DONE;
+    }
+
+  if (unaligned_memory_operand (operands[1], HImode))
+    {
+      rtx seq
+       = gen_unaligned_extendhidi (operands[0],
+                                   get_unaligned_address (operands[1], 2));
+
+      alpha_set_memflags (seq, operands[1]);
+      emit_insn (seq);
+      DONE;
+    }
+
+  operands[1] = gen_lowpart (DImode, force_reg (HImode, operands[1]));
   operands[2] = gen_reg_rtx (DImode);
 }")
 
+;; Here's how we sign extend an unaligned byte and halfword.  Doing this
+;; as a pattern saves one instruction.  The code is similar to that for
+;; the unaligned loads (see below).
+;;
+;; Operand 1 is the address + 1 (+2 for HI), operand 0 is the result.
+(define_expand "unaligned_extendqidi"
+  [(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
+   (set (match_dup 3)
+       (mem:DI (and:DI (plus:DI (match_dup 2) (const_int -1))
+                       (const_int -8))))
+   (set (match_dup 4)
+       (ashift:DI (match_dup 3)
+                  (minus:DI (const_int 56)
+                            (ashift:DI
+                             (and:DI (plus:DI (match_dup 2) (const_int -1))
+                                     (const_int 7))
+                             (const_int 3)))))
+   (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0)
+       (ashiftrt:DI (match_dup 4) (const_int 56)))]
+  ""
+  "
+{ operands[2] = gen_reg_rtx (DImode);
+  operands[3] = gen_reg_rtx (DImode);
+  operands[4] = gen_reg_rtx (DImode);
+}")
+
+(define_expand "unaligned_extendhidi"
+  [(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
+   (set (match_dup 3)
+       (mem:DI (and:DI (plus:DI (match_dup 2) (const_int -2))
+                       (const_int -8))))
+   (set (match_dup 4)
+       (ashift:DI (match_dup 3)
+                  (minus:DI (const_int 56)
+                            (ashift:DI
+                             (and:DI (plus:DI (match_dup 2) (const_int -1))
+                                     (const_int 7))
+                             (const_int 3)))))
+   (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0)
+       (ashiftrt:DI (match_dup 4) (const_int 48)))]
+  ""
+  "
+{ operands[2] = gen_reg_rtx (DImode);
+  operands[3] = gen_reg_rtx (DImode);
+  operands[4] = gen_reg_rtx (DImode);
+}")
+
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
                         (match_operand:DI 2 "mode_width_operand" "n")
                         (match_operand:DI 3 "mul8_operand" "I")))]
   ""
-  "ext%M2l %r1,%s3,%0")
+  "ext%M2l %r1,%s3,%0"
+  [(set_attr "type" "shift")])
 
-(define_insn ""
+(define_insn "extxl"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
                         (match_operand:DI 2 "mode_width_operand" "n")
                         (ashift:DI (match_operand:DI 3 "reg_or_8bit_operand" "rI")
                                    (const_int 3))))]
   ""
-  "ext%M2l %r1,%3,%0")
+  "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")
-       (ashift:DI
-        (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
-                         (const_int 8)
-                         (ashift:DI
-                          (plus:DI
-                           (match_operand:DI 2 "reg_or_8bit_operand" "rI")
-                           (const_int -1))
+       (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)))
-        (const_int 56)))]
+            (match_operand:DI 3 "mode_mask_operand" "n")))]
   ""
-  "extqh %r1,%2,%0")
+  "ext%U3l %1,%2,%0"
+  [(set_attr "type" "shift")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
-       (ashift:DI
-        (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
-                         (const_int 16)
-                         (ashift:DI
-                          (plus:DI
-                           (match_operand:DI 2 "reg_or_8bit_operand" "rI")
-                           (const_int -2))
-                          (const_int 3)))
-        (const_int 48)))]
+       (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))))]
   ""
-  "extwh %r1,%2,%0")
+  "extql %1,%2,%0"
+  [(set_attr "type" "shift")])
 
-(define_insn ""
+(define_insn "extqh"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (ashift:DI
-        (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
-                         (const_int 32)
-                         (ashift:DI
-                          (plus:DI
-                           (match_operand:DI 2 "reg_or_8bit_operand" "rI")
-                           (const_int -4))
-                          (const_int 3)))
-        (const_int 32)))]
-  ""
-  "extlh %r1,%2,%0")
+        (match_operand:DI 1 "reg_or_0_operand" "rJ")
+         (minus:DI (const_int 56)
+                   (ashift:DI
+                    (and:DI
+                     (plus:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+                              (const_int -1))
+                     (const_int 7))
+                    (const_int 3)))))]
+  ""
+  "extqh %r1,%2,%0"
+  [(set_attr "type" "shift")])
+
+(define_insn "extlh"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (ashift:DI
+        (and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
+                (const_int 2147483647))
+        (minus:DI (const_int 56)
+                   (ashift:DI
+                    (and:DI
+                     (plus:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+                              (const_int -1))
+                     (const_int 7))
+                    (const_int 3)))))]
+  ""
+  "extlh %r1,%2,%0"
+  [(set_attr "type" "shift")])
+
+(define_insn "extwh"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (ashift:DI
+        (and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
+                (const_int 65535))
+        (minus:DI (const_int 56)
+                   (ashift:DI
+                    (and:DI
+                     (plus:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+                              (const_int -1))
+                     (const_int 7))
+                    (const_int 3)))))]
+  ""
+  "extwh %r1,%2,%0"
+  [(set_attr "type" "shift")])
 
 ;; This converts an extXl into an extXh with an appropriate adjustment
 ;; to the address calculation.
 
-(define_split
-  [(set (match_operand:DI 0 "register_operand" "")
-       (ashift:DI (zero_extract:DI (match_operand:DI 1 "register_operand" "")
-                                   (match_operand:DI 2 "mode_width_operand" "")
-                                   (ashift:DI (match_operand:DI 3 "" "")
-                                              (const_int 3)))
-                  (match_operand:DI 4 "const_int_operand" "")))
-   (clobber (match_operand:DI 5 "register_operand" ""))]
-  "INTVAL (operands[4]) == 64 - INTVAL (operands[2])"
-  [(set (match_dup 5) (match_dup 6))
-   (set (match_dup 0)
-       (ashift:DI (zero_extract:DI (match_dup 1) (match_dup 2)
-                                   (ashift:DI (plus:DI (match_dup 5)
-                                                       (match_dup 7))
-                                              (const_int 3)))
-                  (match_dup 4)))]
-  "
-{
-  operands[6] = plus_constant (operands[3], 
-                              INTVAL (operands[2]) / BITS_PER_UNIT);
-  operands[7] = GEN_INT (- INTVAL (operands[2]) / BITS_PER_UNIT);
-}")
+;;(define_split
+;;  [(set (match_operand:DI 0 "register_operand" "")
+;;     (ashift:DI (zero_extract:DI (match_operand:DI 1 "register_operand" "")
+;;                                 (match_operand:DI 2 "mode_width_operand" "")
+;;                                 (ashift:DI (match_operand:DI 3 "" "")
+;;                                            (const_int 3)))
+;;                (match_operand:DI 4 "const_int_operand" "")))
+;;   (clobber (match_operand:DI 5 "register_operand" ""))]
+;;  "INTVAL (operands[4]) == 64 - INTVAL (operands[2])"
+;;  [(set (match_dup 5) (match_dup 6))
+;;   (set (match_dup 0)
+;;     (ashift:DI (zero_extract:DI (match_dup 1) (match_dup 2)
+;;                                 (ashift:DI (plus:DI (match_dup 5)
+;;                                                     (match_dup 7))
+;;                                            (const_int 3)))
+;;                (match_dup 4)))]
+;;  "
+;;{
+;;  operands[6] = plus_constant (operands[3], 
+;;                            INTVAL (operands[2]) / BITS_PER_UNIT);
+;;  operands[7] = GEN_INT (- INTVAL (operands[2]) / BITS_PER_UNIT);
+;;}")
   
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "r"))
                   (match_operand:DI 2 "mul8_operand" "I")))]
   ""
-  "insbl %1,%s2,%0")
+  "insbl %1,%s2,%0"
+  [(set_attr "type" "shift")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "r"))
                   (match_operand:DI 2 "mul8_operand" "I")))]
   ""
-  "inswl %1,%s2,%0")
+  "inswl %1,%s2,%0"
+  [(set_attr "type" "shift")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
        (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
                   (match_operand:DI 2 "mul8_operand" "I")))]
   ""
-  "insll %1,%s2,%0")
+  "insll %1,%s2,%0"
+  [(set_attr "type" "shift")])
 
-(define_insn ""
+(define_insn "insbl"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "r"))
                   (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
                              (const_int 3))))]
   ""
-  "insbl %1,%2,%0")
+  "insbl %1,%2,%0"
+  [(set_attr "type" "shift")])
 
-(define_insn ""
+(define_insn "inswl"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "r"))
                   (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
                              (const_int 3))))]
   ""
-  "inswl %1,%2,%0")
+  "inswl %1,%2,%0"
+  [(set_attr "type" "shift")])
 
-(define_insn ""
+(define_insn "insll"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
                   (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
                              (const_int 3))))]
   ""
-  "insll %1,%2,%0")
+  "insll %1,%2,%0"
+  [(set_attr "type" "shift")])
+
+(define_insn "insql"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (ashift:DI (match_operand:DI 1 "register_operand" "r")
+                  (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+                             (const_int 3))))]
+  ""
+  "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.
+;;
+;; Since we need them for block moves, though, cop out and use unspec.
 
-(define_insn ""
+(define_insn "insxh"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec [(match_operand:DI 1 "register_operand" "r")
+                (match_operand:DI 2 "mode_width_operand" "n")
+                (match_operand:DI 3 "reg_or_8bit_operand" "rI")] 2))]
+  ""
+  "ins%M2h %1,%3,%0"
+  [(set_attr "type" "shift")])
+
+(define_insn "mskxl"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (and:DI (not:DI (ashift:DI
                         (match_operand:DI 2 "mode_mask_operand" "n")
                          (const_int 3))))
                (match_operand:DI 1 "reg_or_0_operand" "rJ")))]
   ""
-  "msk%U2l %r1,%3,%0")
+  "msk%U2l %r1,%3,%0"
+  [(set_attr "type" "shift")])
+
+;; We do not include the mskXh insns because it does not appear we would
+;; ever generate one.
+;;
+;; Again, we do for block moves and we use unspec again.
 
-;; We do not include the mskXh insns because it does not appear we would ever
-;; generate one.
+(define_insn "mskxh"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec [(match_operand:DI 1 "register_operand" "r")
+                (match_operand:DI 2 "mode_width_operand" "n")
+                (match_operand:DI 3 "reg_or_8bit_operand" "rI")] 3))]
+  ""
+  "msk%M2h %1,%3,%0"
+  [(set_attr "type" "shift")])
 \f
 ;; Floating-point operations.  All the double-precision insns can extend
 ;; from single, so indicate that.  The exception are the ones that simply
        (abs:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
   "TARGET_FP"
   "cpys $f31,%R1,%0"
-  [(set_attr "type" "fpop")])
+  [(set_attr "type" "fcpys")])
 
 (define_insn "absdf2"
   [(set (match_operand:DF 0 "register_operand" "=f")
        (abs:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
   "TARGET_FP"
   "cpys $f31,%R1,%0"
-  [(set_attr "type" "fpop")])
+  [(set_attr "type" "fcpys")])
 
 (define_insn "negsf2"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (neg:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
   "TARGET_FP"
   "cpysn %R1,%R1,%0"
-  [(set_attr "type" "fpop")])
+  [(set_attr "type" "fadd")])
 
 (define_insn "negdf2"
   [(set (match_operand:DF 0 "register_operand" "=f")
        (neg:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
   "TARGET_FP"
   "cpysn %R1,%R1,%0"
-  [(set_attr "type" "fpop")])
+  [(set_attr "type" "fadd")])
+
+(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")))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "add%,%)%& %R1,%R2,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
 (define_insn "addsf3"
   [(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")))]
   "TARGET_FP"
-  "adds %R1,%R2,%0"
-  [(set_attr "type" "fpop")])
+  "add%,%)%& %R1,%R2,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:DF 0 "register_operand" "=&f")
+       (plus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG")
+                (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "add%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
 (define_insn "adddf3"
   [(set (match_operand:DF 0 "register_operand" "=f")
        (plus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG")
                 (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
   "TARGET_FP"
-  "addt %R1,%R2,%0"
-  [(set_attr "type" "fpop")])
+  "add%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
        (plus:DF (float_extend:DF
                  (match_operand:SF 1 "reg_or_fp0_operand" "fG"))
                 (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
-  "TARGET_FP"
-  "addt %R1,%R2,%0"
-  [(set_attr "type" "fpop")])
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "add%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
                  (match_operand:SF 1 "reg_or_fp0_operand" "%fG"))
                 (float_extend:DF
                  (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))]
-  "TARGET_FP"
-  "addt %R1,%R2,%0"
-  [(set_attr "type" "fpop")])
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "add%-%)%& %R1,%R2,%0"
+  [(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 "fix_truncdfdi2"
-  [(set (match_operand:DI 0 "register_operand" "=f")
-       (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+(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"
-  "cvttqc %R1,%0"
-  [(set_attr "type" "fpop")])
+  "cvtql%` %R1,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
-(define_insn "fix_truncsfdi2"
-  [(set (match_operand:DI 0 "register_operand" "=f")
-       (fix:DI (float_extend:DF
-                (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))]
-  "TARGET_FP"
-  "cvttqc %R1,%0"
-  [(set_attr "type" "fpop")])
+(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")))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "cvt%-q%(c %R1,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_insn "fix_truncdfdi2"
+  [(set (match_operand:DI 0 "register_operand" "=f")
+       (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+  "TARGET_FP"
+  "cvt%-q%(c %R1,%0"
+  [(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
+                (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "cvt%-q%(c %R1,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_insn "fix_truncsfdi2"
+  [(set (match_operand:DI 0 "register_operand" "=f")
+       (fix:DI (float_extend:DF
+                (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))]
+  "TARGET_FP"
+  "cvt%-q%(c %R1,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:SF 0 "register_operand" "=&f")
+       (float:SF (match_operand:DI 1 "register_operand" "f")))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "cvtq%,%+%& %1,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
 (define_insn "floatdisf2"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (float:SF (match_operand:DI 1 "register_operand" "f")))]
   "TARGET_FP"
-  "cvtqs %1,%0"
-  [(set_attr "type" "fpop")])
+  "cvtq%,%+%& %1,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:DF 0 "register_operand" "=&f")
+       (float:DF (match_operand:DI 1 "register_operand" "f")))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "cvtq%-%+%& %1,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
 (define_insn "floatdidf2"
   [(set (match_operand:DF 0 "register_operand" "=f")
        (float:DF (match_operand:DI 1 "register_operand" "f")))]
   "TARGET_FP"
-  "cvtqt %1,%0"
-  [(set_attr "type" "fpop")])
+  "cvtq%-%+%& %1,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
-(define_insn "extendsfdf2"
-  [(set (match_operand:DF 0 "register_operand" "=f,f")
-       (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f,m")))]
+(define_expand "extendsfdf2"
+  [(use (match_operand:DF 0 "register_operand" ""))
+   (use (match_operand:SF 1 "nonimmediate_operand" ""))]
   "TARGET_FP"
+"
+{
+  if (alpha_tp == ALPHA_TP_INSN)
+    emit_insn (gen_extendsfdf2_tp (operands[0],
+                                  force_reg (SFmode, operands[1])));
+  else
+    emit_insn (gen_extendsfdf2_no_tp (operands[0], operands[1]));
+
+  DONE;
+}")
+;; FIXME
+(define_insn "extendsfdf2_tp"
+  [(set (match_operand:DF 0 "register_operand" "=&f")
+       (float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "cvtsts %1,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_insn "extendsfdf2_no_tp"
+  [(set (match_operand:DF 0 "register_operand" "=f,f,m")
+       (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f,m,f")))]
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
   "@
-   addt $f31,%1,%0
-   lds %0,%1"
-  [(set_attr "type" "fpop,ld")])
+   cpys %1,%1,%0
+   ld%, %0,%1
+   st%- %1,%0"
+  [(set_attr "type" "fcpys,fld,fst")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:SF 0 "register_operand" "=&f")
+       (float_truncate:SF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "cvt%-%,%)%& %R1,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
 (define_insn "truncdfsf2"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (float_truncate:SF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
   "TARGET_FP"
-  "cvtts %R1,%0"
-  [(set_attr "type" "fpop")])
+  "cvt%-%,%)%& %R1,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:SF 0 "register_operand" "=&f")
+       (div:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")
+               (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "div%,%)%& %R1,%R2,%0"
+  [(set_attr "type" "fdiv")
+   (set_attr "opsize" "si")
+   (set_attr "trap" "yes")])
 
 (define_insn "divsf3"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (div:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")
                (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
   "TARGET_FP"
-  "divs %R1,%R2,%0"
-  [(set_attr "type" "fdivs")])
+  "div%,%)%& %R1,%R2,%0"
+  [(set_attr "type" "fdiv")
+   (set_attr "opsize" "si")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:DF 0 "register_operand" "=&f")
+       (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")
+               (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "div%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fdiv")
+   (set_attr "trap" "yes")])
 
 (define_insn "divdf3"
   [(set (match_operand:DF 0 "register_operand" "=f")
        (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")
                (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
   "TARGET_FP"
-  "divt %R1,%R2,%0"
-  [(set_attr "type" "fdivt")])
+  "div%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fdiv")
+   (set_attr "trap" "yes")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
        (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG"))
                (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
-  "TARGET_FP"
-  "divt %R1,%R2,%0"
-  [(set_attr "type" "fdivt")])
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "div%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fdiv")
+   (set_attr "trap" "yes")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
        (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")
                (float_extend:DF
                 (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))]
-  "TARGET_FP"
-  "divt %R1,%R2,%0"
-  [(set_attr "type" "fdivt")])
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "div%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fdiv")
+   (set_attr "trap" "yes")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
        (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG"))
                (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))]
-  "TARGET_FP"
-  "divt %R1,%R2,%0"
-  [(set_attr "type" "fdivt")])
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "div%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fdiv")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:SF 0 "register_operand" "=&f")
+       (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG")
+                (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "mul%,%)%& %R1,%R2,%0"
+  [(set_attr "type" "fmul")
+   (set_attr "trap" "yes")])
 
 (define_insn "mulsf3"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG")
                 (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
   "TARGET_FP"
-  "muls %R1,%R2,%0"
-  [(set_attr "type" "fpop")])
+  "mul%,%)%& %R1,%R2,%0"
+  [(set_attr "type" "fmul")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:DF 0 "register_operand" "=&f")
+       (mult:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG")
+                (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "mul%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fmul")
+   (set_attr "trap" "yes")])
 
 (define_insn "muldf3"
   [(set (match_operand:DF 0 "register_operand" "=f")
        (mult:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG")
                 (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
   "TARGET_FP"
-  "mult %R1,%R2,%0"
-  [(set_attr "type" "fpop")])
+  "mul%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fmul")
+   (set_attr "trap" "yes")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
        (mult:DF (float_extend:DF
                  (match_operand:SF 1 "reg_or_fp0_operand" "fG"))
                 (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
-  "TARGET_FP"
-  "mult %R1,%R2,%0"
-  [(set_attr "type" "fpop")])
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "mul%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fmul")
+   (set_attr "trap" "yes")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
                  (match_operand:SF 1 "reg_or_fp0_operand" "%fG"))
                 (float_extend:DF
                  (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))]
-  "TARGET_FP"
-  "mult %R1,%R2,%0"
-  [(set_attr "type" "fpop")])
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "mul%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fmul")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:SF 0 "register_operand" "=&f")
+       (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")
+                 (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "sub%,%)%& %R1,%R2,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
 (define_insn "subsf3"
   [(set (match_operand:SF 0 "register_operand" "=f")
        (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")
                  (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
   "TARGET_FP"
-  "subs %R1,%R2,%0"
-  [(set_attr "type" "fpop")])
+  "sub%,%)%& %R1,%R2,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:DF 0 "register_operand" "=&f")
+       (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")
+                 (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+  "TARGET_FP && alpha_tp == ALPHA_TP_INSN"
+  "sub%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
 (define_insn "subdf3"
   [(set (match_operand:DF 0 "register_operand" "=f")
        (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")
                  (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
   "TARGET_FP"
-  "subt %R1,%R2,%0"
-  [(set_attr "type" "fpop")])
+  "sub%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
        (minus:DF (float_extend:DF
                   (match_operand:SF 1 "reg_or_fp0_operand" "fG"))
                  (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
-  "TARGET_FP"
-  "subt %R1,%R2,%0"
-  [(set_attr "type" "fpop")])
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "sub%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
        (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")
                  (float_extend:DF
                   (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))]
-  "TARGET_FP"
-  "subt %R1,%R2,%0"
-  [(set_attr "type" "fpop")])
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "sub%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f")
                   (match_operand:SF 1 "reg_or_fp0_operand" "fG"))
                  (float_extend:DF
                   (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))]
-  "TARGET_FP"
-  "subt %R1,%R2,%0"
-  [(set_attr "type" "fpop")])
+  "TARGET_FP && alpha_tp != ALPHA_TP_INSN"
+  "sub%-%)%& %R1,%R2,%0"
+  [(set_attr "type" "fadd")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:SF 0 "register_operand" "=&f")
+       (sqrt:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
+  "TARGET_FP && TARGET_CIX && alpha_tp == ALPHA_TP_INSN"
+  "sqrt%,%)%& %R1,%0"
+  [(set_attr "type" "fsqrt")
+   (set_attr "opsize" "si")
+   (set_attr "trap" "yes")])
+
+(define_insn "sqrtsf2"
+  [(set (match_operand:SF 0 "register_operand" "=f")
+       (sqrt:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
+  "TARGET_FP && TARGET_CIX"
+  "sqrt%,%)%& %R1,%0"
+  [(set_attr "type" "fsqrt")
+   (set_attr "opsize" "si")
+   (set_attr "trap" "yes")])
+
+(define_insn ""
+  [(set (match_operand:DF 0 "register_operand" "=&f")
+       (sqrt:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+  "TARGET_FP && TARGET_CIX && alpha_tp == ALPHA_TP_INSN"
+  "sqrt%-%)%& %R1,%0"
+  [(set_attr "type" "fsqrt")
+   (set_attr "trap" "yes")])
+
+(define_insn "sqrtdf2"
+  [(set (match_operand:DF 0 "register_operand" "=f")
+       (sqrt:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+  "TARGET_FP && TARGET_CIX"
+  "sqrt%-%)%& %1,%0"
+  [(set_attr "type" "fsqrt")
+   (set_attr "trap" "yes")])
 \f
 ;; Next are all the integer comparisons, and conditional moves and branches
 ;; and some of the related define_expand's and define_split's.
   "cmp%C1 %r2,%3,%0"
   [(set_attr "type" "icmp")])
 
-;; There are three important special-case that don't fit the above pattern
-;; but which we want to handle here.
-
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r")
-       (ne:DI (match_operand:DI 1 "register_operand" "r")
-              (const_int 0)))]
+        (match_operator:DI 1 "alpha_swapped_comparison_operator"
+                          [(match_operand:DI 2 "reg_or_8bit_operand" "rI")
+                           (match_operand:DI 3 "reg_or_0_operand" "rJ")]))]
   ""
-  "cmpult $31,%1,%0"
+  "cmp%c1 %r3,%2,%0"
   [(set_attr "type" "icmp")])
 
-(define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (gt:DI (match_operand:DI 1 "register_operand" "r")
-              (const_int 0)))]
-  ""
-  "cmplt $31,%1,%0"
-  [(set_attr "type" "icmp")])
+;; This pattern exists so conditional moves of SImode values are handled.
+;; Comparisons are still done in DImode though.
 
 (define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (ge:DI (match_operand:DI 1 "register_operand" "r")
-              (const_int 0)))]
-  ""
-  "cmple $31,%1,%0"
-  [(set_attr "type" "icmp")])
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+       (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")])
+        (match_operand:SI 1 "reg_or_8bit_operand" "rI,0,rI,0")
+        (match_operand:SI 5 "reg_or_8bit_operand" "0,rI,0,rI")))]
+  "operands[3] == const0_rtx || operands[4] == const0_rtx"
+  "@
+   cmov%C2 %r3,%1,%0
+   cmov%D2 %r3,%5,%0
+   cmov%c2 %r4,%1,%0
+   cmov%d2 %r4,%5,%0"
+  [(set_attr "type" "icmov")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
    cmov%C2 %r3,%1,%0
    cmov%D2 %r3,%5,%0
    cmov%c2 %r4,%1,%0
-   cmov%d2 %r4,%5,%0")
+   cmov%d2 %r4,%5,%0"
+  [(set_attr "type" "icmov")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r,r")
   ""
   "@
    cmovlbc %r2,%1,%0
-   cmovlbs %r2,%3,%0")
+   cmovlbs %r2,%3,%0"
+  [(set_attr "type" "icmov")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r,r")
   ""
   "@
    cmovlbs %r2,%1,%0
-   cmovlbc %r2,%3,%0")
+   cmovlbc %r2,%3,%0"
+  [(set_attr "type" "icmov")])
 
 ;; This form is added since combine thinks that an IF_THEN_ELSE with both
 ;; arms constant is a single insn, so it won't try to form it if combine
         (match_dup 0)))
    (clobber (match_scratch:DI 4 "=&r"))]
   ""
-  "addq %0,%1,%4\;cmov%C2 %r3,%4,%0")
+  "addq %0,%1,%4\;cmov%C2 %r3,%4,%0"
+  [(set_attr "type" "icmov")
+   (set_attr "length" "8")])
 
 (define_split
   [(set (match_operand:DI 0 "register_operand" "")
                                       (match_dup 0) (match_dup 1)))]
   "")
 
+(define_insn "sminqi3"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (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"
+  [(set_attr "type" "mvi")])
+
+(define_insn "uminqi3"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (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"
+  [(set_attr "type" "mvi")])
+
+(define_insn "smaxqi3"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (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"
+  [(set_attr "type" "mvi")])
+
+(define_insn "umaxqi3"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (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"
+  [(set_attr "type" "mvi")])
+
+(define_insn "sminhi3"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (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"
+  [(set_attr "type" "mvi")])
+
+(define_insn "uminhi3"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (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"
+  [(set_attr "type" "mvi")])
+
+(define_insn "smaxhi3"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (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"
+  [(set_attr "type" "mvi")])
+
+(define_insn "umaxhi3"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (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 "type" "shift")])
+
 (define_expand "smaxdi3"
   [(set (match_dup 3)
        (le:DI (match_operand:DI 1 "reg_or_0_operand" "")
        (smax:DI (match_operand:DI 1 "register_operand" "0")
                 (const_int 0)))]
   ""
-  "cmovlt %0,0,%0")
+  "cmovlt %0,0,%0"
+  [(set_attr "type" "icmov")])
 
 (define_expand "smindi3"
   [(set (match_dup 3)
        (smin:DI (match_operand:DI 1 "register_operand" "0")
                 (const_int 0)))]
   ""
-  "cmovgt %0,0,%0")
+  "cmovgt %0,0,%0"
+  [(set_attr "type" "icmov")])
 
 (define_expand "umaxdi3"
   [(set (match_dup 3) 
 (define_insn ""
   [(set (pc)
        (if_then_else
+        (match_operator 1 "signed_comparison_operator"
+                        [(const_int 0)
+                         (match_operand:DI 2 "register_operand" "r")])
+        (label_ref (match_operand 0 "" ""))
+        (pc)))]
+  ""
+  "b%c1 %2,%0"
+  [(set_attr "type" "ibr")])
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else
         (ne (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
                              (const_int 1)
                              (const_int 0))
 ;; to DFmode.
 
 (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")
+                           (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"
                           [(match_operand:DF 2 "reg_or_fp0_operand" "fG")
                            (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
-  "TARGET_FP"
-  "cmpt%C1 %R2,%R3,%0"
-  [(set_attr "type" "fpop")])
+  "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
+                            (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")
                           [(float_extend:DF
                             (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
                            (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
-  "TARGET_FP"
-  "cmpt%C1 %R2,%R3,%0"
-  [(set_attr "type" "fpop")])
+  "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")
+                           (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_operand:DF 2 "reg_or_fp0_operand" "fG")
                            (float_extend:DF
                             (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))]
-  "TARGET_FP"
-  "cmpt%C1 %R2,%R3,%0"
-  [(set_attr "type" "fpop")])
+  "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
+                            (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")
                             (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
                            (float_extend:DF
                             (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))]
-  "TARGET_FP"
-  "cmpt%C1 %R2,%R3,%0"
-  [(set_attr "type" "fpop")])
+  "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")
   "@
    fcmov%C3 %R4,%R1,%0
    fcmov%D3 %R4,%R5,%0"
-  [(set_attr "type" "fpop")])
+  [(set_attr "type" "fcmov")])
 
 (define_insn ""
   [(set (match_operand:SF 0 "register_operand" "=f,f")
   "@
    fcmov%C3 %R4,%R1,%0
    fcmov%D3 %R4,%R5,%0"
-  [(set_attr "type" "fpop")])
+  [(set_attr "type" "fcmov")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f,f")
        (if_then_else:DF 
         (match_operator 3 "signed_comparison_operator"
-                        [(match_operand:DF 1 "reg_or_fp0_operand" "fG,fG")
+                        [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG")
                          (match_operand:DF 2 "fp0_operand" "G,G")])
-        (float_extend:DF (match_operand:SF 4 "reg_or_fp0_operand" "fG,0"))
+        (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"
   "@
    fcmov%C3 %R4,%R1,%0
    fcmov%D3 %R4,%R5,%0"
-  [(set_attr "type" "fpop")])
+  [(set_attr "type" "fcmov")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f,f")
   "@
    fcmov%C3 %R4,%R1,%0
    fcmov%D3 %R4,%R5,%0"
-  [(set_attr "type" "fpop")])
+  [(set_attr "type" "fcmov")])
 
 (define_insn ""
   [(set (match_operand:SF 0 "register_operand" "=f,f")
   "@
    fcmov%C3 %R4,%R1,%0
    fcmov%D3 %R4,%R5,%0"
-  [(set_attr "type" "fpop")])
+  [(set_attr "type" "fcmov")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "register_operand" "=f,f")
   "@
    fcmov%C3 %R4,%R1,%0
    fcmov%D3 %R4,%R5,%0"
-  [(set_attr "type" "fpop")])
+  [(set_attr "type" "fcmov")])
 
 (define_expand "maxdf3"
   [(set (match_dup 3)
 (define_expand "cmpdf"
   [(set (cc0) (compare (match_operand:DF 0 "reg_or_fp0_operand" "")
                       (match_operand:DF 1 "reg_or_fp0_operand" "")))]
-  ""
+  "TARGET_FP"
   "
 {
   alpha_compare_op0 = operands[0];
 }")
 
 (define_expand "beq"
-  [(set (match_dup 1) (match_dup 2))
-   (set (pc)
-       (if_then_else (match_dup 3)
+  [(set (pc)
+       (if_then_else (match_dup 1)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "
-{
-  enum machine_mode mode;
-  enum rtx_code compare_code, branch_code;
-
-  if (alpha_compare_fp_p)
-    mode = DFmode, compare_code = EQ, branch_code = NE;
-  else
-    {
-      mode = DImode, compare_code = MINUS, branch_code = EQ;
-      if (GET_CODE (alpha_compare_op1) == CONST_INT)
-       {
-         compare_code = PLUS;
-         alpha_compare_op1 = GEN_INT (- INTVAL (alpha_compare_op1));
-       }
-    }
-
-  operands[1] = gen_reg_rtx (mode);
-  operands[2] = gen_rtx (compare_code, mode,
-                        alpha_compare_op0, alpha_compare_op1);
-  operands[3] = gen_rtx (branch_code, VOIDmode,
-                        operands[1], CONST0_RTX (mode));
-}")
+  "{ operands[1] = alpha_emit_conditional_branch (EQ); }")
 
 (define_expand "bne"
-  [(set (match_dup 1) (match_dup 2))
-   (set (pc)
-       (if_then_else (match_dup 3)
+  [(set (pc)
+       (if_then_else (match_dup 1)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "
-{
-  enum machine_mode mode;
-  enum rtx_code compare_code, branch_code;
-
-  if (alpha_compare_fp_p)
-    mode = DFmode, compare_code = EQ, branch_code = EQ;
-  else
-    {
-      mode = DImode, compare_code = MINUS, branch_code = NE;
-      if (GET_CODE (alpha_compare_op1) == CONST_INT)
-       {
-         compare_code = PLUS;
-         alpha_compare_op1 = GEN_INT (- INTVAL (alpha_compare_op1));
-       }
-    }
-
-  operands[1] = gen_reg_rtx (mode);
-  operands[2] = gen_rtx (compare_code, mode,
-                        alpha_compare_op0, alpha_compare_op1);
-  operands[3] = gen_rtx (branch_code, VOIDmode,
-                        operands[1], CONST0_RTX (mode));
-}")
+  "{ operands[1] = alpha_emit_conditional_branch (NE); }")
 
 (define_expand "blt"
-  [(set (match_dup 1) (match_dup 2))
-   (set (pc)
-       (if_then_else (match_dup 3)
+  [(set (pc)
+       (if_then_else (match_dup 1)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "
-{
-  enum machine_mode mode = alpha_compare_fp_p ? DFmode : DImode;
-  operands[1] = gen_reg_rtx (mode);
-  operands[2] = gen_rtx (LT, mode, alpha_compare_op0, alpha_compare_op1);
-  operands[3] = gen_rtx (NE, VOIDmode, operands[1], CONST0_RTX (mode));
-}")
+  "{ operands[1] = alpha_emit_conditional_branch (LT); }")
 
 (define_expand "ble"
-  [(set (match_dup 1) (match_dup 2))
-   (set (pc)
-       (if_then_else (match_dup 3)
+  [(set (pc)
+       (if_then_else (match_dup 1)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "
-{
-  enum machine_mode mode = alpha_compare_fp_p ? DFmode : DImode;
-  operands[1] = gen_reg_rtx (mode);
-  operands[2] = gen_rtx (LE, mode, alpha_compare_op0, alpha_compare_op1);
-  operands[3] = gen_rtx (NE, VOIDmode, operands[1], CONST0_RTX (mode));
-}")
+  "{ operands[1] = alpha_emit_conditional_branch (LE); }")
 
 (define_expand "bgt"
-  [(set (match_dup 1) (match_dup 2))
-   (set (pc)
-       (if_then_else (match_dup 3)
+  [(set (pc)
+       (if_then_else (match_dup 1)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "
-{
-  if (alpha_compare_fp_p)
-    {
-      operands[1] = gen_reg_rtx (DFmode);
-      operands[2] = gen_rtx (LT, DFmode, alpha_compare_op1, alpha_compare_op0);
-      operands[3] = gen_rtx (NE, VOIDmode, operands[1], CONST0_RTX (DFmode));
-    }
-  else
-    {
-      operands[1] = gen_reg_rtx (DImode);
-      operands[2] = gen_rtx (LE, DImode, alpha_compare_op0, alpha_compare_op1);
-      operands[3] = gen_rtx (EQ, VOIDmode, operands[1], const0_rtx);
-    }
-}")
+  "{ operands[1] = alpha_emit_conditional_branch (GT); }")
 
 (define_expand "bge"
-  [(set (match_dup 1) (match_dup 2))
-   (set (pc)
-       (if_then_else (match_dup 3)
+  [(set (pc)
+       (if_then_else (match_dup 1)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "
-{
-  if (alpha_compare_fp_p)
-    {
-      operands[1] = gen_reg_rtx (DFmode);
-      operands[2] = gen_rtx (LE, DFmode, alpha_compare_op1, alpha_compare_op0);
-      operands[3] = gen_rtx (NE, VOIDmode, operands[1], CONST0_RTX (DFmode));
-    }
-  else
-    {
-      operands[1] = gen_reg_rtx (DImode);
-      operands[2] = gen_rtx (LT, DImode, alpha_compare_op0, alpha_compare_op1);
-      operands[3] = gen_rtx (EQ, VOIDmode, operands[1], const0_rtx);
-    }
-}")
+  "{ operands[1] = alpha_emit_conditional_branch (GE); }")
 
 (define_expand "bltu"
-  [(set (match_dup 1) (match_dup 2))
-   (set (pc)
-       (if_then_else (match_dup 3)
+  [(set (pc)
+       (if_then_else (match_dup 1)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "
-{
-  operands[1] = gen_reg_rtx (DImode);
-  operands[2] = gen_rtx (LTU, DImode, alpha_compare_op0, alpha_compare_op1);
-  operands[3] = gen_rtx (NE, VOIDmode, operands[1], const0_rtx);
-}")
+  "{ operands[1] = alpha_emit_conditional_branch (LTU); }")
 
 (define_expand "bleu"
-  [(set (match_dup 1) (match_dup 2))
-   (set (pc)
-       (if_then_else (match_dup 3)
+  [(set (pc)
+       (if_then_else (match_dup 1)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "
-{
-  operands[1] = gen_reg_rtx (DImode);
-  operands[2] = gen_rtx (LEU, DImode, alpha_compare_op0, alpha_compare_op1);
-  operands[3] = gen_rtx (NE, VOIDmode, operands[1], const0_rtx);
-}")
+  "{ operands[1] = alpha_emit_conditional_branch (LEU); }")
 
 (define_expand "bgtu"
-  [(set (match_dup 1) (match_dup 2))
-   (set (pc)
-       (if_then_else (match_dup 3)
+  [(set (pc)
+       (if_then_else (match_dup 1)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "
-{
-  operands[1] = gen_reg_rtx (DImode);
-  operands[2] = gen_rtx (LEU, DImode, alpha_compare_op0, alpha_compare_op1);
-  operands[3] = gen_rtx (EQ, VOIDmode, operands[1], const0_rtx);
-}")
+  "{ operands[1] = alpha_emit_conditional_branch (GTU); }")
 
 (define_expand "bgeu"
-  [(set (match_dup 1) (match_dup 2))
-   (set (pc)
-       (if_then_else (match_dup 3)
+  [(set (pc)
+       (if_then_else (match_dup 1)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "
-{
-  operands[1] = gen_reg_rtx (DImode);
-  operands[2] = gen_rtx (LTU, DImode, alpha_compare_op0, alpha_compare_op1);
-  operands[3] = gen_rtx (EQ, VOIDmode, operands[1], const0_rtx);
-}")
+  "{ operands[1] = alpha_emit_conditional_branch (GEU); }")
 
 (define_expand "seq"
   [(set (match_operand:DI 0 "register_operand" "")
   if (alpha_compare_fp_p)
     FAIL;
 
-  operands[1] = gen_rtx (EQ, DImode, alpha_compare_op0, alpha_compare_op1);
+  operands[1] = gen_rtx_EQ (DImode, alpha_compare_op0, alpha_compare_op1);
 }")
 
 (define_expand "sne"
   if (alpha_compare_fp_p)
     FAIL;
 
-  operands[1] = gen_rtx (EQ, DImode, alpha_compare_op0, alpha_compare_op1);
+  operands[1] = gen_rtx_EQ (DImode, alpha_compare_op0, alpha_compare_op1);
 }")
 
 (define_expand "slt"
   if (alpha_compare_fp_p)
     FAIL;
 
-  operands[1] = gen_rtx (LT, DImode, alpha_compare_op0, alpha_compare_op1);
+  operands[1] = gen_rtx_LT (DImode, alpha_compare_op0, alpha_compare_op1);
 }")
 
 (define_expand "sle"
   if (alpha_compare_fp_p)
     FAIL;
 
-  operands[1] = gen_rtx (LE, DImode, alpha_compare_op0, alpha_compare_op1);
+  operands[1] = gen_rtx_LE (DImode, alpha_compare_op0, alpha_compare_op1);
 }")
 
 (define_expand "sgt"
   if (alpha_compare_fp_p)
     FAIL;
 
-  operands[1] = gen_rtx (LT, DImode, force_reg (DImode, alpha_compare_op1),
-                        alpha_compare_op0);
+  operands[1] = gen_rtx_LT (DImode, force_reg (DImode, alpha_compare_op1),
+                           alpha_compare_op0);
 }")
 
 (define_expand "sge"
   if (alpha_compare_fp_p)
     FAIL;
 
-  operands[1] = gen_rtx (LE, DImode, force_reg (DImode, alpha_compare_op1),
-                        alpha_compare_op0);
+  operands[1] = gen_rtx_LE (DImode, force_reg (DImode, alpha_compare_op1),
+                           alpha_compare_op0);
 }")
 
 (define_expand "sltu"
   if (alpha_compare_fp_p)
     FAIL;
 
-  operands[1] = gen_rtx (LTU, DImode, alpha_compare_op0, alpha_compare_op1);
+  operands[1] = gen_rtx_LTU (DImode, alpha_compare_op0, alpha_compare_op1);
 }")
 
 (define_expand "sleu"
   if (alpha_compare_fp_p)
     FAIL;
 
-  operands[1] = gen_rtx (LEU, DImode, alpha_compare_op0, alpha_compare_op1);
+  operands[1] = gen_rtx_LEU (DImode, alpha_compare_op0, alpha_compare_op1);
 }")
 
 (define_expand "sgtu"
   if (alpha_compare_fp_p)
     FAIL;
 
-  operands[1] = gen_rtx (LTU, DImode, force_reg (DImode, alpha_compare_op1),
-                        alpha_compare_op0);
+  operands[1] = gen_rtx_LTU (DImode, force_reg (DImode, alpha_compare_op1),
+                            alpha_compare_op0);
 }")
 
 (define_expand "sgeu"
   if (alpha_compare_fp_p)
     FAIL;
 
-  operands[1] = gen_rtx (LEU, DImode, force_reg (DImode, alpha_compare_op1),
-                        alpha_compare_op0);
+  operands[1] = gen_rtx_LEU (DImode, force_reg (DImode, alpha_compare_op1),
+                            alpha_compare_op0);
 }")
 \f
-;; These define_split definitions are used in cases when comparisons have
-;; not be stated in the correct way and we need to reverse the second
-;; comparison.  For example, x >= 7 has to be done as x < 6 with the
-;; comparison that tests the result being reversed.  We have one define_split
-;; for each use of a comparison.  They do not match valid insns and need
-;; not generate valid insns.
-;;
-;; We can also handle equality comparisons (and inequality comparisons in
-;; cases where the resulting add cannot overflow) by doing an add followed by
-;; a comparison with zero.  This is faster since the addition takes one
-;; less cycle than a compare when feeding into a conditional move.
-;; For this case, we also have an SImode pattern since we can merge the add
-;; and sign extend and the order doesn't matter.
-;;
-;; We do not do this for floating-point, since it isn't clear how the "wrong"
-;; operation could have been generated.
+;; These are the main define_expand's used to make conditional moves.
 
-(define_split
-  [(set (match_operand:DI 0 "register_operand" "")
+(define_expand "movsicc"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (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 ((operands[1] = alpha_emit_conditional_move (operands[1], SImode)) == 0)
+    FAIL;
+}")
+
+(define_expand "movdicc"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (if_then_else:DI (match_operand 1 "comparison_operator" "")
+                        (match_operand:DI 2 "reg_or_8bit_operand" "")
+                        (match_operand:DI 3 "reg_or_8bit_operand" "")))]
+  ""
+  "
+{
+  if ((operands[1] = alpha_emit_conditional_move (operands[1], DImode)) == 0)
+    FAIL;
+}")
+
+(define_expand "movsfcc"
+  [(set (match_operand:SF 0 "register_operand" "")
+       (if_then_else:SF (match_operand 1 "comparison_operator" "")
+                        (match_operand:SF 2 "reg_or_8bit_operand" "")
+                        (match_operand:SF 3 "reg_or_8bit_operand" "")))]
+  ""
+  "
+{
+  if ((operands[1] = alpha_emit_conditional_move (operands[1], SFmode)) == 0)
+    FAIL;
+}")
+
+(define_expand "movdfcc"
+  [(set (match_operand:DF 0 "register_operand" "")
+       (if_then_else:DF (match_operand 1 "comparison_operator" "")
+                        (match_operand:DF 2 "reg_or_8bit_operand" "")
+                        (match_operand:DF 3 "reg_or_8bit_operand" "")))]
+  ""
+  "
+{
+  if ((operands[1] = alpha_emit_conditional_move (operands[1], DFmode)) == 0)
+    FAIL;
+}")
+\f
+;; These define_split definitions are used in cases when comparisons have
+;; not be stated in the correct way and we need to reverse the second
+;; comparison.  For example, x >= 7 has to be done as x < 6 with the
+;; comparison that tests the result being reversed.  We have one define_split
+;; for each use of a comparison.  They do not match valid insns and need
+;; not generate valid insns.
+;;
+;; We can also handle equality comparisons (and inequality comparisons in
+;; cases where the resulting add cannot overflow) by doing an add followed by
+;; a comparison with zero.  This is faster since the addition takes one
+;; less cycle than a compare when feeding into a conditional move.
+;; For this case, we also have an SImode pattern since we can merge the add
+;; and sign extend and the order doesn't matter.
+;;
+;; We do not do this for floating-point, since it isn't clear how the "wrong"
+;; operation could have been generated.
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
        (if_then_else:DI
         (match_operator 1 "comparison_operator"
                         [(match_operand:DI 2 "reg_or_0_operand" "")
          && extended_count (operands[3], DImode, unsignedp) >= 1))
     {
       if (GET_CODE (operands[3]) == CONST_INT)
-       operands[7] = gen_rtx (PLUS, DImode, operands[2],
-                              GEN_INT (- INTVAL (operands[3])));
+       operands[7] = gen_rtx_PLUS (DImode, operands[2],
+                                   GEN_INT (- INTVAL (operands[3])));
       else
-       operands[7] = gen_rtx (MINUS, DImode, operands[2], operands[3]);
+       operands[7] = gen_rtx_MINUS (DImode, operands[2], operands[3]);
 
-      operands[8] = gen_rtx (code, VOIDmode, operands[6], const0_rtx);
+      operands[8] = gen_rtx_fmt_ee (code, VOIDmode, operands[6], const0_rtx);
     }
 
   else if (code == EQ || code == LE || code == LT
           || code == LEU || code == LTU)
     {
-      operands[7] = gen_rtx (code, DImode, operands[2], operands[3]);
-      operands[8] = gen_rtx (NE, VOIDmode, operands[6], const0_rtx);
+      operands[7] = gen_rtx_fmt_ee (code, DImode, operands[2], operands[3]);
+      operands[8] = gen_rtx_NE (VOIDmode, operands[6], const0_rtx);
     }
   else
     {
-      operands[7] = gen_rtx (reverse_condition (code), DImode, operands[2],
-                            operands[3]);
-      operands[8] = gen_rtx (EQ, VOIDmode, operands[6], const0_rtx);
+      operands[7] = gen_rtx_fmt_ee (reverse_condition (code), DImode,
+                                   operands[2], operands[3]);
+      operands[8] = gen_rtx_EQ (VOIDmode, operands[6], const0_rtx);
     }
 }")
 
     FAIL;
  
   if (GET_CODE (operands[3]) == CONST_INT)
-    tem = gen_rtx (PLUS, SImode, operands[2],
-                  GEN_INT (- INTVAL (operands[3])));
+    tem = gen_rtx_PLUS (SImode, operands[2],
+                       GEN_INT (- INTVAL (operands[3])));
   else
-    tem = gen_rtx (MINUS, SImode, operands[2], operands[3]);
+    tem = gen_rtx_MINUS (SImode, operands[2], operands[3]);
 
-  operands[7] = gen_rtx (SIGN_EXTEND, DImode, tem);
-  operands[8] = gen_rtx (GET_CODE (operands[1]), VOIDmode, operands[6],
-                        const0_rtx);
+  operands[7] = gen_rtx_SIGN_EXTEND (DImode, tem);
+  operands[8] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
+                               operands[6], const0_rtx);
 }")
 
 (define_split
          && extended_count (operands[3], DImode, unsignedp) >= 1))
     {
       if (GET_CODE (operands[3]) == CONST_INT)
-       operands[5] = gen_rtx (PLUS, DImode, operands[2],
-                              GEN_INT (- INTVAL (operands[3])));
+       operands[5] = gen_rtx_PLUS (DImode, operands[2],
+                                   GEN_INT (- INTVAL (operands[3])));
       else
-       operands[5] = gen_rtx (MINUS, DImode, operands[2], operands[3]);
+       operands[5] = gen_rtx_MINUS (DImode, operands[2], operands[3]);
 
-      operands[6] = gen_rtx (code, VOIDmode, operands[4], const0_rtx);
+      operands[6] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx);
     }
 
   else if (code == EQ || code == LE || code == LT
           || code == LEU || code == LTU)
     {
-      operands[5] = gen_rtx (code, DImode, operands[2], operands[3]);
-      operands[6] = gen_rtx (NE, VOIDmode, operands[4], const0_rtx);
+      operands[5] = gen_rtx_fmt_ee (code, DImode, operands[2], operands[3]);
+      operands[6] = gen_rtx_NE (VOIDmode, operands[4], const0_rtx);
     }
   else
     {
-      operands[5] = gen_rtx (reverse_condition (code), DImode, operands[2],
-                            operands[3]);
-      operands[6] = gen_rtx (EQ, VOIDmode, operands[4], const0_rtx);
+      operands[5] = gen_rtx_fmt_ee (reverse_condition (code), DImode,
+                                   operands[2], operands[3]);
+      operands[6] = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx);
     }
 }")
 
 { rtx tem;
 
   if (GET_CODE (operands[3]) == CONST_INT)
-    tem = gen_rtx (PLUS, SImode, operands[2],
-                  GEN_INT (- INTVAL (operands[3])));
+    tem = gen_rtx_PLUS (SImode, operands[2],
+                       GEN_INT (- INTVAL (operands[3])));
   else
-    tem = gen_rtx (MINUS, SImode, operands[2], operands[3]);
+    tem = gen_rtx_MINUS (SImode, operands[2], operands[3]);
   
-  operands[5] = gen_rtx (SIGN_EXTEND, DImode, tem);
-  operands[6] = gen_rtx (GET_CODE (operands[1]), VOIDmode,
-                        operands[4], const0_rtx);
+  operands[5] = gen_rtx_SIGN_EXTEND (DImode, tem);
+  operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode,
+                               operands[4], const0_rtx);
 }")
 
 ;; We can convert such things as "a > 0xffff" to "t = a & ~ 0xffff; t != 0".
   "
 {
   operands[5] = GEN_INT (~ INTVAL (operands[3]));
-  operands[6] = gen_rtx (((GET_CODE (operands[1]) == GTU
-                          || GET_CODE (operands[1]) == GT)
-                         ? NE : EQ),
-                        DImode, operands[4], const0_rtx);
+  operands[6] = gen_rtx_fmt_ee (((GET_CODE (operands[1]) == GTU
+                                 || GET_CODE (operands[1]) == GT)
+                                ? NE : EQ),
+                               DImode, operands[4], const0_rtx);
 }")
 \f
-;; Here are the CALL and unconditional branch insns.
+;; Here are the CALL and unconditional branch insns.  Calls on NT and OSF
+;; work differently, so we have different patterns for each.
 
 (define_expand "call"
+  [(use (match_operand:DI 0 "" ""))
+   (use (match_operand 1 "" ""))
+   (use (match_operand 2 "" ""))
+   (use (match_operand 3 "" ""))]
+  ""
+  "
+{ if (TARGET_WINDOWS_NT)
+    emit_call_insn (gen_call_nt (operands[0], operands[1]));
+  else if (TARGET_OPEN_VMS)
+    emit_call_insn (gen_call_vms (operands[0], operands[2]));
+  else
+    emit_call_insn (gen_call_osf (operands[0], operands[1]));
+
+  DONE;
+}")
+
+(define_expand "call_osf"
   [(parallel [(call (mem:DI (match_operand 0 "" ""))
                    (match_operand 1 "" ""))
              (clobber (reg:DI 27))
   if (GET_CODE (operands[0]) != SYMBOL_REF
       && ! (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 27))
     {
-      rtx tem = gen_rtx (REG, DImode, 27);
+      rtx tem = gen_rtx_REG (DImode, 27);
       emit_move_insn (tem, operands[0]);
       operands[0] = tem;
     }
 }")
 
+(define_expand "call_nt"
+  [(parallel [(call (mem:DI (match_operand 0 "" ""))
+                   (match_operand 1 "" ""))
+             (clobber (reg:DI 26))])]
+  ""
+  "
+{ if (GET_CODE (operands[0]) != MEM)
+    abort ();
+
+  operands[0] = XEXP (operands[0], 0);
+  if (GET_CODE (operands[0]) != SYMBOL_REF && GET_CODE (operands[0]) != REG)
+    operands[0] = force_reg (DImode, operands[0]);
+}")
+
+;;
+;; call openvms/alpha
+;; op 0: symbol ref for called function
+;; op 1: next_arg_reg (argument information value for R25)
+;;
+(define_expand "call_vms"
+  [(parallel [(call (mem:DI (match_operand 0 "" ""))
+                   (match_operand 1 "" ""))
+             (use (match_dup 2))
+             (use (reg:DI 25))
+             (use (reg:DI 26))
+             (clobber (reg:DI 27))])]
+  ""
+  "
+{ if (GET_CODE (operands[0]) != MEM)
+    abort ();
+
+  operands[0] = XEXP (operands[0], 0);
+
+  /* Always load AI with argument information, then handle symbolic and
+     indirect call differently.  Load RA and set operands[2] to PV in
+     both cases.  */
+
+  emit_move_insn (gen_rtx_REG (DImode, 25), operands[1]);
+  if (GET_CODE (operands[0]) == SYMBOL_REF)
+    {
+      extern char *savealloc ();
+      char *linksym, *symbol = XSTR (operands[0], 0);
+      rtx linkage;
+
+      if (*symbol == '*')
+       symbol++;
+      linksym = savealloc (strlen (symbol) + 6);
+
+      alpha_need_linkage (symbol, 0);
+
+      linksym[0] = '$';
+      strcpy (linksym+1, symbol);
+      strcat (linksym, \"..lk\");
+      linkage = gen_rtx_SYMBOL_REF (Pmode, linksym);
+
+      emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, linkage));
+
+      operands[2]
+       = validize_mem (gen_rtx_MEM (Pmode, plus_constant (linkage, 8)));
+    }
+  else
+    {
+      emit_move_insn (gen_rtx_REG (Pmode, 26),
+                     gen_rtx_MEM (Pmode, plus_constant (operands[0], 8)));
+
+      operands[2] = operands[0];
+    }
+
+}")
+
 (define_expand "call_value"
+  [(use (match_operand 0 "" ""))
+   (use (match_operand:DI 1 "" ""))
+   (use (match_operand 2 "" ""))
+   (use (match_operand 3 "" ""))
+   (use (match_operand 4 "" ""))]
+  ""
+  "
+{ if (TARGET_WINDOWS_NT)
+    emit_call_insn (gen_call_value_nt (operands[0], operands[1], operands[2]));
+  else if (TARGET_OPEN_VMS)
+    emit_call_insn (gen_call_value_vms (operands[0], operands[1],
+                                       operands[3]));
+  else
+    emit_call_insn (gen_call_value_osf (operands[0], operands[1],
+                                       operands[2]));
+  DONE;
+}")
+
+(define_expand "call_value_osf"
   [(parallel [(set (match_operand 0 "" "")
                   (call (mem:DI (match_operand 1 "" ""))
                         (match_operand 2 "" "")))
   if (GET_CODE (operands[1]) != SYMBOL_REF
       && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 27))
     {
-      rtx tem = gen_rtx (REG, DImode, 27);
+      rtx tem = gen_rtx_REG (DImode, 27);
       emit_move_insn (tem, operands[1]);
       operands[1] = tem;
     }
 }")
 
+(define_expand "call_value_nt"
+  [(parallel [(set (match_operand 0 "" "")
+                  (call (mem:DI (match_operand 1 "" ""))
+                        (match_operand 2 "" "")))
+             (clobber (reg:DI 26))])]
+  ""
+  "
+{ if (GET_CODE (operands[1]) != MEM)
+    abort ();
+
+  operands[1] = XEXP (operands[1], 0);
+  if (GET_CODE (operands[0]) != SYMBOL_REF && GET_CODE (operands[0]) != REG)
+    operands[1] = force_reg (DImode, operands[1]);
+}")
+
+(define_expand "call_value_vms"
+  [(parallel [(set (match_operand 0 "" "")
+                  (call (mem:DI (match_operand:DI 1 "" ""))
+                        (match_operand 2 "" "")))
+             (use (match_dup 3))
+             (use (reg:DI 25))
+             (use (reg:DI 26))
+             (clobber (reg:DI 27))])]
+  ""
+  "
+{ if (GET_CODE (operands[1]) != MEM)
+    abort ();
+
+  operands[1] = XEXP (operands[1], 0);
+
+  /* Always load AI with argument information, then handle symbolic and
+     indirect call differently.  Load RA and set operands[3] to PV in
+     both cases.  */
+
+  emit_move_insn (gen_rtx_REG (DImode, 25), operands[2]);
+  if (GET_CODE (operands[1]) == SYMBOL_REF)
+    {
+      extern char *savealloc ();
+      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);
+      strcat (linksym, \"..lk\");
+      linkage = gen_rtx_SYMBOL_REF (Pmode, linksym);
+
+      emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, linkage));
+
+      operands[3]
+       = validize_mem (gen_rtx_MEM (Pmode, plus_constant (linkage, 8)));
+    }
+  else
+    {
+      emit_move_insn (gen_rtx_REG (Pmode, 26),
+                     gen_rtx_MEM (Pmode, plus_constant (operands[1], 8)));
+
+      operands[3] = operands[1];
+    }
+}")
+
 (define_insn ""
   [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i"))
         (match_operand 1 "" ""))
    (clobber (reg:DI 27))
    (clobber (reg:DI 26))]
-  ""
+  "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS"
   "@
    jsr $26,($27),0\;ldgp $29,0($26)
-   bsr $26,%0..ng
+   bsr $26,$%0..ng
    jsr $26,%0\;ldgp $29,0($26)"
-  [(set_attr "type" "jsr,jsr,ibr")])
+  [(set_attr "type" "jsr")
+   (set_attr "length" "12,*,16")])
       
 (define_insn ""
+  [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i"))
+        (match_operand 1 "" ""))
+   (clobber (reg:DI 26))]
+  "TARGET_WINDOWS_NT"
+  "@
+   jsr $26,(%0)
+   bsr $26,%0
+   jsr $26,%0"
+  [(set_attr "type" "jsr")
+   (set_attr "length" "*,*,12")])
+      
+(define_insn ""
+  [(call (mem:DI (match_operand:DI 0 "call_operand" "r,i"))
+        (match_operand 1 "" ""))
+   (use (match_operand:DI 2 "general_operand" "r,m"))
+   (use (reg:DI 25))
+   (use (reg:DI 26))
+   (clobber (reg:DI 27))]
+  "TARGET_OPEN_VMS"
+  "@
+   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 "length" "12,16")])
+
+(define_insn ""
   [(set (match_operand 0 "register_operand" "=rf,rf,rf")
        (call (mem:DI (match_operand:DI 1 "call_operand" "r,R,i"))
              (match_operand 2 "" "")))
    (clobber (reg:DI 27))
    (clobber (reg:DI 26))]
-  ""
+  "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS"
   "@
    jsr $26,($27),0\;ldgp $29,0($26)
-   bsr $26,%1..ng
+   bsr $26,$%1..ng
    jsr $26,%1\;ldgp $29,0($26)"
-  [(set_attr "type" "jsr,jsr,ibr")])
+  [(set_attr "type" "jsr")
+   (set_attr "length" "12,*,16")])
+
+(define_insn ""
+  [(set (match_operand 0 "register_operand" "=rf,rf,rf")
+       (call (mem:DI (match_operand:DI 1 "call_operand" "r,R,i"))
+             (match_operand 2 "" "")))
+   (clobber (reg:DI 26))]
+  "TARGET_WINDOWS_NT"
+  "@
+   jsr $26,(%1)
+   bsr $26,%1
+   jsr $26,%1"
+  [(set_attr "type" "jsr")
+   (set_attr "length" "*,*,12")])
+
+(define_insn ""
+  [(set (match_operand 0 "register_operand" "")
+       (call (mem:DI (match_operand:DI 1 "call_operand" "r,i"))
+             (match_operand 2 "" "")))
+   (use (match_operand:DI 3 "general_operand" "r,m"))
+   (use (reg:DI 25))
+   (use (reg:DI 26))
+   (clobber (reg:DI 27))]
+  "TARGET_OPEN_VMS"
+  "@
+   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 "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)]
+(define_expand "tablejump"
+  [(use (match_operand:SI 0 "register_operand" ""))
+   (use (match_operand:SI 1 "" ""))]
   ""
-  "bis $31,$31,$31"
-  [(set_attr "type" "iaddlog")])
+  "
+{
+  if (TARGET_WINDOWS_NT)
+    emit_jump_insn (gen_tablejump_nt (operands[0], operands[1]));
+  else if (TARGET_OPEN_VMS)
+    emit_jump_insn (gen_tablejump_vms (operands[0], operands[1]));
+  else
+    emit_jump_insn (gen_tablejump_osf (operands[0], operands[1]));
 
-(define_expand "tablejump"
+  DONE;
+}")
+
+(define_expand "tablejump_osf"
   [(set (match_dup 3)
        (sign_extend:DI (match_operand:SI 0 "register_operand" "")))
    (parallel [(set (pc)
   "
 { operands[3] = gen_reg_rtx (DImode); }")
 
+(define_expand "tablejump_nt"
+  [(set (match_dup 3)
+       (sign_extend:DI (match_operand:SI 0 "register_operand" "")))
+   (parallel [(set (pc)
+                  (match_dup 3))
+             (use (label_ref (match_operand 1 "" "")))])]
+  ""
+  "
+{ operands[3] = gen_reg_rtx (DImode); }")
+
+;;
+;; tablejump, openVMS way
+;; op 0: offset
+;; op 1: label preceding jump-table
+;;
+(define_expand "tablejump_vms"
+  [(set (match_dup 2)
+      (match_operand:DI 0 "register_operand" ""))
+        (set (pc)
+       (plus:DI (match_dup 2)
+               (label_ref:DI (match_operand 1 "" ""))))]
+  ""
+  "
+{ operands[2] = gen_reg_rtx (DImode); }")
+
 (define_insn ""
   [(set (pc)
        (plus:DI (match_operand:DI 0 "register_operand" "r")
                 (label_ref:DI (match_operand 1 "" ""))))
    (clobber (match_scratch:DI 2 "=r"))]
-  "next_active_insn (insn) != 0
+  "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && next_active_insn (insn) != 0
    && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC
    && PREV_INSN (next_active_insn (insn)) == operands[1]"
   "*
   else
     return \"addq %0,$29,%2\;jmp $31,(%2),0\";
 }"
+  [(set_attr "type" "ibr")
+   (set_attr "length" "8")])
+
+(define_insn ""
+  [(set (pc)
+       (match_operand:DI 0 "register_operand" "r"))
+   (use (label_ref (match_operand 1 "" "")))]
+  "TARGET_WINDOWS_NT && next_active_insn (insn) != 0
+   && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC
+   && PREV_INSN (next_active_insn (insn)) == operands[1]"
+  "*
+{ rtx best_label = 0;
+  rtx jump_table_insn = next_active_insn (operands[1]);
+
+  if (GET_CODE (jump_table_insn) == JUMP_INSN
+      && GET_CODE (PATTERN (jump_table_insn)) == ADDR_DIFF_VEC)
+    {
+      rtx jump_table = PATTERN (jump_table_insn);
+      int n_labels = XVECLEN (jump_table, 1);
+      int best_count = -1;
+      int i, j;
+
+      for (i = 0; i < n_labels; i++)
+       {
+         int count = 1;
+
+         for (j = i + 1; j < n_labels; j++)
+           if (XEXP (XVECEXP (jump_table, 1, i), 0)
+               == XEXP (XVECEXP (jump_table, 1, j), 0))
+             count++;
+
+         if (count > best_count)
+           best_count = count, best_label = XVECEXP (jump_table, 1, i);
+       }
+    }
+
+  if (best_label)
+    {
+      operands[2] = best_label;
+      return \"jmp $31,(%0),%2\";
+    }
+  else
+    return \"jmp $31,(%0),0\";
+}"
+  [(set_attr "type" "ibr")])
+
+;;
+;; op 0 is table offset
+;; op 1 is table label
+;;
+
+(define_insn ""
+  [(set (pc)
+       (plus:DI (match_operand 0 "register_operand" "r")
+               (label_ref (match_operand 1 "" ""))))]
+  "TARGET_OPEN_VMS"
+  "jmp $31,(%0),0"
   [(set_attr "type" "ibr")])
 
 ;; Cache flush.  Used by INITIALIZE_TRAMPOLINE.  0x86 is PAL_imb, but we don't
 ;; want to have to include pal.h in our .s file.
-(define_insn ""
+;;
+;; 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 "imb"
   [(unspec_volatile [(const_int 0)] 0)]
   ""
-  "call_pal 0x86")
+  "call_pal 0x86"
+  [(set_attr "type" "ibr")])
 \f
 ;; Finally, we have the basic data motion insns.  The byte and word insns
 ;; are done via define_expand.  Start with the floating-point insns, since
 (define_insn ""
   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m")
        (match_operand:SF 1 "input_operand" "rG,m,rG,f,G,m,fG"))]
-  "register_operand (operands[0], SFmode)
-   || reg_or_fp0_operand (operands[1], SFmode)"
+  "! TARGET_CIX
+   && (register_operand (operands[0], SFmode)
+       || reg_or_fp0_operand (operands[1], SFmode))"
+  "@
+   bis %r1,%r1,%0
+   ldl %0,%1
+   stl %r1,%0
+   cpys %1,%1,%0
+   cpys $f31,$f31,%0
+   ld%, %0,%1
+   st%, %R1,%0"
+  [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst")])
+
+(define_insn ""
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m,f,*r")
+       (match_operand:SF 1 "input_operand" "rG,m,rG,f,G,m,fG,r,*f"))]
+  "TARGET_CIX
+   && (register_operand (operands[0], SFmode)
+       || reg_or_fp0_operand (operands[1], SFmode))"
   "@
    bis %r1,%r1,%0
    ldl %0,%1
    stl %r1,%0
    cpys %1,%1,%0
    cpys $f31,$f31,%0
-   lds %0,%1
-   sts %R1,%0"
-  [(set_attr "type" "iaddlog,ld,st,fpop,fpop,ld,st")])
+   ld%, %0,%1
+   st%, %R1,%0
+   itofs %1,%0
+   ftois %1,%0"
+  [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst,itof,ftoi")])
 
 (define_insn ""
   [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m")
        (match_operand:DF 1 "input_operand" "rG,m,rG,f,G,m,fG"))]
-  "register_operand (operands[0], DFmode)
-   || reg_or_fp0_operand (operands[1], DFmode)"
+  "! TARGET_CIX
+   && (register_operand (operands[0], DFmode)
+       || reg_or_fp0_operand (operands[1], DFmode))"
   "@
    bis %r1,%r1,%0
    ldq %0,%1
    stq %r1,%0
    cpys %1,%1,%0
    cpys $f31,$f31,%0
-   ldt %0,%1
-   stt %R1,%0"
-  [(set_attr "type" "iaddlog,ld,st,fpop,fpop,ld,st")])
+   ld%- %0,%1
+   st%- %R1,%0"
+  [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst")])
+
+(define_insn ""
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m,f,*r")
+       (match_operand:DF 1 "input_operand" "rG,m,rG,f,G,m,fG,r,*f"))]
+  "TARGET_CIX
+   && (register_operand (operands[0], DFmode)
+       || reg_or_fp0_operand (operands[1], DFmode))"
+  "@
+   bis %r1,%r1,%0
+   ldq %0,%1
+   stq %r1,%0
+   cpys %1,%1,%0
+   cpys $f31,$f31,%0
+   ld%- %0,%1
+   st%- %R1,%0
+   itoft %1,%0
+   ftoit %1,%0"
+  [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst,itof,ftoi")])
 
 (define_expand "movsf"
   [(set (match_operand:SF 0 "nonimmediate_operand" "")
     operands[1] = force_reg (DFmode, operands[1]);
 }")
 
-;; There is a problem with 32-bit values in FP registers.  We keep such
-;; values in the register as a quadword.  This is done on loads by using
-;; the cvtlq instruction.  On stores, we can't do anything directly from
-;; floating-point registers.  Disallow such an operation and let reload
-;; use an integer register instead.  Don't encourage 32-bit values to
-;; be placed in FP registers at all.
+(define_insn ""
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,f,f,f,m")
+       (match_operand:SI 1 "input_operand" "r,J,I,K,L,m,rJ,f,J,m,fG"))]
+  "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && ! TARGET_CIX
+   && (register_operand (operands[0], SImode)
+       || reg_or_0_operand (operands[1], SImode))"
+  "@
+   bis %1,%1,%0
+   bis $31,$31,%0
+   bis $31,%1,%0
+   lda %0,%1
+   ldah %0,%h1
+   ldl %0,%1
+   stl %r1,%0
+   cpys %1,%1,%0
+   cpys $f31,$f31,%0
+   ld%, %0,%1
+   st%, %R1,%0"
+  [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ild,ist,fcpys,fcpys,fld,fst")])
 
 (define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,*f")
-       (match_operand:SI 1 "input_operand" "r,J,I,K,L,m,rJ,*f,J,m"))]
-  "register_operand (operands[0], SImode)
-   || reg_or_0_operand (operands[1], SImode)"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,f,f,f,m,r,*f")
+       (match_operand:SI 1 "input_operand" "r,J,I,K,L,m,rJ,f,J,m,fG,f,*r"))]
+  "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && TARGET_CIX
+   && (register_operand (operands[0], SImode)
+       || reg_or_0_operand (operands[1], SImode))"
   "@
    bis %1,%1,%0
    bis $31,$31,%0
    stl %r1,%0
    cpys %1,%1,%0
    cpys $f31,$f31,%0
-   lds %0,%1\;cvtlq %0,%0"
-  [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,iaddlog,ld,st,fpop,fpop,ld")])
+   ld%, %0,%1
+   st%, %R1,%0
+   ftois %1,%0
+   itofs %1,%0"
+  [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ild,ist,fcpys,fcpys,fld,fst,ftoi,itof")])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,r,m,f,f,f,m")
+       (match_operand:SI 1 "input_operand" "r,J,I,K,L,s,m,rJ,f,J,m,fG"))]
+  "(TARGET_WINDOWS_NT || TARGET_OPEN_VMS)
+    && (register_operand (operands[0], SImode)
+        || reg_or_0_operand (operands[1], SImode))"
+  "@
+   bis %1,%1,%0
+   bis $31,$31,%0
+   bis $31,%1,%0
+   lda %0,%1
+   ldah %0,%h1
+   lda %0,%1
+   ldl %0,%1
+   stl %r1,%0
+   cpys %1,%1,%0
+   cpys $f31,$f31,%0
+   ld%, %0,%1
+   st%, %R1,%0"
+  [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ldsym,ild,ist,fcpys,fcpys,fld,fst")])
 
 (define_insn ""
   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,r,f,f")
        (match_operand:HI 1 "input_operand" "r,J,I,n,f,J"))]
-  "register_operand (operands[0], HImode)
-   || register_operand (operands[1], HImode)"
+  "! TARGET_BWX
+   && (register_operand (operands[0], HImode)
+       || register_operand (operands[1], HImode))"
+  "@
+   bis %1,%1,%0
+   bis $31,$31,%0
+   bis $31,%1,%0
+   lda %0,%L1
+   cpys %1,%1,%0
+   cpys $f31,$f31,%0"
+  [(set_attr "type" "ilog,ilog,ilog,iadd,fcpys,fcpys")])
+
+(define_insn ""
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,r,r,m,f,f")
+       (match_operand:HI 1 "input_operand" "r,J,I,n,m,rJ,f,J"))]
+  "TARGET_BWX
+   && (register_operand (operands[0], HImode)
+       || reg_or_0_operand (operands[1], HImode))"
   "@
    bis %1,%1,%0
    bis $31,$31,%0
    bis $31,%1,%0
    lda %0,%L1
+   ldwu %0,%1
+   stw %r1,%0
    cpys %1,%1,%0
    cpys $f31,$f31,%0"
-  [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,fpop,fpop")])
+  [(set_attr "type" "ilog,ilog,ilog,iadd,ild,ist,fcpys,fcpys")])
 
 (define_insn ""
   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,r,f,f")
        (match_operand:QI 1 "input_operand" "r,J,I,n,f,J"))]
-  "register_operand (operands[0], QImode)
-   || register_operand (operands[1], QImode)"
+  "! TARGET_BWX
+   && (register_operand (operands[0], QImode)
+       || register_operand (operands[1], QImode))"
+  "@
+   bis %1,%1,%0
+   bis $31,$31,%0
+   bis $31,%1,%0
+   lda %0,%L1
+   cpys %1,%1,%0
+   cpys $f31,$f31,%0"
+  [(set_attr "type" "ilog,ilog,ilog,iadd,fcpys,fcpys")])
+
+(define_insn ""
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,r,r,m,f,f")
+       (match_operand:QI 1 "input_operand" "r,J,I,n,m,rJ,f,J"))]
+  "TARGET_BWX
+   && (register_operand (operands[0], QImode)
+       || reg_or_0_operand (operands[1], QImode))"
   "@
    bis %1,%1,%0
    bis $31,$31,%0
    bis $31,%1,%0
    lda %0,%L1
+   ldbu %0,%1
+   stb %r1,%0
    cpys %1,%1,%0
    cpys $f31,$f31,%0"
-  [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,fpop,fpop")])
+  [(set_attr "type" "ilog,ilog,ilog,iadd,ild,ist,fcpys,fcpys")])
 
 ;; We do two major things here: handle mem->mem and construct long
 ;; constants.
     ;
   else if (GET_CODE (operands[1]) == CONST_INT)
     {
-      if (alpha_emit_set_const (operands[0], INTVAL (operands[1]), 3))
+      operands[1]
+       = alpha_emit_set_const (operands[0], SImode, INTVAL (operands[1]), 3);
+      if (rtx_equal_p (operands[0], operands[1]))
        DONE;
-      else
-       abort ();
     }
 }")
 
   [(set (match_dup 0) (match_dup 2))
    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
   "
-{ if (alpha_emit_set_const (operands[0], INTVAL (operands[1]), 2))
+{ rtx tem
+    = alpha_emit_set_const (operands[0], SImode, INTVAL (operands[1]), 2);
+
+  if (tem == operands[0])
     DONE;
   else
     FAIL;
 (define_insn ""
   [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,r,r,m,f,f,f,Q")
        (match_operand:DI 1 "input_operand" "r,J,I,K,L,s,m,rJ,f,J,Q,fG"))]
-  "register_operand (operands[0], DImode)
-   || reg_or_0_operand (operands[1], DImode)"
+  "! TARGET_CIX
+   && (register_operand (operands[0], DImode)
+       || reg_or_0_operand (operands[1], DImode))"
   "@
    bis %1,%1,%0
    bis $31,$31,%0
    cpys $f31,$f31,%0
    ldt %0,%1
    stt %R1,%0"
-  [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,iaddlog,ldsym,ld,st,fpop,fpop,ld,st")])
+  [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ldsym,ild,ist,fcpys,fcpys,fld,fst")])
+
+(define_insn ""
+  [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,r,r,m,f,f,f,Q,r,*f")
+       (match_operand:DI 1 "input_operand" "r,J,I,K,L,s,m,rJ,f,J,Q,fG,f,*r"))]
+  "TARGET_CIX
+   && (register_operand (operands[0], DImode)
+       || reg_or_0_operand (operands[1], DImode))"
+  "@
+   bis %1,%1,%0
+   bis $31,$31,%0
+   bis $31,%1,%0
+   lda %0,%1
+   ldah %0,%h1
+   lda %0,%1
+   ldq%A1 %0,%1
+   stq%A0 %r1,%0
+   cpys %1,%1,%0
+   cpys $f31,$f31,%0
+   ldt %0,%1
+   stt %R1,%0
+   ftoit %1,%0
+   itoft %1,%0"
+  [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ldsym,ild,ist,fcpys,fcpys,fld,fst,ftoi,itof")])
 
 ;; We do three major things here: handle mem->mem, put 64-bit constants in
 ;; memory, and construct long 32-bit constants.
   ""
   "
 {
+  rtx tem;
+
   if (GET_CODE (operands[0]) == MEM
       && ! reg_or_0_operand (operands[1], DImode))
     operands[1] = force_reg (DImode, operands[1]);
   if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode))
     ;
   else if (GET_CODE (operands[1]) == CONST_INT
-          && alpha_emit_set_const (operands[0], INTVAL (operands[1]), 3))
-    DONE;
+          && (tem = alpha_emit_set_const (operands[0], DImode,
+                                          INTVAL (operands[1]), 3)) != 0)
+    {
+      if (rtx_equal_p (tem, operands[0]))
+       DONE;
+      else
+       operands[1] = tem;
+    }
   else if (CONSTANT_P (operands[1]))
     {
-      operands[1] = force_const_mem (DImode, operands[1]);
-      if (reload_in_progress)
+      if (TARGET_BUILD_CONSTANTS)
        {
-         emit_move_insn (operands[0], XEXP (operands[1], 0));
-         XEXP (operands[1], 0) = operands[0];
+         HOST_WIDE_INT i0, i1;
+
+         if (GET_CODE (operands[1]) == CONST_INT)
+           {
+             i0 = INTVAL (operands[1]);
+             i1 = -(i0 < 0);
+           }
+         else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+           {
+#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], i0, i1);
+          if (rtx_equal_p (tem, operands[0]))
+           DONE;
+          else
+           operands[1] = tem;
        }
       else
-       operands[1] = validize_mem (operands[1]);
+       {
+         operands[1] = force_const_mem (DImode, operands[1]);
+         if (reload_in_progress)
+           {
+             emit_move_insn (operands[0], XEXP (operands[1], 0));
+             operands[1] = copy_rtx (operands[1]);
+             XEXP (operands[1], 0) = operands[0];
+           }
+         else
+           operands[1] = validize_mem (operands[1]);
+       }
     }
   else
     abort ();
   [(set (match_dup 0) (match_dup 2))
    (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
   "
-{ if (alpha_emit_set_const (operands[0], INTVAL (operands[1]), 2))
+{ rtx tem
+    = alpha_emit_set_const (operands[0], DImode, INTVAL (operands[1]), 2);
+
+  if (tem == operands[0])
     DONE;
   else
     FAIL;
   ""
   "")
   
-;; Similar for unaligned loads.  For QImode, we use the sequence from the
-;; Alpha Architecture manual.  However, for HImode, we do not.  HImode pointers
-;; are normally aligned to the byte boundary, so an HImode object cannot
-;; cross a longword boundary.  We could use a sequence similar to that for
-;; QImode, but that would fail if the pointer, was, in fact, not aligned.
-;; Instead, we clear bit 1 in the address and do an ldl.  If the low-order
-;; bit was not aligned, this will trap and the trap handler will do what is
-;; needed.
+;; Similar for unaligned loads, where we use the sequence from the
+;; Alpha Architecture manual.
 ;;
-;; Here operand 1 is the address.  Operands 2 and 3 are temporaries, where
+;; Operand 1 is the address.  Operands 2 and 3 are temporaries, where
 ;; operand 3 can overlap the input and output registers.
 
 (define_expand "unaligned_loadqi"
   ""
   "")
 
-;; For this, the address must already be in a register.  We also need two
-;; DImode temporaries, neither of which may overlap the input (and hence the
-;; output, since they might be the same register), but both of which may
-;; be the same.
-
 (define_expand "unaligned_loadhi"
   [(set (match_operand:DI 2 "register_operand" "")
-       (and:DI (match_operand:DI 1 "register_operand" "")
-               (const_int -7)))
+       (mem:DI (and:DI (match_operand:DI 1 "address_operand" "")
+                       (const_int -8))))
    (set (match_operand:DI 3 "register_operand" "")
-       (mem:DI (match_dup 2)))
-   (set (match_operand:DI 4 "register_operand" "")
-       (and:DI (match_dup 1) (const_int -2)))
-   (set (subreg:DI (match_operand:HI 0 "register_operand" "") 0)
-       (zero_extract:DI (match_dup 3)
+       (match_dup 1))
+   (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0)
+       (zero_extract:DI (match_dup 2)
                         (const_int 16)
-                        (ashift:DI (match_dup 4) (const_int 3))))]
+                        (ashift:DI (match_dup 3) (const_int 3))))]
   ""
   "")
-       
+
 ;; Storing an aligned byte or word requires two temporaries.  Operand 0 is the
 ;; aligned SImode MEM.  Operand 1 is the register containing the 
 ;; byte or word to store.  Operand 2 is the number of bits within the word that
                            << INTVAL (operands[2])));
 }")
 
-;; For the unaligned byte case, we use code similar to that in the
-;; Architecture book, but reordered to lower the number of registers
+;; For the unaligned byte and halfword cases, we use code similar to that
+;; in the ;; Architecture book, but reordered to lower the number of registers
 ;; required.  Operand 0 is the address.  Operand 1 is the data to store.
 ;; Operands 2, 3, and 4 are DImode temporaries, where operands 2 and 4 may
 ;; be the same temporary, if desired.  If the address is in a register,
   ""
   "")
 
-;; This is the code for storing into an unaligned short.  It uses the same
-;; trick as loading from an unaligned short.  It needs lots of temporaries.
-;; However, during reload, we only have two registers available.  So we
-;; repeat code so that only two temporaries are available.  During RTL
-;; generation, we can use different pseudos for each temporary and CSE
-;; will remove the redundancies.  During reload, we have to settle with
-;; what we get.  Luckily, unaligned accesses of this kind produced during
-;; reload are quite rare.
-;;
-;; Operand 0 is the address of the memory location.  Operand 1 contains the
-;; data to store.  The rest of the operands are all temporaries, with
-;; various overlap possibilities during reload.  See reload_outhi for
-;; details of this use.
-
 (define_expand "unaligned_storehi"
-  [(set (match_operand:DI 2 "register_operand" "")
-       (match_operand:DI 0 "address_operand" ""))
-   (set (match_operand:DI 3 "register_operand" "")
-       (and:DI (match_dup 2) (const_int -7)))
-   (set (match_operand:DI 4 "register_operand" "")
-       (mem:DI (match_dup 3)))
-   (set (match_operand:DI 10 "register_operand" "")
-       (and:DI (match_dup 2) (const_int -2)))
-   (set (match_operand:DI 5 "register_operand" "")
+  [(set (match_operand:DI 3 "register_operand" "")
+       (mem:DI (and:DI (match_operand:DI 0 "address_operand" "")
+                       (const_int -8))))
+   (set (match_operand:DI 2 "register_operand" "")
+       (match_dup 0))
+   (set (match_dup 3)
        (and:DI (not:DI (ashift:DI (const_int 65535)
-                                  (ashift:DI (match_dup 10) (const_int 3))))
-               (match_dup 4)))
-   (set (match_operand:DI 6 "register_operand" "")
+                                  (ashift:DI (match_dup 2) (const_int 3))))
+               (match_dup 3)))
+   (set (match_operand:DI 4 "register_operand" "")
        (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" ""))
-                  (ashift:DI (match_dup 10) (const_int 3))))
-   (set (match_operand:DI 7 "register_operand" "")
-       (ior:DI (match_dup 5) (match_dup 6)))
-   (set (match_operand:DI 8 "register_operand" "") (match_dup 0))
-   (set (match_operand:DI 9 "register_operand" "")
-       (and:DI (match_dup 8) (const_int -7)))
-   (set (mem:DI (match_dup 9)) (match_dup 7))]
+                  (ashift:DI (match_dup 2) (const_int 3))))
+   (set (match_dup 4) (ior:DI (match_dup 4) (match_dup 3)))
+   (set (mem:DI (and:DI (match_dup 0) (const_int -8)))
+       (match_dup 4))]
   ""
   "")
 \f
        (match_operand:QI 1 "general_operand" ""))]
   ""
   "
-{ extern rtx get_unaligned_address ();
+{
+  if (TARGET_BWX)
+    {
+      if (GET_CODE (operands[0]) == MEM
+         && ! reg_or_0_operand (operands[1], QImode))
+       operands[1] = force_reg (QImode, operands[1]);
+
+      if (GET_CODE (operands[1]) == CONST_INT
+              && ! input_operand (operands[1], QImode))
+       {
+         operands[1] = alpha_emit_set_const (operands[0], QImode,
+                                             INTVAL (operands[1]), 3);
+
+         if (rtx_equal_p (operands[0], operands[1]))
+           DONE;
+       }
+
+      goto def;
+    }
 
   /* If the output is not a register, the input must be.  */
   if (GET_CODE (operands[0]) == MEM)
        {
          rtx aligned_mem, bitnum;
          rtx scratch = (reload_in_progress
-                        ? gen_rtx (REG, SImode, REGNO (operands[0]))
+                        ? gen_rtx_REG (SImode, REGNO (operands[0]))
                         : gen_reg_rtx (SImode));
 
          get_aligned_mem (operands[1], &aligned_mem, &bitnum);
 
          rtx temp1 = gen_reg_rtx (DImode);
          rtx temp2 = gen_reg_rtx (DImode);
-         rtx seq = gen_unaligned_loadqi (operands[0],
-                                         get_unaligned_address (operands[1]),
-                                         temp1, temp2);
+         rtx seq
+           = gen_unaligned_loadqi (operands[0],
+                                   get_unaligned_address (operands[1], 0),
+                                   temp1, temp2);
 
          alpha_set_memflags (seq, operands[1]);
          emit_insn (seq);
          rtx temp1 = gen_reg_rtx (DImode);
          rtx temp2 = gen_reg_rtx (DImode);
          rtx temp3 = gen_reg_rtx (DImode);
-         rtx seq = gen_unaligned_storeqi (get_unaligned_address (operands[0]),
+         rtx seq
+           = gen_unaligned_storeqi (get_unaligned_address (operands[0], 0),
                                           operands[1], temp1, temp2, temp3);
 
          alpha_set_memflags (seq, operands[0]);
        }
       DONE;
     }
+ def:;
 }")
 
 (define_expand "movhi"
        (match_operand:HI 1 "general_operand" ""))]
   ""
   "
-{ extern rtx get_unaligned_address ();
+{
+  if (TARGET_BWX)
+    {
+      if (GET_CODE (operands[0]) == MEM
+         && ! reg_or_0_operand (operands[1], HImode))
+       operands[1] = force_reg (HImode, operands[1]);
+
+      if (GET_CODE (operands[1]) == CONST_INT
+              && ! input_operand (operands[1], HImode))
+       {
+         operands[1] = alpha_emit_set_const (operands[0], HImode,
+                                             INTVAL (operands[1]), 3);
+
+         if (rtx_equal_p (operands[0], operands[1]))
+           DONE;
+       }
+
+      goto def;
+    }
 
   /* If the output is not a register, the input must be.  */
   if (GET_CODE (operands[0]) == MEM)
        {
          rtx aligned_mem, bitnum;
          rtx scratch = (reload_in_progress
-                        ? gen_rtx (REG, SImode, REGNO (operands[0]))
+                        ? gen_rtx_REG (SImode, REGNO (operands[0]))
                         : gen_reg_rtx (SImode));
 
          get_aligned_mem (operands[1], &aligned_mem, &bitnum);
        }
       else
        {
-         rtx addr
-           = force_reg (DImode,
-                        force_operand (get_unaligned_address (operands[1]),
-                                       NULL_RTX));
-         rtx scratch1 = gen_reg_rtx (DImode);
-         rtx scratch2 = gen_reg_rtx (DImode);
-         rtx scratch3 = gen_reg_rtx (DImode);
+         /* Don't pass these as parameters since that makes the generated
+            code depend on parameter evaluation order which will cause
+            bootstrap failures.  */
 
-         rtx seq = gen_unaligned_loadhi (operands[0], addr, scratch1,
-                                         scratch2, scratch3);
+         rtx temp1 = gen_reg_rtx (DImode);
+         rtx temp2 = gen_reg_rtx (DImode);
+         rtx seq
+           = gen_unaligned_loadhi (operands[0],
+                                   get_unaligned_address (operands[1], 0),
+                                   temp1, temp2);
 
          alpha_set_memflags (seq, operands[1]);
          emit_insn (seq);
          rtx temp1 = gen_reg_rtx (DImode);
          rtx temp2 = gen_reg_rtx (DImode);
          rtx temp3 = gen_reg_rtx (DImode);
-         rtx temp4 = gen_reg_rtx (DImode);
-         rtx temp5 = gen_reg_rtx (DImode);
-         rtx temp6 = gen_reg_rtx (DImode);
-         rtx temp7 = gen_reg_rtx (DImode);
-         rtx temp8 = gen_reg_rtx (DImode);
-         rtx temp9 = gen_reg_rtx (DImode);
-
-         rtx seq = gen_unaligned_storehi (get_unaligned_address (operands[0]),
-                                          operands[1], temp1, temp2,temp3,
-                                          temp4, temp5, temp6,temp7,
-                                          temp8, temp9);
+         rtx seq
+           = gen_unaligned_storehi (get_unaligned_address (operands[0], 0),
+                                    operands[1], temp1, temp2, temp3);
 
          alpha_set_memflags (seq, operands[0]);
          emit_insn (seq);
 
       DONE;
     }
+ def:;
 }")
 
 ;; Here are the versions for reload.  Note that in the unaligned cases
   [(parallel [(match_operand:QI 0 "register_operand" "=r")
              (match_operand:QI 1 "unaligned_memory_operand" "m")
              (match_operand:TI 2 "register_operand" "=&r")])]
-  ""
+  "! TARGET_BWX"
   "
-{ extern rtx get_unaligned_address ();
-  rtx addr = get_unaligned_address (operands[1]);
+{
+  rtx addr = get_unaligned_address (operands[1], 0);
+
   /* It is possible that one of the registers we got for operands[2]
-     might co-incide with that of operands[0] (which is why we made
+     might coincide with that of operands[0] (which is why we made
      it TImode).  Pick the other one to use as our scratch.  */
-  rtx scratch = gen_rtx (REG, DImode,
-                        REGNO (operands[0]) == REGNO (operands[2]) 
-                        ? REGNO (operands[2]) + 1 : REGNO (operands[2]));
+  rtx scratch = gen_rtx_REG (DImode,
+                            REGNO (operands[0]) == REGNO (operands[2]) 
+                            ? REGNO (operands[2]) + 1 : REGNO (operands[2]));
+
   rtx seq = gen_unaligned_loadqi (operands[0], addr, scratch,
-                                 gen_rtx (REG, DImode, REGNO (operands[0])));
+                                 gen_rtx_REG (DImode, REGNO (operands[0])));
 
   alpha_set_memflags (seq, operands[1]);
   emit_insn (seq);
   [(parallel [(match_operand:HI 0 "register_operand" "=r")
              (match_operand:HI 1 "unaligned_memory_operand" "m")
              (match_operand:TI 2 "register_operand" "=&r")])]
-  ""
+  "! TARGET_BWX"
   "
-{ extern rtx get_unaligned_address ();
-  rtx addr = get_unaligned_address (operands[1]);
-  rtx scratch1 = gen_rtx (REG, DImode, REGNO (operands[2]));
-  rtx scratch2 = gen_rtx (REG, DImode, REGNO (operands[2]) + 1);
-  rtx seq;
+{
+  rtx addr = get_unaligned_address (operands[1], 0);
+
+  /* It is possible that one of the registers we got for operands[2]
+     might coincide with that of operands[0] (which is why we made
+     it TImode).  Pick the other one to use as our scratch.  */
+  rtx scratch = gen_rtx_REG (DImode,
+                            REGNO (operands[0]) == REGNO (operands[2]) 
+                            ? REGNO (operands[2]) + 1 : REGNO (operands[2]));
+
+  rtx seq = gen_unaligned_loadhi (operands[0], addr, scratch,
+                                 gen_rtx_REG (DImode, REGNO (operands[0])));
 
-  if (GET_CODE (addr) != REG)
-    {
-      emit_insn (gen_rtx (SET, VOIDmode, scratch2, addr));
-      addr = scratch2;
-    }
-      
-  seq = gen_unaligned_loadhi (operands[0], addr, scratch1, scratch1, scratch2);
   alpha_set_memflags (seq, operands[1]);
   emit_insn (seq);
   DONE;
   [(parallel [(match_operand:QI 0 "any_memory_operand" "=m")
              (match_operand:QI 1 "register_operand" "r")
              (match_operand:TI 2 "register_operand" "=&r")])]
-  ""
+  "! TARGET_BWX"
   "
-{ extern rtx get_unaligned_address ();
-
+{
   if (aligned_memory_operand (operands[0], QImode))
     {
       rtx aligned_mem, bitnum;
       get_aligned_mem (operands[0], &aligned_mem, &bitnum);
 
       emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
-                                   gen_rtx (REG, SImode, REGNO (operands[2])),
-                                   gen_rtx (REG, SImode,
-                                            REGNO (operands[2]) + 1)));
+                                   gen_rtx_REG (SImode, REGNO (operands[2])),
+                                   gen_rtx_REG (SImode,
+                                                REGNO (operands[2]) + 1)));
     }
   else
     {
-      rtx addr = get_unaligned_address (operands[0]);
-      rtx scratch1 = gen_rtx (REG, DImode, REGNO (operands[2]));
-      rtx scratch2 = gen_rtx (REG, DImode, REGNO (operands[2]) + 1);
+      rtx addr = get_unaligned_address (operands[0], 0);
+      rtx scratch1 = gen_rtx_REG (DImode, REGNO (operands[2]));
+      rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
       rtx scratch3 = scratch1;
       rtx seq;
 
   [(parallel [(match_operand:HI 0 "any_memory_operand" "=m")
              (match_operand:HI 1 "register_operand" "r")
              (match_operand:TI 2 "register_operand" "=&r")])]
-  ""
+  "! TARGET_BWX"
   "
-{ extern rtx get_unaligned_address ();
-
+{
   if (aligned_memory_operand (operands[0], HImode))
     {
       rtx aligned_mem, bitnum;
       get_aligned_mem (operands[0], &aligned_mem, &bitnum);
 
       emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
-                                   gen_rtx (REG, SImode, REGNO (operands[2])),
-                                   gen_rtx (REG, SImode,
-                                            REGNO (operands[2]) + 1)));
+                                   gen_rtx_REG (SImode, REGNO (operands[2])),
+                                   gen_rtx_REG (SImode,
+                                                REGNO (operands[2]) + 1)));
     }
   else
     {
-      rtx addr = get_unaligned_address (operands[0]);
-      rtx scratch1 = gen_rtx (REG, DImode, REGNO (operands[2]));
-      rtx scratch2 = gen_rtx (REG, DImode, REGNO (operands[2]) + 1);
-      rtx scratch_a = GET_CODE (addr) == REG ? addr : scratch1;
+      rtx addr = get_unaligned_address (operands[0], 0);
+      rtx scratch1 = gen_rtx_REG (DImode, REGNO (operands[2]));
+      rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
+      rtx scratch3 = scratch1;
       rtx seq;
 
-      seq = gen_unaligned_storehi (addr, operands[1], scratch_a,
-                                  scratch2, scratch2, scratch2,
-                                  scratch1, scratch2, scratch_a,
-                                  scratch1, scratch_a);
+      if (GET_CODE (addr) == REG)
+       scratch1 = addr;
+
+      seq = gen_unaligned_storehi (addr, operands[1], scratch1,
+                                  scratch2, scratch3);
       alpha_set_memflags (seq, operands[0]);
       emit_insn (seq);
     }
   DONE;
 }")
 \f
+;; Bit field extract patterns which use ext[wlq][lh]
+
+(define_expand "extv"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (sign_extract:DI (match_operand:QI 1 "memory_operand" "")
+                        (match_operand:DI 2 "immediate_operand" "")
+                        (match_operand:DI 3 "immediate_operand" "")))]
+  ""
+  "
+{
+  /* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries.  */
+  if (INTVAL (operands[3]) % 8 != 0
+      || (INTVAL (operands[2]) != 16
+         && INTVAL (operands[2]) != 32
+         && INTVAL (operands[2]) != 64))
+    FAIL;
+
+  /* From mips.md: extract_bit_field doesn't verify that our source
+     matches the predicate, so we force it to be a MEM here.  */
+  if (GET_CODE (operands[1]) != MEM)
+    FAIL;
+
+  alpha_expand_unaligned_load (operands[0], operands[1],
+                              INTVAL (operands[2]) / 8,
+                              INTVAL (operands[3]) / 8, 1);
+  DONE;
+}")
+
+(define_expand "extzv"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (zero_extract:DI (match_operand:DI 1 "general_operand" "")
+                        (match_operand:DI 2 "immediate_operand" "")
+                        (match_operand:DI 3 "immediate_operand" "")))]
+  ""
+  "
+{
+  /* We can do 8, 16, 32 and 64 bit fields, if aligned on byte boundaries.  */
+  if (INTVAL (operands[3]) % 8 != 0
+      || (INTVAL (operands[2]) != 8
+         && INTVAL (operands[2]) != 16
+         && INTVAL (operands[2]) != 32
+         && INTVAL (operands[2]) != 64))
+    FAIL;
+
+  if (GET_CODE (operands[1]) == MEM)
+    {
+      /* Fail 8 bit fields, falling back on a simple byte load.  */
+      if (INTVAL (operands[2]) == 8)
+       FAIL;
+
+      alpha_expand_unaligned_load (operands[0], operands[1],
+                                  INTVAL (operands[2]) / 8,
+                                  INTVAL (operands[3]) / 8, 0);
+      DONE;
+    }
+}")
+
+(define_expand "insv"
+  [(set (zero_extract:DI (match_operand:QI 0 "memory_operand" "")
+                        (match_operand:DI 1 "immediate_operand" "")
+                        (match_operand:DI 2 "immediate_operand" ""))
+       (match_operand:DI 3 "register_operand" ""))]
+  ""
+  "
+{
+  /* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries.  */
+  if (INTVAL (operands[2]) % 8 != 0
+      || (INTVAL (operands[1]) != 16
+         && INTVAL (operands[1]) != 32
+         && INTVAL (operands[1]) != 64))
+    FAIL;
+
+  /* From mips.md: store_bit_field doesn't verify that our source
+     matches the predicate, so we force it to be a MEM here.  */
+  if (GET_CODE (operands[0]) != MEM)
+    FAIL;
+
+  alpha_expand_unaligned_store (operands[0], operands[3],
+                               INTVAL (operands[1]) / 8,
+                               INTVAL (operands[2]) / 8);
+  DONE;
+}")
+
+
+
+;; Block move/clear, see alpha.c for more details.
+;; Argument 0 is the destination
+;; Argument 1 is the source
+;; Argument 2 is the length
+;; Argument 3 is the alignment
+
+(define_expand "movstrqi"
+  [(parallel [(set (match_operand:BLK 0 "general_operand" "")
+                  (match_operand:BLK 1 "general_operand" ""))
+             (use (match_operand:DI 2 "immediate_operand" ""))
+             (use (match_operand:DI 3 "immediate_operand" ""))])]
+  ""
+  "
+{
+  if (alpha_expand_block_move (operands))
+    DONE;
+  else
+    FAIL;
+}")
+
+(define_expand "clrstrqi"
+  [(parallel [(set (match_operand:BLK 0 "general_operand" "")
+                  (const_int 0))
+             (use (match_operand:DI 1 "immediate_operand" ""))
+             (use (match_operand:DI 2 "immediate_operand" ""))])]
+  ""
+  "
+{
+  if (alpha_expand_block_clear (operands))
+    DONE;
+  else
+    FAIL;
+}")
+\f
 ;; Subroutine of stack space allocation.  Perform a stack probe.
 (define_expand "probe_stack"
   [(set (match_dup 1) (match_operand:DI 0 "const_int_operand" ""))]
   ""
   "
 {
-  operands[0] = gen_rtx (MEM, DImode, plus_constant (stack_pointer_rtx,
-                                                    INTVAL (operands[0])));
-  MEM_VOLATILE_P (operands[0]) = 1;
+  operands[1] = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx,
+                                                   INTVAL (operands[0])));
+  MEM_VOLATILE_P (operands[1]) = 1;
 
-  operands[1] = gen_reg_rtx (DImode);
+  operands[0] = const0_rtx;
 }")
 
 ;; This is how we allocate stack space.  If we are allocating a
 (define_expand "allocate_stack"
   [(set (reg:DI 30)
        (plus:DI (reg:DI 30)
-                (match_operand:DI 0 "reg_or_cint_operand" "")))]
+                (match_operand:DI 1 "reg_or_cint_operand" "")))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (match_dup 2))]
   ""
   "
 {
-  if (GET_CODE (operands[0]) == CONST_INT
-          && INTVAL (operands[0]) < 32768)
+  if (GET_CODE (operands[1]) == CONST_INT
+      && INTVAL (operands[1]) < 32768)
     {
-      if (INTVAL (operands[0]) >= 4096)
+      if (INTVAL (operands[1]) >= 4096)
        {
          /* We do this the same way as in the prologue and generate explicit
             probes.  Then we update the stack by the constant.  */
          int probed = 4096;
 
          emit_insn (gen_probe_stack (GEN_INT (- probed)));
-         while (probed + 8192 < INTVAL (operands[0]))
+         while (probed + 8192 < INTVAL (operands[1]))
            emit_insn (gen_probe_stack (GEN_INT (- (probed += 8192))));
 
-         if (probed + 4096 < INTVAL (operands[0]))
-           emit_insn (gen_probe_stack (GEN_INT (- (probed += 4096))));
+         if (probed + 4096 < INTVAL (operands[1]))
+           emit_insn (gen_probe_stack (GEN_INT (- INTVAL(operands[1]))));
        }
 
-      operands[0] = GEN_INT (- INTVAL (operands[0]));
+      operands[1] = GEN_INT (- INTVAL (operands[1]));
+      operands[2] = virtual_stack_dynamic_rtx;
     }
   else
     {
       rtx out_label = 0;
       rtx loop_label = gen_label_rtx ();
-      rtx count = gen_reg_rtx (DImode);
-      rtx access = gen_reg_rtx (Pmode);
-      rtx memref = gen_rtx (MEM, DImode, access);
-
-      MEM_VOLATILE_P (memref) = 1;
+      rtx want = gen_reg_rtx (Pmode);
+      rtx tmp = gen_reg_rtx (Pmode);
+      rtx memref;
 
-      /* If the amount to be allocated is not a constant, we only need to
-        do something special if it is >= 4096.  */
+      emit_insn (gen_subdi3 (want, stack_pointer_rtx,
+                            force_reg (Pmode, operands[1])));
+      emit_insn (gen_adddi3 (tmp, stack_pointer_rtx, GEN_INT (-4096)));
 
-      if (GET_CODE (operands[0]) != CONST_INT)
+      if (GET_CODE (operands[1]) != CONST_INT)
        {
-         operands[0] = force_reg (DImode, operands[0]);
          out_label = gen_label_rtx ();
-         emit_insn (gen_cmpdi (operands[0],
-                               force_reg (DImode, GEN_INT (4096))));
-         emit_jump_insn (gen_ble (out_label));
-
-         /* Compute COUNT = (N + 4096) / 8192.  N is known positive.  */
-         emit_insn (gen_adddi3 (count, operands[0], GEN_INT (4096)));
-         emit_insn (gen_lshrdi3 (count, count, GEN_INT (13)));
+         emit_insn (gen_cmpdi (want, tmp));
+         emit_jump_insn (gen_bgeu (out_label));
        }
-      else
-       emit_move_insn (count, GEN_INT ((INTVAL (operands[0]) + 4096) >> 13));
 
-      /* ACCESS = SP + 4096.  */
-      emit_insn (gen_adddi3 (access, stack_pointer_rtx, GEN_INT (4096)));
       emit_label (loop_label);
-
-      /* Each iteration subtracts 8192 from ACCESS and references it.  */
-      emit_insn (gen_adddi3 (count, count, constm1_rtx));
-      emit_insn (gen_adddi3 (access, access, GEN_INT (-8192)));
-      emit_move_insn (gen_reg_rtx (DImode), memref);
-      emit_insn (gen_cmpdi (count, const0_rtx));
-      emit_jump_insn (gen_bgt (loop_label));
+      memref = gen_rtx_MEM (DImode, tmp);
+      MEM_VOLATILE_P (memref) = 1;
+      emit_move_insn (memref, const0_rtx);
+      emit_insn (gen_adddi3 (tmp, tmp, GEN_INT(-8192)));
+      emit_insn (gen_cmpdi (tmp, want));
+      emit_jump_insn (gen_bgtu (loop_label));
+      if (obey_regdecls)
+       gen_rtx_USE (VOIDmode, tmp);
+
+      memref = gen_rtx_MEM (DImode, want);
+      MEM_VOLATILE_P (memref) = 1;
+      emit_move_insn (memref, const0_rtx);
 
       if (out_label)
        emit_label (out_label);
 
-      /* We need to subtract operands[0] from SP.  We know it isn't a
-        constant less than 32768, so we know we have to load it into
-        a register.  */
+      emit_move_insn (stack_pointer_rtx, want);
+      emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
+      DONE;
+    }
+}")
 
-      emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
-                            force_reg (Pmode, operands[0])));
+;; 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.
 
-      /* Now, unless we have a constant and we know that we are within
-        4096 from the end, we need to access sp + 4096.  */
-      if (! (GET_CODE (operands[0]) == CONST_INT
-            && (INTVAL (operands[0]) % 8192) < 4096))
-       emit_insn (gen_probe_stack (GEN_INT (4096)));
+(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")])
 
-      DONE;
+(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"
+  "
+{
+  /* The elements of the buffer are, in order:  */
+  rtx fp = gen_rtx_MEM (Pmode, operands[0]);
+  rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 8));
+  rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 16));
+  rtx pv = gen_rtx_REG (Pmode, 27);
+
+  /* This bit is the same as expand_builtin_longjmp.  */
+  emit_move_insn (hard_frame_pointer_rtx, fp);
+  emit_move_insn (pv, lab);
+  emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
+  emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
+  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+
+  /* Load the label we are jumping through into $27 so that we know
+     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)"
+  [(set_attr "length" "8")
+   (set_attr "type" "multi")])
+
+(define_insn ""
+  [(unspec_volatile [(match_operand 0 "" "")] 2)]
+  "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
+  "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)
+   (set (reg:DI 27) (mem:DI (reg:DI 29)))
+   (unspec_volatile [(const_int 0)] 1)
+   (use (reg:DI 27))]
+  "TARGET_OPEN_VMS"
+  "")
+
+(define_insn "arg_home"
+  [(unspec [(const_int 0)] 0)
+   (use (reg:DI 1))
+   (use (reg:DI 25))
+   (use (reg:DI 16))
+   (use (reg:DI 17))
+   (use (reg:DI 18))
+   (use (reg:DI 19))
+   (use (reg:DI 20))
+   (use (reg:DI 21))
+   (use (reg:DI 48))
+   (use (reg:DI 49))
+   (use (reg:DI 50))
+   (use (reg:DI 51))
+   (use (reg:DI 52))
+   (use (reg:DI 53))
+   (clobber (mem:BLK (const_int 0)))
+   (clobber (reg:DI 24))
+   (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"
+  [(set_attr "length" "16")
+   (set_attr "type" "multi")])
+
+;; Close the trap shadow of preceeding instructions.  This is generated
+;; by alpha_reorg.
+
+(define_insn "trapb"
+  [(unspec_volatile [(const_int 0)] 4)]
+  ""
+  "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")