public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Georg-Johann Lay <avr@gjlay.de>
To: Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
Cc: Denis Chertykov <chertykov@gmail.com>,
	 GCC Patches <gcc-patches@gcc.gnu.org>,
	Joerg Wunsch <joerg_wunsch@uriah.heep.sax.de>,
	 Joern Rennecke <joern.rennecke@embecosm.com>
Subject: Re: [patch,avr]: Part2: Fix various problems with specs and specs file generation.
Date: Mon, 09 Mar 2015 16:03:00 -0000	[thread overview]
Message-ID: <54FDC417.1000008@gjlay.de> (raw)
In-Reply-To: <20150303132144.GC24277@atmel.com>

[-- Attachment #1: Type: text/plain, Size: 5175 bytes --]

Am 03/03/2015 um 02:21 PM schrieb Senthil Kumar Selvaraj:
> On Mon, Mar 02, 2015 at 08:40:17PM +0100, Georg-Johann Lay wrote:
>> The new specs file generation introduces several problems.  This patch
>>
>> - Fix build warnings
>>
>> - Clean up unused code and the old, now dead specs definitions.
>>
>> - Removes unused files and adjust build scripts / rules.
>>
>> - Issues with avr-libc awareness:
>>
>> -- Makes specs-generation aware of avr-libc (include tm.h in build script
>> and depend on WITH_AVRLIBC).
>>
>> -- avr-libc implements functions in libm.a which usually live in libgcc,
>> hence add -lm to libgcc_spec, cf. PR54461.
>>
>> -- The new libdev.a is a feature of avr-libc and not available with, e.g.,
>> newlib.  Hence remove it from lib_spec if the compiler is not configured for
>> avr-libc (--with-avrlibc=no).
>>
>> - Many minor issues with option propagation.
>>
>> - -march had been added to multilib generation some time ago, but
>> driver_self_spec was not aware of that option.
>>
>>
>> Ok for trunk?
>>
>>
>> BTW, anyone knows what -march= is good for?  It allows all kinds of silly
>> option combinations like "-march=avrtiny -mmcu=atmega8" without any
>> complaints.
>
> IIRC, -march was added because replacing -mmcu=<device> to
> -mmcu=<arch> in the driver's self specs broke multilib selection - the
> driver always acted as if no -mmcu was specified. Adding

For me both multilib selection and multilib generation are working as expected 
with -mmcu= and without that -march=.

Attached is a 2nd part of improvements for the specs file generation:

- Remove -arch= and use -mmcu= again.

- Wrap specs file selection into a new specs function so that a comprehensible 
error message can be issued if no specs file is found.  It also informs about a 
link to spec file documentation of gcc inline docs.

- Remove genopt.sh and avr-tables.opt.  These files are no more used because 
-mmcu= is a vanilla string option now.  Using Enum option for -mmcu= does not 
allow to specify unknown devices, and target_handle_option cannot letgigimize 
unknown strings of Enum options.

- Resurrect driver-avr.c but with new content: The new specs function.

- New file specs.h with specs known to gcc and which can be overridden by 
avrlibc.h, rtems.h, etc.

- New device-specs files mostly repeat spec definitions, e.g.

     fprintf (f, "*startfile:\n\t%s\n\n", STARTFILE_SPEC);
     fprintf (f, "*endfile:\n\t%s\n\n", ENDFILE_SPEC);

- Device feature are expressed as subspecs now, e.g. avrlibc_startfile spec.

- Clean up code from "current device" stuff, adjust diagnostics, avr-arch.h, etc.

- Use INSTALL_DATA to install spec files, not INSTALL_PROGRAM.



Ok to install this, too?


Johann

	PR target/65296
	* config.gcc (extra_options) [avr]: Remove.
	(extra_gcc_objs) [avr]: Use driver-avr.o, avr-devices.o.
	(tm_file) [avr]: Add avr/specs.h after avr/avr.h.
	(tm_defines) [avr, rtems]: Add WITH_RTEMS.

	* config/avr/genmultilib.awk: Use -mmcu= instead of -march=.
	* config/avr/t-multilib: Regenerate.
	* config/avr/specs.h: New file.
	* config/avr/driver-avr.c: New file.
	* config/avr/genopt.sh: Remove file.
	* config/avr/avr-tables.opt: Remove file.
	* config/avr/predicates.md (avr_current_arch): Rename to avr_arch.
	* config/avr/avr-c.c: Same.
	* avr-arch.h: Same.
	(avr_current_device): Remove proto.
	* config/avr/avr.c (avr_current_arch): Rename to avr_arch.
	(avr_current_device): Remove definition and usage.
	(avr_set_core_architecture): New static function.
	(avr_option_override): Use it.
	* config/avr/avr.h (avr_current_arch): Rename to avr_arch.
	(AVR_HAVE_8BIT_SP): Don't depend on avr_current_device.
	(EXTRA_SPEC_FUNCTIONS): Define.
	(avr_devicespecs_file): New specs function proto.
	(DRIVER_SELF_SPECS): Use device-specs-file spec function.
	* config/avr/avr-devices.c (diagnostic.h, avr-arch.h): Include them.
	(mcu_name): New static array.
	(comparator, avr_archs_str, avr_mcus_str): New static functions.
	(avr_inform_devices, avr_inform_core_architectures): New functions.
	* config/avr/gen-avr-mmcu-specs.c (avr-arch.h, specs.h): Include.
	(avrlibc.h) [WITH_AVRLIBC]: Include.
	(../rtems.h, rtems.h) [WITH_RTEMS]: Include.
	(print_mcu): Rewrite from scratch.
	* config/avr/avrlibc.h (LIB_SPEC, LIBGCC_SPEC, STARTFILE_SPEC):
	Forward to avr-specific specs defined in device-specs file.
	* config/avr/avr.opt (config/avr/avr-arch.h): Remove include.
	(-mmcu=): Add Var and MissingArgError properties.
	(-march=): Remove.
	* config/avr/t-avr (driver-avr.o): New rule.
	(avr-devices.o): Depend on avr-arch.h.
	(avr-mcus): No more depend on avr-tables.opt.
	(avr-tables.opt): Remove rule.
	(install-device-specs): Use INSTALL_DATA, not INSTALL_PROGRAM.


> a new option (-march), translating mmcu=<device> to march=<arch> and then
> basing t-multilib on that worked ok.
>
>>
>> What's wrong with -mmcu=avr* ? All architecture names start with "avr", and
>> /no/ device name starts /with/ "avr", hence -mmcu= should be fine and work
>> as smooth as in the last 10 years.
>>
>> Why that -march= option?  If there is not a good reason for -march=, I'd
>> propose to clean it up and use -mmcu=avr* instead.
>>
>>
>> Johann


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: pr65296-part2.diff --]
[-- Type: text/x-patch; name="pr65296-part2.diff", Size: 48464 bytes --]

Index: config.gcc
===================================================================
--- config.gcc	(revision 221144)
+++ config.gcc	(working copy)
@@ -330,7 +330,6 @@ avr-*-*)
 	cpu_type=avr
 	c_target_objs="avr-c.o"
 	cxx_target_objs="avr-c.o"
-	extra_options="${extra_options} avr/avr-tables.opt"
 	;;
 bfin*-*)
 	cpu_type=bfin
@@ -1090,18 +1089,21 @@ arm*-*-eabi* | arm*-*-symbianelf* | arm*
 	tm_file="${tm_file} arm/aout.h vxworks-dummy.h arm/arm.h"
 	;;
 avr-*-rtems*)
-	tm_file="elfos.h avr/elf.h avr/avr-arch.h avr/avr.h dbxelf.h avr/rtems.h rtems.h newlib-stdint.h"
+	tm_file="elfos.h avr/elf.h avr/avr-arch.h avr/avr.h avr/specs.h dbxelf.h avr/rtems.h rtems.h newlib-stdint.h"
+	tm_defines="${tm_defines} WITH_RTEMS"
 	tmake_file="${tmake_file} avr/t-avr avr/t-multilib avr/t-rtems"
+	extra_gcc_objs="driver-avr.o avr-devices.o"
 	extra_objs="avr-devices.o avr-log.o"
 	;;
 avr-*-*)
-	tm_file="elfos.h avr/elf.h avr/avr-arch.h avr/avr.h dbxelf.h avr/avr-stdint.h"
+	tm_file="elfos.h avr/elf.h avr/avr-arch.h avr/avr.h avr/specs.h dbxelf.h avr/avr-stdint.h"
 	if test x${with_avrlibc} != xno; then
 	    tm_file="${tm_file} ${cpu_type}/avrlibc.h"
 	    tm_defines="${tm_defines} WITH_AVRLIBC"
 	fi
 	tmake_file="${tmake_file} avr/t-avr avr/t-multilib"
 	use_gcc_stdint=wrap
+	extra_gcc_objs="driver-avr.o avr-devices.o"
 	extra_objs="avr-devices.o avr-log.o"
 	;;
 bfin*-elf*)
Index: config/avr/gen-avr-mmcu-texi.c
===================================================================
--- config/avr/gen-avr-mmcu-texi.c	(revision 221140)
+++ config/avr/gen-avr-mmcu-texi.c	(working copy)
@@ -22,7 +22,6 @@
 
 #define IN_GEN_AVR_MMCU_TEXI
 
-#include "avr-arch.h"
 #include "avr-devices.c"
 
 static const char*
@@ -97,7 +96,7 @@ print_mcus (size_t n_mcus)
 
 int main (void)
 {
-  enum avr_arch arch = ARCH_UNKNOWN;
+  enum avr_arch_id arch_id = ARCH_UNKNOWN;
   size_t i, n_mcus = 0;
   const avr_mcu_t *mcu;
 
@@ -120,7 +119,7 @@ int main (void)
     {
       if (mcu->macro == NULL)
         {
-          arch = mcu->arch;
+          arch_id = mcu->arch_id;
 
           /* Start a new architecture:  Flush the MCUs collected so far.  */
 
@@ -128,10 +127,10 @@ if (mcu->macro == NULL)
           n_mcus = 0;
 
           for (i = 0; i < sizeof (avr_texinfo) / sizeof (*avr_texinfo); i++)
-            if (arch == avr_texinfo[i].arch)
+            if (arch_id == avr_texinfo[i].arch_id)
               printf ("@item %s\n%s\n", mcu->name, avr_texinfo[i].texinfo);
         }
-      else if (arch == (enum avr_arch) mcu->arch)
+      else if (arch_id == (enum avr_arch_id) mcu->arch_id)
         {
           mcu_name[n_mcus++] = mcu->name;
         }
Index: config/avr/avr-devices.c
===================================================================
--- config/avr/avr-devices.c	(revision 221140)
+++ config/avr/avr-devices.c	(working copy)
@@ -21,9 +21,12 @@
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "diagnostic.h"
 #include "tm.h"
 #endif /* IN_GEN_AVR_MMCU_TEXI */
 
+#include "avr-arch.h"
+
 /* List of all known AVR MCU architectures.
    Order as of enum avr_arch from avr.h.  */
 
@@ -31,7 +34,7 @@ const avr_arch_t
 avr_arch_types[] =
 {
   /* unknown device specified */
-  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, NULL,  "avr2"  },
+  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, NULL, AVR_MMCU_DEFAULT },
   /*
     A  M  J  LM E  E  E  X  R  T  d S   S O   A
     S  U  M  PO L  L  I  M  A  I  a t   F ff  r
@@ -116,3 +119,98 @@ avr_mcu_types[] =
   { NULL, ARCH_UNKNOWN, AVR_ISA_NONE, NULL, 0, 0, 0, NULL }
 };
 
+
+\f
+
+#ifndef IN_GEN_AVR_MMCU_TEXI
+
+/* Copy-pastes from `gen-avr-mmcu-texi.c' follow...  */
+
+static const char*
+mcu_name[sizeof avr_mcu_types / sizeof avr_mcu_types[0]];
+
+static int
+comparator (const void *va, const void *vb)
+{
+  const char *a = *(const char* const*) va;
+  const char *b = *(const char* const*) vb;
+
+  while (*a && *b)
+    {
+      /* Make letters smaller than digits so that `atmega16a' follows
+         `atmega16' without `atmega161' etc. between them.  */
+      
+      if (ISALPHA (*a) && ISDIGIT (*b))
+        return -1;
+
+      if (ISDIGIT (*a) && ISALPHA (*b))
+        return 1;
+
+      if (*a != *b)
+        return *a - *b;
+      
+      a++;
+      b++;
+    }
+
+  return *a - *b;
+}
+
+
+static char*
+avr_archs_str (void)
+{
+  char *archs = concat ("", NULL);
+
+  // Build of core architectures' names.
+
+  for (const avr_mcu_t *mcu = avr_mcu_types; mcu->name; mcu++)
+    if (!mcu->macro)
+      archs = concat (archs, " ", avr_arch_types[mcu->arch_id].name, NULL);
+
+  return archs;
+}
+
+  
+static char*
+avr_mcus_str (void)
+{
+  size_t n_mcus = 0;
+  char *mcus = concat ("", NULL);
+
+  // Build array of proper devices' names.
+
+  for (const avr_mcu_t *mcu = avr_mcu_types; mcu->name; mcu++)
+    if (mcu->macro)
+      mcu_name[n_mcus++] = mcu->name;
+
+  // Sort MCUs so that they are displayed in the same canonical order as
+  // in doc/avr-mcus.texi.
+
+  qsort (mcu_name, n_mcus, sizeof (char*), comparator);
+
+  for (size_t i = 0; i < n_mcus; i++)
+    mcus = concat (mcus, " ", mcu_name[i], NULL);
+
+  return mcus;
+}
+
+
+void
+avr_inform_devices (void)
+{
+  char *mcus = avr_mcus_str ();
+  inform (input_location, "devices natively supported:%s", mcus);
+  free (mcus);
+}
+
+
+void
+avr_inform_core_architectures (void)
+{
+  char *archs = avr_archs_str ();
+  inform (input_location, "supported core architectures:%s", archs);
+  free (archs);
+}
+
+#endif // IN_GEN_AVR_MMCU_TEXI
Index: config/avr/avr-arch.h
===================================================================
--- config/avr/avr-arch.h	(revision 221140)
+++ config/avr/avr-arch.h	(working copy)
@@ -22,9 +22,11 @@ along with GCC; see the file COPYING3.
 #ifndef AVR_ARCH_H
 #define AVR_ARCH_H
 
+#define AVR_MMCU_DEFAULT "avr2"
+
 /* This enum supplies indices into the avr_arch_types[] table below. */
 
-enum avr_arch
+enum avr_arch_id
 {
   ARCH_UNKNOWN,
   ARCH_AVR1,
@@ -92,7 +94,7 @@ /* Architecture id to built-in define __
   const char *const macro;
 
   /* Architecture name.  */
-  const char *const arch_name;
+  const char *const name;
 } avr_arch_t;
 
 
@@ -104,7 +106,7 @@ typedef struct
   const char *const name;
 
   /* Index in avr_arch_types[].  */
-  enum avr_arch arch;
+  enum avr_arch_id arch_id;
 
   /* device specific feature */
   int dev_attribute;
@@ -166,7 +168,7 @@ enum avr_device_specific_features
 typedef struct
 {
   /* Architecture ID.  */
-  enum avr_arch arch;
+  enum avr_arch_id arch_id;
 
   /* textinfo source to describe the archtiecture.  */
   const char *texinfo;
@@ -175,9 +177,11 @@ typedef struct
 /* Preprocessor macros to define depending on MCU type.  */
 
 extern const avr_arch_t avr_arch_types[];
-extern const avr_arch_t *avr_current_arch;
+extern const avr_arch_t *avr_arch;
 
 extern const avr_mcu_t avr_mcu_types[];
-extern const avr_mcu_t *avr_current_device;
+
+extern void avr_inform_devices (void);
+extern void avr_inform_core_architectures (void);
 
 #endif /* AVR_ARCH_H */
Index: config/avr/avr-mcus.def
===================================================================
--- config/avr/avr-mcus.def	(revision 221140)
+++ config/avr/avr-mcus.def	(working copy)
@@ -24,11 +24,10 @@
    This will regenerate / update the following source files:
 
    -  $(srcdir)/config/avr/t-multilib
-   -  $(srcdir)/config/avr/avr-tables.opt
    -  $(srcdir)/doc/avr-mmcu.texi
 
    After that, rebuild everything and check-in the new sources to the repo.
-   The device list below has to be kept in sync with AVR-LibC.
+   The device list below should be kept in sync with AVR-LibC.
 
 
    Before including this file, define a macro:
@@ -53,8 +52,7 @@ supply respective built-in macro.
 
        N_FLASH       Number of 64 KiB flash segments, rounded up.
 
-       LIBRARY_NAME  Used by the driver to linke startup code from avr-libc
-                     as of  crt<LIBRARY_NAME>.o
+       LIBRARY_NAME  Used to define __AVR_DEV_LIB_NAME__.
 
    "avr2" must be first for the "0" default to work as intended.  */
 
Index: config/avr/genmultilib.awk
===================================================================
--- config/avr/genmultilib.awk	(revision 221140)
+++ config/avr/genmultilib.awk	(working copy)
@@ -97,7 +97,7 @@ BEGIN {
 	cores[n_cores] = core
 	n_cores++
 	tiny_stack[core] = 0
-	option[core] = "march=" core
+	option[core] = "mmcu=" core
 
 	next
     }
Index: config/avr/genopt.sh
===================================================================
--- config/avr/genopt.sh	(revision 221140)
+++ config/avr/genopt.sh	(working copy)
@@ -1,58 +0,0 @@
-#!/bin/sh
-# Generate avr-tables.opt from the list in avr-mcus.def.
-# Copyright (C) 2011-2015 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3.  If not see
-# <http://www.gnu.org/licenses/>.
-
-cat <<EOF
-; -*- buffer-read-only: t -*-
-; Generated automatically by genopt.sh from avr-mcus.def.
-
-; Copyright (C) 2011-2015 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 3, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-; for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING3.  If not see
-; <http://www.gnu.org/licenses/>.
-
-Enum
-Name(avr_arch) Type(enum avr_arch)
-Known MCU architectures:
-
-EOF
-
-awk -F'[(, 	]+' 'BEGIN {
-}
-/^AVR_MCU.*NULL/ {
-    name = $2
-    value = $3
-    gsub("\"", "", name)
-    print "EnumValue"
-    print "Enum(avr_arch) String(" name ") Value(" value ")"
-    print ""
-}' $1
Index: config/avr/avrlibc.h
===================================================================
--- config/avr/avrlibc.h	(revision 221141)
+++ config/avr/avrlibc.h	(working copy)
@@ -27,6 +27,18 @@ along with GCC; see the file COPYING3.
    
 */
 
+#undef  LIB_SPEC
+#define LIB_SPEC                                \
+  " -lc %(avrlibc_devicelib) "
+
+#undef  LIBGCC_SPEC
+#define LIBGCC_SPEC                             \
+  " -lgcc -lm "
+
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC                          \
+  " %(avrlibc_startfile) "
+
 #undef  LINK_GCC_C_SEQUENCE_SPEC
 #define LINK_GCC_C_SEQUENCE_SPEC \
   "--start-group %G %L --end-group"
Index: config/avr/t-multilib
===================================================================
--- config/avr/t-multilib	(revision 221140)
+++ config/avr/t-multilib	(working copy)
@@ -21,21 +21,21 @@
 # along with GCC; see the file COPYING3.  If not see
 # <http://www.gnu.org/licenses/>.
 
-MULTILIB_OPTIONS = march=avr2/march=avr25/march=avr3/march=avr31/march=avr35/march=avr4/march=avr5/march=avr51/march=avr6/march=avrxmega2/march=avrxmega4/march=avrxmega5/march=avrxmega6/march=avrxmega7/march=avrtiny msp8
+MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega2/mmcu=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7/mmcu=avrtiny msp8
 
 MULTILIB_DIRNAMES =  avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny tiny-stack avr25/tiny-stack
 
 MULTILIB_EXCEPTIONS = \
-	march=avr3/msp8 \
-	march=avr31/msp8 \
-	march=avr35/msp8 \
-	march=avr4/msp8 \
-	march=avr5/msp8 \
-	march=avr51/msp8 \
-	march=avr6/msp8 \
-	march=avrxmega2/msp8 \
-	march=avrxmega4/msp8 \
-	march=avrxmega5/msp8 \
-	march=avrxmega6/msp8 \
-	march=avrxmega7/msp8 \
-	march=avrtiny/msp8
+	mmcu=avr3/msp8 \
+	mmcu=avr31/msp8 \
+	mmcu=avr35/msp8 \
+	mmcu=avr4/msp8 \
+	mmcu=avr5/msp8 \
+	mmcu=avr51/msp8 \
+	mmcu=avr6/msp8 \
+	mmcu=avrxmega2/msp8 \
+	mmcu=avrxmega4/msp8 \
+	mmcu=avrxmega5/msp8 \
+	mmcu=avrxmega6/msp8 \
+	mmcu=avrxmega7/msp8 \
+	mmcu=avrtiny/msp8
Index: config/avr/predicates.md
===================================================================
--- config/avr/predicates.md	(revision 221140)
+++ config/avr/predicates.md	(working copy)
@@ -45,7 +45,7 @@ (define_predicate "stack_register_operan
 ;; Return true if OP is a valid address for lower half of I/O space.
 (define_special_predicate "low_io_address_operand"
   (ior (and (match_code "const_int")
-	    (match_test "IN_RANGE (INTVAL (op) - avr_current_arch->sfr_offset,
+	    (match_test "IN_RANGE (INTVAL (op) - avr_arch->sfr_offset,
 				   0, 0x20 - GET_MODE_SIZE (mode))"))
        (and (match_code "symbol_ref")
 	    (match_test "SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_IO_LOW"))))
@@ -53,13 +53,13 @@ (define_special_predicate "low_io_addres
 ;; Return true if OP is a valid address for high half of I/O space.
 (define_predicate "high_io_address_operand"
   (and (match_code "const_int")
-       (match_test "IN_RANGE (INTVAL (op) - avr_current_arch->sfr_offset,
+       (match_test "IN_RANGE (INTVAL (op) - avr_arch->sfr_offset,
                               0x20, 0x3F)")))
 
 ;; Return true if OP is a valid address of I/O space.
 (define_special_predicate "io_address_operand"
   (ior (and (match_code "const_int")
-	    (match_test "IN_RANGE (INTVAL (op) - avr_current_arch->sfr_offset,
+	    (match_test "IN_RANGE (INTVAL (op) - avr_arch->sfr_offset,
 				   0, 0x40 - GET_MODE_SIZE (mode))"))
        (and (match_code "symbol_ref")
 	    (match_test "SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_IO"))))
Index: config/avr/avr-c.c
===================================================================
--- config/avr/avr-c.c	(revision 221140)
+++ config/avr/avr-c.c	(working copy)
@@ -305,8 +305,11 @@ avr_cpu_cpp_builtins (struct cpp_reader
 
   builtin_define_std ("AVR");
 
-  if (avr_current_arch->macro)
-    cpp_define_formatted (pfile, "__AVR_ARCH__=%s", avr_current_arch->macro);
+  /* __AVR_DEVICE_NAME__ and  avr_mcu_types[].macro like __AVR_ATmega8__
+	 are defined by -D command option, see device-specs file.  */
+
+  if (avr_arch->macro)
+    cpp_define_formatted (pfile, "__AVR_ARCH__=%s", avr_arch->macro);
   if (AVR_HAVE_RAMPD)    cpp_define (pfile, "__AVR_HAVE_RAMPD__");
   if (AVR_HAVE_RAMPX)    cpp_define (pfile, "__AVR_HAVE_RAMPX__");
   if (AVR_HAVE_RAMPY)    cpp_define (pfile, "__AVR_HAVE_RAMPY__");
@@ -316,14 +319,14 @@ cpp_define_formatted (pfile, "__AVR_ARCH
   if (AVR_HAVE_MOVW)     cpp_define (pfile, "__AVR_HAVE_MOVW__");
   if (AVR_HAVE_LPMX)     cpp_define (pfile, "__AVR_HAVE_LPMX__");
 
-  if (avr_current_arch->asm_only)
+  if (avr_arch->asm_only)
     cpp_define (pfile, "__AVR_ASM_ONLY__");
   if (AVR_HAVE_MUL)
     {
       cpp_define (pfile, "__AVR_ENHANCED__");
       cpp_define (pfile, "__AVR_HAVE_MUL__");
     }
-  if (avr_current_arch->have_jmp_call)
+  if (avr_arch->have_jmp_call)
     {
       cpp_define (pfile, "__AVR_MEGA__");
       cpp_define (pfile, "__AVR_HAVE_JMP_CALL__");
@@ -347,7 +350,7 @@ start address.  This macro shall be used
       cpp_define (pfile, "__AVR_TINY_PM_BASE_ADDRESS__=0x4000");
     }
 
-  if (avr_current_arch->have_eijmp_eicall)
+  if (AVR_HAVE_EIJMP_EICALL)
     {
       cpp_define (pfile, "__AVR_HAVE_EIJMP_EICALL__");
       cpp_define (pfile, "__AVR_3_BYTE_PC__");
@@ -362,11 +365,10 @@ start address.  This macro shall be used
   else
     cpp_define (pfile, "__AVR_HAVE_16BIT_SP__");
 
-  if (avr_sp8)
-    cpp_define (pfile, "__AVR_SP8__");
-
   if (AVR_HAVE_SPH)
     cpp_define (pfile, "__AVR_HAVE_SPH__");
+  else
+    cpp_define (pfile, "__AVR_SP8__");
 
   if (TARGET_NO_INTERRUPTS)
     cpp_define (pfile, "__NO_INTERRUPTS__");
@@ -375,7 +377,7 @@ start address.  This macro shall be used
     {
       cpp_define (pfile, "__AVR_ERRATA_SKIP__");
 
-      if (avr_current_arch->have_jmp_call)
+      if (AVR_HAVE_JMP_CALL)
         cpp_define (pfile, "__AVR_ERRATA_SKIP_JMP_CALL__");
     }
 
@@ -383,7 +385,7 @@ start address.  This macro shall be used
     cpp_define (pfile, "__AVR_ISA_RMW__");
 
   cpp_define_formatted (pfile, "__AVR_SFR_OFFSET__=0x%x",
-                        avr_current_arch->sfr_offset);
+                        avr_arch->sfr_offset);
 
 #ifdef WITH_AVRLIBC
   cpp_define (pfile, "__WITH_AVRLIBC__");
Index: config/avr/avr.opt
===================================================================
--- config/avr/avr.opt	(revision 221140)
+++ config/avr/avr.opt	(working copy)
@@ -18,21 +18,14 @@
 ; along with GCC; see the file COPYING3.  If not see
 ; <http://www.gnu.org/licenses/>.
 
-HeaderInclude
-config/avr/avr-arch.h
-
 mcall-prologues
 Target Report Mask(CALL_PROLOGUES)
 Use subroutines for function prologues and epilogues
 
 mmcu=
-Target RejectNegative Joined
+Target RejectNegative Joined Var(avr_mmcu) MissingArgError(missing device or architecture after %qs)
 -mmcu=MCU	Select the target MCU
 
-march=
-Target RejectNegative Joined Var(avr_arch_index) Init(ARCH_AVR2) Enum(avr_arch)
--march=ARCH Select target architecture
-
 mn-flash=
 Target RejectNegative Joined Var(avr_n_flash) UInteger Init(-1)
 Set the number of 64 KiB flash segments
Index: config/avr/t-avr
===================================================================
--- config/avr/t-avr	(revision 221141)
+++ config/avr/t-avr	(working copy)
@@ -16,8 +16,14 @@
 # along with GCC; see the file COPYING3.  If not see
 # <http://www.gnu.org/licenses/>.
 
+driver-avr.o: $(srcdir)/config/avr/driver-avr.c \
+  $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+  $(srcdir)/config/avr/avr-arch.h $(TM_H)
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+
 avr-devices.o: $(srcdir)/config/avr/avr-devices.c \
   $(srcdir)/config/avr/avr-mcus.def \
+  $(srcdir)/config/avr/avr-arch.h \
   $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
 
@@ -49,15 +55,9 @@ AVR_MCUS = $(srcdir)/config/avr/avr-mcus
 .PHONY: avr-mcus
 
 avr-mcus: $(srcdir)/config/avr/t-multilib \
-	  $(srcdir)/config/avr/avr-tables.opt \
 	  $(srcdir)/doc/avr-mmcu.texi ; @true
 
-# Make sure that -mmcu= is supported for devices from avr-mcus.def and
-# all -mmcu= values are displayed on the help screen
-$(srcdir)/config/avr/avr-tables.opt: $(srcdir)/config/avr/genopt.sh $(AVR_MCUS)
-	$(SHELL) $< $(AVR_MCUS) > $@
-
-# Make sure that -mmcu= support is in sync with -mmcu= documentation.
+# Make sure that native -mmcu= support is in sync with -mmcu= documentation.
 gen-avr-mmcu-texi$(build_exeext): $(srcdir)/config/avr/gen-avr-mmcu-texi.c \
   $(AVR_MCUS) $(srcdir)/config/avr/avr-devices.c \
   $(srcdir)/config/avr/avr-arch.h
@@ -84,7 +84,7 @@ install-device-specs: s-device-specs ins
 	-rm -rf $(DESTDIR)$(libsubdir)/device-specs
 	mkdir $(DESTDIR)$(libsubdir)/device-specs
 	-for file in device-specs/*; do \
-	$(INSTALL_PROGRAM) $${file} $(DESTDIR)$(libsubdir)/$${file}; \
+		$(INSTALL_DATA) $${file} $(DESTDIR)$(libsubdir)/$${file}; \
 	done
 
 # Map -mmcu= to the right multilib variant
Index: config/avr/gen-avr-mmcu-specs.c
===================================================================
--- config/avr/gen-avr-mmcu-specs.c	(revision 221141)
+++ config/avr/gen-avr-mmcu-specs.c	(working copy)
@@ -23,20 +23,31 @@
 
 #define IN_GEN_AVR_MMCU_TEXI
 
-#include "avr-arch.h"
 #include "avr-devices.c"
 
+// Get rid of "defaults.h".  We just need tm.h for `WITH_AVRLIBS' and
+// and `WITH_RTEMS'.  */
 #define GCC_DEFAULTS_H
 
 #include "tm.h"
 
+// Mimic the include order as specified in config.gcc::tm_file.
+
+#include "specs.h"
+
 #if defined (WITH_AVRLIBC)
-static const bool with_avrlibc = true;
-#else
-static const bool with_avrlibc = false;
-#endif /* WITH_AVRLIBC */
+#include "avrlibc.h"
+#endif
+
+#if defined (WITH_RTEMS)
+#include "../rtems.h"
+#include "rtems.h"
+#endif
 
 
+#define SPECFILE_DOC_URL                                \
+  "http://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html"
+
 /* Return true iff STR starts with PREFIX.  */
 
 static bool
@@ -46,17 +57,41 @@ str_prefix_p (const char *str, const cha
 }
 
 
+static const char header[] =
+  "#\n"
+  "# Generated by   : ./gcc/config/avr/gen-avr-mmcu-specs.c\n"
+  "# Generated from : ./gcc/config/gcc.c\n"
+  "#                  ./gcc/config/avr/specs.h\n"
+#if defined (WITH_RTEMS)
+  "#                  ./gcc/config/rtems.h\n"
+  "#                  ./gcc/config/avr/rtems.h\n"
+#endif
+#if defined (WITH_AVRLIBC)
+  "#                  ./gcc/config/avr/avrlibc.h\n"
+#endif
+  "# Used by        : avr-gcc compiler driver\n"
+  "# Used for       : building command options for sub-processes\n"
+  "#\n"
+  "# See <" SPECFILE_DOC_URL ">\n"
+  "# for a documentation of spec files.\n"
+  "\n";
+
+
 static void
 print_mcu (const avr_mcu_t *mcu)
 {
   const char *sp8_spec;
   const avr_mcu_t *arch_mcu;
+  const avr_arch_t *arch;
+  enum avr_arch_id arch_id = mcu->arch_id;
 
   for (arch_mcu = mcu; arch_mcu->macro; )
     arch_mcu--;
-  if (arch_mcu->arch != mcu->arch)
+  if (arch_mcu->arch_id != arch_id)
     exit (EXIT_FAILURE);
 
+  arch = &avr_arch_types[arch_id];
+
   char name[100];
   if (snprintf (name, sizeof name, "specs-%s", mcu->name) >= (int) sizeof name)
    exit (EXIT_FAILURE);
@@ -66,9 +101,12 @@ for (arch_mcu = mcu; arch_mcu->macro; )
   bool errata_skip = 0 != (mcu->dev_attribute & AVR_ERRATA_SKIP);
   bool rmw = 0 != (mcu->dev_attribute & AVR_ISA_RMW);
   bool sp8 = 0 != (mcu->dev_attribute & AVR_SHORT_SP);
+  bool is_arch = NULL == mcu->macro;
+  bool is_device = ! is_arch;
 
-  if (mcu->macro == NULL
-      && (mcu->arch == ARCH_AVR2 || mcu->arch == ARCH_AVR25))
+  if (is_arch
+      && (ARCH_AVR2 == arch_id
+          || ARCH_AVR25 == arch_id))
     {
       // Leave "avr2" and "avr25" alone.  These two architectures are
       // the only ones that mix devices with 8-bit SP and 16-bit SP.
@@ -76,97 +114,124 @@ if (mcu->macro == NULL
     }
   else
     {
-      sp8_spec = sp8
-        ? " -msp8"
-        : " %<msp8";
+      sp8_spec = sp8 ? "-msp8" :"%<msp8";
     }
 
-  const char *errata_skip_spec = errata_skip
-    ? " %{!mno-skip-bug:-mskip-bug}"
-    : " %{!mskip-bug:-mno-skip-bug}";
-
-  const char *rmw_spec = rmw
-    ? " %{!mno-rmw: -mrmw}"
-    : " %{mrmw}";
-
-  const char *arch_name = avr_arch_types[mcu->arch].arch_name;
-
-  fprintf (f, "*self_spec:\n"
-           " %%{!march=*:-march=%s}"
-           " %s\n\n", arch_name, sp8_spec);
-
-  if (mcu->macro)
-    fprintf (f, "*cpp:\n-D__AVR_DEV_LIB_NAME__=%s -D%s "
-	     "-D__AVR_DEVICE_NAME__=%s\n\n",
-	     mcu->library_name, mcu->macro, mcu->name);
+  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)\n",
+             mcu->name, arch->name, sp8 ? 8 : 16);
+  fprintf (f, "%s\n", header);
+
+  // avrlibc-specific specs for linking / thelinker.
+
+  fprintf (f, "*avrlibc_startfile:\n");
+  if (is_device)
+    fprintf (f, "\tdev/%s/crt1.o%%s", mcu->name);
+  fprintf (f, "\n\n");
 
-  fprintf (f, "*cc1:\n%s%s", errata_skip_spec, rmw_spec);
-  if (mcu->n_flash != arch_mcu->n_flash)
-    fprintf (f, " %%{!mn-flash:-mn-flash=%d}", mcu->n_flash);
-  fprintf (f, "\n\n");
-
-  fprintf (f, "*cc1plus:\n%s%s ", errata_skip_spec, rmw_spec);
-  if (mcu->n_flash != arch_mcu->n_flash)
-    fprintf (f, " %%{!mn-flash:-mn-flash=%d}", mcu->n_flash);
-  fprintf (f, (" %%{!frtti: -fno-rtti}"
-               " %%{!fenforce-eh-specs: -fno-enforce-eh-specs}"
-               " %%{!fexceptions: -fno-exceptions}\n\n"));
-
-  fprintf (f, "*asm:\n"
-           " %%{march=*:-mmcu=%%*}"
-           " %%{mrelax: --mlink-relax}"
-           " %s%s\n\n", rmw_spec, (errata_skip
-                                  ? " %{mno-skip-bug}"
-                                  : " %{!mskip-bug:-mno-skip-bug}"));
-  fprintf (f, "*link:\n"
-           " %%{mrelax:--relax");
-  {
-    int wrap_k =
-      str_prefix_p (mcu->name, "at90usb8") ? 8
-      : str_prefix_p (mcu->name, "atmega16") ? 16
-      : (str_prefix_p (mcu->name, "atmega32")
-         || str_prefix_p (mcu->name, "at90can32")) ? 32
-      : (str_prefix_p (mcu->name, "atmega64")
-        || str_prefix_p (mcu->name, "at90can64")
-        || str_prefix_p (mcu->name, "at90usb64")) ? 64
-      : 0;
-
-    if (wrap_k)
-      fprintf (f, " %%{mpmem-wrap-around: --pmem-wrap-around=%dk}", wrap_k);
-  }
-  fprintf (f, "}"
-           " %%{march=*:-m%%*}");
+  fprintf (f, "*avrlibc_devicelib:\n");
+  if (is_device)
+    fprintf (f, "\tdev/%s/libdev.a%%s", mcu->name);
+  fprintf (f, "\n\n");
 
-  if (mcu->data_section_start
-      != avr_arch_types[mcu->arch].default_data_section_start)
-    fprintf (f, " -Tdata 0x%lX", 0x800000UL + mcu->data_section_start);
+  // avr-specific specs for the compilation / the compiler proper.
 
-  if (mcu->text_section_start != 0x0)
-    fprintf (f, " -Ttext 0x%lX", 0UL + mcu->text_section_start);
+  fprintf (f, "*cc1_n_flash:\n"
+           "\t%%{!mn-flash=*:-mn-flash=%d}\n\n", mcu->n_flash);
 
-  fprintf (f, " %%{shared:%%eshared is not supported}\n\n");
+  fprintf (f, "*cc1_rmw:\n%s\n\n", rmw
+           ? "\t%{!mno-rmw: -mrmw}"
+           : "\t%{mrmw}");
 
-  bool has_libs = mcu->arch != ARCH_AVR1;
+  fprintf (f, "*cc1_errata_skip:\n%s\n\n", errata_skip
+           ? "\t%{!mno-skip-bug: -mskip-bug}"
+           : "\t%{!mskip-bug: -mno-skip-bug}");
 
-  fprintf (f, "*lib:\n");
-  if (has_libs)
-    {
-      fprintf (f, "-lc");
-      if (with_avrlibc
-          && mcu->macro)
-	fprintf (f, " dev/%s/libdev.a%%s", mcu->name);
-    }
+  // avr-specific specs for assembling / the assembler.
+
+  fprintf (f, "*asm_arch:\n\t-mmcu=%s\n\n", arch->name);
+
+  fprintf (f, "*asm_relax:\n\t%s\n\n", ASM_RELAX_SPEC);
+
+  fprintf (f, "*asm_rmw:\n%s\n\n", rmw
+           ? "\t%{!mno-rmw: -mrmw}"
+           : "\t%{mrmw}");
+
+  fprintf (f, "*asm_errata_skip:\n%s\n\n", errata_skip
+           ? "\t%{mno-skip-bug}"
+           : "\t%{!mskip-bug: -mno-skip-bug}");
+
+  // avr-specific specs for linking / the linker.
+
+  int wrap_k =
+    str_prefix_p (mcu->name, "at90usb8") ? 8
+    : str_prefix_p (mcu->name, "atmega16") ? 16
+    : (str_prefix_p (mcu->name, "atmega32")
+       || str_prefix_p (mcu->name, "at90can32")) ? 32
+    : (str_prefix_p (mcu->name, "atmega64")
+       || str_prefix_p (mcu->name, "at90can64")
+       || str_prefix_p (mcu->name, "at90usb64")) ? 64
+    : 0;
+
+  fprintf (f, "*link_pmem_wrap:\n");
+  if (wrap_k)
+    fprintf (f, "\t%%{mpmem-wrap-around: --pmem-wrap-around=%dk}", wrap_k);
+  fprintf (f, "\n\n");
+
+  fprintf (f, "*link_relax:\n\t%s\n\n", LINK_RELAX_SPEC);
+
+  fprintf (f, "*link_arch:\n\t%s\n\n", LINK_ARCH_SPEC);
+
+  fprintf (f, "*link_data_start:\n");
+  if (mcu->data_section_start
+      != arch->default_data_section_start)
+    fprintf (f, "\t-Tdata 0x%lX", 0x800000UL + mcu->data_section_start);
+  fprintf (f, "\n\n");
+
+  fprintf (f, "*link_text_start:\n");
+  if (mcu->text_section_start != 0x0)
+    fprintf (f, "\t-Ttext 0x%lX", 0UL + mcu->text_section_start);
   fprintf (f, "\n\n");
 
-  fprintf (f, "*libgcc:\n");
-  if (has_libs)
-    fprintf (f, with_avrlibc
-             ? "-lgcc -lm"
-             : "-lgcc");
+  // Default specs.  Rewritten to the device-specific specs file so
+  // they can be adjusted as needed.
+     
+  bool has_libs = arch_id != ARCH_AVR1;
+
+  fprintf (f, "*self_spec:\n");
+  if (is_device)
+    fprintf (f, "\t%%{!mmcu=avr*: %%<mmcu=* -mmcu=%s} ", arch->name);
+  fprintf (f, "%s\n\n", sp8_spec);
+
+  fprintf (f, "*cpp:\n");
+  if (is_device)
+    fprintf (f,"\t-D__AVR_DEV_LIB_NAME__=%s"
+             " -D%s"
+	     " -D__AVR_DEVICE_NAME__=%s",
+	     mcu->library_name, mcu->macro, mcu->name);
   fprintf (f, "\n\n");
 
-  fprintf (f, "*startfile:\n"
-           "dev/%s/crt1.o%%s\n\n", mcu->name);
+  fprintf (f, "*cc1:\n\t%s\n\n", CC1_SPEC);
+
+  fprintf (f, "*cc1plus:\n\t%s\n\n", CC1PLUS_SPEC);
+
+  fprintf (f, "*asm:\n\t%s\n\n", ASM_SPEC);
+
+  fprintf (f, "*link:\n\t%s\n\n", LINK_SPEC);
+
+  fprintf (f, "*lib:\n\t%s\n\n", has_libs ? LIB_SPEC : "");
+
+  fprintf (f, "*libgcc:\n\t%s\n\n", has_libs ? LIBGCC_SPEC : "");
+
+  fprintf (f, "*startfile:\n\t%s\n\n", STARTFILE_SPEC);
+
+  fprintf (f, "*endfile:\n%s\n\n", ENDFILE_SPEC);
+
+  fprintf (f, "# End of file\n");
 }
 
 
Index: config/avr/avr-tables.opt
===================================================================
--- config/avr/avr-tables.opt	(revision 221140)
+++ config/avr/avr-tables.opt	(working copy)
@@ -1,73 +0,0 @@
-; -*- buffer-read-only: t -*-
-; Generated automatically by genopt.sh from avr-mcus.def.
-
-; Copyright (C) 2011-2015 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 3, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-; for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING3.  If not see
-; <http://www.gnu.org/licenses/>.
-
-Enum
-Name(avr_arch) Type(enum avr_arch)
-Known MCU architectures:
-
-EnumValue
-Enum(avr_arch) String(avr2) Value(ARCH_AVR2)
-
-EnumValue
-Enum(avr_arch) String(avr25) Value(ARCH_AVR25)
-
-EnumValue
-Enum(avr_arch) String(avr3) Value(ARCH_AVR3)
-
-EnumValue
-Enum(avr_arch) String(avr31) Value(ARCH_AVR31)
-
-EnumValue
-Enum(avr_arch) String(avr35) Value(ARCH_AVR35)
-
-EnumValue
-Enum(avr_arch) String(avr4) Value(ARCH_AVR4)
-
-EnumValue
-Enum(avr_arch) String(avr5) Value(ARCH_AVR5)
-
-EnumValue
-Enum(avr_arch) String(avr51) Value(ARCH_AVR51)
-
-EnumValue
-Enum(avr_arch) String(avr6) Value(ARCH_AVR6)
-
-EnumValue
-Enum(avr_arch) String(avrxmega2) Value(ARCH_AVRXMEGA2)
-
-EnumValue
-Enum(avr_arch) String(avrxmega4) Value(ARCH_AVRXMEGA4)
-
-EnumValue
-Enum(avr_arch) String(avrxmega5) Value(ARCH_AVRXMEGA5)
-
-EnumValue
-Enum(avr_arch) String(avrxmega6) Value(ARCH_AVRXMEGA6)
-
-EnumValue
-Enum(avr_arch) String(avrxmega7) Value(ARCH_AVRXMEGA7)
-
-EnumValue
-Enum(avr_arch) String(avrtiny) Value(ARCH_AVRTINY)
-
-EnumValue
-Enum(avr_arch) String(avr1) Value(ARCH_AVR1)
-
Index: config/avr/driver-avr.c
===================================================================
--- config/avr/driver-avr.c	(revision 0)
+++ config/avr/driver-avr.c	(revision 0)
@@ -0,0 +1,124 @@
+/* Subroutines for the gcc driver.
+   Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Contributed by Georg-Johann Lay <avr@gjlay.de>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "diagnostic.h"
+#include "tm.h"
+
+static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
+
+static const char specfiles_doc_url[] =
+  "http://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html";
+
+
+static const char*
+avr_diagnose_devicespecs_error (const char *mcu, const char *filename)
+{
+  error ("cannot access device-specs for %qs expected at %qs",
+         mcu, filename);
+
+  // Inform about natively supported devices and cores.
+
+  if (strncmp (mcu, "avr", strlen ("avr")))
+    avr_inform_devices ();
+
+  avr_inform_core_architectures ();
+
+  inform (input_location, "you can provide your own specs files, "
+          "see <%s> for details", specfiles_doc_url);
+
+  return "";
+}
+
+
+/* Implement spec function `device-specs-file´.
+
+   Compose -specs=<specs-file-name>.  If everything went well then argv[0]
+   is the inflated specs directory and argv[1] is a device or core name as
+   supplied to -mmcu=*.  */
+
+const char*
+avr_devicespecs_file (int argc, const char **argv)
+{
+  char *specfile_name;
+  const char *mmcu = NULL;
+
+#ifdef DEBUG_SPECS
+  if (verbose_flag)
+    fnotice (stderr, "Running spec function '%s' with %d args\n\n",
+             __FUNCTION__, argc);
+#endif
+
+  switch (argc)
+    {
+    case 0:
+      fatal_error (input_location,
+                   "bad usage of spec function %qs", "device-specs-file");
+      return "";
+
+    case 1:
+      mmcu = AVR_MMCU_DEFAULT;
+      break;
+
+    case 2:
+      mmcu = argv[1];
+      break;
+
+    default:
+      error ("specified option %qs more than once", "-mmcu=");
+      return "";
+    }
+
+  specfile_name = concat (argv[0], dir_separator_str, "specs-", mmcu, NULL);
+
+#ifdef DEBUG_SPECS
+  if (verbose_flag)
+    fnotice (stderr, "'%s': mmcu='%s'\n'%s': specfile='%s'\n\n",
+             __FUNCTION__, mmcu, __FUNCTION__, specfile_name);
+#endif
+
+  // Filter out silly -mmcu= arguments like "foo bar".
+
+  for (const char *s = mmcu; *s; s++)
+    if (!ISALNUM (*s)
+        && '-' != *s
+        && '_' != *s)
+      {
+        error ("strange device name %qs after %qs: bad character %qc",
+               mmcu, "-mmcu=", *s);
+        return "";
+      }
+
+  if (/* When building / configuring the compiler we might get a relative path
+         as supplied by "-B.".  Assume that the specs file exists and MCU is
+         a core, not a proper device then, i.e. we have "-mmcu=avr*".  */
+      (0 == strncmp (mmcu, "avr", strlen ("avr"))
+       && specfile_name[0] == '.')
+      /* vanilla */
+      || (IS_ABSOLUTE_PATH (specfile_name)
+          && !access (specfile_name, R_OK)))
+    {
+      return concat ("-specs=", specfile_name, NULL);
+    }
+
+  return avr_diagnose_devicespecs_error (mmcu, specfile_name);
+}
Index: config/avr/specs.h
===================================================================
--- config/avr/specs.h	(revision 0)
+++ config/avr/specs.h	(revision 0)
@@ -0,0 +1,77 @@
+/* Specs definitions for Atmel AVR back end.
+
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
+   Contributed by Georg-Johann Lay (avr@gjlay.de)
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+/* Default specs layout.  The actual definitions might be superseeded
+   by device- or OS- specific files, like avrlibc.h, ../rtems.h, etc.
+   The specs are repeated in the device specs files.  Subspecs are
+   specs known to GCC or specs defined in the device specs files.  */
+
+
+#undef  CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC                      \
+  "%(cpp)"
+
+#undef  CC1_SPEC
+#define CC1_SPEC                                \
+  "%(cc1_n_flash) "                             \
+  "%(cc1_errata_skip) "                         \
+  "%(cc1_rmw) "
+
+#undef  CC1PLUS_SPEC
+#define CC1PLUS_SPEC                                    \
+  "%(cc1) "                                             \
+  "%{!frtti:-fno-rtti} "                                \
+  "%{!fenforce-eh-specs:-fno-enforce-eh-specs} "        \
+  "%{!fexceptions:-fno-exceptions} "
+
+#define ASM_RELAX_SPEC                          \
+  "%{mrelax:--mlink-relax} "
+
+#undef  ASM_SPEC
+#define ASM_SPEC                                \
+  "%(asm_arch) "                                \
+  "%(asm_relax) "                               \
+  "%(asm_rmw) "                                 \
+  "%(asm_errata_skip) "
+
+#define LINK_ARCH_SPEC                          \
+  "%{mmcu=*:-m%*} "
+
+#define LINK_RELAX_SPEC                         \
+  "%{mrelax:--relax %(link_pmem_wrap)} "
+
+#undef  LINK_SPEC
+#define LINK_SPEC                               \
+  "%(link_arch) "                               \
+  "%(link_data_start) "                         \
+  "%(link_text_start) "                         \
+  "%(link_relax) "                              \
+  "%{shared:%eshared is not supported} "
+
+#undef  LIB_SPEC
+#define LIB_SPEC " -lc "
+
+#undef  LIBGCC_SPEC
+#define LIBGCC_SPEC " -lgcc "
+
+#define STARTFILE_SPEC ""
+#define ENDFILE_SPEC ""
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(revision 221143)
+++ config/avr/avr.c	(working copy)
@@ -234,10 +234,7 @@ static GTY(()) rtx xstring_empty;
 static GTY(()) rtx xstring_e;
 
 /* Current architecture.  */
-const avr_arch_t *avr_current_arch;
-
-/* Current device.  */
-const avr_mcu_t *avr_current_device;
+const avr_arch_t *avr_arch;
 
 /* Section to put switch tables in.  */
 static GTY(()) section *progmem_swtable_section;
@@ -380,6 +377,49 @@ avr_register_passes (void)
 }
 
 
+/* Set `avr_arch' as specified by `-mmcu='.
+   Return true on success.  */
+
+static bool
+avr_set_core_architecture (void)
+{
+  /* Search for mcu core architecture.  */
+
+  if (!avr_mmcu)
+    avr_mmcu = AVR_MMCU_DEFAULT;
+
+  avr_arch = &avr_arch_types[0];
+
+  for (const avr_mcu_t *mcu = avr_mcu_types; ; mcu++)
+    {
+      if (NULL == mcu->name)
+        {
+          /* Reached the end of `avr_mcu_types'.  This should actually never
+             happen as options are provided by device-specs.  It could be a
+             typo in a device-specs or calling the compiler proper directly
+             with -mmcu=<device>. */
+
+          error ("unknown core architecture %qs specified with %qs",
+                 avr_mmcu, "-mmcu=");
+          avr_inform_core_architectures ();
+          break;
+        }
+      else if (0 == strcmp (mcu->name, avr_mmcu)
+               // Is this a proper architecture ? 
+               && NULL == mcu->macro)
+        {
+          avr_arch = &avr_arch_types[mcu->arch_id];
+          if (avr_n_flash < 0)
+            avr_n_flash = mcu->n_flash;
+
+          return true;
+        }
+    }
+
+  return false;
+}
+
+
 /* Implement `TARGET_OPTION_OVERRIDE'.  */
 
 static void
@@ -424,39 +464,24 @@ avr_option_override (void)
   if (flag_pie == 2)
     warning (OPT_fPIE, "-fPIE is not supported");
 
-  /* Search for mcu arch.
-     ??? We should probably just put the architecture-default device
-     settings in the architecture struct and remove any notion of a current
-     device from gcc.  */
-
-  for (avr_current_device = avr_mcu_types; ; avr_current_device++)
-    {
-      if (!avr_current_device->name)
-        fatal_error (input_location, "mcu not found");
-      if (!avr_current_device->macro
-          && avr_current_device->arch == avr_arch_index)
-        break;
-    }
-
-  avr_current_arch = &avr_arch_types[avr_arch_index];
-  if (avr_n_flash < 0)
-    avr_n_flash = avr_current_device->n_flash;
+  if (!avr_set_core_architecture())
+    return;
 
   /* RAM addresses of some SFRs common to all devices in respective arch. */
 
   /* SREG: Status Register containing flags like I (global IRQ) */
-  avr_addr.sreg = 0x3F + avr_current_arch->sfr_offset;
+  avr_addr.sreg = 0x3F + avr_arch->sfr_offset;
 
   /* RAMPZ: Address' high part when loading via ELPM */
-  avr_addr.rampz = 0x3B + avr_current_arch->sfr_offset;
+  avr_addr.rampz = 0x3B + avr_arch->sfr_offset;
 
-  avr_addr.rampy = 0x3A + avr_current_arch->sfr_offset;
-  avr_addr.rampx = 0x39 + avr_current_arch->sfr_offset;
-  avr_addr.rampd = 0x38 + avr_current_arch->sfr_offset;
-  avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_current_arch->sfr_offset;
+  avr_addr.rampy = 0x3A + avr_arch->sfr_offset;
+  avr_addr.rampx = 0x39 + avr_arch->sfr_offset;
+  avr_addr.rampd = 0x38 + avr_arch->sfr_offset;
+  avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_arch->sfr_offset;
 
   /* SP: Stack Pointer (SP_H:SP_L) */
-  avr_addr.sp_l = 0x3D + avr_current_arch->sfr_offset;
+  avr_addr.sp_l = 0x3D + avr_arch->sfr_offset;
   avr_addr.sp_h = avr_addr.sp_l + 1;
 
   init_machine_status = avr_init_machine_status;
@@ -2328,7 +2353,7 @@ avr_print_operand (FILE *file, rtx x, in
           else
             {
               fprintf (file, HOST_WIDE_INT_PRINT_HEX,
-                       ival - avr_current_arch->sfr_offset);
+                       ival - avr_arch->sfr_offset);
             }
         }
       else
@@ -2396,7 +2421,7 @@ avr_print_operand (FILE *file, rtx x, in
     {
       if (GET_CODE (x) == SYMBOL_REF && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO))
 	avr_print_operand_address
-	  (file, plus_constant (HImode, x, -avr_current_arch->sfr_offset));
+	  (file, plus_constant (HImode, x, -avr_arch->sfr_offset));
       else
 	fatal_insn ("bad address, not an I/O address:", x);
     }
@@ -9246,12 +9271,11 @@ avr_pgm_check_var_decl (tree node)
       if (avr_addrspace[as].segment >= avr_n_flash)
         {
           if (TYPE_P (node))
-            error ("%qT uses address space %qs beyond flash of %qs",
-                   node, avr_addrspace[as].name, avr_current_device->name);
+            error ("%qT uses address space %qs beyond flash of %d KiB",
+                   node, avr_addrspace[as].name, avr_n_flash);
           else
-            error ("%s %q+D uses address space %qs beyond flash of %qs",
-                   reason, node, avr_addrspace[as].name,
-                   avr_current_device->name);
+            error ("%s %q+D uses address space %qs beyond flash of %d KiB",
+                   reason, node, avr_addrspace[as].name, avr_n_flash);
         }
       else
         {
@@ -9297,15 +9321,14 @@ avr_insert_attributes (tree node, tree *
 
       if (avr_addrspace[as].segment >= avr_n_flash)
         {
-          error ("variable %q+D located in address space %qs"
-                 " beyond flash of %qs",
-                 node, avr_addrspace[as].name, avr_current_device->name);
+          error ("variable %q+D located in address space %qs beyond flash "
+                 "of %d KiB", node, avr_addrspace[as].name, avr_n_flash);
         }
       else if (!AVR_HAVE_LPM && avr_addrspace[as].pointer_size > 2)
 	{
           error ("variable %q+D located in address space %qs"
-                 " which is not supported by %qs",
-                 node, avr_addrspace[as].name, avr_current_arch->arch_name);
+                 " which is not supported for architecture %qs",
+                 node, avr_addrspace[as].name, avr_arch->name);
 	}
 
       if (!TYPE_READONLY (node0)
@@ -9723,10 +9746,10 @@ avr_asm_select_section (tree decl, int r
 static void
 avr_file_start (void)
 {
-  int sfr_offset = avr_current_arch->sfr_offset;
+  int sfr_offset = avr_arch->sfr_offset;
 
-  if (avr_current_arch->asm_only)
-    error ("MCU %qs supported for assembler only", avr_current_device->name);
+  if (avr_arch->asm_only)
+    error ("architecture %qs supported for assembler only", avr_mmcu);
 
   default_file_start ();
 
Index: config/avr/avr.h
===================================================================
--- config/avr/avr.h	(revision 221141)
+++ config/avr/avr.h	(working copy)
@@ -60,19 +60,19 @@ enum
 
 #define TARGET_CPU_CPP_BUILTINS()	avr_cpu_cpp_builtins (pfile)
 
-#define AVR_HAVE_JMP_CALL (avr_current_arch->have_jmp_call)
-#define AVR_HAVE_MUL (avr_current_arch->have_mul)
-#define AVR_HAVE_MOVW (avr_current_arch->have_movw_lpmx)
+#define AVR_HAVE_JMP_CALL (avr_arch->have_jmp_call)
+#define AVR_HAVE_MUL (avr_arch->have_mul)
+#define AVR_HAVE_MOVW (avr_arch->have_movw_lpmx)
 #define AVR_HAVE_LPM (!AVR_TINY)
-#define AVR_HAVE_LPMX (avr_current_arch->have_movw_lpmx)
-#define AVR_HAVE_ELPM (avr_current_arch->have_elpm)
-#define AVR_HAVE_ELPMX (avr_current_arch->have_elpmx)
-#define AVR_HAVE_RAMPD (avr_current_arch->have_rampd)
-#define AVR_HAVE_RAMPX (avr_current_arch->have_rampd)
-#define AVR_HAVE_RAMPY (avr_current_arch->have_rampd)
-#define AVR_HAVE_RAMPZ (avr_current_arch->have_elpm             \
-                        || avr_current_arch->have_rampd)
-#define AVR_HAVE_EIJMP_EICALL (avr_current_arch->have_eijmp_eicall)
+#define AVR_HAVE_LPMX (avr_arch->have_movw_lpmx)
+#define AVR_HAVE_ELPM (avr_arch->have_elpm)
+#define AVR_HAVE_ELPMX (avr_arch->have_elpmx)
+#define AVR_HAVE_RAMPD (avr_arch->have_rampd)
+#define AVR_HAVE_RAMPX (avr_arch->have_rampd)
+#define AVR_HAVE_RAMPY (avr_arch->have_rampd)
+#define AVR_HAVE_RAMPZ (avr_arch->have_elpm             \
+                        || avr_arch->have_rampd)
+#define AVR_HAVE_EIJMP_EICALL (avr_arch->have_eijmp_eicall)
 
 /* Handling of 8-bit SP versus 16-bit SP is as follows:
 
@@ -90,17 +90,16 @@ These two properties are reflected by bu
    __AVR_HAVE_8BIT_SP__ and __AVR_HAVE_16BIT_SP__.  During multilib generation
    there is always __AVR_SP8__ == __AVR_HAVE_8BIT_SP__.  */
 
-#define AVR_HAVE_8BIT_SP                                 \
-  ((avr_current_device->dev_attribute & AVR_SHORT_SP)    \
-   || TARGET_TINY_STACK || avr_sp8)
+#define AVR_HAVE_8BIT_SP                        \
+  (TARGET_TINY_STACK || avr_sp8)
 
 #define AVR_HAVE_SPH (!avr_sp8)
 
 #define AVR_2_BYTE_PC (!AVR_HAVE_EIJMP_EICALL)
 #define AVR_3_BYTE_PC (AVR_HAVE_EIJMP_EICALL)
 
-#define AVR_XMEGA (avr_current_arch->xmega_p)
-#define AVR_TINY  (avr_current_arch->tiny_p)
+#define AVR_XMEGA (avr_arch->xmega_p)
+#define AVR_TINY  (avr_arch->tiny_p)
 
 #define BITS_BIG_ENDIAN 0
 #define BYTES_BIG_ENDIAN 0
@@ -492,25 +491,24 @@ typedef struct avr_args
 #define ADJUST_INSN_LENGTH(INSN, LENGTH)                \
     (LENGTH = avr_adjust_insn_length (INSN, LENGTH))
 
-#define DRIVER_SELF_SPECS                                       \
-  " %{!mmcu=*:%{!march=*:-specs=device-specs/specs-avr2%s} "    \
-  "           %{march=*:-specs=device-specs/specs-%*%s}} "      \
-  " %{mmcu=*:-specs=device-specs/specs-%*%s %<mmcu=*} "
-
-/* We want cc1plus used as a preprocessor to pick up the cpp spec from the
-   per-device spec files  */
-#define CPLUSPLUS_CPP_SPEC "%(cpp)"
+extern const char *avr_devicespecs_file (int, const char**);
 
-#define LIBSTDCXX "gcc"
-/* No libstdc++ for now.  Empty string doesn't work.  */
+#define EXTRA_SPEC_FUNCTIONS                                   \
+  { "device-specs-file", avr_devicespecs_file },
 
-/* The actual definition will come from the device-specific spec file.  */
-#define STARTFILE_SPEC ""
+/* Driver self specs has lmited functionality w.r.t. '%s' for dynamic specs.
+   Apply '%s' to a static string to inflate the file (directory) name which
+   is used to diagnose problems with reading the specs file.  */
+
+#undef  DRIVER_SELF_SPECS
+#define DRIVER_SELF_SPECS                       \
+  " %:device-specs-file(device-specs%s %{mmcu=*:%*})"
 
-#define ENDFILE_SPEC ""
+/* No libstdc++ for now.  Empty string doesn't work.  */
+#define LIBSTDCXX "gcc"
 
-/* This is the default without any -mmcu=* option (AT90S*).  */
-#define MULTILIB_DEFAULTS { "mmcu=avr2" }
+/* This is the default without any -mmcu=* option.  */
+#define MULTILIB_DEFAULTS { "mmcu=" AVR_MMCU_DEFAULT }
 
 #define TEST_HARD_REG_CLASS(CLASS, REGNO) \
   TEST_HARD_REG_BIT (reg_class_contents[ (int) (CLASS)], REGNO)

  reply	other threads:[~2015-03-09 16:03 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-02 19:40 [patch,avr]: " Georg-Johann Lay
2015-03-03  7:46 ` Denis Chertykov
2015-03-03 13:20 ` Senthil Kumar Selvaraj
2015-03-09 16:03   ` Georg-Johann Lay [this message]
2015-03-09 20:00     ` [patch,avr]: Part2: " Denis Chertykov
2015-03-10 15:02       ` [patch,avr]: Part3 and 4: " Georg-Johann Lay
2015-03-11 18:18         ` Denis Chertykov
2015-03-16 18:18           ` [patch,avr]: Part5: " Georg-Johann Lay
2015-03-17  6:37             ` Denis Chertykov
2015-04-06  9:54     ` [patch,avr]: Part2: " Sivanupandi, Pitchumani
2015-04-07 12:34       ` Georg-Johann Lay
2015-04-08  8:28         ` Denis Chertykov
2015-04-08 11:25           ` Georg-Johann Lay
2015-04-09 10:59             ` Sivanupandi, Pitchumani
2015-04-09 11:23               ` Georg-Johann Lay
2015-04-09 12:55                 ` Sivanupandi, Pitchumani
2015-04-15 10:17                   ` Sivanupandi, Pitchumani
2015-04-17 14:03                     ` [patch,avr,installed] ad PR65296: Adjust specs to new avr-libc layout as of #44574 Georg-Johann Lay
2015-04-17 14:43                       ` Denis Chertykov
2015-04-17 15:32                         ` Georg-Johann Lay
2015-04-17 16:46                           ` Denis Chertykov
2015-04-09 11:44               ` [patch,avr,committed]: ad PR65296: work around device-specs file + dejagnu for c++ Georg-Johann Lay
2015-03-09 16:21   ` [patch,avr]: Fix various problems with specs and specs file generation Georg-Johann Lay

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54FDC417.1000008@gjlay.de \
    --to=avr@gjlay.de \
    --cc=chertykov@gmail.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=joerg_wunsch@uriah.heep.sax.de \
    --cc=joern.rennecke@embecosm.com \
    --cc=senthil_kumar.selvaraj@atmel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).