public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch,avr,ping] PR112944: Support .rodata in RAM for AVR64* and AVR128* devices
@ 2023-12-19 12:25 Georg-Johann Lay
  0 siblings, 0 replies; only message in thread
From: Georg-Johann Lay @ 2023-12-19 12:25 UTC (permalink / raw)
  To: gcc-patches, Jeff Law, Denis Chertykov

Ping #1

https://gcc.gnu.org/pipermail/gcc-patches/2023-December/640140.html

FYI, Binutils https://sourceware.org/PR31124 us upstream.

Johann


> This is a patch that locates .rodata in flash for some AVR
> devices that can support it.  All new functionality depends
> on Binutils PR31124 and is switched on by configure checks
> for the new emulations.
> 
> https://sourceware.org/PR31124
> 
> For explanation of the gcc part see commit message below.
> 
> Most of the patch is adjusting device-specs generation.
> 
> Ok for master?
> 
> 
> Johann
> 
> -- 
> 
> avr: Support .rodata in Flash for AVR64* and AVR128* Devices.
> 
> These devices see a 32 KiB block of their program memory (flash) in
> the RAM address space.  This can be used to support .rodata in flash
> provided Binutils support PR31124 (Add new emulations which locate
> .rodata in flash).  This patch does the following:
> 
> * configure checks availability of Binutils PR31124.
> 
> * Add new command line options -mrodata-in-ram and -flmap.
> While -flmap is for internal usage (communicate hardware properties
> to the compiler proper), -mrodata-in-ram is a user space option that
> allows to return to the current rodata-in-ram layout.
> 
> * Adjust gen-avr-mmcu-specs.cc so that specs are generated that sanity
> check options, and that translate -m[no-]rodata-in-ram to its emulation.
> 
> * Objects in .rodata don't drag __do_copy_data.
> 
> * Document new options and built-in macros.
> 
>     PR target/112944
> 
> gcc/
>     * configure.ac [target=avr]: Check availability of emulations
>     avrxmega2_flmap and avrxmega4_flmap, resulting in new config vars
>     HAVE_LD_AVR_AVRXMEGA2_FLMAP and HAVE_LD_AVR_AVRXMEGA4_FLMAP.
>     * configure: Regenerate.
>     * config.in: Regenerate.
>     * doc/invoke.texi (AVR Options): Document -mflmap, -mrodata-in-ram,
>     __AVR_HAVE_FLMAP__, __AVR_RODATA_IN_RAM__.
>     * doc/avr-mmcu.texi: Regenerate.
> 
>     * gcc/config/avr/avr.opt (-mflmap, -mrodata-in-ram): New options.
>     * config/avr/avr-arch.h (enum avr_device_specific_features):
>     Add AVR_ISA_FLMAP.
>     * config/avr/avr-mcus.def (AVR_MCU) [avr64*, avr128*]: Set isa flag
>     AVR_ISA_FLMAP.
>     * gcc/config/avr/avr.cc (avr_arch_index, avr_has_rodata_p): New vars.
>     (avr_set_core_architecture): Set avr_arch_index.
>     (have_avrxmega2_flmap, have_avrxmega4_flmap)
>     (have_avrxmega3_rodata_in_flash): Set new static const bool according
>     to configure results.
>     (avr_rodata_in_flash_p): New function.
>     (avr_asm_init_sections): Let readonly_data_section->unnamed.callback
>     track avr_need_copy_data_p only if not avr_rodata_in_flash_p().
>     (avr_asm_named_section): Track avr_has_rodata_p.
>     (avr_file_end): Emit __do_copy_data also when avr_has_rodata_p
>     and not avr_rodata_in_flash_p ().
>     * config/avr/specs.h (CC1_SPEC): Add %(cc1_rodata_in_ram).
>     (LINK_SPEC): Add %(link_rodata_in_ram).
>     (LINK_ARCH_SPEC): Remove.
>     * gcc/config/avr/gen-avr-mmcu-specs.cc (have_avrxmega3_rodata_in_flash)
>     (have_avrxmega2_flmap, have_avrxmega4_flmap): Set new static
>     const bool according to configure results.
>     (diagnose_mrodata_in_ram): New function.
>     (print_mcu): Generate specs with the following changes:
>     <*cc1_misc, *asm_misc, *link_misc>: New specs so that we don't
>     need to extend avr/specs.h each time we add a new bell or whistle.
>     <*cc1_rodata_in_ram, *link_rodata_in_ram>: New specs to diagnose
>     -m[no-]rodata-in-ram.
>     <*cpp_rodata_in_ram>: New. Does -D__AVR_RODATA_IN_RAM__=0/1.
>     <*cpp_mcu>: Add -D__AVR_AVR_FLMAP__ if it applies.
>     <*cpp>: Add %(cpp_rodata_in_ram).
>     <*link_arch>: Use emulation avrxmega2_flmap, avrxmega4_flmap as needed.
>     <*self_spec>: Add -mflmap or %<mflmap as needed.
>     * gcc/config/avr/gen-avr-mmcu-texi.cc (main): Add @anchor to core
>     architectures for external referencing.
> 
> gcc/testsuite/
>     * gcc.target/avr/torture/pr112944.c: New test.
> 
> pr112944-flmap.diff
> 
> diff --git a/gcc/config.in b/gcc/config.in
> index fa40825d6d0..18e0538af30 100644
> --- a/gcc/config.in
> +++ b/gcc/config.in
> @@ -1673,6 +1673,12 @@
>  #endif
>  
>  
> +/* Define if your linker supports emulation avrxmega2_flmap. */
> +#ifndef USED_FOR_TARGET
> +#undef HAVE_LD_AVR_AVRXMEGA2_FLMAP
> +#endif
> +
> +
>  /* Define if your default avr linker script for avrxmega3 leaves .rodata in
>     flash. */
>  #ifndef USED_FOR_TARGET
> @@ -1680,6 +1686,12 @@
>  #endif
>  
>  
> +/* Define if your linker supports emulation avrxmega4_flmap. */
> +#ifndef USED_FOR_TARGET
> +#undef HAVE_LD_AVR_AVRXMEGA4_FLMAP
> +#endif
> +
> +
>  /* Define if your linker supports -z bndplt */
>  #ifndef USED_FOR_TARGET
>  #undef HAVE_LD_BNDPLT_SUPPORT
> diff --git a/gcc/config/avr/avr-arch.h b/gcc/config/avr/avr-arch.h
> index 79445fe7987..9ef187a1fd1 100644
> --- a/gcc/config/avr/avr-arch.h
> +++ b/gcc/config/avr/avr-arch.h
> @@ -166,7 +166,35 @@ AVR_ISA_RCALL
>    assume these instructions are not available and we set the built-in
>    macro __AVR_HAVE_JMP_CALL__ accordingly.  This macro is used to
>    determine a rough estimate of flash size in libgcc, and AVR-LibC uses
> -  this macro to determine vector sizes.  */
> +  this macro to determine vector sizes.
> +
> +AVR_ISA_FLMAP
> +  The device has the NVMCTRL_CTRLB.FLMAP bitfield.  The value of FLMAP
> +  determines which 32 KiB segment of the program memory (flash) is visible
> +  in the RAM address space at 0x8000.
> +
> +  If Binutils support emulations avrxmega2_flmap resp. avrxmega4_flmap
> +  (PR31124), then  the location of the .rodata section can be determined
> +  by means of option -m[no-]rodata-in-ram.  If .rodata is located in flash,
> +  the user can chose which 32 KiB flash block is visible in RAM space by
> +  means of defining symbol __flmap.
> +
> +  The startup code from AVR-LibC initializes FLMAP according to __flmap
> +  provided one of the avrxmega*_flmap emulations is used. If avrxmega2/4
> +  is used, then the startup code does not initialize FLMAP.
> +
> +  __AVR_HAVE_FLMAP__ is a macro defined in device-specs and supposed to be
> +  consumed by code that sets FLMAP, like the startup code for example.
> +  The macro is defined when all of the following conditions are met:
> +    * The device is AVR_ISA_FLMAP.
> +    * It's not known at compile time / assembler time whether or not .rodata
> +      will be located in flash or in RAM. This implies Binutils PR31124.
> +    * The definition of the macro is independent of -m[no-]rodata-in-ram.
> +
> +  AVR_ISA_FLMAP does not affect multilib layout or selection in any way.
> +
> +  For details on which symbols are defined in which way depending on the
> +  emulation, see <Binutils>/ld/scripttempl/avr.sc.  */
>  
>  enum avr_device_specific_features
>  {
> @@ -175,9 +203,12 @@ enum avr_device_specific_features
>    AVR_SHORT_SP    = 0x2, /* Stack Pointer has 8 bits width. */
>    AVR_ERRATA_SKIP = 0x4, /* device has a core erratum. */
>    AVR_ISA_LDS     = 0x8, /* whether LDS / STS is valid for all data in static
> -                            storage.  Only useful for reduced Tiny.  */
> -  AVR_ISA_RCALL   = 0x10 /* Use RJMP / RCALL even though JMP / CALL
> -                            are available (-mshort-calls).  */
> +			    storage.  Only useful for reduced Tiny.	 */
> +  AVR_ISA_RCALL	  = 0x10, /* Use RJMP / RCALL even though JMP / CALL
> +			     are available (-mshort-calls).	 */
> +  AVR_ISA_FLMAP	  = 0x20  /* Has NVMCTRL_CTRLB.FLMAP to select which 32 KiB
> +			     block of program memory is visible in the RAM
> +			     address space.	 */
>  };
>  
>  /* Map architecture to its texinfo string.  */
> diff --git a/gcc/config/avr/avr-mcus.def b/gcc/config/avr/avr-mcus.def
> index 4c4269cd429..a8e2ff29f30 100644
> --- a/gcc/config/avr/avr-mcus.def
> +++ b/gcc/config/avr/avr-mcus.def
> @@ -306,21 +306,21 @@ AVR_MCU ("atxmega16c4",      ARCH_AVRXMEGA2, AVR_ISA_RMW,  "__AVR_ATxmega16C4__"
>  AVR_MCU ("atxmega32a4u",     ARCH_AVRXMEGA2, AVR_ISA_RMW,  "__AVR_ATxmega32A4U__", 0x2000, 0x0, 0x9000, 0)
>  AVR_MCU ("atxmega32c4",      ARCH_AVRXMEGA2, AVR_ISA_RMW,  "__AVR_ATxmega32C4__",  0x2000, 0x0, 0x9000, 0)
>  AVR_MCU ("atxmega32e5",      ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_ATxmega32E5__",  0x2000, 0x0, 0x9000, 0)
> -AVR_MCU ("avr64da28",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64DA28__",    0x6000, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64da32",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64DA32__",    0x6000, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64da48",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64DA48__",    0x6000, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64da64",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64DA64__",    0x6000, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64db28",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64DB28__",    0x6000, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64db32",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64DB32__",    0x6000, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64db48",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64DB48__",    0x6000, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64db64",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64DB64__",    0x6000, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64dd14",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64DD14__",    0x6000, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64dd20",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64DD20__",    0x6000, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64dd28",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64DD28__",    0x6000, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64dd32",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64DD32__",    0x6000, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64ea28",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64EA28__",    0x6800, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64ea32",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64EA32__",    0x6800, 0x0, 0x10000, 0)
> -AVR_MCU ("avr64ea48",        ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_AVR64EA48__",    0x6800, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64da28",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64DA28__",   0x6000, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64da32",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64DA32__",   0x6000, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64da48",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64DA48__",   0x6000, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64da64",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64DA64__",   0x6000, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64db28",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64DB28__",   0x6000, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64db32",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64DB32__",   0x6000, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64db48",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64DB48__",   0x6000, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64db64",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64DB64__",   0x6000, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64dd14",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64DD14__",   0x6000, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64dd20",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64DD20__",   0x6000, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64dd28",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64DD28__",   0x6000, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64dd32",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64DD32__",   0x6000, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64ea28",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64EA28__",   0x6800, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64ea32",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64EA32__",   0x6800, 0x0, 0x10000, 0)
> +AVR_MCU ("avr64ea48",        ARCH_AVRXMEGA2, AVR_ISA_FLMAP, "__AVR_AVR64EA48__",   0x6800, 0x0, 0x10000, 0)
>  /* Xmega, Flash + RAM < 64K, flash visible in RAM address space */
>  AVR_MCU ("avrxmega3",        ARCH_AVRXMEGA3, AVR_ISA_NONE,  NULL,                  0x3f00, 0x0, 0x8000, 0)
>  AVR_MCU ("attiny202",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny202__",   0x3f80, 0x0, 0x800,  0x8000)
> @@ -393,14 +393,14 @@ AVR_MCU ("atxmega64b1",      ARCH_AVRXMEGA4, AVR_ISA_RMW,  "__AVR_ATxmega64B1__"
>  AVR_MCU ("atxmega64b3",      ARCH_AVRXMEGA4, AVR_ISA_RMW,  "__AVR_ATxmega64B3__",  0x2000, 0x0, 0x11000, 0)
>  AVR_MCU ("atxmega64c3",      ARCH_AVRXMEGA4, AVR_ISA_RMW,  "__AVR_ATxmega64C3__",  0x2000, 0x0, 0x11000, 0)
>  AVR_MCU ("atxmega64d4",      ARCH_AVRXMEGA4, AVR_ISA_NONE, "__AVR_ATxmega64D4__",  0x2000, 0x0, 0x11000, 0)
> -AVR_MCU ("avr128da28",       ARCH_AVRXMEGA4, AVR_ISA_NONE, "__AVR_AVR128DA28__",   0x4000, 0x0, 0x20000, 0)
> -AVR_MCU ("avr128da32",       ARCH_AVRXMEGA4, AVR_ISA_NONE, "__AVR_AVR128DA32__",   0x4000, 0x0, 0x20000, 0)
> -AVR_MCU ("avr128da48",       ARCH_AVRXMEGA4, AVR_ISA_NONE, "__AVR_AVR128DA48__",   0x4000, 0x0, 0x20000, 0)
> -AVR_MCU ("avr128da64",       ARCH_AVRXMEGA4, AVR_ISA_NONE, "__AVR_AVR128DA64__",   0x4000, 0x0, 0x20000, 0)
> -AVR_MCU ("avr128db28",       ARCH_AVRXMEGA4, AVR_ISA_NONE, "__AVR_AVR128DB28__",   0x4000, 0x0, 0x20000, 0)
> -AVR_MCU ("avr128db32",       ARCH_AVRXMEGA4, AVR_ISA_NONE, "__AVR_AVR128DB32__",   0x4000, 0x0, 0x20000, 0)
> -AVR_MCU ("avr128db48",       ARCH_AVRXMEGA4, AVR_ISA_NONE, "__AVR_AVR128DB48__",   0x4000, 0x0, 0x20000, 0)
> -AVR_MCU ("avr128db64",       ARCH_AVRXMEGA4, AVR_ISA_NONE, "__AVR_AVR128DB64__",   0x4000, 0x0, 0x20000, 0)
> +AVR_MCU ("avr128da28",       ARCH_AVRXMEGA4, AVR_ISA_FLMAP, "__AVR_AVR128DA28__",  0x4000, 0x0, 0x20000, 0)
> +AVR_MCU ("avr128da32",       ARCH_AVRXMEGA4, AVR_ISA_FLMAP, "__AVR_AVR128DA32__",  0x4000, 0x0, 0x20000, 0)
> +AVR_MCU ("avr128da48",       ARCH_AVRXMEGA4, AVR_ISA_FLMAP, "__AVR_AVR128DA48__",  0x4000, 0x0, 0x20000, 0)
> +AVR_MCU ("avr128da64",       ARCH_AVRXMEGA4, AVR_ISA_FLMAP, "__AVR_AVR128DA64__",  0x4000, 0x0, 0x20000, 0)
> +AVR_MCU ("avr128db28",       ARCH_AVRXMEGA4, AVR_ISA_FLMAP, "__AVR_AVR128DB28__",  0x4000, 0x0, 0x20000, 0)
> +AVR_MCU ("avr128db32",       ARCH_AVRXMEGA4, AVR_ISA_FLMAP, "__AVR_AVR128DB32__",  0x4000, 0x0, 0x20000, 0)
> +AVR_MCU ("avr128db48",       ARCH_AVRXMEGA4, AVR_ISA_FLMAP, "__AVR_AVR128DB48__",  0x4000, 0x0, 0x20000, 0)
> +AVR_MCU ("avr128db64",       ARCH_AVRXMEGA4, AVR_ISA_FLMAP, "__AVR_AVR128DB64__",  0x4000, 0x0, 0x20000, 0)
>  /* Xmega, 64K < Flash <= 128K, RAM > 64K */
>  AVR_MCU ("avrxmega5",        ARCH_AVRXMEGA5, AVR_ISA_NONE, NULL,                   0x2000, 0x0, 0x11000, 0)
>  AVR_MCU ("atxmega64a1",      ARCH_AVRXMEGA5, AVR_ISA_NONE, "__AVR_ATxmega64A1__",  0x2000, 0x0, 0x11000, 0)
> diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
> index c5e9ccf9663..224cb6c665f 100644
> --- a/gcc/config/avr/avr.cc
> +++ b/gcc/config/avr/avr.cc
> @@ -220,6 +220,7 @@ static GTY(()) rtx xstring_e;
>  
>  /* Current architecture.  */
>  const avr_arch_t *avr_arch;
> +enum avr_arch_id avr_arch_index;
>  
>  /* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
>     or to address space __flash* or __memx.  Only used as singletons inside
> @@ -229,9 +230,10 @@ static GTY(()) section *progmem_section[ADDR_SPACE_COUNT];
>  /* Condition for insns/expanders from avr-dimode.md.  */
>  bool avr_have_dimode = true;
>  
> -/* To track if code will use .bss and/or .data.  */
> +/* To track if code will use .bss, .data, .rodata.  */
>  bool avr_need_clear_bss_p = false;
>  bool avr_need_copy_data_p = false;
> +bool avr_has_rodata_p = false;
>  
>  
>  /* Transform UP into lowercase and write the result to LO.
> @@ -1059,6 +1061,7 @@ avr_set_core_architecture (void)
>  	       && mcu->macro == NULL)
>          {
>            avr_arch = &avr_arch_types[mcu->arch_id];
> +	  avr_arch_index = mcu->arch_id;
>            if (avr_n_flash < 0)
>              avr_n_flash = 1 + (mcu->flash_size - 1) / 0x10000;
>  
> @@ -10740,6 +10743,49 @@ avr_insert_attributes (tree node, tree *attributes)
>      }
>  }
>  
> +#ifdef HAVE_LD_AVR_AVRXMEGA2_FLMAP
> +static const bool have_avrxmega2_flmap = true;
> +#else
> +static const bool have_avrxmega2_flmap = false;
> +#endif
> +
> +#ifdef HAVE_LD_AVR_AVRXMEGA4_FLMAP
> +static const bool have_avrxmega4_flmap = true;
> +#else
> +static const bool have_avrxmega4_flmap = false;
> +#endif
> +
> +#ifdef HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
> +static const bool have_avrxmega3_rodata_in_flash = true;
> +#else
> +static const bool have_avrxmega3_rodata_in_flash = false;
> +#endif
> +
> +
> +static bool
> +avr_rodata_in_flash_p ()
> +{
> +  switch (avr_arch_index)
> +    {
> +    default:
> +      break;
> +
> +    case ARCH_AVRTINY:
> +      return true;
> +
> +    case ARCH_AVRXMEGA3:
> +      return have_avrxmega3_rodata_in_flash;
> +
> +    case ARCH_AVRXMEGA2:
> +      return avr_flmap && have_avrxmega2_flmap && avr_rodata_in_ram != 1;
> +
> +    case ARCH_AVRXMEGA4:
> +      return avr_flmap && have_avrxmega4_flmap && avr_rodata_in_ram != 1;
> +    }
> +
> +  return false;
> +}
> +
>  
>  /* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'.  */
>  /* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'.  */
> @@ -10853,13 +10899,11 @@ avr_output_progmem_section_asm_op (const char *data)
>  static void
>  avr_asm_init_sections (void)
>  {
> -  /* Override section callbacks to keep track of `avr_need_clear_bss_p'
> -     resp. `avr_need_copy_data_p'.  If flash is not mapped to RAM then
> -     we have also to track .rodata because it is located in RAM then.  */
> +  /* Override section callbacks to keep track of `avr_need_clear_bss_p',
> +     `avr_need_copy_data_p' and `avr_has_rodata_p'.
> +     Track also .rodata for the case when .rodata is located in RAM.  */
>  
> -#if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
> -  if (avr_arch->flash_pm_offset == 0)
> -#endif
> +  if (! avr_rodata_in_flash_p ())
>      readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
>    data_section->unnamed.callback = avr_output_data_section_asm_op;
>    bss_section->unnamed.callback = avr_output_bss_section_asm_op;
> @@ -10899,13 +10943,9 @@ avr_asm_named_section (const char *name, unsigned int flags, tree decl)
>      avr_need_copy_data_p = (startswith (name, ".data")
>  			    || startswith (name, ".gnu.linkonce.d"));
>  
> -  if (!avr_need_copy_data_p
> -#if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
> -      && avr_arch->flash_pm_offset == 0
> -#endif
> -      )
> -    avr_need_copy_data_p = (startswith (name, ".rodata")
> -			    || startswith (name, ".gnu.linkonce.r"));
> +  if (!avr_has_rodata_p)
> +    avr_has_rodata_p = (startswith (name, ".rodata")
> +			 || startswith (name, ".gnu.linkonce.r"));
>  
>    if (!avr_need_clear_bss_p)
>      avr_need_clear_bss_p = startswith (name, ".bss");
> @@ -11203,7 +11243,8 @@ avr_file_end (void)
>       linking in the initialization code from libgcc if resp.
>       sections are empty, see PR18145.  */
>  
> -  if (avr_need_copy_data_p)
> +  if (avr_need_copy_data_p
> +      || (avr_has_rodata_p && ! avr_rodata_in_flash_p ()))
>      fputs (".global __do_copy_data\n", asm_out_file);
>  
>    if (avr_need_clear_bss_p)
> diff --git a/gcc/config/avr/avr.opt b/gcc/config/avr/avr.opt
> index 5a0b46539aa..26c63bc10aa 100644
> --- a/gcc/config/avr/avr.opt
> +++ b/gcc/config/avr/avr.opt
> @@ -94,6 +94,14 @@ mstrict-X
>  Target Var(avr_strict_X) Init(0)
>  When accessing RAM, use X as imposed by the hardware, i.e. just use pre-decrement, post-increment and indirect addressing with the X register.  Without this option, the compiler may assume that there is an addressing mode X+const similar to Y+const and Z+const and emit instructions to emulate such an addressing mode for X.
>  
> +mflmap
> +Target Var(avr_flmap) Init(0)
> +The device has the bitfield NVMCTRL_CTRLB.FLMAP.  This option is used internally.
> +
> +mrodata-in-ram
> +Target Var(avr_rodata_in_ram) Init(-1)
> +The device has the .rodata section located in the RAM area.
> +
>  ;; For rationale behind -msp8 see explanation in avr.h.
>  msp8
>  Target RejectNegative Var(avr_sp8) Init(0)
> diff --git a/gcc/config/avr/gen-avr-mmcu-specs.cc b/gcc/config/avr/gen-avr-mmcu-specs.cc
> index b9a5ad44e4e..9754d75c7e3 100644
> --- a/gcc/config/avr/gen-avr-mmcu-specs.cc
> +++ b/gcc/config/avr/gen-avr-mmcu-specs.cc
> @@ -103,6 +103,61 @@ static const char help_dev_lib_name[] =
>    "\n";
>  #endif // WITH_AVRLIBC
>  
> +
> +#ifdef HAVE_LD_AVR_AVRXMEGA2_FLMAP
> +static const bool have_avrxmega2_flmap = true;
> +#else
> +static const bool have_avrxmega2_flmap = false;
> +#endif
> +
> +#ifdef HAVE_LD_AVR_AVRXMEGA4_FLMAP
> +static const bool have_avrxmega4_flmap = true;
> +#else
> +static const bool have_avrxmega4_flmap = false;
> +#endif
> +
> +#ifdef HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
> +static const bool have_avrxmega3_rodata_in_flash = true;
> +#else
> +static const bool have_avrxmega3_rodata_in_flash = false;
> +#endif
> +
> +
> +static void
> +diagnose_mrodata_in_ram (FILE *f, const char *spec, const avr_mcu_t *mcu)
> +{
> +  enum avr_arch_id arch_id = mcu->arch_id;
> +  const avr_arch_t *arch = &avr_arch_types[arch_id];
> +  const bool is_arch = mcu->macro == NULL;
> +  const bool flmap = (mcu->dev_attribute & AVR_ISA_FLMAP);
> +  const bool have_flmap2 = have_avrxmega2_flmap && arch_id == ARCH_AVRXMEGA2;
> +  const bool have_flmap4 = have_avrxmega4_flmap && arch_id == ARCH_AVRXMEGA4;
> +  const bool have_flmap = flmap && (have_flmap2 || have_flmap4);
> +
> +  const bool rodata_in_flash = (arch_id == ARCH_AVRTINY
> +				|| (arch_id == ARCH_AVRXMEGA3
> +				    && have_avrxmega3_rodata_in_flash));
> +
> +  fprintf (f, "%s:\n", spec);
> +  if (rodata_in_flash && is_arch)
> +    fprintf (f, "\t%%{mrodata-in-ram: %%e-mrodata-in-ram not supported"
> +	     " for %s}", mcu->name);
> +  else if (rodata_in_flash)
> +    fprintf (f, "\t%%{mrodata-in-ram: %%e-mrodata-in-ram not supported"
> +	     " for %s (arch=%s)}", mcu->name, arch->name);
> +  else if (is_arch)
> +    {
> +      if (! have_flmap2 && ! have_flmap4)
> +	fprintf (f, "\t%%{mno-rodata-in-ram: %%e-mno-rodata-in-ram not"
> +		 " supported for %s}", mcu->name);
> +    }
> +  else if (! have_flmap)
> +    fprintf (f, "\t%%{mno-rodata-in-ram: %%e-mno-rodata-in-ram not supported"
> +	     " for %s (arch=%s)}", mcu->name, arch->name);
> +  fprintf (f, "\n\n");
> +}
> +
> +
>  static void
>  print_mcu (const avr_mcu_t *mcu)
>  {
> @@ -130,6 +185,7 @@ print_mcu (const avr_mcu_t *mcu)
>    bool rmw = (mcu->dev_attribute & AVR_ISA_RMW) != 0;
>    bool sp8 = (mcu->dev_attribute & AVR_SHORT_SP) != 0;
>    bool rcall = (mcu->dev_attribute & AVR_ISA_RCALL);
> +  bool flmap = (mcu->dev_attribute & AVR_ISA_FLMAP);
>    bool is_arch = mcu->macro == NULL;
>    bool is_device = ! is_arch;
>    int flash_pm_offset = 0;
> @@ -166,13 +222,24 @@ print_mcu (const avr_mcu_t *mcu)
>        rcall_spec = rcall ? "-mshort-calls" : "%<mshort-calls";
>      }
>  
> +  const char *flmap_spec = flmap ? "-mflmap" : "%<mflmap";
> +  const char *link_arch_spec = "%{mmcu=*:-m%*}";
> +  const char *link_arch_flmap_spec = "%{mmcu=*:-m%*%{!mrodata-in-ram:_flmap}}";
> +  const bool have_flmap2 = have_avrxmega2_flmap && arch_id == ARCH_AVRXMEGA2;
> +  const bool have_flmap4 = have_avrxmega4_flmap && arch_id == ARCH_AVRXMEGA4;
> +  const bool have_flmap = flmap && (have_flmap2 || have_flmap4);
> +
> +  if (have_flmap)
> +    link_arch_spec = link_arch_flmap_spec;
> +
>    fprintf (f, "#\n"
>             "# Auto-generated specs for AVR ");
>    if (is_arch)
>      fprintf (f, "core architecture %s\n", arch->name);
>    else
> -    fprintf (f, "device %s (core %s, %d-bit SP%s)\n", mcu->name,
> -             arch->name, sp8 ? 8 : 16, rcall ? ", short-calls" : "");
> +    fprintf (f, "device %s (core %s, %d-bit SP%s%s)\n", mcu->name,
> +	     arch->name, sp8 ? 8 : 16, rcall ? ", short-calls" : "",
> +	     have_flmap ? ", FLMAP" : "");
>    fprintf (f, "%s\n", header);
>  
>    if (is_device)
> @@ -212,6 +279,11 @@ print_mcu (const avr_mcu_t *mcu)
>             ? "\t%{!mno-absdata: -mabsdata}"
>             : "\t%{mabsdata}");
>  
> +  // -m[no-]rodata-in-ram basically affects linking, but sanity-check early.
> +  diagnose_mrodata_in_ram (f, "*cc1_rodata_in_ram", mcu);
> +
> +  fprintf (f, "*cc1_misc:\n\t%%(cc1_rodata_in_ram)\n\n");
> +
>    // avr-gcc specific specs for assembling / the assembler.
>  
>    fprintf (f, "*asm_arch:\n\t-mmcu=%s\n\n", arch->name);
> @@ -235,6 +307,8 @@ print_mcu (const avr_mcu_t *mcu)
>             ? "\t%{mno-skip-bug}"
>             : "\t%{!mskip-bug: -mno-skip-bug}");
>  
> +  fprintf (f, "*asm_misc:\n" /* empty */ "\n\n");
> +
>    // avr-specific specs for linking / the linker.
>  
>    int wrap_k =
> @@ -253,7 +327,10 @@ print_mcu (const avr_mcu_t *mcu)
>  
>    fprintf (f, "*link_relax:\n\t%s\n\n", LINK_RELAX_SPEC);
>  
> -  fprintf (f, "*link_arch:\n\t%s", LINK_ARCH_SPEC);
> +  // -m[no-]rodata-in-ram affects linking.  Sanity check its usage.
> +  diagnose_mrodata_in_ram (f, "*link_rodata_in_ram", mcu);
> +
> +  fprintf (f, "*link_arch:\n\t%s", link_arch_spec);
>    if (is_device
>        && flash_pm_offset)
>      fprintf (f, " --defsym=__RODATA_PM_OFFSET__=0x%x", flash_pm_offset);
> @@ -274,12 +351,15 @@ print_mcu (const avr_mcu_t *mcu)
>        fprintf (f, "\n\n");
>      }
>  
> +  fprintf (f, "*link_misc:\n\t%%(link_rodata_in_ram)\n\n");
> +
>    // Specs known to GCC.
>  
>    if (is_device)
>      {
>        fprintf (f, "*self_spec:\n");
>        fprintf (f, "\t%%<mmcu=* -mmcu=%s ", arch->name);
> +      fprintf (f, "%s ", flmap_spec);
>        fprintf (f, "%s ", rcall_spec);
>        fprintf (f, "%s\n\n", sp8_spec);
>  
> @@ -298,10 +378,26 @@ print_mcu (const avr_mcu_t *mcu)
>  	  fprintf (f, " -U__AVR_PM_BASE_ADDRESS__");
>  	  fprintf (f, " -D__AVR_PM_BASE_ADDRESS__=0x%x", flash_pm_offset);
>  	}
> +      if (have_flmap)
> +	fprintf (f, " -D__AVR_HAVE_FLMAP__");
> +
> +      fprintf (f, "\n\n"); // *cpp_mcu
> +
> +      const bool rodata_in_flash = (arch_id == ARCH_AVRTINY
> +				    || (arch_id == ARCH_AVRXMEGA3
> +					&& have_avrxmega3_rodata_in_flash));
> +      fprintf (f, "*cpp_rodata_in_ram:\n\t-D__AVR_RODATA_IN_RAM__=");
> +      if (rodata_in_flash)
> +	fprintf (f, "0");
> +      else if (! have_flmap)
> +	fprintf (f, "1");
> +      else
> +	fprintf (f, "%%{!mrodata-in-ram:%%{!mno-rodata-in-ram:0}}"
> +		 "%%{mrodata-in-ram:1}" "%%{mno-rodata-in-ram:0}");
>        fprintf (f, "\n\n");
>  
>        fprintf (f, "*cpp:\n");
> -      fprintf (f, "\t%%(cpp_mcu)");
> +      fprintf (f, "\t%%(cpp_mcu) %%(cpp_rodata_in_ram)");
>  #if defined (WITH_AVRLIBC)
>        fprintf (f, " %%(cpp_avrlibc)");
>  #endif // WITH_AVRLIBC
> diff --git a/gcc/config/avr/gen-avr-mmcu-texi.cc b/gcc/config/avr/gen-avr-mmcu-texi.cc
> index f6eca3adcaa..5cfa4c2e397 100644
> --- a/gcc/config/avr/gen-avr-mmcu-texi.cc
> +++ b/gcc/config/avr/gen-avr-mmcu-texi.cc
> @@ -189,7 +189,8 @@ int main (void)
>  
>  	  for (i = 0; i < ARRAY_SIZE (avr_texinfo); i++)
>  	    if (arch_id == avr_texinfo[i].arch_id)
> -	      printf ("@item %s\n%s\n", mcu->name, avr_texinfo[i].texinfo);
> +	      printf ("@item @anchor{%s}%s\n%s\n", mcu->name, mcu->name,
> +		      avr_texinfo[i].texinfo);
>  	}
>        else if (arch_id == (enum avr_arch_id) mcu->arch_id)
>  	{
> diff --git a/gcc/config/avr/specs.h b/gcc/config/avr/specs.h
> index b4a5ee6e5fc..29231bfc166 100644
> --- a/gcc/config/avr/specs.h
> +++ b/gcc/config/avr/specs.h
> @@ -35,7 +35,8 @@ along with GCC; see the file COPYING3.  If not see
>    "%(cc1_n_flash) "                             \
>    "%(cc1_errata_skip) "                         \
>    "%(cc1_rmw) "                                 \
> -  "%(cc1_absdata) "
> +  "%(cc1_absdata) "                             \
> +  "%(cc1_misc) "
>  
>  #undef  CC1PLUS_SPEC
>  #define CC1PLUS_SPEC                                    \
> @@ -53,10 +54,8 @@ along with GCC; see the file COPYING3.  If not see
>    "%(asm_relax) "                               \
>    "%(asm_rmw) "                                 \
>    "%(asm_gccisr) "                              \
> -  "%(asm_errata_skip) "
> -
> -#define LINK_ARCH_SPEC                          \
> -  "%{mmcu=*:-m%*} "
> +  "%(asm_errata_skip) "                         \
> +  "%(asm_misc) "
>  
>  #define LINK_RELAX_SPEC                         \
>    "%{mrelax:--relax} "
> @@ -68,6 +67,7 @@ along with GCC; see the file COPYING3.  If not see
>    "%(link_text_start) "                         \
>    "%(link_relax) "                              \
>    "%(link_pmem_wrap) "                          \
> +  "%(link_misc) "                               \
>    "%{shared:%eshared is not supported} "
>  
>  #undef  LIB_SPEC
> diff --git a/gcc/configure b/gcc/configure
> index de72cb1e1fe..97d89cd879b 100755
> --- a/gcc/configure
> +++ b/gcc/configure
> @@ -28455,6 +28455,7 @@ $as_echo "#define HAVE_AS_AVR_MGCCISR_OPTION 1" >>confdefs.h
>  fi
>  
>  
> +    avr_ld_ver="`$gcc_cv_ld -v | sed -e 's:^.* ::'`"
>      # Check how default linker description file implements .rodata for
>      # avrxmega3 (PR21472).  avr-gcc assumes .rodata is *not* loaded to
>      # RAM so avr-gcc skips __do_copy_data for .rodata objects.
> @@ -28499,7 +28500,6 @@ $as_echo "#define HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH 1" >>confdefs.h
>  $as_echo "no: avrxmega3 .rodata located in RAM" >&6; }
>  	    echo "$as_me: nm output was" >&5
>  	    cat conftest.nm >&5
> -	    avr_ld_ver="`$gcc_cv_ld -v | sed -e 's:^.* ::'`"
>  	    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: support for avrxmega3 .rodata in flash needs Binutils 2.29 or higher (have $avr_ld_ver)" >&5
>  $as_echo "$as_me: WARNING: support for avrxmega3 .rodata in flash needs Binutils 2.29 or higher (have $avr_ld_ver)" >&2;}
>  	fi
> @@ -28511,7 +28511,71 @@ $as_echo "test failed" >&6; }
>  	{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: see \`config.log' for details" >&5
>  $as_echo "$as_me: WARNING: see \`config.log' for details" >&2;}
>      fi
> -    rm -f conftest.s conftest.o conftest.elf conftest.nm
> +    rm -f conftest.o conftest.elf conftest.nm
> +
> +    # Check for emulation avrxmega2_flmap.
> +    { $as_echo "$as_me:${as_lineno-$LINENO}: checking binutils for avrxmega2_flmap support (PR31124)" >&5
> +$as_echo_n "checking binutils for avrxmega2_flmap support (PR31124)... " >&6; }
> +    { ac_try='$gcc_cv_as -mmcu=avrxmega2 conftest.s -o conftest.o'
> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
> +  (eval $ac_try) 2>&5
> +  ac_status=$?
> +  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> +  test $ac_status = 0; }; }
> +    { ac_try='$gcc_cv_ld -mavrxmega2_flmap conftest.o -o conftest.elf'
> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
> +  (eval $ac_try) 2>&5
> +  ac_status=$?
> +  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> +  test $ac_status = 0; }; }
> +    if test -s conftest.elf
> +    then
> +	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
> +$as_echo "yes" >&6; }
> +
> +$as_echo "#define HAVE_LD_AVR_AVRXMEGA2_FLMAP 1" >>confdefs.h
> +
> +    else
> +	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +	{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: support for avrxmega2_flmap requires Binutils 2.42 or higher (have $avr_ld_ver)" >&5
> +$as_echo "$as_me: WARNING: support for avrxmega2_flmap requires Binutils 2.42 or higher (have $avr_ld_ver)" >&2;}
> +	{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: see \`config.log' for details" >&5
> +$as_echo "$as_me: WARNING: see \`config.log' for details" >&2;}
> +    fi
> +    rm -f conftest.o conftest.elf
> +
> +    # Check for emulation avrxmega4_flmap.
> +    { $as_echo "$as_me:${as_lineno-$LINENO}: checking binutils for avrxmega4_flmap support (PR31124)" >&5
> +$as_echo_n "checking binutils for avrxmega4_flmap support (PR31124)... " >&6; }
> +    { ac_try='$gcc_cv_as -mmcu=avrxmega4 conftest.s -o conftest.o'
> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
> +  (eval $ac_try) 2>&5
> +  ac_status=$?
> +  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> +  test $ac_status = 0; }; }
> +    { ac_try='$gcc_cv_ld -mavrxmega4_flmap conftest.o -o conftest.elf'
> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
> +  (eval $ac_try) 2>&5
> +  ac_status=$?
> +  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> +  test $ac_status = 0; }; }
> +    if test -s conftest.elf
> +    then
> +	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
> +$as_echo "yes" >&6; }
> +
> +$as_echo "#define HAVE_LD_AVR_AVRXMEGA4_FLMAP 1" >>confdefs.h
> +
> +    else
> +	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +	{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: support for avrxmega4_flmap requires Binutils 2.42 or higher (have $avr_ld_ver)" >&5
> +$as_echo "$as_me: WARNING: support for avrxmega4_flmap requires Binutils 2.42 or higher (have $avr_ld_ver)" >&2;}
> +	{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: see \`config.log' for details" >&5
> +$as_echo "$as_me: WARNING: see \`config.log' for details" >&2;}
> +    fi
> +    rm -f conftest.s conftest.o conftest.elf
>      ;;
>  
>    cris-*-*)
> diff --git a/gcc/configure.ac b/gcc/configure.ac
> index 21ba631482f..747fb1a75b3 100644
> --- a/gcc/configure.ac
> +++ b/gcc/configure.ac
> @@ -4549,6 +4549,7 @@ AS_HELP_STRING([--disable-fix-cortex-a53-843419],
>        [AC_DEFINE(HAVE_AS_AVR_MGCCISR_OPTION, 1,
>  		[Define if your avr assembler supports -mgcc-isr option.])])
>  
> +    avr_ld_ver="`$gcc_cv_ld -v | sed -e 's:^.* ::'`"
>      # Check how default linker description file implements .rodata for
>      # avrxmega3 (PR21472).  avr-gcc assumes .rodata is *not* loaded to
>      # RAM so avr-gcc skips __do_copy_data for .rodata objects.
> @@ -4574,7 +4575,6 @@ EOF
>  	    AC_MSG_RESULT(no: avrxmega3 .rodata located in RAM)
>  	    echo "$as_me: nm output was" >&AS_MESSAGE_LOG_FD
>  	    cat conftest.nm >&AS_MESSAGE_LOG_FD
> -	    avr_ld_ver="`$gcc_cv_ld -v | sed -e 's:^.* ::'`"
>  	    AC_MSG_WARN([[support for avrxmega3 .rodata in flash needs Binutils 2.29 or higher (have $avr_ld_ver)]])
>  	fi
>      else
> @@ -4583,7 +4583,39 @@ EOF
>  	cat conftest.s >&AS_MESSAGE_LOG_FD
>  	AC_MSG_WARN([[see `config.log' for details]])
>      fi
> -    rm -f conftest.s conftest.o conftest.elf conftest.nm
> +    rm -f conftest.o conftest.elf conftest.nm
> +
> +    # Check for emulation avrxmega2_flmap.
> +    AC_MSG_CHECKING(binutils for avrxmega2_flmap support (PR31124))
> +    AC_TRY_COMMAND([$gcc_cv_as -mmcu=avrxmega2 conftest.s -o conftest.o])
> +    AC_TRY_COMMAND([$gcc_cv_ld -mavrxmega2_flmap conftest.o -o conftest.elf])
> +    if test -s conftest.elf
> +    then
> +	AC_MSG_RESULT(yes)
> +	AC_DEFINE(HAVE_LD_AVR_AVRXMEGA2_FLMAP, 1,
> +	    [Define if your linker supports emulation avrxmega2_flmap.])
> +    else
> +	AC_MSG_RESULT(no)
> +	AC_MSG_WARN([[support for avrxmega2_flmap requires Binutils 2.42 or higher (have $avr_ld_ver)]])
> +	AC_MSG_WARN([[see `config.log' for details]])
> +    fi
> +    rm -f conftest.o conftest.elf
> +
> +    # Check for emulation avrxmega4_flmap.
> +    AC_MSG_CHECKING(binutils for avrxmega4_flmap support (PR31124))
> +    AC_TRY_COMMAND([$gcc_cv_as -mmcu=avrxmega4 conftest.s -o conftest.o])
> +    AC_TRY_COMMAND([$gcc_cv_ld -mavrxmega4_flmap conftest.o -o conftest.elf])
> +    if test -s conftest.elf
> +    then
> +	AC_MSG_RESULT(yes)
> +	AC_DEFINE(HAVE_LD_AVR_AVRXMEGA4_FLMAP, 1,
> +	    [Define if your linker supports emulation avrxmega4_flmap.])
> +    else
> +	AC_MSG_RESULT(no)
> +	AC_MSG_WARN([[support for avrxmega4_flmap requires Binutils 2.42 or higher (have $avr_ld_ver)]])
> +	AC_MSG_WARN([[see `config.log' for details]])
> +    fi
> +    rm -f conftest.s conftest.o conftest.elf
>      ;;
>  
>    cris-*-*)
> diff --git a/gcc/doc/avr-mmcu.texi b/gcc/doc/avr-mmcu.texi
> index bec8e4322ce..f96e1a93a8b 100644
> --- a/gcc/doc/avr-mmcu.texi
> +++ b/gcc/doc/avr-mmcu.texi
> @@ -12,71 +12,71 @@
>  
>  @table @code
>  
> -@item avr2
> +@item @anchor{avr2}avr2
>  ``Classic'' devices with up to 8@tie{}KiB of program memory.
>  @*@var{mcu}@tie{}= @code{attiny22}, @code{attiny26}, @code{at90s2313}, @code{at90s2323}, @code{at90s2333}, @code{at90s2343}, @code{at90s4414}, @code{at90s4433}, @code{at90s4434}, @code{at90c8534}, @code{at90s8515}, @code{at90s8535}.
>  
> -@item avr25
> +@item @anchor{avr25}avr25
>  ``Classic'' devices with up to 8@tie{}KiB of program memory and with the @code{MOVW} instruction.
>  @*@var{mcu}@tie{}= @code{attiny13}, @code{attiny13a}, @code{attiny24}, @code{attiny24a}, @code{attiny25}, @code{attiny261}, @code{attiny261a}, @code{attiny2313}, @code{attiny2313a}, @code{attiny43u}, @code{attiny44}, @code{attiny44a}, @code{attiny45}, @code{attiny48}, @code{attiny441}, @code{attiny461}, @code{attiny461a}, @code{attiny4313}, @code{attiny84}, @code{attiny84a}, @code{attiny85}, @code{attiny87}, @code{attiny88}, @code{attiny828}, @code{attiny841}, @code{attiny861}, @code{attiny861a}, @code{ata5272}, @code{ata6616c}, @code{at86rf401}.
>  
> -@item avr3
> +@item @anchor{avr3}avr3
>  ``Classic'' devices with 16@tie{}KiB up to 64@tie{}KiB of program memory.
>  @*@var{mcu}@tie{}= @code{at76c711}, @code{at43usb355}.
>  
> -@item avr31
> +@item @anchor{avr31}avr31
>  ``Classic'' devices with 128@tie{}KiB of program memory.
>  @*@var{mcu}@tie{}= @code{atmega103}, @code{at43usb320}.
>  
> -@item avr35
> +@item @anchor{avr35}avr35
>  ``Classic'' devices with 16@tie{}KiB up to 64@tie{}KiB of program memory and with the @code{MOVW} instruction.
>  @*@var{mcu}@tie{}= @code{attiny167}, @code{attiny1634}, @code{atmega8u2}, @code{atmega16u2}, @code{atmega32u2}, @code{ata5505}, @code{ata6617c}, @code{ata664251}, @code{at90usb82}, @code{at90usb162}.
>  
> -@item avr4
> +@item @anchor{avr4}avr4
>  ``Enhanced'' devices with up to 8@tie{}KiB of program memory.
>  @*@var{mcu}@tie{}= @code{atmega48}, @code{atmega48a}, @code{atmega48p}, @code{atmega48pa}, @code{atmega48pb}, @code{atmega8}, @code{atmega8a}, @code{atmega8hva}, @code{atmega88}, @code{atmega88a}, @code{atmega88p}, @code{atmega88pa}, @code{atmega88pb}, @code{atmega8515}, @code{atmega8535}, @code{ata6285}, @code{ata6286}, @code{ata6289}, @code{ata6612c}, @code{at90pwm1}, @code{at90pwm2}, @code{at90pwm2b}, @code{at90pwm3}, @code{at90pwm3b}, @code{at90pwm81}.
>  
> -@item avr5
> +@item @anchor{avr5}avr5
>  ``Enhanced'' devices with 16@tie{}KiB up to 64@tie{}KiB of program memory.
>  @*@var{mcu}@tie{}= @code{atmega16}, @code{atmega16a}, @code{atmega16hva}, @code{atmega16hva2}, @code{atmega16hvb}, @code{atmega16hvbrevb}, @code{atmega16m1}, @code{atmega16u4}, @code{atmega161}, @code{atmega162}, @code{atmega163}, @code{atmega164a}, @code{atmega164p}, @code{atmega164pa}, @code{atmega165}, @code{atmega165a}, @code{atmega165p}, @code{atmega165pa}, @code{atmega168}, @code{atmega168a}, @code{atmega168p}, @code{atmega168pa}, @code{atmega168pb}, @code{atmega169}, @code{atmega169a}, @code{atmega169p}, @code{atmega169pa}, @code{atmega32}, @code{atmega32a}, @code{atmega32c1}, @code{atmega32hvb}, @code{atmega32hvbrevb}, @code{atmega32m1}, @code{atmega32u4}, @code{atmega32u6}, @code{atmega323}, @code{atmega324a}, @code{atmega324p}, @code{atmega324pa}, @code{atmega324pb}, @code{atmega325}, @code{atmega325a}, @code{atmega325p}, @code{atmega325pa}, @code{atmega328}, @code{atmega328p}, @code{atmega328pb}, @code{atmega329}, @code{atmega329a}, @code{atmega329p}, @code{atmega329pa}, @code{atmega3250}, @code{atmega3250a}, @code{atmega3250p}, @code{atmega3250pa}, @code{atmega3290}, @code{atmega3290a}, @code{atmega3290p}, @code{atmega3290pa}, @code{atmega406}, @code{atmega64}, @code{atmega64a}, @code{atmega64c1}, @code{atmega64hve}, @code{atmega64hve2}, @code{atmega64m1}, @code{atmega64rfr2}, @code{atmega640}, @code{atmega644}, @code{atmega644a}, @code{atmega644p}, @code{atmega644pa}, @code{atmega644rfr2}, @code{atmega645}, @code{atmega645a}, @code{atmega645p}, @code{atmega649}, @code{atmega649a}, @code{atmega649p}, @code{atmega6450}, @code{atmega6450a}, @code{atmega6450p}, @code{atmega6490}, @code{atmega6490a}, @code{atmega6490p}, @code{ata5795}, @code{ata5790}, @code{ata5790n}, @code{ata5791}, @code{ata6613c}, @code{ata6614q}, @code{ata5782}, @code{ata5831}, @code{ata8210}, @code{ata8510}, @code{ata5702m322}, @code{at90pwm161}, @code{at90pwm216}, @code{at90pwm316}, @code{at90can32}, @code{at90can64}, @code{at90scr100}, @code{at90usb646}, @code{at90usb647}, @code{at94k}, @code{m3000}.
>  
> -@item avr51
> +@item @anchor{avr51}avr51
>  ``Enhanced'' devices with 128@tie{}KiB of program memory.
>  @*@var{mcu}@tie{}= @code{atmega128}, @code{atmega128a}, @code{atmega128rfa1}, @code{atmega128rfr2}, @code{atmega1280}, @code{atmega1281}, @code{atmega1284}, @code{atmega1284p}, @code{atmega1284rfr2}, @code{at90can128}, @code{at90usb1286}, @code{at90usb1287}.
>  
> -@item avr6
> +@item @anchor{avr6}avr6
>  ``Enhanced'' devices with 3-byte PC, i.e.@: with more than 128@tie{}KiB of program memory.
>  @*@var{mcu}@tie{}= @code{atmega256rfr2}, @code{atmega2560}, @code{atmega2561}, @code{atmega2564rfr2}.
>  
> -@item avrxmega2
> +@item @anchor{avrxmega2}avrxmega2
>  ``XMEGA'' devices with more than 8@tie{}KiB and up to 64@tie{}KiB of program memory.
>  @*@var{mcu}@tie{}= @code{atxmega8e5}, @code{atxmega16a4}, @code{atxmega16a4u}, @code{atxmega16c4}, @code{atxmega16d4}, @code{atxmega16e5}, @code{atxmega32a4}, @code{atxmega32a4u}, @code{atxmega32c3}, @code{atxmega32c4}, @code{atxmega32d3}, @code{atxmega32d4}, @code{atxmega32e5}, @code{avr64da28}, @code{avr64da32}, @code{avr64da48}, @code{avr64da64}, @code{avr64db28}, @code{avr64db32}, @code{avr64db48}, @code{avr64db64}, @code{avr64dd14}, @code{avr64dd20}, @code{avr64dd28}, @code{avr64dd32}, @code{avr64ea28}, @code{avr64ea32}, @code{avr64ea48}.
>  
> -@item avrxmega3
> +@item @anchor{avrxmega3}avrxmega3
>  ``XMEGA'' devices with up to 64@tie{}KiB of combined program memory and RAM, and with program memory visible in the RAM address space.
>  @*@var{mcu}@tie{}= @code{attiny202}, @code{attiny204}, @code{attiny212}, @code{attiny214}, @code{attiny402}, @code{attiny404}, @code{attiny406}, @code{attiny412}, @code{attiny414}, @code{attiny416}, @code{attiny417}, @code{attiny424}, @code{attiny426}, @code{attiny427}, @code{attiny804}, @code{attiny806}, @code{attiny807}, @code{attiny814}, @code{attiny816}, @code{attiny817}, @code{attiny824}, @code{attiny826}, @code{attiny827}, @code{attiny1604}, @code{attiny1606}, @code{attiny1607}, @code{attiny1614}, @code{attiny1616}, @code{attiny1617}, @code{attiny1624}, @code{attiny1626}, @code{attiny1627}, @code{attiny3214}, @code{attiny3216}, @code{attiny3217}, @code{attiny3224}, @code{attiny3226}, @code{attiny3227}, @code{atmega808}, @code{atmega809}, @code{atmega1608}, @code{atmega1609}, @code{atmega3208}, @code{atmega3209}, @code{atmega4808}, @code{atmega4809}, @code{avr16dd14}, @code{avr16dd20}, @code{avr16dd28}, @code{avr16dd32}, @code{avr32da28}, @code{avr32da32}, @code{avr32da48}, @code{avr32db28}, @code{avr32db32}, @code{avr32db48}, @code{avr32dd14}, @code{avr32dd20}, @code{avr32dd28}, @code{avr32dd32}.
>  
> -@item avrxmega4
> +@item @anchor{avrxmega4}avrxmega4
>  ``XMEGA'' devices with more than 64@tie{}KiB and up to 128@tie{}KiB of program memory.
>  @*@var{mcu}@tie{}= @code{atxmega64a3}, @code{atxmega64a3u}, @code{atxmega64a4u}, @code{atxmega64b1}, @code{atxmega64b3}, @code{atxmega64c3}, @code{atxmega64d3}, @code{atxmega64d4}, @code{avr128da28}, @code{avr128da32}, @code{avr128da48}, @code{avr128da64}, @code{avr128db28}, @code{avr128db32}, @code{avr128db48}, @code{avr128db64}.
>  
> -@item avrxmega5
> +@item @anchor{avrxmega5}avrxmega5
>  ``XMEGA'' devices with more than 64@tie{}KiB and up to 128@tie{}KiB of program memory and more than 64@tie{}KiB of RAM.
>  @*@var{mcu}@tie{}= @code{atxmega64a1}, @code{atxmega64a1u}.
>  
> -@item avrxmega6
> +@item @anchor{avrxmega6}avrxmega6
>  ``XMEGA'' devices with more than 128@tie{}KiB of program memory.
>  @*@var{mcu}@tie{}= @code{atxmega128a3}, @code{atxmega128a3u}, @code{atxmega128b1}, @code{atxmega128b3}, @code{atxmega128c3}, @code{atxmega128d3}, @code{atxmega128d4}, @code{atxmega192a3}, @code{atxmega192a3u}, @code{atxmega192c3}, @code{atxmega192d3}, @code{atxmega256a3}, @code{atxmega256a3b}, @code{atxmega256a3bu}, @code{atxmega256a3u}, @code{atxmega256c3}, @code{atxmega256d3}, @code{atxmega384c3}, @code{atxmega384d3}.
>  
> -@item avrxmega7
> +@item @anchor{avrxmega7}avrxmega7
>  ``XMEGA'' devices with more than 128@tie{}KiB of program memory and more than 64@tie{}KiB of RAM.
>  @*@var{mcu}@tie{}= @code{atxmega128a1}, @code{atxmega128a1u}, @code{atxmega128a4u}.
>  
> -@item avrtiny
> +@item @anchor{avrtiny}avrtiny
>  ``TINY'' Tiny core devices with 512@tie{}B up to 4@tie{}KiB of program memory.
>  @*@var{mcu}@tie{}= @code{attiny4}, @code{attiny5}, @code{attiny9}, @code{attiny10}, @code{attiny102}, @code{attiny104}, @code{attiny20}, @code{attiny40}.
>  
> -@item avr1
> +@item @anchor{avr1}avr1
>  This ISA is implemented by the minimal AVR core and supported for assembler only.
>  @*@var{mcu}@tie{}= @code{attiny11}, @code{attiny12}, @code{attiny15}, @code{attiny28}, @code{at90s1200}.
>  
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index d4e689b64c0..51f703ad34c 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -882,11 +882,11 @@ Objective-C and Objective-C++ Dialects}.
>  @emph{AVR Options}
>  @gccoptlist{-mmcu=@var{mcu}  -mabsdata  -maccumulate-args
>  -mbranch-cost=@var{cost}
> --mcall-prologues  -mgas-isr-prologues  -mint8
> +-mcall-prologues  -mgas-isr-prologues  -mint8 -mflmap
>  -mdouble=@var{bits} -mlong-double=@var{bits}
>  -mn_flash=@var{size}  -mno-interrupts
>  -mmain-is-OS_task  -mrelax  -mrmw  -mstrict-X  -mtiny-stack
> --mfract-convert-truncate
> +-mrodata-in-ram -mfract-convert-truncate
>  -mshort-calls  -nodevicelib  -nodevicespecs
>  -Waddr-space-convert  -Wmisspelled-isr}
>  
> @@ -23610,6 +23610,13 @@ the @code{--with-double=} and @code{--with-long-double=}
>  @w{@uref{https://gcc.gnu.org/install/configure.html#avr,configure options}},
>  and the same applies for the default values of the options.
>  
> +@opindex mflmap
> +@item -mflmap
> +The device has the @code{FLMAP} bit field located in special function
> +register @code{NVMCTRL_CTRLB}.
> +This option is used internally by the compiler, and you don't need to
> +set it manually.
> +
>  @opindex mgas-isr-prologues
>  @item -mgas-isr-prologues
>  Interrupt service routines (ISRs) may use the @code{__gcc_isr} pseudo
> @@ -23665,6 +23672,20 @@ section on @code{EIND} and linker stubs below.
>  Assume that the device supports the Read-Modify-Write
>  instructions @code{XCH}, @code{LAC}, @code{LAS} and @code{LAT}.
>  
> +@opindex mrodata-in-ram
> +@item -mrodata-in-ram
> +@itemx -mno-rodata-in-ram
> +Locate the @code{.rodata} sections for read-only data in RAM resp.@:
> +in program memory.
> +For most devices, there is no choice and this option acts rather
> +like an assertion.
> +
> +Since v14 and for the AVR64* and AVR128* devices, @code{.rodata}
> +is located in flash memory per default, provided the required GNU Binutils
> +support (@w{@uref{https://sourceware.org/PR31124,PR31124}}) is available.
> +In that case, @option{-mrodata-in-ram} can be used to return to the old
> +layout with @code{.rodata} in RAM.
> +
>  @opindex mshort-calls
>  @item -mshort-calls
>  
> @@ -23747,6 +23768,7 @@ Warn if the ISR is misspelled, i.e.@: without __vector prefix.
>  Enabled by default.
>  @end table
>  
> +@anchor{eind}
>  @subsubsection @code{EIND} and Devices with More Than 128 Ki Bytes of Flash
>  @cindex @code{EIND}
>  Pointers in the implementation are 16@tie{}bits wide.
> @@ -23883,6 +23905,7 @@ and the application be linked with @option{-Wl,--defsym,func_4=0x4}.
>  Alternatively, @code{func_4} can be defined in the linker script.
>  @end itemize
>  
> +@anchor{ramp}
>  @subsubsection Handling of the @code{RAMPD}, @code{RAMPX}, @code{RAMPY} and @code{RAMPZ} Special Function Registers
>  @cindex @code{RAMPD}
>  @cindex @code{RAMPX}
> @@ -23925,6 +23948,7 @@ you must reset it to zero after the access.
>  
>  @end itemize
>  
> +@anchor{macros}
>  @subsubsection AVR Built-in Macros
>  
>  GCC defines several built-in macros so that the user code can test
> @@ -24079,6 +24103,23 @@ description file, and is currently available for
>  there is no need to use address spaces like @code{__flash} or
>  features like attribute @code{progmem} and @code{pgm_read_*}.
>  
> +@item __AVR_HAVE_FLMAP__
> +This macro is defined provided the following conditions are met:
> +@itemize @bullet
> +@item The device has the @code{NVMCTRL_CTRLB.FLMAP} bitfield.
> +This applies to the AVR64* and AVR128* devices.
> +@item It's not known at assembler-time which emulation will be used.
> +@end itemize
> +This implies the compiler was configured with GNU Binutils that implement
> +@w{@uref{https://sourceware.org/PR31124,PR31124}}.
> +
> +@item __AVR_RODATA_IN_RAM__
> +This macro is undefined when the code is compiled for a core architecture.
> +
> +When the code is compiled for a device, the macro is defined to@tie{}1
> +when the @code{.rodata} sections for read-only data is located in RAM;
> +and defined to@tie{}0, otherwise.
> +
>  @item __WITH_AVRLIBC__
>  The compiler is configured to be used together with AVR-Libc.
>  See the @option{--with-avrlibc} configure option.
> diff --git a/gcc/testsuite/gcc.target/avr/torture/pr112944-flmap.c b/gcc/testsuite/gcc.target/avr/torture/pr112944-flmap.c
> new file mode 100644
> index 00000000000..ac2521a4c9f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/avr/torture/pr112944-flmap.c
> @@ -0,0 +1,15 @@
> +/* { dg-do run } */
> +/* { dg-options "-Wl,--defsym,__flmap=0" } */
> +
> +const int val = 1234;
> +
> +int main (void)
> +{
> +  const int *p = & val;
> +  __asm ("" : "+r" (p));
> +
> +  if (*p != 1234)
> +    __builtin_abort ();
> +
> +  return 0;
> +}
> 

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-12-19 12:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-19 12:25 [patch,avr,ping] PR112944: Support .rodata in RAM for AVR64* and AVR128* devices Georg-Johann Lay

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).