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;")
 
