diff options
Diffstat (limited to 'gcc-4.8/gcc/config/rs6000/rs6000.md')
-rw-r--r-- | gcc-4.8/gcc/config/rs6000/rs6000.md | 4027 |
1 files changed, 2989 insertions, 1038 deletions
diff --git a/gcc-4.8/gcc/config/rs6000/rs6000.md b/gcc-4.8/gcc/config/rs6000/rs6000.md index ade39ea5f..8f1fd769b 100644 --- a/gcc-4.8/gcc/config/rs6000/rs6000.md +++ b/gcc-4.8/gcc/config/rs6000/rs6000.md @@ -25,10 +25,14 @@ ;; (define_constants - [(STACK_POINTER_REGNUM 1) + [(FIRST_GPR_REGNO 0) + (STACK_POINTER_REGNUM 1) (TOC_REGNUM 2) (STATIC_CHAIN_REGNUM 11) (HARD_FRAME_POINTER_REGNUM 31) + (LAST_GPR_REGNO 31) + (FIRST_FPR_REGNO 32) + (LAST_FPR_REGNO 63) (LR_REGNO 65) (CTR_REGNO 66) (ARG_POINTER_REGNUM 67) @@ -49,18 +53,9 @@ (SPE_ACC_REGNO 111) (SPEFSCR_REGNO 112) (FRAME_POINTER_REGNUM 113) - - ; ABI defined stack offsets for storing the TOC pointer with AIX calls. - (TOC_SAVE_OFFSET_32BIT 20) - (TOC_SAVE_OFFSET_64BIT 40) - - ; Function TOC offset in the AIX function descriptor. - (AIX_FUNC_DESC_TOC_32BIT 4) - (AIX_FUNC_DESC_TOC_64BIT 8) - - ; Static chain offset in the AIX function descriptor. - (AIX_FUNC_DESC_SC_32BIT 8) - (AIX_FUNC_DESC_SC_64BIT 16) + (TFHAR_REGNO 114) + (TFIAR_REGNO 115) + (TEXASR_REGNO 116) ]) ;; @@ -123,6 +118,22 @@ UNSPEC_LFIWZX UNSPEC_FCTIWUZ UNSPEC_GRP_END_NOP + UNSPEC_P8V_FMRGOW + UNSPEC_P8V_MTVSRWZ + UNSPEC_P8V_RELOAD_FROM_GPR + UNSPEC_P8V_MTVSRD + UNSPEC_P8V_XXPERMDI + UNSPEC_P8V_RELOAD_FROM_VSX + UNSPEC_ADDG6S + UNSPEC_CDTBCD + UNSPEC_CBCDTD + UNSPEC_DIVE + UNSPEC_DIVEO + UNSPEC_DIVEU + UNSPEC_DIVEUO + UNSPEC_UNPACK_128BIT + UNSPEC_PACK_128BIT + UNSPEC_LSQ ]) ;; @@ -142,7 +153,7 @@ ;; Define an insn type attribute. This is used in function unit delay ;; computations. -(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt" +(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt,crypto,htm" (const_string "integer")) ;; Define floating point instruction sub-types for use with Xfpu.md @@ -164,7 +175,7 @@ ;; Processor type -- this attribute must exactly match the processor_type ;; enumeration in rs6000.h. -(define_attr "cpu" "rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppc8548,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,ppce5500,ppce6500,power4,power5,power6,power7,cell,ppca2,titan" +(define_attr "cpu" "rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppc8548,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,ppce5500,ppce6500,power4,power5,power6,power7,cell,ppca2,titan,power8" (const (symbol_ref "rs6000_cpu_attr"))) @@ -197,6 +208,7 @@ (include "power5.md") (include "power6.md") (include "power7.md") +(include "power8.md") (include "cell.md") (include "xfpu.md") (include "a2.md") @@ -215,7 +227,7 @@ (define_mode_iterator GPR [SI (DI "TARGET_POWERPC64")]) ; Any supported integer mode. -(define_mode_iterator INT [QI HI SI DI TI]) +(define_mode_iterator INT [QI HI SI DI TI PTI]) ; Any supported integer mode that fits in one register. (define_mode_iterator INT1 [QI HI SI (DI "TARGET_POWERPC64")]) @@ -223,6 +235,12 @@ ; extend modes for DImode (define_mode_iterator QHSI [QI HI SI]) +; QImode or HImode for small atomic ops +(define_mode_iterator QHI [QI HI]) + +; HImode or SImode for sign extended fusion ops +(define_mode_iterator HSI [HI SI]) + ; SImode or DImode, even if DImode doesn't fit in GPRs. (define_mode_iterator SDI [SI DI]) @@ -230,6 +248,10 @@ ; (one with a '.') will compare; and the size used for arithmetic carries. (define_mode_iterator P [(SI "TARGET_32BIT") (DI "TARGET_64BIT")]) +; Iterator to add PTImode along with TImode (TImode can go in VSX registers, +; PTImode is GPR only) +(define_mode_iterator TI2 [TI PTI]) + ; Any hardware-supported floating-point mode (define_mode_iterator FP [ (SF "TARGET_HARD_FLOAT @@ -253,6 +275,50 @@ (V2DF "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode)") ]) +; Floating point move iterators to combine binary and decimal moves +(define_mode_iterator FMOVE32 [SF SD]) +(define_mode_iterator FMOVE64 [DF DD]) +(define_mode_iterator FMOVE64X [DI DF DD]) +(define_mode_iterator FMOVE128 [(TF "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128") + (TD "TARGET_HARD_FLOAT && TARGET_FPRS")]) + +; Iterators for 128 bit types for direct move +(define_mode_iterator FMOVE128_GPR [(TI "TARGET_VSX_TIMODE") + (V16QI "") + (V8HI "") + (V4SI "") + (V4SF "") + (V2DI "") + (V2DF "") + (V1TI "")]) + +; Whether a floating point move is ok, don't allow SD without hardware FP +(define_mode_attr fmove_ok [(SF "") + (DF "") + (SD "TARGET_HARD_FLOAT && TARGET_FPRS") + (DD "")]) + +; Convert REAL_VALUE to the appropriate bits +(define_mode_attr real_value_to_target [(SF "REAL_VALUE_TO_TARGET_SINGLE") + (DF "REAL_VALUE_TO_TARGET_DOUBLE") + (SD "REAL_VALUE_TO_TARGET_DECIMAL32") + (DD "REAL_VALUE_TO_TARGET_DECIMAL64")]) + +; Definitions for load to 32-bit fpr register +(define_mode_attr f32_lr [(SF "f") (SD "wz")]) +(define_mode_attr f32_lm [(SF "m") (SD "Z")]) +(define_mode_attr f32_li [(SF "lfs%U1%X1 %0,%1") (SD "lfiwzx %0,%y1")]) +(define_mode_attr f32_lv [(SF "lxsspx %x0,%y1") (SD "lxsiwzx %x0,%y1")]) + +; Definitions for store from 32-bit fpr register +(define_mode_attr f32_sr [(SF "f") (SD "wx")]) +(define_mode_attr f32_sm [(SF "m") (SD "Z")]) +(define_mode_attr f32_si [(SF "stfs%U0%X0 %1,%0") (SD "stfiwx %1,%y0")]) +(define_mode_attr f32_sv [(SF "stxsspx %x1,%y0") (SD "stxsiwzx %x1,%y0")]) + +; Definitions for 32-bit fpr direct move +(define_mode_attr f32_dm [(SF "wn") (SD "wm")]) + ; These modes do not fit in integer registers in 32-bit mode. ; but on e500v2, the gpr are 64 bit registers (define_mode_iterator DIFD [DI (DF "!TARGET_E500_DOUBLE") DD]) @@ -263,6 +329,25 @@ ; Iterator for just SF/DF (define_mode_iterator SFDF [SF DF]) +; SF/DF suffix for traditional floating instructions +(define_mode_attr Ftrad [(SF "s") (DF "")]) + +; SF/DF suffix for VSX instructions +(define_mode_attr Fvsx [(SF "sp") (DF "dp")]) + +; SF/DF constraint for arithmetic on traditional floating point registers +(define_mode_attr Ff [(SF "f") (DF "d")]) + +; SF/DF constraint for arithmetic on VSX registers +(define_mode_attr Fv [(SF "wy") (DF "ws")]) + +; s/d suffix for things like fp_addsub_s/fp_addsub_d +(define_mode_attr Fs [(SF "s") (DF "d")]) + +; FRE/FRES support +(define_mode_attr Ffre [(SF "fres") (DF "fre")]) +(define_mode_attr FFRE [(SF "FRES") (DF "FRE")]) + ; Conditional returns. (define_code_iterator any_return [return simple_return]) (define_code_attr return_pred [(return "direct_return ()") @@ -271,7 +356,14 @@ ; Various instructions that come in SI and DI forms. ; A generic w/d attribute, for things like cmpw/cmpd. -(define_mode_attr wd [(QI "b") (HI "h") (SI "w") (DI "d")]) +(define_mode_attr wd [(QI "b") + (HI "h") + (SI "w") + (DI "d") + (V16QI "b") + (V8HI "h") + (V4SI "w") + (V2DI "d")]) ; DImode bits (define_mode_attr dbits [(QI "56") (HI "48") (SI "32")]) @@ -297,6 +389,8 @@ (define_mode_attr rreg [(SF "f") (DF "ws") + (TF "f") + (TD "f") (V4SF "wf") (V2DF "wd")]) @@ -312,6 +406,87 @@ (define_mode_attr TARGET_FLOAT [(SF "TARGET_SINGLE_FLOAT") (DF "TARGET_DOUBLE_FLOAT")]) +;; Mode iterator for logical operations on 128-bit types +(define_mode_iterator BOOL_128 [TI + PTI + (V16QI "TARGET_ALTIVEC") + (V8HI "TARGET_ALTIVEC") + (V4SI "TARGET_ALTIVEC") + (V4SF "TARGET_ALTIVEC") + (V2DI "TARGET_ALTIVEC") + (V2DF "TARGET_ALTIVEC") + (V1TI "TARGET_ALTIVEC")]) + +;; For the GPRs we use 3 constraints for register outputs, two that are the +;; same as the output register, and a third where the output register is an +;; early clobber, so we don't have to deal with register overlaps. For the +;; vector types, we prefer to use the vector registers. For TI mode, allow +;; either. + +;; Mode attribute for boolean operation register constraints for output +(define_mode_attr BOOL_REGS_OUTPUT [(TI "&r,r,r,wa,v") + (PTI "&r,r,r") + (V16QI "wa,v,&?r,?r,?r") + (V8HI "wa,v,&?r,?r,?r") + (V4SI "wa,v,&?r,?r,?r") + (V4SF "wa,v,&?r,?r,?r") + (V2DI "wa,v,&?r,?r,?r") + (V2DF "wa,v,&?r,?r,?r") + (V1TI "wa,v,&?r,?r,?r")]) + +;; Mode attribute for boolean operation register constraints for operand1 +(define_mode_attr BOOL_REGS_OP1 [(TI "r,0,r,wa,v") + (PTI "r,0,r") + (V16QI "wa,v,r,0,r") + (V8HI "wa,v,r,0,r") + (V4SI "wa,v,r,0,r") + (V4SF "wa,v,r,0,r") + (V2DI "wa,v,r,0,r") + (V2DF "wa,v,r,0,r") + (V1TI "wa,v,r,0,r")]) + +;; Mode attribute for boolean operation register constraints for operand2 +(define_mode_attr BOOL_REGS_OP2 [(TI "r,r,0,wa,v") + (PTI "r,r,0") + (V16QI "wa,v,r,r,0") + (V8HI "wa,v,r,r,0") + (V4SI "wa,v,r,r,0") + (V4SF "wa,v,r,r,0") + (V2DI "wa,v,r,r,0") + (V2DF "wa,v,r,r,0") + (V1TI "wa,v,r,r,0")]) + +;; Mode attribute for boolean operation register constraints for operand1 +;; for one_cmpl. To simplify things, we repeat the constraint where 0 +;; is used for operand1 or operand2 +(define_mode_attr BOOL_REGS_UNARY [(TI "r,0,0,wa,v") + (PTI "r,0,0") + (V16QI "wa,v,r,0,0") + (V8HI "wa,v,r,0,0") + (V4SI "wa,v,r,0,0") + (V4SF "wa,v,r,0,0") + (V2DI "wa,v,r,0,0") + (V2DF "wa,v,r,0,0") + (V1TI "wa,v,r,0,0")]) + +;; Mode attribute for the clobber of CC0 for AND expansion. +;; For the 128-bit types, we never do AND immediate, but we need to +;; get the correct number of X's for the number of operands. +(define_mode_attr BOOL_REGS_AND_CR0 [(TI "X,X,X,X,X") + (PTI "X,X,X") + (V16QI "X,X,X,X,X") + (V8HI "X,X,X,X,X") + (V4SI "X,X,X,X,X") + (V4SF "X,X,X,X,X") + (V2DI "X,X,X,X,X") + (V2DF "X,X,X,X,X") + (V1TI "X,X,X,X,X")]) + +;; Mode attribute to give the correct type for integer divides +(define_mode_attr idiv_ldiv [(SI "idiv") + (DI "ldiv")]) + + ;; Start with fixed-point load and store insns. Here we put only the more ;; complex forms. Basic data transfer is done later. @@ -324,11 +499,19 @@ (define_insn "*zero_extend<mode>di2_internal1" [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r") (zero_extend:DI (match_operand:QHSI 1 "reg_or_mem_operand" "m,r")))] - "TARGET_POWERPC64" + "TARGET_POWERPC64 && (<MODE>mode != SImode || !TARGET_LFIWZX)" "@ l<wd>z%U1%X1 %0,%1 rldicl %0,%1,0,<dbits>" - [(set_attr "type" "load,*")]) + [(set_attr_alternative "type" + [(if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (const_string "*")])]) (define_insn "*zero_extend<mode>di2_internal2" [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y") @@ -382,6 +565,29 @@ (const_int 0)))] "") +(define_insn "*zero_extendsidi2_lfiwzx" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wz,!wu") + (zero_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "m,r,r,Z,Z")))] + "TARGET_POWERPC64 && TARGET_LFIWZX" + "@ + lwz%U1%X1 %0,%1 + rldicl %0,%1,0,32 + mtvsrwz %x0,%1 + lfiwzx %0,%y1 + lxsiwzx %x0,%y1" + [(set_attr_alternative "type" + [(if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (const_string "*") + (const_string "mffgpr") + (const_string "fpload") + (const_string "fpload")])]) + (define_insn "extendqidi2" [(set (match_operand:DI 0 "gpc_reg_operand" "=r") (sign_extend:DI (match_operand:QI 1 "gpc_reg_operand" "r")))] @@ -454,7 +660,15 @@ "@ lha%U1%X1 %0,%1 extsh %0,%1" - [(set_attr "type" "load_ext,exts")]) + [(set_attr_alternative "type" + [(if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ext_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_ext_u") + (const_string "load_ext"))) + (const_string "exts")])]) (define_insn "" [(set (match_operand:DI 0 "gpc_reg_operand" "=r") @@ -521,16 +735,47 @@ "TARGET_POWERPC64" "") -(define_insn "" +(define_insn "*extendsidi2_lfiwax" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wl,!wu") + (sign_extend:DI (match_operand:SI 1 "lwa_operand" "m,r,r,Z,Z")))] + "TARGET_POWERPC64 && TARGET_LFIWAX" + "@ + lwa%U1%X1 %0,%1 + extsw %0,%1 + mtvsrwa %x0,%1 + lfiwax %0,%y1 + lxsiwax %x0,%y1" + [(set_attr_alternative "type" + [(if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ext_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_ext_u") + (const_string "load_ext"))) + (const_string "exts") + (const_string "mffgpr") + (const_string "fpload") + (const_string "fpload")])]) + +(define_insn "*extendsidi2_nocell" [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r") (sign_extend:DI (match_operand:SI 1 "lwa_operand" "m,r")))] - "TARGET_POWERPC64 && rs6000_gen_cell_microcode" + "TARGET_POWERPC64 && rs6000_gen_cell_microcode && !TARGET_LFIWAX" "@ lwa%U1%X1 %0,%1 extsw %0,%1" - [(set_attr "type" "load_ext,exts")]) - -(define_insn "" + [(set_attr_alternative "type" + [(if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ext_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_ext_u") + (const_string "load_ext"))) + (const_string "exts")])]) + +(define_insn "*extendsidi2_nocell" [(set (match_operand:DI 0 "gpc_reg_operand" "=r") (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r")))] "TARGET_POWERPC64 && !rs6000_gen_cell_microcode" @@ -602,7 +847,15 @@ "@ lbz%U1%X1 %0,%1 rlwinm %0,%1,0,0xff" - [(set_attr "type" "load,*")]) + [(set_attr_alternative "type" + [(if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (const_string "*")])]) (define_insn "" [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y") @@ -722,7 +975,15 @@ "@ lbz%U1%X1 %0,%1 rlwinm %0,%1,0,0xff" - [(set_attr "type" "load,*")]) + [(set_attr_alternative "type" + [(if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (const_string "*")])]) (define_insn "" [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y") @@ -848,7 +1109,15 @@ "@ lhz%U1%X1 %0,%1 rlwinm %0,%1,0,0xffff" - [(set_attr "type" "load,*")]) + [(set_attr_alternative "type" + [(if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (const_string "*")])]) (define_insn "" [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y") @@ -915,7 +1184,15 @@ "@ lha%U1%X1 %0,%1 extsh %0,%1" - [(set_attr "type" "load_ext,exts")]) + [(set_attr_alternative "type" + [(if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ext_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_ext_u") + (const_string "load_ext"))) + (const_string "exts")])]) (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") @@ -1658,7 +1935,19 @@ FAIL; }) -(define_insn "one_cmpl<mode>2" +(define_expand "one_cmpl<mode>2" + [(set (match_operand:SDI 0 "gpc_reg_operand" "") + (not:SDI (match_operand:SDI 1 "gpc_reg_operand" "")))] + "" +{ + if (<MODE>mode == DImode && !TARGET_POWERPC64) + { + rs6000_split_logical (operands, NOT, false, false, false, NULL_RTX); + DONE; + } +}) + +(define_insn "*one_cmpl<mode>2" [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))] "" @@ -1935,7 +2224,9 @@ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") (unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")] UNSPEC_PARITY))] "TARGET_CMPB && TARGET_POPCNTB" - "prty<wd> %0,%1") + "prty<wd> %0,%1" + [(set_attr "length" "4") + (set_attr "type" "popcnt")]) (define_expand "parity<mode>2" [(set (match_operand:GPR 0 "gpc_reg_operand" "") @@ -2412,7 +2703,7 @@ (match_operand:SI 2 "gpc_reg_operand" "r,r")) (const_int 0))) (clobber (match_scratch:SI 3 "=r,r"))] - "" + "TARGET_32BIT" "@ mullw. %3,%1,%2 #" @@ -2425,7 +2716,7 @@ (match_operand:SI 2 "gpc_reg_operand" "")) (const_int 0))) (clobber (match_scratch:SI 3 ""))] - "reload_completed" + "TARGET_32BIT && reload_completed" [(set (match_dup 3) (mult:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) @@ -2440,7 +2731,7 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r,r") (mult:SI (match_dup 1) (match_dup 2)))] - "" + "TARGET_32BIT" "@ mullw. %0,%1,%2 #" @@ -2454,7 +2745,7 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "") (mult:SI (match_dup 1) (match_dup 2)))] - "reload_completed" + "TARGET_32BIT && reload_completed" [(set (match_dup 0) (mult:SI (match_dup 1) (match_dup 2))) (set (match_dup 3) @@ -2469,10 +2760,7 @@ (match_operand:GPR 2 "gpc_reg_operand" "r")))] "" "div<wd>u %0,%1,%2" - [(set (attr "type") - (cond [(match_operand:SI 0 "" "") - (const_string "idiv")] - (const_string "ldiv")))]) + [(set_attr "type" "<idiv_ldiv>")]) ;; For powers of two we can do srai/aze for divide and then adjust for @@ -2496,10 +2784,7 @@ (match_operand:GPR 2 "gpc_reg_operand" "r")))] "" "div<wd> %0,%1,%2" - [(set (attr "type") - (cond [(match_operand:SI 0 "" "") - (const_string "idiv")] - (const_string "ldiv")))]) + [(set_attr "type" "<idiv_ldiv>")]) (define_expand "mod<mode>3" [(use (match_operand:GPR 0 "gpc_reg_operand" "")) @@ -3698,20 +3983,33 @@ (const_int 0)))] "") -(define_insn "*rotlsi3_internal7" +(define_insn "*rotlsi3_internal7le" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (zero_extend:SI (subreg:QI (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r") (match_operand:SI 2 "reg_or_cint_operand" "ri")) 0)))] - "" + "!BYTES_BIG_ENDIAN" "rlw%I2nm %0,%1,%h2,0xff" [(set (attr "cell_micro") (if_then_else (match_operand:SI 2 "const_int_operand" "") (const_string "not") (const_string "always")))]) -(define_insn "*rotlsi3_internal8" +(define_insn "*rotlsi3_internal7be" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r") + (zero_extend:SI + (subreg:QI + (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r") + (match_operand:SI 2 "reg_or_cint_operand" "ri")) 3)))] + "BYTES_BIG_ENDIAN" + "rlw%I2nm %0,%1,%h2,0xff" + [(set (attr "cell_micro") + (if_then_else (match_operand:SI 2 "const_int_operand" "") + (const_string "not") + (const_string "always")))]) + +(define_insn "*rotlsi3_internal8le" [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y") (compare:CC (zero_extend:SI (subreg:QI @@ -3719,7 +4017,24 @@ (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) 0)) (const_int 0))) (clobber (match_scratch:SI 3 "=r,r,r,r"))] - "" + "!BYTES_BIG_ENDIAN" + "@ + rlwnm. %3,%1,%2,0xff + rlwinm. %3,%1,%h2,0xff + # + #" + [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") + (set_attr "length" "4,4,8,8")]) + +(define_insn "*rotlsi3_internal8be" + [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y") + (compare:CC (zero_extend:SI + (subreg:QI + (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r") + (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) 3)) + (const_int 0))) + (clobber (match_scratch:SI 3 "=r,r,r,r"))] + "BYTES_BIG_ENDIAN" "@ rlwnm. %3,%1,%2,0xff rlwinm. %3,%1,%h2,0xff @@ -3736,7 +4051,7 @@ (match_operand:SI 2 "reg_or_cint_operand" "")) 0)) (const_int 0))) (clobber (match_scratch:SI 3 ""))] - "reload_completed" + "!BYTES_BIG_ENDIAN && reload_completed" [(set (match_dup 3) (zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) @@ -3746,7 +4061,25 @@ (const_int 0)))] "") -(define_insn "*rotlsi3_internal9" +(define_split + [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "") + (compare:CC (zero_extend:SI + (subreg:QI + (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "reg_or_cint_operand" "")) 3)) + (const_int 0))) + (clobber (match_scratch:SI 3 ""))] + "BYTES_BIG_ENDIAN && reload_completed" + [(set (match_dup 3) + (zero_extend:SI (subreg:QI + (rotate:SI (match_dup 1) + (match_dup 2)) 3))) + (set (match_dup 0) + (compare:CC (match_dup 3) + (const_int 0)))] + "") + +(define_insn "*rotlsi3_internal9le" [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") (compare:CC (zero_extend:SI (subreg:QI @@ -3755,7 +4088,25 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r") (zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 0)))] - "" + "!BYTES_BIG_ENDIAN" + "@ + rlwnm. %0,%1,%2,0xff + rlwinm. %0,%1,%h2,0xff + # + #" + [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") + (set_attr "length" "4,4,8,8")]) + +(define_insn "*rotlsi3_internal9be" + [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") + (compare:CC (zero_extend:SI + (subreg:QI + (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r") + (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) 3)) + (const_int 0))) + (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r") + (zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 3)))] + "BYTES_BIG_ENDIAN" "@ rlwnm. %0,%1,%2,0xff rlwinm. %0,%1,%h2,0xff @@ -3773,7 +4124,7 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "") (zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 0)))] - "reload_completed" + "!BYTES_BIG_ENDIAN && reload_completed" [(set (match_dup 0) (zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 0))) (set (match_dup 3) @@ -3781,20 +4132,48 @@ (const_int 0)))] "") -(define_insn "*rotlsi3_internal10" +(define_split + [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "") + (compare:CC (zero_extend:SI + (subreg:QI + (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "reg_or_cint_operand" "")) 3)) + (const_int 0))) + (set (match_operand:SI 0 "gpc_reg_operand" "") + (zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 3)))] + "BYTES_BIG_ENDIAN && reload_completed" + [(set (match_dup 0) + (zero_extend:SI (subreg:QI (rotate:SI (match_dup 1) (match_dup 2)) 3))) + (set (match_dup 3) + (compare:CC (match_dup 0) + (const_int 0)))] + "") + +(define_insn "*rotlsi3_internal10le" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") (zero_extend:SI (subreg:HI (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r") (match_operand:SI 2 "reg_or_cint_operand" "r,i")) 0)))] - "" + "!BYTES_BIG_ENDIAN" "@ rlwnm %0,%1,%2,0xffff rlwinm %0,%1,%h2,0xffff" [(set_attr "type" "var_shift_rotate,integer")]) +(define_insn "*rotlsi3_internal10be" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") + (zero_extend:SI + (subreg:HI + (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r") + (match_operand:SI 2 "reg_or_cint_operand" "r,i")) 2)))] + "BYTES_BIG_ENDIAN" + "@ + rlwnm %0,%1,%2,0xffff + rlwinm %0,%1,%h2,0xffff" + [(set_attr "type" "var_shift_rotate,integer")]) -(define_insn "*rotlsi3_internal11" +(define_insn "*rotlsi3_internal11le" [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y") (compare:CC (zero_extend:SI (subreg:HI @@ -3802,7 +4181,24 @@ (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) 0)) (const_int 0))) (clobber (match_scratch:SI 3 "=r,r,r,r"))] - "" + "!BYTES_BIG_ENDIAN" + "@ + rlwnm. %3,%1,%2,0xffff + rlwinm. %3,%1,%h2,0xffff + # + #" + [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") + (set_attr "length" "4,4,8,8")]) + +(define_insn "*rotlsi3_internal11be" + [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y") + (compare:CC (zero_extend:SI + (subreg:HI + (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r") + (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) 2)) + (const_int 0))) + (clobber (match_scratch:SI 3 "=r,r,r,r"))] + "BYTES_BIG_ENDIAN" "@ rlwnm. %3,%1,%2,0xffff rlwinm. %3,%1,%h2,0xffff @@ -3819,7 +4215,7 @@ (match_operand:SI 2 "reg_or_cint_operand" "")) 0)) (const_int 0))) (clobber (match_scratch:SI 3 ""))] - "reload_completed" + "!BYTES_BIG_ENDIAN && reload_completed" [(set (match_dup 3) (zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) @@ -3829,7 +4225,25 @@ (const_int 0)))] "") -(define_insn "*rotlsi3_internal12" +(define_split + [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "") + (compare:CC (zero_extend:SI + (subreg:HI + (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "reg_or_cint_operand" "")) 2)) + (const_int 0))) + (clobber (match_scratch:SI 3 ""))] + "BYTES_BIG_ENDIAN && reload_completed" + [(set (match_dup 3) + (zero_extend:SI (subreg:HI + (rotate:SI (match_dup 1) + (match_dup 2)) 2))) + (set (match_dup 0) + (compare:CC (match_dup 3) + (const_int 0)))] + "") + +(define_insn "*rotlsi3_internal12le" [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") (compare:CC (zero_extend:SI (subreg:HI @@ -3838,7 +4252,25 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r") (zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 0)))] - "" + "!BYTES_BIG_ENDIAN" + "@ + rlwnm. %0,%1,%2,0xffff + rlwinm. %0,%1,%h2,0xffff + # + #" + [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") + (set_attr "length" "4,4,8,8")]) + +(define_insn "*rotlsi3_internal12be" + [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") + (compare:CC (zero_extend:SI + (subreg:HI + (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r") + (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) 2)) + (const_int 0))) + (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r") + (zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 2)))] + "BYTES_BIG_ENDIAN" "@ rlwnm. %0,%1,%2,0xffff rlwinm. %0,%1,%h2,0xffff @@ -3856,7 +4288,7 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "") (zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 0)))] - "reload_completed" + "!BYTES_BIG_ENDIAN && reload_completed" [(set (match_dup 0) (zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 0))) (set (match_dup 3) @@ -3864,6 +4296,23 @@ (const_int 0)))] "") +(define_split + [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "") + (compare:CC (zero_extend:SI + (subreg:HI + (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "reg_or_cint_operand" "")) 2)) + (const_int 0))) + (set (match_operand:SI 0 "gpc_reg_operand" "") + (zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 2)))] + "BYTES_BIG_ENDIAN && reload_completed" + [(set (match_dup 0) + (zero_extend:SI (subreg:HI (rotate:SI (match_dup 1) (match_dup 2)) 2))) + (set (match_dup 3) + (compare:CC (match_dup 0) + (const_int 0)))] + "") + (define_insn "ashlsi3" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r,r") @@ -4054,7 +4503,7 @@ # # #" - [(set_attr "type" "delayed_compare,var_delayed_compare,delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") + [(set_attr "type" "fast_compare,var_delayed_compare,delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") (set_attr "length" "4,4,4,8,8,8")]) (define_split @@ -4086,7 +4535,7 @@ # # #" - [(set_attr "type" "delayed_compare,var_delayed_compare,delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") + [(set_attr "type" "fast_compare,var_delayed_compare,delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") (set_attr "length" "4,4,4,8,8,8")]) (define_split @@ -4177,16 +4626,25 @@ (const_int 0)))] "") -(define_insn "" +(define_insn "*lshiftrt_internal1le" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (zero_extend:SI (subreg:QI (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r") (match_operand:SI 2 "const_int_operand" "i")) 0)))] - "includes_rshift_p (operands[2], GEN_INT (255))" + "!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255))" "rlwinm %0,%1,%s2,0xff") -(define_insn "" +(define_insn "*lshiftrt_internal1be" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r") + (zero_extend:SI + (subreg:QI + (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r") + (match_operand:SI 2 "const_int_operand" "i")) 3)))] + "BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255))" + "rlwinm %0,%1,%s2,0xff") + +(define_insn "*lshiftrt_internal2le" [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y") (compare:CC (zero_extend:SI @@ -4195,7 +4653,23 @@ (match_operand:SI 2 "const_int_operand" "i,i")) 0)) (const_int 0))) (clobber (match_scratch:SI 3 "=r,r"))] - "includes_rshift_p (operands[2], GEN_INT (255))" + "!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255))" + "@ + rlwinm. %3,%1,%s2,0xff + #" + [(set_attr "type" "delayed_compare") + (set_attr "length" "4,8")]) + +(define_insn "*lshiftrt_internal2be" + [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y") + (compare:CC + (zero_extend:SI + (subreg:QI + (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r") + (match_operand:SI 2 "const_int_operand" "i,i")) 3)) + (const_int 0))) + (clobber (match_scratch:SI 3 "=r,r"))] + "BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255))" "@ rlwinm. %3,%1,%s2,0xff #" @@ -4211,7 +4685,7 @@ (match_operand:SI 2 "const_int_operand" "")) 0)) (const_int 0))) (clobber (match_scratch:SI 3 ""))] - "includes_rshift_p (operands[2], GEN_INT (255)) && reload_completed" + "!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255)) && reload_completed" [(set (match_dup 3) (zero_extend:SI (subreg:QI (lshiftrt:SI (match_dup 1) @@ -4221,7 +4695,26 @@ (const_int 0)))] "") -(define_insn "" +(define_split + [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "") + (compare:CC + (zero_extend:SI + (subreg:QI + (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "const_int_operand" "")) 3)) + (const_int 0))) + (clobber (match_scratch:SI 3 ""))] + "BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255)) && reload_completed" + [(set (match_dup 3) + (zero_extend:SI (subreg:QI + (lshiftrt:SI (match_dup 1) + (match_dup 2)) 3))) + (set (match_dup 0) + (compare:CC (match_dup 3) + (const_int 0)))] + "") + +(define_insn "*lshiftrt_internal3le" [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y") (compare:CC (zero_extend:SI @@ -4231,7 +4724,24 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r,r") (zero_extend:SI (subreg:QI (lshiftrt:SI (match_dup 1) (match_dup 2)) 0)))] - "includes_rshift_p (operands[2], GEN_INT (255))" + "!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255))" + "@ + rlwinm. %0,%1,%s2,0xff + #" + [(set_attr "type" "delayed_compare") + (set_attr "length" "4,8")]) + +(define_insn "*lshiftrt_internal3be" + [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y") + (compare:CC + (zero_extend:SI + (subreg:QI + (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r") + (match_operand:SI 2 "const_int_operand" "i,i")) 3)) + (const_int 0))) + (set (match_operand:SI 0 "gpc_reg_operand" "=r,r") + (zero_extend:SI (subreg:QI (lshiftrt:SI (match_dup 1) (match_dup 2)) 3)))] + "BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255))" "@ rlwinm. %0,%1,%s2,0xff #" @@ -4248,7 +4758,7 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "") (zero_extend:SI (subreg:QI (lshiftrt:SI (match_dup 1) (match_dup 2)) 0)))] - "includes_rshift_p (operands[2], GEN_INT (255)) && reload_completed" + "!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255)) && reload_completed" [(set (match_dup 0) (zero_extend:SI (subreg:QI (lshiftrt:SI (match_dup 1) (match_dup 2)) 0))) (set (match_dup 3) @@ -4256,16 +4766,43 @@ (const_int 0)))] "") -(define_insn "" +(define_split + [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "") + (compare:CC + (zero_extend:SI + (subreg:QI + (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "const_int_operand" "")) 3)) + (const_int 0))) + (set (match_operand:SI 0 "gpc_reg_operand" "") + (zero_extend:SI (subreg:QI (lshiftrt:SI (match_dup 1) (match_dup 2)) 3)))] + "BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255)) && reload_completed" + [(set (match_dup 0) + (zero_extend:SI (subreg:QI (lshiftrt:SI (match_dup 1) (match_dup 2)) 3))) + (set (match_dup 3) + (compare:CC (match_dup 0) + (const_int 0)))] + "") + +(define_insn "*lshiftrt_internal4le" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (zero_extend:SI (subreg:HI (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r") (match_operand:SI 2 "const_int_operand" "i")) 0)))] - "includes_rshift_p (operands[2], GEN_INT (65535))" + "!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535))" "rlwinm %0,%1,%s2,0xffff") -(define_insn "" +(define_insn "*lshiftrt_internal4be" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r") + (zero_extend:SI + (subreg:HI + (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r") + (match_operand:SI 2 "const_int_operand" "i")) 2)))] + "BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535))" + "rlwinm %0,%1,%s2,0xffff") + +(define_insn "*lshiftrt_internal5le" [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y") (compare:CC (zero_extend:SI @@ -4274,7 +4811,23 @@ (match_operand:SI 2 "const_int_operand" "i,i")) 0)) (const_int 0))) (clobber (match_scratch:SI 3 "=r,r"))] - "includes_rshift_p (operands[2], GEN_INT (65535))" + "!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535))" + "@ + rlwinm. %3,%1,%s2,0xffff + #" + [(set_attr "type" "delayed_compare") + (set_attr "length" "4,8")]) + +(define_insn "*lshiftrt_internal5be" + [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y") + (compare:CC + (zero_extend:SI + (subreg:HI + (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r") + (match_operand:SI 2 "const_int_operand" "i,i")) 2)) + (const_int 0))) + (clobber (match_scratch:SI 3 "=r,r"))] + "BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535))" "@ rlwinm. %3,%1,%s2,0xffff #" @@ -4290,7 +4843,7 @@ (match_operand:SI 2 "const_int_operand" "")) 0)) (const_int 0))) (clobber (match_scratch:SI 3 ""))] - "includes_rshift_p (operands[2], GEN_INT (65535)) && reload_completed" + "!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535)) && reload_completed" [(set (match_dup 3) (zero_extend:SI (subreg:HI (lshiftrt:SI (match_dup 1) @@ -4300,7 +4853,26 @@ (const_int 0)))] "") -(define_insn "" +(define_split + [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "") + (compare:CC + (zero_extend:SI + (subreg:HI + (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "const_int_operand" "")) 2)) + (const_int 0))) + (clobber (match_scratch:SI 3 ""))] + "BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535)) && reload_completed" + [(set (match_dup 3) + (zero_extend:SI (subreg:HI + (lshiftrt:SI (match_dup 1) + (match_dup 2)) 2))) + (set (match_dup 0) + (compare:CC (match_dup 3) + (const_int 0)))] + "") + +(define_insn "*lshiftrt_internal5le" [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y") (compare:CC (zero_extend:SI @@ -4310,7 +4882,24 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r,r") (zero_extend:SI (subreg:HI (lshiftrt:SI (match_dup 1) (match_dup 2)) 0)))] - "includes_rshift_p (operands[2], GEN_INT (65535))" + "!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535))" + "@ + rlwinm. %0,%1,%s2,0xffff + #" + [(set_attr "type" "delayed_compare") + (set_attr "length" "4,8")]) + +(define_insn "*lshiftrt_internal5be" + [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y") + (compare:CC + (zero_extend:SI + (subreg:HI + (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r") + (match_operand:SI 2 "const_int_operand" "i,i")) 2)) + (const_int 0))) + (set (match_operand:SI 0 "gpc_reg_operand" "=r,r") + (zero_extend:SI (subreg:HI (lshiftrt:SI (match_dup 1) (match_dup 2)) 2)))] + "BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535))" "@ rlwinm. %0,%1,%s2,0xffff #" @@ -4327,7 +4916,7 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "") (zero_extend:SI (subreg:HI (lshiftrt:SI (match_dup 1) (match_dup 2)) 0)))] - "includes_rshift_p (operands[2], GEN_INT (65535)) && reload_completed" + "!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535)) && reload_completed" [(set (match_dup 0) (zero_extend:SI (subreg:HI (lshiftrt:SI (match_dup 1) (match_dup 2)) 0))) (set (match_dup 3) @@ -4335,6 +4924,24 @@ (const_int 0)))] "") +(define_split + [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "") + (compare:CC + (zero_extend:SI + (subreg:HI + (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "const_int_operand" "")) 2)) + (const_int 0))) + (set (match_operand:SI 0 "gpc_reg_operand" "") + (zero_extend:SI (subreg:HI (lshiftrt:SI (match_dup 1) (match_dup 2)) 2)))] + "BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535)) && reload_completed" + [(set (match_dup 0) + (zero_extend:SI (subreg:HI (lshiftrt:SI (match_dup 1) (match_dup 2)) 2))) + (set (match_dup 3) + (compare:CC (match_dup 0) + (const_int 0)))] + "") + (define_insn "ashrsi3" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r") @@ -4455,224 +5062,226 @@ (const_int 0)))] "") -;; Floating-point insns, excluding normal data motion. -;; -;; PowerPC has a full set of single-precision floating point instructions. -;; -;; For the POWER architecture, we pretend that we have both SFmode and -;; DFmode insns, while, in fact, all fp insns are actually done in double. -;; The only conversions we will do will be when storing to memory. In that -;; case, we will use the "frsp" instruction before storing. -;; -;; Note that when we store into a single-precision memory location, we need to -;; use the frsp insn first. If the register being stored isn't dead, we -;; need a scratch register for the frsp. But this is difficult when the store -;; is done by reload. It is not incorrect to do the frsp on the register in -;; this case, we just lose precision that we would have otherwise gotten but -;; is not guaranteed. Perhaps this should be tightened up at some point. - -(define_expand "extendsfdf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (float_extend:DF (match_operand:SF 1 "reg_or_none500mem_operand" "")))] - "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)" - "") - -(define_insn_and_split "*extendsfdf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d") - (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" - "@ - # - fmr %0,%1 - lfs%U1%X1 %0,%1" - "&& reload_completed && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])" - [(const_int 0)] -{ - emit_note (NOTE_INSN_DELETED); - DONE; -} - [(set_attr "type" "fp,fp,fpload")]) - -(define_expand "truncdfsf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)" - "") - -(define_insn "*truncdfsf2_fpr" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "d")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" - "frsp %0,%1" - [(set_attr "type" "fp")]) - -(define_expand "negsf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (neg:SF (match_operand:SF 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT" - "") -(define_insn "*negsf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" - "fneg %0,%1" - [(set_attr "type" "fp")]) +;; Floating-point insns, excluding normal data motion. We combine the SF/DF +;; modes here, and also add in conditional vsx/power8-vector support to access +;; values in the traditional Altivec registers if the appropriate +;; -mupper-regs-{df,sf} option is enabled. -(define_expand "abssf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (abs:SF (match_operand:SF 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT" +(define_expand "abs<mode>2" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "") + (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))] + "TARGET_<MODE>_INSN" "") -(define_insn "*abssf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (abs:SF (match_operand:SF 1 "gpc_reg_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" - "fabs %0,%1" - [(set_attr "type" "fp")]) +(define_insn "*abs<mode>2_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))] + "TARGET_<MODE>_FPR" + "@ + fabs %0,%1 + xsabsdp %x0,%x1" + [(set_attr "type" "fp") + (set_attr "fp_type" "fp_addsub_<Fs>")]) -(define_insn "" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (neg:SF (abs:SF (match_operand:SF 1 "gpc_reg_operand" "f"))))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" - "fnabs %0,%1" - [(set_attr "type" "fp")]) +(define_insn "*nabs<mode>2_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (neg:SFDF + (abs:SFDF + (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))))] + "TARGET_<MODE>_FPR" + "@ + fnabs %0,%1 + xsnabsdp %x0,%x1" + [(set_attr "type" "fp") + (set_attr "fp_type" "fp_addsub_<Fs>")]) -(define_expand "addsf3" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (plus:SF (match_operand:SF 1 "gpc_reg_operand" "") - (match_operand:SF 2 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT" +(define_expand "neg<mode>2" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "") + (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))] + "TARGET_<MODE>_INSN" "") -(define_insn "" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (plus:SF (match_operand:SF 1 "gpc_reg_operand" "%f") - (match_operand:SF 2 "gpc_reg_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" - "fadds %0,%1,%2" +(define_insn "*neg<mode>2_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))] + "TARGET_<MODE>_FPR" + "@ + fneg %0,%1 + xsnegdp %x0,%x1" [(set_attr "type" "fp") - (set_attr "fp_type" "fp_addsub_s")]) + (set_attr "fp_type" "fp_addsub_<Fs>")]) -(define_expand "subsf3" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (minus:SF (match_operand:SF 1 "gpc_reg_operand" "") - (match_operand:SF 2 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT" +(define_expand "add<mode>3" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "") + (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "") + (match_operand:SFDF 2 "gpc_reg_operand" "")))] + "TARGET_<MODE>_INSN" "") -(define_insn "" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (minus:SF (match_operand:SF 1 "gpc_reg_operand" "f") - (match_operand:SF 2 "gpc_reg_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" - "fsubs %0,%1,%2" +(define_insn "*add<mode>3_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>") + (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))] + "TARGET_<MODE>_FPR" + "@ + fadd<Ftrad> %0,%1,%2 + xsadd<Fvsx> %x0,%x1,%x2" [(set_attr "type" "fp") - (set_attr "fp_type" "fp_addsub_s")]) + (set_attr "fp_type" "fp_addsub_<Fs>")]) -(define_expand "mulsf3" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (mult:SF (match_operand:SF 1 "gpc_reg_operand" "") - (match_operand:SF 2 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT" +(define_expand "sub<mode>3" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "") + (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "") + (match_operand:SFDF 2 "gpc_reg_operand" "")))] + "TARGET_<MODE>_INSN" "") -(define_insn "" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") - (match_operand:SF 2 "gpc_reg_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" - "fmuls %0,%1,%2" +(define_insn "*sub<mode>3_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>") + (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))] + "TARGET_<MODE>_FPR" + "@ + fsub<Ftrad> %0,%1,%2 + xssub<Fvsx> %x0,%x1,%x2" [(set_attr "type" "fp") - (set_attr "fp_type" "fp_mul_s")]) + (set_attr "fp_type" "fp_addsub_<Fs>")]) -(define_expand "divsf3" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (div:SF (match_operand:SF 1 "gpc_reg_operand" "") - (match_operand:SF 2 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT && !TARGET_SIMPLE_FPU" +(define_expand "mul<mode>3" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "") + (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "") + (match_operand:SFDF 2 "gpc_reg_operand" "")))] + "TARGET_<MODE>_INSN" "") -(define_insn "" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (div:SF (match_operand:SF 1 "gpc_reg_operand" "f") - (match_operand:SF 2 "gpc_reg_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_FPRS - && TARGET_SINGLE_FLOAT && !TARGET_SIMPLE_FPU" - "fdivs %0,%1,%2" - [(set_attr "type" "sdiv")]) - -(define_insn "fres" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))] - "TARGET_FRES" - "fres %0,%1" +(define_insn "*mul<mode>3_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>") + (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))] + "TARGET_<MODE>_FPR" + "@ + fmul<Ftrad> %0,%1,%2 + xsmul<Fvsx> %x0,%x1,%x2" + [(set_attr "type" "dmul") + (set_attr "fp_type" "fp_mul_<Fs>")]) + +(define_expand "div<mode>3" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "") + (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "") + (match_operand:SFDF 2 "gpc_reg_operand" "")))] + "TARGET_<MODE>_INSN && !TARGET_SIMPLE_FPU" + "") + +(define_insn "*div<mode>3_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>") + (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))] + "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU" + "@ + fdiv<Ftrad> %0,%1,%2 + xsdiv<Fvsx> %x0,%x1,%x2" + [(set_attr "type" "<Fs>div") + (set_attr "fp_type" "fp_div_<Fs>")]) + +(define_insn "sqrt<mode>2" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))] + "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU + && (TARGET_PPC_GPOPT || (<MODE>mode == SFmode && TARGET_XILINX_FPU))" + "@ + fsqrt<Ftrad> %0,%1 + xssqrt<Fvsx> %x0,%x1" + [(set_attr "type" "<Fs>sqrt") + (set_attr "fp_type" "fp_sqrt_<Fs>")]) + +;; Floating point reciprocal approximation +(define_insn "fre<Fs>" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")] + UNSPEC_FRES))] + "TARGET_<FFRE>" + "@ + fre<Ftrad> %0,%1 + xsre<Fvsx> %x0,%x1" [(set_attr "type" "fp")]) -; builtin fmaf support -(define_insn "*fmasf4_fpr" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f") - (match_operand:SF 2 "gpc_reg_operand" "f") - (match_operand:SF 3 "gpc_reg_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" - "fmadds %0,%1,%2,%3" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_maddsub_s")]) +(define_insn "*rsqrt<mode>2" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")] + UNSPEC_RSQRT))] + "RS6000_RECIP_HAVE_RSQRTE_P (<MODE>mode)" + "@ + frsqrte<Ftrad> %0,%1 + xsrsqrte<Fvsx> %x0,%x1" + [(set_attr "type" "fp")]) -(define_insn "*fmssf4_fpr" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f") - (match_operand:SF 2 "gpc_reg_operand" "f") - (neg:SF (match_operand:SF 3 "gpc_reg_operand" "f"))))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" - "fmsubs %0,%1,%2,%3" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_maddsub_s")]) +;; Floating point comparisons +(define_insn "*cmp<mode>_fpr" + [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,y") + (compare:CCFP (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>") + (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))] + "TARGET_<MODE>_FPR" + "@ + fcmpu %0,%1,%2 + xscmpudp %0,%x1,%x2" + [(set_attr "type" "fpcompare")]) -(define_insn "*nfmasf4_fpr" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (neg:SF (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f") - (match_operand:SF 2 "gpc_reg_operand" "f") - (match_operand:SF 3 "gpc_reg_operand" "f"))))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" - "fnmadds %0,%1,%2,%3" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_maddsub_s")]) +;; Floating point conversions +(define_expand "extendsfdf2" + [(set (match_operand:DF 0 "gpc_reg_operand" "") + (float_extend:DF (match_operand:SF 1 "reg_or_none500mem_operand" "")))] + "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)" + "") -(define_insn "*nfmssf4_fpr" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (neg:SF (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f") - (match_operand:SF 2 "gpc_reg_operand" "f") - (neg:SF (match_operand:SF 3 "gpc_reg_operand" "f")))))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" - "fnmsubs %0,%1,%2,%3" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_maddsub_s")]) +(define_insn_and_split "*extendsfdf2_fpr" + [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d,ws,?ws,wv") + (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m,0,wy,Z")))] + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" + "@ + # + fmr %0,%1 + lfs%U1%X1 %0,%1 + # + xxlor %x0,%x1,%x1 + lxsspx %x0,%y1" + "&& reload_completed && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])" + [(const_int 0)] +{ + emit_note (NOTE_INSN_DELETED); + DONE; +} + [(set_attr_alternative "type" + [(const_string "fp") + (const_string "fp") + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "fpload_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "fpload_u") + (const_string "fpload"))) + (const_string "fp") + (const_string "vecsimple") + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "fpload_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "fpload_u") + (const_string "fpload")))])]) -(define_expand "sqrtsf2" +(define_expand "truncdfsf2" [(set (match_operand:SF 0 "gpc_reg_operand" "") - (sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "")))] - "(TARGET_PPC_GPOPT || TARGET_XILINX_FPU) - && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT - && !TARGET_SIMPLE_FPU" + (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "")))] + "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)" "") -(define_insn "" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "f")))] - "(TARGET_PPC_GPOPT || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT - && TARGET_FPRS && TARGET_SINGLE_FLOAT && !TARGET_SIMPLE_FPU" - "fsqrts %0,%1" - [(set_attr "type" "ssqrt")]) - -(define_insn "*rsqrtsf_internal1" +(define_insn "*truncdfsf2_fpr" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] - UNSPEC_RSQRT))] - "TARGET_FRSQRTES" - "frsqrtes %0,%1" + (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "d")))] + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" + "frsp %0,%1" [(set_attr "type" "fp")]) ;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in @@ -4742,37 +5351,82 @@ ;; Use an unspec rather providing an if-then-else in RTL, to prevent the ;; compiler from optimizing -0.0 (define_insn "copysign<mode>3_fcpsgn" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>") - (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>") - (match_operand:SFDF 2 "gpc_reg_operand" "<rreg2>")] + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>") + (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")] UNSPEC_COPYSIGN))] - "TARGET_CMPB && !VECTOR_UNIT_VSX_P (<MODE>mode)" - "fcpsgn %0,%2,%1" + "TARGET_<MODE>_FPR && TARGET_CMPB" + "@ + fcpsgn %0,%2,%1 + xscpsgn<Fvsx> %x0,%x2,%x1" [(set_attr "type" "fp")]) ;; For MIN, MAX, and conditional move, we use DEFINE_EXPAND's that involve a ;; fsel instruction and some auxiliary computations. Then we just have a ;; single DEFINE_INSN for fsel and the define_splits to make them if made by ;; combine. -(define_expand "smaxsf3" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "") - (match_operand:SF 2 "gpc_reg_operand" "")) +;; For MIN, MAX on non-VSX machines, and conditional move all of the time, we +;; use DEFINE_EXPAND's that involve a fsel instruction and some auxiliary +;; computations. Then we just have a single DEFINE_INSN for fsel and the +;; define_splits to make them if made by combine. On VSX machines we have the +;; min/max instructions. +;; +;; On VSX, we only check for TARGET_VSX instead of checking for a vsx/p8 vector +;; to allow either DF/SF to use only traditional registers. + +(define_expand "smax<mode>3" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "") + (if_then_else:SFDF (ge (match_operand:SFDF 1 "gpc_reg_operand" "") + (match_operand:SFDF 2 "gpc_reg_operand" "")) (match_dup 1) (match_dup 2)))] - "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS - && TARGET_SINGLE_FLOAT && !flag_trapping_math" - "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}") + "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math" +{ + rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); + DONE; +}) -(define_expand "sminsf3" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "") - (match_operand:SF 2 "gpc_reg_operand" "")) +(define_insn "*smax<mode>3_vsx" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (smax:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>") + (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))] + "TARGET_<MODE>_FPR && TARGET_VSX" + "xsmaxdp %x0,%x1,%x2" + [(set_attr "type" "fp")]) + +(define_expand "smin<mode>3" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "") + (if_then_else:SFDF (ge (match_operand:SFDF 1 "gpc_reg_operand" "") + (match_operand:SFDF 2 "gpc_reg_operand" "")) (match_dup 2) (match_dup 1)))] - "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS - && TARGET_SINGLE_FLOAT && !flag_trapping_math" - "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}") + "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math" +{ + rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); + DONE; +}) + +(define_insn "*smin<mode>3_vsx" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (smin:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>") + (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))] + "TARGET_<MODE>_FPR && TARGET_VSX" + "xsmindp %x0,%x1,%x2" + [(set_attr "type" "fp")]) + +(define_split + [(set (match_operand:SFDF 0 "gpc_reg_operand" "") + (match_operator:SFDF 3 "min_max_operator" + [(match_operand:SFDF 1 "gpc_reg_operand" "") + (match_operand:SFDF 2 "gpc_reg_operand" "")]))] + "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math + && !TARGET_VSX" + [(const_int 0)] +{ + rs6000_emit_minmax (operands[0], GET_CODE (operands[3]), operands[1], + operands[2]); + DONE; +}) (define_split [(set (match_operand:SF 0 "gpc_reg_operand" "") @@ -4904,208 +5558,9 @@ "fsel %0,%1,%2,%3" [(set_attr "type" "fp")]) -(define_expand "negdf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (neg:DF (match_operand:DF 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)" - "") - -(define_insn "*negdf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (neg:DF (match_operand:DF 1 "gpc_reg_operand" "d")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && !VECTOR_UNIT_VSX_P (DFmode)" - "fneg %0,%1" - [(set_attr "type" "fp")]) - -(define_expand "absdf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (abs:DF (match_operand:DF 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)" - "") - -(define_insn "*absdf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (abs:DF (match_operand:DF 1 "gpc_reg_operand" "d")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && !VECTOR_UNIT_VSX_P (DFmode)" - "fabs %0,%1" - [(set_attr "type" "fp")]) - -(define_insn "*nabsdf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "d"))))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && !VECTOR_UNIT_VSX_P (DFmode)" - "fnabs %0,%1" - [(set_attr "type" "fp")]) - -(define_expand "adddf3" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (plus:DF (match_operand:DF 1 "gpc_reg_operand" "") - (match_operand:DF 2 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)" - "") - -(define_insn "*adddf3_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (plus:DF (match_operand:DF 1 "gpc_reg_operand" "%d") - (match_operand:DF 2 "gpc_reg_operand" "d")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && !VECTOR_UNIT_VSX_P (DFmode)" - "fadd %0,%1,%2" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_addsub_d")]) - -(define_expand "subdf3" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (minus:DF (match_operand:DF 1 "gpc_reg_operand" "") - (match_operand:DF 2 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)" - "") - -(define_insn "*subdf3_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (minus:DF (match_operand:DF 1 "gpc_reg_operand" "d") - (match_operand:DF 2 "gpc_reg_operand" "d")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && !VECTOR_UNIT_VSX_P (DFmode)" - "fsub %0,%1,%2" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_addsub_d")]) - -(define_expand "muldf3" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (mult:DF (match_operand:DF 1 "gpc_reg_operand" "") - (match_operand:DF 2 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)" - "") - -(define_insn "*muldf3_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d") - (match_operand:DF 2 "gpc_reg_operand" "d")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && !VECTOR_UNIT_VSX_P (DFmode)" - "fmul %0,%1,%2" - [(set_attr "type" "dmul") - (set_attr "fp_type" "fp_mul_d")]) - -(define_expand "divdf3" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (div:DF (match_operand:DF 1 "gpc_reg_operand" "") - (match_operand:DF 2 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT - && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE) - && !TARGET_SIMPLE_FPU" - "") - -(define_insn "*divdf3_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (div:DF (match_operand:DF 1 "gpc_reg_operand" "d") - (match_operand:DF 2 "gpc_reg_operand" "d")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !TARGET_SIMPLE_FPU - && !VECTOR_UNIT_VSX_P (DFmode)" - "fdiv %0,%1,%2" - [(set_attr "type" "ddiv")]) - -(define_insn "*fred_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))] - "TARGET_FRE && !VECTOR_UNIT_VSX_P (DFmode)" - "fre %0,%1" - [(set_attr "type" "fp")]) - -(define_insn "*rsqrtdf_internal1" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] - UNSPEC_RSQRT))] - "TARGET_FRSQRTE && !VECTOR_UNIT_VSX_P (DFmode)" - "frsqrte %0,%1" - [(set_attr "type" "fp")]) - -; builtin fma support -(define_insn "*fmadf4_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f") - (match_operand:DF 2 "gpc_reg_operand" "f") - (match_operand:DF 3 "gpc_reg_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && VECTOR_UNIT_NONE_P (DFmode)" - "fmadd %0,%1,%2,%3" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_maddsub_d")]) - -(define_insn "*fmsdf4_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f") - (match_operand:DF 2 "gpc_reg_operand" "f") - (neg:DF (match_operand:DF 3 "gpc_reg_operand" "f"))))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && VECTOR_UNIT_NONE_P (DFmode)" - "fmsub %0,%1,%2,%3" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_maddsub_d")]) - -(define_insn "*nfmadf4_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (neg:DF (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f") - (match_operand:DF 2 "gpc_reg_operand" "f") - (match_operand:DF 3 "gpc_reg_operand" "f"))))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && VECTOR_UNIT_NONE_P (DFmode)" - "fnmadd %0,%1,%2,%3" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_maddsub_d")]) - -(define_insn "*nfmsdf4_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (neg:DF (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f") - (match_operand:DF 2 "gpc_reg_operand" "f") - (neg:DF (match_operand:DF 3 "gpc_reg_operand" "f")))))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && VECTOR_UNIT_NONE_P (DFmode)" - "fnmsub %0,%1,%2,%3" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_maddsub_d")]) - -(define_expand "sqrtdf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "")))] - "TARGET_PPC_GPOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" - "") - -(define_insn "*sqrtdf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "d")))] - "TARGET_PPC_GPOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && !VECTOR_UNIT_VSX_P (DFmode)" - "fsqrt %0,%1" - [(set_attr "type" "dsqrt")]) - ;; The conditional move instructions allow us to perform max and min ;; operations even when -(define_expand "smaxdf3" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "") - (match_operand:DF 2 "gpc_reg_operand" "")) - (match_dup 1) - (match_dup 2)))] - "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && !flag_trapping_math" - "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}") - -(define_expand "smindf3" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "") - (match_operand:DF 2 "gpc_reg_operand" "")) - (match_dup 2) - (match_dup 1)))] - "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && !flag_trapping_math" - "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}") - (define_split [(set (match_operand:DF 0 "gpc_reg_operand" "") (match_operator:DF 3 "min_max_operator" @@ -5159,12 +5614,15 @@ ; We don't define lfiwax/lfiwzx with the normal definition, because we ; don't want to support putting SImode in FPR registers. (define_insn "lfiwax" - [(set (match_operand:DI 0 "gpc_reg_operand" "=d") - (unspec:DI [(match_operand:SI 1 "indexed_or_indirect_operand" "Z")] + [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wm,!wm") + (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r")] UNSPEC_LFIWAX))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX" - "lfiwax %0,%y1" - [(set_attr "type" "fpload")]) + "@ + lfiwax %0,%y1 + lxsiwax %x0,%y1 + mtvsrwa %x0,%1" + [(set_attr "type" "fpload,fpload,mffgpr")]) ; This split must be run before register allocation because it allocates the ; memory slot that is needed to move values to/from the FPR. We don't allocate @@ -5186,7 +5644,8 @@ rtx src = operands[1]; rtx tmp; - if (!MEM_P (src) && TARGET_MFPGPR && TARGET_POWERPC64) + if (!MEM_P (src) && TARGET_POWERPC64 + && (TARGET_MFPGPR || TARGET_DIRECT_MOVE)) tmp = convert_to_mode (DImode, src, false); else { @@ -5235,12 +5694,15 @@ (set_attr "type" "fpload")]) (define_insn "lfiwzx" - [(set (match_operand:DI 0 "gpc_reg_operand" "=d") - (unspec:DI [(match_operand:SI 1 "indexed_or_indirect_operand" "Z")] + [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wm,!wm") + (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r")] UNSPEC_LFIWZX))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX" - "lfiwzx %0,%y1" - [(set_attr "type" "fpload")]) + "@ + lfiwzx %0,%y1 + lxsiwzx %x0,%y1 + mtvsrwz %x0,%1" + [(set_attr "type" "fpload,fpload,mftgpr")]) (define_insn_and_split "floatunssi<mode>2_lfiwzx" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d") @@ -5257,7 +5719,8 @@ rtx src = operands[1]; rtx tmp; - if (!MEM_P (src) && TARGET_MFPGPR && TARGET_POWERPC64) + if (!MEM_P (src) && TARGET_POWERPC64 + && (TARGET_MFPGPR || TARGET_DIRECT_MOVE)) tmp = convert_to_mode (DImode, src, true); else { @@ -5548,7 +6011,7 @@ emit_insn (gen_stfiwx (dest, tmp)); DONE; } - else if (TARGET_MFPGPR && TARGET_POWERPC64) + else if (TARGET_POWERPC64 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE)) { dest = gen_lowpart (DImode, dest); emit_move_insn (dest, tmp); @@ -5642,7 +6105,7 @@ emit_insn (gen_stfiwx (dest, tmp)); DONE; } - else if (TARGET_MFPGPR && TARGET_POWERPC64) + else if (TARGET_POWERPC64 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE)) { dest = gen_lowpart (DImode, dest); emit_move_insn (dest, tmp); @@ -5781,66 +6244,52 @@ [(set (match_operand:DI 0 "gpc_reg_operand" "=d") (unspec:DI [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")] UNSPEC_FCTID))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>" + "TARGET_<MODE>_FPR && TARGET_FPRND" "fctid %0,%1" [(set_attr "type" "fp")]) -(define_expand "btrunc<mode>2" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "") - (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")] - UNSPEC_FRIZ))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>" - "") - -(define_insn "*btrunc<mode>2_fpr" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>") - (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")] +(define_insn "btrunc<mode>2" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")] UNSPEC_FRIZ))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> - && !VECTOR_UNIT_VSX_P (<MODE>mode)" - "friz %0,%1" - [(set_attr "type" "fp")]) + "TARGET_<MODE>_FPR && TARGET_FPRND" + "@ + friz %0,%1 + xsrdpiz %x0,%x1" + [(set_attr "type" "fp") + (set_attr "fp_type" "fp_addsub_<Fs>")]) -(define_expand "ceil<mode>2" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "") - (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")] +(define_insn "ceil<mode>2" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")] UNSPEC_FRIP))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>" - "") - -(define_insn "*ceil<mode>2_fpr" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>") - (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")] - UNSPEC_FRIP))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> - && !VECTOR_UNIT_VSX_P (<MODE>mode)" - "frip %0,%1" - [(set_attr "type" "fp")]) - -(define_expand "floor<mode>2" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "") - (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")] - UNSPEC_FRIM))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>" - "") + "TARGET_<MODE>_FPR && TARGET_FPRND" + "@ + frip %0,%1 + xsrdpip %x0,%x1" + [(set_attr "type" "fp") + (set_attr "fp_type" "fp_addsub_<Fs>")]) -(define_insn "*floor<mode>2_fpr" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>") - (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")] +(define_insn "floor<mode>2" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")] UNSPEC_FRIM))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> - && !VECTOR_UNIT_VSX_P (<MODE>mode)" - "frim %0,%1" - [(set_attr "type" "fp")]) + "TARGET_<MODE>_FPR && TARGET_FPRND" + "@ + frim %0,%1 + xsrdpim %x0,%x1" + [(set_attr "type" "fp") + (set_attr "fp_type" "fp_addsub_<Fs>")]) ;; No VSX equivalent to frin (define_insn "round<mode>2" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>") (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")] UNSPEC_FRIN))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>" + "TARGET_<MODE>_FPR && TARGET_FPRND" "frin %0,%1" - [(set_attr "type" "fp")]) + [(set_attr "type" "fp") + (set_attr "fp_type" "fp_addsub_<Fs>")]) ; An UNSPEC is used so we don't have to support SImode in FP registers. (define_insn "stfiwx" @@ -6084,6 +6533,49 @@ [(set_attr "length" "8") (set_attr "type" "fpload")]) +;; Define the TImode operations that can be done in a small number +;; of instructions. The & constraints are to prevent the register +;; allocator from allocating registers that overlap with the inputs +;; (for example, having an input in 7,8 and an output in 6,7). We +;; also allow for the output being the same as one of the inputs. + +(define_insn "addti3" + [(set (match_operand:TI 0 "gpc_reg_operand" "=&r,&r,r,r") + (plus:TI (match_operand:TI 1 "gpc_reg_operand" "%r,r,0,0") + (match_operand:TI 2 "reg_or_short_operand" "r,I,r,I")))] + "TARGET_64BIT" +{ + if (WORDS_BIG_ENDIAN) + return (GET_CODE (operands[2])) != CONST_INT + ? \"addc %L0,%L1,%L2\;adde %0,%1,%2\" + : \"addic %L0,%L1,%2\;add%G2e %0,%1\"; + else + return (GET_CODE (operands[2])) != CONST_INT + ? \"addc %0,%1,%2\;adde %L0,%L1,%L2\" + : \"addic %0,%1,%2\;add%G2e %L0,%L1\"; +} + [(set_attr "type" "two") + (set_attr "length" "8")]) + +(define_insn "subti3" + [(set (match_operand:TI 0 "gpc_reg_operand" "=&r,&r,r,r,r") + (minus:TI (match_operand:TI 1 "reg_or_short_operand" "r,I,0,r,I") + (match_operand:TI 2 "gpc_reg_operand" "r,r,r,0,0")))] + "TARGET_64BIT" +{ + if (WORDS_BIG_ENDIAN) + return (GET_CODE (operands[1]) != CONST_INT) + ? \"subfc %L0,%L2,%L1\;subfe %0,%2,%1\" + : \"subfic %L0,%L2,%1\;subf%G1e %0,%2\"; + else + return (GET_CODE (operands[1]) != CONST_INT) + ? \"subfc %0,%2,%1\;subfe %L0,%L2,%L1\" + : \"subfic %0,%2,%1\;subf%G1e %L0,%L2\"; +} + [(set_attr "type" "two") + (set_attr "length" "8")]) + + ;; Define the DImode operations that can be done in a small number ;; of instructions. The & constraints are to prevent the register ;; allocator from allocating registers that overlap with the inputs @@ -6260,11 +6752,11 @@ [(set_attr "type" "two,three") (set_attr "length" "8,12")]) -(define_insn "*ashrdisi3_noppc64" +(define_insn "*ashrdisi3_noppc64be" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (subreg:SI (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r") (const_int 32)) 4))] - "TARGET_32BIT && !TARGET_POWERPC64" + "TARGET_32BIT && !TARGET_POWERPC64 && WORDS_BIG_ENDIAN" "* { if (REGNO (operands[0]) == REGNO (operands[1])) @@ -6551,19 +7043,31 @@ (const_int 0)))] "") -(define_insn "*rotldi3_internal7" +(define_insn "*rotldi3_internal7le" [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r") (zero_extend:DI (subreg:QI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 0)))] - "TARGET_POWERPC64" + "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN" + "@ + rldcl %0,%1,%2,56 + rldicl %0,%1,%H2,56" + [(set_attr "type" "var_shift_rotate,integer")]) + +(define_insn "*rotldi3_internal7be" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r") + (zero_extend:DI + (subreg:QI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") + (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 7)))] + "TARGET_POWERPC64 && BYTES_BIG_ENDIAN" "@ rldcl %0,%1,%2,56 rldicl %0,%1,%H2,56" [(set_attr "type" "var_shift_rotate,integer")]) -(define_insn "*rotldi3_internal8" +(define_insn "*rotldi3_internal8le" [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y") (compare:CC (zero_extend:DI (subreg:QI @@ -6571,7 +7075,24 @@ (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 0)) (const_int 0))) (clobber (match_scratch:DI 3 "=r,r,r,r"))] - "TARGET_64BIT" + "TARGET_64BIT && !BYTES_BIG_ENDIAN" + "@ + rldcl. %3,%1,%2,56 + rldicl. %3,%1,%H2,56 + # + #" + [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") + (set_attr "length" "4,4,8,8")]) + +(define_insn "*rotldi3_internal8be" + [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y") + (compare:CC (zero_extend:DI + (subreg:QI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r") + (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 7)) + (const_int 0))) + (clobber (match_scratch:DI 3 "=r,r,r,r"))] + "TARGET_64BIT && BYTES_BIG_ENDIAN" "@ rldcl. %3,%1,%2,56 rldicl. %3,%1,%H2,56 @@ -6588,7 +7109,7 @@ (match_operand:DI 2 "reg_or_cint_operand" "")) 0)) (const_int 0))) (clobber (match_scratch:DI 3 ""))] - "TARGET_POWERPC64 && reload_completed" + "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed" [(set (match_dup 3) (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) @@ -6598,7 +7119,25 @@ (const_int 0)))] "") -(define_insn "*rotldi3_internal9" +(define_split + [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "") + (compare:CC (zero_extend:DI + (subreg:QI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:DI 2 "reg_or_cint_operand" "")) 7)) + (const_int 0))) + (clobber (match_scratch:DI 3 ""))] + "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed" + [(set (match_dup 3) + (zero_extend:DI (subreg:QI + (rotate:DI (match_dup 1) + (match_dup 2)) 7))) + (set (match_dup 0) + (compare:CC (match_dup 3) + (const_int 0)))] + "") + +(define_insn "*rotldi3_internal9le" [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") (compare:CC (zero_extend:DI (subreg:QI @@ -6607,7 +7146,25 @@ (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r") (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 0)))] - "TARGET_64BIT" + "TARGET_64BIT && !BYTES_BIG_ENDIAN" + "@ + rldcl. %0,%1,%2,56 + rldicl. %0,%1,%H2,56 + # + #" + [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") + (set_attr "length" "4,4,8,8")]) + +(define_insn "*rotldi3_internal9be" + [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") + (compare:CC (zero_extend:DI + (subreg:QI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r") + (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 7)) + (const_int 0))) + (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r") + (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 7)))] + "TARGET_64BIT && BYTES_BIG_ENDIAN" "@ rldcl. %0,%1,%2,56 rldicl. %0,%1,%H2,56 @@ -6625,7 +7182,7 @@ (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "") (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 0)))] - "TARGET_POWERPC64 && reload_completed" + "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed" [(set (match_dup 0) (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 0))) (set (match_dup 3) @@ -6633,19 +7190,48 @@ (const_int 0)))] "") -(define_insn "*rotldi3_internal10" +(define_split + [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "") + (compare:CC (zero_extend:DI + (subreg:QI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:DI 2 "reg_or_cint_operand" "")) 7)) + (const_int 0))) + (set (match_operand:DI 0 "gpc_reg_operand" "") + (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 7)))] + "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed" + [(set (match_dup 0) + (zero_extend:DI (subreg:QI (rotate:DI (match_dup 1) (match_dup 2)) 7))) + (set (match_dup 3) + (compare:CC (match_dup 0) + (const_int 0)))] + "") + +(define_insn "*rotldi3_internal10le" [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r") (zero_extend:DI (subreg:HI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 0)))] - "TARGET_POWERPC64" + "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN" "@ rldcl %0,%1,%2,48 rldicl %0,%1,%H2,48" [(set_attr "type" "var_shift_rotate,integer")]) -(define_insn "*rotldi3_internal11" +(define_insn "*rotldi3_internal10be" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r") + (zero_extend:DI + (subreg:HI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") + (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 6)))] + "TARGET_POWERPC64 && BYTES_BIG_ENDIAN" + "@ + rldcl %0,%1,%2,48 + rldicl %0,%1,%H2,48" + [(set_attr "type" "var_shift_rotate,integer")]) + +(define_insn "*rotldi3_internal11le" [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y") (compare:CC (zero_extend:DI (subreg:HI @@ -6653,7 +7239,24 @@ (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 0)) (const_int 0))) (clobber (match_scratch:DI 3 "=r,r,r,r"))] - "TARGET_64BIT" + "TARGET_64BIT && !BYTES_BIG_ENDIAN" + "@ + rldcl. %3,%1,%2,48 + rldicl. %3,%1,%H2,48 + # + #" + [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") + (set_attr "length" "4,4,8,8")]) + +(define_insn "*rotldi3_internal11be" + [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y") + (compare:CC (zero_extend:DI + (subreg:HI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r") + (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 6)) + (const_int 0))) + (clobber (match_scratch:DI 3 "=r,r,r,r"))] + "TARGET_64BIT && BYTES_BIG_ENDIAN" "@ rldcl. %3,%1,%2,48 rldicl. %3,%1,%H2,48 @@ -6670,7 +7273,7 @@ (match_operand:DI 2 "reg_or_cint_operand" "")) 0)) (const_int 0))) (clobber (match_scratch:DI 3 ""))] - "TARGET_POWERPC64 && reload_completed" + "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed" [(set (match_dup 3) (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) @@ -6680,7 +7283,25 @@ (const_int 0)))] "") -(define_insn "*rotldi3_internal12" +(define_split + [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "") + (compare:CC (zero_extend:DI + (subreg:HI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:DI 2 "reg_or_cint_operand" "")) 6)) + (const_int 0))) + (clobber (match_scratch:DI 3 ""))] + "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed" + [(set (match_dup 3) + (zero_extend:DI (subreg:HI + (rotate:DI (match_dup 1) + (match_dup 2)) 6))) + (set (match_dup 0) + (compare:CC (match_dup 3) + (const_int 0)))] + "") + +(define_insn "*rotldi3_internal12le" [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") (compare:CC (zero_extend:DI (subreg:HI @@ -6689,7 +7310,25 @@ (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r") (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 0)))] - "TARGET_64BIT" + "TARGET_64BIT && !BYTES_BIG_ENDIAN" + "@ + rldcl. %0,%1,%2,48 + rldicl. %0,%1,%H2,48 + # + #" + [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") + (set_attr "length" "4,4,8,8")]) + +(define_insn "*rotldi3_internal12be" + [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") + (compare:CC (zero_extend:DI + (subreg:HI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r") + (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 6)) + (const_int 0))) + (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r") + (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 6)))] + "TARGET_64BIT && BYTES_BIG_ENDIAN" "@ rldcl. %0,%1,%2,48 rldicl. %0,%1,%H2,48 @@ -6707,7 +7346,7 @@ (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "") (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 0)))] - "TARGET_POWERPC64 && reload_completed" + "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed" [(set (match_dup 0) (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 0))) (set (match_dup 3) @@ -6715,19 +7354,48 @@ (const_int 0)))] "") -(define_insn "*rotldi3_internal13" +(define_split + [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "") + (compare:CC (zero_extend:DI + (subreg:HI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:DI 2 "reg_or_cint_operand" "")) 6)) + (const_int 0))) + (set (match_operand:DI 0 "gpc_reg_operand" "") + (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 6)))] + "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed" + [(set (match_dup 0) + (zero_extend:DI (subreg:HI (rotate:DI (match_dup 1) (match_dup 2)) 6))) + (set (match_dup 3) + (compare:CC (match_dup 0) + (const_int 0)))] + "") + +(define_insn "*rotldi3_internal13le" [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r") (zero_extend:DI (subreg:SI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 0)))] - "TARGET_POWERPC64" + "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN" + "@ + rldcl %0,%1,%2,32 + rldicl %0,%1,%H2,32" + [(set_attr "type" "var_shift_rotate,integer")]) + +(define_insn "*rotldi3_internal13be" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r") + (zero_extend:DI + (subreg:SI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") + (match_operand:DI 2 "reg_or_cint_operand" "r,i")) 4)))] + "TARGET_POWERPC64 && BYTES_BIG_ENDIAN" "@ rldcl %0,%1,%2,32 rldicl %0,%1,%H2,32" [(set_attr "type" "var_shift_rotate,integer")]) -(define_insn "*rotldi3_internal14" +(define_insn "*rotldi3_internal14le" [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y") (compare:CC (zero_extend:DI (subreg:SI @@ -6735,7 +7403,24 @@ (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 0)) (const_int 0))) (clobber (match_scratch:DI 3 "=r,r,r,r"))] - "TARGET_64BIT" + "TARGET_64BIT && !BYTES_BIG_ENDIAN" + "@ + rldcl. %3,%1,%2,32 + rldicl. %3,%1,%H2,32 + # + #" + [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") + (set_attr "length" "4,4,8,8")]) + +(define_insn "*rotldi3_internal14be" + [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y") + (compare:CC (zero_extend:DI + (subreg:SI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r") + (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 4)) + (const_int 0))) + (clobber (match_scratch:DI 3 "=r,r,r,r"))] + "TARGET_64BIT && BYTES_BIG_ENDIAN" "@ rldcl. %3,%1,%2,32 rldicl. %3,%1,%H2,32 @@ -6752,7 +7437,7 @@ (match_operand:DI 2 "reg_or_cint_operand" "")) 0)) (const_int 0))) (clobber (match_scratch:DI 3 ""))] - "TARGET_POWERPC64 && reload_completed" + "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed" [(set (match_dup 3) (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) @@ -6762,7 +7447,25 @@ (const_int 0)))] "") -(define_insn "*rotldi3_internal15" +(define_split + [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "") + (compare:CC (zero_extend:DI + (subreg:SI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:DI 2 "reg_or_cint_operand" "")) 4)) + (const_int 0))) + (clobber (match_scratch:DI 3 ""))] + "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed" + [(set (match_dup 3) + (zero_extend:DI (subreg:SI + (rotate:DI (match_dup 1) + (match_dup 2)) 4))) + (set (match_dup 0) + (compare:CC (match_dup 3) + (const_int 0)))] + "") + +(define_insn "*rotldi3_internal15le" [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") (compare:CC (zero_extend:DI (subreg:SI @@ -6771,7 +7474,25 @@ (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r") (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 0)))] - "TARGET_64BIT" + "TARGET_64BIT && !BYTES_BIG_ENDIAN" + "@ + rldcl. %0,%1,%2,32 + rldicl. %0,%1,%H2,32 + # + #" + [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") + (set_attr "length" "4,4,8,8")]) + +(define_insn "*rotldi3_internal15be" + [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") + (compare:CC (zero_extend:DI + (subreg:SI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r") + (match_operand:DI 2 "reg_or_cint_operand" "r,i,r,i")) 4)) + (const_int 0))) + (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r") + (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 4)))] + "TARGET_64BIT && BYTES_BIG_ENDIAN" "@ rldcl. %0,%1,%2,32 rldicl. %0,%1,%H2,32 @@ -6789,7 +7510,7 @@ (const_int 0))) (set (match_operand:DI 0 "gpc_reg_operand" "") (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 0)))] - "TARGET_POWERPC64 && reload_completed" + "TARGET_POWERPC64 && !BYTES_BIG_ENDIAN && reload_completed" [(set (match_dup 0) (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 0))) (set (match_dup 3) @@ -6797,6 +7518,23 @@ (const_int 0)))] "") +(define_split + [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "") + (compare:CC (zero_extend:DI + (subreg:SI + (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:DI 2 "reg_or_cint_operand" "")) 4)) + (const_int 0))) + (set (match_operand:DI 0 "gpc_reg_operand" "") + (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 4)))] + "TARGET_POWERPC64 && BYTES_BIG_ENDIAN && reload_completed" + [(set (match_dup 0) + (zero_extend:DI (subreg:SI (rotate:DI (match_dup 1) (match_dup 2)) 4))) + (set (match_dup 3) + (compare:CC (match_dup 0) + (const_int 0)))] + "") + (define_expand "ashldi3" [(set (match_operand:DI 0 "gpc_reg_operand" "") (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "") @@ -7195,10 +7933,19 @@ [(parallel [(set (match_operand:DI 0 "gpc_reg_operand" "") (and:DI (match_operand:DI 1 "gpc_reg_operand" "") - (match_operand:DI 2 "and64_2_operand" ""))) + (match_operand:DI 2 "reg_or_cint_operand" ""))) (clobber (match_scratch:CC 3 ""))])] - "TARGET_POWERPC64" - "") + "" +{ + if (!TARGET_POWERPC64) + { + rtx cc = gen_rtx_SCRATCH (CCmode); + rs6000_split_logical (operands, AND, false, false, false, cc); + DONE; + } + else if (!and64_2_operand (operands[2], DImode)) + operands[2] = force_reg (DImode, operands[2]); +}) (define_insn "anddi3_mc" [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r") @@ -7379,11 +8126,17 @@ (define_expand "iordi3" [(set (match_operand:DI 0 "gpc_reg_operand" "") (ior:DI (match_operand:DI 1 "gpc_reg_operand" "") - (match_operand:DI 2 "reg_or_logical_cint_operand" "")))] - "TARGET_POWERPC64" - " + (match_operand:DI 2 "reg_or_cint_operand" "")))] + "" { - if (non_logical_cint_operand (operands[2], DImode)) + if (!TARGET_POWERPC64) + { + rs6000_split_logical (operands, IOR, false, false, false, NULL_RTX); + DONE; + } + else if (!reg_or_logical_cint_operand (operands[2], DImode)) + operands[2] = force_reg (DImode, operands[2]); + else if (non_logical_cint_operand (operands[2], DImode)) { HOST_WIDE_INT value; rtx tmp = ((!can_create_pseudo_p () @@ -7408,15 +8161,21 @@ emit_insn (gen_iordi3 (operands[0], tmp, GEN_INT (value & 0xffff))); DONE; } -}") +}) (define_expand "xordi3" [(set (match_operand:DI 0 "gpc_reg_operand" "") (xor:DI (match_operand:DI 1 "gpc_reg_operand" "") - (match_operand:DI 2 "reg_or_logical_cint_operand" "")))] - "TARGET_POWERPC64" - " + (match_operand:DI 2 "reg_or_cint_operand" "")))] + "" { + if (!TARGET_POWERPC64) + { + rs6000_split_logical (operands, XOR, false, false, false, NULL_RTX); + DONE; + } + else if (!reg_or_logical_cint_operand (operands[2], DImode)) + operands[2] = force_reg (DImode, operands[2]); if (non_logical_cint_operand (operands[2], DImode)) { HOST_WIDE_INT value; @@ -7442,7 +8201,7 @@ emit_insn (gen_xordi3 (operands[0], tmp, GEN_INT (value & 0xffff))); DONE; } -}") +}) (define_insn "*booldi3_internal1" [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r") @@ -7678,6 +8437,384 @@ (compare:CC (match_dup 0) (const_int 0)))] "") + +;; Eqv operation. +(define_insn "*eqv<mode>3" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (not:GPR + (xor:GPR (match_operand:GPR 1 "gpc_reg_operand" "r") + (match_operand:GPR 2 "gpc_reg_operand" "r"))))] + "" + "eqv %0,%1,%2" + [(set_attr "type" "integer") + (set_attr "length" "4")]) + + +;; 128-bit logical operations expanders + +(define_expand "and<mode>3" + [(parallel [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + (and:BOOL_128 + (match_operand:BOOL_128 1 "vlogical_operand" "") + (match_operand:BOOL_128 2 "vlogical_operand" ""))) + (clobber (match_scratch:CC 3 ""))])] + "" + "") + +(define_expand "ior<mode>3" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + (ior:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "") + (match_operand:BOOL_128 2 "vlogical_operand" "")))] + "" + "") + +(define_expand "xor<mode>3" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + (xor:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "") + (match_operand:BOOL_128 2 "vlogical_operand" "")))] + "" + "") + +(define_expand "one_cmpl<mode>2" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")))] + "" + "") + +(define_expand "nor<mode>3" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + (and:BOOL_128 + (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")) + (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" ""))))] + "" + "") + +(define_expand "andc<mode>3" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + (and:BOOL_128 + (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" "")) + (match_operand:BOOL_128 1 "vlogical_operand" "")))] + "" + "") + +;; Power8 vector logical instructions. +(define_expand "eqv<mode>3" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + (not:BOOL_128 + (xor:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "") + (match_operand:BOOL_128 2 "vlogical_operand" ""))))] + "<MODE>mode == TImode || <MODE>mode == PTImode || TARGET_P8_VECTOR" + "") + +;; Rewrite nand into canonical form +(define_expand "nand<mode>3" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + (ior:BOOL_128 + (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")) + (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" ""))))] + "<MODE>mode == TImode || <MODE>mode == PTImode || TARGET_P8_VECTOR" + "") + +;; The canonical form is to have the negated element first, so we need to +;; reverse arguments. +(define_expand "orc<mode>3" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + (ior:BOOL_128 + (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" "")) + (match_operand:BOOL_128 1 "vlogical_operand" "")))] + "<MODE>mode == TImode || <MODE>mode == PTImode || TARGET_P8_VECTOR" + "") + +;; 128-bit logical operations insns and split operations +(define_insn_and_split "*and<mode>3_internal" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>") + (and:BOOL_128 + (match_operand:BOOL_128 1 "vlogical_operand" "%<BOOL_REGS_OP1>") + (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>"))) + (clobber (match_scratch:CC 3 "<BOOL_REGS_AND_CR0>"))] + "" +{ + if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode)) + return "xxland %x0,%x1,%x2"; + + if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode)) + return "vand %0,%1,%2"; + + return "#"; +} + "reload_completed && int_reg_operand (operands[0], <MODE>mode)" + [(const_int 0)] +{ + rs6000_split_logical (operands, AND, false, false, false, operands[3]); + DONE; +} + [(set (attr "type") + (if_then_else + (match_test "vsx_register_operand (operands[0], <MODE>mode)") + (const_string "vecsimple") + (const_string "integer"))) + (set (attr "length") + (if_then_else + (match_test "vsx_register_operand (operands[0], <MODE>mode)") + (const_string "4") + (if_then_else + (match_test "TARGET_POWERPC64") + (const_string "8") + (const_string "16"))))]) + +;; 128-bit IOR/XOR +(define_insn_and_split "*bool<mode>3_internal" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>") + (match_operator:BOOL_128 3 "boolean_or_operator" + [(match_operand:BOOL_128 1 "vlogical_operand" "%<BOOL_REGS_OP1>") + (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>")]))] + "" +{ + if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode)) + return "xxl%q3 %x0,%x1,%x2"; + + if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode)) + return "v%q3 %0,%1,%2"; + + return "#"; +} + "reload_completed && int_reg_operand (operands[0], <MODE>mode)" + [(const_int 0)] +{ + rs6000_split_logical (operands, GET_CODE (operands[3]), false, false, false, + NULL_RTX); + DONE; +} + [(set (attr "type") + (if_then_else + (match_test "vsx_register_operand (operands[0], <MODE>mode)") + (const_string "vecsimple") + (const_string "integer"))) + (set (attr "length") + (if_then_else + (match_test "vsx_register_operand (operands[0], <MODE>mode)") + (const_string "4") + (if_then_else + (match_test "TARGET_POWERPC64") + (const_string "8") + (const_string "16"))))]) + +;; 128-bit ANDC/ORC +(define_insn_and_split "*boolc<mode>3_internal1" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>") + (match_operator:BOOL_128 3 "boolean_operator" + [(not:BOOL_128 + (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP1>")) + (match_operand:BOOL_128 1 "vlogical_operand" "<BOOL_REGS_OP2>")]))] + "TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND)" +{ + if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode)) + return "xxl%q3 %x0,%x1,%x2"; + + if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode)) + return "v%q3 %0,%1,%2"; + + return "#"; +} + "(TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND)) + && reload_completed && int_reg_operand (operands[0], <MODE>mode)" + [(const_int 0)] +{ + rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, false, + NULL_RTX); + DONE; +} + [(set (attr "type") + (if_then_else + (match_test "vsx_register_operand (operands[0], <MODE>mode)") + (const_string "vecsimple") + (const_string "integer"))) + (set (attr "length") + (if_then_else + (match_test "vsx_register_operand (operands[0], <MODE>mode)") + (const_string "4") + (if_then_else + (match_test "TARGET_POWERPC64") + (const_string "8") + (const_string "16"))))]) + +(define_insn_and_split "*boolc<mode>3_internal2" + [(set (match_operand:TI2 0 "int_reg_operand" "=&r,r,r") + (match_operator:TI2 3 "boolean_operator" + [(not:TI2 + (match_operand:TI2 1 "int_reg_operand" "r,0,r")) + (match_operand:TI2 2 "int_reg_operand" "r,r,0")]))] + "!TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)" + "#" + "reload_completed && !TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)" + [(const_int 0)] +{ + rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, false, + NULL_RTX); + DONE; +} + [(set_attr "type" "integer") + (set (attr "length") + (if_then_else + (match_test "TARGET_POWERPC64") + (const_string "8") + (const_string "16")))]) + +;; 128-bit NAND/NOR +(define_insn_and_split "*boolcc<mode>3_internal1" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>") + (match_operator:BOOL_128 3 "boolean_operator" + [(not:BOOL_128 + (match_operand:BOOL_128 1 "vlogical_operand" "<BOOL_REGS_OP1>")) + (not:BOOL_128 + (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>"))]))] + "TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND)" +{ + if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode)) + return "xxl%q3 %x0,%x1,%x2"; + + if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode)) + return "v%q3 %0,%1,%2"; + + return "#"; +} + "(TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND)) + && reload_completed && int_reg_operand (operands[0], <MODE>mode)" + [(const_int 0)] +{ + rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, true, + NULL_RTX); + DONE; +} + [(set (attr "type") + (if_then_else + (match_test "vsx_register_operand (operands[0], <MODE>mode)") + (const_string "vecsimple") + (const_string "integer"))) + (set (attr "length") + (if_then_else + (match_test "vsx_register_operand (operands[0], <MODE>mode)") + (const_string "4") + (if_then_else + (match_test "TARGET_POWERPC64") + (const_string "8") + (const_string "16"))))]) + +(define_insn_and_split "*boolcc<mode>3_internal2" + [(set (match_operand:TI2 0 "int_reg_operand" "=&r,r,r") + (match_operator:TI2 3 "boolean_operator" + [(not:TI2 + (match_operand:TI2 1 "int_reg_operand" "r,0,r")) + (not:TI2 + (match_operand:TI2 2 "int_reg_operand" "r,r,0"))]))] + "!TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)" + "#" + "reload_completed && !TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)" + [(const_int 0)] +{ + rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, true, + NULL_RTX); + DONE; +} + [(set_attr "type" "integer") + (set (attr "length") + (if_then_else + (match_test "TARGET_POWERPC64") + (const_string "8") + (const_string "16")))]) + + +;; 128-bit EQV +(define_insn_and_split "*eqv<mode>3_internal1" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>") + (not:BOOL_128 + (xor:BOOL_128 + (match_operand:BOOL_128 1 "vlogical_operand" "<BOOL_REGS_OP1>") + (match_operand:BOOL_128 2 "vlogical_operand" "<BOOL_REGS_OP2>"))))] + "TARGET_P8_VECTOR" +{ + if (vsx_register_operand (operands[0], <MODE>mode)) + return "xxleqv %x0,%x1,%x2"; + + return "#"; +} + "TARGET_P8_VECTOR && reload_completed + && int_reg_operand (operands[0], <MODE>mode)" + [(const_int 0)] +{ + rs6000_split_logical (operands, XOR, true, false, false, NULL_RTX); + DONE; +} + [(set (attr "type") + (if_then_else + (match_test "vsx_register_operand (operands[0], <MODE>mode)") + (const_string "vecsimple") + (const_string "integer"))) + (set (attr "length") + (if_then_else + (match_test "vsx_register_operand (operands[0], <MODE>mode)") + (const_string "4") + (if_then_else + (match_test "TARGET_POWERPC64") + (const_string "8") + (const_string "16"))))]) + +(define_insn_and_split "*eqv<mode>3_internal2" + [(set (match_operand:TI2 0 "int_reg_operand" "=&r,r,r") + (not:TI2 + (xor:TI2 + (match_operand:TI2 1 "int_reg_operand" "r,0,r") + (match_operand:TI2 2 "int_reg_operand" "r,r,0"))))] + "!TARGET_P8_VECTOR" + "#" + "reload_completed && !TARGET_P8_VECTOR" + [(const_int 0)] +{ + rs6000_split_logical (operands, XOR, true, false, false, NULL_RTX); + DONE; +} + [(set_attr "type" "integer") + (set (attr "length") + (if_then_else + (match_test "TARGET_POWERPC64") + (const_string "8") + (const_string "16")))]) + +;; 128-bit one's complement +(define_insn_and_split "*one_cmpl<mode>3_internal" + [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>") + (not:BOOL_128 + (match_operand:BOOL_128 1 "vlogical_operand" "<BOOL_REGS_UNARY>")))] + "" +{ + if (TARGET_VSX && vsx_register_operand (operands[0], <MODE>mode)) + return "xxlnor %x0,%x1,%x1"; + + if (TARGET_ALTIVEC && altivec_register_operand (operands[0], <MODE>mode)) + return "vnor %0,%1,%1"; + + return "#"; +} + "reload_completed && int_reg_operand (operands[0], <MODE>mode)" + [(const_int 0)] +{ + rs6000_split_logical (operands, NOT, false, false, false, NULL_RTX); + DONE; +} + [(set (attr "type") + (if_then_else + (match_test "vsx_register_operand (operands[0], <MODE>mode)") + (const_string "vecsimple") + (const_string "integer"))) + (set (attr "length") + (if_then_else + (match_test "vsx_register_operand (operands[0], <MODE>mode)") + (const_string "4") + (if_then_else + (match_test "TARGET_POWERPC64") + (const_string "8") + (const_string "16"))))]) + ;; Now define ways of moving data around. @@ -7765,7 +8902,31 @@ mt%0 %1 mt%0 %1 nop" - [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,mtjmpr,*,*") + [(set_attr_alternative "type" + [(const_string "*") + (const_string "*") + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "store_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "store_u") + (const_string "store"))) + (const_string "*") + (const_string "*") + (const_string "*") + (const_string "mfjmpr") + (const_string "mtjmpr") + (const_string "*") + (const_string "*")]) + (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4")]) (define_insn "*movsi_internal1_single" @@ -7787,7 +8948,44 @@ nop stfs%U0%X0 %1,%0 lfs%U1%X1 %0,%1" - [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,mtjmpr,*,*,*,*") + [(set_attr_alternative "type" + [(const_string "*") + (const_string "*") + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "store_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "store_u") + (const_string "store"))) + (const_string "*") + (const_string "*") + (const_string "*") + (const_string "mfjmpr") + (const_string "mtjmpr") + (const_string "*") + (const_string "*") + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_u") + (const_string "fpstore"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "fpload_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "fpload_u") + (const_string "fpload")))]) (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4")]) ;; Split a load of a large constant into the appropriate two-insn @@ -7822,7 +9020,7 @@ cmp<wd>i %2,%0,0 mr. %0,%1 #" - [(set_attr "type" "cmp,compare,cmp") + [(set_attr "type" "cmp,fast_compare,cmp") (set_attr "length" "4,4,8")]) (define_split @@ -7850,7 +9048,26 @@ mf%1 %0 mt%0 %1 nop" - [(set_attr "type" "*,load,store,*,mfjmpr,mtjmpr,*")]) + [(set_attr_alternative "type" + [(const_string "*") + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "store_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "store_u") + (const_string "store"))) + (const_string "*") + (const_string "mfjmpr") + (const_string "mtjmpr") + (const_string "*")])]) (define_expand "mov<mode>" [(set (match_operand:INT 0 "general_operand" "") @@ -7871,7 +9088,26 @@ mf%1 %0 mt%0 %1 nop" - [(set_attr "type" "*,load,store,*,mfjmpr,mtjmpr,*")]) + [(set_attr_alternative "type" + [(const_string "*") + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "store_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "store_u") + (const_string "store"))) + (const_string "*") + (const_string "mfjmpr") + (const_string "mtjmpr") + (const_string "*")])]) ;; Here is how to move condition codes around. When we store CC data in ;; an integer register or memory, we store just the high-order 4 bits. @@ -7899,7 +9135,7 @@ mf%1 %0 mt%0 %1 lwz%U1%X1 %0,%1 - stw%U0%U1 %1,%0" + stw%U0%X0 %1,%0" [(set (attr "type") (cond [(eq_attr "alternative" "0,3") (const_string "cr_logical") @@ -7912,9 +9148,23 @@ (eq_attr "alternative" "9") (const_string "mtjmpr") (eq_attr "alternative" "10") - (const_string "load") + (if_then_else + (match_test "update_indexed_address_mem (operands[1], + VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) (eq_attr "alternative" "11") - (const_string "store") + (if_then_else + (match_test "update_indexed_address_mem (operands[0], + VOIDmode)") + (const_string "store_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "store_u") + (const_string "store"))) (match_test "TARGET_MFCRF") (const_string "mfcrf") ] @@ -7926,15 +9176,17 @@ ;; can produce floating-point values in fixed-point registers. Unless the ;; value is a simple constant or already in memory, we deal with this by ;; allocating memory and copying the value explicitly via that memory location. -(define_expand "movsf" - [(set (match_operand:SF 0 "nonimmediate_operand" "") - (match_operand:SF 1 "any_operand" ""))] - "" - "{ rs6000_emit_move (operands[0], operands[1], SFmode); DONE; }") + +;; Move 32-bit binary/decimal floating point +(define_expand "mov<mode>" + [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "") + (match_operand:FMOVE32 1 "any_operand" ""))] + "<fmove_ok>" + "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }") (define_split - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (match_operand:SF 1 "const_double_operand" ""))] + [(set (match_operand:FMOVE32 0 "gpc_reg_operand" "") + (match_operand:FMOVE32 1 "const_double_operand" ""))] "reload_completed && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) || (GET_CODE (operands[0]) == SUBREG @@ -7947,42 +9199,89 @@ REAL_VALUE_TYPE rv; REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_SINGLE (rv, l); + <real_value_to_target> (rv, l); if (! TARGET_POWERPC64) - operands[2] = operand_subword (operands[0], 0, 0, SFmode); + operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode); else operands[2] = gen_lowpart (SImode, operands[0]); operands[3] = gen_int_mode (l, SImode); }") -(define_insn "*movsf_hardfloat" - [(set (match_operand:SF 0 "nonimmediate_operand" "=!r,!r,m,f,f,m,*c*l,!r,*h,!r,!r") - (match_operand:SF 1 "input_operand" "r,m,r,f,m,f,r,h,0,G,Fn"))] - "(gpc_reg_operand (operands[0], SFmode) - || gpc_reg_operand (operands[1], SFmode)) +(define_insn "mov<mode>_hardfloat" + [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=!r,!r,m,f,wa,wa,<f32_lr>,<f32_sm>,wu,Z,?<f32_dm>,?r,*c*l,!r,*h,!r,!r") + (match_operand:FMOVE32 1 "input_operand" "r,m,r,f,wa,j,<f32_lm>,<f32_sr>,Z,wu,r,<f32_dm>,r,h,0,G,Fn"))] + "(gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode)) && (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT)" "@ mr %0,%1 lwz%U1%X1 %0,%1 stw%U0%X0 %1,%0 fmr %0,%1 - lfs%U1%X1 %0,%1 - stfs%U0%X0 %1,%0 + xxlor %x0,%x1,%x1 + xxlxor %x0,%x0,%x0 + <f32_li> + <f32_si> + <f32_lv> + <f32_sv> + mtvsrwz %x0,%1 + mfvsrwz %0,%x1 mt%0 %1 mf%1 %0 nop # #" - [(set_attr "type" "*,load,store,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*") - (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8")]) - -(define_insn "*movsf_softfloat" - [(set (match_operand:SF 0 "nonimmediate_operand" "=r,cl,r,r,m,r,r,r,r,*h") - (match_operand:SF 1 "input_operand" "r,r,h,m,r,I,L,G,Fn,0"))] - "(gpc_reg_operand (operands[0], SFmode) - || gpc_reg_operand (operands[1], SFmode)) + [(set_attr_alternative "type" + [(const_string "*") + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "store_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "store_u") + (const_string "store"))) + (const_string "fp") + (const_string "vecsimple") + (const_string "vecsimple") + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "fpload_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "fpload_u") + (const_string "fpload"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_u") + (const_string "fpstore"))) + (const_string "fpload") + (const_string "fpstore") + (const_string "mftgpr") + (const_string "mffgpr") + (const_string "mtjmpr") + (const_string "mfjmpr") + (const_string "*") + (const_string "*") + (const_string "*")]) + (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8")]) + +(define_insn "*mov<mode>_softfloat" + [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=r,cl,r,r,m,r,r,r,r,*h") + (match_operand:FMOVE32 1 "input_operand" "r,r,h,m,r,I,L,G,Fn,0"))] + "(gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode)) && (TARGET_SOFT_FLOAT || !TARGET_FPRS)" "@ mr %0,%1 @@ -7995,19 +9294,42 @@ # # nop" - [(set_attr "type" "*,mtjmpr,mfjmpr,load,store,*,*,*,*,*") + [(set_attr_alternative "type" + [(const_string "*") + (const_string "mtjmpr") + (const_string "mfjmpr") + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "store_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "store_u") + (const_string "store"))) + (const_string "*") + (const_string "*") + (const_string "*") + (const_string "*") + (const_string "*")]) (set_attr "length" "4,4,4,4,4,4,4,4,8,4")]) -(define_expand "movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "") - (match_operand:DF 1 "any_operand" ""))] +;; Move 64-bit binary/decimal floating point +(define_expand "mov<mode>" + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "") + (match_operand:FMOVE64 1 "any_operand" ""))] "" - "{ rs6000_emit_move (operands[0], operands[1], DFmode); DONE; }") + "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }") (define_split - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (match_operand:DF 1 "const_int_operand" ""))] + [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "") + (match_operand:FMOVE64 1 "const_int_operand" ""))] "! TARGET_POWERPC64 && reload_completed && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) || (GET_CODE (operands[0]) == SUBREG @@ -8020,8 +9342,8 @@ int endian = (WORDS_BIG_ENDIAN == 0); HOST_WIDE_INT value = INTVAL (operands[1]); - operands[2] = operand_subword (operands[0], endian, 0, DFmode); - operands[3] = operand_subword (operands[0], 1 - endian, 0, DFmode); + operands[2] = operand_subword (operands[0], endian, 0, <MODE>mode); + operands[3] = operand_subword (operands[0], 1 - endian, 0, <MODE>mode); #if HOST_BITS_PER_WIDE_INT == 32 operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx; #else @@ -8031,8 +9353,8 @@ }") (define_split - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (match_operand:DF 1 "const_double_operand" ""))] + [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "") + (match_operand:FMOVE64 1 "const_double_operand" ""))] "! TARGET_POWERPC64 && reload_completed && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) || (GET_CODE (operands[0]) == SUBREG @@ -8047,17 +9369,17 @@ REAL_VALUE_TYPE rv; REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_DOUBLE (rv, l); + <real_value_to_target> (rv, l); - operands[2] = operand_subword (operands[0], endian, 0, DFmode); - operands[3] = operand_subword (operands[0], 1 - endian, 0, DFmode); + operands[2] = operand_subword (operands[0], endian, 0, <MODE>mode); + operands[3] = operand_subword (operands[0], 1 - endian, 0, <MODE>mode); operands[4] = gen_int_mode (l[endian], SImode); operands[5] = gen_int_mode (l[1 - endian], SImode); }") (define_split - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (match_operand:DF 1 "const_double_operand" ""))] + [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "") + (match_operand:FMOVE64 1 "const_double_operand" ""))] "TARGET_POWERPC64 && reload_completed && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) || (GET_CODE (operands[0]) == SUBREG @@ -8074,7 +9396,7 @@ #endif REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_DOUBLE (rv, l); + <real_value_to_target> (rv, l); operands[2] = gen_lowpart (DImode, operands[0]); /* HIGHPART is lower memory address when WORDS_BIG_ENDIAN. */ @@ -8099,21 +9421,18 @@ ;; since the D-form version of the memory instructions does not need a GPR for ;; reloading. -(define_insn "*movdf_hardfloat32" - [(set (match_operand:DF 0 "nonimmediate_operand" "=m,d,d,ws,?wa,Z,?Z,ws,?wa,wa,Y,r,!r,!r,!r,!r") - (match_operand:DF 1 "input_operand" "d,m,d,Z,Z,ws,wa,ws,wa,j,r,Y,r,G,H,F"))] +(define_insn "*mov<mode>_hardfloat32" + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,wv,Z,wa,wa,Y,r,!r,!r,!r,!r") + (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,wv,wa,j,r,Y,r,G,H,F"))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && (gpc_reg_operand (operands[0], DFmode) - || gpc_reg_operand (operands[1], DFmode))" + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" "@ stfd%U0%X0 %1,%0 lfd%U1%X1 %0,%1 fmr %0,%1 lxsd%U1x %x0,%y1 - lxsd%U1x %x0,%y1 stxsd%U0x %x1,%y0 - stxsd%U0x %x1,%y0 - xxlor %x0,%x1,%x1 xxlor %x0,%x1,%x1 xxlxor %x0,%x0,%x0 # @@ -8122,115 +9441,141 @@ # # #" - [(set_attr "type" "fpstore,fpload,fp,fpload,fpload,fpstore,fpstore,vecsimple,vecsimple,vecsimple,store,load,two,fp,fp,*") - (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,8,8,8,12,16")]) - -(define_insn "*movdf_softfloat32" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,r,r,r,r") - (match_operand:DF 1 "input_operand" "r,Y,r,G,H,F"))] + [(set_attr_alternative "type" + [(if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_u") + (const_string "fpstore"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "fpload_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "fpload_u") + (const_string "fpload"))) + (const_string "fp") + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "fpload_ux") + (const_string "fpload")) + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_ux") + (const_string "fpstore")) + (const_string "vecsimple") + (const_string "vecsimple") + (const_string "store") + (const_string "load") + (const_string "two") + (const_string "fp") + (const_string "fp") + (const_string "*")]) + (set_attr "length" "4,4,4,4,4,4,4,8,8,8,8,12,16")]) + +(define_insn "*mov<mode>_softfloat32" + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,r,r,r") + (match_operand:FMOVE64 1 "input_operand" "r,Y,r,G,H,F"))] "! TARGET_POWERPC64 && ((TARGET_FPRS && TARGET_SINGLE_FLOAT) - || TARGET_SOFT_FLOAT || TARGET_E500_SINGLE) - && (gpc_reg_operand (operands[0], DFmode) - || gpc_reg_operand (operands[1], DFmode))" + || TARGET_SOFT_FLOAT || TARGET_E500_SINGLE + || (<MODE>mode == DDmode && TARGET_E500_DOUBLE)) + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" "#" [(set_attr "type" "store,load,two,*,*,*") (set_attr "length" "8,8,8,8,12,16")]) -;; Reload patterns to support gpr load/store with misaligned mem. -;; and multiple gpr load/store at offset >= 0xfffc -(define_expand "reload_<mode>_store" - [(parallel [(match_operand 0 "memory_operand" "=m") - (match_operand 1 "gpc_reg_operand" "r") - (match_operand:GPR 2 "register_operand" "=&b")])] - "" -{ - rs6000_secondary_reload_gpr (operands[1], operands[0], operands[2], true); - DONE; -}) - -(define_expand "reload_<mode>_load" - [(parallel [(match_operand 0 "gpc_reg_operand" "=r") - (match_operand 1 "memory_operand" "m") - (match_operand:GPR 2 "register_operand" "=b")])] - "" -{ - rs6000_secondary_reload_gpr (operands[0], operands[1], operands[2], false); - DONE; -}) - -; ld/std require word-aligned displacements -> 'Y' constraint. -; List Y->r and r->Y before r->r for reload. -(define_insn "*movdf_hardfloat64_mfpgpr" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,ws,?wa,ws,?wa,Z,?Z,m,d,d,wa,*c*l,!r,*h,!r,!r,!r,r,d") - (match_operand:DF 1 "input_operand" "r,Y,r,ws,?wa,Z,Z,ws,wa,d,m,d,j,r,h,0,G,H,F,d,r"))] - "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS - && TARGET_DOUBLE_FLOAT - && (gpc_reg_operand (operands[0], DFmode) - || gpc_reg_operand (operands[1], DFmode))" - "@ - std%U0%X0 %1,%0 - ld%U1%X1 %0,%1 - mr %0,%1 - xxlor %x0,%x1,%x1 - xxlor %x0,%x1,%x1 - lxsd%U1x %x0,%y1 - lxsd%U1x %x0,%y1 - stxsd%U0x %x1,%y0 - stxsd%U0x %x1,%y0 - stfd%U0%X0 %1,%0 - lfd%U1%X1 %0,%1 - fmr %0,%1 - xxlxor %x0,%x0,%x0 - mt%0 %1 - mf%1 %0 - nop - # - # - # - mftgpr %0,%1 - mffgpr %0,%1" - [(set_attr "type" "store,load,*,fp,fp,fpload,fpload,fpstore,fpstore,fpstore,fpload,fp,vecsimple,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr") - (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16,4,4")]) - ; ld/std require word-aligned displacements -> 'Y' constraint. ; List Y->r and r->Y before r->r for reload. -(define_insn "*movdf_hardfloat64" - [(set (match_operand:DF 0 "nonimmediate_operand" "=m,d,d,Y,r,!r,ws,?wa,Z,?Z,ws,?wa,wa,*c*l,!r,*h,!r,!r,!r") - (match_operand:DF 1 "input_operand" "d,m,d,r,Y,r,Z,Z,ws,wa,ws,wa,j,r,h,0,G,H,F"))] - "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS - && TARGET_DOUBLE_FLOAT - && (gpc_reg_operand (operands[0], DFmode) - || gpc_reg_operand (operands[1], DFmode))" +(define_insn "*mov<mode>_hardfloat64" + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,wv,Z,wa,wa,Y,r,!r,*c*l,!r,*h,!r,!r,!r,r,wg,r,wm") + (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,wv,wa,j,r,Y,r,r,h,0,G,H,F,wg,r,wm,r"))] + "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" "@ stfd%U0%X0 %1,%0 lfd%U1%X1 %0,%1 fmr %0,%1 - std%U0%X0 %1,%0 - ld%U1%X1 %0,%1 - mr %0,%1 - lxsd%U1x %x0,%y1 lxsd%U1x %x0,%y1 stxsd%U0x %x1,%y0 - stxsd%U0x %x1,%y0 - xxlor %x0,%x1,%x1 xxlor %x0,%x1,%x1 xxlxor %x0,%x0,%x0 + std%U0%X0 %1,%0 + ld%U1%X1 %0,%1 + mr %0,%1 mt%0 %1 mf%1 %0 nop # # - #" - [(set_attr "type" "fpstore,fpload,fp,store,load,*,fpload,fpload,fpstore,fpstore,vecsimple,vecsimple,vecsimple,mtjmpr,mfjmpr,*,*,*,*") - (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16")]) - -(define_insn "*movdf_softfloat64" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,r,cl,r,r,r,r,*h") - (match_operand:DF 1 "input_operand" "r,Y,r,r,h,G,H,F,0"))] + # + mftgpr %0,%1 + mffgpr %0,%1 + mfvsrd %0,%x1 + mtvsrd %x0,%1" + [(set_attr_alternative "type" + [(if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_u") + (const_string "fpstore"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "fpload_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "fpload_u") + (const_string "fpload"))) + (const_string "fp") + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "fpload_ux") + (const_string "fpload")) + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_ux") + (const_string "fpstore")) + (const_string "vecsimple") + (const_string "vecsimple") + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "store_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "store_u") + (const_string "store"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (const_string "*") + (const_string "mtjmpr") + (const_string "mfjmpr") + (const_string "*") + (const_string "*") + (const_string "*") + (const_string "*") + (const_string "mftgpr") + (const_string "mffgpr") + (const_string "mftgpr") + (const_string "mffgpr")]) + (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16,4,4,4,4")]) + +(define_insn "*mov<mode>_softfloat64" + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,cl,r,r,r,r,*h") + (match_operand:FMOVE64 1 "input_operand" "r,Y,r,r,h,G,H,F,0"))] "TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS) - && (gpc_reg_operand (operands[0], DFmode) - || gpc_reg_operand (operands[1], DFmode))" + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" "@ std%U0%X0 %1,%0 ld%U1%X1 %0,%1 @@ -8241,38 +9586,87 @@ # # nop" - [(set_attr "type" "store,load,*,mtjmpr,mfjmpr,*,*,*,*") + [(set_attr_alternative "type" + [(if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "store_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "store_u") + (const_string "store"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (const_string "*") + (const_string "mtjmpr") + (const_string "mfjmpr") + (const_string "*") + (const_string "*") + (const_string "*") + (const_string "*")]) (set_attr "length" "4,4,4,4,4,8,12,16,4")]) -(define_expand "movtf" - [(set (match_operand:TF 0 "general_operand" "") - (match_operand:TF 1 "any_operand" ""))] - "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128" - "{ rs6000_emit_move (operands[0], operands[1], TFmode); DONE; }") +(define_expand "mov<mode>" + [(set (match_operand:FMOVE128 0 "general_operand" "") + (match_operand:FMOVE128 1 "any_operand" ""))] + "" + "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }") ;; It's important to list Y->r and r->Y before r->r because otherwise ;; reload, given m->r, will try to pick r->r and reload it, which ;; doesn't make progress. -(define_insn_and_split "*movtf_internal" - [(set (match_operand:TF 0 "nonimmediate_operand" "=m,d,d,Y,r,r") - (match_operand:TF 1 "input_operand" "d,m,d,r,YGHF,r"))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128 - && (gpc_reg_operand (operands[0], TFmode) - || gpc_reg_operand (operands[1], TFmode))" + +;; We can't split little endian direct moves of TDmode, because the words are +;; not swapped like they are for TImode or TFmode. Subregs therefore are +;; problematical. Don't allow direct move for this case. + +(define_insn_and_split "*mov<mode>_64bit_dm" + [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,Y,r,r,r,wm") + (match_operand:FMOVE128 1 "input_operand" "d,m,d,r,YGHF,r,wm,r"))] + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64 + && (<MODE>mode != TDmode || WORDS_BIG_ENDIAN) + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" + "#" + "&& reload_completed" + [(pc)] +{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; } + [(set_attr "length" "8,8,8,12,12,8,8,8")]) + +(define_insn_and_split "*movtd_64bit_nodm" + [(set (match_operand:TD 0 "nonimmediate_operand" "=m,d,d,Y,r,r") + (match_operand:TD 1 "input_operand" "d,m,d,r,YGHF,r"))] + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64 && !WORDS_BIG_ENDIAN + && (gpc_reg_operand (operands[0], TDmode) + || gpc_reg_operand (operands[1], TDmode))" + "#" + "&& reload_completed" + [(pc)] +{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; } + [(set_attr "length" "8,8,8,12,12,8")]) + +(define_insn_and_split "*mov<mode>_32bit" + [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,Y,r,r") + (match_operand:FMOVE128 1 "input_operand" "d,m,d,r,YGHF,r"))] + "TARGET_HARD_FLOAT && TARGET_FPRS && !TARGET_POWERPC64 + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" "#" "&& reload_completed" [(pc)] { rs6000_split_multireg_move (operands[0], operands[1]); DONE; } [(set_attr "length" "8,8,8,20,20,16")]) -(define_insn_and_split "*movtf_softfloat" - [(set (match_operand:TF 0 "rs6000_nonimmediate_operand" "=Y,r,r") - (match_operand:TF 1 "input_operand" "r,YGHF,r"))] - "!TARGET_IEEEQUAD - && (TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_LONG_DOUBLE_128 - && (gpc_reg_operand (operands[0], TFmode) - || gpc_reg_operand (operands[1], TFmode))" +(define_insn_and_split "*mov<mode>_softfloat" + [(set (match_operand:FMOVE128 0 "rs6000_nonimmediate_operand" "=Y,r,r") + (match_operand:FMOVE128 1 "input_operand" "r,YGHF,r"))] + "(TARGET_SOFT_FLOAT || !TARGET_FPRS) + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" "#" "&& reload_completed" [(pc)] @@ -8557,6 +9951,252 @@ operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word); }") +;; Reload helper functions used by rs6000_secondary_reload. The patterns all +;; must have 3 arguments, and scratch register constraint must be a single +;; constraint. + +;; Reload patterns to support gpr load/store with misaligned mem. +;; and multiple gpr load/store at offset >= 0xfffc +(define_expand "reload_<mode>_store" + [(parallel [(match_operand 0 "memory_operand" "=m") + (match_operand 1 "gpc_reg_operand" "r") + (match_operand:GPR 2 "register_operand" "=&b")])] + "" +{ + rs6000_secondary_reload_gpr (operands[1], operands[0], operands[2], true); + DONE; +}) + +(define_expand "reload_<mode>_load" + [(parallel [(match_operand 0 "gpc_reg_operand" "=r") + (match_operand 1 "memory_operand" "m") + (match_operand:GPR 2 "register_operand" "=b")])] + "" +{ + rs6000_secondary_reload_gpr (operands[0], operands[1], operands[2], false); + DONE; +}) + + +;; Power8 merge instructions to allow direct move to/from floating point +;; registers in 32-bit mode. We use TF mode to get two registers to move the +;; individual 32-bit parts across. Subreg doesn't work too well on the TF +;; value, since it is allocated in reload and not all of the flow information +;; is setup for it. We have two patterns to do the two moves between gprs and +;; fprs. There isn't a dependancy between the two, but we could potentially +;; schedule other instructions between the two instructions. TFmode is +;; currently limited to traditional FPR registers. If/when this is changed, we +;; will need to revist %L to make sure it works with VSX registers, or add an +;; %x version of %L. + +(define_insn "p8_fmrgow_<mode>" + [(set (match_operand:FMOVE64X 0 "register_operand" "=d") + (unspec:FMOVE64X [(match_operand:TF 1 "register_operand" "d")] + UNSPEC_P8V_FMRGOW))] + "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "fmrgow %0,%1,%L1" + [(set_attr "type" "vecperm")]) + +(define_insn "p8_mtvsrwz_1" + [(set (match_operand:TF 0 "register_operand" "=d") + (unspec:TF [(match_operand:SI 1 "register_operand" "r")] + UNSPEC_P8V_MTVSRWZ))] + "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "mtvsrwz %x0,%1" + [(set_attr "type" "mftgpr")]) + +(define_insn "p8_mtvsrwz_2" + [(set (match_operand:TF 0 "register_operand" "+d") + (unspec:TF [(match_dup 0) + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_P8V_MTVSRWZ))] + "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "mtvsrwz %L0,%1" + [(set_attr "type" "mftgpr")]) + +(define_insn_and_split "reload_fpr_from_gpr<mode>" + [(set (match_operand:FMOVE64X 0 "register_operand" "=ws") + (unspec:FMOVE64X [(match_operand:FMOVE64X 1 "register_operand" "r")] + UNSPEC_P8V_RELOAD_FROM_GPR)) + (clobber (match_operand:TF 2 "register_operand" "=d"))] + "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx dest = operands[0]; + rtx src = operands[1]; + rtx tmp = operands[2]; + rtx gpr_hi_reg = gen_highpart (SImode, src); + rtx gpr_lo_reg = gen_lowpart (SImode, src); + + emit_insn (gen_p8_mtvsrwz_1 (tmp, gpr_hi_reg)); + emit_insn (gen_p8_mtvsrwz_2 (tmp, gpr_lo_reg)); + emit_insn (gen_p8_fmrgow_<mode> (dest, tmp)); + DONE; +} + [(set_attr "length" "12") + (set_attr "type" "three")]) + +;; Move 128 bit values from GPRs to VSX registers in 64-bit mode +(define_insn "p8_mtvsrd_1" + [(set (match_operand:TF 0 "register_operand" "=ws") + (unspec:TF [(match_operand:DI 1 "register_operand" "r")] + UNSPEC_P8V_MTVSRD))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "mtvsrd %0,%1" + [(set_attr "type" "mftgpr")]) + +(define_insn "p8_mtvsrd_2" + [(set (match_operand:TF 0 "register_operand" "+ws") + (unspec:TF [(match_dup 0) + (match_operand:DI 1 "register_operand" "r")] + UNSPEC_P8V_MTVSRD))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "mtvsrd %L0,%1" + [(set_attr "type" "mftgpr")]) + +(define_insn "p8_xxpermdi_<mode>" + [(set (match_operand:FMOVE128_GPR 0 "register_operand" "=wa") + (unspec:FMOVE128_GPR [(match_operand:TF 1 "register_operand" "ws")] + UNSPEC_P8V_XXPERMDI))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "xxpermdi %x0,%1,%L1,0" + [(set_attr "type" "vecperm")]) + +(define_insn_and_split "reload_vsx_from_gpr<mode>" + [(set (match_operand:FMOVE128_GPR 0 "register_operand" "=wa") + (unspec:FMOVE128_GPR + [(match_operand:FMOVE128_GPR 1 "register_operand" "r")] + UNSPEC_P8V_RELOAD_FROM_GPR)) + (clobber (match_operand:TF 2 "register_operand" "=ws"))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx dest = operands[0]; + rtx src = operands[1]; + rtx tmp = operands[2]; + rtx gpr_hi_reg = gen_highpart (DImode, src); + rtx gpr_lo_reg = gen_lowpart (DImode, src); + + emit_insn (gen_p8_mtvsrd_1 (tmp, gpr_hi_reg)); + emit_insn (gen_p8_mtvsrd_2 (tmp, gpr_lo_reg)); + emit_insn (gen_p8_xxpermdi_<mode> (dest, tmp)); +} + [(set_attr "length" "12") + (set_attr "type" "three")]) + +(define_split + [(set (match_operand:FMOVE128_GPR 0 "nonimmediate_operand" "") + (match_operand:FMOVE128_GPR 1 "input_operand" ""))] + "reload_completed + && (int_reg_operand (operands[0], <MODE>mode) + || int_reg_operand (operands[1], <MODE>mode))" + [(pc)] +{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }) + +;; Move SFmode to a VSX from a GPR register. Because scalar floating point +;; type is stored internally as double precision in the VSX registers, we have +;; to convert it from the vector format. + +(define_insn_and_split "reload_vsx_from_gprsf" + [(set (match_operand:SF 0 "register_operand" "=wa") + (unspec:SF [(match_operand:SF 1 "register_operand" "r")] + UNSPEC_P8V_RELOAD_FROM_GPR)) + (clobber (match_operand:DI 2 "register_operand" "=r"))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + rtx op2 = operands[2]; + rtx op0_di = simplify_gen_subreg (DImode, op0, SFmode, 0); + rtx op1_di = simplify_gen_subreg (DImode, op1, SFmode, 0); + + /* Move SF value to upper 32-bits for xscvspdpn. */ + emit_insn (gen_ashldi3 (op2, op1_di, GEN_INT (32))); + emit_move_insn (op0_di, op2); + emit_insn (gen_vsx_xscvspdpn_directmove (op0, op0)); + DONE; +} + [(set_attr "length" "8") + (set_attr "type" "two")]) + +;; Move 128 bit values from VSX registers to GPRs in 64-bit mode by doing a +;; normal 64-bit move, followed by an xxpermdi to get the bottom 64-bit value, +;; and then doing a move of that. +(define_insn "p8_mfvsrd_3_<mode>" + [(set (match_operand:DF 0 "register_operand" "=r") + (unspec:DF [(match_operand:FMOVE128_GPR 1 "register_operand" "wa")] + UNSPEC_P8V_RELOAD_FROM_VSX))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "mfvsrd %0,%x1" + [(set_attr "type" "mftgpr")]) + +(define_insn_and_split "reload_gpr_from_vsx<mode>" + [(set (match_operand:FMOVE128_GPR 0 "register_operand" "=r") + (unspec:FMOVE128_GPR + [(match_operand:FMOVE128_GPR 1 "register_operand" "wa")] + UNSPEC_P8V_RELOAD_FROM_VSX)) + (clobber (match_operand:FMOVE128_GPR 2 "register_operand" "=wa"))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx dest = operands[0]; + rtx src = operands[1]; + rtx tmp = operands[2]; + rtx gpr_hi_reg = gen_highpart (DFmode, dest); + rtx gpr_lo_reg = gen_lowpart (DFmode, dest); + + emit_insn (gen_p8_mfvsrd_3_<mode> (gpr_hi_reg, src)); + emit_insn (gen_vsx_xxpermdi_<mode> (tmp, src, src, GEN_INT (3))); + emit_insn (gen_p8_mfvsrd_3_<mode> (gpr_lo_reg, tmp)); +} + [(set_attr "length" "12") + (set_attr "type" "three")]) + +;; Move SFmode to a GPR from a VSX register. Because scalar floating point +;; type is stored internally as double precision, we have to convert it to the +;; vector format. + +(define_insn_and_split "reload_gpr_from_vsxsf" + [(set (match_operand:SF 0 "register_operand" "=r") + (unspec:SF [(match_operand:SF 1 "register_operand" "wa")] + UNSPEC_P8V_RELOAD_FROM_VSX)) + (clobber (match_operand:V4SF 2 "register_operand" "=wa"))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + rtx op2 = operands[2]; + rtx diop0 = simplify_gen_subreg (DImode, op0, SFmode, 0); + + emit_insn (gen_vsx_xscvdpspn_scalar (op2, op1)); + emit_insn (gen_p8_mfvsrd_4_disf (diop0, op2)); + emit_insn (gen_lshrdi3 (diop0, diop0, GEN_INT (32))); + DONE; +} + [(set_attr "length" "12") + (set_attr "type" "three")]) + +(define_insn "p8_mfvsrd_4_disf" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(match_operand:V4SF 1 "register_operand" "wa")] + UNSPEC_P8V_RELOAD_FROM_VSX))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "mfvsrd %0,%x1" + [(set_attr "type" "mftgpr")]) + + ;; Next come the multi-word integer load and store and the load and store ;; multiple insns. @@ -8565,8 +10205,8 @@ ;; Use of fprs is disparaged slightly otherwise reload prefers to reload ;; a gpr into a fpr instead of reloading an invalid 'Y' address (define_insn "*movdi_internal32" - [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "=Y,r,r,?m,?*d,?*d,r,?wa") - (match_operand:DI 1 "input_operand" "r,Y,r,d,m,d,IJKnGHF,O"))] + [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "=Y,r,r,?m,?*d,?*d,r") + (match_operand:DI 1 "input_operand" "r,Y,r,d,m,d,IJKnGHF"))] "! TARGET_POWERPC64 && (gpc_reg_operand (operands[0], DImode) || gpc_reg_operand (operands[1], DImode))" @@ -8577,15 +10217,34 @@ stfd%U0%X0 %1,%0 lfd%U1%X1 %0,%1 fmr %0,%1 - # - xxlxor %x0,%x0,%x0" - [(set_attr "type" "store,load,*,fpstore,fpload,fp,*,vecsimple")]) + #" + [(set_attr_alternative "type" + [(const_string "store") + (const_string "load") + (const_string "*") + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_u") + (const_string "fpstore"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "fpload_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "fpload_u") + (const_string "fpload"))) + (const_string "fp") + (const_string "*")])]) (define_split [(set (match_operand:DI 0 "gpc_reg_operand" "") (match_operand:DI 1 "const_int_operand" ""))] "! TARGET_POWERPC64 && reload_completed - && gpr_or_gpr_p (operands[0], operands[1])" + && gpr_or_gpr_p (operands[0], operands[1]) + && !direct_move_p (operands[0], operands[1])" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 1))] " @@ -8607,38 +10266,15 @@ [(set (match_operand:DIFD 0 "rs6000_nonimmediate_operand" "") (match_operand:DIFD 1 "input_operand" ""))] "reload_completed && !TARGET_POWERPC64 - && gpr_or_gpr_p (operands[0], operands[1])" + && gpr_or_gpr_p (operands[0], operands[1]) + && !direct_move_p (operands[0], operands[1])" [(pc)] { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }) -(define_insn "*movdi_mfpgpr" - [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,r,*h,*h,r,?*d") - (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,*h,r,0,*d,r"))] - "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS - && (gpc_reg_operand (operands[0], DImode) - || gpc_reg_operand (operands[1], DImode))" - "@ - std%U0%X0 %1,%0 - ld%U1%X1 %0,%1 - mr %0,%1 - li %0,%1 - lis %0,%v1 - # - stfd%U0%X0 %1,%0 - lfd%U1%X1 %0,%1 - fmr %0,%1 - mf%1 %0 - mt%0 %1 - nop - mftgpr %0,%1 - mffgpr %0,%1" - [(set_attr "type" "store,load,*,*,*,*,fpstore,fpload,fp,mfjmpr,mtjmpr,*,mftgpr,mffgpr") - (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4")]) - (define_insn "*movdi_internal64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,r,*h,*h,?wa") - (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,*h,r,0,O"))] - "TARGET_POWERPC64 && (!TARGET_MFPGPR || !TARGET_HARD_FLOAT || !TARGET_FPRS) + [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,r,*h,*h,r,?*wg,r,?*wm") + (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,*h,r,0,*wg,r,*wm,r"))] + "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], DImode) || gpc_reg_operand (operands[1], DImode))" "@ @@ -8654,9 +10290,52 @@ mf%1 %0 mt%0 %1 nop - xxlxor %x0,%x0,%x0" - [(set_attr "type" "store,load,*,*,*,*,fpstore,fpload,fp,mfjmpr,mtjmpr,*,vecsimple") - (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4")]) + mftgpr %0,%1 + mffgpr %0,%1 + mfvsrd %0,%x1 + mtvsrd %x0,%1" + [(set_attr_alternative "type" + [(if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "store_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "store_u") + (const_string "store"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "load_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "load_u") + (const_string "load"))) + (const_string "*") + (const_string "*") + (const_string "*") + (const_string "*") + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "fpstore_u") + (const_string "fpstore"))) + (if_then_else + (match_test "update_indexed_address_mem (operands[1], VOIDmode)") + (const_string "fpload_ux") + (if_then_else + (match_test "update_address_mem (operands[1], VOIDmode)") + (const_string "fpload_u") + (const_string "fpload"))) + (const_string "fp") + (const_string "mfjmpr") + (const_string "mtjmpr") + (const_string "*") + (const_string "mftgpr") + (const_string "mffgpr") + (const_string "mftgpr") + (const_string "mffgpr")]) + (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4,4")]) ;; immediate value valid for a single instruction hiding in a const_double (define_insn "" @@ -8719,14 +10398,16 @@ FAIL; }") -;; TImode is similar, except that we usually want to compute the address into -;; a register and use lsi/stsi (the exception is during reload). +;; TImode/PTImode is similar, except that we usually want to compute the +;; address into a register and use lsi/stsi (the exception is during reload). -(define_insn "*movti_string" - [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,Y,????r,????r,????r,r") - (match_operand:TI 1 "input_operand" "r,r,Q,Y,r,n"))] +(define_insn "*mov<mode>_string" + [(set (match_operand:TI2 0 "reg_or_mem_operand" "=Q,Y,????r,????r,????r,r") + (match_operand:TI2 1 "input_operand" "r,r,Q,Y,r,n"))] "! TARGET_POWERPC64 - && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))" + && (<MODE>mode != TImode || VECTOR_MEM_NONE_P (TImode)) + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" "* { switch (which_alternative) @@ -8756,27 +10437,32 @@ (const_string "always") (const_string "conditional")))]) -(define_insn "*movti_ppc64" - [(set (match_operand:TI 0 "nonimmediate_operand" "=Y,r,r") - (match_operand:TI 1 "input_operand" "r,Y,r"))] - "(TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode) - || gpc_reg_operand (operands[1], TImode))) - && VECTOR_MEM_NONE_P (TImode)" - "#" - [(set_attr "type" "store,load,*")]) +(define_insn "*mov<mode>_ppc64" + [(set (match_operand:TI2 0 "nonimmediate_operand" "=wQ,Y,r,r,r,r") + (match_operand:TI2 1 "input_operand" "r,r,wQ,Y,r,n"))] + "(TARGET_POWERPC64 && VECTOR_MEM_NONE_P (<MODE>mode) + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode)))" +{ + return rs6000_output_move_128bit (operands); +} + [(set_attr "type" "store,store,load,load,*,*") + (set_attr "length" "8")]) (define_split - [(set (match_operand:TI 0 "gpc_reg_operand" "") - (match_operand:TI 1 "const_double_operand" ""))] - "TARGET_POWERPC64 && VECTOR_MEM_NONE_P (TImode)" + [(set (match_operand:TI2 0 "int_reg_operand" "") + (match_operand:TI2 1 "const_double_operand" ""))] + "TARGET_POWERPC64 + && (VECTOR_MEM_NONE_P (<MODE>mode) + || (reload_completed && INT_REGNO_P (REGNO (operands[0]))))" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] " { operands[2] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN == 0, - TImode); + <MODE>mode); operands[3] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN != 0, - TImode); + <MODE>mode); if (GET_CODE (operands[1]) == CONST_DOUBLE) { operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1])); @@ -8792,10 +10478,12 @@ }") (define_split - [(set (match_operand:TI 0 "nonimmediate_operand" "") - (match_operand:TI 1 "input_operand" ""))] - "reload_completed && VECTOR_MEM_NONE_P (TImode) - && gpr_or_gpr_p (operands[0], operands[1])" + [(set (match_operand:TI2 0 "nonimmediate_operand" "") + (match_operand:TI2 1 "input_operand" ""))] + "reload_completed + && gpr_or_gpr_p (operands[0], operands[1]) + && !direct_move_p (operands[0], operands[1]) + && !quad_load_store_p (operands[0], operands[1])" [(pc)] { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }) @@ -9651,7 +11339,7 @@ (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] UNSPEC_TLSGD) (clobber (reg:SI LR_REGNO))] - "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX" + "HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)" { if (TARGET_CMODEL != CMODEL_SMALL) return "addis %0,%1,%2@got@tlsgd@ha\;addi %0,%0,%2@got@tlsgd@l\;" @@ -9723,7 +11411,7 @@ (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGD))) (set (match_dup 0) (lo_sum:TLSmode (match_dup 3) - (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD)))] + (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGD)))] " { operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode); @@ -9746,7 +11434,8 @@ (define_insn "*tls_gd_low<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") (lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b") - (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] + (unspec:TLSmode [(match_operand:TLSmode 3 "gpc_reg_operand" "b") + (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] UNSPEC_TLSGD)))] "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL" "addi %0,%1,%2@got@tlsgd@l" @@ -9759,7 +11448,8 @@ (unspec:TLSmode [(match_operand:TLSmode 3 "rs6000_tls_symbol_ref" "")] UNSPEC_TLSGD) (clobber (reg:SI LR_REGNO))] - "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX && TARGET_TLS_MARKERS" + "HAVE_AS_TLS && TARGET_TLS_MARKERS + && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)" "bl %z1(%3@tlsgd)\;nop" [(set_attr "type" "branch") (set_attr "length" "8")]) @@ -9791,7 +11481,7 @@ (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")] UNSPEC_TLSLD) (clobber (reg:SI LR_REGNO))] - "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX" + "HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)" { if (TARGET_CMODEL != CMODEL_SMALL) return "addis %0,%1,%&@got@tlsld@ha\;addi %0,%0,%&@got@tlsld@l\;" @@ -9858,7 +11548,7 @@ (unspec:TLSmode [(const_int 0) (match_dup 1)] UNSPEC_TLSLD))) (set (match_dup 0) (lo_sum:TLSmode (match_dup 2) - (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))] + (unspec:TLSmode [(const_int 0) (match_dup 1)] UNSPEC_TLSLD)))] " { operands[2] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode); @@ -9881,7 +11571,9 @@ (define_insn "*tls_ld_low<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") (lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b") - (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))] + (unspec:TLSmode [(const_int 0) + (match_operand:TLSmode 2 "gpc_reg_operand" "b")] + UNSPEC_TLSLD)))] "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL" "addi %0,%1,%&@got@tlsld@l" [(set_attr "length" "4")]) @@ -9892,7 +11584,8 @@ (match_operand 2 "" "g"))) (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD) (clobber (reg:SI LR_REGNO))] - "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX && TARGET_TLS_MARKERS" + "HAVE_AS_TLS && TARGET_TLS_MARKERS + && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)" "bl %z1(%&@tlsld)\;nop" [(set_attr "type" "branch") (set_attr "length" "8")]) @@ -9953,7 +11646,7 @@ (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTDTPREL))) (set (match_dup 0) (lo_sum:TLSmode (match_dup 3) - (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL)))] + (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTDTPREL)))] " { operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode); @@ -9976,7 +11669,8 @@ (define_insn "*tls_got_dtprel_low<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r") (lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b") - (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] + (unspec:TLSmode [(match_operand:TLSmode 3 "gpc_reg_operand" "b") + (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] UNSPEC_TLSGOTDTPREL)))] "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL" "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel@l(%1)" @@ -10022,7 +11716,7 @@ (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTTPREL))) (set (match_dup 0) (lo_sum:TLSmode (match_dup 3) - (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL)))] + (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTTPREL)))] " { operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode); @@ -10045,7 +11739,8 @@ (define_insn "*tls_got_tprel_low<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r") (lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b") - (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] + (unspec:TLSmode [(match_operand:TLSmode 3 "gpc_reg_operand" "b") + (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] UNSPEC_TLSGOTTPREL)))] "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL" "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel@l(%1)" @@ -10261,7 +11956,7 @@ [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (unspec:SI [(const_int 0)] UNSPEC_TOC)) (use (reg:SI 2))])] - "DEFAULT_ABI == ABI_AIX && TARGET_32BIT" + "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) && TARGET_32BIT" "* { char buf[30]; @@ -10276,7 +11971,7 @@ [(parallel [(set (match_operand:DI 0 "gpc_reg_operand" "=r") (unspec:DI [(const_int 0)] UNSPEC_TOC)) (use (reg:DI 2))])] - "DEFAULT_ABI == ABI_AIX && TARGET_64BIT" + "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) && TARGET_64BIT" "* { char buf[30]; @@ -10306,7 +12001,7 @@ [(parallel [(set (reg:SI LR_REGNO) (match_operand:SI 0 "immediate_operand" "s")) (use (unspec [(match_dup 0)] UNSPEC_TOC))])] - "TARGET_ELF && DEFAULT_ABI != ABI_AIX + "TARGET_ELF && DEFAULT_ABI == ABI_V4 && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))" "") @@ -10314,7 +12009,7 @@ [(set (reg:SI LR_REGNO) (match_operand:SI 0 "immediate_operand" "s")) (use (unspec [(match_dup 0)] UNSPEC_TOC))] - "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX + "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4 && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))" "bcl 20,31,%0\\n%0:" [(set_attr "type" "branch") @@ -10324,7 +12019,7 @@ [(set (reg:SI LR_REGNO) (match_operand:SI 0 "immediate_operand" "s")) (use (unspec [(match_dup 0)] UNSPEC_TOC))] - "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX + "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4 && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))" "* { @@ -10344,7 +12039,7 @@ (label_ref (match_operand 1 "" ""))] UNSPEC_TOCPTR)) (match_dup 1)])] - "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2" + "TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2" "") (define_insn "load_toc_v4_PIC_1b_normal" @@ -10353,7 +12048,7 @@ (label_ref (match_operand 1 "" ""))] UNSPEC_TOCPTR)) (match_dup 1)] - "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2" + "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2" "bcl 20,31,$+8\;.long %0-$" [(set_attr "type" "branch") (set_attr "length" "8")]) @@ -10364,7 +12059,7 @@ (label_ref (match_operand 1 "" ""))] UNSPEC_TOCPTR)) (match_dup 1)] - "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2" + "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2" "* { char name[32]; @@ -10382,7 +12077,7 @@ (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b") (minus:SI (match_operand:SI 2 "immediate_operand" "s") (match_operand:SI 3 "immediate_operand" "s")))))] - "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2" + "TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2" "lwz %0,%2-%3(%1)" [(set_attr "type" "load")]) @@ -10392,7 +12087,7 @@ (high:SI (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s") (match_operand:SI 3 "symbol_ref_operand" "s")))))] - "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic" + "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI == ABI_V4 && flag_pic" "addis %0,%1,%2-%3@ha") (define_insn "load_toc_v4_PIC_3c" @@ -10400,7 +12095,7 @@ (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b") (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s") (match_operand:SI 3 "symbol_ref_operand" "s"))))] - "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic" + "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI == ABI_V4 && flag_pic" "addi %0,%1,%2-%3@l") ;; If the TOC is shared over a translation unit, as happens with all @@ -10542,8 +12237,13 @@ operands[0] = XEXP (operands[0], 0); + if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) + { + rs6000_call_aix (NULL_RTX, operands[0], operands[1], operands[2]); + DONE; + } + if (GET_CODE (operands[0]) != SYMBOL_REF - || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[0])) || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0)) { if (INTVAL (operands[2]) & CALL_LONG) @@ -10556,12 +12256,6 @@ operands[0] = force_reg (Pmode, operands[0]); break; - case ABI_AIX: - /* AIX function pointers are really pointers to a three word - area. */ - rs6000_call_indirect_aix (NULL_RTX, operands[0], operands[1]); - DONE; - default: gcc_unreachable (); } @@ -10587,8 +12281,13 @@ operands[1] = XEXP (operands[1], 0); + if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) + { + rs6000_call_aix (operands[0], operands[1], operands[2], operands[3]); + DONE; + } + if (GET_CODE (operands[1]) != SYMBOL_REF - || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[1])) || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0)) { if (INTVAL (operands[3]) & CALL_LONG) @@ -10601,12 +12300,6 @@ operands[1] = force_reg (Pmode, operands[1]); break; - case ABI_AIX: - /* AIX function pointers are really pointers to a three word - area. */ - rs6000_call_indirect_aix (operands[0], operands[1], operands[2]); - DONE; - default: gcc_unreachable (); } @@ -10698,135 +12391,6 @@ [(set_attr "type" "branch") (set_attr "length" "4,8")]) -;; Call to indirect functions with the AIX abi using a 3 word descriptor. -;; Operand0 is the addresss of the function to call -;; Operand1 is the flag for System V.4 for unprototyped or FP registers -;; Operand2 is the location in the function descriptor to load r2 from -;; Operand3 is the stack location to hold the current TOC pointer - -(define_insn "call_indirect_aix<ptrsize>" - [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l")) - (match_operand 1 "" "g,g")) - (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>")) - (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>")) - (use (reg:P STATIC_CHAIN_REGNUM)) - (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_AIX && TARGET_POINTERS_TO_NESTED_FUNCTIONS" - "<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3" - [(set_attr "type" "jmpreg") - (set_attr "length" "12")]) - -;; Like call_indirect_aix<ptrsize>, but no use of the static chain -;; Operand0 is the addresss of the function to call -;; Operand1 is the flag for System V.4 for unprototyped or FP registers -;; Operand2 is the location in the function descriptor to load r2 from -;; Operand3 is the stack location to hold the current TOC pointer - -(define_insn "call_indirect_aix<ptrsize>_nor11" - [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l")) - (match_operand 1 "" "g,g")) - (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>")) - (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>")) - (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_AIX && !TARGET_POINTERS_TO_NESTED_FUNCTIONS" - "<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3" - [(set_attr "type" "jmpreg") - (set_attr "length" "12")]) - -;; Operand0 is the return result of the function -;; Operand1 is the addresss of the function to call -;; Operand2 is the flag for System V.4 for unprototyped or FP registers -;; Operand3 is the location in the function descriptor to load r2 from -;; Operand4 is the stack location to hold the current TOC pointer - -(define_insn "call_value_indirect_aix<ptrsize>" - [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) - (match_operand 2 "" "g,g"))) - (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>")) - (set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>")) - (use (reg:P STATIC_CHAIN_REGNUM)) - (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_AIX && TARGET_POINTERS_TO_NESTED_FUNCTIONS" - "<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4" - [(set_attr "type" "jmpreg") - (set_attr "length" "12")]) - -;; Like call_value_indirect_aix<ptrsize>, but no use of the static chain -;; Operand0 is the return result of the function -;; Operand1 is the addresss of the function to call -;; Operand2 is the flag for System V.4 for unprototyped or FP registers -;; Operand3 is the location in the function descriptor to load r2 from -;; Operand4 is the stack location to hold the current TOC pointer - -(define_insn "call_value_indirect_aix<ptrsize>_nor11" - [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) - (match_operand 2 "" "g,g"))) - (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>")) - (set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>")) - (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_AIX && !TARGET_POINTERS_TO_NESTED_FUNCTIONS" - "<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4" - [(set_attr "type" "jmpreg") - (set_attr "length" "12")]) - -;; Call to function which may be in another module. Restore the TOC -;; pointer (r2) after the call unless this is System V. -;; Operand2 is nonzero if we are using the V.4 calling sequence and -;; either the function was not prototyped, or it was prototyped as a -;; variable argument function. It is > 0 if FP registers were passed -;; and < 0 if they were not. - -(define_insn "*call_nonlocal_aix32" - [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s")) - (match_operand 1 "" "g")) - (use (match_operand:SI 2 "immediate_operand" "O")) - (clobber (reg:SI LR_REGNO))] - "TARGET_32BIT - && DEFAULT_ABI == ABI_AIX - && (INTVAL (operands[2]) & CALL_LONG) == 0" - "bl %z0\;nop" - [(set_attr "type" "branch") - (set_attr "length" "8")]) - -(define_insn "*call_nonlocal_aix64" - [(call (mem:SI (match_operand:DI 0 "symbol_ref_operand" "s")) - (match_operand 1 "" "g")) - (use (match_operand:SI 2 "immediate_operand" "O")) - (clobber (reg:SI LR_REGNO))] - "TARGET_64BIT - && DEFAULT_ABI == ABI_AIX - && (INTVAL (operands[2]) & CALL_LONG) == 0" - "bl %z0\;nop" - [(set_attr "type" "branch") - (set_attr "length" "8")]) - -(define_insn "*call_value_nonlocal_aix32" - [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s")) - (match_operand 2 "" "g"))) - (use (match_operand:SI 3 "immediate_operand" "O")) - (clobber (reg:SI LR_REGNO))] - "TARGET_32BIT - && DEFAULT_ABI == ABI_AIX - && (INTVAL (operands[3]) & CALL_LONG) == 0" - "bl %z1\;nop" - [(set_attr "type" "branch") - (set_attr "length" "8")]) - -(define_insn "*call_value_nonlocal_aix64" - [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:DI 1 "symbol_ref_operand" "s")) - (match_operand 2 "" "g"))) - (use (match_operand:SI 3 "immediate_operand" "O")) - (clobber (reg:SI LR_REGNO))] - "TARGET_64BIT - && DEFAULT_ABI == ABI_AIX - && (INTVAL (operands[3]) & CALL_LONG) == 0" - "bl %z1\;nop" - [(set_attr "type" "branch") - (set_attr "length" "8")]) ;; A function pointer under System V is just a normal pointer ;; operands[0] is the function pointer @@ -11009,6 +12573,104 @@ [(set_attr "type" "branch,branch") (set_attr "length" "4,8")]) + +;; Call to AIX abi function in the same module. + +(define_insn "*call_local_aix<mode>" + [(call (mem:SI (match_operand:P 0 "current_file_function_operand" "s")) + (match_operand 1 "" "g")) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2" + "bl %z0" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + +(define_insn "*call_value_local_aix<mode>" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "current_file_function_operand" "s")) + (match_operand 2 "" "g"))) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2" + "bl %z1" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + +;; Call to AIX abi function which may be in another module. +;; Restore the TOC pointer (r2) after the call. + +(define_insn "*call_nonlocal_aix<mode>" + [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s")) + (match_operand 1 "" "g")) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2" + "bl %z0\;nop" + [(set_attr "type" "branch") + (set_attr "length" "8")]) + +(define_insn "*call_value_nonlocal_aix<mode>" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s")) + (match_operand 2 "" "g"))) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2" + "bl %z1\;nop" + [(set_attr "type" "branch") + (set_attr "length" "8")]) + +;; Call to indirect functions with the AIX abi using a 3 word descriptor. +;; Operand0 is the addresss of the function to call +;; Operand2 is the location in the function descriptor to load r2 from +;; Operand3 is the stack location to hold the current TOC pointer + +(define_insn "*call_indirect_aix<mode>" + [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l")) + (match_operand 1 "" "g,g")) + (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>")) + (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>")) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX" + "<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3" + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) + +(define_insn "*call_value_indirect_aix<mode>" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) + (match_operand 2 "" "g,g"))) + (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>")) + (set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>")) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX" + "<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4" + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) + +;; Call to indirect functions with the ELFv2 ABI. +;; Operand0 is the addresss of the function to call +;; Operand2 is the stack location to hold the current TOC pointer + +(define_insn "*call_indirect_elfv2<mode>" + [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l")) + (match_operand 1 "" "g,g")) + (set (reg:P TOC_REGNUM) (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>")) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_ELFv2" + "b%T0l\;<ptrload> 2,%2" + [(set_attr "type" "jmpreg") + (set_attr "length" "8")]) + +(define_insn "*call_value_indirect_elfv2<mode>" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) + (match_operand 2 "" "g,g"))) + (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>")) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_ELFv2" + "b%T1l\;<ptrload> 2,%3" + [(set_attr "type" "jmpreg") + (set_attr "length" "8")]) + + ;; Call subroutine returning any type. (define_expand "untyped_call" [(parallel [(call (match_operand 0 "" "") @@ -11056,6 +12718,39 @@ gcc_assert (GET_CODE (operands[1]) == CONST_INT); operands[0] = XEXP (operands[0], 0); + + if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) + { + rs6000_sibcall_aix (NULL_RTX, operands[0], operands[1], operands[2]); + DONE; + } +}") + +(define_expand "sibcall_value" + [(parallel [(set (match_operand 0 "register_operand" "") + (call (mem:SI (match_operand 1 "address_operand" "")) + (match_operand 2 "" ""))) + (use (match_operand 3 "" "")) + (use (reg:SI LR_REGNO)) + (simple_return)])] + "" + " +{ +#if TARGET_MACHO + if (MACHOPIC_INDIRECT) + operands[1] = machopic_indirect_call_target (operands[1]); +#endif + + gcc_assert (GET_CODE (operands[1]) == MEM); + gcc_assert (GET_CODE (operands[2]) == CONST_INT); + + operands[1] = XEXP (operands[1], 0); + + if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) + { + rs6000_sibcall_aix (operands[0], operands[1], operands[2], operands[3]); + DONE; + } }") ;; this and similar patterns must be marked as using LR, otherwise @@ -11123,7 +12818,6 @@ [(set_attr "type" "branch") (set_attr "length" "4,8")]) - (define_insn "*sibcall_value_local64" [(set (match_operand 0 "" "") (call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s")) @@ -11145,35 +12839,6 @@ [(set_attr "type" "branch") (set_attr "length" "4,8")]) -(define_insn "*sibcall_nonlocal_aix<mode>" - [(call (mem:SI (match_operand:P 0 "call_operand" "s,c")) - (match_operand 1 "" "g,g")) - (use (match_operand:SI 2 "immediate_operand" "O,O")) - (use (reg:SI LR_REGNO)) - (simple_return)] - "DEFAULT_ABI == ABI_AIX - && (INTVAL (operands[2]) & CALL_LONG) == 0" - "@ - b %z0 - b%T0" - [(set_attr "type" "branch") - (set_attr "length" "4")]) - -(define_insn "*sibcall_value_nonlocal_aix<mode>" - [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:P 1 "call_operand" "s,c")) - (match_operand 2 "" "g,g"))) - (use (match_operand:SI 3 "immediate_operand" "O,O")) - (use (reg:SI LR_REGNO)) - (simple_return)] - "DEFAULT_ABI == ABI_AIX - && (INTVAL (operands[3]) & CALL_LONG) == 0" - "@ - b %z1 - b%T1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) - (define_insn "*sibcall_nonlocal_sysv<mode>" [(call (mem:SI (match_operand:P 0 "call_operand" "s,s,c,c")) (match_operand 1 "" "")) @@ -11204,27 +12869,6 @@ [(set_attr "type" "branch") (set_attr "length" "4,8,4,8")]) -(define_expand "sibcall_value" - [(parallel [(set (match_operand 0 "register_operand" "") - (call (mem:SI (match_operand 1 "address_operand" "")) - (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) - (use (reg:SI LR_REGNO)) - (simple_return)])] - "" - " -{ -#if TARGET_MACHO - if (MACHOPIC_INDIRECT) - operands[1] = machopic_indirect_call_target (operands[1]); -#endif - - gcc_assert (GET_CODE (operands[1]) == MEM); - gcc_assert (GET_CODE (operands[2]) == CONST_INT); - - operands[1] = XEXP (operands[1], 0); -}") - (define_insn "*sibcall_value_nonlocal_sysv<mode>" [(set (match_operand 0 "" "") (call (mem:SI (match_operand:P 1 "call_operand" "s,s,c,c")) @@ -11256,6 +12900,31 @@ [(set_attr "type" "branch") (set_attr "length" "4,8,4,8")]) +;; AIX ABI sibling call patterns. + +(define_insn "*sibcall_aix<mode>" + [(call (mem:SI (match_operand:P 0 "call_operand" "s,c")) + (match_operand 1 "" "g,g")) + (simple_return)] + "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2" + "@ + b %z0 + b%T0" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + +(define_insn "*sibcall_value_aix<mode>" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "call_operand" "s,c")) + (match_operand 2 "" "g,g"))) + (simple_return)] + "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2" + "@ + b %z1 + b%T1" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + (define_expand "sibcall_epilogue" [(use (const_int 0))] "" @@ -11294,7 +12963,14 @@ operands[1] = gen_rtx_REG (Pmode, 0); return "st<wd>%U0%X0 %1,%0"; } - [(set_attr "type" "store") + [(set (attr "type") + (if_then_else + (match_test "update_indexed_address_mem (operands[0], VOIDmode)") + (const_string "store_ux") + (if_then_else + (match_test "update_address_mem (operands[0], VOIDmode)") + (const_string "store_u") + (const_string "store")))) (set_attr "length" "4")]) (define_insn "probe_stack_range<P:mode>" @@ -11589,23 +13265,6 @@ [(set (match_dup 3) (compare:CCUNS (match_dup 1) (match_dup 2))) (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 4)))]) -(define_insn "*cmpsf_internal1" - [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") - (compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "f") - (match_operand:SF 2 "gpc_reg_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" - "fcmpu %0,%1,%2" - [(set_attr "type" "fpcompare")]) - -(define_insn "*cmpdf_internal1" - [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") - (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "d") - (match_operand:DF 2 "gpc_reg_operand" "d")))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && !VECTOR_UNIT_VSX_P (DFmode)" - "fcmpu %0,%1,%2" - [(set_attr "type" "fpcompare")]) - ;; Only need to compare second words if first words equal (define_insn "*cmptf_internal1" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") @@ -13501,6 +15160,14 @@ "mfcr %0" [(set_attr "type" "mfcr")]) +(define_insn "*crsave" + [(match_parallel 0 "crsave_operation" + [(set (match_operand:SI 1 "memory_operand" "=m") + (match_operand:SI 2 "gpc_reg_operand" "r"))])] + "" + "stw %2,%1" + [(set_attr "type" "store")]) + (define_insn "*stmw" [(match_parallel 0 "stmw_operation" [(set (match_operand:SI 1 "memory_operand" "=m") @@ -13885,7 +15552,7 @@ (match_operand:P 2 "gpc_reg_operand" "r")] UNSPEC_BPERM))] "TARGET_POPCNTD" "bpermd %0,%1,%2" - [(set_attr "type" "integer")]) + [(set_attr "type" "popcnt")]) ;; Builtin fma support. Handle @@ -13900,6 +15567,20 @@ "" "") +(define_insn "*fma<mode>4_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>") + (fma:SFDF + (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>,<Fv>") + (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0") + (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>")))] + "TARGET_<MODE>_FPR" + "@ + fmadd<Ftrad> %0,%1,%2,%3 + xsmadda<Fvsx> %x0,%x1,%x2 + xsmaddm<Fvsx> %x0,%x1,%x3" + [(set_attr "type" "fp") + (set_attr "fp_type" "fp_maddsub_<Fs>")]) + ; Altivec only has fma and nfms. (define_expand "fms<mode>4" [(set (match_operand:FMA_F 0 "register_operand" "") @@ -13910,6 +15591,20 @@ "!VECTOR_UNIT_ALTIVEC_P (<MODE>mode)" "") +(define_insn "*fms<mode>4_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>") + (fma:SFDF + (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>,<Fv>") + (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0") + (neg:SFDF (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>"))))] + "TARGET_<MODE>_FPR" + "@ + fmsub<Ftrad> %0,%1,%2,%3 + xsmsuba<Fvsx> %x0,%x1,%x2 + xsmsubm<Fvsx> %x0,%x1,%x3" + [(set_attr "type" "fp") + (set_attr "fp_type" "fp_maddsub_<Fs>")]) + ;; If signed zeros are ignored, -(a * b - c) = -a * b + c. (define_expand "fnma<mode>4" [(set (match_operand:FMA_F 0 "register_operand" "") @@ -13943,6 +15638,21 @@ "!VECTOR_UNIT_ALTIVEC_P (<MODE>mode)" "") +(define_insn "*nfma<mode>4_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>") + (neg:SFDF + (fma:SFDF + (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>,<Fv>") + (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0") + (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>"))))] + "TARGET_<MODE>_FPR" + "@ + fnmadd<Ftrad> %0,%1,%2,%3 + xsnmadda<Fvsx> %x0,%x1,%x2 + xsnmaddm<Fvsx> %x0,%x1,%x3" + [(set_attr "type" "fp") + (set_attr "fp_type" "fp_maddsub_<Fs>")]) + ; Not an official optab name, but used from builtins. (define_expand "nfms<mode>4" [(set (match_operand:FMA_F 0 "register_operand" "") @@ -13954,6 +15664,23 @@ "" "") +(define_insn "*nfmssf4_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>") + (neg:SFDF + (fma:SFDF + (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>,<Fv>") + (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0") + (neg:SFDF + (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>")))))] + "TARGET_<MODE>_FPR" + "@ + fnmsub<Ftrad> %0,%1,%2,%3 + xsnmsuba<Fvsx> %x0,%x1,%x2 + xsnmsubm<Fvsx> %x0,%x1,%x3" + [(set_attr "type" "fp") + (set_attr "fp_type" "fp_maddsub_<Fs>")]) + + (define_expand "rs6000_get_timebase" [(use (match_operand:DI 0 "gpc_reg_operand" ""))] "" @@ -14020,6 +15747,228 @@ }) +;; Power8 fusion support for fusing an addis instruction with a D-form load of +;; a GPR. The addis instruction must be adjacent to the load, and use the same +;; register that is being loaded. The fused ops must be physically adjacent. + +;; We use define_peephole for the actual addis/load, and the register used to +;; hold the addis value must be the same as the register being loaded. We use +;; define_peephole2 to change the register used for addis to be the register +;; being loaded, since we can look at whether it is dead after the load insn. + +(define_peephole + [(set (match_operand:P 0 "base_reg_operand" "") + (match_operand:P 1 "fusion_gpr_addis" "")) + (set (match_operand:INT1 2 "base_reg_operand" "") + (match_operand:INT1 3 "fusion_gpr_mem_load" ""))] + "TARGET_P8_FUSION && fusion_gpr_load_p (operands, false)" +{ + return emit_fusion_gpr_load (operands); +} + [(set_attr "type" "load") + (set_attr "length" "8")]) + +(define_peephole2 + [(set (match_operand:P 0 "base_reg_operand" "") + (match_operand:P 1 "fusion_gpr_addis" "")) + (set (match_operand:INT1 2 "base_reg_operand" "") + (match_operand:INT1 3 "fusion_gpr_mem_load" ""))] + "TARGET_P8_FUSION + && (REGNO (operands[0]) != REGNO (operands[2]) + || GET_CODE (operands[3]) == SIGN_EXTEND) + && fusion_gpr_load_p (operands, true)" + [(const_int 0)] +{ + expand_fusion_gpr_load (operands); + DONE; +}) + + +;; Miscellaneous ISA 2.06 (power7) instructions +(define_insn "addg6s" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "register_operand" "r")] + UNSPEC_ADDG6S))] + "TARGET_POPCNTD" + "addg6s %0,%1,%2" + [(set_attr "type" "integer") + (set_attr "length" "4")]) + +(define_insn "cdtbcd" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "register_operand" "r")] + UNSPEC_CDTBCD))] + "TARGET_POPCNTD" + "cdtbcd %0,%1" + [(set_attr "type" "integer") + (set_attr "length" "4")]) + +(define_insn "cbcdtd" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "register_operand" "r")] + UNSPEC_CBCDTD))] + "TARGET_POPCNTD" + "cbcdtd %0,%1" + [(set_attr "type" "integer") + (set_attr "length" "4")]) + +(define_int_iterator UNSPEC_DIV_EXTEND [UNSPEC_DIVE + UNSPEC_DIVEO + UNSPEC_DIVEU + UNSPEC_DIVEUO]) + +(define_int_attr div_extend [(UNSPEC_DIVE "e") + (UNSPEC_DIVEO "eo") + (UNSPEC_DIVEU "eu") + (UNSPEC_DIVEUO "euo")]) + +(define_insn "div<div_extend>_<mode>" + [(set (match_operand:GPR 0 "register_operand" "=r") + (unspec:GPR [(match_operand:GPR 1 "register_operand" "r") + (match_operand:GPR 2 "register_operand" "r")] + UNSPEC_DIV_EXTEND))] + "TARGET_POPCNTD" + "div<wd><div_extend> %0,%1,%2" + [(set_attr "type" "<idiv_ldiv>")]) + + +;; Pack/unpack 128-bit floating point types that take 2 scalar registers + +; Type of the 64-bit part when packing/unpacking 128-bit floating point types +(define_mode_attr FP128_64 [(TF "DF") (TD "DI")]) + +(define_expand "unpack<mode>" + [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "") + (unspec:<FP128_64> + [(match_operand:FMOVE128 1 "register_operand" "") + (match_operand:QI 2 "const_0_to_1_operand" "")] + UNSPEC_UNPACK_128BIT))] + "" + "") + +;; The Advance Toolchain 7.0-3 added private builtins: __builtin_longdouble_dw0 +;; and __builtin_longdouble_dw1 to optimize glibc. Add support for these +;; builtins here. + +(define_expand "unpacktf_0" + [(set (match_operand:DF 0 "nonimmediate_operand" "") + (unspec:DF [(match_operand:TF 1 "register_operand" "") + (const_int 0)] + UNSPEC_UNPACK_128BIT))] + "" + "") + +(define_expand "unpacktf_1" + [(set (match_operand:DF 0 "nonimmediate_operand" "") + (unspec:DF [(match_operand:TF 1 "register_operand" "") + (const_int 1)] + UNSPEC_UNPACK_128BIT))] + "" + "") + +(define_insn_and_split "unpack<mode>_dm" + [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m,d,r,m") + (unspec:<FP128_64> + [(match_operand:FMOVE128 1 "register_operand" "d,d,r,d,r") + (match_operand:QI 2 "const_0_to_1_operand" "i,i,i,i,i")] + UNSPEC_UNPACK_128BIT))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 3))] +{ + unsigned fp_regno = REGNO (operands[1]) + UINTVAL (operands[2]); + + if (REG_P (operands[0]) && REGNO (operands[0]) == fp_regno) + { + emit_note (NOTE_INSN_DELETED); + DONE; + } + + operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno); +} + [(set_attr "type" "fp,fpstore,mffgpr,mftgpr,store") + (set_attr "length" "4")]) + +(define_insn_and_split "unpack<mode>_nodm" + [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m") + (unspec:<FP128_64> + [(match_operand:FMOVE128 1 "register_operand" "d,d") + (match_operand:QI 2 "const_0_to_1_operand" "i,i")] + UNSPEC_UNPACK_128BIT))] + "!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 3))] +{ + unsigned fp_regno = REGNO (operands[1]) + UINTVAL (operands[2]); + + if (REG_P (operands[0]) && REGNO (operands[0]) == fp_regno) + { + emit_note (NOTE_INSN_DELETED); + DONE; + } + + operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno); +} + [(set_attr "type" "fp,fpstore") + (set_attr "length" "4")]) + +(define_insn_and_split "pack<mode>" + [(set (match_operand:FMOVE128 0 "register_operand" "=d,&d") + (unspec:FMOVE128 + [(match_operand:<FP128_64> 1 "register_operand" "0,d") + (match_operand:<FP128_64> 2 "register_operand" "d,d")] + UNSPEC_PACK_128BIT))] + "" + "@ + fmr %L0,%2 + #" + "&& reload_completed && REGNO (operands[0]) != REGNO (operands[1])" + [(set (match_dup 3) (match_dup 1)) + (set (match_dup 4) (match_dup 2))] +{ + unsigned dest_hi = REGNO (operands[0]); + unsigned dest_lo = dest_hi + 1; + + gcc_assert (!IN_RANGE (REGNO (operands[1]), dest_hi, dest_lo)); + gcc_assert (!IN_RANGE (REGNO (operands[2]), dest_hi, dest_lo)); + + operands[3] = gen_rtx_REG (<FP128_64>mode, dest_hi); + operands[4] = gen_rtx_REG (<FP128_64>mode, dest_lo); +} + [(set_attr "type" "fp,fp") + (set_attr "length" "4,8")]) + +(define_insn "unpackv1ti" + [(set (match_operand:DI 0 "register_operand" "=d,d") + (unspec:DI [(match_operand:V1TI 1 "register_operand" "0,wa") + (match_operand:QI 2 "const_0_to_1_operand" "O,i")] + UNSPEC_UNPACK_128BIT))] + "TARGET_VSX" +{ + if (REGNO (operands[0]) == REGNO (operands[1]) && INTVAL (operands[2]) == 0) + return ASM_COMMENT_START " xxpermdi to same register"; + + operands[3] = GEN_INT (INTVAL (operands[2]) == 0 ? 0 : 3); + return "xxpermdi %x0,%x1,%x1,%3"; +} + [(set_attr "type" "vecperm") + (set_attr "length" "4")]) + +(define_insn "packv1ti" + [(set (match_operand:V1TI 0 "register_operand" "=wa") + (unspec:V1TI + [(match_operand:DI 1 "register_operand" "d") + (match_operand:DI 2 "register_operand" "d")] + UNSPEC_PACK_128BIT))] + "TARGET_VSX" + "xxpermdi %x0,%x1,%x2,0" + [(set_attr "type" "vecperm") + (set_attr "length" "4")]) + + (include "sync.md") (include "vector.md") @@ -14028,3 +15977,5 @@ (include "spe.md") (include "dfp.md") (include "paired.md") +(include "crypto.md") +(include "htm.md") |