This adds variable delays to __builtin_avr_delay_cycles.
Is this okay?
Johann
gcc/
PR target/56254
* config/avr/avr.c (avr_expand_builtin) <AVR_BUILTIN_DELAY_CYCLES>:
Expand to delay_cycles for non-const delays.
* config/avr/avr.md (delay_cycles): New expander.
(*delay_cycles.libgcc): New insn.
* config/avr/builtins.def (DELAY_CYCLES) <LIBNAME>: Set to
__delay_cycles.
* doc/extend.texi (AVR Built-in Functions)
<__builtin_avr_delay_cycles>: Adjust documentation.
libgcc/
PR target/56254
* config/avr/t-avr (LIB1ASMFUNCS): Add _delay_cycles.
* config/avr/lib1funcs.S (__delay_cycles): Implement it.
(skip): New macro.
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 \