OSDN Git Service

* defaults.h (CONSTANT_ADDRESS_P): Provide a default definition.
[pf3gnuchains/gcc-fork.git] / gcc / config / avr / avr.h
index 53a0f9f..782ad11 100644 (file)
@@ -1,14 +1,14 @@
 /* Definitions of target machine for GNU compiler,
    for ATMEL AVR at90s8515, ATmega103/103L, ATmega603/603L microcontrollers.
-   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-   Free Software Foundation, Inc.
-   Contributed by Denis Chertykov (denisc@overta.ru)
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 
+   2008, 2009 Free Software Foundation, Inc.
+   Contributed by Denis Chertykov (chertykov@gmail.com)
 
 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 2, or (at your option)
+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,
@@ -17,39 +17,107 @@ 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 COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* Names to predefine in the preprocessor for this target machine.  */
 
-#define TARGET_CPU_CPP_BUILTINS()              \
-  do                                           \
-    {                                          \
-      builtin_define_std ("AVR");              \
-      if (avr_base_arch_macro)                 \
-       builtin_define (avr_base_arch_macro);   \
-      if (avr_extra_arch_macro)                        \
-       builtin_define (avr_extra_arch_macro);  \
-      if (avr_asm_only_p)                      \
-       builtin_define ("__AVR_ASM_ONLY__");    \
-      if (avr_enhanced_p)                      \
-       builtin_define ("__AVR_ENHANCED__");    \
-      if (avr_mega_p)                          \
-       builtin_define ("__AVR_MEGA__");        \
-      if (TARGET_NO_INTERRUPTS)                        \
-       builtin_define ("__NO_INTERRUPTS__");   \
-    }                                          \
-  while (0)
+struct base_arch_s {
+  /* Assembler only.  */
+  int asm_only;
+
+  /* Core have 'MUL*' instructions.  */
+  int have_mul;
+
+  /* Core have 'CALL' and 'JMP' instructions.  */
+  int have_jmp_call;
+
+  /* Core have 'MOVW' and 'LPM Rx,Z' instructions.  */
+  int have_movw_lpmx;
+
+  /* Core have 'ELPM' instructions.  */
+  int have_elpm;
+
+  /* Core have 'ELPM Rx,Z' instructions.  */
+  int have_elpmx;
+
+  /* Core have 'EICALL' and 'EIJMP' instructions.  */
+  int have_eijmp_eicall;
+
+  /* Reserved for xmega architecture.  */
+  int reserved;
+
+  /* Reserved for xmega architecture.  */
+  int reserved2;
+  
+  /* Default start of data section address for architecture.  */
+  int default_data_section_start;
+
+  const char *const macro;
+  
+  /* Architecture name.  */
+  const char *const arch_name;  
+};
+
+/* These names are used as the index into the avr_arch_types[] table 
+   above.  */
+
+enum avr_arch
+{
+  ARCH_UNKNOWN,
+  ARCH_AVR1,
+  ARCH_AVR2,
+  ARCH_AVR25,
+  ARCH_AVR3,
+  ARCH_AVR31,
+  ARCH_AVR35,
+  ARCH_AVR4,
+  ARCH_AVR5,
+  ARCH_AVR51,
+  ARCH_AVR6
+};
+
+struct mcu_type_s {
+  /* Device name.  */
+  const char *const name;
+  
+  /* Index in avr_arch_types[].  */
+  int arch; 
+  
+  /* Must lie outside user's namespace.  NULL == no macro.  */
+  const char *const macro;
+  
+  /* Stack pointer have 8 bits width.  */
+  int short_sp;
+  
+  /* Start of data section.  */
+  int data_section_start;
+  
+  /* Name of device library.  */
+  const char *const library_name; 
+};
+
+extern const struct base_arch_s *avr_current_arch;
+extern const struct mcu_type_s *avr_current_device;
+extern const struct mcu_type_s avr_mcu_types[];
+extern const struct base_arch_s avr_arch_types[];
 
-extern const char *avr_base_arch_macro;
-extern const char *avr_extra_arch_macro;
-extern int avr_mega_p;
-extern int avr_enhanced_p;
-extern int avr_asm_only_p;
+#define TARGET_CPU_CPP_BUILTINS()      avr_cpu_cpp_builtins (pfile)
 
-#define AVR_MEGA (avr_mega_p && !TARGET_SHORT_CALLS)
-#define AVR_ENHANCED (avr_enhanced_p)
+#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS)
+extern GTY(()) section *progmem_section;
+#endif
+
+#define AVR_HAVE_JMP_CALL (avr_current_arch->have_jmp_call && !TARGET_SHORT_CALLS)
+#define AVR_HAVE_MUL (avr_current_arch->have_mul)
+#define AVR_HAVE_MOVW (avr_current_arch->have_movw_lpmx)
+#define AVR_HAVE_LPMX (avr_current_arch->have_movw_lpmx)
+#define AVR_HAVE_RAMPZ (avr_current_arch->have_elpm)
+#define AVR_HAVE_EIJMP_EICALL (avr_current_arch->have_eijmp_eicall)
+#define AVR_HAVE_8BIT_SP (avr_current_device->short_sp || TARGET_TINY_STACK)
+
+#define AVR_2_BYTE_PC (!AVR_HAVE_EIJMP_EICALL)
+#define AVR_3_BYTE_PC (AVR_HAVE_EIJMP_EICALL)
 
 #define TARGET_VERSION fprintf (stderr, " (GNU assembler syntax)");
 
@@ -85,6 +153,9 @@ extern int avr_asm_only_p;
 /* No data type wants to be aligned rounder than this.  */
 #define BIGGEST_ALIGNMENT 8
 
+#define MAX_OFILE_ALIGNMENT (32768 * 8)
+
+#define TARGET_VTABLE_ENTRY_ALIGN 8
 
 #define STRICT_ALIGNMENT 0
 
@@ -203,11 +274,6 @@ enum reg_class {
                   "GENERAL_REGS", /* r0 - r31 */               \
                   "ALL_REGS" }
 
-#define REG_X 26
-#define REG_Y 28
-#define REG_Z 30
-#define REG_W 24
-
 #define REG_CLASS_CONTENTS {                                           \
   {0x00000000,0x00000000},     /* NO_REGS */                           \
   {0x00000001,0x00000000},     /* R0_REG */                            \
@@ -231,12 +297,23 @@ enum reg_class {
 
 #define REGNO_REG_CLASS(R) avr_regno_reg_class(R)
 
+/* The following macro defines cover classes for Integrated Register
+   Allocator.  Cover classes is a set of non-intersected register
+   classes covering all hard registers used for register allocation
+   purpose.  Any move between two registers of a cover class should be
+   cheaper than load or store of the registers.  The macro value is
+   array of register classes with LIM_REG_CLASSES used as the end
+   marker.  */
+
+#define IRA_COVER_CLASSES               \
+{                                       \
+  GENERAL_REGS, LIM_REG_CLASSES         \
+}
+
 #define BASE_REG_CLASS (reload_completed ? BASE_POINTER_REGS : POINTER_REGS)
 
 #define INDEX_REG_CLASS NO_REGS
 
-#define REG_CLASS_FROM_LETTER(C) avr_reg_class_from_letter(C)
-
 #define REGNO_OK_FOR_BASE_P(r) (((r) < FIRST_PSEUDO_REGISTER           \
                                 && ((r) == REG_X                       \
                                     || (r) == REG_Y                    \
@@ -259,23 +336,6 @@ enum reg_class {
 
 #define CLASS_MAX_NREGS(CLASS, MODE)   class_max_nregs (CLASS, MODE)
 
-#define CONST_OK_FOR_LETTER_P(VALUE, C)                                \
-  ((C) == 'I' ? (VALUE) >= 0 && (VALUE) <= 63 :                        \
-   (C) == 'J' ? (VALUE) <= 0 && (VALUE) >= -63:                        \
-   (C) == 'K' ? (VALUE) == 2 :                                 \
-   (C) == 'L' ? (VALUE) == 0 :                                 \
-   (C) == 'M' ? (VALUE) >= 0 && (VALUE) <= 0xff :              \
-   (C) == 'N' ? (VALUE) == -1:                                 \
-   (C) == 'O' ? (VALUE) == 8 || (VALUE) == 16 || (VALUE) == 24:        \
-   (C) == 'P' ? (VALUE) == 1 :                                 \
-   0)
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
-  ((C) == 'G' ? (VALUE) == CONST0_RTX (SFmode) \
-   : 0)
-
-#define EXTRA_CONSTRAINT(x, c) extra_constraint(x, c)
-
 #define STACK_PUSH_CODE POST_DEC
 
 #define STACK_GROWS_DOWNWARD
@@ -296,27 +356,23 @@ enum reg_class {
 
 #define STATIC_CHAIN_REGNUM 2
 
-#define FRAME_POINTER_REQUIRED frame_pointer_required_p()
+/* Offset from the frame pointer register value to the top of the stack.  */
+#define FRAME_POINTER_CFA_OFFSET(FNDECL) 0
 
 #define ELIMINABLE_REGS {                                      \
       {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM},              \
        {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}            \
        ,{FRAME_POINTER_REGNUM+1,STACK_POINTER_REGNUM+1}}
 
-#define CAN_ELIMINATE(FROM, TO) (((FROM) == ARG_POINTER_REGNUM            \
-                                 && (TO) == FRAME_POINTER_REGNUM)         \
-                                || (((FROM) == FRAME_POINTER_REGNUM       \
-                                     || (FROM) == FRAME_POINTER_REGNUM+1) \
-                                    && ! FRAME_POINTER_REQUIRED           \
-                                    ))
-
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                   \
-     OFFSET = initial_elimination_offset (FROM, TO)
+  OFFSET = avr_initial_elimination_offset (FROM, TO)
 
 #define RETURN_ADDR_RTX(count, x) \
   gen_rtx_MEM (Pmode, memory_address (Pmode, plus_constant (tem, 1)))
 
-#define PUSH_ROUNDING(NPUSHED) (NPUSHED)
+/* Don't use Push rounding. expr.c: emit_single_push_insn is broken 
+   for POST_DEC targets (PR27386).  */
+/*#define PUSH_ROUNDING(NPUSHED) (NPUSHED)*/
 
 #define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
 
@@ -339,37 +395,19 @@ extern int avr_reg_order[];
 
 #define RET_REGISTER avr_ret_register ()
 
-#define FUNCTION_VALUE(VALTYPE, FUNC) avr_function_value (VALTYPE, FUNC)
-
 #define LIBCALL_VALUE(MODE)  avr_libcall_value (MODE)
 
 #define FUNCTION_VALUE_REGNO_P(N) ((int) (N) == RET_REGISTER)
 
 #define DEFAULT_PCC_STRUCT_RETURN 0
 
-#define EPILOGUE_USES(REGNO) 0
+#define EPILOGUE_USES(REGNO) avr_epilogue_uses(REGNO)
 
 #define HAVE_POST_INCREMENT 1
 #define HAVE_PRE_DECREMENT 1
 
-#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
-
 #define MAX_REGS_PER_ADDRESS 1
 
-#ifdef REG_OK_STRICT
-#  define GO_IF_LEGITIMATE_ADDRESS(mode, operand, ADDR)        \
-{                                                      \
-  if (legitimate_address_p (mode, operand, 1))         \
-    goto ADDR;                                         \
-}
-#  else
-#  define GO_IF_LEGITIMATE_ADDRESS(mode, operand, ADDR)        \
-{                                                      \
-  if (legitimate_address_p (mode, operand, 0))         \
-    goto ADDR;                                         \
-}
-#endif
-
 #define REG_OK_FOR_BASE_NOSTRICT_P(X) \
   (REGNO (X) >= FIRST_PSEUDO_REGISTER || REG_OK_FOR_BASE_STRICT_P(X))
 
@@ -383,14 +421,12 @@ extern int avr_reg_order[];
 
 #define REG_OK_FOR_INDEX_P(X) 0
 
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)                         \
-{                                                                      \
-  (X) = legitimize_address (X, OLDX, MODE);                            \
-  if (memory_address_p (MODE, X))                                      \
-    goto WIN;                                                          \
-}
-
 #define XEXP_(X,Y) (X)
+
+/* LEGITIMIZE_RELOAD_ADDRESS will allow register R26/27 to be used, where it
+   is no worse than normal base pointers R28/29 and R30/31. For example:
+   If base offset is greater than 63 bytes or for R++ or --R addressing.  */
+   
 #define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)    \
 do {                                                                       \
   if (1&&(GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC))            \
@@ -402,6 +438,7 @@ do {                                                                            \
     }                                                                      \
   if (GET_CODE (X) == PLUS                                                 \
       && REG_P (XEXP (X, 0))                                               \
+      && reg_equiv_constant[REGNO (XEXP (X, 0))] == 0                      \
       && GET_CODE (XEXP (X, 1)) == CONST_INT                               \
       && INTVAL (XEXP (X, 1)) >= 1)                                        \
     {                                                                      \
@@ -420,10 +457,6 @@ do {                                                                           \
                           OPNUM, TYPE);                                    \
              goto WIN;                                                     \
            }                                                               \
-         push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL,           \
-                      BASE_POINTER_REGS, GET_MODE (X), VOIDmode, 0, 0,     \
-                      OPNUM, TYPE);                                        \
-          goto WIN;                                                        \
        }                                                                   \
       else if (! (frame_pointer_needed && XEXP (X,0) == frame_pointer_rtx)) \
        {                                                                   \
@@ -435,10 +468,6 @@ do {                                                                           \
     }                                                                      \
 } while(0)
 
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)                       \
-      if (GET_CODE (ADDR) == POST_INC || GET_CODE (ADDR) == PRE_DEC)   \
-        goto LABEL
-
 #define LEGITIMATE_CONSTANT_P(X) 1
 
 #define REGISTER_MOVE_COST(MODE, FROM, TO) ((FROM) == STACK_REG ? 6 \
@@ -450,7 +479,7 @@ do {                                                                            \
                                         (MODE)==SImode ? 8 :   \
                                         (MODE)==SFmode ? 8 : 16)
 
-#define BRANCH_COST 0
+#define BRANCH_COST(speed_p, predictable_p) 0
 
 #define SLOW_BYTE_ACCESS 0
 
@@ -476,25 +505,7 @@ do {                                                                           \
 
 #define TARGET_ASM_DESTRUCTOR avr_asm_out_dtor
 
-#define EXTRA_SECTIONS in_progmem
-
-#define EXTRA_SECTION_FUNCTIONS                                                      \
-                                                                             \
-void                                                                         \
-progmem_section (void)                                                       \
-{                                                                            \
-  if (in_section != in_progmem)                                                      \
-    {                                                                        \
-      fprintf (asm_out_file,                                                 \
-              "\t.section .progmem.gcc_sw_table, \"%s\", @progbits\n",       \
-              AVR_MEGA ? "a" : "ax");                                        \
-      /* Should already be aligned, this is just to be safe if it isn't.  */  \
-      fprintf (asm_out_file, "\t.p2align 1\n");                                      \
-      in_section = in_progmem;                                               \
-    }                                                                        \
-}
-
-#define READONLY_DATA_SECTION data_section
+#define SUPPORTS_INIT_PRIORITY 0
 
 #define JUMP_TABLES_IN_TEXT_SECTION 0
 
@@ -506,11 +517,11 @@ progmem_section (void)                                                          \
 
 /* Switch into a generic section.  */
 #define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
+#define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
 
 #define ASM_OUTPUT_ASCII(FILE, P, SIZE)         gas_output_ascii (FILE,P,SIZE)
 
-#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == '\n'                   \
-                                         || ((C) == '$'))
+#define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) ((C) == '\n' || ((C) == '$'))
 
 #define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED)                    \
 do {                                                                      \
@@ -551,10 +562,7 @@ do {                                                                       \
    specific tm.h file (depending upon the particulars of your assembler).  */
 
 #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL)            \
-do {                                                           \
-     ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function");       \
-     ASM_OUTPUT_LABEL (FILE, NAME);                            \
-} while (0)
+avr_asm_declare_function_name ((FILE), (NAME), (DECL))
 
 #define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL)                   \
   do {                                                                 \
@@ -631,6 +639,8 @@ do {                                                                         \
 /* Globalizing directive for a label.  */
 #define GLOBAL_ASM_OP ".global\t"
 
+#define SET_ASM_OP     "\t.set\t"
+
 #define ASM_WEAKEN_LABEL(FILE, NAME)   \
   do                                   \
     {                                  \
@@ -652,19 +662,19 @@ sprintf (STRING, "*.%s%lu", PREFIX, (unsigned long)(NUM))
     "r8","r9","r10","r11","r12","r13","r14","r15",     \
     "r16","r17","r18","r19","r20","r21","r22","r23",   \
     "r24","r25","r26","r27","r28","r29","r30","r31",   \
-    "__SPL__","__SPH__","argL","argH"}
+    "__SP_L__","__SP_H__","argL","argH"}
 
 #define FINAL_PRESCAN_INSN(insn, operand, nop) final_prescan_insn (insn, operand,nop)
 
 #define PRINT_OPERAND(STREAM, X, CODE) print_operand (STREAM, X, CODE)
 
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '~')
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '~' || (CODE) == '!')
 
 #define PRINT_OPERAND_ADDRESS(STREAM, X) print_operand_address(STREAM, X)
 
 #define USER_LABEL_PREFIX ""
 
-#define ASSEMBLER_DIALECT AVR_ENHANCED
+#define ASSEMBLER_DIALECT AVR_HAVE_MOVW
 
 #define ASM_OUTPUT_REG_PUSH(STREAM, REGNO)     \
 {                                              \
@@ -682,19 +692,20 @@ sprintf (STRING, "*.%s%lu", PREFIX, (unsigned long)(NUM))
   avr_output_addr_vec_elt(STREAM, VALUE)
 
 #define ASM_OUTPUT_CASE_LABEL(STREAM, PREFIX, NUM, TABLE) \
-  progmem_section (), (*targetm.asm_out.internal_label) (STREAM, PREFIX, NUM)
+  (switch_to_section (progmem_section), \
+   (*targetm.asm_out.internal_label) (STREAM, PREFIX, NUM))
 
 #define ASM_OUTPUT_SKIP(STREAM, N)             \
 fprintf (STREAM, "\t.skip %lu,0\n", (unsigned long)(N))
 
-#define ASM_OUTPUT_ALIGN(STREAM, POWER)
+#define ASM_OUTPUT_ALIGN(STREAM, POWER)                        \
+  do {                                                 \
+      if ((POWER) > 1)                                 \
+          fprintf (STREAM, "\t.p2align\t%d\n", POWER); \
+  } while (0)
 
 #define CASE_VECTOR_MODE HImode
 
-extern int avr_case_values_threshold;
-
-#define CASE_VALUES_THRESHOLD avr_case_values_threshold
-
 #undef WORD_REGISTER_OPERATIONS
 
 #define MOVE_MAX 4
@@ -709,16 +720,8 @@ extern int avr_case_values_threshold;
 
 #define NO_DOLLAR_IN_LABEL 1
 
-#define TRAMPOLINE_TEMPLATE(FILE) \
-  internal_error ("trampolines not supported")
-
 #define TRAMPOLINE_SIZE 4
 
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT)                            \
-{                                                                            \
-  emit_move_insn (gen_rtx_MEM (HImode, plus_constant ((TRAMP), 2)), CXT);    \
-  emit_move_insn (gen_rtx_MEM (HImode, plus_constant ((TRAMP), 6)), FNADDR); \
-}
 /* Store in cc_status the expressions
    that the condition codes will describe
    after execution of an instruction whose pattern is EXP.
@@ -745,6 +748,17 @@ extern int avr_case_values_threshold;
 #define ADJUST_INSN_LENGTH(INSN, LENGTH) (LENGTH =\
                                          adjust_insn_length (INSN, LENGTH))
 
+extern const char *avr_device_to_arch (int argc, const char **argv);
+extern const char *avr_device_to_data_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);
+
+#define EXTRA_SPEC_FUNCTIONS \
+  { "device_to_arch", avr_device_to_arch }, \
+  { "device_to_data_start", avr_device_to_data_start }, \
+  { "device_to_startfile", avr_device_to_startfiles }, \
+  { "device_to_devicelib", avr_device_to_devicelib },
+
 #define CPP_SPEC "%{posix:-D_POSIX_SOURCE}"
 
 #define CC1_SPEC "%{profile:-p}"
@@ -752,18 +766,23 @@ extern int avr_case_values_threshold;
 #define CC1PLUS_SPEC "%{!frtti:-fno-rtti} \
     %{!fenforce-eh-specs:-fno-enforce-eh-specs} \
     %{!fexceptions:-fno-exceptions}"
-/* A C string constant that tells the GCC drvier program options to
+/* A C string constant that tells the GCC driver program options to
    pass to `cc1plus'.  */
 
-#define ASM_SPEC "%{mmcu=*:-mmcu=%*}"
-
-#define LINK_SPEC " %{!mmcu*:-m avr2}\
-%{mmcu=at90s1200|mmcu=attiny11|mmcu=attiny12|mmcu=attiny15|mmcu=attiny28:-m avr1} \
-%{mmcu=attiny22|mmcu=attiny26|mmcu=at90s2*|mmcu=at90s4*|mmcu=at90s8*|mmcu=at90c8*|mmcu=at86rf401|mmcu=attiny13|mmcu=attiny2313:-m avr2}\
-%{mmcu=atmega103|mmcu=atmega603|mmcu=at43*|mmcu=at76*:-m avr3}\
-%{mmcu=atmega8*|mmcu=atmega48:-m avr4}\
-%{mmcu=atmega16*|mmcu=atmega32*|mmcu=atmega64*|mmcu=atmega128|mmcu=at90can128|mmcu=at94k:-m avr5}\
-%{mmcu=atmega325|mmcu=atmega3250|mmcu=atmega48|mmcu=atmega88|mmcu=atmega64|mmcu=atmega645|mmcu=atmega6450|mmcu=atmega128|mmcu=at90can128|mmcu=at90can128|mmcu=atmega162|mmcu=atmega165|mmcu=atmega168|mmcu=atmega169: -Tdata 0x800100} "
+#define ASM_SPEC "%{mmcu=avr25:-mmcu=avr2;mmcu=avr35:-mmcu=avr3;mmcu=avr31:-mmcu=avr3;mmcu=avr51:-mmcu=avr5;\
+mmcu=*:-mmcu=%*}"
+
+#define LINK_SPEC "\
+%{mrelax:--relax\
+         %{mpmem-wrap-around:%{mmcu=at90usb8*:--pmem-wrap-around=8k}\
+                             %{mmcu=atmega16*:--pmem-wrap-around=16k}\
+                             %{mmcu=atmega32*|\
+                               mmcu=at90can32*:--pmem-wrap-around=32k}\
+                             %{mmcu=atmega64*|\
+                               mmcu=at90can64*|\
+                               mmcu=at90usb64*:--pmem-wrap-around=64k}}}\
+%:device_to_arch(%{mmcu=*:%*})\
+%:device_to_data_start(%{mmcu=*:%*})"
 
 #define LIB_SPEC \
   "%{!mmcu=at90s1*:%{!mmcu=attiny11:%{!mmcu=attiny12:%{!mmcu=attiny15:%{!mmcu=attiny28: -lc }}}}}"
@@ -774,61 +793,10 @@ extern int avr_case_values_threshold;
 #define LIBGCC_SPEC \
   "%{!mmcu=at90s1*:%{!mmcu=attiny11:%{!mmcu=attiny12:%{!mmcu=attiny15:%{!mmcu=attiny28: -lgcc }}}}}"
 
-#define STARTFILE_SPEC "%(crt_binutils)"
+#define STARTFILE_SPEC "%:device_to_startfile(%{mmcu=*:%*})"
 
 #define ENDFILE_SPEC ""
 
-#define CRT_BINUTILS_SPECS "\
-%{mmcu=at90s1200|mmcu=avr1:crts1200.o%s} \
-%{mmcu=attiny11:crttn11.o%s} \
-%{mmcu=attiny12:crttn12.o%s} \
-%{mmcu=attiny15:crttn15.o%s} \
-%{mmcu=attiny28:crttn28.o%s} \
-%{!mmcu*|mmcu=at90s8515|mmcu=avr2:crts8515.o%s} \
-%{mmcu=at90s2313:crts2313.o%s} \
-%{mmcu=at90s2323:crts2323.o%s} \
-%{mmcu=at90s2333:crts2333.o%s} \
-%{mmcu=at90s2343:crts2343.o%s} \
-%{mmcu=attiny22:crttn22.o%s} \
-%{mmcu=attiny26:crttn26.o%s} \
-%{mmcu=at90s4433:crts4433.o%s} \
-%{mmcu=at90s4414:crts4414.o%s} \
-%{mmcu=at90s4434:crts4434.o%s} \
-%{mmcu=at90c8534:crtc8534.o%s} \
-%{mmcu=at90s8535:crts8535.o%s} \
-%{mmcu=at86rf401:crt86401.o%s} \
-%{mmcu=attiny13:crttn13.o%s} \
-%{mmcu=attiny2313:crttn2313.o%s} \
-%{mmcu=atmega103|mmcu=avr3:crtm103.o%s} \
-%{mmcu=atmega603:crtm603.o%s} \
-%{mmcu=at43usb320:crt43320.o%s} \
-%{mmcu=at43usb355:crt43355.o%s} \
-%{mmcu=at76c711:crt76711.o%s} \
-%{mmcu=atmega8|mmcu=avr4:crtm8.o%s} \
-%{mmcu=atmega48:crtm48.o%s} \
-%{mmcu=atmega88:crtm88.o%s} \
-%{mmcu=atmega8515:crtm8515.o%s} \
-%{mmcu=atmega8535:crtm8535.o%s} \
-%{mmcu=atmega16:crtm16.o%s} \
-%{mmcu=atmega161|mmcu=avr5:crtm161.o%s} \
-%{mmcu=atmega162:crtm162.o%s} \
-%{mmcu=atmega163:crtm163.o%s} \
-%{mmcu=atmega165:crtm165.o%s} \
-%{mmcu=atmega168:crtm168.o%s} \
-%{mmcu=atmega169:crtm169.o%s} \
-%{mmcu=atmega32:crtm32.o%s} \
-%{mmcu=atmega323:crtm323.o%s} \
-%{mmcu=atmega325:crtm325.o%s} \
-%{mmcu=atmega3250:crtm3250.o%s} \
-%{mmcu=atmega64:crtm64.o%s} \
-%{mmcu=atmega645:crtm6450.o%s} \
-%{mmcu=atmega6450:crtm6450.o%s} \
-%{mmcu=atmega128:crtm128.o%s} \
-%{mmcu=at90can128:crtcan128.o%s} \
-%{mmcu=at94k:crtat94k.o%s}"
-
-#define EXTRA_SPECS {"crt_binutils", CRT_BINUTILS_SPECS},
-
 /* This is the default without any -mmcu=* option (AT90S*).  */
 #define MULTILIB_DEFAULTS { "mmcu=avr2" }
 
@@ -856,10 +824,37 @@ extern int avr_case_values_threshold;
 #define OUT_AS2(a,b,c) output_asm_insn (AS2(a,b,c), operands)
 #define CR_TAB "\n\t"
 
-/* Temporary register r0 */
-#define TMP_REGNO 0
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
 
-/* zero register r1 */
-#define ZERO_REGNO 1
+#define DWARF2_DEBUGGING_INFO 1
 
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+#define DWARF2_ADDR_SIZE 4
+
+#define OBJECT_FORMAT_ELF
+
+#define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \
+  avr_hard_regno_rename_ok (OLD_REG, NEW_REG)
+
+/* A C structure for machine-specific, per-function data.
+   This is added to the cfun structure.  */
+struct GTY(()) machine_function
+{
+  /* 'true' - if current function is a naked function.  */
+  int is_naked;
+
+  /* 'true' - if current function is an interrupt function 
+     as specified by the "interrupt" attribute.  */
+  int is_interrupt;
+
+  /* 'true' - if current function is a signal function 
+     as specified by the "signal" attribute.  */
+  int is_signal;
+  
+  /* 'true' - if current function is a 'task' function 
+     as specified by the "OS_task" attribute.  */
+  int is_OS_task;
+
+  /* 'true' - if current function is a 'main' function 
+     as specified by the "OS_main" attribute.  */
+  int is_OS_main;
+};