OSDN Git Service

* target.h (asm_out.byte_op, asm_out.aligned_op, asm_out.unaligned_op,
[pf3gnuchains/gcc-fork.git] / gcc / config / avr / avr.c
index b01f951..7e20748 100644 (file)
@@ -27,7 +27,6 @@
 #include "real.h"
 #include "insn-config.h"
 #include "conditions.h"
-#include "insn-flags.h"
 #include "output.h"
 #include "insn-attr.h"
 #include "flags.h"
@@ -39,6 +38,8 @@
 #include "function.h"
 #include "recog.h"
 #include "tm_p.h"
+#include "target.h"
+#include "target-def.h"
 
 /* Maximal allowed offset for an address in the LD command */
 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
@@ -57,6 +58,12 @@ static int    compare_sign_p       PARAMS ((rtx insn));
 static int    reg_was_0            PARAMS ((rtx insn, rtx op));
 static int    io_address_p         PARAMS ((rtx x, int size));
 void          debug_hard_reg_set   PARAMS ((HARD_REG_SET set));
+static tree   avr_handle_progmem_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static tree   avr_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
+const struct attribute_spec avr_attribute_table[];
+static bool   avr_assemble_integer PARAMS ((rtx, unsigned int, int));
+static void   avr_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void   avr_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
 
 /* Allocate registers from r25 to r8 for parameters for function calls */
 #define FIRST_CUM_REG 26
@@ -72,7 +79,7 @@ rtx zero_reg_rtx;
 rtx ldi_reg_rtx;
 
 /* AVR register names {"r0", "r1", ..., "r31"} */
-const char * avr_regnames[] = REGISTER_NAMES;
+static const char *const avr_regnames[] = REGISTER_NAMES;
 
 /* This holds the last insn address.  */
 static int last_insn_address = 0;
@@ -114,8 +121,8 @@ enum avr_arch {
 };
 
 struct mcu_type_s {
-  const char *name;
-  enum avr_arch arch;
+  const char *const name;
+  const enum avr_arch arch;
 };
 
 /* List of all known AVR MCU types - if updated, it has to be kept
@@ -166,7 +173,22 @@ static const struct mcu_type_s avr_mcu_types[] = {
 };
 
 int avr_case_values_threshold = 30000;
-
+\f
+/* Initialize the GCC target structure.  */
+#undef TARGET_ASM_ALIGNED_HI_OP
+#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
+#undef TARGET_ASM_INTEGER
+#define TARGET_ASM_INTEGER avr_assemble_integer
+
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE avr_attribute_table
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+\f
 void
 avr_override_options ()
 {
@@ -178,7 +200,7 @@ avr_override_options ()
 
   if (!t->name)
     {
-      fprintf (stderr, "Unknown MCU `%s' specified\nKnown MCU names:\n",
+      fprintf (stderr, "unknown MCU `%s' specified\nKnown MCU names:\n",
               avr_mcu_name);
       for (t = avr_mcu_types; t->name; t++)
        fprintf (stderr,"   %s\n", t->name);
@@ -226,7 +248,7 @@ avr_init_once ()
 
 /*  return register class from register number */
 
-static int reg_class_tab[]={
+static const int reg_class_tab[]={
   GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
   GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
   GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
@@ -292,7 +314,7 @@ avr_naked_function_p (func)
   if (TREE_CODE (func) != FUNCTION_DECL)
     abort ();
   
-  a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
+  a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
   return a != NULL_TREE;
 }
 
@@ -308,7 +330,7 @@ interrupt_function_p (func)
   if (TREE_CODE (func) != FUNCTION_DECL)
     return 0;
 
-  a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));
+  a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
   return a != NULL_TREE;
 }
 
@@ -324,7 +346,7 @@ signal_function_p (func)
   if (TREE_CODE (func) != FUNCTION_DECL)
     return 0;
 
-  a = lookup_attribute ("signal", DECL_MACHINE_ATTRIBUTES (func));
+  a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
   return a != NULL_TREE;
 }
 
@@ -526,10 +548,10 @@ out_set_stack_ptr (file, before, after)
 
 /* Output function prologue */
 
-void
-function_prologue (file, size)
+static void
+avr_output_function_prologue (file, size)
      FILE *file;
-     int size;
+     HOST_WIDE_INT size;
 {
   int reg;
   int interrupt_func_p;
@@ -663,10 +685,10 @@ function_prologue (file, size)
 
 /* Output function epilogue */
 
-void
-function_epilogue (file, size)
+static void
+avr_output_function_epilogue (file, size)
      FILE *file;
-     int size;
+     HOST_WIDE_INT size;
 {
   int reg;
   int interrupt_func_p;
@@ -803,7 +825,8 @@ legitimate_address_p (mode, x, strict)
      rtx x;
      int strict;
 {
-  int r = 0;
+  enum reg_class r = NO_REGS;
+  
   if (TARGET_ALL_DEBUG)
     {
       fprintf (stderr, "mode: (%s) %s %s %s %s:",
@@ -825,9 +848,9 @@ legitimate_address_p (mode, x, strict)
     }
   if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
                     : REG_OK_FOR_BASE_NOSTRICT_P (x)))
-    r = 'R';
+    r = POINTER_REGS;
   else if (CONSTANT_ADDRESS_P (x))
-    r = 'S';
+    r = ALL_REGS;
   else if (GET_CODE (x) == PLUS
            && REG_P (XEXP (x, 0))
           && GET_CODE (XEXP (x, 1)) == CONST_INT
@@ -839,26 +862,26 @@ legitimate_address_p (mode, x, strict)
          if (! strict
              || REGNO (XEXP (x,0)) == REG_Y
              || REGNO (XEXP (x,0)) == REG_Z)
-             r = 'Q';
+           r = BASE_POINTER_REGS;
          if (XEXP (x,0) == frame_pointer_rtx
              || XEXP (x,0) == arg_pointer_rtx)
-           r = 'Q';
+           r = BASE_POINTER_REGS;
        }
       else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
-       r = 'U';
+       r = POINTER_Y_REGS;
     }
   else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
            && REG_P (XEXP (x, 0))
            && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
                : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
     {
-      r = 'T';
+      r = POINTER_REGS;
     }
   if (TARGET_ALL_DEBUG)
     {
       fprintf (stderr, "   ret = %c\n", r);
     }
-  return r;
+  return r == NO_REGS ? 0 : (int)r;
 }
 
 /* Attempts to replace X with a valid
@@ -1022,7 +1045,7 @@ print_operand (file, x, code)
       else if (code == 'o')
        {
          if (GET_CODE (addr) != PLUS)
-           fatal_insn ("Bad address, not (reg+disp):", addr);
+           fatal_insn ("bad address, not (reg+disp):", addr);
 
          print_operand (file, XEXP (addr, 1), 0);
        }
@@ -1030,7 +1053,7 @@ print_operand (file, x, code)
        {
          print_operand_address (file, XEXP (addr,0));
          if (REGNO (XEXP (addr, 0)) == REG_X)
-           fatal_insn ("Internal compiler bug.\nBad address:"
+           fatal_insn ("internal compiler error.  Bad address:"
                        ,addr);
          fputc ('+', file);
          print_operand (file, XEXP (addr,1), code);
@@ -1043,7 +1066,7 @@ print_operand (file, x, code)
       long val;
       REAL_VALUE_TYPE rv;
       if (GET_MODE (x) != SFmode)
-       fatal_insn ("Internal compiler bug. Unknown mode:", x);
+       fatal_insn ("internal compiler error.  Unknown mode:", x);
       REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
       REAL_VALUE_TO_TARGET_SINGLE (rv, val);
       asm_fprintf (file, "0x%lx", val);
@@ -1341,7 +1364,7 @@ avr_simplify_comparision_p (mode, operator, x)
 {
   unsigned int max = (mode == QImode ? 0xff :
                       mode == HImode ? 0xffff :
-                      mode == SImode ? 0xffffffffU : 0);
+                      mode == SImode ? 0xffffffff : 0);
   if (max && operator && GET_CODE (x) == CONST_INT)
     {
       if (unsigned_condition (operator) != operator)
@@ -1751,7 +1774,7 @@ output_movhi (insn, operands, l)
       operands[1] = src;
       return "";
     }
-  fatal_insn ("Invalid insn:", insn);
+  fatal_insn ("invalid insn:", insn);
   return "";
 }
 
@@ -1788,7 +1811,7 @@ out_movqi_r_mr (insn, op, l)
        {
          int disp = INTVAL (XEXP (x,1));
          if (REGNO (XEXP (x,0)) != REG_Y)
-           fatal_insn ("Incorrect insn:",insn);
+           fatal_insn ("incorrect insn:",insn);
 
          if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
            return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
@@ -1874,7 +1897,7 @@ out_movhi_r_mr (insn, op, l)
       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
        {
          if (REGNO (XEXP (base, 0)) != REG_Y)
-           fatal_insn ("Incorrect insn:",insn);
+           fatal_insn ("incorrect insn:",insn);
          
          if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
            return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
@@ -1923,7 +1946,7 @@ out_movhi_r_mr (insn, op, l)
   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
     {
       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
-       fatal_insn ("Incorrect insn:", insn);
+       fatal_insn ("incorrect insn:", insn);
 
       *l = 2;
       return (AS2 (ld,%B0,%1) CR_TAB
@@ -1932,7 +1955,7 @@ out_movhi_r_mr (insn, op, l)
   else if (GET_CODE (base) == POST_INC) /* (R++) */
     {
       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
-       fatal_insn ("Incorrect insn:", insn);
+       fatal_insn ("incorrect insn:", insn);
 
       *l = 2;
       return (AS2 (ld,%A0,%1)  CR_TAB
@@ -1951,7 +1974,7 @@ out_movhi_r_mr (insn, op, l)
              AS2 (lds,%B0,%B1));
     }
   
-  fatal_insn ("Unknown move insn:",insn);
+  fatal_insn ("unknown move insn:",insn);
   return "";
 }
 
@@ -2030,7 +2053,7 @@ out_movsi_r_mr (insn, op, l)
       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
        {
          if (REGNO (XEXP (base, 0)) != REG_Y)
-           fatal_insn ("Incorrect insn:",insn);
+           fatal_insn ("incorrect insn:",insn);
 
          if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
            return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
@@ -2115,7 +2138,7 @@ out_movsi_r_mr (insn, op, l)
                    AS2 (lds,%C0,%C1) CR_TAB
                    AS2 (lds,%D0,%D1));
     
-  fatal_insn ("Unknown move insn:",insn);
+  fatal_insn ("unknown move insn:",insn);
   return "";
 }
 
@@ -2202,7 +2225,7 @@ out_movsi_mr_r (insn, op, l)
       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
        {
          if (reg_base != REG_Y)
-           fatal_insn ("Incorrect insn:",insn);
+           fatal_insn ("incorrect insn:",insn);
 
          if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
            return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
@@ -2273,7 +2296,7 @@ out_movsi_mr_r (insn, op, l)
                  AS2 (st,%0,%B1) CR_TAB
                  AS2 (st,%0,%C1) CR_TAB
                  AS2 (st,%0,%D1));
-  fatal_insn ("Unknown move insn:",insn);
+  fatal_insn ("unknown move insn:",insn);
   return "";
 }
 
@@ -2344,7 +2367,7 @@ output_movsisf(insn, operands, l)
          
          if (GET_CODE (src) == CONST_INT)
            {
-             const char *clr_op0 =
+             const char *const clr_op0 =
                AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
                                AS1 (clr,%B0) CR_TAB
                                AS2 (movw,%C0,%A0))
@@ -2463,7 +2486,7 @@ output_movsisf(insn, operands, l)
       operands[1] = src;
       return "";
     }
-  fatal_insn ("Invalid insn:", insn);
+  fatal_insn ("invalid insn:", insn);
   return "";
 }
 
@@ -2500,7 +2523,7 @@ out_movqi_mr_r (insn, op, l)
        {
          int disp = INTVAL (XEXP (x,1));
          if (REGNO (XEXP (x,0)) != REG_Y)
-           fatal_insn ("Incorrect insn:",insn);
+           fatal_insn ("incorrect insn:",insn);
 
          if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
            return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
@@ -2611,7 +2634,7 @@ out_movhi_mr_r (insn, op, l)
       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
        {
          if (reg_base != REG_Y)
-           fatal_insn ("Incorrect insn:",insn);
+           fatal_insn ("incorrect insn:",insn);
 
          if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
            return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
@@ -2655,7 +2678,7 @@ out_movhi_mr_r (insn, op, l)
   else if (GET_CODE (base) == POST_INC) /* (R++) */
     return *l=2, (AS2 (st,%0,%A1)  CR_TAB
                  AS2 (st,%0,%B1));
-  fatal_insn ("Unknown move insn:",insn);
+  fatal_insn ("unknown move insn:",insn);
   return "";
 }
 
@@ -2891,7 +2914,7 @@ out_shift_with_cnt (template, insn, operands, len, t_len)
        }
     }
   else
-    fatal_insn ("Bad shift insn:", insn);
+    fatal_insn ("bad shift insn:", insn);
 
   if (second_label)
     {
@@ -3007,7 +3030,7 @@ ashlqi3_out (insn, operands, len)
        }
     }
   else if (CONSTANT_P (operands[2]))
-    fatal_insn ("Internal compiler bug.\nIncorrect shift:", insn);
+    fatal_insn ("internal compiler error.  Incorrect shift:", insn);
 
   out_shift_with_cnt (AS1 (lsl,%0),
                      insn, operands, len, 1);
@@ -3437,7 +3460,7 @@ ashrqi3_out (insn, operands, len)
        }
     }
   else if (CONSTANT_P (operands[2]))
-    fatal_insn ("Internal compiler bug.\nIncorrect shift:", insn);
+    fatal_insn ("internal compiler error.  Incorrect shift:", insn);
 
   out_shift_with_cnt (AS1 (asr,%0),
                      insn, operands, len, 1);
@@ -3817,7 +3840,7 @@ lshrqi3_out (insn, operands, len)
        }
     }
   else if (CONSTANT_P (operands[2]))
-    fatal_insn ("Internal compiler bug.\nIncorrect shift:", insn);
+    fatal_insn ("internal compiler error.  Incorrect shift:", insn);
   
   out_shift_with_cnt (AS1 (lsr,%0),
                      insn, operands, len, 1);
@@ -4225,8 +4248,8 @@ adjust_insn_length (insn, len)
              if (GET_MODE (op[1]) == SImode)
                len = (((mask & 0xff) != 0xff)
                       + ((mask & 0xff00) != 0xff00)
-                      + ((mask & 0xff0000UL) != 0xff0000UL)
-                      + ((mask & 0xff000000UL) != 0xff000000UL));
+                      + ((mask & 0xff0000L) != 0xff0000L)
+                      + ((mask & 0xff000000L) != 0xff000000L));
              else if (GET_MODE (op[1]) == HImode)
                len = (((mask & 0xff) != 0xff)
                       + ((mask & 0xff00) != 0xff00));
@@ -4240,8 +4263,8 @@ adjust_insn_length (insn, len)
              if (GET_MODE (op[1]) == SImode)
                len = (((mask & 0xff) != 0)
                       + ((mask & 0xff00) != 0)
-                      + ((mask & 0xff0000UL) != 0)
-                      + ((mask & 0xff000000UL) != 0));
+                      + ((mask & 0xff0000L) != 0)
+                      + ((mask & 0xff000000L) != 0));
              else if (GET_MODE (op[1]) == HImode)
                len = (((mask & 0xff) != 0)
                       + ((mask & 0xff00) != 0));
@@ -4441,49 +4464,25 @@ _reg_unused_after (insn, reg)
   return 1;
 }
 
-/* Output rtx VALUE as .byte to file FILE */
-
-void
-asm_output_char (file, value)
-     FILE *file;
-     rtx value;
-{
-  fprintf (file, "\t.byte ");
-  output_addr_const (file, value);
-  fprintf (file, "\n");
-}
-
+/* Target hook for assembling integer objects.  The AVR version needs
+   special handling for references to certain labels.  */
 
-/* Output VALUE as .byte to file FILE */
-
-void
-asm_output_byte (file, value)
-     FILE *file;
-     int value;
-{
-  fprintf (file, "\t.byte 0x%x\n", value & 0xff);
-}
-
-
-/* Output rtx VALUE as .word to file FILE */
-
-void
-asm_output_short (file, value)
-     FILE *file;
-     rtx value;
+static bool
+avr_assemble_integer (x, size, aligned_p)
+     rtx x;
+     unsigned int size;
+     int aligned_p;
 {
-  if (SYMBOL_REF_FLAG (value) || GET_CODE (value) == LABEL_REF)
+  if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
+      && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x))
+         || GET_CODE (x) == LABEL_REF))
     {
-      fprintf (file, "\t.word pm(");
-      output_addr_const (file, (value));
-      fprintf (file, ")\n");
-    }
-  else
-    {
-      fprintf (file, "\t.word ");
-      output_addr_const (file, (value));
-      fprintf (file, "\n");
+      fputs ("\t.word\tpm(", asm_out_file);
+      output_addr_const (asm_out_file, x);
+      fputs (")\n", asm_out_file);
+      return true;
     }
+  return default_assemble_integer (x, size, aligned_p);
 }
 
 
@@ -4536,23 +4535,6 @@ unique_section (decl, reloc)
 }
 
 
-/* Output section name to file FILE
-   We make the section read-only and executable for a function decl,
-   read-only for a const data decl, and writable for a non-const data decl.  */
-
-void
-asm_output_section_name(file, decl, name, reloc)
-     FILE *file;
-     tree decl;
-     const char *name;
-     int reloc ATTRIBUTE_UNUSED;
-{
-  fprintf (file, ".section %s, \"%s\", @progbits\n", name,
-          decl && TREE_CODE (decl) == FUNCTION_DECL ? "ax" :
-          decl && TREE_READONLY (decl) ? "a" : "aw");
-}
-
-
 /* The routine used to output NUL terminated strings.  We use a special
    version of this for most svr4 targets because doing so makes the
    generated assembly code more compact (and thus faster to assemble)
@@ -4663,54 +4645,76 @@ class_likely_spilled_p (c)
   return (c != ALL_REGS && c != ADDW_REGS);
 }
 
-/* Only `progmem' attribute valid for type.  */
-
-int
-valid_machine_type_attribute(type, attributes, identifier, args)
-     tree type ATTRIBUTE_UNUSED;
-     tree attributes ATTRIBUTE_UNUSED;
-     tree identifier;
-     tree args ATTRIBUTE_UNUSED;
-{
-  return is_attribute_p ("progmem", identifier);
-}
-
-/* If IDENTIFIER with arguments ARGS is a valid machine specific
-   attribute for DECL return 1.
-   Valid attributes:
+/* Valid attributes:
    progmem - put data to program memory;
    signal - make a function to be hardware interrupt. After function
    prologue interrupts are disabled;
    interrupt - make a function to be hardware interrupt. After function
    prologue interrupts are enabled;
-   naked     - don't generate function prologue/epilogue and `ret' command.  */
+   naked     - don't generate function prologue/epilogue and `ret' command.
 
-int
-valid_machine_decl_attribute (decl, attributes, attr, args)
-     tree decl;
-     tree attributes ATTRIBUTE_UNUSED;
-     tree attr;
-     tree args ATTRIBUTE_UNUSED;
+   Only `progmem' attribute valid for type.  */
+
+const struct attribute_spec avr_attribute_table[] =
 {
-  if (is_attribute_p ("interrupt", attr)
-      || is_attribute_p ("signal", attr)
-      || is_attribute_p ("naked", attr))
-    return TREE_CODE (decl) == FUNCTION_DECL;
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+  { "progmem",   0, 0, false, false, false,  avr_handle_progmem_attribute },
+  { "signal",    0, 0, true,  false, false,  avr_handle_fndecl_attribute },
+  { "interrupt", 0, 0, true,  false, false,  avr_handle_fndecl_attribute },
+  { "naked",     0, 0, true,  false, false,  avr_handle_fndecl_attribute },
+  { NULL,        0, 0, false, false, false, NULL }
+};
 
-  if (is_attribute_p ("progmem", attr)
-      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+/* Handle a "progmem" attribute; arguments as in
+   struct attribute_spec.handler.  */
+static tree
+avr_handle_progmem_attribute (node, name, args, flags, no_add_attrs)
+     tree *node;
+     tree name;
+     tree args ATTRIBUTE_UNUSED;
+     int flags ATTRIBUTE_UNUSED;
+     bool *no_add_attrs;
+{
+  if (DECL_P (*node))
     {
-      if (DECL_INITIAL (decl) == NULL_TREE && !DECL_EXTERNAL (decl))
+      if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
+       {
+         if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
+           {
+             warning ("only initialized variables can be placed into "
+                      "program memory area");
+             *no_add_attrs = true;
+           }
+       }
+      else
        {
-         warning ("Only initialized variables can be placed into "
-                  "program memory area.");
-         return 0;
+         warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+         *no_add_attrs = true;
        }
-      return 1;
     }
-  return 0;
+
+  return NULL_TREE;
 }
 
+/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
+   struct attribute_spec.handler.  */
+static tree
+avr_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
+     tree *node;
+     tree name;
+     tree args ATTRIBUTE_UNUSED;
+     int flags ATTRIBUTE_UNUSED;
+     bool *no_add_attrs;
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning ("`%s' attribute only applies to functions",
+              IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
 
 /* Look for attribute `progmem' in DECL
    if found return 1, otherwise 0.  */
@@ -4725,7 +4729,7 @@ avr_progmem_p (decl)
     return 0;
 
   if (NULL_TREE
-      != lookup_attribute ("progmem", DECL_MACHINE_ATTRIBUTES (decl)))
+      != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl)))
     return 1;
 
   a=decl;
@@ -4754,7 +4758,7 @@ encode_section_info (decl)
           && TREE_CODE (decl) == VAR_DECL
           && avr_progmem_p (decl))
     {
-      const char *dsec = ".progmem.data";
+      static const char *const dsec = ".progmem.data";
       DECL_SECTION_NAME (decl) = build_string (strlen (dsec), dsec);
       TREE_READONLY (decl) = 1;
     }
@@ -4809,7 +4813,7 @@ void
 order_regs_for_local_alloc ()
 {
   unsigned int i;
-  int order_0[] = {
+  static const int order_0[] = {
     24,25,
     18,19,
     20,21,
@@ -4821,7 +4825,7 @@ order_regs_for_local_alloc ()
     0,1,
     32,33,34,35
   };
-  int order_1[] = {
+  static const int order_1[] = {
     18,19,
     20,21,
     22,23,
@@ -4833,7 +4837,7 @@ order_regs_for_local_alloc ()
     0,1,
     32,33,34,35
   };
-  int order_2[] = {
+  static const int order_2[] = {
     25,24,
     23,22,
     21,20,
@@ -4847,9 +4851,9 @@ order_regs_for_local_alloc ()
     32,33,34,35
   };
   
-  int *order = (TARGET_ORDER_1 ? order_1 :
-               TARGET_ORDER_2 ? order_2 :
-               order_0);
+  const int *order = (TARGET_ORDER_1 ? order_1 :
+                     TARGET_ORDER_2 ? order_2 :
+                     order_0);
   for (i=0; i < ARRAY_SIZE (order_0); ++i)
       reg_alloc_order[i] = order[i];
 }
@@ -5140,9 +5144,9 @@ mask_one_bit_p (mask)
   unsigned HOST_WIDE_INT n=mask;
   for (i = 0; i < 32; ++i)
     {
-      if (n & 0x80000000UL)
+      if (n & 0x80000000L)
        {
-         if (n & 0x7fffffffUL)
+         if (n & 0x7fffffffL)
            return 0;
          else
            return 32-i;
@@ -5325,7 +5329,7 @@ output_reload_insisf (insn, operands, len)
        *len = 4 + ((INTVAL (src) & 0xff) != 0)
                + ((INTVAL (src) & 0xff00) != 0)
                + ((INTVAL (src) & 0xff0000) != 0)
-               + ((INTVAL (src) & 0xff000000U) != 0);
+               + ((INTVAL (src) & 0xff000000) != 0);
       else
        *len = 8;
 
@@ -5353,7 +5357,7 @@ output_reload_insisf (insn, operands, len)
       output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
       output_asm_insn (AS2 (mov, %C0, %2), operands);
     }
-  if (cnst && ((INTVAL (src) & 0xff000000U) == 0))
+  if (cnst && ((INTVAL (src) & 0xff000000) == 0))
     output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
   else
     {