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