bool
avr_builtin_supported_p (unsigned id)
{
- const bool uses_as = id == AVR_BUILTIN_FLASH_SEGMENT;
+ const bool uses_as = (id == AVR_BUILTIN_FLASH_SEGMENT
+ || id == AVR_BUILTIN_STRLEN_FLASH
+ || id == AVR_BUILTIN_STRLEN_FLASHX
+ || id == AVR_BUILTIN_STRLEN_MEMX);
// We don't support address-spaces on Reduced Tiny.
if (AVR_TINY && uses_as)
}
+/* Return a function signature type similar to strlen, but where
+ the address is qualified by named address-space AS. */
+
+static tree
+avr_ftype_strlen (addr_space_t as)
+{
+ tree const_AS_char_node
+ = build_qualified_type (char_type_node,
+ TYPE_QUAL_CONST | ENCODE_QUAL_ADDR_SPACE (as));
+ tree const_AS_ptr_type_node
+ = build_pointer_type_for_mode (const_AS_char_node,
+ avr_addr_space_pointer_mode (as), false);
+ tree size_ftype_const_AS_char_ptr
+ = build_function_type_list (size_type_node, const_AS_ptr_type_node, NULL);
+
+ return size_ftype_const_AS_char_ptr;
+}
+
+
/* Implement `TARGET_INIT_BUILTINS' */
/* Set up all builtin functions for this target. */
const_memx_ptr_type_node,
NULL);
+ tree strlen_flash_node = avr_ftype_strlen (ADDR_SPACE_FLASH);
+ tree strlen_flashx_node = avr_ftype_strlen (ADDR_SPACE_FLASHX);
+ tree strlen_memx_node = avr_ftype_strlen (ADDR_SPACE_MEMX);
+
#define ITYP(T) \
lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
build_int_cst (val_type, 4));
}
+ case AVR_BUILTIN_STRLEN_FLASH:
+ case AVR_BUILTIN_STRLEN_FLASHX:
+ case AVR_BUILTIN_STRLEN_MEMX:
+ if (tree len = c_strlen (arg[0], 0))
+ return len;
+ break;
+
case AVR_BUILTIN_ABSHR:
case AVR_BUILTIN_ABSR:
case AVR_BUILTIN_ABSLR:
DEF_BUILTIN (FLASH_SEGMENT, 1, intQI_ftype_const_memx_ptr, flash_segment, NULL, attr_const)
+/* strlen for ASes so that __builtin_constant_p can be used wthout raising
+ a diagnostic from -Waddr-space-convert in some AVR-LibC headers. */
+DEF_BUILTIN (STRLEN_FLASH, 1, strlen_flash_node, nothing, "__strlen_P", attr_const) // AVR-LibC
+DEF_BUILTIN (STRLEN_FLASHX, 1, strlen_flashx_node, nothing, "strlen_PF", attr_const) // AVR-LibC
+DEF_BUILTIN (STRLEN_MEMX, 1, strlen_memx_node, nothing, "__strlen_memx", NULL_TREE)
+
/* ISO/IEC TR 18037 "Embedded C"
The following builtins are undocumented and used by stdfix.h. */
If the address does not point to flash memory, return @code{-1}.
@enddefbuiltin
+@defbuiltin{size_t __builtin_avr_strlen_flash (const __flash char*)}
+@defbuiltinx{size_t __builtin_avr_strlen_flashx (const __flashx char*)}
+@defbuiltinx{size_t __builtin_avr_strlen_memx (const __memx char*)}
+These built-ins return the length of a string located in
+named address-space @code{__flash}, @code{__flashx} or @code{__memx},
+respectively. They are used to support functions like @code{strlen_F} from
+@w{@uref{https://avrdudes.github.io/avr-libc/avr-libc-user-manual/,AVR-LibC}}'s
+header @code{avr/flash.h}.
+@enddefbuiltin
+
@noindent
There are many more AVR-specific built-in functions that are used to
implement the ISO/IEC TR 18037 ``Embedded C'' fixed-point functions of
#endif /* L_fload_{1|2|3|4} */
#endif /* if !defined (__AVR_TINY__) */
+
+#if !defined (__AVR_TINY__)
+#if defined (L_strlen_memx)
+DEFUN __strlen_memx
+#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
+ tst r24
+ brmi 1f
+#else
+ sbrs r24, 7
+#endif
+ XJMP strlen_PF ; AVR-LibC
+1: wmov 24, 22
+ XJMP strlen ; AVR-LibC
+ENDF __strlen_memx
+#endif /* L_strlen_memx */
+#endif /* if !defined (__AVR_TINY__) */
+
+
#if !defined (__AVR_TINY__)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; memcopy from Address Space __memx to RAM
_popcountsi2 \
_popcountqi2 \
_bswapsi2 \
- _fmul _fmuls _fmulsu
+ _fmul _fmuls _fmulsu \
+ _strlen_memx
# The below functions either use registers that are not present
# in tiny core, or use a different register convention (don't save