1 diff -Naurp gcc/config/avr/avr.c gcc/config/avr/avr.c
2 --- gcc/config/avr/avr.c 2011-01-19 13:48:07.000000000 -0600
3 +++ gcc/config/avr/avr.c 2011-01-19 13:49:37.000000000 -0600
5 #include "insn-config.h"
6 #include "conditions.h"
8 +#include "insn-codes.h"
18 +#include "langhooks.h"
21 #include "target-def.h"
22 @@ -87,6 +90,8 @@ static bool avr_rtx_costs (rtx, int, int
23 static int avr_address_cost (rtx, bool);
24 static bool avr_return_in_memory (const_tree, const_tree);
25 static struct machine_function * avr_init_machine_status (void);
26 +static void avr_init_builtins (void);
27 +static rtx avr_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
28 static rtx avr_builtin_setjmp_frame_value (void);
29 static bool avr_hard_regno_scratch_ok (unsigned int);
30 static unsigned int avr_case_values_threshold (void);
31 @@ -197,6 +202,13 @@ static const struct attribute_spec avr_a
32 #undef TARGET_SCALAR_MODE_SUPPORTED_P
33 #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
35 +#undef TARGET_INIT_BUILTINS
36 +#define TARGET_INIT_BUILTINS avr_init_builtins
38 +#undef TARGET_EXPAND_BUILTIN
39 +#define TARGET_EXPAND_BUILTIN avr_expand_builtin
42 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */
44 avr_scalar_mode_supported_p (enum machine_mode mode)
45 @@ -7286,4 +7298,237 @@ unsigned int avr_case_values_threshold (
46 return (!AVR_HAVE_JMP_CALL || TARGET_CALL_PROLOGUES) ? 8 : 17;
49 +/* Codes for all the AVR builtins. */
61 + AVR_BUILTIN_DELAY_CYCLES
64 +#define def_builtin(NAME, TYPE, CODE) \
66 + add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
70 +/* Set up all builtin functions for this target. */
73 +avr_init_builtins (void)
75 + tree void_ftype_void
76 + = build_function_type (void_type_node, void_list_node);
77 + tree uchar_ftype_uchar
78 + = build_function_type_list (unsigned_char_type_node,
79 + unsigned_char_type_node,
81 + tree uint_ftype_uchar_uchar
82 + = build_function_type_list (unsigned_type_node,
83 + unsigned_char_type_node,
84 + unsigned_char_type_node,
86 + tree int_ftype_char_char
87 + = build_function_type_list (integer_type_node,
91 + tree int_ftype_char_uchar
92 + = build_function_type_list (integer_type_node,
94 + unsigned_char_type_node,
96 + tree void_ftype_ulong
97 + = build_function_type_list (void_type_node,
98 + long_unsigned_type_node,
101 + def_builtin ("__builtin_avr_sei", void_ftype_void, AVR_BUILTIN_SEI);
102 + def_builtin ("__builtin_avr_cli", void_ftype_void, AVR_BUILTIN_CLI);
103 + def_builtin ("__builtin_avr_wdr", void_ftype_void, AVR_BUILTIN_WDR);
104 + def_builtin ("__builtin_avr_sleep", void_ftype_void, AVR_BUILTIN_SLEEP);
108 + def_builtin ("__builtin_avr_fmul", uint_ftype_uchar_uchar,
110 + def_builtin ("__builtin_avr_fmuls", int_ftype_char_char,
111 + AVR_BUILTIN_FMULS);
112 + def_builtin ("__builtin_avr_fmulsu", int_ftype_char_uchar,
113 + AVR_BUILTIN_FMULSU);
116 + def_builtin ("__builtin_avr_swap", uchar_ftype_uchar, AVR_BUILTIN_SWAP);
117 + def_builtin ("__builtin_avr_delay_cycles", void_ftype_ulong,
118 + AVR_BUILTIN_DELAY_CYCLES);
121 +struct builtin_description
123 + const enum insn_code icode;
124 + const char *const name;
125 + const enum avr_builtins code;
128 +static const struct builtin_description bdesc_1arg[] =
130 + { CODE_FOR_swap, "__builtin_avr_swap", AVR_BUILTIN_SWAP }
133 +static const struct builtin_description bdesc_2arg[] =
135 + { CODE_FOR_fmul, "__builtin_avr_fmul", AVR_BUILTIN_FMUL },
136 + { CODE_FOR_fmuls, "__builtin_avr_fmuls", AVR_BUILTIN_FMULS },
137 + { CODE_FOR_fmulsu, "__builtin_avr_fmulsu", AVR_BUILTIN_FMULSU }
140 +/* Subroutine of avr_expand_builtin to take care of unop insns. */
143 +avr_expand_unop_builtin (enum insn_code icode, tree exp,
147 + tree arg0 = CALL_EXPR_ARG (exp, 0);
148 + rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
149 + enum machine_mode op0mode = GET_MODE (op0);
150 + enum machine_mode tmode = insn_data[icode].operand[0].mode;
151 + enum machine_mode mode0 = insn_data[icode].operand[1].mode;
154 + || GET_MODE (target) != tmode
155 + || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
156 + target = gen_reg_rtx (tmode);
158 + if (op0mode == SImode && mode0 == HImode)
161 + op0 = gen_lowpart (HImode, op0);
163 + gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
165 + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
166 + op0 = copy_to_mode_reg (mode0, op0);
168 + pat = GEN_FCN (icode) (target, op0);
175 +/* Subroutine of avr_expand_builtin to take care of binop insns. */
178 +avr_expand_binop_builtin (enum insn_code icode, tree exp, rtx target)
181 + tree arg0 = CALL_EXPR_ARG (exp, 0);
182 + tree arg1 = CALL_EXPR_ARG (exp, 1);
183 + rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
184 + rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
185 + enum machine_mode op0mode = GET_MODE (op0);
186 + enum machine_mode op1mode = GET_MODE (op1);
187 + enum machine_mode tmode = insn_data[icode].operand[0].mode;
188 + enum machine_mode mode0 = insn_data[icode].operand[1].mode;
189 + enum machine_mode mode1 = insn_data[icode].operand[2].mode;
192 + || GET_MODE (target) != tmode
193 + || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
194 + target = gen_reg_rtx (tmode);
196 + if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
199 + op0 = gen_lowpart (HImode, op0);
201 + if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
204 + op1 = gen_lowpart (HImode, op1);
206 + /* In case the insn wants input operands in modes different from
207 + the result, abort. */
208 + gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
209 + && (op1mode == mode1 || op1mode == VOIDmode));
211 + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
212 + op0 = copy_to_mode_reg (mode0, op0);
213 + if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
214 + op1 = copy_to_mode_reg (mode1, op1);
216 + pat = GEN_FCN (icode) (target, op0, op1);
224 +/* Expand an expression EXP that calls a built-in function,
225 + with result going to TARGET if that's convenient
226 + (and in mode MODE if that's convenient).
227 + SUBTARGET may be used as the target for computing one of EXP's operands.
228 + IGNORE is nonzero if the value is to be ignored. */
231 +avr_expand_builtin (tree exp, rtx target,
232 + rtx subtarget ATTRIBUTE_UNUSED,
233 + enum machine_mode mode ATTRIBUTE_UNUSED,
234 + int ignore ATTRIBUTE_UNUSED)
237 + const struct builtin_description *d;
238 + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
239 + unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
246 + case AVR_BUILTIN_SEI:
247 + emit_insn (gen_enable_interrupt ());
249 + case AVR_BUILTIN_CLI:
250 + emit_insn (gen_disable_interrupt ());
252 + case AVR_BUILTIN_WDR:
253 + emit_insn (gen_wdr ());
255 + case AVR_BUILTIN_SLEEP:
256 + emit_insn (gen_sleep ());
258 + case AVR_BUILTIN_DELAY_CYCLES:
260 + arg0 = CALL_EXPR_ARG (exp, 0);
261 + op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
263 + if (!CONSTANT_P (op0))
264 + error ("__builtin_avr_delay_cycles expects an integer constant.");
266 + emit_insn (gen_delay_cycles (op0));
271 + for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
272 + if (d->code == fcode)
273 + return avr_expand_unop_builtin (d->icode, exp, target);
275 + for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
276 + if (d->code == fcode)
277 + return avr_expand_binop_builtin (d->icode, exp, target);
279 + gcc_unreachable ();
283 diff -Naurp gcc/config/avr/avr.md gcc/config/avr/avr.md
284 --- gcc/config/avr/avr.md 2011-01-19 13:45:00.000000000 -0600
285 +++ gcc/config/avr/avr.md 2011-01-19 13:49:37.000000000 -0600
298 (UNSPECV_PROLOGUE_SAVES 0)
299 (UNSPECV_EPILOGUE_RESTORES 1)
300 (UNSPECV_WRITE_SP_IRQ_ON 2)
301 (UNSPECV_WRITE_SP_IRQ_OFF 3)
302 - (UNSPECV_GOTO_RECEIVER 4)])
303 + (UNSPECV_GOTO_RECEIVER 4)
311 + (UNSPECV_DELAY_CYCLES 100)
312 + (UNSPECV_DELAY_CYCLES_1 101)
313 + (UNSPECV_DELAY_CYCLES_2 102)
314 + (UNSPECV_DELAY_CYCLES_3 103)
315 + (UNSPECV_DELAY_CYCLES_4 104)])
317 (include "predicates.md")
318 (include "constraints.md")
319 @@ -2813,13 +2828,6 @@
327 - [(set_attr "cc" "none")
328 - (set_attr "length" "1")])
332 (define_expand "indirect_jump"
333 @@ -3221,7 +3229,7 @@
336 (define_insn "enable_interrupt"
337 - [(unspec [(const_int 0)] UNSPEC_SEI)]
338 + [(unspec_volatile [(const_int 0)] UNSPECV_SEI)]
341 [(set_attr "length" "1")
342 @@ -3230,7 +3238,7 @@
344 ;; Disable Interrupts
345 (define_insn "disable_interrupt"
346 - [(unspec [(const_int 0)] UNSPEC_CLI)]
347 + [(unspec_volatile [(const_int 0)] UNSPECV_CLI)]
350 [(set_attr "length" "1")
351 @@ -3330,3 +3338,219 @@
356 +;;delay_cycles_delay_cycles_delay_cycles_delay_cycles_delay_cycles_delay
359 +(define_expand "delay_cycles"
360 + [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i")]
361 + UNSPECV_DELAY_CYCLES)]
365 + unsigned int cycles = INTVAL (operands[0]);
366 + if (IN_RANGE(cycles, 83886082, 0xFFFFFFFF))
368 + unsigned int loop_count = ((cycles - 9) / 6) + 1;
369 + unsigned int cycles_used = (((loop_count - 1) * 6) + 9);
370 + emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode)));
371 + cycles -= cycles_used;
373 + if (IN_RANGE(cycles, 262145, 83886081))
375 + unsigned int loop_count = ((cycles - 7) / 5) + 1;
376 + if (loop_count > 0xFFFFFF)
377 + loop_count = 0xFFFFFF;
378 + unsigned int cycles_used = (((loop_count - 1) * 5) + 7);
379 + emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode)));
380 + cycles -= cycles_used;
382 + if (IN_RANGE(cycles, 768, 262144))
384 + unsigned int loop_count = ((cycles - 5) / 4) + 1;
385 + if (loop_count > 0xFFFF)
386 + loop_count = 0xFFFF;
387 + unsigned int cycles_used = (((loop_count - 1) * 4) + 5);
388 + emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode)));
389 + cycles -= cycles_used;
391 + if (IN_RANGE(cycles, 6, 767))
393 + unsigned int loop_count = (cycles/ 3);
394 + if (loop_count > 255)
396 + unsigned int cycles_used = (loop_count * 3);
397 + emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode)));
398 + cycles -= cycles_used;
400 + while (cycles >= 2)
402 + emit_insn (gen_nop2 ());
407 + emit_insn (gen_nop ());
413 +(define_insn "delay_cycles_1"
414 +[(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_1)
415 + (match_operand:QI 0 "immediate_operand" "")
416 + (clobber (match_scratch:QI 1 "=&d"))]
421 + [(set_attr "length" "3")
422 + (set_attr "cc" "clobber")])
424 +(define_insn "delay_cycles_2"
425 + [(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_2)
426 + (match_operand:HI 0 "immediate_operand" "")
427 + (clobber (match_scratch:HI 1 "=&w"))]
433 + [(set_attr "length" "4")
434 + (set_attr "cc" "clobber")])
436 +(define_insn "delay_cycles_3"
437 + [(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_3)
438 + (match_operand:SI 0 "immediate_operand" "")
439 + (clobber (match_scratch:SI 1 "=&d"))]
448 + [(set_attr "length" "7")
449 + (set_attr "cc" "clobber")])
451 +(define_insn "delay_cycles_4"
452 + [(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_4)
453 + (match_operand:SI 0 "immediate_operand" "")
454 + (clobber (match_scratch:SI 1 "=&d"))]
465 + [(set_attr "length" "9")
466 + (set_attr "cc" "clobber")])
472 + [(unspec_volatile [(const_int 0)] UNSPECV_NOP)]
475 + [(set_attr "length" "1")
476 + (set_attr "cc" "none")])
480 + [(unspec_volatile [(const_int 0)] UNSPECV_NOP2)]
483 + [(set_attr "length" "1")
484 + (set_attr "cc" "none")])
486 +;; SEI, Enable Interrupts
488 +; [(unspec_volatile [(const_int 0)] UNSPECV_SEI)]
491 +; [(set_attr "length" "1")
492 +; (set_attr "cc" "none")
495 +;; CLI, Disable Interrupts
497 +; [(unspec_volatile [(const_int 0)] UNSPECV_CLI)]
500 +; [(set_attr "length" "1")
501 +; (set_attr "cc" "none")
505 +(define_insn "sleep"
506 + [(unspec_volatile [(const_int 0)] UNSPECV_SLEEP)]
509 + [(set_attr "length" "1")
510 + (set_attr "cc" "none")
515 + [(unspec_volatile [(const_int 0)] UNSPECV_WDR)]
518 + [(set_attr "length" "1")
519 + (set_attr "cc" "none")
524 + [(set (match_operand:QI 0 "register_operand" "=r")
525 + (unspec:QI [(match_operand:QI 1 "register_operand" "0")]
529 + [(set_attr "length" "1")
530 + (set_attr "cc" "none")])
534 + [(set (match_operand:HI 0 "a_register_operand" "=r")
535 + (unspec:HI [(match_operand:QI 1 "a_register_operand" "r")
536 + (match_operand:QI 2 "a_register_operand" "r")]
542 + [(set_attr "length" "3")
543 + (set_attr "cc" "clobber")])
546 +(define_insn "fmuls"
547 + [(set (match_operand:HI 0 "a_register_operand" "=r")
548 + (unspec:HI [(match_operand:QI 1 "a_register_operand" "r")
549 + (match_operand:QI 2 "a_register_operand" "r")]
555 + [(set_attr "length" "3")
556 + (set_attr "cc" "clobber")])
559 +(define_insn "fmulsu"
560 + [(set (match_operand:HI 0 "a_register_operand" "=r")
561 + (unspec:HI [(match_operand:QI 1 "a_register_operand" "r")
562 + (match_operand:QI 2 "a_register_operand" "r")]
568 + [(set_attr "length" "3")
569 + (set_attr "cc" "clobber")])
571 diff -Naurp gcc/config/avr/predicates.md gcc/config/avr/predicates.md
572 --- gcc/config/avr/predicates.md 2011-01-19 13:03:59.000000000 -0600
573 +++ gcc/config/avr/predicates.md 2011-01-19 13:49:37.000000000 -0600
575 (and (match_code "reg")
576 (match_test "REGNO (op) >= 16 && REGNO (op) <= 31")))
578 +;; Registers from r16 to 24.
579 +(define_predicate "a_register_operand"
580 + (and (match_code "reg")
581 + (match_test "REGNO (op) >= 16 && REGNO (op) <= 24")))
583 (define_predicate "even_register_operand"
584 (and (match_code "reg")
585 (and (match_test "REGNO (op) <= 31")