;; Machine description for IBM RISC System 6000 (POWER) for GNU C compiler
;; Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
;; Free Software Foundation, Inc.
;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
(CR6_REGNO 74)
(CR7_REGNO 75)
(MAX_CR_REGNO 75)
- (XER_REGNO 76)
+ (CA_REGNO 76)
(FIRST_ALTIVEC_REGNO 77)
(LAST_ALTIVEC_REGNO 108)
(VRSAVE_REGNO 109)
(define_constants
[(UNSPEC_FRSP 0) ; frsp for POWER machines
+ (UNSPEC_PROBE_STACK 4) ; probe stack memory reference
(UNSPEC_TIE 5) ; tie stack contents and stack pointer
(UNSPEC_TOCPTR 6) ; address of a word pointing to the TOC
(UNSPEC_TOC 7) ; address of the TOC (more-or-less)
(UNSPEC_RSQRT 48)
(UNSPEC_TOCREL 49)
(UNSPEC_MACHOPIC_OFFSET 50)
+ (UNSPEC_BPERM 51)
])
;;
\f
;; 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,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr"
+(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,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel"
(const_string "integer"))
;; Define floating point instruction sub-types for use with Xfpu.md
;; Processor type -- this attribute must exactly match the processor_type
;; enumeration in rs6000.h.
-(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,cell"
+(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,power4,power5,power6,power7,cell,ppca2"
(const (symbol_ref "rs6000_cpu_attr")))
(include "mpc.md")
(include "40x.md")
(include "440.md")
+(include "476.md")
(include "603.md")
(include "6xx.md")
(include "7xx.md")
(include "8540.md")
(include "e300c2c3.md")
(include "e500mc.md")
+(include "e500mc64.md")
(include "power4.md")
(include "power5.md")
(include "power6.md")
+(include "power7.md")
(include "cell.md")
(include "xfpu.md")
+(include "a2.md")
(include "predicates.md")
(include "constraints.md")
(define_mode_iterator SDI [SI DI])
; The size of a pointer. Also, the size of the value that a record-condition
-; (one with a '.') will compare.
+; (one with a '.') will compare; and the size used for arithmetic carries.
(define_mode_iterator P [(SI "TARGET_32BIT") (DI "TARGET_64BIT")])
; Any hardware-supported floating-point mode
(DD "TARGET_DFP")
(TD "TARGET_DFP")])
+; 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])
+
+;; Iterator for reciprocal estimate instructions
+(define_mode_iterator RECIPF [SF DF V4SF V2DF])
+
; 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")])
; DImode bits
(define_mode_attr dbits [(QI "56") (HI "48") (SI "32")])
+;; ISEL/ISEL64 target selection
+(define_mode_attr sel [(SI "") (DI "64")])
+
+;; Suffix for reload patterns
+(define_mode_attr ptrsize [(SI "32bit")
+ (DI "64bit")])
+
+(define_mode_attr tptrsize [(SI "TARGET_32BIT")
+ (DI "TARGET_64BIT")])
+
+(define_mode_attr mptrsize [(SI "si")
+ (DI "di")])
+
+(define_mode_attr rreg [(SF "f")
+ (DF "Ws")
+ (V4SF "Wf")
+ (V2DF "Wd")])
+
\f
;; Start with fixed-point load and store insns. Here we put only the more
;; complex forms. Basic data transfer is done later.
"@
{andil.|andi.} %2,%1,0xff
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
{andil.|andi.} %0,%1,0xff
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
{andil.|andi.} %2,%1,0xff
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
{andil.|andi.} %0,%1,0xff
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
{andil.|andi.} %2,%1,0xffff
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
{andil.|andi.} %0,%1,0xffff
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
[(set_attr "type" "compare")
(set_attr "length" "4,8")])
\f
-;; IBM 405, 440 and 464 half-word multiplication operations.
+;; IBM 405, 440, 464 and 476 half-word multiplication operations.
(define_insn "*macchwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
"mullhwu %0, %1, %2"
[(set_attr "type" "imul3")])
\f
-;; IBM 405, 440 and 464 string-search dlmzb instruction support.
+;; IBM 405, 440, 464 and 476 string-search dlmzb instruction support.
(define_insn "dlmzb"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
"@
nor. %2,%1,%1
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
nor. %0,%1,%1
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"TARGET_POWER"
"abs %0,%1")
-(define_insn_and_split "abssi2_isel"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (abs:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
- (clobber (match_scratch:SI 2 "=&b"))
+(define_insn_and_split "abs<mode>2_isel"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (abs:GPR (match_operand:GPR 1 "gpc_reg_operand" "b")))
+ (clobber (match_scratch:GPR 2 "=&b"))
(clobber (match_scratch:CC 3 "=y"))]
"TARGET_ISEL"
"#"
"&& reload_completed"
- [(set (match_dup 2) (neg:SI (match_dup 1)))
+ [(set (match_dup 2) (neg:GPR (match_dup 1)))
(set (match_dup 3)
(compare:CC (match_dup 1)
(const_int 0)))
(set (match_dup 0)
- (if_then_else:SI (ge (match_dup 3)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
+ (if_then_else:GPR (ge (match_dup 3)
+ (const_int 0))
+ (match_dup 1)
+ (match_dup 2)))]
+ "")
+
+(define_insn_and_split "nabs<mode>2_isel"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (neg:GPR (abs:GPR (match_operand:GPR 1 "gpc_reg_operand" "b"))))
+ (clobber (match_scratch:GPR 2 "=&b"))
+ (clobber (match_scratch:CC 3 "=y"))]
+ "TARGET_ISEL"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2) (neg:GPR (match_dup 1)))
+ (set (match_dup 3)
+ (compare:CC (match_dup 1)
+ (const_int 0)))
+ (set (match_dup 0)
+ (if_then_else:GPR (ge (match_dup 3)
+ (const_int 0))
+ (match_dup 2)
+ (match_dup 1)))]
"")
(define_insn_and_split "abssi2_nopower"
"TARGET_POPCNTB"
"popcntb %0,%1")
+(define_insn "popcntwsi2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (popcount:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
+ "TARGET_POPCNTD"
+ "popcntw %0,%1")
+
+(define_insn "popcntddi2"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (popcount:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
+ "TARGET_POPCNTD && TARGET_POWERPC64"
+ "popcntd %0,%1")
+
(define_expand "popcount<mode>2"
[(set (match_operand:GPR 0 "gpc_reg_operand" "")
(popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))]
- "TARGET_POPCNTB"
+ "TARGET_POPCNTB || TARGET_POPCNTD"
{
rs6000_emit_popcount (operands[0], operands[1]);
DONE;
DONE;
})
-(define_insn "bswapsi2"
+;; Since the hardware zeros the upper part of the register, save generating the
+;; AND immediate if we are converting to unsigned
+(define_insn "*bswaphi2_extenddi"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (zero_extend:DI
+ (bswap:HI (match_operand:HI 1 "memory_operand" "Z"))))]
+ "TARGET_POWERPC64"
+ "lhbrx %0,%y1"
+ [(set_attr "length" "4")
+ (set_attr "type" "load")])
+
+(define_insn "*bswaphi2_extendsi"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (zero_extend:SI
+ (bswap:HI (match_operand:HI 1 "memory_operand" "Z"))))]
+ "TARGET_POWERPC"
+ "lhbrx %0,%y1"
+ [(set_attr "length" "4")
+ (set_attr "type" "load")])
+
+(define_expand "bswaphi2"
+ [(parallel [(set (match_operand:HI 0 "reg_or_mem_operand" "")
+ (bswap:HI
+ (match_operand:HI 1 "reg_or_mem_operand" "")))
+ (clobber (match_scratch:SI 2 ""))])]
+ ""
+{
+ if (!REG_P (operands[0]) && !REG_P (operands[1]))
+ operands[1] = force_reg (HImode, operands[1]);
+})
+
+(define_insn "bswaphi2_internal"
+ [(set (match_operand:HI 0 "reg_or_mem_operand" "=r,Z,&r")
+ (bswap:HI
+ (match_operand:HI 1 "reg_or_mem_operand" "Z,r,r")))
+ (clobber (match_scratch:SI 2 "=X,X,&r"))]
+ "TARGET_POWERPC"
+ "@
+ lhbrx %0,%y1
+ sthbrx %1,%y0
+ #"
+ [(set_attr "length" "4,4,12")
+ (set_attr "type" "load,store,*")])
+
+(define_split
+ [(set (match_operand:HI 0 "gpc_reg_operand" "")
+ (bswap:HI (match_operand:HI 1 "gpc_reg_operand" "")))
+ (clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
+ "TARGET_POWERPC && reload_completed"
+ [(set (match_dup 3)
+ (zero_extract:SI (match_dup 4)
+ (const_int 8)
+ (const_int 16)))
+ (set (match_dup 2)
+ (and:SI (ashift:SI (match_dup 4)
+ (const_int 8))
+ (const_int 65280))) ;; 0xff00
+ (set (match_dup 3)
+ (ior:SI (match_dup 3)
+ (match_dup 2)))]
+ "
+{
+ operands[3] = simplify_gen_subreg (SImode, operands[0], HImode, 0);
+ operands[4] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
+}")
+
+(define_insn "*bswapsi2_extenddi"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (zero_extend:DI
+ (bswap:SI (match_operand:SI 1 "memory_operand" "Z"))))]
+ "TARGET_POWERPC64"
+ "lwbrx %0,%y1"
+ [(set_attr "length" "4")
+ (set_attr "type" "load")])
+
+(define_expand "bswapsi2"
+ [(set (match_operand:SI 0 "reg_or_mem_operand" "")
+ (bswap:SI
+ (match_operand:SI 1 "reg_or_mem_operand" "")))]
+ ""
+{
+ if (!REG_P (operands[0]) && !REG_P (operands[1]))
+ operands[1] = force_reg (SImode, operands[1]);
+})
+
+(define_insn "*bswapsi2_internal"
[(set (match_operand:SI 0 "reg_or_mem_operand" "=r,Z,&r")
- (bswap:SI (match_operand:SI 1 "reg_or_mem_operand" "Z,r,r")))]
+ (bswap:SI
+ (match_operand:SI 1 "reg_or_mem_operand" "Z,r,r")))]
""
"@
{lbrx|lwbrx} %0,%y1
{stbrx|stwbrx} %1,%y0
#"
- [(set_attr "length" "4,4,12")])
+ [(set_attr "length" "4,4,12")
+ (set_attr "type" "load,store,*")])
(define_split
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(const_int 16)))]
"")
+(define_expand "bswapdi2"
+ [(parallel [(set (match_operand:DI 0 "reg_or_mem_operand" "")
+ (bswap:DI
+ (match_operand:DI 1 "reg_or_mem_operand" "")))
+ (clobber (match_scratch:DI 2 ""))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (match_scratch:DI 4 ""))])]
+ ""
+{
+ if (!REG_P (operands[0]) && !REG_P (operands[1]))
+ operands[1] = force_reg (DImode, operands[1]);
+
+ if (!TARGET_POWERPC64)
+ {
+ /* 32-bit mode needs fewer scratch registers, but 32-bit addressing mode
+ that uses 64-bit registers needs the same scratch registers as 64-bit
+ mode. */
+ emit_insn (gen_bswapdi2_32bit (operands[0], operands[1]));
+ DONE;
+ }
+})
+
+;; Power7/cell has ldbrx/stdbrx, so use it directly
+(define_insn "*bswapdi2_ldbrx"
+ [(set (match_operand:DI 0 "reg_or_mem_operand" "=&r,Z,??&r")
+ (bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
+ (clobber (match_scratch:DI 2 "=X,X,&r"))
+ (clobber (match_scratch:DI 3 "=X,X,&r"))
+ (clobber (match_scratch:DI 4 "=X,X,&r"))]
+ "TARGET_POWERPC64 && TARGET_LDBRX
+ && (REG_P (operands[0]) || REG_P (operands[1]))"
+ "@
+ ldbrx %0,%y1
+ stdbrx %1,%y0
+ #"
+ [(set_attr "length" "4,4,36")
+ (set_attr "type" "load,store,*")])
+
+;; Non-power7/cell, fall back to use lwbrx/stwbrx
+(define_insn "*bswapdi2_64bit"
+ [(set (match_operand:DI 0 "reg_or_mem_operand" "=&r,Z,??&r")
+ (bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
+ (clobber (match_scratch:DI 2 "=&b,&b,&r"))
+ (clobber (match_scratch:DI 3 "=&r,&r,&r"))
+ (clobber (match_scratch:DI 4 "=&r,X,&r"))]
+ "TARGET_POWERPC64 && !TARGET_LDBRX
+ && (REG_P (operands[0]) || REG_P (operands[1]))"
+ "#"
+ [(set_attr "length" "16,12,36")])
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand" "")))
+ (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
+ (clobber (match_operand:DI 3 "gpc_reg_operand" ""))
+ (clobber (match_operand:DI 4 "gpc_reg_operand" ""))]
+ "TARGET_POWERPC64 && !TARGET_LDBRX && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx op2 = operands[2];
+ rtx op3 = operands[3];
+ rtx op4 = operands[4];
+ rtx op3_32 = simplify_gen_subreg (SImode, op3, DImode, 4);
+ rtx op4_32 = simplify_gen_subreg (SImode, op4, DImode, 4);
+ rtx addr1;
+ rtx addr2;
+ rtx word_high;
+ rtx word_low;
+
+ addr1 = XEXP (src, 0);
+ if (GET_CODE (addr1) == PLUS)
+ {
+ emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4)));
+ addr2 = gen_rtx_PLUS (Pmode, op2, XEXP (addr1, 1));
+ }
+ else
+ {
+ emit_move_insn (op2, GEN_INT (4));
+ addr2 = gen_rtx_PLUS (Pmode, op2, addr1);
+ }
+
+ if (BYTES_BIG_ENDIAN)
+ {
+ word_high = change_address (src, SImode, addr1);
+ word_low = change_address (src, SImode, addr2);
+ }
+ else
+ {
+ word_high = change_address (src, SImode, addr2);
+ word_low = change_address (src, SImode, addr1);
+ }
+
+ emit_insn (gen_bswapsi2 (op3_32, word_low));
+ emit_insn (gen_bswapsi2 (op4_32, word_high));
+ emit_insn (gen_ashldi3 (dest, op3, GEN_INT (32)));
+ emit_insn (gen_iordi3 (dest, dest, op4));
+}")
+
+(define_split
+ [(set (match_operand:DI 0 "indexed_or_indirect_operand" "")
+ (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
+ (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
+ (clobber (match_operand:DI 3 "gpc_reg_operand" ""))
+ (clobber (match_operand:DI 4 "" ""))]
+ "TARGET_POWERPC64 && !TARGET_LDBRX && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx op2 = operands[2];
+ rtx op3 = operands[3];
+ rtx src_si = simplify_gen_subreg (SImode, src, DImode, 4);
+ rtx op3_si = simplify_gen_subreg (SImode, op3, DImode, 4);
+ rtx addr1;
+ rtx addr2;
+ rtx word_high;
+ rtx word_low;
+
+ addr1 = XEXP (dest, 0);
+ if (GET_CODE (addr1) == PLUS)
+ {
+ emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4)));
+ addr2 = gen_rtx_PLUS (Pmode, op2, XEXP (addr1, 1));
+ }
+ else
+ {
+ emit_move_insn (op2, GEN_INT (4));
+ addr2 = gen_rtx_PLUS (Pmode, op2, addr1);
+ }
+
+ emit_insn (gen_lshrdi3 (op3, src, GEN_INT (32)));
+ if (BYTES_BIG_ENDIAN)
+ {
+ word_high = change_address (dest, SImode, addr1);
+ word_low = change_address (dest, SImode, addr2);
+ emit_insn (gen_bswapsi2 (word_high, src_si));
+ emit_insn (gen_bswapsi2 (word_low, op3_si));
+ }
+ else
+ {
+ word_high = change_address (dest, SImode, addr2);
+ word_low = change_address (dest, SImode, addr1);
+ emit_insn (gen_bswapsi2 (word_low, src_si));
+ emit_insn (gen_bswapsi2 (word_high, op3_si));
+ }
+}")
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
+ (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
+ (clobber (match_operand:DI 3 "gpc_reg_operand" ""))
+ (clobber (match_operand:DI 4 "" ""))]
+ "TARGET_POWERPC64 && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx op2 = operands[2];
+ rtx op3 = operands[3];
+ rtx dest_si = simplify_gen_subreg (SImode, dest, DImode, 4);
+ rtx src_si = simplify_gen_subreg (SImode, src, DImode, 4);
+ rtx op2_si = simplify_gen_subreg (SImode, op2, DImode, 4);
+ rtx op3_si = simplify_gen_subreg (SImode, op3, DImode, 4);
+
+ emit_insn (gen_lshrdi3 (op2, src, GEN_INT (32)));
+ emit_insn (gen_bswapsi2 (dest_si, src_si));
+ emit_insn (gen_bswapsi2 (op3_si, op2_si));
+ emit_insn (gen_ashldi3 (dest, dest, GEN_INT (32)));
+ emit_insn (gen_iordi3 (dest, dest, op3));
+}")
+
+(define_insn "bswapdi2_32bit"
+ [(set (match_operand:DI 0 "reg_or_mem_operand" "=&r,Z,??&r")
+ (bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
+ (clobber (match_scratch:SI 2 "=&b,&b,X"))]
+ "!TARGET_POWERPC64 && (REG_P (operands[0]) || REG_P (operands[1]))"
+ "#"
+ [(set_attr "length" "16,12,36")])
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand" "")))
+ (clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
+ "!TARGET_POWERPC64 && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx op2 = operands[2];
+ rtx dest_hi = simplify_gen_subreg (SImode, dest, DImode, 0);
+ rtx dest_lo = simplify_gen_subreg (SImode, dest, DImode, 4);
+ rtx addr1;
+ rtx addr2;
+ rtx word_high;
+ rtx word_low;
+
+ addr1 = XEXP (src, 0);
+ if (GET_CODE (addr1) == PLUS)
+ {
+ emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4)));
+ addr2 = gen_rtx_PLUS (SImode, op2, XEXP (addr1, 1));
+ }
+ else
+ {
+ emit_move_insn (op2, GEN_INT (4));
+ addr2 = gen_rtx_PLUS (SImode, op2, addr1);
+ }
+
+ if (BYTES_BIG_ENDIAN)
+ {
+ word_high = change_address (src, SImode, addr1);
+ word_low = change_address (src, SImode, addr2);
+ }
+ else
+ {
+ word_high = change_address (src, SImode, addr2);
+ word_low = change_address (src, SImode, addr1);
+ }
+
+ emit_insn (gen_bswapsi2 (dest_hi, word_low));
+ emit_insn (gen_bswapsi2 (dest_lo, word_high));
+}")
+
+(define_split
+ [(set (match_operand:DI 0 "indexed_or_indirect_operand" "")
+ (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
+ (clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
+ "!TARGET_POWERPC64 && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx op2 = operands[2];
+ rtx src_high = simplify_gen_subreg (SImode, src, DImode, 0);
+ rtx src_low = simplify_gen_subreg (SImode, src, DImode, 4);
+ rtx addr1;
+ rtx addr2;
+ rtx word_high;
+ rtx word_low;
+
+ addr1 = XEXP (dest, 0);
+ if (GET_CODE (addr1) == PLUS)
+ {
+ emit_insn (gen_add3_insn (op2, XEXP (addr1, 0), GEN_INT (4)));
+ addr2 = gen_rtx_PLUS (SImode, op2, XEXP (addr1, 1));
+ }
+ else
+ {
+ emit_move_insn (op2, GEN_INT (4));
+ addr2 = gen_rtx_PLUS (SImode, op2, addr1);
+ }
+
+ if (BYTES_BIG_ENDIAN)
+ {
+ word_high = change_address (dest, SImode, addr1);
+ word_low = change_address (dest, SImode, addr2);
+ }
+ else
+ {
+ word_high = change_address (dest, SImode, addr2);
+ word_low = change_address (dest, SImode, addr1);
+ }
+
+ emit_insn (gen_bswapsi2 (word_high, src_low));
+ emit_insn (gen_bswapsi2 (word_low, src_high));
+}")
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
+ (clobber (match_operand:SI 2 "" ""))]
+ "!TARGET_POWERPC64 && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx src_high = simplify_gen_subreg (SImode, src, DImode, 0);
+ rtx src_low = simplify_gen_subreg (SImode, src, DImode, 4);
+ rtx dest_high = simplify_gen_subreg (SImode, dest, DImode, 0);
+ rtx dest_low = simplify_gen_subreg (SImode, dest, DImode, 4);
+
+ emit_insn (gen_bswapsi2 (dest_high, src_low));
+ emit_insn (gen_bswapsi2 (dest_low, src_high));
+}")
+
(define_expand "mulsi3"
[(use (match_operand:SI 0 "gpc_reg_operand" ""))
(use (match_operand:SI 1 "gpc_reg_operand" ""))
{rlinm|rlwinm} %0,%1,0,%m2,%M2
{andil.|andi.} %0,%1,%b2
{andiu.|andis.} %0,%1,%u2"
- [(set_attr "type" "*,*,compare,compare")])
+ [(set_attr "type" "*,*,fast_compare,fast_compare")])
(define_insn "andsi3_nomc"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
#
#
#"
- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
+ [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
+ compare,compare,compare,compare")
(set_attr "length" "4,4,4,4,8,8,8,8")])
(define_insn "*andsi3_internal3_mc"
#
#
#"
- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
+ [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
+ compare,compare,compare")
(set_attr "length" "8,4,4,4,8,8,8,8")])
(define_split
#
#
#"
- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
+ [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
+ compare,compare,compare,compare")
(set_attr "length" "4,4,4,4,8,8,8,8")])
(define_insn "*andsi3_internal5_mc"
#
#
#"
- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
+ [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
+ compare,compare,compare")
(set_attr "length" "8,4,4,4,8,8,8,8")])
(define_split
"@
%q4. %3,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
%q4. %0,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
%q4. %3,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
%q4. %0,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
{rlinm|rlwinm} %0,%1,%h2,0xffffffff"
[(set_attr "type" "var_shift_rotate,integer")])
+(define_insn "*rotlsi3_64"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+ (zero_extend:DI
+ (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+ (match_operand:SI 2 "reg_or_cint_operand" "r,i"))))]
+ "TARGET_64BIT"
+ "@
+ {rlnm|rlwnm} %0,%1,%2,0xffffffff
+ {rlinm|rlwinm} %0,%1,%h2,0xffffffff"
+ [(set_attr "type" "var_shift_rotate,integer")])
+
(define_insn "*rotlsi3_internal2"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
(compare:CC (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
{sli|slwi} %0,%1,%h2"
[(set_attr "type" "var_shift_rotate,shift")])
+(define_insn "*ashlsi3_64"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+ (zero_extend:DI
+ (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+ (match_operand:SI 2 "reg_or_cint_operand" "r,i"))))]
+ "TARGET_POWERPC64"
+ "@
+ {sl|slw} %0,%1,%2
+ {sli|slwi} %0,%1,%h2"
+ [(set_attr "type" "var_shift_rotate,shift")])
+
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
(compare:CC (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
{sri|srwi} %0,%1,%h2"
[(set_attr "type" "integer,var_shift_rotate,shift")])
+(define_insn "*lshrsi3_64"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+ (zero_extend:DI
+ (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+ (match_operand:SI 2 "reg_or_cint_operand" "r,i"))))]
+ "TARGET_POWERPC64"
+ "@
+ {sr|srw} %0,%1,%2
+ {sri|srwi} %0,%1,%h2"
+ [(set_attr "type" "var_shift_rotate,shift")])
+
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,?y,?y,?y")
(compare:CC (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r,r,r")
{srai|srawi} %0,%1,%h2"
[(set_attr "type" "var_shift_rotate,shift")])
+(define_insn "*ashrsi3_64"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+ (sign_extend:DI
+ (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+ (match_operand:SI 2 "reg_or_cint_operand" "r,i"))))]
+ "TARGET_POWERPC64"
+ "@
+ {sra|sraw} %0,%1,%2
+ {srai|srawi} %0,%1,%h2"
+ [(set_attr "type" "var_shift_rotate,shift")])
+
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
(compare:CC (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
[(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
(set_attr "length" "4,4,8,8")])
\f
+;; Builtins to replace a division to generate FRE reciprocal estimate
+;; instructions and the necessary fixup instructions
+(define_expand "recip<mode>3"
+ [(match_operand:RECIPF 0 "gpc_reg_operand" "")
+ (match_operand:RECIPF 1 "gpc_reg_operand" "")
+ (match_operand:RECIPF 2 "gpc_reg_operand" "")]
+ "RS6000_RECIP_HAVE_RE_P (<MODE>mode)"
+{
+ rs6000_emit_swdiv (operands[0], operands[1], operands[2], false);
+ DONE;
+})
+
+;; Split to create division from FRE/FRES/etc. and fixup instead of the normal
+;; hardware division. This is only done before register allocation and with
+;; -ffast-math. This must appear before the divsf3/divdf3 insns.
+(define_split
+ [(set (match_operand:RECIPF 0 "gpc_reg_operand" "")
+ (div:RECIPF (match_operand 1 "gpc_reg_operand" "")
+ (match_operand 2 "gpc_reg_operand" "")))]
+ "RS6000_RECIP_AUTO_RE_P (<MODE>mode)
+ && can_create_pseudo_p () && optimize_insn_for_speed_p ()
+ && flag_finite_math_only && !flag_trapping_math && flag_reciprocal_math"
+ [(const_int 0)]
+{
+ rs6000_emit_swdiv (operands[0], operands[1], operands[2], true);
+ DONE;
+})
+
+;; Builtins to replace 1/sqrt(x) with instructions using RSQRTE and the
+;; appropriate fixup.
+(define_expand "rsqrt<mode>2"
+ [(match_operand:RECIPF 0 "gpc_reg_operand" "")
+ (match_operand:RECIPF 1 "gpc_reg_operand" "")]
+ "RS6000_RECIP_HAVE_RSQRT_P (<MODE>mode)"
+{
+ rs6000_emit_swrsqrt (operands[0], operands[1]);
+ DONE;
+})
+\f
(define_split
[(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
(compare:CC (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "")
"{fd|fdiv} %0,%1,%2"
[(set_attr "type" "ddiv")])
-(define_expand "recipsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")]
- UNSPEC_FRES))]
- "TARGET_RECIP && TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT && !optimize_size
- && flag_finite_math_only && !flag_trapping_math"
-{
- rs6000_emit_swdivsf (operands[0], operands[1], operands[2]);
- DONE;
-})
-
(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_PPC_GFXOPT && flag_finite_math_only"
+ "TARGET_FRES"
"fres %0,%1"
[(set_attr "type" "fp")])
-(define_insn ""
+(define_insn "*fmaddsf4_powerpc"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn ""
+(define_insn "*fmaddsf4_power"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
"{fma|fmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
-(define_insn ""
+(define_insn "*fmsubsf4_powerpc"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn ""
+(define_insn "*fmsubsf4_power"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
"{fms|fmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
-(define_insn ""
+(define_insn "*fnmaddsf4_powerpc_1"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(neg:SF (plus:SF (mult: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_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
- && TARGET_SINGLE_FLOAT && HONOR_SIGNED_ZEROS (SFmode)"
+ && TARGET_SINGLE_FLOAT"
"fnmadds %0,%1,%2,%3"
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn ""
+(define_insn "*fnmaddsf4_powerpc_2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
(match_operand:SF 2 "gpc_reg_operand" "f"))
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn ""
+(define_insn "*fnmaddsf4_power_1"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
"{fnma|fnmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
-(define_insn ""
+(define_insn "*fnmaddsf4_power_2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
(match_operand:SF 2 "gpc_reg_operand" "f"))
"{fnma|fnmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
-(define_insn ""
+(define_insn "*fnmsubsf4_powerpc_1"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(neg:SF (minus:SF (mult: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_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
- && TARGET_SINGLE_FLOAT && HONOR_SIGNED_ZEROS (SFmode)"
+ && TARGET_SINGLE_FLOAT"
"fnmsubs %0,%1,%2,%3"
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn ""
+(define_insn "*fnmsubsf4_powerpc_2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
(mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn ""
+(define_insn "*fnmsubsf4_power_1"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
"{fnms|fnmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
-(define_insn ""
+(define_insn "*fnmsubsf4_power_2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
(mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
"fsqrt %0,%1"
[(set_attr "type" "dsqrt")])
-(define_expand "rsqrtsf2"
+(define_insn "*rsqrtsf_internal1"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")]
UNSPEC_RSQRT))]
- "TARGET_RECIP && TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT && !optimize_size
- && flag_finite_math_only && !flag_trapping_math"
-{
- rs6000_emit_swrsqrtsf (operands[0], operands[1]);
- DONE;
-})
-
-(define_insn "*rsqrt_internal1"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")]
- UNSPEC_RSQRT))]
- "TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT"
- "frsqrte %0,%1"
+ "TARGET_FRSQRTES"
+ "frsqrtes %0,%1"
[(set_attr "type" "fp")])
(define_expand "copysignsf3"
(match_dup 5))
(match_dup 3)
(match_dup 4)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
- && !HONOR_NANS (SFmode) && !HONOR_SIGNED_ZEROS (SFmode)"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+ && ((TARGET_PPC_GFXOPT
+ && !HONOR_NANS (SFmode)
+ && !HONOR_SIGNED_ZEROS (SFmode))
+ || VECTOR_UNIT_VSX_P (DFmode))"
{
+ if (VECTOR_UNIT_VSX_P (DFmode))
+ {
+ emit_insn (gen_vsx_copysignsf3 (operands[0], operands[1], operands[2],
+ CONST0_RTX (SFmode)));
+ DONE;
+ }
operands[3] = gen_reg_rtx (SFmode);
operands[4] = gen_reg_rtx (SFmode);
operands[5] = CONST0_RTX (SFmode);
(match_dup 5))
(match_dup 3)
(match_dup 4)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !HONOR_NANS (DFmode) && !HONOR_SIGNED_ZEROS (DFmode)"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && ((TARGET_PPC_GFXOPT
+ && !HONOR_NANS (DFmode)
+ && !HONOR_SIGNED_ZEROS (DFmode))
+ || VECTOR_UNIT_VSX_P (DFmode))"
{
+ if (VECTOR_UNIT_VSX_P (DFmode))
+ {
+ emit_insn (gen_vsx_copysigndf3 (operands[0], operands[1],
+ operands[2], CONST0_RTX (DFmode)));
+ DONE;
+ }
operands[3] = gen_reg_rtx (DFmode);
operands[4] = gen_reg_rtx (DFmode);
operands[5] = CONST0_RTX (DFmode);
DONE;
}")
-(define_expand "movsicc"
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (if_then_else:SI (match_operand 1 "comparison_operator" "")
- (match_operand:SI 2 "gpc_reg_operand" "")
- (match_operand:SI 3 "gpc_reg_operand" "")))]
- "TARGET_ISEL"
+(define_expand "mov<mode>cc"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+ (if_then_else:GPR (match_operand 1 "comparison_operator" "")
+ (match_operand:GPR 2 "gpc_reg_operand" "")
+ (match_operand:GPR 3 "gpc_reg_operand" "")))]
+ "TARGET_ISEL<sel>"
"
{
if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
;; leave out the mode in operand 4 and use one pattern, but reload can
;; change the mode underneath our feet and then gets confused trying
;; to reload the value.
-(define_insn "isel_signed"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (if_then_else:SI
+(define_insn "isel_signed_<mode>"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (if_then_else:GPR
(match_operator 1 "comparison_operator"
[(match_operand:CC 4 "cc_reg_operand" "y")
(const_int 0)])
- (match_operand:SI 2 "gpc_reg_operand" "b")
- (match_operand:SI 3 "gpc_reg_operand" "b")))]
- "TARGET_ISEL"
+ (match_operand:GPR 2 "gpc_reg_operand" "b")
+ (match_operand:GPR 3 "gpc_reg_operand" "b")))]
+ "TARGET_ISEL<sel>"
"*
{ return output_isel (operands); }"
- [(set_attr "length" "4")])
+ [(set_attr "type" "isel")
+ (set_attr "length" "4")])
-(define_insn "isel_unsigned"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (if_then_else:SI
+(define_insn "isel_unsigned_<mode>"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (if_then_else:GPR
(match_operator 1 "comparison_operator"
[(match_operand:CCUNS 4 "cc_reg_operand" "y")
(const_int 0)])
- (match_operand:SI 2 "gpc_reg_operand" "b")
- (match_operand:SI 3 "gpc_reg_operand" "b")))]
- "TARGET_ISEL"
+ (match_operand:GPR 2 "gpc_reg_operand" "b")
+ (match_operand:GPR 3 "gpc_reg_operand" "b")))]
+ "TARGET_ISEL<sel>"
"*
{ return output_isel (operands); }"
- [(set_attr "length" "4")])
+ [(set_attr "type" "isel")
+ (set_attr "length" "4")])
(define_expand "movsfcc"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
(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"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"fneg %0,%1"
[(set_attr "type" "fp")])
(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"
+ "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"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"fnabs %0,%1"
[(set_attr "type" "fp")])
[(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"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"{fa|fadd} %0,%1,%2"
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_addsub_d")])
[(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"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"{fs|fsub} %0,%1,%2"
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_addsub_d")])
[(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"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"{fm|fmul} %0,%1,%2"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_mul_d")])
[(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"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !TARGET_SIMPLE_FPU
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"{fd|fdiv} %0,%1,%2"
[(set_attr "type" "ddiv")])
-(define_expand "recipdf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")
- (match_operand:DF 2 "gpc_reg_operand" "d")]
- UNSPEC_FRES))]
- "TARGET_RECIP && TARGET_HARD_FLOAT && TARGET_POPCNTB && !optimize_size
- && flag_finite_math_only && !flag_trapping_math"
-{
- rs6000_emit_swdivdf (operands[0], operands[1], operands[2]);
- DONE;
-})
+(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 "fred"
+(define_insn "*rsqrtdf_internal1"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRES))]
- "TARGET_POPCNTB && flag_finite_math_only"
- "fre %0,%1"
+ (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")])
-(define_insn ""
+(define_insn "*fmadddf4_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
(match_operand:DF 2 "gpc_reg_operand" "d"))
(match_operand:DF 3 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
+ && VECTOR_UNIT_NONE_P (DFmode)"
"{fma|fmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_maddsub_d")])
-(define_insn ""
+(define_insn "*fmsubdf4_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
(match_operand:DF 2 "gpc_reg_operand" "d"))
(match_operand:DF 3 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
+ && VECTOR_UNIT_NONE_P (DFmode)"
"{fms|fmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_maddsub_d")])
-(define_insn ""
+(define_insn "*fnmadddf4_fpr_1"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(neg:DF (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
(match_operand:DF 2 "gpc_reg_operand" "d"))
(match_operand:DF 3 "gpc_reg_operand" "d"))))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
- && HONOR_SIGNED_ZEROS (DFmode)"
+ && VECTOR_UNIT_NONE_P (DFmode)"
"{fnma|fnmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_maddsub_d")])
-(define_insn ""
+(define_insn "*fnmadddf4_fpr_2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(minus:DF (mult:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" "d"))
(match_operand:DF 2 "gpc_reg_operand" "d"))
(match_operand:DF 3 "gpc_reg_operand" "d")))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
- && ! HONOR_SIGNED_ZEROS (DFmode)"
+ && ! HONOR_SIGNED_ZEROS (DFmode) && VECTOR_UNIT_NONE_P (DFmode)"
"{fnma|fnmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_maddsub_d")])
-(define_insn ""
+(define_insn "*fnmsubdf4_fpr_1"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(neg:DF (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
(match_operand:DF 2 "gpc_reg_operand" "d"))
(match_operand:DF 3 "gpc_reg_operand" "d"))))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT
- && HONOR_SIGNED_ZEROS (DFmode)"
+ && VECTOR_UNIT_NONE_P (DFmode)"
"{fnms|fnmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_maddsub_d")])
-(define_insn ""
+(define_insn "*fnmsubdf4_fpr_2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(minus:DF (match_operand:DF 3 "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_FUSED_MADD && TARGET_DOUBLE_FLOAT
- && ! HONOR_SIGNED_ZEROS (DFmode)"
+ && ! HONOR_SIGNED_ZEROS (DFmode) && VECTOR_UNIT_NONE_P (DFmode)"
"{fnms|fnmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")
(set_attr "fp_type" "fp_maddsub_d")])
-(define_insn "sqrtdf2"
+(define_expand "sqrtdf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
+ "(TARGET_PPC_GPOPT || TARGET_POWER2) && 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_POWER2) && TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_DOUBLE_FLOAT"
+ && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"fsqrt %0,%1"
[(set_attr "type" "dsqrt")])
"TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT"
"")
+(define_expand "fixuns_truncdfsi2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "")
+
+(define_expand "fixuns_truncdfdi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unsigned_fix:DI (match_operand:DF 1 "register_operand" "")))]
+ "TARGET_HARD_FLOAT && TARGET_VSX"
+ "")
+
; For each of these conversions, there is a define_expand, a define_insn
; with a '#' template, and a define_split (with C code). The idea is
; to allow constant folding with the template of the define_insn,
(clobber (match_operand:SI 6 "gpc_reg_operand" "=&r"))]
"! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
"#"
- "&& (can_create_pseudo_p () || offsettable_nonstrict_memref_p (operands[4]))"
+ ""
[(pc)]
"
{
(clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))]
"! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
"#"
- "&& (can_create_pseudo_p () || offsettable_nonstrict_memref_p (operands[4]))"
+ ""
[(pc)]
"
{
"(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS
&& TARGET_DOUBLE_FLOAT"
"#"
- "&& (can_create_pseudo_p () || offsettable_nonstrict_memref_p (operands[3]))"
+ ""
[(pc)]
"
{
"{fcirz|fctiwz} %0,%1"
[(set_attr "type" "fp")])
-(define_insn "btruncdf2"
+(define_expand "btruncdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIZ))]
"TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "")
+
+(define_insn "*btruncdf2_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"friz %0,%1"
[(set_attr "type" "fp")])
(define_insn "btruncsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT "
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
"friz %0,%1"
[(set_attr "type" "fp")])
-(define_insn "ceildf2"
+(define_expand "ceildf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "")] UNSPEC_FRIP))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "")
+
+(define_insn "*ceildf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIP))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"frip %0,%1"
[(set_attr "type" "fp")])
"frip %0,%1"
[(set_attr "type" "fp")])
-(define_insn "floordf2"
+(define_expand "floordf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "")] UNSPEC_FRIM))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "")
+
+(define_insn "*floordf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIM))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"frim %0,%1"
[(set_attr "type" "fp")])
"frim %0,%1"
[(set_attr "type" "fp")])
+;; No VSX equivalent to frin
(define_insn "rounddf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIN))]
"frin %0,%1"
[(set_attr "type" "fp")])
+(define_expand "ftruncdf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (fix:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
+ "VECTOR_UNIT_VSX_P (DFmode)"
+ "")
+
; An UNSPEC is used so we don't have to support SImode in FP registers.
(define_insn "stfiwx"
[(set (match_operand:SI 0 "memory_operand" "=Z")
"TARGET_HARD_FLOAT && !TARGET_FPRS"
"")
-(define_insn "floatdidf2"
+(define_expand "floatdidf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (float:DF (match_operand:DI 1 "gpc_reg_operand" "")))]
+ "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode))
+ && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
+ "")
+
+(define_insn "*floatdidf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=d")
(float:DF (match_operand:DI 1 "gpc_reg_operand" "!d#r")))]
- "(TARGET_POWERPC64 || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
+ "(TARGET_POWERPC64 || TARGET_XILINX_FPU)
+ && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"fcfid %0,%1"
[(set_attr "type" "fp")])
-(define_insn "fix_truncdfdi2"
+(define_expand "floatunsdidf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (unsigned_float:DF (match_operand:DI 1 "gpc_reg_operand" "")))]
+ "TARGET_VSX"
+ "")
+
+(define_expand "fix_truncdfdi2"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (fix:DI (match_operand:DF 1 "gpc_reg_operand" "")))]
+ "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode))
+ && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
+ "")
+
+(define_insn "*fix_truncdfdi2_fpr"
[(set (match_operand:DI 0 "gpc_reg_operand" "=!d#r")
(fix:DI (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "(TARGET_POWERPC64 || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
+ "(TARGET_POWERPC64 || TARGET_XILINX_FPU)
+ && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"fctidz %0,%1"
[(set_attr "type" "fp")])
\f
;; PowerPC64 DImode operations.
-(define_insn_and_split "absdi2"
+(define_expand "absdi2"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (abs:DI (match_operand:DI 1 "gpc_reg_operand" "")))]
+ "TARGET_POWERPC64"
+ "
+{
+ if (TARGET_ISEL)
+ emit_insn (gen_absdi2_isel (operands[0], operands[1]));
+ else
+ emit_insn (gen_absdi2_internal (operands[0], operands[1]));
+ DONE;
+}")
+
+(define_insn_and_split "absdi2_internal"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
(abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))
(clobber (match_scratch:DI 2 "=&r,&r"))]
- "TARGET_POWERPC64"
+ "TARGET_POWERPC64 && !TARGET_ISEL"
"#"
"&& reload_completed"
[(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
(neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0"))))
(clobber (match_scratch:DI 2 "=&r,&r"))]
- "TARGET_POWERPC64"
+ "TARGET_POWERPC64 && !TARGET_ISEL"
"#"
"&& reload_completed"
[(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
andi. %0,%1,%b2
andis. %0,%1,%u2
#"
- [(set_attr "type" "*,*,*,compare,compare,*")
+ [(set_attr "type" "*,*,*,fast_compare,fast_compare,*")
(set_attr "length" "4,4,4,4,4,8")])
(define_insn "anddi3_nomc"
#
#
#"
- [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
+ [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
+ fast_compare,compare,compare,compare,compare,compare,\
+ compare,compare")
(set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
(define_split
#
#
#"
- [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
+ [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
+ fast_compare,compare,compare,compare,compare,compare,\
+ compare,compare")
(set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
(define_split
"@
%q4. %3,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
%q4. %0,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
%q4. %3,%2,%1
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
%q4. %0,%2,%1
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
%q4. %3,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
"@
%q4. %0,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
(compare:CC (match_dup 0)
(const_int 0)))]
"")
+
+(define_expand "smindi3"
+ [(match_operand:DI 0 "gpc_reg_operand" "")
+ (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "gpc_reg_operand" "")]
+ "TARGET_ISEL64"
+ "
+{
+ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]);
+ DONE;
+}")
+
+(define_expand "smaxdi3"
+ [(match_operand:DI 0 "gpc_reg_operand" "")
+ (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "gpc_reg_operand" "")]
+ "TARGET_ISEL64"
+ "
+{
+ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]);
+ DONE;
+}")
+
+(define_expand "umindi3"
+ [(match_operand:DI 0 "gpc_reg_operand" "")
+ (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "gpc_reg_operand" "")]
+ "TARGET_ISEL64"
+ "
+{
+ rs6000_emit_minmax (operands[0], UMIN, operands[1], operands[2]);
+ DONE;
+}")
+
+(define_expand "umaxdi3"
+ [(match_operand:DI 0 "gpc_reg_operand" "")
+ (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "gpc_reg_operand" "")]
+ "TARGET_ISEL64"
+ "
+{
+ rs6000_emit_minmax (operands[0], UMAX, operands[1], operands[2]);
+ DONE;
+}")
+
\f
;; Now define ways of moving data around.
;; The "??" is a kludge until we can figure out a more reasonable way
;; of handling these non-offsettable values.
(define_insn "*movdf_hardfloat32"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,d,d,m,!r,!r,!r")
- (match_operand:DF 1 "input_operand" "r,m,r,d,m,d,G,H,F"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,ws,?wa,ws,?wa,Z,?Z,d,d,m,wa,!r,!r,!r")
+ (match_operand:DF 1 "input_operand" "r,m,r,ws,wa,Z,Z,ws,wa,d,m,d,j,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))"
default:
gcc_unreachable ();
case 0:
- /* We normally copy the low-numbered register first. However, if
- the first register operand 0 is the same as the second register
- of operand 1, we must copy in the opposite order. */
- if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- return \"mr %L0,%L1\;mr %0,%1\";
- else
- return \"mr %0,%1\;mr %L0,%L1\";
case 1:
- if (rs6000_offsettable_memref_p (operands[1])
- || (GET_CODE (operands[1]) == MEM
- && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM
- || GET_CODE (XEXP (operands[1], 0)) == PRE_INC
- || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC
- || GET_CODE (XEXP (operands[1], 0)) == PRE_MODIFY)))
- {
- /* If the low-address word is used in the address, we must load
- it last. Otherwise, load it first. Note that we cannot have
- auto-increment in that case since the address register is
- known to be dead. */
- if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands[1], 0))
- return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
- else
- return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\";
- }
- else
- {
- rtx addreg;
-
- addreg = find_addr_reg (XEXP (operands[1], 0));
- if (refers_to_regno_p (REGNO (operands[0]),
- REGNO (operands[0]) + 1,
- operands[1], 0))
- {
- output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
- output_asm_insn (\"{l%X1|lwz%X1} %L0,%1\", operands);
- output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
- return \"{l%X1|lwz%X1} %0,%1\";
- }
- else
- {
- output_asm_insn (\"{l%X1|lwz%X1} %0,%1\", operands);
- output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
- output_asm_insn (\"{l%X1|lwz%X1} %L0,%1\", operands);
- output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
- return \"\";
- }
- }
case 2:
- if (rs6000_offsettable_memref_p (operands[0])
- || (GET_CODE (operands[0]) == MEM
- && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM
- || GET_CODE (XEXP (operands[0], 0)) == PRE_INC
- || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
- || GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)))
- return \"{st%U0%X0|stw%U0%X0} %1,%0\;{st|stw} %L1,%L0\";
- else
- {
- rtx addreg;
-
- addreg = find_addr_reg (XEXP (operands[0], 0));
- output_asm_insn (\"{st%X0|stw%X0} %1,%0\", operands);
- output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
- output_asm_insn (\"{st%X0|stw%X0} %L1,%0\", operands);
- output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
- return \"\";
- }
+ return \"#\";
case 3:
- return \"fmr %0,%1\";
case 4:
- return \"lfd%U1%X1 %0,%1\";
+ return \"xxlor %x0,%x1,%x1\";
case 5:
- return \"stfd%U0%X0 %1,%0\";
case 6:
+ return \"lxsd%U1x %x0,%y1\";
case 7:
case 8:
+ return \"stxsd%U0x %x1,%y0\";
+ case 9:
+ return \"fmr %0,%1\";
+ case 10:
+ return \"lfd%U1%X1 %0,%1\";
+ case 11:
+ return \"stfd%U0%X0 %1,%0\";
+ case 12:
+ return \"xxlxor %x0,%x0,%x0\";
+ case 13:
+ case 14:
+ case 15:
return \"#\";
}
}"
- [(set_attr "type" "two,load,store,fp,fpload,fpstore,*,*,*")
- (set_attr "length" "8,16,16,4,4,4,8,12,16")])
+ [(set_attr "type" "two,load,store,fp,fp,fpload,fpload,fpstore,fpstore,fp,fpload,fpstore,vecsimple,*,*,*")
+ (set_attr "length" "8,16,16,4,4,4,4,4,4,4,4,4,4,8,12,16")])
(define_insn "*movdf_softfloat32"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,r,r,r")
|| TARGET_SOFT_FLOAT || TARGET_E500_SINGLE)
&& (gpc_reg_operand (operands[0], DFmode)
|| gpc_reg_operand (operands[1], DFmode))"
- "*
-{
- switch (which_alternative)
- {
- default:
- gcc_unreachable ();
- case 0:
- /* We normally copy the low-numbered register first. However, if
- the first register operand 0 is the same as the second register of
- operand 1, we must copy in the opposite order. */
- if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- return \"mr %L0,%L1\;mr %0,%1\";
- else
- return \"mr %0,%1\;mr %L0,%L1\";
- case 1:
- /* If the low-address word is used in the address, we must load
- it last. Otherwise, load it first. Note that we cannot have
- auto-increment in that case since the address register is
- known to be dead. */
- if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands[1], 0))
- return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
- else
- return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\";
- case 2:
- return \"{st%U0%X0|stw%U0%X0} %1,%0\;{st|stw} %L1,%L0\";
- case 3:
- case 4:
- case 5:
- return \"#\";
- }
-}"
+ "#"
[(set_attr "type" "two,load,store,*,*,*")
(set_attr "length" "8,8,8,8,12,16")])
; 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,d,d,m,*c*l,!r,*h,!r,!r,!r,r,d")
- (match_operand:DF 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F,d,r"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,ws,?wa,ws,?wa,Z,?Z,d,d,m,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
+ && 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
fmr %0,%1
lfd%U1%X1 %0,%1
stfd%U0%X0 %1,%0
+ xxlxor %x0,%x0,%x0
mt%0 %1
mf%1 %0
{cror 0,0,0|nop}
#
mftgpr %0,%1
mffgpr %0,%1"
- [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr")
- (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16,4,4")])
+ [(set_attr "type" "store,load,*,fp,fp,fpload,fpload,fpstore,fpstore,fp,fpload,fpstore,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" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r")
- (match_operand:DF 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,ws,?wa,ws,?wa,Z,?Z,d,d,m,wa,*c*l,!r,*h,!r,!r,!r")
+ (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"))]
"TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_DOUBLE_FLOAT
+ && 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
fmr %0,%1
lfd%U1%X1 %0,%1
stfd%U0%X0 %1,%0
+ xxlxor %x0,%x0,%x0
mt%0 %1
mf%1 %0
{cror 0,0,0|nop}
#
#
#"
- [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*")
- (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16")])
+ [(set_attr "type" "store,load,*,fp,fp,fpload,fpload,fpstore,fpstore,fp,fpload,fpstore,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" "=r,Y,r,cl,r,r,r,r,*h")
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"#"
- "&& (can_create_pseudo_p () || offsettable_nonstrict_memref_p (operands[5]))"
+ ""
[(pc)]
{
rtx lowword;
}")
(define_split
- [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "")
- (match_operand:DI 1 "input_operand" ""))]
+ [(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])"
[(pc)]
(define_insn "*movti_ppc64"
[(set (match_operand:TI 0 "nonimmediate_operand" "=r,o<>,r")
(match_operand:TI 1 "input_operand" "r,r,m"))]
- "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
- || gpc_reg_operand (operands[1], TImode))"
+ "(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_split
[(set (match_operand:TI 0 "gpc_reg_operand" "")
(match_operand:TI 1 "const_double_operand" ""))]
- "TARGET_POWERPC64"
+ "TARGET_POWERPC64 && VECTOR_MEM_NONE_P (TImode)"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
"
(define_split
[(set (match_operand:TI 0 "nonimmediate_operand" "")
(match_operand:TI 1 "input_operand" ""))]
- "reload_completed
+ "reload_completed && VECTOR_MEM_NONE_P (TImode)
&& gpr_or_gpr_p (operands[0], operands[1])"
[(pc)]
{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
UNSPEC_TLSGD)
(clobber (reg:SI LR_REGNO))]
"HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX"
- "addi %0,%1,%2@got@tlsgd\;bl %z3\;%."
+{
+ if (TARGET_CMODEL != CMODEL_SMALL)
+ return "addis %0,%1,%2@got@tlsgd@ha\;addi %0,%0,%2@got@tlsgd@l\;bl %z3\;%.";
+ else
+ return "addi %0,%1,%2@got@tlsgd\;bl %z3\;%.";
+}
"&& TARGET_TLS_MARKERS"
[(set (match_dup 0)
(unspec:TLSmode [(match_dup 1)
(clobber (reg:SI LR_REGNO))])]
""
[(set_attr "type" "two")
- (set_attr "length" "12")])
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
+ (const_int 16)
+ (const_int 12)))])
(define_insn_and_split "tls_gd_sysv<TLSmode:tls_sysv_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
[(set_attr "type" "two")
(set_attr "length" "8")])
-(define_insn "*tls_gd<TLSmode:tls_abi_suffix>"
+(define_insn_and_split "*tls_gd<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
(unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGD))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS"
"addi %0,%1,%2@got@tlsgd"
+ "&& TARGET_CMODEL != CMODEL_SMALL"
+ [(set (match_dup 3)
+ (plus:TLSmode (match_dup 1)
+ (high:TLSmode
+ (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD))))
+ (set (match_dup 0)
+ (lo_sum:TLSmode (match_dup 3)
+ (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD)))]
+ "
+{
+ operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
+}"
+ [(set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
+ (const_int 8)
+ (const_int 4)))])
+
+(define_insn "*tls_gd_high<TLSmode:tls_abi_suffix>"
+ [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
+ (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
+ (high:TLSmode
+ (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
+ UNSPEC_TLSGD))))]
+ "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
+ "addis %0,%1,%2@got@tlsgd@ha"
+ [(set_attr "length" "4")])
+
+(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_TLSGD)))]
+ "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
+ "addi %0,%1,%2@got@tlsgd@l"
[(set_attr "length" "4")])
(define_insn "*tls_gd_call_aix<TLSmode:tls_abi_suffix>"
UNSPEC_TLSLD)
(clobber (reg:SI LR_REGNO))]
"HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX"
- "addi %0,%1,%&@got@tlsld\;bl %z2\;%."
+{
+ if (TARGET_CMODEL != CMODEL_SMALL)
+ return "addis %0,%1,%&@got@tlsld@ha\;addi %0,%0,%&@got@tlsld@l\;bl %z2\;%.";
+ else
+ return "addi %0,%1,%&@got@tlsld\;bl %z2\;%.";
+}
"&& TARGET_TLS_MARKERS"
[(set (match_dup 0)
(unspec:TLSmode [(match_dup 1)]
(unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)
(clobber (reg:SI LR_REGNO))])]
""
- [(set_attr "length" "12")])
+ [(set_attr "type" "two")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
+ (const_int 16)
+ (const_int 12)))])
(define_insn_and_split "tls_ld_sysv<TLSmode:tls_sysv_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
""
[(set_attr "length" "8")])
-(define_insn "*tls_ld<TLSmode:tls_abi_suffix>"
+(define_insn_and_split "*tls_ld<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
(unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")]
UNSPEC_TLSLD))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS"
"addi %0,%1,%&@got@tlsld"
+ "&& TARGET_CMODEL != CMODEL_SMALL"
+ [(set (match_dup 2)
+ (plus:TLSmode (match_dup 1)
+ (high:TLSmode
+ (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD))))
+ (set (match_dup 0)
+ (lo_sum:TLSmode (match_dup 2)
+ (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))]
+ "
+{
+ operands[2] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
+}"
+ [(set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
+ (const_int 8)
+ (const_int 4)))])
+
+(define_insn "*tls_ld_high<TLSmode:tls_abi_suffix>"
+ [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
+ (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
+ (high:TLSmode
+ (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD))))]
+ "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
+ "addis %0,%1,%&@got@tlsld@ha"
+ [(set_attr "length" "4")])
+
+(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)))]
+ "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
+ "addi %0,%1,%&@got@tlsld@l"
[(set_attr "length" "4")])
(define_insn "*tls_ld_call_aix<TLSmode:tls_abi_suffix>"
"HAVE_AS_TLS"
"addi %0,%1,%2@dtprel@l")
-(define_insn "tls_got_dtprel_<TLSmode:tls_abi_suffix>"
+(define_insn_and_split "tls_got_dtprel_<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
(unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGOTDTPREL))]
"HAVE_AS_TLS"
- "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel(%1)")
+ "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel(%1)"
+ "&& TARGET_CMODEL != CMODEL_SMALL"
+ [(set (match_dup 3)
+ (plus:TLSmode (match_dup 1)
+ (high:TLSmode
+ (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL))))
+ (set (match_dup 0)
+ (lo_sum:TLSmode (match_dup 3)
+ (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL)))]
+ "
+{
+ operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
+}"
+ [(set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
+ (const_int 8)
+ (const_int 4)))])
+
+(define_insn "*tls_got_dtprel_high<TLSmode:tls_abi_suffix>"
+ [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
+ (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
+ (high:TLSmode
+ (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
+ UNSPEC_TLSGOTDTPREL))))]
+ "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
+ "addis %0,%1,%2@got@dtprel@ha"
+ [(set_attr "length" "4")])
+
+(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_TLSGOTDTPREL)))]
+ "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
+ "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel@l(%1)"
+ [(set_attr "length" "4")])
(define_insn "tls_tprel_<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
;; "b" output constraint here and on tls_tls input to support linker tls
;; optimization. The linker may edit the instructions emitted by a
;; tls_got_tprel/tls_tls pair to addis,addi.
-(define_insn "tls_got_tprel_<TLSmode:tls_abi_suffix>"
+(define_insn_and_split "tls_got_tprel_<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
(unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGOTTPREL))]
"HAVE_AS_TLS"
- "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel(%1)")
+ "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel(%1)"
+ "&& TARGET_CMODEL != CMODEL_SMALL"
+ [(set (match_dup 3)
+ (plus:TLSmode (match_dup 1)
+ (high:TLSmode
+ (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL))))
+ (set (match_dup 0)
+ (lo_sum:TLSmode (match_dup 3)
+ (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL)))]
+ "
+{
+ operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
+}"
+ [(set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
+ (const_int 8)
+ (const_int 4)))])
+
+(define_insn "*tls_got_tprel_high<TLSmode:tls_abi_suffix>"
+ [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
+ (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
+ (high:TLSmode
+ (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
+ UNSPEC_TLSGOTTPREL))))]
+ "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
+ "addis %0,%1,%2@got@tprel@ha"
+ [(set_attr "length" "4")])
+
+(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_TLSGOTTPREL)))]
+ "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
+ "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel@l(%1)"
+ [(set_attr "length" "4")])
(define_insn "tls_tls_<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
UNSPEC_TLSTLS))]
"HAVE_AS_TLS"
"add %0,%1,%2@tls")
-
\f
;; Next come insns related to the calling sequence.
;;
(define_insn "load_toc_v4_PIC_1b"
[(set (reg:SI LR_REGNO)
- (unspec:SI [(match_operand:SI 0 "immediate_operand" "s")]
- UNSPEC_TOCPTR))]
+ (unspec:SI [(match_operand:SI 0 "immediate_operand" "s")
+ (label_ref (match_operand 1 "" ""))]
+ UNSPEC_TOCPTR))
+ (match_dup 1)]
"TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
- "bcl 20,31,$+8\\n\\t.long %0-$"
+ "bcl 20,31,$+8\;.long %0-$"
[(set_attr "type" "branch")
(set_attr "length" "8")])
(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"
- "{cal|addi} %0,%1,%2-%3@l")
+ "{cal %0,%2-%3@l(%1)|addi %0,%1,%2-%3@l}")
;; If the TOC is shared over a translation unit, as happens with all
;; the kinds of PIC that we support, we need to restore the TOC
"@
{cal|la} %0,%2@l(%1)
{ai|addic} %0,%1,%K2")
+
+;; Largetoc support
+(define_insn "largetoc_high"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=b")
+ (plus:DI (match_operand:DI 1 "gpc_reg_operand" "b")
+ (high:DI (match_operand:DI 2 "" ""))))]
+ "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
+ "{cau|addis} %0,%1,%2@ha")
+
+(define_insn "largetoc_low"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b")
+ (match_operand:DI 2 "" "")))]
+ "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
+ "{cal %0,%2@l(%1)|addi %0,%1,%2@l}")
\f
;; A function pointer under AIX is a pointer to a data area whose first word
;; contains the actual address of the function, whose second word contains a
[(unspec_volatile [(const_int 0)] UNSPECV_BLOCK)]
""
"")
+
+(define_insn "probe_stack"
+ [(set (match_operand 0 "memory_operand" "=m")
+ (unspec [(const_int 0)] UNSPEC_PROBE_STACK))]
+ ""
+ "{st%U0%X0|stw%U0%X0} 0,%0"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")])
\f
;; Compare insns are next. Note that the RS/6000 has two types of compares,
;; signed & unsigned, and one type of branch.
[(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"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+ && !VECTOR_UNIT_VSX_P (DFmode)"
"fcmpu %0,%1,%2"
[(set_attr "type" "fpcompare")])
(clobber (match_scratch:DF 7 "=d"))
(clobber (match_scratch:DF 8 "=d"))
(clobber (match_scratch:DF 9 "=d"))
- (clobber (match_scratch:DF 10 "=d"))]
+ (clobber (match_scratch:DF 10 "=d"))
+ (clobber (match_scratch:GPR 11 "=b"))]
"!TARGET_IEEEQUAD && TARGET_XL_COMPAT
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
"#"
"&& reload_completed"
- [(set (match_dup 3) (match_dup 13))
- (set (match_dup 4) (match_dup 14))
+ [(set (match_dup 3) (match_dup 14))
+ (set (match_dup 4) (match_dup 15))
(set (match_dup 9) (abs:DF (match_dup 5)))
(set (match_dup 0) (compare:CCFP (match_dup 9) (match_dup 3)))
(set (pc) (if_then_else (ne (match_dup 0) (const_int 0))
- (label_ref (match_dup 11))
+ (label_ref (match_dup 12))
(pc)))
(set (match_dup 0) (compare:CCFP (match_dup 5) (match_dup 7)))
- (set (pc) (label_ref (match_dup 12)))
- (match_dup 11)
+ (set (pc) (label_ref (match_dup 13)))
+ (match_dup 12)
(set (match_dup 10) (minus:DF (match_dup 5) (match_dup 7)))
(set (match_dup 9) (minus:DF (match_dup 6) (match_dup 8)))
(set (match_dup 9) (plus:DF (match_dup 10) (match_dup 9)))
- (set (match_dup 0) (compare:CCFP (match_dup 7) (match_dup 4)))
- (match_dup 12)]
+ (set (match_dup 0) (compare:CCFP (match_dup 9) (match_dup 4)))
+ (match_dup 13)]
{
REAL_VALUE_TYPE rv;
const int lo_word = FLOAT_WORDS_BIG_ENDIAN ? GET_MODE_SIZE (DFmode) : 0;
operands[6] = simplify_gen_subreg (DFmode, operands[1], TFmode, lo_word);
operands[7] = simplify_gen_subreg (DFmode, operands[2], TFmode, hi_word);
operands[8] = simplify_gen_subreg (DFmode, operands[2], TFmode, lo_word);
- operands[11] = gen_label_rtx ();
operands[12] = gen_label_rtx ();
+ operands[13] = gen_label_rtx ();
real_inf (&rv);
- operands[13] = force_const_mem (DFmode,
- CONST_DOUBLE_FROM_REAL_VALUE (rv, DFmode));
operands[14] = force_const_mem (DFmode,
+ CONST_DOUBLE_FROM_REAL_VALUE (rv, DFmode));
+ operands[15] = force_const_mem (DFmode,
CONST_DOUBLE_FROM_REAL_VALUE (dconst0,
DFmode));
if (TARGET_TOC)
{
- operands[13] = gen_const_mem (DFmode,
- create_TOC_reference (XEXP (operands[13], 0)));
- operands[14] = gen_const_mem (DFmode,
- create_TOC_reference (XEXP (operands[14], 0)));
- set_mem_alias_set (operands[13], get_TOC_alias_set ());
+ rtx tocref;
+ tocref = create_TOC_reference (XEXP (operands[14], 0), operands[11]);
+ operands[14] = gen_const_mem (DFmode, tocref);
+ tocref = create_TOC_reference (XEXP (operands[15], 0), operands[11]);
+ operands[15] = gen_const_mem (DFmode, tocref);
set_mem_alias_set (operands[14], get_TOC_alias_set ());
+ set_mem_alias_set (operands[15], get_TOC_alias_set ());
}
})
\f
(set (match_operand:P 3 "memory_operand" "=m")
(match_operand:P 4 "gpc_reg_operand" "r"))])]
""
- "bl %z1"
+ "bl %1"
[(set_attr "type" "branch")
(set_attr "length" "4")])
(set (match_operand:DF 3 "memory_operand" "=m")
(match_operand:DF 4 "gpc_reg_operand" "d"))])]
""
- "bl %z1"
+ "bl %1"
[(set_attr "type" "branch")
(set_attr "length" "4")])
""
[(set_attr "length" "0")])
+; Like stack_tie, but depend on both fp and sp based memory.
+(define_insn "frame_tie"
+ [(set (match_operand:BLK 0 "memory_operand" "+m")
+ (unspec:BLK [(match_dup 0)
+ (match_operand:BLK 1 "memory_operand" "m")] UNSPEC_TIE))]
+ ""
+ ""
+ [(set_attr "length" "0")])
+
(define_expand "epilogue"
[(use (const_int 0))]
(set (match_operand:P 4 "gpc_reg_operand" "=r")
(match_operand:P 5 "memory_operand" "m"))])]
""
- "bl %z2"
+ "bl %2"
[(set_attr "type" "branch")
(set_attr "length" "4")])
(set (match_operand:P 4 "gpc_reg_operand" "=r")
(match_operand:P 5 "memory_operand" "m"))])]
""
- "b %z2"
+ "b %2"
[(set_attr "type" "branch")
(set_attr "length" "4")])
(set (match_operand:DF 4 "gpc_reg_operand" "=d")
(match_operand:DF 5 "memory_operand" "m"))])]
""
- "b %z2"
+ "b %2"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "*return_and_restore_fpregs_aix_<mode>"
+ [(match_parallel 0 "any_parallel_operand"
+ [(return)
+ (use (match_operand:P 1 "register_operand" "l"))
+ (use (match_operand:P 2 "symbol_ref_operand" "s"))
+ (use (match_operand:P 3 "gpc_reg_operand" "r"))
+ (set (match_operand:DF 4 "gpc_reg_operand" "=d")
+ (match_operand:DF 5 "memory_operand" "m"))])]
+ ""
+ "b %2"
[(set_attr "type" "branch")
(set_attr "length" "4")])
}"
[(set_attr "type" "load")])
\f
+(define_insn "bpermd_<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (unspec:P [(match_operand:P 1 "gpc_reg_operand" "r")
+ (match_operand:P 2 "gpc_reg_operand" "r")] UNSPEC_BPERM))]
+ "TARGET_POPCNTD"
+ "bpermd %0,%1,%2"
+ [(set_attr "type" "integer")])
+
+\f
(include "sync.md")
+(include "vector.md")
+(include "vsx.md")
(include "altivec.md")
(include "spe.md")
(include "dfp.md")