Index: gcc/ChangeLog =================================================================== --- gcc/ChangeLog (revision 142584) +++ gcc/ChangeLog (working copy) @@ -27988,3 +27988,28 @@ * config/i386/sse.md (sse5_pperm, sse5_pperm_pack_v2di_v4si, sse5_pperm_pack_v4si_v8hi, sse5_pperm_pack_v8hi_v16qi, sse5_perm): Fix constraints. + +2008-12-10 Georg-Johann Lay + * config/avr/avr.md (adjust_len): New insn attribute to + prevent some insns' lengths to be altered by ADJUST_INSN_LENGTH. + * consig/avr/avr.c (adjust_insn_length): Use it. Exclude SET insns + that say adjust_len="no" from insn length adjustment. + * config/avr/predicates.md (shiftrt_operator): New operator + predicate for LSHIFTRT and ASHIFTRT used in some of the following + new insns. + * config/avr/avr.md (*sbrx_branch_shiftrt, + *sbix_branch_shiftrt, + *extract_bithiqi, *extract_bithihi, *extract_bitqihi, + *extract_bitqi, *insert_bitqi, + *ashift_1_bit, *shiftrt_1_bit, + *insert_1_bit_ashift, *insert_1_bit0, + *iorqi2_ashift_bit7, *iorqi2_ashift_bit, + *movebit_ashift, *iorqi2_shiftrt_bit, + *movebit_shiftrt, *movebit_shiftrt_7, *movebit_ashift_7, + *ior2_bit0, *ior2_zeroextract_bit, + *zero_extendqihi2_bit): New, anonymous insns for better + support of single bit operations. + * config/avr/constraints.md (Ya): New multiletter constraint for + 32 bit CONST_INT that has exactly one bit set + * config/avr/avr.md (iorsi3): Use It. Added new alternative that + avoids reload for NO_LD_REGS ored with a power of 2. Index: gcc/config/avr/predicates.md =================================================================== --- gcc/config/avr/predicates.md (revision 142584) +++ gcc/config/avr/predicates.md (working copy) @@ -110,3 +110,7 @@ (and (match_code "mem") (ior (match_test "register_operand (XEXP (op, 0), mode)") (match_test "CONSTANT_ADDRESS_P (XEXP (op, 0))")))) + +;; True for ASHIFTRT & LSHIFTRT +(define_predicate "shiftrt_operator" + (match_code "ashiftrt,lshiftrt")) Index: gcc/config/avr/constraints.md =================================================================== --- gcc/config/avr/constraints.md (revision 142584) +++ gcc/config/avr/constraints.md (working copy) @@ -107,3 +107,8 @@ "A memory address based on Y or Z pointer with displacement." (and (match_code "mem") (match_test "extra_constraint_Q (op)"))) + +(define_constraint "Ya" + "Integer constant of 32 bit is a power of 2." + (and (match_code "const_int") + (match_test "exact_log2 (0xffffffff & ival) >= 0 && avr_test"))) Index: gcc/config/avr/avr.md =================================================================== --- gcc/config/avr/avr.md (revision 142584) +++ gcc/config/avr/avr.md (working copy) @@ -1,4 +1,3 @@ -;; -*- Mode: Scheme -*- ;; Machine description for GNU compiler, ;; for ATMEL AVR micro controllers. ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008 @@ -116,9 +115,20 @@ (const_int 2))] (const_int 2))) +;; Some complex insns don't need length adjustment and thererfore, +;; the length of these insns must not be altered. +;; It is easier to state that in an insn attribute +;; than to clutter up code in avr.c:adjust_insn_length() +(define_attr "adjust_len" "yes,no" + (const_string "yes")) + ;; Define mode iterator (define_mode_iterator QISI [(QI "") (HI "") (SI "")]) +;; Some mode iterators for scalar int modes used in bit insns. +(define_mode_iterator HISI [HI SI]) +(define_mode_iterator QIHISI [QI HI SI]) + ;;======================================================================== ;; The following is used by nonlocal_goto and setjmp. ;; The receiver pattern will create no instructions since internally @@ -1329,9 +1339,9 @@ (set_attr "cc" "clobber,set_n")]) (define_insn "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=r,d") - (ior:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "nonmemory_operand" "r,i")))] + [(set (match_operand:SI 0 "register_operand" "=r,d,l") + (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0") + (match_operand:SI 2 "nonmemory_operand" "r,i,Ya")))] "" "*{ if (which_alternative==0) @@ -1339,6 +1349,18 @@ AS2 (or, %B0,%B2) CR_TAB AS2 (or, %C0,%C2) CR_TAB AS2 (or, %D0,%D2)); + + if (avr_test && which_alternative==2) + { + HOST_WIDE_INT bit = exact_log2 (0xffffffff & INTVAL (operands[2])); + operands[2] = GEN_INT (bit); + output_asm_insn (\"set\", operands); + if (bit >= 24) return (AS2 (bld, %D0,%2-24)); + if (bit >= 16) return (AS2 (bld, %C0,%2-16)); + if (bit >= 8) return (AS2 (bld, %B0,%2-8)); + return (AS2 (bld, %A0,%2)); + } + if (GET_CODE (operands[2]) == CONST_INT) { HOST_WIDE_INT mask = INTVAL (operands[2]); @@ -1357,15 +1379,16 @@ AS2 (ori, %C0,hlo8(%2)) CR_TAB AS2 (ori, %D0,hhi8(%2))); }" - [(set_attr "length" "4,4") - (set_attr "cc" "set_n,clobber")]) + [(set_attr "length" "4,4,2") + (set_attr "adjust_len" "no,yes,no") + (set_attr "cc" "set_n,clobber,none")]) (define_insn "*iorsi3_clobber" [(set (match_operand:SI 0 "register_operand" "=r,r") (ior:SI (match_operand:SI 1 "register_operand" "%0,0") (match_operand:SI 2 "immediate_operand" "M,i"))) (clobber (match_scratch:QI 3 "=&d,&d"))] - "" + "!avr_test || (avr_test && !single_one_operand(operands[2], SImode))" "@ ldi %3,lo8(%2)\;or %A0,%3 ldi %3,lo8(%2)\;or %A0,%3\;ldi %3,hi8(%2)\;or %B0,%3\;ldi %3,hlo8(%2)\;or %C0,%3\;ldi %3,hhi8(%2)\;or %D0,%3" @@ -2476,6 +2499,30 @@ (const_int 4)))) (set_attr "cc" "clobber")]) +;; same as above +(define_insn "*sbrx_branch_shiftrt" + [(set (pc) + (if_then_else + (match_operator 0 "eqne_operator" + [(zero_extract (match_operator:QIHISI 4 "shiftrt_operator" + [(match_operand:QIHISI 1 "register_operand" "r") + (match_operand 2 "const_int_operand" "n")]) + (const_int 1) + (const_int 0)) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "(avr_test & 512)" + "* 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_branchhi" [(set (pc) (if_then_else @@ -2938,6 +2985,30 @@ (const_int 4)))) (set_attr "cc" "clobber")]) +;; same as above, needed because rtx was not canonicalised +(define_insn "*sbix_branch_shiftrt" + [(set (pc) + (if_then_else + (match_operator 0 "eqne_operator" + [(zero_extract (match_operator:QI 4 "shiftrt_operator" + [(mem:QI (match_operand 1 "low_io_address_operand" "n")) + (match_operand 2 "const_int_operand" "n")]) + (const_int 1) + (const_int 0)) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "(optimize > 0) && (avr_test & 512)" + "* 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")]) + ;; Tests of bit 7 are pessimized to sign tests, so we need this too... (define_insn "*sbix_branch_bit7" [(set (pc) @@ -3262,3 +3333,355 @@ expand_epilogue (); DONE; }") + +;; :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 :1 +;; Move and extract single bits. +;; The patterns are generated by combine, almost all use BST/BLD to move +;; bits around. + +;; Extract one bit from a complex expression. +;; Note that introducing (zero_extract:QI) would reduce performance. +;; [0] = [1].[2] +(define_insn "*extract_bithiqi" + [(set (match_operand:QI 0 "register_operand" "=r") + (subreg:QI (zero_extract:HI (match_operand:QI 1 "register_operand" "r") + (const_int 1) + (match_operand:QI 2 "const_int_operand" "n")) 0))] + "(avr_test & 2) && INTVAL(operands[2]) > 1" + "bst %1,%2\;clr %0\;bld %0,0" + [(set_attr "length" "3") + (set_attr "adjust_len" "no") + (set_attr "cc" "clobber")]) + +;; [0] = [1].[2] +(define_insn "*extract_bithihi" + [(set (match_operand:HI 0 "register_operand" "=r") + (and:HI (match_operator:HI 3 "shiftrt_operator" + [(match_operand:HI 1 "register_operand" "r") + (match_operand:HI 2 "const_int_operand" "n")]) + (const_int 1)))] + "(avr_test & 2) && (INTVAL (operands[2]) & 7) > 1" + { + return (INTVAL (operands[2]) >= 8) + ? "bst %B1,%2-8\;clr %B0\;clr %A0\;bld %A0,0" + : "bst %A1,%2 \;clr %B0\;clr %A0\;bld %A0,0"; + } + [(set_attr "length" "4") + (set_attr "adjust_len" "no") + (set_attr "cc" "clobber")]) + +;; [0] = [1].[2] +(define_insn "*extract_bitqihi" + [(set (match_operand:HI 0 "register_operand" "=r") + (zero_extract:HI (match_operand:QI 1 "register_operand" "r") + (const_int 1) + (match_operand:QI 2 "const_int_operand" "n")))] + "(avr_test & 2) && INTVAL(operands[2]) > 1" + "bst %1,%2\;clr %B0\;clr %A0\;bld %A0,0" + [(set_attr "length" "4") + (set_attr "adjust_len" "no") + (set_attr "cc" "clobber")]) + +;; [0] = [2].[3] +(define_insn "*extract_bitqi" + [(set (match_operand:QI 0 "register_operand" "=r") + (and:QI (subreg:QI (match_operator:HISI 1 "shiftrt_operator" + [(match_operand:HISI 2 "register_operand" "r") + (match_operand:HISI 3 "const_int_operand" "n")]) 0) + (const_int 1)))] + "(avr_test & 2) && (mode == SImode || (INTVAL(operands[3]) & 7) > 1)" + { + HOST_WIDE_INT bit = INTVAL (operands[3]); + if (bit >= 24) return "bst %D2,%3-24\;clr %A0\;bld %A0,0"; + if (bit >= 16) return "bst %C2,%3-16\;clr %A0\;bld %A0,0"; + if (bit >= 8) return "bst %B2,%3-8 \;clr %A0\;bld %A0,0"; + return "bst %A2,%3 \;clr %A0\;bld %A0,0"; + } + [(set_attr "length" "3") + (set_attr "adjust_len" "no") + (set_attr "cc" "clobber")]) + +;; [0] = 0 +;; [0].[4] = [2].[3] +(define_insn "*insert_bitqi" + [(set (match_operand:QI 0 "register_operand" "=r") + (and:QI (ashift:QI (subreg:QI (match_operator:HISI 1 "shiftrt_operator" + [(match_operand:HISI 2 "register_operand" "r") + (match_operand:HISI 3 "const_int_operand" "n")]) 0) + (match_operand:QI 4 "const_int_operand" "n")) + (match_operand:QI 5 "single_one_operand" "n")))] ; = (1 << [4]) + "(avr_test & 4) && INTVAL(operands[4]) == exact_log2(0xff & INTVAL(operands[5]))" + { + HOST_WIDE_INT from_bit = INTVAL(operands[3]); + + if (from_bit >= 24) return "bst %D2,%3-24\;clr %0\;bld %0,%4"; + if (from_bit >= 16) return "bst %C2,%3-16\;clr %0\;bld %0,%4"; + if (from_bit >= 8) return "bst %B2,%3-8 \;clr %0\;bld %0,%4"; + return "bst %A2,%3 \;clr %0\;bld %0,%4"; + } + [(set_attr "length" "3") + (set_attr "adjust_len" "no") + (set_attr "cc" "clobber")]) + +;; [0] = 0 +;; [0].log[3] = [1].log[3]-[2] +(define_insn "*ashift_1_bit" + [(set (match_operand:QI 0 "register_operand" "=r") + (and:QI (ashift:QI (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "const_int_operand" "n")) + (match_operand:QI 3 "single_one_operand" "n")))] + "(avr_test & 4) && INTVAL(operands[2]) > 1" + { + HOST_WIDE_INT to_bit = exact_log2 (0xff & INTVAL(operands[3])); + HOST_WIDE_INT from_bit = to_bit - INTVAL(operands[2]); + operands[2] = GEN_INT(from_bit); + operands[3] = GEN_INT(to_bit); + return "bst %1,%2\;clr %0\;bld %0,%3"; + } + [(set_attr "length" "3") + (set_attr "adjust_len" "no") + (set_attr "cc" "clobber")]) + +;; [0] = 0 +;; [0].log[3] = [1].log[3]+[2] +(define_insn "*shiftrt_1_bit" + [(set (match_operand:QI 0 "register_operand" "=r") + (and:QI (match_operator:QI 4 "shiftrt_operator" + [(match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "const_int_operand" "n")]) + (match_operand:QI 3 "single_one_operand" "n")))] + "(avr_test & 4) && INTVAL(operands[2]) > 1" + { + HOST_WIDE_INT to_bit = exact_log2 (0xff & INTVAL(operands[3])); + HOST_WIDE_INT from_bit = to_bit + INTVAL(operands[2]); + operands[2] = GEN_INT(from_bit); + operands[3] = GEN_INT(to_bit); + return "bst %1,%2\;clr %0\;bld %0,%3"; + } + [(set_attr "length" "3") + (set_attr "adjust_len" "no") + (set_attr "cc" "clobber")]) + +;; [0].log[5] = [3].log[5]-[4] +(define_insn "*insert_1_bit_ashift" + [(set (match_operand:QI 0 "register_operand" "=r") + (ior:QI (and:QI (match_operand:QI 1 "register_operand" "%0") + (match_operand:QI 2 "single_zero_operand" "n")) ; = ~[5] + (and:QI (ashift:QI (match_operand:QI 3 "register_operand" "r") + (match_operand:QI 4 "const_int_operand" "n")) + (match_operand:QI 5 "single_one_operand" "n"))))] + + "(avr_test & 8) + && 0xff == (0xff & (INTVAL(operands[5]) ^ INTVAL(operands[2])))" + { + HOST_WIDE_INT to_bit = exact_log2(0xff & INTVAL(operands[5])); + HOST_WIDE_INT from_bit = to_bit - INTVAL(operands[4]); + operands[5] = GEN_INT (to_bit); + operands[4] = GEN_INT (from_bit); + return "bst %3,%4\;bld %0,%5"; + } + [(set_attr "length" "2") + (set_attr "adjust_len" "no") + (set_attr "cc" "none")]) + +;; [0].log[4] = [3].log[4] +(define_insn "*insert_1_bit0" + [(set (match_operand:QI 0 "register_operand" "=r") + (ior:QI (and:QI (match_operand:QI 1 "register_operand" "%0") + (match_operand:QI 2 "single_zero_operand" "n")) ; = ~[4] + (and:QI (match_operand:QI 3 "register_operand" "r") + (match_operand:QI 4 "single_one_operand" "n"))))] + "(avr_test & 8) + && 0xff == (0xff & (INTVAL(operands[4]) ^ INTVAL(operands[2])))" + { + operands[4] = GEN_INT(exact_log2(0xff & INTVAL(operands[4]))); + return "bst %3,%4\;bld %0,%4"; + } + [(set_attr "length" "2") + (set_attr "adjust_len" "no") + (set_attr "cc" "none")]) + +;; special case of pattern below +;; [0].7 |= [1].0 +(define_insn "*iorqi2_ashift_bit7" + [(set (match_operand:QI 0 "register_operand" "=d,r") + (ior:QI (ashift:QI (match_operand:QI 1 "register_operand" "r,r") + (const_int 7)) + (match_operand:QI 2 "register_operand" "0,0")))] + "(avr_test & 16)" + "@ + sbrc %1,0\;ori %0,0x80 + bst %1,0\;sbrs %0,7\;bld %0,7" + [(set_attr "length" "2,3") + (set_attr "adjust_len" "no,no") + (set_attr "cc" "clobber,none")]) + +;; [0].log[3] |= [1].log[3]-[2] +(define_insn "*iorqi2_ashift_bit" + [(set (match_operand:QI 0 "register_operand" "=d,r") + (ior:QI (and:QI (ashift:QI (match_operand:QI 1 "register_operand" "r,r") + (match_operand:QI 2 "const_int_operand" "n,n")) + (match_operand:QI 3 "single_one_operand" "n,n")) + (match_operand:QI 4 "register_operand" "0,0")))] + "(avr_test & 16)" + { + HOST_WIDE_INT to_bit = exact_log2 (0xff & INTVAL(operands[3])); + HOST_WIDE_INT from_bit = to_bit - INTVAL(operands[2]); + + operands[2] = GEN_INT (from_bit); + operands[3] = GEN_INT (to_bit); + + if (0 == which_alternative) + return "sbrc %1,%2\;ori %0,(1<<%3)"; + + return "bst %1,%2\;sbrs %0,%3\;bld %0,%3"; + } + [(set_attr "length" "2,3") + (set_attr "adjust_len" "no,no") + (set_attr "cc" "clobber,none")]) + +;; needs the above pattern as combiner bridge +;; [0].log[3] = [1].log[3]-[2] +(define_insn "*movebit_ashift" + [(set (match_operand:QI 0 "register_operand" "=r") + (ior:QI (and:QI (ashift:QI (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "const_int_operand" "n")) + (match_operand:QI 3 "single_one_operand" "n")) + (and:QI (match_operand:QI 4 "register_operand" "%0") + (match_operand:QI 5 "single_zero_operand" "n"))))] ; = ~[3] + "(avr_test & 8) + && 0xff == (0xff & (INTVAL(operands[3]) ^ INTVAL(operands[5])))" + { + HOST_WIDE_INT to_bit = exact_log2 (0xff & INTVAL(operands[3])); + HOST_WIDE_INT from_bit = to_bit - INTVAL(operands[2]); + + operands[2] = GEN_INT (from_bit); + operands[3] = GEN_INT (to_bit); + return "bst %1,%2\;bld %0,%3"; + } + [(set_attr "length" "2") + (set_attr "cc" "none")]) + +;; [0].log[4] |= [2].log[4]+[3] +(define_insn "*iorqi2_shiftrt_bit" + [(set (match_operand:QI 0 "register_operand" "=d,r") + (ior:QI (and:QI (match_operator:QI 1 "shiftrt_operator" + [(match_operand:QI 2 "register_operand" "r,r") + (match_operand:QI 3 "const_int_operand" "n,n")]) + (match_operand:QI 4 "single_one_operand" "n,n")) + (match_operand:QI 5 "register_operand" "0,0")))] + "(avr_test & 16)" + { + HOST_WIDE_INT to_bit = exact_log2 (0xff & INTVAL(operands[4])); + HOST_WIDE_INT from_bit = to_bit + INTVAL(operands[3]); + + operands[3] = GEN_INT (from_bit); + operands[4] = GEN_INT (to_bit); + + if (0 == which_alternative) + return "sbrc %2,%3\;ori %0,(1<<%4)"; + + return "bst %2,%3\;sbrs %0,%4\;bld %0,%4"; + } + [(set_attr "length" "2,3") + (set_attr "adjust_len" "no,no") + (set_attr "cc" "clobber,none")]) + +;; needs the above pattern as combiner bridge +;; [0].log[4] = [2].log[4]+[3] +(define_insn "*movebit_shiftrt" + [(set (match_operand:QI 0 "register_operand" "=r") + (ior:QI (and:QI (match_operator:QI 1 "shiftrt_operator" + [(match_operand:QI 2 "register_operand" "r") + (match_operand:QI 3 "const_int_operand" "n")]) + (match_operand:QI 4 "single_one_operand" "n")) + (and:QI (match_operand:QI 5 "register_operand" "%0") + (match_operand:QI 6 "single_zero_operand" "n"))))] ; = ~[4] + "(avr_test & 8) + && 0xff == (0xff & (INTVAL(operands[4]) ^ INTVAL(operands[6])))" + { + HOST_WIDE_INT to_bit = exact_log2 (0xff & INTVAL(operands[4])); + HOST_WIDE_INT from_bit = to_bit + INTVAL(operands[3]); + + operands[3] = GEN_INT (from_bit); + operands[4] = GEN_INT (to_bit); + return "bst %2,%3\;bld %0,%4"; + } + [(set_attr "length" "2") + (set_attr "adjust_len" "no") + (set_attr "cc" "none")]) + +;; same as above, for .0 <- .7 +;; [0].0 = [2].7 +(define_insn "*movebit_shiftrt_7" + [(set (match_operand:QI 0 "register_operand" "=r") + (ior:QI (and:QI (match_operand:QI 1 "register_operand" "%0") + (match_operand:QI 2 "single_zero_operand" "n")) ; ~1 + (match_operator:QI 3 "shiftrt_operator" + [(match_operand:QI 4 "register_operand" "r") + (const_int 7)])))] + "(avr_test & 8) && 0xfe == (0xff & INTVAL(operands[2]))" + "bst %4,7\;bld %0,0" + [(set_attr "length" "2") + (set_attr "cc" "none")]) + +;; same as above, for .7 <- .0 +;; [0].7 = [3].0 +(define_insn "*movebit_ashift_7" + [(set (match_operand:QI 0 "register_operand" "=r") + (ior:QI (and:QI (match_operand:QI 1 "register_operand" "%0") + (match_operand:QI 2 "single_zero_operand" "n")) ; 0x7f + (ashift:QI (match_operand:QI 3 "register_operand" "r") + (const_int 7))))] + "(avr_test & 8) && 0x7f == (0xff & INTVAL(operands[2]))" + "bst %3,0\;bld %0,7" + [(set_attr "length" "2") + (set_attr "adjust_len" "no") + (set_attr "cc" "none")]) + +;;[0] |= [1].0 +(define_insn "*ior2_bit0" + [(set (match_operand:QIHISI 0 "register_operand" "=d,r") + (ior:QIHISI (and:QIHISI (match_operand:QIHISI 1 "register_operand" "r,r") + (const_int 1)) + (match_operand:QIHISI 2 "register_operand" "0,0")))] + "(avr_test & 16)" + "@ + sbrc %A1,0\;ori %A0,1 + bst %A1,0\;sbrs %A0,0\;bld %A0,0" + [(set_attr "length" "2,3") + (set_attr "adjust_len" "no,no") + (set_attr "cc" "clobber,none")]) + +;; Same as above for bit [2] +;; [0] |= [1].[2] +;; FIXME: [0] and [1] need not to have the same mode. +;; Do mode iterators allow cross products by introducing +;; more than one iterator per insn? +(define_insn "*ior2_zeroextract_bit" + [(set (match_operand:QIHISI 0 "register_operand" "=d,r") + (ior:QIHISI (zero_extract:QIHISI (match_operand:QIHISI 1 "register_operand" "r,r") + (const_int 1) + (match_operand:QI 2 "const_int_operand" "n,n")) + (match_operand:QIHISI 3 "register_operand" "0,0")))] + "(avr_test & 16)" + "@ + sbrc %A1,%2\;ori %A0,1 + bst %A1,%2\;sbrs %A0,0\;bld %A0,0" + [(set_attr "length" "2,3") + (set_attr "adjust_len" "no,no") + (set_attr "cc" "clobber,none")]) + +;; [0] = [1].[2] +(define_insn "*zero_extendqihi2_bit" + [(set (match_operand:HI 0 "register_operand" "=d,*r") + (zero_extend:HI (zero_extract:QI (match_operand:QI 1 "register_operand" "0,r") + (const_int 1) + (match_operand:QI 2 "const_int_operand" "P,n"))))] + "(avr_test & 2) && INTVAL (operands[2]) > 0" + "@ + lsr %A0\;andi %A0,1\;clr %B0 + bst %A1,%2\;clr %A0\;bld %A0,0\;clr %B0" + [(set_attr "length" "3,4") + (set_attr "adjust_len" "no,no") + (set_attr "cc" "clobber,clobber")]) Index: gcc/config/avr/avr.c =================================================================== --- gcc/config/avr/avr.c (revision 142584) +++ gcc/config/avr/avr.c (working copy) @@ -4313,6 +4313,19 @@ adjust_insn_length (rtx insn, int len) rtx patt = PATTERN (insn); rtx set; + /* Some complex insns don't need length adjustment and + * therefore, the length must not ne adjusted for these insns. + * It is easier to state that in an insn attribute than + * to clutter up code here... + */ + if (GET_CODE (patt) == SET) + { + enum attr_adjust_len need_adjust = get_attr_adjust_len (insn); + + if (ADJUST_LEN_NO == need_adjust) + return len; + } + if (GET_CODE (patt) == SET) { rtx op[10]; Index: gcc/config/avr/avr.opt =================================================================== --- gcc/config/avr/avr.opt (revision 142584) +++ gcc/config/avr/avr.opt (working copy) @@ -66,3 +66,6 @@ Relax branches mpmem-wrap-around Target Report Make the linker relaxation machine assume that a program counter wrap-around occures. + +mtest= +Target RejectNegative Report Joined Undocumented UInteger Var(avr_test) Init(0)