diff --git a/gcc/config.in b/gcc/config.in
index b499bbfdda7..99fd2d89fe3 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1679,6 +1679,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
@@ -1686,6 +1692,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 03b3263d529..d0a297d81e4 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 87b59245e3c..9fb23776d39 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 4bc3cf929de..d77e1aad5cd 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;
 
@@ -10758,6 +10761,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'.  */
@@ -10890,13 +10936,11 @@ avr_output_addr_attrib (tree decl, const char *name,
 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;
@@ -10937,13 +10981,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");
@@ -11273,7 +11313,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 e75730857f5..ee0b40603f0 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 89f8680e244..eb9ab8854d8 100644
--- a/gcc/config/avr/gen-avr-mmcu-specs.cc
+++ b/gcc/config/avr/gen-avr-mmcu-specs.cc
@@ -50,6 +50,8 @@
 #define SPECFILE_USAGE_URL                              \
   "https://gcc.gnu.org/gcc-5/changes.html"
 
+#define WIKI_URL				        \
+  "https://gcc.gnu.org/wiki/avr-gcc#spec-files"
 
 static const char header[] =
   "#\n"
@@ -68,9 +70,13 @@ static const char header[] =
 
 static const char help_copy_paste[] =
   "# If you intend to use an existing device specs file as a starting point\n"
-  "# for a new device spec file, make sure you are copying from a specs\n"
-  "# file for a device from the same core architecture and SP width.\n"
-  "# See <" SPECFILE_USAGE_URL "> for a description\n"
+  "# for a new device spec file, make sure you are copying from a specs file\n"
+  "# for a device from the same or compatible:\n"
+  "#     compiler version, compiler vendor, core architecture, SP width,\n"
+  "#     short-calls and FLMAP.\n"
+  "# Otherwise, errors and wrong or sub-optimal code may likely occur.\n"
+  "# See <" WIKI_URL ">\n"
+  "# and <" SPECFILE_USAGE_URL "> for a description\n"
   "# of how to use such own spec files.\n";
 
 #if defined (WITH_AVRLIBC)
@@ -103,6 +109,60 @@ 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 +190,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 +227,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 +284,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 +312,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 +332,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 +356,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 +383,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/specs.h b/gcc/config/avr/specs.h
index 433231fb6a9..574402035bc 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 996046f5198..4acb254d830 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
@@ -28512,6 +28512,74 @@ $as_echo "test failed" >&6; }
 $as_echo "$as_me: WARNING: see \`config.log' for details" >&2;}
     fi
     rm -f conftest.s 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; }
+    cat > conftest.s <<EOF
+        .section .text,"ax",@progbits
+        ldi r16, __flmap_value_with_lock
+EOF
+    { 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 596e5f22f4f..d2ed14496c1 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
@@ -4584,6 +4584,42 @@ EOF
 	AC_MSG_WARN([[see `config.log' for details]])
     fi
     rm -f conftest.s conftest.o conftest.elf conftest.nm
+
+    # Check for emulation avrxmega2_flmap.
+    AC_MSG_CHECKING(binutils for avrxmega2_flmap support (PR31124))
+    cat > conftest.s <<EOF
+        .section .text,"ax",@progbits
+        ldi r16, __flmap_value_with_lock
+EOF
+    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/invoke.texi b/gcc/doc/invoke.texi
index b7a201317ce..1773f0d3f0c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -883,11 +883,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}
 
@@ -23719,6 +23719,20 @@ differ from instructions in the assembler code.
 Relaxing must be turned on if linker stubs are needed, see the
 section on @code{EIND} and linker stubs below.
 
+@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 mstrict-X
 @item -mstrict-X
 Use address register @code{X} in a way proposed by the hardware.  This means
@@ -24112,6 +24126,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.
@@ -24165,6 +24196,11 @@ files.
 Assume that the flash memory has a size of @var{num} times 64@tie{}KiB.
 This determines which @code{__flash@var{N}} address spaces are available.
 
+@opindex mflmap
+@item -mflmap
+The device has the @code{FLMAP} bit field located in special function
+register @code{NVMCTRL_CTRLB}.
+
 @opindex mrmw
 @item -mrmw
 Assume that the device supports the Read-Modify-Write
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr112944-flmap-0.c b/gcc/testsuite/gcc.target/avr/torture/pr112944-flmap-0.c
new file mode 100644
index 00000000000..3aae7b56b4c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr112944-flmap-0.c
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-additional-options "-Wl,--defsym,__flmap=0" } */
+
+const int val = 1234;
+
+#ifdef __AVR_HAVE_FLMAP__
+/* Initialize NVMCTRL_CTRLB.FLMAP to __flmap.  */
+#include <avr/io.h>
+__attribute__((naked, section(".init2")))
+__attribute__((used, unused, no_instrument_function))
+static void init_flmap (void)
+{
+  uint8_t ctrlb = NVMCTRL_CTRLB;
+  ctrlb &= ~ NVMCTRL_FLMAP_gm;
+  ctrlb |= 0 << NVMCTRL_FLMAP_gp;
+  NVMCTRL_CTRLB = ctrlb;
+}
+#endif
+
+int main (void)
+{
+  const int *p = & val;
+  __asm ("" : "+r" (p));
+
+  if (*p != 1234)
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr112944-flmap-1.c b/gcc/testsuite/gcc.target/avr/torture/pr112944-flmap-1.c
new file mode 100644
index 00000000000..f18078d2e2c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr112944-flmap-1.c
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-additional-options "-Wl,--defsym,__flmap=1" } */
+
+const int val = 1234;
+
+#ifdef __AVR_HAVE_FLMAP__
+/* Initialize NVMCTRL_CTRLB.FLMAP to __flmap.  */
+#include <avr/io.h>
+__attribute__((naked, section(".init2")))
+__attribute__((used, unused, no_instrument_function))
+static void init_flmap (void)
+{
+  uint8_t ctrlb = NVMCTRL_CTRLB;
+  ctrlb &= ~ NVMCTRL_FLMAP_gm;
+  ctrlb |= 1 << NVMCTRL_FLMAP_gp;
+  NVMCTRL_CTRLB = ctrlb;
+}
+#endif
+
+int main (void)
+{
+  const int *p = & val;
+  __asm ("" : "+r" (p));
+
+  if (*p != 1234)
+    __builtin_abort ();
+
+  return 0;
+}
