$OpenBSD: patch-gcc-4_3_4_gcc_config_avr_avr_md,v 1.1 2010/06/27 20:58:10 ckuethe Exp $
--- gcc-4.3.4/gcc/config/avr/avr.md.orig	Mon Mar  9 14:49:28 2009
+++ gcc-4.3.4/gcc/config/avr/avr.md	Sat Jun 26 11:58:40 2010
@@ -32,6 +32,7 @@
 ;;  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)
 ;;  ~  Output 'r' if not AVR_MEGA.
+;;  !  Output 'e' if AVR_HAVE_EIJMP_EICALL.
 
 ;; UNSPEC usage:
 ;;  0  Length of a string, see "strlenhi".
@@ -46,17 +47,29 @@
    (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		2)
+   (UNSPEC_FMUL		3)
+   (UNSPEC_FMULS	4)
+   (UNSPEC_FMULSU	5)
+  
    (UNSPECV_PROLOGUE_SAVES	0)
-   (UNSPECV_EPILOGUE_RESTORES	1)])
+   (UNSPECV_EPILOGUE_RESTORES	1)
+   (UNSPECV_SEI			2)
+   (UNSPECV_CLI			3)   
+   (UNSPECV_NOP			4)   
+   (UNSPECV_NOP2		5)   
+   (UNSPECV_SLEEP		6)   
+   (UNSPECV_WDR			7)   
 
+   (UNSPECV_DELAY_CYCLES	100)
+   (UNSPECV_DELAY_CYCLES_1	101)
+   (UNSPECV_DELAY_CYCLES_2	102)
+   (UNSPECV_DELAY_CYCLES_3	103)
+   (UNSPECV_DELAY_CYCLES_4	104)])
+
+
 (include "predicates.md")
 (include "constraints.md")
   
@@ -1182,6 +1195,19 @@
   [(set_attr "length" "4,4")
    (set_attr "cc" "set_n,clobber")])
 
+(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
 
@@ -1310,10 +1336,57 @@
   [(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")))]
@@ -1343,6 +1416,47 @@
 ;; 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" "")
@@ -1461,7 +1575,49 @@
 ;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
 ;; 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")))]
@@ -1491,6 +1647,47 @@
 ;; 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" "")
@@ -2290,22 +2487,22 @@
   "(register_operand (operands[0], HImode) || CONSTANT_P (operands[0]))"
   "*{
   if (which_alternative==0)
-     return \"icall\";
+     return \"%!icall\";
   else if (which_alternative==1)
     {
       if (AVR_HAVE_MOVW)
 	return (AS2 (movw, r30, %0) CR_TAB
-		\"icall\");
+               \"%!icall\");
       else
 	return (AS2 (mov, r30, %A0) CR_TAB
 		AS2 (mov, r31, %B0) CR_TAB
-		\"icall\");
+		\"%!icall\");
     }
   else if (which_alternative==2)
     return AS1(%~call,%c0);
   return (AS2 (ldi,r30,lo8(%0)) CR_TAB
           AS2 (ldi,r31,hi8(%0)) CR_TAB
-          \"icall\");
+          \"%!icall\");
 }"
   [(set_attr "cc" "clobber,clobber,clobber,clobber")
    (set_attr_alternative "length"
@@ -2327,22 +2524,22 @@
   "(register_operand (operands[0], VOIDmode) || CONSTANT_P (operands[0]))"
   "*{
   if (which_alternative==0)
-     return \"icall\";
+     return \"%!icall\";
   else if (which_alternative==1)
     {
       if (AVR_HAVE_MOVW)
 	return (AS2 (movw, r30, %1) CR_TAB
-		\"icall\");
+		\"%!icall\");
       else
 	return (AS2 (mov, r30, %A1) CR_TAB
 		AS2 (mov, r31, %B1) CR_TAB
-		\"icall\");
+		\"%!icall\");
     }
   else if (which_alternative==2)
     return AS1(%~call,%c1);
   return (AS2 (ldi, r30, lo8(%1)) CR_TAB
           AS2 (ldi, r31, hi8(%1)) CR_TAB
-          \"icall\");
+          \"%!icall\");
 }"
   [(set_attr "cc" "clobber,clobber,clobber,clobber")
    (set_attr_alternative "length"
@@ -2355,23 +2552,23 @@
 					(const_int 1))
 			  (const_int 3)])])
 
-(define_insn "nop"
-  [(const_int 0)]
-  ""
-  "nop"
-  [(set_attr "cc" "none")
-   (set_attr "length" "1")])
-
 ; indirect jump
 (define_insn "indirect_jump"
   [(set (pc) (match_operand:HI 0 "register_operand" "!z,*r"))]
-  ""
+  "!AVR_HAVE_EIJMP_EICALL"
   "@
 	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")
+   (set_attr "cc" "none")])
+
 ;; table jump
 
 ;; Table made from "rjmp" instructions for <=8K devices.
@@ -2380,7 +2577,7 @@
 			UNSPEC_INDEX_JMP))
    (use (label_ref (match_operand 1 "" "")))
    (clobber (match_dup 0))]
-  "!AVR_MEGA"
+  "(!AVR_MEGA) && (!AVR_HAVE_EIJMP_EICALL)"
   "@
 	ijmp
 	push %A0\;push %B0\;ret"
@@ -2409,7 +2606,7 @@
 	lpm __tmp_reg__,Z+
 	lpm r31,Z
 	mov r30,__tmp_reg__
-	ijmp"
+	%!ijmp"
   [(set_attr "length" "6")
    (set_attr "cc" "clobber")])
 
@@ -2418,7 +2615,7 @@
 			UNSPEC_INDEX_JMP))
    (use (label_ref (match_operand 1 "" "")))
    (clobber (match_dup 0))]
-  "AVR_MEGA"
+  "AVR_MEGA && !AVR_HAVE_EIJMP_EICALL"
   "lsl r30
 	rol r31
 	lpm
@@ -2477,7 +2674,8 @@
   "(optimize > 0)"
 {
   operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff));
-  return AS2 (cbi,%0-0x20,%2);
+  operands[3] = GEN_INT(AVR_IO_OFFSET);
+  return AS2 (cbi,%0-%3,%2);
 }
   [(set_attr "length" "1")
    (set_attr "cc" "none")])
@@ -2489,7 +2687,8 @@
   "(optimize > 0)"
 {
   operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff));
-  return AS2 (sbi,%0-0x20,%2);
+  operands[3] = GEN_INT(AVR_IO_OFFSET);
+  return AS2 (sbi,%0-%3,%2);
 }
   [(set_attr "length" "1")
    (set_attr "cc" "none")])
@@ -2732,7 +2931,7 @@
 
 ;; Enable Interrupts
 (define_insn "enable_interrupt"
-  [(unspec [(const_int 0)] UNSPEC_SEI)]
+  [(unspec_volatile [(const_int 0)] UNSPECV_SEI)]
   ""
   "sei"
   [(set_attr "length" "1")
@@ -2741,7 +2940,7 @@
 
 ;; Disable Interrupts
 (define_insn "disable_interrupt"
-  [(unspec [(const_int 0)] UNSPEC_CLI)]
+  [(unspec_volatile [(const_int 0)] UNSPECV_CLI)]
   ""
   "cli"
   [(set_attr "length" "1")
@@ -2758,8 +2957,8 @@
    (use (reg:HI REG_X))
    (clobber (reg:HI REG_Z))]
   ""
-  "ldi r30,pm_lo8(1f)
-	ldi r31,pm_hi8(1f)
+  "ldi r30,lo8(gs(1f))
+	ldi r31,hi8(gs(1f))
 	%~jmp __prologue_saves__+((18 - %0) * 2)
 1:"
   [(set_attr_alternative "length"
@@ -2841,3 +3040,219 @@
     expand_epilogue (); 
     DONE;
   }")
+
+;;delay_cycles_delay_cycles_delay_cycles_delay_cycles_delay_cycles_delay
+;; delay_cycles
+
+(define_expand "delay_cycles"
+  [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i")]
+                    UNSPECV_DELAY_CYCLES)]
+  ""
+  "
+  rtx loop_reg;
+  unsigned int cycles = INTVAL (operands[0]);
+  if (IN_RANGE(cycles, 83886082, 0xFFFFFFFF))
+    {
+      unsigned int loop_count = ((cycles - 9) / 6) + 1;
+      unsigned int cycles_used = (((loop_count - 1) * 6) + 9);
+      emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode)));
+      cycles -= cycles_used;
+    }
+  if (IN_RANGE(cycles, 262145, 83886081))
+    {
+      unsigned int loop_count = ((cycles - 7) / 5) + 1;
+      if (loop_count > 0xFFFFFF)
+        loop_count = 0xFFFFFF;
+      unsigned int cycles_used = (((loop_count - 1) * 5) + 7);
+      emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode)));
+      cycles -= cycles_used;
+    }
+  if (IN_RANGE(cycles, 768, 262144))
+    {
+      unsigned int loop_count = ((cycles - 5) / 4) + 1;
+      if (loop_count > 0xFFFF)
+        loop_count = 0xFFFF;
+      unsigned int cycles_used = (((loop_count - 1) * 4) + 5);
+      emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode)));
+      cycles -= cycles_used;
+    }
+  if (IN_RANGE(cycles, 6, 767))
+    {
+      unsigned int loop_count = (cycles/ 3);
+      if (loop_count > 255) 
+        loop_count = 255;
+      unsigned int cycles_used = (loop_count * 3);
+      emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode)));
+      cycles -= cycles_used;
+    }
+  while (cycles >= 2)
+    {
+      emit_insn (gen_nop2 ());
+      cycles -= 2;
+    }
+  if (cycles == 1)
+    {
+      emit_insn (gen_nop ());
+      cycles--;
+    }
+  DONE;
+  ")
+
+(define_insn "delay_cycles_1"
+[(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_1)
+  (match_operand:QI 0 "immediate_operand" "")
+  (clobber (match_scratch:QI 1 "=&d"))]
+  ""
+  " ldi %1,lo8(%0)
+    1:dec %1
+    brne 1b"
+  [(set_attr "length" "3")
+   (set_attr "cc" "clobber")]) 
+
+(define_insn "delay_cycles_2"
+  [(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_2)
+   (match_operand:HI 0 "immediate_operand" "")
+   (clobber (match_scratch:HI 1 "=&w"))]
+  ""
+  " ldi %A1,lo8(%0)
+    ldi %B1,hi8(%0)
+    1:sbiw %A1,1
+    brne 1b"
+  [(set_attr "length" "4")
+   (set_attr "cc" "clobber")])
+
+(define_insn "delay_cycles_3"
+  [(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_3)
+   (match_operand:SI 0 "immediate_operand" "")
+   (clobber (match_scratch:SI 1 "=&d"))]
+  ""
+  " ldi %A1,lo8(%0)
+    ldi %B1,hi8(%0)
+    ldi %C1,hlo8(%0)
+    1:subi %A1,1
+    sbci %B1,0
+    sbci %C1,0
+    brne 1b"
+  [(set_attr "length" "7")
+   (set_attr "cc" "clobber")])
+
+(define_insn "delay_cycles_4"
+  [(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_4)
+   (match_operand:SI 0 "immediate_operand" "")
+   (clobber (match_scratch:SI 1 "=&d"))]
+  ""
+  " ldi %A1,lo8(%0)
+    ldi %B1,hi8(%0)
+    ldi %C1,hlo8(%0)
+    ldi %D1,hhi8(%0)
+    1:subi %A1,1
+    sbci %B1,0
+    sbci %C1,0
+    sbci %D1,0
+    brne 1b"
+  [(set_attr "length" "9")
+   (set_attr "cc" "clobber")])
+
+;; CPU instructions
+
+;; NOP
+(define_insn "nop"
+  [(unspec_volatile [(const_int 0)] UNSPECV_NOP)]
+  ""
+  "nop"
+  [(set_attr "length" "1")
+  (set_attr "cc" "none")])
+
+;; NOP2
+(define_insn "nop2"
+  [(unspec_volatile [(const_int 0)] UNSPECV_NOP2)]
+  ""
+  "rjmp ."
+  [(set_attr "length" "1")
+  (set_attr "cc" "none")])
+
+;; SEI, Enable Interrupts
+;(define_insn "sei"
+;  [(unspec_volatile [(const_int 0)] UNSPECV_SEI)]
+;  ""
+;  "sei"
+;  [(set_attr "length" "1")
+;  (set_attr "cc" "none")
+;  ])
+
+;; CLI, Disable Interrupts
+;(define_insn "cli"
+;  [(unspec_volatile [(const_int 0)] UNSPECV_CLI)]
+;  ""
+;  "cli"
+;  [(set_attr "length" "1")
+;  (set_attr "cc" "none")
+;  ])
+
+;; SLEEP
+(define_insn "sleep"
+  [(unspec_volatile [(const_int 0)] UNSPECV_SLEEP)]
+  ""
+  "sleep"
+  [(set_attr "length" "1")
+  (set_attr "cc" "none")
+  ])
+ 
+;; WDR
+(define_insn "wdr"
+  [(unspec_volatile [(const_int 0)] UNSPECV_WDR)]
+  ""
+  "wdr"
+  [(set_attr "length" "1")
+  (set_attr "cc" "none")
+  ])
+  
+;; 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")])
+
+;; FMUL
+(define_insn "fmul"
+  [(set (match_operand:HI 0 "a_register_operand" "=r")
+	(unspec:HI [(match_operand:QI 1 "a_register_operand" "r")
+		    (match_operand:QI 2 "a_register_operand" "r")]
+		    UNSPEC_FMUL))]
+  "AVR_HAVE_MUL"
+  "fmul %1,%2
+	movw %0,r0
+	clr r1"
+  [(set_attr "length" "3")
+   (set_attr "cc" "clobber")])
+
+;; FMULS
+(define_insn "fmuls"
+  [(set (match_operand:HI 0 "a_register_operand" "=r")
+	(unspec:HI [(match_operand:QI 1 "a_register_operand" "r")
+		    (match_operand:QI 2 "a_register_operand" "r")]
+		    UNSPEC_FMULS))]
+  "AVR_HAVE_MUL"
+  "fmuls %1,%2
+	movw %0,r0
+	clr r1"
+  [(set_attr "length" "3")
+   (set_attr "cc" "clobber")])
+
+;; FMULSU
+(define_insn "fmulsu"
+  [(set (match_operand:HI 0 "a_register_operand" "=r")
+	(unspec:HI [(match_operand:QI 1 "a_register_operand" "r")
+		    (match_operand:QI 2 "a_register_operand" "r")]
+		    UNSPEC_FMULSU))]
+  "AVR_HAVE_MUL"
+  "fmulsu %1,%2
+	movw %0,r0
+	clr r1"
+  [(set_attr "length" "3")
+   (set_attr "cc" "clobber")])
+
