Mercurial > hg > CbC > CbC_gcc
diff gcc/config/avr/avr.md @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | b7f97abdc517 |
line wrap: on
line diff
--- a/gcc/config/avr/avr.md Sun Feb 07 18:28:00 2010 +0900 +++ b/gcc/config/avr/avr.md Fri Feb 12 23:39:51 2010 +0900 @@ -3,7 +3,7 @@ ;; for ATMEL AVR micro controllers. ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, ;; 2009 Free Software Foundation, Inc. -;; Contributed by Denis Chertykov (denisc@overta.ru) +;; Contributed by Denis Chertykov (chertykov@gmail.com) ;; This file is part of GCC. @@ -28,9 +28,11 @@ ;; D Add 3. ;; j Branch condition. ;; k Reverse branch condition. +;;..m..Constant Direct Data memory address. ;; o Displacement for (mem (plus (reg) (const_int))) operands. ;; p POST_INC or PRE_DEC address as a pointer (X, Y, Z) ;; r POST_INC or PRE_DEC address as a register (r26, r28, r30) +;;..x..Constant Direct Program memory address. ;; ~ Output 'r' if not AVR_HAVE_JMP_CALL. ;; ! Output 'e' if AVR_HAVE_EIJMP_EICALL. @@ -118,6 +120,7 @@ ;; Define mode iterator (define_mode_iterator QISI [(QI "") (HI "") (SI "")]) +(define_mode_iterator QIDI [(QI "") (HI "") (SI "") (DI "")]) ;;======================================================================== ;; The following is used by nonlocal_goto and setjmp. @@ -235,7 +238,7 @@ (define_insn "*movqi" [(set (match_operand:QI 0 "nonimmediate_operand" "=r,d,Qm,r,q,r,*r") - (match_operand:QI 1 "general_operand" "r,i,rL,Qm,r,q,i"))] + (match_operand:QI 1 "general_operand" "rL,i,rL,Qm,r,q,i"))] "(register_operand (operands[0],QImode) || register_operand (operands[1], QImode) || const0_rtx == operands[1])" "* return output_movqi (insn, operands, NULL);" @@ -336,7 +339,7 @@ (define_insn "*movhi" [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,d,*r,q,r") - (match_operand:HI 1 "general_operand" "r,m,rL,i,i,r,q"))] + (match_operand:HI 1 "general_operand" "rL,m,rL,i,i,r,q"))] "(register_operand (operands[0],HImode) || register_operand (operands[1],HImode) || const0_rtx == operands[1])" "* return output_movhi (insn, operands, NULL);" @@ -507,9 +510,7 @@ label); /* Set jump probability based on loop count. */ jump = get_last_insn (); - REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB, - GEN_INT (prob), - REG_NOTES (jump)); + add_reg_note (jump, REG_BR_PROB, GEN_INT (prob)); DONE; }") @@ -1053,17 +1054,30 @@ ;; - we know exactly which registers are clobbered (for QI and HI ;; modes, some of the call-used registers are preserved) ;; - we get both the quotient and the remainder at no extra cost - -(define_expand "divmodqi4" - [(set (reg:QI 24) (match_operand:QI 1 "register_operand" "")) - (set (reg:QI 22) (match_operand:QI 2 "register_operand" "")) +;; - we split the patterns only after the first CSE passes because +;; CSE has problems to operate on hard regs. +;; +(define_insn_and_split "divmodqi4" + [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "") + (div:QI (match_operand:QI 1 "pseudo_register_operand" "") + (match_operand:QI 2 "pseudo_register_operand" ""))) + (set (match_operand:QI 3 "pseudo_register_operand" "") + (mod:QI (match_dup 1) (match_dup 2))) + (clobber (reg:QI 22)) + (clobber (reg:QI 23)) + (clobber (reg:QI 24)) + (clobber (reg:QI 25))])] + "" + "this divmodqi4 pattern should have been splitted;" + "" + [(set (reg:QI 24) (match_dup 1)) + (set (reg:QI 22) (match_dup 2)) (parallel [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22))) (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22))) (clobber (reg:QI 22)) (clobber (reg:QI 23))]) - (set (match_operand:QI 0 "register_operand" "") (reg:QI 24)) - (set (match_operand:QI 3 "register_operand" "") (reg:QI 25))] - "" + (set (match_dup 0) (reg:QI 24)) + (set (match_dup 3) (reg:QI 25))] "") (define_insn "*divmodqi4_call" @@ -1076,15 +1090,26 @@ [(set_attr "type" "xcall") (set_attr "cc" "clobber")]) -(define_expand "udivmodqi4" - [(set (reg:QI 24) (match_operand:QI 1 "register_operand" "")) - (set (reg:QI 22) (match_operand:QI 2 "register_operand" "")) +(define_insn_and_split "udivmodqi4" + [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "") + (udiv:QI (match_operand:QI 1 "pseudo_register_operand" "") + (match_operand:QI 2 "pseudo_register_operand" ""))) + (set (match_operand:QI 3 "pseudo_register_operand" "") + (umod:QI (match_dup 1) (match_dup 2))) + (clobber (reg:QI 22)) + (clobber (reg:QI 23)) + (clobber (reg:QI 24)) + (clobber (reg:QI 25))])] + "" + "this udivmodqi4 pattern should have been splitted;" + "" + [(set (reg:QI 24) (match_dup 1)) + (set (reg:QI 22) (match_dup 2)) (parallel [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22))) (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22))) (clobber (reg:QI 23))]) - (set (match_operand:QI 0 "register_operand" "") (reg:QI 24)) - (set (match_operand:QI 3 "register_operand" "") (reg:QI 25))] - "" + (set (match_dup 0) (reg:QI 24)) + (set (match_dup 3) (reg:QI 25))] "") (define_insn "*udivmodqi4_call" @@ -1096,17 +1121,28 @@ [(set_attr "type" "xcall") (set_attr "cc" "clobber")]) -(define_expand "divmodhi4" - [(set (reg:HI 24) (match_operand:HI 1 "register_operand" "")) - (set (reg:HI 22) (match_operand:HI 2 "register_operand" "")) +(define_insn_and_split "divmodhi4" + [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "") + (div:HI (match_operand:HI 1 "pseudo_register_operand" "") + (match_operand:HI 2 "pseudo_register_operand" ""))) + (set (match_operand:HI 3 "pseudo_register_operand" "") + (mod:HI (match_dup 1) (match_dup 2))) + (clobber (reg:QI 21)) + (clobber (reg:HI 22)) + (clobber (reg:HI 24)) + (clobber (reg:HI 26))])] + "" + "this should have been splitted;" + "" + [(set (reg:HI 24) (match_dup 1)) + (set (reg:HI 22) (match_dup 2)) (parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22))) (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22))) (clobber (reg:HI 26)) (clobber (reg:QI 21))]) - (set (match_operand:HI 0 "register_operand" "") (reg:HI 22)) - (set (match_operand:HI 3 "register_operand" "") (reg:HI 24))] - "" - "") + (set (match_dup 0) (reg:HI 22)) + (set (match_dup 3) (reg:HI 24))] + "") (define_insn "*divmodhi4_call" [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22))) @@ -1118,16 +1154,27 @@ [(set_attr "type" "xcall") (set_attr "cc" "clobber")]) -(define_expand "udivmodhi4" - [(set (reg:HI 24) (match_operand:HI 1 "register_operand" "")) - (set (reg:HI 22) (match_operand:HI 2 "register_operand" "")) +(define_insn_and_split "udivmodhi4" + [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "") + (udiv:HI (match_operand:HI 1 "pseudo_register_operand" "") + (match_operand:HI 2 "pseudo_register_operand" ""))) + (set (match_operand:HI 3 "pseudo_register_operand" "") + (umod:HI (match_dup 1) (match_dup 2))) + (clobber (reg:QI 21)) + (clobber (reg:HI 22)) + (clobber (reg:HI 24)) + (clobber (reg:HI 26))])] + "" + "this udivmodhi4 pattern should have been splitted.;" + "" + [(set (reg:HI 24) (match_dup 1)) + (set (reg:HI 22) (match_dup 2)) (parallel [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22))) (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22))) (clobber (reg:HI 26)) (clobber (reg:QI 21))]) - (set (match_operand:HI 0 "register_operand" "") (reg:HI 22)) - (set (match_operand:HI 3 "register_operand" "") (reg:HI 24))] - "" + (set (match_dup 0) (reg:HI 22)) + (set (match_dup 3) (reg:HI 24))] "") (define_insn "*udivmodhi4_call" @@ -1140,16 +1187,27 @@ [(set_attr "type" "xcall") (set_attr "cc" "clobber")]) -(define_expand "divmodsi4" - [(set (reg:SI 22) (match_operand:SI 1 "register_operand" "")) - (set (reg:SI 18) (match_operand:SI 2 "register_operand" "")) +(define_insn_and_split "divmodsi4" + [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") + (div:SI (match_operand:SI 1 "pseudo_register_operand" "") + (match_operand:SI 2 "pseudo_register_operand" ""))) + (set (match_operand:SI 3 "pseudo_register_operand" "") + (mod:SI (match_dup 1) (match_dup 2))) + (clobber (reg:SI 18)) + (clobber (reg:SI 22)) + (clobber (reg:HI 26)) + (clobber (reg:HI 30))])] + "" + "this divmodsi4 pattern should have been splitted;" + "" + [(set (reg:SI 22) (match_dup 1)) + (set (reg:SI 18) (match_dup 2)) (parallel [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18))) (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18))) (clobber (reg:HI 26)) (clobber (reg:HI 30))]) - (set (match_operand:SI 0 "register_operand" "") (reg:SI 18)) - (set (match_operand:SI 3 "register_operand" "") (reg:SI 22))] - "" + (set (match_dup 0) (reg:SI 18)) + (set (match_dup 3) (reg:SI 22))] "") (define_insn "*divmodsi4_call" @@ -1162,16 +1220,27 @@ [(set_attr "type" "xcall") (set_attr "cc" "clobber")]) -(define_expand "udivmodsi4" - [(set (reg:SI 22) (match_operand:SI 1 "register_operand" "")) - (set (reg:SI 18) (match_operand:SI 2 "register_operand" "")) +(define_insn_and_split "udivmodsi4" + [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") + (udiv:SI (match_operand:SI 1 "pseudo_register_operand" "") + (match_operand:SI 2 "pseudo_register_operand" ""))) + (set (match_operand:SI 3 "pseudo_register_operand" "") + (umod:SI (match_dup 1) (match_dup 2))) + (clobber (reg:SI 18)) + (clobber (reg:SI 22)) + (clobber (reg:HI 26)) + (clobber (reg:HI 30))])] + "" + "this udivmodsi4 pattern should have been splitted;" + "" + [(set (reg:SI 22) (match_dup 1)) + (set (reg:SI 18) (match_dup 2)) (parallel [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18))) (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18))) (clobber (reg:HI 26)) (clobber (reg:HI 30))]) - (set (match_operand:SI 0 "register_operand" "") (reg:SI 18)) - (set (match_operand:SI 3 "register_operand" "") (reg:SI 22))] - "" + (set (match_dup 0) (reg:SI 18)) + (set (match_dup 3) (reg:SI 22))] "") (define_insn "*udivmodsi4_call" @@ -1204,10 +1273,10 @@ (match_operand:HI 2 "nonmemory_operand" "r,i,M"))) (clobber (match_scratch:QI 3 "=X,X,&d"))] "" - "*{ +{ if (which_alternative==0) - return (AS2 (and,%A0,%A2) CR_TAB - AS2 (and,%B0,%B2)); + return ("and %A0,%A2" CR_TAB + "and %B0,%B2"); else if (which_alternative==1) { if (GET_CODE (operands[2]) == CONST_INT) @@ -1217,15 +1286,15 @@ output_asm_insn (AS2 (andi,%A0,lo8(%2)), operands); if ((mask & 0xff00) != 0xff00) output_asm_insn (AS2 (andi,%B0,hi8(%2)), operands); - return \"\"; + return ""; } return (AS2 (andi,%A0,lo8(%2)) CR_TAB AS2 (andi,%B0,hi8(%2))); } return (AS2 (ldi,%3,lo8(%2)) CR_TAB - AS2 (and,%A0,%3) CR_TAB + "and %A0,%3" CR_TAB AS1 (clr,%B0)); -}" +} [(set_attr "length" "2,2,3") (set_attr "cc" "set_n,clobber,set_n")]) @@ -1234,12 +1303,12 @@ (and:SI (match_operand:SI 1 "register_operand" "%0,0") (match_operand:SI 2 "nonmemory_operand" "r,i")))] "" - "*{ +{ if (which_alternative==0) - return (AS2 (and, %0,%2) CR_TAB - AS2 (and, %B0,%B2) CR_TAB - AS2 (and, %C0,%C2) CR_TAB - AS2 (and, %D0,%D2)); + return ("and %0,%2" CR_TAB + "and %B0,%B2" CR_TAB + "and %C0,%C2" CR_TAB + "and %D0,%D2"); else if (which_alternative==1) { if (GET_CODE (operands[2]) == CONST_INT) @@ -1253,15 +1322,15 @@ output_asm_insn (AS2 (andi,%C0,hlo8(%2)), operands); if ((mask & 0xff000000L) != 0xff000000L) output_asm_insn (AS2 (andi,%D0,hhi8(%2)), operands); - return \"\"; + return ""; } return (AS2 (andi, %A0,lo8(%2)) CR_TAB AS2 (andi, %B0,hi8(%2)) CR_TAB AS2 (andi, %C0,hlo8(%2)) CR_TAB AS2 (andi, %D0,hhi8(%2))); } - return \"bug\"; -}" + return "bug"; +} [(set_attr "length" "4,4") (set_attr "cc" "set_n,clobber")]) @@ -1297,10 +1366,10 @@ (ior:HI (match_operand:HI 1 "register_operand" "%0,0") (match_operand:HI 2 "nonmemory_operand" "r,i")))] "" - "*{ +{ if (which_alternative==0) - return (AS2 (or,%A0,%A2) CR_TAB - AS2 (or,%B0,%B2)); + return ("or %A0,%A2" CR_TAB + "or %B0,%B2"); if (GET_CODE (operands[2]) == CONST_INT) { int mask = INTVAL (operands[2]); @@ -1308,11 +1377,11 @@ output_asm_insn (AS2 (ori,%A0,lo8(%2)), operands); if (mask & 0xff00) output_asm_insn (AS2 (ori,%B0,hi8(%2)), operands); - return \"\"; + return ""; } return (AS2 (ori,%0,lo8(%2)) CR_TAB AS2 (ori,%B0,hi8(%2))); -}" +} [(set_attr "length" "2,2") (set_attr "cc" "set_n,clobber")]) @@ -1333,12 +1402,12 @@ (ior:SI (match_operand:SI 1 "register_operand" "%0,0") (match_operand:SI 2 "nonmemory_operand" "r,i")))] "" - "*{ +{ if (which_alternative==0) - return (AS2 (or, %0,%2) CR_TAB - AS2 (or, %B0,%B2) CR_TAB - AS2 (or, %C0,%C2) CR_TAB - AS2 (or, %D0,%D2)); + return ("or %0,%2" CR_TAB + "or %B0,%B2" CR_TAB + "or %C0,%C2" CR_TAB + "or %D0,%D2"); if (GET_CODE (operands[2]) == CONST_INT) { HOST_WIDE_INT mask = INTVAL (operands[2]); @@ -1350,13 +1419,13 @@ output_asm_insn (AS2 (ori,%C0,hlo8(%2)), operands); if (mask & 0xff000000L) output_asm_insn (AS2 (ori,%D0,hhi8(%2)), operands); - return \"\"; + return ""; } return (AS2 (ori, %A0,lo8(%2)) CR_TAB AS2 (ori, %B0,hi8(%2)) CR_TAB AS2 (ori, %C0,hlo8(%2)) CR_TAB AS2 (ori, %D0,hhi8(%2))); -}" +} [(set_attr "length" "4,4") (set_attr "cc" "set_n,clobber")]) @@ -2202,53 +2271,65 @@ ;;<=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=> ;; compare -(define_insn "tstqi" +; Optimize negated tests into reverse compare if overflow is undefined. +(define_insn "*negated_tstqi" [(set (cc0) - (match_operand:QI 0 "register_operand" "r"))] - "" - "tst %0" + (compare (neg:QI (match_operand:QI 0 "register_operand" "r")) + (const_int 0)))] + "(!flag_wrapv && !flag_trapv && flag_strict_overflow)" + "cp __zero_reg__,%0" [(set_attr "cc" "compare") (set_attr "length" "1")]) (define_insn "*reversed_tstqi" [(set (cc0) - (compare (const_int 0) + (compare (const_int 0) (match_operand:QI 0 "register_operand" "r")))] "" "cp __zero_reg__,%0" - [(set_attr "cc" "compare") - (set_attr "length" "1")]) - -(define_insn "tsthi" +[(set_attr "cc" "compare") + (set_attr "length" "2")]) + +(define_insn "*negated_tsthi" [(set (cc0) - (match_operand:HI 0 "register_operand" "!w,r"))] - "" - "* return out_tsthi (insn,NULL);" -[(set_attr "cc" "compare,compare") - (set_attr "length" "1,2")]) - + (compare (neg:HI (match_operand:HI 0 "register_operand" "r")) + (const_int 0)))] + "(!flag_wrapv && !flag_trapv && flag_strict_overflow)" + "cp __zero_reg__,%A0 + cpc __zero_reg__,%B0" +[(set_attr "cc" "compare") + (set_attr "length" "2")]) + +;; Leave here the clobber used by the cmphi pattern for simplicity, even +;; though it is unused, because this pattern is synthesized by avr_reorg. (define_insn "*reversed_tsthi" [(set (cc0) (compare (const_int 0) - (match_operand:HI 0 "register_operand" "r")))] + (match_operand:HI 0 "register_operand" "r"))) + (clobber (match_scratch:QI 1 "=X"))] "" "cp __zero_reg__,%A0 cpc __zero_reg__,%B0" [(set_attr "cc" "compare") (set_attr "length" "2")]) -(define_insn "tstsi" +(define_insn "*negated_tstsi" [(set (cc0) - (match_operand:SI 0 "register_operand" "r"))] - "" - "* return out_tstsi (insn,NULL);" + (compare (neg:SI (match_operand:SI 0 "register_operand" "r")) + (const_int 0)))] + "(!flag_wrapv && !flag_trapv && flag_strict_overflow)" + "cp __zero_reg__,%A0 + cpc __zero_reg__,%B0 + cpc __zero_reg__,%C0 + cpc __zero_reg__,%D0" [(set_attr "cc" "compare") (set_attr "length" "4")]) (define_insn "*reversed_tstsi" [(set (cc0) - (compare (const_int 0) - (match_operand:SI 0 "register_operand" "r")))] + (compare (const_int 0) + (match_operand:SI 0 "register_operand" "r"))) + (clobber (match_scratch:QI 1 "=X"))] "" "cp __zero_reg__,%A0 cpc __zero_reg__,%B0 @@ -2258,16 +2339,17 @@ (set_attr "length" "4")]) -(define_insn "cmpqi" +(define_insn "*cmpqi" [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "r,d") - (match_operand:QI 1 "nonmemory_operand" "r,i")))] + (compare (match_operand:QI 0 "register_operand" "r,r,d") + (match_operand:QI 1 "nonmemory_operand" "L,r,i")))] "" "@ + tst %0 cp %0,%1 cpi %0,lo8(%1)" - [(set_attr "cc" "compare,compare") - (set_attr "length" "1,1")]) + [(set_attr "cc" "compare,compare,compare") + (set_attr "length" "1,1,1")]) (define_insn "*cmpqi_sign_extend" [(set (cc0) @@ -2279,19 +2361,22 @@ [(set_attr "cc" "compare") (set_attr "length" "1")]) -(define_insn "cmphi" +(define_insn "*cmphi" [(set (cc0) - (compare (match_operand:HI 0 "register_operand" "r,d,d,r,r") - (match_operand:HI 1 "nonmemory_operand" "r,M,i,M,i"))) - (clobber (match_scratch:QI 2 "=X,X,&d,&d,&d"))] + (compare (match_operand:HI 0 "register_operand" "!w,r,r,d,d,r,r") + (match_operand:HI 1 "nonmemory_operand" "L,L,r,M,i,M,i"))) + (clobber (match_scratch:QI 2 "=X,X,X,X,&d,&d,&d"))] "" "*{ switch (which_alternative) { - case 0: + case 0: case 1: + return out_tsthi (insn, operands[0], NULL); + + case 2: return (AS2 (cp,%A0,%A1) CR_TAB AS2 (cpc,%B0,%B1)); - case 1: + case 3: if (reg_unused_after (insn, operands[0]) && INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 63 && test_hard_reg_class (ADDW_REGS, operands[0])) @@ -2299,7 +2384,7 @@ else return (AS2 (cpi,%0,%1) CR_TAB AS2 (cpc,%B0,__zero_reg__)); - case 2: + case 4: if (reg_unused_after (insn, operands[0])) return (AS2 (subi,%0,lo8(%1)) CR_TAB AS2 (sbci,%B0,hi8(%1))); @@ -2307,12 +2392,12 @@ return (AS2 (ldi, %2,hi8(%1)) CR_TAB AS2 (cpi, %A0,lo8(%1)) CR_TAB AS2 (cpc, %B0,%2)); - case 3: + case 5: return (AS2 (ldi, %2,lo8(%1)) CR_TAB AS2 (cp, %A0,%2) CR_TAB AS2 (cpc, %B0,__zero_reg__)); - case 4: + case 6: return (AS2 (ldi, %2,lo8(%1)) CR_TAB AS2 (cp, %A0,%2) CR_TAB AS2 (ldi, %2,hi8(%1)) CR_TAB @@ -2320,25 +2405,28 @@ } return \"bug\"; }" - [(set_attr "cc" "compare,compare,compare,compare,compare") - (set_attr "length" "2,2,3,3,4")]) - - -(define_insn "cmpsi" + [(set_attr "cc" "compare,compare,compare,compare,compare,compare,compare") + (set_attr "length" "1,2,2,2,3,3,4")]) + + +(define_insn "*cmpsi" [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "r,d,d,r,r") - (match_operand:SI 1 "nonmemory_operand" "r,M,i,M,i"))) - (clobber (match_scratch:QI 2 "=X,X,&d,&d,&d"))] + (compare (match_operand:SI 0 "register_operand" "r,r,d,d,r,r") + (match_operand:SI 1 "nonmemory_operand" "L,r,M,i,M,i"))) + (clobber (match_scratch:QI 2 "=X,X,X,&d,&d,&d"))] "" "*{ switch (which_alternative) { case 0: + return out_tstsi (insn, operands[0], NULL); + + case 1: return (AS2 (cp,%A0,%A1) CR_TAB AS2 (cpc,%B0,%B1) CR_TAB AS2 (cpc,%C0,%C1) CR_TAB AS2 (cpc,%D0,%D1)); - case 1: + case 2: if (reg_unused_after (insn, operands[0]) && INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 63 && test_hard_reg_class (ADDW_REGS, operands[0])) @@ -2350,7 +2438,7 @@ AS2 (cpc,%B0,__zero_reg__) CR_TAB AS2 (cpc,%C0,__zero_reg__) CR_TAB AS2 (cpc,%D0,__zero_reg__)); - case 2: + case 3: if (reg_unused_after (insn, operands[0])) return (AS2 (subi,%A0,lo8(%1)) CR_TAB AS2 (sbci,%B0,hi8(%1)) CR_TAB @@ -2364,13 +2452,13 @@ AS2 (cpc, %C0,%2) CR_TAB AS2 (ldi, %2,hhi8(%1)) CR_TAB AS2 (cpc, %D0,%2)); - case 3: + case 4: return (AS2 (ldi,%2,lo8(%1)) CR_TAB AS2 (cp,%A0,%2) CR_TAB AS2 (cpc,%B0,__zero_reg__) CR_TAB AS2 (cpc,%C0,__zero_reg__) CR_TAB AS2 (cpc,%D0,__zero_reg__)); - case 4: + case 5: return (AS2 (ldi, %2,lo8(%1)) CR_TAB AS2 (cp, %A0,%2) CR_TAB AS2 (ldi, %2,hi8(%1)) CR_TAB @@ -2382,121 +2470,64 @@ } return \"bug\"; }" - [(set_attr "cc" "compare,compare,compare,compare,compare") - (set_attr "length" "4,4,7,5,8")]) - -; Optimize negated tests into reverse compare if overflow is undefined. -(define_insn_and_split "negated_tst<mode>" - [(set (cc0) - (neg:QISI (match_operand:QISI 0 "register_operand")))] - - "(!flag_wrapv && !flag_trapv && flag_strict_overflow)" - "#" - "" - [(set (cc0) - (compare (const_int 0) - (match_dup 0)))] - "") + [(set_attr "cc" "compare,compare,compare,compare,compare,compare") + (set_attr "length" "4,4,4,7,5,8")]) + ;; ---------------------------------------------------------------------- ;; JUMP INSTRUCTIONS ;; ---------------------------------------------------------------------- ;; Conditional jump instructions -(define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - - - -/**************************************************************** - AVR not have following conditional jumps: LE,LEU,GT,GTU. - Convert them all to proper jumps. -*****************************************************************/ - -(define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") +(define_expand "cbranchsi4" + [(parallel [(set (cc0) + (compare (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" ""))) + (clobber (match_scratch:QI 4 ""))]) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") + +(define_expand "cbranchhi4" + [(parallel [(set (cc0) + (compare (match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "nonmemory_operand" ""))) + (clobber (match_scratch:QI 4 ""))]) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") + +(define_expand "cbranchqi4" + [(set (cc0) + (compare (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "nonmemory_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") + ;; Test a single bit in a QI/HI/SImode register. -(define_insn "*sbrx_branch" +;; Combine will create zero extract patterns for single bit tests. +;; permit any mode in source pattern by using VOIDmode. + +(define_insn "*sbrx_branch<mode>" [(set (pc) (if_then_else (match_operator 0 "eqne_operator" - [(zero_extract:HI - (match_operand:QI 1 "register_operand" "r") + [(zero_extract:QIDI + (match_operand:VOID 1 "register_operand" "r") (const_int 1) (match_operand 2 "const_int_operand" "n")) (const_int 0)]) @@ -2513,39 +2544,27 @@ (const_int 4)))) (set_attr "cc" "clobber")]) -(define_insn "*sbrx_and_branchhi" +;; Same test based on Bitwise AND RTL. Keep this incase gcc changes patterns. +;; or for old peepholes. +;; Fixme - bitwise Mask will not work for DImode + +(define_insn "*sbrx_and_branch<mode>" [(set (pc) (if_then_else (match_operator 0 "eqne_operator" - [(and:HI - (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "single_one_operand" "n")) + [(and:QISI + (match_operand:QISI 1 "register_operand" "r") + (match_operand:QISI 2 "single_one_operand" "n")) (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc)))] "" - "* 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)))) - (set_attr "cc" "clobber")]) - -(define_insn "*sbrx_and_branchsi" - [(set (pc) - (if_then_else - (match_operator 0 "eqne_operator" - [(and:SI - (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "single_one_operand" "n")) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "" - "* return avr_out_sbxx_branch (insn, operands);" +{ + HOST_WIDE_INT bitnumber; + bitnumber = exact_log2 (GET_MODE_MASK (<MODE>mode) & INTVAL (operands[2])); + operands[2] = GEN_INT (bitnumber); + 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))) @@ -2557,7 +2576,8 @@ ;; Convert sign tests to bit 7/15/31 tests that match the above insns. (define_peephole2 - [(set (cc0) (match_operand:QI 0 "register_operand" "")) + [(set (cc0) (compare (match_operand:QI 0 "register_operand" "") + (const_int 0))) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2571,7 +2591,8 @@ "") (define_peephole2 - [(set (cc0) (match_operand:QI 0 "register_operand" "")) + [(set (cc0) (compare (match_operand:QI 0 "register_operand" "") + (const_int 0))) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2585,7 +2606,9 @@ "") (define_peephole2 - [(set (cc0) (match_operand:HI 0 "register_operand" "")) + [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "") + (const_int 0))) + (clobber (match_operand:HI 2 ""))]) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2597,7 +2620,9 @@ "") (define_peephole2 - [(set (cc0) (match_operand:HI 0 "register_operand" "")) + [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "") + (const_int 0))) + (clobber (match_operand:HI 2 ""))]) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2609,7 +2634,9 @@ "") (define_peephole2 - [(set (cc0) (match_operand:SI 0 "register_operand" "")) + [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "") + (const_int 0))) + (clobber (match_operand:SI 2 ""))]) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2621,7 +2648,9 @@ "operands[2] = GEN_INT (-2147483647 - 1);") (define_peephole2 - [(set (cc0) (match_operand:SI 0 "register_operand" "")) + [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "") + (const_int 0))) + (clobber (match_operand:SI 2 ""))]) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2650,6 +2679,11 @@ [(set_attr "type" "branch") (set_attr "cc" "clobber")]) +;; **************************************************************** +;; AVR does not have following conditional jumps: LE,LEU,GT,GTU. +;; Convert them all to proper jumps. +;; ****************************************************************/ + (define_insn "difficult_branch" [(set (pc) (if_then_else (match_operator 1 "difficult_comparison_operator" @@ -2700,8 +2734,8 @@ "" "*{ if (AVR_HAVE_JMP_CALL && get_attr_length (insn) != 1) - return AS1 (jmp,%0); - return AS1 (rjmp,%0); + return AS1 (jmp,%x0); + return AS1 (rjmp,%x0); }" [(set (attr "length") (if_then_else (match_operand 0 "symbol_ref_operand" "") @@ -2753,7 +2787,7 @@ \"%!icall\"); } else if (which_alternative==2) - return AS1(%~call,%c0); + return AS1(%~call,%x0); return (AS2 (ldi,r30,lo8(%0)) CR_TAB AS2 (ldi,r31,hi8(%0)) CR_TAB \"%!icall\"); @@ -2790,7 +2824,7 @@ \"%!icall\"); } else if (which_alternative==2) - return AS1(%~call,%c1); + return AS1(%~call,%x1); return (AS2 (ldi, r30, lo8(%1)) CR_TAB AS2 (ldi, r31, hi8(%1)) CR_TAB \"%!icall\"); @@ -2814,7 +2848,27 @@ (set_attr "length" "1")]) ; indirect jump -(define_insn "indirect_jump" + +(define_expand "indirect_jump" + [(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); + }" +) + +; indirect jump +(define_insn "*jcindirect_jump" + [(set (pc) (match_operand:HI 0 "immediate_operand" "i"))] + "" + "@ + %~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" "@ @@ -2852,7 +2906,7 @@ (use (label_ref (match_operand 1 "" ""))) (clobber (match_dup 0))] "AVR_HAVE_JMP_CALL && TARGET_CALL_PROLOGUES" - "jmp __tablejump2__" + "%~jmp __tablejump2__" [(set_attr "length" "2") (set_attr "cc" "clobber")]) @@ -2935,7 +2989,7 @@ "(optimize > 0)" { operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff)); - return AS2 (cbi,%0-0x20,%2); + return AS2 (cbi,%m0-0x20,%2); } [(set_attr "length" "1") (set_attr "cc" "none")]) @@ -2947,7 +3001,7 @@ "(optimize > 0)" { operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff)); - return AS2 (sbi,%0-0x20,%2); + return AS2 (sbi,%m0-0x20,%2); } [(set_attr "length" "1") (set_attr "cc" "none")]) @@ -3150,7 +3204,9 @@ }") (define_peephole - [(set (cc0) (match_operand:QI 0 "register_operand" "")) + [(set (cc0) + (compare (match_operand:QI 0 "register_operand" "") + (const_int 0))) (set (pc) (if_then_else (eq (cc0) (const_int 0)) (label_ref (match_operand 1 "" ""))