Mercurial > hg > CbC > CbC_gcc
diff gcc/config/arc/arc.md @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/gcc/config/arc/arc.md Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/config/arc/arc.md Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ ;; Machine description of the Synopsys DesignWare ARC cpu for GNU C compiler -;; Copyright (C) 1994-2018 Free Software Foundation, Inc. +;; Copyright (C) 1994-2020 Free Software Foundation, Inc. ;; Sources derived from work done by Sankhya Technologies (www.sankhya.com) on ;; behalf of Synopsys Inc. @@ -136,7 +136,6 @@ UNSPEC_ARC_VMAC2HU UNSPEC_ARC_VMPY2H UNSPEC_ARC_VMPY2HU - UNSPEC_ARC_STKTIE VUNSPEC_ARC_RTIE VUNSPEC_ARC_SYNC @@ -163,6 +162,11 @@ VUNSPEC_ARC_SC VUNSPEC_ARC_LL VUNSPEC_ARC_BLOCKAGE + VUNSPEC_ARC_EH_RETURN + VUNSPEC_ARC_ARC600_RTIE + VUNSPEC_ARC_ARC600_STALL + VUNSPEC_ARC_LDDI + VUNSPEC_ARC_STDI ]) (define_constants @@ -170,20 +174,57 @@ (R1_REG 1) (R2_REG 2) (R3_REG 3) + (R4_REG 4) + + (R9_REG 9) (R10_REG 10) + (R12_REG 12) + + (R15_REG 15) + (R16_REG 16) + + (R25_REG 25) (SP_REG 28) - (ILINK1_REGNUM 29) - (ILINK2_REGNUM 30) + (ILINK1_REG 29) + (ILINK2_REG 30) + (R30_REG 30) (RETURN_ADDR_REGNUM 31) + (R32_REG 32) + (R33_REG 33) + (R34_REG 34) + (R35_REG 35) + (R36_REG 36) + (R37_REG 37) + (R38_REG 38) + (R39_REG 39) + (R40_REG 40) + (R41_REG 41) + (R42_REG 42) + (R43_REG 43) + (R44_REG 44) + (R45_REG 45) + (R46_REG 46) + (R47_REG 47) + (R48_REG 48) + (R49_REG 49) + (R50_REG 50) + (R51_REG 51) + (R52_REG 52) + (R53_REG 53) + (R54_REG 54) + (R55_REG 55) + (R56_REG 56) + (R57_REG 57) + (R58_REG 58) + (R59_REG 59) + (MUL64_OUT_REG 58) (MUL32x16_REG 56) (ARCV2_ACC 58) - (LP_COUNT 60) (CC_REG 61) - (LP_START 144) - (LP_END 145) + (PCL_REG 63) ] ) @@ -197,7 +238,7 @@ (define_attr "type" "move,load,store,cmove,unary,binary,compare,shift,uncond_branch,jump,branch, - brcc,brcc_no_delay_slot,call,sfunc,call_no_delay_slot, + brcc,brcc_no_delay_slot,call,sfunc,call_no_delay_slot,rtie, multi,umulti, two_cycle_core,lr,sr,divaw,loop_setup,loop_end,return, misc,spfp,dpfp_mult,dpfp_addsub,mulmac_600,cc_arith, simd_vload, simd_vload128, simd_vstore, simd_vmove, simd_vmove_else_zero, @@ -514,9 +555,7 @@ (cond [(eq_attr "in_delay_slot" "false") (const_string "no") (match_test "regno_clobbered_p - (arc_return_address_register - (arc_compute_function_type (cfun)), - insn, SImode, 1)") + (RETURN_ADDR_REGNUM, insn, SImode, 1)") (const_string "no")] (const_string "yes"))) @@ -600,11 +639,13 @@ ;; somehow modify them to become inelegible for delay slots if a decision ;; is made that makes conditional execution required. -(define_attr "tune" "none,arc600,arc700_4_2_std,arc700_4_2_xmac, core_3, \ -archs4x, archs4xd, archs4xd_slow" +(define_attr "tune" "none,arc600,arc7xx,arc700_4_2_std,arc700_4_2_xmac, \ +core_3, archs4x, archs4xd, archs4xd_slow" (const (cond [(symbol_ref "arc_tune == TUNE_ARC600") (const_string "arc600") + (symbol_ref "arc_tune == ARC_TUNE_ARC7XX") + (const_string "arc7xx") (symbol_ref "arc_tune == TUNE_ARC700_4_2_STD") (const_string "arc700_4_2_std") (symbol_ref "arc_tune == TUNE_ARC700_4_2_XMAC") @@ -619,7 +660,7 @@ (const_string "none")))) (define_attr "tune_arc700" "false,true" - (if_then_else (eq_attr "tune" "arc700_4_2_std, arc700_4_2_xmac") + (if_then_else (eq_attr "tune" "arc7xx, arc700_4_2_std, arc700_4_2_xmac") (const_string "true") (const_string "false"))) @@ -649,10 +690,12 @@ ; The iscompact attribute allows the epilogue expander to know for which ; insns it should lengthen the return insn. (define_insn "*movqi_insn" - [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h,w*l,w*l,???w,h,w*l,Rcq, S,!*x, r,r, Ucm,m,???m, m,Usc") - (match_operand:QI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1, cL, I,?Rac,i, ?i, T,Rcq,Usd,Ucm,m,?Rac,c,?Rac,Cm3,i"))] + [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h, w, w,???w,h, w,Rcq, S,!*x, r,r, Ucm,m,???m, m,Usc") + (match_operand:QI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1,cL, I,?Rac,i,?i, T,Rcq,Usd,Ucm,m,?Rac,c,?Rac,Cm3,i"))] "register_operand (operands[0], QImode) - || register_operand (operands[1], QImode)" + || register_operand (operands[1], QImode) + || (satisfies_constraint_Cm3 (operands[1]) + && memory_operand (operands[0], QImode))" "@ mov%? %0,%1%& mov%? %0,%1%& @@ -686,15 +729,17 @@ "if (prepare_move_operands (operands, HImode)) DONE;") (define_insn "*movhi_insn" - [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h,w*l,w*l,???w,Rcq#q,h,w*l,Rcq, S, r,r, Ucm,m,???m, m,VUsc") - (match_operand:HI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1, cL, I,?Rac, i,i, ?i, T,Rcq,Ucm,m,?Rac,c,?Rac,Cm3,i"))] + [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h, w, w,???w,Rcq#q,h, w,Rcq, S, r,r, Ucm,m,???m, m,VUsc") + (match_operand:HI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1,cL, I,?Rac, i,i,?i, T,Rcq,Ucm,m,?Rac,c,?Rac,Cm3,i"))] "register_operand (operands[0], HImode) || register_operand (operands[1], HImode) || (CONSTANT_P (operands[1]) /* Don't use a LIMM that we could load with a single insn - we loose delay-slot filling opportunities. */ && !satisfies_constraint_I (operands[1]) - && satisfies_constraint_Usc (operands[0]))" + && satisfies_constraint_Usc (operands[0])) + || (satisfies_constraint_Cm3 (operands[1]) + && memory_operand (operands[0], HImode))" "@ mov%? %0,%1%& mov%? %0,%1%& @@ -730,66 +775,66 @@ ; In order to allow the ccfsm machinery to do its work, the leading compact ; alternatives say 'canuse' - there is another alternative that will match ; when the condition codes are used. -; Rcq won't match if the condition is actually used; to avoid a spurious match -; via q, q is inactivated as constraint there. -; Likewise, the length of an alternative that might be shifted to conditional +; The length of an alternative that might be shifted to conditional ; execution must reflect this, lest out-of-range branches are created. ; the iscompact attribute allows the epilogue expander to know for which ; insns it should lengthen the return insn. -; N.B. operand 1 of alternative 7 expands into pcl,symbol@gotpc . -(define_insn "*movsi_insn" ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 - [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h,w*l,w*l, w, w, w, w, ???w, ?w, w,Rcq#q, h, w*l,Rcq, S, Us<,RcqRck,!*x, r,!*Rsd,!*Rcd,r,Ucm, Usd,m,???m, m,VUsc") - (match_operand:SI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1, cL, I,Crr,Clo,Chi,Cbi,?Rac*l,Cpc,Clb, ?Cal,Cal,?Cal,Uts,Rcq,RcqRck, Us>,Usd,Ucm, Usd, Ucd,m, w,!*Rzd,c,?Rac,Cm3, C32"))] +(define_insn_and_split "*movsi_insn" ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 + [(set (match_operand:SI 0 "move_dest_operand" "=q, q,r,q, h, rl,r, r, r, r, ?r, r, q, h, rl, q, S, Us<,RcqRck,!*x, r,!*Rsd,!*Rcd,r,Ucm, Usd,m, m,VUsc") + (match_operand:SI 1 "move_src_operand" "rL,rP,q,P,hCm1,rLl,I,Clo,Chi,Cbi,Cpc,Clb,Cax,Cal,Cal,Uts,Rcq,RcqRck, Us>,Usd,Ucm, Usd, Ucd,m, r,!*Rzd,r,Cm3, C32"))] "register_operand (operands[0], SImode) || register_operand (operands[1], SImode) || (CONSTANT_P (operands[1]) - /* Don't use a LIMM that we could load with a single insn - we loose - delay-slot filling opportunities. */ - && !satisfies_constraint_I (operands[1]) + && (!satisfies_constraint_I (operands[1]) || !optimize_size) && satisfies_constraint_Usc (operands[0])) || (satisfies_constraint_Cm3 (operands[1]) && memory_operand (operands[0], SImode))" "@ - mov%? %0,%1%& ;0 - mov%? %0,%1%& ;1 - mov%? %0,%1%& ;2 - mov%? %0,%1%& ;3 - mov%? %0,%1%& ;4 - mov%? %0,%1 ;5 - mov%? %0,%1 ;6 - ror %0,((%1*2+1) & 0x3f) ;7 - movl.cl %0,%1 ;8 - movh.cl %0,%L1>>16 ;9 - * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;10\" : \"movbi.cl %0,%L1 >> 24,24,8;10\"; - mov%? %0,%1 ;11 - add %0,%1 ;12 - add %0,pcl,%1@pcl ;13 - mov%? %0,%j1 ;14 - mov%? %0,%j1 ;15 - mov%? %0,%j1 ;16 - ld%? %0,%1 ;17 - st%? %1,%0%& ;18 - * return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\"); - * return arc_short_long (insn, \"pop%? %0%&\", \"ld%U1 %0,%1%&\"); - ld%? %0,%1%& ;21 - xld%U1 %0,%1 ;22 - ld%? %0,%1%& ;23 - ld%? %0,%1%& ;24 - ld%U1%V1 %0,%1 ;25 - xst%U0 %1,%0 ;26 - st%? %1,%0%& ;27 - st%U0%V0 %1,%0 ;28 - st%U0%V0 %1,%0 ;29 - st%U0%V0 %1,%0 ;30 - st%U0%V0 %1,%0 ;31" - ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 - [(set_attr "type" "move, move, move,move,move, move, move,two_cycle_core,shift,shift,shift, move,binary,binary, move, move, move,load,store,store,load,load, load,load,load, load,store,store,store,store,store,store") - (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false, false,false,false,false,false, false, false,maybe_limm,maybe_limm,false,true, true, true,true,true,false,true,true,false,false, true,false,false,false,false") - ; Use default length for iscompact to allow for COND_EXEC. But set length - ; of Crr to 4. - (set_attr "length" "*,*,*,*,*,4,4,4,4,4,4,4,8,8,*,*,*,*,*,*,*,*,4,*,4,*,*,*,*,*,*,8") - (set_attr "predicable" "yes,no,yes,no,no,yes,no,no,no,no,no,yes,no,no,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no") - (set_attr "cpu_facility" "av1,av1,av1,av2,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,*,av2,*")]) + mov%?\\t%0,%1 ;0 + mov%?\\t%0,%1 ;1 + mov%?\\t%0,%1 ;2 + mov%?\\t%0,%1 ;3 + mov%?\\t%0,%1 ;4 + mov%?\\t%0,%1 ;5 + mov%?\\t%0,%1 ;6 + movl.cl\\t%0,%1 ;7 + movh.cl\\t%0,%L1>>16 ;8 + * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl\\t%0,%1 >> %p1,%p1,8;9\" : \"movbi.cl\\t%0,%L1 >> 24,24,8;9\"; + add\\t%0,%1 ;10 + add\\t%0,pcl,%1@pcl ;11 + # + mov%?\\t%0,%j1 ;13 + mov%?\\t%0,%j1 ;14 + ld%?\\t%0,%1 ;15 + st%?\\t%1,%0 ;16 + * return arc_short_long (insn, \"push%?\\t%1%&\", \"st%U0\\t%1,%0%&\"); + * return arc_short_long (insn, \"pop%?\\t%0%&\", \"ld%U1\\t%0,%1%&\"); + ld%?\\t%0,%1 ;19 + xld%U1\\t%0,%1 ;20 + ld%?\\t%0,%1 ;21 + ld%?\\t%0,%1 ;22 + ld%U1%V1\\t%0,%1 ;23 + xst%U0\\t%1,%0 ;24 + st%?\\t%1,%0%& ;25 + st%U0%V0\\t%1,%0 ;26 + st%U0%V0\\t%1,%0 ;37 + st%U0%V0\\t%1,%0 ;28" + "reload_completed + && GET_CODE (PATTERN (insn)) != COND_EXEC + && register_operand (operands[0], SImode) + && IN_RANGE (REGNO (operands[0]) ^ 4, 4, 11) + && satisfies_constraint_Cax (operands[1])" + [(const_int 0)] + " + arc_split_mov_const (operands); + DONE; + " + ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 + [(set_attr "type" "move, move, move,move,move, move, move,shift,shift,shift,binary,binary,multi,move, move,load,store,store,load,load, load,load,load, load,store,store,store,store,store") + (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false,false,false,false, false, false,false,true,false,true, true, true,true,true,false,true,true,false,false, true,false,false,false") + (set_attr "length" "*,*,*,*,*,4,4,4,4,4,8,8,*,6,*,*,*,*,*,*,4,*,4,*,*,*,*,*,8") + (set_attr "predicable" "yes,no,yes,no,no,yes,no,no,no,yes,no,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no,no,no") + (set_attr "cpu_facility" "av1,av1,av1,av2,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,av2,*")]) ;; Sometimes generated by the epilogue code. We don't want to ;; recognize these addresses in general, because the limm is costly, @@ -938,10 +983,10 @@ (match_operand 0 "cc_register" "") (match_operator 4 "zn_compare_operator" [(and:SI - (match_operand:SI 1 "register_operand" "%Rcq,Rcq, c, c, c, c,Rrq, 3, c") + (match_operand:SI 1 "register_operand" "%Rcq,Rcq, c, c, c, c,Rrq,Rrq, c") (match_operand:SI 2 "nonmemory_operand" "Rcq,C0p,cI,C1p,Ccp,Chs,Cbf,Cbf,???Cal")) (const_int 0)])) - (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,Rrq,Rrq,c"))] + (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,Rrq,1,c"))] "TARGET_NPS_BITOPS" "movb.f.cl %3,%1,%p2,%p2,%s2" "TARGET_NPS_BITOPS && reload_completed @@ -1221,7 +1266,7 @@ "") (define_insn "*bic_f" - [(set (match_operand 3 "cc_register" "=Rcc,Rcc,Rcc") + [(set (match_operand 3 "cc_set_register" "") (match_operator 4 "zn_compare_operator" [(and:SI (match_operand:SI 1 "register_operand" "c,0,c") (not:SI @@ -1235,6 +1280,34 @@ (set_attr "cond" "set_zn,set_zn,set_zn") (set_attr "length" "4,4,8")]) +(define_insn "*bic_cmp0_noout" + [(set (match_operand 0 "cc_set_register" "") + (compare:CC_ZN + (and:SI (not:SI (match_operand:SI 1 "nonmemory_operand" "Lr,Cal,r")) + (match_operand:SI 2 "nonmemory_operand" "r,r,Cal")) + (const_int 0)))] + "register_operand (operands[1], SImode) + || register_operand (operands[2], SImode)" + "bic.f\\t0,%2,%1" + [(set_attr "type" "unary") + (set_attr "cond" "set_zn") + (set_attr "length" "4,8,8")]) + +(define_insn "*bic_cmp0" + [(set (match_operand 0 "cc_set_register" "") + (compare:CC_ZN + (and:SI (not:SI (match_operand:SI 1 "nonmemory_operand" "Lr,Cal,r")) + (match_operand:SI 2 "nonmemory_operand" "r,r,Cal")) + (const_int 0))) + (set (match_operand:SI 3 "register_operand" "=r,r,r") + (and:SI (not:SI (match_dup 1)) (match_dup 2)))] + "register_operand (operands[1], SImode) + || register_operand (operands[2], SImode)" + "bic.f\\t%3,%2,%1" + [(set_attr "type" "unary") + (set_attr "cond" "set_zn") + (set_attr "length" "4,8,8")]) + (define_expand "movdi" [(set (match_operand:DI 0 "move_dest_operand" "") (match_operand:DI 1 "general_operand" ""))] @@ -1762,18 +1835,22 @@ [(set_attr "type" "cmove,cmove") (set_attr "length" "8,16")]) +;; ------------------------------------------------------------------- +;; Sign/Zero extension +;; ------------------------------------------------------------------- (define_insn "*zero_extendqihi2_i" - [(set (match_operand:HI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,r,r") - (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,Ucm,m")))] + [(set (match_operand:HI 0 "dest_reg_operand" "=q,q,r,r,r,r") + (zero_extend:HI + (match_operand:QI 1 "nonvol_nonimm_operand" "0,q,0,r,Ucm,m")))] "" "@ - extb%? %0,%1%& - extb%? %0,%1%& - bmsk%? %0,%1,7 - extb %0,%1 - xldb%U1 %0,%1 - ldb%U1 %0,%1" + extb%?\\t%0,%1 + extb%?\\t%0,%1 + bmsk%?\\t%0,%1,7 + extb\\t%0,%1 + xldb%U1\\t%0,%1 + ldb%U1\\t%0,%1" [(set_attr "type" "unary,unary,unary,unary,load,load") (set_attr "iscompact" "maybe,true,false,false,false,false") (set_attr "predicable" "no,no,yes,no,no,no")]) @@ -1786,18 +1863,19 @@ ) (define_insn "*zero_extendqisi2_ac" - [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,qRcq,!*x,r,r") - (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,T,Usd,Ucm,m")))] + [(set (match_operand:SI 0 "dest_reg_operand" "=q,q,r,r,q,!*x,r,r") + (zero_extend:SI + (match_operand:QI 1 "nonvol_nonimm_operand" "0,q,0,r,T,Usd,Ucm,m")))] "" "@ - extb%? %0,%1%& - extb%? %0,%1%& - bmsk%? %0,%1,7 - extb %0,%1 - ldb%? %0,%1%& - ldb%? %0,%1%& - xldb%U1 %0,%1 - ldb%U1 %0,%1" + extb%?\\t%0,%1 + extb%?\\t%0,%1 + bmsk%?\\t%0,%1,7 + extb\\t%0,%1 + ldb%?\\t%0,%1 + ldb%?\\t%0,%1 + xldb%U1\\t%0,%1 + ldb%U1\\t%0,%1" [(set_attr "type" "unary,unary,unary,unary,load,load,load,load") (set_attr "iscompact" "maybe,true,false,false,true,true,false,false") (set_attr "predicable" "no,no,yes,no,no,no,no,no")]) @@ -1810,23 +1888,23 @@ ) (define_insn "*zero_extendhisi2_i" - [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,q,Rcw,w,!x,Rcqq,r,r") - (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "0,q,0,c,Usd,T,Ucm,m")))] + [(set (match_operand:SI 0 "dest_reg_operand" "=q,q,r,r,!x,q,r,r") + (zero_extend:SI + (match_operand:HI 1 "nonvol_nonimm_operand" "0,q,0,r,Usd,T,Ucm,m")))] "" "@ - ext%_%? %0,%1%& - ext%_%? %0,%1%& - bmsk%? %0,%1,15 - ext%_ %0,%1 - ld%_%? %0,%1 - ld%_%? %0,%1 - * return TARGET_EM ? \"xldh%U1%V1 %0,%1\" : \"xldw%U1 %0,%1\"; - ld%_%U1%V1 %0,%1" + ext%_%?\\t%0,%1 + ext%_%?\\t%0,%1 + bmsk%?\\t%0,%1,15 + ext%_\\t%0,%1 + ld%_%?\\t%0,%1 + ld%_%?\\t%0,%1 + xldw%U1\\t%0,%1 + ld%_%U1%V1\\t%0,%1" [(set_attr "type" "unary,unary,unary,unary,load,load,load,load") (set_attr "iscompact" "maybe,true,false,false,true,true,false,false") (set_attr "predicable" "no,no,yes,no,no,no,no,no")]) - (define_expand "zero_extendhisi2" [(set (match_operand:SI 0 "dest_reg_operand" "") (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "")))] @@ -1837,19 +1915,19 @@ ;; Sign extension instructions. (define_insn "*extendqihi2_i" - [(set (match_operand:HI 0 "dest_reg_operand" "=Rcqq,r,r,r") - (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,r,Uex,m")))] + [(set (match_operand:HI 0 "dest_reg_operand" "=q,r,r,r") + (sign_extend:HI + (match_operand:QI 1 "nonvol_nonimm_operand" "q,r,Uex,m")))] "" "@ - sexb%? %0,%1%& - sexb %0,%1 - ldb.x%U1 %0,%1 - ldb.x%U1 %0,%1" + sexb%?\\t%0,%1 + sexb\\t%0,%1 + ldb.x%U1\\t%0,%1 + ldb.x%U1\\t%0,%1" [(set_attr "type" "unary,unary,load,load") (set_attr "iscompact" "true,false,false,false") (set_attr "length" "*,*,*,8")]) - (define_expand "extendqihi2" [(set (match_operand:HI 0 "dest_reg_operand" "") (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "")))] @@ -1858,14 +1936,15 @@ ) (define_insn "*extendqisi2_ac" - [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r,r") - (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,c,Uex,m")))] + [(set (match_operand:SI 0 "dest_reg_operand" "=q,r,r,r") + (sign_extend:SI + (match_operand:QI 1 "nonvol_nonimm_operand" "q,r,Uex,m")))] "" "@ - sexb%? %0,%1%& - sexb %0,%1 - ldb.x%U1 %0,%1 - ldb.x%U1 %0,%1" + sexb%?\\t%0,%1 + sexb\\t%0,%1 + ldb.x%U1\\t%0,%1 + ldb.x%U1\\t%0,%1" [(set_attr "type" "unary,unary,load,load") (set_attr "iscompact" "true,false,false,false") (set_attr "length" "*,*,*,8")]) @@ -1878,15 +1957,16 @@ ) (define_insn "*extendhisi2_i" - [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,Rcqq,r,r") - (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "Rcqq,c,Ucd,Uex,m")))] + [(set (match_operand:SI 0 "dest_reg_operand" "=q,r,q,r,r") + (sign_extend:SI + (match_operand:HI 1 "nonvol_nonimm_operand" "q,r,Ucd,Uex,m")))] "" "@ - sex%_%? %0,%1%& - sex%_ %0,%1 - ldh%?.x %0,%1%& - ld%_.x%U1%V1 %0,%1 - ld%_.x%U1%V1 %0,%1" + sex%_%?\\t%0,%1 + sex%_\\t%0,%1 + ldh%?.x\\t%0,%1%& + ld%_.x%U1%V1\\t%0,%1 + ld%_.x%U1%V1\\t%0,%1" [(set_attr "type" "unary,unary,load,load,load") (set_attr "iscompact" "true,false,true,false,false") (set_attr "length" "*,*,*,4,8")]) @@ -2076,44 +2156,21 @@ ;; SI <- SI * SI (define_expand "mulsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") + [(set (match_operand:SI 0 "register_operand" "") (mult:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "nonmemory_operand" "")))] - "" + "TARGET_ANY_MPY" { - if (TARGET_MPY) + if (TARGET_MUL64_SET) { - if (!register_operand (operands[0], SImode)) - { - rtx result = gen_reg_rtx (SImode); - - emit_insn (gen_mulsi3 (result, operands[1], operands[2])); - emit_move_insn (operands[0], result); - DONE; - } - } - else if (TARGET_MUL64_SET) - { - rtx tmp = gen_reg_rtx (SImode); - emit_insn (gen_mulsi64 (tmp, operands[1], operands[2])); - emit_move_insn (operands[0], tmp); + emit_insn (gen_mulsi64 (operands[0], operands[1], operands[2])); DONE; } else if (TARGET_MULMAC_32BY16_SET) { - rtx tmp = gen_reg_rtx (SImode); - emit_insn (gen_mulsi32x16 (tmp, operands[1], operands[2])); - emit_move_insn (operands[0], tmp); + emit_insn (gen_mulsi32x16 (operands[0], operands[1], operands[2])); DONE; } - else - { - emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]); - emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]); - emit_insn (gen_mulsi3_600_lib ()); - emit_move_insn (operands[0], gen_rtx_REG (SImode, R0_REG)); - DONE; - } }) (define_insn_and_split "mulsi32x16" @@ -2182,6 +2239,9 @@ (set_attr "predicable" "no, no, yes") (set_attr "cond" "nocond, canuse_limm, canuse")]) +; The gcc-internal representation may differ from the hardware +; register number in order to allow the generic code to correctly +; split the concatenation of mhi and mlo. (define_insn_and_split "mulsi64" [(set (match_operand:SI 0 "register_operand" "=w") (mult:SI (match_operand:SI 1 "register_operand" "%c") @@ -2191,12 +2251,13 @@ "#" "TARGET_MUL64_SET && reload_completed" [(const_int 0)] -{ - emit_insn (gen_mulsi_600 (operands[1], operands[2], - gen_mlo (), gen_mhi ())); - emit_move_insn (operands[0], gen_mlo ()); - DONE; -} + { + rtx mhi = gen_rtx_REG (SImode, R59_REG); + rtx mlo = gen_rtx_REG (SImode, R58_REG); + emit_insn (gen_mulsi_600 (operands[1], operands[2], mlo, mhi)); + emit_move_insn (operands[0], mlo); + DONE; + } [(set_attr "type" "multi") (set_attr "length" "8")]) @@ -2206,50 +2267,13 @@ (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,I,Cal"))) (clobber (match_operand:SI 3 "mhi_operand" ""))] "TARGET_MUL64_SET" -; The assembler mis-assembles mul64 / mulu64 with "I" constraint constants, -; using a machine code pattern that only allows "L" constraint constants. -; "mul64%? \t0, %0, %1%&" -{ - if (satisfies_constraint_I (operands[1]) - && !satisfies_constraint_L (operands[1])) - { - /* MUL64 <0,>b,s12 00101bbb10000100 0BBBssssssSSSSSS */ - int n = true_regnum (operands[0]); - int i = INTVAL (operands[1]); - asm_fprintf (asm_out_file, "\t.short %d`", 0x2884 + ((n & 7) << 8)); - asm_fprintf (asm_out_file, "\t.short %d`", - ((i & 0x3f) << 6) + ((i >> 6) & 0x3f) + ((n & 070) << 9)); - return "; mul64%? \t0, %0, %1%&"; - } - return "mul64%? \t0, %0, %1%&"; -} + "mul64%?\\t0,%0,%1" [(set_attr "length" "*,4,4,8") (set_attr "iscompact" "maybe,false,false,false") (set_attr "type" "multi,multi,multi,multi") (set_attr "predicable" "yes,yes,no,yes") (set_attr "cond" "canuse,canuse,canuse_limm,canuse")]) -; If we compile without an mul option enabled, but link with libraries -; for a mul option, we'll see clobbers of multiplier output registers. -; There is also an implementation using norm that clobbers the loop registers. -(define_insn "mulsi3_600_lib" - [(set (reg:SI R0_REG) - (mult:SI (reg:SI R0_REG) (reg:SI R1_REG))) - (clobber (reg:SI RETURN_ADDR_REGNUM)) - (clobber (reg:SI R1_REG)) - (clobber (reg:SI R2_REG)) - (clobber (reg:SI R3_REG)) - (clobber (reg:DI MUL64_OUT_REG)) - (clobber (reg:SI LP_COUNT)) - (clobber (reg:SI LP_START)) - (clobber (reg:SI LP_END)) - (clobber (reg:CC CC_REG))] - "!TARGET_ANY_MPY - && SFUNC_CHECK_PREDICABLE" - "*return arc_output_libcall (\"__mulsi3\");" - [(set_attr "is_sfunc" "yes") - (set_attr "predicable" "yes")]) - (define_insn_and_split "mulsidi_600" [(set (match_operand:DI 0 "register_operand" "=c, c,c, c") (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%Rcq#q, c,c, c")) @@ -2328,16 +2352,23 @@ ; ARCv2 has no penalties between mpy and mpyu. So, we use mpy because of its ; short variant. LP_COUNT constraints are still valid. (define_insn "mulsi3_v2" - [(set (match_operand:SI 0 "mpy_dest_reg_operand" "=Rcqq,Rcr, r,r,Rcr, r") - (mult:SI (match_operand:SI 1 "register_operand" "%0, 0, c,0, 0, c") - (match_operand:SI 2 "nonmemory_operand" " Rcqq, cL,cL,I,Cal,Cal")))] + [(set (match_operand:SI 0 "mpy_dest_reg_operand" "=q,q, r, r,r, r, r") + (mult:SI (match_operand:SI 1 "register_operand" "%0,q, 0, r,0, 0, c") + (match_operand:SI 2 "nonmemory_operand" "q,0,rL,rL,I,Cal,Cal")))] "TARGET_MULTI" - "mpy%? %0,%1,%2" - [(set_attr "length" "*,4,4,4,8,8") - (set_attr "iscompact" "maybe,false,false,false,false,false") + "@ + mpy%?\\t%0,%1,%2 + mpy%?\\t%0,%2,%1 + mpy%?\\t%0,%1,%2 + mpy%?\\t%0,%1,%2 + mpy%?\\t%0,%1,%2 + mpy%?\\t%0,%1,%2 + mpy%?\\t%0,%1,%2" + [(set_attr "length" "*,*,4,4,4,8,8") + (set_attr "iscompact" "maybe,maybe,false,false,false,false,false") (set_attr "type" "umulti") - (set_attr "predicable" "no,yes,no,no,yes,no") - (set_attr "cond" "nocond,canuse,nocond,canuse_limm,canuse,nocond")]) + (set_attr "predicable" "no,no,yes,no,no,yes,no") + (set_attr "cond" "nocond,nocond,canuse,nocond,canuse_limm,canuse,nocond")]) (define_expand "mulsidi3" [(set (match_operand:DI 0 "register_operand" "") @@ -2504,48 +2535,6 @@ (set_attr "predicable" "yes,no,yes,no") (set_attr "cond" "canuse,nocond,canuse,nocond")]) -; Implementations include additional labels for umulsidi3, so we got all -; the same clobbers - plus one for the result low part. */ -(define_insn "umulsi3_highpart_600_lib_le" - [(set (reg:SI R1_REG) - (truncate:SI - (lshiftrt:DI - (mult:DI (zero_extend:DI (reg:SI R0_REG)) - (zero_extend:DI (reg:SI R1_REG))) - (const_int 32)))) - (clobber (reg:SI RETURN_ADDR_REGNUM)) - (clobber (reg:SI R0_REG)) - (clobber (reg:DI R2_REG)) - (clobber (reg:SI R12_REG)) - (clobber (reg:DI MUL64_OUT_REG)) - (clobber (reg:CC CC_REG))] - "!TARGET_BIG_ENDIAN - && !TARGET_ANY_MPY - && SFUNC_CHECK_PREDICABLE" - "*return arc_output_libcall (\"__umulsi3_highpart\");" - [(set_attr "is_sfunc" "yes") - (set_attr "predicable" "yes")]) - -(define_insn "umulsi3_highpart_600_lib_be" - [(set (reg:SI R0_REG) - (truncate:SI - (lshiftrt:DI - (mult:DI (zero_extend:DI (reg:SI R0_REG)) - (zero_extend:DI (reg:SI R1_REG))) - (const_int 32)))) - (clobber (reg:SI RETURN_ADDR_REGNUM)) - (clobber (reg:SI R1_REG)) - (clobber (reg:DI R2_REG)) - (clobber (reg:SI R12_REG)) - (clobber (reg:DI MUL64_OUT_REG)) - (clobber (reg:CC CC_REG))] - "TARGET_BIG_ENDIAN - && !TARGET_ANY_MPY - && SFUNC_CHECK_PREDICABLE" - "*return arc_output_libcall (\"__umulsi3_highpart\");" - [(set_attr "is_sfunc" "yes") - (set_attr "predicable" "yes")]) - ;; (zero_extend:DI (const_int)) leads to internal errors in combine, so we ;; need a separate pattern for immediates ;; ??? This is fine for combine, but not for reload. @@ -2572,23 +2561,11 @@ (zero_extend:DI (match_operand:SI 1 "register_operand" "")) (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))) (const_int 32))))] - "!TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET" + "TARGET_MPY" " { rtx target = operands[0]; - if (!TARGET_MPY) - { - emit_move_insn (gen_rtx_REG (SImode, 0), operands[1]); - emit_move_insn (gen_rtx_REG (SImode, 1), operands[2]); - if (TARGET_BIG_ENDIAN) - emit_insn (gen_umulsi3_highpart_600_lib_be ()); - else - emit_insn (gen_umulsi3_highpart_600_lib_le ()); - emit_move_insn (target, gen_rtx_REG (SImode, 0)); - DONE; - } - if (!register_operand (target, SImode)) target = gen_reg_rtx (SImode); @@ -2607,7 +2584,7 @@ [(set (match_operand:DI 0 "register_operand" "") (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))] - "" + "TARGET_ANY_MPY" { if (TARGET_PLUS_MACD) { @@ -2646,12 +2623,8 @@ DONE; } else - { - emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]); - emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]); - emit_insn (gen_umulsidi3_600_lib ()); - emit_move_insn (operands[0], gen_rtx_REG (DImode, R0_REG)); - DONE; + { + gcc_unreachable (); } }) @@ -2729,7 +2702,7 @@ (zero_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))] "TARGET_MPY && !TARGET_PLUS_MACD" "#" - "reload_completed" + "TARGET_MPY && !TARGET_PLUS_MACD && reload_completed" [(const_int 0)] { int hi = !TARGET_BIG_ENDIAN; @@ -2743,42 +2716,6 @@ [(set_attr "type" "umulti") (set_attr "length" "8")]) -(define_insn "umulsidi3_600_lib" - [(set (reg:DI R0_REG) - (mult:DI (zero_extend:DI (reg:SI R0_REG)) - (zero_extend:DI (reg:SI R1_REG)))) - (clobber (reg:SI RETURN_ADDR_REGNUM)) - (clobber (reg:DI R2_REG)) - (clobber (reg:SI R12_REG)) - (clobber (reg:DI MUL64_OUT_REG)) - (clobber (reg:CC CC_REG))] - "!TARGET_ANY_MPY - && SFUNC_CHECK_PREDICABLE" - "*return arc_output_libcall (\"__umulsidi3\");" - [(set_attr "is_sfunc" "yes") - (set_attr "predicable" "yes")]) - -(define_peephole2 - [(parallel - [(set (reg:DI R0_REG) - (mult:DI (zero_extend:DI (reg:SI R0_REG)) - (zero_extend:DI (reg:SI R1_REG)))) - (clobber (reg:SI RETURN_ADDR_REGNUM)) - (clobber (reg:DI R2_REG)) - (clobber (reg:SI R12_REG)) - (clobber (reg:DI MUL64_OUT_REG)) - (clobber (reg:CC CC_REG))])] - "!TARGET_ANY_MPY - && peep2_regno_dead_p (1, TARGET_BIG_ENDIAN ? R1_REG : R0_REG)" - [(pc)] -{ - if (TARGET_BIG_ENDIAN) - emit_insn (gen_umulsi3_highpart_600_lib_be ()); - else - emit_insn (gen_umulsi3_highpart_600_lib_le ()); - DONE; -}) - (define_expand "addsi3" [(set (match_operand:SI 0 "dest_reg_operand" "") (plus:SI (match_operand:SI 1 "register_operand" "") @@ -3335,10 +3272,10 @@ operands[1] = force_reg (SImode, operands[1]); ") -(define_insn "andsi3_i" - [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw, Rcw,Rcw,Rcw,Rcw, w, w, w, w,Rrq,w,Rcw, w,W") - (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq, 0, 0,Rcqq, 0, c, 0, 0, 0, 0, c, c, c, c,Rrq,0, 0, c,o") - (match_operand:SI 2 "nonmemory_operand" "Rcqq, 0, C1p, Ccp, Cux, cL, 0,C2pC1p,Ccp,CnL, I,Lc,C2pC1p,Ccp,CnL,Cbf,I,Cal,Cal,Cux")))] +(define_insn "andsi3_i" ;0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + [(set (match_operand:SI 0 "dest_reg_operand" "=q,q, q, q, q, r,r, r, r, r,r, r, r, r, r, q,r, r, r, W") + (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,q, 0, 0, q, 0,r, 0, 0, 0,0, r, r, r, r, q,0, 0, r, o") + (match_operand:SI 2 "nonmemory_operand" "q,0,C1p,Ccp,Cux,rL,0,C2pC1p,Ccp,CnL,I,rL,C2pC1p,Ccp,CnL,Cbf,I,Cal,Cal,Cux")))] "(register_operand (operands[1], SImode) && nonmemory_operand (operands[2], SImode)) || (memory_operand (operands[1], SImode) @@ -3436,27 +3373,39 @@ (set_attr "predicable" "no,yes,no,yes,no,no,no") (set_attr "cond" "canuse,canuse,canuse_limm,canuse,nocond,nocond,nocond")]) -(define_insn "iorsi3" - [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcw,Rcw,Rcw,Rcw,w, w,w,Rcw, w") - (ior:SI (match_operand:SI 1 "nonmemory_operand" "% 0,Rcq, 0, 0, c, 0, 0, c, c,0, 0, c") - (match_operand:SI 2 "nonmemory_operand" "Rcqq, 0, C0p, cL, 0,C0p, I,cL,C0p,I,Cal,Cal")))] - "" - "* - switch (which_alternative) - { - case 0: case 3: case 6: case 7: case 9: case 10: case 11: - return \"or%? %0,%1,%2%&\"; - case 1: case 4: - return \"or%? %0,%2,%1%&\"; - case 2: case 5: case 8: - return \"bset%? %0,%1,%z2%&\"; - default: - gcc_unreachable (); - }" - [(set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false") - (set_attr "length" "*,*,*,4,4,4,4,4,4,4,8,8") - (set_attr "predicable" "no,no,no,yes,yes,yes,no,no,no,no,yes,no") - (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,canuse,nocond")]) +(define_insn_and_split "iorsi3" + [(set (match_operand:SI 0 "dest_reg_operand" "=q,q, q, r,r, r,r, r, r,r, q, r, r") + (ior:SI (match_operand:SI 1 "register_operand" "%0,q, 0, 0,r, 0,0, r, r,0, r, 0, r") + (match_operand:SI 2 "nonmemory_operand" "q,0,C0p,rL,0,C0p,I,rL,C0p,I,C0x,Cal,Cal")))] + "" + "@ + or%?\\t%0,%1,%2 + or%?\\t%0,%2,%1 + bset%?\\t%0,%1,%z2 + or%?\\t%0,%1,%2 + or%?\\t%0,%2,%1 + bset%?\\t%0,%1,%z2 + or%?\\t%0,%1,%2 + or%?\\t%0,%1,%2 + bset%?\\t%0,%1,%z2 + or%?\\t%0,%1,%2 + # + or%?\\t%0,%1,%2 + or%?\\t%0,%1,%2" + "reload_completed + && GET_CODE (PATTERN (insn)) != COND_EXEC + && register_operand (operands[0], SImode) + && IN_RANGE (REGNO (operands[0]) ^ 4, 4, 11) + && satisfies_constraint_C0x (operands[2])" + [(const_int 0)] + " + arc_split_ior (operands); + DONE; + " + [(set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false,false") + (set_attr "length" "*,*,*,4,4,4,4,4,4,4,*,8,8") + (set_attr "predicable" "no,no,no,yes,yes,yes,no,no,no,no,no,yes,no") + (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,nocond,canuse,nocond")]) (define_insn "xorsi3" [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcw,Rcw,Rcw,Rcw, w, w,w, w, w") @@ -3583,8 +3532,6 @@ (match_operand:SI 2 "nonmemory_operand" "rn,Cal")])) (clobber (match_scratch:SI 4 "=X,X")) (clobber (reg:SI LP_COUNT)) - (clobber (reg:SI LP_START)) - (clobber (reg:SI LP_END)) (clobber (reg:CC CC_REG)) ] "!TARGET_BARREL_SHIFTER" @@ -3791,7 +3738,7 @@ }) (define_mode_iterator SDF [(SF "TARGET_FP_SP_BASE || TARGET_OPTFPE") - (DF "TARGET_OPTFPE")]) + (DF "TARGET_FP_DP_BASE || TARGET_OPTFPE")]) (define_expand "cstore<mode>4" [(set (reg:CC CC_REG) @@ -3801,7 +3748,7 @@ (match_operator:SI 1 "comparison_operator" [(reg CC_REG) (const_int 0)]))] - "TARGET_FP_SP_BASE || TARGET_OPTFPE" + "TARGET_HARD_FLOAT || TARGET_OPTFPE" { gcc_assert (XEXP (operands[1], 0) == operands[2]); gcc_assert (XEXP (operands[1], 1) == operands[3]); @@ -3834,45 +3781,23 @@ } [(set_attr "type" "unary")]) -;; ??? At least for ARC600, we should use sbc b,b,s12 if we want a value -;; that is one lower if the carry flag is set. - -;; ??? Look up negscc insn. See pa.md for example. -(define_insn "*neg_scc_insn" - [(set (match_operand:SI 0 "dest_reg_operand" "=w") - (neg:SI (match_operator:SI 1 "proper_comparison_operator" - [(reg CC_REG) (const_int 0)])))] - "" - "mov %0,-1\;sub.%D1 %0,%0,%0" - [(set_attr "type" "unary") - (set_attr "length" "8")]) - -(define_insn "*not_scc_insn" - [(set (match_operand:SI 0 "dest_reg_operand" "=w") - (not:SI (match_operator:SI 1 "proper_comparison_operator" - [(reg CC_REG) (const_int 0)])))] - "" - "mov %0,1\;sub.%d1 %0,%0,%0" - [(set_attr "type" "unary") - (set_attr "length" "8")]) - ; cond_exec patterns (define_insn "*movsi_ne" [(cond_exec - (ne (match_operand:CC_Z 2 "cc_use_register" "Rcc, Rcc, Rcc,Rcc,Rcc") (const_int 0)) - (set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,Rcq#q,Rcq#q, w,w") - (match_operand:SI 1 "nonmemory_operand" "C_0, h, ?Cal, Lc,?Cal")))] + (ne (match_operand:CC_Z 2 "cc_use_register" "Rcc,Rcc,Rcc,Rcc,Rcc") (const_int 0)) + (set (match_operand:SI 0 "dest_reg_operand" "=q, q, r, q, r") + (match_operand:SI 1 "nonmemory_operand" "C_0, h, Lr,Cal,Cal")))] "" "@ - * current_insn_predicate = 0; return \"sub%?.ne %0,%0,%0%&\"; - * current_insn_predicate = 0; return \"mov%?.ne %0,%1\"; - * current_insn_predicate = 0; return \"mov%?.ne %0,%1\"; - mov.ne %0,%1 - mov.ne %0,%1" + * current_insn_predicate = 0; return \"sub%?.ne\\t%0,%0,%0\"; + * current_insn_predicate = 0; return \"mov%?.ne\\t%0,%1\"; + mov.ne\\t%0,%1 + * current_insn_predicate = 0; return \"mov%?.ne\\t%0,%1\"; + mov.ne\\t%0,%1" [(set_attr "type" "cmove") - (set_attr "iscompact" "true,true,true_limm,false,false") - (set_attr "length" "2,2,6,4,8") - (set_attr "cpu_facility" "*,av2,av2,*,*")]) + (set_attr "iscompact" "true,true,false,true_limm,false") + (set_attr "length" "2,2,4,6,8") + (set_attr "cpu_facility" "*,av2,*,av2,*")]) (define_insn "*movsi_cond_exec" [(cond_exec @@ -4106,60 +4031,70 @@ (set_attr "cond" "canuse,canuse_limm,canuse,canuse,canuse")]) ;; Implement a switch statement. - (define_expand "casesi" - [(set (match_dup 5) - (minus:SI (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "nonmemory_operand" ""))) - (set (reg:CC CC_REG) - (compare:CC (match_dup 5) - (match_operand:SI 2 "nonmemory_operand" ""))) - (set (pc) - (if_then_else (gtu (reg:CC CC_REG) - (const_int 0)) - (label_ref (match_operand 4 "" "")) - (pc))) - (set (match_dup 6) - (unspec:SI [(match_operand 3 "" "") - (match_dup 5) (match_dup 7)] UNSPEC_ARC_CASESI)) - (parallel [(set (pc) (match_dup 6)) (use (match_dup 7))])] - "" - " + [(match_operand:SI 0 "register_operand" "") ; Index + (match_operand:SI 1 "const_int_operand" "") ; Lower bound + (match_operand:SI 2 "const_int_operand" "") ; Total range + (match_operand:SI 3 "" "") ; Table label + (match_operand:SI 4 "" "")] ; Out of range label + "" { - rtx x; - - operands[5] = gen_reg_rtx (SImode); - operands[6] = gen_reg_rtx (SImode); - operands[7] = operands[3]; - emit_insn (gen_subsi3 (operands[5], operands[0], operands[1])); - emit_insn (gen_cmpsi_cc_insn_mixed (operands[5], operands[2])); - x = gen_rtx_GTU (VOIDmode, gen_rtx_REG (CCmode, CC_REG), const0_rtx); - x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, - gen_rtx_LABEL_REF (VOIDmode, operands[4]), pc_rtx); - emit_jump_insn (gen_rtx_SET (pc_rtx, x)); - if (TARGET_COMPACT_CASESI) + if (operands[1] != const0_rtx) { - emit_jump_insn (gen_casesi_compact_jump (operands[5], operands[7])); + rtx reg = gen_reg_rtx (SImode); + emit_insn (gen_subsi3 (reg, operands[0], operands[1])); + operands[0] = reg; } + emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, operands[0], + operands[2]), + operands[0], operands[2], operands[4])); + if (TARGET_BI_BIH) + emit_jump_insn (gen_casesi_dispatch (operands[0], operands[3])); else { + rtx reg = gen_reg_rtx (SImode); + rtx lbl = operands[3]; operands[3] = gen_rtx_LABEL_REF (VOIDmode, operands[3]); - if (flag_pic || !cse_not_expected) + if (flag_pic) operands[3] = force_reg (Pmode, operands[3]); - emit_insn (gen_casesi_load (operands[6], - operands[3], operands[5], operands[7])); + emit_insn (gen_casesi_load (reg, + operands[3], operands[0], lbl)); if (CASE_VECTOR_PC_RELATIVE || flag_pic) - emit_insn (gen_addsi3 (operands[6], operands[6], operands[3])); - emit_jump_insn (gen_casesi_jump (operands[6], operands[7])); + emit_insn (gen_addsi3 (reg, reg, operands[3])); + emit_jump_insn (gen_casesi_jump (reg, lbl)); } DONE; -}") +}) + +(define_insn "casesi_dispatch" + [(set (pc) + (unspec:SI [(match_operand:SI 0 "register_operand" "r") + (label_ref (match_operand 1 "" ""))] + UNSPEC_ARC_CASESI))] + "TARGET_BI_BIH" +{ + rtx diff_vec = PATTERN (next_nonnote_insn (as_a<rtx_insn *> (operands[1]))); + gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); + switch (GET_MODE (diff_vec)) + { + case E_SImode: + return \"bi\\t[%0]\"; + case E_HImode: + case E_QImode: + return \"bih\\t[%0]\"; + default: gcc_unreachable (); + } +} + [(set_attr "type" "brcc_no_delay_slot") + (set_attr "iscompact" "false") + (set_attr "length" "4")]) (define_insn "casesi_load" - [(set (match_operand:SI 0 "register_operand" "=Rcq,r,r") - (unspec:SI [(match_operand:SI 1 "nonmemory_operand" "Rcq,c,Cal") - (match_operand:SI 2 "register_operand" "Rcq,c,c") - (label_ref (match_operand 3 "" ""))] UNSPEC_ARC_CASESI))] + [(set (match_operand:SI 0 "register_operand" "=q,r,r") + (mem:SI (unspec:SI [(match_operand:SI 1 "nonmemory_operand" "q,r,Cal") + (match_operand:SI 2 "register_operand" "q,r,r")] + UNSPEC_ARC_CASESI))) + (use (label_ref (match_operand 3 "" "")))] "" "* { @@ -4175,15 +4110,15 @@ switch (GET_MODE (diff_vec)) { case E_SImode: - return \"ld.as %0,[%1,%2]%&\"; + return \"ld.as\\t%0,[%1,%2]%&\"; case E_HImode: if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) - return \"ld%_.as %0,[%1,%2]\"; - return \"ld%_.x.as %0,[%1,%2]\"; + return \"ld%_.as\\t%0,[%1,%2]\"; + return \"ld%_.x.as\\t%0,[%1,%2]\"; case E_QImode: if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) - return \"ldb%? %0,[%1,%2]%&\"; - return \"ldb.x %0,[%1,%2]\"; + return \"ldb%?\\t%0,[%1,%2]%&\"; + return \"ldb.x\\t%0,[%1,%2]\"; default: gcc_unreachable (); } @@ -4223,110 +4158,6 @@ (set_attr "iscompact" "false,maybe,false") (set_attr "cond" "canuse")]) -(define_insn "casesi_compact_jump" - [(set (pc) - (unspec:SI [(match_operand:SI 0 "register_operand" "c,q")] - UNSPEC_ARC_CASESI)) - (use (label_ref (match_operand 1 "" ""))) - (clobber (match_scratch:SI 2 "=q,0"))] - "TARGET_COMPACT_CASESI" - "* -{ - rtx diff_vec = PATTERN (next_nonnote_insn (as_a<rtx_insn *> (operands[1]))); - int unalign = arc_get_unalign (); - rtx xop[3]; - const char *s; - - xop[0] = operands[0]; - xop[2] = operands[2]; - gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); - - switch (GET_MODE (diff_vec)) - { - case E_SImode: - /* Max length can be 12 in this case, but this is OK because - 2 of these are for alignment, and are anticipated in the length - of the ADDR_DIFF_VEC. */ - if (unalign && !satisfies_constraint_Rcq (xop[0])) - s = \"add2 %2,pcl,%0\n\tld_s %2,[%2,12]\"; - else if (unalign) - s = \"add_s %2,%0,2\n\tld.as %2,[pcl,%2]\"; - else - s = \"add %2,%0,2\n\tld.as %2,[pcl,%2]\"; - arc_clear_unalign (); - break; - case E_HImode: - if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) - { - if (satisfies_constraint_Rcq (xop[0])) - { - s = \"add_s %2,%0,%1\n\tld%_.as %2,[pcl,%2]\"; - xop[1] = GEN_INT ((10 - unalign) / 2U); - } - else - { - s = \"add1 %2,pcl,%0\n\tld%__s %2,[%2,%1]\"; - xop[1] = GEN_INT (10 + unalign); - } - } - else - { - if (satisfies_constraint_Rcq (xop[0])) - { - s = \"add_s %2,%0,%1\n\tld%_.x.as %2,[pcl,%2]\"; - xop[1] = GEN_INT ((10 - unalign) / 2U); - } - else - { - s = \"add1 %2,pcl,%0\n\tld%__s.x %2,[%2,%1]\"; - xop[1] = GEN_INT (10 + unalign); - } - } - arc_toggle_unalign (); - break; - case E_QImode: - if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned) - { - if ((rtx_equal_p (xop[2], xop[0]) - || find_reg_note (insn, REG_DEAD, xop[0])) - && satisfies_constraint_Rcq (xop[0])) - { - s = \"add_s %0,%0,pcl\n\tldb_s %2,[%0,%1]\"; - xop[1] = GEN_INT (8 + unalign); - } - else - { - s = \"add %2,%0,pcl\n\tldb_s %2,[%2,%1]\"; - xop[1] = GEN_INT (10 + unalign); - arc_toggle_unalign (); - } - } - else if ((rtx_equal_p (xop[0], xop[2]) - || find_reg_note (insn, REG_DEAD, xop[0])) - && satisfies_constraint_Rcq (xop[0])) - { - s = \"add_s %0,%0,%1\n\tldb.x %2,[pcl,%0]\"; - xop[1] = GEN_INT (10 - unalign); - arc_toggle_unalign (); - } - else - { - /* ??? Length is 12. */ - s = \"add %2,%0,%1\n\tldb.x %2,[pcl,%2]\"; - xop[1] = GEN_INT (8 + unalign); - } - break; - default: - gcc_unreachable (); - } - output_asm_insn (s, xop); - return \"add_s %2,%2,pcl\n\tj_s%* [%2]\"; -}" - [(set_attr "length" "10") - (set_attr "type" "jump") - (set_attr "iscompact" "true") - (set_attr "cond" "nocond")]) - (define_expand "call" ;; operands[1] is stack_size_rtx ;; operands[2] is next_arg_register @@ -4456,6 +4287,14 @@ (set_attr "type" "block")] ) +(define_insn "arc600_stall" + [(unspec_volatile [(const_int 0)] VUNSPEC_ARC_ARC600_STALL)] + "TARGET_MUL64_SET" + "mov\\t0,mlo\t;wait until multiply complete." + [(set_attr "length" "4") + (set_attr "type" "move")] +) + ;; Split up troublesome insns for better scheduling. ;; Peepholes go at the end. @@ -4759,13 +4598,13 @@ (set_attr "type" "misc")]) (define_insn "rtie" - [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")] - VUNSPEC_ARC_RTIE)] - "" + [(return) + (unspec_volatile [(const_int 0)] VUNSPEC_ARC_RTIE)] + "!TARGET_ARC600_FAMILY" "rtie" [(set_attr "length" "4") - (set_attr "type" "misc") - (set_attr "cond" "clob")]) + (set_attr "type" "rtie") + (set_attr "cond" "clob")]) (define_insn "sync" [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")] @@ -4842,6 +4681,64 @@ [(set_attr "length" "8,4,8,4") (set_attr "type" "sr,sr,sr,sr")]) +(define_mode_iterator ALLI [QI HI SI (DI "TARGET_LL64")]) +(define_mode_attr mALLI [(QI "b") (HI "%_") (SI "") (DI "d")]) + +(define_insn "lddi<mode>" + [(set (match_operand:ALLI 0 "register_operand" "=r") + (unspec_volatile:ALLI [(match_operand:ALLI 1 "memory_operand" "m")] + VUNSPEC_ARC_LDDI))] + "" + "ld<mALLI>%U1.di\\t%0,%1" + [(set_attr "type" "load")]) + +(define_insn "stdi<mode>" + [(unspec_volatile [(match_operand:ALLI 0 "memory_operand" "m,m,Usc") + (match_operand:ALLI 1 "nonmemory_operand" "r,Cm3,i")] + VUNSPEC_ARC_STDI)] + "" + "st<mALLI>%U0.di\\t%1,%0" + [(set_attr "length" "*,*,8") + (set_attr "type" "store")]) + +(define_insn_and_split "*stdidi_split" + [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m") + (match_operand:DI 1 "register_operand" "r")] + VUNSPEC_ARC_STDI)] + "!TARGET_LL64" + "#" + "&& reload_completed" + [(unspec_volatile:SI [(match_dup 2) (match_dup 3)] VUNSPEC_ARC_STDI) + (unspec_volatile:SI [(match_dup 4) (match_dup 5)] VUNSPEC_ARC_STDI)] + " + { + operands[3] = gen_lowpart (SImode, operands[1]); + operands[5] = gen_highpart_mode (SImode, DImode, operands[1]); + operands[2] = gen_lowpart (SImode, operands[0]); + operands[4] = gen_highpart (SImode, operands[0]); + } + " + ) + +(define_insn_and_split "*lddidi_split" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec_volatile:DI [(match_operand:DI 1 "memory_operand" "m")] + VUNSPEC_ARC_LDDI))] + "!TARGET_LL64" + "#" + "&& reload_completed" + [(set (match_dup 2) (unspec_volatile:SI [(match_dup 3)] VUNSPEC_ARC_LDDI)) + (set (match_dup 4) (unspec_volatile:SI [(match_dup 5)] VUNSPEC_ARC_LDDI))] + " + { + operands[3] = gen_lowpart (SImode, operands[1]); + operands[5] = gen_highpart (SImode, operands[1]); + operands[2] = gen_lowpart (SImode, operands[0]); + operands[4] = gen_highpart (SImode, operands[0]); + } + " + ) + (define_insn "trap_s" [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "L,Cal")] VUNSPEC_ARC_TRAP_S)] @@ -4917,17 +4814,17 @@ (define_insn "*sibcall_insn" [(call (mem:SI (match_operand:SI 0 "call_address_operand" - "Cbp,Cbr,Rs5,Rsc,Cal")) + "Cbp,Cbr,!Rcd,Rsc,Cal")) (match_operand 1 "" "")) (simple_return) (use (match_operand 2 "" ""))] "" "@ - b%!%* %P0 - b%!%* %P0 - j%!%* [%0]%& - j%!%* [%0] - j%! %P0" + b%!%*\\t%P0 + b%!%*\\t%P0 + j%!%*\\t[%0] + j%!%*\\t[%0] + j%!\\t%P0" [(set_attr "type" "call,call,call,call,call_no_delay_slot") (set_attr "predicable" "yes,no,no,yes,yes") (set_attr "iscompact" "false,false,maybe,false,false") @@ -4937,17 +4834,17 @@ (define_insn "*sibcall_value_insn" [(set (match_operand 0 "dest_reg_operand" "") (call (mem:SI (match_operand:SI 1 "call_address_operand" - "Cbp,Cbr,Rs5,Rsc,Cal")) + "Cbp,Cbr,!Rcd,Rsc,Cal")) (match_operand 2 "" ""))) (simple_return) (use (match_operand 3 "" ""))] "" "@ - b%!%* %P1 - b%!%* %P1 - j%!%* [%1]%& - j%!%* [%1] - j%! %P1" + b%!%*\\t%P1 + b%!%*\\t%P1 + j%!%*\\t[%1] + j%!%*\\t[%1] + j%!\\t%P1" [(set_attr "type" "call,call,call,call,call_no_delay_slot") (set_attr "predicable" "yes,no,no,yes,yes") (set_attr "iscompact" "false,false,maybe,false,false") @@ -4987,88 +4884,52 @@ ; forbid instructions that change blink in the return / sibcall delay slot. (define_insn "simple_return" [(simple_return)] - "reload_completed" -{ - rtx reg - = gen_rtx_REG (Pmode, - arc_return_address_register (arc_compute_function_type - (cfun))); - - if (TARGET_V2 - && ARC_INTERRUPT_P (arc_compute_function_type (cfun))) - { - return \"rtie\"; - } - output_asm_insn (\"j%!%* [%0]%&\", ®); - return \"\"; -} - [(set (attr "type") - (cond [(and (match_test "ARC_INTERRUPT_P (arc_compute_function_type (cfun))") - (match_test "TARGET_V2")) - (const_string "brcc_no_delay_slot")] - (const_string "return"))) - ; predicable won't help here since the canonical rtl looks different - ; for branches. - (set (attr "cond") - (cond [(and (eq (symbol_ref "arc_compute_function_type (cfun)") - (symbol_ref "ARC_FUNCTION_ILINK1")) - (match_test "TARGET_V2")) - (const_string "nocond")] - (const_string "canuse"))) - (set (attr "iscompact") - (cond [(eq (symbol_ref "arc_compute_function_type (cfun)") - (symbol_ref "ARC_FUNCTION_NORMAL")) - (const_string "maybe")] - (const_string "false"))) - (set (attr "length") - (cond [(ne (symbol_ref "arc_compute_function_type (cfun)") - (symbol_ref "ARC_FUNCTION_NORMAL")) - (const_int 4)] - (const_int 2)))]) + "" + "j%!%*\\t[blink]" + [(set_attr "type" "return") + (set_attr "cond" "canuse") + (set_attr "iscompact" "maybe") + (set_attr "length" "*")]) + +(define_insn "arc600_rtie" + [(return) + (unspec_volatile [(match_operand 0 "pmode_register_operand" "")] + VUNSPEC_ARC_ARC600_RTIE)] + "TARGET_ARC600_FAMILY" + "j.f\\t[%0]" + [(set_attr "length" "4") + (set_attr "type" "rtie") + (set_attr "cond" "clob")]) (define_insn "p_return_i" [(set (pc) (if_then_else (match_operator 0 "proper_comparison_operator" [(reg CC_REG) (const_int 0)]) (simple_return) (pc)))] - "reload_completed - && !(TARGET_V2 - && ARC_INTERRUPT_P (arc_compute_function_type (cfun)))" + "reload_completed" { - rtx xop[2]; - xop[0] = operands[0]; - xop[1] - = gen_rtx_REG (Pmode, - arc_return_address_register (arc_compute_function_type - (cfun))); - - output_asm_insn (\"j%d0%!%# [%1]%&\", xop); + output_asm_insn (\"j%d0%!%#\\t[blink]\", operands); /* record the condition in case there is a delay insn. */ - arc_ccfsm_record_condition (xop[0], false, insn, 0); + arc_ccfsm_record_condition (operands[0], false, insn, 0); return \"\"; } [(set_attr "type" "return") (set_attr "cond" "use") - (set (attr "iscompact") - (cond [(eq (symbol_ref "arc_compute_function_type (cfun)") - (symbol_ref "ARC_FUNCTION_NORMAL")) - (const_string "maybe")] - (const_string "false"))) + (set_attr "iscompact" "maybe" ) (set (attr "length") - (cond [(ne (symbol_ref "arc_compute_function_type (cfun)") - (symbol_ref "ARC_FUNCTION_NORMAL")) - (const_int 4) - (not (match_operand 0 "equality_comparison_operator" "")) + (cond [(not (match_operand 0 "equality_comparison_operator" "")) (const_int 4) (eq_attr "delay_slot_filled" "yes") (const_int 4)] (const_int 2)))]) -;; ??? #ifdefs in function.c require the presence of this pattern, with a -;; non-constant predicate. +;; Return nonzero if this function is known to have a null epilogue. +;; This allows the optimizer to omit jumps to jumps if no stack +;; was created. (define_expand "return" [(return)] - "optimize < 0") + "arc_can_use_return_insn ()" + "") ;; Comment in final.c (insn_current_reference_address) says ;; forward branch addresses are calculated from the next insn after branch @@ -5231,12 +5092,12 @@ }) (define_insn "arc_lp" - [(unspec:SI [(match_operand:SI 0 "register_operand" "l")] + [(unspec:SI [(reg:SI LP_COUNT)] UNSPEC_ARC_LP) - (use (label_ref (match_operand 1 "" ""))) - (use (label_ref (match_operand 2 "" "")))] - "" - "lp\\t@%l2\\t; %0:@%l1->@%l2" + (use (label_ref (match_operand 0 "" ""))) + (use (label_ref (match_operand 1 "" "")))] + "" + "lp\\t@%l1\\t; lp_count:@%l0->@%l1" [(set_attr "type" "loop_setup") (set_attr "length" "4")]) @@ -5244,16 +5105,16 @@ ;; register, instead of going to memory. (define_insn "loop_end" [(set (pc) - (if_then_else (ne (match_operand:SI 2 "nonimmediate_operand" "0,0") + (if_then_else (ne (match_operand:SI 2 "nonimmediate_operand" "0,m") (const_int 1)) (label_ref (match_operand 1 "" "")) (pc))) - (set (match_operand:SI 0 "nonimmediate_operand" "=l!r,m") + (set (match_operand:SI 0 "nonimmediate_operand" "=r,m") (plus (match_dup 2) (const_int -1))) (unspec [(const_int 0)] UNSPEC_ARC_LP) (clobber (match_scratch:SI 3 "=X,&r"))] "" - "\\t;%0 %1 %2" + "; ZOL_END, begins @%l1" [(set_attr "length" "0") (set_attr "predicable" "no") (set_attr "type" "loop_end")]) @@ -5298,7 +5159,7 @@ (define_insn_and_split "dbnz" [(set (pc) (if_then_else - (ne (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+r!l,m") + (ne (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+rl,m") (const_int -1)) (const_int 0)) (label_ref (match_operand 1 "" "")) @@ -5325,13 +5186,13 @@ (set_attr "type" "loop_end") (set_attr "length" "4,20")]) -(define_expand "movmemsi" +(define_expand "cpymemsi" [(match_operand:BLK 0 "" "") (match_operand:BLK 1 "" "") (match_operand:SI 2 "nonmemory_operand" "") (match_operand 3 "immediate_operand" "")] "" - "if (arc_expand_movmem (operands)) DONE; else FAIL;") + "if (arc_expand_cpymem (operands)) DONE; else FAIL;") ;; Close http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35803 if this works ;; to the point that we can generate cmove instructions. @@ -5448,27 +5309,6 @@ [(set_attr "type" "call") (set_attr "is_SIBCALL" "yes")]) -(define_insn "tls_load_tp_soft" - [(set (reg:SI R0_REG) (unspec:SI [(const_int 0)] UNSPEC_TLS_OFF)) - (clobber (reg:SI RETURN_ADDR_REGNUM))] - "" - "*return arc_output_libcall (\"__read_tp\");" - [(set_attr "is_sfunc" "yes") - (set_attr "predicable" "yes")]) - -(define_insn "tls_gd_get_addr" - [(set (reg:SI R0_REG) - (call:SI (mem:SI (unspec:SI [(match_operand:SI 0 - "symbolic_operand" "X,X")] - UNSPEC_TLS_GD)) - (const_int 0))) - (clobber (reg:SI RETURN_ADDR_REGNUM))] - "" - ".tls_gd_ld %0`bl%* __tls_get_addr@plt" - [(set_attr "type" "call") - ; With TARGET_MEDIUM_CALLS, plt calls are not predicable. - (set_attr "predicable" "no")]) - ;; For thread pointer builtins (define_expand "get_thread_pointersi" [(set (match_operand:SI 0 "register_operand") (match_dup 1))] @@ -6208,11 +6048,21 @@ (match_dup 1)]) (define_insn "*rotrsi3_cnt1" - [(set (match_operand:SI 0 "dest_reg_operand" "=w") - (rotatert:SI (match_operand:SI 1 "register_operand" "c") + [(set (match_operand:SI 0 "dest_reg_operand" "=r") + (rotatert:SI (match_operand:SI 1 "nonmemory_operand" "rL") (const_int 1)))] "" - "ror %0,%1%&" + "ror\\t%0,%1" + [(set_attr "type" "shift") + (set_attr "predicable" "no") + (set_attr "length" "4")]) + +(define_insn "*rotrsi3_cnt8" + [(set (match_operand:SI 0 "register_operand" "=r") + (rotatert:SI (match_operand:SI 1 "nonmemory_operand" "rL") + (const_int 8)))] + "TARGET_BARREL_SHIFTER && TARGET_V2" + "ror8\\t%0,%1" [(set_attr "type" "shift") (set_attr "predicable" "no") (set_attr "length" "4")]) @@ -6225,8 +6075,31 @@ "asl%? %0,%1%&" [(set_attr "type" "shift") (set_attr "iscompact" "maybe,false") + (set_attr "length" "4") (set_attr "predicable" "no,no")]) +(define_insn "*ashlsi2_cnt8" + [(set (match_operand:SI 0 "register_operand" "=r") + (ashift:SI (match_operand:SI 1 "nonmemory_operand" "rL") + (const_int 8)))] + "TARGET_BARREL_SHIFTER && TARGET_V2" + "lsl8\\t%0,%1" + [(set_attr "type" "shift") + (set_attr "iscompact" "false") + (set_attr "length" "4") + (set_attr "predicable" "no")]) + +(define_insn "*ashlsi2_cnt16" + [(set (match_operand:SI 0 "register_operand" "=r") + (ashift:SI (match_operand:SI 1 "nonmemory_operand" "rL") + (const_int 16)))] + "TARGET_BARREL_SHIFTER && TARGET_V2" + "lsl16\\t%0,%1" + [(set_attr "type" "shift") + (set_attr "iscompact" "false") + (set_attr "length" "4") + (set_attr "predicable" "no")]) + (define_insn "*lshrsi3_cnt1" [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w") (lshiftrt:SI (match_operand:SI 1 "register_operand" "Rcqq,c") @@ -6531,18 +6404,6 @@ (set_attr "predicable" "yes,no,no,yes,no") (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")]) -(define_insn "stack_tie" - [(set (mem:BLK (scratch)) - (unspec:BLK [(match_operand:SI 0 "register_operand" "rb") - (match_operand:SI 1 "register_operand" "rb")] - UNSPEC_ARC_STKTIE))] - "" - "" - [(set_attr "length" "0") - (set_attr "iscompact" "false") - (set_attr "type" "block")] - ) - (define_insn "*add_shift" [(set (match_operand:SI 0 "register_operand" "=q,r,r") (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "q,r,r") @@ -6614,6 +6475,267 @@ [(set (reg:CC CC_REG) (compare:CC (match_dup 3) (ashift:SI (match_dup 1) (match_dup 2))))]) +(define_peephole2 ; std + [(set (match_operand:SI 2 "memory_operand" "") + (match_operand:SI 0 "register_operand" "")) + (set (match_operand:SI 3 "memory_operand" "") + (match_operand:SI 1 "register_operand" ""))] + "TARGET_LL64" + [(const_int 0)] +{ + if (!gen_operands_ldd_std (operands, false, false)) + FAIL; + operands[0] = gen_rtx_REG (DImode, REGNO (operands[0])); + operands[2] = adjust_address (operands[2], DImode, 0); + emit_insn (gen_rtx_SET (operands[2], operands[0])); + DONE; +}) + +(define_peephole2 ; ldd + [(set (match_operand:SI 0 "register_operand" "") + (match_operand:SI 2 "memory_operand" "")) + (set (match_operand:SI 1 "register_operand" "") + (match_operand:SI 3 "memory_operand" ""))] + "TARGET_LL64" + [(const_int 0)] +{ + if (!gen_operands_ldd_std (operands, true, false)) + FAIL; + operands[0] = gen_rtx_REG (DImode, REGNO (operands[0])); + operands[2] = adjust_address (operands[2], DImode, 0); + emit_insn (gen_rtx_SET (operands[0], operands[2])); + DONE; +}) + +;; We require consecutive registers for LDD instruction. Check if we +;; can reorder them and use an LDD. + +(define_peephole2 ; swap the destination registers of two loads + ; before a commutative operation. + [(set (match_operand:SI 0 "register_operand" "") + (match_operand:SI 2 "memory_operand" "")) + (set (match_operand:SI 1 "register_operand" "") + (match_operand:SI 3 "memory_operand" "")) + (set (match_operand:SI 4 "register_operand" "") + (match_operator:SI 5 "commutative_operator" + [(match_operand 6 "register_operand" "") + (match_operand 7 "register_operand" "") ]))] + "TARGET_LL64 + && (((rtx_equal_p (operands[0], operands[6])) + && (rtx_equal_p (operands[1], operands[7]))) + || ((rtx_equal_p (operands[0], operands[7])) + && (rtx_equal_p (operands[1], operands[6])))) + && (peep2_reg_dead_p (3, operands[0]) + || rtx_equal_p (operands[0], operands[4])) + && (peep2_reg_dead_p (3, operands[1]) + || rtx_equal_p (operands[1], operands[4]))" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))] + { + if (!gen_operands_ldd_std (operands, true, true)) + { + FAIL; + } + else + { + operands[0] = gen_rtx_REG (DImode, REGNO (operands[0])); + operands[2] = adjust_address (operands[2], DImode, 0); + } + } +) + +(define_insn "*push_multi_fp" + [(match_parallel 0 "push_multi_operand" + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand 1 "immediate_operand" ""))) + (set (mem:SI (plus:SI (reg:SI SP_REG) + (match_operand 2 "immediate_operand" + ""))) + (reg:SI 13))])] + "TARGET_CODE_DENSITY" + { + int len = XVECLEN (operands[0], 0); + rtx tmp = XVECEXP (operands[0], 0, len - 1); + if (MEM_P (XEXP (tmp, 0))) + { + operands[3] = XEXP (tmp, 1); + return "enter_s\\t{r13-%3} ; sp=sp+(%1)"; + } + else + { + tmp = XVECEXP (operands[0], 0, len - 3); + operands[3] = XEXP (tmp, 1); + return "enter_s\\t{r13-%3, fp} ; sp=sp+(%1)"; + } + } + [(set_attr "type" "call_no_delay_slot") + (set_attr "length" "2")]) + +(define_insn "*push_multi_fp_blink" + [(match_parallel 0 "push_multi_operand" + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand 1 "immediate_operand" ""))) + (set (mem:SI (plus:SI (reg:SI SP_REG) + (match_operand 2 "immediate_operand" + ""))) + (reg:SI RETURN_ADDR_REGNUM))])] + "TARGET_CODE_DENSITY" + { + int len = XVECLEN (operands[0], 0); + rtx tmp = XVECEXP (operands[0], 0, len - 1); + if (MEM_P (XEXP (tmp, 0))) + { + operands[3] = XEXP (tmp, 1); + return "enter_s\\t{r13-%3, blink} ; sp=sp+(%1)"; + } + else + { + tmp = XVECEXP (operands[0], 0, len - 3); + operands[3] = XEXP (tmp, 1); + return "enter_s\\t{r13-%3, fp, blink} ; sp=sp+(%1)"; + } + } + [(set_attr "type" "call_no_delay_slot") + (set_attr "length" "2")]) + +(define_insn "*pop_multi_fp" + [(match_parallel 0 "pop_multi_operand" + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand 1 "immediate_operand" ""))) + (set (reg:SI 13) + (mem:SI + (plus:SI + (reg:SI SP_REG) + (match_operand 2 "immediate_operand" ""))))])] + "TARGET_CODE_DENSITY" + { + int len = XVECLEN (operands[0], 0); + rtx tmp = XVECEXP (operands[0], 0, len - 1); + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) + { + operands[3] = XEXP (tmp, 0); + gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); + return "leave_s\\t{r13-%3} ; sp=sp+%1"; + } + else + { + tmp = XVECEXP (operands[0], 0, len - 2); + operands[3] = XEXP (tmp, 0); + return "leave_s\\t{r13-%3, fp} ; sp=sp+%1"; + } + } + [(set_attr "type" "call_no_delay_slot") + (set_attr "length" "2")]) + +(define_insn "*pop_multi_fp_blink" + [(match_parallel 0 "pop_multi_operand" + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand 1 "immediate_operand" ""))) + (set (reg:SI RETURN_ADDR_REGNUM) + (mem:SI + (plus:SI + (reg:SI SP_REG) + (match_operand 2 "immediate_operand" ""))))])] + "TARGET_CODE_DENSITY" + { + int len = XVECLEN (operands[0], 0); + rtx tmp = XVECEXP (operands[0], 0, len - 1); + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) + { + operands[3] = XEXP (tmp, 0); + gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); + return "leave_s\\t{r13-%3, blink} ; sp=sp+%1"; + } + else + { + tmp = XVECEXP (operands[0], 0, len - 2); + operands[3] = XEXP (tmp, 0); + return "leave_s\\t{r13-%3, fp, blink} ; sp=sp+%1"; + } + } + [(set_attr "type" "call_no_delay_slot") + (set_attr "length" "2")]) + +(define_insn "*pop_multi_fp_ret" + [(match_parallel 0 "pop_multi_operand" + [(return) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand 1 "immediate_operand" ""))) + (set (reg:SI 13) + (mem:SI + (plus:SI + (reg:SI SP_REG) + (match_operand 2 "immediate_operand" ""))))])] + "TARGET_CODE_DENSITY" + { + int len = XVECLEN (operands[0], 0); + rtx tmp = XVECEXP (operands[0], 0, len - 1); + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) + { + operands[3] = XEXP (tmp, 0); + gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); + return "leave_s\\t{r13-%3, pcl} ; sp=sp+%1"; + } + else + { + tmp = XVECEXP (operands[0], 0, len - 2); + operands[3] = XEXP (tmp, 0); + return "leave_s\\t{r13-%3, fp, pcl} ; sp=sp+%1"; + } + } + [(set_attr "type" "call_no_delay_slot") + (set_attr "length" "2")]) + +(define_insn "*pop_multi_fp_blink_ret" + [(match_parallel 0 "pop_multi_operand" + [(return) + (set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand 1 "immediate_operand" ""))) + (set (reg:SI RETURN_ADDR_REGNUM) + (mem:SI + (plus:SI + (reg:SI SP_REG) + (match_operand 2 "immediate_operand" ""))))])] + "TARGET_CODE_DENSITY" + { + int len = XVECLEN (operands[0], 0); + rtx tmp = XVECEXP (operands[0], 0, len - 1); + if (XEXP (tmp, 0) != hard_frame_pointer_rtx) + { + operands[3] = XEXP (tmp, 0); + gcc_assert (INTVAL (operands[1]) == INTVAL (operands[2])); + return "leave_s\\t{r13-%3, blink, pcl} ; sp=sp+%1"; + } + else + { + tmp = XVECEXP (operands[0], 0, len - 2); + operands[3] = XEXP (tmp, 0); + return "leave_s\\t{r13-%3, fp, blink, pcl} ; sp=sp+%1"; + } + } + [(set_attr "type" "call_no_delay_slot") + (set_attr "length" "2")]) + +;; Patterns for exception handling +(define_insn_and_split "eh_return" + [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] + VUNSPEC_ARC_EH_RETURN)] + "" + "#" + "reload_completed" + [(const_int 0)] + " + { + arc_eh_return_address_location (operands[0]); + DONE; + }" +) ;; include the arc-FPX instructions (include "fpx.md")