diff options
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/avr/avr-arch.h | 39 | ||||
-rw-r--r-- | gcc/config/avr/avr-mcus.def | 46 | ||||
-rw-r--r-- | gcc/config/avr/avr.cc | 71 | ||||
-rw-r--r-- | gcc/config/avr/avr.opt | 8 | ||||
-rw-r--r-- | gcc/config/avr/gen-avr-mmcu-specs.cc | 115 | ||||
-rw-r--r-- | gcc/config/avr/specs.h | 10 |
6 files changed, 235 insertions, 54 deletions
diff --git a/gcc/config/avr/avr-arch.h b/gcc/config/avr/avr-arch.h index 03b3263..d0a297d 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 87b5924..9fb2377 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 4bc3cf9..d77e1aad 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 e757308..ee0b406 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 89f8680..eb9ab88 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 433231f..5744020 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 |