Index: gcc/config/avr/avr.md =================================================================== --- gcc/config/avr/avr.md (revision 129892) +++ gcc/config/avr/avr.md (working copy) @@ -45,21 +45,22 @@ (REG_SP 32) (TMP_REGNO 0) ; temporary register r0 (ZERO_REGNO 1) ; zero register r1 (SREG_ADDR 0x5F) (RAMPZ_ADDR 0x5B) (UNSPEC_STRLEN 0) (UNSPEC_INDEX_JMP 1) (UNSPEC_SEI 2) (UNSPEC_CLI 3) + (UNSPEC_SWAP 4) (UNSPECV_PROLOGUE_SAVES 0) (UNSPECV_EPILOGUE_RESTORES 1)]) (include "predicates.md") (include "constraints.md") ;; Condition code settings. (define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber" (const_string "none")) @@ -1185,20 +1186,33 @@ 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\"; }" [(set_attr "length" "4,4") (set_attr "cc" "set_n,set_n")]) +(define_peephole2 ; andi + [(set (match_operand:QI 0 "d_register_operand" "") + (and:QI (match_dup 0) + (match_operand:QI 1 "const_int_operand" ""))) + (set (match_dup 0) + (and:QI (match_dup 0) + (match_operand:QI 2 "const_int_operand" "")))] + "" + [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))] + { + operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[2])); + }) + ;;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ;; ior (define_insn "iorqi3" [(set (match_operand:QI 0 "register_operand" "=r,d") (ior:QI (match_operand:QI 1 "register_operand" "%0,0") (match_operand:QI 2 "nonmemory_operand" "r,i")))] "" "@ or %0,%2 @@ -1313,24 +1327,71 @@ (xor:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "register_operand" "r")))] "" "eor %0,%2 eor %B0,%B2 eor %C0,%C2 eor %D0,%D2" [(set_attr "length" "4") (set_attr "cc" "set_n")]) +;; swap + +(define_insn "*swap" + [(set (match_operand:QI 0 "register_operand" "=r") + (unspec:QI [(match_operand:QI 1 "register_operand" "0")] + UNSPEC_SWAP))] + "" + "swap %0" + [(set_attr "length" "1") + (set_attr "cc" "none")]) + ;;<< << << << << << << << << << << << << << << << << << << << << << << << << << ;; arithmetic shift left -(define_insn "ashlqi3" +(define_expand "ashlqi3" + [(set (match_operand:QI 0 "register_operand" "") + (ashift:QI (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "general_operand" "")))] + "" + "") + +(define_split ; ashlqi3_const4 + [(set (match_operand:QI 0 "d_register_operand" "") + (ashift:QI (match_operand:QI 1 "d_register_operand" "") + (const_int 4)))] + "" + [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP)) + (set (match_dup 0) (and:QI (match_dup 0) (const_int -16)))] + "") + +(define_split ; ashlqi3_const5 + [(set (match_operand:QI 0 "d_register_operand" "") + (ashift:QI (match_operand:QI 1 "d_register_operand" "") + (const_int 5)))] + "" + [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP)) + (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1))) + (set (match_dup 0) (and:QI (match_dup 0) (const_int -32)))] + "") + +(define_split ; ashlqi3_const6 + [(set (match_operand:QI 0 "d_register_operand" "") + (ashift:QI (match_operand:QI 1 "d_register_operand" "") + (const_int 6)))] + "" + [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP)) + (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 2))) + (set (match_dup 0) (and:QI (match_dup 0) (const_int -64)))] + "") + +(define_insn "*ashlqi3" [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,!d,r,r") (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0,0,0") (match_operand:QI 2 "general_operand" "r,L,P,K,n,n,Qm")))] "" "* return ashlqi3_out (insn, operands, NULL);" [(set_attr "length" "5,0,1,2,4,6,9") (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")]) (define_insn "ashlhi3" [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r,r") @@ -1346,20 +1407,61 @@ (ashift:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0") (match_operand:QI 2 "general_operand" "r,L,P,O,K,n,Qm")))] "" "* return ashlsi3_out (insn, operands, NULL);" [(set_attr "length" "8,0,4,4,8,10,12") (set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")]) ;; Optimize if a scratch register from LD_REGS happens to be available. (define_peephole2 + [(match_scratch:QI 2 "d") + (set (match_operand:QI 0 "l_register_operand" "") + (ashift:QI (match_operand:QI 1 "l_register_operand" "") + (const_int 4)))] + "" + [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP)) + (set (match_dup 2) (const_int -16)) + (set (match_dup 0) (and:QI (match_dup 0) (match_dup 2))) + (clobber (match_dup 2))] + "if (!avr_peep2_scratch_safe (operands[2])) + FAIL;") + +(define_peephole2 + [(match_scratch:QI 2 "d") + (set (match_operand:QI 0 "l_register_operand" "") + (ashift:QI (match_operand:QI 1 "l_register_operand" "") + (const_int 5)))] + "" + [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP)) + (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1))) + (set (match_dup 2) (const_int -32)) + (set (match_dup 0) (and:QI (match_dup 0) (match_dup 2))) + (clobber (match_dup 2))] + "if (!avr_peep2_scratch_safe (operands[2])) + FAIL;") + +(define_peephole2 + [(match_scratch:QI 2 "d") + (set (match_operand:QI 0 "l_register_operand" "") + (ashift:QI (match_operand:QI 1 "l_register_operand" "") + (const_int 6)))] + "" + [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP)) + (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 2))) + (set (match_dup 2) (const_int -64)) + (set (match_dup 0) (and:QI (match_dup 0) (match_dup 2))) + (clobber (match_dup 2))] + "if (!avr_peep2_scratch_safe (operands[2])) + FAIL;") + +(define_peephole2 [(match_scratch:QI 3 "d") (set (match_operand:HI 0 "register_operand" "") (ashift:HI (match_operand:HI 1 "register_operand" "") (match_operand:QI 2 "const_int_operand" "")))] "" [(parallel [(set (match_dup 0) (ashift:HI (match_dup 1) (match_dup 2))) (clobber (match_dup 3))])] "if (!avr_peep2_scratch_safe (operands[3])) FAIL;") @@ -1464,21 +1566,63 @@ (match_operand:QI 2 "const_int_operand" "L,P,O,n"))) (clobber (match_scratch:QI 3 "=X,X,X,&d"))] "reload_completed" "* return ashrsi3_out (insn, operands, NULL);" [(set_attr "length" "0,4,4,10") (set_attr "cc" "none,clobber,set_n,clobber")]) ;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> ;; logical shift right -(define_insn "lshrqi3" +(define_expand "lshrqi3" + [(set (match_operand:QI 0 "register_operand" "") + (lshiftrt:QI (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "general_operand" "")))] + "" + "") + +(define_insn_and_split "*lshrqi3_const4" + [(set (match_operand:QI 0 "d_register_operand" "=d") + (lshiftrt:QI (match_operand:QI 1 "d_register_operand" "0") + (const_int 4)))] + "" + "#" + "" + [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP)) + (set (match_dup 0) (and:QI (match_dup 0) (const_int 15)))] + "") + +(define_insn_and_split "*lshrqi3_const5" + [(set (match_operand:QI 0 "d_register_operand" "=d") + (lshiftrt:QI (match_operand:QI 1 "d_register_operand" "0") + (const_int 5)))] + "" + "#" + "" + [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP)) + (set (match_dup 0) (lshiftrt:QI (match_dup 0) (const_int 1))) + (set (match_dup 0) (and:QI (match_dup 0) (const_int 7)))] + "") + +(define_insn_and_split "*lshrqi3_const6" + [(set (match_operand:QI 0 "d_register_operand" "=d") + (lshiftrt:QI (match_operand:QI 1 "d_register_operand" "0") + (const_int 6)))] + "" + "#" + "" + [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP)) + (set (match_dup 0) (lshiftrt:QI (match_dup 0) (const_int 2))) + (set (match_dup 0) (and:QI (match_dup 0) (const_int 3)))] + "") + +(define_insn "*lshrqi3" [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,!d,r,r") (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0,0,0") (match_operand:QI 2 "general_operand" "r,L,P,K,n,n,Qm")))] "" "* return lshrqi3_out (insn, operands, NULL);" [(set_attr "length" "5,0,1,2,4,6,9") (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")]) (define_insn "lshrhi3" [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r,r") @@ -1494,20 +1638,61 @@ (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0") (match_operand:QI 2 "general_operand" "r,L,P,O,K,n,Qm")))] "" "* return lshrsi3_out (insn, operands, NULL);" [(set_attr "length" "8,0,4,4,8,10,12") (set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")]) ;; Optimize if a scratch register from LD_REGS happens to be available. (define_peephole2 + [(match_scratch:QI 2 "d") + (set (match_operand:QI 0 "l_register_operand" "") + (lshiftrt:QI (match_operand:QI 1 "l_register_operand" "") + (const_int 4)))] + "" + [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP)) + (set (match_dup 2) (const_int 15)) + (set (match_dup 0) (and:QI (match_dup 0) (match_dup 2))) + (clobber (match_dup 2))] + "if (!avr_peep2_scratch_safe (operands[2])) + FAIL;") + +(define_peephole2 + [(match_scratch:QI 2 "d") + (set (match_operand:QI 0 "l_register_operand" "") + (lshiftrt:QI (match_operand:QI 1 "l_register_operand" "") + (const_int 5)))] + "" + [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP)) + (set (match_dup 0) (lshiftrt:QI (match_dup 0) (const_int 1))) + (set (match_dup 2) (const_int 7)) + (set (match_dup 0) (and:QI (match_dup 0) (match_dup 2))) + (clobber (match_dup 2))] + "if (!avr_peep2_scratch_safe (operands[2])) + FAIL;") + +(define_peephole2 + [(match_scratch:QI 2 "d") + (set (match_operand:QI 0 "l_register_operand" "") + (lshiftrt:QI (match_operand:QI 1 "l_register_operand" "") + (const_int 6)))] + "" + [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP)) + (set (match_dup 0) (lshiftrt:QI (match_dup 0) (const_int 2))) + (set (match_dup 2) (const_int 3)) + (set (match_dup 0) (and:QI (match_dup 0) (match_dup 2))) + (clobber (match_dup 2))] + "if (!avr_peep2_scratch_safe (operands[2])) + FAIL;") + +(define_peephole2 [(match_scratch:QI 3 "d") (set (match_operand:HI 0 "register_operand" "") (lshiftrt:HI (match_operand:HI 1 "register_operand" "") (match_operand:QI 2 "const_int_operand" "")))] "" [(parallel [(set (match_dup 0) (lshiftrt:HI (match_dup 1) (match_dup 2))) (clobber (match_dup 3))])] "if (!avr_peep2_scratch_safe (operands[3])) FAIL;")