summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/config/sparc/sparc.md
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/config/sparc/sparc.md')
-rw-r--r--contrib/gcc/config/sparc/sparc.md912
1 files changed, 329 insertions, 583 deletions
diff --git a/contrib/gcc/config/sparc/sparc.md b/contrib/gcc/config/sparc/sparc.md
index c0b8f60..ebb6768 100644
--- a/contrib/gcc/config/sparc/sparc.md
+++ b/contrib/gcc/config/sparc/sparc.md
@@ -1,4 +1,4 @@
-;- Machine description for SPARC chip for GNU C compiler
+;; Machine description for SPARC chip for GNU C compiler
;; Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
;; 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
;; Contributed by Michael Tiemann (tiemann@cygnus.com)
@@ -87,8 +87,78 @@
"ialu,compare,shift,load,sload,store,uncond_branch,branch,call,sibcall,call_no_delay_slot,return,imul,idiv,fpload,fpstore,fp,fpmove,fpcmove,fpcmp,fpmul,fpdivs,fpdivd,fpsqrts,fpsqrtd,cmove,multi,misc"
(const_string "ialu"))
+;; true if branch/call has empty delay slot and will emit a nop in it
+(define_attr "empty_delay_slot" "false,true"
+ (symbol_ref "empty_delay_slot (insn)"))
+
+(define_attr "branch_type" "none,icc,fcc,reg" (const_string "none"))
+
+(define_attr "pic" "false,true"
+ (symbol_ref "flag_pic != 0"))
+
;; Length (in # of insns).
-(define_attr "length" "" (const_int 1))
+(define_attr "length" ""
+ (cond [(eq_attr "type" "uncond_branch,call,sibcall")
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (eq_attr "branch_type" "icc")
+ (if_then_else (match_operand 0 "noov_compare64_op" "")
+ (if_then_else (lt (pc) (match_dup 1))
+ (if_then_else (lt (minus (match_dup 1) (pc)) (const_int 260000))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 4)
+ (const_int 3)))
+ (if_then_else (lt (minus (pc) (match_dup 1)) (const_int 260000))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 4)
+ (const_int 3))))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1)))
+ (eq_attr "branch_type" "fcc")
+ (if_then_else (match_operand 0 "fcc0_reg_operand" "")
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (lt (pc) (match_dup 2))
+ (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 260000))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 4)
+ (const_int 3)))
+ (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 260000))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 4)
+ (const_int 3)))))
+ (eq_attr "branch_type" "reg")
+ (if_then_else (lt (pc) (match_dup 2))
+ (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 32000))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 4)
+ (const_int 3)))
+ (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 32000))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 4)
+ (const_int 3))))
+ ] (const_int 1)))
;; FP precision.
(define_attr "fptype" "single,double" (const_string "single"))
@@ -1893,11 +1963,12 @@
""
"*
{
- return output_cbranch (operands[0], 1, 0,
+ return output_cbranch (operands[0], operands[1], 1, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "icc")])
;; XXX fpcmp nop braindamage
(define_insn "*inverted_branch"
@@ -1909,11 +1980,12 @@
""
"*
{
- return output_cbranch (operands[0], 1, 1,
+ return output_cbranch (operands[0], operands[1], 1, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "icc")])
;; XXX fpcmp nop braindamage
(define_insn "*normal_fp_branch"
@@ -1926,11 +1998,12 @@
""
"*
{
- return output_cbranch (operands[1], 2, 0,
+ return output_cbranch (operands[1], operands[2], 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "fcc")])
;; XXX fpcmp nop braindamage
(define_insn "*inverted_fp_branch"
@@ -1943,11 +2016,12 @@
""
"*
{
- return output_cbranch (operands[1], 2, 1,
+ return output_cbranch (operands[1], operands[2], 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "fcc")])
;; XXX fpcmp nop braindamage
(define_insn "*normal_fpe_branch"
@@ -1960,11 +2034,12 @@
""
"*
{
- return output_cbranch (operands[1], 2, 0,
+ return output_cbranch (operands[1], operands[2], 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "fcc")])
;; XXX fpcmp nop braindamage
(define_insn "*inverted_fpe_branch"
@@ -1977,11 +2052,12 @@
""
"*
{
- return output_cbranch (operands[1], 2, 1,
+ return output_cbranch (operands[1], operands[2], 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "fcc")])
;; Sparc V9-specific jump insns. None of these are guaranteed to be
;; in the architecture.
@@ -1999,11 +2075,12 @@
"TARGET_ARCH64"
"*
{
- return output_v9branch (operands[0], 1, 2, 0,
+ return output_v9branch (operands[0], operands[2], 1, 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "reg")])
;; XXX
(define_insn "*inverted_int_branch_sp64"
@@ -2016,11 +2093,12 @@
"TARGET_ARCH64"
"*
{
- return output_v9branch (operands[0], 1, 2, 1,
+ return output_v9branch (operands[0], operands[2], 1, 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "reg")])
;; Load program counter insns.
@@ -2053,14 +2131,8 @@
a double if needed. */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
{
- operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) & 0xff);
- }
- else if (GET_CODE (operands[1]) == CONST_INT)
- {
- /* And further, we know for all QI cases that only the
- low byte is significant, which we can always process
- in a single insn. So mask it now. */
- operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
+ operands[1] = GEN_INT (trunc_int_for_mode
+ (CONST_DOUBLE_LOW (operands[1]), QImode));
}
/* Handle sets of MEM first. */
@@ -2459,13 +2531,14 @@
(define_insn "*movdi_insn_sp32_v9"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=m,T,U,o,r,r,r,?T,?f,?f,?o,?f")
+ "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
(match_operand:DI 1 "input_operand"
- " J,U,T,r,o,i,r, f, T, o, f, f"))]
+ " J,J,U,T,r,o,i,r, f, T, o, f, f"))]
"! TARGET_ARCH64 && TARGET_V9
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"@
stx\\t%%g0, %0
+ #
std\\t%1, %0
ldd\\t%1, %0
#
@@ -2477,18 +2550,19 @@
#
#
#"
- [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
- (set_attr "length" "*,*,*,2,2,2,2,*,*,2,2,2")])
+ [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
+ (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,2")])
(define_insn "*movdi_insn_sp32"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=T,U,o,r,r,r,?T,?f,?f,?o,?f")
+ "=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
(match_operand:DI 1 "input_operand"
- " U,T,r,o,i,r, f, T, o, f, f"))]
+ " J,U,T,r,o,i,r, f, T, o, f, f"))]
"! TARGET_ARCH64
&& (register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))"
"@
+ #
std\\t%1, %0
ldd\\t%1, %0
#
@@ -2500,8 +2574,8 @@
#
#
#"
- [(set_attr "type" "store,load,*,*,*,*,fpstore,fpload,*,*,*")
- (set_attr "length" "*,*,2,2,2,2,*,*,2,2,2")])
+ [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
+ (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
;; The following are generated by sparc_emit_set_const64
(define_insn "*movdi_sp64_dbl"
@@ -2520,8 +2594,8 @@
"sethi\\t%%hi(%a1), %0")
(define_insn "*movdi_insn_sp64_novis"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?m")
- (match_operand:DI 1 "input_operand" "rI,K,J,m,rJ,e,m,e"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W")
+ (match_operand:DI 1 "input_operand" "rI,N,J,m,rJ,e,W,e"))]
"TARGET_ARCH64 && ! TARGET_VIS
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
@@ -2538,8 +2612,8 @@
(set_attr "fptype" "*,*,*,*,*,double,*,*")])
(define_insn "*movdi_insn_sp64_vis"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?m,b")
- (match_operand:DI 1 "input_operand" "rI,K,J,m,rJ,e,m,e,J"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W,b")
+ (match_operand:DI 1 "input_operand" "rI,N,J,m,rJ,e,W,e,J"))]
"TARGET_ARCH64 && TARGET_VIS &&
(register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
@@ -2734,8 +2808,7 @@
&& ! flag_pic"
"
{
- sparc_emit_set_symbolic_const64 (operands[0], operands[1],
- gen_rtx_REG (DImode, REGNO (operands[2])));
+ sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
DONE;
}")
@@ -2748,8 +2821,7 @@
&& ! flag_pic"
"
{
- sparc_emit_set_symbolic_const64 (operands[0], operands[1],
- gen_rtx_REG (DImode, REGNO (operands[2])));
+ sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
DONE;
}")
@@ -2771,8 +2843,8 @@
#else
unsigned int low, high;
- low = INTVAL (operands[1]) & 0xffffffff;
- high = (INTVAL (operands[1]) >> 32) & 0xffffffff;
+ low = trunc_int_for_mode (INTVAL (operands[1]), SImode);
+ high = trunc_int_for_mode (INTVAL (operands[1]) >> 32, SImode);
emit_insn (gen_movsi (gen_highpart (SImode, operands[0]), GEN_INT (high)));
/* Slick... but this trick loses if this subreg constant part
@@ -2799,7 +2871,7 @@
/* Slick... but this trick loses if this subreg constant part
can be done in one insn. */
if (CONST_DOUBLE_LOW (operands[1]) == CONST_DOUBLE_HIGH (operands[1])
- && !(SPARC_SETHI_P (CONST_DOUBLE_HIGH (operands[1]))
+ && !(SPARC_SETHI32_P (CONST_DOUBLE_HIGH (operands[1]))
|| SPARC_SIMM13_P (CONST_DOUBLE_HIGH (operands[1]))))
{
emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
@@ -2890,6 +2962,21 @@
DONE;
}")
+(define_split
+ [(set (match_operand:DI 0 "memory_operand" "")
+ (const_int 0))]
+ "reload_completed
+ && (! TARGET_V9
+ || (! TARGET_ARCH64
+ && ! mem_min_alignment (operands[0], 8)))
+ && offsettable_memref_p (operands[0])"
+ [(clobber (const_int 0))]
+ "
+{
+ emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0), const0_rtx));
+ emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4), const0_rtx));
+ DONE;
+}")
;; Floating point move insns
@@ -3202,8 +3289,8 @@
;; Be careful, fmovd does not exist when !v9.
(define_insn "*movdf_insn_sp32"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,T,U,T,o,e,*r,o,e,o")
- (match_operand:DF 1 "input_operand" "T#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
+ [(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)
@@ -3262,8 +3349,8 @@
;; We have available v9 double floats but not 64-bit
;; integer registers and no VIS.
(define_insn "*movdf_insn_v9only_novis"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,T,T,U,T,e,*r,o")
- (match_operand:DF 1 "input_operand" "e,T#F,G,e,T,U,o#F,*roF,*rGe"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,T,W,U,T,f,*r,o")
+ (match_operand:DF 1 "input_operand" "e,W#F,G,e,T,U,o#F,*roF,*rGf"))]
"TARGET_FPU
&& TARGET_V9
&& ! TARGET_VIS
@@ -3288,8 +3375,8 @@
;; We have available v9 double floats but not 64-bit
;; integer registers but we have VIS.
(define_insn "*movdf_insn_v9only_vis"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,T,T,U,T,e,*r,o")
- (match_operand:DF 1 "input_operand" "G,e,T#F,G,e,T,U,o#F,*roGF,*rGe"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,T,W,U,T,f,*r,o")
+ (match_operand:DF 1 "input_operand" "G,e,W#F,G,e,T,U,o#F,*roGF,*rGf"))]
"TARGET_FPU
&& TARGET_VIS
&& ! TARGET_ARCH64
@@ -3314,8 +3401,8 @@
;; We have available both v9 double floats and 64-bit
;; integer registers. No VIS though.
(define_insn "*movdf_insn_sp64_novis"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,m,*r,*r,m,*r")
- (match_operand:DF 1 "input_operand" "e,m#F,e,*rG,m,*rG,F"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,W,*r,*r,m,*r")
+ (match_operand:DF 1 "input_operand" "e,W#F,e,*rG,m,*rG,F"))]
"TARGET_FPU
&& ! TARGET_VIS
&& TARGET_ARCH64
@@ -3337,8 +3424,8 @@
;; We have available both v9 double floats and 64-bit
;; integer registers. And we have VIS.
(define_insn "*movdf_insn_sp64_vis"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,m,*r,*r,m,*r")
- (match_operand:DF 1 "input_operand" "G,e,m#F,e,*rG,m,*rG,F"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,W,*r,*r,m,*r")
+ (match_operand:DF 1 "input_operand" "G,e,W#F,e,*rG,m,*rG,F"))]
"TARGET_FPU
&& TARGET_VIS
&& TARGET_ARCH64
@@ -3411,7 +3498,7 @@
/* Slick... but this trick loses if this subreg constant part
can be done in one insn. */
if (l[1] == l[0]
- && !(SPARC_SETHI_P (l[0])
+ && !(SPARC_SETHI32_P (l[0])
|| SPARC_SIMM13_P (l[0])))
{
emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
@@ -3753,7 +3840,8 @@
"reload_completed
&& (! TARGET_ARCH64
|| (TARGET_FPU
- && ! TARGET_HARD_QUAD))"
+ && ! TARGET_HARD_QUAD)
+ || ! fp_register_operand (operands[0], TFmode))"
[(clobber (const_int 0))]
"
{
@@ -3815,7 +3903,10 @@
[(set (match_operand:TF 0 "register_operand" "")
(match_operand:TF 1 "memory_operand" ""))]
"(reload_completed
- && offsettable_memref_p (operands[1]))"
+ && offsettable_memref_p (operands[1])
+ && (! TARGET_ARCH64
+ || ! TARGET_HARD_QUAD
+ || ! fp_register_operand (operands[0], TFmode)))"
[(clobber (const_int 0))]
"
{
@@ -3848,7 +3939,10 @@
[(set (match_operand:TF 0 "memory_operand" "")
(match_operand:TF 1 "register_operand" ""))]
"(reload_completed
- && offsettable_memref_p (operands[0]))"
+ && offsettable_memref_p (operands[0])
+ && (! TARGET_ARCH64
+ || ! TARGET_HARD_QUAD
+ || ! fp_register_operand (operands[1], TFmode)))"
[(clobber (const_int 0))]
"
{
@@ -4929,31 +5023,11 @@
(set_attr "fptype" "double")])
(define_expand "extendsftf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
(float_extend:TF
- (match_operand:SF 1 "register_operand" "f")))]
+ (match_operand:SF 1 "register_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_stoq\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- operands[1], SFmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
(define_insn "*extendsftf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -4964,31 +5038,11 @@
[(set_attr "type" "fp")])
(define_expand "extenddftf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
(float_extend:TF
- (match_operand:DF 1 "register_operand" "e")))]
+ (match_operand:DF 1 "register_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_dtoq\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- operands[1], DFmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
(define_insn "*extenddftf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -5008,30 +5062,11 @@
(set_attr "fptype" "double")])
(define_expand "trunctfsf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
+ [(set (match_operand:SF 0 "register_operand" "")
(float_truncate:SF
- (match_operand:TF 1 "register_operand" "e")))]
+ (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- {
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
- }
- else
- slot0 = operands[1];
-
- emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtos\"),
- operands[0], 0, SFmode, 1,
- XEXP (slot0, 0), Pmode);
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
(define_insn "*trunctfsf2_hq"
[(set (match_operand:SF 0 "register_operand" "=f")
@@ -5042,30 +5077,11 @@
[(set_attr "type" "fp")])
(define_expand "trunctfdf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
+ [(set (match_operand:DF 0 "register_operand" "")
(float_truncate:DF
- (match_operand:TF 1 "register_operand" "e")))]
+ (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- {
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
- }
- else
- slot0 = operands[1];
-
- emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtod\"),
- operands[0], 0, DFmode, 1,
- XEXP (slot0, 0), Pmode);
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
(define_insn "*trunctfdf2_hq"
[(set (match_operand:DF 0 "register_operand" "=e")
@@ -5094,30 +5110,10 @@
(set_attr "fptype" "double")])
(define_expand "floatsitf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (float:TF (match_operand:SI 1 "register_operand" "f")))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (float:TF (match_operand:SI 1 "register_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[1];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_itoq\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- operands[1], SImode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FLOAT, operands); DONE;")
(define_insn "*floatsitf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -5127,27 +5123,10 @@
[(set_attr "type" "fp")])
(define_expand "floatunssitf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (unsigned_float:TF (match_operand:SI 1 "register_operand" "e")))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (unsigned_float:TF (match_operand:SI 1 "register_operand" "")))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
- "
-{
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[1];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_uitoq\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- operands[1], SImode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
-}")
+ "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
;; Now the same for 64 bit sources.
@@ -5159,6 +5138,12 @@
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
+(define_expand "floatunsdisf2"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:DI 1 "register_operand" ""))]
+ "TARGET_ARCH64 && TARGET_FPU"
+ "sparc_emit_floatunsdi (operands); DONE;")
+
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "register_operand" "=e")
(float:DF (match_operand:DI 1 "register_operand" "e")))]
@@ -5167,31 +5152,17 @@
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
+(define_expand "floatunsdidf2"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DI 1 "register_operand" ""))]
+ "TARGET_ARCH64 && TARGET_FPU"
+ "sparc_emit_floatunsdi (operands); DONE;")
+
(define_expand "floatditf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (float:TF (match_operand:DI 1 "register_operand" "e")))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (float:TF (match_operand:DI 1 "register_operand" "")))]
"TARGET_FPU && TARGET_V9 && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[1];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_xtoq\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- operands[1], DImode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FLOAT, operands); DONE;")
(define_insn "*floatditf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -5201,27 +5172,10 @@
[(set_attr "type" "fp")])
(define_expand "floatunsditf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (unsigned_float:TF (match_operand:DI 1 "register_operand" "e")))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (unsigned_float:TF (match_operand:DI 1 "register_operand" "")))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
- "
-{
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[1];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_uxtoq\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- operands[1], DImode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
-}")
+ "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
;; Convert a float to an actual integer.
;; Truncation is performed as part of the conversion.
@@ -5243,58 +5197,23 @@
(set_attr "fptype" "double")])
(define_expand "fix_trunctfsi2"
- [(set (match_operand:SI 0 "register_operand" "=f")
- (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ [(set (match_operand:SI 0 "register_operand" "")
+ (fix:SI (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- {
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
- }
- else
- slot0 = operands[1];
-
- emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoi\"),
- operands[0], 0, SImode, 1,
- XEXP (slot0, 0), Pmode);
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FIX, operands); DONE;")
(define_insn "*fix_trunctfsi2_hq"
[(set (match_operand:SI 0 "register_operand" "=f")
- (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ (fix:SI (match_operand:TF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
"fqtoi\\t%1, %0"
[(set_attr "type" "fp")])
(define_expand "fixuns_trunctfsi2"
- [(set (match_operand:SI 0 "register_operand" "=f")
- (unsigned_fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unsigned_fix:SI (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
- "
-{
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- {
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
- }
- else
- slot0 = operands[1];
-
- emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoui\"),
- operands[0], 0, SImode, 1,
- XEXP (slot0, 0), Pmode);
- DONE;
-}")
+ "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
;; Now the same, for V9 targets
@@ -5315,59 +5234,23 @@
(set_attr "fptype" "double")])
(define_expand "fix_trunctfdi2"
- [(set (match_operand:DI 0 "register_operand" "=e")
- (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ [(set (match_operand:DI 0 "register_operand" "")
+ (fix:DI (match_operand:TF 1 "general_operand" "")))]
"TARGET_V9 && TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- {
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
- }
- else
- slot0 = operands[1];
-
- emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtox\"),
- operands[0], 0, DImode, 1,
- XEXP (slot0, 0), Pmode);
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FIX, operands); DONE;")
(define_insn "*fix_trunctfdi2_hq"
[(set (match_operand:DI 0 "register_operand" "=e")
- (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ (fix:DI (match_operand:TF 1 "register_operand" "e")))]
"TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
"fqtox\\t%1, %0"
[(set_attr "type" "fp")])
(define_expand "fixuns_trunctfdi2"
- [(set (match_operand:DI 0 "register_operand" "=f")
- (unsigned_fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unsigned_fix:DI (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
- "
-{
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- {
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
- }
- else
- slot0 = operands[1];
-
- emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoux\"),
- operands[0], 0, DImode, 1,
- XEXP (slot0, 0), Pmode);
- DONE;
-}")
-
+ "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
;;- arithmetic instructions
@@ -5920,6 +5803,13 @@
else
return \"sllx\\t%H1, 32, %3\\n\\tor\\t%L1, %3, %3\\n\\tmulx\\t%3, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0\";
}
+ else if (rtx_equal_p (operands[1], operands[2]))
+ {
+ if (which_alternative == 1)
+ return \"or\\t%L1, %H1, %H1\\n\\tmulx\\t%H1, %H1, %L0\;srlx\\t%L0, 32, %H0\";
+ else
+ return \"sllx\\t%H1, 32, %3\\n\\tor\\t%L1, %3, %3\\n\\tmulx\\t%3, %3, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0\";
+ }
if (sparc_check_64 (operands[2], insn) <= 0)
output_asm_insn (\"srl\\t%L2, 0, %L2\", operands);
if (which_alternative == 1)
@@ -6377,7 +6267,7 @@
[(set_attr "type" "multi")
(set (attr "length")
(if_then_else (eq_attr "isa" "v9")
- (const_int 4) (const_int 7)))])
+ (const_int 4) (const_int 6)))])
(define_insn "divsi3_sp64"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -6576,7 +6466,7 @@
(set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
"
{
- operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff);
+ operands[4] = GEN_INT (~INTVAL (operands[2]));
}")
;; Split DImode logical operations requiring two instructions.
@@ -6719,7 +6609,7 @@
(set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
"
{
- operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff);
+ operands[4] = GEN_INT (~INTVAL (operands[2]));
}")
(define_insn "*or_not_di_sp32"
@@ -6835,7 +6725,7 @@
(set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
"
{
- operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff);
+ operands[4] = GEN_INT (~INTVAL (operands[2]));
}")
(define_split
@@ -6850,7 +6740,7 @@
(set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
"
{
- operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff);
+ operands[4] = GEN_INT (~INTVAL (operands[2]));
}")
;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
@@ -7267,42 +7157,7 @@
(plus:TF (match_operand:TF 1 "general_operand" "")
(match_operand:TF 2 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0, slot1, slot2;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
- if (GET_CODE (operands[1]) != MEM)
- {
- slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
- }
- else
- slot1 = operands[1];
- if (GET_CODE (operands[2]) != MEM)
- {
- slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
- }
- else
- slot2 = operands[2];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_add\"), 0,
- VOIDmode, 3,
- XEXP (slot0, 0), Pmode,
- XEXP (slot1, 0), Pmode,
- XEXP (slot2, 0), Pmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_binop (PLUS, operands); DONE;")
(define_insn "*addtf3_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -7334,42 +7189,7 @@
(minus:TF (match_operand:TF 1 "general_operand" "")
(match_operand:TF 2 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0, slot1, slot2;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
- if (GET_CODE (operands[1]) != MEM)
- {
- slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
- }
- else
- slot1 = operands[1];
- if (GET_CODE (operands[2]) != MEM)
- {
- slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
- }
- else
- slot2 = operands[2];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_sub\"), 0,
- VOIDmode, 3,
- XEXP (slot0, 0), Pmode,
- XEXP (slot1, 0), Pmode,
- XEXP (slot2, 0), Pmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_binop (MINUS, operands); DONE;")
(define_insn "*subtf3_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -7401,42 +7221,7 @@
(mult:TF (match_operand:TF 1 "general_operand" "")
(match_operand:TF 2 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0, slot1, slot2;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
- if (GET_CODE (operands[1]) != MEM)
- {
- slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
- }
- else
- slot1 = operands[1];
- if (GET_CODE (operands[2]) != MEM)
- {
- slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
- }
- else
- slot2 = operands[2];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_mul\"), 0,
- VOIDmode, 3,
- XEXP (slot0, 0), Pmode,
- XEXP (slot1, 0), Pmode,
- XEXP (slot2, 0), Pmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_binop (MULT, operands); DONE;")
(define_insn "*multf3_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -7485,42 +7270,7 @@
(div:TF (match_operand:TF 1 "general_operand" "")
(match_operand:TF 2 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0, slot1, slot2;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
- if (GET_CODE (operands[1]) != MEM)
- {
- slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
- }
- else
- slot1 = operands[1];
- if (GET_CODE (operands[2]) != MEM)
- {
- slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
- }
- else
- slot2 = operands[2];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_div\"), 0,
- VOIDmode, 3,
- XEXP (slot0, 0), Pmode,
- XEXP (slot1, 0), Pmode,
- XEXP (slot2, 0), Pmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_binop (DIV, operands); DONE;")
;; don't have timing for quad-prec. divide.
(define_insn "*divtf3_hq"
@@ -7769,37 +7519,10 @@
[(set_attr "type" "fpmove")])
(define_expand "sqrttf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (sqrt:TF (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0, slot1;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
- if (GET_CODE (operands[1]) != MEM)
- {
- slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
- }
- else
- slot1 = operands[1];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_sqrt\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- XEXP (slot1, 0), Pmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_unop (SQRT, operands); DONE;")
(define_insn "*sqrttf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -8403,7 +8126,7 @@
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
"call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
[(set_attr "type" "call_no_delay_slot")
- (set_attr "length" "2")])
+ (set_attr "length" "3")])
;; This is a call that wants a structure value.
;; There is no such critter for v9 (??? we may need one anyway).
@@ -8416,7 +8139,7 @@
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
"call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
[(set_attr "type" "call_no_delay_slot")
- (set_attr "length" "2")])
+ (set_attr "length" "3")])
;; This is a call that may want a structure value. This is used for
;; untyped_calls.
@@ -8429,7 +8152,7 @@
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
"call\\t%a0, %1\\n\\tnop\\n\\tnop"
[(set_attr "type" "call_no_delay_slot")
- (set_attr "length" "2")])
+ (set_attr "length" "3")])
;; This is a call that wants a structure value.
(define_insn "*call_symbolic_untyped_struct_value_sp32"
@@ -8441,7 +8164,7 @@
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
"call\\t%a0, %1\\n\\tnop\\n\\tnop"
[(set_attr "type" "call_no_delay_slot")
- (set_attr "length" "2")])
+ (set_attr "length" "3")])
(define_expand "call_value"
;; Note that this expression is not used for generating RTL.
@@ -8665,21 +8388,6 @@
[(set_attr "type" "multi")
(set_attr "length" "3")])
-(define_insn "return"
- [(return)
- (use (reg:SI 31))]
- "! TARGET_EPILOGUE"
- "* return output_return (operands);"
- [(set_attr "type" "return")])
-
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "arith_operand" "rI"))
- (parallel [(return)
- (use (reg:SI 31))])]
- "sparc_return_peephole_ok (operands[0], operands[1])"
- "return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0")
-
(define_insn "nop"
[(const_int 0)]
""
@@ -8737,7 +8445,7 @@
/* Restore %fp from stack pointer value for containing function.
The restore insn that follows will move this to %sp,
and reload the appropriate value into %fp. */
- emit_move_insn (frame_pointer_rtx, stack);
+ emit_move_insn (hard_frame_pointer_rtx, stack);
/* USE of frame_pointer_rtx added for consistency; not clear if
really needed. */
@@ -8813,22 +8521,41 @@
DONE;
}")
-;; ??? Should set length to zero when !current_function_calls_alloca,
-;; ??? but there is no easy way to get at that definition. It would
-;; ??? require including function.h into sparc-protos.h and that is
-;; ??? likely not a good idea. -DaveM
(define_insn "do_builtin_setjmp_setup"
[(unspec_volatile [(const_int 0)] 5)]
""
"*
{
- if (!current_function_calls_alloca)
- return \"\";
- if (TARGET_V9)
- return \"flushw\";
- return \"ta\\t3\";
+ if (! current_function_calls_alloca || ! TARGET_V9 || TARGET_FLAT)
+ return \"#\";
+ fputs (\"\tflushw\n\", asm_out_file);
+ if (flag_pic)
+ fprintf (asm_out_file, \"\tst%c\t%%l7, [%%sp+%d]\n\",
+ TARGET_ARCH64 ? 'x' : 'w',
+ SPARC_STACK_BIAS + 7 * UNITS_PER_WORD);
+ fprintf (asm_out_file, \"\tst%c\t%%fp, [%%sp+%d]\n\",
+ TARGET_ARCH64 ? 'x' : 'w',
+ SPARC_STACK_BIAS + 14 * UNITS_PER_WORD);
+ fprintf (asm_out_file, \"\tst%c\t%%i7, [%%sp+%d]\n\",
+ TARGET_ARCH64 ? 'x' : 'w',
+ SPARC_STACK_BIAS + 15 * UNITS_PER_WORD);
+ return \"\";
}"
- [(set_attr "type" "misc")])
+ [(set_attr "type" "misc")
+ (set (attr "length") (if_then_else (eq_attr "pic" "true")
+ (const_int 4)
+ (const_int 3)))])
+
+(define_split
+ [(unspec_volatile [(const_int 0)] 5)]
+ "! current_function_calls_alloca || ! TARGET_V9 || TARGET_FLAT"
+ [(const_int 0)]
+ "
+{
+ if (current_function_calls_alloca)
+ emit_insn (gen_flush_register_windows ());
+ DONE;
+}")
;; Pattern for use after a setjmp to store FP and the return register
;; into the stack area.
@@ -8998,7 +8725,7 @@
(set (match_operand:SI 2 "register_operand" "")
(match_operand:SI 3 "memory_operand" ""))]
"registers_ok_for_ldd_peep (operands[2], operands[0])
- && mems_ok_for_ldd_peep (operands[3], operands[1], operands[2])"
+ && mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
[(set (match_dup 2)
(match_dup 3))]
"operands[3] = change_address (operands[3], DImode, NULL);
@@ -9023,7 +8750,7 @@
(set (match_operand:SF 2 "register_operand" "")
(match_operand:SF 3 "memory_operand" ""))]
"registers_ok_for_ldd_peep (operands[2], operands[0])
- && mems_ok_for_ldd_peep (operands[3], operands[1], operands[2])"
+ && mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
[(set (match_dup 2)
(match_dup 3))]
"operands[3] = change_address (operands[3], DFmode, NULL);
@@ -9073,17 +8800,17 @@
&& ! SPARC_FP_REG_P (REGNO (operands[1]))"
[(parallel [(set (match_dup 0) (match_dup 1))
(set (reg:CCX 100)
- (compare:CC (match_dup 1) (const_int 0)))])]
+ (compare:CCX (match_dup 1) (const_int 0)))])]
"")
-;; Return peepholes. First the "normal" ones.
-;; These are necessary to catch insns ending up in the epilogue delay list.
+;; Return peepholes. These are generated by sparc_nonflat_function_epilogue
+;; who then immediately calls final_scan_insn.
(define_insn "*return_qi"
[(set (match_operand:QI 0 "restore_operand" "")
(match_operand:QI 1 "arith_operand" "rI"))
(return)]
- "! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -9101,7 +8828,7 @@
[(set (match_operand:HI 0 "restore_operand" "")
(match_operand:HI 1 "arith_operand" "rI"))
(return)]
- "! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -9119,7 +8846,7 @@
[(set (match_operand:SI 0 "restore_operand" "")
(match_operand:SI 1 "arith_operand" "rI"))
(return)]
- "! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -9133,15 +8860,11 @@
[(set_attr "type" "multi")
(set_attr "length" "2")])
-;; The following pattern is only generated by delayed-branch scheduling,
-;; when the insn winds up in the epilogue. This can happen not only when
-;; ! TARGET_FPU because we move complex types around by parts using
-;; SF mode SUBREGs.
(define_insn "*return_sf_no_fpu"
[(set (match_operand:SF 0 "restore_operand" "=r")
(match_operand:SF 1 "register_operand" "r"))
(return)]
- "! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -9158,7 +8881,7 @@
[(set (match_operand:DF 0 "restore_operand" "=r")
(match_operand:DF 1 "register_operand" "r"))
(return)]
- "! TARGET_EPILOGUE && TARGET_ARCH64"
+ "sparc_emitting_epilogue && TARGET_ARCH64"
"*
{
if (IN_OR_GLOBAL_P (operands[1]))
@@ -9174,7 +8897,7 @@
(plus:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))
(return)]
- "! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -9195,7 +8918,7 @@
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "immediate_operand" "in")))
(return)]
- "! TARGET_EPILOGUE && ! TARGET_CM_MEDMID"
+ "sparc_emitting_epilogue && ! TARGET_CM_MEDMID"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -9213,7 +8936,7 @@
[(set (match_operand:DI 0 "restore_operand" "")
(match_operand:DI 1 "arith_double_operand" "rHI"))
(return)]
- "TARGET_ARCH64 && ! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue && TARGET_ARCH64"
"ret\;restore %%g0, %1, %Y0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -9223,7 +8946,7 @@
(plus:DI (match_operand:DI 1 "arith_operand" "%r")
(match_operand:DI 2 "arith_double_operand" "rHI")))
(return)]
- "TARGET_ARCH64 && ! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue && TARGET_ARCH64"
"ret\;restore %r1, %2, %Y0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -9233,23 +8956,24 @@
(lo_sum:DI (match_operand:DI 1 "arith_operand" "%r")
(match_operand:DI 2 "immediate_operand" "in")))
(return)]
- "TARGET_ARCH64 && ! TARGET_EPILOGUE && ! TARGET_CM_MEDMID"
+ "sparc_emitting_epilogue && TARGET_ARCH64 && ! TARGET_CM_MEDMID"
"ret\;restore %r1, %%lo(%a2), %Y0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
-;; The following pattern is only generated by delayed-branch scheduling,
-;; when the insn winds up in the epilogue.
(define_insn "*return_sf"
[(set (reg:SF 32)
(match_operand:SF 0 "register_operand" "f"))
(return)]
- "! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue"
"ret\;fmovs\\t%0, %%f0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
;; Now peepholes to do a call followed by a jump.
+;; Do not match this on V9 and later processors, which have a call-return
+;; stack as this corrupts it and causes the code to run slower not faster.
+;; There are not TARGET_ARCH64 patterns because that implies TARGET_V9.
(define_peephole
[(parallel [(set (match_operand 0 "" "")
@@ -9257,7 +8981,8 @@
(match_operand 2 "" "")))
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 3 "" "")))]
- "short_branch (INSN_UID (insn), INSN_UID (operands[3]))
+ "! TARGET_V9
+ && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
&& (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
"call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
@@ -9266,49 +8991,70 @@
(match_operand 1 "" ""))
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 2 "" "")))]
- "short_branch (INSN_UID (insn), INSN_UID (operands[2]))
- && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
- "call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
-
-(define_peephole
- [(parallel [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:DI 1 "call_operand_address" "ps"))
- (match_operand 2 "" "")))
- (clobber (reg:DI 15))])
- (set (pc) (label_ref (match_operand 3 "" "")))]
- "TARGET_ARCH64
- && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
- && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
- "call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
-
-(define_peephole
- [(parallel [(call (mem:SI (match_operand:DI 0 "call_operand_address" "ps"))
- (match_operand 1 "" ""))
- (clobber (reg:DI 15))])
- (set (pc) (label_ref (match_operand 2 "" "")))]
- "TARGET_ARCH64
+ "! TARGET_V9
&& short_branch (INSN_UID (insn), INSN_UID (operands[2]))
&& (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
"call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
-(define_insn "prefetch"
+;; ??? UltraSPARC-III note: A memory operation loading into the floating point register
+;; ??? file, if it hits the prefetch cache, has a chance to dual-issue with other memory
+;; ??? operations. With DFA we might be able to model this, but it requires a lot of
+;; ??? state.
+(define_expand "prefetch"
+ [(match_operand 0 "address_operand" "")
+ (match_operand 1 "const_int_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_V9"
+ "
+{
+ if (TARGET_ARCH64)
+ emit_insn (gen_prefetch_64 (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_prefetch_32 (operands[0], operands[1], operands[2]));
+ DONE;
+}")
+
+(define_insn "prefetch_64"
[(prefetch (match_operand:DI 0 "address_operand" "p")
(match_operand:DI 1 "const_int_operand" "n")
(match_operand:DI 2 "const_int_operand" "n"))]
- "TARGET_V9"
+ ""
+{
+ static const char * const prefetch_instr[2][2] = {
+ {
+ "prefetch\\t[%a0], 1", /* no locality: prefetch for one read */
+ "prefetch\\t[%a0], 0", /* medium to high locality: prefetch for several reads */
+ },
+ {
+ "prefetch\\t[%a0], 3", /* no locality: prefetch for one write */
+ "prefetch\\t[%a0], 2", /* medium to high locality: prefetch for several writes */
+ }
+ };
+ int read_or_write = INTVAL (operands[1]);
+ int locality = INTVAL (operands[2]);
+
+ if (read_or_write != 0 && read_or_write != 1)
+ abort ();
+ if (locality < 0 || locality > 3)
+ abort ();
+ return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
+}
+ [(set_attr "type" "load")])
+
+(define_insn "prefetch_32"
+ [(prefetch (match_operand:SI 0 "address_operand" "p")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "const_int_operand" "n"))]
+ ""
{
- static const char * const prefetch_instr[2][4] = {
+ static const char * const prefetch_instr[2][2] = {
{
"prefetch\\t[%a0], 1", /* no locality: prefetch for one read */
- "prefetch\\t[%a0], 0", /* medium locality: prefetch for several reads */
- "prefetch\\t[%a0], 0", /* medium locality: prefetch for several reads */
- "prefetch\\t[%a0], 4", /* high locality: prefetch page */
+ "prefetch\\t[%a0], 0", /* medium to high locality: prefetch for several reads */
},
{
"prefetch\\t[%a0], 3", /* no locality: prefetch for one write */
- "prefetch\\t[%a0], 2", /* medium locality: prefetch for several writes */
- "prefetch\\t[%a0], 2", /* medium locality: prefetch for several writes */
- "prefetch\\t[%a0], 4", /* high locality: prefetch page */
+ "prefetch\\t[%a0], 2", /* medium to high locality: prefetch for several writes */
}
};
int read_or_write = INTVAL (operands[1]);
@@ -9318,7 +9064,7 @@
abort ();
if (locality < 0 || locality > 3)
abort ();
- return prefetch_instr [read_or_write][locality];
+ return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
}
[(set_attr "type" "load")])
OpenPOWER on IntegriCloud