;; IA-64 Machine description template ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 ;; Free Software Foundation, Inc. ;; Contributed by James E. Wilson and ;; David Mosberger . ;; 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 ;; . ;;- 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_constants [; Relocations (UNSPEC_LTOFF_DTPMOD 0) (UNSPEC_LTOFF_DTPREL 1) (UNSPEC_DTPREL 2) (UNSPEC_LTOFF_TPREL 3) (UNSPEC_TPREL 4) (UNSPEC_DTPMOD 5) (UNSPEC_LD_BASE 9) (UNSPEC_GR_SPILL 10) (UNSPEC_GR_RESTORE 11) (UNSPEC_FR_SPILL 12) (UNSPEC_FR_RESTORE 13) (UNSPEC_FR_RECIP_APPROX 14) (UNSPEC_PRED_REL_MUTEX 15) (UNSPEC_GETF_EXP 16) (UNSPEC_PIC_CALL 17) (UNSPEC_MF 18) (UNSPEC_CMPXCHG_ACQ 19) (UNSPEC_FETCHADD_ACQ 20) (UNSPEC_BSP_VALUE 21) (UNSPEC_FLUSHRS 22) (UNSPEC_BUNDLE_SELECTOR 23) (UNSPEC_ADDP4 24) (UNSPEC_PROLOGUE_USE 25) (UNSPEC_RET_ADDR 26) (UNSPEC_SETF_EXP 27) (UNSPEC_FR_SQRT_RECIP_APPROX 28) (UNSPEC_SHRP 29) (UNSPEC_COPYSIGN 30) (UNSPEC_VECT_EXTR 31) (UNSPEC_LDA 40) (UNSPEC_LDS 41) (UNSPEC_LDSA 42) (UNSPEC_LDCCLR 43) (UNSPEC_CHKACLR 45) (UNSPEC_CHKS 47) (UNSPEC_FR_RECIP_APPROX_RES 48) ]) (define_constants [(UNSPECV_ALLOC 0) (UNSPECV_BLOCKAGE 1) (UNSPECV_INSN_GROUP_BARRIER 2) (UNSPECV_BREAK 3) (UNSPECV_SET_BSP 4) (UNSPECV_PSAC_ALL 5) ; pred.safe_across_calls (UNSPECV_PSAC_NORMAL 6) (UNSPECV_SETJMP_RECEIVER 7) ]) (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 "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")) ;; 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 "itanium1.md") (include "itanium2.md") ;; :::::::::::::::::::: ;; :: ;; :: Moves ;; :: ;; :::::::::::::::::::: ;; Set of a single predicate register. This is only used to implement ;; pr-to-pr move and complement. (define_insn "*movcci" [(set (match_operand:CCI 0 "register_operand" "=c,c,c") (match_operand:CCI 1 "nonmemory_operand" "O,n,c"))] "" "@ cmp.ne %0, p0 = r0, r0 cmp.eq %0, p0 = r0, r0 (%1) cmp.eq.unc %0, p0 = r0, r0" [(set_attr "itanium_class" "icmp") (set_attr "predicable" "no")]) (define_insn "movbi" [(set (match_operand:BI 0 "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")]) (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")]) (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")]) (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, m, r,*f,*f, r,*d") (match_operand:SI 1 "move_operand" "rO,J,i,m,rO,*f,rO,*f,*d,rK"))] "ia64_move_ok (operands[0], operands[1])" "@ mov %0 = %r1 addl %0 = %1, r0 movl %0 = %1 ld4%O1 %0 = %1%P1 st4%Q0 %0 = %r1%P0 getf.sig %0 = %1 setf.sig %0 = %r1 mov %0 = %1 mov %0 = %1 mov %0 = %r1" ;; frar_m, toar_m ??? why not frar_i and toar_i [(set_attr "itanium_class" "ialu,ialu,long_i,ld,st,frfr,tofr,fmisc,frar_m,toar_m")]) (define_expand "movdi" [(set (match_operand:DI 0 "general_operand" "") (match_operand:DI 1 "general_operand" ""))] "" { rtx op1 = ia64_expand_move (operands[0], operands[1]); if (!op1) DONE; operands[1] = op1; }) (define_insn "*movdi_internal" [(set (match_operand:DI 0 "destination_operand" "=r,r,r,r, m, r,*f,*f,*f, Q, r,*b, r,*e, r,*d, r,*c") (match_operand:DI 1 "move_operand" "rO,JT,i,m,rO,*f,rO,*f, Q,*f,*b,rO,*e,rK,*d,rK,*c,rO"))] "ia64_move_ok (operands[0], operands[1])" { static const char * const alt[] = { "%,mov %0 = %r1", "%,addl %0 = %1, r0", "%,movl %0 = %1", "%,ld8%O1 %0 = %1%P1", "%,st8%Q0 %0 = %r1%P0", "%,getf.sig %0 = %1", "%,setf.sig %0 = %r1", "%,mov %0 = %1", "%,ldf8 %0 = %1%P1", "%,stf8 %0 = %1%P0", "%,mov %0 = %1", "%,mov %0 = %r1", "%,mov %0 = %1", "%,mov %0 = %1", "%,mov %0 = %1", "%,mov %0 = %1", "mov %0 = pr", "mov pr = %1, -1" }; gcc_assert (which_alternative != 2 || TARGET_NO_PIC || !symbolic_operand (operands[1], VOIDmode)); return alt[which_alternative]; } [(set_attr "itanium_class" "ialu,ialu,long_i,ld,st,frfr,tofr,fmisc,fld,stf,frbr,tobr,frar_i,toar_i,frar_m,toar_m,frpr,topr")]) (define_mode_iterator MODE [BI QI HI SI DI SF DF XF TI]) (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 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 "_register_operand" "") (unspec:MODE [(match_operand:MODE 1 "memory_operand" "")] UNSPEC_LDA))] "ia64_move_ok (operands[0], operands[1])" "" [(set_attr "itanium_class" "") (set_attr "data_speculative" "")]) (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" "")] UNSPEC_LDA)))] "" "" [(set_attr "itanium_class" "") (set_attr "data_speculative" "")]) (define_insn "mov_speculative" [(set (match_operand:MODE 0 "_register_operand" "") (unspec:MODE [(match_operand:MODE 1 "memory_operand" "")] UNSPEC_LDS))] "ia64_move_ok (operands[0], operands[1])" "" [(set_attr "itanium_class" "") (set_attr "control_speculative" "")]) (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" "")] UNSPEC_LDS)))] "" "" [(set_attr "itanium_class" "") (set_attr "control_speculative" "")]) (define_insn "mov_speculative_advanced" [(set (match_operand:MODE 0 "_register_operand" "") (unspec:MODE [(match_operand:MODE 1 "memory_operand" "")] UNSPEC_LDSA))] "ia64_move_ok (operands[0], operands[1])" "" [(set_attr "itanium_class" "") (set_attr "data_speculative" "") (set_attr "control_speculative" "")]) (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" "")] UNSPEC_LDSA)))] "" "" [(set_attr "itanium_class" "") (set_attr "data_speculative" "") (set_attr "control_speculative" "")]) (define_insn "mov_clr" [(set (match_operand:MODE 0 "_register_operand" "") (if_then_else:MODE (ne (unspec [(match_dup 0)] UNSPEC_LDCCLR) (const_int 0)) (match_operand:MODE 1 "memory_operand" "") (match_dup 0)))] "ia64_move_ok (operands[0], operands[1])" "" [(set_attr "itanium_class" "") (set_attr "check_load" "")]) (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" "")) (match_dup 0)))] "" "" [(set_attr "itanium_class" "") (set_attr "check_load" "")]) (define_insn "advanced_load_check_clr_" [(set (pc) (if_then_else (ne (unspec [(match_operand:MODE 0 "_register_operand" "")] UNSPEC_CHKACLR) (const_int 0)) (pc) (label_ref (match_operand 1 "" ""))))] "" "chk.a.clr %0, %l1" [(set_attr "itanium_class" "")]) (define_insn "speculation_check_" [(set (pc) (if_then_else (ne (unspec [(match_operand:MODE 0 "_register_operand" "")] UNSPEC_CHKS) (const_int 0)) (pc) (label_ref (match_operand 1 "" ""))))] "" "chk.s %0, %l1" [(set_attr "itanium_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 (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")]) ;; 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") (match_operand:SF 1 "general_operand" "fG,Q,fG,fG,*r,*r, m,*r"))] "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" [(set_attr "itanium_class" "fmisc,fld,stf,frfr,tofr,ialu,ld,st")]) (define_expand "movdf" [(set (match_operand:DF 0 "general_operand" "") (match_operand:DF 1 "general_operand" ""))] "" { rtx op1 = ia64_expand_move (operands[0], operands[1]); if (!op1) DONE; operands[1] = op1; }) (define_insn "*movdf_internal" [(set (match_operand:DF 0 "destination_operand" "=f,f, Q,*r, f,*r,*r, m") (match_operand:DF 1 "general_operand" "fG,Q,fG,fG,*r,*r, m,*r"))] "ia64_move_ok (operands[0], operands[1])" "@ mov %0 = %F1 ldfd %0 = %1%P1 stfd %0 = %F1%P0 getf.d %0 = %F1 setf.d %0 = %1 mov %0 = %1 ld8%O1 %0 = %1%P1 st8%Q0 %0 = %1%P0" [(set_attr "itanium_class" "fmisc,fld,stf,frfr,tofr,ialu,ld,st")]) ;; With no offsettable memory references, we've got to have a scratch ;; around to play with the second word if the variable winds up in GRs. (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")]) ;; 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")]) (define_insn "zero_extendhidi2" [(set (match_operand:DI 0 "gr_register_operand" "=r,r") (zero_extend:DI (match_operand:HI 1 "gr_nonimmediate_operand" "r,m")))] "" "@ zxt2 %0 = %1 ld2%O1 %0 = %1%P1" [(set_attr "itanium_class" "xtd,ld")]) (define_insn "zero_extendsidi2" [(set (match_operand:DI 0 "grfr_register_operand" "=r,r,?f") (zero_extend:DI (match_operand:SI 1 "grfr_nonimmediate_operand" "r,m,f")))] "" "@ addp4 %0 = %1, r0 ld4%O1 %0 = %1%P1 fmix.r %0 = f0, %1" [(set_attr "itanium_class" "ialu,ld,fmisc")]) ;; Convert between floating point types of different sizes. ;; At first glance, it would appear that emitting fnorm for an extending ;; conversion is unnecessary. However, the stf and getf instructions work ;; correctly only if the input is properly rounded for its type. In ;; particular, we get the wrong result for getf.d/stfd if the input is a ;; denorm single. Since we don't know what the next instruction will be, we ;; have to emit an fnorm. ;; ??? Optimization opportunity here. Get rid of the insn altogether ;; when we can. Should probably use a scheme like has been proposed ;; for ia32 in dealing with operands that match unary operators. This ;; would let combine merge the thing into adjacent insns. See also how the ;; mips port handles SIGN_EXTEND as operands to integer arithmetic insns via ;; se_register_operand. (define_insn "extendsfdf2" [(set (match_operand:DF 0 "fr_register_operand" "=f") (float_extend:DF (match_operand:SF 1 "fr_register_operand" "f")))] "" "fnorm.d %0 = %1" [(set_attr "itanium_class" "fmac")]) (define_insn "extendsfxf2" [(set (match_operand:XF 0 "fr_register_operand" "=f") (float_extend:XF (match_operand:SF 1 "fr_register_operand" "f")))] "" "fnorm %0 = %1" [(set_attr "itanium_class" "fmac")]) (define_insn "extenddfxf2" [(set (match_operand:XF 0 "fr_register_operand" "=f") (float_extend:XF (match_operand:DF 1 "fr_register_operand" "f")))] "" "fnorm %0 = %1" [(set_attr "itanium_class" "fmac")]) (define_insn "truncdfsf2" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (match_operand:DF 1 "fr_register_operand" "f")))] "" "fnorm.s %0 = %1" [(set_attr "itanium_class" "fmac")]) (define_insn "truncxfsf2" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (match_operand:XF 1 "fr_register_operand" "f")))] "" "fnorm.s %0 = %1" [(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_register_operand" "f")))] "" "fnorm.d %0 = %1" [(set_attr "itanium_class" "fmac")]) ;; Convert between signed integer types and floating point. (define_insn "floatdixf2" [(set (match_operand:XF 0 "fr_register_operand" "=f") (float:XF (match_operand:DI 1 "fr_register_operand" "f")))] "" "fcvt.xf %0 = %1" [(set_attr "itanium_class" "fcvtfx")]) (define_insn "fix_truncsfdi2" [(set (match_operand:DI 0 "fr_register_operand" "=f") (fix:DI (match_operand:SF 1 "fr_register_operand" "f")))] "" "fcvt.fx.trunc %0 = %1" [(set_attr "itanium_class" "fcvtfx")]) (define_insn "fix_truncdfdi2" [(set (match_operand:DI 0 "fr_register_operand" "=f") (fix:DI (match_operand:DF 1 "fr_register_operand" "f")))] "" "fcvt.fx.trunc %0 = %1" [(set_attr "itanium_class" "fcvtfx")]) (define_insn "fix_truncxfdi2" [(set (match_operand:DI 0 "fr_register_operand" "=f") (fix:DI (match_operand:XF 1 "fr_register_operand" "f")))] "" "fcvt.fx.trunc %0 = %1" [(set_attr "itanium_class" "fcvtfx")]) (define_insn "fix_truncxfdi2_alts" [(set (match_operand:DI 0 "fr_register_operand" "=f") (fix:DI (match_operand:XF 1 "fr_register_operand" "f"))) (use (match_operand:SI 2 "const_int_operand" ""))] "" "fcvt.fx.trunc.s%2 %0 = %1" [(set_attr "itanium_class" "fcvtfx")]) ;; Convert between unsigned integer types and floating point. (define_insn "floatunsdisf2" [(set (match_operand:SF 0 "fr_register_operand" "=f") (unsigned_float:SF (match_operand:DI 1 "fr_register_operand" "f")))] "" "fcvt.xuf.s %0 = %1" [(set_attr "itanium_class" "fcvtfx")]) (define_insn "floatunsdidf2" [(set (match_operand:DF 0 "fr_register_operand" "=f") (unsigned_float:DF (match_operand:DI 1 "fr_register_operand" "f")))] "" "fcvt.xuf.d %0 = %1" [(set_attr "itanium_class" "fcvtfx")]) (define_insn "floatunsdixf2" [(set (match_operand:XF 0 "fr_register_operand" "=f") (unsigned_float:XF (match_operand:DI 1 "fr_register_operand" "f")))] "" "fcvt.xuf %0 = %1" [(set_attr "itanium_class" "fcvtfx")]) (define_insn "fixuns_truncsfdi2" [(set (match_operand:DI 0 "fr_register_operand" "=f") (unsigned_fix:DI (match_operand:SF 1 "fr_register_operand" "f")))] "" "fcvt.fxu.trunc %0 = %1" [(set_attr "itanium_class" "fcvtfx")]) (define_insn "fixuns_truncdfdi2" [(set (match_operand:DI 0 "fr_register_operand" "=f") (unsigned_fix:DI (match_operand:DF 1 "fr_register_operand" "f")))] "" "fcvt.fxu.trunc %0 = %1" [(set_attr "itanium_class" "fcvtfx")]) (define_insn "fixuns_truncxfdi2" [(set (match_operand:DI 0 "fr_register_operand" "=f") (unsigned_fix:DI (match_operand:XF 1 "fr_register_operand" "f")))] "" "fcvt.fxu.trunc %0 = %1" [(set_attr "itanium_class" "fcvtfx")]) (define_insn "fixuns_truncxfdi2_alts" [(set (match_operand:DI 0 "fr_register_operand" "=f") (unsigned_fix:DI (match_operand:XF 1 "fr_register_operand" "f"))) (use (match_operand:SI 2 "const_int_operand" ""))] "" "fcvt.fxu.trunc.s%2 %0 = %1" [(set_attr "itanium_class" "fcvtfx")]) ;; :::::::::::::::::::: ;; :: ;; :: Bit field extraction ;; :: ;; :::::::::::::::::::: (define_insn "extv" [(set (match_operand:DI 0 "gr_register_operand" "=r") (sign_extract:DI (match_operand:DI 1 "gr_register_operand" "r") (match_operand:DI 2 "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); }) (define_expand "divsi3" [(set (match_operand:SI 0 "register_operand" "") (div:SI (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "general_operand" "")))] "TARGET_INLINE_INT_DIV" { rtx op1_xf, op2_xf, op0_xf, op0_di, twon34, twon34_exp; op0_xf = gen_reg_rtx (XFmode); op0_di = gen_reg_rtx (DImode); if (CONSTANT_P (operands[1])) operands[1] = force_reg (SImode, operands[1]); op1_xf = gen_reg_rtx (XFmode); expand_float (op1_xf, operands[1], 0); if (CONSTANT_P (operands[2])) operands[2] = force_reg (SImode, operands[2]); op2_xf = gen_reg_rtx (XFmode); expand_float (op2_xf, operands[2], 0); /* 2^-34 */ twon34_exp = gen_reg_rtx (DImode); emit_move_insn (twon34_exp, GEN_INT (65501)); twon34 = gen_reg_rtx (XFmode); emit_insn (gen_setf_exp_xf (twon34, twon34_exp)); emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode), CONST1_RTX (SImode))); emit_insn (gen_divsi3_internal (op0_xf, op1_xf, op2_xf, twon34)); emit_insn (gen_fix_truncxfdi2_alts (op0_di, op0_xf, const1_rtx)); emit_move_insn (operands[0], gen_lowpart (SImode, op0_di)); DONE; }) (define_expand "modsi3" [(set (match_operand:SI 0 "register_operand" "") (mod:SI (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "general_operand" "")))] "TARGET_INLINE_INT_DIV" { rtx op2_neg, op1_di, div; div = gen_reg_rtx (SImode); emit_insn (gen_divsi3 (div, operands[1], operands[2])); op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0); /* This is a trick to get us to reuse the value that we're sure to have already copied to the FP regs. */ op1_di = gen_reg_rtx (DImode); convert_move (op1_di, operands[1], 0); emit_insn (gen_maddsi4 (operands[0], div, op2_neg, gen_lowpart (SImode, op1_di))); DONE; }) (define_expand "udivsi3" [(set (match_operand:SI 0 "register_operand" "") (udiv:SI (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "general_operand" "")))] "TARGET_INLINE_INT_DIV" { rtx op1_xf, op2_xf, op0_xf, op0_di, twon34, twon34_exp; op0_xf = gen_reg_rtx (XFmode); op0_di = gen_reg_rtx (DImode); if (CONSTANT_P (operands[1])) operands[1] = force_reg (SImode, operands[1]); op1_xf = gen_reg_rtx (XFmode); expand_float (op1_xf, operands[1], 1); if (CONSTANT_P (operands[2])) operands[2] = force_reg (SImode, operands[2]); op2_xf = gen_reg_rtx (XFmode); expand_float (op2_xf, operands[2], 1); /* 2^-34 */ twon34_exp = gen_reg_rtx (DImode); emit_move_insn (twon34_exp, GEN_INT (65501)); twon34 = gen_reg_rtx (XFmode); emit_insn (gen_setf_exp_xf (twon34, twon34_exp)); emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode), CONST1_RTX (SImode))); emit_insn (gen_divsi3_internal (op0_xf, op1_xf, op2_xf, twon34)); emit_insn (gen_fixuns_truncxfdi2_alts (op0_di, op0_xf, const1_rtx)); emit_move_insn (operands[0], gen_lowpart (SImode, op0_di)); DONE; }) (define_expand "umodsi3" [(set (match_operand:SI 0 "register_operand" "") (umod:SI (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "general_operand" "")))] "TARGET_INLINE_INT_DIV" { rtx op2_neg, op1_di, div; div = gen_reg_rtx (SImode); emit_insn (gen_udivsi3 (div, operands[1], operands[2])); op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0); /* This is a trick to get us to reuse the value that we're sure to have already copied to the FP regs. */ op1_di = gen_reg_rtx (DImode); convert_move (op1_di, operands[1], 1); emit_insn (gen_maddsi4 (operands[0], div, op2_neg, gen_lowpart (SImode, op1_di))); DONE; }) (define_insn_and_split "divsi3_internal" [(set (match_operand:XF 0 "fr_register_operand" "=&f") (float:XF (div:SI (match_operand:XF 1 "fr_register_operand" "f") (match_operand:XF 2 "fr_register_operand" "f")))) (clobber (match_scratch:XF 4 "=&f")) (clobber (match_scratch:XF 5 "=&f")) (clobber (match_scratch:BI 6 "=c")) (use (match_operand:XF 3 "fr_register_operand" "f"))] "TARGET_INLINE_INT_DIV" "#" "&& reload_completed" [(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2))) (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)] UNSPEC_FR_RECIP_APPROX)) (use (const_int 1))]) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 5) (minus:XF (match_dup 7) (mult:XF (match_dup 2) (match_dup 0)))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (plus:XF (mult:XF (match_dup 5) (match_dup 4)) (match_dup 4))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 5) (plus:XF (mult:XF (match_dup 5) (match_dup 5)) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 0) (plus:XF (mult:XF (match_dup 5) (match_dup 4)) (match_dup 4))) (use (const_int 1))])) ] "operands[7] = CONST1_RTX (XFmode);" [(set_attr "predicable" "no")]) ;; :::::::::::::::::::: ;; :: ;; :: 64-bit Integer arithmetic ;; :: ;; :::::::::::::::::::: (define_insn "adddi3" [(set (match_operand:DI 0 "gr_register_operand" "=r,r,r") (plus:DI (match_operand:DI 1 "gr_register_operand" "%r,r,a") (match_operand:DI 2 "gr_reg_or_22bit_operand" "r,I,J")))] "" "@ 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_register_operand" "f")) (sign_extend:TI (match_operand:DI 2 "fr_register_operand" "f"))) (const_int 64))))] "" "xmpy.h %0 = %1, %2" [(set_attr "itanium_class" "xmpy")]) (define_insn "umuldi3_highpart" [(set (match_operand:DI 0 "fr_register_operand" "=f") (truncate:DI (lshiftrt:TI (mult:TI (zero_extend:TI (match_operand:DI 1 "fr_register_operand" "f")) (zero_extend:TI (match_operand:DI 2 "fr_register_operand" "f"))) (const_int 64))))] "" "xmpy.hu %0 = %1, %2" [(set_attr "itanium_class" "xmpy")]) (define_insn "negdi2" [(set (match_operand:DI 0 "gr_register_operand" "=r") (neg:DI (match_operand:DI 1 "gr_register_operand" "r")))] "" "sub %0 = r0, %1" [(set_attr "itanium_class" "ialu")]) (define_expand "absdi2" [(set (match_dup 2) (ge:BI (match_operand:DI 1 "gr_register_operand" "") (const_int 0))) (set (match_operand:DI 0 "gr_register_operand" "") (if_then_else:DI (eq (match_dup 2) (const_int 0)) (neg:DI (match_dup 1)) (match_dup 1)))] "" { 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_register_operand" ""))) (set (match_dup 3) (unspec:DI [(match_dup 2)] UNSPEC_GETF_EXP)) (set (match_dup 4) (const_int 65598)) (set (match_operand:DI 0 "gr_register_operand" "") (minus:DI (match_dup 4) (match_dup 3)))] "" { operands[2] = gen_reg_rtx (XFmode); operands[3] = gen_reg_rtx (DImode); operands[4] = gen_reg_rtx (DImode); }) (define_insn "popcountdi2" [(set (match_operand:DI 0 "gr_register_operand" "=r") (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_register_operand" "f")] UNSPEC_GETF_EXP))] "" "getf.exp %0 = %1" [(set_attr "itanium_class" "frfr")]) (define_expand "divdi3" [(set (match_operand:DI 0 "register_operand" "") (div:DI (match_operand:DI 1 "general_operand" "") (match_operand:DI 2 "general_operand" "")))] "TARGET_INLINE_INT_DIV" { rtx op1_xf, op2_xf, op0_xf; op0_xf = gen_reg_rtx (XFmode); if (CONSTANT_P (operands[1])) operands[1] = force_reg (DImode, operands[1]); op1_xf = gen_reg_rtx (XFmode); expand_float (op1_xf, operands[1], 0); if (CONSTANT_P (operands[2])) operands[2] = force_reg (DImode, operands[2]); op2_xf = gen_reg_rtx (XFmode); expand_float (op2_xf, operands[2], 0); emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode), CONST1_RTX (DImode))); if (TARGET_INLINE_INT_DIV == INL_MIN_LAT) emit_insn (gen_divdi3_internal_lat (op0_xf, op1_xf, op2_xf)); else emit_insn (gen_divdi3_internal_thr (op0_xf, op1_xf, op2_xf)); emit_insn (gen_fix_truncxfdi2_alts (operands[0], op0_xf, const1_rtx)); DONE; }) (define_expand "moddi3" [(set (match_operand:DI 0 "register_operand" "") (mod:SI (match_operand:DI 1 "general_operand" "") (match_operand:DI 2 "general_operand" "")))] "TARGET_INLINE_INT_DIV" { rtx op2_neg, div; div = gen_reg_rtx (DImode); emit_insn (gen_divdi3 (div, operands[1], operands[2])); op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0); emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1])); DONE; }) (define_expand "udivdi3" [(set (match_operand:DI 0 "register_operand" "") (udiv:DI (match_operand:DI 1 "general_operand" "") (match_operand:DI 2 "general_operand" "")))] "TARGET_INLINE_INT_DIV" { rtx op1_xf, op2_xf, op0_xf; op0_xf = gen_reg_rtx (XFmode); if (CONSTANT_P (operands[1])) operands[1] = force_reg (DImode, operands[1]); op1_xf = gen_reg_rtx (XFmode); expand_float (op1_xf, operands[1], 1); if (CONSTANT_P (operands[2])) operands[2] = force_reg (DImode, operands[2]); op2_xf = gen_reg_rtx (XFmode); expand_float (op2_xf, operands[2], 1); emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode), CONST1_RTX (DImode))); if (TARGET_INLINE_INT_DIV == INL_MIN_LAT) emit_insn (gen_divdi3_internal_lat (op0_xf, op1_xf, op2_xf)); else emit_insn (gen_divdi3_internal_thr (op0_xf, op1_xf, op2_xf)); emit_insn (gen_fixuns_truncxfdi2_alts (operands[0], op0_xf, const1_rtx)); DONE; }) (define_expand "umoddi3" [(set (match_operand:DI 0 "register_operand" "") (umod:DI (match_operand:DI 1 "general_operand" "") (match_operand:DI 2 "general_operand" "")))] "TARGET_INLINE_INT_DIV" { rtx op2_neg, div; div = gen_reg_rtx (DImode); emit_insn (gen_udivdi3 (div, operands[1], operands[2])); op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0); emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1])); DONE; }) (define_insn_and_split "divdi3_internal_lat" [(set (match_operand:XF 0 "fr_register_operand" "=&f") (float:XF (div:SI (match_operand:XF 1 "fr_register_operand" "f") (match_operand:XF 2 "fr_register_operand" "f")))) (clobber (match_scratch:XF 3 "=&f")) (clobber (match_scratch:XF 4 "=&f")) (clobber (match_scratch:XF 5 "=&f")) (clobber (match_scratch:BI 6 "=c"))] "TARGET_INLINE_INT_DIV == INL_MIN_LAT" "#" "&& reload_completed" [(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2))) (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)] UNSPEC_FR_RECIP_APPROX)) (use (const_int 1))]) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 3) (minus:XF (match_dup 7) (mult:XF (match_dup 2) (match_dup 0)))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 5) (mult:XF (match_dup 3) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (plus:XF (mult:XF (match_dup 3) (match_dup 4)) (match_dup 4))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 0) (plus:XF (mult:XF (match_dup 3) (match_dup 0)) (match_dup 0))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 5) (match_dup 4)) (match_dup 4))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 0) (plus:XF (mult:XF (match_dup 5) (match_dup 0)) (match_dup 0))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (minus:XF (match_dup 1) (mult:XF (match_dup 2) (match_dup 3)))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 0) (plus:XF (mult:XF (match_dup 4) (match_dup 0)) (match_dup 3))) (use (const_int 1))])) ] "operands[7] = CONST1_RTX (XFmode);" [(set_attr "predicable" "no")]) (define_insn_and_split "divdi3_internal_thr" [(set (match_operand:XF 0 "fr_register_operand" "=&f") (float:XF (div:SI (match_operand:XF 1 "fr_register_operand" "f") (match_operand:XF 2 "fr_register_operand" "f")))) (clobber (match_scratch:XF 3 "=&f")) (clobber (match_scratch:XF 4 "=f")) (clobber (match_scratch:BI 5 "=c"))] "TARGET_INLINE_INT_DIV == INL_MAX_THR" "#" "&& reload_completed" [(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2))) (set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)] UNSPEC_FR_RECIP_APPROX)) (use (const_int 1))]) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (minus:XF (match_dup 6) (mult:XF (match_dup 2) (match_dup 0)))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 0) (plus:XF (mult:XF (match_dup 3) (match_dup 0)) (match_dup 0))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (mult:XF (match_dup 3) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 0) (plus:XF (mult:XF (match_dup 3) (match_dup 0)) (match_dup 0))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (mult:XF (match_dup 0) (match_dup 1))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 4) (minus:XF (match_dup 1) (mult:XF (match_dup 2) (match_dup 3)))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 0) (plus:XF (mult:XF (match_dup 4) (match_dup 0)) (match_dup 3))) (use (const_int 1))])) ] "operands[6] = CONST1_RTX (XFmode);" [(set_attr "predicable" "no")]) ;; :::::::::::::::::::: ;; :: ;; :: 128-bit Integer arithmetic ;; :: ;; :::::::::::::::::::: (define_insn "addti3" [(set (match_operand:TI 0 "gr_register_operand" "=&r") (plus:TI (match_operand:TI 1 "gr_register_operand" "%r") (match_operand:TI 2 "gr_reg_or_14bit_operand" "rI"))) (clobber (match_scratch:BI 3 "=&c"))] "" "#" [(set_attr "itanium_class" "unknown")]) (define_split [(set (match_operand:TI 0 "register_operand" "") (plus:TI (match_operand:TI 1 "register_operand" "") (match_operand:TI 2 "register_operand" ""))) (clobber (match_scratch:BI 3 ""))] "reload_completed" [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2))) (set (match_dup 3) (ltu:BI (match_dup 0) (match_dup 1))) (cond_exec (eq (match_dup 3) (const_int 0)) (set (match_dup 4) (plus:DI (match_dup 5) (match_dup 6)))) (cond_exec (ne (match_dup 3) (const_int 0)) (set (match_dup 4) (plus:DI (plus:DI (match_dup 5) (match_dup 6)) (const_int 1))))] { operands[4] = gen_highpart (DImode, operands[0]); operands[0] = gen_lowpart (DImode, operands[0]); operands[5] = gen_highpart (DImode, operands[1]); operands[1] = gen_lowpart (DImode, operands[1]); operands[6] = gen_highpart (DImode, operands[2]); operands[2] = gen_lowpart (DImode, operands[2]); }) (define_split [(set (match_operand:TI 0 "register_operand" "") (plus:TI (match_operand:TI 1 "register_operand" "") (match_operand:TI 2 "immediate_operand" ""))) (clobber (match_scratch:BI 3 ""))] "reload_completed" [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2))) (set (match_dup 3) (ltu:BI (match_dup 0) (match_dup 1))) (cond_exec (eq (match_dup 3) (const_int 0)) (set (match_dup 4) (plus:DI (match_dup 5) (match_dup 6)))) (cond_exec (ne (match_dup 3) (const_int 0)) (set (match_dup 4) (plus:DI (match_dup 5) (match_dup 7))))] { operands[4] = gen_highpart (DImode, operands[0]); operands[0] = gen_lowpart (DImode, operands[0]); operands[5] = gen_highpart (DImode, operands[1]); operands[1] = gen_lowpart (DImode, operands[1]); operands[6] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx; operands[7] = INTVAL (operands[2]) < 0 ? const0_rtx : const1_rtx; }) (define_insn "subti3" [(set (match_operand:TI 0 "gr_register_operand" "=&r") (minus:TI (match_operand:TI 1 "gr_reg_or_8bit_operand" "rK") (match_operand:TI 2 "gr_register_operand" "r"))) (clobber (match_scratch:BI 3 "=&c"))] "" "#" [(set_attr "itanium_class" "unknown")]) (define_split [(set (match_operand:TI 0 "register_operand" "") (minus:TI (match_operand:TI 1 "register_operand" "") (match_operand:TI 2 "register_operand" ""))) (clobber (match_scratch:BI 3 "=&c"))] "reload_completed" [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2))) (set (match_dup 3) (ltu:BI (match_dup 1) (match_dup 0))) (cond_exec (eq (match_dup 3) (const_int 0)) (set (match_dup 4) (minus:DI (match_dup 5) (match_dup 6)))) (cond_exec (ne (match_dup 3) (const_int 0)) (set (match_dup 4) (plus:DI (not:DI (match_dup 6)) (match_dup 5))))] { operands[4] = gen_highpart (DImode, operands[0]); operands[0] = gen_lowpart (DImode, operands[0]); operands[5] = gen_highpart (DImode, operands[1]); operands[1] = gen_lowpart (DImode, operands[1]); operands[6] = gen_highpart (DImode, operands[2]); operands[2] = gen_lowpart (DImode, operands[2]); }) (define_split [(set (match_operand:TI 0 "register_operand" "") (minus:TI (match_operand:TI 1 "immediate_operand" "") (match_operand:TI 2 "register_operand" ""))) (clobber (match_scratch:BI 3 "=&c"))] "reload_completed && satisfies_constraint_K (operands[1])" [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2))) (set (match_dup 3) (gtu:BI (match_dup 0) (match_dup 1))) (cond_exec (ne (match_dup 3) (const_int 0)) (set (match_dup 4) (minus:DI (match_dup 6) (match_dup 5)))) (cond_exec (eq (match_dup 3) (const_int 0)) (set (match_dup 4) (minus:DI (match_dup 7) (match_dup 5))))] { operands[4] = gen_highpart (DImode, operands[0]); operands[0] = gen_lowpart (DImode, operands[0]); operands[5] = gen_highpart (DImode, operands[2]); operands[2] = gen_lowpart (DImode, operands[2]); operands[6] = INTVAL (operands[1]) < 0 ? GEN_INT (-2) : constm1_rtx; operands[7] = INTVAL (operands[1]) < 0 ? constm1_rtx : const0_rtx; }) (define_expand "mulditi3" [(set (match_operand:TI 0 "fr_register_operand" "") (mult:TI (sign_extend:TI (match_operand:DI 1 "fr_register_operand" "")) (sign_extend:TI (match_operand:DI 2 "fr_register_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_register_operand" "%f")) (sign_extend:TI (match_operand:DI 2 "fr_register_operand" "f"))))] "" "#" "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_register_operand" "")) (zero_extend:TI (match_operand:DI 2 "fr_register_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_register_operand" "%f")) (zero_extend:TI (match_operand:DI 2 "fr_register_operand" "f"))))] "" "#" "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_register_operand" "%f") (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fadd.s %0 = %1, %F2" [(set_attr "itanium_class" "fmac")]) (define_insn "subsf3" [(set (match_operand:SF 0 "fr_register_operand" "=f") (minus:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG") (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fsub.s %0 = %F1, %F2" [(set_attr "itanium_class" "fmac")]) (define_insn "mulsf3" [(set (match_operand:SF 0 "fr_register_operand" "=f") (mult:SF (match_operand:SF 1 "fr_register_operand" "%f") (match_operand:SF 2 "fr_register_operand" "f")))] "" "fmpy.s %0 = %1, %2" [(set_attr "itanium_class" "fmac")]) (define_insn "abssf2" [(set (match_operand:SF 0 "fr_register_operand" "=f") (abs:SF (match_operand:SF 1 "fr_register_operand" "f")))] "" "fabs %0 = %1" [(set_attr "itanium_class" "fmisc")]) (define_insn "negsf2" [(set (match_operand:SF 0 "fr_register_operand" "=f") (neg:SF (match_operand:SF 1 "fr_register_operand" "f")))] "" "fneg %0 = %1" [(set_attr "itanium_class" "fmisc")]) (define_insn "*nabssf2" [(set (match_operand:SF 0 "fr_register_operand" "=f") (neg:SF (abs:SF (match_operand:SF 1 "fr_register_operand" "f"))))] "" "fnegabs %0 = %1" [(set_attr "itanium_class" "fmisc")]) (define_insn "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_register_operand" "f") (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fmin %0 = %1, %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_register_operand" "f") (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fmax %0 = %1, %F2" [(set_attr "itanium_class" "fmisc")]) (define_insn "*maddsf4" [(set (match_operand:SF 0 "fr_register_operand" "=f") (plus:SF (mult:SF (match_operand:SF 1 "fr_register_operand" "f") (match_operand:SF 2 "fr_register_operand" "f")) (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))] "" "fma.s %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*msubsf4" [(set (match_operand:SF 0 "fr_register_operand" "=f") (minus:SF (mult:SF (match_operand:SF 1 "fr_register_operand" "f") (match_operand:SF 2 "fr_register_operand" "f")) (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))] "" "fms.s %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmulsf3" [(set (match_operand:SF 0 "fr_register_operand" "=f") (neg:SF (mult:SF (match_operand:SF 1 "fr_register_operand" "f") (match_operand:SF 2 "fr_register_operand" "f"))))] "" "fnmpy.s %0 = %1, %2" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmaddsf4" [(set (match_operand:SF 0 "fr_register_operand" "=f") (minus:SF (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG") (mult:SF (match_operand:SF 1 "fr_register_operand" "f") (match_operand:SF 2 "fr_register_operand" "f"))))] "" "fnma.s %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmaddsf4_alts" [(set (match_operand:SF 0 "fr_register_operand" "=f") (minus:SF (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG") (mult:SF (match_operand:SF 1 "fr_register_operand" "f") (match_operand:SF 2 "fr_register_operand" "f")))) (use (match_operand:SI 4 "const_int_operand" ""))] "" "fnma.s.s%4 %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_expand "divsf3" [(set (match_operand:SF 0 "fr_register_operand" "") (div:SF (match_operand:SF 1 "fr_register_operand" "") (match_operand:SF 2 "fr_register_operand" "")))] "TARGET_INLINE_FLOAT_DIV" { rtx insn; if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT) insn = gen_divsf3_internal_lat (operands[0], operands[1], operands[2]); else insn = gen_divsf3_internal_thr (operands[0], operands[1], operands[2]); emit_insn (insn); DONE; }) (define_insn_and_split "divsf3_internal_lat" [(set (match_operand:SF 0 "fr_register_operand" "=&f") (div:SF (match_operand:SF 1 "fr_register_operand" "f") (match_operand:SF 2 "fr_register_operand" "f"))) (clobber (match_scratch:XF 3 "=&f")) (clobber (match_scratch:XF 4 "=f")) (clobber (match_scratch:BI 5 "=c"))] "TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT" "#" "&& reload_completed" [(parallel [(set (match_dup 6) (div:XF (const_int 1) (match_dup 8))) (set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)] UNSPEC_FR_RECIP_APPROX)) (use (const_int 0))]) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (mult:XF (match_dup 7) (match_dup 6))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 4) (minus:XF (match_dup 10) (mult:XF (match_dup 8) (match_dup 6)))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 4) (match_dup 3)) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 4) (mult:XF (match_dup 4) (match_dup 4))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 4) (match_dup 3)) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 4) (mult:XF (match_dup 4) (match_dup 4))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 9) (float_truncate:DF (plus:XF (mult:XF (match_dup 4) (match_dup 3)) (match_dup 3)))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (set (match_dup 0) (float_truncate:SF (match_dup 6)))) ] { operands[6] = gen_rtx_REG (XFmode, REGNO (operands[0])); operands[7] = gen_rtx_REG (XFmode, REGNO (operands[1])); operands[8] = gen_rtx_REG (XFmode, REGNO (operands[2])); operands[9] = gen_rtx_REG (DFmode, REGNO (operands[0])); operands[10] = CONST1_RTX (XFmode); } [(set_attr "predicable" "no")]) ;; Inline square root. (define_insn "*sqrt_approx" [(set (match_operand:XF 0 "fr_register_operand" "=f") (div:XF (const_int 1) (sqrt:XF (match_operand:XF 2 "fr_register_operand" "f")))) (set (match_operand:BI 1 "register_operand" "=c") (unspec:BI [(match_dup 2)] UNSPEC_FR_SQRT_RECIP_APPROX)) (use (match_operand:SI 3 "const_int_operand" "")) ] "" "frsqrta.s%3 %0, %1 = %2" [(set_attr "itanium_class" "fmisc") (set_attr "predicable" "no")]) (define_insn "setf_exp_xf" [(set (match_operand:XF 0 "fr_register_operand" "=f") (unspec:XF [(match_operand:DI 1 "register_operand" "r")] UNSPEC_SETF_EXP))] "" "setf.exp %0 = %1" [(set_attr "itanium_class" "frfr")]) (define_expand "sqrtsf2" [(set (match_operand:SF 0 "fr_register_operand" "=&f") (sqrt:SF (match_operand:SF 1 "fr_register_operand" "f")))] "TARGET_INLINE_SQRT" { rtx insn; #if 0 if (TARGET_INLINE_SQRT == INL_MIN_LAT) insn = gen_sqrtsf2_internal_lat (operands[0], operands[1]); else #else gcc_assert (TARGET_INLINE_SQRT != INL_MIN_LAT); #endif insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]); emit_insn (insn); DONE; }) ;; Latency-optimized square root. ;; FIXME: Implement. ;; Throughput-optimized square root. (define_insn_and_split "sqrtsf2_internal_thr" [(set (match_operand:SF 0 "fr_register_operand" "=&f") (sqrt:SF (match_operand:SF 1 "fr_register_operand" "f"))) ;; Register r2 in optimization guide. (clobber (match_scratch:DI 2 "=r")) ;; Register f8 in optimization guide (clobber (match_scratch:XF 3 "=&f")) ;; Register f9 in optimization guide (clobber (match_scratch:XF 4 "=&f")) ;; Register f10 in optimization guide (clobber (match_scratch:XF 5 "=&f")) ;; Register p6 in optimization guide. (clobber (match_scratch:BI 6 "=c"))] "TARGET_INLINE_SQRT == INL_MAX_THR" "#" "&& reload_completed" [ ;; exponent of +1/2 in r2 (set (match_dup 2) (const_int 65534)) ;; +1/2 in f8 (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_SETF_EXP)) ;; Step 1 ;; y0 = 1/sqrt(a) in f7 (parallel [(set (match_dup 7) (div:XF (const_int 1) (sqrt:XF (match_dup 8)))) (set (match_dup 6) (unspec:BI [(match_dup 8)] UNSPEC_FR_SQRT_RECIP_APPROX)) (use (const_int 0))]) ;; Step 2 ;; H0 = 1/2 * y0 in f9 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (plus:XF (mult:XF (match_dup 3) (match_dup 7)) (match_dup 9))) (use (const_int 1))])) ;; Step 3 ;; S0 = a * y0 in f7 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 7) (plus:XF (mult:XF (match_dup 8) (match_dup 7)) (match_dup 9))) (use (const_int 1))])) ;; Step 4 ;; d = 1/2 - S0 * H0 in f10 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 5) (minus:XF (match_dup 3) (mult:XF (match_dup 7) (match_dup 4)))) (use (const_int 1))])) ;; Step 5 ;; d' = d + 1/2 * d in f8 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 3) (match_dup 5)) (match_dup 5))) (use (const_int 1))])) ;; Step 6 ;; e = d + d * d' in f8 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 5) (match_dup 3)) (match_dup 5))) (use (const_int 1))])) ;; Step 7 ;; S1 = S0 + e * S0 in f7 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 0) (float_truncate:SF (plus:XF (mult:XF (match_dup 3) (match_dup 7)) (match_dup 7)))) (use (const_int 1))])) ;; Step 8 ;; H1 = H0 + e * H0 in f8 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 3) (match_dup 4)) (match_dup 4))) (use (const_int 1))])) ;; Step 9 ;; d1 = a - S1 * S1 in f9 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (minus:XF (match_dup 8) (mult:XF (match_dup 7) (match_dup 7)))) (use (const_int 1))])) ;; Step 10 ;; S = S1 + d1 * H1 in f7 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 0) (float_truncate:SF (plus:XF (mult:XF (match_dup 4) (match_dup 3)) (match_dup 7)))) (use (const_int 0))]))] { /* Generate 82-bit versions of the input and output operands. */ operands[7] = gen_rtx_REG (XFmode, REGNO (operands[0])); operands[8] = gen_rtx_REG (XFmode, REGNO (operands[1])); /* Generate required floating-point constants. */ operands[9] = CONST0_RTX (XFmode); } [(set_attr "predicable" "no")]) ;; :::::::::::::::::::: ;; :: ;; :: 64-bit floating point arithmetic ;; :: ;; :::::::::::::::::::: (define_insn "adddf3" [(set (match_operand:DF 0 "fr_register_operand" "=f") (plus:DF (match_operand:DF 1 "fr_register_operand" "%f") (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fadd.d %0 = %1, %F2" [(set_attr "itanium_class" "fmac")]) (define_insn "*adddf3_trunc" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (plus:DF (match_operand:DF 1 "fr_register_operand" "%f") (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))))] "" "fadd.s %0 = %1, %F2" [(set_attr "itanium_class" "fmac")]) (define_insn "subdf3" [(set (match_operand:DF 0 "fr_register_operand" "=f") (minus:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG") (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fsub.d %0 = %F1, %F2" [(set_attr "itanium_class" "fmac")]) (define_insn "*subdf3_trunc" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (minus:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG") (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))))] "" "fsub.s %0 = %F1, %F2" [(set_attr "itanium_class" "fmac")]) (define_insn "muldf3" [(set (match_operand:DF 0 "fr_register_operand" "=f") (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f")))] "" "fmpy.d %0 = %1, %2" [(set_attr "itanium_class" "fmac")]) (define_insn "*muldf3_trunc" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f"))))] "" "fmpy.s %0 = %1, %2" [(set_attr "itanium_class" "fmac")]) (define_insn "absdf2" [(set (match_operand:DF 0 "fr_register_operand" "=f") (abs:DF (match_operand:DF 1 "fr_register_operand" "f")))] "" "fabs %0 = %1" [(set_attr "itanium_class" "fmisc")]) (define_insn "negdf2" [(set (match_operand:DF 0 "fr_register_operand" "=f") (neg:DF (match_operand:DF 1 "fr_register_operand" "f")))] "" "fneg %0 = %1" [(set_attr "itanium_class" "fmisc")]) (define_insn "*nabsdf2" [(set (match_operand:DF 0 "fr_register_operand" "=f") (neg:DF (abs:DF (match_operand:DF 1 "fr_register_operand" "f"))))] "" "fnegabs %0 = %1" [(set_attr "itanium_class" "fmisc")]) (define_insn "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_register_operand" "f") (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fmin %0 = %1, %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_register_operand" "f") (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fmax %0 = %1, %F2" [(set_attr "itanium_class" "fmisc")]) (define_insn "*madddf4" [(set (match_operand:DF 0 "fr_register_operand" "=f") (plus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f")) (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))] "" "fma.d %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*madddf4_trunc" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (plus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f")) (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))] "" "fma.s %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*msubdf4" [(set (match_operand:DF 0 "fr_register_operand" "=f") (minus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f")) (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))] "" "fms.d %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*msubdf4_trunc" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (minus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f")) (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))] "" "fms.s %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmuldf3" [(set (match_operand:DF 0 "fr_register_operand" "=f") (neg:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f"))))] "" "fnmpy.d %0 = %1, %2" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmuldf3_trunc" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (neg:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f")))))] "" "fnmpy.s %0 = %1, %2" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmadddf4" [(set (match_operand:DF 0 "fr_register_operand" "=f") (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG") (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f"))))] "" "fnma.d %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmadddf4_alts" [(set (match_operand:DF 0 "fr_register_operand" "=f") (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG") (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f")))) (use (match_operand:SI 4 "const_int_operand" ""))] "" "fnma.d.s%4 %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmadddf4_truncsf" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG") (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f")))))] "" "fnma.s %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmadddf4_truncsf_alts" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG") (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f"))))) (use (match_operand:SI 4 "const_int_operand" ""))] "" "fnma.s.s%4 %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_expand "divdf3" [(set (match_operand:DF 0 "fr_register_operand" "") (div:DF (match_operand:DF 1 "fr_register_operand" "") (match_operand:DF 2 "fr_register_operand" "")))] "TARGET_INLINE_FLOAT_DIV" { rtx insn; if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT) insn = gen_divdf3_internal_lat (operands[0], operands[1], operands[2]); else insn = gen_divdf3_internal_thr (operands[0], operands[1], operands[2]); emit_insn (insn); DONE; }) (define_insn_and_split "divdf3_internal_lat" [(set (match_operand:DF 0 "fr_register_operand" "=&f") (div:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f"))) (clobber (match_scratch:XF 3 "=&f")) (clobber (match_scratch:XF 4 "=&f")) (clobber (match_scratch:XF 5 "=&f")) (clobber (match_scratch:BI 6 "=c"))] "TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT" "#" "&& reload_completed" [(parallel [(set (match_dup 7) (div:XF (const_int 1) (match_dup 9))) (set (match_dup 6) (unspec:BI [(match_dup 8) (match_dup 9)] UNSPEC_FR_RECIP_APPROX)) (use (const_int 0))]) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 3) (mult:XF (match_dup 8) (match_dup 7))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (minus:XF (match_dup 12) (mult:XF (match_dup 9) (match_dup 7)))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 4) (match_dup 3)) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 5) (mult:XF (match_dup 4) (match_dup 4))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 7) (plus:XF (mult:XF (match_dup 4) (match_dup 7)) (match_dup 7))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 5) (match_dup 3)) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (mult:XF (match_dup 5) (match_dup 5))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 7) (plus:XF (mult:XF (match_dup 5) (match_dup 7)) (match_dup 7))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 10) (float_truncate:DF (plus:XF (mult:XF (match_dup 4) (match_dup 3)) (match_dup 3)))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 7) (plus:XF (mult:XF (match_dup 4) (match_dup 7)) (match_dup 7))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 11) (float_truncate:DF (minus:XF (match_dup 8) (mult:XF (match_dup 9) (match_dup 3))))) (use (const_int 1))])) (cond_exec (ne (match_dup 6) (const_int 0)) (set (match_dup 0) (float_truncate:DF (plus:XF (mult:XF (match_dup 5) (match_dup 7)) (match_dup 3))))) ] { operands[7] = gen_rtx_REG (XFmode, REGNO (operands[0])); operands[8] = gen_rtx_REG (XFmode, REGNO (operands[1])); operands[9] = gen_rtx_REG (XFmode, REGNO (operands[2])); operands[10] = gen_rtx_REG (DFmode, REGNO (operands[3])); operands[11] = gen_rtx_REG (DFmode, REGNO (operands[5])); operands[12] = CONST1_RTX (XFmode); } [(set_attr "predicable" "no")]) ;; Inline square root. (define_expand "sqrtdf2" [(set (match_operand:DF 0 "fr_register_operand" "=&f") (sqrt:DF (match_operand:DF 1 "fr_register_operand" "f")))] "TARGET_INLINE_SQRT" { rtx insn; #if 0 if (TARGET_INLINE_SQRT == INL_MIN_LAT) insn = gen_sqrtdf2_internal_lat (operands[0], operands[1]); else #else gcc_assert (TARGET_INLINE_SQRT != INL_MIN_LAT); #endif insn = gen_sqrtdf2_internal_thr (operands[0], operands[1]); emit_insn (insn); DONE; }) ;; Latency-optimized square root. ;; FIXME: Implement. ;; Throughput-optimized square root. (define_insn_and_split "sqrtdf2_internal_thr" [(set (match_operand:DF 0 "fr_register_operand" "=&f") (sqrt:DF (match_operand:DF 1 "fr_register_operand" "f"))) ;; Register r2 in optimization guide. (clobber (match_scratch:DI 2 "=r")) ;; Register f8 in optimization guide (clobber (match_scratch:XF 3 "=&f")) ;; Register f9 in optimization guide (clobber (match_scratch:XF 4 "=&f")) ;; Register f10 in optimization guide (clobber (match_scratch:XF 5 "=&f")) ;; Register p6 in optimization guide. (clobber (match_scratch:BI 6 "=c"))] "TARGET_INLINE_SQRT == INL_MAX_THR" "#" "&& reload_completed" [ ;; exponent of +1/2 in r2 (set (match_dup 2) (const_int 65534)) ;; +1/2 in f10 (set (match_dup 5) (unspec:XF [(match_dup 2)] UNSPEC_SETF_EXP)) ;; Step 1 ;; y0 = 1/sqrt(a) in f7 (parallel [(set (match_dup 7) (div:XF (const_int 1) (sqrt:XF (match_dup 8)))) (set (match_dup 6) (unspec:BI [(match_dup 8)] UNSPEC_FR_SQRT_RECIP_APPROX)) (use (const_int 0))]) ;; Step 2 ;; H0 = 1/2 * y0 in f8 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 5) (match_dup 7)) (match_dup 9))) (use (const_int 1))])) ;; Step 3 ;; G0 = a * y0 in f7 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 7) (plus:XF (mult:XF (match_dup 8) (match_dup 7)) (match_dup 9))) (use (const_int 1))])) ;; Step 4 ;; r0 = 1/2 - G0 * H0 in f9 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (minus:XF (match_dup 5) (mult:XF (match_dup 7) (match_dup 3)))) (use (const_int 1))])) ;; Step 5 ;; H1 = H0 + r0 * H0 in f8 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 4) (match_dup 3)) (match_dup 3))) (use (const_int 1))])) ;; Step 6 ;; G1 = G0 + r0 * G0 in f7 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 7) (plus:XF (mult:XF (match_dup 4) (match_dup 7)) (match_dup 7))) (use (const_int 1))])) ;; Step 7 ;; r1 = 1/2 - G1 * H1 in f9 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (minus:XF (match_dup 5) (mult:XF (match_dup 7) (match_dup 3)))) (use (const_int 1))])) ;; Step 8 ;; H2 = H1 + r1 * H1 in f8 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 4) (match_dup 3)) (match_dup 3))) (use (const_int 1))])) ;; Step 9 ;; G2 = G1 + r1 * G1 in f7 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 7) (plus:XF (mult:XF (match_dup 4) (match_dup 7)) (match_dup 7))) (use (const_int 1))])) ;; Step 10 ;; d2 = a - G2 * G2 in f9 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (minus:XF (match_dup 8) (mult:XF (match_dup 7) (match_dup 7)))) (use (const_int 1))])) ;; Step 11 ;; G3 = G2 + d2 * H2 in f7 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 7) (plus:XF (mult:XF (match_dup 4) (match_dup 3)) (match_dup 7))) (use (const_int 1))])) ;; Step 12 ;; d3 = a - G3 * G3 in f9 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (minus:XF (match_dup 8) (mult:XF (match_dup 7) (match_dup 7)))) (use (const_int 1))])) ;; Step 13 ;; S = G3 + d3 * H2 in f7 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 0) (float_truncate:DF (plus:XF (mult:XF (match_dup 4) (match_dup 3)) (match_dup 7)))) (use (const_int 0))]))] { /* Generate 82-bit versions of the input and output operands. */ operands[7] = gen_rtx_REG (XFmode, REGNO (operands[0])); operands[8] = gen_rtx_REG (XFmode, REGNO (operands[1])); /* Generate required floating-point constants. */ operands[9] = CONST0_RTX (XFmode); } [(set_attr "predicable" "no")]) ;; :::::::::::::::::::: ;; :: ;; :: 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_fp01_operand" "fG")))] "" "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_fp01_operand" "fG"))))] "" "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_fp01_operand" "fG"))))] "" "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_fp01_operand" "fG")))] "" "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_fp01_operand" "fG"))))] "" "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_fp01_operand" "fG"))))] "" "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 "*mulxf3_alts" [(set (match_operand:XF 0 "fr_register_operand" "=f") (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))) (use (match_operand:SI 3 "const_int_operand" ""))] "" "fmpy.s%3 %0 = %F1, %F2" [(set_attr "itanium_class" "fmac")]) (define_insn "*mulxf3_truncsf_alts" [(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")))) (use (match_operand:SI 3 "const_int_operand" ""))] "" "fmpy.s.s%3 %0 = %F1, %F2" [(set_attr "itanium_class" "fmac")]) (define_insn "*mulxf3_truncdf_alts" [(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")))) (use (match_operand:SI 3 "const_int_operand" ""))] "" "fmpy.d.s%3 %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 "*maddxf4" [(set (match_operand:XF 0 "fr_register_operand" "=f") (plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")) (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))] "" "fma %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*maddxf4_truncsf" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")) (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))] "" "fma.s %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*maddxf4_truncdf" [(set (match_operand:DF 0 "fr_register_operand" "=f") (float_truncate:DF (plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")) (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))] "" "fma.d %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*maddxf4_alts" [(set (match_operand:XF 0 "fr_register_operand" "=f") (plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")) (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))) (use (match_operand:SI 4 "const_int_operand" ""))] "" "fma.s%4 %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*maddxf4_alts_truncsf" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")) (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))) (use (match_operand:SI 4 "const_int_operand" ""))] "" "fma.s.s%4 %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*maddxf4_alts_truncdf" [(set (match_operand:DF 0 "fr_register_operand" "=f") (float_truncate:DF (plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")) (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))) (use (match_operand:SI 4 "const_int_operand" ""))] "" "fma.d.s%4 %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*msubxf4" [(set (match_operand:XF 0 "fr_register_operand" "=f") (minus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")) (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))] "" "fms %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*msubxf4_truncsf" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (minus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")) (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))] "" "fms.s %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*msubxf4_truncdf" [(set (match_operand:DF 0 "fr_register_operand" "=f") (float_truncate:DF (minus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")) (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))] "" "fms.d %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (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 "*nmaddxf4" [(set (match_operand:XF 0 "fr_register_operand" "=f") (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG") (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG") )))] "" "fnma %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmaddxf4_truncsf" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG") (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG") ))))] "" "fnma.s %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmaddxf4_truncdf" [(set (match_operand:DF 0 "fr_register_operand" "=f") (float_truncate:DF (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG") (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG") ))))] "" "fnma.d %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmaddxf4_alts" [(set (match_operand:XF 0 "fr_register_operand" "=f") (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG") (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG") ))) (use (match_operand:SI 4 "const_int_operand" ""))] "" "fnma.s%4 %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmaddxf4_truncsf_alts" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG") (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG") )))) (use (match_operand:SI 4 "const_int_operand" ""))] "" "fnma.s.s%4 %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmaddxf4_truncdf_alts" [(set (match_operand:DF 0 "fr_register_operand" "=f") (float_truncate:DF (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG") (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG") )))) (use (match_operand:SI 4 "const_int_operand" ""))] "" "fnma.d.s%4 %0 = %F1, %F2, %F3" [(set_attr "itanium_class" "fmac")]) (define_expand "divxf3" [(set (match_operand:XF 0 "fr_register_operand" "") (div:XF (match_operand:XF 1 "fr_register_operand" "") (match_operand:XF 2 "fr_register_operand" "")))] "TARGET_INLINE_FLOAT_DIV" { rtx insn; if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT) insn = gen_divxf3_internal_lat (operands[0], operands[1], operands[2]); else insn = gen_divxf3_internal_thr (operands[0], operands[1], operands[2]); emit_insn (insn); DONE; }) (define_insn_and_split "divxf3_internal_lat" [(set (match_operand:XF 0 "fr_register_operand" "=&f") (div:XF (match_operand:XF 1 "fr_register_operand" "f") (match_operand:XF 2 "fr_register_operand" "f"))) (clobber (match_scratch:XF 3 "=&f")) (clobber (match_scratch:XF 4 "=&f")) (clobber (match_scratch:XF 5 "=&f")) (clobber (match_scratch:XF 6 "=&f")) (clobber (match_scratch:BI 7 "=c"))] "TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT" "#" "&& reload_completed" [(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2))) (set (match_dup 7) (unspec:BI [(match_dup 1) (match_dup 2)] UNSPEC_FR_RECIP_APPROX)) (use (const_int 0))]) (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 3) (minus:XF (match_dup 8) (mult:XF (match_dup 2) (match_dup 0)))) (use (const_int 1))])) (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0))) (use (const_int 1))])) (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 5) (mult:XF (match_dup 3) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 6) (plus:XF (mult:XF (match_dup 3) (match_dup 3)) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 5) (match_dup 5)) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 5) (plus:XF (mult:XF (match_dup 6) (match_dup 0)) (match_dup 0))) (use (const_int 1))])) (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 0) (plus:XF (mult:XF (match_dup 5) (match_dup 3)) (match_dup 0))) (use (const_int 1))])) (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 4) (minus:XF (match_dup 1) (mult:XF (match_dup 2) (match_dup 4)))) (use (const_int 1))])) (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 3) (match_dup 0)) (match_dup 4))) (use (const_int 1))])) (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 5) (minus:XF (match_dup 8) (mult:XF (match_dup 2) (match_dup 0)))) (use (const_int 1))])) (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 0) (plus:XF (mult:XF (match_dup 4) (match_dup 0)) (match_dup 0))) (use (const_int 1))])) (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 4) (minus:XF (match_dup 1) (mult:XF (match_dup 2) (match_dup 3)))) (use (const_int 1))])) (cond_exec (ne (match_dup 7) (const_int 0)) (set (match_dup 0) (plus:XF (mult:XF (match_dup 4) (match_dup 0)) (match_dup 3)))) ] "operands[8] = CONST1_RTX (XFmode);" [(set_attr "predicable" "no")]) (define_insn_and_split "divxf3_internal_thr" [(set (match_operand:XF 0 "fr_register_operand" "=&f") (div:XF (match_operand:XF 1 "fr_register_operand" "f") (match_operand:XF 2 "fr_register_operand" "f"))) (clobber (match_scratch:XF 3 "=&f")) (clobber (match_scratch:XF 4 "=&f")) (clobber (match_scratch:BI 5 "=c"))] "TARGET_INLINE_FLOAT_DIV == INL_MAX_THR" "#" "&& reload_completed" [(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2))) (set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)] UNSPEC_FR_RECIP_APPROX)) (use (const_int 0))]) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (minus:XF (match_dup 6) (mult:XF (match_dup 2) (match_dup 0)))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 4) (plus:XF (mult:XF (match_dup 3) (match_dup 0)) (match_dup 0))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (mult:XF (match_dup 3) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 3) (match_dup 4)) (match_dup 4))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 0) (minus:XF (match_dup 6) (mult:XF (match_dup 2) (match_dup 3)))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 0) (plus:XF (mult:XF (match_dup 0) (match_dup 3)) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (minus:XF (match_dup 1) (mult:XF (match_dup 2) (match_dup 4)))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 3) (match_dup 0)) (match_dup 4))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 4) (minus:XF (match_dup 6) (mult:XF (match_dup 2) (match_dup 0)))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 0) (plus:XF (mult:XF (match_dup 4) (match_dup 0)) (match_dup 0))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 4) (minus:XF (match_dup 1) (mult:XF (match_dup 2) (match_dup 3)))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (set (match_dup 0) (plus:XF (mult:XF (match_dup 4) (match_dup 0)) (match_dup 3)))) ] "operands[6] = CONST1_RTX (XFmode);" [(set_attr "predicable" "no")]) ;; Inline square root. (define_expand "sqrtxf2" [(set (match_operand:XF 0 "fr_register_operand" "=&f") (sqrt:XF (match_operand:XF 1 "fr_register_operand" "f")))] "TARGET_INLINE_SQRT" { rtx insn; #if 0 if (TARGET_INLINE_SQRT == INL_MIN_LAT) insn = gen_sqrtxf2_internal_lat (operands[0], operands[1]); else #else gcc_assert (TARGET_INLINE_SQRT != INL_MIN_LAT); #endif insn = gen_sqrtxf2_internal_thr (operands[0], operands[1]); emit_insn (insn); DONE; }) ;; Latency-optimized square root. ;; FIXME: Implement. ;; Throughput-optimized square root. (define_insn_and_split "sqrtxf2_internal_thr" [(set (match_operand:XF 0 "fr_register_operand" "=&f") (sqrt:XF (match_operand:XF 1 "fr_register_operand" "f"))) ;; Register r2 in optimization guide. (clobber (match_scratch:DI 2 "=r")) ;; Register f8 in optimization guide (clobber (match_scratch:XF 3 "=&f")) ;; Register f9 in optimization guide (clobber (match_scratch:XF 4 "=&f")) ;; Register f10 in optimization guide (clobber (match_scratch:XF 5 "=&f")) ;; Register f11 in optimization guide (clobber (match_scratch:XF 6 "=&f")) ;; Register p6 in optimization guide. (clobber (match_scratch:BI 7 "=c"))] "TARGET_INLINE_SQRT == INL_MAX_THR" "#" "&& reload_completed" [ ;; exponent of +1/2 in r2 (set (match_dup 2) (const_int 65534)) ;; +1/2 in f8. The Intel manual mistakenly specifies f10. (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_SETF_EXP)) ;; Step 1 ;; y0 = 1/sqrt(a) in f7 (parallel [(set (match_dup 8) (div:XF (const_int 1) (sqrt:XF (match_dup 9)))) (set (match_dup 7) (unspec:BI [(match_dup 9)] UNSPEC_FR_SQRT_RECIP_APPROX)) (use (const_int 0))]) ;; Step 2 ;; H0 = 1/2 * y0 in f9 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 4) (plus:XF (mult:XF (match_dup 3) (match_dup 8)) (match_dup 10))) (use (const_int 1))])) ;; Step 3 ;; S0 = a * y0 in f7 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 8) (plus:XF (mult:XF (match_dup 9) (match_dup 8)) (match_dup 10))) (use (const_int 1))])) ;; Step 4 ;; d0 = 1/2 - S0 * H0 in f10 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 5) (minus:XF (match_dup 3) (mult:XF (match_dup 8) (match_dup 4)))) (use (const_int 1))])) ;; Step 5 ;; H1 = H0 + d0 * H0 in f9 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 4) (plus:XF (mult:XF (match_dup 5) (match_dup 4)) (match_dup 4))) (use (const_int 1))])) ;; Step 6 ;; S1 = S0 + d0 * S0 in f7 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 8) (plus:XF (mult:XF (match_dup 5) (match_dup 8)) (match_dup 8))) (use (const_int 1))])) ;; Step 7 ;; d1 = 1/2 - S1 * H1 in f10 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 5) (minus:XF (match_dup 3) (mult:XF (match_dup 8) (match_dup 4)))) (use (const_int 1))])) ;; Step 8 ;; H2 = H1 + d1 * H1 in f9 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 4) (plus:XF (mult:XF (match_dup 5) (match_dup 4)) (match_dup 4))) (use (const_int 1))])) ;; Step 9 ;; S2 = S1 + d1 * S1 in f7 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 8) (plus:XF (mult:XF (match_dup 5) (match_dup 8)) (match_dup 8))) (use (const_int 1))])) ;; Step 10 ;; d2 = 1/2 - S2 * H2 in f10 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 5) (minus:XF (match_dup 3) (mult:XF (match_dup 8) (match_dup 4)))) (use (const_int 1))])) ;; Step 11 ;; e2 = a - S2 * S2 in f8 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 3) (minus:XF (match_dup 9) (mult:XF (match_dup 8) (match_dup 8)))) (use (const_int 1))])) ;; Step 12 ;; S3 = S2 + e2 * H2 in f7 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 8) (plus:XF (mult:XF (match_dup 3) (match_dup 4)) (match_dup 8))) (use (const_int 1))])) ;; Step 13 ;; H3 = H2 + d2 * H2 in f9 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 4) (plus:XF (mult:XF (match_dup 5) (match_dup 4)) (match_dup 4))) (use (const_int 1))])) ;; Step 14 ;; e3 = a - S3 * S3 in f8 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 3) (minus:XF (match_dup 9) (mult:XF (match_dup 8) (match_dup 8)))) (use (const_int 1))])) ;; Step 15 ;; S = S3 + e3 * H3 in f7 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 0) (plus:XF (mult:XF (match_dup 3) (match_dup 4)) (match_dup 8))) (use (const_int 0))]))] { /* Generate 82-bit versions of the input and output operands. */ operands[8] = gen_rtx_REG (XFmode, REGNO (operands[0])); operands[9] = gen_rtx_REG (XFmode, REGNO (operands[1])); /* Generate required floating-point constants. */ operands[10] = CONST0_RTX (XFmode); } [(set_attr "predicable" "no")]) ;; ??? frcpa works like cmp.foo.unc. (define_insn "*recip_approx" [(set (match_operand:XF 0 "fr_register_operand" "=f") (div:XF (const_int 1) (match_operand:XF 3 "fr_register_operand" "f"))) (set (match_operand:BI 1 "register_operand" "=c") (unspec:BI [(match_operand:XF 2 "fr_register_operand" "f") (match_dup 3)] UNSPEC_FR_RECIP_APPROX)) (use (match_operand:SI 4 "const_int_operand" ""))] "" "frcpa.s%4 %0, %1 = %2, %3" [(set_attr "itanium_class" "fmisc") (set_attr "predicable" "no")]) ;; :::::::::::::::::::: ;; :: ;; :: 32-bit Integer Shifts and Rotates ;; :: ;; :::::::::::::::::::: (define_expand "ashlsi3" [(set (match_operand:SI 0 "gr_register_operand" "") (ashift:SI (match_operand:SI 1 "gr_register_operand" "") (match_operand:SI 2 "gr_reg_or_5bit_operand" "")))] "" { if (GET_CODE (operands[2]) != CONST_INT) { /* Why oh why didn't Intel arrange for SHIFT_COUNT_TRUNCATED? Now we've got to get rid of stray bits outside the SImode register. */ rtx subshift = gen_reg_rtx (DImode); emit_insn (gen_zero_extendsidi2 (subshift, operands[2])); operands[2] = subshift; } }) (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 "cmpbi" [(set (cc0) (compare (match_operand:BI 0 "register_operand" "") (match_operand:BI 1 "const_int_operand" "")))] "" { ia64_compare_op0 = operands[0]; ia64_compare_op1 = operands[1]; DONE; }) (define_expand "cmpsi" [(set (cc0) (compare (match_operand:SI 0 "gr_register_operand" "") (match_operand:SI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))] "" { ia64_compare_op0 = operands[0]; ia64_compare_op1 = operands[1]; DONE; }) (define_expand "cmpdi" [(set (cc0) (compare (match_operand:DI 0 "gr_register_operand" "") (match_operand:DI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))] "" { ia64_compare_op0 = operands[0]; ia64_compare_op1 = operands[1]; DONE; }) (define_expand "cmpsf" [(set (cc0) (compare (match_operand:SF 0 "fr_reg_or_fp01_operand" "") (match_operand:SF 1 "fr_reg_or_fp01_operand" "")))] "" { ia64_compare_op0 = operands[0]; ia64_compare_op1 = operands[1]; DONE; }) (define_expand "cmpdf" [(set (cc0) (compare (match_operand:DF 0 "fr_reg_or_fp01_operand" "") (match_operand:DF 1 "fr_reg_or_fp01_operand" "")))] "" { ia64_compare_op0 = operands[0]; ia64_compare_op1 = operands[1]; DONE; }) (define_expand "cmpxf" [(set (cc0) (compare (match_operand:XF 0 "xfreg_or_fp01_operand" "") (match_operand:XF 1 "xfreg_or_fp01_operand" "")))] "" { ia64_compare_op0 = operands[0]; ia64_compare_op1 = operands[1]; DONE; }) (define_expand "cmptf" [(set (cc0) (compare (match_operand:TF 0 "gr_register_operand" "") (match_operand:TF 1 "gr_register_operand" "")))] "TARGET_HPUX" { ia64_compare_op0 = operands[0]; ia64_compare_op1 = operands[1]; DONE; }) (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_expand "beq" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (EQ, VOIDmode);") (define_expand "bne" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (NE, VOIDmode);") (define_expand "blt" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (LT, VOIDmode);") (define_expand "ble" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (LE, VOIDmode);") (define_expand "bgt" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (GT, VOIDmode);") (define_expand "bge" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (GE, VOIDmode);") (define_expand "bltu" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (LTU, VOIDmode);") (define_expand "bleu" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (LEU, VOIDmode);") (define_expand "bgtu" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (GTU, VOIDmode);") (define_expand "bgeu" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (GEU, VOIDmode);") (define_expand "bunordered" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (UNORDERED, VOIDmode);") (define_expand "bordered" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (ORDERED, VOIDmode);") (define_insn "*br_true" [(set (pc) (if_then_else (match_operator 0 "predicate_operator" [(match_operand:BI 1 "register_operand" "c") (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] "" "(%J0) br.cond%+ %l2" [(set_attr "itanium_class" "br") (set_attr "predicable" "no")]) (define_insn "*br_false" [(set (pc) (if_then_else (match_operator 0 "predicate_operator" [(match_operand:BI 1 "register_operand" "c") (const_int 0)]) (pc) (label_ref (match_operand 2 "" ""))))] "" "(%j0) br.cond%+ %l2" [(set_attr "itanium_class" "br") (set_attr "predicable" "no")]) ;; :::::::::::::::::::: ;; :: ;; :: Counted loop operations ;; :: ;; :::::::::::::::::::: (define_expand "doloop_end" [(use (match_operand 0 "" "")) ; loop pseudo (use (match_operand 1 "" "")) ; iterations; zero if unknown (use (match_operand 2 "" "")) ; max iterations (use (match_operand 3 "" "")) ; loop level (use (match_operand 4 "" ""))] ; label "" { /* Only use cloop on innermost loops. */ if (INTVAL (operands[3]) > 1) FAIL; emit_jump_insn (gen_doloop_end_internal (gen_rtx_REG (DImode, AR_LC_REGNUM), operands[4])); DONE; }) (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 "seq" [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] "" "operands[1] = ia64_expand_compare (EQ, DImode);") (define_expand "sne" [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] "" "operands[1] = ia64_expand_compare (NE, DImode);") (define_expand "slt" [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] "" "operands[1] = ia64_expand_compare (LT, DImode);") (define_expand "sle" [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] "" "operands[1] = ia64_expand_compare (LE, DImode);") (define_expand "sgt" [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] "" "operands[1] = ia64_expand_compare (GT, DImode);") (define_expand "sge" [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] "" "operands[1] = ia64_expand_compare (GE, DImode);") (define_expand "sltu" [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] "" "operands[1] = ia64_expand_compare (LTU, DImode);") (define_expand "sleu" [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] "" "operands[1] = ia64_expand_compare (LEU, DImode);") (define_expand "sgtu" [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] "" "operands[1] = ia64_expand_compare (GTU, DImode);") (define_expand "sgeu" [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] "" "operands[1] = ia64_expand_compare (GEU, DImode);") (define_expand "sunordered" [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] "" "operands[1] = ia64_expand_compare (UNORDERED, DImode);") (define_expand "sordered" [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] "" "operands[1] = ia64_expand_compare (ORDERED, DImode);") ;; Don't allow memory as destination here, because cmov/cmov/st is more ;; efficient than mov/mov/cst/cst. (define_insn_and_split "*sne_internal" [(set (match_operand:DI 0 "gr_register_operand" "=r") (ne:DI (match_operand:BI 1 "register_operand" "c") (const_int 0)))] "" "#" "reload_completed" [(cond_exec (ne (match_dup 1) (const_int 0)) (set (match_dup 0) (const_int 1))) (cond_exec (eq (match_dup 1) (const_int 0)) (set (match_dup 0) (const_int 0)))] "" [(set_attr "itanium_class" "unknown")]) (define_insn_and_split "*seq_internal" [(set (match_operand:DI 0 "gr_register_operand" "=r") (eq:DI (match_operand:BI 1 "register_operand" "c") (const_int 0)))] "" "#" "reload_completed" [(cond_exec (ne (match_dup 1) (const_int 0)) (set (match_dup 0) (const_int 0))) (cond_exec (eq (match_dup 1) (const_int 0)) (set (match_dup 0) (const_int 1)))] "" [(set_attr "itanium_class" "unknown")]) ;; :::::::::::::::::::: ;; :: ;; :: Conditional move instructions. ;; :: ;; :::::::::::::::::::: ;; ??? Add movXXcc patterns? ;; ;; DImode if_then_else patterns. ;; (define_insn "*cmovdi_internal" [(set (match_operand:DI 0 "destination_operand" "= r, r, r, r, r, r, r, r, r, r, m, Q, *f,*b,*d*e") (if_then_else:DI (match_operator 4 "predicate_operator" [(match_operand:BI 1 "register_operand" "c,c,c,c,c,c,c,c,c,c,c,c,c,c,c") (const_int 0)]) (match_operand:DI 2 "move_operand" "rim, *f, *b,*d*e,rim,rim, rim,*f,*b,*d*e,rO,*f,rOQ,rO, rK") (match_operand:DI 3 "move_operand" "rim,rim,rim, rim, *f, *b,*d*e,*f,*b,*d*e,rO,*f,rOQ,rO, rK")))] "ia64_move_ok (operands[0], operands[2]) && ia64_move_ok (operands[0], operands[3])" { gcc_unreachable (); } [(set_attr "predicable" "no")]) (define_split [(set (match_operand 0 "destination_operand" "") (if_then_else (match_operator 4 "predicate_operator" [(match_operand:BI 1 "register_operand" "") (const_int 0)]) (match_operand 2 "move_operand" "") (match_operand 3 "move_operand" "")))] "reload_completed" [(const_int 0)] { bool emitted_something = false; rtx dest = operands[0]; rtx srct = operands[2]; rtx srcf = operands[3]; rtx cond = operands[4]; if (! rtx_equal_p (dest, srct)) { ia64_emit_cond_move (dest, srct, cond); emitted_something = true; } if (! rtx_equal_p (dest, srcf)) { cond = gen_rtx_fmt_ee (GET_CODE (cond) == NE ? EQ : NE, VOIDmode, operands[1], const0_rtx); ia64_emit_cond_move (dest, srcf, cond); emitted_something = true; } if (! emitted_something) emit_note (NOTE_INSN_DELETED); DONE; }) ;; Absolute value pattern. (define_insn "*absdi2_internal" [(set (match_operand:DI 0 "gr_register_operand" "=r,r") (if_then_else:DI (match_operator 4 "predicate_operator" [(match_operand:BI 1 "register_operand" "c,c") (const_int 0)]) (neg:DI (match_operand:DI 2 "gr_reg_or_22bit_operand" "rI,rI")) (match_operand:DI 3 "gr_reg_or_22bit_operand" "0,rI")))] "" "#" [(set_attr "itanium_class" "ialu,unknown") (set_attr "predicable" "no")]) (define_split [(set (match_operand:DI 0 "register_operand" "") (if_then_else:DI (match_operator 4 "predicate_operator" [(match_operand:BI 1 "register_operand" "c,c") (const_int 0)]) (neg:DI (match_operand:DI 2 "gr_reg_or_22bit_operand" "")) (match_operand:DI 3 "gr_reg_or_22bit_operand" "")))] "reload_completed && rtx_equal_p (operands[0], operands[3])" [(cond_exec (match_dup 4) (set (match_dup 0) (neg:DI (match_dup 2))))] "") (define_split [(set (match_operand:DI 0 "register_operand" "") (if_then_else:DI (match_operator 4 "predicate_operator" [(match_operand:BI 1 "register_operand" "c,c") (const_int 0)]) (neg:DI (match_operand:DI 2 "gr_reg_or_22bit_operand" "")) (match_operand:DI 3 "gr_reg_or_22bit_operand" "")))] "reload_completed" [(cond_exec (match_dup 4) (set (match_dup 0) (neg:DI (match_dup 2)))) (cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))] { operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? EQ : NE, VOIDmode, operands[1], const0_rtx); }) ;; ;; SImode if_then_else patterns. ;; (define_insn "*cmovsi_internal" [(set (match_operand:SI 0 "destination_operand" "=r,m,*f,r,m,*f,r,m,*f") (if_then_else:SI (match_operator 4 "predicate_operator" [(match_operand:BI 1 "register_operand" "c,c,c,c,c,c,c,c,c") (const_int 0)]) (match_operand:SI 2 "move_operand" "0,0,0,rim*f,rO,rO,rim*f,rO,rO") (match_operand:SI 3 "move_operand" "rim*f,rO,rO,0,0,0,rim*f,rO,rO")))] "ia64_move_ok (operands[0], operands[2]) && ia64_move_ok (operands[0], operands[3])" { gcc_unreachable (); } [(set_attr "predicable" "no")]) (define_insn "*abssi2_internal" [(set (match_operand:SI 0 "gr_register_operand" "=r,r") (if_then_else:SI (match_operator 4 "predicate_operator" [(match_operand:BI 1 "register_operand" "c,c") (const_int 0)]) (neg:SI (match_operand:SI 3 "gr_reg_or_22bit_operand" "rI,rI")) (match_operand:SI 2 "gr_reg_or_22bit_operand" "0,rI")))] "" "#" [(set_attr "itanium_class" "ialu,unknown") (set_attr "predicable" "no")]) (define_split [(set (match_operand:SI 0 "register_operand" "") (if_then_else:SI (match_operator 4 "predicate_operator" [(match_operand:BI 1 "register_operand" "c,c") (const_int 0)]) (neg:SI (match_operand:SI 2 "gr_reg_or_22bit_operand" "")) (match_operand:SI 3 "gr_reg_or_22bit_operand" "")))] "reload_completed && rtx_equal_p (operands[0], operands[3])" [(cond_exec (match_dup 4) (set (match_dup 0) (neg:SI (match_dup 2))))] "") (define_split [(set (match_operand:SI 0 "register_operand" "") (if_then_else:SI (match_operator 4 "predicate_operator" [(match_operand:BI 1 "register_operand" "c,c") (const_int 0)]) (neg:SI (match_operand:SI 2 "gr_reg_or_22bit_operand" "")) (match_operand:SI 3 "gr_reg_or_22bit_operand" "")))] "reload_completed" [(cond_exec (match_dup 4) (set (match_dup 0) (neg:SI (match_dup 2)))) (cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))] { operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? EQ : NE, VOIDmode, operands[1], const0_rtx); }) (define_insn_and_split "*cond_opsi2_internal" [(set (match_operand:SI 0 "gr_register_operand" "=r") (match_operator:SI 5 "condop_operator" [(if_then_else:SI (match_operator 6 "predicate_operator" [(match_operand:BI 1 "register_operand" "c") (const_int 0)]) (match_operand:SI 2 "gr_register_operand" "r") (match_operand:SI 3 "gr_register_operand" "r")) (match_operand:SI 4 "gr_register_operand" "r")]))] "" "#" "reload_completed" [(cond_exec (match_dup 6) (set (match_dup 0) (match_op_dup:SI 5 [(match_dup 2) (match_dup 4)]))) (cond_exec (match_dup 7) (set (match_dup 0) (match_op_dup:SI 5 [(match_dup 3) (match_dup 4)])))] { operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[6]) == NE ? EQ : NE, VOIDmode, operands[1], const0_rtx); } [(set_attr "itanium_class" "ialu") (set_attr "predicable" "no")]) (define_insn_and_split "*cond_opsi2_internal_b" [(set (match_operand:SI 0 "gr_register_operand" "=r") (match_operator:SI 5 "condop_operator" [(match_operand:SI 4 "gr_register_operand" "r") (if_then_else:SI (match_operator 6 "predicate_operator" [(match_operand:BI 1 "register_operand" "c") (const_int 0)]) (match_operand:SI 2 "gr_register_operand" "r") (match_operand:SI 3 "gr_register_operand" "r"))]))] "" "#" "reload_completed" [(cond_exec (match_dup 6) (set (match_dup 0) (match_op_dup:SI 5 [(match_dup 4) (match_dup 2)]))) (cond_exec (match_dup 7) (set (match_dup 0) (match_op_dup:SI 5 [(match_dup 4) (match_dup 3)])))] { operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[6]) == NE ? EQ : NE, VOIDmode, operands[1], const0_rtx); } [(set_attr "itanium_class" "ialu") (set_attr "predicable" "no")]) ;; :::::::::::::::::::: ;; :: ;; :: Call and branch instructions ;; :: ;; :::::::::::::::::::: ;; Subroutine call instruction returning no value. Operand 0 is the function ;; to call; operand 1 is the number of bytes of arguments pushed (in mode ;; `SImode', except it is normally a `const_int'); operand 2 is the number of ;; registers used as operands. ;; On most machines, operand 2 is not actually stored into the RTL pattern. It ;; is supplied for the sake of some RISC machines which need to put this ;; information into the assembler code; they can put it in the RTL instead of ;; operand 1. (define_expand "call" [(use (match_operand:DI 0 "" "")) (use (match_operand 1 "" "")) (use (match_operand 2 "" "")) (use (match_operand 3 "" ""))] "" { ia64_expand_call (NULL_RTX, operands[0], operands[2], false); DONE; }) (define_expand "sibcall" [(use (match_operand:DI 0 "" "")) (use (match_operand 1 "" "")) (use (match_operand 2 "" "")) (use (match_operand 3 "" ""))] "" { ia64_expand_call (NULL_RTX, operands[0], operands[2], true); DONE; }) ;; Subroutine call instruction returning a value. Operand 0 is the hard ;; register in which the value is returned. There are three more operands, ;; the same as the three operands of the `call' instruction (but with numbers ;; increased by one). ;; ;; Subroutines that return `BLKmode' objects use the `call' insn. (define_expand "call_value" [(use (match_operand 0 "" "")) (use (match_operand:DI 1 "" "")) (use (match_operand 2 "" "")) (use (match_operand 3 "" "")) (use (match_operand 4 "" ""))] "" { ia64_expand_call (operands[0], operands[1], operands[3], false); DONE; }) (define_expand "sibcall_value" [(use (match_operand 0 "" "")) (use (match_operand:DI 1 "" "")) (use (match_operand 2 "" "")) (use (match_operand 3 "" "")) (use (match_operand 4 "" ""))] "" { ia64_expand_call (operands[0], operands[1], operands[3], true); DONE; }) ;; Call subroutine returning any type. (define_expand "untyped_call" [(parallel [(call (match_operand 0 "" "") (const_int 0)) (match_operand 1 "" "") (match_operand 2 "" "")])] "" { int i; emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { rtx set = XVECEXP (operands[2], 0, i); emit_move_insn (SET_DEST (set), SET_SRC (set)); } /* The optimizer does not know that the call sets the function value registers we stored in the result block. We avoid problems by claiming that all hard registers are used and clobbered at this point. */ emit_insn (gen_blockage ()); DONE; }) (define_insn "call_nogp" [(call (mem:DI (match_operand:DI 0 "call_operand" "?b,i")) (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,i")) (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,i")) (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,i")) (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,i")) (const_int 1))) (clobber (match_operand:DI 2 "register_operand" "=b,b")) (clobber (match_scratch:DI 3 "=&r,X")) (clobber (match_scratch:DI 4 "=b,X"))] "" "#" [(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,i")) (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:DI 0 "memory_operand" "")) (use (label_ref (match_operand 1 "" "")))])] "" { rtx op0 = operands[0]; rtx addr; /* ??? Bother -- do_tablejump is "helpful" and pulls the table element into a register without bothering to see whether that is necessary given the operand predicate. Check for MEM just in case someone fixes this. */ if (GET_CODE (op0) == MEM) addr = XEXP (op0, 0); else { /* Otherwise, cheat and guess that the previous insn in the stream was the memory load. Grab the address from that. Note we have to momentarily pop out of the sequence started by the insn-emit wrapper in order to grab the last insn. */ rtx last, set; end_sequence (); last = get_last_insn (); start_sequence (); set = single_set (last); 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, 1, OPTAB_DIRECT); }) (define_insn "*tablejump_internal" [(set (pc) (match_operand:DI 0 "register_operand" "b")) (use (label_ref (match_operand 1 "" "")))] "" "br %0" [(set_attr "itanium_class" "br")]) ;; :::::::::::::::::::: ;; :: ;; :: Prologue and Epilogue instructions ;; :: ;; :::::::::::::::::::: (define_expand "prologue" [(const_int 1)] "" { ia64_expand_prologue (); DONE; }) (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. (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")]) ;; This prevents the scheduler from moving the SP restore past FP-relative ;; stack accesses. This is similar to movdi plus the extra set. (define_insn "epilogue_deallocate_stack" [(set (match_operand:DI 0 "register_operand" "=r") (match_operand:DI 1 "register_operand" "+r")) (set (match_dup 1) (match_dup 1))] "" "mov %0 = %1" [(set_attr "itanium_class" "ialu")]) ;; 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 "conditional_trap" [(trap_if (match_operand 0 "" "") (match_operand 1 "" ""))] "" { operands[0] = ia64_expand_compare (GET_CODE (operands[0]), VOIDmode); }) (define_insn "*conditional_trap" [(trap_if (match_operator 0 "predicate_operator" [(match_operand:BI 1 "register_operand" "c") (const_int 0)]) (match_operand 2 "const_int_operand" ""))] "" "(%J0) break %2" [(set_attr "itanium_class" "chk_s_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\"), 0, VOIDmode, 2, XEXP (operands[0], 0), Pmode, operands[1], Pmode); DONE; }) (define_expand "nonlocal_goto" [(use (match_operand 0 "general_operand" "")) (use (match_operand 1 "general_operand" "")) (use (match_operand 2 "general_operand" "")) (use (match_operand 3 "general_operand" ""))] "" { emit_library_call (gen_rtx_SYMBOL_REF (Pmode, \"__ia64_nonlocal_goto\"), LCT_NORETURN, VOIDmode, 3, operands[1], Pmode, copy_to_reg (XEXP (operands[2], 0)), Pmode, operands[3], Pmode); emit_barrier (); DONE; }) (define_insn_and_split "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_insn (gen_rtx_USE (VOIDmode, sp)); emit_insn (gen_rtx_USE (VOIDmode, bsp)); cfun->machine->ia64_eh_epilogue_sp = sp; cfun->machine->ia64_eh_epilogue_bsp = bsp; }) ;; 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"), 0, VOIDmode, 1, copy_to_reg (XEXP (operands[1], 0)), Pmode); DONE; }) ;; Predication. (define_cond_exec [(match_operator 0 "predicate_operator" [(match_operand:BI 1 "register_operand" "c") (const_int 0)])] "" "(%J0)") (define_insn "pred_rel_mutex" [(set (match_operand:BI 0 "register_operand" "+c") (unspec:BI [(match_dup 0)] UNSPEC_PRED_REL_MUTEX))] "" ".pred.rel.mutex %0, %I0" [(set_attr "itanium_class" "ignore") (set_attr "predicable" "no")]) (define_insn "safe_across_calls_all" [(unspec_volatile [(const_int 0)] UNSPECV_PSAC_ALL)] "" ".pred.safe_across_calls p1-p63" [(set_attr "itanium_class" "ignore") (set_attr "predicable" "no")]) (define_insn "safe_across_calls_normal" [(unspec_volatile [(const_int 0)] UNSPECV_PSAC_NORMAL)] "" { emit_safe_across_calls (); return ""; } [(set_attr "itanium_class" "ignore") (set_attr "predicable" "no")]) ;; UNSPEC instruction definition to "swizzle" 32-bit pointer into 64-bit ;; pointer. This is used by the HP-UX 32 bit mode. (define_insn "ptr_extend" [(set (match_operand:DI 0 "gr_register_operand" "=r") (unspec:DI [(match_operand:SI 1 "gr_register_operand" "r")] UNSPEC_ADDP4))] "" "addp4 %0 = 0,%1" [(set_attr "itanium_class" "ialu")]) ;; ;; Optimizations for ptr_extend (define_insn "ptr_extend_plus_imm" [(set (match_operand:DI 0 "gr_register_operand" "=r") (unspec:DI [(plus:SI (match_operand:SI 1 "basereg_operand" "r") (match_operand:SI 2 "gr_reg_or_14bit_operand" "rI"))] UNSPEC_ADDP4))] "addp4_optimize_ok (operands[1], operands[2])" "addp4 %0 = %2, %1" [(set_attr "itanium_class" "ialu")]) (define_insn "*ptr_extend_plus_2" [(set (match_operand:DI 0 "gr_register_operand" "=r") (unspec:DI [(plus:SI (match_operand:SI 1 "gr_register_operand" "r") (match_operand:SI 2 "basereg_operand" "r"))] UNSPEC_ADDP4))] "addp4_optimize_ok (operands[1], operands[2])" "addp4 %0 = %1, %2" [(set_attr "itanium_class" "ialu")]) ;; ;; Get instruction pointer (define_insn "ip_value" [(set (match_operand:DI 0 "register_operand" "=r") (pc))] "" "mov %0 = ip" [(set_attr "itanium_class" "frbr")]) ;; Vector operations (include "vect.md") ;; Atomic operations (include "sync.md") ;; New division operations (include "div.md")