This built-in basically returns the high byte of a 24-bit address. It can be used to test at run time where a pointer points to (Flash or RAM).
Ok for trunk? Johann * doc/extend.texi (AVR Built-in Functions): Document __builtin_avr_flash_segment. * config/avr/builtins.def (__builtin_avr_flash_segment): New entry. * config/avr/avr.md (flash_segment, flash_segment1): New expanders. (*split.flash_segment): New insn-and-split. * config/avr/avr.c (avr_init_builtins): Add local variables: const_memx_void_node, const_memx_ptr_type_node, char_ftype_const_memx_ptr.
Index: doc/extend.texi =================================================================== --- doc/extend.texi (revision 184739) +++ doc/extend.texi (working copy) @@ -8809,7 +8809,18 @@ might increase delay time. @code{ticks} integer constant; delays with a variable number of cycles are not supported. @smallexample - unsigned char __builtin_avr_insert_bits (unsigned long map, unsigned char bits, unsigned char val) +char __builtin_avr_flash_segment (const __memx void*) +@end smallexample + +@noindent +This built-in takes a byte address to the 24-bit +@ref{AVR Named Address Spaces,address space} @code{__memx} and returns +the number of the flash segment (the 64 KiB chunk) where the address +points to. Counting starts at @code{0}. +If the address does not point to flash memory, return @code{-1}. + +@smallexample +unsigned char __builtin_avr_insert_bits (unsigned long map, unsigned char bits, unsigned char val) @end smallexample @noindent Index: config/avr/builtins.def =================================================================== --- config/avr/builtins.def (revision 184659) +++ config/avr/builtins.def (working copy) @@ -48,3 +48,4 @@ DEF_BUILTIN ("__builtin_avr_fmulsu", 2, /* More complex stuff that cannot be mapped 1:1 to an instruction. */ DEF_BUILTIN ("__builtin_avr_delay_cycles", -1, AVR_BUILTIN_DELAY_CYCLES, void_ftype_ulong, -1) DEF_BUILTIN ("__builtin_avr_insert_bits", 3, AVR_BUILTIN_INSERT_BITS, uchar_ftype_ulong_uchar_uchar, CODE_FOR_insert_bits) +DEF_BUILTIN ("__builtin_avr_flash_segment", 1, AVR_BUILTIN_FLASH_SEGMENT, char_ftype_const_memx_ptr, CODE_FOR_flash_segment) Index: config/avr/avr.md =================================================================== --- config/avr/avr.md (revision 184659) +++ config/avr/avr.md (working copy) @@ -5393,6 +5393,53 @@ (define_insn "insert_bits" (set_attr "cc" "clobber")]) +;; __builtin_avr_flash_segment + +;; Just a helper for the next "official" expander. + +(define_expand "flash_segment1" + [(set (match_operand:QI 0 "register_operand" "") + (subreg:QI (match_operand:PSI 1 "register_operand" "") + 2)) + (set (cc0) + (compare (match_dup 0) + (const_int 0))) + (set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (match_dup 0) + (const_int -1))]) + +(define_expand "flash_segment" + [(parallel [(match_operand:QI 0 "register_operand" "") + (match_operand:PSI 1 "register_operand" "")])] + "" + { + rtx label = gen_label_rtx (); + emit (gen_flash_segment1 (operands[0], operands[1], label)); + emit_label (label); + DONE; + }) + +;; Actually, it's too late now to work out address spaces known at compiletime. +;; Best place would be to fold ADDR_SPACE_CONVERT_EXPR in avr_fold_builtin. +;; However, avr_addr_space_convert can add some built-in knowledge for PSTR +;; so that ADDR_SPACE_CONVERT_EXPR in the built-in must not be resolved. + +(define_insn_and_split "*split.flash_segment" + [(set (match_operand:QI 0 "register_operand" "=d") + (subreg:QI (lo_sum:PSI (match_operand:QI 1 "nonmemory_operand" "ri") + (match_operand:HI 2 "register_operand" "r")) + 2))] + "" + { gcc_unreachable(); } + "" + [(set (match_dup 0) + (match_dup 1))]) + + ;; Parity ;; Postpone expansion of 16-bit parity to libgcc call until after combine for Index: config/avr/avr.c =================================================================== --- config/avr/avr.c (revision 184661) +++ config/avr/avr.c (working copy) @@ -10432,6 +10432,19 @@ avr_init_builtins (void) unsigned_char_type_node, NULL_TREE); + tree const_memx_void_node + = build_qualified_type (void_type_node, + TYPE_QUAL_CONST + | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX)); + + tree const_memx_ptr_type_node + = build_pointer_type_for_mode (const_memx_void_node, PSImode, false); + + tree char_ftype_const_memx_ptr + = build_function_type_list (char_type_node, + const_memx_ptr_type_node, + NULL); + #define DEF_BUILTIN(NAME, N_ARGS, ID, TYPE, CODE) \ add_builtin_function (NAME, TYPE, ID, BUILT_IN_MD, NULL, NULL_TREE); #include "builtins.def"