(define_predicate "nvptx_float_comparison_operator"
(match_code "eq,ne,le,ge,lt,gt,uneq,unle,unge,unlt,ungt,unordered,ordered"))
+(define_predicate "nvptx_vector_index_operand"
+ (and (match_code "const_int")
+ (match_test "UINTVAL (op) < 4")))
+
;; Test for a valid operand for a call instruction.
(define_predicate "call_insn_operand"
(match_code "symbol_ref,reg")
;; pointer-sized quantities. Exactly one of the two alternatives will match.
(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
+;; Define element mode for each vector mode.
+(define_mode_attr VECELEM [(V2SI "SI") (V2DI "DI")])
+(define_mode_attr Vecelem [(V2SI "si") (V2DI "di")])
+
;; We should get away with not defining memory alternatives, since we don't
;; get variables in this mode and pseudos are never spilled.
(define_insn "movbi"
""
"%.\\tcvt<FPINT2:fpint2_roundingmode>.s%T0%t1\\t%0, %1;")
+;; Vector operations
+
+(define_insn "*vec_set<mode>_0"
+ [(set (match_operand:VECIM 0 "nvptx_register_operand" "=R")
+ (vec_merge:VECIM
+ (vec_duplicate:VECIM
+ (match_operand:<VECELEM> 1 "nvptx_register_operand" "R"))
+ (match_dup 0)
+ (const_int 1)))]
+ ""
+ "%.\\tmov%t1\\t%0.x, %1;")
+
+(define_insn "*vec_set<mode>_1"
+ [(set (match_operand:VECIM 0 "nvptx_register_operand" "=R")
+ (vec_merge:VECIM
+ (vec_duplicate:VECIM
+ (match_operand:<VECELEM> 1 "nvptx_register_operand" "R"))
+ (match_dup 0)
+ (const_int 2)))]
+ ""
+ "%.\\tmov%t1\\t%0.y, %1;")
+
+(define_insn "*vec_set<mode>_2"
+ [(set (match_operand:VECIM 0 "nvptx_register_operand" "=R")
+ (vec_merge:VECIM
+ (vec_duplicate:VECIM
+ (match_operand:<VECELEM> 1 "nvptx_register_operand" "R"))
+ (match_dup 0)
+ (const_int 4)))]
+ ""
+ "%.\\tmov%t1\\t%0.z, %1;")
+
+(define_insn "*vec_set<mode>_3"
+ [(set (match_operand:VECIM 0 "nvptx_register_operand" "=R")
+ (vec_merge:VECIM
+ (vec_duplicate:VECIM
+ (match_operand:<VECELEM> 1 "nvptx_register_operand" "R"))
+ (match_dup 0)
+ (const_int 8)))]
+ ""
+ "%.\\tmov%t1\\t%0.w, %1;")
+
+(define_expand "vec_set<mode>"
+ [(match_operand:VECIM 0 "nvptx_register_operand")
+ (match_operand:<VECELEM> 1 "nvptx_register_operand")
+ (match_operand:SI 2 "nvptx_vector_index_operand")]
+ ""
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+ int mask = 1 << INTVAL (operands[2]);
+ rtx tmp = gen_rtx_VEC_DUPLICATE (mode, operands[1]);
+ tmp = gen_rtx_VEC_MERGE (mode, tmp, operands[0], GEN_INT (mask));
+ emit_insn (gen_rtx_SET (operands[0], tmp));
+ DONE;
+})
+
+(define_insn "vec_extract<mode><Vecelem>"
+ [(set (match_operand:<VECELEM> 0 "nvptx_register_operand" "=R")
+ (vec_select:<VECELEM>
+ (match_operand:VECIM 1 "nvptx_register_operand" "R")
+ (parallel [(match_operand:SI 2 "nvptx_vector_index_operand" "")])))]
+ ""
+{
+ static const char *const asms[4] = {
+ "%.\\tmov%t0\\t%0, %1.x;",
+ "%.\\tmov%t0\\t%0, %1.y;",
+ "%.\\tmov%t0\\t%0, %1.z;",
+ "%.\\tmov%t0\\t%0, %1.w;"
+ };
+ return asms[INTVAL (operands[2])];
+})
+
;; Miscellaneous
(define_insn "nop"