freebsd-dev/contrib/gcc/config/ia64/ia64.md

5912 lines
187 KiB
Markdown
Raw Normal View History

;; IA-64 Machine description template
2004-07-28 03:11:36 +00:00
;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
;; Free Software Foundation, Inc.
;; Contributed by James E. Wilson <wilson@cygnus.com> and
;; David Mosberger <davidm@hpl.hp.com>.
2004-07-28 03:11:36 +00:00
;; This file is part of GCC.
2004-07-28 03:11:36 +00:00
;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
2004-07-28 03:11:36 +00:00
;; 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
2004-07-28 03:11:36 +00:00
;; along with GCC; see the file COPYING. If not, write to
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;; ??? 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.
2003-07-11 03:40:53 +00:00
(define_constants
[; Relocations
(UNSPEC_LTOFF_DTPMOD 0)
(UNSPEC_LTOFF_DTPREL 1)
(UNSPEC_DTPREL 2)
(UNSPEC_LTOFF_TPREL 3)
(UNSPEC_TPREL 4)
(UNSPEC_LD_BASE 9)
(UNSPEC_GR_SPILL 10)
(UNSPEC_GR_RESTORE 11)
(UNSPEC_FR_SPILL 12)
(UNSPEC_FR_RESTORE 13)
(UNSPEC_FR_RECIP_APPROX 14)
(UNSPEC_PRED_REL_MUTEX 15)
2004-07-28 03:11:36 +00:00
(UNSPEC_GETF_EXP 16)
2003-07-11 03:40:53 +00:00
(UNSPEC_PIC_CALL 17)
(UNSPEC_MF 18)
(UNSPEC_CMPXCHG_ACQ 19)
(UNSPEC_FETCHADD_ACQ 20)
(UNSPEC_BSP_VALUE 21)
(UNSPEC_FLUSHRS 22)
(UNSPEC_BUNDLE_SELECTOR 23)
(UNSPEC_ADDP4 24)
(UNSPEC_PROLOGUE_USE 25)
2003-11-07 02:43:04 +00:00
(UNSPEC_RET_ADDR 26)
2004-07-28 03:11:36 +00:00
(UNSPEC_SETF_EXP 27)
(UNSPEC_FR_SQRT_RECIP_APPROX 28)
2003-07-11 03:40:53 +00:00
])
(define_constants
[(UNSPECV_ALLOC 0)
(UNSPECV_BLOCKAGE 1)
(UNSPECV_INSN_GROUP_BARRIER 2)
(UNSPECV_BREAK 3)
(UNSPECV_SET_BSP 4)
(UNSPECV_PSAC_ALL 5) ; pred.safe_across_calls
(UNSPECV_PSAC_NORMAL 6)
(UNSPECV_SETJMP_RECEIVER 7)
])
;; ::::::::::::::::::::
;; ::
;; :: Attributes
;; ::
;; ::::::::::::::::::::
2004-07-28 03:11:36 +00:00
;; Processor type. This attribute must exactly match the processor_type
;; enumeration in ia64.h.
(define_attr "cpu" "itanium,itanium2" (const (symbol_ref "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).
2003-07-11 03:40:53 +00:00
(define_attr "itanium_class" "unknown,ignore,stop_bit,br,fcmp,fcvtfx,fld,
fmac,fmisc,frar_i,frar_m,frbr,frfr,frpr,ialu,icmp,ilog,ishf,ld,
chk_s,long_i,mmmul,mmshf,mmshfi,rse_m,scall,sem,stf,st,syst_m0,
2004-07-28 03:11:36 +00:00
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"
2003-07-11 03:40:53 +00:00
(const_string "unknown"))
;; chk_s 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,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,ialu,icmp,ilog") (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"))
2004-07-28 03:11:36 +00:00
;; Empty. True iff this insn does not generate any code.
(define_attr "empty" "no,yes" (const_string "no"))
2004-07-28 03:11:36 +00:00
;; 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")
;;(automata_option "no-minimization")
(include "itanium1.md")
(include "itanium2.md")
;; ::::::::::::::::::::
;; ::
;; :: 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 "register_operand" "=c,c,c")
(match_operand:CCI 1 "nonmemory_operand" "O,n,c"))]
""
"@
cmp.ne %0, p0 = r0, r0
cmp.eq %0, p0 = r0, r0
(%1) cmp.eq.unc %0, p0 = r0, r0"
[(set_attr "itanium_class" "icmp")
(set_attr "predicable" "no")])
(define_insn "movbi"
[(set (match_operand:BI 0 "nonimmediate_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")])
(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))
2003-07-11 03:40:53 +00:00
(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" ""))]
""
{
2003-07-11 03:40:53 +00:00
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")])
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
{
2003-07-11 03:40:53 +00:00
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")])
(define_expand "movsi"
[(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
{
2003-07-11 03:40:53 +00:00
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, m, r,*f,*f, r,*d")
(match_operand:SI 1 "move_operand" "rO,J,i,m,rO,*f,rO,*f,*d,rK"))]
"ia64_move_ok (operands[0], operands[1])"
"@
mov %0 = %r1
addl %0 = %1, 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"
2003-07-11 03:40:53 +00:00
;; frar_m, toar_m ??? why not frar_i and toar_i
[(set_attr "itanium_class" "ialu,ialu,long_i,ld,st,frfr,tofr,fmisc,frar_m,toar_m")])
(define_expand "movdi"
[(set (match_operand:DI 0 "general_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
{
2003-07-11 03:40:53 +00:00
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, m, r,*f,*f,*f, Q, r,*b, r,*e, r,*d, r,*c")
(match_operand:DI 1 "move_operand"
2004-07-28 03:11:36 +00:00
"rO,JT,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[] = {
2003-07-11 03:40:53 +00:00
"%,mov %0 = %r1",
"%,addl %0 = %1, 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"
};
if (which_alternative == 2 && ! TARGET_NO_PIC
&& symbolic_operand (operands[1], VOIDmode))
abort ();
return alt[which_alternative];
2003-07-11 03:40:53 +00:00
}
[(set_attr "itanium_class" "ialu,ialu,long_i,ld,st,frfr,tofr,fmisc,fld,stf,frbr,tobr,frar_i,toar_i,frar_m,toar_m,frpr,topr")])
(define_split
2004-07-28 03:11:36 +00:00
[(set (match_operand 0 "register_operand" "")
(match_operand 1 "symbolic_operand" ""))]
"reload_completed && ! TARGET_NO_PIC"
[(const_int 0)]
{
2004-07-28 03:11:36 +00:00
ia64_expand_load_address (operands[0], operands[1]);
DONE;
2003-07-11 03:40:53 +00:00
})
(define_expand "load_fptr"
[(set (match_dup 2)
2003-07-11 03:40:53 +00:00
(plus:DI (reg:DI 1) (match_operand 1 "function_operand" "")))
(set (match_operand:DI 0 "register_operand" "") (match_dup 3))]
""
{
operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
operands[3] = gen_rtx_MEM (DImode, operands[2]);
RTX_UNCHANGING_P (operands[3]) = 1;
2003-07-11 03:40:53 +00:00
})
(define_insn "*load_fptr_internal1"
[(set (match_operand:DI 0 "register_operand" "=r")
2003-07-11 03:40:53 +00:00
(plus:DI (reg:DI 1) (match_operand 1 "function_operand" "s")))]
""
"addl %0 = @ltoff(@fptr(%1)), gp"
[(set_attr "itanium_class" "ialu")])
(define_insn "load_gprel"
[(set (match_operand:DI 0 "register_operand" "=r")
2003-07-11 03:40:53 +00:00
(plus:DI (reg:DI 1) (match_operand 1 "sdata_symbolic_operand" "s")))]
""
"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)))]
""
"movl %0 = @gprel(%1)"
[(set_attr "itanium_class" "long_i")])
(define_expand "load_gprel64"
[(set (match_dup 2)
(minus:DI (match_operand:DI 1 "symbolic_operand" "") (match_dup 3)))
(set (match_operand:DI 0 "register_operand" "")
(plus:DI (match_dup 3) (match_dup 2)))]
""
{
operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
operands[3] = pic_offset_table_rtx;
2003-07-11 03:40:53 +00:00
})
2004-07-28 03:11:36 +00:00
;; 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))]
""
2004-07-28 03:11:36 +00:00
"#"
"reload_completed"
[(const_int 0)]
{
2004-07-28 03:11:36 +00:00
ia64_split_return_addr_rtx (operands[0]);
DONE;
}
[(set_attr "itanium_class" "ialu")])
2003-07-11 03:40:53 +00:00
(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")))]
""
{
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 (match_operand:DI 1 "register_operand" "r")
(match_operand 2 "got_symbolic_operand" "s")))]
""
{
if (HAVE_AS_LTOFFX_LDXMOV_RELOCS)
return "%,ld8.mov %0 = [%1], %2";
else
return "%,ld8 %0 = [%1]";
}
[(set_attr "itanium_class" "ld")])
(define_insn "load_ltoff_dtpmod"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (reg:DI 1)
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
UNSPEC_LTOFF_DTPMOD)))]
""
"addl %0 = @ltoff(@dtpmod(%1)), gp"
[(set_attr "itanium_class" "ialu")])
(define_insn "load_ltoff_dtprel"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (reg:DI 1)
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
UNSPEC_LTOFF_DTPREL)))]
""
"addl %0 = @ltoff(@dtprel(%1)), gp"
[(set_attr "itanium_class" "ialu")])
(define_expand "load_dtprel"
[(set (match_operand:DI 0 "register_operand" "")
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
UNSPEC_DTPREL))]
""
"")
2003-07-11 03:40:53 +00:00
(define_insn "*load_dtprel64"
[(set (match_operand:DI 0 "register_operand" "=r")
2003-07-11 03:40:53 +00:00
(unspec:DI [(match_operand:DI 1 "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:DI 1 "symbolic_operand" "")]
UNSPEC_DTPREL))]
""
2003-07-11 03:40:53 +00:00
"addl %0 = @dtprel(%1), r0"
[(set_attr "itanium_class" "ialu")])
(define_expand "add_dtprel"
[(set (match_operand:DI 0 "register_operand" "")
(plus:DI (match_operand:DI 1 "register_operand" "")
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
UNSPEC_DTPREL)))]
"!TARGET_TLS64"
"")
(define_insn "*add_dtprel14"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "register_operand" "r")
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
UNSPEC_DTPREL)))]
"TARGET_TLS14"
"adds %0 = @dtprel(%2), %1"
[(set_attr "itanium_class" "ialu")])
(define_insn "*add_dtprel22"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "register_operand" "a")
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
UNSPEC_DTPREL)))]
"TARGET_TLS22"
"addl %0 = @dtprel(%2), %1"
[(set_attr "itanium_class" "ialu")])
(define_insn "load_ltoff_tprel"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (reg:DI 1)
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
UNSPEC_LTOFF_TPREL)))]
""
"addl %0 = @ltoff(@tprel(%1)), gp"
[(set_attr "itanium_class" "ialu")])
(define_expand "load_tprel"
[(set (match_operand:DI 0 "register_operand" "")
(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
UNSPEC_TPREL))]
""
"")
(define_insn "*load_tprel64"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:DI 1 "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:DI 1 "symbolic_operand" "")]
UNSPEC_TPREL))]
""
"addl %0 = @tprel(%1), r0"
[(set_attr "itanium_class" "ialu")])
(define_expand "add_tprel"
[(set (match_operand:DI 0 "register_operand" "")
(plus:DI (match_operand:DI 1 "register_operand" "")
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
UNSPEC_TPREL)))]
"!TARGET_TLS64"
"")
(define_insn "*add_tprel14"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "register_operand" "r")
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
UNSPEC_TPREL)))]
"TARGET_TLS14"
"adds %0 = @tprel(%2), %1"
[(set_attr "itanium_class" "ialu")])
(define_insn "*add_tprel22"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "register_operand" "a")
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
UNSPEC_TPREL)))]
"TARGET_TLS22"
"addl %0 = @tprel(%2), %1"
[(set_attr "itanium_class" "ialu")])
;; With no offsettable memory references, we've got to have a scratch
2004-07-28 03:11:36 +00:00
;; 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"
2004-07-28 03:11:36 +00:00
[(set (match_operand:TI 0 "general_operand" "")
(match_operand:TI 1 "general_operand" ""))]
""
{
2003-07-11 03:40:53 +00:00
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 "nonimmediate_operand" "=r,r,m")
2004-07-28 03:11:36 +00:00
(match_operand:TI 1 "general_operand" "ri,m,r"))]
"ia64_move_ok (operands[0], operands[1])"
"#"
"reload_completed"
[(const_int 0)]
{
2004-07-28 03:11:36 +00:00
ia64_split_tmode_move (operands);
DONE;
2003-07-11 03:40:53 +00:00
}
[(set_attr "itanium_class" "unknown")
(set_attr "predicable" "no")])
;; Floating Point Moves
;;
;; Note - Patterns for SF mode moves are compulsory, but
2003-07-11 03:40:53 +00:00
;; 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" ""))]
""
{
2003-07-11 03:40:53 +00:00
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")
(match_operand:SF 1 "general_operand" "fG,Q,fG,fG,*r,*r, m,*r"))]
"ia64_move_ok (operands[0], operands[1])"
"@
2003-07-11 03:40:53 +00:00
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"
[(set_attr "itanium_class" "fmisc,fld,stf,frfr,tofr,ialu,ld,st")])
(define_expand "movdf"
[(set (match_operand:DF 0 "general_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
{
2003-07-11 03:40:53 +00:00
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")
(match_operand:DF 1 "general_operand" "fG,Q,fG,fG,*r,*r, m,*r"))]
"ia64_move_ok (operands[0], operands[1])"
"@
2003-07-11 03:40:53 +00:00
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"
[(set_attr "itanium_class" "fmisc,fld,stf,frfr,tofr,ialu,ld,st")])
;; 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.
2004-07-28 03:11:36 +00:00
(define_expand "movxf"
[(set (match_operand:XF 0 "general_operand" "")
(match_operand:XF 1 "general_operand" ""))]
""
{
2004-07-28 03:11:36 +00:00
/* We must support XFmode loads into general registers for stdarg/vararg
and unprototyped calls. We split them into DImode loads for convenience.
2004-07-28 03:11:36 +00:00
We don't need XFmode stores from general regs, because a stdarg/vararg
routine does a block store to memory of unnamed arguments. */
if (GET_CODE (operands[0]) == REG
&& GR_REGNO_P (REGNO (operands[0])))
{
2004-07-28 03:11:36 +00:00
/* We're hoping to transform everything that deals with XFmode
quantities and GR registers early in the compiler. */
if (no_new_pseudos)
abort ();
/* Struct to register can just use TImode instead. */
if ((GET_CODE (operands[1]) == SUBREG
&& GET_MODE (SUBREG_REG (operands[1])) == TImode)
|| (GET_CODE (operands[1]) == REG
&& GR_REGNO_P (REGNO (operands[1]))))
{
emit_move_insn (gen_rtx_REG (TImode, REGNO (operands[0])),
SUBREG_REG (operands[1]));
DONE;
}
if (GET_CODE (operands[1]) == CONST_DOUBLE)
{
emit_move_insn (gen_rtx_REG (DImode, REGNO (operands[0])),
2004-07-28 03:11:36 +00:00
operand_subword (operands[1], 0, 0, XFmode));
emit_move_insn (gen_rtx_REG (DImode, REGNO (operands[0]) + 1),
2004-07-28 03:11:36 +00:00
operand_subword (operands[1], 1, 0, XFmode));
DONE;
}
/* If the quantity is in a register not known to be GR, spill it. */
2004-07-28 03:11:36 +00:00
if (register_operand (operands[1], XFmode))
operands[1] = spill_xfmode_operand (operands[1], 1);
if (GET_CODE (operands[1]) == MEM)
{
rtx out[2];
out[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[0]));
out[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[0])+1);
emit_move_insn (out[0], adjust_address (operands[1], DImode, 0));
emit_move_insn (out[1], adjust_address (operands[1], DImode, 8));
DONE;
}
abort ();
}
if (! reload_in_progress && ! reload_completed)
{
2004-07-28 03:11:36 +00:00
operands[0] = spill_xfmode_operand (operands[0], 0);
operands[1] = spill_xfmode_operand (operands[1], 0);
if (! ia64_move_ok (operands[0], operands[1]))
2004-07-28 03:11:36 +00:00
operands[1] = force_reg (XFmode, operands[1]);
}
2003-07-11 03:40:53 +00:00
})
;; ??? There's no easy way to mind volatile acquire/release semantics.
2004-07-28 03:11:36 +00:00
(define_insn "*movxf_internal"
[(set (match_operand:XF 0 "destination_xfmode_operand" "=f,f, m")
(match_operand:XF 1 "general_xfmode_operand" "fG,m,fG"))]
"ia64_move_ok (operands[0], operands[1])"
"@
2003-07-11 03:40:53 +00:00
mov %0 = %F1
ldfe %0 = %1%P1
stfe %0 = %F1%P0"
[(set_attr "itanium_class" "fmisc,fld,stf")])
2004-07-28 03:11:36 +00:00
;; 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 "nonimmediate_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")])
(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")])
(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")))]
""
"@
zxt4 %0 = %1
ld4%O1 %0 = %1%P1
fmix.r %0 = f0, %1"
[(set_attr "itanium_class" "xtd,ld,fmisc")])
;; 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_register_operand" "f")))]
""
"fnorm.d %0 = %1"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "extendsfxf2"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(float_extend:XF (match_operand:SF 1 "fr_register_operand" "f")))]
""
"fnorm %0 = %1"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "extenddfxf2"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(float_extend:XF (match_operand:DF 1 "fr_register_operand" "f")))]
""
"fnorm %0 = %1"
[(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_register_operand" "f")))]
""
"fnorm.s %0 = %1"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "truncxfsf2"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
2004-07-28 03:11:36 +00:00
(float_truncate:SF (match_operand:XF 1 "fr_register_operand" "f")))]
""
"fnorm.s %0 = %1"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "truncxfdf2"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
2004-07-28 03:11:36 +00:00
(float_truncate:DF (match_operand:XF 1 "fr_register_operand" "f")))]
""
"fnorm.d %0 = %1"
[(set_attr "itanium_class" "fmac")])
;; Convert between signed integer types and floating point.
2004-07-28 03:11:36 +00:00
(define_insn "floatdixf2"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(float:XF (match_operand:DI 1 "fr_register_operand" "f")))]
""
"fcvt.xf %0 = %1"
[(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_register_operand" "f")))]
""
"fcvt.fx.trunc %0 = %1"
[(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_register_operand" "f")))]
""
"fcvt.fx.trunc %0 = %1"
[(set_attr "itanium_class" "fcvtfx")])
2004-07-28 03:11:36 +00:00
(define_insn "fix_truncxfdi2"
[(set (match_operand:DI 0 "fr_register_operand" "=f")
2004-07-28 03:11:36 +00:00
(fix:DI (match_operand:XF 1 "fr_register_operand" "f")))]
""
"fcvt.fx.trunc %0 = %1"
[(set_attr "itanium_class" "fcvtfx")])
2004-07-28 03:11:36 +00:00
(define_insn "fix_truncxfdi2_alts"
[(set (match_operand:DI 0 "fr_register_operand" "=f")
2004-07-28 03:11:36 +00:00
(fix:DI (match_operand:XF 1 "fr_register_operand" "f")))
(use (match_operand:SI 2 "const_int_operand" ""))]
2004-07-28 03:11:36 +00:00
""
"fcvt.fx.trunc.s%2 %0 = %1"
[(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_register_operand" "f")))]
""
"fcvt.xuf.s %0 = %1"
[(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_register_operand" "f")))]
""
"fcvt.xuf.d %0 = %1"
[(set_attr "itanium_class" "fcvtfx")])
2004-07-28 03:11:36 +00:00
(define_insn "floatunsdixf2"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(unsigned_float:XF (match_operand:DI 1 "fr_register_operand" "f")))]
""
"fcvt.xuf %0 = %1"
[(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_register_operand" "f")))]
""
"fcvt.fxu.trunc %0 = %1"
[(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_register_operand" "f")))]
""
"fcvt.fxu.trunc %0 = %1"
[(set_attr "itanium_class" "fcvtfx")])
2004-07-28 03:11:36 +00:00
(define_insn "fixuns_truncxfdi2"
[(set (match_operand:DI 0 "fr_register_operand" "=f")
2004-07-28 03:11:36 +00:00
(unsigned_fix:DI (match_operand:XF 1 "fr_register_operand" "f")))]
""
"fcvt.fxu.trunc %0 = %1"
[(set_attr "itanium_class" "fcvtfx")])
2004-07-28 03:11:36 +00:00
(define_insn "fixuns_truncxfdi2_alts"
[(set (match_operand:DI 0 "fr_register_operand" "=f")
2004-07-28 03:11:36 +00:00
(unsigned_fix:DI (match_operand:XF 1 "fr_register_operand" "f")))
(use (match_operand:SI 2 "const_int_operand" ""))]
2004-07-28 03:11:36 +00:00
""
"fcvt.fxu.trunc.s%2 %0 = %1"
[(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 "const_int_operand" "n")
(match_operand:DI 3 "const_int_operand" "n")))]
""
"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 "const_int_operand" "n")
(match_operand:DI 3 "const_int_operand" "n")))]
""
"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
}
2003-07-11 03:40:53 +00:00
})
(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")])
2003-07-11 03:40:53 +00:00
;; Combine doesn't like to create bit-field insertions into zero.
(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" "n"))
(match_operand:DI 3 "const_int_operand" "n")))]
"CONST_OK_FOR_M (INTVAL (operands[2]))
&& ia64_depz_field_mask (operands[3], operands[2]) > 0"
{
operands[3] = GEN_INT (ia64_depz_field_mask (operands[3], operands[2]));
2003-07-11 03:40:53 +00:00
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" ""))]
"reload_completed"
[(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_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" ""))]
"! reload_completed"
[(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)))
2003-07-11 03:40:53 +00:00
(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)))
2003-07-11 03:40:53 +00:00
(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 "const_int_operand" "n"))
(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 "const_int_operand" "n"))
(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 "const_int_operand" "n"))
(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 "const_int_operand" "n"))
(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" "")
2003-07-11 03:40:53 +00:00
(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")))]
""
"@
2003-07-11 03:40:53 +00:00
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)))]
""
2003-07-11 03:40:53 +00:00
{ 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)))]
""
2003-07-11 03:40:53 +00:00
{ 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)))]
""
2003-07-11 03:40:53 +00:00
{ 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)))]
""
2003-07-11 03:40:53 +00:00
{ 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)))]
""
2003-07-11 03:40:53 +00:00
{ operands[3] = gen_reg_rtx (BImode); })
(define_expand "divsi3"
[(set (match_operand:SI 0 "register_operand" "")
(div:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_INT_DIV"
{
2004-07-28 03:11:36 +00:00
rtx op1_xf, op2_xf, op0_xf, op0_di, twon34;
2003-07-11 03:40:53 +00:00
REAL_VALUE_TYPE twon34_r;
2004-07-28 03:11:36 +00:00
op0_xf = gen_reg_rtx (XFmode);
op0_di = gen_reg_rtx (DImode);
if (CONSTANT_P (operands[1]))
operands[1] = force_reg (SImode, operands[1]);
2004-07-28 03:11:36 +00:00
op1_xf = gen_reg_rtx (XFmode);
expand_float (op1_xf, operands[1], 0);
if (CONSTANT_P (operands[2]))
operands[2] = force_reg (SImode, operands[2]);
2004-07-28 03:11:36 +00:00
op2_xf = gen_reg_rtx (XFmode);
expand_float (op2_xf, operands[2], 0);
/* 2^-34 */
2003-07-11 03:40:53 +00:00
real_2expN (&twon34_r, -34);
2004-07-28 03:11:36 +00:00
twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, XFmode);
twon34 = force_reg (XFmode, twon34);
2004-07-28 03:11:36 +00:00
emit_insn (gen_divsi3_internal (op0_xf, op1_xf, op2_xf, twon34));
2004-07-28 03:11:36 +00:00
emit_insn (gen_fix_truncxfdi2_alts (op0_di, op0_xf, const1_rtx));
emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
DONE;
2003-07-11 03:40:53 +00:00
})
(define_expand "modsi3"
[(set (match_operand:SI 0 "register_operand" "")
(mod:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_INT_DIV"
{
rtx op2_neg, op1_di, div;
div = gen_reg_rtx (SImode);
emit_insn (gen_divsi3 (div, operands[1], operands[2]));
op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
/* This is a trick to get us to reuse the value that we're sure to
have already copied to the FP regs. */
op1_di = gen_reg_rtx (DImode);
convert_move (op1_di, operands[1], 0);
emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
gen_lowpart (SImode, op1_di)));
DONE;
2003-07-11 03:40:53 +00:00
})
(define_expand "udivsi3"
[(set (match_operand:SI 0 "register_operand" "")
(udiv:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_INT_DIV"
{
2004-07-28 03:11:36 +00:00
rtx op1_xf, op2_xf, op0_xf, op0_di, twon34;
2003-07-11 03:40:53 +00:00
REAL_VALUE_TYPE twon34_r;
2004-07-28 03:11:36 +00:00
op0_xf = gen_reg_rtx (XFmode);
op0_di = gen_reg_rtx (DImode);
if (CONSTANT_P (operands[1]))
operands[1] = force_reg (SImode, operands[1]);
2004-07-28 03:11:36 +00:00
op1_xf = gen_reg_rtx (XFmode);
expand_float (op1_xf, operands[1], 1);
if (CONSTANT_P (operands[2]))
operands[2] = force_reg (SImode, operands[2]);
2004-07-28 03:11:36 +00:00
op2_xf = gen_reg_rtx (XFmode);
expand_float (op2_xf, operands[2], 1);
/* 2^-34 */
2003-07-11 03:40:53 +00:00
real_2expN (&twon34_r, -34);
2004-07-28 03:11:36 +00:00
twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, XFmode);
twon34 = force_reg (XFmode, twon34);
2004-07-28 03:11:36 +00:00
emit_insn (gen_divsi3_internal (op0_xf, op1_xf, op2_xf, twon34));
2004-07-28 03:11:36 +00:00
emit_insn (gen_fixuns_truncxfdi2_alts (op0_di, op0_xf, const1_rtx));
emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
DONE;
2003-07-11 03:40:53 +00:00
})
(define_expand "umodsi3"
[(set (match_operand:SI 0 "register_operand" "")
(umod:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_INT_DIV"
{
rtx op2_neg, op1_di, div;
div = gen_reg_rtx (SImode);
emit_insn (gen_udivsi3 (div, operands[1], operands[2]));
op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
/* This is a trick to get us to reuse the value that we're sure to
have already copied to the FP regs. */
op1_di = gen_reg_rtx (DImode);
convert_move (op1_di, operands[1], 1);
emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
gen_lowpart (SImode, op1_di)));
DONE;
2003-07-11 03:40:53 +00:00
})
(define_insn_and_split "divsi3_internal"
2004-07-28 03:11:36 +00:00
[(set (match_operand:XF 0 "fr_register_operand" "=&f")
(float:XF (div:SI (match_operand:XF 1 "fr_register_operand" "f")
(match_operand:XF 2 "fr_register_operand" "f"))))
(clobber (match_scratch:XF 4 "=&f"))
(clobber (match_scratch:XF 5 "=&f"))
(clobber (match_scratch:BI 6 "=c"))
2004-07-28 03:11:36 +00:00
(use (match_operand:XF 3 "fr_register_operand" "f"))]
"TARGET_INLINE_INT_DIV"
"#"
"&& reload_completed"
2004-07-28 03:11:36 +00:00
[(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2)))
2003-07-11 03:40:53 +00:00
(set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)]
UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 6) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 5)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
(match_dup 7)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 5) (match_dup 4))
(match_dup 4)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 5)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 5) (match_dup 5))
(match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 5) (match_dup 4))
(match_dup 4)))
(use (const_int 1))]))
]
2004-07-28 03:11:36 +00:00
"operands[7] = CONST1_RTX (XFmode);"
[(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
;; :: 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")))]
""
"@
2003-07-11 03:40:53 +00:00
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)))]
"")
;; ??? There are highpart multiply and add instructions, but we have no way
;; to generate them.
(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_register_operand" "f"))
(sign_extend:TI
(match_operand:DI 2 "fr_register_operand" "f")))
(const_int 64))))]
""
"xmpy.h %0 = %1, %2"
[(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_register_operand" "f"))
(zero_extend:TI
(match_operand:DI 2 "fr_register_operand" "f")))
(const_int 64))))]
""
"xmpy.hu %0 = %1, %2"
[(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)))]
""
2003-07-11 03:40:53 +00:00
{ 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)))]
""
2003-07-11 03:40:53 +00:00
{ 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)))]
""
2003-07-11 03:40:53 +00:00
{ 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)))]
""
2003-07-11 03:40:53 +00:00
{ 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)))]
""
2003-07-11 03:40:53 +00:00
{ 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)))
2004-07-28 03:11:36 +00:00
(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);
2003-07-11 03:40:53 +00:00
})
2004-07-28 03:11:36 +00:00
(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_register_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")
2004-07-28 03:11:36 +00:00
(popcount:DI (match_operand:DI 1 "gr_register_operand" "r")))]
""
"popcnt %0 = %1"
[(set_attr "itanium_class" "mmmul")])
2004-07-28 03:11:36 +00:00
(define_insn "*getf_exp_xf"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
(unspec:DI [(match_operand:XF 1 "fr_register_operand" "f")]
UNSPEC_GETF_EXP))]
""
"getf.exp %0 = %1"
[(set_attr "itanium_class" "frfr")])
(define_expand "divdi3"
[(set (match_operand:DI 0 "register_operand" "")
(div:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_INT_DIV"
{
2004-07-28 03:11:36 +00:00
rtx op1_xf, op2_xf, op0_xf;
2004-07-28 03:11:36 +00:00
op0_xf = gen_reg_rtx (XFmode);
if (CONSTANT_P (operands[1]))
operands[1] = force_reg (DImode, operands[1]);
2004-07-28 03:11:36 +00:00
op1_xf = gen_reg_rtx (XFmode);
expand_float (op1_xf, operands[1], 0);
if (CONSTANT_P (operands[2]))
operands[2] = force_reg (DImode, operands[2]);
2004-07-28 03:11:36 +00:00
op2_xf = gen_reg_rtx (XFmode);
expand_float (op2_xf, operands[2], 0);
2003-07-11 03:40:53 +00:00
if (TARGET_INLINE_INT_DIV_LAT)
2004-07-28 03:11:36 +00:00
emit_insn (gen_divdi3_internal_lat (op0_xf, op1_xf, op2_xf));
else
2004-07-28 03:11:36 +00:00
emit_insn (gen_divdi3_internal_thr (op0_xf, op1_xf, op2_xf));
2004-07-28 03:11:36 +00:00
emit_insn (gen_fix_truncxfdi2_alts (operands[0], op0_xf, const1_rtx));
DONE;
2003-07-11 03:40:53 +00:00
})
(define_expand "moddi3"
[(set (match_operand:DI 0 "register_operand" "")
(mod:SI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_INT_DIV"
{
rtx op2_neg, div;
div = gen_reg_rtx (DImode);
emit_insn (gen_divdi3 (div, operands[1], operands[2]));
op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
DONE;
2003-07-11 03:40:53 +00:00
})
(define_expand "udivdi3"
[(set (match_operand:DI 0 "register_operand" "")
(udiv:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_INT_DIV"
{
2004-07-28 03:11:36 +00:00
rtx op1_xf, op2_xf, op0_xf;
2004-07-28 03:11:36 +00:00
op0_xf = gen_reg_rtx (XFmode);
if (CONSTANT_P (operands[1]))
operands[1] = force_reg (DImode, operands[1]);
2004-07-28 03:11:36 +00:00
op1_xf = gen_reg_rtx (XFmode);
expand_float (op1_xf, operands[1], 1);
if (CONSTANT_P (operands[2]))
operands[2] = force_reg (DImode, operands[2]);
2004-07-28 03:11:36 +00:00
op2_xf = gen_reg_rtx (XFmode);
expand_float (op2_xf, operands[2], 1);
2003-07-11 03:40:53 +00:00
if (TARGET_INLINE_INT_DIV_LAT)
2004-07-28 03:11:36 +00:00
emit_insn (gen_divdi3_internal_lat (op0_xf, op1_xf, op2_xf));
else
2004-07-28 03:11:36 +00:00
emit_insn (gen_divdi3_internal_thr (op0_xf, op1_xf, op2_xf));
2004-07-28 03:11:36 +00:00
emit_insn (gen_fixuns_truncxfdi2_alts (operands[0], op0_xf, const1_rtx));
DONE;
2003-07-11 03:40:53 +00:00
})
(define_expand "umoddi3"
[(set (match_operand:DI 0 "register_operand" "")
(umod:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_INT_DIV"
{
rtx op2_neg, div;
div = gen_reg_rtx (DImode);
emit_insn (gen_udivdi3 (div, operands[1], operands[2]));
op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
DONE;
2003-07-11 03:40:53 +00:00
})
(define_insn_and_split "divdi3_internal_lat"
2004-07-28 03:11:36 +00:00
[(set (match_operand:XF 0 "fr_register_operand" "=&f")
(float:XF (div:SI (match_operand:XF 1 "fr_register_operand" "f")
(match_operand:XF 2 "fr_register_operand" "f"))))
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=&f"))
(clobber (match_scratch:XF 5 "=&f"))
(clobber (match_scratch:BI 6 "=c"))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_INT_DIV_LAT"
"#"
"&& reload_completed"
2004-07-28 03:11:36 +00:00
[(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2)))
2003-07-11 03:40:53 +00:00
(set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)]
UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
(match_dup 7)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 5) (mult:XF (match_dup 3) (match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 4))
(match_dup 4)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 0))
(match_dup 0)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 5) (match_dup 4))
(match_dup 4)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 5) (match_dup 0))
(match_dup 0)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
(match_dup 1)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 0))
(match_dup 3)))
(use (const_int 1))]))
]
2004-07-28 03:11:36 +00:00
"operands[7] = CONST1_RTX (XFmode);"
[(set_attr "predicable" "no")])
(define_insn_and_split "divdi3_internal_thr"
2004-07-28 03:11:36 +00:00
[(set (match_operand:XF 0 "fr_register_operand" "=&f")
(float:XF (div:SI (match_operand:XF 1 "fr_register_operand" "f")
(match_operand:XF 2 "fr_register_operand" "f"))))
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_INT_DIV_THR"
"#"
"&& reload_completed"
2004-07-28 03:11:36 +00:00
[(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2)))
2003-07-11 03:40:53 +00:00
(set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)]
UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
(match_dup 6)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 0))
(match_dup 0)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 3) (mult:XF (match_dup 3) (match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 0))
(match_dup 0)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 3) (mult:XF (match_dup 0) (match_dup 1)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
(match_dup 1)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 0))
(match_dup 3)))
(use (const_int 1))]))
]
2004-07-28 03:11:36 +00:00
"operands[6] = CONST1_RTX (XFmode);"
[(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
;; :: 32 bit floating point arithmetic
;; ::
;; ::::::::::::::::::::
(define_insn "addsf3"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(plus:SF (match_operand:SF 1 "fr_register_operand" "%f")
(match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
""
"fadd.s %0 = %1, %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_fp01_operand" "fG")))]
""
"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_register_operand" "%f")
(match_operand:SF 2 "fr_register_operand" "f")))]
""
"fmpy.s %0 = %1, %2"
[(set_attr "itanium_class" "fmac")])
(define_insn "abssf2"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(abs:SF (match_operand:SF 1 "fr_register_operand" "f")))]
""
"fabs %0 = %1"
[(set_attr "itanium_class" "fmisc")])
(define_insn "negsf2"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(neg:SF (match_operand:SF 1 "fr_register_operand" "f")))]
""
"fneg %0 = %1"
[(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_register_operand" "f"))))]
""
"fnegabs %0 = %1"
[(set_attr "itanium_class" "fmisc")])
(define_insn "minsf3"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(smin:SF (match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
""
"fmin %0 = %1, %F2"
[(set_attr "itanium_class" "fmisc")])
(define_insn "maxsf3"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(smax:SF (match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
""
"fmax %0 = %1, %F2"
[(set_attr "itanium_class" "fmisc")])
(define_insn "*maddsf4"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(plus:SF (mult:SF (match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_register_operand" "f"))
(match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))]
""
"fma.s %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_insn "*msubsf4"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(minus:SF (mult:SF (match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_register_operand" "f"))
(match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))]
""
"fms.s %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_insn "*nmulsf3"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(neg:SF (mult:SF (match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_register_operand" "f"))))]
""
"fnmpy.s %0 = %1, %2"
[(set_attr "itanium_class" "fmac")])
;; ??? Is it possible to canonicalize this as (minus (reg) (mult))?
(define_insn "*nmaddsf4"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(plus:SF (neg:SF (mult:SF
(match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_register_operand" "f")))
(match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))]
""
"fnma.s %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_expand "divsf3"
[(set (match_operand:SF 0 "fr_register_operand" "")
(div:SF (match_operand:SF 1 "fr_register_operand" "")
(match_operand:SF 2 "fr_register_operand" "")))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
2003-07-11 03:40:53 +00:00
if (TARGET_INLINE_FLOAT_DIV_LAT)
insn = gen_divsf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divsf3_internal_thr (operands[0], operands[1], operands[2]);
emit_insn (insn);
DONE;
2003-07-11 03:40:53 +00:00
})
(define_insn_and_split "divsf3_internal_lat"
[(set (match_operand:SF 0 "fr_register_operand" "=&f")
(div:SF (match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_register_operand" "f")))
2004-07-28 03:11:36 +00:00
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_FLOAT_DIV_LAT"
"#"
"&& reload_completed"
2004-07-28 03:11:36 +00:00
[(parallel [(set (match_dup 6) (div:XF (const_int 1) (match_dup 8)))
2003-07-11 03:40:53 +00:00
(set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 3) (mult:XF (match_dup 7) (match_dup 6)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 6)))
(match_dup 10)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 3))
(match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 4) (mult:XF (match_dup 4) (match_dup 4)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 3))
(match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 4) (mult:XF (match_dup 4) (match_dup 4)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 9)
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 3))
(match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(set (match_dup 0)
(float_truncate:SF (match_dup 6))))
]
2003-07-11 03:40:53 +00:00
{
2004-07-28 03:11:36 +00:00
operands[6] = gen_rtx_REG (XFmode, REGNO (operands[0]));
operands[7] = gen_rtx_REG (XFmode, REGNO (operands[1]));
operands[8] = gen_rtx_REG (XFmode, REGNO (operands[2]));
2003-07-11 03:40:53 +00:00
operands[9] = gen_rtx_REG (DFmode, REGNO (operands[0]));
2004-07-28 03:11:36 +00:00
operands[10] = CONST1_RTX (XFmode);
2003-07-11 03:40:53 +00:00
}
[(set_attr "predicable" "no")])
(define_insn_and_split "divsf3_internal_thr"
[(set (match_operand:SF 0 "fr_register_operand" "=&f")
(div:SF (match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_register_operand" "f")))
2004-07-28 03:11:36 +00:00
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_FLOAT_DIV_THR"
"#"
"&& reload_completed"
2004-07-28 03:11:36 +00:00
[(parallel [(set (match_dup 6) (div:XF (const_int 1) (match_dup 8)))
2003-07-11 03:40:53 +00:00
(set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 6)))
(match_dup 10)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 3))
(match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 6)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 6))
(match_dup 6)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 9)
(float_truncate:SF
2004-07-28 03:11:36 +00:00
(mult:XF (match_dup 7) (match_dup 6))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 3)))
(match_dup 7)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(set (match_dup 0)
(float_truncate:SF
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 6))
(match_dup 3)))))
]
2003-07-11 03:40:53 +00:00
{
2004-07-28 03:11:36 +00:00
operands[6] = gen_rtx_REG (XFmode, REGNO (operands[0]));
operands[7] = gen_rtx_REG (XFmode, REGNO (operands[1]));
operands[8] = gen_rtx_REG (XFmode, REGNO (operands[2]));
2003-07-11 03:40:53 +00:00
operands[9] = gen_rtx_REG (SFmode, REGNO (operands[3]));
2004-07-28 03:11:36 +00:00
operands[10] = CONST1_RTX (XFmode);
}
[(set_attr "predicable" "no")])
;; Inline square root.
(define_insn "*sqrt_approx"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(div:XF (const_int 1)
(sqrt:XF (match_operand:XF 2 "fr_register_operand" "f"))))
(set (match_operand:BI 1 "register_operand" "=c")
(unspec:BI [(match_dup 2)] UNSPEC_FR_SQRT_RECIP_APPROX))
(use (match_operand:SI 3 "const_int_operand" "")) ]
""
"frsqrta.s%3 %0, %1 = %2"
[(set_attr "itanium_class" "fmisc")
(set_attr "predicable" "no")])
(define_insn "*setf_exp_xf"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(unspec:XF [(match_operand:DI 1 "register_operand" "r")]
UNSPEC_SETF_EXP))]
""
"setf.exp %0 = %1"
[(set_attr "itanium_class" "frfr")])
(define_expand "sqrtsf2"
[(set (match_operand:SF 0 "fr_register_operand" "=&f")
(sqrt:SF (match_operand:SF 1 "fr_register_operand" "f")))]
"TARGET_INLINE_SQRT"
{
rtx insn;
if (TARGET_INLINE_SQRT_LAT)
#if 0
insn = gen_sqrtsf2_internal_lat (operands[0], operands[1]);
#else
abort ();
#endif
else
insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]);
emit_insn (insn);
DONE;
})
;; Latency-optimized square root.
;; FIXME: Implement.
;; Throughput-optimized square root.
(define_insn_and_split "sqrtsf2_internal_thr"
[(set (match_operand:SF 0 "fr_register_operand" "=&f")
(sqrt:SF (match_operand:SF 1 "fr_register_operand" "f")))
;; Register r2 in optimization guide.
(clobber (match_scratch:DI 2 "=r"))
;; Register f8 in optimization guide
(clobber (match_scratch:XF 3 "=&f"))
;; Register f9 in optimization guide
(clobber (match_scratch:XF 4 "=&f"))
;; Register f10 in optimization guide
(clobber (match_scratch:XF 5 "=&f"))
;; Register p6 in optimization guide.
(clobber (match_scratch:BI 6 "=c"))]
"TARGET_INLINE_SQRT_THR"
"#"
"&& reload_completed"
[ ;; exponent of +1/2 in r2
(set (match_dup 2) (const_int 65534))
;; +1/2 in f8
(set (match_dup 3)
(unspec:XF [(match_dup 2)] UNSPEC_SETF_EXP))
;; Step 1
;; y0 = 1/sqrt(a) in f7
(parallel [(set (match_dup 7)
(div:XF (const_int 1)
(sqrt:XF (match_dup 8))))
(set (match_dup 6)
(unspec:BI [(match_dup 8)]
UNSPEC_FR_SQRT_RECIP_APPROX))
(use (const_int 0))])
;; Step 2
;; H0 = 1/2 * y0 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
(plus:XF (mult:XF (match_dup 3) (match_dup 7))
(match_dup 9)))
(use (const_int 1))]))
;; Step 3
;; S0 = a * y0 in f7
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 7)
(plus:XF (mult:XF (match_dup 8) (match_dup 7))
(match_dup 9)))
(use (const_int 1))]))
;; Step 4
;; d = 1/2 - S0 * H0 in f10
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 5)
(plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 4)))
(match_dup 3)))
(use (const_int 1))]))
;; Step 5
;; d' = d + 1/2 * d in f8
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
(plus:XF (mult:XF (match_dup 3) (match_dup 5))
(match_dup 5)))
(use (const_int 1))]))
;; Step 6
;; e = d + d * d' in f8
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
(plus:XF (mult:XF (match_dup 5) (match_dup 3))
(match_dup 5)))
(use (const_int 1))]))
;; Step 7
;; S1 = S0 + e * S0 in f7
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 0)
(float_truncate:SF
(plus:XF (mult:XF (match_dup 3) (match_dup 7))
(match_dup 7))))
(use (const_int 1))]))
;; Step 8
;; H1 = H0 + e * H0 in f8
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
(plus:XF (mult:XF (match_dup 3) (match_dup 4))
(match_dup 4)))
(use (const_int 1))]))
;; Step 9
;; d1 = a - S1 * S1 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
(plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 7)))
(match_dup 8)))
(use (const_int 1))]))
;; Step 10
;; S = S1 + d1 * H1 in f7
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 0)
(float_truncate:SF
(plus:XF (mult:XF (match_dup 4) (match_dup 3))
(match_dup 7))))
(use (const_int 0))]))]
{
/* Generate 82-bit versions of the input and output operands. */
operands[7] = gen_rtx_REG (XFmode, REGNO (operands[0]));
operands[8] = gen_rtx_REG (XFmode, REGNO (operands[1]));
/* Generate required floating-point constants. */
operands[9] = CONST0_RTX (XFmode);
2003-07-11 03:40:53 +00:00
}
[(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
;; :: 64 bit floating point arithmetic
;; ::
;; ::::::::::::::::::::
(define_insn "adddf3"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(plus:DF (match_operand:DF 1 "fr_register_operand" "%f")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))]
""
"fadd.d %0 = %1, %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_register_operand" "%f")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))))]
""
"fadd.s %0 = %1, %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_fp01_operand" "fG")))]
""
"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_fp01_operand" "fG"))))]
""
"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_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f")))]
""
"fmpy.d %0 = %1, %2"
[(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_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f"))))]
""
"fmpy.s %0 = %1, %2"
[(set_attr "itanium_class" "fmac")])
(define_insn "absdf2"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(abs:DF (match_operand:DF 1 "fr_register_operand" "f")))]
""
"fabs %0 = %1"
[(set_attr "itanium_class" "fmisc")])
(define_insn "negdf2"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(neg:DF (match_operand:DF 1 "fr_register_operand" "f")))]
""
"fneg %0 = %1"
[(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_register_operand" "f"))))]
""
"fnegabs %0 = %1"
[(set_attr "itanium_class" "fmisc")])
(define_insn "mindf3"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(smin:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))]
""
"fmin %0 = %1, %F2"
[(set_attr "itanium_class" "fmisc")])
(define_insn "maxdf3"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(smax:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))]
""
"fmax %0 = %1, %F2"
[(set_attr "itanium_class" "fmisc")])
(define_insn "*madddf4"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(plus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f"))
(match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))]
""
"fma.d %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_insn "*madddf4_trunc"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
(plus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f"))
(match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))]
""
"fma.s %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_insn "*msubdf4"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(minus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f"))
(match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))]
""
"fms.d %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_insn "*msubdf4_trunc"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
(minus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f"))
(match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))]
""
"fms.s %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_insn "*nmuldf3"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(neg:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f"))))]
""
"fnmpy.d %0 = %1, %2"
[(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_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f")))))]
""
"fnmpy.s %0 = %1, %2"
[(set_attr "itanium_class" "fmac")])
;; ??? Is it possible to canonicalize this as (minus (reg) (mult))?
(define_insn "*nmadddf4"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(plus:DF (neg:DF (mult:DF
(match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f")))
(match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))]
""
"fnma.d %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_insn "*nmadddf4_alts"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(plus:DF (neg:DF (mult:DF
(match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f")))
(match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))
(use (match_operand:SI 4 "const_int_operand" ""))]
""
"fnma.d.s%4 %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_insn "*nmadddf4_trunc"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
(plus:DF (neg:DF (mult:DF
(match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f")))
(match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))]
""
"fnma.s %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_expand "divdf3"
[(set (match_operand:DF 0 "fr_register_operand" "")
(div:DF (match_operand:DF 1 "fr_register_operand" "")
(match_operand:DF 2 "fr_register_operand" "")))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
2003-07-11 03:40:53 +00:00
if (TARGET_INLINE_FLOAT_DIV_LAT)
insn = gen_divdf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divdf3_internal_thr (operands[0], operands[1], operands[2]);
emit_insn (insn);
DONE;
2003-07-11 03:40:53 +00:00
})
(define_insn_and_split "divdf3_internal_lat"
[(set (match_operand:DF 0 "fr_register_operand" "=&f")
(div:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f")))
2004-07-28 03:11:36 +00:00
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=&f"))
(clobber (match_scratch:XF 5 "=&f"))
(clobber (match_scratch:BI 6 "=c"))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_FLOAT_DIV_LAT"
"#"
"&& reload_completed"
2004-07-28 03:11:36 +00:00
[(parallel [(set (match_dup 7) (div:XF (const_int 1) (match_dup 9)))
2003-07-11 03:40:53 +00:00
(set (match_dup 6) (unspec:BI [(match_dup 8) (match_dup 9)]
UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 6) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 3) (mult:XF (match_dup 8) (match_dup 7)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 9) (match_dup 7)))
(match_dup 12)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 3))
(match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 5) (mult:XF (match_dup 4) (match_dup 4)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 7)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 7))
(match_dup 7)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 5) (match_dup 3))
(match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 4) (mult:XF (match_dup 5) (match_dup 5)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 7)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 5) (match_dup 7))
(match_dup 7)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 10)
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 3))
(match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 7)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 7))
(match_dup 7)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 11)
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 9) (match_dup 3)))
(match_dup 8))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(float_truncate:DF (plus:XF (mult:XF (match_dup 5) (match_dup 7))
(match_dup 3)))))
]
2003-07-11 03:40:53 +00:00
{
2004-07-28 03:11:36 +00:00
operands[7] = gen_rtx_REG (XFmode, REGNO (operands[0]));
operands[8] = gen_rtx_REG (XFmode, REGNO (operands[1]));
operands[9] = gen_rtx_REG (XFmode, REGNO (operands[2]));
2003-07-11 03:40:53 +00:00
operands[10] = gen_rtx_REG (DFmode, REGNO (operands[3]));
operands[11] = gen_rtx_REG (DFmode, REGNO (operands[5]));
2004-07-28 03:11:36 +00:00
operands[12] = CONST1_RTX (XFmode);
2003-07-11 03:40:53 +00:00
}
[(set_attr "predicable" "no")])
(define_insn_and_split "divdf3_internal_thr"
[(set (match_operand:DF 0 "fr_register_operand" "=&f")
(div:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_register_operand" "f")))
2004-07-28 03:11:36 +00:00
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:DF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_FLOAT_DIV_THR"
"#"
"&& reload_completed"
2004-07-28 03:11:36 +00:00
[(parallel [(set (match_dup 6) (div:XF (const_int 1) (match_dup 8)))
2003-07-11 03:40:53 +00:00
(set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 6)))
(match_dup 10)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 6)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 6))
(match_dup 6)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(mult:XF (match_dup 3) (match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 6)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 6))
(match_dup 6)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(mult:XF (match_dup 3) (match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 6)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 6))
(match_dup 6)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 9)
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(mult:XF (match_dup 7) (match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
(plus:DF (neg:DF (mult:DF (match_dup 2) (match_dup 9)))
(match_dup 1)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(set (match_dup 0)
(plus:DF (mult:DF (match_dup 4) (match_dup 0))
(match_dup 9))))
]
2003-07-11 03:40:53 +00:00
{
2004-07-28 03:11:36 +00:00
operands[6] = gen_rtx_REG (XFmode, REGNO (operands[0]));
operands[7] = gen_rtx_REG (XFmode, REGNO (operands[1]));
operands[8] = gen_rtx_REG (XFmode, REGNO (operands[2]));
2003-07-11 03:40:53 +00:00
operands[9] = gen_rtx_REG (DFmode, REGNO (operands[3]));
2004-07-28 03:11:36 +00:00
operands[10] = CONST1_RTX (XFmode);
}
[(set_attr "predicable" "no")])
;; Inline square root.
(define_expand "sqrtdf2"
[(set (match_operand:DF 0 "fr_register_operand" "=&f")
(sqrt:DF (match_operand:DF 1 "fr_register_operand" "f")))]
"TARGET_INLINE_SQRT"
{
rtx insn;
if (TARGET_INLINE_SQRT_LAT)
#if 0
insn = gen_sqrtdf2_internal_lat (operands[0], operands[1]);
#else
abort ();
#endif
else
insn = gen_sqrtdf2_internal_thr (operands[0], operands[1]);
emit_insn (insn);
DONE;
})
;; Latency-optimized square root.
;; FIXME: Implement.
;; Throughput-optimized square root.
(define_insn_and_split "sqrtdf2_internal_thr"
[(set (match_operand:DF 0 "fr_register_operand" "=&f")
(sqrt:DF (match_operand:DF 1 "fr_register_operand" "f")))
;; Register r2 in optimization guide.
(clobber (match_scratch:DI 2 "=r"))
;; Register f8 in optimization guide
(clobber (match_scratch:XF 3 "=&f"))
;; Register f9 in optimization guide
(clobber (match_scratch:XF 4 "=&f"))
;; Register f10 in optimization guide
(clobber (match_scratch:XF 5 "=&f"))
;; Register p6 in optimization guide.
(clobber (match_scratch:BI 6 "=c"))]
"TARGET_INLINE_SQRT_THR"
"#"
"&& reload_completed"
[ ;; exponent of +1/2 in r2
(set (match_dup 2) (const_int 65534))
;; +1/2 in f10
(set (match_dup 5)
(unspec:XF [(match_dup 2)] UNSPEC_SETF_EXP))
;; Step 1
;; y0 = 1/sqrt(a) in f7
(parallel [(set (match_dup 7)
(div:XF (const_int 1)
(sqrt:XF (match_dup 8))))
(set (match_dup 6)
(unspec:BI [(match_dup 8)]
UNSPEC_FR_SQRT_RECIP_APPROX))
(use (const_int 0))])
;; Step 2
;; H0 = 1/2 * y0 in f8
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
(plus:XF (mult:XF (match_dup 5) (match_dup 7))
(match_dup 9)))
(use (const_int 1))]))
;; Step 3
;; G0 = a * y0 in f7
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 7)
(plus:XF (mult:XF (match_dup 8) (match_dup 7))
(match_dup 9)))
(use (const_int 1))]))
;; Step 4
;; r0 = 1/2 - G0 * H0 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
(plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 3)))
(match_dup 5)))
(use (const_int 1))]))
;; Step 5
;; H1 = H0 + r0 * H0 in f8
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
(plus:XF (mult:XF (match_dup 4) (match_dup 3))
(match_dup 3)))
(use (const_int 1))]))
;; Step 6
;; G1 = G0 + r0 * G0 in f7
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 7)
(plus:XF (mult:XF (match_dup 4) (match_dup 7))
(match_dup 7)))
(use (const_int 1))]))
;; Step 7
;; r1 = 1/2 - G1 * H1 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
(plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 3)))
(match_dup 5)))
(use (const_int 1))]))
;; Step 8
;; H2 = H1 + r1 * H1 in f8
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
(plus:XF (mult:XF (match_dup 4) (match_dup 3))
(match_dup 3)))
(use (const_int 1))]))
;; Step 9
;; G2 = G1 + r1 * G1 in f7
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 7)
(plus:XF (mult:XF (match_dup 4) (match_dup 7))
(match_dup 7)))
(use (const_int 1))]))
;; Step 10
;; d2 = a - G2 * G2 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
(plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 7)))
(match_dup 8)))
(use (const_int 1))]))
;; Step 11
;; G3 = G2 + d2 * H2 in f7
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 7)
(plus:XF (mult:XF (match_dup 4) (match_dup 3))
(match_dup 7)))
(use (const_int 1))]))
;; Step 12
;; d3 = a - G3 * G3 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
(plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 7)))
(match_dup 8)))
(use (const_int 1))]))
;; Step 13
;; S = G3 + d3 * H2 in f7
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 0)
(float_truncate:DF
(plus:XF (mult:XF (match_dup 4) (match_dup 3))
(match_dup 7))))
(use (const_int 0))]))]
{
/* Generate 82-bit versions of the input and output operands. */
operands[7] = gen_rtx_REG (XFmode, REGNO (operands[0]));
operands[8] = gen_rtx_REG (XFmode, REGNO (operands[1]));
/* Generate required floating-point constants. */
operands[9] = CONST0_RTX (XFmode);
2003-07-11 03:40:53 +00:00
}
[(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
;; :: 80 bit floating point arithmetic
;; ::
;; ::::::::::::::::::::
2004-07-28 03:11:36 +00:00
(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_fp01_operand" "fG")))]
""
"fadd %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*addxf3_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
2004-07-28 03:11:36 +00:00
(plus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))]
""
"fadd.s %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*addxf3_truncdf"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(plus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))]
""
"fadd.d %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(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_fp01_operand" "fG")))]
""
"fsub %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*subxf3_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
2004-07-28 03:11:36 +00:00
(minus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))]
""
"fsub.s %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*subxf3_truncdf"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(minus:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))]
""
"fsub.d %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(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")])
2004-07-28 03:11:36 +00:00
(define_insn "*mulxf3_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
2004-07-28 03:11:36 +00:00
(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")])
2004-07-28 03:11:36 +00:00
(define_insn "*mulxf3_truncdf"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(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")])
2004-07-28 03:11:36 +00:00
(define_insn "*mulxf3_alts"
[(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")))
(use (match_operand:SI 3 "const_int_operand" ""))]
2004-07-28 03:11:36 +00:00
""
"fmpy.s%3 %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*mulxf3_truncsf_alts"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
2004-07-28 03:11:36 +00:00
(mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))
(use (match_operand:SI 3 "const_int_operand" ""))]
2004-07-28 03:11:36 +00:00
""
"fmpy.s.s%3 %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*mulxf3_truncdf_alts"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))
(use (match_operand:SI 3 "const_int_operand" ""))]
2004-07-28 03:11:36 +00:00
""
"fmpy.d.s%3 %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(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")])
2004-07-28 03:11:36 +00:00
(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")])
2004-07-28 03:11:36 +00:00
(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")])
2004-07-28 03:11:36 +00:00
(define_insn "minxf3"
[(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")])
2004-07-28 03:11:36 +00:00
(define_insn "maxxf3"
[(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")])
2004-07-28 03:11:36 +00:00
(define_insn "*maddxf4"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))]
""
"fma %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*maddxf4_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
""
"fma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*maddxf4_truncdf"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
""
"fma.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*maddxf4_alts"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))
(use (match_operand:SI 4 "const_int_operand" ""))]
2004-07-28 03:11:36 +00:00
""
"fma.s%4 %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*maddxf4_alts_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
(plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))
(use (match_operand:SI 4 "const_int_operand" ""))]
""
"fma.s.s%4 %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_insn "*maddxf4_alts_truncdf"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))
(use (match_operand:SI 4 "const_int_operand" ""))]
2004-07-28 03:11:36 +00:00
""
"fma.d.s%4 %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*msubxf4"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(minus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))]
""
"fms %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*msubxf4_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
2004-07-28 03:11:36 +00:00
(minus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
""
"fms.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*msubxf4_truncdf"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(minus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
""
"fms.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(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")])
2004-07-28 03:11:36 +00:00
(define_insn "*nmulxf3_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
2004-07-28 03:11:36 +00:00
(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")])
2004-07-28 03:11:36 +00:00
(define_insn "*nmulxf3_truncdf"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(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")])
;; ??? Is it possible to canonicalize this as (minus (reg) (mult))?
2004-07-28 03:11:36 +00:00
(define_insn "*nmaddxf4"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(plus:XF (neg:XF (mult:XF
(match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))]
""
"fnma %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*nmaddxf4_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF
(match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
""
"fnma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*nmaddxf4_truncdf"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF
(match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
""
"fnma.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*nmaddxf4_alts"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(plus:XF (neg:XF (mult:XF
(match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))
(use (match_operand:SI 4 "const_int_operand" ""))]
2004-07-28 03:11:36 +00:00
""
"fnma.s%4 %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_insn "*nmaddxf4_truncdf_alts"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF
(mult:XF
(match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
(match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))
(use (match_operand:SI 4 "const_int_operand" ""))]
2004-07-28 03:11:36 +00:00
""
"fnma.d.s%4 %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
2004-07-28 03:11:36 +00:00
(define_expand "divxf3"
[(set (match_operand:XF 0 "fr_register_operand" "")
(div:XF (match_operand:XF 1 "fr_register_operand" "")
(match_operand:XF 2 "fr_register_operand" "")))]
"TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
2003-07-11 03:40:53 +00:00
if (TARGET_INLINE_FLOAT_DIV_LAT)
2004-07-28 03:11:36 +00:00
insn = gen_divxf3_internal_lat (operands[0], operands[1], operands[2]);
else
2004-07-28 03:11:36 +00:00
insn = gen_divxf3_internal_thr (operands[0], operands[1], operands[2]);
emit_insn (insn);
DONE;
2003-07-11 03:40:53 +00:00
})
2004-07-28 03:11:36 +00:00
(define_insn_and_split "divxf3_internal_lat"
[(set (match_operand:XF 0 "fr_register_operand" "=&f")
(div:XF (match_operand:XF 1 "fr_register_operand" "f")
(match_operand:XF 2 "fr_register_operand" "f")))
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=&f"))
(clobber (match_scratch:XF 5 "=&f"))
(clobber (match_scratch:XF 6 "=&f"))
(clobber (match_scratch:BI 7 "=c"))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_FLOAT_DIV_LAT"
"#"
"&& reload_completed"
2004-07-28 03:11:36 +00:00
[(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2)))
2003-07-11 03:40:53 +00:00
(set (match_dup 7) (unspec:BI [(match_dup 1) (match_dup 2)]
UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
(match_dup 8)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 5) (mult:XF (match_dup 3) (match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 6)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 3))
(match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 5) (match_dup 5))
(match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 5)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 6) (match_dup 0))
(match_dup 0)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 5) (match_dup 3))
(match_dup 0)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 4)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 4)))
(match_dup 1)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 0))
(match_dup 4)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 5)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
(match_dup 8)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 0))
(match_dup 0)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 4)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
(match_dup 1)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 0))
(match_dup 3))))
]
2004-07-28 03:11:36 +00:00
"operands[8] = CONST1_RTX (XFmode);"
[(set_attr "predicable" "no")])
2004-07-28 03:11:36 +00:00
(define_insn_and_split "divxf3_internal_thr"
[(set (match_operand:XF 0 "fr_register_operand" "=&f")
(div:XF (match_operand:XF 1 "fr_register_operand" "f")
(match_operand:XF 2 "fr_register_operand" "f")))
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=&f"))
(clobber (match_scratch:BI 5 "=c"))]
2004-07-28 03:11:36 +00:00
"TARGET_INLINE_FLOAT_DIV_THR"
"#"
"&& reload_completed"
2004-07-28 03:11:36 +00:00
[(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2)))
2003-07-11 03:40:53 +00:00
(set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)]
UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
(match_dup 6)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 0))
(match_dup 0)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 3) (mult:XF (match_dup 3) (match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 4))
(match_dup 4)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
2004-07-28 03:11:36 +00:00
(parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
(match_dup 6)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 0) (match_dup 3))
(match_dup 3)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 4)))
(match_dup 1)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 3) (match_dup 0))
(match_dup 4)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
(match_dup 6)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 0))
(match_dup 0)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
2004-07-28 03:11:36 +00:00
(plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
(match_dup 1)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(set (match_dup 0)
2004-07-28 03:11:36 +00:00
(plus:XF (mult:XF (match_dup 4) (match_dup 0))
(match_dup 3))))
]
2004-07-28 03:11:36 +00:00
"operands[6] = CONST1_RTX (XFmode);"
[(set_attr "predicable" "no")])
;; Inline square root.
(define_expand "sqrtxf2"
[(set (match_operand:XF 0 "fr_register_operand" "=&f")
(sqrt:XF (match_operand:XF 1 "fr_register_operand" "f")))]
"TARGET_INLINE_SQRT"
{
rtx insn;
if (TARGET_INLINE_SQRT_LAT)
#if 0
insn = gen_sqrtxf2_internal_lat (operands[0], operands[1]);
#else
abort ();
#endif
else
insn = gen_sqrtxf2_internal_thr (operands[0], operands[1]);
emit_insn (insn);
DONE;
})
;; Latency-optimized square root.
;; FIXME: Implement.
;; Throughput-optimized square root.
(define_insn_and_split "sqrtxf2_internal_thr"
[(set (match_operand:XF 0 "fr_register_operand" "=&f")
(sqrt:XF (match_operand:XF 1 "fr_register_operand" "f")))
;; Register r2 in optimization guide.
(clobber (match_scratch:DI 2 "=r"))
;; Register f8 in optimization guide
(clobber (match_scratch:XF 3 "=&f"))
;; Register f9 in optimization guide
(clobber (match_scratch:XF 4 "=&f"))
;; Register f10 in optimization guide
(clobber (match_scratch:XF 5 "=&f"))
;; Register f11 in optimization guide
(clobber (match_scratch:XF 6 "=&f"))
;; Register p6 in optimization guide.
(clobber (match_scratch:BI 7 "=c"))]
"TARGET_INLINE_SQRT_THR"
"#"
"&& reload_completed"
[ ;; exponent of +1/2 in r2
(set (match_dup 2) (const_int 65534))
;; +1/2 in f8. The Intel manual mistakenly specifies f10.
(set (match_dup 3)
(unspec:XF [(match_dup 2)] UNSPEC_SETF_EXP))
;; Step 1
;; y0 = 1/sqrt(a) in f7
(parallel [(set (match_dup 8)
(div:XF (const_int 1)
(sqrt:XF (match_dup 9))))
(set (match_dup 7)
(unspec:BI [(match_dup 9)]
UNSPEC_FR_SQRT_RECIP_APPROX))
(use (const_int 0))])
;; Step 2
;; H0 = 1/2 * y0 in f9
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 4)
(plus:XF (mult:XF (match_dup 3) (match_dup 8))
(match_dup 10)))
(use (const_int 1))]))
;; Step 3
;; S0 = a * y0 in f7
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 8)
(plus:XF (mult:XF (match_dup 9) (match_dup 8))
(match_dup 10)))
(use (const_int 1))]))
;; Step 4
;; d0 = 1/2 - S0 * H0 in f10
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 5)
(plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 4)))
(match_dup 3)))
(use (const_int 1))]))
;; Step 5
;; H1 = H0 + d0 * H0 in f9
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 4)
(plus:XF (mult:XF (match_dup 5) (match_dup 4))
(match_dup 4)))
(use (const_int 1))]))
;; Step 6
;; S1 = S0 + d0 * S0 in f7
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 8)
(plus:XF (mult:XF (match_dup 5) (match_dup 8))
(match_dup 8)))
(use (const_int 1))]))
;; Step 7
;; d1 = 1/2 - S1 * H1 in f10
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 5)
(plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 4)))
(match_dup 3)))
(use (const_int 1))]))
;; Step 8
;; H2 = H1 + d1 * H1 in f9
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 4)
(plus:XF (mult:XF (match_dup 5) (match_dup 4))
(match_dup 4)))
(use (const_int 1))]))
;; Step 9
;; S2 = S1 + d1 * S1 in f7
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 8)
(plus:XF (mult:XF (match_dup 5) (match_dup 8))
(match_dup 8)))
(use (const_int 1))]))
;; Step 10
;; d2 = 1/2 - S2 * H2 in f10
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 5)
(plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 4)))
(match_dup 3)))
(use (const_int 1))]))
;; Step 11
;; e2 = a - S2 * S2 in f8
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
(plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 8)))
(match_dup 9)))
(use (const_int 1))]))
;; Step 12
;; S3 = S2 + e2 * H2 in f7
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 8)
(plus:XF (mult:XF (match_dup 3) (match_dup 4))
(match_dup 8)))
(use (const_int 1))]))
;; Step 13
;; H3 = H2 + d2 * H2 in f9
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 4)
(plus:XF (mult:XF (match_dup 5) (match_dup 4))
(match_dup 4)))
(use (const_int 1))]))
;; Step 14
;; e3 = a - S3 * S3 in f8
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
(plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 8)))
(match_dup 9)))
(use (const_int 1))]))
;; Step 15
;; S = S3 + e3 * H3 in f7
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 0)
(plus:XF (mult:XF (match_dup 3) (match_dup 4))
(match_dup 8)))
(use (const_int 0))]))]
{
/* Generate 82-bit versions of the input and output operands. */
operands[8] = gen_rtx_REG (XFmode, REGNO (operands[0]));
operands[9] = gen_rtx_REG (XFmode, REGNO (operands[1]));
/* Generate required floating-point constants. */
operands[10] = CONST0_RTX (XFmode);
}
[(set_attr "predicable" "no")])
;; ??? frcpa works like cmp.foo.unc.
(define_insn "*recip_approx"
2004-07-28 03:11:36 +00:00
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(div:XF (const_int 1)
(match_operand:XF 3 "fr_register_operand" "f")))
(set (match_operand:BI 1 "register_operand" "=c")
2004-07-28 03:11:36 +00:00
(unspec:BI [(match_operand:XF 2 "fr_register_operand" "f")
2003-07-11 03:40:53 +00:00
(match_dup 3)] UNSPEC_FR_RECIP_APPROX))
(use (match_operand:SI 4 "const_int_operand" ""))]
2004-07-28 03:11:36 +00:00
""
"frcpa.s%4 %0, %1 = %2, %3"
[(set_attr "itanium_class" "fmisc")
(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
;; :: 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;
}
2003-07-11 03:40:53 +00:00
})
(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;
2003-07-11 03:40:53 +00:00
})
(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;
2003-07-11 03:40:53 +00:00
})
;; 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;
}
2003-07-11 03:40:53 +00:00
})
(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;
}
2003-07-11 03:40:53 +00:00
})
(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")))]
""
"#"
"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)))]
2003-07-11 03:40:53 +00:00
{
operands[3] = gen_rtx_REG (DImode, REGNO (operands[0]));
operands[2] = GEN_INT (32 - INTVAL (operands[2]));
})
;; ::::::::::::::::::::
;; ::
;; :: 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"
"* abort ();"
"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;
2003-07-11 03:40:53 +00:00
})
(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;
2003-07-11 03:40:53 +00:00
})
(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")])
;; ::::::::::::::::::::
;; ::
;; :: 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 "cmpbi"
[(set (cc0)
(compare (match_operand:BI 0 "register_operand" "")
(match_operand:BI 1 "const_int_operand" "")))]
""
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
2003-07-11 03:40:53 +00:00
})
(define_expand "cmpsi"
[(set (cc0)
(compare (match_operand:SI 0 "gr_register_operand" "")
(match_operand:SI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))]
""
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
2003-07-11 03:40:53 +00:00
})
(define_expand "cmpdi"
[(set (cc0)
(compare (match_operand:DI 0 "gr_register_operand" "")
(match_operand:DI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))]
""
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
2003-07-11 03:40:53 +00:00
})
(define_expand "cmpsf"
[(set (cc0)
(compare (match_operand:SF 0 "fr_reg_or_fp01_operand" "")
(match_operand:SF 1 "fr_reg_or_fp01_operand" "")))]
""
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
2003-07-11 03:40:53 +00:00
})
(define_expand "cmpdf"
[(set (cc0)
(compare (match_operand:DF 0 "fr_reg_or_fp01_operand" "")
(match_operand:DF 1 "fr_reg_or_fp01_operand" "")))]
""
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
2003-07-11 03:40:53 +00:00
})
2004-07-28 03:11:36 +00:00
(define_expand "cmpxf"
[(set (cc0)
(compare (match_operand:XF 0 "xfreg_or_fp01_operand" "")
(match_operand:XF 1 "xfreg_or_fp01_operand" "")))]
""
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
})
(define_expand "cmptf"
[(set (cc0)
2004-07-28 03:11:36 +00:00
(compare (match_operand:TF 0 "gr_register_operand" "")
(match_operand:TF 1 "gr_register_operand" "")))]
"TARGET_HPUX"
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
2003-07-11 03:40:53 +00:00
})
(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")])
2004-07-28 03:11:36 +00:00
(define_insn "*cmpxf_internal"
[(set (match_operand:BI 0 "register_operand" "=c")
(match_operator:BI 1 "comparison_operator"
2004-07-28 03:11:36 +00:00
[(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 "immediate_operand" "n"))
(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 "immediate_operand" "n"))
(const_int 0)))]
""
"tbit.nz %0, %I0 = %1, %2"
[(set_attr "itanium_class" "tbit")])
;; ::::::::::::::::::::
;; ::
;; :: Branches
;; ::
;; ::::::::::::::::::::
(define_expand "beq"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = ia64_expand_compare (EQ, VOIDmode);")
(define_expand "bne"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = ia64_expand_compare (NE, VOIDmode);")
(define_expand "blt"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = ia64_expand_compare (LT, VOIDmode);")
(define_expand "ble"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = ia64_expand_compare (LE, VOIDmode);")
(define_expand "bgt"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = ia64_expand_compare (GT, VOIDmode);")
(define_expand "bge"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = ia64_expand_compare (GE, VOIDmode);")
(define_expand "bltu"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = ia64_expand_compare (LTU, VOIDmode);")
(define_expand "bleu"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = ia64_expand_compare (LEU, VOIDmode);")
(define_expand "bgtu"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = ia64_expand_compare (GTU, VOIDmode);")
(define_expand "bgeu"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = ia64_expand_compare (GEU, VOIDmode);")
(define_expand "bunordered"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = ia64_expand_compare (UNORDERED, VOIDmode);")
(define_expand "bordered"
[(set (pc)
(if_then_else (match_dup 1)
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = ia64_expand_compare (ORDERED, VOIDmode);")
(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 "" "")) ; iterations; zero if unknown
(use (match_operand 2 "" "")) ; max iterations
(use (match_operand 3 "" "")) ; loop level
(use (match_operand 4 "" ""))] ; label
""
{
/* Only use cloop on innermost loops. */
if (INTVAL (operands[3]) > 1)
FAIL;
emit_jump_insn (gen_doloop_end_internal (gen_rtx_REG (DImode, AR_LC_REGNUM),
operands[4]));
DONE;
2003-07-11 03:40:53 +00:00
})
(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))
2003-07-11 03:40:53 +00:00
(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 "seq"
[(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
""
"operands[1] = ia64_expand_compare (EQ, DImode);")
(define_expand "sne"
[(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
""
"operands[1] = ia64_expand_compare (NE, DImode);")
(define_expand "slt"
[(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
""
"operands[1] = ia64_expand_compare (LT, DImode);")
(define_expand "sle"
[(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
""
"operands[1] = ia64_expand_compare (LE, DImode);")
(define_expand "sgt"
[(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
""
"operands[1] = ia64_expand_compare (GT, DImode);")
(define_expand "sge"
[(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
""
"operands[1] = ia64_expand_compare (GE, DImode);")
(define_expand "sltu"
[(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
""
"operands[1] = ia64_expand_compare (LTU, DImode);")
(define_expand "sleu"
[(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
""
"operands[1] = ia64_expand_compare (LEU, DImode);")
(define_expand "sgtu"
[(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
""
"operands[1] = ia64_expand_compare (GTU, DImode);")
(define_expand "sgeu"
[(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
""
"operands[1] = ia64_expand_compare (GEU, DImode);")
(define_expand "sunordered"
[(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
""
"operands[1] = ia64_expand_compare (UNORDERED, DImode);")
(define_expand "sordered"
[(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))]
""
"operands[1] = ia64_expand_compare (ORDERED, DImode);")
;; 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 "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 "move_operand"
2004-07-28 03:11:36 +00:00
"rim, *f, *b,*d*e,rim,rim, rim,*f,*b,*d*e,rO,*f,rOQ,rO, rK")
(match_operand:DI 3 "move_operand"
2004-07-28 03:11:36 +00:00
"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])"
2003-07-11 03:40:53 +00:00
{ abort (); }
[(set_attr "predicable" "no")])
(define_split
[(set (match_operand 0 "destination_operand" "")
(if_then_else
(match_operator 4 "predicate_operator"
[(match_operand:BI 1 "register_operand" "")
(const_int 0)])
(match_operand 2 "move_operand" "")
(match_operand 3 "move_operand" "")))]
"reload_completed"
[(const_int 0)]
{
2004-07-28 03:11:36 +00:00
bool emitted_something = false;
rtx dest = operands[0];
rtx srct = operands[2];
rtx srcf = operands[3];
rtx cond = operands[4];
2003-07-11 03:40:53 +00:00
2004-07-28 03:11:36 +00:00
if (! rtx_equal_p (dest, srct))
{
2004-07-28 03:11:36 +00:00
ia64_emit_cond_move (dest, srct, cond);
emitted_something = true;
}
2004-07-28 03:11:36 +00:00
if (! rtx_equal_p (dest, srcf))
{
2004-07-28 03:11:36 +00:00
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;
}
2003-07-11 03:40:53 +00:00
if (! emitted_something)
2004-07-28 03:11:36 +00:00
emit_note (NOTE_INSN_DELETED);
DONE;
2003-07-11 03:40:53 +00:00
})
;; 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);
2003-07-11 03:40:53 +00:00
})
;;
;; SImode if_then_else patterns.
;;
(define_insn "*cmovsi_internal"
[(set (match_operand:SI 0 "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 "move_operand"
2004-07-28 03:11:36 +00:00
"0,0,0,rim*f,rO,rO,rim*f,rO,rO")
(match_operand:SI 3 "move_operand"
2004-07-28 03:11:36 +00:00
"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])"
2003-07-11 03:40:53 +00:00
{ abort (); }
[(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);
2003-07-11 03:40:53 +00:00
})
(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);
2003-07-11 03:40:53 +00:00
}
[(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);
2003-07-11 03:40:53 +00:00
}
[(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 "" ""))]
""
{
2003-07-11 03:40:53 +00:00
ia64_expand_call (NULL_RTX, operands[0], operands[2], false);
DONE;
2003-07-11 03:40:53 +00:00
})
(define_expand "sibcall"
[(use (match_operand:DI 0 "" ""))
(use (match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(use (match_operand 3 "" ""))]
""
{
2003-07-11 03:40:53 +00:00
ia64_expand_call (NULL_RTX, operands[0], operands[2], true);
DONE;
2003-07-11 03:40:53 +00:00
})
;; 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 "" ""))]
""
{
2003-07-11 03:40:53 +00:00
ia64_expand_call (operands[0], operands[1], operands[3], false);
DONE;
2003-07-11 03:40:53 +00:00
})
(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 "" ""))]
""
{
2003-07-11 03:40:53 +00:00
ia64_expand_call (operands[0], operands[1], operands[3], true);
DONE;
2003-07-11 03:40:53 +00:00
})
;; 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;
2003-07-11 03:40:53 +00:00
})
2003-07-11 03:40:53 +00:00
(define_insn "call_nogp"
[(call (mem:DI (match_operand:DI 0 "call_operand" "?b,i"))
(const_int 0))
(clobber (match_operand:DI 1 "register_operand" "=b,b"))]
""
2003-07-11 03:40:53 +00:00
"br.call%+.many %1 = %0"
[(set_attr "itanium_class" "br,scall")])
2003-07-11 03:40:53 +00:00
(define_insn "call_value_nogp"
2004-07-28 03:11:36 +00:00
[(set (match_operand 0 "" "=X,X")
2003-07-11 03:40:53 +00:00
(call (mem:DI (match_operand:DI 1 "call_operand" "?b,i"))
(const_int 0)))
(clobber (match_operand:DI 2 "register_operand" "=b,b"))]
""
2003-07-11 03:40:53 +00:00
"br.call%+.many %2 = %1"
[(set_attr "itanium_class" "br,scall")])
2003-07-11 03:40:53 +00:00
(define_insn "sibcall_nogp"
[(call (mem:DI (match_operand:DI 0 "call_operand" "?b,i"))
(const_int 0))]
""
"br%+.many %0"
[(set_attr "itanium_class" "br,scall")])
2003-07-11 03:40:53 +00:00
(define_insn "call_gp"
2004-07-28 03:11:36 +00:00
[(call (mem:DI (match_operand:DI 0 "call_operand" "?r,i"))
2003-07-11 03:40:53 +00:00
(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"))]
""
2003-07-11 03:40:53 +00:00
"#"
[(set_attr "itanium_class" "br,scall")])
2003-07-11 03:40:53 +00:00
;; 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"
2004-07-28 03:11:36 +00:00
[(set (match_operand 0 "" "=X,X")
2003-07-11 03:40:53 +00:00
(call (mem:DI (match_operand:DI 1 "call_operand" "?r,i"))
(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"))]
""
2003-07-11 03:40:53 +00:00
"#"
[(set_attr "itanium_class" "br,scall")])
2003-07-11 03:40:53 +00:00
(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,i"))
(const_int 1))
(clobber (match_scratch:DI 1 "=&r,X"))
(clobber (match_scratch:DI 2 "=b,X"))]
""
2003-07-11 03:40:53 +00:00
"#"
"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:DI 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);
if (! rtx_equal_p (SET_DEST (set), op0)
|| GET_CODE (SET_SRC (set)) != MEM)
abort ();
addr = XEXP (SET_SRC (set), 0);
if (rtx_equal_p (addr, op0))
abort ();
}
/* 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, 1, 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;
2003-07-11 03:40:53 +00:00
})
(define_expand "epilogue"
[(return)]
""
{
ia64_expand_epilogue (0);
DONE;
2003-07-11 03:40:53 +00:00
})
(define_expand "sibcall_epilogue"
[(return)]
""
{
ia64_expand_epilogue (1);
DONE;
2003-07-11 03:40:53 +00:00
})
;; This prevents the scheduler from moving the SP decrement past FP-relative
;; stack accesses. This is the same as adddi3 plus the extra set.
(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))]
""
"@
2003-07-11 03:40:53 +00:00
add %0 = %1, %2
adds %0 = %2, %1
addl %0 = %2, %1"
[(set_attr "itanium_class" "ialu")])
;; This prevents the scheduler from moving the SP restore past FP-relative
;; stack accesses. This is similar to movdi plus the extra set.
(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")])
2003-07-11 03:40:53 +00:00
;; 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")
2004-07-28 03:11:36 +00:00
(set_attr "predicable" "no")
(set_attr "empty" "yes")])
2003-07-11 03:40:53 +00:00
;; Allocate a new register frame.
(define_insn "alloc"
[(set (match_operand:DI 0 "register_operand" "=r")
2003-07-11 03:40:53 +00:00
(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")])
;; 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")
2003-07-11 03:40:53 +00:00
(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 "memory_operand" "=m")
(unspec:DI [(match_operand:DI 1 "register_operand" "r")
2003-07-11 03:40:53 +00:00
(match_operand:DI 2 "const_int_operand" "")]
UNSPEC_GR_SPILL))
(clobber (match_operand:DI 3 "register_operand" ""))]
""
{
2003-07-11 03:40:53 +00:00
/* 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")
2003-07-11 03:40:53 +00:00
(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")
2003-07-11 03:40:53 +00:00
(match_operand:DI 2 "const_int_operand" "")]
UNSPEC_GR_RESTORE))
(use (match_operand:DI 3 "register_operand" ""))]
""
2003-07-11 03:40:53 +00:00
{ return ".mem.offset %2, 0\;%,ld8.fill %0 = %1%P1"; }
[(set_attr "itanium_class" "ld")])
(define_insn "fr_spill"
2004-07-28 03:11:36 +00:00
[(set (match_operand:XF 0 "memory_operand" "=m")
(unspec:XF [(match_operand:XF 1 "register_operand" "f")]
2003-07-11 03:40:53 +00:00
UNSPEC_FR_SPILL))]
""
"stf.spill %0 = %1%P0"
[(set_attr "itanium_class" "stf")])
(define_insn "fr_restore"
2004-07-28 03:11:36 +00:00
[(set (match_operand:XF 0 "register_operand" "=f")
(unspec:XF [(match_operand:XF 1 "memory_operand" "m")]
2003-07-11 03:40:53 +00:00
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")
2003-07-11 03:40:53 +00:00
(unspec:DI [(const_int 0)] UNSPEC_BSP_VALUE))]
""
2003-07-11 03:40:53 +00:00
"*
{
return \";;\;%,mov %0 = ar.bsp\";
}"
[(set_attr "itanium_class" "frar_i")])
(define_insn "set_bsp"
2003-07-11 03:40:53 +00:00
[(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"
2003-07-11 03:40:53 +00:00
[(unspec [(const_int 0)] UNSPEC_FLUSHRS)]
""
";;\;flushrs\;;;"
2003-07-11 03:40:53 +00:00
[(set_attr "itanium_class" "rse_m")
(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
;; :: Miscellaneous instructions
;; ::
;; ::::::::::::::::::::
2004-07-28 03:11:36 +00:00
;; ??? 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"
2004-07-28 03:11:36 +00:00
[(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)]
""
""
2004-07-28 03:11:36 +00:00
[(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"
2003-07-11 03:40:53 +00:00
[(unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BUNDLE_SELECTOR)]
""
2003-07-11 03:40:53 +00:00
{ 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"
2003-07-11 03:40:53 +00:00
[(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
""
""
[(set_attr "itanium_class" "ignore")
(set_attr "predicable" "no")])
(define_insn "insn_group_barrier"
2003-07-11 03:40:53 +00:00
[(unspec_volatile [(match_operand 0 "const_int_operand" "")]
UNSPECV_INSN_GROUP_BARRIER)]
""
";;"
[(set_attr "itanium_class" "stop_bit")
2004-07-28 03:11:36 +00:00
(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")])
(define_expand "conditional_trap"
[(trap_if (match_operand 0 "" "") (match_operand 1 "" ""))]
""
{
operands[0] = ia64_expand_compare (GET_CODE (operands[0]), VOIDmode);
})
(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")
(set_attr "predicable" "no")])
(define_insn "break_f"
2003-07-11 03:40:53 +00:00
[(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] = {
{
2003-08-22 02:56:07 +00:00
"%,lfetch.nta [%0]",
"%,lfetch.nt1 [%0]",
"%,lfetch.nt2 [%0]",
"%,lfetch [%0]"
},
{
2003-08-22 02:56:07 +00:00
"%,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]));
if (i != 0 && i != 1)
abort ();
if (j < 0 || j > 3)
abort ();
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\"),
0, VOIDmode, 2, XEXP (operands[0], 0), Pmode,
operands[1], Pmode);
DONE;
2003-07-11 03:40:53 +00:00
})
(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;
2003-07-11 03:40:53 +00:00
})
2003-07-11 03:40:53 +00:00
(define_insn_and_split "builtin_setjmp_receiver"
[(unspec_volatile [(match_operand:DI 0 "" "")] UNSPECV_SETJMP_RECEIVER)]
""
2003-07-11 03:40:53 +00:00
"#"
"reload_completed"
[(const_int 0)]
{
2003-07-11 03:40:53 +00:00
ia64_reload_gp ();
DONE;
2003-07-11 03:40:53 +00:00
})
(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_insn (gen_rtx_USE (VOIDmode, sp));
emit_insn (gen_rtx_USE (VOIDmode, bsp));
cfun->machine->ia64_eh_epilogue_sp = sp;
cfun->machine->ia64_eh_epilogue_bsp = bsp;
2003-07-11 03:40:53 +00:00
})
;; 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,
2003-07-11 03:40:53 +00:00
"__ia64_restore_stack_nonlocal"),
0, VOIDmode, 1,
copy_to_reg (XEXP (operands[1], 0)), Pmode);
DONE;
2003-07-11 03:40:53 +00:00
})
;;; Intrinsics support.
(define_expand "mf"
[(set (mem:BLK (match_dup 0))
2003-07-11 03:40:53 +00:00
(unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_MF))]
""
{
operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
MEM_VOLATILE_P (operands[0]) = 1;
2003-07-11 03:40:53 +00:00
})
(define_insn "*mf_internal"
[(set (match_operand:BLK 0 "" "")
2003-07-11 03:40:53 +00:00
(unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_MF))]
""
"mf"
[(set_attr "itanium_class" "syst_m")])
(define_insn "fetchadd_acq_si"
[(set (match_operand:SI 0 "gr_register_operand" "=r")
2004-07-28 03:11:36 +00:00
(match_operand:SI 1 "not_postinc_memory_operand" "+S"))
(set (match_dup 1)
(unspec:SI [(match_dup 1)
2003-07-11 03:40:53 +00:00
(match_operand:SI 2 "fetchadd_operand" "n")]
UNSPEC_FETCHADD_ACQ))]
""
"fetchadd4.acq %0 = %1, %2"
[(set_attr "itanium_class" "sem")])
(define_insn "fetchadd_acq_di"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
2004-07-28 03:11:36 +00:00
(match_operand:DI 1 "not_postinc_memory_operand" "+S"))
(set (match_dup 1)
(unspec:DI [(match_dup 1)
2003-07-11 03:40:53 +00:00
(match_operand:DI 2 "fetchadd_operand" "n")]
UNSPEC_FETCHADD_ACQ))]
""
"fetchadd8.acq %0 = %1, %2"
[(set_attr "itanium_class" "sem")])
(define_insn "cmpxchg_acq_si"
[(set (match_operand:SI 0 "gr_register_operand" "=r")
2004-07-28 03:11:36 +00:00
(match_operand:SI 1 "not_postinc_memory_operand" "+S"))
(set (match_dup 1)
(unspec:SI [(match_dup 1)
(match_operand:SI 2 "gr_register_operand" "r")
2004-07-28 03:11:36 +00:00
(match_operand:DI 3 "ar_ccv_reg_operand" "")]
2003-07-11 03:40:53 +00:00
UNSPEC_CMPXCHG_ACQ))]
""
"cmpxchg4.acq %0 = %1, %2, %3"
[(set_attr "itanium_class" "sem")])
(define_insn "cmpxchg_acq_di"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
2004-07-28 03:11:36 +00:00
(match_operand:DI 1 "not_postinc_memory_operand" "+S"))
(set (match_dup 1)
(unspec:DI [(match_dup 1)
(match_operand:DI 2 "gr_register_operand" "r")
2003-07-11 03:40:53 +00:00
(match_operand:DI 3 "ar_ccv_reg_operand" "")]
UNSPEC_CMPXCHG_ACQ))]
""
"cmpxchg8.acq %0 = %1, %2, %3"
[(set_attr "itanium_class" "sem")])
(define_insn "xchgsi"
[(set (match_operand:SI 0 "gr_register_operand" "=r")
(match_operand:SI 1 "not_postinc_memory_operand" "+S"))
(set (match_dup 1)
(match_operand:SI 2 "gr_register_operand" "r"))]
""
"xchg4 %0 = %1, %2"
[(set_attr "itanium_class" "sem")])
(define_insn "xchgdi"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
(match_operand:DI 1 "not_postinc_memory_operand" "+S"))
(set (match_dup 1)
(match_operand:DI 2 "gr_register_operand" "r"))]
""
"xchg8 %0 = %1, %2"
[(set_attr "itanium_class" "sem")])
;; 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")
2003-07-11 03:40:53 +00:00
(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"
2003-07-11 03:40:53 +00:00
[(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"
2003-07-11 03:40:53 +00:00
[(unspec_volatile [(const_int 0)] UNSPECV_PSAC_NORMAL)]
""
{
2004-07-28 03:11:36 +00:00
emit_safe_across_calls ();
2003-07-11 03:40:53 +00:00
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")
2003-07-11 03:40:53 +00:00
(unspec:DI [(match_operand:SI 1 "gr_register_operand" "r")]
UNSPEC_ADDP4))]
""
"addp4 %0 = 0,%1"
[(set_attr "itanium_class" "ialu")])
;;
2003-07-11 03:40:53 +00:00
;; Optimizations for ptr_extend
2004-07-28 03:11:36 +00:00
(define_insn "ptr_extend_plus_imm"
2003-07-11 03:40:53 +00:00
[(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")])