diff mbox

RFA: AVR: add infrastructure for device packages

Message ID CAMqJFConoc-yRZDKCHK=Wpb58gpc74f_SfrhxN5JNvwyPKEinw@mail.gmail.com
State New
Headers show

Commit Message

Joern Rennecke Oct. 8, 2014, 5:50 p.m. UTC
As the steering commitee still hasn't spoken on the maintainership issue,
apparently this still has to go the write-after-approval route.

The purpose of this patch is to make it possible to add support for new
devices (MCUs) to the AVR toolchain, without having to re-build the
entire toolchain.  This capability is desirable because new MCUs are added
fairly frequently.

There are multiple parts of the toolchain involved.
gcc changes multilibbing to key off the new -march option; the -mmcu option
is translated via DRIVER_SELF_SPECS into a -specs option, and the
individual spec files contain the required settings like -march, and various
more detailed settings (some of which are for new options).

binutils provides new relocation and relaxation facilities to allow referring
symbolically to symbol differences and/or I/O addresses.
avr-libc puts the device-specifc header settings in avr/io*.h, and a few
small device-specific likbale functions into a device-specific library.

The other toolchain parts are staged here:
git@github.com:embecosm/avr-binutils-gdb.git avr-mainline
git@github.com:embecosm/avr-libc.git avr-libc-embecosm-mainline


Attached is the GCC patch for the basic device package infrastructure.
OK to apply?


I intend to send the patch sets for avrtiny support (modified for device
package support) and for libstdc++-v3 support next, each building on the
previous patch set.  The avrtiny support is also dependent on the
caller-save patch https://gcc.gnu.org/ml/gcc-patches/2014-10/msg00420.html ,
as avr-libc won't build otherwise.
2014-10-08  Joern Rennecke  <joern.rennecke@embecosm.com>

	* config/avr/avr.opt (mmcu=): Change to have a string value.
	(mn-flash=, mskip-bug, march=, mrmw): New options.
	(HeaderInclude): New.
	(mmcu=): Remove Var / Init clauses.
	* config/avr/avr.h (DRIVER_SELF_SPECS): Translate -mmcu into a
	-specs option.
	(SYMBOL_FLAG_IO, SYMBOL_FLAG_ADDRESS): Define.
	(ASM_OUTPUT_ALIGNED_BSS): Use avr_asm_asm_output_aligned_bss.
	(SYMBOL_FLAG_IO_LOW): Define.
	(avr_device_to_as, avr_device_to_ld): Don't declare.
	(avr_device_to_data_start, avr_device_to_startfiles): Likewise.
	(avr_device_to_devicelib, avr_device_to_sp8): Likewise.
	(EXTRA_SPEC_FUNCTIONS): Don't define.
	(ASM_SPEC): Translate -arch= option to -mmcu= option.
	(LINK_SPEC): Translate -arch= option to -m= option.
	Don't use device_to_ld / device_to_data_start.
	(STARTFILE_SPEC): Now empty.
	(ASM_SPEC): Add -%{mrelax: --mlink-relax}.
	* config/avr/gen-avr-mmcu-specs.c: New file.
	* config/avr/t-avr (gen-avr-mmcu-specs$(build_exeext)): New rule.
	(s-device-specs): Likewise.
	(GCC_PASSES): Add s-device-specs.
	(install-driver): Depend on install-device-specs.
	(install-device-specs): New rule.
	* config/avr/avr.c (avr_option_override): Look up mcu arch by
	avr_arch_index and provide fallback initialization for avr_n_flash.
	(varasm.h): #include.
	(avr_print_operand) <i>: Allow SYMBOL_REF with SYMBOL_FLAG_IO;
	(avr_handle_addr_attribute, avr_eval_addr_attrib): New functions.
	(avr_attribute_table): Add "io", "address" and "io_low".
	(avr_asm_output_aligned_decl_common): Change type of decl to tree.
	Add special handling for symbols with "io" and/or "address" attributes.
	(avr_asm_asm_output_aligned_bss): New function.
	(avr_encode_section_info): Set SYMBOL_FLAG_IO and SYMBOL_FLAG_ADDRESS
	as appropriate.  Handle io_low attribute.
	(avr_out_sbxx_branch): Handle symbolic io addresses.
	(avr_xload_libgcc_p, avr_nonconst_pointer_addrspace): Use
	avr_n_flash instead of avr_current_device->n_flash.
	(avr_pgm_check_var_decl, avr_insert_attributes): Likewise.
	(avr_emit_movmemhi): Likewise.
	* config/avr/avr-c.c (avr_cpu_cpp_builtins): Likewise.
	Use TARGET_RMW instead of avr_current_device->dev_attributes.
	Don't define avr_current_device->macro (that's the specfile's job).
	Use TARGET_SKIP_BUG instead of avr_current_device->errata_skip.
	* config/avr/avr.c (avr_2word_insn_p): Likewise.
	* config/avr/avr.md (*cpse.ne): Likewise.
	(mov<mode>): Use avr_eval_addr_attrib.
	(cbi): Change constraint for low_io_address_operand operand to "i".
	(sbi, sbix_branch, sbix_branch_bit7, insv.io, insv.not.io): Likewise.
	* config/avr/predicates.md (io_address_operand):
	Allow SYMBOL_REF with SYMBOL_FLAG_IO.
	(low_io_address_operand): Allow SYMBOL_REF with SYMBOL_FLAG_IO_LOW.
	* config/avr/avr-protos.h (avr_asm_output_aligned_decl_common):
	Update prototype.
	(avr_eval_addr_attrib, avr_asm_asm_output_aligned_bss): Prototype.
	* config/avr/genmultilib.awk: Use -march=.
	Remove Multilib matches processing.
	* config/avr/t-multilib, config/avr/avr-tables.opt: Regenerate.
	* config/avr/avr-arch.h: Add double include guard.
	(avr_mcu_t) <library_name>: Update comment.
	* config/avr/driver-avr.c (avr_device_to_as): Delete.
	(avr_device_to_ld, avr_device_to_data_start): Likewise.
	(avr_device_to_startfiles, avr_device_to_devicelib): Likewise.
	(avr_device_to_sp8): Likewise.
	* config/avr/genopt.sh:  Instead avr_mcu, emit an Enum for avr_arch.

	* doc/extend.texi (io, address): Document new AVR variable attributes.
	(io_low): Likewise.

Comments

Denis Chertykov Oct. 9, 2014, 8:33 a.m. UTC | #1
2014-10-08 21:50 GMT+04:00 Joern Rennecke <joern.rennecke@embecosm.com>:
> As the steering commitee still hasn't spoken on the maintainership issue,
> apparently this still has to go the write-after-approval route.
>
> The purpose of this patch is to make it possible to add support for new
> devices (MCUs) to the AVR toolchain, without having to re-build the
> entire toolchain.  This capability is desirable because new MCUs are added
> fairly frequently.
>
> There are multiple parts of the toolchain involved.
> gcc changes multilibbing to key off the new -march option; the -mmcu option
> is translated via DRIVER_SELF_SPECS into a -specs option, and the
> individual spec files contain the required settings like -march, and various
> more detailed settings (some of which are for new options).
>
> binutils provides new relocation and relaxation facilities to allow referring
> symbolically to symbol differences and/or I/O addresses.
> avr-libc puts the device-specifc header settings in avr/io*.h, and a few
> small device-specific likbale functions into a device-specific library.
>
> The other toolchain parts are staged here:
> git@github.com:embecosm/avr-binutils-gdb.git avr-mainline
> git@github.com:embecosm/avr-libc.git avr-libc-embecosm-mainline
>
>
> Attached is the GCC patch for the basic device package infrastructure.
> OK to apply?


Please, apply.

Denis.
Jan-Benedict Glaw Oct. 29, 2014, 1:23 a.m. UTC | #2
On Wed, 2014-10-08 18:50:32 +0100, Joern Rennecke <joern.rennecke@embecosm.com> wrote:
> Attached is the GCC patch for the basic device package infrastructure.
> OK to apply?

There's some fallout on config-list.mk builds:

g++ -c   -g -O2 -DIN_GCC  -DCROSS_DIRECTORY_STRUCTURE  -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Werror -fno-common  -DHAVE_CONFIG_H -I. -I. -I../../../gcc/gcc -I../../../gcc/gcc/. -I../../../gcc/gcc/../include -I../../../gcc/gcc/../libcpp/include -I/opt/cfarm/mpc/include  -I../../../gcc/gcc/../libdecnumber -I../../../gcc/gcc/../libdecnumber/dpd -I../libdecnumber -I../../../gcc/gcc/../libbacktrace    -I. -I. -I../../../gcc/gcc -I../../../gcc/gcc/. -I../../../gcc/gcc/../include -I../../../gcc/gcc/../libcpp/include -I/opt/cfarm/mpc/include  -I../../../gcc/gcc/../libdecnumber -I../../../gcc/gcc/../libdecnumber/dpd -I../libdecnumber -I../../../gcc/gcc/../libbacktrace   ../../../gcc/gcc/config/avr/driver-avr.c
../../../gcc/gcc/config/avr/driver-avr.c:35:1: error: ‘void avr_set_current_device(const char*)’ defined but not used [-Werror=unused-function]
 avr_set_current_device (const char *name)
 ^
cc1plus: all warnings being treated as errors
make[2]: *** [driver-avr.o] Error 1

See build
http://toolchain.lug-owl.de/buildbot/show_build_details.php?id=370682

Is it planned to use that function later on? Or shall we just drop it?

MfG, JBG
diff mbox

Patch

Index: config/avr/avr-arch.h
===================================================================
--- config/avr/avr-arch.h	(revision 215966)
+++ config/avr/avr-arch.h	(working copy)
@@ -19,6 +19,8 @@  the Free Software Foundation; either ver
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
+#ifndef AVR_ARCH_H
+#define AVR_ARCH_H
 
 /* This enum supplies indices into the avr_arch_types[] table below. */
 
@@ -115,7 +117,7 @@  enum avr_arch
   /* Number of 64k segments in the flash.  */
   int n_flash;
 
-  /* Name of device library.  */
+  /* Old name of device library.  */
   const char *const library_name;
 } avr_mcu_t;
 
@@ -173,3 +175,5 @@  enum avr_device_specific_features
 
 extern const avr_mcu_t avr_mcu_types[];
 extern const avr_mcu_t *avr_current_device;
+
+#endif /* AVR_ARCH_H */
Index: config/avr/avr-c.c
===================================================================
--- config/avr/avr-c.c	(revision 215966)
+++ config/avr/avr-c.c	(working copy)
@@ -298,12 +298,6 @@  avr_cpu_cpp_builtins (struct cpp_reader
 
   if (avr_current_arch->macro)
     cpp_define_formatted (pfile, "__AVR_ARCH__=%s", avr_current_arch->macro);
-  if (avr_current_device->macro)
-    {
-      cpp_define (pfile, avr_current_device->macro);
-      cpp_define_formatted (pfile, "__AVR_DEVICE_NAME__=%s",
-			    avr_current_device->name);
-    }
   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__");
@@ -351,7 +345,7 @@  avr_cpu_cpp_builtins (struct cpp_reader
   if (TARGET_NO_INTERRUPTS)
     cpp_define (pfile, "__NO_INTERRUPTS__");
 
-  if (avr_current_device->dev_attribute & AVR_ERRATA_SKIP)
+  if (TARGET_SKIP_BUG)
     {
       cpp_define (pfile, "__AVR_ERRATA_SKIP__");
 
@@ -359,7 +353,7 @@  avr_cpu_cpp_builtins (struct cpp_reader
         cpp_define (pfile, "__AVR_ERRATA_SKIP_JMP_CALL__");
     }
 
-  if (avr_current_device->dev_attribute & AVR_ISA_RMW)
+  if (TARGET_RMW)
     cpp_define (pfile, "__AVR_ISA_RMW__");
 
   cpp_define_formatted (pfile, "__AVR_SFR_OFFSET__=0x%x",
@@ -382,7 +376,7 @@  avr_cpu_cpp_builtins (struct cpp_reader
             /* Only supply __FLASH<n> macro if the address space is reasonable
                for this target.  The address space qualifier itself is still
                supported, but using it will throw an error.  */
-            && avr_addrspace[i].segment < avr_current_device->n_flash)
+            && avr_addrspace[i].segment < avr_n_flash)
           {
             const char *name = avr_addrspace[i].name;
             char *Name = (char*) alloca (1 + strlen (name));
Index: config/avr/avr-protos.h
===================================================================
--- config/avr/avr-protos.h	(revision 215966)
+++ config/avr/avr-protos.h	(working copy)
@@ -33,7 +33,8 @@  extern void avr_register_target_pragmas
 extern void avr_init_expanders (void);
 
 #ifdef TREE_CODE
-extern void avr_asm_output_aligned_decl_common (FILE*, const_tree, const char*, unsigned HOST_WIDE_INT, unsigned int, bool);
+extern void avr_asm_output_aligned_decl_common (FILE*, tree, const char*, unsigned HOST_WIDE_INT, unsigned int, bool);
+extern void avr_asm_asm_output_aligned_bss (FILE *, tree, const char *, unsigned HOST_WIDE_INT, int, void (*) (FILE *, tree, const char *, unsigned HOST_WIDE_INT, int));
 extern void asm_output_external (FILE *file, tree decl, char *name);
 extern int avr_progmem_p (tree decl, tree attributes);
 
@@ -124,6 +125,7 @@  extern bool avr_mem_flash_p (rtx);
 extern bool avr_mem_memx_p (rtx);
 extern bool avr_load_libgcc_p (rtx);
 extern bool avr_xload_libgcc_p (enum machine_mode);
+extern rtx avr_eval_addr_attrib (rtx x);
 
 extern rtx lpm_reg_rtx;
 extern rtx lpm_addr_reg_rtx;
Index: config/avr/avr-tables.opt
===================================================================
--- config/avr/avr-tables.opt	(revision 215966)
+++ config/avr/avr-tables.opt	(working copy)
@@ -20,786 +20,51 @@ 
 ; <http://www.gnu.org/licenses/>.
 
 Enum
-Name(avr_mcu) Type(int)
-Known MCU names:
+Name(avr_arch) Type(enum avr_arch)
+Known MCU architectures:
 
 EnumValue
-Enum(avr_mcu) String(avr2) Value(0)
+Enum(avr_arch) String(avr2) Value(ARCH_AVR2)
 
 EnumValue
-Enum(avr_mcu) String(at90s2313) Value(1)
+Enum(avr_arch) String(avr25) Value(ARCH_AVR25)
 
 EnumValue
-Enum(avr_mcu) String(at90s2323) Value(2)
+Enum(avr_arch) String(avr3) Value(ARCH_AVR3)
 
 EnumValue
-Enum(avr_mcu) String(at90s2333) Value(3)
+Enum(avr_arch) String(avr31) Value(ARCH_AVR31)
 
 EnumValue
-Enum(avr_mcu) String(at90s2343) Value(4)
+Enum(avr_arch) String(avr35) Value(ARCH_AVR35)
 
 EnumValue
-Enum(avr_mcu) String(attiny22) Value(5)
+Enum(avr_arch) String(avr4) Value(ARCH_AVR4)
 
 EnumValue
-Enum(avr_mcu) String(attiny26) Value(6)
+Enum(avr_arch) String(avr5) Value(ARCH_AVR5)
 
 EnumValue
-Enum(avr_mcu) String(at90s4414) Value(7)
+Enum(avr_arch) String(avr51) Value(ARCH_AVR51)
 
 EnumValue
-Enum(avr_mcu) String(at90s4433) Value(8)
+Enum(avr_arch) String(avr6) Value(ARCH_AVR6)
 
 EnumValue
-Enum(avr_mcu) String(at90s4434) Value(9)
+Enum(avr_arch) String(avrxmega2) Value(ARCH_AVRXMEGA2)
 
 EnumValue
-Enum(avr_mcu) String(at90s8515) Value(10)
+Enum(avr_arch) String(avrxmega4) Value(ARCH_AVRXMEGA4)
 
 EnumValue
-Enum(avr_mcu) String(at90c8534) Value(11)
+Enum(avr_arch) String(avrxmega5) Value(ARCH_AVRXMEGA5)
 
 EnumValue
-Enum(avr_mcu) String(at90s8535) Value(12)
+Enum(avr_arch) String(avrxmega6) Value(ARCH_AVRXMEGA6)
 
 EnumValue
-Enum(avr_mcu) String(avr25) Value(13)
+Enum(avr_arch) String(avrxmega7) Value(ARCH_AVRXMEGA7)
 
 EnumValue
-Enum(avr_mcu) String(ata5272) Value(14)
-
-EnumValue
-Enum(avr_mcu) String(ata6616c) Value(15)
-
-EnumValue
-Enum(avr_mcu) String(attiny13) Value(16)
-
-EnumValue
-Enum(avr_mcu) String(attiny13a) Value(17)
-
-EnumValue
-Enum(avr_mcu) String(attiny2313) Value(18)
-
-EnumValue
-Enum(avr_mcu) String(attiny2313a) Value(19)
-
-EnumValue
-Enum(avr_mcu) String(attiny24) Value(20)
-
-EnumValue
-Enum(avr_mcu) String(attiny24a) Value(21)
-
-EnumValue
-Enum(avr_mcu) String(attiny4313) Value(22)
-
-EnumValue
-Enum(avr_mcu) String(attiny44) Value(23)
-
-EnumValue
-Enum(avr_mcu) String(attiny44a) Value(24)
-
-EnumValue
-Enum(avr_mcu) String(attiny441) Value(25)
-
-EnumValue
-Enum(avr_mcu) String(attiny84) Value(26)
-
-EnumValue
-Enum(avr_mcu) String(attiny84a) Value(27)
-
-EnumValue
-Enum(avr_mcu) String(attiny25) Value(28)
-
-EnumValue
-Enum(avr_mcu) String(attiny45) Value(29)
-
-EnumValue
-Enum(avr_mcu) String(attiny85) Value(30)
-
-EnumValue
-Enum(avr_mcu) String(attiny261) Value(31)
-
-EnumValue
-Enum(avr_mcu) String(attiny261a) Value(32)
-
-EnumValue
-Enum(avr_mcu) String(attiny461) Value(33)
-
-EnumValue
-Enum(avr_mcu) String(attiny461a) Value(34)
-
-EnumValue
-Enum(avr_mcu) String(attiny861) Value(35)
-
-EnumValue
-Enum(avr_mcu) String(attiny861a) Value(36)
-
-EnumValue
-Enum(avr_mcu) String(attiny43u) Value(37)
-
-EnumValue
-Enum(avr_mcu) String(attiny87) Value(38)
-
-EnumValue
-Enum(avr_mcu) String(attiny48) Value(39)
-
-EnumValue
-Enum(avr_mcu) String(attiny88) Value(40)
-
-EnumValue
-Enum(avr_mcu) String(attiny828) Value(41)
-
-EnumValue
-Enum(avr_mcu) String(attiny841) Value(42)
-
-EnumValue
-Enum(avr_mcu) String(at86rf401) Value(43)
-
-EnumValue
-Enum(avr_mcu) String(avr3) Value(44)
-
-EnumValue
-Enum(avr_mcu) String(at43usb355) Value(45)
-
-EnumValue
-Enum(avr_mcu) String(at76c711) Value(46)
-
-EnumValue
-Enum(avr_mcu) String(avr31) Value(47)
-
-EnumValue
-Enum(avr_mcu) String(atmega103) Value(48)
-
-EnumValue
-Enum(avr_mcu) String(at43usb320) Value(49)
-
-EnumValue
-Enum(avr_mcu) String(avr35) Value(50)
-
-EnumValue
-Enum(avr_mcu) String(ata5505) Value(51)
-
-EnumValue
-Enum(avr_mcu) String(ata6617c) Value(52)
-
-EnumValue
-Enum(avr_mcu) String(ata664251) Value(53)
-
-EnumValue
-Enum(avr_mcu) String(at90usb82) Value(54)
-
-EnumValue
-Enum(avr_mcu) String(at90usb162) Value(55)
-
-EnumValue
-Enum(avr_mcu) String(atmega8u2) Value(56)
-
-EnumValue
-Enum(avr_mcu) String(atmega16u2) Value(57)
-
-EnumValue
-Enum(avr_mcu) String(atmega32u2) Value(58)
-
-EnumValue
-Enum(avr_mcu) String(attiny167) Value(59)
-
-EnumValue
-Enum(avr_mcu) String(attiny1634) Value(60)
-
-EnumValue
-Enum(avr_mcu) String(avr4) Value(61)
-
-EnumValue
-Enum(avr_mcu) String(ata6285) Value(62)
-
-EnumValue
-Enum(avr_mcu) String(ata6286) Value(63)
-
-EnumValue
-Enum(avr_mcu) String(ata6289) Value(64)
-
-EnumValue
-Enum(avr_mcu) String(ata6612c) Value(65)
-
-EnumValue
-Enum(avr_mcu) String(atmega8) Value(66)
-
-EnumValue
-Enum(avr_mcu) String(atmega8a) Value(67)
-
-EnumValue
-Enum(avr_mcu) String(atmega48) Value(68)
-
-EnumValue
-Enum(avr_mcu) String(atmega48a) Value(69)
-
-EnumValue
-Enum(avr_mcu) String(atmega48p) Value(70)
-
-EnumValue
-Enum(avr_mcu) String(atmega48pa) Value(71)
-
-EnumValue
-Enum(avr_mcu) String(atmega88) Value(72)
-
-EnumValue
-Enum(avr_mcu) String(atmega88a) Value(73)
-
-EnumValue
-Enum(avr_mcu) String(atmega88p) Value(74)
-
-EnumValue
-Enum(avr_mcu) String(atmega88pa) Value(75)
-
-EnumValue
-Enum(avr_mcu) String(atmega8515) Value(76)
-
-EnumValue
-Enum(avr_mcu) String(atmega8535) Value(77)
-
-EnumValue
-Enum(avr_mcu) String(atmega8hva) Value(78)
-
-EnumValue
-Enum(avr_mcu) String(at90pwm1) Value(79)
-
-EnumValue
-Enum(avr_mcu) String(at90pwm2) Value(80)
-
-EnumValue
-Enum(avr_mcu) String(at90pwm2b) Value(81)
-
-EnumValue
-Enum(avr_mcu) String(at90pwm3) Value(82)
-
-EnumValue
-Enum(avr_mcu) String(at90pwm3b) Value(83)
-
-EnumValue
-Enum(avr_mcu) String(at90pwm81) Value(84)
-
-EnumValue
-Enum(avr_mcu) String(avr5) Value(85)
-
-EnumValue
-Enum(avr_mcu) String(ata5702m322) Value(86)
-
-EnumValue
-Enum(avr_mcu) String(ata5782) Value(87)
-
-EnumValue
-Enum(avr_mcu) String(ata5790) Value(88)
-
-EnumValue
-Enum(avr_mcu) String(ata5790n) Value(89)
-
-EnumValue
-Enum(avr_mcu) String(ata5795) Value(90)
-
-EnumValue
-Enum(avr_mcu) String(ata5831) Value(91)
-
-EnumValue
-Enum(avr_mcu) String(ata6613c) Value(92)
-
-EnumValue
-Enum(avr_mcu) String(ata6614q) Value(93)
-
-EnumValue
-Enum(avr_mcu) String(atmega16) Value(94)
-
-EnumValue
-Enum(avr_mcu) String(atmega16a) Value(95)
-
-EnumValue
-Enum(avr_mcu) String(atmega161) Value(96)
-
-EnumValue
-Enum(avr_mcu) String(atmega162) Value(97)
-
-EnumValue
-Enum(avr_mcu) String(atmega163) Value(98)
-
-EnumValue
-Enum(avr_mcu) String(atmega164a) Value(99)
-
-EnumValue
-Enum(avr_mcu) String(atmega164p) Value(100)
-
-EnumValue
-Enum(avr_mcu) String(atmega164pa) Value(101)
-
-EnumValue
-Enum(avr_mcu) String(atmega165) Value(102)
-
-EnumValue
-Enum(avr_mcu) String(atmega165a) Value(103)
-
-EnumValue
-Enum(avr_mcu) String(atmega165p) Value(104)
-
-EnumValue
-Enum(avr_mcu) String(atmega165pa) Value(105)
-
-EnumValue
-Enum(avr_mcu) String(atmega168) Value(106)
-
-EnumValue
-Enum(avr_mcu) String(atmega168a) Value(107)
-
-EnumValue
-Enum(avr_mcu) String(atmega168p) Value(108)
-
-EnumValue
-Enum(avr_mcu) String(atmega168pa) Value(109)
-
-EnumValue
-Enum(avr_mcu) String(atmega169) Value(110)
-
-EnumValue
-Enum(avr_mcu) String(atmega169a) Value(111)
-
-EnumValue
-Enum(avr_mcu) String(atmega169p) Value(112)
-
-EnumValue
-Enum(avr_mcu) String(atmega169pa) Value(113)
-
-EnumValue
-Enum(avr_mcu) String(atmega16hvb) Value(114)
-
-EnumValue
-Enum(avr_mcu) String(atmega16hvbrevb) Value(115)
-
-EnumValue
-Enum(avr_mcu) String(atmega16m1) Value(116)
-
-EnumValue
-Enum(avr_mcu) String(atmega16u4) Value(117)
-
-EnumValue
-Enum(avr_mcu) String(atmega32a) Value(118)
-
-EnumValue
-Enum(avr_mcu) String(atmega32) Value(119)
-
-EnumValue
-Enum(avr_mcu) String(atmega323) Value(120)
-
-EnumValue
-Enum(avr_mcu) String(atmega324a) Value(121)
-
-EnumValue
-Enum(avr_mcu) String(atmega324p) Value(122)
-
-EnumValue
-Enum(avr_mcu) String(atmega324pa) Value(123)
-
-EnumValue
-Enum(avr_mcu) String(atmega325) Value(124)
-
-EnumValue
-Enum(avr_mcu) String(atmega325a) Value(125)
-
-EnumValue
-Enum(avr_mcu) String(atmega325p) Value(126)
-
-EnumValue
-Enum(avr_mcu) String(atmega325pa) Value(127)
-
-EnumValue
-Enum(avr_mcu) String(atmega3250) Value(128)
-
-EnumValue
-Enum(avr_mcu) String(atmega3250a) Value(129)
-
-EnumValue
-Enum(avr_mcu) String(atmega3250p) Value(130)
-
-EnumValue
-Enum(avr_mcu) String(atmega3250pa) Value(131)
-
-EnumValue
-Enum(avr_mcu) String(atmega328) Value(132)
-
-EnumValue
-Enum(avr_mcu) String(atmega328p) Value(133)
-
-EnumValue
-Enum(avr_mcu) String(atmega329) Value(134)
-
-EnumValue
-Enum(avr_mcu) String(atmega329a) Value(135)
-
-EnumValue
-Enum(avr_mcu) String(atmega329p) Value(136)
-
-EnumValue
-Enum(avr_mcu) String(atmega329pa) Value(137)
-
-EnumValue
-Enum(avr_mcu) String(atmega3290) Value(138)
-
-EnumValue
-Enum(avr_mcu) String(atmega3290a) Value(139)
-
-EnumValue
-Enum(avr_mcu) String(atmega3290p) Value(140)
-
-EnumValue
-Enum(avr_mcu) String(atmega3290pa) Value(141)
-
-EnumValue
-Enum(avr_mcu) String(atmega32c1) Value(142)
-
-EnumValue
-Enum(avr_mcu) String(atmega32m1) Value(143)
-
-EnumValue
-Enum(avr_mcu) String(atmega32u4) Value(144)
-
-EnumValue
-Enum(avr_mcu) String(atmega32u6) Value(145)
-
-EnumValue
-Enum(avr_mcu) String(atmega406) Value(146)
-
-EnumValue
-Enum(avr_mcu) String(atmega64) Value(147)
-
-EnumValue
-Enum(avr_mcu) String(atmega64a) Value(148)
-
-EnumValue
-Enum(avr_mcu) String(atmega640) Value(149)
-
-EnumValue
-Enum(avr_mcu) String(atmega644) Value(150)
-
-EnumValue
-Enum(avr_mcu) String(atmega644a) Value(151)
-
-EnumValue
-Enum(avr_mcu) String(atmega644p) Value(152)
-
-EnumValue
-Enum(avr_mcu) String(atmega644pa) Value(153)
-
-EnumValue
-Enum(avr_mcu) String(atmega645) Value(154)
-
-EnumValue
-Enum(avr_mcu) String(atmega645a) Value(155)
-
-EnumValue
-Enum(avr_mcu) String(atmega645p) Value(156)
-
-EnumValue
-Enum(avr_mcu) String(atmega6450) Value(157)
-
-EnumValue
-Enum(avr_mcu) String(atmega6450a) Value(158)
-
-EnumValue
-Enum(avr_mcu) String(atmega6450p) Value(159)
-
-EnumValue
-Enum(avr_mcu) String(atmega649) Value(160)
-
-EnumValue
-Enum(avr_mcu) String(atmega649a) Value(161)
-
-EnumValue
-Enum(avr_mcu) String(atmega649p) Value(162)
-
-EnumValue
-Enum(avr_mcu) String(atmega6490) Value(163)
-
-EnumValue
-Enum(avr_mcu) String(atmega16hva) Value(164)
-
-EnumValue
-Enum(avr_mcu) String(atmega16hva2) Value(165)
-
-EnumValue
-Enum(avr_mcu) String(atmega32hvb) Value(166)
-
-EnumValue
-Enum(avr_mcu) String(atmega6490a) Value(167)
-
-EnumValue
-Enum(avr_mcu) String(atmega6490p) Value(168)
-
-EnumValue
-Enum(avr_mcu) String(atmega64c1) Value(169)
-
-EnumValue
-Enum(avr_mcu) String(atmega64m1) Value(170)
-
-EnumValue
-Enum(avr_mcu) String(atmega64hve) Value(171)
-
-EnumValue
-Enum(avr_mcu) String(atmega64hve2) Value(172)
-
-EnumValue
-Enum(avr_mcu) String(atmega64rfr2) Value(173)
-
-EnumValue
-Enum(avr_mcu) String(atmega644rfr2) Value(174)
-
-EnumValue
-Enum(avr_mcu) String(atmega32hvbrevb) Value(175)
-
-EnumValue
-Enum(avr_mcu) String(at90can32) Value(176)
-
-EnumValue
-Enum(avr_mcu) String(at90can64) Value(177)
-
-EnumValue
-Enum(avr_mcu) String(at90pwm161) Value(178)
-
-EnumValue
-Enum(avr_mcu) String(at90pwm216) Value(179)
-
-EnumValue
-Enum(avr_mcu) String(at90pwm316) Value(180)
-
-EnumValue
-Enum(avr_mcu) String(at90scr100) Value(181)
-
-EnumValue
-Enum(avr_mcu) String(at90usb646) Value(182)
-
-EnumValue
-Enum(avr_mcu) String(at90usb647) Value(183)
-
-EnumValue
-Enum(avr_mcu) String(at94k) Value(184)
-
-EnumValue
-Enum(avr_mcu) String(m3000) Value(185)
-
-EnumValue
-Enum(avr_mcu) String(avr51) Value(186)
-
-EnumValue
-Enum(avr_mcu) String(atmega128) Value(187)
-
-EnumValue
-Enum(avr_mcu) String(atmega128a) Value(188)
-
-EnumValue
-Enum(avr_mcu) String(atmega1280) Value(189)
-
-EnumValue
-Enum(avr_mcu) String(atmega1281) Value(190)
-
-EnumValue
-Enum(avr_mcu) String(atmega1284) Value(191)
-
-EnumValue
-Enum(avr_mcu) String(atmega1284p) Value(192)
-
-EnumValue
-Enum(avr_mcu) String(atmega128rfa1) Value(193)
-
-EnumValue
-Enum(avr_mcu) String(atmega128rfr2) Value(194)
-
-EnumValue
-Enum(avr_mcu) String(atmega1284rfr2) Value(195)
-
-EnumValue
-Enum(avr_mcu) String(at90can128) Value(196)
-
-EnumValue
-Enum(avr_mcu) String(at90usb1286) Value(197)
-
-EnumValue
-Enum(avr_mcu) String(at90usb1287) Value(198)
-
-EnumValue
-Enum(avr_mcu) String(avr6) Value(199)
-
-EnumValue
-Enum(avr_mcu) String(atmega2560) Value(200)
-
-EnumValue
-Enum(avr_mcu) String(atmega2561) Value(201)
-
-EnumValue
-Enum(avr_mcu) String(atmega256rfr2) Value(202)
-
-EnumValue
-Enum(avr_mcu) String(atmega2564rfr2) Value(203)
-
-EnumValue
-Enum(avr_mcu) String(avrxmega2) Value(204)
-
-EnumValue
-Enum(avr_mcu) String(atxmega8e5) Value(205)
-
-EnumValue
-Enum(avr_mcu) String(atxmega16a4) Value(206)
-
-EnumValue
-Enum(avr_mcu) String(atxmega16d4) Value(207)
-
-EnumValue
-Enum(avr_mcu) String(atxmega16e5) Value(208)
-
-EnumValue
-Enum(avr_mcu) String(atxmega32a4) Value(209)
-
-EnumValue
-Enum(avr_mcu) String(atxmega32c3) Value(210)
-
-EnumValue
-Enum(avr_mcu) String(atxmega32d3) Value(211)
-
-EnumValue
-Enum(avr_mcu) String(atxmega32d4) Value(212)
-
-EnumValue
-Enum(avr_mcu) String(atxmega16a4u) Value(213)
-
-EnumValue
-Enum(avr_mcu) String(atxmega16c4) Value(214)
-
-EnumValue
-Enum(avr_mcu) String(atxmega32a4u) Value(215)
-
-EnumValue
-Enum(avr_mcu) String(atxmega32c4) Value(216)
-
-EnumValue
-Enum(avr_mcu) String(atxmega32e5) Value(217)
-
-EnumValue
-Enum(avr_mcu) String(avrxmega4) Value(218)
-
-EnumValue
-Enum(avr_mcu) String(atxmega64a3) Value(219)
-
-EnumValue
-Enum(avr_mcu) String(atxmega64d3) Value(220)
-
-EnumValue
-Enum(avr_mcu) String(atxmega64a3u) Value(221)
-
-EnumValue
-Enum(avr_mcu) String(atxmega64a4u) Value(222)
-
-EnumValue
-Enum(avr_mcu) String(atxmega64b1) Value(223)
-
-EnumValue
-Enum(avr_mcu) String(atxmega64b3) Value(224)
-
-EnumValue
-Enum(avr_mcu) String(atxmega64c3) Value(225)
-
-EnumValue
-Enum(avr_mcu) String(atxmega64d4) Value(226)
-
-EnumValue
-Enum(avr_mcu) String(avrxmega5) Value(227)
-
-EnumValue
-Enum(avr_mcu) String(atxmega64a1) Value(228)
-
-EnumValue
-Enum(avr_mcu) String(atxmega64a1u) Value(229)
-
-EnumValue
-Enum(avr_mcu) String(avrxmega6) Value(230)
-
-EnumValue
-Enum(avr_mcu) String(atxmega128a3) Value(231)
-
-EnumValue
-Enum(avr_mcu) String(atxmega128d3) Value(232)
-
-EnumValue
-Enum(avr_mcu) String(atxmega192a3) Value(233)
-
-EnumValue
-Enum(avr_mcu) String(atxmega192d3) Value(234)
-
-EnumValue
-Enum(avr_mcu) String(atxmega256a3) Value(235)
-
-EnumValue
-Enum(avr_mcu) String(atxmega256a3b) Value(236)
-
-EnumValue
-Enum(avr_mcu) String(atxmega256a3bu) Value(237)
-
-EnumValue
-Enum(avr_mcu) String(atxmega256d3) Value(238)
-
-EnumValue
-Enum(avr_mcu) String(atxmega128a3u) Value(239)
-
-EnumValue
-Enum(avr_mcu) String(atxmega128b1) Value(240)
-
-EnumValue
-Enum(avr_mcu) String(atxmega128b3) Value(241)
-
-EnumValue
-Enum(avr_mcu) String(atxmega128c3) Value(242)
-
-EnumValue
-Enum(avr_mcu) String(atxmega128d4) Value(243)
-
-EnumValue
-Enum(avr_mcu) String(atxmega192a3u) Value(244)
-
-EnumValue
-Enum(avr_mcu) String(atxmega192c3) Value(245)
-
-EnumValue
-Enum(avr_mcu) String(atxmega256a3u) Value(246)
-
-EnumValue
-Enum(avr_mcu) String(atxmega256c3) Value(247)
-
-EnumValue
-Enum(avr_mcu) String(atxmega384c3) Value(248)
-
-EnumValue
-Enum(avr_mcu) String(atxmega384d3) Value(249)
-
-EnumValue
-Enum(avr_mcu) String(avrxmega7) Value(250)
-
-EnumValue
-Enum(avr_mcu) String(atxmega128a1) Value(251)
-
-EnumValue
-Enum(avr_mcu) String(atxmega128a1u) Value(252)
-
-EnumValue
-Enum(avr_mcu) String(atxmega128a4u) Value(253)
-
-EnumValue
-Enum(avr_mcu) String(avr1) Value(254)
-
-EnumValue
-Enum(avr_mcu) String(at90s1200) Value(255)
-
-EnumValue
-Enum(avr_mcu) String(attiny11) Value(256)
-
-EnumValue
-Enum(avr_mcu) String(attiny12) Value(257)
-
-EnumValue
-Enum(avr_mcu) String(attiny15) Value(258)
-
-EnumValue
-Enum(avr_mcu) String(attiny28) Value(259)
+Enum(avr_arch) String(avr1) Value(ARCH_AVR1)
 
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(revision 215966)
+++ config/avr/avr.c	(working copy)
@@ -32,6 +32,7 @@ 
 #include "flags.h"
 #include "reload.h"
 #include "tree.h"
+#include "varasm.h"
 #include "print-tree.h"
 #include "calls.h"
 #include "stor-layout.h"
@@ -330,8 +331,23 @@  avr_option_override (void)
   if (flag_pie == 2)
     warning (OPT_fPIE, "-fPIE is not supported");
 
-  avr_current_device = &avr_mcu_types[avr_mcu_index];
-  avr_current_arch = &avr_arch_types[avr_current_device->arch];
+  /* 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 ("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;
 
   /* RAM addresses of some SFRs common to all devices in respective arch. */
 
@@ -2242,7 +2258,11 @@  avr_print_operand (FILE *file, rtx x, in
     }
   else if (code == 'i')
     {
-      fatal_insn ("bad address, not an I/O address:", x);
+      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));
+      else
+	fatal_insn ("bad address, not an I/O address:", x);
     }
   else if (code == 'x')
     {
@@ -2767,7 +2787,7 @@  avr_xload_libgcc_p (enum machine_mode mo
   int n_bytes = GET_MODE_SIZE (mode);
 
   return (n_bytes > 1
-          || avr_current_device->n_flash > 1);
+          || avr_n_flash > 1);
 }
 
 
@@ -8132,6 +8152,86 @@  avr_handle_fntype_attribute (tree *node,
   return NULL_TREE;
 }
 
+static tree
+avr_handle_addr_attribute (tree *node, tree name, tree args,
+			   int flags ATTRIBUTE_UNUSED, bool *no_add)
+{
+  bool io_p = (strncmp (IDENTIFIER_POINTER (name), "io", 2) == 0);
+  location_t loc = DECL_SOURCE_LOCATION (*node);
+
+  if (TREE_CODE (*node) != VAR_DECL)
+    {
+      warning_at (loc, 0, "%qE attribute only applies to variables", name);
+      *no_add = true;
+    }
+
+  if (args != NULL_TREE)
+    {
+      if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
+	TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
+      tree arg = TREE_VALUE (args);
+      if (TREE_CODE (arg) != INTEGER_CST)
+	{
+	  warning (0, "%qE attribute allows only an integer constant argument",
+		   name);
+	  *no_add = true;
+	}
+      else if (io_p
+	       && (!tree_fits_shwi_p (arg)
+		   || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
+			? low_io_address_operand : io_address_operand)
+			 (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
+	{
+	  warning_at (loc, 0, "%qE attribute address out of range", name);
+	  *no_add = true;
+	}
+      else
+	{
+	  tree attribs = DECL_ATTRIBUTES (*node);
+	  const char *names[] = { "io", "io_low", "address", NULL } ;
+	  for (const char **p = names; *p; p++)
+	    {
+	      tree other = lookup_attribute (*p, attribs);
+	      if (other && TREE_VALUE (other))
+		{
+		  warning_at (loc, 0,
+			      "both %s and %qE attribute provide address",
+			      *p, name);
+		  *no_add = true;
+		  break;
+		}
+	    }
+	}
+    }
+
+  if (*no_add == false && io_p && !TREE_THIS_VOLATILE (*node))
+    warning_at (loc, 0, "%qE attribute on non-volatile variable", name);
+
+  return NULL_TREE;
+}
+
+rtx
+avr_eval_addr_attrib (rtx x)
+{
+  if (GET_CODE (x) == SYMBOL_REF
+      && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_ADDRESS))
+    {
+      tree decl = SYMBOL_REF_DECL (x);
+      tree attr = NULL_TREE;
+
+      if (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO)
+	{
+	  attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
+	  gcc_assert (attr);
+	}
+      if (!attr || !TREE_VALUE (attr))
+	attr = lookup_attribute ("address", DECL_ATTRIBUTES (decl));
+      gcc_assert (attr && TREE_VALUE (attr) && TREE_VALUE (TREE_VALUE (attr)));
+      return GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
+    }
+  return x;
+}
+
 
 /* AVR attributes.  */
 static const struct attribute_spec
@@ -8151,6 +8251,12 @@  avr_handle_fntype_attribute (tree *node,
     false },
   { "OS_main",   0, 0, false, true,  true,   avr_handle_fntype_attribute,
     false },
+  { "io",        0, 1, false, false, false,  avr_handle_addr_attribute,
+    false },
+  { "io_low",    0, 1, false, false, false,  avr_handle_addr_attribute,
+    false },
+  { "address",   1, 1, false, false, false,  avr_handle_addr_attribute,
+    false },
   { NULL,        0, 0, false, false, false, NULL, false }
 };
 
@@ -8232,7 +8338,7 @@  avr_nonconst_pointer_addrspace (tree typ
 
       if (!ADDR_SPACE_GENERIC_P (as)
           && (!TYPE_READONLY (target)
-              || avr_addrspace[as].segment >= avr_current_device->n_flash))
+              || avr_addrspace[as].segment >= avr_n_flash))
         {
           return as;
         }
@@ -8296,7 +8402,7 @@  avr_pgm_check_var_decl (tree node)
 
   if (reason)
     {
-      if (avr_addrspace[as].segment >= avr_current_device->n_flash)
+      if (avr_addrspace[as].segment >= avr_n_flash)
         {
           if (TYPE_P (node))
             error ("%qT uses address space %qs beyond flash of %qs",
@@ -8348,7 +8454,7 @@  avr_insert_attributes (tree node, tree *
 
       as = TYPE_ADDR_SPACE (TREE_TYPE (node));
 
-      if (avr_addrspace[as].segment >= avr_current_device->n_flash)
+      if (avr_addrspace[as].segment >= avr_n_flash)
         {
           error ("variable %q+D located in address space %qs"
                  " beyond flash of %qs",
@@ -8379,11 +8485,37 @@  avr_insert_attributes (tree node, tree *
 
 void
 avr_asm_output_aligned_decl_common (FILE * stream,
-                                    const_tree decl ATTRIBUTE_UNUSED,
+                                    tree decl,
                                     const char *name,
                                     unsigned HOST_WIDE_INT size,
                                     unsigned int align, bool local_p)
 {
+  rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
+  rtx symbol;
+
+  if (mem != NULL_RTX && MEM_P (mem)
+      && GET_CODE ((symbol = XEXP (mem, 0))) == SYMBOL_REF
+      && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
+    {
+
+      if (!local_p)
+	{
+	  fprintf (stream, "\t.globl\t");
+	  assemble_name (stream, name);
+	  fprintf (stream, "\n");
+	}
+      if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
+	{
+	  assemble_name (stream, name);
+	  fprintf (stream, " = %ld\n",
+		   (long) INTVAL (avr_eval_addr_attrib (symbol)));
+	}
+      else if (local_p)
+	error_at (DECL_SOURCE_LOCATION (decl),
+		  "static IO declaration for %q+D needs an address", decl);
+      return;
+    }
+
   /* __gnu_lto_v1 etc. are just markers for the linker injected by toplev.c.
      There is no need to trigger __do_clear_bss code for them.  */
 
@@ -8396,6 +8528,29 @@  avr_asm_output_aligned_decl_common (FILE
     ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
 }
 
+void
+avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
+				unsigned HOST_WIDE_INT size, int align,
+				void (*default_func)
+				  (FILE *, tree, const char *,
+				   unsigned HOST_WIDE_INT, int))
+{
+  rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
+  rtx symbol;
+
+  if (mem != NULL_RTX && MEM_P (mem)
+      && GET_CODE ((symbol = XEXP (mem, 0))) == SYMBOL_REF
+      && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
+    {
+      if (!(SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS))
+	error_at (DECL_SOURCE_LOCATION (decl),
+		  "IO definition for %q+D needs an address", decl);
+      avr_asm_output_aligned_decl_common (file, decl, name, size, align, false);
+    }
+  else
+    default_func (file, decl, name, size, align);
+}
+
 
 /* Unnamed section callback for data_section
    to track need of __do_copy_data.  */
@@ -8627,17 +8782,43 @@  avr_encode_section_info (tree decl, rtx
    {
       rtx sym = XEXP (rtl, 0);
       tree type = TREE_TYPE (decl);
+      tree attr = DECL_ATTRIBUTES (decl);
       if (type == error_mark_node)
 	return;
+
       addr_space_t as = TYPE_ADDR_SPACE (type);
 
       /* PSTR strings are in generic space but located in flash:
          patch address space.  */
 
-      if (-1 == avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
+      if (-1 == avr_progmem_p (decl, attr))
         as = ADDR_SPACE_FLASH;
 
       AVR_SYMBOL_SET_ADDR_SPACE (sym, as);
+
+      tree io_low_attr = lookup_attribute ("io_low", attr);
+      tree io_attr = lookup_attribute ("io", attr);
+      tree addr_attr;
+      if (io_low_attr
+	  && TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
+	addr_attr = io_attr;
+      else if (io_attr
+	       && TREE_VALUE (io_attr) && TREE_VALUE (TREE_VALUE (io_attr)))
+	addr_attr = io_attr;
+      else
+	addr_attr = lookup_attribute ("address", attr);
+      if (io_low_attr
+	  || (io_attr && addr_attr && 
+	      low_io_address_operand (GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (addr_attr)))), QImode)))
+	SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO_LOW;
+      if (io_attr || io_low_attr)
+	SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO;
+      /* If we have an (io) address attribute specification, but the variable
+	 is external, treat the address as only a tentative definition
+	 to be used to determine if an io port is in the lower range, but
+	 don't use the exact value for constant propagation.  */
+      if (addr_attr && !DECL_EXTERNAL (decl))
+	SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_ADDRESS;
     }
 }
 
@@ -10142,7 +10323,7 @@  test_hard_reg_class (enum reg_class rcla
 static bool
 avr_2word_insn_p (rtx_insn *insn)
 {
-  if ((avr_current_device->dev_attribute & AVR_ERRATA_SKIP)
+  if (TARGET_SKIP_BUG
       || !insn
       || 2 != get_attr_length (insn))
     {
@@ -10760,6 +10941,8 @@  avr_out_sbxx_branch (rtx_insn *insn, rtx
       gcc_unreachable();
 
     case CONST_INT:
+    case CONST:
+    case SYMBOL_REF:
 
       if (low_io_address_operand (operands[1], QImode))
         {
@@ -10770,6 +10953,7 @@  avr_out_sbxx_branch (rtx_insn *insn, rtx
         }
       else
         {
+	  gcc_assert (io_address_operand (operands[1], QImode));
           output_asm_insn ("in __tmp_reg__,%i1", operands);
           if (comp == EQ)
             output_asm_insn ("sbrs __tmp_reg__,%2", operands);
@@ -11179,7 +11363,7 @@  avr_emit_movmemhi (rtx *xop)
       int segment = avr_addrspace[as].segment;
 
       if (segment
-          && avr_current_device->n_flash > 1)
+          && avr_n_flash > 1)
         {
           a_hi8 = GEN_INT (segment);
           emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
Index: config/avr/avr.h
===================================================================
--- config/avr/avr.h	(revision 215966)
+++ config/avr/avr.h	(working copy)
@@ -75,6 +75,7 @@  #define AVR_HAVE_RAMPZ (avr_current_arch
 
 /* Handling of 8-bit SP versus 16-bit SP is as follows:
 
+FIXME: DRIVER_SELF_SPECS has changed.
    -msp8 is used internally to select the right multilib for targets with
    8-bit SP.  -msp8 is set automatically by DRIVER_SELF_SPECS for devices
    with 8-bit SP or by multilib generation machinery.  If a frame pointer is
@@ -403,7 +404,8 @@  #define ASM_OUTPUT_ALIGNED_DECL_COMMON(S
   avr_asm_output_aligned_decl_common (STREAM, DECL, NAME, SIZE, ALIGN, false)
 
 #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
-  asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
+  avr_asm_asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN, \
+				  asm_output_aligned_bss)
 
 #define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGN)  \
   avr_asm_output_aligned_decl_common (STREAM, DECL, NAME, SIZE, ALIGN, true)
@@ -488,24 +490,7 @@  #define FUNCTION_PROFILER(FILE, LABELNO)
 #define ADJUST_INSN_LENGTH(INSN, LENGTH)                \
     (LENGTH = avr_adjust_insn_length (INSN, LENGTH))
 
-extern const char *avr_device_to_as (int argc, const char **argv);
-extern const char *avr_device_to_ld (int argc, const char **argv);
-extern const char *avr_device_to_data_start (int argc, const char **argv);
-extern const char *avr_device_to_text_start (int argc, const char **argv);
-extern const char *avr_device_to_startfiles (int argc, const char **argv);
-extern const char *avr_device_to_devicelib (int argc, const char **argv);
-extern const char *avr_device_to_sp8 (int argc, const char **argv);
-
-#define EXTRA_SPEC_FUNCTIONS                            \
-  { "device_to_as", avr_device_to_as },                 \
-  { "device_to_ld", avr_device_to_ld },                 \
-  { "device_to_data_start", avr_device_to_data_start }, \
-  { "device_to_text_start", avr_device_to_text_start }, \
-  { "device_to_startfile", avr_device_to_startfiles },  \
-  { "device_to_devicelib", avr_device_to_devicelib },   \
-  { "device_to_sp8", avr_device_to_sp8 },
-
-#define DRIVER_SELF_SPECS " %:device_to_sp8(%{mmcu=*:%*}) "
+#define DRIVER_SELF_SPECS " %{mmcu=*:-specs=device-specs/specs-%*%s %<mmcu=*} "
 #define CPP_SPEC ""
 
 #define CC1_SPEC ""
@@ -514,7 +499,7 @@  #define CC1PLUS_SPEC "%{!frtti:-fno-rtti
     %{!fenforce-eh-specs:-fno-enforce-eh-specs} \
     %{!fexceptions:-fno-exceptions}"
 
-#define ASM_SPEC "%:device_to_as(%{mmcu=*:%*}) "
+#define ASM_SPEC "%{march=*:-mmcu=%*}%{mrelax: --mlink-relax}"
   
 #define LINK_SPEC "\
 %{mrelax:--relax\
@@ -525,9 +510,7 @@  #define LINK_SPEC "\
                              %{mmcu=atmega64*|\
                                mmcu=at90can64*|\
                                mmcu=at90usb64*:--pmem-wrap-around=64k}}}\
-%:device_to_ld(%{mmcu=*:%*})\
-%:device_to_data_start(%{mmcu=*:%*})\
-%:device_to_text_start(%{mmcu=*:%*}) \
+%{march=*:-m%*}\
 %{shared:%eshared is not supported}"
 
 #define LIB_SPEC \
@@ -539,7 +522,8 @@  #define LIB_SPEC \
 #define LIBGCC_SPEC \
   "%{!mmcu=at90s1*:%{!mmcu=attiny11:%{!mmcu=attiny12:%{!mmcu=attiny15:%{!mmcu=attiny28: -lgcc }}}}}"
 
-#define STARTFILE_SPEC "%:device_to_startfile(%{mmcu=*:%*})"
+/* The actual definition will come from the device-specific spec file.  */
+#define STARTFILE_SPEC ""
 
 #define ENDFILE_SPEC ""
 
@@ -608,3 +592,8 @@  extern int avr_accumulate_outgoing_args
 #define ACCUMULATE_OUTGOING_ARGS avr_accumulate_outgoing_args()
 
 #define INIT_EXPANDERS avr_init_expanders()
+
+/* Flags used for io and address attributes.  */
+#define SYMBOL_FLAG_IO_LOW	(SYMBOL_FLAG_MACH_DEP << 4)
+#define SYMBOL_FLAG_IO		(SYMBOL_FLAG_MACH_DEP << 5)
+#define SYMBOL_FLAG_ADDRESS	(SYMBOL_FLAG_MACH_DEP << 6)
Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md	(revision 215966)
+++ config/avr/avr.md	(working copy)
@@ -585,7 +585,7 @@  (define_expand "mov<mode>"
   ""
   {
     rtx dest = operands[0];
-    rtx src  = operands[1];
+    rtx src  = avr_eval_addr_attrib (operands[1]);
 
     if (avr_mem_flash_p (dest))
       DONE;
@@ -5014,7 +5014,7 @@  (define_insn "sez"
 ;; Clear/set/test a single bit in I/O address space.
 
 (define_insn "*cbi"
-  [(set (mem:QI (match_operand 0 "low_io_address_operand" "n"))
+  [(set (mem:QI (match_operand 0 "low_io_address_operand" "i"))
         (and:QI (mem:QI (match_dup 0))
                 (match_operand:QI 1 "single_zero_operand" "n")))]
   ""
@@ -5026,7 +5026,7 @@  (define_insn "*cbi"
    (set_attr "cc" "none")])
 
 (define_insn "*sbi"
-  [(set (mem:QI (match_operand 0 "low_io_address_operand" "n"))
+  [(set (mem:QI (match_operand 0 "low_io_address_operand" "i"))
         (ior:QI (mem:QI (match_dup 0))
                 (match_operand:QI 1 "single_one_operand" "n")))]
   ""
@@ -5043,7 +5043,7 @@  (define_insn "*sbix_branch"
         (if_then_else
          (match_operator 0 "eqne_operator"
                          [(zero_extract:QIHI
-                           (mem:QI (match_operand 1 "low_io_address_operand" "n"))
+                           (mem:QI (match_operand 1 "low_io_address_operand" "i"))
                            (const_int 1)
                            (match_operand 2 "const_int_operand" "n"))
                           (const_int 0)])
@@ -5067,7 +5067,7 @@  (define_insn "*sbix_branch_bit7"
   [(set (pc)
         (if_then_else
          (match_operator 0 "gelt_operator"
-                         [(mem:QI (match_operand 1 "low_io_address_operand" "n"))
+                         [(mem:QI (match_operand 1 "low_io_address_operand" "i"))
                           (const_int 0)])
          (label_ref (match_operand 2 "" ""))
          (pc)))]
@@ -5382,7 +5382,7 @@  (define_peephole ; "*cpse.ne"
                       (label_ref (match_operand 0 "" ""))
                       (pc)))]
   "!AVR_HAVE_JMP_CALL
-   || !(avr_current_device->dev_attribute & AVR_ERRATA_SKIP)"
+   || !TARGET_SKIP_BUG"
   {
     if (operands[2] == CONST0_RTX (<MODE>mode))
       operands[2] = zero_reg_rtx;
@@ -6240,7 +6240,7 @@  (define_insn "*movbitqi.7"
 ;; in contrast to a IN/BST/BLD/OUT sequence we need less registers and the
 ;; operation on I/O is atomic.
 (define_insn "*insv.io"
-  [(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "n,n,n"))
+  [(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "i,i,i"))
                          (const_int 1)
                          (match_operand:QI 1 "const_0_to_7_operand"        "n,n,n"))
         (match_operand:QI 2 "nonmemory_operand"                            "L,P,r"))]
@@ -6253,7 +6253,7 @@  (define_insn "*insv.io"
    (set_attr "cc" "none")])
 
 (define_insn "*insv.not.io"
-  [(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "n"))
+  [(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "i"))
                          (const_int 1)
                          (match_operand:QI 1 "const_0_to_7_operand"        "n"))
         (not:QI (match_operand:QI 2 "register_operand"                     "r")))]
Index: config/avr/avr.opt
===================================================================
--- config/avr/avr.opt	(revision 215966)
+++ config/avr/avr.opt	(working copy)
@@ -18,14 +18,33 @@ 
 ; 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 Var(avr_mcu_index) Init(0) Enum(avr_mcu)
+Target RejectNegative Joined
 -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
+
+mskip-bug
+Target Report Mask(SKIP_BUG)
+Indicate presence of a processor erratum
+
+mrmw
+Target Report Mask(RMW)
+Enable Read-Modify-Write (RMW) instructions support/use
+
 mdeb
 Target Report Undocumented Mask(ALL_DEBUG)
 
Index: config/avr/driver-avr.c
===================================================================
--- config/avr/driver-avr.c	(revision 215966)
+++ config/avr/driver-avr.c	(working copy)
@@ -47,128 +47,3 @@  avr_set_current_device (const char *name
 
   avr_current_arch = &avr_arch_types[avr_current_device->arch];
 }
-
-/* Returns command line parameters to pass to as.  */
-
-const char*
-avr_device_to_as (int argc, const char **argv)
-{
-  if (0 == argc)
-    return NULL;
-
-  avr_set_current_device (argv[0]);
-
-  return concat ("-mmcu=", avr_current_arch->arch_name,
-    avr_current_device->dev_attribute & AVR_ERRATA_SKIP ? "" : " -mno-skip-bug",
-    avr_current_device->dev_attribute & AVR_ISA_RMW ? " -mrmw" : "", NULL);
-}
-
-/* Returns command line parameters to pass to ld.  */
-
-const char*
-avr_device_to_ld (int argc, const char **argv)
-{
-  if (0 == argc)
-    return NULL;
-
-  avr_set_current_device (argv[0]);
-
-  return concat ("-m ", avr_current_arch->arch_name, NULL);
-}
-
-/* Returns command line parameters that describe start of date section.  */
-
-const char *
-avr_device_to_data_start (int argc, const char **argv)
-{
-  unsigned long data_section_start;
-  char data_section_start_str[16];
-
-  if (0 == argc)
-    return NULL;
-
-  avr_set_current_device (argv[0]);
-  
-  if (avr_current_device->data_section_start 
-      == avr_current_arch->default_data_section_start)
-    return NULL;
-    
-  data_section_start = 0x800000 + avr_current_device->data_section_start;
-  
-  snprintf (data_section_start_str, sizeof(data_section_start_str) - 1,
-            "0x%lX", data_section_start);
-  
-  return concat ("-Tdata ", data_section_start_str, NULL);    
-}
-
-/* Returns command line parameters that describe start of text section.  */
-
-const char *
-avr_device_to_text_start (int argc, const char **argv)
-{
-  unsigned long text_section_start;
-  char text_section_start_str[16];
-
-  if (0 == argc)
-    return NULL;
-
-  avr_set_current_device (argv[0]);
-
-  if (avr_current_device->text_section_start == 0x0)
-    return NULL;
-
-  text_section_start = avr_current_device->text_section_start;
-
-  snprintf (text_section_start_str, sizeof(text_section_start_str) - 1,
-            "0x%lX", text_section_start);
-
-  return concat ("-Ttext ", text_section_start_str, NULL);
-}
-
-/* Returns command line parameters that describe the device startfile.  */
-
-const char *
-avr_device_to_startfiles (int argc, const char **argv)
-{
-  if (0 == argc)
-    return NULL;
-
-  avr_set_current_device (argv[0]);
-
-  return concat ("crt", avr_current_device->library_name, ".o%s", NULL);
-}
-
-/* Returns command line parameters that describe the device library.  */
-
-const char *
-avr_device_to_devicelib (int argc, const char **argv)
-{
-  if (0 == argc)
-    return NULL;
-
-  avr_set_current_device (argv[0]);
-
-  return concat ("-l", avr_current_device->library_name, NULL);
-}
-
-const char*
-avr_device_to_sp8 (int argc, const char **argv)
-{
-  if (0 == argc)
-    return NULL;
-
-  avr_set_current_device (argv[0]);
-
-  /* Leave "avr2" and "avr25" alone.  These two architectures are
-     the only ones that mix devices with 8-bit SP and 16-bit SP.
-     -msp8 is set by mmultilib machinery.  */
-
-  if (avr_current_device->macro == NULL
-      && (avr_current_device->arch == ARCH_AVR2
-          || avr_current_device->arch == ARCH_AVR25))
-    return "";
-
-  return (avr_current_device->dev_attribute & AVR_SHORT_SP)
-    ? "-msp8"
-    : "%<msp8";
-}
Index: config/avr/gen-avr-mmcu-specs.c
===================================================================
--- config/avr/gen-avr-mmcu-specs.c	(revision 0)
+++ config/avr/gen-avr-mmcu-specs.c	(working copy)
@@ -0,0 +1,137 @@ 
+/* Copyright (C) 1998-2014 Free Software Foundation, Inc.
+   Contributed by Joern Rennecke
+
+   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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define IN_GEN_AVR_MMCU_TEXI
+
+#include "avr-arch.h"
+#include "avr-devices.c"
+
+static void
+print_mcu (const avr_mcu_t *mcu)
+{
+  const avr_mcu_t *arch_mcu;
+
+  for (arch_mcu = mcu; arch_mcu->macro; )
+    arch_mcu--;
+  if (arch_mcu->arch != mcu->arch)
+    exit (EXIT_FAILURE);
+
+  char name[100];
+  if (snprintf (name, sizeof name, "specs-%s", mcu->name) >= sizeof name)
+   exit (EXIT_FAILURE);
+
+  FILE *f = fopen (name ,"w");
+
+  const char *sp8, *errata_skip, *rmw;
+  /* Leave "avr2" and "avr25" alone.  These two architectures are
+     the only ones that mix devices with 8-bit SP and 16-bit SP.  */
+  if (mcu->macro == NULL
+      && (mcu->arch == ARCH_AVR2 || mcu->arch == ARCH_AVR25))
+    sp8 = "";
+
+  sp8 = ((mcu->dev_attribute & AVR_SHORT_SP)
+	 ? " -msp8" : " %<msp8");
+
+  errata_skip = (mcu->dev_attribute & AVR_ERRATA_SKIP) ? " -mskip-bug" : "";
+  rmw = (mcu->dev_attribute & AVR_ISA_RMW) ? "%%{!mno-rmw: -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);
+
+  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, "*cc1:\n%s%s", errata_skip, rmw);
+  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, rmw);
+  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\n\n",
+	   *errata_skip ? "" : " -mno-skip-bug");
+
+  fprintf (f, "*link:\n%%{mrelax:--relax");
+  if (strncmp (mcu->name, "at90usb8", strlen ("at90usb8")) == 0)
+    fprintf (f, "%%{mpmem-wrap-around: --pmem-wrap-around=8k}");
+  if (strncmp (mcu->name, "atmega16", strlen ("atmega16")) == 0)
+    fprintf (f, "%%{mpmem-wrap-around: --pmem-wrap-around=16k}");
+  if (strncmp (mcu->name, "atmega32", strlen ("atmega32")) == 0
+      || strncmp (mcu->name, "at90can32", strlen ("at90can32")) == 0)
+    fprintf (f, "%%{mpmem-wrap-around: --pmem-wrap-around=32k}");
+  if (strncmp (mcu->name, "atmega64", strlen ("atmega64")) == 0
+      || strncmp (mcu->name, "at90can64", strlen ("at90can64")) == 0
+      || strncmp (mcu->name, "at90usb64", strlen ("at90usb64")) == 0)
+    fprintf (f, "%%{mpmem-wrap-around: --pmem-wrap-around=64k}");
+  fprintf (f, "} %%{march=*:-m%%*}");
+  if (mcu->data_section_start
+      != avr_arch_types[mcu->arch].default_data_section_start)
+    fprintf (f, " -Tdata 0x%lX", 0x800000UL + mcu->data_section_start);
+  if (mcu->text_section_start != 0x0)
+    fprintf (f, " -Ttext 0x%lX", mcu->text_section_start);
+
+  fprintf (f, " %%{shared:%%eshared is not supported}\n\n");
+
+  fprintf (f, "*lib:\n");
+  if (strncmp (mcu->name, "mmcu=at90s1", strlen ("mmcu=at90s1")) != 0
+      && strncmp (mcu->name, "mmcu=attiny11", strlen ("mmcu=attiny11")) != 0
+      && strncmp (mcu->name, "mmcu=attiny12", strlen ("mmcu=attiny12")) != 0
+      && strncmp (mcu->name, "mmcu=attiny15", strlen ("mmcu=attiny15")) != 0
+      && strncmp (mcu->name, "mmcu=attiny28", strlen ("mmcu=attiny28")) != 0)
+    {
+      fprintf (f, "-lc");
+      if (mcu->macro)
+	fprintf (f, " dev/%s/libdev.a%%s", mcu->name);
+    }
+  fprintf (f, "\n\n");
+
+  fprintf (f, "*libgcc:\n");
+  if (strncmp (mcu->name, "mmcu=at90s1", strlen ("mmcu=at90s1")) != 0
+      && strncmp (mcu->name, "mmcu=attiny11", strlen ("mmcu=attiny11")) != 0
+      && strncmp (mcu->name, "mmcu=attiny12", strlen ("mmcu=attiny12")) != 0
+      && strncmp (mcu->name, "mmcu=attiny15", strlen ("mmcu=attiny15")) != 0
+      && strncmp (mcu->name, "mmcu=attiny28", strlen ("mmcu=attiny28")) != 0)
+    fprintf (f, "-lgcc");
+  fprintf (f, "\n\n");
+
+  fprintf (f, "*startfile:\ndev/%s/crt1.o%%s\n\n", mcu->name);
+}
+
+int main (void)
+{
+  enum avr_arch arch = ARCH_UNKNOWN;
+  size_t i, n_mcus = 0;
+  const avr_mcu_t *mcu;
+
+  for (mcu = avr_mcu_types; mcu->name; mcu++)
+    print_mcu (mcu);
+
+  return EXIT_SUCCESS;
+}
Index: config/avr/genmultilib.awk
===================================================================
--- config/avr/genmultilib.awk	(revision 215966)
+++ config/avr/genmultilib.awk	(working copy)
@@ -97,7 +97,7 @@ 
 	cores[n_cores] = core
 	n_cores++
 	tiny_stack[core] = 0
-	option[core] = "mmcu=" core
+	option[core] = "march=" core
 
 	next
     }
@@ -135,7 +135,6 @@ 
 #    m_options     <->    MULTILIB_OPTIONS         Makefile
 #    m_dirnames    <->    MULTILIB_DIRNAMES           "
 #    m_exceptions  <->    MULTILIB_EXCEPTIONS         "
-#    m_matches     <->    MULTILIB_MATCHES            "
 #
 ##################################################################
 
@@ -143,7 +142,6 @@ 
     m_options    = "\nMULTILIB_OPTIONS = "
     m_dirnames   = "\nMULTILIB_DIRNAMES ="
     m_exceptions = "\nMULTILIB_EXCEPTIONS ="
-    m_matches    = "\nMULTILIB_MATCHES ="
 
     ##############################################################
     # Compose MULTILIB_OPTIONS.  This represents the Cross-Product
@@ -169,8 +167,6 @@ 
 	line = option[core] ":" option[mcu[t]]
 	gsub ("=", "?", line)
 	gsub (":", "=", line)
-
-	m_matches = m_matches " \\\n\t" line
     }
 
     ####################################################################
@@ -221,6 +217,5 @@ 
 	print m_options
 	print m_dirnames
 	print m_exceptions
-	print m_matches
     }
 }
Index: config/avr/genopt.sh
===================================================================
--- config/avr/genopt.sh	(revision 215966)
+++ config/avr/genopt.sh	(working copy)
@@ -41,19 +41,18 @@ 
 ; <http://www.gnu.org/licenses/>.
 
 Enum
-Name(avr_mcu) Type(int)
-Known MCU names:
+Name(avr_arch) Type(enum avr_arch)
+Known MCU architectures:
 
 EOF
 
 awk -F'[(, 	]+' 'BEGIN {
-    value = 0
 }
-/^AVR_MCU/ {
+/^AVR_MCU.*NULL/ {
     name = $2
+    value = $3
     gsub("\"", "", name)
     print "EnumValue"
-    print "Enum(avr_mcu) String(" name ") Value(" value ")"
+    print "Enum(avr_arch) String(" name ") Value(" value ")"
     print ""
-    value++
 }' $1
Index: config/avr/predicates.md
===================================================================
--- config/avr/predicates.md	(revision 215966)
+++ config/avr/predicates.md	(working copy)
@@ -43,10 +43,12 @@  (define_predicate "stack_register_operan
        (match_test "REGNO (op) == REG_SP")))
 
 ;; Return true if OP is a valid address for lower half of I/O space.
-(define_predicate "low_io_address_operand"
-  (and (match_code "const_int")
-       (match_test "IN_RANGE (INTVAL (op) - avr_current_arch->sfr_offset,
-                              0, 0x1f)")))
+(define_special_predicate "low_io_address_operand"
+  (ior (and (match_code "const_int")
+	    (match_test "IN_RANGE (INTVAL (op) - avr_current_arch->sfr_offset,
+				   0, 020 - GET_MODE_SIZE (mode))"))
+       (and (match_code "symbol_ref")
+	    (match_test "SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_IO_LOW"))))
 
 ;; Return true if OP is a valid address for high half of I/O space.
 (define_predicate "high_io_address_operand"
@@ -55,10 +57,12 @@  (define_predicate "high_io_address_opera
                               0x20, 0x3F)")))
 
 ;; Return true if OP is a valid address of I/O space.
-(define_predicate "io_address_operand"
-  (and (match_code "const_int")
-       (match_test "IN_RANGE (INTVAL (op) - avr_current_arch->sfr_offset,
-                              0, 0x40 - GET_MODE_SIZE (mode))")))
+(define_special_predicate "io_address_operand"
+  (ior (and (match_code "const_int")
+	    (match_test "IN_RANGE (INTVAL (op) - avr_current_arch->sfr_offset,
+				   0, 0x40 - GET_MODE_SIZE (mode))"))
+       (and (match_code "symbol_ref")
+	    (match_test "SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_IO"))))
 
 ;; Return 1 if OP is a general operand not in flash memory
 (define_predicate "nop_general_operand"
Index: config/avr/t-avr
===================================================================
--- config/avr/t-avr	(revision 215966)
+++ config/avr/t-avr	(working copy)
@@ -67,9 +67,30 @@  gen-avr-mmcu-texi$(build_exeext): $(srcd
   $(srcdir)/config/avr/avr-arch.h
 	$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $< -o $@
 
+gen-avr-mmcu-specs$(build_exeext): $(srcdir)/config/avr/gen-avr-mmcu-specs.c \
+  $(AVR_MCUS) $(srcdir)/config/avr/avr-devices.c \
+  $(srcdir)/config/avr/avr-arch.h
+	$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $< -o $@
+
 $(srcdir)/doc/avr-mmcu.texi: gen-avr-mmcu-texi$(build_exeext)
 	$(RUN_GEN) ./$< > $@
 
+s-device-specs: gen-avr-mmcu-specs$(build_exeext)
+	rm -rf device-specs
+	mkdir device-specs && cd device-specs && $(RUN_GEN) ../$<
+	$(STAMP) s-device-specs
+
+GCC_PASSES+=s-device-specs
+
+install-driver: install-device-specs
+
+install-device-specs: s-device-specs installdirs
+	-rm -rf $(DESTDIR)$(libsubdir)/device-specs
+	mkdir $(DESTDIR)$(libsubdir)/device-specs
+	-for file in device-specs/*; do \
+	$(INSTALL_PROGRAM) $${file} $(DESTDIR)$(libsubdir)/$${file}; \
+	done
+
 # Map -mmcu= to the right multilib variant
 # MULTILIB_OPTIONS
 # MULTILIB_DIRNAMES
Index: config/avr/t-multilib
===================================================================
--- config/avr/t-multilib	(revision 215966)
+++ config/avr/t-multilib	(working copy)
@@ -21,262 +21,20 @@ 
 # along with GCC; see the file COPYING3.  If not see
 # <http://www.gnu.org/licenses/>.
 
-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 msp8
+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 msp8
 
 MULTILIB_DIRNAMES =  avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 tiny-stack avr25/tiny-stack
 
 MULTILIB_EXCEPTIONS = \
-	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
-
-MULTILIB_MATCHES = \
-	mmcu?avr2=mmcu?at90s2313 \
-	mmcu?avr2=mmcu?at90s2323 \
-	mmcu?avr2=mmcu?at90s2333 \
-	mmcu?avr2=mmcu?at90s2343 \
-	mmcu?avr2=mmcu?attiny22 \
-	mmcu?avr2=mmcu?attiny26 \
-	mmcu?avr2=mmcu?at90s4414 \
-	mmcu?avr2=mmcu?at90s4433 \
-	mmcu?avr2=mmcu?at90s4434 \
-	mmcu?avr2=mmcu?at90s8515 \
-	mmcu?avr2=mmcu?at90c8534 \
-	mmcu?avr2=mmcu?at90s8535 \
-	mmcu?avr25=mmcu?ata5272 \
-	mmcu?avr25=mmcu?ata6616c \
-	mmcu?avr25=mmcu?attiny13 \
-	mmcu?avr25=mmcu?attiny13a \
-	mmcu?avr25=mmcu?attiny2313 \
-	mmcu?avr25=mmcu?attiny2313a \
-	mmcu?avr25=mmcu?attiny24 \
-	mmcu?avr25=mmcu?attiny24a \
-	mmcu?avr25=mmcu?attiny4313 \
-	mmcu?avr25=mmcu?attiny44 \
-	mmcu?avr25=mmcu?attiny44a \
-	mmcu?avr25=mmcu?attiny441 \
-	mmcu?avr25=mmcu?attiny84 \
-	mmcu?avr25=mmcu?attiny84a \
-	mmcu?avr25=mmcu?attiny25 \
-	mmcu?avr25=mmcu?attiny45 \
-	mmcu?avr25=mmcu?attiny85 \
-	mmcu?avr25=mmcu?attiny261 \
-	mmcu?avr25=mmcu?attiny261a \
-	mmcu?avr25=mmcu?attiny461 \
-	mmcu?avr25=mmcu?attiny461a \
-	mmcu?avr25=mmcu?attiny861 \
-	mmcu?avr25=mmcu?attiny861a \
-	mmcu?avr25=mmcu?attiny43u \
-	mmcu?avr25=mmcu?attiny87 \
-	mmcu?avr25=mmcu?attiny48 \
-	mmcu?avr25=mmcu?attiny88 \
-	mmcu?avr25=mmcu?attiny828 \
-	mmcu?avr25=mmcu?attiny841 \
-	mmcu?avr25=mmcu?at86rf401 \
-	mmcu?avr3=mmcu?at43usb355 \
-	mmcu?avr3=mmcu?at76c711 \
-	mmcu?avr31=mmcu?atmega103 \
-	mmcu?avr31=mmcu?at43usb320 \
-	mmcu?avr35=mmcu?ata5505 \
-	mmcu?avr35=mmcu?ata6617c \
-	mmcu?avr35=mmcu?ata664251 \
-	mmcu?avr35=mmcu?at90usb82 \
-	mmcu?avr35=mmcu?at90usb162 \
-	mmcu?avr35=mmcu?atmega8u2 \
-	mmcu?avr35=mmcu?atmega16u2 \
-	mmcu?avr35=mmcu?atmega32u2 \
-	mmcu?avr35=mmcu?attiny167 \
-	mmcu?avr35=mmcu?attiny1634 \
-	mmcu?avr4=mmcu?ata6285 \
-	mmcu?avr4=mmcu?ata6286 \
-	mmcu?avr4=mmcu?ata6289 \
-	mmcu?avr4=mmcu?ata6612c \
-	mmcu?avr4=mmcu?atmega8 \
-	mmcu?avr4=mmcu?atmega8a \
-	mmcu?avr4=mmcu?atmega48 \
-	mmcu?avr4=mmcu?atmega48a \
-	mmcu?avr4=mmcu?atmega48p \
-	mmcu?avr4=mmcu?atmega48pa \
-	mmcu?avr4=mmcu?atmega88 \
-	mmcu?avr4=mmcu?atmega88a \
-	mmcu?avr4=mmcu?atmega88p \
-	mmcu?avr4=mmcu?atmega88pa \
-	mmcu?avr4=mmcu?atmega8515 \
-	mmcu?avr4=mmcu?atmega8535 \
-	mmcu?avr4=mmcu?atmega8hva \
-	mmcu?avr4=mmcu?at90pwm1 \
-	mmcu?avr4=mmcu?at90pwm2 \
-	mmcu?avr4=mmcu?at90pwm2b \
-	mmcu?avr4=mmcu?at90pwm3 \
-	mmcu?avr4=mmcu?at90pwm3b \
-	mmcu?avr4=mmcu?at90pwm81 \
-	mmcu?avr5=mmcu?ata5702m322 \
-	mmcu?avr5=mmcu?ata5782 \
-	mmcu?avr5=mmcu?ata5790 \
-	mmcu?avr5=mmcu?ata5790n \
-	mmcu?avr5=mmcu?ata5795 \
-	mmcu?avr5=mmcu?ata5831 \
-	mmcu?avr5=mmcu?ata6613c \
-	mmcu?avr5=mmcu?ata6614q \
-	mmcu?avr5=mmcu?atmega16 \
-	mmcu?avr5=mmcu?atmega16a \
-	mmcu?avr5=mmcu?atmega161 \
-	mmcu?avr5=mmcu?atmega162 \
-	mmcu?avr5=mmcu?atmega163 \
-	mmcu?avr5=mmcu?atmega164a \
-	mmcu?avr5=mmcu?atmega164p \
-	mmcu?avr5=mmcu?atmega164pa \
-	mmcu?avr5=mmcu?atmega165 \
-	mmcu?avr5=mmcu?atmega165a \
-	mmcu?avr5=mmcu?atmega165p \
-	mmcu?avr5=mmcu?atmega165pa \
-	mmcu?avr5=mmcu?atmega168 \
-	mmcu?avr5=mmcu?atmega168a \
-	mmcu?avr5=mmcu?atmega168p \
-	mmcu?avr5=mmcu?atmega168pa \
-	mmcu?avr5=mmcu?atmega169 \
-	mmcu?avr5=mmcu?atmega169a \
-	mmcu?avr5=mmcu?atmega169p \
-	mmcu?avr5=mmcu?atmega169pa \
-	mmcu?avr5=mmcu?atmega16hvb \
-	mmcu?avr5=mmcu?atmega16hvbrevb \
-	mmcu?avr5=mmcu?atmega16m1 \
-	mmcu?avr5=mmcu?atmega16u4 \
-	mmcu?avr5=mmcu?atmega32a \
-	mmcu?avr5=mmcu?atmega32 \
-	mmcu?avr5=mmcu?atmega323 \
-	mmcu?avr5=mmcu?atmega324a \
-	mmcu?avr5=mmcu?atmega324p \
-	mmcu?avr5=mmcu?atmega324pa \
-	mmcu?avr5=mmcu?atmega325 \
-	mmcu?avr5=mmcu?atmega325a \
-	mmcu?avr5=mmcu?atmega325p \
-	mmcu?avr5=mmcu?atmega325pa \
-	mmcu?avr5=mmcu?atmega3250 \
-	mmcu?avr5=mmcu?atmega3250a \
-	mmcu?avr5=mmcu?atmega3250p \
-	mmcu?avr5=mmcu?atmega3250pa \
-	mmcu?avr5=mmcu?atmega328 \
-	mmcu?avr5=mmcu?atmega328p \
-	mmcu?avr5=mmcu?atmega329 \
-	mmcu?avr5=mmcu?atmega329a \
-	mmcu?avr5=mmcu?atmega329p \
-	mmcu?avr5=mmcu?atmega329pa \
-	mmcu?avr5=mmcu?atmega3290 \
-	mmcu?avr5=mmcu?atmega3290a \
-	mmcu?avr5=mmcu?atmega3290p \
-	mmcu?avr5=mmcu?atmega3290pa \
-	mmcu?avr5=mmcu?atmega32c1 \
-	mmcu?avr5=mmcu?atmega32m1 \
-	mmcu?avr5=mmcu?atmega32u4 \
-	mmcu?avr5=mmcu?atmega32u6 \
-	mmcu?avr5=mmcu?atmega406 \
-	mmcu?avr5=mmcu?atmega64 \
-	mmcu?avr5=mmcu?atmega64a \
-	mmcu?avr5=mmcu?atmega640 \
-	mmcu?avr5=mmcu?atmega644 \
-	mmcu?avr5=mmcu?atmega644a \
-	mmcu?avr5=mmcu?atmega644p \
-	mmcu?avr5=mmcu?atmega644pa \
-	mmcu?avr5=mmcu?atmega645 \
-	mmcu?avr5=mmcu?atmega645a \
-	mmcu?avr5=mmcu?atmega645p \
-	mmcu?avr5=mmcu?atmega6450 \
-	mmcu?avr5=mmcu?atmega6450a \
-	mmcu?avr5=mmcu?atmega6450p \
-	mmcu?avr5=mmcu?atmega649 \
-	mmcu?avr5=mmcu?atmega649a \
-	mmcu?avr5=mmcu?atmega649p \
-	mmcu?avr5=mmcu?atmega6490 \
-	mmcu?avr5=mmcu?atmega16hva \
-	mmcu?avr5=mmcu?atmega16hva2 \
-	mmcu?avr5=mmcu?atmega32hvb \
-	mmcu?avr5=mmcu?atmega6490a \
-	mmcu?avr5=mmcu?atmega6490p \
-	mmcu?avr5=mmcu?atmega64c1 \
-	mmcu?avr5=mmcu?atmega64m1 \
-	mmcu?avr5=mmcu?atmega64hve \
-	mmcu?avr5=mmcu?atmega64hve2 \
-	mmcu?avr5=mmcu?atmega64rfr2 \
-	mmcu?avr5=mmcu?atmega644rfr2 \
-	mmcu?avr5=mmcu?atmega32hvbrevb \
-	mmcu?avr5=mmcu?at90can32 \
-	mmcu?avr5=mmcu?at90can64 \
-	mmcu?avr5=mmcu?at90pwm161 \
-	mmcu?avr5=mmcu?at90pwm216 \
-	mmcu?avr5=mmcu?at90pwm316 \
-	mmcu?avr5=mmcu?at90scr100 \
-	mmcu?avr5=mmcu?at90usb646 \
-	mmcu?avr5=mmcu?at90usb647 \
-	mmcu?avr5=mmcu?at94k \
-	mmcu?avr5=mmcu?m3000 \
-	mmcu?avr51=mmcu?atmega128 \
-	mmcu?avr51=mmcu?atmega128a \
-	mmcu?avr51=mmcu?atmega1280 \
-	mmcu?avr51=mmcu?atmega1281 \
-	mmcu?avr51=mmcu?atmega1284 \
-	mmcu?avr51=mmcu?atmega1284p \
-	mmcu?avr51=mmcu?atmega128rfa1 \
-	mmcu?avr51=mmcu?atmega128rfr2 \
-	mmcu?avr51=mmcu?atmega1284rfr2 \
-	mmcu?avr51=mmcu?at90can128 \
-	mmcu?avr51=mmcu?at90usb1286 \
-	mmcu?avr51=mmcu?at90usb1287 \
-	mmcu?avr6=mmcu?atmega2560 \
-	mmcu?avr6=mmcu?atmega2561 \
-	mmcu?avr6=mmcu?atmega256rfr2 \
-	mmcu?avr6=mmcu?atmega2564rfr2 \
-	mmcu?avrxmega2=mmcu?atxmega8e5 \
-	mmcu?avrxmega2=mmcu?atxmega16a4 \
-	mmcu?avrxmega2=mmcu?atxmega16d4 \
-	mmcu?avrxmega2=mmcu?atxmega16e5 \
-	mmcu?avrxmega2=mmcu?atxmega32a4 \
-	mmcu?avrxmega2=mmcu?atxmega32c3 \
-	mmcu?avrxmega2=mmcu?atxmega32d3 \
-	mmcu?avrxmega2=mmcu?atxmega32d4 \
-	mmcu?avrxmega2=mmcu?atxmega16a4u \
-	mmcu?avrxmega2=mmcu?atxmega16c4 \
-	mmcu?avrxmega2=mmcu?atxmega32a4u \
-	mmcu?avrxmega2=mmcu?atxmega32c4 \
-	mmcu?avrxmega2=mmcu?atxmega32e5 \
-	mmcu?avrxmega4=mmcu?atxmega64a3 \
-	mmcu?avrxmega4=mmcu?atxmega64d3 \
-	mmcu?avrxmega4=mmcu?atxmega64a3u \
-	mmcu?avrxmega4=mmcu?atxmega64a4u \
-	mmcu?avrxmega4=mmcu?atxmega64b1 \
-	mmcu?avrxmega4=mmcu?atxmega64b3 \
-	mmcu?avrxmega4=mmcu?atxmega64c3 \
-	mmcu?avrxmega4=mmcu?atxmega64d4 \
-	mmcu?avrxmega5=mmcu?atxmega64a1 \
-	mmcu?avrxmega5=mmcu?atxmega64a1u \
-	mmcu?avrxmega6=mmcu?atxmega128a3 \
-	mmcu?avrxmega6=mmcu?atxmega128d3 \
-	mmcu?avrxmega6=mmcu?atxmega192a3 \
-	mmcu?avrxmega6=mmcu?atxmega192d3 \
-	mmcu?avrxmega6=mmcu?atxmega256a3 \
-	mmcu?avrxmega6=mmcu?atxmega256a3b \
-	mmcu?avrxmega6=mmcu?atxmega256a3bu \
-	mmcu?avrxmega6=mmcu?atxmega256d3 \
-	mmcu?avrxmega6=mmcu?atxmega128a3u \
-	mmcu?avrxmega6=mmcu?atxmega128b1 \
-	mmcu?avrxmega6=mmcu?atxmega128b3 \
-	mmcu?avrxmega6=mmcu?atxmega128c3 \
-	mmcu?avrxmega6=mmcu?atxmega128d4 \
-	mmcu?avrxmega6=mmcu?atxmega192a3u \
-	mmcu?avrxmega6=mmcu?atxmega192c3 \
-	mmcu?avrxmega6=mmcu?atxmega256a3u \
-	mmcu?avrxmega6=mmcu?atxmega256c3 \
-	mmcu?avrxmega6=mmcu?atxmega384c3 \
-	mmcu?avrxmega6=mmcu?atxmega384d3 \
-	mmcu?avrxmega7=mmcu?atxmega128a1 \
-	mmcu?avrxmega7=mmcu?atxmega128a1u \
-	mmcu?avrxmega7=mmcu?atxmega128a4u
+	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
Index: doc/extend.texi
===================================================================
--- doc/extend.texi	(revision 215966)
+++ doc/extend.texi	(working copy)
@@ -5318,6 +5318,47 @@  normally resides in the data memory (RAM
 
 See also the @ref{AVR Named Address Spaces} section for
 an alternate way to locate and access data in flash memory.
+
+@item io
+@itemx io (@var{addr})
+Variables with the @code{io} attribute are used to address
+memory-mapped peripherals in the io address range.
+If an address is specified, the variable
+is assigned that address, and the value is interpreted as an
+address in the data address space.
+Example:
+
+@smallexample
+volatile int porta __attribute__((io (0x22)));
+@end smallexample
+
+The address specified in the address in the data address range.
+
+Otherwise, the variable it is not assigned an address, but the
+compiler will still use in/out instructions where applicable,
+assuming some other module assigns an address in the io address range.
+Example:
+
+@smallexample
+extern volatile int porta __attribute__((io));
+@end smallexample
+
+@item io_low
+@itemx io_low (@var{addr})
+This is like the @code{io} attribute, but additionally it informs the
+compiler that the object lies in the lower half of the I/O area,
+allowing the use of @code{cbi}, @code{sbi}, @code{sbic} and @code{sbis}
+instructions.
+
+@item address
+@itemx address (@var{addr})
+Variables with the @code{address} attribute are used to address
+memory-mapped peripherals that may lie outside the io address range.
+
+@smallexample
+volatile int porta __attribute__((address (0x600)));
+@end smallexample
+
 @end table
 
 @subsection Blackfin Variable Attributes