aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/config/ia64/ia64.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/config/ia64/ia64.md')
-rw-r--r--gcc-4.9/gcc/config/ia64/ia64.md5242
1 files changed, 5242 insertions, 0 deletions
diff --git a/gcc-4.9/gcc/config/ia64/ia64.md b/gcc-4.9/gcc/config/ia64/ia64.md
new file mode 100644
index 000000000..5fedc9214
--- /dev/null
+++ b/gcc-4.9/gcc/config/ia64/ia64.md
@@ -0,0 +1,5242 @@
+;; IA-64 Machine description template
+;; Copyright (C) 1999-2014 Free Software Foundation, Inc.
+;; Contributed by James E. Wilson <wilson@cygnus.com> and
+;; David Mosberger <davidm@hpl.hp.com>.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+;; ??? register_operand accepts (subreg:DI (mem:SI X)) which forces later
+;; reload. This will be fixed once scheduling support is turned on.
+
+;; ??? Optimize for post-increment addressing modes.
+
+;; ??? fselect is not supported, because there is no integer register
+;; equivalent.
+
+;; ??? fp abs/min/max instructions may also work for integer values.
+
+;; ??? Would a predicate_reg_operand predicate be useful? The HP one is buggy,
+;; it assumes the operand is a register and takes REGNO of it without checking.
+
+;; ??? Would a branch_reg_operand predicate be useful? The HP one is buggy,
+;; it assumes the operand is a register and takes REGNO of it without checking.
+
+;; ??? Go through list of documented named patterns and look for more to
+;; implement.
+
+;; ??? Go through instruction manual and look for more instructions that
+;; can be emitted.
+
+;; ??? Add function unit scheduling info for Itanium (TM) processor.
+
+;; ??? Need a better way to describe alternate fp status registers.
+
+(define_c_enum "unspec"
+ [; Relocations
+ UNSPEC_LTOFF_DTPMOD
+ UNSPEC_LTOFF_DTPREL
+ UNSPEC_DTPREL
+ UNSPEC_LTOFF_TPREL
+ UNSPEC_TPREL
+ UNSPEC_DTPMOD
+
+ UNSPEC_LD_BASE
+ UNSPEC_GR_SPILL
+ UNSPEC_GR_RESTORE
+ UNSPEC_FR_SPILL
+ UNSPEC_FR_RESTORE
+ UNSPEC_FR_RECIP_APPROX
+ UNSPEC_PRED_REL_MUTEX
+ UNSPEC_GETF_EXP
+ UNSPEC_PIC_CALL
+ UNSPEC_MF
+ UNSPEC_CMPXCHG_ACQ
+ UNSPEC_CMPXCHG_REL
+ UNSPEC_FETCHADD_ACQ
+ UNSPEC_FETCHADD_REL
+ UNSPEC_BSP_VALUE
+ UNSPEC_FLUSHRS
+ UNSPEC_BUNDLE_SELECTOR
+ UNSPEC_ADDP4
+ UNSPEC_PROLOGUE_USE
+ UNSPEC_RET_ADDR
+ UNSPEC_SETF_EXP
+ UNSPEC_FR_SQRT_RECIP_APPROX
+ UNSPEC_SHRP
+ UNSPEC_COPYSIGN
+ UNSPEC_VECT_EXTR
+ UNSPEC_LDA
+ UNSPEC_LDS
+ UNSPEC_LDS_A
+ UNSPEC_LDSA
+ UNSPEC_LDCCLR
+ UNSPEC_LDCNC
+ UNSPEC_CHKACLR
+ UNSPEC_CHKANC
+ UNSPEC_CHKS
+ UNSPEC_FR_RECIP_APPROX_RES
+ UNSPEC_FR_SQRT_RECIP_APPROX_RES
+ ])
+
+(define_c_enum "unspecv" [
+ UNSPECV_ALLOC
+ UNSPECV_BLOCKAGE
+ UNSPECV_INSN_GROUP_BARRIER
+ UNSPECV_BREAK
+ UNSPECV_SET_BSP
+ UNSPECV_PSAC_ALL ; pred.safe_across_calls
+ UNSPECV_PSAC_NORMAL
+ UNSPECV_SETJMP_RECEIVER
+ UNSPECV_GOTO_RECEIVER
+ UNSPECV_PROBE_STACK_ADDRESS
+ UNSPECV_PROBE_STACK_RANGE
+ ])
+
+(include "predicates.md")
+(include "constraints.md")
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Attributes
+;; ::
+;; ::::::::::::::::::::
+
+;; Processor type. This attribute must exactly match the processor_type
+;; enumeration in ia64.h.
+(define_attr "cpu" "itanium,itanium2"
+ (const (symbol_ref "((enum attr_cpu) ia64_tune)")))
+
+;; Instruction type. This primarily determines how instructions can be
+;; packed in bundles, and secondarily affects scheduling to function units.
+
+;; A alu, can go in I or M syllable of a bundle
+;; I integer
+;; M memory
+;; F floating-point
+;; B branch
+;; L long immediate, takes two syllables
+;; S stop bit
+
+;; ??? Should not have any pattern with type unknown. Perhaps add code to
+;; check this in md_reorg? Currently use unknown for patterns which emit
+;; multiple instructions, patterns which emit 0 instructions, and patterns
+;; which emit instruction that can go in any slot (e.g. nop).
+
+(define_attr "itanium_class" "unknown,ignore,stop_bit,br,fcmp,fcvtfx,fld,
+ fldp,fmac,fmisc,frar_i,frar_m,frbr,frfr,frpr,ialu,icmp,ilog,ishf,
+ ld,chk_s_i,chk_s_f,chk_a,long_i,mmalua,mmmul,mmshf,mmshfi,rse_m,scall,sem,stf,
+ st,syst_m0, syst_m,tbit,toar_i,toar_m,tobr,tofr,topr,xmpy,xtd,nop,
+ nop_b,nop_f,nop_i,nop_m,nop_x,lfetch,pre_cycle"
+ (const_string "unknown"))
+
+;; chk_s_i has an I and an M form; use type A for convenience.
+(define_attr "type" "unknown,A,I,M,F,B,L,X,S"
+ (cond [(eq_attr "itanium_class" "ld,st,fld,fldp,stf,sem,nop_m") (const_string "M")
+ (eq_attr "itanium_class" "rse_m,syst_m,syst_m0") (const_string "M")
+ (eq_attr "itanium_class" "frar_m,toar_m,frfr,tofr") (const_string "M")
+ (eq_attr "itanium_class" "lfetch") (const_string "M")
+ (eq_attr "itanium_class" "chk_s_f,chk_a") (const_string "M")
+ (eq_attr "itanium_class" "chk_s_i,ialu,icmp,ilog,mmalua")
+ (const_string "A")
+ (eq_attr "itanium_class" "fmisc,fmac,fcmp,xmpy") (const_string "F")
+ (eq_attr "itanium_class" "fcvtfx,nop_f") (const_string "F")
+ (eq_attr "itanium_class" "frar_i,toar_i,frbr,tobr") (const_string "I")
+ (eq_attr "itanium_class" "frpr,topr,ishf,xtd,tbit") (const_string "I")
+ (eq_attr "itanium_class" "mmmul,mmshf,mmshfi,nop_i") (const_string "I")
+ (eq_attr "itanium_class" "br,scall,nop_b") (const_string "B")
+ (eq_attr "itanium_class" "stop_bit") (const_string "S")
+ (eq_attr "itanium_class" "nop_x") (const_string "X")
+ (eq_attr "itanium_class" "long_i") (const_string "L")]
+ (const_string "unknown")))
+
+(define_attr "itanium_requires_unit0" "no,yes"
+ (cond [(eq_attr "itanium_class" "syst_m0,sem,frfr,rse_m") (const_string "yes")
+ (eq_attr "itanium_class" "toar_m,frar_m") (const_string "yes")
+ (eq_attr "itanium_class" "frbr,tobr,mmmul") (const_string "yes")
+ (eq_attr "itanium_class" "tbit,ishf,topr,frpr") (const_string "yes")
+ (eq_attr "itanium_class" "toar_i,frar_i") (const_string "yes")
+ (eq_attr "itanium_class" "fmisc,fcmp") (const_string "yes")]
+ (const_string "no")))
+
+;; Predication. True iff this instruction can be predicated.
+
+(define_attr "predicable" "no,yes" (const_string "yes"))
+
+;; Empty. True iff this insn does not generate any code.
+
+(define_attr "empty" "no,yes" (const_string "no"))
+
+;; True iff this insn must be the first insn of an instruction group.
+;; This is true for the alloc instruction, and will also be true of others
+;; when we have full intrinsics support.
+
+(define_attr "first_insn" "no,yes" (const_string "no"))
+
+(define_attr "data_speculative" "no,yes" (const_string "no"))
+
+(define_attr "control_speculative" "no,yes" (const_string "no"))
+
+(define_attr "check_load" "no,yes" (const_string "no"))
+
+(define_attr "speculable1" "no,yes" (const_string "no"))
+
+(define_attr "speculable2" "no,yes" (const_string "no"))
+
+;; DFA descriptions of ia64 processors used for insn scheduling and
+;; bundling.
+
+(automata_option "ndfa")
+
+;; Uncomment the following line to output automata for debugging.
+;; (automata_option "v")
+
+(automata_option "w")
+
+(include "itanium2.md")
+
+;; Mode iterators
+
+; Used for truncations from XFmode.
+(define_mode_iterator MODE_SDF [SF DF])
+
+(define_mode_attr suffix [
+ (SF ".s")
+ (DF ".d")
+ (XF "")
+ ])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Moves
+;; ::
+;; ::::::::::::::::::::
+
+;; Set of a single predicate register. This is only used to implement
+;; pr-to-pr move and complement.
+
+(define_insn "movcci"
+ [(set (match_operand:CCI 0 "destination_operand" "=c,c,?c,?*r, c,*r,*m,*r")
+ (match_operand:CCI 1 "move_operand" " O,n, c, c,*r,*m,*r,*r"))]
+ ""
+ "@
+ cmp.ne %0, p0 = r0, r0
+ cmp.eq %0, p0 = r0, r0
+ (%1) cmp.eq.unc %0, p0 = r0, r0
+ #
+ tbit.nz %0, p0 = %1, 0
+ ld1%O1 %0 = %1%P1
+ st1%Q0 %0 = %1%P0
+ mov %0 = %1"
+ [(set_attr "itanium_class" "icmp,icmp,icmp,unknown,tbit,ld,st,ialu")
+ (set_attr "predicable" "no")])
+
+(define_split
+ [(set (match_operand:CCI 0 "register_operand" "")
+ (match_operand:CCI 1 "register_operand" ""))]
+ "reload_completed
+ && GET_CODE (operands[0]) == REG && GR_REGNO_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == REG && PR_REGNO_P (REGNO (operands[1]))"
+ [(set (match_dup 2) (const_int 0))
+ (cond_exec (ne (match_dup 3) (const_int 0))
+ (set (match_dup 2) (const_int 1)))]
+ "operands[2] = gen_rtx_REG (BImode, REGNO (operands[0]));
+ operands[3] = gen_rtx_REG (BImode, REGNO (operands[1]));")
+
+(define_insn "movbi"
+ [(set (match_operand:BI 0 "destination_operand" "=c,c,?c,?*r, c,*r,*r,*m,*r")
+ (match_operand:BI 1 "move_operand" " O,n, c, c,*r, n,*m,*r,*r"))]
+ ""
+ "@
+ cmp.ne %0, %I0 = r0, r0
+ cmp.eq %0, %I0 = r0, r0
+ #
+ #
+ tbit.nz %0, %I0 = %1, 0
+ adds %0 = %1, r0
+ ld1%O1 %0 = %1%P1
+ st1%Q0 %0 = %1%P0
+ mov %0 = %1"
+ [(set_attr "itanium_class" "icmp,icmp,unknown,unknown,tbit,ialu,ld,st,ialu")
+ (set_attr "speculable1" "yes")
+ (set_attr "speculable2" "no, no, no, no, no, no, yes,no,no")])
+
+(define_split
+ [(set (match_operand:BI 0 "register_operand" "")
+ (match_operand:BI 1 "register_operand" ""))]
+ "reload_completed
+ && GET_CODE (operands[0]) == REG && GR_REGNO_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == REG && PR_REGNO_P (REGNO (operands[1]))"
+ [(cond_exec (ne (match_dup 1) (const_int 0))
+ (set (match_dup 0) (const_int 1)))
+ (cond_exec (eq (match_dup 1) (const_int 0))
+ (set (match_dup 0) (const_int 0)))]
+ "")
+
+(define_split
+ [(set (match_operand:BI 0 "register_operand" "")
+ (match_operand:BI 1 "register_operand" ""))]
+ "reload_completed
+ && GET_CODE (operands[0]) == REG && PR_REGNO_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == REG && PR_REGNO_P (REGNO (operands[1]))"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))
+ (set (match_dup 0) (unspec:BI [(match_dup 0)] UNSPEC_PRED_REL_MUTEX))]
+ "operands[2] = gen_rtx_REG (CCImode, REGNO (operands[0]));
+ operands[3] = gen_rtx_REG (CCImode, REGNO (operands[0]) + 1);
+ operands[4] = gen_rtx_REG (CCImode, REGNO (operands[1]));
+ operands[5] = gen_rtx_REG (CCImode, REGNO (operands[1]) + 1);")
+
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+{
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+(define_insn "movqi_internal"
+ [(set (match_operand:QI 0 "destination_operand" "=r,r,r, m, r,*f,*f")
+ (match_operand:QI 1 "move_operand" "rO,J,m,rO,*f,rO,*f"))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "@
+ mov %0 = %r1
+ addl %0 = %1, r0
+ ld1%O1 %0 = %1%P1
+ st1%Q0 %0 = %r1%P0
+ getf.sig %0 = %1
+ setf.sig %0 = %r1
+ mov %0 = %1"
+ [(set_attr "itanium_class" "ialu,ialu,ld,st,frfr,tofr,fmisc")
+ (set_attr "speculable1" "yes")
+ (set_attr "speculable2" "no, no, yes,no,no, no, no")])
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "general_operand" "")
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+{
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+(define_insn "movhi_internal"
+ [(set (match_operand:HI 0 "destination_operand" "=r,r,r, m, r,*f,*f")
+ (match_operand:HI 1 "move_operand" "rO,J,m,rO,*f,rO,*f"))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "@
+ mov %0 = %r1
+ addl %0 = %1, r0
+ ld2%O1 %0 = %1%P1
+ st2%Q0 %0 = %r1%P0
+ getf.sig %0 = %1
+ setf.sig %0 = %r1
+ mov %0 = %1"
+ [(set_attr "itanium_class" "ialu,ialu,ld,st,frfr,tofr,fmisc")
+ (set_attr "speculable1" "yes")
+ (set_attr "speculable2" "no, no, yes,no,no, no, no")])
+
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" ""))]
+ ""
+{
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+(define_insn "movsi_internal"
+ [(set (match_operand:SI 0 "destination_operand" "=r,r,r,r,r, m, r,*f,*f, r,*d")
+ (match_operand:SI 1 "move_operand" "rO,J,j,i,m,rO,*f,rO,*f,*d,rK"))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "@
+ mov %0 = %r1
+ addl %0 = %1, r0
+ addp4 %0 = %1 - 0x100000000, r0
+ movl %0 = %1
+ ld4%O1 %0 = %1%P1
+ st4%Q0 %0 = %r1%P0
+ getf.sig %0 = %1
+ setf.sig %0 = %r1
+ mov %0 = %1
+ mov %0 = %1
+ mov %0 = %r1"
+ ;; frar_m, toar_m ??? why not frar_i and toar_i
+ [(set_attr "itanium_class" "ialu,ialu,ialu,long_i,ld,st,frfr,tofr,fmisc,frar_m,toar_m")
+ (set_attr "speculable1" "yes")
+ (set_attr "speculable2" "no, no, no, no, yes,no,no, no, no, no, no")])
+
+(define_expand "movdi"
+ [(set (match_operand:DI 0 "general_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
+ ""
+{
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+(define_insn "movdi_internal"
+ [(set (match_operand:DI 0 "destination_operand"
+ "=r,r,r,r,r, m, r,*f,*f,*f, Q, r,*b, r,*e, r,*d, r,*c")
+ (match_operand:DI 1 "move_operand"
+ "rO,JT,j,i,m,rO,*f,rO,*f, Q,*f,*b,rO,*e,rK,*d,rK,*c,rO"))]
+ "ia64_move_ok (operands[0], operands[1])"
+{
+ static const char * const alt[] = {
+ "%,mov %0 = %r1",
+ "%,addl %0 = %1, r0",
+ "%,addp4 %0 = %1 - 0x100000000, r0",
+ "%,movl %0 = %1",
+ "%,ld8%O1 %0 = %1%P1",
+ "%,st8%Q0 %0 = %r1%P0",
+ "%,getf.sig %0 = %1",
+ "%,setf.sig %0 = %r1",
+ "%,mov %0 = %1",
+ "%,ldf8 %0 = %1%P1",
+ "%,stf8 %0 = %1%P0",
+ "%,mov %0 = %1",
+ "%,mov %0 = %r1",
+ "%,mov %0 = %1",
+ "%,mov %0 = %1",
+ "%,mov %0 = %1",
+ "%,mov %0 = %1",
+ "mov %0 = pr",
+ "mov pr = %1, -1"
+ };
+
+ gcc_assert (which_alternative != 2 || TARGET_NO_PIC
+ || !symbolic_operand (operands[1], VOIDmode));
+
+ return alt[which_alternative];
+}
+ [(set_attr "itanium_class" "ialu,ialu,ialu,long_i,ld,st,frfr,tofr,fmisc,fld,stf,frbr,tobr,frar_i,toar_i,frar_m,toar_m,frpr,topr")
+ (set_attr "speculable1" "yes")
+ (set_attr "speculable2" "no, no, no, no, yes,no,no, no, no, yes,no, no, no, no, no, no, no, no, no")])
+
+(define_mode_iterator MODE [BI QI HI SI DI SF DF XF TI])
+(define_mode_iterator MODE_FOR_CMP [BI SI DI SF DF XF (TF "TARGET_HPUX")])
+(define_mode_iterator MODE_FOR_EXTEND [QI HI SI])
+
+(define_mode_attr output_a [
+ (BI "ld1.a %0 = %1%P1")
+ (QI "ld1.a %0 = %1%P1")
+ (HI "ld2.a %0 = %1%P1")
+ (SI "ld4.a %0 = %1%P1")
+ (DI
+ "@
+ ld8.a %0 = %1%P1
+ ldf8.a %0 = %1%P1")
+ (SF
+ "@
+ ldfs.a %0 = %1%P1
+ ld4.a %0 = %1%P1")
+ (DF
+ "@
+ ldfd.a %0 = %1%P1
+ ld8.a %0 = %1%P1")
+ (XF "ldfe.a %0 = %1%P1")
+ (TI "ldfp8.a %X0 = %1%P1")])
+
+(define_mode_attr output_s [
+ (BI "ld1.s %0 = %1%P1")
+ (QI "ld1.s %0 = %1%P1")
+ (HI "ld2.s %0 = %1%P1")
+ (SI "ld4.s %0 = %1%P1")
+ (DI
+ "@
+ ld8.s %0 = %1%P1
+ ldf8.s %0 = %1%P1")
+ (SF
+ "@
+ ldfs.s %0 = %1%P1
+ ld4.s %0 = %1%P1")
+ (DF
+ "@
+ ldfd.s %0 = %1%P1
+ ld8.s %0 = %1%P1")
+ (XF "ldfe.s %0 = %1%P1")
+ (TI "ldfp8.s %X0 = %1%P1")])
+
+(define_mode_attr output_sa [
+ (BI "ld1.sa %0 = %1%P1")
+ (QI "ld1.sa %0 = %1%P1")
+ (HI "ld2.sa %0 = %1%P1")
+ (SI "ld4.sa %0 = %1%P1")
+ (DI
+ "@
+ ld8.sa %0 = %1%P1
+ ldf8.sa %0 = %1%P1")
+ (SF
+ "@
+ ldfs.sa %0 = %1%P1
+ ld4.sa %0 = %1%P1")
+ (DF
+ "@
+ ldfd.sa %0 = %1%P1
+ ld8.sa %0 = %1%P1")
+ (XF "ldfe.sa %0 = %1%P1")
+ (TI "ldfp8.sa %X0 = %1%P1")])
+
+(define_mode_attr output_c_clr [
+ (BI "ld1.c.clr%O1 %0 = %1%P1")
+ (QI "ld1.c.clr%O1 %0 = %1%P1")
+ (HI "ld2.c.clr%O1 %0 = %1%P1")
+ (SI "ld4.c.clr%O1 %0 = %1%P1")
+ (DI
+ "@
+ ld8.c.clr%O1 %0 = %1%P1
+ ldf8.c.clr %0 = %1%P1")
+ (SF
+ "@
+ ldfs.c.clr %0 = %1%P1
+ ld4.c.clr%O1 %0 = %1%P1")
+ (DF
+ "@
+ ldfd.c.clr %0 = %1%P1
+ ld8.c.clr%O1 %0 = %1%P1")
+ (XF "ldfe.c.clr %0 = %1%P1")
+ (TI "ldfp8.c.clr %X0 = %1%P1")])
+
+(define_mode_attr output_c_nc [
+ (BI "ld1.c.nc%O1 %0 = %1%P1")
+ (QI "ld1.c.nc%O1 %0 = %1%P1")
+ (HI "ld2.c.nc%O1 %0 = %1%P1")
+ (SI "ld4.c.nc%O1 %0 = %1%P1")
+ (DI
+ "@
+ ld8.c.nc%O1 %0 = %1%P1
+ ldf8.c.nc %0 = %1%P1")
+ (SF
+ "@
+ ldfs.c.nc %0 = %1%P1
+ ld4.c.nc%O1 %0 = %1%P1")
+ (DF
+ "@
+ ldfd.c.nc %0 = %1%P1
+ ld8.c.nc%O1 %0 = %1%P1")
+ (XF "ldfe.c.nc %0 = %1%P1")
+ (TI "ldfp8.c.nc %X0 = %1%P1")])
+
+(define_mode_attr ld_reg_constr [(BI "=*r") (QI "=r") (HI "=r") (SI "=r") (DI "=r,*f") (SF "=f,*r") (DF "=f,*r") (XF "=f") (TI "=*x")])
+(define_mode_attr ldc_reg_constr [(BI "+*r") (QI "+r") (HI "+r") (SI "+r") (DI "+r,*f") (SF "+f,*r") (DF "+f,*r") (XF "+f") (TI "+*x")])
+(define_mode_attr chk_reg_constr [(BI "*r") (QI "r") (HI "r") (SI "r") (DI "r,*f") (SF "f,*r") (DF "f,*r") (XF "f") (TI "*x")])
+
+(define_mode_attr mem_constr [(BI "*m") (QI "m") (HI "m") (SI "m") (DI "m,Q") (SF "Q,m") (DF "Q,m") (XF "m") (TI "Q")])
+
+;; Define register predicate prefix.
+;; We can generate speculative loads only for general and fp registers - this
+;; is constrained in ia64.c: ia64_speculate_insn ().
+(define_mode_attr reg_pred_prefix [(BI "gr") (QI "gr") (HI "gr") (SI "gr") (DI "grfr") (SF "grfr") (DF "grfr") (XF "fr") (TI "fr")])
+
+(define_mode_attr ld_class [(BI "ld") (QI "ld") (HI "ld") (SI "ld") (DI "ld,fld") (SF "fld,ld") (DF "fld,ld") (XF "fld") (TI "fldp")])
+(define_mode_attr chka_class [(BI "chk_a") (QI "chk_a") (HI "chk_a") (SI "chk_a") (DI "chk_a,chk_a") (SF "chk_a,chk_a") (DF "chk_a,chk_a") (XF "chk_a") (TI "chk_a")])
+(define_mode_attr chks_class [(BI "chk_s_i") (QI "chk_s_i") (HI "chk_s_i") (SI "chk_s_i") (DI "chk_s_i,chk_s_f") (SF "chk_s_f,chk_s_i") (DF "chk_s_f,chk_s_i") (XF "chk_s_f") (TI "chk_s_i")])
+
+(define_mode_attr attr_yes [(BI "yes") (QI "yes") (HI "yes") (SI "yes") (DI "yes,yes") (SF "yes,yes") (DF "yes,yes") (XF "yes") (TI "yes")])
+
+(define_insn "mov<mode>_advanced"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ld_reg_constr>")
+ (unspec:MODE [(match_operand:MODE 1 "memory_operand" "<mem_constr>")] UNSPEC_LDA))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_a>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_advanced"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extend:DI (unspec:MODE_FOR_EXTEND [(match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>")] UNSPEC_LDA)))]
+ ""
+ "<output_a>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")])
+
+(define_insn "mov<mode>_speculative"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ld_reg_constr>")
+ (unspec:MODE [(match_operand:MODE 1 "memory_operand" "<mem_constr>")] UNSPEC_LDS))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_s>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_speculative"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extend:DI (unspec:MODE_FOR_EXTEND [(match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>")] UNSPEC_LDS)))]
+ ""
+ "<output_s>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "mov<mode>_speculative_advanced"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ld_reg_constr>")
+ (unspec:MODE [(match_operand:MODE 1 "memory_operand" "<mem_constr>")] UNSPEC_LDSA))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_sa>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "mov<mode>_speculative_a"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ld_reg_constr>")
+ (unspec:MODE [(match_operand:MODE 1 "memory_operand" "<mem_constr>")] UNSPEC_LDS_A))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_sa>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_speculative_advanced"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extend:DI (unspec:MODE_FOR_EXTEND [(match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>")] UNSPEC_LDSA)))]
+ ""
+ "<output_sa>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_speculative_a"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extend:DI (unspec:MODE_FOR_EXTEND [(match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>")] UNSPEC_LDS_A)))]
+ ""
+ "<output_sa>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "mov<mode>_clr"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ldc_reg_constr>")
+ (if_then_else:MODE (ne (unspec [(match_dup 0)] UNSPEC_LDCCLR) (const_int 0))
+ (match_operand:MODE 1 "memory_operand" "<mem_constr>")
+ (match_dup 0)))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_c_clr>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "check_load" "<attr_yes>")])
+
+(define_insn "mov<mode>_nc"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ldc_reg_constr>")
+ (if_then_else:MODE (ne (unspec [(match_dup 0)] UNSPEC_LDCNC) (const_int 0))
+ (match_operand:MODE 1 "memory_operand" "<mem_constr>")
+ (match_dup 0)))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_c_nc>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "check_load" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_clr"
+ [(set (match_operand:DI 0 "gr_register_operand" "+r")
+ (if_then_else:DI (ne (unspec [(match_dup 0)] UNSPEC_LDCCLR) (const_int 0))
+ (zero_extend:DI (match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>"))
+ (match_dup 0)))]
+ ""
+ "<output_c_clr>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "check_load" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_nc"
+ [(set (match_operand:DI 0 "gr_register_operand" "+r")
+ (if_then_else:DI (ne (unspec [(match_dup 0)] UNSPEC_LDCNC) (const_int 0))
+ (zero_extend:DI (match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>"))
+ (match_dup 0)))]
+ ""
+ "<output_c_nc>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "check_load" "<attr_yes>")])
+
+(define_insn "advanced_load_check_clr_<mode>"
+ [(set (pc)
+ (if_then_else (ne (unspec [(match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<chk_reg_constr>")] UNSPEC_CHKACLR) (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "chk.a.clr %0, %l1"
+ [(set_attr "itanium_class" "<chka_class>")])
+
+(define_insn "advanced_load_check_nc_<mode>"
+ [(set (pc)
+ (if_then_else (ne (unspec [(match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<chk_reg_constr>")] UNSPEC_CHKANC) (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "chk.a.clr %0, %l1"
+ [(set_attr "itanium_class" "<chka_class>")])
+
+(define_insn "speculation_check_<mode>"
+ [(set (pc)
+ (if_then_else (ne (unspec [(match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<chk_reg_constr>")] UNSPEC_CHKS) (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "chk.s %0, %l1"
+ [(set_attr "itanium_class" "<chks_class>")])
+
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (match_operand 1 "symbolic_operand" ""))]
+ "reload_completed"
+ [(const_int 0)]
+{
+ if (ia64_expand_load_address (operands[0], operands[1]))
+ DONE;
+ else
+ FAIL;
+})
+
+(define_expand "load_fptr"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_dup 2) (match_operand 1 "function_operand" "")))
+ (set (match_dup 0) (match_dup 3))]
+ "reload_completed"
+{
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = gen_const_mem (DImode, operands[0]);
+})
+
+(define_insn "*load_fptr_internal1"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (reg:DI 1) (match_operand 1 "function_operand" "s")))]
+ "reload_completed"
+ "addl %0 = @ltoff(@fptr(%1)), gp"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "load_gprel"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (reg:DI 1) (match_operand 1 "sdata_symbolic_operand" "s")))]
+ "reload_completed"
+ "addl %0 = @gprel(%1), gp"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*gprel64_offset"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (minus:DI (match_operand:DI 1 "symbolic_operand" "") (reg:DI 1)))]
+ "reload_completed"
+ "movl %0 = @gprel(%1)"
+ [(set_attr "itanium_class" "long_i")])
+
+(define_expand "load_gprel64"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (minus:DI (match_operand:DI 1 "symbolic_operand" "") (match_dup 2)))
+ (set (match_dup 0)
+ (plus:DI (match_dup 2) (match_dup 0)))]
+ "reload_completed"
+{
+ operands[2] = pic_offset_table_rtx;
+})
+
+;; This is used as a placeholder for the return address during early
+;; compilation. We won't know where we've placed this until during
+;; reload, at which point it can wind up in b0, a general register,
+;; or memory. The only safe destination under these conditions is a
+;; general register.
+
+(define_insn_and_split "*movdi_ret_addr"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(const_int 0)] UNSPEC_RET_ADDR))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_split_return_addr_rtx (operands[0]);
+ DONE;
+}
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*load_symptr_high"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (high:DI (match_operand 1 "got_symbolic_operand" "s"))
+ (match_operand:DI 2 "register_operand" "a")))]
+ "reload_completed"
+{
+ if (HAVE_AS_LTOFFX_LDXMOV_RELOCS)
+ return "%,addl %0 = @ltoffx(%1), %2";
+ else
+ return "%,addl %0 = @ltoff(%1), %2";
+}
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*load_symptr_low"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (mem:DI (match_operand:DI 1 "register_operand" "r"))
+ (match_operand 2 "got_symbolic_operand" "s")))]
+ "reload_completed"
+{
+ if (HAVE_AS_LTOFFX_LDXMOV_RELOCS)
+ return "%,ld8.mov %0 = [%1], %2";
+ else
+ return "%,ld8 %0 = [%1]";
+}
+ [(set_attr "itanium_class" "ld")])
+
+(define_insn_and_split "load_dtpmod"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_DTPMOD))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (plus:DI (unspec:DI [(match_dup 1)] UNSPEC_LTOFF_DTPMOD)
+ (match_dup 2)))
+ (set (match_dup 0) (match_dup 3))]
+{
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = gen_const_mem (DImode, operands[0]);
+})
+
+(define_insn "*load_ltoff_dtpmod"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_LTOFF_DTPMOD)
+ (match_operand:DI 2 "register_operand" "a")))]
+ "reload_completed"
+ "addl %0 = @ltoff(@dtpmod(%1)), %2"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "load_dtprel"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_DTPREL))]
+ ""
+ "")
+
+(define_insn "*load_dtprel64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
+ UNSPEC_DTPREL))]
+ "TARGET_TLS64"
+ "movl %0 = @dtprel(%1)"
+ [(set_attr "itanium_class" "long_i")])
+
+(define_insn "*load_dtprel22"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
+ UNSPEC_DTPREL))]
+ ""
+ "addl %0 = @dtprel(%1), r0"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn_and_split "*load_dtprel_gd"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_DTPREL))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (plus:DI (unspec:DI [(match_dup 1)] UNSPEC_LTOFF_DTPREL)
+ (match_dup 2)))
+ (set (match_dup 0) (match_dup 3))]
+{
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = gen_const_mem (DImode, operands[0]);
+})
+
+(define_insn "*load_ltoff_dtprel"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_LTOFF_DTPREL)
+ (match_operand:DI 2 "register_operand" "a")))]
+ ""
+ "addl %0 = @ltoff(@dtprel(%1)), %2"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "add_dtprel"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
+ UNSPEC_DTPREL)
+ (match_operand:DI 2 "register_operand" "")))]
+ "!TARGET_TLS64"
+ "")
+
+(define_insn "*add_dtprel14"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
+ UNSPEC_DTPREL)
+ (match_operand:DI 2 "register_operand" "r")))]
+ "TARGET_TLS14"
+ "adds %0 = @dtprel(%1), %2"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*add_dtprel22"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
+ UNSPEC_DTPREL)
+ (match_operand:DI 2 "register_operand" "a")))]
+ "TARGET_TLS22"
+ "addl %0 = @dtprel(%1), %2"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "load_tprel"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_TPREL))]
+ ""
+ "")
+
+(define_insn "*load_tprel64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
+ UNSPEC_TPREL))]
+ "TARGET_TLS64"
+ "movl %0 = @tprel(%1)"
+ [(set_attr "itanium_class" "long_i")])
+
+(define_insn "*load_tprel22"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
+ UNSPEC_TPREL))]
+ ""
+ "addl %0 = @tprel(%1), r0"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn_and_split "*load_tprel_ie"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand 1 "ie_tls_symbolic_operand" "")]
+ UNSPEC_TPREL))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (plus:DI (unspec:DI [(match_dup 1)] UNSPEC_LTOFF_TPREL)
+ (match_dup 2)))
+ (set (match_dup 0) (match_dup 3))]
+{
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = gen_const_mem (DImode, operands[0]);
+})
+
+(define_insn "*load_ltoff_tprel"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (unspec:DI [(match_operand 1 "ie_tls_symbolic_operand" "")]
+ UNSPEC_LTOFF_TPREL)
+ (match_operand:DI 2 "register_operand" "a")))]
+ ""
+ "addl %0 = @ltoff(@tprel(%1)), %2"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "add_tprel"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
+ UNSPEC_TPREL)
+ (match_operand:DI 2 "register_operand" "")))]
+ "!TARGET_TLS64"
+ "")
+
+(define_insn "*add_tprel14"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
+ UNSPEC_TPREL)
+ (match_operand:DI 2 "register_operand" "r")))]
+ "TARGET_TLS14"
+ "adds %0 = @tprel(%1), %2"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*add_tprel22"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
+ UNSPEC_TPREL)
+ (match_operand:DI 2 "register_operand" "a")))]
+ "TARGET_TLS22"
+ "addl %0 = @tprel(%1), %2"
+ [(set_attr "itanium_class" "ialu")])
+
+;; With no offsettable memory references, we've got to have a scratch
+;; around to play with the second word. However, in order to avoid a
+;; reload nightmare we lie, claim we don't need one, and fix it up
+;; in ia64_split_tmode_move.
+(define_expand "movti"
+ [(set (match_operand:TI 0 "general_operand" "")
+ (match_operand:TI 1 "general_operand" ""))]
+ ""
+{
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+(define_insn_and_split "movti_internal"
+ [(set (match_operand:TI 0 "destination_operand" "=r, *fm,*x,*f, Q")
+ (match_operand:TI 1 "general_operand" "r*fim,r, Q, *fOQ,*f"))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "@
+ #
+ #
+ ldfp8 %X0 = %1%P1
+ #
+ #"
+ "reload_completed && !ia64_load_pair_ok(operands[0], operands[1])"
+ [(const_int 0)]
+{
+ ia64_split_tmode_move (operands);
+ DONE;
+}
+ [(set_attr "itanium_class" "unknown,unknown,fldp,unknown,unknown")
+ (set_attr "speculable1" "yes")
+ (set_attr "speculable2" "no, no, yes, no, no")])
+
+;; Floating Point Moves
+;;
+;; Note - Patterns for SF mode moves are compulsory, but
+;; patterns for DF are optional, as GCC can synthesize them.
+
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (match_operand:SF 1 "general_operand" ""))]
+ ""
+{
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+(define_insn "movsf_internal"
+ [(set (match_operand:SF 0 "destination_operand" "=f,f, Q,*r, f,*r,*r, m,*r")
+ (match_operand:SF 1 "general_operand" "fG,Q,fG,fG,*r,*r, m,*r, F"))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "@
+ mov %0 = %F1
+ ldfs %0 = %1%P1
+ stfs %0 = %F1%P0
+ getf.s %0 = %F1
+ setf.s %0 = %1
+ mov %0 = %1
+ ld4%O1 %0 = %1%P1
+ st4%Q0 %0 = %1%P0
+ movl %0 = %G1"
+ [(set_attr "itanium_class" "fmisc,fld,stf,frfr,tofr,ialu,ld,st,long_i")
+ (set_attr "speculable1" "yes")
+ (set_attr "speculable2" "no, yes,no, no, no, no, yes,no,no")])
+
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ ""
+{
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+(define_insn "movdf_internal"
+ [(set (match_operand:DF 0 "destination_operand" "=f,f, Q,*r, f,*r,*r, m,*r")
+ (match_operand:DF 1 "general_operand" "fG,Q,fG,fG,*r,*r, m,*r, F"))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "@
+ mov %0 = %F1
+ ldfd %0 = %1%P1
+ stfd %0 = %F1%P0
+ getf.d %0 = %F1
+ setf.d %0 = %1
+ mov %0 = %1
+ ld8%O1 %0 = %1%P1
+ st8%Q0 %0 = %1%P0
+ movl %0 = %G1"
+ [(set_attr "itanium_class" "fmisc,fld,stf,frfr,tofr,ialu,ld,st,long_i")
+ (set_attr "speculable1" "yes")
+ (set_attr "speculable2" "no, yes,no, no, no, no, yes,no,no")])
+
+;; With no offsettable memory references, we've got to have a scratch
+;; around to play with the second word if the variable winds up in GRs.
+(define_expand "movxf"
+ [(set (match_operand:XF 0 "general_operand" "")
+ (match_operand:XF 1 "general_operand" ""))]
+ ""
+{
+ if (ia64_expand_movxf_movrf (XFmode, operands))
+ DONE;
+})
+
+;; ??? There's no easy way to mind volatile acquire/release semantics.
+
+(define_insn "movxf_internal"
+ [(set (match_operand:XF 0 "destination_operand" "=f,f, m")
+ (match_operand:XF 1 "general_operand" "fG,m,fG"))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "@
+ mov %0 = %F1
+ ldfe %0 = %1%P1
+ stfe %0 = %F1%P0"
+ [(set_attr "itanium_class" "fmisc,fld,stf")
+ (set_attr "speculable1" "yes")
+ (set_attr "speculable2" "no, yes,no")])
+
+;; Same as for movxf, but for RFmode.
+(define_expand "movrf"
+ [(set (match_operand:RF 0 "general_operand" "")
+ (match_operand:RF 1 "general_operand" ""))]
+ ""
+{
+ if (ia64_expand_movxf_movrf (RFmode, operands))
+ DONE;
+})
+
+(define_insn "*movrf_internal"
+ [(set (match_operand:RF 0 "destination_operand" "=f,f, m")
+ (match_operand:RF 1 "general_operand" "fG,m,fG"))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "@
+ mov %0 = %F1
+ ldf.fill %0 = %1%P1
+ stf.spill %0 = %F1%P0"
+ [(set_attr "itanium_class" "fmisc,fld,stf")])
+
+;; Better code generation via insns that deal with TFmode register pairs
+;; directly. Same concerns apply as for TImode.
+(define_expand "movtf"
+ [(set (match_operand:TF 0 "general_operand" "")
+ (match_operand:TF 1 "general_operand" ""))]
+ ""
+{
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+(define_insn_and_split "*movtf_internal"
+ [(set (match_operand:TF 0 "destination_operand" "=r,r,m")
+ (match_operand:TF 1 "general_operand" "ri,m,r"))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_split_tmode_move (operands);
+ DONE;
+}
+ [(set_attr "itanium_class" "unknown")
+ (set_attr "predicable" "no")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Conversions
+;; ::
+;; ::::::::::::::::::::
+
+;; Signed conversions from a smaller integer to a larger integer
+
+(define_insn "extendqidi2"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (sign_extend:DI (match_operand:QI 1 "gr_register_operand" "r")))]
+ ""
+ "sxt1 %0 = %1"
+ [(set_attr "itanium_class" "xtd")])
+
+(define_insn "extendhidi2"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (sign_extend:DI (match_operand:HI 1 "gr_register_operand" "r")))]
+ ""
+ "sxt2 %0 = %1"
+ [(set_attr "itanium_class" "xtd")])
+
+(define_insn "extendsidi2"
+ [(set (match_operand:DI 0 "grfr_register_operand" "=r,?f")
+ (sign_extend:DI (match_operand:SI 1 "grfr_register_operand" "r,f")))]
+ ""
+ "@
+ sxt4 %0 = %1
+ fsxt.r %0 = %1, %1"
+ [(set_attr "itanium_class" "xtd,fmisc")])
+
+;; Unsigned conversions from a smaller integer to a larger integer
+
+(define_insn "zero_extendqidi2"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r,r")
+ (zero_extend:DI (match_operand:QI 1 "gr_nonimmediate_operand" "r,m")))]
+ ""
+ "@
+ zxt1 %0 = %1
+ ld1%O1 %0 = %1%P1"
+ [(set_attr "itanium_class" "xtd,ld")
+ (set_attr "speculable1" "yes")
+ (set_attr "speculable2" "no, yes")])
+
+(define_insn "zero_extendhidi2"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r,r")
+ (zero_extend:DI (match_operand:HI 1 "gr_nonimmediate_operand" "r,m")))]
+ ""
+ "@
+ zxt2 %0 = %1
+ ld2%O1 %0 = %1%P1"
+ [(set_attr "itanium_class" "xtd,ld")
+ (set_attr "speculable1" "yes")
+ (set_attr "speculable2" "no, yes")])
+
+(define_insn "zero_extendsidi2"
+ [(set (match_operand:DI 0 "grfr_register_operand" "=r,r,?f")
+ (zero_extend:DI
+ (match_operand:SI 1 "grfr_nonimmediate_operand" "r,m,f")))]
+ ""
+ "@
+ addp4 %0 = %1, r0
+ ld4%O1 %0 = %1%P1
+ fmix.r %0 = f0, %1"
+ [(set_attr "itanium_class" "ialu,ld,fmisc")
+ (set_attr "speculable1" "yes")
+ (set_attr "speculable2" "no, yes,no")])
+
+;; Convert between floating point types of different sizes.
+
+;; At first glance, it would appear that emitting fnorm for an extending
+;; conversion is unnecessary. However, the stf and getf instructions work
+;; correctly only if the input is properly rounded for its type. In
+;; particular, we get the wrong result for getf.d/stfd if the input is a
+;; denorm single. Since we don't know what the next instruction will be, we
+;; have to emit an fnorm.
+
+;; ??? Optimization opportunity here. Get rid of the insn altogether
+;; when we can. Should probably use a scheme like has been proposed
+;; for ia32 in dealing with operands that match unary operators. This
+;; would let combine merge the thing into adjacent insns. See also how the
+;; mips port handles SIGN_EXTEND as operands to integer arithmetic insns via
+;; se_register_operand.
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_extend:DF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fnorm.d %0 = %F1"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "extendsfxf2"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (float_extend:XF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fnorm %0 = %F1"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "extenddfxf2"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (float_extend:XF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fnorm %0 = %F1"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fnorm.s %0 = %F1"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "truncxfsf2"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fnorm.s %0 = %F1"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "truncxfdf2"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fnorm.d %0 = %F1"
+ [(set_attr "itanium_class" "fmac")])
+
+;; Convert between signed integer types and floating point.
+
+(define_insn "floatdirf2"
+ [(set (match_operand:RF 0 "fr_register_operand" "=f")
+ (float:RF (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.xf %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "floatdixf2"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (float:XF (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.xf %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "fix_truncsfdi2"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (fix:DI (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.fx.trunc %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "fix_truncdfdi2"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (fix:DI (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.fx.trunc %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "fix_truncxfdi2"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (fix:DI (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.fx.trunc %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "fix_truncrfdi2"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (fix:DI (match_operand:RF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.fx.trunc %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+;; Convert between unsigned integer types and floating point.
+
+(define_insn "floatunsdisf2"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (unsigned_float:SF (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.xuf.s %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "floatunsdidf2"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (unsigned_float:DF (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.xuf.d %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "floatunsdixf2"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (unsigned_float:XF (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.xuf %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "floatunsdirf2"
+ [(set (match_operand:RF 0 "fr_register_operand" "=f")
+ (unsigned_float:RF (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.xuf %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "fixuns_truncsfdi2"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (unsigned_fix:DI (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.fxu.trunc %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "fixuns_truncdfdi2"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (unsigned_fix:DI (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.fxu.trunc %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "fixuns_truncxfdi2"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (unsigned_fix:DI (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.fxu.trunc %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "fixuns_truncrfdi2"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (unsigned_fix:DI (match_operand:RF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.fxu.trunc %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Bit field extraction
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "extv"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (sign_extract:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "extr_len_operand" "n")
+ (match_operand:DI 3 "shift_count_operand" "M")))]
+ ""
+ "extr %0 = %1, %3, %2"
+ [(set_attr "itanium_class" "ishf")])
+
+(define_insn "extzv"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "extr_len_operand" "n")
+ (match_operand:DI 3 "shift_count_operand" "M")))]
+ ""
+ "extr.u %0 = %1, %3, %2"
+ [(set_attr "itanium_class" "ishf")])
+
+;; Insert a bit field.
+;; Can have 3 operands, source1 (inserter), source2 (insertee), dest.
+;; Source1 can be 0 or -1.
+;; Source2 can be 0.
+
+;; ??? Actual dep instruction is more powerful than what these insv
+;; patterns support. Unfortunately, combine is unable to create patterns
+;; where source2 != dest.
+
+(define_expand "insv"
+ [(set (zero_extract:DI (match_operand:DI 0 "gr_register_operand" "")
+ (match_operand:DI 1 "const_int_operand" "")
+ (match_operand:DI 2 "const_int_operand" ""))
+ (match_operand:DI 3 "nonmemory_operand" ""))]
+ ""
+{
+ int width = INTVAL (operands[1]);
+ int shift = INTVAL (operands[2]);
+
+ /* If operand[3] is a constant, and isn't 0 or -1, then load it into a
+ pseudo. */
+ if (! register_operand (operands[3], DImode)
+ && operands[3] != const0_rtx && operands[3] != constm1_rtx)
+ operands[3] = force_reg (DImode, operands[3]);
+
+ /* If this is a single dep instruction, we have nothing to do. */
+ if (! ((register_operand (operands[3], DImode) && width <= 16)
+ || operands[3] == const0_rtx || operands[3] == constm1_rtx))
+ {
+ /* Check for cases that can be implemented with a mix instruction. */
+ if (width == 32 && shift == 0)
+ {
+ /* Directly generating the mix4left instruction confuses
+ optimize_bit_field in function.c. Since this is performing
+ a useful optimization, we defer generation of the complicated
+ mix4left RTL to the first splitting phase. */
+ rtx tmp = gen_reg_rtx (DImode);
+ emit_insn (gen_shift_mix4left (operands[0], operands[3], tmp));
+ DONE;
+ }
+ else if (width == 32 && shift == 32)
+ {
+ emit_insn (gen_mix4right (operands[0], operands[3]));
+ DONE;
+ }
+
+ /* We could handle remaining cases by emitting multiple dep
+ instructions.
+
+ If we need more than two dep instructions then we lose. A 6
+ insn sequence mov mask1,mov mask2,shl;;and,and;;or is better than
+ mov;;dep,shr;;dep,shr;;dep. The former can be executed in 3 cycles,
+ the latter is 6 cycles on an Itanium (TM) processor, because there is
+ only one function unit that can execute dep and shr immed.
+
+ If we only need two dep instruction, then we still lose.
+ mov;;dep,shr;;dep is still 4 cycles. Even if we optimize away
+ the unnecessary mov, this is still undesirable because it will be
+ hard to optimize, and it creates unnecessary pressure on the I0
+ function unit. */
+
+ FAIL;
+
+#if 0
+ /* This code may be useful for other IA-64 processors, so we leave it in
+ for now. */
+ while (width > 16)
+ {
+ rtx tmp;
+
+ emit_insn (gen_insv (operands[0], GEN_INT (16), GEN_INT (shift),
+ operands[3]));
+ shift += 16;
+ width -= 16;
+ tmp = gen_reg_rtx (DImode);
+ emit_insn (gen_lshrdi3 (tmp, operands[3], GEN_INT (16)));
+ operands[3] = tmp;
+ }
+ operands[1] = GEN_INT (width);
+ operands[2] = GEN_INT (shift);
+#endif
+ }
+})
+
+(define_insn "*insv_internal"
+ [(set (zero_extract:DI (match_operand:DI 0 "gr_register_operand" "+r")
+ (match_operand:DI 1 "const_int_operand" "n")
+ (match_operand:DI 2 "const_int_operand" "n"))
+ (match_operand:DI 3 "nonmemory_operand" "rP"))]
+ "(gr_register_operand (operands[3], DImode) && INTVAL (operands[1]) <= 16)
+ || operands[3] == const0_rtx || operands[3] == constm1_rtx"
+ "dep %0 = %3, %0, %2, %1"
+ [(set_attr "itanium_class" "ishf")])
+
+;; Combine doesn't like to create bit-field insertions into zero.
+(define_insn "*shladdp4_internal"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (and:DI (ashift:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "shladd_log2_operand" "n"))
+ (match_operand:DI 3 "const_int_operand" "n")))]
+ "ia64_depz_field_mask (operands[3], operands[2]) + INTVAL (operands[2]) == 32"
+ "shladdp4 %0 = %1, %2, r0"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*depz_internal"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (and:DI (ashift:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "const_int_operand" "M"))
+ (match_operand:DI 3 "const_int_operand" "n")))]
+ "satisfies_constraint_M (operands[2])
+ && ia64_depz_field_mask (operands[3], operands[2]) > 0"
+{
+ operands[3] = GEN_INT (ia64_depz_field_mask (operands[3], operands[2]));
+ return "%,dep.z %0 = %1, %2, %3";
+}
+ [(set_attr "itanium_class" "ishf")])
+
+(define_insn "shift_mix4left"
+ [(set (zero_extract:DI (match_operand:DI 0 "gr_register_operand" "+r")
+ (const_int 32) (const_int 0))
+ (match_operand:DI 1 "gr_register_operand" "r"))
+ (clobber (match_operand:DI 2 "gr_register_operand" "=r"))]
+ ""
+ "#"
+ [(set_attr "itanium_class" "unknown")])
+
+(define_split
+ [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "")
+ (const_int 32) (const_int 0))
+ (match_operand:DI 1 "register_operand" ""))
+ (clobber (match_operand:DI 2 "register_operand" ""))]
+ ""
+ [(set (match_dup 3) (ashift:DI (match_dup 1) (const_int 32)))
+ (set (zero_extract:DI (match_dup 0) (const_int 32) (const_int 0))
+ (lshiftrt:DI (match_dup 3) (const_int 32)))]
+ "operands[3] = operands[2];")
+
+(define_insn "*mix4left"
+ [(set (zero_extract:DI (match_operand:DI 0 "gr_register_operand" "+r")
+ (const_int 32) (const_int 0))
+ (lshiftrt:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (const_int 32)))]
+ ""
+ "mix4.l %0 = %0, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "mix4right"
+ [(set (zero_extract:DI (match_operand:DI 0 "gr_register_operand" "+r")
+ (const_int 32) (const_int 32))
+ (match_operand:DI 1 "gr_reg_or_0_operand" "rO"))]
+ ""
+ "mix4.r %0 = %r1, %0"
+ [(set_attr "itanium_class" "mmshf")])
+
+;; This is used by the rotrsi3 pattern.
+
+(define_insn "*mix4right_3op"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (ior:DI (zero_extend:DI (match_operand:SI 1 "gr_register_operand" "r"))
+ (ashift:DI (zero_extend:DI
+ (match_operand:SI 2 "gr_register_operand" "r"))
+ (const_int 32))))]
+ ""
+ "mix4.r %0 = %2, %1"
+ [(set_attr "itanium_class" "mmshf")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 1-bit Integer arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn_and_split "andbi3"
+ [(set (match_operand:BI 0 "register_operand" "=c,c,r")
+ (and:BI (match_operand:BI 1 "register_operand" "%0,0,r")
+ (match_operand:BI 2 "register_operand" "c,r,r")))]
+ ""
+ "@
+ #
+ tbit.nz.and.orcm %0, %I0 = %2, 0
+ and %0 = %2, %1"
+ "reload_completed
+ && GET_CODE (operands[0]) == REG && PR_REGNO_P (REGNO (operands[0]))
+ && GET_CODE (operands[2]) == REG && PR_REGNO_P (REGNO (operands[2]))"
+ [(cond_exec (eq (match_dup 2) (const_int 0))
+ (set (match_dup 0) (and:BI (ne:BI (const_int 0) (const_int 0))
+ (match_dup 0))))]
+ ""
+ [(set_attr "itanium_class" "unknown,tbit,ilog")])
+
+(define_insn_and_split "*andcmbi3"
+ [(set (match_operand:BI 0 "register_operand" "=c,c,r")
+ (and:BI (not:BI (match_operand:BI 1 "register_operand" "c,r,r"))
+ (match_operand:BI 2 "register_operand" "0,0,r")))]
+ ""
+ "@
+ #
+ tbit.z.and.orcm %0, %I0 = %1, 0
+ andcm %0 = %2, %1"
+ "reload_completed
+ && GET_CODE (operands[0]) == REG && PR_REGNO_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == REG && PR_REGNO_P (REGNO (operands[1]))"
+ [(cond_exec (ne (match_dup 1) (const_int 0))
+ (set (match_dup 0) (and:BI (ne:BI (const_int 0) (const_int 0))
+ (match_dup 0))))]
+ ""
+ [(set_attr "itanium_class" "unknown,tbit,ilog")])
+
+(define_insn_and_split "iorbi3"
+ [(set (match_operand:BI 0 "register_operand" "=c,c,r")
+ (ior:BI (match_operand:BI 1 "register_operand" "%0,0,r")
+ (match_operand:BI 2 "register_operand" "c,r,r")))]
+ ""
+ "@
+ #
+ tbit.nz.or.andcm %0, %I0 = %2, 0
+ or %0 = %2, %1"
+ "reload_completed
+ && GET_CODE (operands[0]) == REG && PR_REGNO_P (REGNO (operands[0]))
+ && GET_CODE (operands[2]) == REG && PR_REGNO_P (REGNO (operands[2]))"
+ [(cond_exec (ne (match_dup 2) (const_int 0))
+ (set (match_dup 0) (ior:BI (eq:BI (const_int 0) (const_int 0))
+ (match_dup 0))))]
+ ""
+ [(set_attr "itanium_class" "unknown,tbit,ilog")])
+
+(define_insn_and_split "*iorcmbi3"
+ [(set (match_operand:BI 0 "register_operand" "=c,c")
+ (ior:BI (not:BI (match_operand:BI 1 "register_operand" "c,r"))
+ (match_operand:BI 2 "register_operand" "0,0")))]
+ ""
+ "@
+ #
+ tbit.z.or.andcm %0, %I0 = %1, 0"
+ "reload_completed
+ && GET_CODE (operands[0]) == REG && PR_REGNO_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == REG && PR_REGNO_P (REGNO (operands[1]))"
+ [(cond_exec (eq (match_dup 1) (const_int 0))
+ (set (match_dup 0) (ior:BI (eq:BI (const_int 0) (const_int 0))
+ (match_dup 0))))]
+ ""
+ [(set_attr "itanium_class" "unknown,tbit")])
+
+(define_insn "one_cmplbi2"
+ [(set (match_operand:BI 0 "register_operand" "=c,r,c,&c")
+ (not:BI (match_operand:BI 1 "register_operand" "r,r,0,c")))
+ (clobber (match_scratch:BI 2 "=X,X,c,X"))]
+ ""
+ "@
+ tbit.z %0, %I0 = %1, 0
+ xor %0 = 1, %1
+ #
+ #"
+ [(set_attr "itanium_class" "tbit,ilog,unknown,unknown")])
+
+(define_split
+ [(set (match_operand:BI 0 "register_operand" "")
+ (not:BI (match_operand:BI 1 "register_operand" "")))
+ (clobber (match_scratch:BI 2 ""))]
+ "reload_completed
+ && GET_CODE (operands[0]) == REG && PR_REGNO_P (REGNO (operands[0]))
+ && rtx_equal_p (operands[0], operands[1])"
+ [(set (match_dup 4) (match_dup 3))
+ (set (match_dup 0) (const_int 1))
+ (cond_exec (ne (match_dup 2) (const_int 0))
+ (set (match_dup 0) (const_int 0)))
+ (set (match_dup 0) (unspec:BI [(match_dup 0)] UNSPEC_PRED_REL_MUTEX))]
+ "operands[3] = gen_rtx_REG (CCImode, REGNO (operands[1]));
+ operands[4] = gen_rtx_REG (CCImode, REGNO (operands[2]));")
+
+(define_split
+ [(set (match_operand:BI 0 "register_operand" "")
+ (not:BI (match_operand:BI 1 "register_operand" "")))
+ (clobber (match_scratch:BI 2 ""))]
+ "reload_completed
+ && GET_CODE (operands[0]) == REG && PR_REGNO_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == REG && PR_REGNO_P (REGNO (operands[1]))
+ && ! rtx_equal_p (operands[0], operands[1])"
+ [(cond_exec (ne (match_dup 1) (const_int 0))
+ (set (match_dup 0) (const_int 0)))
+ (cond_exec (eq (match_dup 1) (const_int 0))
+ (set (match_dup 0) (const_int 1)))
+ (set (match_dup 0) (unspec:BI [(match_dup 0)] UNSPEC_PRED_REL_MUTEX))]
+ "")
+
+(define_insn "*cmpsi_and_0"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (and:BI (match_operator:BI 4 "predicate_operator"
+ [(match_operand:SI 2 "gr_reg_or_0_operand" "rO")
+ (match_operand:SI 3 "gr_reg_or_8bit_operand" "rK")])
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp4.%C4.and.orcm %0, %I0 = %3, %r2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpsi_and_1"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (and:BI (match_operator:BI 3 "signed_inequality_operator"
+ [(match_operand:SI 2 "gr_register_operand" "r")
+ (const_int 0)])
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp4.%C3.and.orcm %0, %I0 = r0, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpsi_andnot_0"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (and:BI (not:BI (match_operator:BI 4 "predicate_operator"
+ [(match_operand:SI 2 "gr_reg_or_0_operand" "rO")
+ (match_operand:SI 3 "gr_reg_or_8bit_operand" "rK")]))
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp4.%C4.or.andcm %I0, %0 = %3, %r2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpsi_andnot_1"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (and:BI (not:BI (match_operator:BI 3 "signed_inequality_operator"
+ [(match_operand:SI 2 "gr_register_operand" "r")
+ (const_int 0)]))
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp4.%C3.or.andcm %I0, %0 = r0, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpdi_and_0"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (and:BI (match_operator:BI 4 "predicate_operator"
+ [(match_operand:DI 2 "gr_register_operand" "r")
+ (match_operand:DI 3 "gr_reg_or_8bit_operand" "rK")])
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp.%C4.and.orcm %0, %I0 = %3, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpdi_and_1"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (and:BI (match_operator:BI 3 "signed_inequality_operator"
+ [(match_operand:DI 2 "gr_register_operand" "r")
+ (const_int 0)])
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp.%C3.and.orcm %0, %I0 = r0, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpdi_andnot_0"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (and:BI (not:BI (match_operator:BI 4 "predicate_operator"
+ [(match_operand:DI 2 "gr_register_operand" "r")
+ (match_operand:DI 3 "gr_reg_or_8bit_operand" "rK")]))
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp.%C4.or.andcm %I0, %0 = %3, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpdi_andnot_1"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (and:BI (not:BI (match_operator:BI 3 "signed_inequality_operator"
+ [(match_operand:DI 2 "gr_register_operand" "r")
+ (const_int 0)]))
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp.%C3.or.andcm %I0, %0 = r0, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*tbit_and_0"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (and:BI (ne:BI (and:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (const_int 1))
+ (const_int 0))
+ (match_operand:BI 2 "register_operand" "0")))]
+ ""
+ "tbit.nz.and.orcm %0, %I0 = %1, 0"
+ [(set_attr "itanium_class" "tbit")])
+
+(define_insn "*tbit_and_1"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (and:BI (eq:BI (and:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (const_int 1))
+ (const_int 0))
+ (match_operand:BI 2 "register_operand" "0")))]
+ ""
+ "tbit.z.and.orcm %0, %I0 = %1, 0"
+ [(set_attr "itanium_class" "tbit")])
+
+(define_insn "*tbit_and_2"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (and:BI (ne:BI (zero_extract:DI
+ (match_operand:DI 1 "gr_register_operand" "r")
+ (const_int 1)
+ (match_operand:DI 2 "shift_count_operand" "M"))
+ (const_int 0))
+ (match_operand:BI 3 "register_operand" "0")))]
+ ""
+ "tbit.nz.and.orcm %0, %I0 = %1, %2"
+ [(set_attr "itanium_class" "tbit")])
+
+(define_insn "*tbit_and_3"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (and:BI (eq:BI (zero_extract:DI
+ (match_operand:DI 1 "gr_register_operand" "r")
+ (const_int 1)
+ (match_operand:DI 2 "shift_count_operand" "M"))
+ (const_int 0))
+ (match_operand:BI 3 "register_operand" "0")))]
+ ""
+ "tbit.z.and.orcm %0, %I0 = %1, %2"
+ [(set_attr "itanium_class" "tbit")])
+
+(define_insn "*cmpsi_or_0"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (ior:BI (match_operator:BI 4 "predicate_operator"
+ [(match_operand:SI 2 "gr_reg_or_0_operand" "rO")
+ (match_operand:SI 3 "gr_reg_or_8bit_operand" "rK")])
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp4.%C4.or.andcm %0, %I0 = %3, %r2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpsi_or_1"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (ior:BI (match_operator:BI 3 "signed_inequality_operator"
+ [(match_operand:SI 2 "gr_register_operand" "r")
+ (const_int 0)])
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp4.%C3.or.andcm %0, %I0 = r0, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpsi_orcm_0"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (ior:BI (not:BI (match_operator:BI 4 "predicate_operator"
+ [(match_operand:SI 2 "gr_reg_or_0_operand" "rO")
+ (match_operand:SI 3 "gr_reg_or_8bit_operand" "rK")]))
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp4.%C4.and.orcm %I0, %0 = %3, %r2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpsi_orcm_1"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (ior:BI (not:BI (match_operator:BI 3 "signed_inequality_operator"
+ [(match_operand:SI 2 "gr_register_operand" "r")
+ (const_int 0)]))
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp4.%C3.and.orcm %I0, %0 = r0, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpdi_or_0"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (ior:BI (match_operator:BI 4 "predicate_operator"
+ [(match_operand:DI 2 "gr_register_operand" "r")
+ (match_operand:DI 3 "gr_reg_or_8bit_operand" "rK")])
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp.%C4.or.andcm %0, %I0 = %3, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpdi_or_1"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (ior:BI (match_operator:BI 3 "signed_inequality_operator"
+ [(match_operand:DI 2 "gr_register_operand" "r")
+ (const_int 0)])
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp.%C3.or.andcm %0, %I0 = r0, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpdi_orcm_0"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (ior:BI (not:BI (match_operator:BI 4 "predicate_operator"
+ [(match_operand:DI 2 "gr_register_operand" "r")
+ (match_operand:DI 3 "gr_reg_or_8bit_operand" "rK")]))
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp.%C4.and.orcm %I0, %0 = %3, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpdi_orcm_1"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (ior:BI (not:BI (match_operator:BI 3 "signed_inequality_operator"
+ [(match_operand:DI 2 "gr_register_operand" "r")
+ (const_int 0)]))
+ (match_operand:BI 1 "register_operand" "0")))]
+ ""
+ "cmp.%C3.and.orcm %I0, %0 = r0, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*tbit_or_0"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (ior:BI (ne:BI (and:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (const_int 1))
+ (const_int 0))
+ (match_operand:BI 2 "register_operand" "0")))]
+ ""
+ "tbit.nz.or.andcm %0, %I0 = %1, 0"
+ [(set_attr "itanium_class" "tbit")])
+
+(define_insn "*tbit_or_1"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (ior:BI (eq:BI (and:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (const_int 1))
+ (const_int 0))
+ (match_operand:BI 2 "register_operand" "0")))]
+ ""
+ "tbit.z.or.andcm %0, %I0 = %1, 0"
+ [(set_attr "itanium_class" "tbit")])
+
+(define_insn "*tbit_or_2"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (ior:BI (ne:BI (zero_extract:DI
+ (match_operand:DI 1 "gr_register_operand" "r")
+ (const_int 1)
+ (match_operand:DI 2 "shift_count_operand" "M"))
+ (const_int 0))
+ (match_operand:BI 3 "register_operand" "0")))]
+ ""
+ "tbit.nz.or.andcm %0, %I0 = %1, %2"
+ [(set_attr "itanium_class" "tbit")])
+
+(define_insn "*tbit_or_3"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (ior:BI (eq:BI (zero_extract:DI
+ (match_operand:DI 1 "gr_register_operand" "r")
+ (const_int 1)
+ (match_operand:DI 2 "shift_count_operand" "M"))
+ (const_int 0))
+ (match_operand:BI 3 "register_operand" "0")))]
+ ""
+ "tbit.z.or.andcm %0, %I0 = %1, %2"
+ [(set_attr "itanium_class" "tbit")])
+
+;; Transform test of and/or of setcc into parallel comparisons.
+
+(define_split
+ [(set (match_operand:BI 0 "register_operand" "")
+ (ne:BI (and:DI (ne:DI (match_operand:BI 2 "register_operand" "")
+ (const_int 0))
+ (match_operand:DI 3 "register_operand" ""))
+ (const_int 0)))]
+ ""
+ [(set (match_dup 0)
+ (and:BI (ne:BI (and:DI (match_dup 3) (const_int 1)) (const_int 0))
+ (match_dup 2)))]
+ "")
+
+(define_split
+ [(set (match_operand:BI 0 "register_operand" "")
+ (eq:BI (and:DI (ne:DI (match_operand:BI 2 "register_operand" "")
+ (const_int 0))
+ (match_operand:DI 3 "register_operand" ""))
+ (const_int 0)))]
+ ""
+ [(set (match_dup 0)
+ (and:BI (ne:BI (and:DI (match_dup 3) (const_int 1)) (const_int 0))
+ (match_dup 2)))
+ (parallel [(set (match_dup 0) (not:BI (match_dup 0)))
+ (clobber (scratch))])]
+ "")
+
+(define_split
+ [(set (match_operand:BI 0 "register_operand" "")
+ (ne:BI (ior:DI (ne:DI (match_operand:BI 2 "register_operand" "")
+ (const_int 0))
+ (match_operand:DI 3 "register_operand" ""))
+ (const_int 0)))]
+ ""
+ [(set (match_dup 0)
+ (ior:BI (ne:BI (match_dup 3) (const_int 0))
+ (match_dup 2)))]
+ "")
+
+(define_split
+ [(set (match_operand:BI 0 "register_operand" "")
+ (eq:BI (ior:DI (ne:DI (match_operand:BI 2 "register_operand" "")
+ (const_int 0))
+ (match_operand:DI 3 "register_operand" ""))
+ (const_int 0)))]
+ ""
+ [(set (match_dup 0)
+ (ior:BI (ne:BI (match_dup 3) (const_int 0))
+ (match_dup 2)))
+ (parallel [(set (match_dup 0) (not:BI (match_dup 0)))
+ (clobber (scratch))])]
+ "")
+
+;; ??? Incredibly hackish. Either need four proper patterns with all
+;; the alternatives, or rely on sched1 to split the insn and hope that
+;; nothing bad happens to the comparisons in the meantime.
+;;
+;; Alternately, adjust combine to allow 2->2 and 3->3 splits, assuming
+;; that we're doing height reduction.
+;
+;(define_insn_and_split ""
+; [(set (match_operand:BI 0 "register_operand" "=c")
+; (and:BI (and:BI (match_operator:BI 1 "comparison_operator"
+; [(match_operand 2 "" "")
+; (match_operand 3 "" "")])
+; (match_operator:BI 4 "comparison_operator"
+; [(match_operand 5 "" "")
+; (match_operand 6 "" "")]))
+; (match_dup 0)))]
+; "flag_schedule_insns"
+; "#"
+; ""
+; [(set (match_dup 0) (and:BI (match_dup 1) (match_dup 0)))
+; (set (match_dup 0) (and:BI (match_dup 4) (match_dup 0)))]
+; "")
+;
+;(define_insn_and_split ""
+; [(set (match_operand:BI 0 "register_operand" "=c")
+; (ior:BI (ior:BI (match_operator:BI 1 "comparison_operator"
+; [(match_operand 2 "" "")
+; (match_operand 3 "" "")])
+; (match_operator:BI 4 "comparison_operator"
+; [(match_operand 5 "" "")
+; (match_operand 6 "" "")]))
+; (match_dup 0)))]
+; "flag_schedule_insns"
+; "#"
+; ""
+; [(set (match_dup 0) (ior:BI (match_dup 1) (match_dup 0)))
+; (set (match_dup 0) (ior:BI (match_dup 4) (match_dup 0)))]
+; "")
+;
+;(define_split
+; [(set (match_operand:BI 0 "register_operand" "")
+; (and:BI (and:BI (match_operator:BI 1 "comparison_operator"
+; [(match_operand 2 "" "")
+; (match_operand 3 "" "")])
+; (match_operand:BI 7 "register_operand" ""))
+; (and:BI (match_operator:BI 4 "comparison_operator"
+; [(match_operand 5 "" "")
+; (match_operand 6 "" "")])
+; (match_operand:BI 8 "register_operand" ""))))]
+; ""
+; [(set (match_dup 0) (and:BI (match_dup 7) (match_dup 8)))
+; (set (match_dup 0) (and:BI (and:BI (match_dup 1) (match_dup 4))
+; (match_dup 0)))]
+; "")
+;
+;(define_split
+; [(set (match_operand:BI 0 "register_operand" "")
+; (ior:BI (ior:BI (match_operator:BI 1 "comparison_operator"
+; [(match_operand 2 "" "")
+; (match_operand 3 "" "")])
+; (match_operand:BI 7 "register_operand" ""))
+; (ior:BI (match_operator:BI 4 "comparison_operator"
+; [(match_operand 5 "" "")
+; (match_operand 6 "" "")])
+; (match_operand:BI 8 "register_operand" ""))))]
+; ""
+; [(set (match_dup 0) (ior:BI (match_dup 7) (match_dup 8)))
+; (set (match_dup 0) (ior:BI (ior:BI (match_dup 1) (match_dup 4))
+; (match_dup 0)))]
+; "")
+
+;; Try harder to avoid predicate copies by duplicating compares.
+;; Note that we'll have already split the predicate copy, which
+;; is kind of a pain, but oh well.
+
+(define_peephole2
+ [(set (match_operand:BI 0 "register_operand" "")
+ (match_operand:BI 1 "comparison_operator" ""))
+ (set (match_operand:CCI 2 "register_operand" "")
+ (match_operand:CCI 3 "register_operand" ""))
+ (set (match_operand:CCI 4 "register_operand" "")
+ (match_operand:CCI 5 "register_operand" ""))
+ (set (match_operand:BI 6 "register_operand" "")
+ (unspec:BI [(match_dup 6)] UNSPEC_PRED_REL_MUTEX))]
+ "REGNO (operands[3]) == REGNO (operands[0])
+ && REGNO (operands[4]) == REGNO (operands[0]) + 1
+ && REGNO (operands[4]) == REGNO (operands[2]) + 1
+ && REGNO (operands[6]) == REGNO (operands[2])"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 6) (match_dup 7))]
+ "operands[7] = copy_rtx (operands[1]);")
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 16-bit Integer arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "mulhi3"
+ [(set (match_operand:HI 0 "gr_register_operand" "=r")
+ (mult:HI (match_operand:HI 1 "gr_register_operand" "r")
+ (match_operand:HI 2 "gr_register_operand" "r")))]
+ ""
+ "pmpy2.r %0 = %1, %2"
+ [(set_attr "itanium_class" "mmmul")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 32-bit Integer arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r,r,r")
+ (plus:SI (match_operand:SI 1 "gr_register_operand" "%r,r,a")
+ (match_operand:SI 2 "gr_reg_or_22bit_operand" "r,I,J")))]
+ ""
+ "@
+ add %0 = %1, %2
+ adds %0 = %2, %1
+ addl %0 = %2, %1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*addsi3_plus1"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r")
+ (plus:SI (plus:SI (match_operand:SI 1 "gr_register_operand" "r")
+ (match_operand:SI 2 "gr_register_operand" "r"))
+ (const_int 1)))]
+ ""
+ "add %0 = %1, %2, 1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*addsi3_plus1_alt"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r")
+ (plus:SI (mult:SI (match_operand:SI 1 "gr_register_operand" "r")
+ (const_int 2))
+ (const_int 1)))]
+ ""
+ "add %0 = %1, %1, 1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*addsi3_shladd"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r")
+ (plus:SI (mult:SI (match_operand:SI 1 "gr_register_operand" "r")
+ (match_operand:SI 2 "shladd_operand" "n"))
+ (match_operand:SI 3 "gr_register_operand" "r")))]
+ ""
+ "shladd %0 = %1, %S2, %3"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "gr_reg_or_8bit_operand" "rK")
+ (match_operand:SI 2 "gr_register_operand" "r")))]
+ ""
+ "sub %0 = %1, %2"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*subsi3_minus1"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r")
+ (plus:SI (not:SI (match_operand:SI 1 "gr_register_operand" "r"))
+ (match_operand:SI 2 "gr_register_operand" "r")))]
+ ""
+ "sub %0 = %2, %1, 1"
+ [(set_attr "itanium_class" "ialu")])
+
+;; ??? Could add maddsi3 patterns patterned after the madddi3 patterns.
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "fr_register_operand" "=f")
+ (mult:SI (match_operand:SI 1 "grfr_register_operand" "f")
+ (match_operand:SI 2 "grfr_register_operand" "f")))]
+ ""
+ "xmpy.l %0 = %1, %2"
+ [(set_attr "itanium_class" "xmpy")])
+
+(define_insn "maddsi4"
+ [(set (match_operand:SI 0 "fr_register_operand" "=f")
+ (plus:SI (mult:SI (match_operand:SI 1 "grfr_register_operand" "f")
+ (match_operand:SI 2 "grfr_register_operand" "f"))
+ (match_operand:SI 3 "grfr_register_operand" "f")))]
+ ""
+ "xma.l %0 = %1, %2, %3"
+ [(set_attr "itanium_class" "xmpy")])
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r")
+ (neg:SI (match_operand:SI 1 "gr_register_operand" "r")))]
+ ""
+ "sub %0 = r0, %1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "abssi2"
+ [(set (match_dup 2)
+ (ge:BI (match_operand:SI 1 "gr_register_operand" "") (const_int 0)))
+ (set (match_operand:SI 0 "gr_register_operand" "")
+ (if_then_else:SI (eq (match_dup 2) (const_int 0))
+ (neg:SI (match_dup 1))
+ (match_dup 1)))]
+ ""
+ { operands[2] = gen_reg_rtx (BImode); })
+
+(define_expand "sminsi3"
+ [(set (match_dup 3)
+ (ge:BI (match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_register_operand" "")))
+ (set (match_operand:SI 0 "gr_register_operand" "")
+ (if_then_else:SI (ne (match_dup 3) (const_int 0))
+ (match_dup 2) (match_dup 1)))]
+ ""
+ { operands[3] = gen_reg_rtx (BImode); })
+
+(define_expand "smaxsi3"
+ [(set (match_dup 3)
+ (ge:BI (match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_register_operand" "")))
+ (set (match_operand:SI 0 "gr_register_operand" "")
+ (if_then_else:SI (ne (match_dup 3) (const_int 0))
+ (match_dup 1) (match_dup 2)))]
+ ""
+ { operands[3] = gen_reg_rtx (BImode); })
+
+(define_expand "uminsi3"
+ [(set (match_dup 3)
+ (geu:BI (match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_register_operand" "")))
+ (set (match_operand:SI 0 "gr_register_operand" "")
+ (if_then_else:SI (ne (match_dup 3) (const_int 0))
+ (match_dup 2) (match_dup 1)))]
+ ""
+ { operands[3] = gen_reg_rtx (BImode); })
+
+(define_expand "umaxsi3"
+ [(set (match_dup 3)
+ (geu:BI (match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_register_operand" "")))
+ (set (match_operand:SI 0 "gr_register_operand" "")
+ (if_then_else:SI (ne (match_dup 3) (const_int 0))
+ (match_dup 1) (match_dup 2)))]
+ ""
+ { operands[3] = gen_reg_rtx (BImode); })
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 64-bit Integer arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "adddi3"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r,r,r")
+ (plus:DI (match_operand:DI 1 "gr_register_operand" "%r,r,a")
+ (match_operand:DI 2 "gr_reg_or_22bit_operand" "r,I,J")))]
+ ""
+ "@
+ add %0 = %1, %2
+ adds %0 = %2, %1
+ addl %0 = %2, %1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*adddi3_plus1"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (plus:DI (plus:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "gr_register_operand" "r"))
+ (const_int 1)))]
+ ""
+ "add %0 = %1, %2, 1"
+ [(set_attr "itanium_class" "ialu")])
+
+;; This has some of the same problems as shladd. We let the shladd
+;; eliminator hack handle it, which results in the 1 being forced into
+;; a register, but not more ugliness here.
+(define_insn "*adddi3_plus1_alt"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (plus:DI (mult:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (const_int 2))
+ (const_int 1)))]
+ ""
+ "add %0 = %1, %1, 1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "subdi3"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (minus:DI (match_operand:DI 1 "gr_reg_or_8bit_operand" "rK")
+ (match_operand:DI 2 "gr_register_operand" "r")))]
+ ""
+ "sub %0 = %1, %2"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*subdi3_minus1"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (plus:DI (not:DI (match_operand:DI 1 "gr_register_operand" "r"))
+ (match_operand:DI 2 "gr_register_operand" "r")))]
+ ""
+ "sub %0 = %2, %1, 1"
+ [(set_attr "itanium_class" "ialu")])
+
+;; ??? Use grfr instead of fr because of virtual register elimination
+;; and silly test cases multiplying by the frame pointer.
+(define_insn "muldi3"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (mult:DI (match_operand:DI 1 "grfr_register_operand" "f")
+ (match_operand:DI 2 "grfr_register_operand" "f")))]
+ ""
+ "xmpy.l %0 = %1, %2"
+ [(set_attr "itanium_class" "xmpy")])
+
+;; ??? If operand 3 is an eliminable reg, then register elimination causes the
+;; same problem that we have with shladd below. Unfortunately, this case is
+;; much harder to fix because the multiply puts the result in an FP register,
+;; but the add needs inputs from a general register. We add a spurious clobber
+;; here so that it will be present just in case register elimination gives us
+;; the funny result.
+
+;; ??? Maybe validate_changes should try adding match_scratch clobbers?
+
+;; ??? Maybe we should change how adds are canonicalized.
+
+(define_insn "madddi4"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (plus:DI (mult:DI (match_operand:DI 1 "grfr_register_operand" "f")
+ (match_operand:DI 2 "grfr_register_operand" "f"))
+ (match_operand:DI 3 "grfr_register_operand" "f")))
+ (clobber (match_scratch:DI 4 "=X"))]
+ ""
+ "xma.l %0 = %1, %2, %3"
+ [(set_attr "itanium_class" "xmpy")])
+
+;; This can be created by register elimination if operand3 of shladd is an
+;; eliminable register or has reg_equiv_constant set.
+
+;; We have to use nonmemory_operand for operand 4, to ensure that the
+;; validate_changes call inside eliminate_regs will always succeed. If it
+;; doesn't succeed, then this remain a madddi4 pattern, and will be reloaded
+;; incorrectly.
+
+(define_insn "*madddi4_elim"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (plus:DI (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "f")
+ (match_operand:DI 2 "register_operand" "f"))
+ (match_operand:DI 3 "register_operand" "f"))
+ (match_operand:DI 4 "nonmemory_operand" "rI")))
+ (clobber (match_scratch:DI 5 "=f"))]
+ "reload_in_progress"
+ "#"
+ [(set_attr "itanium_class" "unknown")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "register_operand" ""))
+ (match_operand:DI 3 "register_operand" ""))
+ (match_operand:DI 4 "gr_reg_or_14bit_operand" "")))
+ (clobber (match_scratch:DI 5 ""))]
+ "reload_completed"
+ [(parallel [(set (match_dup 5) (plus:DI (mult:DI (match_dup 1) (match_dup 2))
+ (match_dup 3)))
+ (clobber (match_dup 0))])
+ (set (match_dup 0) (match_dup 5))
+ (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
+ "")
+
+(define_insn "smuldi3_highpart"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (sign_extend:TI
+ (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG"))
+ (sign_extend:TI
+ (match_operand:DI 2 "fr_reg_or_fp01_operand" "fG")))
+ (const_int 64))))]
+ ""
+ "xmpy.h %0 = %F1, %F2"
+ [(set_attr "itanium_class" "xmpy")])
+
+(define_insn "umuldi3_highpart"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG"))
+ (zero_extend:TI
+ (match_operand:DI 2 "fr_reg_or_fp01_operand" "fG")))
+ (const_int 64))))]
+ ""
+ "xmpy.hu %0 = %F1, %F2"
+ [(set_attr "itanium_class" "xmpy")])
+
+(define_insn "negdi2"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (neg:DI (match_operand:DI 1 "gr_register_operand" "r")))]
+ ""
+ "sub %0 = r0, %1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "absdi2"
+ [(set (match_dup 2)
+ (ge:BI (match_operand:DI 1 "gr_register_operand" "") (const_int 0)))
+ (set (match_operand:DI 0 "gr_register_operand" "")
+ (if_then_else:DI (eq (match_dup 2) (const_int 0))
+ (neg:DI (match_dup 1))
+ (match_dup 1)))]
+ ""
+ { operands[2] = gen_reg_rtx (BImode); })
+
+(define_expand "smindi3"
+ [(set (match_dup 3)
+ (ge:BI (match_operand:DI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "gr_register_operand" "")))
+ (set (match_operand:DI 0 "gr_register_operand" "")
+ (if_then_else:DI (ne (match_dup 3) (const_int 0))
+ (match_dup 2) (match_dup 1)))]
+ ""
+ { operands[3] = gen_reg_rtx (BImode); })
+
+(define_expand "smaxdi3"
+ [(set (match_dup 3)
+ (ge:BI (match_operand:DI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "gr_register_operand" "")))
+ (set (match_operand:DI 0 "gr_register_operand" "")
+ (if_then_else:DI (ne (match_dup 3) (const_int 0))
+ (match_dup 1) (match_dup 2)))]
+ ""
+ { operands[3] = gen_reg_rtx (BImode); })
+
+(define_expand "umindi3"
+ [(set (match_dup 3)
+ (geu:BI (match_operand:DI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "gr_register_operand" "")))
+ (set (match_operand:DI 0 "gr_register_operand" "")
+ (if_then_else:DI (ne (match_dup 3) (const_int 0))
+ (match_dup 2) (match_dup 1)))]
+ ""
+ { operands[3] = gen_reg_rtx (BImode); })
+
+(define_expand "umaxdi3"
+ [(set (match_dup 3)
+ (geu:BI (match_operand:DI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "gr_register_operand" "")))
+ (set (match_operand:DI 0 "gr_register_operand" "")
+ (if_then_else:DI (ne (match_dup 3) (const_int 0))
+ (match_dup 1) (match_dup 2)))]
+ ""
+ { operands[3] = gen_reg_rtx (BImode); })
+
+(define_expand "ffsdi2"
+ [(set (match_dup 6)
+ (eq:BI (match_operand:DI 1 "gr_register_operand" "") (const_int 0)))
+ (set (match_dup 2) (plus:DI (match_dup 1) (const_int -1)))
+ (set (match_dup 5) (const_int 0))
+ (set (match_dup 3) (xor:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 4) (popcount:DI (match_dup 3)))
+ (set (match_operand:DI 0 "gr_register_operand" "")
+ (if_then_else:DI (ne (match_dup 6) (const_int 0))
+ (match_dup 5) (match_dup 4)))]
+ ""
+{
+ operands[2] = gen_reg_rtx (DImode);
+ operands[3] = gen_reg_rtx (DImode);
+ operands[4] = gen_reg_rtx (DImode);
+ operands[5] = gen_reg_rtx (DImode);
+ operands[6] = gen_reg_rtx (BImode);
+})
+
+(define_expand "ctzdi2"
+ [(set (match_dup 2) (plus:DI (match_operand:DI 1 "gr_register_operand" "")
+ (const_int -1)))
+ (set (match_dup 3) (not:DI (match_dup 1)))
+ (set (match_dup 4) (and:DI (match_dup 2) (match_dup 3)))
+ (set (match_operand:DI 0 "gr_register_operand" "")
+ (popcount:DI (match_dup 4)))]
+ ""
+{
+ operands[2] = gen_reg_rtx (DImode);
+ operands[3] = gen_reg_rtx (DImode);
+ operands[4] = gen_reg_rtx (DImode);
+})
+
+;; Note the computation here is op0 = 63 - (exp - 0xffff).
+(define_expand "clzdi2"
+ [(set (match_dup 2)
+ (unsigned_float:XF (match_operand:DI 1 "fr_reg_or_fp01_operand" "")))
+ (set (match_dup 3)
+ (unspec:DI [(match_dup 2)] UNSPEC_GETF_EXP))
+ (set (match_dup 4) (const_int 65598))
+ (set (match_operand:DI 0 "gr_register_operand" "")
+ (minus:DI (match_dup 4) (match_dup 3)))]
+ ""
+{
+ operands[2] = gen_reg_rtx (XFmode);
+ operands[3] = gen_reg_rtx (DImode);
+ operands[4] = gen_reg_rtx (DImode);
+})
+
+(define_insn "popcountdi2"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (popcount:DI (match_operand:DI 1 "gr_register_operand" "r")))]
+ ""
+ "popcnt %0 = %1"
+ [(set_attr "itanium_class" "mmmul")])
+
+(define_insn "bswapdi2"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (bswap:DI (match_operand:DI 1 "gr_register_operand" "r")))]
+ ""
+ "mux1 %0 = %1, @rev"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*getf_exp_xf"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (unspec:DI [(match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_GETF_EXP))]
+ ""
+ "getf.exp %0 = %F1"
+ [(set_attr "itanium_class" "frfr")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 128-bit Integer arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "addti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (plus:TI (match_operand:TI 1 "gr_register_operand" "%r")
+ (match_operand:TI 2 "gr_reg_or_14bit_operand" "rI")))
+ (clobber (match_scratch:BI 3 "=&c"))]
+ ""
+ "#"
+ [(set_attr "itanium_class" "unknown")])
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (plus:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:TI 2 "register_operand" "")))
+ (clobber (match_scratch:BI 3 ""))]
+ "reload_completed"
+ [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (ltu:BI (match_dup 0) (match_dup 1)))
+ (cond_exec (eq (match_dup 3) (const_int 0))
+ (set (match_dup 4) (plus:DI (match_dup 5) (match_dup 6))))
+ (cond_exec (ne (match_dup 3) (const_int 0))
+ (set (match_dup 4)
+ (plus:DI (plus:DI (match_dup 5) (match_dup 6))
+ (const_int 1))))]
+{
+ operands[4] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[5] = gen_highpart (DImode, operands[1]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ operands[6] = gen_highpart (DImode, operands[2]);
+ operands[2] = gen_lowpart (DImode, operands[2]);
+})
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (plus:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:TI 2 "immediate_operand" "")))
+ (clobber (match_scratch:BI 3 ""))]
+ "reload_completed"
+ [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (ltu:BI (match_dup 0) (match_dup 1)))
+ (cond_exec (eq (match_dup 3) (const_int 0))
+ (set (match_dup 4)
+ (plus:DI (match_dup 5) (match_dup 6))))
+ (cond_exec (ne (match_dup 3) (const_int 0))
+ (set (match_dup 4)
+ (plus:DI (match_dup 5) (match_dup 7))))]
+{
+ operands[4] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[5] = gen_highpart (DImode, operands[1]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ operands[6] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx;
+ operands[7] = INTVAL (operands[2]) < 0 ? const0_rtx : const1_rtx;
+})
+
+(define_insn "subti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (minus:TI (match_operand:TI 1 "gr_reg_or_8bit_operand" "rK")
+ (match_operand:TI 2 "gr_register_operand" "r")))
+ (clobber (match_scratch:BI 3 "=&c"))]
+ ""
+ "#"
+ [(set_attr "itanium_class" "unknown")])
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (minus:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:TI 2 "register_operand" "")))
+ (clobber (match_scratch:BI 3 "=&c"))]
+ "reload_completed"
+ [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (ltu:BI (match_dup 1) (match_dup 0)))
+ (cond_exec (eq (match_dup 3) (const_int 0))
+ (set (match_dup 4) (minus:DI (match_dup 5) (match_dup 6))))
+ (cond_exec (ne (match_dup 3) (const_int 0))
+ (set (match_dup 4)
+ (plus:DI (not:DI (match_dup 6)) (match_dup 5))))]
+{
+ operands[4] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[5] = gen_highpart (DImode, operands[1]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ operands[6] = gen_highpart (DImode, operands[2]);
+ operands[2] = gen_lowpart (DImode, operands[2]);
+})
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (minus:TI (match_operand:TI 1 "immediate_operand" "")
+ (match_operand:TI 2 "register_operand" "")))
+ (clobber (match_scratch:BI 3 "=&c"))]
+ "reload_completed && satisfies_constraint_K (operands[1])"
+ [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (gtu:BI (match_dup 0) (match_dup 1)))
+ (cond_exec (ne (match_dup 3) (const_int 0))
+ (set (match_dup 4) (minus:DI (match_dup 6) (match_dup 5))))
+ (cond_exec (eq (match_dup 3) (const_int 0))
+ (set (match_dup 4) (minus:DI (match_dup 7) (match_dup 5))))]
+{
+ operands[4] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[5] = gen_highpart (DImode, operands[2]);
+ operands[2] = gen_lowpart (DImode, operands[2]);
+ operands[6] = INTVAL (operands[1]) < 0 ? GEN_INT (-2) : constm1_rtx;
+ operands[7] = INTVAL (operands[1]) < 0 ? constm1_rtx : const0_rtx;
+})
+
+(define_expand "mulditi3"
+ [(set (match_operand:TI 0 "fr_register_operand" "")
+ (mult:TI (sign_extend:TI
+ (match_operand:DI 1 "fr_reg_or_fp01_operand" ""))
+ (sign_extend:TI
+ (match_operand:DI 2 "fr_reg_or_fp01_operand" ""))))]
+ ""
+ "")
+
+(define_insn_and_split "*mulditi3_internal"
+ [(set (match_operand:TI 0 "fr_register_operand" "=&f")
+ (mult:TI (sign_extend:TI
+ (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG"))
+ (sign_extend:TI
+ (match_operand:DI 2 "fr_reg_or_fp01_operand" "fG"))))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (mult:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (sign_extend:TI (match_dup 1))
+ (sign_extend:TI (match_dup 2)))
+ (const_int 64))))]
+{
+ operands[3] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+}
+ [(set_attr "itanium_class" "unknown")])
+
+(define_expand "umulditi3"
+ [(set (match_operand:TI 0 "fr_register_operand" "")
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "fr_reg_or_fp01_operand" ""))
+ (zero_extend:TI
+ (match_operand:DI 2 "fr_reg_or_fp01_operand" ""))))]
+ ""
+ "")
+
+(define_insn_and_split "*umulditi3_internal"
+ [(set (match_operand:TI 0 "fr_register_operand" "=&f")
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG"))
+ (zero_extend:TI
+ (match_operand:DI 2 "fr_reg_or_fp01_operand" "fG"))))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (mult:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (zero_extend:TI (match_dup 1))
+ (zero_extend:TI (match_dup 2)))
+ (const_int 64))))]
+{
+ operands[3] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+}
+ [(set_attr "itanium_class" "unknown")])
+
+(define_insn_and_split "negti2"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (neg:TI (match_operand:TI 1 "gr_register_operand" "r")))
+ (clobber (match_scratch:BI 2 "=&c"))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 2) (eq:BI (match_dup 1) (const_int 0)))
+ (set (match_dup 0) (minus:DI (const_int 0) (match_dup 1)))
+ (cond_exec (eq (match_dup 2) (const_int 0))
+ (set (match_dup 3) (minus:DI (const_int -1) (match_dup 4))))
+ (cond_exec (ne (match_dup 2) (const_int 0))
+ (set (match_dup 3) (minus:DI (const_int 0) (match_dup 4))))]
+{
+ operands[3] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[4] = gen_highpart (DImode, operands[1]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+}
+ [(set_attr "itanium_class" "unknown")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 32-bit floating point arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (plus:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "%fG")
+ (match_operand:SF 2 "fr_reg_or_signed_fp01_operand" "fZ")))]
+ ""
+ "fadd.s %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (minus:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_signed_fp01_operand" "fZ")))]
+ ""
+ "fsub.s %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (mult:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fmpy.s %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (abs:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fabs %0 = %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (neg:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fneg %0 = %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*nabssf2"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (neg:SF (abs:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG"))))]
+ ""
+ "fnegabs %0 = %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "copysignsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN))]
+ ""
+ "fmerge.s %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*ncopysignsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (unspec:SF [(match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN)))]
+ ""
+ "fmerge.ns %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "sminsf3"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (smin:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fmin %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "smaxsf3"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (smax:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fmax %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*nmulsf3"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (neg:SF (mult:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG"))))]
+ ""
+ "fnmpy.s %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "fmasf4"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (fma:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 3 "fr_reg_or_signed_fp01_operand" "fZ")))]
+ ""
+ "fma.s %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "fmssf4"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (fma:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")
+ (neg:SF
+ (match_operand:SF 3 "fr_reg_or_signed_fp01_operand" "fZ"))))]
+ ""
+ "fms.s %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "fnmasf4"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (fma:SF (neg:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG"))
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 3 "fr_reg_or_signed_fp01_operand" "fZ")))]
+ ""
+ "fnma.s %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 64-bit floating point arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (plus:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "%fG")
+ (match_operand:DF 2 "fr_reg_or_signed_fp01_operand" "fZ")))]
+ ""
+ "fadd.d %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*adddf3_trunc"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (plus:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "%fG")
+ (match_operand:DF 2 "fr_reg_or_signed_fp01_operand" "fZ"))))]
+ ""
+ "fadd.s %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (minus:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_signed_fp01_operand" "fZ")))]
+ ""
+ "fsub.d %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*subdf3_trunc"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (minus:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_signed_fp01_operand" "fZ"))))]
+ ""
+ "fsub.s %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fmpy.d %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*muldf3_trunc"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))))]
+ ""
+ "fmpy.s %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "absdf2"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (abs:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fabs %0 = %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (neg:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fneg %0 = %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*nabsdf2"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (neg:DF (abs:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG"))))]
+ ""
+ "fnegabs %0 = %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "copysigndf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN))]
+ ""
+ "fmerge.s %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*ncopysigndf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (unspec:DF [(match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN)))]
+ ""
+ "fmerge.ns %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "smindf3"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (smin:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fmin %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "smaxdf3"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (smax:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fmax %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*nmuldf3"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (neg:DF (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))))]
+ ""
+ "fnmpy.d %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*nmuldf3_trunc"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (neg:DF (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))))]
+ ""
+ "fnmpy.s %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "fmadf4"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (fma:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 3 "fr_reg_or_signed_fp01_operand" "fZ")))]
+ ""
+ "fma.d %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fmadf_trunc_sf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (fma:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 3 "fr_reg_or_signed_fp01_operand" "fZ"))))]
+ ""
+ "fma.s %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "fmsdf4"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (fma:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")
+ (neg:DF
+ (match_operand:DF 3 "fr_reg_or_signed_fp01_operand" "fZ"))))]
+ ""
+ "fms.d %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fmsdf_trunc_sf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (fma:DF
+ (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")
+ (neg:DF
+ (match_operand:DF 3 "fr_reg_or_signed_fp01_operand" "fZ")))))]
+ ""
+ "fms.s %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "fnmadf4"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (fma:DF (neg:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG"))
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 3 "fr_reg_or_signed_fp01_operand" "fZ")))]
+ ""
+ "fnma.d %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fnmadf_trunc_sf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (fma:DF
+ (neg:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG"))
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 3 "fr_reg_or_signed_fp01_operand" "fZ"))))]
+ ""
+ "fnma.s %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 80-bit floating point arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "addxf3"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (plus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "%fG")
+ (match_operand:XF 2 "xfreg_or_signed_fp01_operand" "fZ")))]
+ ""
+ "fadd %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*addxf3_truncsf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (plus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "%fG")
+ (match_operand:XF 2 "xfreg_or_signed_fp01_operand" "fZ"))))]
+ ""
+ "fadd.s %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*addxf3_truncdf"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (plus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "%fG")
+ (match_operand:XF 2 "xfreg_or_signed_fp01_operand" "fZ"))))]
+ ""
+ "fadd.d %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "subxf3"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (minus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_signed_fp01_operand" "fZ")))]
+ ""
+ "fsub %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*subxf3_truncsf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (minus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_signed_fp01_operand" "fZ"))))]
+ ""
+ "fsub.s %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*subxf3_truncdf"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (minus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_signed_fp01_operand" "fZ"))))]
+ ""
+ "fsub.d %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "mulxf3"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))]
+ ""
+ "fmpy %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*mulxf3_truncsf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fmpy.s %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*mulxf3_truncdf"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fmpy.d %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "absxf2"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (abs:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")))]
+ ""
+ "fabs %0 = %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "negxf2"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (neg:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")))]
+ ""
+ "fneg %0 = %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*nabsxf2"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (neg:XF (abs:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fnegabs %0 = %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "copysignxf3"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN))]
+ ""
+ "fmerge.s %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*ncopysignxf3"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (neg:XF (unspec:XF [(match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN)))]
+ ""
+ "fmerge.ns %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "sminxf3"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (smin:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))]
+ ""
+ "fmin %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "smaxxf3"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (smax:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))]
+ ""
+ "fmax %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*nmulxf3"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (neg:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))]
+ ""
+ "fnmpy %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*nmulxf3_truncsf"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (neg:XF (mult:XF
+ (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))))]
+ ""
+ "fnmpy.s %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*nmulxf3_truncdf"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_truncate:DF
+ (neg:XF (mult:XF
+ (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))))]
+ ""
+ "fnmpy.d %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "fmaxf4"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (fma:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 3 "fr_reg_or_signed_fp01_operand" "fZ")))]
+ ""
+ "fma %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fmaxf_trunc_<mode>"
+ [(set (match_operand:MODE_SDF 0 "fr_register_operand" "=f")
+ (float_truncate:MODE_SDF
+ (fma:XF
+ (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 3 "fr_reg_or_signed_fp01_operand" "fZ"))))]
+ ""
+ "fma<suffix> %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "fmsxf4"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (fma:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")
+ (neg:XF
+ (match_operand:XF 3 "fr_reg_or_signed_fp01_operand" "fZ"))))]
+ ""
+ "fms %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fmsxf_trunc_<mode>"
+ [(set (match_operand:MODE_SDF 0 "fr_register_operand" "=f")
+ (float_truncate:MODE_SDF
+ (fma:XF
+ (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")
+ (neg:XF
+ (match_operand:XF 3 "fr_reg_or_signed_fp01_operand" "fZ")))))]
+ ""
+ "fms<suffix> %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "fnmaxf4"
+ [(set (match_operand:XF 0 "fr_register_operand" "=f")
+ (fma:XF (neg:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG"))
+ (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 3 "fr_reg_or_signed_fp01_operand" "fZ")))]
+ ""
+ "fnma %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fnmaxf_trunc_<mode>"
+ [(set (match_operand:MODE_SDF 0 "fr_register_operand" "=f")
+ (float_truncate:MODE_SDF
+ (fma:XF
+ (neg:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG"))
+ (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 3 "fr_reg_or_signed_fp01_operand" "fZ"))))]
+ ""
+ "fnma<suffix> %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 32-bit Integer Shifts and Rotates
+;; ::
+;; ::::::::::::::::::::
+
+(define_expand "ashlsi3"
+ [(set (match_operand:SI 0 "gr_register_operand" "")
+ (ashift:SI (match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
+ ""
+{
+ if (GET_CODE (operands[2]) != CONST_INT)
+ {
+ /* Why oh why didn't Intel arrange for SHIFT_COUNT_TRUNCATED? Now
+ we've got to get rid of stray bits outside the SImode register. */
+ rtx subshift = gen_reg_rtx (DImode);
+ emit_insn (gen_zero_extendsidi2 (subshift, operands[2]));
+ operands[2] = subshift;
+ }
+})
+
+(define_insn "*ashlsi3_internal"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r,r,r")
+ (ashift:SI (match_operand:SI 1 "gr_register_operand" "r,r,r")
+ (match_operand:DI 2 "gr_reg_or_5bit_operand" "R,n,r")))]
+ ""
+ "@
+ shladd %0 = %1, %2, r0
+ dep.z %0 = %1, %2, %E2
+ shl %0 = %1, %2"
+ [(set_attr "itanium_class" "ialu,ishf,mmshf")])
+
+(define_expand "ashrsi3"
+ [(set (match_operand:SI 0 "gr_register_operand" "")
+ (ashiftrt:SI (match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
+ ""
+{
+ rtx subtarget = gen_reg_rtx (DImode);
+ if (GET_CODE (operands[2]) == CONST_INT)
+ emit_insn (gen_extv (subtarget, gen_lowpart (DImode, operands[1]),
+ GEN_INT (32 - INTVAL (operands[2])), operands[2]));
+ else
+ {
+ rtx subshift = gen_reg_rtx (DImode);
+ emit_insn (gen_extendsidi2 (subtarget, operands[1]));
+ emit_insn (gen_zero_extendsidi2 (subshift, operands[2]));
+ emit_insn (gen_ashrdi3 (subtarget, subtarget, subshift));
+ }
+ emit_move_insn (gen_lowpart (DImode, operands[0]), subtarget);
+ DONE;
+})
+
+(define_expand "lshrsi3"
+ [(set (match_operand:SI 0 "gr_register_operand" "")
+ (lshiftrt:SI (match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
+ ""
+{
+ rtx subtarget = gen_reg_rtx (DImode);
+ if (GET_CODE (operands[2]) == CONST_INT)
+ emit_insn (gen_extzv (subtarget, gen_lowpart (DImode, operands[1]),
+ GEN_INT (32 - INTVAL (operands[2])), operands[2]));
+ else
+ {
+ rtx subshift = gen_reg_rtx (DImode);
+ emit_insn (gen_zero_extendsidi2 (subtarget, operands[1]));
+ emit_insn (gen_zero_extendsidi2 (subshift, operands[2]));
+ emit_insn (gen_lshrdi3 (subtarget, subtarget, subshift));
+ }
+ emit_move_insn (gen_lowpart (DImode, operands[0]), subtarget);
+ DONE;
+})
+
+;; Use mix4.r/shr to implement rotrsi3. We only get 32 bits of valid result
+;; here, instead of 64 like the patterns above. Keep the pattern together
+;; until after combine; otherwise it won't get matched often.
+
+(define_expand "rotrsi3"
+ [(set (match_operand:SI 0 "gr_register_operand" "")
+ (rotatert:SI (match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
+ ""
+{
+ if (GET_MODE (operands[2]) != VOIDmode)
+ {
+ rtx tmp = gen_reg_rtx (DImode);
+ emit_insn (gen_zero_extendsidi2 (tmp, operands[2]));
+ operands[2] = tmp;
+ }
+})
+
+(define_insn_and_split "*rotrsi3_internal"
+ [(set (match_operand:SI 0 "gr_register_operand" "=&r")
+ (rotatert:SI (match_operand:SI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "gr_reg_or_5bit_operand" "rM")))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 3)
+ (ior:DI (zero_extend:DI (match_dup 1))
+ (ashift:DI (zero_extend:DI (match_dup 1)) (const_int 32))))
+ (set (match_dup 3)
+ (lshiftrt:DI (match_dup 3) (match_dup 2)))]
+ "operands[3] = gen_rtx_REG (DImode, REGNO (operands[0]));")
+
+(define_expand "rotlsi3"
+ [(set (match_operand:SI 0 "gr_register_operand" "")
+ (rotate:SI (match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
+ ""
+{
+ if (! shift_32bit_count_operand (operands[2], SImode))
+ {
+ rtx tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_subsi3 (tmp, GEN_INT (32), operands[2]));
+ emit_insn (gen_rotrsi3 (operands[0], operands[1], tmp));
+ DONE;
+ }
+})
+
+(define_insn_and_split "*rotlsi3_internal"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r")
+ (rotate:SI (match_operand:SI 1 "gr_register_operand" "r")
+ (match_operand:SI 2 "shift_32bit_count_operand" "n")))]
+ ""
+ "mux2 %0 = %1, 0xe1"
+ "reload_completed && INTVAL (operands[2]) != 16"
+ [(set (match_dup 3)
+ (ior:DI (zero_extend:DI (match_dup 1))
+ (ashift:DI (zero_extend:DI (match_dup 1)) (const_int 32))))
+ (set (match_dup 3)
+ (lshiftrt:DI (match_dup 3) (match_dup 2)))]
+{
+ operands[3] = gen_rtx_REG (DImode, REGNO (operands[0]));
+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));
+}
+ [(set_attr "itanium_class" "mmshf")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 64-bit Integer Shifts and Rotates
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "ashldi3"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r,r,r")
+ (ashift:DI (match_operand:DI 1 "gr_register_operand" "r,r,r")
+ (match_operand:DI 2 "gr_reg_or_6bit_operand" "R,r,rM")))]
+ ""
+ "@
+ shladd %0 = %1, %2, r0
+ shl %0 = %1, %2
+ shl %0 = %1, %2"
+ [(set_attr "itanium_class" "ialu,mmshf,mmshfi")])
+
+;; ??? Maybe combine this with the multiply and add instruction?
+
+(define_insn "*shladd"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (plus:DI (mult:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "shladd_operand" "n"))
+ (match_operand:DI 3 "gr_register_operand" "r")))]
+ ""
+ "shladd %0 = %1, %S2, %3"
+ [(set_attr "itanium_class" "ialu")])
+
+;; This can be created by register elimination if operand3 of shladd is an
+;; eliminable register or has reg_equiv_constant set.
+
+;; We have to use nonmemory_operand for operand 4, to ensure that the
+;; validate_changes call inside eliminate_regs will always succeed. If it
+;; doesn't succeed, then this remain a shladd pattern, and will be reloaded
+;; incorrectly.
+
+(define_insn_and_split "*shladd_elim"
+ [(set (match_operand:DI 0 "gr_register_operand" "=&r")
+ (plus:DI (plus:DI (mult:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "shladd_operand" "n"))
+ (match_operand:DI 3 "nonmemory_operand" "r"))
+ (match_operand:DI 4 "nonmemory_operand" "rI")))]
+ "reload_in_progress"
+ "* gcc_unreachable ();"
+ "reload_completed"
+ [(set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (match_dup 2))
+ (match_dup 3)))
+ (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
+ ""
+ [(set_attr "itanium_class" "unknown")])
+
+(define_insn "ashrdi3"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r,r")
+ (ashiftrt:DI (match_operand:DI 1 "gr_register_operand" "r,r")
+ (match_operand:DI 2 "gr_reg_or_6bit_operand" "r,rM")))]
+ ""
+ "@
+ shr %0 = %1, %2
+ shr %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf,mmshfi")])
+
+(define_insn "lshrdi3"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r,r")
+ (lshiftrt:DI (match_operand:DI 1 "gr_register_operand" "r,r")
+ (match_operand:DI 2 "gr_reg_or_6bit_operand" "r,rM")))]
+ ""
+ "@
+ shr.u %0 = %1, %2
+ shr.u %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf,mmshfi")])
+
+;; Using a predicate that accepts only constants doesn't work, because optabs
+;; will load the operand into a register and call the pattern if the predicate
+;; did not accept it on the first try. So we use nonmemory_operand and then
+;; verify that we have an appropriate constant in the expander.
+
+(define_expand "rotrdi3"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (rotatert:DI (match_operand:DI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (! shift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn "*rotrdi3_internal"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (rotatert:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "shift_count_operand" "M")))]
+ ""
+ "shrp %0 = %1, %1, %2"
+ [(set_attr "itanium_class" "ishf")])
+
+(define_expand "rotldi3"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (rotate:DI (match_operand:DI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (! shift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn "*rotldi3_internal"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (rotate:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "shift_count_operand" "M")))]
+ ""
+ "shrp %0 = %1, %1, %e2"
+ [(set_attr "itanium_class" "ishf")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 128-bit Integer Shifts and Rotates
+;; ::
+;; ::::::::::::::::::::
+
+(define_expand "ashlti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "")
+ (ashift:TI (match_operand:TI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (!dshift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn_and_split "*ashlti3_internal"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (ashift:TI (match_operand:TI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "dshift_count_operand" "n")))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT shift = INTVAL (operands[2]);
+ rtx rl = gen_lowpart (DImode, operands[0]);
+ rtx rh = gen_highpart (DImode, operands[0]);
+ rtx lo = gen_lowpart (DImode, operands[1]);
+ rtx shiftlo = GEN_INT (shift & 63);
+
+ if (shift & 64)
+ {
+ emit_move_insn (rl, const0_rtx);
+ if (shift & 63)
+ emit_insn (gen_ashldi3 (rh, lo, shiftlo));
+ else
+ emit_move_insn (rh, lo);
+ }
+ else
+ {
+ rtx hi = gen_highpart (DImode, operands[1]);
+
+ emit_insn (gen_shrp (rh, hi, lo, GEN_INT (-shift & 63)));
+ emit_insn (gen_ashldi3 (rl, lo, shiftlo));
+ }
+ DONE;
+})
+
+(define_expand "ashrti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "")
+ (ashiftrt:TI (match_operand:TI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (!dshift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn_and_split "*ashrti3_internal"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (ashiftrt:TI (match_operand:TI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "dshift_count_operand" "n")))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT shift = INTVAL (operands[2]);
+ rtx rl = gen_lowpart (DImode, operands[0]);
+ rtx rh = gen_highpart (DImode, operands[0]);
+ rtx hi = gen_highpart (DImode, operands[1]);
+ rtx shiftlo = GEN_INT (shift & 63);
+
+ if (shift & 64)
+ {
+ if (shift & 63)
+ emit_insn (gen_ashrdi3 (rl, hi, shiftlo));
+ else
+ emit_move_insn (rl, hi);
+ emit_insn (gen_ashrdi3 (rh, hi, GEN_INT (63)));
+ }
+ else
+ {
+ rtx lo = gen_lowpart (DImode, operands[1]);
+
+ emit_insn (gen_shrp (rl, hi, lo, shiftlo));
+ emit_insn (gen_ashrdi3 (rh, hi, shiftlo));
+ }
+ DONE;
+})
+
+(define_expand "lshrti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "")
+ (lshiftrt:TI (match_operand:TI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (!dshift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn_and_split "*lshrti3_internal"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (lshiftrt:TI (match_operand:TI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "dshift_count_operand" "n")))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT shift = INTVAL (operands[2]);
+ rtx rl = gen_lowpart (DImode, operands[0]);
+ rtx rh = gen_highpart (DImode, operands[0]);
+ rtx hi = gen_highpart (DImode, operands[1]);
+ rtx shiftlo = GEN_INT (shift & 63);
+
+ if (shift & 64)
+ {
+ if (shift & 63)
+ emit_insn (gen_lshrdi3 (rl, hi, shiftlo));
+ else
+ emit_move_insn (rl, hi);
+ emit_move_insn (rh, const0_rtx);
+ }
+ else
+ {
+ rtx lo = gen_lowpart (DImode, operands[1]);
+
+ emit_insn (gen_shrp (rl, hi, lo, shiftlo));
+ emit_insn (gen_lshrdi3 (rh, hi, shiftlo));
+ }
+ DONE;
+})
+
+(define_expand "rotlti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "")
+ (rotate:TI (match_operand:TI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (! dshift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn_and_split "*rotlti3_internal"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (rotate:TI (match_operand:TI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "dshift_count_operand" "n")))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT count = INTVAL (operands[2]);
+ rtx rl = gen_lowpart (DImode, operands[0]);
+ rtx rh = gen_highpart (DImode, operands[0]);
+ rtx lo = gen_lowpart (DImode, operands[1]);
+ rtx hi = gen_highpart (DImode, operands[1]);
+ rtx countlo = GEN_INT (-count & 63);
+
+ if (count & 64)
+ {
+ if (count & 63)
+ {
+ emit_insn (gen_shrp (rl, hi, lo, countlo));
+ emit_insn (gen_shrp (rh, lo, hi, countlo));
+ }
+ else
+ {
+ emit_move_insn (rl, hi);
+ emit_move_insn (rh, lo);
+ }
+ }
+ else
+ {
+ emit_insn (gen_shrp (rl, lo, hi, countlo));
+ emit_insn (gen_shrp (rh, hi, lo, countlo));
+ }
+ DONE;
+}
+ [(set_attr "itanium_class" "unknown")])
+
+(define_insn "shrp"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "gr_register_operand" "r")
+ (match_operand:DI 3 "shift_count_operand" "M")]
+ UNSPEC_SHRP))]
+ ""
+ "shrp %0 = %1, %2, %3"
+ [(set_attr "itanium_class" "ishf")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 32-bit Integer Logical operations
+;; ::
+;; ::::::::::::::::::::
+
+;; We don't seem to need any other 32-bit logical operations, because gcc
+;; generates zero-extend;zero-extend;DImode-op, which combine optimizes to
+;; DImode-op;zero-extend, and then we can optimize away the zero-extend.
+;; This doesn't work for unary logical operations, because we don't call
+;; apply_distributive_law for them.
+
+;; ??? Likewise, this doesn't work for andnot, which isn't handled by
+;; apply_distributive_law. We get inefficient code for
+;; int sub4 (int i, int j) { return i & ~j; }
+;; We could convert (and (not (sign_extend A)) (sign_extend B)) to
+;; (zero_extend (and (not A) B)) in combine.
+;; Or maybe fix this by adding andsi3/iorsi3/xorsi3 patterns like the
+;; one_cmplsi2 pattern.
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r")
+ (not:SI (match_operand:SI 1 "gr_register_operand" "r")))]
+ ""
+ "andcm %0 = -1, %1"
+ [(set_attr "itanium_class" "ilog")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 64-bit Integer Logical operations
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "anddi3"
+ [(set (match_operand:DI 0 "grfr_register_operand" "=r,*f")
+ (and:DI (match_operand:DI 1 "grfr_register_operand" "%r,*f")
+ (match_operand:DI 2 "grfr_reg_or_8bit_operand" "rK,*f")))]
+ ""
+ "@
+ and %0 = %2, %1
+ fand %0 = %2, %1"
+ [(set_attr "itanium_class" "ilog,fmisc")])
+
+(define_insn "*andnot"
+ [(set (match_operand:DI 0 "grfr_register_operand" "=r,*f")
+ (and:DI (not:DI (match_operand:DI 1 "grfr_register_operand" "r,*f"))
+ (match_operand:DI 2 "grfr_reg_or_8bit_operand" "rK,*f")))]
+ ""
+ "@
+ andcm %0 = %2, %1
+ fandcm %0 = %2, %1"
+ [(set_attr "itanium_class" "ilog,fmisc")])
+
+(define_insn "iordi3"
+ [(set (match_operand:DI 0 "grfr_register_operand" "=r,*f")
+ (ior:DI (match_operand:DI 1 "grfr_register_operand" "%r,*f")
+ (match_operand:DI 2 "grfr_reg_or_8bit_operand" "rK,*f")))]
+ ""
+ "@
+ or %0 = %2, %1
+ for %0 = %2, %1"
+ [(set_attr "itanium_class" "ilog,fmisc")])
+
+(define_insn "xordi3"
+ [(set (match_operand:DI 0 "grfr_register_operand" "=r,*f")
+ (xor:DI (match_operand:DI 1 "grfr_register_operand" "%r,*f")
+ (match_operand:DI 2 "grfr_reg_or_8bit_operand" "rK,*f")))]
+ ""
+ "@
+ xor %0 = %2, %1
+ fxor %0 = %2, %1"
+ [(set_attr "itanium_class" "ilog,fmisc")])
+
+(define_insn "one_cmpldi2"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (not:DI (match_operand:DI 1 "gr_register_operand" "r")))]
+ ""
+ "andcm %0 = -1, %1"
+ [(set_attr "itanium_class" "ilog")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Comparisons
+;; ::
+;; ::::::::::::::::::::
+
+(define_expand "cbranchbi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:BI 1 "register_operand" "")
+ (match_operand:BI 2 "const_int_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "cbranchsi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_reg_or_8bit_and_adjusted_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "cbranchdi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:DI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "gr_reg_or_8bit_and_adjusted_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "cbranchsf4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:SF 1 "fr_reg_or_fp01_operand" "")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "cbranchdf4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:DF 1 "fr_reg_or_fp01_operand" "")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "cbranchxf4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:XF 1 "xfreg_or_fp01_operand" "")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "cbranchtf4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:TF 1 "gr_register_operand" "")
+ (match_operand:TF 2 "gr_register_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_HPUX"
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+
+(define_insn "*cmpsi_normal"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (match_operator:BI 1 "normal_comparison_operator"
+ [(match_operand:SI 2 "gr_register_operand" "r")
+ (match_operand:SI 3 "gr_reg_or_8bit_operand" "rK")]))]
+ ""
+ "cmp4.%C1 %0, %I0 = %3, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+;; We use %r3 because it is possible for us to match a 0, and two of the
+;; unsigned comparisons don't accept immediate operands of zero.
+
+(define_insn "*cmpsi_adjusted"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (match_operator:BI 1 "adjusted_comparison_operator"
+ [(match_operand:SI 2 "gr_register_operand" "r")
+ (match_operand:SI 3 "gr_reg_or_8bit_adjusted_operand" "rL")]))]
+ ""
+ "cmp4.%C1 %0, %I0 = %r3, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpdi_normal"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (match_operator:BI 1 "normal_comparison_operator"
+ [(match_operand:DI 2 "gr_reg_or_0_operand" "rO")
+ (match_operand:DI 3 "gr_reg_or_8bit_operand" "rK")]))]
+ ""
+ "cmp.%C1 %0, %I0 = %3, %r2"
+ [(set_attr "itanium_class" "icmp")])
+
+;; We use %r3 because it is possible for us to match a 0, and two of the
+;; unsigned comparisons don't accept immediate operands of zero.
+
+(define_insn "*cmpdi_adjusted"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (match_operator:BI 1 "adjusted_comparison_operator"
+ [(match_operand:DI 2 "gr_register_operand" "r")
+ (match_operand:DI 3 "gr_reg_or_8bit_adjusted_operand" "rL")]))]
+ ""
+ "cmp.%C1 %0, %I0 = %r3, %2"
+ [(set_attr "itanium_class" "icmp")])
+
+(define_insn "*cmpsf_internal"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (match_operator:BI 1 "comparison_operator"
+ [(match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")]))]
+ ""
+ "fcmp.%D1 %0, %I0 = %F2, %F3"
+ [(set_attr "itanium_class" "fcmp")])
+
+(define_insn "*cmpdf_internal"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (match_operator:BI 1 "comparison_operator"
+ [(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")]))]
+ ""
+ "fcmp.%D1 %0, %I0 = %F2, %F3"
+ [(set_attr "itanium_class" "fcmp")])
+
+(define_insn "*cmpxf_internal"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (match_operator:BI 1 "comparison_operator"
+ [(match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")]))]
+ ""
+ "fcmp.%D1 %0, %I0 = %F2, %F3"
+ [(set_attr "itanium_class" "fcmp")])
+
+;; ??? Can this pattern be generated?
+
+(define_insn "*bit_zero"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (eq:BI (zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (const_int 1)
+ (match_operand:DI 2 "shift_count_operand" "M"))
+ (const_int 0)))]
+ ""
+ "tbit.z %0, %I0 = %1, %2"
+ [(set_attr "itanium_class" "tbit")])
+
+(define_insn "*bit_one"
+ [(set (match_operand:BI 0 "register_operand" "=c")
+ (ne:BI (zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (const_int 1)
+ (match_operand:DI 2 "shift_count_operand" "M"))
+ (const_int 0)))]
+ ""
+ "tbit.nz %0, %I0 = %1, %2"
+ [(set_attr "itanium_class" "tbit")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Branches
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "*br_true"
+ [(set (pc)
+ (if_then_else (match_operator 0 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c")
+ (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+ "(%J0) br.cond%+ %l2"
+ [(set_attr "itanium_class" "br")
+ (set_attr "predicable" "no")])
+
+(define_insn "*br_false"
+ [(set (pc)
+ (if_then_else (match_operator 0 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c")
+ (const_int 0)])
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ ""
+ "(%j0) br.cond%+ %l2"
+ [(set_attr "itanium_class" "br")
+ (set_attr "predicable" "no")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Counted loop operations
+;; ::
+;; ::::::::::::::::::::
+
+(define_expand "doloop_end"
+ [(use (match_operand 0 "" "")) ; loop pseudo
+ (use (match_operand 1 "" ""))] ; label
+ ""
+{
+ emit_jump_insn (gen_doloop_end_internal (gen_rtx_REG (DImode, AR_LC_REGNUM),
+ operands[1]));
+ DONE;
+})
+
+(define_insn "doloop_end_internal"
+ [(set (pc) (if_then_else (ne (match_operand:DI 0 "ar_lc_reg_operand" "")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0) (if_then_else:DI (ne (match_dup 0) (const_int 0))
+ (plus:DI (match_dup 0) (const_int -1))
+ (match_dup 0)))]
+ ""
+ "br.cloop.sptk.few %l1"
+ [(set_attr "itanium_class" "br")
+ (set_attr "predicable" "no")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Set flag operations
+;; ::
+;; ::::::::::::::::::::
+
+(define_expand "cstorebi4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:BI 2 "register_operand" "")
+ (match_operand:BI 3 "const_int_operand" "")]))]
+ ""
+ "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);")
+
+(define_expand "cstoresi4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:SI 2 "gr_register_operand" "")
+ (match_operand:SI 3 "gr_reg_or_8bit_and_adjusted_operand" "")]))]
+ ""
+ "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);")
+
+(define_expand "cstoredi4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:DI 2 "gr_register_operand" "")
+ (match_operand:DI 3 "gr_reg_or_8bit_and_adjusted_operand" "")]))]
+ ""
+ "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);")
+
+(define_expand "cstoresf4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:SF 2 "fr_reg_or_fp01_operand" "")
+ (match_operand:SF 3 "fr_reg_or_fp01_operand" "")]))]
+ ""
+ "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);")
+
+(define_expand "cstoredf4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:DF 2 "fr_reg_or_fp01_operand" "")
+ (match_operand:DF 3 "fr_reg_or_fp01_operand" "")]))]
+ ""
+ "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);")
+
+(define_expand "cstorexf4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:XF 2 "xfreg_or_fp01_operand" "")
+ (match_operand:XF 3 "xfreg_or_fp01_operand" "")]))]
+ ""
+ "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);")
+
+(define_expand "cstoretf4"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (match_operator:DI 1 "ia64_cbranch_operator"
+ [(match_operand:TF 2 "gr_register_operand" "")
+ (match_operand:TF 3 "gr_register_operand" "")]))]
+ "TARGET_HPUX"
+ "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);")
+
+;; Don't allow memory as destination here, because cmov/cmov/st is more
+;; efficient than mov/mov/cst/cst.
+
+(define_insn_and_split "*sne_internal"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (ne:DI (match_operand:BI 1 "register_operand" "c")
+ (const_int 0)))]
+ ""
+ "#"
+ "reload_completed"
+ [(cond_exec (ne (match_dup 1) (const_int 0))
+ (set (match_dup 0) (const_int 1)))
+ (cond_exec (eq (match_dup 1) (const_int 0))
+ (set (match_dup 0) (const_int 0)))]
+ ""
+ [(set_attr "itanium_class" "unknown")])
+
+(define_insn_and_split "*seq_internal"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (eq:DI (match_operand:BI 1 "register_operand" "c")
+ (const_int 0)))]
+ ""
+ "#"
+ "reload_completed"
+ [(cond_exec (ne (match_dup 1) (const_int 0))
+ (set (match_dup 0) (const_int 0)))
+ (cond_exec (eq (match_dup 1) (const_int 0))
+ (set (match_dup 0) (const_int 1)))]
+ ""
+ [(set_attr "itanium_class" "unknown")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Conditional move instructions.
+;; ::
+;; ::::::::::::::::::::
+
+;; ??? Add movXXcc patterns?
+
+;;
+;; DImode if_then_else patterns.
+;;
+
+(define_insn "*cmovdi_internal"
+ [(set (match_operand:DI 0 "not_postinc_destination_operand"
+ "= r, r, r, r, r, r, r, r, r, r, m, Q, *f,*b,*d*e")
+ (if_then_else:DI
+ (match_operator 4 "predicate_operator"
+ [(match_operand:BI 1 "register_operand"
+ "c,c,c,c,c,c,c,c,c,c,c,c,c,c,c")
+ (const_int 0)])
+ (match_operand:DI 2 "not_postinc_move_operand"
+ "rim, *f, *b,*d*e,rim,rim, rim,*f,*b,*d*e,rO,*f,rOQ,rO, rK")
+ (match_operand:DI 3 "not_postinc_move_operand"
+ "rim,rim,rim, rim, *f, *b,*d*e,*f,*b,*d*e,rO,*f,rOQ,rO, rK")))]
+ "ia64_move_ok (operands[0], operands[2])
+ && ia64_move_ok (operands[0], operands[3])"
+ { gcc_unreachable (); }
+ [(set_attr "predicable" "no")])
+
+(define_split
+ [(set (match_operand 0 "not_postinc_destination_operand" "")
+ (if_then_else
+ (match_operator 4 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "")
+ (const_int 0)])
+ (match_operand 2 "not_postinc_move_operand" "")
+ (match_operand 3 "not_postinc_move_operand" "")))]
+ "reload_completed"
+ [(const_int 0)]
+{
+ bool emitted_something = false;
+ rtx dest = operands[0];
+ rtx srct = operands[2];
+ rtx srcf = operands[3];
+ rtx cond = operands[4];
+
+ if (! rtx_equal_p (dest, srct))
+ {
+ ia64_emit_cond_move (dest, srct, cond);
+ emitted_something = true;
+ }
+ if (! rtx_equal_p (dest, srcf))
+ {
+ cond = gen_rtx_fmt_ee (GET_CODE (cond) == NE ? EQ : NE,
+ VOIDmode, operands[1], const0_rtx);
+ ia64_emit_cond_move (dest, srcf, cond);
+ emitted_something = true;
+ }
+ if (! emitted_something)
+ emit_note (NOTE_INSN_DELETED);
+ DONE;
+})
+
+;; Absolute value pattern.
+
+(define_insn "*absdi2_internal"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r,r")
+ (if_then_else:DI
+ (match_operator 4 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c,c")
+ (const_int 0)])
+ (neg:DI (match_operand:DI 2 "gr_reg_or_22bit_operand" "rI,rI"))
+ (match_operand:DI 3 "gr_reg_or_22bit_operand" "0,rI")))]
+ ""
+ "#"
+ [(set_attr "itanium_class" "ialu,unknown")
+ (set_attr "predicable" "no")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (if_then_else:DI
+ (match_operator 4 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c,c")
+ (const_int 0)])
+ (neg:DI (match_operand:DI 2 "gr_reg_or_22bit_operand" ""))
+ (match_operand:DI 3 "gr_reg_or_22bit_operand" "")))]
+ "reload_completed && rtx_equal_p (operands[0], operands[3])"
+ [(cond_exec
+ (match_dup 4)
+ (set (match_dup 0)
+ (neg:DI (match_dup 2))))]
+ "")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (if_then_else:DI
+ (match_operator 4 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c,c")
+ (const_int 0)])
+ (neg:DI (match_operand:DI 2 "gr_reg_or_22bit_operand" ""))
+ (match_operand:DI 3 "gr_reg_or_22bit_operand" "")))]
+ "reload_completed"
+ [(cond_exec
+ (match_dup 4)
+ (set (match_dup 0) (neg:DI (match_dup 2))))
+ (cond_exec
+ (match_dup 5)
+ (set (match_dup 0) (match_dup 3)))]
+{
+ operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? EQ : NE,
+ VOIDmode, operands[1], const0_rtx);
+})
+
+;;
+;; SImode if_then_else patterns.
+;;
+
+(define_insn "*cmovsi_internal"
+ [(set (match_operand:SI 0 "not_postinc_destination_operand"
+ "=r,m,*f,r,m,*f,r,m,*f")
+ (if_then_else:SI
+ (match_operator 4 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c,c,c,c,c,c,c,c,c")
+ (const_int 0)])
+ (match_operand:SI 2 "not_postinc_move_operand"
+ "0,0,0,rim*f,rO,rO,rim*f,rO,rO")
+ (match_operand:SI 3 "not_postinc_move_operand"
+ "rim*f,rO,rO,0,0,0,rim*f,rO,rO")))]
+ "ia64_move_ok (operands[0], operands[2])
+ && ia64_move_ok (operands[0], operands[3])"
+ { gcc_unreachable (); }
+ [(set_attr "predicable" "no")])
+
+(define_insn "*abssi2_internal"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r,r")
+ (if_then_else:SI
+ (match_operator 4 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c,c")
+ (const_int 0)])
+ (neg:SI (match_operand:SI 3 "gr_reg_or_22bit_operand" "rI,rI"))
+ (match_operand:SI 2 "gr_reg_or_22bit_operand" "0,rI")))]
+ ""
+ "#"
+ [(set_attr "itanium_class" "ialu,unknown")
+ (set_attr "predicable" "no")])
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (if_then_else:SI
+ (match_operator 4 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c,c")
+ (const_int 0)])
+ (neg:SI (match_operand:SI 2 "gr_reg_or_22bit_operand" ""))
+ (match_operand:SI 3 "gr_reg_or_22bit_operand" "")))]
+ "reload_completed && rtx_equal_p (operands[0], operands[3])"
+ [(cond_exec
+ (match_dup 4)
+ (set (match_dup 0)
+ (neg:SI (match_dup 2))))]
+ "")
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (if_then_else:SI
+ (match_operator 4 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c,c")
+ (const_int 0)])
+ (neg:SI (match_operand:SI 2 "gr_reg_or_22bit_operand" ""))
+ (match_operand:SI 3 "gr_reg_or_22bit_operand" "")))]
+ "reload_completed"
+ [(cond_exec
+ (match_dup 4)
+ (set (match_dup 0) (neg:SI (match_dup 2))))
+ (cond_exec
+ (match_dup 5)
+ (set (match_dup 0) (match_dup 3)))]
+{
+ operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? EQ : NE,
+ VOIDmode, operands[1], const0_rtx);
+})
+
+(define_insn_and_split "*cond_opsi2_internal"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r")
+ (match_operator:SI 5 "condop_operator"
+ [(if_then_else:SI
+ (match_operator 6 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c")
+ (const_int 0)])
+ (match_operand:SI 2 "gr_register_operand" "r")
+ (match_operand:SI 3 "gr_register_operand" "r"))
+ (match_operand:SI 4 "gr_register_operand" "r")]))]
+ ""
+ "#"
+ "reload_completed"
+ [(cond_exec
+ (match_dup 6)
+ (set (match_dup 0) (match_op_dup:SI 5 [(match_dup 2) (match_dup 4)])))
+ (cond_exec
+ (match_dup 7)
+ (set (match_dup 0) (match_op_dup:SI 5 [(match_dup 3) (match_dup 4)])))]
+{
+ operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[6]) == NE ? EQ : NE,
+ VOIDmode, operands[1], const0_rtx);
+}
+ [(set_attr "itanium_class" "ialu")
+ (set_attr "predicable" "no")])
+
+
+(define_insn_and_split "*cond_opsi2_internal_b"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r")
+ (match_operator:SI 5 "condop_operator"
+ [(match_operand:SI 4 "gr_register_operand" "r")
+ (if_then_else:SI
+ (match_operator 6 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c")
+ (const_int 0)])
+ (match_operand:SI 2 "gr_register_operand" "r")
+ (match_operand:SI 3 "gr_register_operand" "r"))]))]
+ ""
+ "#"
+ "reload_completed"
+ [(cond_exec
+ (match_dup 6)
+ (set (match_dup 0) (match_op_dup:SI 5 [(match_dup 4) (match_dup 2)])))
+ (cond_exec
+ (match_dup 7)
+ (set (match_dup 0) (match_op_dup:SI 5 [(match_dup 4) (match_dup 3)])))]
+{
+ operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[6]) == NE ? EQ : NE,
+ VOIDmode, operands[1], const0_rtx);
+}
+ [(set_attr "itanium_class" "ialu")
+ (set_attr "predicable" "no")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Call and branch instructions
+;; ::
+;; ::::::::::::::::::::
+
+;; Subroutine call instruction returning no value. Operand 0 is the function
+;; to call; operand 1 is the number of bytes of arguments pushed (in mode
+;; `SImode', except it is normally a `const_int'); operand 2 is the number of
+;; registers used as operands.
+
+;; On most machines, operand 2 is not actually stored into the RTL pattern. It
+;; is supplied for the sake of some RISC machines which need to put this
+;; information into the assembler code; they can put it in the RTL instead of
+;; operand 1.
+
+(define_expand "call"
+ [(use (match_operand:DI 0 "" ""))
+ (use (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (use (match_operand 3 "" ""))]
+ ""
+{
+ ia64_expand_call (NULL_RTX, operands[0], operands[2], false);
+ DONE;
+})
+
+(define_expand "sibcall"
+ [(use (match_operand:DI 0 "" ""))
+ (use (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (use (match_operand 3 "" ""))]
+ ""
+{
+ ia64_expand_call (NULL_RTX, operands[0], operands[2], true);
+ DONE;
+})
+
+;; Subroutine call instruction returning a value. Operand 0 is the hard
+;; register in which the value is returned. There are three more operands,
+;; the same as the three operands of the `call' instruction (but with numbers
+;; increased by one).
+;;
+;; Subroutines that return `BLKmode' objects use the `call' insn.
+
+(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 "" ""))]
+ ""
+{
+ ia64_expand_call (operands[0], operands[1], operands[3], false);
+ DONE;
+})
+
+(define_expand "sibcall_value"
+ [(use (match_operand 0 "" ""))
+ (use (match_operand:DI 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (use (match_operand 3 "" ""))
+ (use (match_operand 4 "" ""))]
+ ""
+{
+ ia64_expand_call (operands[0], operands[1], operands[3], true);
+ DONE;
+})
+
+;; Call subroutine returning any type.
+
+(define_expand "untyped_call"
+ [(parallel [(call (match_operand 0 "" "")
+ (const_int 0))
+ (match_operand 1 "" "")
+ (match_operand 2 "" "")])]
+ ""
+{
+ int i;
+
+ emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
+
+ for (i = 0; i < XVECLEN (operands[2], 0); i++)
+ {
+ rtx set = XVECEXP (operands[2], 0, i);
+ emit_move_insn (SET_DEST (set), SET_SRC (set));
+ }
+
+ /* The optimizer does not know that the call sets the function value
+ registers we stored in the result block. We avoid problems by
+ claiming that all hard registers are used and clobbered at this
+ point. */
+ emit_insn (gen_blockage ());
+
+ DONE;
+})
+
+(define_insn "call_nogp"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "?b,s"))
+ (const_int 0))
+ (clobber (match_operand:DI 1 "register_operand" "=b,b"))]
+ ""
+ "br.call%+.many %1 = %0"
+ [(set_attr "itanium_class" "br,scall")])
+
+(define_insn "call_value_nogp"
+ [(set (match_operand 0 "" "=X,X")
+ (call (mem:DI (match_operand:DI 1 "call_operand" "?b,s"))
+ (const_int 0)))
+ (clobber (match_operand:DI 2 "register_operand" "=b,b"))]
+ ""
+ "br.call%+.many %2 = %1"
+ [(set_attr "itanium_class" "br,scall")])
+
+(define_insn "sibcall_nogp"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "?b,s"))
+ (const_int 0))]
+ ""
+ "br%+.many %0"
+ [(set_attr "itanium_class" "br,scall")])
+
+(define_insn "call_gp"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "?r,s"))
+ (const_int 1))
+ (clobber (match_operand:DI 1 "register_operand" "=b,b"))
+ (clobber (match_scratch:DI 2 "=&r,X"))
+ (clobber (match_scratch:DI 3 "=b,X"))]
+ ""
+ "#"
+ [(set_attr "itanium_class" "br,scall")])
+
+;; Irritatingly, we don't have access to INSN within the split body.
+;; See commentary in ia64_split_call as to why these aren't peep2.
+(define_split
+ [(call (mem (match_operand 0 "call_operand" ""))
+ (const_int 1))
+ (clobber (match_operand:DI 1 "register_operand" ""))
+ (clobber (match_scratch:DI 2 ""))
+ (clobber (match_scratch:DI 3 ""))]
+ "reload_completed && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+ [(const_int 0)]
+{
+ ia64_split_call (NULL_RTX, operands[0], operands[1], operands[2],
+ operands[3], true, false);
+ DONE;
+})
+
+(define_split
+ [(call (mem (match_operand 0 "call_operand" ""))
+ (const_int 1))
+ (clobber (match_operand:DI 1 "register_operand" ""))
+ (clobber (match_scratch:DI 2 ""))
+ (clobber (match_scratch:DI 3 ""))]
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_split_call (NULL_RTX, operands[0], operands[1], operands[2],
+ operands[3], false, false);
+ DONE;
+})
+
+(define_insn "call_value_gp"
+ [(set (match_operand 0 "" "=X,X")
+ (call (mem:DI (match_operand:DI 1 "call_operand" "?r,s"))
+ (const_int 1)))
+ (clobber (match_operand:DI 2 "register_operand" "=b,b"))
+ (clobber (match_scratch:DI 3 "=&r,X"))
+ (clobber (match_scratch:DI 4 "=b,X"))]
+ ""
+ "#"
+ [(set_attr "itanium_class" "br,scall")])
+
+(define_split
+ [(set (match_operand 0 "" "")
+ (call (mem:DI (match_operand:DI 1 "call_operand" ""))
+ (const_int 1)))
+ (clobber (match_operand:DI 2 "register_operand" ""))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (match_scratch:DI 4 ""))]
+ "reload_completed && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+ [(const_int 0)]
+{
+ ia64_split_call (operands[0], operands[1], operands[2], operands[3],
+ operands[4], true, false);
+ DONE;
+})
+
+(define_split
+ [(set (match_operand 0 "" "")
+ (call (mem:DI (match_operand:DI 1 "call_operand" ""))
+ (const_int 1)))
+ (clobber (match_operand:DI 2 "register_operand" ""))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (match_scratch:DI 4 ""))]
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_split_call (operands[0], operands[1], operands[2], operands[3],
+ operands[4], false, false);
+ DONE;
+})
+
+(define_insn_and_split "sibcall_gp"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "?r,s"))
+ (const_int 1))
+ (clobber (match_scratch:DI 1 "=&r,X"))
+ (clobber (match_scratch:DI 2 "=b,X"))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_split_call (NULL_RTX, operands[0], NULL_RTX, operands[1],
+ operands[2], true, true);
+ DONE;
+}
+ [(set_attr "itanium_class" "br")])
+
+(define_insn "return_internal"
+ [(return)
+ (use (match_operand:DI 0 "register_operand" "b"))]
+ ""
+ "br.ret.sptk.many %0"
+ [(set_attr "itanium_class" "br")])
+
+(define_insn "return"
+ [(return)]
+ "ia64_direct_return ()"
+ "br.ret.sptk.many rp"
+ [(set_attr "itanium_class" "br")])
+
+(define_insn "*return_true"
+ [(set (pc)
+ (if_then_else (match_operator 0 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c")
+ (const_int 0)])
+ (return)
+ (pc)))]
+ "ia64_direct_return ()"
+ "(%J0) br.ret%+.many rp"
+ [(set_attr "itanium_class" "br")
+ (set_attr "predicable" "no")])
+
+(define_insn "*return_false"
+ [(set (pc)
+ (if_then_else (match_operator 0 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c")
+ (const_int 0)])
+ (pc)
+ (return)))]
+ "ia64_direct_return ()"
+ "(%j0) br.ret%+.many rp"
+ [(set_attr "itanium_class" "br")
+ (set_attr "predicable" "no")])
+
+(define_insn "jump"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ ""
+ "br %l0"
+ [(set_attr "itanium_class" "br")])
+
+(define_insn "indirect_jump"
+ [(set (pc) (match_operand:DI 0 "register_operand" "b"))]
+ ""
+ "br %0"
+ [(set_attr "itanium_class" "br")])
+
+(define_expand "tablejump"
+ [(parallel [(set (pc) (match_operand 0 "memory_operand" ""))
+ (use (label_ref (match_operand 1 "" "")))])]
+ ""
+{
+ rtx op0 = operands[0];
+ rtx addr;
+
+ /* ??? Bother -- do_tablejump is "helpful" and pulls the table
+ element into a register without bothering to see whether that
+ is necessary given the operand predicate. Check for MEM just
+ in case someone fixes this. */
+ if (GET_CODE (op0) == MEM)
+ addr = XEXP (op0, 0);
+ else
+ {
+ /* Otherwise, cheat and guess that the previous insn in the
+ stream was the memory load. Grab the address from that.
+ Note we have to momentarily pop out of the sequence started
+ by the insn-emit wrapper in order to grab the last insn. */
+ rtx last, set;
+
+ end_sequence ();
+ last = get_last_insn ();
+ start_sequence ();
+ set = single_set (last);
+
+ gcc_assert (rtx_equal_p (SET_DEST (set), op0)
+ && GET_CODE (SET_SRC (set)) == MEM);
+ addr = XEXP (SET_SRC (set), 0);
+ gcc_assert (!rtx_equal_p (addr, op0));
+ }
+
+ /* Jump table elements are stored pc-relative. That is, a displacement
+ from the entry to the label. Thus to convert to an absolute address
+ we add the address of the memory from which the value is loaded. */
+ operands[0] = expand_simple_binop (DImode, PLUS, op0, addr,
+ NULL_RTX, 0, OPTAB_DIRECT);
+})
+
+(define_insn "*tablejump_internal"
+ [(set (pc) (match_operand:DI 0 "register_operand" "b"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "br %0"
+ [(set_attr "itanium_class" "br")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Prologue and Epilogue instructions
+;; ::
+;; ::::::::::::::::::::
+
+(define_expand "prologue"
+ [(const_int 1)]
+ ""
+{
+ ia64_expand_prologue ();
+ DONE;
+})
+
+(define_expand "epilogue"
+ [(return)]
+ ""
+{
+ ia64_expand_epilogue (0);
+ DONE;
+})
+
+(define_expand "sibcall_epilogue"
+ [(return)]
+ ""
+{
+ ia64_expand_epilogue (1);
+ DONE;
+})
+
+;; This prevents the scheduler from moving the SP decrement past FP-relative
+;; stack accesses. This is the same as adddi3 plus the extra set.
+;; Explicit predicated version of insn needed to check by CODE_FOR_
+;; in ia64_single_set, where despite of 2 sets this define_insn should be OK.
+
+(define_insn "prologue_allocate_stack"
+ [(set (match_operand:DI 0 "register_operand" "=r,r,r")
+ (plus:DI (match_operand:DI 1 "register_operand" "%r,r,a")
+ (match_operand:DI 2 "gr_reg_or_22bit_operand" "r,I,J")))
+ (set (match_operand:DI 3 "register_operand" "+r,r,r")
+ (match_dup 3))]
+ ""
+ "@
+ add %0 = %1, %2
+ adds %0 = %2, %1
+ addl %0 = %2, %1"
+ [(set_attr "itanium_class" "ialu")
+ (set_attr "predicable" "no")])
+
+(define_insn "prologue_allocate_stack_pr"
+ [(cond_exec (match_operator 0 ("predicate_operator")
+ [(match_operand:BI 1 ("register_operand") ("c,c,c"))
+ (const_int 0)])
+ (parallel
+ [(set (match_operand:DI 2 "register_operand" "=r,r,r")
+ (plus:DI (match_operand:DI 3 "register_operand" "%r,r,a")
+ (match_operand:DI 4 "gr_reg_or_22bit_operand" "r,I,J")))
+ (set (match_operand:DI 5 "register_operand" "+r,r,r")
+ (match_dup 5))]))]
+ ""
+ "@
+ (%J0) add %2 = %3, %4
+ (%J0) adds %2 = %3, %4
+ (%J0) addl %2 = %3, %4"
+ [(set_attr "itanium_class" "ialu")
+ (set_attr "predicable" "no")])
+
+;; This prevents the scheduler from moving the SP restore past FP-relative
+;; stack accesses. This is similar to movdi plus the extra set.
+;; Explicit predicated version of insn needed to check by CODE_FOR_
+;; in ia64_single_set, where despite of 2 sets this define_insn should be OK.
+
+(define_insn "epilogue_deallocate_stack"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (match_operand:DI 1 "register_operand" "+r"))
+ (set (match_dup 1) (match_dup 1))]
+ ""
+ "mov %0 = %1"
+ [(set_attr "itanium_class" "ialu")
+ (set_attr "predicable" "no")])
+
+(define_insn "epilogue_deallocate_stack_pr"
+ [(cond_exec (match_operator 0 ("predicate_operator")
+ [(match_operand:BI 1 ("register_operand") ("c"))
+ (const_int 0)])
+ (parallel
+ [(set (match_operand:DI 2 "register_operand" "=r")
+ (match_operand:DI 3 "register_operand" "+r"))
+ (set (match_dup 3) (match_dup 3))]))]
+ ""
+ "(%J0) mov %2 = %3"
+ [(set_attr "itanium_class" "ialu")
+ (set_attr "predicable" "no")])
+
+;; As USE insns aren't meaningful after reload, this is used instead
+;; to prevent deleting instructions setting registers for EH handling
+(define_insn "prologue_use"
+ [(unspec:DI [(match_operand:DI 0 "register_operand" "")]
+ UNSPEC_PROLOGUE_USE)]
+ ""
+ ""
+ [(set_attr "itanium_class" "ignore")
+ (set_attr "predicable" "no")
+ (set_attr "empty" "yes")])
+
+;; Allocate a new register frame.
+
+(define_insn "alloc"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec_volatile:DI [(const_int 0)] UNSPECV_ALLOC))
+ (use (match_operand:DI 1 "const_int_operand" "i"))
+ (use (match_operand:DI 2 "const_int_operand" "i"))
+ (use (match_operand:DI 3 "const_int_operand" "i"))
+ (use (match_operand:DI 4 "const_int_operand" "i"))]
+ ""
+ "alloc %0 = ar.pfs, %1, %2, %3, %4"
+ [(set_attr "itanium_class" "syst_m0")
+ (set_attr "predicable" "no")
+ (set_attr "first_insn" "yes")])
+
+;; Modifies ar.unat
+(define_expand "gr_spill"
+ [(parallel [(set (match_operand:DI 0 "memory_operand" "=m")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_GR_SPILL))
+ (clobber (match_dup 3))])]
+ ""
+ "operands[3] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);")
+
+(define_insn "gr_spill_internal"
+ [(set (match_operand:DI 0 "destination_operand" "=m")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_GR_SPILL))
+ (clobber (match_operand:DI 3 "register_operand" ""))]
+ ""
+{
+ /* Note that we use a C output pattern here to avoid the predicate
+ being automatically added before the .mem.offset directive. */
+ return ".mem.offset %2, 0\;%,st8.spill %0 = %1%P0";
+}
+ [(set_attr "itanium_class" "st")])
+
+;; Reads ar.unat
+(define_expand "gr_restore"
+ [(parallel [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_GR_RESTORE))
+ (use (match_dup 3))])]
+ ""
+ "operands[3] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);")
+
+(define_insn "gr_restore_internal"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_GR_RESTORE))
+ (use (match_operand:DI 3 "register_operand" ""))]
+ ""
+ { return ".mem.offset %2, 0\;%,ld8.fill %0 = %1%P1"; }
+ [(set_attr "itanium_class" "ld")])
+
+(define_insn "fr_spill"
+ [(set (match_operand:XF 0 "destination_operand" "=m")
+ (unspec:XF [(match_operand:XF 1 "register_operand" "f")]
+ UNSPEC_FR_SPILL))]
+ ""
+ "stf.spill %0 = %1%P0"
+ [(set_attr "itanium_class" "stf")])
+
+(define_insn "fr_restore"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "memory_operand" "m")]
+ UNSPEC_FR_RESTORE))]
+ ""
+ "ldf.fill %0 = %1%P1"
+ [(set_attr "itanium_class" "fld")])
+
+;; ??? The explicit stop is not ideal. It would be better if
+;; rtx_needs_barrier took care of this, but this is something that can be
+;; fixed later. This avoids an RSE DV.
+
+(define_insn "bsp_value"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(const_int 0)] UNSPEC_BSP_VALUE))]
+ ""
+ "*
+{
+ return \";;\;%,mov %0 = ar.bsp\";
+}"
+ [(set_attr "itanium_class" "frar_i")])
+
+(define_insn "set_bsp"
+ [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
+ UNSPECV_SET_BSP)]
+ ""
+ "flushrs
+ mov r19=ar.rsc
+ ;;
+ and r19=0x1c,r19
+ ;;
+ mov ar.rsc=r19
+ ;;
+ mov ar.bspstore=%0
+ ;;
+ or r19=0x3,r19
+ ;;
+ loadrs
+ invala
+ ;;
+ mov ar.rsc=r19"
+ [(set_attr "itanium_class" "unknown")
+ (set_attr "predicable" "no")])
+
+;; ??? The explicit stops are not ideal. It would be better if
+;; rtx_needs_barrier took care of this, but this is something that can be
+;; fixed later. This avoids an RSE DV.
+
+(define_insn "flushrs"
+ [(unspec [(const_int 0)] UNSPEC_FLUSHRS)]
+ ""
+ ";;\;flushrs\;;;"
+ [(set_attr "itanium_class" "rse_m")
+ (set_attr "predicable" "no")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Miscellaneous instructions
+;; ::
+;; ::::::::::::::::::::
+
+;; ??? Emitting a NOP instruction isn't very useful. This should probably
+;; be emitting ";;" to force a break in the instruction packing.
+
+;; No operation, needed in case the user uses -g but not -O.
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop 0"
+ [(set_attr "itanium_class" "nop")])
+
+(define_insn "nop_m"
+ [(const_int 1)]
+ ""
+ "nop.m 0"
+ [(set_attr "itanium_class" "nop_m")])
+
+(define_insn "nop_i"
+ [(const_int 2)]
+ ""
+ "nop.i 0"
+ [(set_attr "itanium_class" "nop_i")])
+
+(define_insn "nop_f"
+ [(const_int 3)]
+ ""
+ "nop.f 0"
+ [(set_attr "itanium_class" "nop_f")])
+
+(define_insn "nop_b"
+ [(const_int 4)]
+ ""
+ "nop.b 0"
+ [(set_attr "itanium_class" "nop_b")])
+
+(define_insn "nop_x"
+ [(const_int 5)]
+ ""
+ ""
+ [(set_attr "itanium_class" "nop_x")
+ (set_attr "empty" "yes")])
+
+;; The following insn will be never generated. It is used only by
+;; insn scheduler to change state before advancing cycle.
+(define_insn "pre_cycle"
+ [(const_int 6)]
+ ""
+ ""
+ [(set_attr "itanium_class" "pre_cycle")])
+
+(define_insn "bundle_selector"
+ [(unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BUNDLE_SELECTOR)]
+ ""
+ { return get_bundle_name (INTVAL (operands[0])); }
+ [(set_attr "itanium_class" "ignore")
+ (set_attr "predicable" "no")])
+
+;; Pseudo instruction that prevents the scheduler from moving code above this
+;; point.
+(define_insn "blockage"
+ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
+ ""
+ ""
+ [(set_attr "itanium_class" "ignore")
+ (set_attr "predicable" "no")])
+
+(define_insn "insn_group_barrier"
+ [(unspec_volatile [(match_operand 0 "const_int_operand" "")]
+ UNSPECV_INSN_GROUP_BARRIER)]
+ ""
+ ";;"
+ [(set_attr "itanium_class" "stop_bit")
+ (set_attr "predicable" "no")
+ (set_attr "empty" "yes")])
+
+(define_expand "trap"
+ [(trap_if (const_int 1) (const_int 0))]
+ ""
+ "")
+
+;; ??? We don't have a match-any slot type. Setting the type to unknown
+;; produces worse code that setting the slot type to A.
+
+(define_insn "*trap"
+ [(trap_if (const_int 1) (match_operand 0 "const_int_operand" ""))]
+ ""
+ "break %0"
+ [(set_attr "itanium_class" "chk_s_i")])
+
+(define_expand "ctrapbi4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:BI 1 "register_operand" "")
+ (match_operand:BI 2 "const_int_operand" "")])
+ (match_operand 3 "" ""))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "ctrapsi4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_reg_or_8bit_and_adjusted_operand" "")])
+ (match_operand 3 "" ""))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "ctrapdi4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:DI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "gr_reg_or_8bit_and_adjusted_operand" "")])
+ (match_operand 3 "" ""))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "ctrapsf4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:SF 1 "fr_reg_or_fp01_operand" "")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "")])
+ (match_operand 3 "" ""))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "ctrapdf4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:DF 1 "fr_reg_or_fp01_operand" "")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "")])
+ (match_operand 3 "" ""))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "ctrapxf4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:XF 1 "xfreg_or_fp01_operand" "")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "")])
+ (match_operand 3 "" ""))]
+ ""
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+(define_expand "ctraptf4"
+ [(trap_if (match_operator 0 "ia64_cbranch_operator"
+ [(match_operand:TF 1 "gr_register_operand" "")
+ (match_operand:TF 2 "gr_register_operand" "")])
+ (match_operand 3 "" ""))]
+ "TARGET_HPUX"
+ "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);")
+
+
+(define_insn "*conditional_trap"
+ [(trap_if (match_operator 0 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c")
+ (const_int 0)])
+ (match_operand 2 "const_int_operand" ""))]
+ ""
+ "(%J0) break %2"
+ [(set_attr "itanium_class" "chk_s_i")
+ (set_attr "predicable" "no")])
+
+(define_insn "break_f"
+ [(unspec_volatile [(const_int 0)] UNSPECV_BREAK)]
+ ""
+ "break.f 0"
+ [(set_attr "itanium_class" "nop_f")])
+
+(define_insn "prefetch"
+ [(prefetch (match_operand:DI 0 "address_operand" "p")
+ (match_operand:DI 1 "const_int_operand" "n")
+ (match_operand:DI 2 "const_int_operand" "n"))]
+ ""
+{
+ static const char * const alt[2][4] = {
+ {
+ "%,lfetch.nta [%0]",
+ "%,lfetch.nt1 [%0]",
+ "%,lfetch.nt2 [%0]",
+ "%,lfetch [%0]"
+ },
+ {
+ "%,lfetch.excl.nta [%0]",
+ "%,lfetch.excl.nt1 [%0]",
+ "%,lfetch.excl.nt2 [%0]",
+ "%,lfetch.excl [%0]"
+ }
+ };
+ int i = (INTVAL (operands[1]));
+ int j = (INTVAL (operands[2]));
+
+ gcc_assert (i == 0 || i == 1);
+ gcc_assert (j >= 0 && j <= 3);
+ return alt[i][j];
+}
+ [(set_attr "itanium_class" "lfetch")])
+
+;; Non-local goto support.
+
+(define_expand "save_stack_nonlocal"
+ [(use (match_operand:OI 0 "memory_operand" ""))
+ (use (match_operand:DI 1 "register_operand" ""))]
+ ""
+{
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode,
+ \"__ia64_save_stack_nonlocal\"),
+ LCT_NORMAL, VOIDmode, 2, XEXP (operands[0], 0), Pmode,
+ operands[1], Pmode);
+ DONE;
+})
+
+(define_expand "nonlocal_goto"
+ [(use (match_operand 0 "general_operand" ""))
+ (use (match_operand 1 "general_operand" ""))
+ (use (match_operand 2 "general_operand" ""))
+ (use (match_operand 3 "general_operand" ""))]
+ ""
+{
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, \"__ia64_nonlocal_goto\"),
+ LCT_NORETURN, VOIDmode, 3,
+ operands[1], Pmode,
+ copy_to_reg (XEXP (operands[2], 0)), Pmode,
+ operands[3], Pmode);
+ emit_barrier ();
+ DONE;
+})
+
+(define_insn_and_split "nonlocal_goto_receiver"
+ [(unspec_volatile [(const_int 0)] UNSPECV_GOTO_RECEIVER)]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_reload_gp ();
+ DONE;
+})
+
+(define_insn_and_split "builtin_setjmp_receiver"
+ [(unspec_volatile [(match_operand:DI 0 "" "")] UNSPECV_SETJMP_RECEIVER)]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_reload_gp ();
+ 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"))]
+ ""
+{
+ rtx bsp = gen_rtx_REG (Pmode, 10);
+ rtx sp = gen_rtx_REG (Pmode, 9);
+
+ if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != 10)
+ {
+ emit_move_insn (bsp, operands[0]);
+ operands[0] = bsp;
+ }
+ if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 9)
+ {
+ emit_move_insn (sp, operands[2]);
+ operands[2] = sp;
+ }
+ emit_use (sp);
+ emit_use (bsp);
+
+ cfun->machine->ia64_eh_epilogue_sp = sp;
+ cfun->machine->ia64_eh_epilogue_bsp = bsp;
+})
+
+;; Builtin apply support.
+
+(define_expand "restore_stack_nonlocal"
+ [(use (match_operand:DI 0 "register_operand" ""))
+ (use (match_operand:OI 1 "memory_operand" ""))]
+ ""
+{
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode,
+ "__ia64_restore_stack_nonlocal"),
+ LCT_NORMAL, VOIDmode, 1,
+ copy_to_reg (XEXP (operands[1], 0)), Pmode);
+ DONE;
+})
+
+
+;; Predication.
+
+(define_cond_exec
+ [(match_operator 0 "predicate_operator"
+ [(match_operand:BI 1 "register_operand" "c")
+ (const_int 0)])]
+ ""
+ "(%J0)")
+
+(define_insn "pred_rel_mutex"
+ [(set (match_operand:BI 0 "register_operand" "+c")
+ (unspec:BI [(match_dup 0)] UNSPEC_PRED_REL_MUTEX))]
+ ""
+ ".pred.rel.mutex %0, %I0"
+ [(set_attr "itanium_class" "ignore")
+ (set_attr "predicable" "no")])
+
+(define_insn "safe_across_calls_all"
+ [(unspec_volatile [(const_int 0)] UNSPECV_PSAC_ALL)]
+ ""
+ ".pred.safe_across_calls p1-p63"
+ [(set_attr "itanium_class" "ignore")
+ (set_attr "predicable" "no")])
+
+(define_insn "safe_across_calls_normal"
+ [(unspec_volatile [(const_int 0)] UNSPECV_PSAC_NORMAL)]
+ ""
+{
+ emit_safe_across_calls ();
+ return "";
+}
+ [(set_attr "itanium_class" "ignore")
+ (set_attr "predicable" "no")])
+
+;; UNSPEC instruction definition to "swizzle" 32-bit pointer into 64-bit
+;; pointer. This is used by the HP-UX 32 bit mode.
+
+(define_insn "ptr_extend"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (unspec:DI [(match_operand:SI 1 "gr_register_operand" "r")]
+ UNSPEC_ADDP4))]
+ ""
+ "addp4 %0 = 0,%1"
+ [(set_attr "itanium_class" "ialu")])
+
+;;
+;; Optimizations for ptr_extend
+
+(define_insn "ptr_extend_plus_imm"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (unspec:DI
+ [(plus:SI (match_operand:SI 1 "basereg_operand" "r")
+ (match_operand:SI 2 "gr_reg_or_14bit_operand" "rI"))]
+ UNSPEC_ADDP4))]
+ "addp4_optimize_ok (operands[1], operands[2])"
+ "addp4 %0 = %2, %1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*ptr_extend_plus_2"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (unspec:DI
+ [(plus:SI (match_operand:SI 1 "gr_register_operand" "r")
+ (match_operand:SI 2 "basereg_operand" "r"))]
+ UNSPEC_ADDP4))]
+ "addp4_optimize_ok (operands[1], operands[2])"
+ "addp4 %0 = %1, %2"
+ [(set_attr "itanium_class" "ialu")])
+
+;;
+;; Get instruction pointer
+
+(define_insn "ip_value"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (pc))]
+ ""
+ "mov %0 = ip"
+ [(set_attr "itanium_class" "frbr")])
+
+;;
+;; Stack checking
+
+(define_insn "probe_stack_address"
+ [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
+ UNSPECV_PROBE_STACK_ADDRESS)]
+ ""
+ "probe.w.fault %0, 0"
+[(set_attr "itanium_class" "chk_s_i")])
+
+(define_insn "probe_stack_range"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "register_operand" "r")]
+ UNSPECV_PROBE_STACK_RANGE))]
+ ""
+ "* return output_probe_stack_range (operands[0], operands[2]);"
+ [(set_attr "itanium_class" "unknown")
+ (set_attr "predicable" "no")])
+
+;; Vector operations
+(include "vect.md")
+;; Atomic operations
+(include "sync.md")
+;; New division operations
+(include "div.md")