aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8/gcc/config/rs6000/rs6000.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8/gcc/config/rs6000/rs6000.md')
-rw-r--r--gcc-4.8/gcc/config/rs6000/rs6000.md4027
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")