summaryrefslogtreecommitdiff
path: root/gcc/config/rs6000
diff options
context:
space:
mode:
authormeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>2014-04-24 22:42:25 +0000
committermeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>2014-04-24 22:42:25 +0000
commitac0adecc1b3caa338757e18744666ba0bfe712fe (patch)
treec8f8ec9a6730285ce8bb60248b53e28228a38ac7 /gcc/config/rs6000
parentdbf10c9790c6e59fa37cbe76fe0117ff567a25d3 (diff)
downloadgcc-ac0adecc1b3caa338757e18744666ba0bfe712fe.tar.gz
[gcc]
2014-04-24 Michael Meissner <meissner@linux.vnet.ibm.com> * doc/extend.texi (PowerPC Built-in Functions): Document new powerpc extended divide, bcd, pack/unpack 128-bit, builtin functions. (PowerPC AltiVec/VSX Built-in Functions): Likewise. * config/rs6000/predicates.md (const_0_to_3_operand): New predicate to match 0..3 integer constants. * config/rs6000/rs6000-builtin.def (BU_DFP_MISC_1): Add new macros to support adding miscellaneous builtin functions. (BU_DFP_MISC_2): Likewise. (BU_P7_MISC_1): Likewise. (BU_P7_MISC_2): Likewise. (BU_P8V_MISC_3): Likewise. (BU_MISC_1): Likewise. (BU_MISC_2): Likewise. (DIVWE): Add extended divide builtin functions. (DIVWEO): Likewise. (DIVWEU): Likewise. (DIVWEUO): Likewise. (DIVDE): Likewise. (DIVDEO): Likewise. (DIVDEU): Likewise. (DIVDEUO): Likewise. (DXEX): Add decimal floating-point builtin functions. (DXEXQ): Likewise. (DDEDPD): Likewise. (DDEDPDQ): Likewise. (DENBCD): Likewise. (DENBCDQ): Likewise. (DIEX): Likewise. (DIEXQ): Likewise. (DSCLI): Likewise. (DSCLIQ): Likewise. (DSCRI): Likewise. (DSCRIQ): Likewise. (CDTBCD): Add new BCD builtin functions. (CBCDTD): Likewise. (ADDG6S): Likewise. (BCDADD): Likewise. (BCDADD_LT): Likewise. (BCDADD_EQ): Likewise. (BCDADD_GT): Likewise. (BCDADD_OV): Likewise. (BCDSUB): Likewise. (BCDSUB_LT): Likewise. (BCDSUB_EQ): Likewise. (BCDSUB_GT): Likewise. (BCDSUB_OV): Likewise. (PACK_TD): Add new pack/unpack 128-bit type builtin functions. (UNPACK_TD): Likewise. (PACK_TF): Likewise. (UNPACK_TF): Likewise. (UNPACK_TF_0): Likewise. (UNPACK_TF_1): Likewise. (PACK_V1TI): Likewise. (UNPACK_V1TI): Likewise. * config/rs6000/rs6000.c (rs6000_builtin_mask_calculate): Add support for decimal floating point builtin functions. (rs6000_expand_ternop_builtin): Add checks for the new builtin functions that take constant arguments. (rs6000_invalid_builtin): Add decimal floating point builtin support. (rs6000_init_builtins): Setup long double, _Decimal64, and _Decimal128 types for new builtin functions. (builtin_function_type): Set the unsigned flags appropriately for the new builtin functions. (rs6000_opt_masks): Add support for decimal floating point builtin functions. * config/rs6000/rs6000.h (RS6000_BTM_DFP): Add support for decimal floating point builtin functions. (RS6000_BTM_COMMON): Likewise. (RS6000_BTI_long_double): Likewise. (RS6000_BTI_dfloat64): Likewise. (RS6000_BTI_dfloat128): Likewise. (long_double_type_internal_node): Likewise. (dfloat64_type_internal_node): Likewise. (dfloat128_type_internal_node): Likewise. * config/rs6000/altivec.h (UNSPEC_BCDADD): Add support for ISA 2.07 bcd arithmetic instructions. (UNSPEC_BCDSUB): Likewise. (UNSPEC_BCD_OVERFLOW): Likewise. (UNSPEC_BCD_ADD_SUB): Likewise. (bcd_add_sub): Likewise. (BCD_TEST): Likewise. (bcd<bcd_add_sub>): Likewise. (bcd<bcd_add_sub>_test): Likewise. (bcd<bcd_add_sub>_test2): Likewise. (bcd<bcd_add_sub>_<code>): Likewise. (peephole2 for combined bcd ops): Likewise. * config/rs6000/dfp.md (UNSPEC_DDEDPD): Add support for new decimal floating point builtin functions. (UNSPEC_DENBCD): Likewise. (UNSPEC_DXEX): Likewise. (UNSPEC_DIEX): Likewise. (UNSPEC_DSCLI): Likewise. (UNSPEC_DSCRI): Likewise. (D64_D128): Likewise. (dfp_suffix): Likewise. (dfp_ddedpd_<mode>): Likewise. (dfp_denbcd_<mode>): Likewise. (dfp_dxex_<mode>): Likewise. (dfp_diex_<mode>): Likewise. (dfp_dscli_<mode>): Likewise. (dfp_dscri_<mode>): Likewise. * config/rs6000/rs6000.md (UNSPEC_ADDG6S): Add support for new BCD builtin functions. (UNSPEC_CDTBCD): Likewise. (UNSPEC_CBCDTD): Likewise. (UNSPEC_DIVE): Add support for new extended divide builtin functions. (UNSPEC_DIVEO): Likewise. (UNSPEC_DIVEU): Likewise. (UNSPEC_DIVEUO): Likewise. (UNSPEC_UNPACK_128BIT): Add support for new builtin functions to pack/unpack 128-bit types. (UNSPEC_PACK_128BIT): Likewise. (idiv_ldiv): New mode attribute to set the 32/64-bit divide type. (udiv<mode>3): Use idiv_ldiv mode attribute. (div<mode>3): Likewise. (addg6s): Add new BCD builtin functions. (cdtbcd): Likewise. (cbcdtd): Likewise. (UNSPEC_DIV_EXTEND): Add support for new extended divide instructions. (div_extend): Likewise. (div<div_extend>_<mode>"): Likewise. (FP128_64): Add support for new builtin functions to pack/unpack 128-bit types. (unpack<mode>): Likewise. (unpacktf_0): Likewise. (unpacktf_1): Likewise. (unpack<mode>_dm): Likewise. (unpack<mode>_nodm): Likewise. (pack<mode>): Likewise. (unpackv1ti): Likewise. (packv1ti): Likewise. [gcc/testsuite] 2014-04-24 Michael Meissner <meissner@linux.vnet.ibm.com> * gcc.target/powerpc/pack01.c: New test to test the new pack and unpack builtin functionss for 128-bit types. * gcc.target/powerpc/pack02.c: Likewise. * gcc.target/powerpc/pack03.c: Likewise. * gcc.target/powerpc/extend-divide-1.c: New test to test extended divide builtin functionss. * gcc.target/powerpc/extend-divide-2.c: Likewise. * gcc.target/powerpc/bcd-1.c: New test for the new BCD builtin functions. * gcc.target/powerpc/bcd-2.c: Likewise. * gcc.target/powerpc/bcd-3.c: Likewise. * gcc.target/powerpc/dfp-builtin-1.c: New test for the new DFP builtin functionss. * gcc.target/powerpc/dfp-builtin-2.c: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@209768 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/rs6000')
-rw-r--r--gcc/config/rs6000/altivec.md112
-rw-r--r--gcc/config/rs6000/dfp.md69
-rw-r--r--gcc/config/rs6000/predicates.md5
-rw-r--r--gcc/config/rs6000/rs6000-builtin.def135
-rw-r--r--gcc/config/rs6000/rs6000.c82
-rw-r--r--gcc/config/rs6000/rs6000.h10
-rw-r--r--gcc/config/rs6000/rs6000.md208
7 files changed, 606 insertions, 15 deletions
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 674cb40bf7a..a8cfcb739ea 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -143,6 +143,9 @@
UNSPEC_VSUBEUQM
UNSPEC_VSUBECUQ
UNSPEC_VBPERMQ
+ UNSPEC_BCDADD
+ UNSPEC_BCDSUB
+ UNSPEC_BCD_OVERFLOW
])
(define_c_enum "unspecv"
@@ -3334,3 +3337,112 @@
"vbpermq %0,%1,%2"
[(set_attr "length" "4")
(set_attr "type" "vecsimple")])
+
+;; Decimal Integer operations
+(define_int_iterator UNSPEC_BCD_ADD_SUB [UNSPEC_BCDADD UNSPEC_BCDSUB])
+
+(define_int_attr bcd_add_sub [(UNSPEC_BCDADD "add")
+ (UNSPEC_BCDSUB "sub")])
+
+(define_code_iterator BCD_TEST [eq lt gt unordered])
+
+(define_insn "bcd<bcd_add_sub>"
+ [(set (match_operand:V1TI 0 "register_operand" "")
+ (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "")
+ (match_operand:V1TI 2 "register_operand" "")
+ (match_operand:QI 3 "const_0_to_1_operand" "")]
+ UNSPEC_BCD_ADD_SUB))
+ (clobber (reg:CCFP 74))]
+ "TARGET_P8_VECTOR"
+ "bcd<bcd_add_sub>. %0,%1,%2,%3"
+ [(set_attr "length" "4")
+ (set_attr "type" "vecsimple")])
+
+;; Use a floating point type (V2DFmode) for the compare to set CR6 so that we
+;; can use the unordered test for BCD nans and add/subtracts that overflow. An
+;; UNORDERED test on an integer type (like V1TImode) is not defined. The type
+;; probably should be one that can go in the VMX (Altivec) registers, so we
+;; can't use DDmode or DFmode.
+(define_insn "*bcd<bcd_add_sub>_test"
+ [(set (reg:CCFP 74)
+ (compare:CCFP
+ (unspec:V2DF [(match_operand:V1TI 1 "register_operand" "v")
+ (match_operand:V1TI 2 "register_operand" "v")
+ (match_operand:QI 3 "const_0_to_1_operand" "i")]
+ UNSPEC_BCD_ADD_SUB)
+ (match_operand:V2DF 4 "zero_constant" "j")))
+ (clobber (match_scratch:V1TI 0 "=v"))]
+ "TARGET_P8_VECTOR"
+ "bcd<bcd_add_sub>. %0,%1,%2,%3"
+ [(set_attr "length" "4")
+ (set_attr "type" "vecsimple")])
+
+(define_insn "*bcd<bcd_add_sub>_test2"
+ [(set (match_operand:V1TI 0 "register_operand" "=v")
+ (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v")
+ (match_operand:V1TI 2 "register_operand" "v")
+ (match_operand:QI 3 "const_0_to_1_operand" "i")]
+ UNSPEC_BCD_ADD_SUB))
+ (set (reg:CCFP 74)
+ (compare:CCFP
+ (unspec:V2DF [(match_dup 1)
+ (match_dup 2)
+ (match_dup 3)]
+ UNSPEC_BCD_ADD_SUB)
+ (match_operand:V2DF 4 "zero_constant" "j")))]
+ "TARGET_P8_VECTOR"
+ "bcd<bcd_add_sub>. %0,%1,%2,%3"
+ [(set_attr "length" "4")
+ (set_attr "type" "vecsimple")])
+
+(define_expand "bcd<bcd_add_sub>_<code>"
+ [(parallel [(set (reg:CCFP 74)
+ (compare:CCFP
+ (unspec:V2DF [(match_operand:V1TI 1 "register_operand" "")
+ (match_operand:V1TI 2 "register_operand" "")
+ (match_operand:QI 3 "const_0_to_1_operand" "")]
+ UNSPEC_BCD_ADD_SUB)
+ (match_dup 4)))
+ (clobber (match_scratch:V1TI 5 ""))])
+ (set (match_operand:SI 0 "register_operand" "")
+ (BCD_TEST:SI (reg:CCFP 74)
+ (const_int 0)))]
+ "TARGET_P8_VECTOR"
+{
+ operands[4] = CONST0_RTX (V2DFmode);
+})
+
+;; Peephole2 pattern to combine a bcdadd/bcdsub that calculates the value and
+;; the bcdadd/bcdsub that tests the value. The combiner won't work since
+;; CR6 is a hard coded register. Unfortunately, all of the Altivec predicate
+;; support is hard coded to use the fixed register CR6 instead of creating
+;; a register class for CR6.
+
+(define_peephole2
+ [(parallel [(set (match_operand:V1TI 0 "register_operand" "")
+ (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "")
+ (match_operand:V1TI 2 "register_operand" "")
+ (match_operand:QI 3 "const_0_to_1_operand" "")]
+ UNSPEC_BCD_ADD_SUB))
+ (clobber (reg:CCFP 74))])
+ (parallel [(set (reg:CCFP 74)
+ (compare:CCFP
+ (unspec:V2DF [(match_dup 1)
+ (match_dup 2)
+ (match_dup 3)]
+ UNSPEC_BCD_ADD_SUB)
+ (match_operand:V2DF 4 "zero_constant" "")))
+ (clobber (match_operand:V1TI 5 "register_operand" ""))])]
+ "TARGET_P8_VECTOR"
+ [(parallel [(set (match_dup 0)
+ (unspec:V1TI [(match_dup 1)
+ (match_dup 2)
+ (match_dup 3)]
+ UNSPEC_BCD_ADD_SUB))
+ (set (reg:CCFP 74)
+ (compare:CCFP
+ (unspec:V2DF [(match_dup 1)
+ (match_dup 2)
+ (match_dup 3)]
+ UNSPEC_BCD_ADD_SUB)
+ (match_dup 4)))])])
diff --git a/gcc/config/rs6000/dfp.md b/gcc/config/rs6000/dfp.md
index 8e99bc0d787..40e27e77d23 100644
--- a/gcc/config/rs6000/dfp.md
+++ b/gcc/config/rs6000/dfp.md
@@ -322,3 +322,72 @@
"TARGET_DFP"
"dctfixq %0,%1"
[(set_attr "type" "fp")])
+
+
+;; Decimal builtin support
+
+(define_c_enum "unspec"
+ [UNSPEC_DDEDPD
+ UNSPEC_DENBCD
+ UNSPEC_DXEX
+ UNSPEC_DIEX
+ UNSPEC_DSCLI
+ UNSPEC_DSCRI])
+
+(define_mode_iterator D64_D128 [DD TD])
+
+(define_mode_attr dfp_suffix [(DD "")
+ (TD "q")])
+
+(define_insn "dfp_ddedpd_<mode>"
+ [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
+ (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i")
+ (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
+ UNSPEC_DDEDPD))]
+ "TARGET_DFP"
+ "ddedpd<dfp_suffix> %1,%0,%2"
+ [(set_attr "type" "fp")])
+
+(define_insn "dfp_denbcd_<mode>"
+ [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
+ (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i")
+ (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
+ UNSPEC_DENBCD))]
+ "TARGET_DFP"
+ "denbcd<dfp_suffix> %1,%0,%2"
+ [(set_attr "type" "fp")])
+
+(define_insn "dfp_dxex_<mode>"
+ [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
+ (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")]
+ UNSPEC_DXEX))]
+ "TARGET_DFP"
+ "dxex<dfp_suffix> %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "dfp_diex_<mode>"
+ [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
+ (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
+ (match_operand:D64_D128 2 "gpc_reg_operand" "d")]
+ UNSPEC_DXEX))]
+ "TARGET_DFP"
+ "diex<dfp_suffix> %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+(define_insn "dfp_dscli_<mode>"
+ [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
+ (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
+ (match_operand:QI 2 "immediate_operand" "i")]
+ UNSPEC_DSCLI))]
+ "TARGET_DFP"
+ "dscli<dfp_suffix> %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+(define_insn "dfp_dscri_<mode>"
+ [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d")
+ (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")
+ (match_operand:QI 2 "immediate_operand" "i")]
+ UNSPEC_DSCRI))]
+ "TARGET_DFP"
+ "dscri<dfp_suffix> %0,%1,%2"
+ [(set_attr "type" "fp")])
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 28f4f5d98b1..99903f36769 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -171,6 +171,11 @@
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 0, 1)")))
+;; Match op = 0..3.
+(define_predicate "const_0_to_3_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 0, 3)")))
+
;; Match op = 2 or op = 3.
(define_predicate "const_2_to_3_operand"
(and (match_code "const_int")
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 83351691fa5..16793f501e7 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -570,6 +570,75 @@
MASK, /* MASK */ \
(ATTR | RS6000_BTC_SPECIAL), /* ATTR */ \
CODE_FOR_nothing) /* ICODE */
+
+
+/* Decimal floating point builtins for instructions. */
+#define BU_DFP_MISC_1(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_1 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_DFP, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_UNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_DFP_MISC_2(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_DFP, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_BINARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+
+/* Miscellaneous builtins for instructions added in ISA 2.06. These
+ instructions don't require either the DFP or VSX options, just the basic ISA
+ 2.06 (popcntd) enablement since they operate on general purpose
+ registers. */
+#define BU_P7_MISC_1(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_1 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_POPCNTD, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_UNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_P7_MISC_2(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_POPCNTD, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_BINARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+
+/* Miscellaneous builtins for instructions added in ISA 2.07. These
+ instructions do require the ISA 2.07 vector support, but they aren't vector
+ instructions. */
+#define BU_P8V_MISC_3(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_3 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_P8_VECTOR, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_TERNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+/* Miscellaneous builtins. */
+#define BU_MISC_1(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_ALWAYS, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_UNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_MISC_2(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_ALWAYS, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_BINARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
#endif
/* Insure 0 is not a legitimate index. */
@@ -1412,10 +1481,10 @@ BU_P8V_AV_2 (ORC_V4SF, "orc_v4sf", CONST, orcv4sf3)
BU_P8V_AV_2 (ORC_V2DF, "orc_v2df", CONST, orcv2df3)
/* 3 argument altivec instructions added in ISA 2.07. */
-BU_P8V_AV_3 (VADDEUQM, "vaddeuqm", CONST, altivec_vaddeuqm)
-BU_P8V_AV_3 (VADDECUQ, "vaddecuq", CONST, altivec_vaddecuq)
-BU_P8V_AV_3 (VSUBEUQM, "vsubeuqm", CONST, altivec_vsubeuqm)
-BU_P8V_AV_3 (VSUBECUQ, "vsubecuq", CONST, altivec_vsubecuq)
+BU_P8V_AV_3 (VADDEUQM, "vaddeuqm", CONST, altivec_vaddeuqm)
+BU_P8V_AV_3 (VADDECUQ, "vaddecuq", CONST, altivec_vaddecuq)
+BU_P8V_AV_3 (VSUBEUQM, "vsubeuqm", CONST, altivec_vsubeuqm)
+BU_P8V_AV_3 (VSUBECUQ, "vsubecuq", CONST, altivec_vsubecuq)
/* Vector comparison instructions added in ISA 2.07. */
BU_P8V_AV_2 (VCMPEQUD, "vcmpequd", CONST, vector_eqv2di)
@@ -1475,6 +1544,64 @@ BU_P8V_OVERLOAD_3 (VSUBECUQ, "vsubecuq")
BU_P8V_OVERLOAD_3 (VSUBEUQM, "vsubeuqm")
+/* 2 argument extended divide functions added in ISA 2.06. */
+BU_P7_MISC_2 (DIVWE, "divwe", CONST, dive_si)
+BU_P7_MISC_2 (DIVWEO, "divweo", CONST, diveo_si)
+BU_P7_MISC_2 (DIVWEU, "divweu", CONST, diveu_si)
+BU_P7_MISC_2 (DIVWEUO, "divweuo", CONST, diveuo_si)
+BU_P7_MISC_2 (DIVDE, "divde", CONST, dive_di)
+BU_P7_MISC_2 (DIVDEO, "divdeo", CONST, diveo_di)
+BU_P7_MISC_2 (DIVDEU, "divdeu", CONST, diveu_di)
+BU_P7_MISC_2 (DIVDEUO, "divdeuo", CONST, diveuo_di)
+
+/* 1 argument DFP (decimal floating point) functions added in ISA 2.05. */
+BU_DFP_MISC_1 (DXEX, "dxex", CONST, dfp_dxex_dd)
+BU_DFP_MISC_1 (DXEXQ, "dxexq", CONST, dfp_dxex_td)
+
+/* 2 argument DFP (decimal floating point) functions added in ISA 2.05. */
+BU_DFP_MISC_2 (DDEDPD, "ddedpd", CONST, dfp_ddedpd_dd)
+BU_DFP_MISC_2 (DDEDPDQ, "ddedpdq", CONST, dfp_ddedpd_td)
+BU_DFP_MISC_2 (DENBCD, "denbcd", CONST, dfp_denbcd_dd)
+BU_DFP_MISC_2 (DENBCDQ, "denbcdq", CONST, dfp_denbcd_td)
+BU_DFP_MISC_2 (DIEX, "diex", CONST, dfp_diex_dd)
+BU_DFP_MISC_2 (DIEXQ, "diexq", CONST, dfp_diex_td)
+BU_DFP_MISC_2 (DSCLI, "dscli", CONST, dfp_dscli_dd)
+BU_DFP_MISC_2 (DSCLIQ, "dscliq", CONST, dfp_dscli_td)
+BU_DFP_MISC_2 (DSCRI, "dscri", CONST, dfp_dscri_dd)
+BU_DFP_MISC_2 (DSCRIQ, "dscriq", CONST, dfp_dscri_td)
+
+/* 1 argument BCD functions added in ISA 2.06. */
+BU_P7_MISC_1 (CDTBCD, "cdtbcd", CONST, cdtbcd)
+BU_P7_MISC_1 (CBCDTD, "cbcdtd", CONST, cbcdtd)
+
+/* 2 argument BCD functions added in ISA 2.06. */
+BU_P7_MISC_2 (ADDG6S, "addg6s", CONST, addg6s)
+
+/* 3 argument BCD functions added in ISA 2.07. */
+BU_P8V_MISC_3 (BCDADD, "bcdadd", CONST, bcdadd)
+BU_P8V_MISC_3 (BCDADD_LT, "bcdadd_lt", CONST, bcdadd_lt)
+BU_P8V_MISC_3 (BCDADD_EQ, "bcdadd_eq", CONST, bcdadd_eq)
+BU_P8V_MISC_3 (BCDADD_GT, "bcdadd_gt", CONST, bcdadd_gt)
+BU_P8V_MISC_3 (BCDADD_OV, "bcdadd_ov", CONST, bcdadd_unordered)
+BU_P8V_MISC_3 (BCDSUB, "bcdsub", CONST, bcdsub)
+BU_P8V_MISC_3 (BCDSUB_LT, "bcdsub_lt", CONST, bcdsub_lt)
+BU_P8V_MISC_3 (BCDSUB_EQ, "bcdsub_eq", CONST, bcdsub_eq)
+BU_P8V_MISC_3 (BCDSUB_GT, "bcdsub_gt", CONST, bcdsub_gt)
+BU_P8V_MISC_3 (BCDSUB_OV, "bcdsub_ov", CONST, bcdsub_unordered)
+
+/* 2 argument pack/unpack 128-bit floating point types. */
+BU_DFP_MISC_2 (PACK_TD, "pack_dec128", CONST, packtd)
+BU_DFP_MISC_2 (UNPACK_TD, "unpack_dec128", CONST, unpacktd)
+
+BU_MISC_2 (PACK_TF, "pack_longdouble", CONST, packtf)
+BU_MISC_2 (UNPACK_TF, "unpack_longdouble", CONST, unpacktf)
+BU_MISC_1 (UNPACK_TF_0, "longdouble_dw0", CONST, unpacktf_0)
+BU_MISC_1 (UNPACK_TF_1, "longdouble_dw1", CONST, unpacktf_1)
+
+BU_P7_MISC_2 (PACK_V1TI, "pack_vector_int128", CONST, packv1ti)
+BU_P7_MISC_2 (UNPACK_V1TI, "unpack_vector_int128", CONST, unpackv1ti)
+
+
/* 1 argument crypto functions. */
BU_CRYPTO_1 (VSBOX, "vsbox", CONST, crypto_vsbox)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index d15b3ca9b9c..ca8fa5953c2 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -3038,7 +3038,8 @@ rs6000_builtin_mask_calculate (void)
| ((rs6000_cpu == PROCESSOR_CELL) ? RS6000_BTM_CELL : 0)
| ((TARGET_P8_VECTOR) ? RS6000_BTM_P8_VECTOR : 0)
| ((TARGET_CRYPTO) ? RS6000_BTM_CRYPTO : 0)
- | ((TARGET_HTM) ? RS6000_BTM_HTM : 0));
+ | ((TARGET_HTM) ? RS6000_BTM_HTM : 0)
+ | ((TARGET_DFP) ? RS6000_BTM_DFP : 0));
}
/* Override command line options. Mostly we process the processor type and
@@ -12402,7 +12403,15 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
}
}
else if (icode == CODE_FOR_vsx_set_v2df
- || icode == CODE_FOR_vsx_set_v2di)
+ || icode == CODE_FOR_vsx_set_v2di
+ || icode == CODE_FOR_bcdadd
+ || icode == CODE_FOR_bcdadd_lt
+ || icode == CODE_FOR_bcdadd_eq
+ || icode == CODE_FOR_bcdadd_gt
+ || icode == CODE_FOR_bcdsub
+ || icode == CODE_FOR_bcdsub_lt
+ || icode == CODE_FOR_bcdsub_eq
+ || icode == CODE_FOR_bcdsub_gt)
{
/* Only allow 1-bit unsigned literals. */
STRIP_NOPS (arg2);
@@ -12413,6 +12422,44 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
return const0_rtx;
}
}
+ else if (icode == CODE_FOR_dfp_ddedpd_dd
+ || icode == CODE_FOR_dfp_ddedpd_td)
+ {
+ /* Only allow 2-bit unsigned literals where the value is 0 or 2. */
+ STRIP_NOPS (arg0);
+ if (TREE_CODE (arg0) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg2) & ~0x3)
+ {
+ error ("argument 1 must be 0 or 2");
+ return const0_rtx;
+ }
+ }
+ else if (icode == CODE_FOR_dfp_denbcd_dd
+ || icode == CODE_FOR_dfp_denbcd_td)
+ {
+ /* Only allow 1-bit unsigned literals. */
+ STRIP_NOPS (arg0);
+ if (TREE_CODE (arg0) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg0) & ~0x1)
+ {
+ error ("argument 1 must be a 1-bit unsigned literal");
+ return const0_rtx;
+ }
+ }
+ else if (icode == CODE_FOR_dfp_dscli_dd
+ || icode == CODE_FOR_dfp_dscli_td
+ || icode == CODE_FOR_dfp_dscri_dd
+ || icode == CODE_FOR_dfp_dscri_td)
+ {
+ /* Only allow 6-bit unsigned literals. */
+ STRIP_NOPS (arg1);
+ if (TREE_CODE (arg1) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg1) & ~0x3f)
+ {
+ error ("argument 2 must be a 6-bit unsigned literal");
+ return const0_rtx;
+ }
+ }
else if (icode == CODE_FOR_crypto_vshasigmaw
|| icode == CODE_FOR_crypto_vshasigmad)
{
@@ -13504,6 +13551,14 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode)
error ("Builtin function %s requires the -mpaired option", name);
else if ((fnmask & RS6000_BTM_SPE) != 0)
error ("Builtin function %s requires the -mspe option", name);
+ else if ((fnmask & (RS6000_BTM_DFP | RS6000_BTM_P8_VECTOR))
+ == (RS6000_BTM_DFP | RS6000_BTM_P8_VECTOR))
+ error ("Builtin function %s requires the -mhard-dfp and"
+ "-mpower8-vector options", name);
+ else if ((fnmask & RS6000_BTM_DFP) != 0)
+ error ("Builtin function %s requires the -mhard-dfp option", name);
+ else if ((fnmask & RS6000_BTM_P8_VECTOR) != 0)
+ error ("Builtin function %s requires the -mpower8-vector option", name);
else
error ("Builtin function %s is not supported with the current options",
name);
@@ -13783,6 +13838,9 @@ rs6000_init_builtins (void)
uintTI_type_internal_node = unsigned_intTI_type_node;
float_type_internal_node = float_type_node;
double_type_internal_node = double_type_node;
+ long_double_type_internal_node = long_double_type_node;
+ dfloat64_type_internal_node = dfloat64_type_node;
+ dfloat128_type_internal_node = dfloat128_type_node;
void_type_internal_node = void_type_node;
/* Initialize the modes for builtin_function_type, mapping a machine mode to
@@ -13797,6 +13855,9 @@ rs6000_init_builtins (void)
builtin_mode_to_type[TImode][1] = unsigned_intTI_type_node;
builtin_mode_to_type[SFmode][0] = float_type_node;
builtin_mode_to_type[DFmode][0] = double_type_node;
+ builtin_mode_to_type[TFmode][0] = long_double_type_node;
+ builtin_mode_to_type[DDmode][0] = dfloat64_type_node;
+ builtin_mode_to_type[TDmode][0] = dfloat128_type_node;
builtin_mode_to_type[V1TImode][0] = V1TI_type_node;
builtin_mode_to_type[V1TImode][1] = unsigned_V1TI_type_node;
builtin_mode_to_type[V2SImode][0] = V2SI_type_node;
@@ -14889,6 +14950,8 @@ builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0,
/* unsigned 1 argument functions. */
case CRYPTO_BUILTIN_VSBOX:
case P8V_BUILTIN_VGBBD:
+ case MISC_BUILTIN_CDTBCD:
+ case MISC_BUILTIN_CBCDTD:
h.uns_p[0] = 1;
h.uns_p[1] = 1;
break;
@@ -14907,6 +14970,11 @@ builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0,
case CRYPTO_BUILTIN_VPMSUMW:
case CRYPTO_BUILTIN_VPMSUMD:
case CRYPTO_BUILTIN_VPMSUM:
+ case MISC_BUILTIN_ADDG6S:
+ case MISC_BUILTIN_DIVWEU:
+ case MISC_BUILTIN_DIVWEUO:
+ case MISC_BUILTIN_DIVDEU:
+ case MISC_BUILTIN_DIVDEUO:
h.uns_p[0] = 1;
h.uns_p[1] = 1;
h.uns_p[2] = 1;
@@ -14968,9 +15036,18 @@ builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0,
/* signed args, unsigned return. */
case VSX_BUILTIN_XVCVDPUXDS_UNS:
case ALTIVEC_BUILTIN_FIXUNS_V4SF_V4SI:
+ case MISC_BUILTIN_UNPACK_TD:
+ case MISC_BUILTIN_UNPACK_V1TI:
h.uns_p[0] = 1;
break;
+ /* unsigned arguments for 128-bit pack instructions. */
+ case MISC_BUILTIN_PACK_TD:
+ case MISC_BUILTIN_PACK_V1TI:
+ h.uns_p[1] = 1;
+ h.uns_p[2] = 1;
+ break;
+
default:
break;
}
@@ -31224,6 +31301,7 @@ static struct rs6000_opt_mask const rs6000_builtin_mask_names[] =
{ "power8-vector", RS6000_BTM_P8_VECTOR, false, false },
{ "crypto", RS6000_BTM_CRYPTO, false, false },
{ "htm", RS6000_BTM_HTM, false, false },
+ { "hard-dfp", RS6000_BTM_DFP, false, false },
};
/* Option variables that we want to support inside attribute((target)) and
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 9ec3647fedd..5a96bebaf10 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -2516,6 +2516,7 @@ extern int frame_pointer_needed;
#define RS6000_BTM_FRSQRTES MASK_POPCNTB /* FRSQRTES instruction. */
#define RS6000_BTM_POPCNTD MASK_POPCNTD /* Target supports ISA 2.06. */
#define RS6000_BTM_CELL MASK_FPRND /* Target is cell powerpc. */
+#define RS6000_BTM_DFP MASK_DFP /* Decimal floating point. */
#define RS6000_BTM_COMMON (RS6000_BTM_ALTIVEC \
| RS6000_BTM_VSX \
@@ -2527,7 +2528,8 @@ extern int frame_pointer_needed;
| RS6000_BTM_FRSQRTES \
| RS6000_BTM_HTM \
| RS6000_BTM_POPCNTD \
- | RS6000_BTM_CELL)
+ | RS6000_BTM_CELL \
+ | RS6000_BTM_DFP)
/* Define builtin enum index. */
@@ -2622,6 +2624,9 @@ enum rs6000_builtin_type_index
RS6000_BTI_UINTTI, /* unsigned_intTI_type_node */
RS6000_BTI_float, /* float_type_node */
RS6000_BTI_double, /* double_type_node */
+ RS6000_BTI_long_double, /* long_double_type_node */
+ RS6000_BTI_dfloat64, /* dfloat64_type_node */
+ RS6000_BTI_dfloat128, /* dfloat128_type_node */
RS6000_BTI_void, /* void_type_node */
RS6000_BTI_MAX
};
@@ -2673,6 +2678,9 @@ enum rs6000_builtin_type_index
#define uintTI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTTI])
#define float_type_internal_node (rs6000_builtin_types[RS6000_BTI_float])
#define double_type_internal_node (rs6000_builtin_types[RS6000_BTI_double])
+#define long_double_type_internal_node (rs6000_builtin_types[RS6000_BTI_long_double])
+#define dfloat64_type_internal_node (rs6000_builtin_types[RS6000_BTI_dfloat64])
+#define dfloat128_type_internal_node (rs6000_builtin_types[RS6000_BTI_dfloat128])
#define void_type_internal_node (rs6000_builtin_types[RS6000_BTI_void])
extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index eca1dde06b6..9207b4d5106 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -125,6 +125,15 @@
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
])
;;
@@ -481,6 +490,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 +2768,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 +2792,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" ""))
@@ -15735,6 +15742,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")