diff options
Diffstat (limited to 'gcc/config/avr/avr.md')
-rw-r--r-- | gcc/config/avr/avr.md | 626 |
1 files changed, 259 insertions, 367 deletions
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 3b1800d3fb0..35d4bdc1717 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -77,23 +77,13 @@ (include "constraints.md") ;; Condition code settings. -(define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber" +(define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber, + out_plus, out_plus_noclobber" (const_string "none")) (define_attr "type" "branch,branch1,arith,xcall" (const_string "arith")) -(define_attr "mcu_have_movw" "yes,no" - (const (if_then_else (symbol_ref "AVR_HAVE_MOVW") - (const_string "yes") - (const_string "no")))) - -(define_attr "mcu_mega" "yes,no" - (const (if_then_else (symbol_ref "AVR_HAVE_JMP_CALL") - (const_string "yes") - (const_string "no")))) - - ;; The size of instructions in bytes. ;; XXX may depend from "cc" @@ -123,7 +113,7 @@ (const_int 3) (const_int 4))) (eq_attr "type" "xcall") - (if_then_else (eq_attr "mcu_mega" "no") + (if_then_else (match_test "!AVR_HAVE_JMP_CALL") (const_int 1) (const_int 2))] (const_int 2))) @@ -132,11 +122,11 @@ ;; Following insn attribute tells if and how the adjustment has to be ;; done: ;; no No adjustment needed; attribute "length" is fine. -;; yes Analyse pattern in adjust_insn_length by hand. ;; Otherwise do special processing depending on the attribute. (define_attr "adjust_len" - "out_bitop, out_plus, tsthi, tstsi, compare, + "out_bitop, out_plus, out_plus_noclobber, addto_sp, + tsthi, tstsi, compare, call, mov8, mov16, mov32, reload_in16, reload_in32, ashlqi, ashrqi, lshrqi, ashlhi, ashrhi, lshrhi, @@ -144,6 +134,50 @@ no" (const_string "no")) +;; Flavours of instruction set architecture (ISA), used in enabled attribute + +;; mov: ISA has no MOVW +;; movw: ISA has MOVW +;; rjmp: ISA has no CALL/JMP +;; jmp: ISA has CALL/JMP +;; ijmp: ISA has no EICALL/EIJMP +;; eijmp: ISA has EICALL/EIJMP + +(define_attr "isa" + "mov,movw, rjmp,jmp, ijmp,eijmp, + standard" + (const_string "standard")) + +(define_attr "enabled" "" + (cond [(eq_attr "isa" "standard") + (const_int 1) + + (and (eq_attr "isa" "mov") + (match_test "!AVR_HAVE_MOVW")) + (const_int 1) + + (and (eq_attr "isa" "movw") + (match_test "AVR_HAVE_MOVW")) + (const_int 1) + + (and (eq_attr "isa" "rjmp") + (match_test "!AVR_HAVE_JMP_CALL")) + (const_int 1) + + (and (eq_attr "isa" "jmp") + (match_test "AVR_HAVE_JMP_CALL")) + (const_int 1) + + (and (eq_attr "isa" "ijmp") + (match_test "!AVR_HAVE_EIJMP_EICALL")) + (const_int 1) + + (and (eq_attr "isa" "eijmp") + (match_test "AVR_HAVE_EIJMP_EICALL")) + (const_int 1) + ] (const_int 0))) + + ;; Define mode iterators (define_mode_iterator QIHI [(QI "") (HI "")]) (define_mode_iterator QIHI2 [(QI "") (HI "")]) @@ -295,7 +329,7 @@ operands[1] = copy_to_mode_reg(QImode, operand1); ") -(define_insn "*movqi" +(define_insn "movqi_insn" [(set (match_operand:QI 0 "nonimmediate_operand" "=r,d,Qm,r,q,r,*r") (match_operand:QI 1 "general_operand" "rL,i,rL,Qm,r,q,i"))] "(register_operand (operands[0],QImode) @@ -346,15 +380,6 @@ } }") -(define_insn "*movhi_sp" - [(set (match_operand:HI 0 "register_operand" "=q,r") - (match_operand:HI 1 "register_operand" "r,q"))] - "((stack_register_operand(operands[0], HImode) && register_operand (operands[1], HImode)) - || (register_operand (operands[0], HImode) && stack_register_operand(operands[1], HImode)))" - "* return output_movhi (insn, operands, NULL);" - [(set_attr "length" "5,2") - (set_attr "cc" "none,none")]) - (define_insn "movhi_sp_r_irq_off" [(set (match_operand:HI 0 "stack_register_operand" "=q") (unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r")] @@ -735,14 +760,22 @@ (plus:HI (match_operand:HI 1 "register_operand" "") (match_operand:HI 2 "nonmemory_operand" "")))] "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - short tmp = INTVAL (operands[2]); - operands[2] = GEN_INT(tmp); - } -}") + { + if (CONST_INT_P (operands[2])) + { + operands[2] = gen_int_mode (INTVAL (operands[2]), HImode); + + if (can_create_pseudo_p() + && !stack_register_operand (operands[0], HImode) + && !stack_register_operand (operands[1], HImode) + && !d_register_operand (operands[0], HImode) + && !d_register_operand (operands[1], HImode)) + { + emit_insn (gen_addhi3_clobber (operands[0], operands[1], operands[2])); + DONE; + } + } + }) (define_insn "*addhi3_zero_extend" @@ -767,184 +800,113 @@ [(set_attr "length" "2") (set_attr "cc" "set_n")]) -(define_insn "*addhi3_sp_R_pc2" +(define_insn "*addhi3_sp_R" [(set (match_operand:HI 1 "stack_register_operand" "=q") (plus:HI (match_operand:HI 2 "stack_register_operand" "q") (match_operand:HI 0 "avr_sp_immediate_operand" "R")))] - "AVR_2_BYTE_PC" - "*{ - if (CONST_INT_P (operands[0])) - { - switch(INTVAL (operands[0])) - { - case -6: - return \"rcall .\" CR_TAB - \"rcall .\" CR_TAB - \"rcall .\"; - case -5: - return \"rcall .\" CR_TAB - \"rcall .\" CR_TAB - \"push __tmp_reg__\"; - case -4: - return \"rcall .\" CR_TAB - \"rcall .\"; - case -3: - return \"rcall .\" CR_TAB - \"push __tmp_reg__\"; - case -2: - return \"rcall .\"; - case -1: - return \"push __tmp_reg__\"; - case 0: - return \"\"; - case 1: - return \"pop __tmp_reg__\"; - case 2: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - case 3: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - case 4: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - case 5: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - } - } - return \"bug\"; - }" - [(set (attr "length") - (cond [(eq (const_int -6) (symbol_ref "INTVAL (operands[0])")) (const_int 3) - (eq (const_int -5) (symbol_ref "INTVAL (operands[0])")) (const_int 3) - (eq (const_int -4) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int -3) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int -2) (symbol_ref "INTVAL (operands[0])")) (const_int 1) - (eq (const_int -1) (symbol_ref "INTVAL (operands[0])")) (const_int 1) - (eq (const_int 0) (symbol_ref "INTVAL (operands[0])")) (const_int 0) - (eq (const_int 1) (symbol_ref "INTVAL (operands[0])")) (const_int 1) - (eq (const_int 2) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int 3) (symbol_ref "INTVAL (operands[0])")) (const_int 3) - (eq (const_int 4) (symbol_ref "INTVAL (operands[0])")) (const_int 4) - (eq (const_int 5) (symbol_ref "INTVAL (operands[0])")) (const_int 5)] - (const_int 0)))]) - -(define_insn "*addhi3_sp_R_pc3" - [(set (match_operand:HI 1 "stack_register_operand" "=q") - (plus:HI (match_operand:HI 2 "stack_register_operand" "q") - (match_operand:QI 0 "avr_sp_immediate_operand" "R")))] - "AVR_3_BYTE_PC" - "*{ - if (CONST_INT_P (operands[0])) - { - switch(INTVAL (operands[0])) - { - case -6: - return \"rcall .\" CR_TAB - \"rcall .\"; - case -5: - return \"rcall .\" CR_TAB - \"push __tmp_reg__\" CR_TAB - \"push __tmp_reg__\"; - case -4: - return \"rcall .\" CR_TAB - \"push __tmp_reg__\"; - case -3: - return \"rcall .\"; - case -2: - return \"push __tmp_reg__\" CR_TAB - \"push __tmp_reg__\"; - case -1: - return \"push __tmp_reg__\"; - case 0: - return \"\"; - case 1: - return \"pop __tmp_reg__\"; - case 2: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - case 3: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - case 4: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - case 5: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - } - } - return \"bug\"; - }" - [(set (attr "length") - (cond [(eq (const_int -6) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int -5) (symbol_ref "INTVAL (operands[0])")) (const_int 3) - (eq (const_int -4) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int -3) (symbol_ref "INTVAL (operands[0])")) (const_int 1) - (eq (const_int -2) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int -1) (symbol_ref "INTVAL (operands[0])")) (const_int 1) - (eq (const_int 0) (symbol_ref "INTVAL (operands[0])")) (const_int 0) - (eq (const_int 1) (symbol_ref "INTVAL (operands[0])")) (const_int 1) - (eq (const_int 2) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int 3) (symbol_ref "INTVAL (operands[0])")) (const_int 3) - (eq (const_int 4) (symbol_ref "INTVAL (operands[0])")) (const_int 4) - (eq (const_int 5) (symbol_ref "INTVAL (operands[0])")) (const_int 5)] - (const_int 0)))]) + "" + { + return avr_out_addto_sp (operands, NULL); + } + [(set_attr "length" "5") + (set_attr "adjust_len" "addto_sp")]) (define_insn "*addhi3" - [(set (match_operand:HI 0 "register_operand" "=r,!w,!w,d,r,r") - (plus:HI - (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0") - (match_operand:HI 2 "nonmemory_operand" "r,I,J,i,P,N")))] + [(set (match_operand:HI 0 "register_operand" "=r,d,d") + (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0") + (match_operand:HI 2 "nonmemory_operand" "r,s,n")))] "" - "@ - add %A0,%A2\;adc %B0,%B2 - adiw %A0,%2 - sbiw %A0,%n2 - subi %A0,lo8(-(%2))\;sbci %B0,hi8(-(%2)) - sec\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__ - sec\;sbc %A0,__zero_reg__\;sbc %B0,__zero_reg__" - [(set_attr "length" "2,1,1,2,3,3") - (set_attr "cc" "set_n,set_czn,set_czn,set_czn,set_n,set_n")]) + { + static const char * const asm_code[] = + { + "add %A0,%A2\;adc %B0,%B2", + "subi %A0,lo8(-(%2))\;sbci %B0,hi8(-(%2))", + "" + }; + + if (*asm_code[which_alternative]) + return asm_code[which_alternative]; + + return avr_out_plus_noclobber (operands, NULL, NULL); + } + [(set_attr "length" "2,2,2") + (set_attr "adjust_len" "*,*,out_plus_noclobber") + (set_attr "cc" "set_n,set_czn,out_plus_noclobber")]) + +;; Adding a constant to NO_LD_REGS might have lead to a reload of +;; that constant to LD_REGS. We don't add a scratch to *addhi3 +;; itself because that insn is special to reload. + +(define_peephole2 ; addhi3_clobber + [(set (match_operand:HI 0 "d_register_operand" "") + (match_operand:HI 1 "const_int_operand" "")) + (set (match_operand:HI 2 "l_register_operand" "") + (plus:HI (match_dup 2) + (match_dup 0)))] + "peep2_reg_dead_p (2, operands[0])" + [(parallel [(set (match_dup 2) + (plus:HI (match_dup 2) + (match_dup 1))) + (clobber (match_dup 3))])] + { + operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 0); + }) + +;; Same, but with reload to NO_LD_REGS +;; Combine *reload_inhi with *addhi3 + +(define_peephole2 ; addhi3_clobber + [(parallel [(set (match_operand:HI 0 "l_register_operand" "") + (match_operand:HI 1 "const_int_operand" "")) + (clobber (match_operand:QI 2 "d_register_operand" ""))]) + (set (match_operand:HI 3 "l_register_operand" "") + (plus:HI (match_dup 3) + (match_dup 0)))] + "peep2_reg_dead_p (2, operands[0])" + [(parallel [(set (match_dup 3) + (plus:HI (match_dup 3) + (match_dup 1))) + (clobber (match_dup 2))])]) + +(define_insn "addhi3_clobber" + [(set (match_operand:HI 0 "register_operand" "=d,l") + (plus:HI (match_operand:HI 1 "register_operand" "%0,0") + (match_operand:HI 2 "const_int_operand" "n,n"))) + (clobber (match_scratch:QI 3 "=X,&d"))] + "" + { + gcc_assert (REGNO (operands[0]) == REGNO (operands[1])); + + return avr_out_plus (operands, NULL, NULL); + } + [(set_attr "length" "4") + (set_attr "adjust_len" "out_plus") + (set_attr "cc" "out_plus")]) + (define_insn "addsi3" - [(set (match_operand:SI 0 "register_operand" "=r,!w,!w,d,l,l ,d,r") - (plus:SI (match_operand:SI 1 "register_operand" "%0,0 ,0 ,0,0,0 ,0,0") - (match_operand:SI 2 "nonmemory_operand" "r,I ,J ,s,P,N ,n,n"))) - (clobber (match_scratch:QI 3 "=X,X ,X ,X,X,X ,X,&d"))] + [(set (match_operand:SI 0 "register_operand" "=r,d ,d,r") + (plus:SI (match_operand:SI 1 "register_operand" "%0,0 ,0,0") + (match_operand:SI 2 "nonmemory_operand" "r,s ,n,n"))) + (clobber (match_scratch:QI 3 "=X,X ,X,&d"))] "" { static const char * const asm_code[] = { "add %A0,%A2\;adc %B0,%B2\;adc %C0,%C2\;adc %D0,%D2", - "adiw %0,%2\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__", - "sbiw %0,%n2\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__", "subi %0,lo8(-(%2))\;sbci %B0,hi8(-(%2))\;sbci %C0,hlo8(-(%2))\;sbci %D0,hhi8(-(%2))", - "sec\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__", - "sec\;sbc %A0,__zero_reg__\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__" + "", + "" }; - if (which_alternative >= (signed) (sizeof (asm_code) / sizeof (*asm_code))) - return avr_out_plus (operands, NULL); + if (*asm_code[which_alternative]) + return asm_code [which_alternative]; - return asm_code [which_alternative]; + return avr_out_plus (operands, NULL, NULL); } - [(set_attr "length" "4,3,3,4,5,5,8,8") - (set_attr "adjust_len" "*,*,*,*,*,*,out_plus,out_plus") - (set_attr "cc" "set_n,set_n,set_czn,set_czn,set_n,set_n,clobber,clobber")]) + [(set_attr "length" "4,4,4,8") + (set_attr "adjust_len" "*,*,out_plus,out_plus") + (set_attr "cc" "set_n,set_czn,out_plus,out_plus")]) (define_insn "*addsi3_zero_extend" [(set (match_operand:SI 0 "register_operand" "=r") @@ -1695,13 +1657,11 @@ (mult:HI (match_operand:HI 1 "register_operand" "r") (match_operand:HI 2 "register_operand" "r")))] "AVR_HAVE_MUL" - "mul %A1,%A2 - movw %0,r0 - mul %A1,%B2 - add %B0,r0 - mul %B1,%A2 - add %B0,r0 - clr r1" + { + return REGNO (operands[1]) == REGNO (operands[2]) + ? "mul %A1,%A1\;movw %0,r0\;mul %A1,%B1\;add %B0,r0\;add %B0,r0\;clr r1" + : "mul %A1,%A2\;movw %0,r0\;mul %A1,%B2\;add %B0,r0\;mul %B1,%A2\;add %B0,r0\;clr r1"; + } [(set_attr "length" "7") (set_attr "cc" "clobber")]) @@ -3087,20 +3047,17 @@ (set_attr "cc" "set_czn,set_n,set_czn")]) (define_insn "negsi2" - [(set (match_operand:SI 0 "register_operand" "=!d,r,&r") - (neg:SI (match_operand:SI 1 "register_operand" "0,0,r")))] + [(set (match_operand:SI 0 "register_operand" "=!d,r,&r,&r") + (neg:SI (match_operand:SI 1 "register_operand" "0,0,r ,r")))] "" "@ com %D0\;com %C0\;com %B0\;neg %A0\;sbci %B0,lo8(-1)\;sbci %C0,lo8(-1)\;sbci %D0,lo8(-1) com %D0\;com %C0\;com %B0\;com %A0\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__ - clr %A0\;clr %B0\;{clr %C0\;clr %D0|movw %C0,%A0}\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1" - [(set_attr_alternative "length" - [(const_int 7) - (const_int 8) - (if_then_else (eq_attr "mcu_have_movw" "yes") - (const_int 7) - (const_int 8))]) - (set_attr "cc" "set_czn,set_n,set_czn")]) + clr %A0\;clr %B0\;clr %C0\;clr %D0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1 + clr %A0\;clr %B0\;movw %C0,%A0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1" + [(set_attr "length" "7,8,8,7") + (set_attr "isa" "*,*,mov,movw") + (set_attr "cc" "set_czn,set_n,set_czn,set_czn")]) (define_insn "negsf2" [(set (match_operand:SF 0 "register_operand" "=d,r") @@ -3174,18 +3131,16 @@ (set_attr "cc" "set_n,set_n")]) (define_insn "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r")))] + [(set (match_operand:SI 0 "register_operand" "=r,r ,r") + (sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r,*r")))] "" "@ clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0 - {mov %A0,%A1\;mov %B0,%B1|movw %A0,%A1}\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0" - [(set_attr_alternative "length" - [(const_int 4) - (if_then_else (eq_attr "mcu_have_movw" "yes") - (const_int 5) - (const_int 6))]) - (set_attr "cc" "set_n,set_n")]) + mov %A0,%A1\;mov %B0,%B1\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0 + movw %A0,%A1\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0" + [(set_attr "length" "4,6,5") + (set_attr "isa" "*,mov,movw") + (set_attr "cc" "set_n")]) ;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x ;; zero extend @@ -3494,7 +3449,7 @@ (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046)) (le (minus (pc) (match_dup 3)) (const_int 2046))) (const_int 2) - (if_then_else (eq_attr "mcu_mega" "no") + (if_then_else (match_test "!AVR_HAVE_JMP_CALL") (const_int 2) (const_int 4)))) (set_attr "cc" "clobber")]) @@ -3524,7 +3479,7 @@ (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046)) (le (minus (pc) (match_dup 3)) (const_int 2046))) (const_int 2) - (if_then_else (eq_attr "mcu_mega" "no") + (if_then_else (match_test "!AVR_HAVE_JMP_CALL") (const_int 2) (const_int 4)))) (set_attr "cc" "clobber")]) @@ -3707,20 +3662,20 @@ [(set (pc) (label_ref (match_operand 0 "" "")))] "" - "*{ - if (AVR_HAVE_JMP_CALL && get_attr_length (insn) != 1) - return AS1 (jmp,%x0); - return AS1 (rjmp,%x0); -}" + { + return AVR_HAVE_JMP_CALL && get_attr_length (insn) != 1 + ? "jmp %x0" + : "rjmp %x0"; + } [(set (attr "length") (if_then_else (match_operand 0 "symbol_ref_operand" "") - (if_then_else (eq_attr "mcu_mega" "no") - (const_int 1) - (const_int 2)) - (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -2047)) - (le (minus (pc) (match_dup 0)) (const_int 2047))) - (const_int 1) - (const_int 2)))) + (if_then_else (match_test "!AVR_HAVE_JMP_CALL") + (const_int 1) + (const_int 2)) + (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -2047)) + (le (minus (pc) (match_dup 0)) (const_int 2047))) + (const_int 1) + (const_int 2)))) (set_attr "cc" "none")]) ;; call @@ -3765,7 +3720,7 @@ "" "") -(define_insn "*call_insn" +(define_insn "call_insn" [(parallel[(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "z,s,z,s")) (match_operand:HI 1 "general_operand" "X,X,X,X")) (use (match_operand:HI 2 "const_int_operand" "L,L,P,P"))])] @@ -3778,17 +3733,10 @@ %!ijmp %~jmp %x0" [(set_attr "cc" "clobber") - (set_attr_alternative "length" - [(const_int 1) - (if_then_else (eq_attr "mcu_mega" "yes") - (const_int 2) - (const_int 1)) - (const_int 1) - (if_then_else (eq_attr "mcu_mega" "yes") - (const_int 2) - (const_int 1))])]) + (set_attr "length" "1,*,1,*") + (set_attr "adjust_len" "*,call,*,call")]) -(define_insn "*call_value_insn" +(define_insn "call_value_insn" [(parallel[(set (match_operand 0 "register_operand" "=r,r,r,r") (call (mem:HI (match_operand:HI 1 "nonmemory_operand" "z,s,z,s")) (match_operand:HI 2 "general_operand" "X,X,X,X"))) @@ -3802,15 +3750,8 @@ %!ijmp %~jmp %x1" [(set_attr "cc" "clobber") - (set_attr_alternative "length" - [(const_int 1) - (if_then_else (eq_attr "mcu_mega" "yes") - (const_int 2) - (const_int 1)) - (const_int 1) - (if_then_else (eq_attr "mcu_mega" "yes") - (const_int 2) - (const_int 1))])]) + (set_attr "length" "1,*,1,*") + (set_attr "adjust_len" "*,call,*,call")]) (define_insn "nop" [(const_int 0)] @@ -3822,96 +3763,52 @@ ; indirect jump (define_expand "indirect_jump" - [(set (pc) (match_operand:HI 0 "nonmemory_operand" ""))] + [(set (pc) + (match_operand:HI 0 "nonmemory_operand" ""))] "" - " if ((!AVR_HAVE_JMP_CALL) && !register_operand(operand0, HImode)) - { - operands[0] = copy_to_mode_reg(HImode, operand0); - }" -) + { + if (!AVR_HAVE_JMP_CALL && !register_operand (operands[0], HImode)) + { + operands[0] = copy_to_mode_reg (HImode, operands[0]); + } + }) ; indirect jump -(define_insn "*jcindirect_jump" - [(set (pc) (match_operand:HI 0 "immediate_operand" "i"))] +(define_insn "*indirect_jump" + [(set (pc) + (match_operand:HI 0 "nonmemory_operand" "i,i,!z,*r,z"))] "" - "%~jmp %x0" - [(set_attr "length" "2") - (set_attr "cc" "none")]) - -;; -(define_insn "*njcindirect_jump" - [(set (pc) (match_operand:HI 0 "register_operand" "!z,*r"))] - "!AVR_HAVE_EIJMP_EICALL" "@ + rjmp %x0 + jmp %x0 ijmp - push %A0\;push %B0\;ret" - [(set_attr "length" "1,3") - (set_attr "cc" "none,none")]) - -(define_insn "*indirect_jump_avr6" - [(set (pc) (match_operand:HI 0 "register_operand" "z"))] - "AVR_HAVE_EIJMP_EICALL" - "eijmp" - [(set_attr "length" "1") + push %A0\;push %B0\;ret + eijmp" + [(set_attr "length" "1,2,1,3,1") + (set_attr "isa" "rjmp,jmp,ijmp,ijmp,eijmp") (set_attr "cc" "none")]) ;; table jump +;; For entries in jump table see avr_output_addr_vec_elt. -;; Table made from "rjmp" instructions for <=8K devices. -(define_insn "*tablejump_rjmp" - [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r")] - UNSPEC_INDEX_JMP)) +;; Table made from +;; "rjmp .L<n>" instructions for <= 8K devices +;; ".word gs(.L<n>)" addresses for > 8K devices +(define_insn "*tablejump" + [(set (pc) + (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r,z")] + UNSPEC_INDEX_JMP)) (use (label_ref (match_operand 1 "" ""))) (clobber (match_dup 0))] - "(!AVR_HAVE_JMP_CALL) && (!AVR_HAVE_EIJMP_EICALL)" + "" "@ ijmp - push %A0\;push %B0\;ret" - [(set_attr "length" "1,3") - (set_attr "cc" "none,none")]) - -;; Not a prologue, but similar idea - move the common piece of code to libgcc. -(define_insn "*tablejump_lib" - [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")] - UNSPEC_INDEX_JMP)) - (use (label_ref (match_operand 1 "" ""))) - (clobber (match_dup 0))] - "AVR_HAVE_JMP_CALL && TARGET_CALL_PROLOGUES" - "%~jmp __tablejump2__" - [(set_attr "length" "2") - (set_attr "cc" "clobber")]) + push %A0\;push %B0\;ret + jmp __tablejump2__" + [(set_attr "length" "1,3,2") + (set_attr "isa" "rjmp,rjmp,jmp") + (set_attr "cc" "none,none,clobber")]) -(define_insn "*tablejump_enh" - [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")] - UNSPEC_INDEX_JMP)) - (use (label_ref (match_operand 1 "" ""))) - (clobber (match_dup 0))] - "AVR_HAVE_JMP_CALL && AVR_HAVE_LPMX" - "lsl r30 - rol r31 - lpm __tmp_reg__,Z+ - lpm r31,Z - mov r30,__tmp_reg__ - %!ijmp" - [(set_attr "length" "6") - (set_attr "cc" "clobber")]) - -(define_insn "*tablejump" - [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")] - UNSPEC_INDEX_JMP)) - (use (label_ref (match_operand 1 "" ""))) - (clobber (match_dup 0))] - "AVR_HAVE_JMP_CALL && !AVR_HAVE_EIJMP_EICALL" - "lsl r30 - rol r31 - lpm - inc r30 - push r0 - lpm - push r0 - ret" - [(set_attr "length" "8") - (set_attr "cc" "clobber")]) (define_expand "casesi" [(set (match_dup 6) @@ -3993,11 +3890,11 @@ "* return avr_out_sbxx_branch (insn, operands);" [(set (attr "length") (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046)) - (le (minus (pc) (match_dup 3)) (const_int 2046))) - (const_int 2) - (if_then_else (eq_attr "mcu_mega" "no") - (const_int 2) - (const_int 4)))) + (le (minus (pc) (match_dup 3)) (const_int 2046))) + (const_int 2) + (if_then_else (match_test "!AVR_HAVE_JMP_CALL") + (const_int 2) + (const_int 4)))) (set_attr "cc" "clobber")]) ;; Tests of bit 7 are pessimized to sign tests, so we need this too... @@ -4017,11 +3914,11 @@ } [(set (attr "length") (if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046)) - (le (minus (pc) (match_dup 2)) (const_int 2046))) - (const_int 2) - (if_then_else (eq_attr "mcu_mega" "no") - (const_int 2) - (const_int 4)))) + (le (minus (pc) (match_dup 2)) (const_int 2046))) + (const_int 2) + (if_then_else (match_test "!AVR_HAVE_JMP_CALL") + (const_int 2) + (const_int 4)))) (set_attr "cc" "clobber")]) ;; Upper half of the I/O space - read port to __tmp_reg__ and use sbrc/sbrs. @@ -4040,11 +3937,11 @@ "* return avr_out_sbxx_branch (insn, operands);" [(set (attr "length") (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046)) - (le (minus (pc) (match_dup 3)) (const_int 2045))) - (const_int 3) - (if_then_else (eq_attr "mcu_mega" "no") - (const_int 3) - (const_int 5)))) + (le (minus (pc) (match_dup 3)) (const_int 2045))) + (const_int 3) + (if_then_else (match_test "!AVR_HAVE_JMP_CALL") + (const_int 3) + (const_int 5)))) (set_attr "cc" "clobber")]) (define_insn "*sbix_branch_tmp_bit7" @@ -4065,7 +3962,7 @@ (if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046)) (le (minus (pc) (match_dup 2)) (const_int 2045))) (const_int 3) - (if_then_else (eq_attr "mcu_mega" "no") + (if_then_else (match_test "!AVR_HAVE_JMP_CALL") (const_int 3) (const_int 5)))) (set_attr "cc" "clobber")]) @@ -4228,10 +4125,10 @@ ;; Library prologue saves (define_insn "call_prologue_saves" [(unspec_volatile:HI [(const_int 0)] UNSPECV_PROLOGUE_SAVES) - (match_operand:HI 0 "immediate_operand" "") - (set (reg:HI REG_SP) (minus:HI - (reg:HI REG_SP) - (match_operand:HI 1 "immediate_operand" ""))) + (match_operand:HI 0 "immediate_operand" "i,i") + (set (reg:HI REG_SP) + (minus:HI (reg:HI REG_SP) + (match_operand:HI 1 "immediate_operand" "i,i"))) (use (reg:HI REG_X)) (clobber (reg:HI REG_Z))] "" @@ -4239,30 +4136,26 @@ ldi r31,hi8(gs(1f)) %~jmp __prologue_saves__+((18 - %0) * 2) 1:" - [(set_attr_alternative "length" - [(if_then_else (eq_attr "mcu_mega" "yes") - (const_int 6) - (const_int 5))]) - (set_attr "cc" "clobber") - ]) + [(set_attr "length" "5,6") + (set_attr "cc" "clobber") + (set_attr "isa" "rjmp,jmp")]) ; epilogue restores using library (define_insn "epilogue_restores" [(unspec_volatile:QI [(const_int 0)] UNSPECV_EPILOGUE_RESTORES) - (set (reg:HI REG_Y ) (plus:HI - (reg:HI REG_Y) - (match_operand:HI 0 "immediate_operand" ""))) - (set (reg:HI REG_SP) (reg:HI REG_Y)) - (clobber (reg:QI REG_Z))] + (set (reg:HI REG_Y) + (plus:HI (reg:HI REG_Y) + (match_operand:HI 0 "immediate_operand" "i,i"))) + (set (reg:HI REG_SP) + (plus:HI (reg:HI REG_Y) + (match_dup 0))) + (clobber (reg:QI REG_Z))] "" "ldi r30, lo8(%0) %~jmp __epilogue_restores__ + ((18 - %0) * 2)" - [(set_attr_alternative "length" - [(if_then_else (eq_attr "mcu_mega" "yes") - (const_int 3) - (const_int 2))]) - (set_attr "cc" "clobber") - ]) + [(set_attr "length" "2,3") + (set_attr "cc" "clobber") + (set_attr "isa" "rjmp,jmp")]) ; return (define_insn "return" @@ -4304,11 +4197,10 @@ (define_expand "prologue" [(const_int 0)] "" - " { expand_prologue (); DONE; - }") + }) (define_expand "epilogue" [(const_int 0)] |