---- ./gcc/config/avr/predicates.md.orig 2007-08-02 12:49:31.000000000 +0200
-+++ ./gcc/config/avr/predicates.md 2010-03-05 15:25:53.000000000 +0100
-@@ -27,6 +27,11 @@
- (and (match_code "reg")
- (match_test "REGNO (op) >= 16 && REGNO (op) <= 31")))
-
-+;; Registers from r16 to 24.
-+(define_predicate "a_register_operand"
-+ (and (match_code "reg")
-+ (match_test "REGNO (op) >= 16 && REGNO (op) <= 24")))
-+
- (define_predicate "even_register_operand"
- (and (match_code "reg")
- (and (match_test "REGNO (op) <= 31")
---- ./gcc/config/avr/avr.md.orig 2010-03-05 15:20:25.000000000 +0100
-+++ ./gcc/config/avr/avr.md 2010-03-05 15:25:53.000000000 +0100
-@@ -52,12 +52,26 @@
-
- (UNSPEC_STRLEN 0)
- (UNSPEC_INDEX_JMP 1)
-- (UNSPEC_SEI 2)
-- (UNSPEC_CLI 3)
-- (UNSPEC_SWAP 4)
--
-+ (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")
-@@ -2541,13 +2555,6 @@
- (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"))]
-@@ -2925,7 +2932,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")
-@@ -2934,7 +2941,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")
-@@ -3034,3 +3041,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")])
-+
---- ./gcc/config/avr/avr.c.orig 2010-03-05 15:24:52.000000000 +0100
-+++ ./gcc/config/avr/avr.c 2010-03-05 15:25:53.000000000 +0100
+diff -Naurp gcc/config/avr/avr.c gcc/config/avr/avr.c
+--- gcc/config/avr/avr.c 2011-01-19 13:48:07.000000000 -0600
++++ gcc/config/avr/avr.c 2011-01-19 13:49:37.000000000 -0600
@@ -30,6 +30,7 @@
#include "insn-config.h"
#include "conditions.h"
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
-@@ -87,6 +90,9 @@
- static int avr_address_cost (rtx);
+@@ -87,6 +90,8 @@ static bool avr_rtx_costs (rtx, int, int
+ static int avr_address_cost (rtx, bool);
static bool avr_return_in_memory (const_tree, const_tree);
static struct machine_function * avr_init_machine_status (void);
+static void avr_init_builtins (void);
+static rtx avr_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
-+
- /* Allocate registers from r25 to r8 for parameters for function calls. */
- #define FIRST_CUM_REG 26
-
-@@ -340,6 +346,12 @@
- #undef TARGET_STRICT_ARGUMENT_NAMING
- #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
+ static rtx avr_builtin_setjmp_frame_value (void);
+ static bool avr_hard_regno_scratch_ok (unsigned int);
+ static unsigned int avr_case_values_threshold (void);
+@@ -197,6 +202,13 @@ static const struct attribute_spec avr_a
+ #undef TARGET_SCALAR_MODE_SUPPORTED_P
+ #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS avr_init_builtins
-+
++
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN avr_expand_builtin
+
- struct gcc_target targetm = TARGET_INITIALIZER;
- \f
- void
-@@ -6079,4 +6091,237 @@
- return false;
++
+ /* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */
+ static bool
+ avr_scalar_mode_supported_p (enum machine_mode mode)
+@@ -7286,4 +7298,237 @@ unsigned int avr_case_values_threshold (
+ return (!AVR_HAVE_JMP_CALL || TARGET_CALL_PROLOGUES) ? 8 : 17;
}
+/* Codes for all the AVR builtins. */
+
+ if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
+ {
-+ op0mode = HImode;
-+ op0 = gen_lowpart (HImode, op0);
++ op0mode = HImode;
++ op0 = gen_lowpart (HImode, op0);
++ }
++ if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
++ {
++ op1mode = HImode;
++ op1 = gen_lowpart (HImode, op1);
++ }
++ /* In case the insn wants input operands in modes different from
++ the result, abort. */
++ gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
++ && (op1mode == mode1 || op1mode == VOIDmode));
++
++ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
++ op0 = copy_to_mode_reg (mode0, op0);
++ if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
++ op1 = copy_to_mode_reg (mode1, op1);
++
++ pat = GEN_FCN (icode) (target, op0, op1);
++ if (! pat)
++ return 0;
++
++ emit_insn (pat);
++ return target;
++}
++
++/* Expand an expression EXP that calls a built-in function,
++ with result going to TARGET if that's convenient
++ (and in mode MODE if that's convenient).
++ SUBTARGET may be used as the target for computing one of EXP's operands.
++ IGNORE is nonzero if the value is to be ignored. */
++
++static rtx
++avr_expand_builtin (tree exp, rtx target,
++ rtx subtarget ATTRIBUTE_UNUSED,
++ enum machine_mode mode ATTRIBUTE_UNUSED,
++ int ignore ATTRIBUTE_UNUSED)
++{
++ size_t i;
++ const struct builtin_description *d;
++ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
++ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
++ rtx pat;
++ tree arg0;
++ rtx op0;
++
++ switch (fcode)
++ {
++ case AVR_BUILTIN_SEI:
++ emit_insn (gen_enable_interrupt ());
++ return 0;
++ case AVR_BUILTIN_CLI:
++ emit_insn (gen_disable_interrupt ());
++ return 0;
++ case AVR_BUILTIN_WDR:
++ emit_insn (gen_wdr ());
++ return 0;
++ case AVR_BUILTIN_SLEEP:
++ emit_insn (gen_sleep ());
++ return 0;
++ case AVR_BUILTIN_DELAY_CYCLES:
++ {
++ arg0 = CALL_EXPR_ARG (exp, 0);
++ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
++
++ if (!CONSTANT_P (op0))
++ error ("__builtin_avr_delay_cycles expects an integer constant.");
++
++ emit_insn (gen_delay_cycles (op0));
++ return 0;
++ }
++ }
++
++ for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
++ if (d->code == fcode)
++ return avr_expand_unop_builtin (d->icode, exp, target);
++
++ for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
++ if (d->code == fcode)
++ return avr_expand_binop_builtin (d->icode, exp, target);
++
++ gcc_unreachable ();
++}
++
+ #include "gt-avr.h"
+diff -Naurp gcc/config/avr/avr.md gcc/config/avr/avr.md
+--- gcc/config/avr/avr.md 2011-01-19 13:45:00.000000000 -0600
++++ gcc/config/avr/avr.md 2011-01-19 13:49:37.000000000 -0600
+@@ -51,14 +51,29 @@
+
+ (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_WRITE_SP_IRQ_ON 2)
+ (UNSPECV_WRITE_SP_IRQ_OFF 3)
+- (UNSPECV_GOTO_RECEIVER 4)])
++ (UNSPECV_GOTO_RECEIVER 4)
++ (UNSPECV_SEI 5)
++ (UNSPECV_CLI 6)
++ (UNSPECV_NOP 7)
++ (UNSPECV_NOP2 8)
++ (UNSPECV_SLEEP 9)
++ (UNSPECV_WDR 10)
++
++ (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")
+@@ -2813,13 +2828,6 @@
+ (const_int 1))
+ (const_int 3)])])
+
+-(define_insn "nop"
+- [(const_int 0)]
+- ""
+- "nop"
+- [(set_attr "cc" "none")
+- (set_attr "length" "1")])
+-
+ ; indirect jump
+
+ (define_expand "indirect_jump"
+@@ -3221,7 +3229,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")
+@@ -3230,7 +3238,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")
+@@ -3330,3 +3338,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 ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
++ if (IN_RANGE(cycles, 6, 767))
+ {
-+ op1mode = HImode;
-+ op1 = gen_lowpart (HImode, op1);
++ 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;
+ }
-+ /* In case the insn wants input operands in modes different from
-+ the result, abort. */
-+ gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
-+ && (op1mode == mode1 || op1mode == VOIDmode));
++ while (cycles >= 2)
++ {
++ emit_insn (gen_nop2 ());
++ cycles -= 2;
++ }
++ if (cycles == 1)
++ {
++ emit_insn (gen_nop ());
++ cycles--;
++ }
++ DONE;
++ ")
+
-+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
-+ op0 = copy_to_mode_reg (mode0, op0);
-+ if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
-+ op1 = copy_to_mode_reg (mode1, op1);
++(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")])
+
-+ pat = GEN_FCN (icode) (target, op0, op1);
-+ if (! pat)
-+ return 0;
++(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")])
+
-+ emit_insn (pat);
-+ return target;
-+}
++(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")])
+
-+/* Expand an expression EXP that calls a built-in function,
-+ with result going to TARGET if that's convenient
-+ (and in mode MODE if that's convenient).
-+ SUBTARGET may be used as the target for computing one of EXP's operands.
-+ IGNORE is nonzero if the value is to be ignored. */
++(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")])
+
-+static rtx
-+avr_expand_builtin (tree exp, rtx target,
-+ rtx subtarget ATTRIBUTE_UNUSED,
-+ enum machine_mode mode ATTRIBUTE_UNUSED,
-+ int ignore ATTRIBUTE_UNUSED)
-+{
-+ size_t i;
-+ const struct builtin_description *d;
-+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
-+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
-+ rtx pat;
-+ tree arg0;
-+ rtx op0;
++;; CPU instructions
+
-+ switch (fcode)
-+ {
-+ case AVR_BUILTIN_SEI:
-+ emit_insn (gen_enable_interrupt ());
-+ return 0;
-+ case AVR_BUILTIN_CLI:
-+ emit_insn (gen_disable_interrupt ());
-+ return 0;
-+ case AVR_BUILTIN_WDR:
-+ emit_insn (gen_wdr ());
-+ return 0;
-+ case AVR_BUILTIN_SLEEP:
-+ emit_insn (gen_sleep ());
-+ return 0;
-+ case AVR_BUILTIN_DELAY_CYCLES:
-+ {
-+ arg0 = CALL_EXPR_ARG (exp, 0);
-+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
++;; NOP
++(define_insn "nop"
++ [(unspec_volatile [(const_int 0)] UNSPECV_NOP)]
++ ""
++ "nop"
++ [(set_attr "length" "1")
++ (set_attr "cc" "none")])
+
-+ if (!CONSTANT_P (op0))
-+ error ("__builtin_avr_delay_cycles expects an integer constant.");
++;; NOP2
++(define_insn "nop2"
++ [(unspec_volatile [(const_int 0)] UNSPECV_NOP2)]
++ ""
++ "rjmp ."
++ [(set_attr "length" "1")
++ (set_attr "cc" "none")])
+
-+ emit_insn (gen_delay_cycles (op0));
-+ return 0;
-+ }
-+ }
++;; SEI, Enable Interrupts
++;(define_insn "sei"
++; [(unspec_volatile [(const_int 0)] UNSPECV_SEI)]
++; ""
++; "sei"
++; [(set_attr "length" "1")
++; (set_attr "cc" "none")
++; ])
+
-+ for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
-+ if (d->code == fcode)
-+ return avr_expand_unop_builtin (d->icode, exp, target);
++;; CLI, Disable Interrupts
++;(define_insn "cli"
++; [(unspec_volatile [(const_int 0)] UNSPECV_CLI)]
++; ""
++; "cli"
++; [(set_attr "length" "1")
++; (set_attr "cc" "none")
++; ])
+
-+ for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
-+ if (d->code == fcode)
-+ return avr_expand_binop_builtin (d->icode, exp, target);
++;; 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")])
+
-+ gcc_unreachable ();
-+}
++;; 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")])
+
- #include "gt-avr.h"
++;; 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")])
++
+diff -Naurp gcc/config/avr/predicates.md gcc/config/avr/predicates.md
+--- gcc/config/avr/predicates.md 2011-01-19 13:03:59.000000000 -0600
++++ gcc/config/avr/predicates.md 2011-01-19 13:49:37.000000000 -0600
+@@ -27,6 +27,11 @@
+ (and (match_code "reg")
+ (match_test "REGNO (op) >= 16 && REGNO (op) <= 31")))
+
++;; Registers from r16 to 24.
++(define_predicate "a_register_operand"
++ (and (match_code "reg")
++ (match_test "REGNO (op) >= 16 && REGNO (op) <= 24")))
++
+ (define_predicate "even_register_operand"
+ (and (match_code "reg")
+ (and (match_test "REGNO (op) <= 31")