;; IA-64 Machine description template ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 ;; 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 2, 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 COPYING. If not, write to ;; the Free Software Foundation, 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. ;; ??? register_operand accepts (subreg:DI (mem:SI X)) which forces later ;; reload. This will be fixed once scheduling support is turned on. ;; ??? Optimize for post-increment addressing modes. ;; ??? fselect is not supported, because there is no integer register ;; equivalent. ;; ??? fp abs/min/max instructions may also work for integer values. ;; ??? Would a predicate_reg_operand predicate be useful? The HP one is buggy, ;; it assumes the operand is a register and takes REGNO of it without checking. ;; ??? Would a branch_reg_operand predicate be useful? The HP one is buggy, ;; it assumes the operand is a register and takes REGNO of it without checking. ;; ??? Go through list of documented named patterns and look for more to ;; implement. ;; ??? Go through instruction manual and look for more instructions that ;; can be emitted. ;; ??? Add function unit scheduling info for Itanium (TM) processor. ;; ??? Need a better way to describe alternate fp status registers. (define_constants [; Relocations (UNSPEC_LTOFF_DTPMOD 0) (UNSPEC_LTOFF_DTPREL 1) (UNSPEC_DTPREL 2) (UNSPEC_LTOFF_TPREL 3) (UNSPEC_TPREL 4) (UNSPEC_LD_BASE 9) (UNSPEC_GR_SPILL 10) (UNSPEC_GR_RESTORE 11) (UNSPEC_FR_SPILL 12) (UNSPEC_FR_RESTORE 13) (UNSPEC_FR_RECIP_APPROX 14) (UNSPEC_PRED_REL_MUTEX 15) (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) ]) (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) ]) ;; :::::::::::::::::::: ;; :: ;; :: Predicates ;; :: ;; :::::::::::::::::::: ;; True if OP is a valid operand for the MEM of a CALL insn. (define_predicate "call_operand" (ior (match_code "symbol_ref") (match_operand 0 "register_operand"))) ;; True if OP refers to any kind of symbol. ;; For roughly the same reasons that pmode_register_operand exists, this ;; predicate ignores its mode argument. (define_special_predicate "symbolic_operand" (match_code "symbol_ref,const,label_ref")) ;; True if OP is a SYMBOL_REF which refers to a function. (define_predicate "function_operand" (and (match_code "symbol_ref") (match_test "SYMBOL_REF_FUNCTION_P (op)"))) ;; True if OP refers to a symbol, and is appropriate for a GOT load. (define_predicate "got_symbolic_operand" (match_operand 0 "symbolic_operand" "") { switch (GET_CODE (op)) { case LABEL_REF: return true; case SYMBOL_REF: /* This sort of load should not be used for things in sdata. */ return !SYMBOL_REF_SMALL_ADDR_P (op); case CONST: /* Accept only (plus (symbol_ref) (const_int)). */ op = XEXP (op, 0); if (GET_CODE (op) != PLUS || GET_CODE (XEXP (op, 0)) != SYMBOL_REF || GET_CODE (XEXP (op, 1)) != CONST_INT) return false; /* Ok if we're not using GOT entries at all. */ if (TARGET_NO_PIC || TARGET_AUTO_PIC) return true; /* The low 14 bits of the constant have been forced to zero by ia64_expand_load_address, so that we do not use up so many GOT entries. Prevent cse from undoing this. */ op = XEXP (op, 1); return (INTVAL (op) & 0x3fff) == 0; default: abort (); } }) ;; True if OP refers to a symbol in the sdata section. (define_predicate "sdata_symbolic_operand" (match_code "symbol_ref,const") { switch (GET_CODE (op)) { case CONST: op = XEXP (op, 0); if (GET_CODE (op) != PLUS || GET_CODE (XEXP (op, 0)) != SYMBOL_REF) return false; op = XEXP (op, 0); /* FALLTHRU */ case SYMBOL_REF: if (CONSTANT_POOL_ADDRESS_P (op)) return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold; else return SYMBOL_REF_LOCAL_P (op) && SYMBOL_REF_SMALL_P (op); default: abort (); } }) ;; Like nonimmediate_operand, but don't allow MEMs that try to use a ;; POST_MODIFY with a REG as displacement. (define_predicate "destination_operand" (and (match_operand 0 "nonimmediate_operand") (match_test "GET_CODE (op) != MEM || GET_CODE (XEXP (op, 0)) != POST_MODIFY || GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 1)) != REG"))) ;; Like memory_operand, but don't allow post-increments. (define_predicate "not_postinc_memory_operand" (and (match_operand 0 "memory_operand") (match_test "GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC"))) ;; True if OP is a general operand, excluding tls symbolic operands. (define_predicate "move_operand" (and (match_operand 0 "general_operand") (not (match_test "GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (op)")))) ;; True if OP is a register operand that is (or could be) a GR reg. (define_predicate "gr_register_operand" (match_operand 0 "register_operand") { unsigned int regno; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); regno = REGNO (op); return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno)); }) ;; True if OP is a register operand that is (or could be) an FR reg. (define_predicate "fr_register_operand" (match_operand 0 "register_operand") { unsigned int regno; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); regno = REGNO (op); return (regno >= FIRST_PSEUDO_REGISTER || FR_REGNO_P (regno)); }) ;; True if OP is a register operand that is (or could be) a GR/FR reg. (define_predicate "grfr_register_operand" (match_operand 0 "register_operand") { unsigned int regno; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); regno = REGNO (op); return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno) || FR_REGNO_P (regno)); }) ;; True if OP is a nonimmediate operand that is (or could be) a GR reg. (define_predicate "gr_nonimmediate_operand" (match_operand 0 "nonimmediate_operand") { unsigned int regno; if (GET_CODE (op) == MEM) return true; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); regno = REGNO (op); return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno)); }) ;; True if OP is a nonimmediate operand that is (or could be) a FR reg. (define_predicate "fr_nonimmediate_operand" (match_operand 0 "nonimmediate_operand") { unsigned int regno; if (GET_CODE (op) == MEM) return true; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); regno = REGNO (op); return (regno >= FIRST_PSEUDO_REGISTER || FR_REGNO_P (regno)); }) ;; True if OP is a nonimmediate operand that is (or could be) a GR/FR reg. (define_predicate "grfr_nonimmediate_operand" (match_operand 0 "nonimmediate_operand") { unsigned int regno; if (GET_CODE (op) == MEM) return true; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); regno = REGNO (op); return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno) || FR_REGNO_P (regno)); }) ;; True if OP is a GR register operand, or zero. (define_predicate "gr_reg_or_0_operand" (ior (match_operand 0 "gr_register_operand") (and (match_code "const_int") (match_test "op == const0_rtx")))) ;; True if OP is a GR register operand, or a 5 bit immediate operand. (define_predicate "gr_reg_or_5bit_operand" (ior (match_operand 0 "gr_register_operand") (and (match_code "const_int") (match_test "INTVAL (op) >= 0 && INTVAL (op) < 32")))) ;; True if OP is a GR register operand, or a 6 bit immediate operand. (define_predicate "gr_reg_or_6bit_operand" (ior (match_operand 0 "gr_register_operand") (and (match_code "const_int") (match_test "CONST_OK_FOR_M (INTVAL (op))")))) ;; True if OP is a GR register operand, or an 8 bit immediate operand. (define_predicate "gr_reg_or_8bit_operand" (ior (match_operand 0 "gr_register_operand") (and (match_code "const_int") (match_test "CONST_OK_FOR_K (INTVAL (op))")))) ;; True if OP is a GR/FR register operand, or an 8 bit immediate operand. (define_predicate "grfr_reg_or_8bit_operand" (ior (match_operand 0 "grfr_register_operand") (and (match_code "const_int") (match_test "CONST_OK_FOR_K (INTVAL (op))")))) ;; True if OP is a register operand, or an 8 bit adjusted immediate operand. (define_predicate "gr_reg_or_8bit_adjusted_operand" (ior (match_operand 0 "gr_register_operand") (and (match_code "const_int") (match_test "CONST_OK_FOR_L (INTVAL (op))")))) ;; True if OP is a register operand, or is valid for both an 8 bit ;; immediate and an 8 bit adjusted immediate operand. This is necessary ;; because when we emit a compare, we don't know what the condition will be, ;; so we need the union of the immediates accepted by GT and LT. (define_predicate "gr_reg_or_8bit_and_adjusted_operand" (ior (match_operand 0 "gr_register_operand") (and (match_code "const_int") (match_test "CONST_OK_FOR_K (INTVAL (op)) && CONST_OK_FOR_L (INTVAL (op))")))) ;; True if OP is a register operand, or a 14 bit immediate operand. (define_predicate "gr_reg_or_14bit_operand" (ior (match_operand 0 "gr_register_operand") (and (match_code "const_int") (match_test "CONST_OK_FOR_I (INTVAL (op))")))) ;; True if OP is a register operand, or a 22 bit immediate operand. (define_predicate "gr_reg_or_22bit_operand" (ior (match_operand 0 "gr_register_operand") (and (match_code "const_int") (match_test "CONST_OK_FOR_J (INTVAL (op))")))) ;; True if OP is a 6 bit immediate operand. (define_predicate "shift_count_operand" (and (match_code "const_int") (match_test "CONST_OK_FOR_M (INTVAL (op))"))) ;; True if OP is a 5 bit immediate operand. (define_predicate "shift_32bit_count_operand" (and (match_code "const_int") (match_test "INTVAL (op) >= 0 && INTVAL (op) < 32"))) ;; True if OP is one of the immediate values 2, 4, 8, or 16. (define_predicate "shladd_operand" (and (match_code "const_int") (match_test "INTVAL (op) == 2 || INTVAL (op) == 4 || INTVAL (op) == 8 || INTVAL (op) == 16"))) ;; True if OP is one of the immediate values -16, -8, -4, -1, 1, 4, 8, 16. (define_predicate "fetchadd_operand" (and (match_code "const_int") (match_test "INTVAL (op) == -16 || INTVAL (op) == -8 || INTVAL (op) == -4 || INTVAL (op) == -1 || INTVAL (op) == 1 || INTVAL (op) == 4 || INTVAL (op) == 8 || INTVAL (op) == 16"))) ;; True if OP is a floating-point constant zero, one, or a register. (define_predicate "fr_reg_or_fp01_operand" (ior (match_operand 0 "fr_register_operand") (and (match_code "const_double") (match_test "CONST_DOUBLE_OK_FOR_G (op)")))) ;; Like fr_reg_or_fp01_operand, but don't allow any SUBREGs. (define_predicate "xfreg_or_fp01_operand" (and (match_operand 0 "fr_reg_or_fp01_operand") (not (match_code "subreg")))) ;; True if this is a comparison operator, which accepts a normal 8-bit ;; signed immediate operand. (define_predicate "normal_comparison_operator" (match_code "eq,ne,gt,le,gtu,leu")) ;; True if this is a comparison operator, which accepts an adjusted 8-bit ;; signed immediate operand. (define_predicate "adjusted_comparison_operator" (match_code "lt,ge,ltu,geu")) ;; True if this is a signed inequality operator. (define_predicate "signed_inequality_operator" (match_code "ge,gt,le,lt")) ;; True if this operator is valid for predication. (define_predicate "predicate_operator" (match_code "eq,ne")) ;; True if this operator can be used in a conditional operation. (define_predicate "condop_operator" (match_code "plus,minus,ior,xor,and")) ;; These three are hardware registers that can only be addressed in ;; DImode. It's not strictly necessary to test mode == DImode here, ;; but it makes decent insurance against someone writing a ;; match_operand wrong. ;; True if this is the ar.lc register. (define_predicate "ar_lc_reg_operand" (and (match_code "reg") (match_test "mode == DImode && REGNO (op) == AR_LC_REGNUM"))) ;; True if this is the ar.ccv register. (define_predicate "ar_ccv_reg_operand" (and (match_code "reg") (match_test "mode == DImode && REGNO (op) == AR_CCV_REGNUM"))) ;; True if this is the ar.pfs register. (define_predicate "ar_pfs_reg_operand" (and (match_code "reg") (match_test "mode == DImode && REGNO (op) == AR_PFS_REGNUM"))) ;; True if OP is valid as a base register in a reg + offset address. ;; ??? Should I copy the flag_omit_frame_pointer and cse_not_expected ;; checks from pa.c basereg_operand as well? Seems to be OK without them ;; in test runs. (define_predicate "basereg_operand" (match_operand 0 "register_operand") { if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); return REG_POINTER (op); }) ;; :::::::::::::::::::: ;; :: ;; :: 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, fmac,fmisc,frar_i,frar_m,frbr,frfr,frpr,ialu,icmp,ilog,ishf,ld, chk_s,long_i,mmmul,mmshf,mmshfi,rse_m,scall,sem,stf,st,syst_m0, 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 has an I and an M form; use type A for convenience. (define_attr "type" "unknown,A,I,M,F,B,L,X,S" (cond [(eq_attr "itanium_class" "ld,st,fld,stf,sem,nop_m") (const_string "M") (eq_attr "itanium_class" "rse_m,syst_m,syst_m0") (const_string "M") (eq_attr "itanium_class" "frar_m,toar_m,frfr,tofr") (const_string "M") (eq_attr "itanium_class" "lfetch") (const_string "M") (eq_attr "itanium_class" "chk_s,ialu,icmp,ilog") (const_string "A") (eq_attr "itanium_class" "fmisc,fmac,fcmp,xmpy") (const_string "F") (eq_attr "itanium_class" "fcvtfx,nop_f") (const_string "F") (eq_attr "itanium_class" "frar_i,toar_i,frbr,tobr") (const_string "I") (eq_attr "itanium_class" "frpr,topr,ishf,xtd,tbit") (const_string "I") (eq_attr "itanium_class" "mmmul,mmshf,mmshfi,nop_i") (const_string "I") (eq_attr "itanium_class" "br,scall,nop_b") (const_string "B") (eq_attr "itanium_class" "stop_bit") (const_string "S") (eq_attr "itanium_class" "nop_x") (const_string "X") (eq_attr "itanium_class" "long_i") (const_string "L")] (const_string "unknown"))) (define_attr "itanium_requires_unit0" "no,yes" (cond [(eq_attr "itanium_class" "syst_m0,sem,frfr,rse_m") (const_string "yes") (eq_attr "itanium_class" "toar_m,frar_m") (const_string "yes") (eq_attr "itanium_class" "frbr,tobr,mmmul") (const_string "yes") (eq_attr "itanium_class" "tbit,ishf,topr,frpr") (const_string "yes") (eq_attr "itanium_class" "toar_i,frar_i") (const_string "yes") (eq_attr "itanium_class" "fmisc,fcmp") (const_string "yes")] (const_string "no"))) ;; Predication. True iff this instruction can be predicated. (define_attr "predicable" "no,yes" (const_string "yes")) ;; Empty. True iff this insn does not generate any code. (define_attr "empty" "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") ;;(automata_option "no-minimization") (include "itanium1.md") (include "itanium2.md") ;; :::::::::::::::::::: ;; :: ;; :: Moves ;; :: ;; :::::::::::::::::::: ;; Set of a single predicate register. This is only used to implement ;; pr-to-pr move and complement. (define_insn "*movcci" [(set (match_operand:CCI 0 "register_operand" "=c,c,c") (match_operand:CCI 1 "nonmemory_operand" "O,n,c"))] "" "@ cmp.ne %0, p0 = r0, r0 cmp.eq %0, p0 = r0, r0 (%1) cmp.eq.unc %0, p0 = r0, r0" [(set_attr "itanium_class" "icmp") (set_attr "predicable" "no")]) (define_insn "movbi" [(set (match_operand:BI 0 "nonimmediate_operand" "=c,c,?c,?*r, c,*r,*r,*m,*r") (match_operand:BI 1 "move_operand" " O,n, c, c,*r, n,*m,*r,*r"))] "" "@ cmp.ne %0, %I0 = r0, r0 cmp.eq %0, %I0 = r0, r0 # # tbit.nz %0, %I0 = %1, 0 adds %0 = %1, r0 ld1%O1 %0 = %1%P1 st1%Q0 %0 = %1%P0 mov %0 = %1" [(set_attr "itanium_class" "icmp,icmp,unknown,unknown,tbit,ialu,ld,st,ialu")]) (define_split [(set (match_operand:BI 0 "register_operand" "") (match_operand:BI 1 "register_operand" ""))] "reload_completed && GET_CODE (operands[0]) == REG && GR_REGNO_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && PR_REGNO_P (REGNO (operands[1]))" [(cond_exec (ne (match_dup 1) (const_int 0)) (set (match_dup 0) (const_int 1))) (cond_exec (eq (match_dup 1) (const_int 0)) (set (match_dup 0) (const_int 0)))] "") (define_split [(set (match_operand:BI 0 "register_operand" "") (match_operand:BI 1 "register_operand" ""))] "reload_completed && GET_CODE (operands[0]) == REG && PR_REGNO_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && PR_REGNO_P (REGNO (operands[1]))" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5)) (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" }; if (which_alternative == 2 && ! TARGET_NO_PIC && symbolic_operand (operands[1], VOIDmode)) abort (); 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_split [(set (match_operand 0 "register_operand" "") (match_operand 1 "symbolic_operand" ""))] "reload_completed && ! TARGET_NO_PIC" [(const_int 0)] { ia64_expand_load_address (operands[0], operands[1]); DONE; }) (define_expand "load_fptr" [(set (match_dup 2) (plus:DI (reg:DI 1) (match_operand 1 "function_operand" ""))) (set (match_operand:DI 0 "register_operand" "") (match_dup 3))] "" { operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode); operands[3] = gen_const_mem (DImode, operands[2]); }) (define_insn "*load_fptr_internal1" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (reg:DI 1) (match_operand 1 "function_operand" "s")))] "" "addl %0 = @ltoff(@fptr(%1)), gp" [(set_attr "itanium_class" "ialu")]) (define_insn "load_gprel" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (reg:DI 1) (match_operand 1 "sdata_symbolic_operand" "s")))] "" "addl %0 = @gprel(%1), gp" [(set_attr "itanium_class" "ialu")]) (define_insn "gprel64_offset" [(set (match_operand:DI 0 "register_operand" "=r") (minus:DI (match_operand:DI 1 "symbolic_operand" "") (reg:DI 1)))] "" "movl %0 = @gprel(%1)" [(set_attr "itanium_class" "long_i")]) (define_expand "load_gprel64" [(set (match_dup 2) (minus:DI (match_operand:DI 1 "symbolic_operand" "") (match_dup 3))) (set (match_operand:DI 0 "register_operand" "") (plus:DI (match_dup 3) (match_dup 2)))] "" { operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode); operands[3] = pic_offset_table_rtx; }) ;; 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")))] "" { if (HAVE_AS_LTOFFX_LDXMOV_RELOCS) return "%,addl %0 = @ltoffx(%1), %2"; else return "%,addl %0 = @ltoff(%1), %2"; } [(set_attr "itanium_class" "ialu")]) (define_insn "*load_symptr_low" [(set (match_operand:DI 0 "register_operand" "=r") (lo_sum:DI (match_operand:DI 1 "register_operand" "r") (match_operand 2 "got_symbolic_operand" "s")))] "" { if (HAVE_AS_LTOFFX_LDXMOV_RELOCS) return "%,ld8.mov %0 = [%1], %2"; else return "%,ld8 %0 = [%1]"; } [(set_attr "itanium_class" "ld")]) (define_insn "load_ltoff_dtpmod" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (reg:DI 1) (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_LTOFF_DTPMOD)))] "" "addl %0 = @ltoff(@dtpmod(%1)), gp" [(set_attr "itanium_class" "ialu")]) (define_insn "load_ltoff_dtprel" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (reg:DI 1) (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_LTOFF_DTPREL)))] "" "addl %0 = @ltoff(@dtprel(%1)), gp" [(set_attr "itanium_class" "ialu")]) (define_expand "load_dtprel" [(set (match_operand:DI 0 "register_operand" "") (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_DTPREL))] "" "") (define_insn "*load_dtprel64" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_DTPREL))] "TARGET_TLS64" "movl %0 = @dtprel(%1)" [(set_attr "itanium_class" "long_i")]) (define_insn "*load_dtprel22" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_DTPREL))] "" "addl %0 = @dtprel(%1), r0" [(set_attr "itanium_class" "ialu")]) (define_expand "add_dtprel" [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_DTPREL)))] "!TARGET_TLS64" "") (define_insn "*add_dtprel14" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (match_operand:DI 1 "register_operand" "r") (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_DTPREL)))] "TARGET_TLS14" "adds %0 = @dtprel(%2), %1" [(set_attr "itanium_class" "ialu")]) (define_insn "*add_dtprel22" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (match_operand:DI 1 "register_operand" "a") (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_DTPREL)))] "TARGET_TLS22" "addl %0 = @dtprel(%2), %1" [(set_attr "itanium_class" "ialu")]) (define_insn "load_ltoff_tprel" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (reg:DI 1) (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_LTOFF_TPREL)))] "" "addl %0 = @ltoff(@tprel(%1)), gp" [(set_attr "itanium_class" "ialu")]) (define_expand "load_tprel" [(set (match_operand:DI 0 "register_operand" "") (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_TPREL))] "" "") (define_insn "*load_tprel64" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_TPREL))] "TARGET_TLS64" "movl %0 = @tprel(%1)" [(set_attr "itanium_class" "long_i")]) (define_insn "*load_tprel22" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_TPREL))] "" "addl %0 = @tprel(%1), r0" [(set_attr "itanium_class" "ialu")]) (define_expand "add_tprel" [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_TPREL)))] "!TARGET_TLS64" "") (define_insn "*add_tprel14" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (match_operand:DI 1 "register_operand" "r") (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_TPREL)))] "TARGET_TLS14" "adds %0 = @tprel(%2), %1" [(set_attr "itanium_class" "ialu")]) (define_insn "*add_tprel22" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (match_operand:DI 1 "register_operand" "a") (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_TPREL)))] "TARGET_TLS22" "addl %0 = @tprel(%2), %1" [(set_attr "itanium_class" "ialu")]) ;; With no offsettable memory references, we've got to have a scratch ;; 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 "nonimmediate_operand" "=r,r,m") (match_operand:TI 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")]) ;; 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" ""))] "" { rtx op0 = operands[0]; if (GET_CODE (op0) == SUBREG) op0 = SUBREG_REG (op0); /* We must support XFmode loads into general registers for stdarg/vararg and unprototyped calls. We split them into DImode loads for convenience. We don't need XFmode stores from general regs, because a stdarg/vararg routine does a block store to memory of unnamed arguments. */ if (GET_CODE (op0) == REG && GR_REGNO_P (REGNO (op0))) { /* We're hoping to transform everything that deals with XFmode quantities and GR registers early in the compiler. */ if (no_new_pseudos) abort (); /* Struct to register can just use TImode instead. */ if ((GET_CODE (operands[1]) == SUBREG && GET_MODE (SUBREG_REG (operands[1])) == TImode) || (GET_CODE (operands[1]) == REG && GR_REGNO_P (REGNO (operands[1])))) { rtx op1 = operands[1]; if (GET_CODE (op1) == SUBREG) op1 = SUBREG_REG (op1); else /* ??? Maybe we should make a SUBREG here? */ op1 = gen_rtx_REG (TImode, REGNO (op1)); emit_move_insn (gen_rtx_REG (TImode, REGNO (op0)), op1); DONE; } if (GET_CODE (operands[1]) == CONST_DOUBLE) { emit_move_insn (gen_rtx_REG (DImode, REGNO (op0)), operand_subword (operands[1], 0, 0, XFmode)); emit_move_insn (gen_rtx_REG (DImode, REGNO (op0) + 1), operand_subword (operands[1], 1, 0, XFmode)); DONE; } /* If the quantity is in a register not known to be GR, spill it. */ if (register_operand (operands[1], XFmode)) operands[1] = spill_xfmode_operand (operands[1], 1); if (GET_CODE (operands[1]) == MEM) { rtx out[2]; out[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (op0)); out[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (op0) + 1); emit_move_insn (out[0], adjust_address (operands[1], DImode, 0)); emit_move_insn (out[1], adjust_address (operands[1], DImode, 8)); DONE; } abort (); } if (! reload_in_progress && ! reload_completed) { operands[1] = spill_xfmode_operand (operands[1], 0); if (GET_MODE (op0) == TImode && GET_CODE (op0) == REG) { rtx memt, memx, in = operands[1]; if (CONSTANT_P (in)) in = validize_mem (force_const_mem (XFmode, in)); if (GET_CODE (in) == MEM) memt = adjust_address (in, TImode, 0); else { memt = assign_stack_temp (TImode, 16, 0); memx = adjust_address (memt, XFmode, 0); emit_move_insn (memx, in); } emit_move_insn (op0, memt); DONE; } if (! ia64_move_ok (operands[0], operands[1])) operands[1] = force_reg (XFmode, operands[1]); } }) ;; ??? 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")]) ;; Better code generation via insns that deal with TFmode register pairs ;; directly. Same concerns apply as for TImode. (define_expand "movtf" [(set (match_operand:TF 0 "general_operand" "") (match_operand:TF 1 "general_operand" ""))] "" { rtx op1 = ia64_expand_move (operands[0], operands[1]); if (!op1) DONE; operands[1] = op1; }) (define_insn_and_split "*movtf_internal" [(set (match_operand:TF 0 "nonimmediate_operand" "=r,r,m") (match_operand:TF 1 "general_operand" "ri,m,r"))] "ia64_move_ok (operands[0], operands[1])" "#" "reload_completed" [(const_int 0)] { ia64_split_tmode_move (operands); DONE; } [(set_attr "itanium_class" "unknown") (set_attr "predicable" "no")]) ;; :::::::::::::::::::: ;; :: ;; :: Conversions ;; :: ;; :::::::::::::::::::: ;; Signed conversions from a smaller integer to a larger integer (define_insn "extendqidi2" [(set (match_operand:DI 0 "gr_register_operand" "=r") (sign_extend:DI (match_operand:QI 1 "gr_register_operand" "r")))] "" "sxt1 %0 = %1" [(set_attr "itanium_class" "xtd")]) (define_insn "extendhidi2" [(set (match_operand:DI 0 "gr_register_operand" "=r") (sign_extend:DI (match_operand:HI 1 "gr_register_operand" "r")))] "" "sxt2 %0 = %1" [(set_attr "itanium_class" "xtd")]) (define_insn "extendsidi2" [(set (match_operand:DI 0 "grfr_register_operand" "=r,?f") (sign_extend:DI (match_operand:SI 1 "grfr_register_operand" "r,f")))] "" "@ sxt4 %0 = %1 fsxt.r %0 = %1, %1" [(set_attr "itanium_class" "xtd,fmisc")]) ;; Unsigned conversions from a smaller integer to a larger integer (define_insn "zero_extendqidi2" [(set (match_operand:DI 0 "gr_register_operand" "=r,r") (zero_extend:DI (match_operand:QI 1 "gr_nonimmediate_operand" "r,m")))] "" "@ zxt1 %0 = %1 ld1%O1 %0 = %1%P1" [(set_attr "itanium_class" "xtd,ld")]) (define_insn "zero_extendhidi2" [(set (match_operand:DI 0 "gr_register_operand" "=r,r") (zero_extend:DI (match_operand:HI 1 "gr_nonimmediate_operand" "r,m")))] "" "@ zxt2 %0 = %1 ld2%O1 %0 = %1%P1" [(set_attr "itanium_class" "xtd,ld")]) (define_insn "zero_extendsidi2" [(set (match_operand:DI 0 "grfr_register_operand" "=r,r,?f") (zero_extend:DI (match_operand:SI 1 "grfr_nonimmediate_operand" "r,m,f")))] "" "@ zxt4 %0 = %1 ld4%O1 %0 = %1%P1 fmix.r %0 = f0, %1" [(set_attr "itanium_class" "xtd,ld,fmisc")]) ;; Convert between floating point types of different sizes. ;; At first glance, it would appear that emitting fnorm for an extending ;; conversion is unnecessary. However, the stf and getf instructions work ;; correctly only if the input is properly rounded for its type. In ;; particular, we get the wrong result for getf.d/stfd if the input is a ;; denorm single. Since we don't know what the next instruction will be, we ;; have to emit an fnorm. ;; ??? Optimization opportunity here. Get rid of the insn altogether ;; when we can. Should probably use a scheme like has been proposed ;; for ia32 in dealing with operands that match unary operators. This ;; would let combine merge the thing into adjacent insns. See also how the ;; mips port handles SIGN_EXTEND as operands to integer arithmetic insns via ;; se_register_operand. (define_insn "extendsfdf2" [(set (match_operand:DF 0 "fr_register_operand" "=f") (float_extend:DF (match_operand:SF 1 "fr_register_operand" "f")))] "" "fnorm.d %0 = %1" [(set_attr "itanium_class" "fmac")]) (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 "const_int_operand" "n") (match_operand:DI 3 "const_int_operand" "n")))] "" "extr %0 = %1, %3, %2" [(set_attr "itanium_class" "ishf")]) (define_insn "extzv" [(set (match_operand:DI 0 "gr_register_operand" "=r") (zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r") (match_operand:DI 2 "const_int_operand" "n") (match_operand:DI 3 "const_int_operand" "n")))] "" "extr.u %0 = %1, %3, %2" [(set_attr "itanium_class" "ishf")]) ;; Insert a bit field. ;; Can have 3 operands, source1 (inserter), source2 (insertee), dest. ;; Source1 can be 0 or -1. ;; Source2 can be 0. ;; ??? Actual dep instruction is more powerful than what these insv ;; patterns support. Unfortunately, combine is unable to create patterns ;; where source2 != dest. (define_expand "insv" [(set (zero_extract:DI (match_operand:DI 0 "gr_register_operand" "") (match_operand:DI 1 "const_int_operand" "") (match_operand:DI 2 "const_int_operand" "")) (match_operand:DI 3 "nonmemory_operand" ""))] "" { int width = INTVAL (operands[1]); int shift = INTVAL (operands[2]); /* If operand[3] is a constant, and isn't 0 or -1, then load it into a pseudo. */ if (! register_operand (operands[3], DImode) && operands[3] != const0_rtx && operands[3] != constm1_rtx) operands[3] = force_reg (DImode, operands[3]); /* If this is a single dep instruction, we have nothing to do. */ if (! ((register_operand (operands[3], DImode) && width <= 16) || operands[3] == const0_rtx || operands[3] == constm1_rtx)) { /* Check for cases that can be implemented with a mix instruction. */ if (width == 32 && shift == 0) { /* Directly generating the mix4left instruction confuses optimize_bit_field in function.c. Since this is performing a useful optimization, we defer generation of the complicated mix4left RTL to the first splitting phase. */ rtx tmp = gen_reg_rtx (DImode); emit_insn (gen_shift_mix4left (operands[0], operands[3], tmp)); DONE; } else if (width == 32 && shift == 32) { emit_insn (gen_mix4right (operands[0], operands[3])); DONE; } /* We could handle remaining cases by emitting multiple dep instructions. If we need more than two dep instructions then we lose. A 6 insn sequence mov mask1,mov mask2,shl;;and,and;;or is better than mov;;dep,shr;;dep,shr;;dep. The former can be executed in 3 cycles, the latter is 6 cycles on an Itanium (TM) processor, because there is only one function unit that can execute dep and shr immed. If we only need two dep instruction, then we still lose. mov;;dep,shr;;dep is still 4 cycles. Even if we optimize away the unnecessary mov, this is still undesirable because it will be hard to optimize, and it creates unnecessary pressure on the I0 function unit. */ FAIL; #if 0 /* This code may be useful for other IA-64 processors, so we leave it in for now. */ while (width > 16) { rtx tmp; emit_insn (gen_insv (operands[0], GEN_INT (16), GEN_INT (shift), operands[3])); shift += 16; width -= 16; tmp = gen_reg_rtx (DImode); emit_insn (gen_lshrdi3 (tmp, operands[3], GEN_INT (16))); operands[3] = tmp; } operands[1] = GEN_INT (width); operands[2] = GEN_INT (shift); #endif } }) (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 "*depz_internal" [(set (match_operand:DI 0 "gr_register_operand" "=r") (and:DI (ashift:DI (match_operand:DI 1 "gr_register_operand" "r") (match_operand:DI 2 "const_int_operand" "n")) (match_operand:DI 3 "const_int_operand" "n")))] "CONST_OK_FOR_M (INTVAL (operands[2])) && ia64_depz_field_mask (operands[3], operands[2]) > 0" { operands[3] = GEN_INT (ia64_depz_field_mask (operands[3], operands[2])); 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 "const_int_operand" "n")) (const_int 0)) (match_operand:BI 3 "register_operand" "0")))] "" "tbit.nz.and.orcm %0, %I0 = %1, %2" [(set_attr "itanium_class" "tbit")]) (define_insn "*tbit_and_3" [(set (match_operand:BI 0 "register_operand" "=c") (and:BI (eq:BI (zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r") (const_int 1) (match_operand:DI 2 "const_int_operand" "n")) (const_int 0)) (match_operand:BI 3 "register_operand" "0")))] "" "tbit.z.and.orcm %0, %I0 = %1, %2" [(set_attr "itanium_class" "tbit")]) (define_insn "*cmpsi_or_0" [(set (match_operand:BI 0 "register_operand" "=c") (ior:BI (match_operator:BI 4 "predicate_operator" [(match_operand:SI 2 "gr_reg_or_0_operand" "rO") (match_operand:SI 3 "gr_reg_or_8bit_operand" "rK")]) (match_operand:BI 1 "register_operand" "0")))] "" "cmp4.%C4.or.andcm %0, %I0 = %3, %r2" [(set_attr "itanium_class" "icmp")]) (define_insn "*cmpsi_or_1" [(set (match_operand:BI 0 "register_operand" "=c") (ior:BI (match_operator:BI 3 "signed_inequality_operator" [(match_operand:SI 2 "gr_register_operand" "r") (const_int 0)]) (match_operand:BI 1 "register_operand" "0")))] "" "cmp4.%C3.or.andcm %0, %I0 = r0, %2" [(set_attr "itanium_class" "icmp")]) (define_insn "*cmpsi_orcm_0" [(set (match_operand:BI 0 "register_operand" "=c") (ior:BI (not:BI (match_operator:BI 4 "predicate_operator" [(match_operand:SI 2 "gr_reg_or_0_operand" "rO") (match_operand:SI 3 "gr_reg_or_8bit_operand" "rK")])) (match_operand:BI 1 "register_operand" "0")))] "" "cmp4.%C4.and.orcm %I0, %0 = %3, %r2" [(set_attr "itanium_class" "icmp")]) (define_insn "*cmpsi_orcm_1" [(set (match_operand:BI 0 "register_operand" "=c") (ior:BI (not:BI (match_operator:BI 3 "signed_inequality_operator" [(match_operand:SI 2 "gr_register_operand" "r") (const_int 0)])) (match_operand:BI 1 "register_operand" "0")))] "" "cmp4.%C3.and.orcm %I0, %0 = r0, %2" [(set_attr "itanium_class" "icmp")]) (define_insn "*cmpdi_or_0" [(set (match_operand:BI 0 "register_operand" "=c") (ior:BI (match_operator:BI 4 "predicate_operator" [(match_operand:DI 2 "gr_register_operand" "r") (match_operand:DI 3 "gr_reg_or_8bit_operand" "rK")]) (match_operand:BI 1 "register_operand" "0")))] "" "cmp.%C4.or.andcm %0, %I0 = %3, %2" [(set_attr "itanium_class" "icmp")]) (define_insn "*cmpdi_or_1" [(set (match_operand:BI 0 "register_operand" "=c") (ior:BI (match_operator:BI 3 "signed_inequality_operator" [(match_operand:DI 2 "gr_register_operand" "r") (const_int 0)]) (match_operand:BI 1 "register_operand" "0")))] "" "cmp.%C3.or.andcm %0, %I0 = r0, %2" [(set_attr "itanium_class" "icmp")]) (define_insn "*cmpdi_orcm_0" [(set (match_operand:BI 0 "register_operand" "=c") (ior:BI (not:BI (match_operator:BI 4 "predicate_operator" [(match_operand:DI 2 "gr_register_operand" "r") (match_operand:DI 3 "gr_reg_or_8bit_operand" "rK")])) (match_operand:BI 1 "register_operand" "0")))] "" "cmp.%C4.and.orcm %I0, %0 = %3, %2" [(set_attr "itanium_class" "icmp")]) (define_insn "*cmpdi_orcm_1" [(set (match_operand:BI 0 "register_operand" "=c") (ior:BI (not:BI (match_operator:BI 3 "signed_inequality_operator" [(match_operand:DI 2 "gr_register_operand" "r") (const_int 0)])) (match_operand:BI 1 "register_operand" "0")))] "" "cmp.%C3.and.orcm %I0, %0 = r0, %2" [(set_attr "itanium_class" "icmp")]) (define_insn "*tbit_or_0" [(set (match_operand:BI 0 "register_operand" "=c") (ior:BI (ne:BI (and:DI (match_operand:DI 1 "gr_register_operand" "r") (const_int 1)) (const_int 0)) (match_operand:BI 2 "register_operand" "0")))] "" "tbit.nz.or.andcm %0, %I0 = %1, 0" [(set_attr "itanium_class" "tbit")]) (define_insn "*tbit_or_1" [(set (match_operand:BI 0 "register_operand" "=c") (ior:BI (eq:BI (and:DI (match_operand:DI 1 "gr_register_operand" "r") (const_int 1)) (const_int 0)) (match_operand:BI 2 "register_operand" "0")))] "" "tbit.z.or.andcm %0, %I0 = %1, 0" [(set_attr "itanium_class" "tbit")]) (define_insn "*tbit_or_2" [(set (match_operand:BI 0 "register_operand" "=c") (ior:BI (ne:BI (zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r") (const_int 1) (match_operand:DI 2 "const_int_operand" "n")) (const_int 0)) (match_operand:BI 3 "register_operand" "0")))] "" "tbit.nz.or.andcm %0, %I0 = %1, %2" [(set_attr "itanium_class" "tbit")]) (define_insn "*tbit_or_3" [(set (match_operand:BI 0 "register_operand" "=c") (ior:BI (eq:BI (zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r") (const_int 1) (match_operand:DI 2 "const_int_operand" "n")) (const_int 0)) (match_operand:BI 3 "register_operand" "0")))] "" "tbit.z.or.andcm %0, %I0 = %1, %2" [(set_attr "itanium_class" "tbit")]) ;; Transform test of and/or of setcc into parallel comparisons. (define_split [(set (match_operand:BI 0 "register_operand" "") (ne:BI (and:DI (ne:DI (match_operand:BI 2 "register_operand" "") (const_int 0)) (match_operand:DI 3 "register_operand" "")) (const_int 0)))] "" [(set (match_dup 0) (and:BI (ne:BI (and:DI (match_dup 3) (const_int 1)) (const_int 0)) (match_dup 2)))] "") (define_split [(set (match_operand:BI 0 "register_operand" "") (eq:BI (and:DI (ne:DI (match_operand:BI 2 "register_operand" "") (const_int 0)) (match_operand:DI 3 "register_operand" "")) (const_int 0)))] "" [(set (match_dup 0) (and:BI (ne:BI (and:DI (match_dup 3) (const_int 1)) (const_int 0)) (match_dup 2))) (parallel [(set (match_dup 0) (not:BI (match_dup 0))) (clobber (scratch))])] "") (define_split [(set (match_operand:BI 0 "register_operand" "") (ne:BI (ior:DI (ne:DI (match_operand:BI 2 "register_operand" "") (const_int 0)) (match_operand:DI 3 "register_operand" "")) (const_int 0)))] "" [(set (match_dup 0) (ior:BI (ne:BI (match_dup 3) (const_int 0)) (match_dup 2)))] "") (define_split [(set (match_operand:BI 0 "register_operand" "") (eq:BI (ior:DI (ne:DI (match_operand:BI 2 "register_operand" "") (const_int 0)) (match_operand:DI 3 "register_operand" "")) (const_int 0)))] "" [(set (match_dup 0) (ior:BI (ne:BI (match_dup 3) (const_int 0)) (match_dup 2))) (parallel [(set (match_dup 0) (not:BI (match_dup 0))) (clobber (scratch))])] "") ;; ??? Incredibly hackish. Either need four proper patterns with all ;; the alternatives, or rely on sched1 to split the insn and hope that ;; nothing bad happens to the comparisons in the meantime. ;; ;; Alternately, adjust combine to allow 2->2 and 3->3 splits, assuming ;; that we're doing height reduction. ; ;(define_insn_and_split "" ; [(set (match_operand:BI 0 "register_operand" "=c") ; (and:BI (and:BI (match_operator:BI 1 "comparison_operator" ; [(match_operand 2 "" "") ; (match_operand 3 "" "")]) ; (match_operator:BI 4 "comparison_operator" ; [(match_operand 5 "" "") ; (match_operand 6 "" "")])) ; (match_dup 0)))] ; "flag_schedule_insns" ; "#" ; "" ; [(set (match_dup 0) (and:BI (match_dup 1) (match_dup 0))) ; (set (match_dup 0) (and:BI (match_dup 4) (match_dup 0)))] ; "") ; ;(define_insn_and_split "" ; [(set (match_operand:BI 0 "register_operand" "=c") ; (ior:BI (ior:BI (match_operator:BI 1 "comparison_operator" ; [(match_operand 2 "" "") ; (match_operand 3 "" "")]) ; (match_operator:BI 4 "comparison_operator" ; [(match_operand 5 "" "") ; (match_operand 6 "" "")])) ; (match_dup 0)))] ; "flag_schedule_insns" ; "#" ; "" ; [(set (match_dup 0) (ior:BI (match_dup 1) (match_dup 0))) ; (set (match_dup 0) (ior:BI (match_dup 4) (match_dup 0)))] ; "") ; ;(define_split ; [(set (match_operand:BI 0 "register_operand" "") ; (and:BI (and:BI (match_operator:BI 1 "comparison_operator" ; [(match_operand 2 "" "") ; (match_operand 3 "" "")]) ; (match_operand:BI 7 "register_operand" "")) ; (and:BI (match_operator:BI 4 "comparison_operator" ; [(match_operand 5 "" "") ; (match_operand 6 "" "")]) ; (match_operand:BI 8 "register_operand" ""))))] ; "" ; [(set (match_dup 0) (and:BI (match_dup 7) (match_dup 8))) ; (set (match_dup 0) (and:BI (and:BI (match_dup 1) (match_dup 4)) ; (match_dup 0)))] ; "") ; ;(define_split ; [(set (match_operand:BI 0 "register_operand" "") ; (ior:BI (ior:BI (match_operator:BI 1 "comparison_operator" ; [(match_operand 2 "" "") ; (match_operand 3 "" "")]) ; (match_operand:BI 7 "register_operand" "")) ; (ior:BI (match_operator:BI 4 "comparison_operator" ; [(match_operand 5 "" "") ; (match_operand 6 "" "")]) ; (match_operand:BI 8 "register_operand" ""))))] ; "" ; [(set (match_dup 0) (ior:BI (match_dup 7) (match_dup 8))) ; (set (match_dup 0) (ior:BI (ior:BI (match_dup 1) (match_dup 4)) ; (match_dup 0)))] ; "") ;; Try harder to avoid predicate copies by duplicating compares. ;; Note that we'll have already split the predicate copy, which ;; is kind of a pain, but oh well. (define_peephole2 [(set (match_operand:BI 0 "register_operand" "") (match_operand:BI 1 "comparison_operator" "")) (set (match_operand:CCI 2 "register_operand" "") (match_operand:CCI 3 "register_operand" "")) (set (match_operand:CCI 4 "register_operand" "") (match_operand:CCI 5 "register_operand" "")) (set (match_operand:BI 6 "register_operand" "") (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_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_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)))] "") ;; ??? There are highpart multiply and add instructions, but we have no way ;; to generate them. (define_insn "smuldi3_highpart" [(set (match_operand:DI 0 "fr_register_operand" "=f") (truncate:DI (lshiftrt:TI (mult:TI (sign_extend:TI (match_operand:DI 1 "fr_register_operand" "f")) (sign_extend:TI (match_operand:DI 2 "fr_register_operand" "f"))) (const_int 64))))] "" "xmpy.h %0 = %1, %2" [(set_attr "itanium_class" "xmpy")]) (define_insn "umuldi3_highpart" [(set (match_operand:DI 0 "fr_register_operand" "=f") (truncate:DI (lshiftrt:TI (mult:TI (zero_extend:TI (match_operand:DI 1 "fr_register_operand" "f")) (zero_extend:TI (match_operand:DI 2 "fr_register_operand" "f"))) (const_int 64))))] "" "xmpy.hu %0 = %1, %2" [(set_attr "itanium_class" "xmpy")]) (define_insn "negdi2" [(set (match_operand:DI 0 "gr_register_operand" "=r") (neg:DI (match_operand:DI 1 "gr_register_operand" "r")))] "" "sub %0 = r0, %1" [(set_attr "itanium_class" "ialu")]) (define_expand "absdi2" [(set (match_dup 2) (ge:BI (match_operand:DI 1 "gr_register_operand" "") (const_int 0))) (set (match_operand:DI 0 "gr_register_operand" "") (if_then_else:DI (eq (match_dup 2) (const_int 0)) (neg:DI (match_dup 1)) (match_dup 1)))] "" { 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 "*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); if (TARGET_INLINE_INT_DIV_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); if (TARGET_INLINE_INT_DIV_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_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_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")]) ;; :::::::::::::::::::: ;; :: ;; :: 32 bit floating point arithmetic ;; :: ;; :::::::::::::::::::: (define_insn "addsf3" [(set (match_operand:SF 0 "fr_register_operand" "=f") (plus:SF (match_operand:SF 1 "fr_register_operand" "%f") (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fadd.s %0 = %1, %F2" [(set_attr "itanium_class" "fmac")]) (define_insn "subsf3" [(set (match_operand:SF 0 "fr_register_operand" "=f") (minus:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG") (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fsub.s %0 = %F1, %F2" [(set_attr "itanium_class" "fmac")]) (define_insn "mulsf3" [(set (match_operand:SF 0 "fr_register_operand" "=f") (mult:SF (match_operand:SF 1 "fr_register_operand" "%f") (match_operand:SF 2 "fr_register_operand" "f")))] "" "fmpy.s %0 = %1, %2" [(set_attr "itanium_class" "fmac")]) (define_insn "abssf2" [(set (match_operand:SF 0 "fr_register_operand" "=f") (abs:SF (match_operand:SF 1 "fr_register_operand" "f")))] "" "fabs %0 = %1" [(set_attr "itanium_class" "fmisc")]) (define_insn "negsf2" [(set (match_operand:SF 0 "fr_register_operand" "=f") (neg:SF (match_operand:SF 1 "fr_register_operand" "f")))] "" "fneg %0 = %1" [(set_attr "itanium_class" "fmisc")]) (define_insn "*nabssf2" [(set (match_operand:SF 0 "fr_register_operand" "=f") (neg:SF (abs:SF (match_operand:SF 1 "fr_register_operand" "f"))))] "" "fnegabs %0 = %1" [(set_attr "itanium_class" "fmisc")]) (define_insn "minsf3" [(set (match_operand:SF 0 "fr_register_operand" "=f") (smin:SF (match_operand:SF 1 "fr_register_operand" "f") (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fmin %0 = %1, %F2" [(set_attr "itanium_class" "fmisc")]) (define_insn "maxsf3" [(set (match_operand:SF 0 "fr_register_operand" "=f") (smax:SF (match_operand:SF 1 "fr_register_operand" "f") (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fmax %0 = %1, %F2" [(set_attr "itanium_class" "fmisc")]) (define_insn "*maddsf4" [(set (match_operand:SF 0 "fr_register_operand" "=f") (plus:SF (mult:SF (match_operand:SF 1 "fr_register_operand" "f") (match_operand:SF 2 "fr_register_operand" "f")) (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))] "" "fma.s %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*msubsf4" [(set (match_operand:SF 0 "fr_register_operand" "=f") (minus:SF (mult:SF (match_operand:SF 1 "fr_register_operand" "f") (match_operand:SF 2 "fr_register_operand" "f")) (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))] "" "fms.s %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmulsf3" [(set (match_operand:SF 0 "fr_register_operand" "=f") (neg:SF (mult:SF (match_operand:SF 1 "fr_register_operand" "f") (match_operand:SF 2 "fr_register_operand" "f"))))] "" "fnmpy.s %0 = %1, %2" [(set_attr "itanium_class" "fmac")]) (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_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_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 1))]) (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")]) (define_insn_and_split "divsf3_internal_thr" [(set (match_operand:SF 0 "fr_register_operand" "=&f") (div:SF (match_operand:SF 1 "fr_register_operand" "f") (match_operand:SF 2 "fr_register_operand" "f"))) (clobber (match_scratch:XF 3 "=&f")) (clobber (match_scratch:XF 4 "=f")) (clobber (match_scratch:BI 5 "=c"))] "TARGET_INLINE_FLOAT_DIV_THR" "#" "&& 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 1))]) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (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 3) (match_dup 3)) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 6) (plus:XF (mult:XF (match_dup 3) (match_dup 6)) (match_dup 6))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 9) (float_truncate:SF (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 7) (mult:XF (match_dup 8) (match_dup 3)))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (set (match_dup 0) (float_truncate:SF (plus:XF (mult:XF (match_dup 4) (match_dup 6)) (match_dup 3))))) ] { 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 (SFmode, REGNO (operands[3])); operands[10] = CONST1_RTX (XFmode); } [(set_attr "predicable" "no")]) ;; Inline square root. (define_insn "*sqrt_approx" [(set (match_operand:XF 0 "fr_register_operand" "=f") (div:XF (const_int 1) (sqrt:XF (match_operand:XF 2 "fr_register_operand" "f")))) (set (match_operand:BI 1 "register_operand" "=c") (unspec:BI [(match_dup 2)] UNSPEC_FR_SQRT_RECIP_APPROX)) (use (match_operand:SI 3 "const_int_operand" "")) ] "" "frsqrta.s%3 %0, %1 = %2" [(set_attr "itanium_class" "fmisc") (set_attr "predicable" "no")]) (define_insn "setf_exp_xf" [(set (match_operand:XF 0 "fr_register_operand" "=f") (unspec:XF [(match_operand:DI 1 "register_operand" "r")] UNSPEC_SETF_EXP))] "" "setf.exp %0 = %1" [(set_attr "itanium_class" "frfr")]) (define_expand "sqrtsf2" [(set (match_operand:SF 0 "fr_register_operand" "=&f") (sqrt:SF (match_operand:SF 1 "fr_register_operand" "f")))] "TARGET_INLINE_SQRT" { rtx insn; if (TARGET_INLINE_SQRT_LAT) #if 0 insn = gen_sqrtsf2_internal_lat (operands[0], operands[1]); #else abort (); #endif else insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]); emit_insn (insn); DONE; }) ;; Latency-optimized square root. ;; FIXME: Implement. ;; Throughput-optimized square root. (define_insn_and_split "sqrtsf2_internal_thr" [(set (match_operand:SF 0 "fr_register_operand" "=&f") (sqrt:SF (match_operand:SF 1 "fr_register_operand" "f"))) ;; Register r2 in optimization guide. (clobber (match_scratch:DI 2 "=r")) ;; Register f8 in optimization guide (clobber (match_scratch:XF 3 "=&f")) ;; Register f9 in optimization guide (clobber (match_scratch:XF 4 "=&f")) ;; Register f10 in optimization guide (clobber (match_scratch:XF 5 "=&f")) ;; Register p6 in optimization guide. (clobber (match_scratch:BI 6 "=c"))] "TARGET_INLINE_SQRT_THR" "#" "&& reload_completed" [ ;; exponent of +1/2 in r2 (set (match_dup 2) (const_int 65534)) ;; +1/2 in f8 (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_SETF_EXP)) ;; Step 1 ;; y0 = 1/sqrt(a) in f7 (parallel [(set (match_dup 7) (div:XF (const_int 1) (sqrt:XF (match_dup 8)))) (set (match_dup 6) (unspec:BI [(match_dup 8)] UNSPEC_FR_SQRT_RECIP_APPROX)) (use (const_int 0))]) ;; Step 2 ;; H0 = 1/2 * y0 in f9 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (plus:XF (mult:XF (match_dup 3) (match_dup 7)) (match_dup 9))) (use (const_int 1))])) ;; Step 3 ;; S0 = a * y0 in f7 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 7) (plus:XF (mult:XF (match_dup 8) (match_dup 7)) (match_dup 9))) (use (const_int 1))])) ;; Step 4 ;; d = 1/2 - S0 * H0 in f10 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 5) (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 "mindf3" [(set (match_operand:DF 0 "fr_register_operand" "=f") (smin:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fmin %0 = %1, %F2" [(set_attr "itanium_class" "fmisc")]) (define_insn "maxdf3" [(set (match_operand:DF 0 "fr_register_operand" "=f") (smax:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))] "" "fmax %0 = %1, %F2" [(set_attr "itanium_class" "fmisc")]) (define_insn "*madddf4" [(set (match_operand:DF 0 "fr_register_operand" "=f") (plus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f")) (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))] "" "fma.d %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*madddf4_trunc" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (plus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f")) (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))] "" "fma.s %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*msubdf4" [(set (match_operand:DF 0 "fr_register_operand" "=f") (minus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f")) (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))] "" "fms.d %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*msubdf4_trunc" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (minus:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f")) (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))] "" "fms.s %0 = %1, %2, %F3" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmuldf3" [(set (match_operand:DF 0 "fr_register_operand" "=f") (neg:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f"))))] "" "fnmpy.d %0 = %1, %2" [(set_attr "itanium_class" "fmac")]) (define_insn "*nmuldf3_trunc" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (neg:DF (mult:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f")))))] "" "fnmpy.s %0 = %1, %2" [(set_attr "itanium_class" "fmac")]) (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_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_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 1))]) (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")]) (define_insn_and_split "divdf3_internal_thr" [(set (match_operand:DF 0 "fr_register_operand" "=&f") (div:DF (match_operand:DF 1 "fr_register_operand" "f") (match_operand:DF 2 "fr_register_operand" "f"))) (clobber (match_scratch:XF 3 "=&f")) (clobber (match_scratch:DF 4 "=f")) (clobber (match_scratch:BI 5 "=c"))] "TARGET_INLINE_FLOAT_DIV_THR" "#" "&& 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 1))]) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (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 6) (plus:XF (mult:XF (match_dup 3) (match_dup 6)) (match_dup 6))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (mult:XF (match_dup 3) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 6) (plus:XF (mult:XF (match_dup 3) (match_dup 6)) (match_dup 6))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 3) (mult:XF (match_dup 3) (match_dup 3))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 6) (plus:XF (mult:XF (match_dup 3) (match_dup 6)) (match_dup 6))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (parallel [(set (match_dup 9) (float_truncate:DF (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:DF (match_dup 1) (mult:DF (match_dup 2) (match_dup 9)))) (use (const_int 1))])) (cond_exec (ne (match_dup 5) (const_int 0)) (set (match_dup 0) (plus:DF (mult:DF (match_dup 4) (match_dup 0)) (match_dup 9)))) ] { 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[3])); operands[10] = CONST1_RTX (XFmode); } [(set_attr "predicable" "no")]) ;; Inline square root. (define_expand "sqrtdf2" [(set (match_operand:DF 0 "fr_register_operand" "=&f") (sqrt:DF (match_operand:DF 1 "fr_register_operand" "f")))] "TARGET_INLINE_SQRT" { rtx insn; if (TARGET_INLINE_SQRT_LAT) #if 0 insn = gen_sqrtdf2_internal_lat (operands[0], operands[1]); #else abort (); #endif else insn = gen_sqrtdf2_internal_thr (operands[0], operands[1]); emit_insn (insn); DONE; }) ;; Latency-optimized square root. ;; FIXME: Implement. ;; Throughput-optimized square root. (define_insn_and_split "sqrtdf2_internal_thr" [(set (match_operand:DF 0 "fr_register_operand" "=&f") (sqrt:DF (match_operand:DF 1 "fr_register_operand" "f"))) ;; Register r2 in optimization guide. (clobber (match_scratch:DI 2 "=r")) ;; Register f8 in optimization guide (clobber (match_scratch:XF 3 "=&f")) ;; Register f9 in optimization guide (clobber (match_scratch:XF 4 "=&f")) ;; Register f10 in optimization guide (clobber (match_scratch:XF 5 "=&f")) ;; Register p6 in optimization guide. (clobber (match_scratch:BI 6 "=c"))] "TARGET_INLINE_SQRT_THR" "#" "&& reload_completed" [ ;; exponent of +1/2 in r2 (set (match_dup 2) (const_int 65534)) ;; +1/2 in f10 (set (match_dup 5) (unspec:XF [(match_dup 2)] UNSPEC_SETF_EXP)) ;; Step 1 ;; y0 = 1/sqrt(a) in f7 (parallel [(set (match_dup 7) (div:XF (const_int 1) (sqrt:XF (match_dup 8)))) (set (match_dup 6) (unspec:BI [(match_dup 8)] UNSPEC_FR_SQRT_RECIP_APPROX)) (use (const_int 0))]) ;; Step 2 ;; H0 = 1/2 * y0 in f8 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 3) (plus:XF (mult:XF (match_dup 5) (match_dup 7)) (match_dup 9))) (use (const_int 1))])) ;; Step 3 ;; G0 = a * y0 in f7 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 7) (plus:XF (mult:XF (match_dup 8) (match_dup 7)) (match_dup 9))) (use (const_int 1))])) ;; Step 4 ;; r0 = 1/2 - G0 * H0 in f9 (cond_exec (ne (match_dup 6) (const_int 0)) (parallel [(set (match_dup 4) (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 "minxf3" [(set (match_operand:XF 0 "fr_register_operand" "=f") (smin:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))] "" "fmin %0 = %F1, %F2" [(set_attr "itanium_class" "fmisc")]) (define_insn "maxxf3" [(set (match_operand:XF 0 "fr_register_operand" "=f") (smax:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG") (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))] "" "fmax %0 = %F1, %F2" [(set_attr "itanium_class" "fmisc")]) (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_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_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 1))]) (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_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 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 (TARGET_INLINE_SQRT_LAT) #if 0 insn = gen_sqrtxf2_internal_lat (operands[0], operands[1]); #else abort (); #endif else insn = gen_sqrtxf2_internal_thr (operands[0], operands[1]); emit_insn (insn); DONE; }) ;; Latency-optimized square root. ;; FIXME: Implement. ;; Throughput-optimized square root. (define_insn_and_split "sqrtxf2_internal_thr" [(set (match_operand:XF 0 "fr_register_operand" "=&f") (sqrt:XF (match_operand:XF 1 "fr_register_operand" "f"))) ;; Register r2 in optimization guide. (clobber (match_scratch:DI 2 "=r")) ;; Register f8 in optimization guide (clobber (match_scratch:XF 3 "=&f")) ;; Register f9 in optimization guide (clobber (match_scratch:XF 4 "=&f")) ;; Register f10 in optimization guide (clobber (match_scratch:XF 5 "=&f")) ;; Register f11 in optimization guide (clobber (match_scratch:XF 6 "=&f")) ;; Register p6 in optimization guide. (clobber (match_scratch:BI 7 "=c"))] "TARGET_INLINE_SQRT_THR" "#" "&& reload_completed" [ ;; exponent of +1/2 in r2 (set (match_dup 2) (const_int 65534)) ;; +1/2 in f8. The Intel manual mistakenly specifies f10. (set (match_dup 3) (unspec:XF [(match_dup 2)] UNSPEC_SETF_EXP)) ;; Step 1 ;; y0 = 1/sqrt(a) in f7 (parallel [(set (match_dup 8) (div:XF (const_int 1) (sqrt:XF (match_dup 9)))) (set (match_dup 7) (unspec:BI [(match_dup 9)] UNSPEC_FR_SQRT_RECIP_APPROX)) (use (const_int 0))]) ;; Step 2 ;; H0 = 1/2 * y0 in f9 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 4) (plus:XF (mult:XF (match_dup 3) (match_dup 8)) (match_dup 10))) (use (const_int 1))])) ;; Step 3 ;; S0 = a * y0 in f7 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 8) (plus:XF (mult:XF (match_dup 9) (match_dup 8)) (match_dup 10))) (use (const_int 1))])) ;; Step 4 ;; d0 = 1/2 - S0 * H0 in f10 (cond_exec (ne (match_dup 7) (const_int 0)) (parallel [(set (match_dup 5) (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")))] "" "#" "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])); operands[2] = GEN_INT (32 - INTVAL (operands[2])); }) ;; :::::::::::::::::::: ;; :: ;; :: 64 bit Integer Shifts and Rotates ;; :: ;; :::::::::::::::::::: (define_insn "ashldi3" [(set (match_operand:DI 0 "gr_register_operand" "=r,r,r") (ashift:DI (match_operand:DI 1 "gr_register_operand" "r,r,r") (match_operand:DI 2 "gr_reg_or_6bit_operand" "R,r,rM")))] "" "@ shladd %0 = %1, %2, r0 shl %0 = %1, %2 shl %0 = %1, %2" [(set_attr "itanium_class" "ialu,mmshf,mmshfi")]) ;; ??? Maybe combine this with the multiply and add instruction? (define_insn "*shladd" [(set (match_operand:DI 0 "gr_register_operand" "=r") (plus:DI (mult:DI (match_operand:DI 1 "gr_register_operand" "r") (match_operand:DI 2 "shladd_operand" "n")) (match_operand:DI 3 "gr_register_operand" "r")))] "" "shladd %0 = %1, %S2, %3" [(set_attr "itanium_class" "ialu")]) ;; This can be created by register elimination if operand3 of shladd is an ;; eliminable register or has reg_equiv_constant set. ;; We have to use nonmemory_operand for operand 4, to ensure that the ;; validate_changes call inside eliminate_regs will always succeed. If it ;; doesn't succeed, then this remain a shladd pattern, and will be reloaded ;; incorrectly. (define_insn_and_split "*shladd_elim" [(set (match_operand:DI 0 "gr_register_operand" "=&r") (plus:DI (plus:DI (mult:DI (match_operand:DI 1 "gr_register_operand" "r") (match_operand:DI 2 "shladd_operand" "n")) (match_operand:DI 3 "nonmemory_operand" "r")) (match_operand:DI 4 "nonmemory_operand" "rI")))] "reload_in_progress" "* abort ();" "reload_completed" [(set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (match_dup 2)) (match_dup 3))) (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))] "" [(set_attr "itanium_class" "unknown")]) (define_insn "ashrdi3" [(set (match_operand:DI 0 "gr_register_operand" "=r,r") (ashiftrt:DI (match_operand:DI 1 "gr_register_operand" "r,r") (match_operand:DI 2 "gr_reg_or_6bit_operand" "r,rM")))] "" "@ shr %0 = %1, %2 shr %0 = %1, %2" [(set_attr "itanium_class" "mmshf,mmshfi")]) (define_insn "lshrdi3" [(set (match_operand:DI 0 "gr_register_operand" "=r,r") (lshiftrt:DI (match_operand:DI 1 "gr_register_operand" "r,r") (match_operand:DI 2 "gr_reg_or_6bit_operand" "r,rM")))] "" "@ shr.u %0 = %1, %2 shr.u %0 = %1, %2" [(set_attr "itanium_class" "mmshf,mmshfi")]) ;; Using a predicate that accepts only constants doesn't work, because optabs ;; will load the operand into a register and call the pattern if the predicate ;; did not accept it on the first try. So we use nonmemory_operand and then ;; verify that we have an appropriate constant in the expander. (define_expand "rotrdi3" [(set (match_operand:DI 0 "gr_register_operand" "") (rotatert:DI (match_operand:DI 1 "gr_register_operand" "") (match_operand:DI 2 "nonmemory_operand" "")))] "" { if (! shift_count_operand (operands[2], DImode)) FAIL; }) (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")]) ;; :::::::::::::::::::: ;; :: ;; :: 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 "immediate_operand" "n")) (const_int 0)))] "" "tbit.z %0, %I0 = %1, %2" [(set_attr "itanium_class" "tbit")]) (define_insn "*bit_one" [(set (match_operand:BI 0 "register_operand" "=c") (ne:BI (zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r") (const_int 1) (match_operand:DI 2 "immediate_operand" "n")) (const_int 0)))] "" "tbit.nz %0, %I0 = %1, %2" [(set_attr "itanium_class" "tbit")]) ;; :::::::::::::::::::: ;; :: ;; :: Branches ;; :: ;; :::::::::::::::::::: (define_expand "beq" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (EQ, VOIDmode);") (define_expand "bne" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (NE, VOIDmode);") (define_expand "blt" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (LT, VOIDmode);") (define_expand "ble" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (LE, VOIDmode);") (define_expand "bgt" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (GT, VOIDmode);") (define_expand "bge" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (GE, VOIDmode);") (define_expand "bltu" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (LTU, VOIDmode);") (define_expand "bleu" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (LEU, VOIDmode);") (define_expand "bgtu" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (GTU, VOIDmode);") (define_expand "bgeu" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (GEU, VOIDmode);") (define_expand "bunordered" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (UNORDERED, VOIDmode);") (define_expand "bordered" [(set (pc) (if_then_else (match_dup 1) (label_ref (match_operand 0 "" "")) (pc)))] "" "operands[1] = ia64_expand_compare (ORDERED, VOIDmode);") (define_insn "*br_true" [(set (pc) (if_then_else (match_operator 0 "predicate_operator" [(match_operand:BI 1 "register_operand" "c") (const_int 0)]) (label_ref (match_operand 2 "" "")) (pc)))] "" "(%J0) br.cond%+ %l2" [(set_attr "itanium_class" "br") (set_attr "predicable" "no")]) (define_insn "*br_false" [(set (pc) (if_then_else (match_operator 0 "predicate_operator" [(match_operand:BI 1 "register_operand" "c") (const_int 0)]) (pc) (label_ref (match_operand 2 "" ""))))] "" "(%j0) br.cond%+ %l2" [(set_attr "itanium_class" "br") (set_attr "predicable" "no")]) ;; :::::::::::::::::::: ;; :: ;; :: Counted loop operations ;; :: ;; :::::::::::::::::::: (define_expand "doloop_end" [(use (match_operand 0 "" "")) ; loop pseudo (use (match_operand 1 "" "")) ; iterations; zero if unknown (use (match_operand 2 "" "")) ; max iterations (use (match_operand 3 "" "")) ; loop level (use (match_operand 4 "" ""))] ; label "" { /* Only use cloop on innermost loops. */ if (INTVAL (operands[3]) > 1) FAIL; emit_jump_insn (gen_doloop_end_internal (gen_rtx_REG (DImode, AR_LC_REGNUM), operands[4])); DONE; }) (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])" { abort (); } [(set_attr "predicable" "no")]) (define_split [(set (match_operand 0 "destination_operand" "") (if_then_else (match_operator 4 "predicate_operator" [(match_operand:BI 1 "register_operand" "") (const_int 0)]) (match_operand 2 "move_operand" "") (match_operand 3 "move_operand" "")))] "reload_completed" [(const_int 0)] { 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])" { abort (); } [(set_attr "predicable" "no")]) (define_insn "*abssi2_internal" [(set (match_operand:SI 0 "gr_register_operand" "=r,r") (if_then_else:SI (match_operator 4 "predicate_operator" [(match_operand:BI 1 "register_operand" "c,c") (const_int 0)]) (neg:SI (match_operand:SI 3 "gr_reg_or_22bit_operand" "rI,rI")) (match_operand:SI 2 "gr_reg_or_22bit_operand" "0,rI")))] "" "#" [(set_attr "itanium_class" "ialu,unknown") (set_attr "predicable" "no")]) (define_split [(set (match_operand:SI 0 "register_operand" "") (if_then_else:SI (match_operator 4 "predicate_operator" [(match_operand:BI 1 "register_operand" "c,c") (const_int 0)]) (neg:SI (match_operand:SI 2 "gr_reg_or_22bit_operand" "")) (match_operand:SI 3 "gr_reg_or_22bit_operand" "")))] "reload_completed && rtx_equal_p (operands[0], operands[3])" [(cond_exec (match_dup 4) (set (match_dup 0) (neg:SI (match_dup 2))))] "") (define_split [(set (match_operand:SI 0 "register_operand" "") (if_then_else:SI (match_operator 4 "predicate_operator" [(match_operand:BI 1 "register_operand" "c,c") (const_int 0)]) (neg:SI (match_operand:SI 2 "gr_reg_or_22bit_operand" "")) (match_operand:SI 3 "gr_reg_or_22bit_operand" "")))] "reload_completed" [(cond_exec (match_dup 4) (set (match_dup 0) (neg:SI (match_dup 2)))) (cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))] { operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? EQ : NE, VOIDmode, operands[1], const0_rtx); }) (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); if (! rtx_equal_p (SET_DEST (set), op0) || GET_CODE (SET_SRC (set)) != MEM) abort (); addr = XEXP (SET_SRC (set), 0); if (rtx_equal_p (addr, op0)) abort (); } /* Jump table elements are stored pc-relative. That is, a displacement from the entry to the label. Thus to convert to an absolute address we add the address of the memory from which the value is loaded. */ operands[0] = expand_simple_binop (DImode, PLUS, op0, addr, NULL_RTX, 1, OPTAB_DIRECT); }) (define_insn "*tablejump_internal" [(set (pc) (match_operand:DI 0 "register_operand" "b")) (use (label_ref (match_operand 1 "" "")))] "" "br %0" [(set_attr "itanium_class" "br")]) ;; :::::::::::::::::::: ;; :: ;; :: Prologue and Epilogue instructions ;; :: ;; :::::::::::::::::::: (define_expand "prologue" [(const_int 1)] "" { ia64_expand_prologue (); DONE; }) (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")]) ;; 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 "memory_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 "memory_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")]) (define_expand "conditional_trap" [(trap_if (match_operand 0 "" "") (match_operand 1 "" ""))] "" { operands[0] = ia64_expand_compare (GET_CODE (operands[0]), VOIDmode); }) (define_insn "*conditional_trap" [(trap_if (match_operator 0 "predicate_operator" [(match_operand:BI 1 "register_operand" "c") (const_int 0)]) (match_operand 2 "const_int_operand" ""))] "" "(%J0) break %2" [(set_attr "itanium_class" "chk_s") (set_attr "predicable" "no")]) (define_insn "break_f" [(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])); if (i != 0 && i != 1) abort (); if (j < 0 || j > 3) abort (); return alt[i][j]; } [(set_attr "itanium_class" "lfetch")]) ;; Non-local goto support. (define_expand "save_stack_nonlocal" [(use (match_operand:OI 0 "memory_operand" "")) (use (match_operand:DI 1 "register_operand" ""))] "" { emit_library_call (gen_rtx_SYMBOL_REF (Pmode, \"__ia64_save_stack_nonlocal\"), 0, VOIDmode, 2, XEXP (operands[0], 0), Pmode, operands[1], Pmode); DONE; }) (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; }) ;;; Intrinsics support. (define_expand "mf" [(set (mem:BLK (match_dup 0)) (unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_MF))] "" { operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode)); MEM_VOLATILE_P (operands[0]) = 1; }) (define_insn "*mf_internal" [(set (match_operand:BLK 0 "" "") (unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_MF))] "" "mf" [(set_attr "itanium_class" "syst_m")]) (define_insn "fetchadd_acq_si" [(set (match_operand:SI 0 "gr_register_operand" "=r") (match_operand:SI 1 "not_postinc_memory_operand" "+S")) (set (match_dup 1) (unspec:SI [(match_dup 1) (match_operand:SI 2 "fetchadd_operand" "n")] UNSPEC_FETCHADD_ACQ))] "" "fetchadd4.acq %0 = %1, %2" [(set_attr "itanium_class" "sem")]) (define_insn "fetchadd_acq_di" [(set (match_operand:DI 0 "gr_register_operand" "=r") (match_operand:DI 1 "not_postinc_memory_operand" "+S")) (set (match_dup 1) (unspec:DI [(match_dup 1) (match_operand:DI 2 "fetchadd_operand" "n")] UNSPEC_FETCHADD_ACQ))] "" "fetchadd8.acq %0 = %1, %2" [(set_attr "itanium_class" "sem")]) (define_insn "cmpxchg_acq_si" [(set (match_operand:SI 0 "gr_register_operand" "=r") (match_operand:SI 1 "not_postinc_memory_operand" "+S")) (set (match_dup 1) (unspec:SI [(match_dup 1) (match_operand:SI 2 "gr_register_operand" "r") (match_operand:DI 3 "ar_ccv_reg_operand" "")] UNSPEC_CMPXCHG_ACQ))] "" "cmpxchg4.acq %0 = %1, %2, %3" [(set_attr "itanium_class" "sem")]) (define_insn "cmpxchg_acq_di" [(set (match_operand:DI 0 "gr_register_operand" "=r") (match_operand:DI 1 "not_postinc_memory_operand" "+S")) (set (match_dup 1) (unspec:DI [(match_dup 1) (match_operand:DI 2 "gr_register_operand" "r") (match_operand:DI 3 "ar_ccv_reg_operand" "")] UNSPEC_CMPXCHG_ACQ))] "" "cmpxchg8.acq %0 = %1, %2, %3" [(set_attr "itanium_class" "sem")]) (define_insn "xchgsi" [(set (match_operand:SI 0 "gr_register_operand" "=r") (match_operand:SI 1 "not_postinc_memory_operand" "+S")) (set (match_dup 1) (match_operand:SI 2 "gr_register_operand" "r"))] "" "xchg4 %0 = %1, %2" [(set_attr "itanium_class" "sem")]) (define_insn "xchgdi" [(set (match_operand:DI 0 "gr_register_operand" "=r") (match_operand:DI 1 "not_postinc_memory_operand" "+S")) (set (match_dup 1) (match_operand:DI 2 "gr_register_operand" "r"))] "" "xchg8 %0 = %1, %2" [(set_attr "itanium_class" "sem")]) ;; Predication. (define_cond_exec [(match_operator 0 "predicate_operator" [(match_operand:BI 1 "register_operand" "c") (const_int 0)])] "" "(%J0)") (define_insn "pred_rel_mutex" [(set (match_operand:BI 0 "register_operand" "+c") (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")])