aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/config/rs6000/rs6000.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/config/rs6000/rs6000.md')
-rw-r--r--gcc-4.9/gcc/config/rs6000/rs6000.md255
1 files changed, 246 insertions, 9 deletions
diff --git a/gcc-4.9/gcc/config/rs6000/rs6000.md b/gcc-4.9/gcc/config/rs6000/rs6000.md
index 64c9e7c10..e853bc4f9 100644
--- a/gcc-4.9/gcc/config/rs6000/rs6000.md
+++ b/gcc-4.9/gcc/config/rs6000/rs6000.md
@@ -125,6 +125,16 @@
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
])
;;
@@ -481,6 +491,10 @@
(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.
@@ -2755,10 +2769,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
@@ -2782,10 +2793,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" ""))
@@ -6534,6 +6542,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
@@ -9395,7 +9446,8 @@
(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)
+ || 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))"
"#"
@@ -15691,6 +15743,191 @@
})
+;; 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")