[(UNSPEC_MOVE_PIC 0)
(UNSPEC_UPDATE_RETURN 1)
(UNSPEC_LOAD_PCREL_SYM 2)
+ (UNSPEC_FRAME_BLOCKAGE 3)
(UNSPEC_MOVE_PIC_LABEL 5)
(UNSPEC_SETH44 6)
(UNSPEC_SETM44 7)
(UNSPEC_MOVE_GOTDATA 19)
(UNSPEC_MEMBAR 20)
+ (UNSPEC_ATOMIC 21)
(UNSPEC_TLSGD 30)
(UNSPEC_TLSLDM 31)
(define_constants
[(UNSPECV_BLOCKAGE 0)
(UNSPECV_FLUSHW 1)
- (UNSPECV_GOTO 2)
(UNSPECV_FLUSH 4)
(UNSPECV_SAVEW 6)
(UNSPECV_CAS 8)
(match_operand:DI 2 "register_operand" "")))
(set (match_operand:SI 0 "register_operand" "")
(ne:SI (match_dup 3) (const_int 0)))]
- "TARGET_ARCH64"
+ "TARGET_ARCH64 && ! TARGET_VIS3"
+ { operands[3] = gen_reg_rtx (DImode); })
+
+(define_expand "snedi_special_vis3"
+ [(set (match_dup 3)
+ (xor:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "register_operand" "")))
+ (parallel [(set (match_operand:SI 0 "register_operand" "")
+ (ne:SI (match_dup 3) (const_int 0)))
+ (clobber (reg:CCX CC_REG))])]
+ "TARGET_ARCH64 && TARGET_VIS3"
{ operands[3] = gen_reg_rtx (DImode); })
""
[(set_attr "length" "2")])
+(define_insn_and_split "*neg_snesi_sign_extend"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (neg:DI (ne:DI (match_operand:SI 1 "register_operand" "r")
+ (const_int 0))))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_ARCH64"
+ "#"
+ "&& 1"
+ [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (minus:SI (const_int 0)
+ (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (sign_extend:DI (neg:SI (ltu:SI (reg:CC CC_REG)
+ (const_int 0)))))]
+ ""
+ [(set_attr "length" "2")])
+
(define_insn_and_split "*snedi_zero"
[(set (match_operand:DI 0 "register_operand" "=&r")
(ne:DI (match_operand:DI 1 "register_operand" "r")
(const_int 0)))]
- "TARGET_ARCH64"
+ "TARGET_ARCH64 && ! TARGET_VIS3"
"#"
"&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
""
[(set_attr "length" "2")])
+(define_insn_and_split "*snedi_zero_vis3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ne:DI (match_operand:DI 1 "register_operand" "r")
+ (const_int 0)))
+ (clobber (reg:CCX CC_REG))]
+ "TARGET_ARCH64 && TARGET_VIS3"
+ "#"
+ ""
+ [(set (reg:CCX_NOOV CC_REG) (compare:CCX_NOOV (neg:DI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (ltu:DI (reg:CCX CC_REG) (const_int 0)))]
+ ""
+ [(set_attr "length" "2")])
+
(define_insn_and_split "*neg_snedi_zero"
[(set (match_operand:DI 0 "register_operand" "=&r")
(neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
[(set (match_operand:SI 0 "register_operand" "=&r")
(ne:SI (match_operand:DI 1 "register_operand" "r")
(const_int 0)))]
- "TARGET_ARCH64"
+ "TARGET_ARCH64 && ! TARGET_VIS3"
"#"
"&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
""
[(set_attr "length" "2")])
+(define_insn_and_split "*snedi_zero_trunc_vis3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ne:SI (match_operand:DI 1 "register_operand" "r")
+ (const_int 0)))
+ (clobber (reg:CCX CC_REG))]
+ "TARGET_ARCH64 && TARGET_VIS3"
+ "#"
+ ""
+ [(set (reg:CCX_NOOV CC_REG) (compare:CCX_NOOV (neg:DI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (ltu:SI (reg:CCX CC_REG) (const_int 0)))]
+ ""
+ [(set_attr "length" "2")])
+
(define_insn_and_split "*seqsi_zero"
[(set (match_operand:SI 0 "register_operand" "=r")
(eq:SI (match_operand:SI 1 "register_operand" "r")
""
[(set_attr "length" "2")])
+(define_insn_and_split "*neg_seqsi_sign_extend"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (neg:DI (eq:DI (match_operand:SI 1 "register_operand" "r")
+ (const_int 0))))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_ARCH64"
+ "#"
+ "&& 1"
+ [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (neg:SI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (sign_extend:DI (neg:SI (geu:SI (reg:CC CC_REG)
+ (const_int 0)))))]
+ ""
+ [(set_attr "length" "2")])
+
(define_insn_and_split "*seqdi_zero"
[(set (match_operand:DI 0 "register_operand" "=&r")
(eq:DI (match_operand:DI 1 "register_operand" "r")
"addx\t%%g0, 0, %0"
[(set_attr "type" "ialuX")])
+(define_insn "*sltu_insn_vis3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ltu:DI (reg:CCX CC_REG) (const_int 0)))]
+ "TARGET_ARCH64 && TARGET_VIS3"
+ "addxc\t%%g0, %%g0, %0"
+ [(set_attr "type" "ialuX")])
+
+(define_insn "*sltu_insn_vis3_trunc"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ltu:SI (reg:CCX CC_REG) (const_int 0)))]
+ "TARGET_ARCH64 && TARGET_VIS3"
+ "addxc\t%%g0, %%g0, %0"
+ [(set_attr "type" "ialuX")])
+
+(define_insn "*sltu_extend_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ltu:DI (reg:CC CC_REG) (const_int 0)))]
+ "TARGET_ARCH64"
+ "addx\t%%g0, 0, %0"
+ [(set_attr "type" "ialuX")])
+
(define_insn "*neg_sltu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (ltu:SI (reg:CC CC_REG) (const_int 0))))]
"subx\t%%g0, 0, %0"
[(set_attr "type" "ialuX")])
+(define_insn "*neg_sltu_extend_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (neg:SI (ltu:SI (reg:CC CC_REG) (const_int 0)))))]
+ "TARGET_ARCH64"
+ "subx\t%%g0, 0, %0"
+ [(set_attr "type" "ialuX")])
+
;; ??? Combine should canonicalize these next two to the same pattern.
(define_insn "*neg_sltu_minus_x"
[(set (match_operand:SI 0 "register_operand" "=r")
"subx\t%%g0, -1, %0"
[(set_attr "type" "ialuX")])
+(define_insn "*sgeu_extend_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (geu:DI (reg:CC CC_REG) (const_int 0)))]
+ "TARGET_ARCH64"
+ "subx\t%%g0, -1, %0"
+ [(set_attr "type" "ialuX")])
+
(define_insn "*neg_sgeu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (geu:SI (reg:CC CC_REG) (const_int 0))))]
"addx\t%%g0, -1, %0"
[(set_attr "type" "ialuX")])
+(define_insn "*neg_sgeu_extend_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (neg:SI (geu:SI (reg:CC CC_REG) (const_int 0)))))]
+ "TARGET_ARCH64"
+ "addx\t%%g0, -1, %0"
+ [(set_attr "type" "ialuX")])
+
;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
;; versions for v9.
;; Load in operand 0 the (absolute) address of operand 1, which is a symbolic
;; value subject to a PC-relative relocation. Operand 2 is a helper function
;; that adds the PC value at the call point to register #(operand 3).
+;;
+;; Even on V9 we use this call sequence with a stub, instead of "rd %pc, ..."
+;; because the RDPC instruction is extremely expensive and incurs a complete
+;; instruction pipeline flush.
(define_insn "load_pcrel_sym<P:mode>"
[(set (match_operand:P 0 "register_operand" "=r")
})
(define_insn "*movsf_insn"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,f, *r,*r,*r,*r, f, f,*r, m, m")
- (match_operand:SF 1 "input_operand" "G,C,f,*rR, Q, S, f,*r, m, m, f,*rG"))]
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,f, *r,*r,*r,*r, f,f,*r,m, m")
+ (match_operand:SF 1 "input_operand" "G,C,f,*rR, Q, S, f,*r,m, m,f,*rG"))]
"(register_operand (operands[0], SFmode)
|| register_or_zero_or_all_ones_operand (operands[1], SFmode))"
{
})
(define_insn "*movdf_insn_sp32"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=b,b,e,e,*r, f, e,T,W,U,T, f, *r, o,o")
- (match_operand:DF 1 "input_operand" "G,C,e,e, f,*r,W#F,G,e,T,U,o#F,*roGF,*rG,f"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=b,b,e,e,*r, f, e,T,W,U,T, f, *r, o,o")
+ (match_operand:DF 1 "input_operand" "G,C,e,e, f,*r,W#F,G,e,T,U,o#F,*roF,*rG,f"))]
"! TARGET_ARCH64
&& (register_operand (operands[0], DFmode)
|| register_or_zero_or_all_ones_operand (operands[1], DFmode))"
(define_insn "*movdf_insn_sp64"
[(set (match_operand:DF 0 "nonimmediate_operand" "=b,b,e,*r, e, e,W, *r,*r, m,*r")
- (match_operand:DF 1 "input_operand" "G,C,e, e,*r,W#F,e,*rG, m,*rG, F"))]
+ (match_operand:DF 1 "input_operand" "G,C,e, e,*r,W#F,e,*rG, m,*rG, F"))]
"TARGET_ARCH64
&& (register_operand (operands[0], DFmode)
|| register_or_zero_or_all_ones_operand (operands[1], DFmode))"
(define_split
[(set (match_operand:DF 0 "register_operand" "")
(match_operand:DF 1 "const_double_operand" ""))]
- "TARGET_FPU
- && (GET_CODE (operands[0]) == REG
- && SPARC_INT_REG_P (REGNO (operands[0])))
+ "REG_P (operands[0])
+ && SPARC_INT_REG_P (REGNO (operands[0]))
&& ! const_zero_operand (operands[1], GET_MODE (operands[0]))
&& reload_completed"
[(clobber (const_int 0))]
})
(define_insn "*movtf_insn_sp32"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,o,U,r")
- (match_operand:TF 1 "input_operand" "G,oe,GeUr,o,roG"))]
- "TARGET_FPU
- && ! TARGET_ARCH64
- && (register_operand (operands[0], TFmode)
- || register_or_zero_operand (operands[1], TFmode))"
- "#"
- [(set_attr "length" "4")])
-
-;; Exactly the same as above, except that all `e' cases are deleted.
-;; This is necessary to prevent reload from ever trying to use a `e' reg
-;; when -mno-fpu.
-
-(define_insn "*movtf_insn_sp32_no_fpu"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=o,U,o,r,o")
- (match_operand:TF 1 "input_operand" "G,o,U,roG,r"))]
- "! TARGET_FPU
- && ! TARGET_ARCH64
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=b, e,o, o,U, r")
+ (match_operand:TF 1 "input_operand" " G,oe,e,rGU,o,roG"))]
+ "! TARGET_ARCH64
&& (register_operand (operands[0], TFmode)
|| register_or_zero_operand (operands[1], TFmode))"
"#"
- [(set_attr "length" "4")])
+ [(set_attr "length" "4,4,4,4,4,4")
+ (set_attr "cpu_feature" "fpu,fpu,fpu,*,*,*")])
(define_insn "*movtf_insn_sp64"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,o,r")
- (match_operand:TF 1 "input_operand" "G,oe,Ger,roG"))]
- "TARGET_FPU
- && TARGET_ARCH64
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=b, e,o, o, r")
+ (match_operand:TF 1 "input_operand" "G,oe,e,rG,roG"))]
+ "TARGET_ARCH64
&& ! TARGET_HARD_QUAD
&& (register_operand (operands[0], TFmode)
|| register_or_zero_operand (operands[1], TFmode))"
"#"
- [(set_attr "length" "2")])
+ [(set_attr "length" "2,2,2,2,2")
+ (set_attr "cpu_feature" "fpu,fpu,fpu,*,*")])
(define_insn "*movtf_insn_sp64_hq"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,e,m,o,r")
- (match_operand:TF 1 "input_operand" "G,e,m,e,rG,roG"))]
- "TARGET_FPU
- && TARGET_ARCH64
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,e,m, o, r")
+ (match_operand:TF 1 "input_operand" "G,e,m,e,rG,roG"))]
+ "TARGET_ARCH64
&& TARGET_HARD_QUAD
&& (register_operand (operands[0], TFmode)
|| register_or_zero_operand (operands[1], TFmode))"
[(set_attr "type" "*,fpmove,fpload,fpstore,*,*")
(set_attr "length" "2,*,*,*,2,2")])
-(define_insn "*movtf_insn_sp64_no_fpu"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o")
- (match_operand:TF 1 "input_operand" "orG,rG"))]
- "! TARGET_FPU
- && TARGET_ARCH64
- && (register_operand (operands[0], TFmode)
- || register_or_zero_operand (operands[1], TFmode))"
- "#"
- [(set_attr "length" "2")])
-
;; Now all the splits to handle multi-insn TF mode moves.
(define_split
[(set (match_operand:TF 0 "register_operand" "")
;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
;; 3 contains the constant if one is present, but we handle either for
;; generality (sparc.c puts a constant in operand 2).
+;;
+;; Our instruction patterns, on the other hand, canonicalize such that
+;; operand 3 must be the set destination.
(define_expand "mov<I:mode>cc"
[(set (match_operand:I 0 "register_operand" "")
(match_operand:I 3 "arith10_operand" "")))]
"TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
{
- rtx cc_reg;
-
- if (GET_MODE (XEXP (operands[1], 0)) == DImode && !TARGET_ARCH64)
+ if (! sparc_expand_conditional_move (<I:MODE>mode, operands))
FAIL;
-
- if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
- operands[1]
- = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1),
- GET_CODE (operands[1]));
-
- if (XEXP (operands[1], 1) == const0_rtx
- && GET_CODE (XEXP (operands[1], 0)) == REG
- && GET_MODE (XEXP (operands[1], 0)) == DImode
- && v9_regcmp_p (GET_CODE (operands[1])))
- cc_reg = XEXP (operands[1], 0);
- else
- cc_reg = gen_compare_reg (operands[1]);
-
- operands[1]
- = gen_rtx_fmt_ee (GET_CODE (operands[1]), GET_MODE (cc_reg), cc_reg,
- const0_rtx);
+ DONE;
})
(define_expand "mov<F:mode>cc"
(match_operand:F 3 "register_operand" "")))]
"TARGET_V9 && TARGET_FPU"
{
- rtx cc_reg;
-
- if (GET_MODE (XEXP (operands[1], 0)) == DImode && !TARGET_ARCH64)
+ if (! sparc_expand_conditional_move (<F:MODE>mode, operands))
FAIL;
-
- if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
- operands[1]
- = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1),
- GET_CODE (operands[1]));
-
- if (XEXP (operands[1], 1) == const0_rtx
- && GET_CODE (XEXP (operands[1], 0)) == REG
- && GET_MODE (XEXP (operands[1], 0)) == DImode
- && v9_regcmp_p (GET_CODE (operands[1])))
- cc_reg = XEXP (operands[1], 0);
- else
- cc_reg = gen_compare_reg (operands[1]);
-
- operands[1]
- = gen_rtx_fmt_ee (GET_CODE (operands[1]), GET_MODE (cc_reg), cc_reg,
- const0_rtx);
+ DONE;
})
;; Conditional move define_insns
(define_insn "*mov<I:mode>_cc_v9"
- [(set (match_operand:I 0 "register_operand" "=r,r")
+ [(set (match_operand:I 0 "register_operand" "=r")
(if_then_else:I (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
(const_int 0)])
- (match_operand:I 3 "arith11_operand" "rL,0")
- (match_operand:I 4 "arith11_operand" "0,rL")))]
+ (match_operand:I 3 "arith11_operand" "rL")
+ (match_operand:I 4 "register_operand" "0")))]
"TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
- "@
- mov%C1\t%x2, %3, %0
- mov%c1\t%x2, %4, %0"
+ "mov%C1\t%x2, %3, %0"
[(set_attr "type" "cmove")])
(define_insn "*mov<I:mode>_cc_reg_sp64"
- [(set (match_operand:I 0 "register_operand" "=r,r")
+ [(set (match_operand:I 0 "register_operand" "=r")
(if_then_else:I (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
+ [(match_operand:DI 2 "register_operand" "r")
(const_int 0)])
- (match_operand:I 3 "arith10_operand" "rM,0")
- (match_operand:I 4 "arith10_operand" "0,rM")))]
+ (match_operand:I 3 "arith10_operand" "rM")
+ (match_operand:I 4 "register_operand" "0")))]
"TARGET_ARCH64"
- "@
- movr%D1\t%2, %r3, %0
- movr%d1\t%2, %r4, %0"
+ "movr%D1\t%2, %r3, %0"
[(set_attr "type" "cmove")])
(define_insn "*movsf_cc_v9"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
+ [(set (match_operand:SF 0 "register_operand" "=f")
(if_then_else:SF (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
(const_int 0)])
- (match_operand:SF 3 "register_operand" "f,0")
- (match_operand:SF 4 "register_operand" "0,f")))]
+ (match_operand:SF 3 "register_operand" "f")
+ (match_operand:SF 4 "register_operand" "0")))]
"TARGET_V9 && TARGET_FPU"
- "@
- fmovs%C1\t%x2, %3, %0
- fmovs%c1\t%x2, %4, %0"
+ "fmovs%C1\t%x2, %3, %0"
[(set_attr "type" "fpcmove")])
(define_insn "*movsf_cc_reg_sp64"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
+ [(set (match_operand:SF 0 "register_operand" "=f")
(if_then_else:SF (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
+ [(match_operand:DI 2 "register_operand" "r")
(const_int 0)])
- (match_operand:SF 3 "register_operand" "f,0")
- (match_operand:SF 4 "register_operand" "0,f")))]
+ (match_operand:SF 3 "register_operand" "f")
+ (match_operand:SF 4 "register_operand" "0")))]
"TARGET_ARCH64 && TARGET_FPU"
- "@
- fmovrs%D1\t%2, %3, %0
- fmovrs%d1\t%2, %4, %0"
+ "fmovrs%D1\t%2, %3, %0"
[(set_attr "type" "fpcrmove")])
;; Named because invoked by movtf_cc_v9
(define_insn "movdf_cc_v9"
- [(set (match_operand:DF 0 "register_operand" "=e,e")
+ [(set (match_operand:DF 0 "register_operand" "=e")
(if_then_else:DF (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
(const_int 0)])
- (match_operand:DF 3 "register_operand" "e,0")
- (match_operand:DF 4 "register_operand" "0,e")))]
+ (match_operand:DF 3 "register_operand" "e")
+ (match_operand:DF 4 "register_operand" "0")))]
"TARGET_V9 && TARGET_FPU"
- "@
- fmovd%C1\t%x2, %3, %0
- fmovd%c1\t%x2, %4, %0"
+ "fmovd%C1\t%x2, %3, %0"
[(set_attr "type" "fpcmove")
(set_attr "fptype" "double")])
;; Named because invoked by movtf_cc_reg_sp64
(define_insn "movdf_cc_reg_sp64"
- [(set (match_operand:DF 0 "register_operand" "=e,e")
+ [(set (match_operand:DF 0 "register_operand" "=e")
(if_then_else:DF (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
+ [(match_operand:DI 2 "register_operand" "r")
(const_int 0)])
- (match_operand:DF 3 "register_operand" "e,0")
- (match_operand:DF 4 "register_operand" "0,e")))]
+ (match_operand:DF 3 "register_operand" "e")
+ (match_operand:DF 4 "register_operand" "0")))]
"TARGET_ARCH64 && TARGET_FPU"
- "@
- fmovrd%D1\t%2, %3, %0
- fmovrd%d1\t%2, %4, %0"
+ "fmovrd%D1\t%2, %3, %0"
[(set_attr "type" "fpcrmove")
(set_attr "fptype" "double")])
(define_insn "*movtf_cc_hq_v9"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
+ [(set (match_operand:TF 0 "register_operand" "=e")
(if_then_else:TF (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
(const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
+ (match_operand:TF 3 "register_operand" "e")
+ (match_operand:TF 4 "register_operand" "0")))]
"TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
- "@
- fmovq%C1\t%x2, %3, %0
- fmovq%c1\t%x2, %4, %0"
+ "fmovq%C1\t%x2, %3, %0"
[(set_attr "type" "fpcmove")])
(define_insn "*movtf_cc_reg_hq_sp64"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
+ [(set (match_operand:TF 0 "register_operand" "=e")
(if_then_else:TF (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
+ [(match_operand:DI 2 "register_operand" "r")
(const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
+ (match_operand:TF 3 "register_operand" "e")
+ (match_operand:TF 4 "register_operand" "0")))]
"TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
- "@
- fmovrq%D1\t%2, %3, %0
- fmovrq%d1\t%2, %4, %0"
+ "fmovrq%D1\t%2, %3, %0"
[(set_attr "type" "fpcrmove")])
(define_insn_and_split "*movtf_cc_v9"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
+ [(set (match_operand:TF 0 "register_operand" "=e")
(if_then_else:TF (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
(const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
+ (match_operand:TF 3 "register_operand" "e")
+ (match_operand:TF 4 "register_operand" "0")))]
"TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
"#"
"&& reload_completed"
{
rtx set_dest = operands[0];
rtx set_srca = operands[3];
- rtx set_srcb = operands[4];
- int third = rtx_equal_p (set_dest, set_srca);
rtx dest1, dest2;
- rtx srca1, srca2, srcb1, srcb2;
+ rtx srca1, srca2;
dest1 = gen_df_reg (set_dest, 0);
dest2 = gen_df_reg (set_dest, 1);
srca1 = gen_df_reg (set_srca, 0);
srca2 = gen_df_reg (set_srca, 1);
- srcb1 = gen_df_reg (set_srcb, 0);
- srcb2 = gen_df_reg (set_srcb, 1);
- /* Now emit using the real source and destination we found, swapping
- the order if we detect overlap. */
- if ((third && reg_overlap_mentioned_p (dest1, srcb2))
- || (!third && reg_overlap_mentioned_p (dest1, srca2)))
+ if (reg_overlap_mentioned_p (dest1, srca2))
{
- emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, srcb2));
- emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, srcb1));
+ emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, dest2));
+ emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, dest1));
}
else
{
- emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, srcb1));
- emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, srcb2));
+ emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, dest1));
+ emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, dest2));
}
DONE;
}
[(set_attr "length" "2")])
(define_insn_and_split "*movtf_cc_reg_sp64"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
+ [(set (match_operand:TF 0 "register_operand" "=e")
(if_then_else:TF (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
+ [(match_operand:DI 2 "register_operand" "r")
(const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
+ (match_operand:TF 3 "register_operand" "e")
+ (match_operand:TF 4 "register_operand" "0")))]
"TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
"#"
"&& reload_completed"
{
rtx set_dest = operands[0];
rtx set_srca = operands[3];
- rtx set_srcb = operands[4];
- int third = rtx_equal_p (set_dest, set_srca);
rtx dest1, dest2;
- rtx srca1, srca2, srcb1, srcb2;
+ rtx srca1, srca2;
dest1 = gen_df_reg (set_dest, 0);
dest2 = gen_df_reg (set_dest, 1);
srca1 = gen_df_reg (set_srca, 0);
srca2 = gen_df_reg (set_srca, 1);
- srcb1 = gen_df_reg (set_srcb, 0);
- srcb2 = gen_df_reg (set_srcb, 1);
- /* Now emit using the real source and destination we found, swapping
- the order if we detect overlap. */
- if ((third && reg_overlap_mentioned_p (dest1, srcb2))
- || (!third && reg_overlap_mentioned_p (dest1, srca2)))
+ if (reg_overlap_mentioned_p (dest1, srca2))
{
- emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
- emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
+ emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, dest2));
+ emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, dest1));
}
else
{
- emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
- emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
+ emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, dest1));
+ emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, dest2));
}
DONE;
}
})
(define_insn_and_split "*adddi3_insn_sp32"
- [(set (match_operand:DI 0 "register_operand" "=r")
+ [(set (match_operand:DI 0 "register_operand" "=&r")
(plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
(match_operand:DI 2 "arith_double_operand" "rHI")))
(clobber (reg:CC CC_REG))]
"addx\t%1, %2, %0"
[(set_attr "type" "ialuX")])
+(define_insn "addxc"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (plus:DI (match_operand:DI 1 "register_or_zero_operand" "%rJ")
+ (match_operand:DI 2 "register_or_zero_operand" "rJ"))
+ (ltu:DI (reg:CCX_NOOV CC_REG) (const_int 0))))]
+ "TARGET_ARCH64 && TARGET_VIS3"
+ "addxc\t%r1, %r2, %0"
+ [(set_attr "type" "ialuX")])
+
(define_insn_and_split "*addx_extend_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (plus:SI (plus:SI
(define_insn "*addx_extend_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ")
- (match_operand:SI 2 "arith_operand" "rI"))
+ (match_operand:SI 2 "register_or_zero_operand" "rJ"))
(ltu:SI (reg:CC_NOOV CC_REG) (const_int 0)))))]
"TARGET_ARCH64"
- "addx\t%r1, %2, %0"
+ "addx\t%r1, %r2, %0"
+ [(set_attr "type" "ialuX")])
+
+(define_insn "*addxc_trunc_sp64_vis3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (plus:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ")
+ (match_operand:SI 2 "register_or_zero_operand" "rJ"))
+ (ltu:SI (reg:CCX_NOOV CC_REG) (const_int 0))))]
+ "TARGET_ARCH64 && TARGET_VIS3"
+ "addxc\t%r1, %r2, %0"
[(set_attr "type" "ialuX")])
(define_insn_and_split "*adddi3_extend_sp32"
(match_operand:SI 2 "arith_operand" "rI,rI,rI")))
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
- "* return output_v8plus_shift (operands, insn, \"sllx\");"
+ "* return output_v8plus_shift (insn ,operands, \"sllx\");"
[(set_attr "type" "multi")
(set_attr "length" "5,5,6")])
(match_operand:SI 2 "arith_operand" "rI,rI,rI")))
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
- "* return output_v8plus_shift (operands, insn, \"srax\");"
+ "* return output_v8plus_shift (insn, operands, \"srax\");"
[(set_attr "type" "multi")
(set_attr "length" "5,5,6")])
(match_operand:SI 2 "arith_operand" "rI,rI,rI")))
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
- "* return output_v8plus_shift (operands, insn, \"srlx\");"
+ "* return output_v8plus_shift (insn, operands, \"srlx\");"
[(set_attr "type" "multi")
(set_attr "length" "5,5,6")])
""
[(set_attr "length" "0")])
+;; Do not schedule instructions accessing memory before this point.
+
+(define_expand "frame_blockage"
+ [(set (match_dup 0)
+ (unspec:BLK [(match_dup 1)] UNSPEC_FRAME_BLOCKAGE))]
+ ""
+{
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[0]) = 1;
+ operands[1] = stack_pointer_rtx;
+})
+
+(define_insn "*frame_blockage<P:mode>"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_operand:P 1 "" "")] UNSPEC_FRAME_BLOCKAGE))]
+ ""
+ ""
+ [(set_attr "length" "0")])
+
(define_expand "probe_stack"
[(set (match_operand 0 "memory_operand" "") (const_int 0))]
""
(match_operand 3 "memory_operand" "")]
""
{
+ rtx i7 = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
rtx r_label = copy_to_reg (operands[1]);
rtx r_sp = adjust_address_nv (operands[2], Pmode, 0);
rtx r_fp = operands[3];
/* Restore frame pointer for containing function. */
emit_move_insn (hard_frame_pointer_rtx, r_fp);
emit_stack_restore (SAVE_NONLOCAL, r_sp);
+ emit_move_insn (i7, r_i7);
/* USE of hard_frame_pointer_rtx added for consistency;
not clear if really needed. */
emit_use (hard_frame_pointer_rtx);
emit_use (stack_pointer_rtx);
+ emit_use (i7);
- /* We need to smuggle the load of %i7 as it is a fixed register. */
- emit_jump_insn (gen_nonlocal_goto_internal (r_label, r_i7));
+ emit_jump_insn (gen_indirect_jump (r_label));
emit_barrier ();
DONE;
})
-(define_insn "nonlocal_goto_internal"
- [(unspec_volatile [(match_operand 0 "register_operand" "r")
- (match_operand 1 "memory_operand" "m")] UNSPECV_GOTO)]
- "GET_MODE (operands[0]) == Pmode && GET_MODE (operands[1]) == Pmode"
-{
- if (flag_delayed_branch)
- {
- if (TARGET_ARCH64)
- return "jmp\t%0\n\t ldx\t%1, %%i7";
- else
- return "jmp\t%0\n\t ld\t%1, %%i7";
- }
- else
- {
- if (TARGET_ARCH64)
- return "ldx\t%1, %%i7\n\tjmp\t%0\n\t nop";
- else
- return "ld\t%1, %%i7\n\tjmp\t%0\n\t nop";
- }
-}
- [(set (attr "type") (const_string "multi"))
- (set (attr "length")
- (if_then_else (eq_attr "delayed_branch" "true")
- (const_int 2)
- (const_int 3)))])
-
(define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0 "" ""))]
"flag_pic"
(set_attr "cpu_feature" "vis,vis,vis,*,*,*,*,*,*,vis3,vis3")])
(define_insn "*mov<VM64:mode>_insn_sp64"
- [(set (match_operand:VM64 0 "nonimmediate_operand" "=e,e,e,e,m,m,*r, m,*r, f,*r")
- (match_operand:VM64 1 "input_operand" "Y,C,e,m,e,Y, m,*r, f,*r,*r"))]
+ [(set (match_operand:VM64 0 "nonimmediate_operand" "=e,e,e,e,m,m,*r, m,*r, e,*r")
+ (match_operand:VM64 1 "input_operand" "Y,C,e,m,e,Y, m,*r, e,*r,*r"))]
"TARGET_VIS
&& TARGET_ARCH64
&& (register_operand (operands[0], <VM64:MODE>mode)
[(set_attr "type" "fpmul")
(set_attr "fptype" "double")])
+(define_expand "vcond<mode><mode>"
+ [(match_operand:GCM 0 "register_operand" "")
+ (match_operand:GCM 1 "register_operand" "")
+ (match_operand:GCM 2 "register_operand" "")
+ (match_operator 3 ""
+ [(match_operand:GCM 4 "register_operand" "")
+ (match_operand:GCM 5 "register_operand" "")])]
+ "TARGET_VIS3"
+{
+ sparc_expand_vcond (<MODE>mode, operands,
+ UNSPEC_CMASK<gcm_name>,
+ UNSPEC_FCMP);
+ DONE;
+})
+
+(define_expand "vconduv8qiv8qi"
+ [(match_operand:V8QI 0 "register_operand" "")
+ (match_operand:V8QI 1 "register_operand" "")
+ (match_operand:V8QI 2 "register_operand" "")
+ (match_operator 3 ""
+ [(match_operand:V8QI 4 "register_operand" "")
+ (match_operand:V8QI 5 "register_operand" "")])]
+ "TARGET_VIS3"
+{
+ sparc_expand_vcond (V8QImode, operands,
+ UNSPEC_CMASK8,
+ UNSPEC_FUCMP);
+ DONE;
+})
+
(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")
;; 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")
+ (unspec:DI [(match_operand:P 0 "register_or_zero_operand" "rJ")
(reg:DI GSR_REG)]
UNSPEC_CMASK8))]
"TARGET_VIS3"
(define_insn "cmask16<P:mode>_vis"
[(set (reg:DI GSR_REG)
- (unspec:DI [(match_operand:P 0 "register_operand" "r")
+ (unspec:DI [(match_operand:P 0 "register_or_zero_operand" "rJ")
(reg:DI GSR_REG)]
UNSPEC_CMASK16))]
"TARGET_VIS3"
(define_insn "cmask32<P:mode>_vis"
[(set (reg:DI GSR_REG)
- (unspec:DI [(match_operand:P 0 "register_operand" "r")
+ (unspec:DI [(match_operand:P 0 "register_or_zero_operand" "rJ")
(reg:DI GSR_REG)]
UNSPEC_CMASK32))]
"TARGET_VIS3"