Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 195736) +++ gcc/doc/extend.texi (working copy) @@ -9030,8 +9030,8 @@ void __builtin_avr_delay_cycles (unsigne @noindent @code{ticks} is the number of ticks to delay execution. Note that this built-in does not take into account the effect of interrupts that -might increase delay time. @code{ticks} must be a compile-time -integer constant; delays with a variable number of cycles are not supported. +might increase delay time. If @code{ticks} is not a compile-time +constant, the delay might be overestimated by up to 15@tie{}cycles. @smallexample char __builtin_avr_flash_segment (const __memx void*) Index: gcc/config/avr/builtins.def =================================================================== --- gcc/config/avr/builtins.def (revision 195878) +++ gcc/config/avr/builtins.def (working copy) @@ -50,7 +50,7 @@ DEF_BUILTIN (FMULSU, 2, int_ftype_char_u /* More complex stuff that cannot be mapped 1:1 to an instruction. */ -DEF_BUILTIN (DELAY_CYCLES, -1, void_ftype_ulong, nothing, NULL) +DEF_BUILTIN (DELAY_CYCLES, -1, void_ftype_ulong, nothing, "__delay_cycles") DEF_BUILTIN (INSERT_BITS, 3, uchar_ftype_ulong_uchar_uchar, insert_bits, NULL) DEF_BUILTIN (FLASH_SEGMENT, 1, char_ftype_const_memx_ptr, flash_segment, NULL) Index: gcc/config/avr/avr.md =================================================================== --- gcc/config/avr/avr.md (revision 195878) +++ gcc/config/avr/avr.md (working copy) @@ -5495,6 +5495,27 @@ (define_expand "sibcall_epilogue" ;; Some instructions resp. instruction sequences available ;; via builtins. +(define_expand "delay_cycles" + [(set (reg:SI 22) + (match_operand:SI 0 "register_operand" "")) + (parallel [(set (reg:SI 22) + (unspec_volatile:SI [(reg:SI 22)] + UNSPECV_DELAY_CYCLES)) + (set (match_operand:BLK 1 "" "") + (unspec_volatile:BLK [(match_dup 1)] + UNSPECV_MEMORY_BARRIER))])]) + +(define_insn "*delay_cycles.libgcc" + [(set (reg:SI 22) + (unspec_volatile:SI [(reg:SI 22)] + UNSPECV_DELAY_CYCLES)) + (set (match_operand:BLK 0 "" "") + (unspec_volatile:BLK [(match_dup 0)] UNSPECV_MEMORY_BARRIER))] + "" + "%~call __delay_cycles" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + (define_insn "delay_cycles_1" [(unspec_volatile [(match_operand:QI 0 "const_int_operand" "n") (const_int 1)] Index: gcc/config/avr/avr.c =================================================================== --- gcc/config/avr/avr.c (revision 195878) +++ gcc/config/avr/avr.c (working copy) @@ -11707,18 +11707,18 @@ avr_expand_builtin (tree exp, rtx target { case AVR_BUILTIN_NOP: emit_insn (gen_nopv (GEN_INT(1))); - return 0; + return NULL_RTX; case AVR_BUILTIN_DELAY_CYCLES: { arg0 = CALL_EXPR_ARG (exp, 0); op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL); - if (!CONST_INT_P (op0)) - error ("%s expects a compile time integer constant", bname); - else + if (CONST_INT_P (op0)) avr_expand_delay_cycles (op0); - + else + emit_insn (gen_delay_cycles (force_reg (SImode, op0), + avr_mem_clobber())); return NULL_RTX; } Index: libgcc/config/avr/lib1funcs.S =================================================================== --- libgcc/config/avr/lib1funcs.S (revision 195878) +++ libgcc/config/avr/lib1funcs.S (working copy) @@ -128,6 +128,9 @@ see the files COPYING3 and COPYING.RUNTI #define exp_lo(N) hlo8 ((N) << 23) #define exp_hi(N) hhi8 ((N) << 23) +;; Skip the next instruction, typically a jump target +#define skip cpse 0,0 + .section .text.libgcc.mul, "ax", @progbits @@ -2752,6 +2755,30 @@ DEFUN __bswapdi2 ENDF __bswapdi2 #endif /* defined (L_bswapdi2) */ +#if defined (L_delay_cycles) + +#define A0 22 +#define A1 A0+1 +#define A2 A0+2 +#define A3 A0+3 + +DEFUN __delay_cycles + subi A0, 14 + skip +0: subi A0, 6 + sbci A1, 0 + sbci A2, 0 + sbci A3, 0 + brcc 0b + ret +ENDF __delay_cycles + +#undef A0 +#undef A1 +#undef A2 +#undef A3 +#endif /* L_delay_cycles */ + /********************************** * 64-bit shifts Index: libgcc/config/avr/t-avr =================================================================== --- libgcc/config/avr/t-avr (revision 195878) +++ libgcc/config/avr/t-avr (working copy) @@ -51,6 +51,7 @@ LIB1ASMFUNCS = \ _popcountqi2 \ _bswapsi2 \ _bswapdi2 \ + _delay_cycles \ _ashldi3 _ashrdi3 _lshrdi3 _rotldi3 \ _adddi3 _adddi3_s8 _subdi3 \ _cmpdi2 _cmpdi2_s8 \