Home | History | Annotate | Line # | Download | only in avr
      1 /* Copyright (C) 1998-2024 Free Software Foundation, Inc.
      2    Contributed by Joern Rennecke
      3 
      4    This file is part of GCC.
      5 
      6    GCC is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 3, or (at your option)
      9    any later version.
     10 
     11    GCC is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with GCC; see the file COPYING3.  If not see
     18    <http://www.gnu.org/licenses/>.  */
     19 
     20 #include <stdlib.h>
     21 #include <stdio.h>
     22 #include <string.h>
     23 
     24 #define IN_TARGET_CODE 1
     25 
     26 #include "config.h"
     27 
     28 #define IN_GEN_AVR_MMCU_TEXI
     29 
     30 #include "avr-devices.cc"
     31 
     32 // Get rid of "defaults.h".  We just need tm.h for `WITH_AVRLIBC' and
     33 // and `WITH_RTEMS'.
     34 #define GCC_DEFAULTS_H
     35 
     36 #include "tm.h"
     37 
     38 // Mimic the include order as specified in config.gcc::tm_file.
     39 
     40 #include "specs.h"
     41 
     42 #if defined (WITH_AVRLIBC)
     43 #include "avrlibc.h"
     44 #endif
     45 
     46 
     47 #define SPECFILE_DOC_URL				\
     48   "https://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html"
     49 
     50 #define SPECFILE_USAGE_URL			        \
     51   "https://gcc.gnu.org/gcc-5/changes.html"
     52 
     53 #define WIKI_URL					\
     54   "https://gcc.gnu.org/wiki/avr-gcc#spec-files"
     55 
     56 static const char header[] =
     57   "#\n"
     58   "# Generated by   : ./gcc/config/avr/gen-avr-mmcu-specs.cc\n"
     59   "# Generated from : ./gcc/config/gcc.cc\n"
     60   "#                  ./gcc/config/avr/specs.h\n"
     61 #if defined (WITH_AVRLIBC)
     62   "#                  ./gcc/config/avr/avrlibc.h\n"
     63 #endif
     64   "# Used by        : avr-gcc compiler driver\n"
     65   "# Used for       : building command options for sub-processes\n"
     66   "#\n"
     67   "# See <" SPECFILE_DOC_URL ">\n"
     68   "# for a documentation of spec files.\n"
     69   "\n";
     70 
     71 static const char help_copy_paste[] =
     72   "# If you intend to use an existing device specs file as a starting point\n"
     73   "# for a new device spec file, make sure you are copying from a specs file\n"
     74   "# for a device from the same or compatible:\n"
     75   "#     compiler version, compiler vendor, core architecture, SP width,\n"
     76   "#     short-calls and FLMAP.\n"
     77   "# Otherwise, errors and wrong or sub-optimal code may likely occur.\n"
     78   "# See <" WIKI_URL ">\n"
     79   "# and <" SPECFILE_USAGE_URL "> for a description\n"
     80   "# of how to use such own spec files.\n";
     81 
     82 #if defined (WITH_AVRLIBC)
     83 static const char help_dev_lib_name[] =
     84   "# AVR-LibC's avr/io.h uses the device specifying macro to determine\n"
     85   "# the name of the device header.  For example, -mmcu=atmega8a triggers\n"
     86   "# the definition of __AVR_ATmega8A__ and avr/io.h includes the device\n"
     87   "# header 'iom8a.h' by means of:\n"
     88   "#\n"
     89   "#     ...\n"
     90   "#     #elif defined (__AVR_ATmega8A__)\n"
     91   "#     #  include <avr/iom8a.h>\n"
     92   "#     #elif ...\n"
     93   "# \n"
     94   "# If no device macro is defined, AVR-LibC uses __AVR_DEV_LIB_NAME__\n"
     95   "# as fallback to determine the name of the device header as\n"
     96   "#\n"
     97   "#     \"avr/io\" + __AVR_DEV_LIB_NAME__ + \".h\"\n"
     98   "#\n"
     99   "# If you provide your own specs file for a device not yet known to\n"
    100   "# AVR-LibC, you can now define the hook macro __AVR_DEV_LIB_NAME__\n"
    101   "# as needed so that\n"
    102   "#\n"
    103   "#     #include <avr/io.h>\n"
    104   "#\n"
    105   "# will include the desired device header.  For ATmega8A the supplement\n"
    106   "# to *cpp_avrlibc would read\n"
    107   "#\n"
    108   "#     -D__AVR_DEV_LIB_NAME__=m8a\n"
    109   "\n";
    110 #endif // WITH_AVRLIBC
    111 
    112 
    113 #ifdef HAVE_LD_AVR_AVRXMEGA2_FLMAP
    114 static const bool have_avrxmega2_flmap = true;
    115 #else
    116 static const bool have_avrxmega2_flmap = false;
    117 #endif
    118 
    119 #ifdef HAVE_LD_AVR_AVRXMEGA4_FLMAP
    120 static const bool have_avrxmega4_flmap = true;
    121 #else
    122 static const bool have_avrxmega4_flmap = false;
    123 #endif
    124 
    125 #ifdef HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
    126 static const bool have_avrxmega3_rodata_in_flash = true;
    127 #else
    128 static const bool have_avrxmega3_rodata_in_flash = false;
    129 #endif
    130 
    131 
    132 struct McuInfo
    133 {
    134   enum avr_arch_id arch_id;
    135   const avr_arch_t *arch;
    136   bool is_arch, is_device;
    137   bool flmap, have_flmap2, have_flmap4, have_flmap;
    138   bool rodata_in_flash;
    139   // Device name as used by the vendor, extracted from "__AVR_<Name>__".
    140   char mcu_Name[50] = { 0 };
    141 
    142   McuInfo (const avr_mcu_t *mcu)
    143     : arch_id (mcu->arch_id), arch (& avr_arch_types[arch_id]),
    144       is_arch (mcu->macro == NULL), is_device (! is_arch),
    145       flmap (mcu->dev_attribute & AVR_ISA_FLMAP),
    146       have_flmap2 (have_avrxmega2_flmap && arch_id == ARCH_AVRXMEGA2),
    147       have_flmap4 (have_avrxmega4_flmap && arch_id == ARCH_AVRXMEGA4),
    148       have_flmap (flmap && (have_flmap2 || have_flmap4)),
    149       rodata_in_flash (arch_id == ARCH_AVRTINY
    150 		       || (arch_id == ARCH_AVRXMEGA3
    151 			   && have_avrxmega3_rodata_in_flash))
    152   {
    153     if (is_device)
    154       snprintf (mcu_Name, 1 + strlen (mcu->macro) - strlen ("__AVR_" "__"),
    155 		"%s", mcu->macro + strlen ("__AVR_"));
    156   }
    157 };
    158 
    159 
    160 static void
    161 diagnose_mrodata_in_ram (FILE *f, const char *spec, const avr_mcu_t *mcu,
    162 			 const McuInfo &mi)
    163 {
    164   fprintf (f, "%s:\n", spec);
    165   if (mi.rodata_in_flash && mi.is_arch)
    166     fprintf (f, "\t%%{mrodata-in-ram: %%e-mrodata-in-ram is not supported"
    167 	     " for %s}", mcu->name);
    168   else if (mi.rodata_in_flash)
    169     fprintf (f, "\t%%{mrodata-in-ram: %%e-mrodata-in-ram is not supported"
    170 	     " for %s (arch=%s)}", mi.mcu_Name, mi.arch->name);
    171   else if (mi.is_arch)
    172     {
    173       if (! mi.have_flmap2 && ! mi.have_flmap4)
    174 	fprintf (f, "\t%%{mno-rodata-in-ram: %%e-mno-rodata-in-ram is not"
    175 		 " supported for %s}", mcu->name);
    176     }
    177   else if (! mi.have_flmap)
    178     fprintf (f, "\t%%{mno-rodata-in-ram: %%e-mno-rodata-in-ram is not supported"
    179 	     " for %s (arch=%s)}", mi.mcu_Name, mi.arch->name);
    180   fprintf (f, "\n\n");
    181 }
    182 
    183 
    184 static void
    185 print_mcu (const avr_mcu_t *mcu, const McuInfo &mi)
    186 {
    187   const char *sp8_spec;
    188   const char *rcall_spec;
    189   const avr_mcu_t *arch_mcu;
    190 
    191   for (arch_mcu = mcu; arch_mcu->macro; )
    192     arch_mcu--;
    193   if (arch_mcu->arch_id != mi.arch_id)
    194     exit (EXIT_FAILURE);
    195 
    196   char name[100];
    197   if (snprintf (name, sizeof name, "specs-%s", mcu->name) >= (int) sizeof name)
    198    exit (EXIT_FAILURE);
    199 
    200   FILE *f = fopen (name ,"w");
    201 
    202   bool absdata = (mcu->dev_attribute & AVR_ISA_LDS) != 0;
    203   bool errata_skip = (mcu->dev_attribute & AVR_ERRATA_SKIP) != 0;
    204   bool rmw = (mcu->dev_attribute & AVR_ISA_RMW) != 0;
    205   bool sp8 = (mcu->dev_attribute & AVR_SHORT_SP) != 0;
    206   bool rcall = (mcu->dev_attribute & AVR_ISA_RCALL);
    207   int rodata_pm_offset = 0;
    208   int pm_base_address = 0;
    209 
    210   if (mi.arch->flash_pm_offset
    211       && mcu->flash_pm_offset
    212       && mcu->flash_pm_offset != mi.arch->flash_pm_offset)
    213     {
    214       rodata_pm_offset = mcu->flash_pm_offset;
    215     }
    216 
    217   if (mi.arch->flash_pm_offset)
    218     {
    219       pm_base_address = mcu->flash_pm_offset
    220 	? mcu->flash_pm_offset
    221 	: mi.arch->flash_pm_offset;
    222     }
    223 
    224   if (mi.is_arch
    225       && (ARCH_AVR2 == mi.arch_id
    226 	  || ARCH_AVR25 == mi.arch_id))
    227     {
    228       // Leave "avr2" and "avr25" alone.  These two architectures are
    229       // the only ones that mix devices with 8-bit SP and 16-bit SP.
    230       sp8_spec = "";
    231     }
    232   else
    233     {
    234       sp8_spec = sp8 ? "-msp8" :"%<msp8";
    235     }
    236 
    237   if (mi.is_arch
    238       && ARCH_AVRXMEGA3 == mi.arch_id)
    239     {
    240       // Leave "avrxmega3" alone.  This architectures is the only one
    241       // that mixes devices with and without JMP / CALL.
    242       rcall_spec = "";
    243     }
    244   else
    245     {
    246       rcall_spec = rcall ? "-mshort-calls" : "%<mshort-calls";
    247     }
    248 
    249   const char *flmap_spec = mi.flmap ? "-mflmap" : "%<mflmap";
    250   const char *link_arch_spec = "%{mmcu=*:-m%*}";
    251   const char *link_arch_flmap_spec = "%{mmcu=*:-m%*%{!mrodata-in-ram:_flmap}}";
    252 
    253   if (mi.have_flmap)
    254     link_arch_spec = link_arch_flmap_spec;
    255 
    256   fprintf (f, "#\n"
    257 	   "# Auto-generated specs for AVR ");
    258   if (mi.is_arch)
    259     fprintf (f, "core architecture %s\n", mi.arch->name);
    260   else
    261     fprintf (f, "device %s (core %s, %d-bit SP%s%s)\n", mi.mcu_Name,
    262 	     mi.arch->name, sp8 ? 8 : 16, rcall ? ", short-calls" : "",
    263 	     mi.have_flmap ? ", FLMAP" : "");
    264   fprintf (f, "%s\n", header);
    265 
    266   if (mi.is_device)
    267     fprintf (f, "%s\n", help_copy_paste);
    268 
    269 #if defined (WITH_AVRLIBC)
    270   // AVR-LibC specific.  See avrlibc.h for the specs using them as subspecs.
    271 
    272   if (mi.is_device)
    273     {
    274       fprintf (f, "*avrlibc_startfile:\n");
    275       fprintf (f, "\tcrt%s.o%%s", mcu->name);
    276       fprintf (f, "\n\n");
    277 
    278       fprintf (f, "*avrlibc_devicelib:\n");
    279       fprintf (f, "\t%%{!nodevicelib:-l%s}", mcu->name);
    280       fprintf (f, "\n\n");
    281     }
    282 #endif  // WITH_AVRLIBC
    283 
    284   // Diagnose usage of -m[no-]rodata-in-ram.
    285   diagnose_mrodata_in_ram (f, "*check_rodata_in_ram", mcu, mi);
    286 
    287   // avr-gcc specific specs for the compilation / the compiler proper.
    288 
    289   int n_flash = 1 + (mcu->flash_size - 1) / 0x10000;
    290 
    291   fprintf (f, "*cc1_n_flash:\n"
    292 	   "\t%%{!mn-flash=*:-mn-flash=%d}\n\n", n_flash);
    293 
    294   fprintf (f, "*cc1_rmw:\n%s\n\n", rmw
    295 	   ? "\t%{!mno-rmw: -mrmw}"
    296 	   : "\t%{mrmw}");
    297 
    298   fprintf (f, "*cc1_errata_skip:\n%s\n\n", errata_skip
    299 	   ? "\t%{!mno-skip-bug: -mskip-bug}"
    300 	   : "\t%{!mskip-bug: -mno-skip-bug}");
    301 
    302   fprintf (f, "*cc1_absdata:\n%s\n\n", absdata
    303 	   ? "\t%{!mno-absdata: -mabsdata}"
    304 	   : "\t%{mabsdata}");
    305 
    306   // -m[no-]rodata-in-ram basically affects linking, but sanity-check early.
    307   fprintf (f, "*cc1_rodata_in_ram:\n\t%%(check_rodata_in_ram)\n\n");
    308 
    309   // avr-gcc specific specs for assembling / the assembler.
    310 
    311   fprintf (f, "*asm_arch:\n\t-mmcu=%s\n\n", mi.arch->name);
    312 
    313 #ifdef HAVE_AS_AVR_MLINK_RELAX_OPTION
    314   fprintf (f, "*asm_relax:\n\t%s\n\n", ASM_RELAX_SPEC);
    315 #endif // have avr-as --mlink-relax
    316 
    317 #ifdef HAVE_AS_AVR_MRMW_OPTION
    318   fprintf (f, "*asm_rmw:\n%s\n\n", rmw
    319 	   ? "\t%{!mno-rmw: -mrmw}"
    320 	   : "\t%{mrmw}");
    321 #endif // have avr-as -mrmw
    322 
    323 #ifdef HAVE_AS_AVR_MGCCISR_OPTION
    324   fprintf (f, "*asm_gccisr:\n%s\n\n",
    325 	   "\t%{!mno-gas-isr-prologues: -mgcc-isr}");
    326 #endif // have avr-as -mgcc-isr
    327 
    328   fprintf (f, "*asm_errata_skip:\n%s\n\n", errata_skip
    329 	   ? "\t%{mno-skip-bug}"
    330 	   : "\t%{!mskip-bug: -mno-skip-bug}");
    331 
    332   // avr-specific specs for linking / the linker.
    333 
    334   int wrap_k =
    335     mcu->flash_size == 0x2000 ? 8
    336     : mcu->flash_size == 0x4000 ? 16
    337     : mcu->flash_size == 0x8000 ? 32
    338     : mcu->flash_size == 0x10000 ? 64
    339     : 0;
    340 
    341   fprintf (f, "*link_pmem_wrap:\n");
    342   if (wrap_k == 8)
    343     fprintf (f, "\t%%{!mno-pmem-wrap-around: --pmem-wrap-around=8k}");
    344   else if (wrap_k > 8)
    345     fprintf (f, "\t%%{mpmem-wrap-around: --pmem-wrap-around=%dk}", wrap_k);
    346   fprintf (f, "\n\n");
    347 
    348   fprintf (f, "*link_relax:\n\t%s\n\n", LINK_RELAX_SPEC);
    349 
    350   fprintf (f, "*link_arch:\n\t%s", link_arch_spec);
    351   if (mi.is_device
    352       && rodata_pm_offset)
    353     fprintf (f, " --defsym=__RODATA_PM_OFFSET__=0x%x", rodata_pm_offset);
    354   fprintf (f, "\n\n");
    355 
    356   if (mi.is_device)
    357     {
    358       fprintf (f, "*link_data_start:\n");
    359       if (mcu->data_section_start
    360 	  != mi.arch->default_data_section_start)
    361 	fprintf (f, "\t%%{!Tdata:-Tdata 0x%lX}",
    362 		 0x800000UL + mcu->data_section_start);
    363       fprintf (f, "\n\n");
    364 
    365       fprintf (f, "*link_text_start:\n");
    366       if (mcu->text_section_start != 0x0)
    367 	fprintf (f, "\t%%{!Ttext:-Ttext 0x%lX}", 0UL + mcu->text_section_start);
    368       fprintf (f, "\n\n");
    369     }
    370 
    371   // -m[no-]rodata-in-ram affects linking.  Sanity check its usage.
    372   fprintf (f, "*link_rodata_in_ram:\n\t%%(check_rodata_in_ram)");
    373   if (mi.is_device && mi.have_flmap)
    374     fprintf (f, " %%{!mrodata-in-ram:-u __do_flmap_init}");
    375   fprintf (f, "\n\n");
    376 
    377   // Specs known to GCC.
    378 
    379   if (mi.is_device)
    380     {
    381       fprintf (f, "*self_spec:\n");
    382       fprintf (f, "\t%%<mmcu=* -mmcu=%s ", mi.arch->name);
    383       fprintf (f, "%s ", flmap_spec);
    384       fprintf (f, "%s ", rcall_spec);
    385       fprintf (f, "%s\n\n", sp8_spec);
    386 
    387 #if defined (WITH_AVRLIBC)
    388       fprintf (f, "%s\n", help_dev_lib_name);
    389 
    390       fprintf (f, "*cpp_avrlibc:\n");
    391       fprintf (f, "\t-D__AVR_DEVICE_NAME__=%s", mcu->name);
    392       fprintf (f, "\n\n");
    393 #endif // WITH_AVRLIBC
    394 
    395       fprintf (f, "*cpp_mcu:\n");
    396       fprintf (f, "\t-D%s", mcu->macro);
    397       if (pm_base_address)
    398 	{
    399 	  fprintf (f, " -U__AVR_PM_BASE_ADDRESS__");
    400 	  fprintf (f, " -D__AVR_PM_BASE_ADDRESS__=0x%x", pm_base_address);
    401 	}
    402       if (mi.have_flmap)
    403 	fprintf (f, " -D__AVR_HAVE_FLMAP__");
    404 
    405       fprintf (f, "\n\n"); // *cpp_mcu
    406 
    407       fprintf (f, "*cpp_rodata_in_ram:\n\t-D__AVR_RODATA_IN_RAM__=");
    408       if (mi.rodata_in_flash)
    409 	fprintf (f, "0");
    410       else if (! mi.have_flmap)
    411 	fprintf (f, "1");
    412       else
    413 	fprintf (f, "%%{!mrodata-in-ram:%%{!mno-rodata-in-ram:0}}"
    414 		 "%%{mrodata-in-ram:1}" "%%{mno-rodata-in-ram:0}");
    415       fprintf (f, "\n\n");
    416 
    417       fprintf (f, "*cpp:\n");
    418       fprintf (f, "\t%%(cpp_mcu) %%(cpp_rodata_in_ram)");
    419 #if defined (WITH_AVRLIBC)
    420       fprintf (f, " %%(cpp_avrlibc)");
    421 #endif // WITH_AVRLIBC
    422       fprintf (f, "\n\n");
    423     }
    424 
    425   fprintf (f, "# End of file\n");
    426 
    427   fclose (f);
    428 }
    429 
    430 
    431 int main (void)
    432 {
    433   for (const avr_mcu_t *mcu = avr_mcu_types; mcu->name; mcu++)
    434     print_mcu (mcu, McuInfo (mcu));
    435 
    436   return EXIT_SUCCESS;
    437 }
    438