[(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)
(symbol_ref "TARGET_SPARCLET") (const_string "sparclet")]
(const_string "v7"))))
+(define_attr "cpu_feature" "none,fpu,fpunotv9,v9,vis,vis3" (const_string "none"))
+
+(define_attr "enabled" ""
+ (cond [(eq_attr "cpu_feature" "none") (const_int 1)
+ (eq_attr "cpu_feature" "fpu") (symbol_ref "TARGET_FPU")
+ (eq_attr "cpu_feature" "fpunotv9") (symbol_ref "TARGET_FPU && ! TARGET_V9")
+ (eq_attr "cpu_feature" "v9") (symbol_ref "TARGET_V9")
+ (eq_attr "cpu_feature" "vis") (symbol_ref "TARGET_VIS")
+ (eq_attr "cpu_feature" "vis3") (symbol_ref "TARGET_VIS3")]
+ (const_int 0)))
+
;; Insn type.
(define_attr "type"
"ialu,compare,shift,
(define_attr "in_call_delay" "false,true"
(cond [(eq_attr "type" "uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
- (const_string "false")
+ (const_string "false")
(eq_attr "type" "load,fpload,store,fpstore")
- (if_then_else (eq_attr "length" "1")
+ (if_then_else (eq_attr "length" "1")
(const_string "true")
(const_string "false"))]
- (if_then_else (and (eq_attr "length" "1")
- (eq_attr "tls_call_delay" "true"))
- (const_string "true")
- (const_string "false"))))
+ (if_then_else (and (eq_attr "length" "1")
+ (eq_attr "tls_call_delay" "true"))
+ (const_string "true")
+ (const_string "false"))))
(define_attr "eligible_for_sibcall_delay" "false,true"
(symbol_ref "(eligible_for_sibcall_delay (insn)
(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 "*movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,!f,!f,!m,d,d")
- (match_operand:SI 1 "input_operand" "rI,K,m,rJ,f,m,f,J,P"))]
- "(register_operand (operands[0], SImode)
- || register_or_zero_or_all_ones_operand (operands[1], SImode))"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, r,*f,*f,*f, m,d,d")
+ (match_operand:SI 1 "input_operand" "rI,K,m,rJ,*f, r, f, m,*f,J,P"))]
+ "register_operand (operands[0], SImode)
+ || register_or_zero_or_all_ones_operand (operands[1], SImode)"
"@
mov\t%1, %0
sethi\t%%hi(%a1), %0
ld\t%1, %0
st\t%r1, %0
+ movstouw\t%1, %0
+ movwtos\t%1, %0
fmovs\t%1, %0
ld\t%1, %0
st\t%1, %0
fzeros\t%0
fones\t%0"
- [(set_attr "type" "*,*,load,store,fpmove,fpload,fpstore,fga,fga")])
+ [(set_attr "type" "*,*,load,store,*,*,fpmove,fpload,fpstore,fga,fga")
+ (set_attr "cpu_feature" "*,*,*,*,vis3,vis3,*,*,*,vis,vis")])
(define_insn "*movsi_lo_sum"
[(set (match_operand:SI 0 "register_operand" "=r")
(define_insn "*movdi_insn_sp32"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
+ "=T,o,T,U,o,r,r,r,?T,?*f,?*f,?o,?*e,?*e, r,?*f,?*e,?W,b,b")
(match_operand:DI 1 "input_operand"
- " J,U,T,r,o,i,r, f, T, o, f, f"))]
- "! TARGET_V9
+ " J,J,U,T,r,o,i,r,*f, T, o,*f, *e, *e,?*f, r, W,*e,J,P"))]
+ "! TARGET_ARCH64
&& (register_operand (operands[0], DImode)
|| register_or_zero_operand (operands[1], DImode))"
"@
+ stx\t%%g0, %0
#
std\t%1, %0
ldd\t%1, %0
ldd\t%1, %0
#
#
- #"
- [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
- (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
-
-(define_insn "*movdi_insn_sp32_v9"
- [(set (match_operand:DI 0 "nonimmediate_operand"
- "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?e,?e,?W")
- (match_operand:DI 1 "input_operand"
- " J,J,U,T,r,o,i,r, f, T, o, f, e, W, e"))]
- "! TARGET_ARCH64
- && TARGET_V9
- && (register_operand (operands[0], DImode)
- || register_or_zero_operand (operands[1], DImode))"
- "@
- stx\t%%g0, %0
- #
- std\t%1, %0
- ldd\t%1, %0
- #
+ fmovd\t%1, %0
#
#
#
- std\t%1, %0
ldd\t%1, %0
- #
- #
- fmovd\\t%1, %0
- ldd\\t%1, %0
- std\\t%1, %0"
- [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,fpmove,fpload,fpstore")
- (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,*,*")
- (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
+ std\t%1, %0
+ fzero\t%0
+ fone\t%0"
+ [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,fpmove,*,*,*,fpload,fpstore,fga,fga")
+ (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,2,2,2,*,*,*,*")
+ (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*,*,*,*,double,double")
+ (set_attr "cpu_feature" "v9,*,*,*,*,*,*,*,fpu,fpu,fpu,fpu,v9,fpunotv9,vis3,vis3,fpu,fpu,vis,vis")])
(define_insn "*movdi_insn_sp64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m,?e,?e,?W,b,b")
- (match_operand:DI 1 "input_operand" "rI,N,m,rJ,e,W,e,J,P"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, r,*e,?*e,?*e,?W,b,b")
+ (match_operand:DI 1 "input_operand" "rI,N,m,rJ,*e, r, *e, W,*e,J,P"))]
"TARGET_ARCH64
&& (register_operand (operands[0], DImode)
|| register_or_zero_or_all_ones_operand (operands[1], DImode))"
sethi\t%%hi(%a1), %0
ldx\t%1, %0
stx\t%r1, %0
+ movdtox\t%1, %0
+ movxtod\t%1, %0
fmovd\t%1, %0
ldd\t%1, %0
std\t%1, %0
fzero\t%0
fone\t%0"
- [(set_attr "type" "*,*,load,store,fpmove,fpload,fpstore,fga,fga")
- (set_attr "fptype" "*,*,*,*,double,*,*,double,double")])
+ [(set_attr "type" "*,*,load,store,*,*,fpmove,fpload,fpstore,fga,fga")
+ (set_attr "fptype" "*,*,*,*,*,*,double,*,*,double,double")
+ (set_attr "cpu_feature" "*,*,*,*,vis3,vis3,*,*,*,vis,vis")])
(define_expand "movdi_pic_label_ref"
[(set (match_dup 3) (high:DI
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(match_operand:DI 1 "const_int_operand" ""))]
- "! TARGET_ARCH64 && reload_completed"
+ "! TARGET_ARCH64
+ && ((GET_CODE (operands[0]) == REG
+ && SPARC_INT_REG_P (REGNO (operands[0])))
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))
+ && reload_completed"
[(clobber (const_int 0))]
{
#if HOST_BITS_PER_WIDE_INT == 32
&& (! TARGET_V9
|| (! TARGET_ARCH64
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))))"
[(clobber (const_int 0))]
{
emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
"reload_completed
&& (! TARGET_V9
|| (! TARGET_ARCH64
- && ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
- || (GET_CODE (operands[0]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))))"
+ && sparc_split_regreg_legitimate (operands[0],
+ operands[1])))"
[(clobber (const_int 0))]
{
rtx set_dest = operands[0];
})
(define_insn "*movsf_insn"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=d, d,f, *r,*r,*r,f,*r,m, m")
- (match_operand:SF 1 "input_operand" "GY,ZC,f,*rRY, Q, S,m, m,f,*rGY"))]
- "TARGET_FPU
- && (register_operand (operands[0], SFmode)
- || register_or_zero_or_all_ones_operand (operands[1], SFmode))"
+ [(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))"
{
if (GET_CODE (operands[1]) == CONST_DOUBLE
&& (which_alternative == 3
case 5:
return "#";
case 6:
+ return "movstouw\t%1, %0";
case 7:
- return "ld\t%1, %0";
+ return "movwtos\t%1, %0";
case 8:
case 9:
- return "st\t%r1, %0";
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "type" "fga,fga,fpmove,*,*,*,fpload,load,fpstore,store")])
-
-;; Exactly the same as above, except that all `f' cases are deleted.
-;; This is necessary to prevent reload from ever trying to use a `f' reg
-;; when -mno-fpu.
-
-(define_insn "*movsf_insn_no_fpu"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,r,m")
- (match_operand:SF 1 "input_operand" "rR,Q,S,m,rG"))]
- "! TARGET_FPU
- && (register_operand (operands[0], SFmode)
- || register_or_zero_operand (operands[1], SFmode))"
-{
- if (GET_CODE (operands[1]) == CONST_DOUBLE
- && (which_alternative == 0
- || which_alternative == 1
- || which_alternative == 2))
- {
- REAL_VALUE_TYPE r;
- long i;
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
- REAL_VALUE_TO_TARGET_SINGLE (r, i);
- operands[1] = GEN_INT (i);
- }
-
- switch (which_alternative)
- {
- case 0:
- return "mov\t%1, %0";
- case 1:
- return "sethi\t%%hi(%a1), %0";
- case 2:
- return "#";
- case 3:
return "ld\t%1, %0";
- case 4:
+ case 10:
+ case 11:
return "st\t%r1, %0";
default:
gcc_unreachable ();
}
}
- [(set_attr "type" "*,*,*,load,store")])
+ [(set_attr "type" "fga,fga,fpmove,*,*,*,*,*,fpload,load,fpstore,store")
+ (set_attr "cpu_feature" "vis,vis,fpu,*,*,*,vis3,vis3,fpu,*,fpu,*")])
;; The following 3 patterns build SFmode constants in integer registers.
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "fp_const_high_losum_operand" ""))]
- "REG_P (operands[0]) && REGNO (operands[0]) < 32"
+ "REG_P (operands[0]) && SPARC_INT_REG_P (REGNO (operands[0]))"
[(set (match_dup 0) (high:SF (match_dup 1)))
(set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
DONE;
})
-;; Be careful, fmovd does not exist when !v9.
(define_insn "*movdf_insn_sp32"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,W,U,T,o,e, *r, o, e,o")
- (match_operand:DF 1 "input_operand" "W#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
- "TARGET_FPU
- && ! TARGET_V9
- && (register_operand (operands[0], DFmode)
- || register_or_zero_operand (operands[1], DFmode))"
- "@
- ldd\t%1, %0
- std\t%1, %0
- ldd\t%1, %0
- std\t%1, %0
- #
- #
- #
- #
- #
- #"
- [(set_attr "type" "fpload,fpstore,load,store,*,*,*,*,*,*")
- (set_attr "length" "*,*,*,*,2,2,2,2,2,2")])
-
-(define_insn "*movdf_insn_sp32_no_fpu"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,o,r,o")
- (match_operand:DF 1 "input_operand" "T,U,G,ro,r"))]
- "! TARGET_FPU
- && ! TARGET_V9
- && (register_operand (operands[0], DFmode)
- || register_or_zero_operand (operands[1], DFmode))"
- "@
- ldd\t%1, %0
- std\t%1, %0
- #
- #
- #"
- [(set_attr "type" "load,store,*,*,*")
- (set_attr "length" "*,*,2,2,2")])
-
-;; We have available v9 double floats but not 64-bit integer registers.
-(define_insn "*movdf_insn_sp32_v9"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=b, b,e, e, T,W,U,T, f, *r, o")
- (match_operand:DF 1 "input_operand" "GY,ZC,e,W#F,GY,e,T,U,o#F,*roGYDF,*rGYf"))]
- "TARGET_FPU
- && TARGET_V9
- && ! TARGET_ARCH64
+ [(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))"
"@
fzero\t%0
fone\t%0
fmovd\t%1, %0
+ #
+ #
+ #
ldd\t%1, %0
stx\t%r1, %0
std\t%1, %0
std\t%1, %0
#
#
- #"
- [(set_attr "type" "fga,fga,fpmove,load,store,store,load,store,*,*,*")
- (set_attr "length" "*,*,*,*,*,*,*,*,2,2,2")
- (set_attr "fptype" "double,double,double,*,*,*,*,*,*,*,*")])
-
-(define_insn "*movdf_insn_sp32_v9_no_fpu"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,T,r,o")
- (match_operand:DF 1 "input_operand" "T,U,G,ro,rG"))]
- "! TARGET_FPU
- && TARGET_V9
- && ! TARGET_ARCH64
- && (register_operand (operands[0], DFmode)
- || register_or_zero_operand (operands[1], DFmode))"
- "@
- ldd\t%1, %0
- std\t%1, %0
- stx\t%r1, %0
#
#"
- [(set_attr "type" "load,store,store,*,*")
- (set_attr "length" "*,*,*,2,2")])
+ [(set_attr "type" "fga,fga,fpmove,*,*,*,fpload,store,fpstore,load,store,*,*,*,*")
+ (set_attr "length" "*,*,*,2,2,2,*,*,*,*,*,2,2,2,2")
+ (set_attr "fptype" "double,double,double,*,*,*,*,*,*,*,*,*,*,*,*")
+ (set_attr "cpu_feature" "vis,vis,v9,fpunotv9,vis3,vis3,fpu,v9,fpu,*,*,fpu,*,*,fpu")])
-;; We have available both v9 double floats and 64-bit integer registers.
(define_insn "*movdf_insn_sp64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=b, b,e, e,W, *r,*r, m,*r")
- (match_operand:DF 1 "input_operand" "GY,ZC,e,W#F,e,*rGY, m,*rGY,DF"))]
- "TARGET_FPU
- && TARGET_ARCH64
+ [(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"))]
+ "TARGET_ARCH64
&& (register_operand (operands[0], DFmode)
|| register_or_zero_or_all_ones_operand (operands[1], DFmode))"
"@
fzero\t%0
fone\t%0
fmovd\t%1, %0
+ movdtox\t%1, %0
+ movxtod\t%1, %0
ldd\t%1, %0
std\t%1, %0
mov\t%r1, %0
ldx\t%1, %0
stx\t%r1, %0
#"
- [(set_attr "type" "fga,fga,fpmove,load,store,*,load,store,*")
- (set_attr "length" "*,*,*,*,*,*,*,*,2")
- (set_attr "fptype" "double,double,double,*,*,*,*,*,*")])
-
-(define_insn "*movdf_insn_sp64_no_fpu"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
- (match_operand:DF 1 "input_operand" "r,m,rG"))]
- "! TARGET_FPU
- && TARGET_ARCH64
- && (register_operand (operands[0], DFmode)
- || register_or_zero_operand (operands[1], DFmode))"
- "@
- mov\t%1, %0
- ldx\t%1, %0
- stx\t%r1, %0"
- [(set_attr "type" "*,load,store")])
+ [(set_attr "type" "fga,fga,fpmove,*,*,load,store,*,load,store,*")
+ (set_attr "length" "*,*,*,*,*,*,*,*,*,*,2")
+ (set_attr "fptype" "double,double,double,double,double,*,*,*,*,*,*")
+ (set_attr "cpu_feature" "vis,vis,fpu,vis3,vis3,fpu,fpu,*,*,*,*")])
;; This pattern builds DFmode constants in integer registers.
(define_split
[(set (match_operand:DF 0 "register_operand" "")
(match_operand:DF 1 "const_double_operand" ""))]
- "TARGET_FPU
- && (GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ "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))]
(match_operand:DF 1 "register_operand" ""))]
"(! TARGET_V9
|| (! TARGET_ARCH64
- && ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
- || (GET_CODE (operands[0]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))))
+ && sparc_split_regreg_legitimate (operands[0],
+ operands[1])))
&& reload_completed"
[(clobber (const_int 0))]
{
"reload_completed
&& ! TARGET_ARCH64
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
[(clobber (const_int 0))]
{
rtx set_dest = operands[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" "")
&& (! TARGET_ARCH64
|| (TARGET_FPU
&& ! TARGET_HARD_QUAD)
- || ! fp_register_operand (operands[0], TFmode))"
+ || (! fp_register_operand (operands[0], TFmode)
+ && ! fp_register_operand (operands[1], TFmode)))"
[(clobber (const_int 0))]
{
rtx set_dest = operands[0];
;; 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 "*zero_extendsidi2_insn_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (zero_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
- "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
+ [(set (match_operand:DI 0 "register_operand" "=r,r,r")
+ (zero_extend:DI (match_operand:SI 1 "input_operand" "r,m,*f")))]
+ "TARGET_ARCH64
+ && GET_CODE (operands[1]) != CONST_INT"
"@
srl\t%1, 0, %0
- lduw\t%1, %0"
- [(set_attr "type" "shift,load")])
+ lduw\t%1, %0
+ movstouw\t%1, %0"
+ [(set_attr "type" "shift,load,*")
+ (set_attr "cpu_feature" "*,*,vis3")])
(define_insn_and_split "*zero_extendsidi2_insn_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
"")
(define_insn "*sign_extendsidi2_insn"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (sign_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
+ [(set (match_operand:DI 0 "register_operand" "=r,r,r")
+ (sign_extend:DI (match_operand:SI 1 "input_operand" "r,m,*f")))]
"TARGET_ARCH64"
"@
sra\t%1, 0, %0
- ldsw\t%1, %0"
- [(set_attr "type" "shift,sload")
- (set_attr "us3load_type" "*,3cycle")])
+ ldsw\t%1, %0
+ movstosw\t%1, %0"
+ [(set_attr "type" "shift,sload,*")
+ (set_attr "us3load_type" "*,3cycle,*")
+ (set_attr "cpu_feature" "*,*,vis3")])
;; Special pattern for optimizing bit-field compares. This is needed
})
(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"
"#"
"&& reload_completed
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
[(set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))
(set (match_dup 6) (and:SI (not:SI (match_dup 7)) (match_dup 8)))]
"operands[3] = gen_highpart (SImode, operands[0]);
"#"
"&& reload_completed
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
[(set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))
(set (match_dup 6) (ior:SI (not:SI (match_dup 7)) (match_dup 8)))]
"operands[3] = gen_highpart (SImode, operands[0]);
"! TARGET_ARCH64
&& reload_completed
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
[(set (match_dup 4) (match_op_dup:SI 1 [(match_dup 6) (match_dup 8)]))
(set (match_dup 5) (match_op_dup:SI 1 [(match_dup 7) (match_dup 9)]))]
{
"#"
"&& reload_completed
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
[(set (match_dup 3) (not:SI (xor:SI (match_dup 4) (match_dup 5))))
(set (match_dup 6) (not:SI (xor:SI (match_dup 7) (match_dup 8))))]
"operands[3] = gen_highpart (SImode, operands[0]);
"#"
"&& reload_completed
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
[(set (match_dup 2) (not:SI (xor:SI (match_dup 3) (const_int 0))))
(set (match_dup 4) (not:SI (xor:SI (match_dup 5) (const_int 0))))]
"operands[2] = gen_highpart (SImode, operands[0]);
(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"
})
(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"))]
+ [(set (match_operand:VM32 0 "nonimmediate_operand" "=f,f,f,f,m,m,*r, m,*r,*r, f")
+ (match_operand:VM32 1 "input_operand" "Y,Z,f,m,f,Y, m,*r,*r, f,*r"))]
"TARGET_VIS
&& (register_operand (operands[0], <VM32:MODE>mode)
|| register_or_zero_or_all_ones_operand (operands[1], <VM32:MODE>mode))"
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,*,*")])
+ mov\t%1, %0
+ movstouw\t%1, %0
+ movwtos\t%1, %0"
+ [(set_attr "type" "fga,fga,fga,fpload,fpstore,store,load,store,*,*,*")
+ (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, r")
- (match_operand:VM64 1 "input_operand" "GY,ZC,e,m,e,GY,m,r,GY,ZC"))]
+ [(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)
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,*,*")])
+ movdtox\t%1, %0
+ movxtod\t%1, %0
+ mov\t%1, %0"
+ [(set_attr "type" "fga,fga,fga,fpload,fpstore,store,load,store,*,*,*")
+ (set_attr "cpu_feature" "vis,vis,vis,*,*,*,*,*,vis3,vis3,*")])
(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"))]
+ [(set (match_operand:VM64 0 "nonimmediate_operand" "=e,e,e,*r, f,e,m,m,U,T, o,*r")
+ (match_operand:VM64 1 "input_operand" "Y,C,e, f,*r,m,e,Y,T,U,*r,*r"))]
"TARGET_VIS
&& ! TARGET_ARCH64
&& (register_operand (operands[0], <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")])
+ #"
+ [(set_attr "type" "fga,fga,fga,*,*,fpload,fpstore,store,load,store,*,*")
+ (set_attr "length" "*,*,*,2,2,*,*,*,*,*,2,2")
+ (set_attr "cpu_feature" "vis,vis,vis,vis3,vis3,*,*,*,*,*,*,*")])
(define_split
[(set (match_operand:VM64 0 "memory_operand" "")
DONE;
})
+(define_split
+ [(set (match_operand:VM64 0 "register_operand" "")
+ (match_operand:VM64 1 "register_operand" ""))]
+ "reload_completed
+ && TARGET_VIS
+ && ! TARGET_ARCH64
+ && sparc_split_regreg_legitimate (operands[0], operands[1])"
+ [(clobber (const_int 0))]
+{
+ rtx set_dest = operands[0];
+ rtx set_src = operands[1];
+ rtx dest1, dest2;
+ rtx src1, src2;
+
+ dest1 = gen_highpart (SImode, set_dest);
+ dest2 = gen_lowpart (SImode, set_dest);
+ src1 = gen_highpart (SImode, set_src);
+ src2 = gen_lowpart (SImode, set_src);
+
+ /* Now emit using the real source and destination we found, swapping
+ the order if we detect overlap. */
+ if (reg_overlap_mentioned_p (dest1, src2))
+ {
+ emit_insn (gen_movsi (dest2, src2));
+ emit_insn (gen_movsi (dest1, src1));
+ }
+ else
+ {
+ emit_insn (gen_movsi (dest1, src1));
+ emit_insn (gen_movsi (dest2, src2));
+ }
+ DONE;
+})
+
(define_expand "vec_init<mode>"
[(match_operand:VMALL 0 "register_operand" "")
(match_operand:VMALL 1 "" "")]
[(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")
[(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")
;; 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"