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 \

Reply via email to