diff options
Diffstat (limited to 'contrib/gcc/config/sparc/sparc.md')
-rw-r--r-- | contrib/gcc/config/sparc/sparc.md | 912 |
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")]) |