+
+
+;; Stack protector instructions.
+
+(define_expand "stack_protect_set"
+ [(match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")]
+ ""
+{
+#ifdef TARGET_THREAD_SSP_OFFSET
+ rtx tlsreg = gen_rtx_REG (Pmode, 7);
+ rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+ operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+ if (TARGET_ARCH64)
+ emit_insn (gen_stack_protect_setdi (operands[0], operands[1]));
+ else
+ emit_insn (gen_stack_protect_setsi (operands[0], operands[1]));
+ DONE;
+})
+
+(define_insn "stack_protect_setsi"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+ (set (match_scratch:SI 2 "=&r") (const_int 0))]
+ "TARGET_ARCH32"
+ "ld\t%1, %2\;st\t%2, %0\;mov\t0, %2"
+ [(set_attr "type" "multi")
+ (set_attr "length" "3")])
+
+(define_insn "stack_protect_setdi"
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+ (set (match_scratch:DI 2 "=&r") (const_int 0))]
+ "TARGET_ARCH64"
+ "ldx\t%1, %2\;stx\t%2, %0\;mov\t0, %2"
+ [(set_attr "type" "multi")
+ (set_attr "length" "3")])
+
+(define_expand "stack_protect_test"
+ [(match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")
+ (match_operand 2 "" "")]
+ ""
+{
+ rtx result, test;
+#ifdef TARGET_THREAD_SSP_OFFSET
+ rtx tlsreg = gen_rtx_REG (Pmode, 7);
+ rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+ operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+ if (TARGET_ARCH64)
+ {
+ result = gen_reg_rtx (Pmode);
+ emit_insn (gen_stack_protect_testdi (result, operands[0], operands[1]));
+ test = gen_rtx_EQ (VOIDmode, result, const0_rtx);
+ emit_jump_insn (gen_cbranchdi4 (test, result, const0_rtx, operands[2]));
+ }
+ else
+ {
+ emit_insn (gen_stack_protect_testsi (operands[0], operands[1]));
+ result = gen_rtx_REG (CCmode, SPARC_ICC_REG);
+ test = gen_rtx_EQ (VOIDmode, result, const0_rtx);
+ emit_jump_insn (gen_cbranchcc4 (test, result, const0_rtx, operands[2]));
+ }
+ DONE;
+})
+
+(define_insn "stack_protect_testsi"
+ [(set (reg:CC CC_REG)
+ (unspec:CC [(match_operand:SI 0 "memory_operand" "m")
+ (match_operand:SI 1 "memory_operand" "m")]
+ UNSPEC_SP_TEST))
+ (set (match_scratch:SI 3 "=r") (const_int 0))
+ (clobber (match_scratch:SI 2 "=&r"))]
+ "TARGET_ARCH32"
+ "ld\t%0, %2\;ld\t%1, %3\;xorcc\t%2, %3, %2\;mov\t0, %3"
+ [(set_attr "type" "multi")
+ (set_attr "length" "4")])
+
+(define_insn "stack_protect_testdi"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
+ (match_operand:DI 2 "memory_operand" "m")]
+ UNSPEC_SP_TEST))
+ (set (match_scratch:DI 3 "=r") (const_int 0))]
+ "TARGET_ARCH64"
+ "ldx\t%1, %0\;ldx\t%2, %3\;xor\t%0, %3, %0\;mov\t0, %3"
+ [(set_attr "type" "multi")
+ (set_attr "length" "4")])
+
+;; Vector instructions.
+
+(define_mode_iterator VM32 [V1SI V2HI V4QI])
+(define_mode_iterator VM64 [V1DI V2SI V4HI V8QI])
+(define_mode_iterator VMALL [V1SI V2HI V4QI V1DI V2SI V4HI V8QI])
+
+(define_mode_attr vbits [(V2SI "32") (V4HI "16") (V1SI "32s") (V2HI "16s")])
+(define_mode_attr vconstr [(V1SI "f") (V2HI "f") (V4QI "f")
+ (V1DI "e") (V2SI "e") (V4HI "e") (V8QI "e")])
+(define_mode_attr vfptype [(V1SI "single") (V2HI "single") (V4QI "single")
+ (V1DI "double") (V2SI "double") (V4HI "double")
+ (V8QI "double")])
+
+(define_expand "mov<VMALL:mode>"
+ [(set (match_operand:VMALL 0 "nonimmediate_operand" "")
+ (match_operand:VMALL 1 "general_operand" ""))]
+ "TARGET_VIS"
+{
+ if (sparc_expand_move (<VMALL:MODE>mode, operands))
+ DONE;
+})
+
+(define_insn "*mov<VM32:mode>_insn"
+ [(set (match_operand:VM32 0 "nonimmediate_operand" "=f, f,f,f,m, m,r,m, r, r")
+ (match_operand:VM32 1 "input_operand" "GY,ZC,f,m,f,GY,m,r,GY,ZC"))]
+ "TARGET_VIS
+ && (register_operand (operands[0], <VM32:MODE>mode)
+ || register_or_zero_or_all_ones_operand (operands[1], <VM32:MODE>mode))"
+ "@
+ fzeros\t%0
+ fones\t%0
+ fsrc1s\t%1, %0
+ ld\t%1, %0
+ st\t%1, %0
+ st\t%r1, %0
+ ld\t%1, %0
+ st\t%1, %0
+ mov\t0, %0
+ mov\t-1, %0"
+ [(set_attr "type" "fga,fga,fga,fpload,fpstore,store,load,store,*,*")])
+
+(define_insn "*mov<VM64:mode>_insn_sp64"
+ [(set (match_operand:VM64 0 "nonimmediate_operand" "=e, e,e,e,m, m,r,m, r, r")
+ (match_operand:VM64 1 "input_operand" "GY,ZC,e,m,e,GY,m,r,GY,ZC"))]
+ "TARGET_VIS
+ && TARGET_ARCH64
+ && (register_operand (operands[0], <VM64:MODE>mode)
+ || register_or_zero_or_all_ones_operand (operands[1], <VM64:MODE>mode))"
+ "@
+ fzero\t%0
+ fone\t%0
+ fsrc1\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0
+ stx\t%r1, %0
+ ldx\t%1, %0
+ stx\t%1, %0
+ mov\t0, %0
+ mov\t-1, %0"
+ [(set_attr "type" "fga,fga,fga,fpload,fpstore,store,load,store,*,*")])
+
+(define_insn "*mov<VM64:mode>_insn_sp32"
+ [(set (match_operand:VM64 0 "nonimmediate_operand" "=e, e,e,e,m, m,U,T,o, r, r")
+ (match_operand:VM64 1 "input_operand" "GY,ZC,e,m,e,GY,T,U,r,GY,ZC"))]
+ "TARGET_VIS
+ && ! TARGET_ARCH64
+ && (register_operand (operands[0], <VM64:MODE>mode)
+ || register_or_zero_or_all_ones_operand (operands[1], <VM64:MODE>mode))"
+ "@
+ fzero\t%0
+ fone\t%0
+ fsrc1\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0
+ stx\t%r1, %0
+ ldd\t%1, %0
+ std\t%1, %0
+ #
+ mov 0, %L0; mov 0, %H0
+ mov -1, %L0; mov -1, %H0"
+ [(set_attr "type" "fga,fga,fga,fpload,fpstore,store,load,store,*,*,*")
+ (set_attr "length" "*,*,*,*,*,*,*,*,2,2,2")])
+
+(define_split
+ [(set (match_operand:VM64 0 "memory_operand" "")
+ (match_operand:VM64 1 "register_operand" ""))]
+ "reload_completed
+ && TARGET_VIS
+ && ! TARGET_ARCH64
+ && (((REGNO (operands[1]) % 2) != 0)
+ || ! mem_min_alignment (operands[0], 8))
+ && offsettable_memref_p (operands[0])"
+ [(clobber (const_int 0))]
+{
+ rtx word0, word1;
+
+ word0 = adjust_address (operands[0], SImode, 0);
+ word1 = adjust_address (operands[0], SImode, 4);
+
+ emit_move_insn_1 (word0, gen_highpart (SImode, operands[1]));
+ emit_move_insn_1 (word1, gen_lowpart (SImode, operands[1]));
+ DONE;
+})
+
+(define_expand "vec_init<mode>"
+ [(match_operand:VMALL 0 "register_operand" "")
+ (match_operand:VMALL 1 "" "")]
+ "TARGET_VIS"
+{
+ sparc_expand_vector_init (operands[0], operands[1]);
+ DONE;
+})
+
+(define_code_iterator plusminus [plus minus])
+(define_code_attr plusminus_insn [(plus "add") (minus "sub")])
+
+(define_mode_iterator VADDSUB [V1SI V2SI V2HI V4HI])
+
+(define_insn "<plusminus_insn><mode>3"
+ [(set (match_operand:VADDSUB 0 "register_operand" "=<vconstr>")
+ (plusminus:VADDSUB (match_operand:VADDSUB 1 "register_operand" "<vconstr>")
+ (match_operand:VADDSUB 2 "register_operand" "<vconstr>")))]
+ "TARGET_VIS"
+ "fp<plusminus_insn><vbits>\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "<vfptype>")])
+
+(define_mode_iterator VL [V1SI V2HI V4QI V1DI V2SI V4HI V8QI])
+(define_mode_attr vlsuf [(V1SI "s") (V2HI "s") (V4QI "s")
+ (V1DI "") (V2SI "") (V4HI "") (V8QI "")])
+(define_code_iterator vlop [ior and xor])
+(define_code_attr vlinsn [(ior "or") (and "and") (xor "xor")])
+(define_code_attr vlninsn [(ior "nor") (and "nand") (xor "xnor")])
+
+(define_insn "<code><mode>3"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (vlop:VL (match_operand:VL 1 "register_operand" "<vconstr>")
+ (match_operand:VL 2 "register_operand" "<vconstr>")))]
+ "TARGET_VIS"
+ "f<vlinsn><vlsuf>\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "<vfptype>")])
+
+(define_insn "*not_<code><mode>3"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (not:VL (vlop:VL (match_operand:VL 1 "register_operand" "<vconstr>")
+ (match_operand:VL 2 "register_operand" "<vconstr>"))))]
+ "TARGET_VIS"
+ "f<vlninsn><vlsuf>\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "<vfptype>")])
+
+;; (ior (not (op1)) (not (op2))) is the canonical form of NAND.
+(define_insn "*nand<mode>_vis"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (ior:VL (not:VL (match_operand:VL 1 "register_operand" "<vconstr>"))
+ (not:VL (match_operand:VL 2 "register_operand" "<vconstr>"))))]
+ "TARGET_VIS"
+ "fnand<vlsuf>\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "<vfptype>")])
+
+(define_code_iterator vlnotop [ior and])
+
+(define_insn "*<code>_not1<mode>_vis"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (vlnotop:VL (not:VL (match_operand:VL 1 "register_operand" "<vconstr>"))
+ (match_operand:VL 2 "register_operand" "<vconstr>")))]
+ "TARGET_VIS"
+ "f<vlinsn>not1<vlsuf>\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "<vfptype>")])
+
+(define_insn "*<code>_not2<mode>_vis"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (vlnotop:VL (match_operand:VL 1 "register_operand" "<vconstr>")
+ (not:VL (match_operand:VL 2 "register_operand" "<vconstr>"))))]
+ "TARGET_VIS"
+ "f<vlinsn>not2<vlsuf>\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "<vfptype>")])
+
+(define_insn "one_cmpl<mode>2"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (not:VL (match_operand:VL 1 "register_operand" "<vconstr>")))]
+ "TARGET_VIS"
+ "fnot1<vlsuf>\t%1, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "<vfptype>")])
+
+;; Hard to generate VIS instructions. We have builtins for these.
+
+(define_insn "fpack16_vis"
+ [(set (match_operand:V4QI 0 "register_operand" "=f")
+ (unspec:V4QI [(match_operand:V4HI 1 "register_operand" "e")
+ (reg:DI GSR_REG)]
+ UNSPEC_FPACK16))]
+ "TARGET_VIS"
+ "fpack16\t%1, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "fpackfix_vis"
+ [(set (match_operand:V2HI 0 "register_operand" "=f")
+ (unspec:V2HI [(match_operand:V2SI 1 "register_operand" "e")
+ (reg:DI GSR_REG)]
+ UNSPEC_FPACKFIX))]
+ "TARGET_VIS"
+ "fpackfix\t%1, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "fpack32_vis"
+ [(set (match_operand:V8QI 0 "register_operand" "=e")
+ (unspec:V8QI [(match_operand:V2SI 1 "register_operand" "e")
+ (match_operand:V8QI 2 "register_operand" "e")
+ (reg:DI GSR_REG)]
+ UNSPEC_FPACK32))]
+ "TARGET_VIS"
+ "fpack32\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "fexpand_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")]
+ UNSPEC_FEXPAND))]
+ "TARGET_VIS"
+ "fexpand\t%1, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "fpmerge_vis"
+ [(set (match_operand:V8QI 0 "register_operand" "=e")
+ (vec_select:V8QI
+ (vec_concat:V8QI (match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V4QI 2 "register_operand" "f"))
+ (parallel [(const_int 0) (const_int 4)
+ (const_int 1) (const_int 5)
+ (const_int 2) (const_int 6)
+ (const_int 3) (const_int 7)])))]
+ "TARGET_VIS"
+ "fpmerge\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "vec_interleave_lowv8qi"
+ [(set (match_operand:V8QI 0 "register_operand" "=e")
+ (vec_select:V8QI
+ (vec_concat:V16QI (match_operand:V8QI 1 "register_operand" "f")
+ (match_operand:V8QI 2 "register_operand" "f"))
+ (parallel [(const_int 0) (const_int 8)
+ (const_int 1) (const_int 9)
+ (const_int 2) (const_int 10)
+ (const_int 3) (const_int 11)])))]
+ "TARGET_VIS"
+ "fpmerge\t%L1, %L2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "vec_interleave_highv8qi"
+ [(set (match_operand:V8QI 0 "register_operand" "=e")
+ (vec_select:V8QI
+ (vec_concat:V16QI (match_operand:V8QI 1 "register_operand" "f")
+ (match_operand:V8QI 2 "register_operand" "f"))
+ (parallel [(const_int 4) (const_int 12)
+ (const_int 5) (const_int 13)
+ (const_int 6) (const_int 14)
+ (const_int 7) (const_int 15)])))]
+ "TARGET_VIS"
+ "fpmerge\t%H1, %H2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+;; Partitioned multiply instructions
+(define_insn "fmul8x16_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V4HI 2 "register_operand" "e")]
+ UNSPEC_MUL8))]
+ "TARGET_VIS"
+ "fmul8x16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fmul8x16au_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")]
+ UNSPEC_MUL16AU))]
+ "TARGET_VIS"
+ "fmul8x16au\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fmul8x16al_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")]
+ UNSPEC_MUL16AL))]
+ "TARGET_VIS"
+ "fmul8x16al\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fmul8sux16_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")]
+ UNSPEC_MUL8SU))]
+ "TARGET_VIS"
+ "fmul8sux16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fmul8ulx16_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")]
+ UNSPEC_MUL8UL))]
+ "TARGET_VIS"
+ "fmul8ulx16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fmuld8sux16_vis"
+ [(set (match_operand:V2SI 0 "register_operand" "=e")
+ (unspec:V2SI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")]
+ UNSPEC_MULDSU))]
+ "TARGET_VIS"
+ "fmuld8sux16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fmuld8ulx16_vis"
+ [(set (match_operand:V2SI 0 "register_operand" "=e")
+ (unspec:V2SI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")]
+ UNSPEC_MULDUL))]
+ "TARGET_VIS"
+ "fmuld8ulx16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_expand "wrgsr_vis"
+ [(set (reg:DI GSR_REG) (match_operand:DI 0 "arith_operand" ""))]
+ "TARGET_VIS"
+{
+ if (! TARGET_ARCH64)
+ {
+ emit_insn (gen_wrgsr_v8plus (operands[0]));
+ DONE;
+ }
+})
+
+(define_insn "*wrgsr_sp64"
+ [(set (reg:DI GSR_REG) (match_operand:DI 0 "arith_operand" "rI"))]
+ "TARGET_VIS && TARGET_ARCH64"
+ "wr\t%%g0, %0, %%gsr"
+ [(set_attr "type" "gsr")])
+
+(define_insn "wrgsr_v8plus"
+ [(set (reg:DI GSR_REG) (match_operand:DI 0 "arith_operand" "I,r"))
+ (clobber (match_scratch:SI 1 "=X,&h"))]
+ "TARGET_VIS && ! TARGET_ARCH64"
+{
+ if (GET_CODE (operands[0]) == CONST_INT
+ || sparc_check_64 (operands[0], insn))
+ return "wr\t%%g0, %0, %%gsr";
+
+ output_asm_insn("srl\t%L0, 0, %L0", operands);
+ return "sllx\t%H0, 32, %1\n\tor\t%L0, %1, %1\n\twr\t%%g0, %1, %%gsr";
+}
+ [(set_attr "type" "multi")])
+
+(define_expand "rdgsr_vis"
+ [(set (match_operand:DI 0 "register_operand" "") (reg:DI GSR_REG))]
+ "TARGET_VIS"
+{
+ if (! TARGET_ARCH64)
+ {
+ emit_insn (gen_rdgsr_v8plus (operands[0]));
+ DONE;
+ }
+})
+
+(define_insn "*rdgsr_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r") (reg:DI GSR_REG))]
+ "TARGET_VIS && TARGET_ARCH64"
+ "rd\t%%gsr, %0"
+ [(set_attr "type" "gsr")])
+
+(define_insn "rdgsr_v8plus"
+ [(set (match_operand:DI 0 "register_operand" "=r") (reg:DI GSR_REG))
+ (clobber (match_scratch:SI 1 "=&h"))]
+ "TARGET_VIS && ! TARGET_ARCH64"
+{
+ return "rd\t%%gsr, %1\n\tsrlx\t%1, 32, %H0\n\tmov %1, %L0";
+}
+ [(set_attr "type" "multi")])
+
+;; Using faligndata only makes sense after an alignaddr since the choice of
+;; bytes to take out of each operand is dependent on the results of the last
+;; alignaddr.
+(define_insn "faligndata<VM64:mode>_vis"
+ [(set (match_operand:VM64 0 "register_operand" "=e")
+ (unspec:VM64 [(match_operand:VM64 1 "register_operand" "e")
+ (match_operand:VM64 2 "register_operand" "e")
+ (reg:DI GSR_REG)]
+ UNSPEC_ALIGNDATA))]
+ "TARGET_VIS"
+ "faligndata\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "alignaddrsi_vis"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "register_or_zero_operand" "rJ")))
+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 3) (const_int 0))
+ (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
+ "TARGET_VIS"
+ "alignaddr\t%r1, %r2, %0")
+
+(define_insn "alignaddrdi_vis"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
+ (match_operand:DI 2 "register_or_zero_operand" "rJ")))
+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 3) (const_int 0))
+ (plus:DI (match_dup 1) (match_dup 2)))]
+ "TARGET_VIS"
+ "alignaddr\t%r1, %r2, %0")
+
+(define_insn "alignaddrlsi_vis"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "register_or_zero_operand" "rJ")))
+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 3) (const_int 0))
+ (xor:DI (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2)))
+ (const_int 7)))]
+ "TARGET_VIS"
+ "alignaddrl\t%r1, %r2, %0")
+
+(define_insn "alignaddrldi_vis"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
+ (match_operand:DI 2 "register_or_zero_operand" "rJ")))
+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 3) (const_int 0))
+ (xor:DI (plus:DI (match_dup 1) (match_dup 2))
+ (const_int 7)))]
+ "TARGET_VIS"
+ "alignaddrl\t%r1, %r2, %0")
+
+(define_insn "pdist_vis"
+ [(set (match_operand:DI 0 "register_operand" "=e")
+ (unspec:DI [(match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V8QI 2 "register_operand" "e")
+ (match_operand:DI 3 "register_operand" "0")]
+ UNSPEC_PDIST))]
+ "TARGET_VIS"
+ "pdist\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+;; Edge instructions produce condition codes equivalent to a 'subcc'
+;; with the same operands.
+(define_insn "edge8<P:mode>_vis"
+ [(set (reg:CC_NOOV CC_REG)
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
+ (const_int 0)))
+ (set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE8))]
+ "TARGET_VIS"
+ "edge8\t%r1, %r2, %0"
+ [(set_attr "type" "edge")])
+
+(define_insn "edge8l<P:mode>_vis"
+ [(set (reg:CC_NOOV CC_REG)
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
+ (const_int 0)))
+ (set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE8L))]
+ "TARGET_VIS"
+ "edge8l\t%r1, %r2, %0"
+ [(set_attr "type" "edge")])
+
+(define_insn "edge16<P:mode>_vis"
+ [(set (reg:CC_NOOV CC_REG)
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
+ (const_int 0)))
+ (set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE16))]
+ "TARGET_VIS"
+ "edge16\t%r1, %r2, %0"
+ [(set_attr "type" "edge")])
+
+(define_insn "edge16l<P:mode>_vis"
+ [(set (reg:CC_NOOV CC_REG)
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
+ (const_int 0)))
+ (set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE16L))]
+ "TARGET_VIS"
+ "edge16l\t%r1, %r2, %0"
+ [(set_attr "type" "edge")])
+
+(define_insn "edge32<P:mode>_vis"
+ [(set (reg:CC_NOOV CC_REG)
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
+ (const_int 0)))
+ (set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE32))]
+ "TARGET_VIS"
+ "edge32\t%r1, %r2, %0"
+ [(set_attr "type" "edge")])
+
+(define_insn "edge32l<P:mode>_vis"
+ [(set (reg:CC_NOOV CC_REG)
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
+ (const_int 0)))
+ (set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE32L))]
+ "TARGET_VIS"
+ "edge32l\t%r1, %r2, %0"
+ [(set_attr "type" "edge")])
+
+(define_code_iterator gcond [le ne gt eq])
+(define_mode_iterator GCM [V4HI V2SI])
+(define_mode_attr gcm_name [(V4HI "16") (V2SI "32")])
+
+(define_insn "fcmp<code><GCM:gcm_name><P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(gcond:GCM (match_operand:GCM 1 "register_operand" "e")
+ (match_operand:GCM 2 "register_operand" "e"))]
+ UNSPEC_FCMP))]
+ "TARGET_VIS"
+ "fcmp<code><GCM:gcm_name>\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "array8<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
+ UNSPEC_ARRAY8))]
+ "TARGET_VIS"
+ "array8\t%r1, %r2, %0"
+ [(set_attr "type" "array")])
+
+(define_insn "array16<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
+ UNSPEC_ARRAY16))]
+ "TARGET_VIS"
+ "array16\t%r1, %r2, %0"
+ [(set_attr "type" "array")])
+
+(define_insn "array32<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
+ UNSPEC_ARRAY32))]
+ "TARGET_VIS"
+ "array32\t%r1, %r2, %0"
+ [(set_attr "type" "array")])
+
+(define_insn "bmaskdi_vis"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
+ (match_operand:DI 2 "register_or_zero_operand" "rJ")))
+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 32) (const_int 32))
+ (plus:DI (match_dup 1) (match_dup 2)))]
+ "TARGET_VIS2"
+ "bmask\t%r1, %r2, %0"
+ [(set_attr "type" "array")])
+
+(define_insn "bmasksi_vis"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "register_or_zero_operand" "rJ")))
+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 32) (const_int 32))
+ (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
+ "TARGET_VIS2"
+ "bmask\t%r1, %r2, %0"
+ [(set_attr "type" "array")])
+
+(define_insn "bshuffle<VM64:mode>_vis"
+ [(set (match_operand:VM64 0 "register_operand" "=e")
+ (unspec:VM64 [(match_operand:VM64 1 "register_operand" "e")
+ (match_operand:VM64 2 "register_operand" "e")
+ (reg:DI GSR_REG)]
+ UNSPEC_BSHUFFLE))]
+ "TARGET_VIS2"
+ "bshuffle\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+;; The rtl expanders will happily convert constant permutations on other
+;; modes down to V8QI. Rely on this to avoid the complexity of the byte
+;; order of the permutation.
+(define_expand "vec_perm_constv8qi"
+ [(match_operand:V8QI 0 "register_operand" "")
+ (match_operand:V8QI 1 "register_operand" "")
+ (match_operand:V8QI 2 "register_operand" "")
+ (match_operand:V8QI 3 "" "")]
+ "TARGET_VIS2"
+{
+ unsigned int i, mask;
+ rtx sel = operands[3];
+
+ for (i = mask = 0; i < 8; ++i)
+ mask |= (INTVAL (XVECEXP (sel, 0, i)) & 0xf) << (28 - i*4);
+ sel = force_reg (SImode, gen_int_mode (mask, SImode));
+
+ emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), sel, const0_rtx));
+ emit_insn (gen_bshufflev8qi_vis (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+;; Unlike constant permutation, we can vastly simplify the compression of
+;; the 64-bit selector input to the 32-bit %gsr value by knowing what the
+;; width of the input is.
+(define_expand "vec_perm<mode>"
+ [(match_operand:VM64 0 "register_operand" "")
+ (match_operand:VM64 1 "register_operand" "")
+ (match_operand:VM64 2 "register_operand" "")
+ (match_operand:VM64 3 "register_operand" "")]
+ "TARGET_VIS2"
+{
+ sparc_expand_vec_perm_bmask (<MODE>mode, operands[3]);
+ emit_insn (gen_bshuffle<mode>_vis (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+;; VIS 2.0 adds edge variants which do not set the condition codes
+(define_insn "edge8n<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
+ UNSPEC_EDGE8N))]
+ "TARGET_VIS2"
+ "edge8n\t%r1, %r2, %0"
+ [(set_attr "type" "edgen")])
+
+(define_insn "edge8ln<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
+ UNSPEC_EDGE8LN))]
+ "TARGET_VIS2"
+ "edge8ln\t%r1, %r2, %0"
+ [(set_attr "type" "edgen")])
+
+(define_insn "edge16n<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
+ UNSPEC_EDGE16N))]
+ "TARGET_VIS2"
+ "edge16n\t%r1, %r2, %0"
+ [(set_attr "type" "edgen")])
+
+(define_insn "edge16ln<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
+ UNSPEC_EDGE16LN))]
+ "TARGET_VIS2"
+ "edge16ln\t%r1, %r2, %0"
+ [(set_attr "type" "edgen")])
+
+(define_insn "edge32n<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
+ UNSPEC_EDGE32N))]
+ "TARGET_VIS2"
+ "edge32n\t%r1, %r2, %0"
+ [(set_attr "type" "edgen")])
+
+(define_insn "edge32ln<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
+ UNSPEC_EDGE32LN))]
+ "TARGET_VIS2"
+ "edge32ln\t%r1, %r2, %0"
+ [(set_attr "type" "edge")])
+
+;; Conditional moves are possible via fcmpX --> cmaskX -> bshuffle
+(define_insn "cmask8<P:mode>_vis"
+ [(set (reg:DI GSR_REG)
+ (unspec:DI [(match_operand:P 0 "register_operand" "r")
+ (reg:DI GSR_REG)]
+ UNSPEC_CMASK8))]
+ "TARGET_VIS3"
+ "cmask8\t%r0")
+
+(define_insn "cmask16<P:mode>_vis"
+ [(set (reg:DI GSR_REG)
+ (unspec:DI [(match_operand:P 0 "register_operand" "r")
+ (reg:DI GSR_REG)]
+ UNSPEC_CMASK16))]
+ "TARGET_VIS3"
+ "cmask16\t%r0")
+
+(define_insn "cmask32<P:mode>_vis"
+ [(set (reg:DI GSR_REG)
+ (unspec:DI [(match_operand:P 0 "register_operand" "r")
+ (reg:DI GSR_REG)]
+ UNSPEC_CMASK32))]
+ "TARGET_VIS3"
+ "cmask32\t%r0")
+
+(define_insn "fchksm16_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")]
+ UNSPEC_FCHKSM16))]
+ "TARGET_VIS3"
+ "fchksm16\t%1, %2, %0")
+
+(define_code_iterator vis3_shift [ashift ss_ashift lshiftrt ashiftrt])
+(define_code_attr vis3_shift_insn
+ [(ashift "fsll") (ss_ashift "fslas") (lshiftrt "fsrl") (ashiftrt "fsra")])
+(define_code_attr vis3_shift_patname
+ [(ashift "ashl") (ss_ashift "ssashl") (lshiftrt "lshr") (ashiftrt "ashr")])
+
+(define_insn "v<vis3_shift_patname><mode>3"
+ [(set (match_operand:GCM 0 "register_operand" "=<vconstr>")
+ (vis3_shift:GCM (match_operand:GCM 1 "register_operand" "<vconstr>")
+ (match_operand:GCM 2 "register_operand" "<vconstr>")))]
+ "TARGET_VIS3"
+ "<vis3_shift_insn><vbits>\t%1, %2, %0")
+
+(define_insn "pdistn<mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V8QI 2 "register_operand" "e")]
+ UNSPEC_PDISTN))]
+ "TARGET_VIS3"
+ "pdistn\t%1, %2, %0")
+
+(define_insn "fmean16_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (truncate:V4HI
+ (lshiftrt:V4SI
+ (plus:V4SI
+ (plus:V4SI
+ (zero_extend:V4SI
+ (match_operand:V4HI 1 "register_operand" "e"))
+ (zero_extend:V4SI
+ (match_operand:V4HI 2 "register_operand" "e")))
+ (const_vector:V4SI [(const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)]))
+ (const_int 1))))]
+ "TARGET_VIS3"
+ "fmean16\t%1, %2, %0")
+
+(define_insn "fp<plusminus_insn>64_vis"
+ [(set (match_operand:V1DI 0 "register_operand" "=e")
+ (plusminus:V1DI (match_operand:V1DI 1 "register_operand" "e")
+ (match_operand:V1DI 2 "register_operand" "e")))]
+ "TARGET_VIS3"
+ "fp<plusminus_insn>64\t%1, %2, %0")
+
+(define_mode_iterator VASS [V4HI V2SI V2HI V1SI])
+(define_code_iterator vis3_addsub_ss [ss_plus ss_minus])
+(define_code_attr vis3_addsub_ss_insn
+ [(ss_plus "fpadds") (ss_minus "fpsubs")])
+(define_code_attr vis3_addsub_ss_patname
+ [(ss_plus "ssadd") (ss_minus "sssub")])
+
+(define_insn "<vis3_addsub_ss_patname><mode>3"
+ [(set (match_operand:VASS 0 "register_operand" "=<vconstr>")
+ (vis3_addsub_ss:VASS (match_operand:VASS 1 "register_operand" "<vconstr>")
+ (match_operand:VASS 2 "register_operand" "<vconstr>")))]
+ "TARGET_VIS3"
+ "<vis3_addsub_ss_insn><vbits>\t%1, %2, %0")
+
+(define_insn "fucmp<code>8<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(gcond:V8QI (match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V8QI 2 "register_operand" "e"))]
+ UNSPEC_FUCMP))]
+ "TARGET_VIS3"
+ "fucmp<code>8\t%1, %2, %0")
+
+(define_insn "*naddsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (plus:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f"))))]
+ "TARGET_VIS3"
+ "fnadds\t%1, %2, %0"
+ [(set_attr "type" "fp")])
+
+(define_insn "*nadddf3"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (neg:DF (plus:DF (match_operand:DF 1 "register_operand" "e")
+ (match_operand:DF 2 "register_operand" "e"))))]
+ "TARGET_VIS3"
+ "fnaddd\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "fptype" "double")])
+
+(define_insn "*nmulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "f"))
+ (match_operand:SF 2 "register_operand" "f")))]
+ "TARGET_VIS3"
+ "fnmuls\t%1, %2, %0"
+ [(set_attr "type" "fpmul")])
+
+(define_insn "*nmuldf3"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (mult:DF (neg:DF (match_operand:DF 1 "register_operand" "e"))
+ (match_operand:DF 2 "register_operand" "e")))]
+ "TARGET_VIS3"
+ "fnmuld\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "*nmuldf3_extend"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (mult:DF (neg:DF (float_extend:DF
+ (match_operand:SF 1 "register_operand" "f")))
+ (float_extend:DF
+ (match_operand:SF 2 "register_operand" "f"))))]
+ "TARGET_VIS3"
+ "fnsmuld\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fhaddsf_vis"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")]
+ UNSPEC_FHADD))]
+ "TARGET_VIS3"
+ "fhadds\t%1, %2, %0"
+ [(set_attr "type" "fp")])
+
+(define_insn "fhadddf_vis"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")]
+ UNSPEC_FHADD))]
+ "TARGET_VIS3"
+ "fhaddd\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "fptype" "double")])
+
+(define_insn "fhsubsf_vis"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")]
+ UNSPEC_FHSUB))]
+ "TARGET_VIS3"
+ "fhsubs\t%1, %2, %0"
+ [(set_attr "type" "fp")])
+
+(define_insn "fhsubdf_vis"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")]
+ UNSPEC_FHSUB))]
+ "TARGET_VIS3"
+ "fhsubd\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "fptype" "double")])
+
+(define_insn "fnhaddsf_vis"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (unspec:SF [(match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")]
+ UNSPEC_FHADD)))]
+ "TARGET_VIS3"
+ "fnhadds\t%1, %2, %0"
+ [(set_attr "type" "fp")])
+
+(define_insn "fnhadddf_vis"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (unspec:DF [(match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")]
+ UNSPEC_FHADD)))]
+ "TARGET_VIS3"
+ "fnhaddd\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "fptype" "double")])
+
+(define_expand "umulxhi_vis"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "arith_operand" ""))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "")))
+ (const_int 64))))]
+ "TARGET_VIS3"
+{
+ if (! TARGET_ARCH64)
+ {
+ emit_insn (gen_umulxhi_v8plus (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+})
+
+(define_insn "*umulxhi_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "arith_operand" "%r"))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "rI")))
+ (const_int 64))))]
+ "TARGET_VIS3 && TARGET_ARCH64"
+ "umulxhi\t%1, %2, %0"
+ [(set_attr "type" "imul")])
+
+(define_insn "umulxhi_v8plus"
+ [(set (match_operand:DI 0 "register_operand" "=r,h")
+ (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "arith_operand" "%r,0"))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "rI,rI")))
+ (const_int 64))))
+ (clobber (match_scratch:SI 3 "=&h,X"))
+ (clobber (match_scratch:SI 4 "=&h,X"))]
+ "TARGET_VIS3 && ! TARGET_ARCH64"
+ "* return output_v8plus_mult (insn, operands, \"umulxhi\");"
+ [(set_attr "type" "imul")
+ (set_attr "length" "9,8")])
+
+(define_expand "xmulx_vis"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (truncate:DI
+ (unspec:TI [(zero_extend:TI
+ (match_operand:DI 1 "arith_operand" ""))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" ""))]
+ UNSPEC_XMUL)))]
+ "TARGET_VIS3"
+{
+ if (! TARGET_ARCH64)
+ {
+ emit_insn (gen_xmulx_v8plus (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+})
+
+(define_insn "*xmulx_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (truncate:DI
+ (unspec:TI [(zero_extend:TI
+ (match_operand:DI 1 "arith_operand" "%r"))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "rI"))]
+ UNSPEC_XMUL)))]
+ "TARGET_VIS3 && TARGET_ARCH64"
+ "xmulx\t%1, %2, %0"
+ [(set_attr "type" "imul")])
+
+(define_insn "xmulx_v8plus"
+ [(set (match_operand:DI 0 "register_operand" "=r,h")
+ (truncate:DI
+ (unspec:TI [(zero_extend:TI
+ (match_operand:DI 1 "arith_operand" "%r,0"))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "rI,rI"))]
+ UNSPEC_XMUL)))
+ (clobber (match_scratch:SI 3 "=&h,X"))
+ (clobber (match_scratch:SI 4 "=&h,X"))]
+ "TARGET_VIS3 && ! TARGET_ARCH64"
+ "* return output_v8plus_mult (insn, operands, \"xmulx\");"
+ [(set_attr "type" "imul")
+ (set_attr "length" "9,8")])
+
+(define_expand "xmulxhi_vis"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (truncate:DI
+ (lshiftrt:TI
+ (unspec:TI [(zero_extend:TI
+ (match_operand:DI 1 "arith_operand" ""))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" ""))]
+ UNSPEC_XMUL)
+ (const_int 64))))]
+ "TARGET_VIS3"
+{
+ if (! TARGET_ARCH64)
+ {
+ emit_insn (gen_xmulxhi_v8plus (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+})
+
+(define_insn "*xmulxhi_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (truncate:DI
+ (lshiftrt:TI
+ (unspec:TI [(zero_extend:TI
+ (match_operand:DI 1 "arith_operand" "%r"))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "rI"))]
+ UNSPEC_XMUL)
+ (const_int 64))))]
+ "TARGET_VIS3 && TARGET_ARCH64"
+ "xmulxhi\t%1, %2, %0"
+ [(set_attr "type" "imul")])
+
+(define_insn "xmulxhi_v8plus"
+ [(set (match_operand:DI 0 "register_operand" "=r,h")
+ (truncate:DI
+ (lshiftrt:TI
+ (unspec:TI [(zero_extend:TI
+ (match_operand:DI 1 "arith_operand" "%r,0"))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "rI,rI"))]
+ UNSPEC_XMUL)
+ (const_int 64))))
+ (clobber (match_scratch:SI 3 "=&h,X"))
+ (clobber (match_scratch:SI 4 "=&h,X"))]
+ "TARGET_VIS3 && !TARGET_ARCH64"
+ "* return output_v8plus_mult (insn, operands, \"xmulxhi\");"
+ [(set_attr "type" "imul")
+ (set_attr "length" "9,8")])
+
+(include "sync.md")