+;; 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")])
+