avr-protos.h: (avr_output_ascii) Removed.
authorDenis Chertykov <denisc@overta.ru>
Tue, 29 Aug 2000 19:37:45 +0000 (23:37 +0400)
committerDenis Chertykov <denisc@gcc.gnu.org>
Tue, 29 Aug 2000 19:37:45 +0000 (23:37 +0400)
* config/avr/avr-protos.h: (avr_output_ascii) Removed.
(avr_progmem_p): New prototype.
(output_movsisf): Prototype declaration changed.
(output_movqi): New prototype.
(output_movhi): New prototype.
(call_insn_operand): Likewise.
(final_prescan_insn): Likewise.
(avr_simplify_comparision_p): Likewise.
(avr_normalize_condition): Likewise.
(compare_eq_p): Likewise.
(out_shift_with_cnt): Likewise.
(const_int_pow2_p): Likewise.
(output_reload_inhi): Prototype declaration changed.

* config/avr/avr.c: (debug_hard_reg_set): Prototype declared.
(ldi_reg_rtx): New. rtx for r31.
(avr_init_stack): Initialize as "__stack".
(function_prologue): Use it.
Replace all TARGET_ENHANCED with AVR_ENHANCED.
(avr_mcu_name): Initialize as "avr2".
(avr_enhanced_p, avr_mega_p): New variables.
(mcu_types, avr_override_options): Handle all known MCU types.
Also handle avr1 (only preprocess, assemble and link).
(print_operand): Using of `%K' in output template removed.
(out_movqi_r_mr): Optimized.
(out_movhi_r_mr): Likewise.
(output_movqi): New function.
(output_movhi): Likewise.
(out_movsi_r_mr): Optimized.
(output_movsisf): Compute insn length for `adjust_insn_length'
(out_movqi_mr_r): Optimized.
(out_movhi_mr_r): Optimized.
(adjust_insn_length): Use output_movsisf, output_movqi,
output_movhi for insn length adjusting.
(reg_unused_after): Use dead_or_set_p.
(preferred_reload_class): Now havn't any restriction.
(reg_was_0): New function.
(io_address_p): Likewise.
(const_int_pow2_p): Likewise.
(output_reload_inhi): Likewise.
(output_reload_insisf): Likewise.

* config/avr/avr.h (MULTILIB_DEFAULTS): Define.
(LIB_SPEC): Use -lc for all supported devices.
(LIBGCC_SPEC): Use -lgcc for all supported devices.
(AVR_MEGA): Define as avr_mega_p.
(AVR_ENHANCED): New, define as avr_enhanced_p.
(TARGET_SWITCHES): Remove -menhanced, now handled by -mmcu=...
(CPP_SPEC, LINK_SPEC): Handle all known MCU types.
(CRT_BINUTILS_SPECS): Handle all known MCU types.
Rename gcrt1-*.o to make file names unique on 8.3 filesystems.
(EXTRA_SPECS): Add CPP_AVR[1-5]_SPEC.
(ASM_SPEC): Pass -mmcu=... to the assembler.
Change all -DAVR_* to -D__AVR_*__.
(INIT_TARGET_OPTABS), config/avr/libgcc.S:
Rename library functions to start with two underscores.
(ASM_OUTPUT_COMMON): Outputs `.comm VAR,VAR-SIZE,1' to avoid
alignment.
(ASM_WEAKEN_LABEL): Declared for __attribute__((weak)).
(SUPPORTS_WEAK): Likewise.
(LDI_REG_REGNO): New. Register r31 will be used as temporary
register for loading constants to r0-r14.

* config/avr/avr.md: Replace all TARGET_ENHANCED with
AVR_ENHANCED.
(*mov_r_sp): Removed. Handled by output_movhi.
(*mov_sp_r): Likewise.
(*mov_sp_r_no_interrupts): Likewise
(*mov_sp_r_tiny): Likewise.
(*movqi): Use output_movqi.
(*reload_inqi): New.
(*movhi): Use output_movhi.
(*reload_inhi): New.
(*negsi2): Optimized.
(*negsf2): Likewise.
Added peepholes (define_peephole2) for loading constants to r0-r14
and for using `cpse' command.

* config/avr/libgcc.S: Rename library functions to start with two
underscores.
Add support for enhanced core.
(_moqhi3): Fix typo, now _modqi3.
(__divsi_raw): Use __zero_reg__ as loop counter, smaller by 1 word.
(__prologue_saves__): Remove test for stack adjust by 0.
(__tablejump__): New.

* config/avr/t-avr: Build libgcc2 with -mcall-prologues.
Add multilib support.

From-SVN: r36047

gcc/ChangeLog
gcc/config/avr/avr-protos.h
gcc/config/avr/avr.c
gcc/config/avr/avr.h
gcc/config/avr/avr.md
gcc/config/avr/libgcc.S
gcc/config/avr/t-avr

index 991af6c..855819e 100644 (file)
@@ -1,3 +1,94 @@
+Tue Aug 29 22:29:58 2000  Denis Chertykov  <denisc@overta.ru> & Marek Michalkiewicz <marekm@linux.org.pl>
+
+       * config/avr/avr-protos.h: (avr_output_ascii) Removed.
+       (avr_progmem_p): New prototype.
+       (output_movsisf): Prototype declaration changed.
+       (output_movqi): New prototype.
+       (output_movhi): New prototype.
+       (call_insn_operand): Likewise.
+       (final_prescan_insn): Likewise. 
+       (avr_simplify_comparision_p): Likewise.
+       (avr_normalize_condition): Likewise.
+       (compare_eq_p): Likewise.
+       (out_shift_with_cnt): Likewise.
+       (const_int_pow2_p): Likewise.
+       (output_reload_inhi): Prototype declaration changed.
+
+       * config/avr/avr.c: (debug_hard_reg_set): Prototype declared.
+       (ldi_reg_rtx): New. rtx for r31.
+       (avr_init_stack): Initialize as "__stack".
+       (function_prologue): Use it.
+       Replace all TARGET_ENHANCED with AVR_ENHANCED.
+       (avr_mcu_name): Initialize as "avr2".
+       (avr_enhanced_p, avr_mega_p): New variables.
+       (mcu_types, avr_override_options): Handle all known MCU types.
+       Also handle avr1 (only preprocess, assemble and link).
+       (print_operand): Using of `%K' in output template removed.
+       (out_movqi_r_mr): Optimized.
+       (out_movhi_r_mr): Likewise.
+       (output_movqi): New function.
+       (output_movhi): Likewise.
+       (out_movsi_r_mr): Optimized.
+       (output_movsisf): Compute insn length for `adjust_insn_length'
+       (out_movqi_mr_r): Optimized.
+       (out_movhi_mr_r): Optimized.
+       (adjust_insn_length): Use output_movsisf, output_movqi,
+       output_movhi for insn length adjusting.
+       (reg_unused_after): Use dead_or_set_p.
+       (preferred_reload_class): Now havn't any restriction.
+       (reg_was_0): New function.
+       (io_address_p): Likewise.
+       (const_int_pow2_p): Likewise.
+       (output_reload_inhi): Likewise.
+       (output_reload_insisf): Likewise.
+
+       * config/avr/avr.h (MULTILIB_DEFAULTS): Define.
+       (LIB_SPEC): Use -lc for all supported devices.
+       (LIBGCC_SPEC): Use -lgcc for all supported devices.
+       (AVR_MEGA): Define as avr_mega_p.
+       (AVR_ENHANCED): New, define as avr_enhanced_p.
+       (TARGET_SWITCHES): Remove -menhanced, now handled by -mmcu=...
+       (CPP_SPEC, LINK_SPEC): Handle all known MCU types.
+       (CRT_BINUTILS_SPECS): Handle all known MCU types.
+       Rename gcrt1-*.o to make file names unique on 8.3 filesystems.
+       (EXTRA_SPECS): Add CPP_AVR[1-5]_SPEC.
+       (ASM_SPEC): Pass -mmcu=... to the assembler.
+       Change all -DAVR_* to -D__AVR_*__.
+       (INIT_TARGET_OPTABS), config/avr/libgcc.S:
+       Rename library functions to start with two underscores.
+       (ASM_OUTPUT_COMMON): Outputs `.comm VAR,VAR-SIZE,1' to avoid
+       alignment.
+       (ASM_WEAKEN_LABEL): Declared for __attribute__((weak)).
+       (SUPPORTS_WEAK): Likewise.
+       (LDI_REG_REGNO): New. Register r31 will be used as temporary
+       register for loading constants to r0-r14.
+
+       * config/avr/avr.md: Replace all TARGET_ENHANCED with
+       AVR_ENHANCED.
+       (*mov_r_sp): Removed. Handled by output_movhi.
+       (*mov_sp_r): Likewise.
+       (*mov_sp_r_no_interrupts): Likewise
+       (*mov_sp_r_tiny): Likewise.
+       (*movqi): Use output_movqi.
+       (*reload_inqi): New.
+       (*movhi): Use output_movhi.
+       (*reload_inhi): New.
+       (*negsi2): Optimized.
+       (*negsf2): Likewise.
+       Added peepholes (define_peephole2) for loading constants to r0-r14
+       and for using `cpse' command.
+
+       * config/avr/libgcc.S: Rename library functions to start with two
+       underscores.
+       Add support for enhanced core.
+       (_moqhi3): Fix typo, now _modqi3.
+       (__divsi_raw): Use __zero_reg__ as loop counter, smaller by 1 word.
+       (__prologue_saves__): Remove test for stack adjust by 0.
+       (__tablejump__): New.
+
+       * config/avr/t-avr: Build libgcc2 with -mcall-prologues.
+       Add multilib support.
+
 Tue Aug 29 15:17:54 EDT 2000  John Wehle  (john@feith.com)
 
        * loop.c (prescan_loop): Don't check unknown_address_altered
index 4399dba..8d08748 100644 (file)
@@ -21,9 +21,6 @@
    Boston, MA 02111-1307, USA.  */
 
 
-extern void   avr_output_ascii                  PARAMS ((FILE *file,
-                                                       const char *p,
-                                                       int size));
 extern int    function_arg_regno_p              PARAMS ((int r));
 extern void   asm_file_start                    PARAMS ((FILE *file));
 extern void   asm_file_end                      PARAMS ((FILE *file));
@@ -35,14 +32,17 @@ extern enum reg_class class_likely_spilled_p    PARAMS ((int c));
 extern enum reg_class avr_regno_reg_class       PARAMS ((int r));
 extern enum reg_class avr_reg_class_from_letter PARAMS ((int c));
 extern int    frame_pointer_required_p          PARAMS ((void));
-extern void   asm_globalize_label               PARAMS ((FILE *file,
-                                                       const char *name));
-extern void   order_regs_for_local_alloc        PARAMS ((void));
-extern int    initial_elimination_offset        PARAMS ((int from, int to));
-extern void   function_prologue                 PARAMS ((FILE *file, int size));
-extern void   function_epilogue                 PARAMS ((FILE *file, int size));
-extern void   progmem_section                   PARAMS ((void));
-extern int    mask_one_bit_p                    PARAMS ((HOST_WIDE_INT mask));
+extern void   asm_globalize_label         PARAMS ((FILE *file, const char *name));
+extern void   order_regs_for_local_alloc  PARAMS ((void));
+extern int    initial_elimination_offset  PARAMS ((int from, int to));
+extern void   function_prologue           PARAMS ((FILE *file, int size));
+extern void   function_epilogue           PARAMS ((FILE *file, int size));
+extern void   progmem_section             PARAMS ((void));
+extern int    mask_one_bit_p              PARAMS ((HOST_WIDE_INT mask));
+extern void   gas_output_limited_string   PARAMS ((FILE *file, char *str));
+extern void   gas_output_ascii            PARAMS ((FILE *file, char * str,
+                                                        size_t length));
+
 
 #ifdef TREE_CODE
 extern void   asm_output_external          PARAMS ((FILE *file, tree decl,
@@ -58,6 +58,9 @@ extern int    valid_machine_type_attribute PARAMS ((tree type, tree attributes,
 extern int    valid_machine_decl_attribute PARAMS ((tree decl, tree attributes,
                                                   tree attr, tree args));
 
+extern int    avr_progmem_p                PARAMS ((tree decl));
+
+
 #ifdef RTX_CODE /* inside TREE_CODE */
 extern rtx    avr_function_value           PARAMS ((tree type, tree func));
 extern void   init_cumulative_args         PARAMS ((CUMULATIVE_ARGS *cum,
@@ -83,14 +86,15 @@ extern int    legitimate_address_p    PARAMS ((enum machine_mode mode, rtx x,
                                        int strict));
 extern void   machine_dependent_reorg PARAMS ((rtx first_insn));
 extern int    compare_diff_p  PARAMS ((rtx insn));
+extern char * output_movqi    PARAMS ((rtx insn, rtx operands[], int *l));
+extern char * output_movhi    PARAMS ((rtx insn, rtx operands[], int *l));
 extern char * out_movqi_r_mr  PARAMS ((rtx insn, rtx op[], int *l));
 extern char * out_movqi_mr_r  PARAMS ((rtx insn, rtx op[], int *l));
 extern char * out_movhi_r_mr  PARAMS ((rtx insn, rtx op[], int *l));
 extern char * out_movhi_mr_r  PARAMS ((rtx insn, rtx op[], int *l));
 extern char * out_movsi_r_mr  PARAMS ((rtx insn, rtx op[], int *l));
 extern char * out_movsi_mr_r  PARAMS ((rtx insn, rtx op[], int *l));
-extern char * output_movsisf  PARAMS ((rtx insn, rtx operands[],
-                                     int which_alternative));
+extern char * output_movsisf  PARAMS ((rtx insn, rtx operands[], int *l));
 extern char * out_tstsi       PARAMS ((rtx insn, int *l));
 extern char * out_tsthi       PARAMS ((rtx insn, int *l));
 extern char * ret_cond_branch PARAMS ((RTX_CODE cond, int len));
@@ -116,7 +120,7 @@ extern rtx    legitimize_address     PARAMS ((rtx x, rtx oldx,
 extern int    adjust_insn_length     PARAMS ((rtx insn, int len));
 extern rtx    avr_libcall_value      PARAMS ((enum machine_mode mode));
 extern char * output_reload_inhi     PARAMS ((rtx insn, rtx *operands,
-                                            int which_alternative));
+                                            int *len));
 extern char * output_reload_insisf   PARAMS ((rtx insn, rtx *operands,
                                             int which_alternative));
 extern int    default_rtx_costs      PARAMS ((rtx X, RTX_CODE code,
@@ -140,6 +144,16 @@ extern int    jump_over_one_insn_p   PARAMS ((rtx insn, rtx dest));
 
 extern int    avr_hard_regno_mode_ok PARAMS ((int regno,
                                             enum machine_mode mode));
+extern int    call_insn_operand      PARAMS ((rtx op, enum machine_mode mode));
+extern void   final_prescan_insn     PARAMS ((rtx insn, rtx *operand,
+                                             int num_operands));
+extern int    avr_simplify_comparision_p PARAMS ((enum machine_mode mode,
+                                             RTX_CODE operator, rtx x));
+extern RTX_CODE avr_normalize_condition  PARAMS ((RTX_CODE condition));
+extern int    compare_eq_p           PARAMS ((rtx insn));
+extern void   out_shift_with_cnt     PARAMS ((char * template, rtx insn,
+                                             rtx operands[], int *len));
+extern int    const_int_pow2_p       PARAMS ((rtx x));
 #endif /* RTX_CODE */
 
 #ifdef HAVE_MACHINE_MODES
@@ -151,6 +165,4 @@ extern int    class_max_nregs        PARAMS ((enum reg_class class,
 
 extern void   asm_output_float       PARAMS ((FILE *file, REAL_VALUE_TYPE n));
 
-#endif 
-
-
+#endif
index 6dec0c5..74bb701 100644 (file)
@@ -52,7 +52,9 @@ static char * cond_string          PARAMS ((enum rtx_code));
 static int    avr_num_arg_regs     PARAMS ((enum machine_mode, tree));
 static int    out_adj_frame_ptr    PARAMS ((FILE *, int));
 static int    out_set_stack_ptr    PARAMS ((FILE *, int, int));
-
+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));
 
 /* Allocate registers from r25 to r8 for parameters for function calls */
 #define FIRST_CUM_REG 26
@@ -63,8 +65,12 @@ rtx tmp_reg_rtx;
 /* Zeroed register RTX (gen_rtx (REG,QImode,ZERO_REGNO)) */
 rtx zero_reg_rtx;
 
+/* RTX for register which will be used for loading immediate values to
+   r0-r15 registers.  */
+rtx ldi_reg_rtx;
+
 /* AVR register names {"r0", "r1", ..., "r31"} */
-char * avr_regnames[] = REGISTER_NAMES;
+const char * avr_regnames[] = REGISTER_NAMES;
 
 /* This holds the last insn address.  */
 static int last_insn_address = 0;
@@ -83,53 +89,108 @@ static int prologue_size;
 static int epilogue_size;
 
 /* Initial stack value specified by the `-minit-stack=' option */
-const char *avr_ram_end = NULL;
-
-/* Numeric representation */
-static const char *initial_stack;
+const char *avr_init_stack = "__stack";
 
 /* Default MCU name */
-const char *avr_mcu_name = "at90s8515";
-
-/* Default MCU */
-struct mcu_type_s *avr_mcu_type;
-
-/* MCU names, initial stack value, flag 'mega' */
-static struct mcu_type_s mcu_types[] =
-{{"at90s2313", 224-1, 0},
- {"at90s2323", 224-1, 0},
- {"at90s2333", 224-1, 0},
- {"attiny22",  224-1, 0},
- {"at90s2343", 224-1, 0},
- {"at90s4433", 224-1, 0},
- {"at90s4414", 0x15f, 0},
- {"at90s4434", 0x15f, 0},
- {"at90s8515", 0x25f, 0},
- {"at90s8535", 0x25f, 0},
- {"atmega603", 0x0fff,1},
- {"atmega103", 0x0fff,1},
- {NULL,0,0}};
-
-/* Setup MCU */
+const char *avr_mcu_name = "avr2";
+
+/* More than 8K of program memory: use "call" and "jmp".  */
+int avr_mega_p = 0;
+
+/* Enhanced core: use "movw", "mul", ...  */
+int avr_enhanced_p = 0;
+
+enum avr_arch {
+  AVR1 = 1,
+  AVR2,
+  AVR3,
+  AVR4,
+  AVR5
+};
+
+struct mcu_type_s {
+  const char *name;
+  enum avr_arch arch;
+};
+
+/* List of all known AVR MCU types - if updated, it has to be kept
+   in sync in several places (FIXME: is there a better way?):
+    - here
+    - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
+    - t-avr (MULTILIB_MATCHES)
+    - gas/config/tc-avr.c
+    - avr-libc  */
+
+static const struct mcu_type_s avr_mcu_types[] = {
+    /* Classic, <= 8K.  */
+  { "avr2",      AVR2 },
+  { "at90s2313", AVR2 },
+  { "at90s2323", AVR2 },
+  { "attiny22",  AVR2 },
+  { "at90s2333", AVR2 },
+  { "at90s2343", AVR2 },
+  { "at90s4414", AVR2 },
+  { "at90s4433", AVR2 },
+  { "at90s4434", AVR2 },
+  { "at90s8515", AVR2 },
+  { "at90c8534", AVR2 },
+  { "at90s8535", AVR2 },
+    /* Classic, > 8K.  */
+  { "avr3",      AVR3 },
+  { "atmega103", AVR3 },
+  { "atmega603", AVR3 },
+    /* Enhanced, <= 8K.  */
+  { "avr4",      AVR4 },
+  { "atmega83",  AVR4 },
+  { "atmega85",  AVR4 },
+    /* Enhanced, > 8K.  */
+  { "avr5",      AVR5 },
+  { "atmega161", AVR5 },
+  { "atmega163", AVR5 },
+  { "atmega32",  AVR5 },
+  { "at94k",     AVR5 },
+    /* Assembler only.  */
+  { "avr1",      AVR1 },
+  { "at90s1200", AVR1 },
+  { "attiny10",  AVR1 },
+  { "attiny11",  AVR1 },
+  { "attiny12",  AVR1 },
+  { "attiny15",  AVR1 },
+  { "attiny28",  AVR1 },
+  { NULL, 0 }
+};
 
 void
 avr_override_options (void)
 {
-  for (avr_mcu_type = mcu_types; avr_mcu_type->name; ++avr_mcu_type)
-    if (strcmp (avr_mcu_type->name, avr_mcu_name) == 0)
+  const struct mcu_type_s *t;
+
+  for (t = avr_mcu_types; t->name; t++)
+    if (strcmp (t->name, avr_mcu_name) == 0)
       break;
-  if (!avr_mcu_type->name)
+
+  if (!t->name)
     {
-      int i;
-      fprintf (stderr,
-              "Wrong mcu `%s' specified\n"
-              "Allowed mcu's:\n", avr_mcu_name);
-      for (i = 0; mcu_types[i].name; ++i)
-       fprintf (stderr,"   %s\n", mcu_types[i].name);
-      fatal ("select right mcu name");
+      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);
+      fatal ("select right MCU name");
+    }
+
+  switch (t->arch)
+    {
+      case AVR1:
+      default:
+      fatal ("MCU `%s' not supported", avr_mcu_name);
+      case AVR2: avr_enhanced_p = 0; avr_mega_p = 0; break;
+      case AVR3: avr_enhanced_p = 0; avr_mega_p = 1; break;
+      case AVR4: avr_enhanced_p = 1; avr_mega_p = 0; break;
+      case AVR5: avr_enhanced_p = 1; avr_mega_p = 1; break;
     }
 }
 
+
 /* Initialize TMP_REG_RTX and ZERO_REG_RTX */
 void
 avr_init_once (void)
@@ -145,6 +206,12 @@ avr_init_once (void)
   PUT_CODE (zero_reg_rtx, REG);
   PUT_MODE (zero_reg_rtx, QImode);
   XINT (zero_reg_rtx, 0) = ZERO_REGNO;
+
+  ldi_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
+  memset (ldi_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
+  PUT_CODE (ldi_reg_rtx, REG);
+  PUT_MODE (ldi_reg_rtx, QImode);
+  XINT (ldi_reg_rtx, 0) = LDI_REG_REGNO;
 }
 
 /*  return register class from register number */
@@ -363,7 +430,7 @@ out_adj_frame_ptr (file, adj)
        {
          fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
                          AS2 (sbci, r29, hi8(%d)) CR_TAB),
-                        adj, adj);
+                  adj, adj);
          size += 2;
        }
       else if (adj < 0)
@@ -496,11 +563,11 @@ function_prologue (FILE *file, int size)
   if (main_p)
     {
       fprintf (file, ("\t" 
-                     AS2 (ldi, r28, lo8(%s - %d)) CR_TAB
-                     AS2 (ldi, r29, hi8(%s - %d)) CR_TAB
-                     AS2 (out, __SP_H__, r29)     CR_TAB
-                     AS2 (out, __SP_L__, r28) "\n"),
-              initial_stack, size, initial_stack, size);
+                     AS2 (ldi,r28,lo8(%s - %d)) CR_TAB
+                     AS2 (ldi,r29,hi8(%s - %d)) CR_TAB
+                     AS2 (out,__SP_H__,r29)     CR_TAB
+                     AS2 (out,__SP_L__,r28) "\n"),
+              avr_init_stack, size, avr_init_stack, size);
       
       prologue_size += 4;
     }
@@ -754,7 +821,8 @@ legitimate_address_p (mode, x, strict)
       if (fit)
        {
          if (! strict
-             || REGNO (XEXP (x,0)) == REG_Y || REGNO (XEXP (x,0)) == REG_Z)
+             || REGNO (XEXP (x,0)) == REG_Y
+             || REGNO (XEXP (x,0)) == REG_Z)
              r = 'Q';
          if (XEXP (x,0) == frame_pointer_rtx
              || XEXP (x,0) == arg_pointer_rtx)
@@ -931,14 +999,8 @@ print_operand (file, x, code)
   else if (GET_CODE (x) == MEM)
     {
       rtx addr = XEXP (x,0);
-      if (code == 'K')
-       {
-         if (CONSTANT_P (addr))
-           putc ('s', file);
-         else if (GET_CODE (addr) == PLUS)
-           putc ('d', file);
-       }
-      else if (CONSTANT_P (addr) && abcd)
+
+      if (CONSTANT_P (addr) && abcd)
        {
          fputc ('(', file);
          output_address (addr);
@@ -964,7 +1026,7 @@ print_operand (file, x, code)
        fatal_insn ("Internal compiler bug. Unknown mode:", x);
       REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
       REAL_VALUE_TO_TARGET_SINGLE (rv, val);
-      asm_fprintf (file, "0x%x", val);
+      asm_fprintf (file, "0x%lx", val);
     }
   else if (code == 'j')
     asm_fprintf (file, cond_string (GET_CODE (x)));
@@ -974,7 +1036,7 @@ print_operand (file, x, code)
     print_operand_address (file, x);
 }
 
-/* Recognise operand OP of mode MODE used in call instructions */
+/* Recognize operand OP of mode MODE used in call instructions */
 
 int
 call_insn_operand (op, mode)
@@ -1355,69 +1417,363 @@ function_arg_advance (cum, mode, type, named)
   Functions for outputting various mov's for a various modes
 ************************************************************************/
 char *
-out_movqi_r_mr (insn, op, l)
+output_movqi (insn, operands, l)
      rtx insn;
-     rtx op[];
-     int *l; /* instruction length */
+     rtx operands[];
+     int *l;
 {
-  /* We handle CONSTANT_ADDRESS_P case in adjust_insn_length */
-  if (l) *l=1;
-  if (GET_CODE (op[1]) == MEM)
+  int dummy;
+  rtx dest = operands[0];
+  rtx src = operands[1];
+  int *real_l = l;
+  
+  if (!l)
+    l = &dummy;
+
+  *l = 1;
+  
+  if (register_operand (dest, QImode))
     {
-      rtx x = XEXP (op[1],0);
-      if (GET_CODE (x) == PLUS
-         && REG_P (XEXP (x,0))
-         && GET_CODE (XEXP (x,1)) == CONST_INT)
+      if (register_operand (src, QImode)) /* mov r,r */
        {
-         if((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (op[1]))) >= 63)
+         if (test_hard_reg_class (STACK_REG, dest))
+           return AS2 (out,%0,%1);
+         else if (test_hard_reg_class (STACK_REG, src))
+           return AS2 (in,%0,%1);
+         
+         return AS2 (mov,%0,%1);
+       }
+      else if (CONSTANT_P (src))
+       {
+         if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
+           return AS2 (ldi,%0,lo8(%1));
+         
+         if (GET_CODE (src) == CONST_INT)
            {
-             int disp = INTVAL (XEXP (x,1));
-             if (REGNO (XEXP (x,0)) != REG_Y)
-               fatal_insn ("Incorrect insn:",insn);
-             if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (op[1])))
+             if (src == const0_rtx) /* mov r,L */
+               return AS1 (clr,%0);
+             else if (src == const1_rtx)
                {
-                 if (l)
-                   *l = 3;
-                 else
+                 if (reg_was_0 (insn, operands[0]))
+                   return AS1 (inc,%0 ; reg_was_0);
+
+                 *l = 2;
+                 return (AS1 (clr,%0) CR_TAB
+                         AS1 (inc,%0));
+               }
+             else if (src == const2_rtx)
+               {
+                 if (reg_was_0 (insn, operands[0]))
                    {
-                     op[4] = GEN_INT (disp - 63);
-                     return (AS2 (adiw, r28, %4) CR_TAB
-                             AS2 (ldd, %0,Y+63)  CR_TAB
-                             AS2 (sbiw, r28, %4));
+                     *l = 2;
+                     return (AS1 (inc,%0 ; reg_was_0) CR_TAB
+                             AS1 (inc,%0));
                    }
+
+                 *l = 3;
+                 return (AS1 (clr,%0) CR_TAB
+                         AS1 (inc,%0) CR_TAB
+                         AS1 (inc,%0));
                }
-             else
+             else if (src == constm1_rtx)
                {
-                 op[4] = XEXP (x,1);
-                 if (l)
-                   *l = 5;
-                 else
-                   return (AS2 (subi, r28, lo8(-%4))  CR_TAB
-                           AS2 (sbci, r29, hi8(-%4)) CR_TAB
-                           AS2 (ld, %0,Y)              CR_TAB
-                           AS2 (subi, r28, lo8(%4))   CR_TAB
-                           AS2 (sbci, r29, hi8(%4)));
+                 /* Immediate constants -1 to any register */
+                 if (reg_was_0 (insn, operands[0]))
+                   return AS1 (dec,%0 ; reg_was_0);
+
+                 *l = 2;
+                 return (AS1 (clr,%0) CR_TAB
+                         AS1 (dec,%0));
                }
+             
            }
-         else if (REGNO (XEXP (x,0)) == REG_X)
+         
+         /* Last resort, larger than loading from memory.  */
+         *l = 4;
+         return (AS2 (mov,__tmp_reg__,r31) CR_TAB
+                 AS2 (ldi,r31,lo8(%1))     CR_TAB
+                 AS2 (mov,%0,r31)          CR_TAB
+                 AS2 (mov,r31,__tmp_reg__));
+       }
+      else if (GET_CODE (src) == MEM)
+       return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
+    }
+  else if (GET_CODE (dest) == MEM)
+    {
+      int save = 0;
+      char *template;
+      
+      if (operands[1] == const0_rtx)
+       {
+         operands[1] = zero_reg_rtx;
+         save = 1;
+       }
+      
+      template = out_movqi_mr_r (insn, operands, real_l);
+
+      if (!real_l)
+       output_asm_insn (template, operands);
+      
+      if (save)
+       operands[1] = const0_rtx;
+    }
+  return "";
+}
+
+
+char *
+output_movhi (insn, operands, l)
+     rtx insn;
+     rtx operands[];
+     int *l;
+{
+  int dummy;
+  rtx dest = operands[0];
+  rtx src = operands[1];
+  int *real_l = l;
+  
+  if (!l)
+    l = &dummy;
+  
+  if (register_operand (dest, HImode))
+    {
+      if (register_operand (src, HImode)) /* mov r,r */
+       {
+         if (test_hard_reg_class (STACK_REG, dest))
            {
-             /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
-                it but I have this situation with extremal optimizing options
-             */
-             if (l)
-               *l=3;
-             else
+             if (TARGET_TINY_STACK)
+               {
+                 *l = 1;
+                 return AS2 (out,__SP_L__,%A1);
+               }
+             else if (TARGET_NO_INTERRUPTS)
+               {
+                 *l = 2;
+                 return (AS2 (out,__SP_H__,%B1) CR_TAB
+                         AS2 (out,__SP_L__,%A1));
+               }
+
+             *l = 5;
+             return (AS2 (in,__tmp_reg__,__SREG__)  CR_TAB
+                     "cli"                          CR_TAB
+                     AS2 (out,__SP_H__,%B1)         CR_TAB
+                     AS2 (out,__SREG__,__tmp_reg__) CR_TAB
+                     AS2 (out,__SP_L__,%A1));
+           }
+         else if (test_hard_reg_class (STACK_REG, src))
+           {
+             *l = 2;   
+             return (AS2 (in,%A0,__SP_L__) CR_TAB
+                     AS2 (in,%B0,__SP_H__));
+           }
+
+         if (AVR_ENHANCED)
+           {
+             *l = 1;
+             return (AS2 (movw,%0,%1));
+           }
+
+         if (true_regnum (operands[0]) > true_regnum (operands[1]))
+           {
+             *l = 2;
+             return (AS2 (mov,%B0,%B1) CR_TAB
+                     AS2 (mov,%A0,%A1));
+           }
+         else
+           {
+             *l = 2;
+             return (AS2 (mov,%A0,%A1) CR_TAB
+                     AS2 (mov,%B0,%B1));
+           }
+       }
+      else if (CONSTANT_P (src))
+       {
+         if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
+           {
+             *l = 2;
+             return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
+                     AS2 (ldi,%B0,hi8(%1)));
+           }
+         
+         if (GET_CODE (src) == CONST_INT)
+           {
+             if (src == const0_rtx) /* mov r,L */
+               {
+                 *l = 2;
+                 return (AS1 (clr,%A0) CR_TAB
+                         AS1 (clr,%B0));
+               }
+             else if (src == const1_rtx)
+               {
+                 if (reg_was_0 (insn, operands[0]))
+                   {
+                     *l = 1;
+                     return AS1 (inc,%0 ; reg_was_0);
+                   }
+
+                 *l = 2;
+                 return (AS1 (clr,%0) CR_TAB
+                         AS1 (inc,%0));
+               }
+             else if (src == const2_rtx)
                {
-                 output_asm_insn (AS2 (adiw, r26, %0),&XEXP (x,1));
-                 output_asm_insn (AS2 (ld ,%0,X),op);
-                 if (!reg_overlap_mentioned_p (op[0],XEXP (x,0)))
-                   output_asm_insn (AS2 (sbiw, r26, %0),&XEXP (x,1));
+                 if (reg_was_0 (insn, operands[0]))
+                   {
+                     *l = 2;
+                     return (AS1 (inc,%0 ; reg_was_0) CR_TAB
+                             AS1 (inc,%0));
+                   }
+
+                 *l = 3;
+                 return (AS1 (clr,%0) CR_TAB
+                         AS1 (inc,%0) CR_TAB
+                         AS1 (inc,%0));
+               }
+             else if (src == constm1_rtx)
+               {
+                 /* Immediate constants -1 to any register */
+                 if (reg_was_0 (insn, operands[0]))
+                   {
+                     *l = 2;
+                     return (AS1 (dec,%A0 ; reg_was_0) CR_TAB
+                             AS1 (dec,%B0));
+                   }
+
+                 *l = 3;
+                 return (AS1 (clr,%0)  CR_TAB
+                         AS1 (dec,%A0) CR_TAB
+                         AS2 (mov,%B0,%A0));
+               }
+             if ((INTVAL (src) & 0xff) == 0)
+               {
+                 *l = 5;
+                 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
+                         AS1 (clr,%A0)             CR_TAB
+                         AS2 (ldi,r31,hi8(%1))     CR_TAB
+                         AS2 (mov,%B0,r31)         CR_TAB
+                         AS2 (mov,r31,__tmp_reg__));
+               }
+             else if ((INTVAL (src) & 0xff00) == 0)
+               {
+                 *l = 5;
+                 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
+                         AS2 (ldi,r31,lo8(%1))     CR_TAB
+                         AS2 (mov,%A0,r31)         CR_TAB
+                         AS1 (clr,%B0)             CR_TAB
+                         AS2 (mov,r31,__tmp_reg__));
                }
-             return "";
            }
+         
+         /* Last resort, equal to loading from memory.  */
+         *l = 6;
+         return (AS2 (mov,__tmp_reg__,r31) CR_TAB
+                 AS2 (ldi,r31,lo8(%1))     CR_TAB
+                 AS2 (mov,%A0,r31)         CR_TAB
+                 AS2 (ldi,r31,hi8(%1))     CR_TAB
+                 AS2 (mov,%B0,r31)         CR_TAB
+                 AS2 (mov,r31,__tmp_reg__));
+       }
+      else if (GET_CODE (src) == MEM)
+       return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
+    }
+  else if (GET_CODE (dest) == MEM)
+    {
+      int save = 0;
+      char *template;
+      
+      if (operands[1] == const0_rtx)
+       {
+         operands[1] = zero_reg_rtx;
+         save = 1;
        }
+      
+      template = out_movhi_mr_r (insn, operands, real_l);
+
+      if (!real_l)
+       output_asm_insn (template, operands);
+      
+      if (save)
+       operands[1] = const0_rtx;
+      return "";
     }
-  return AS2 (ld%K1,%0,%1);
+  fatal_insn ("Invalid insn:", insn);
+  return "";
+}
+
+char *
+out_movqi_r_mr (insn, op, l)
+     rtx insn;
+     rtx op[];
+     int *l; /* instruction length */
+{
+  rtx x;
+  int dummy;
+  
+  if (!l)
+    l = &dummy;
+  x = XEXP (op[1],0);
+  
+  if (CONSTANT_ADDRESS_P (x))
+    {
+      if (io_address_p (x, 1))
+       {
+         *l = 1;
+         return AS2 (in,%0,%1-0x20);
+       }
+      *l = 2;
+      return AS2 (lds,%0,%1);
+    }
+  /* memory access by reg+disp */
+  else if (GET_CODE (x) == PLUS
+      && REG_P (XEXP (x,0))
+      && GET_CODE (XEXP (x,1)) == CONST_INT)
+    {
+      if((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (op[1]))) >= 63)
+       {
+         int disp = INTVAL (XEXP (x,1));
+         if (REGNO (XEXP (x,0)) != REG_Y)
+           fatal_insn ("Incorrect insn:",insn);
+         if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (op[1])))
+           {
+             *l = 3;
+             op[4] = XEXP (x, 1);
+             return (AS2 (adiw, r28, %4-63) CR_TAB
+                     AS2 (ldd, %0,Y+63)  CR_TAB
+                     AS2 (sbiw, r28, %4-63));
+           }
+         else
+           {
+             *l = 5;
+             op[4] = XEXP (x,1);
+             return (AS2 (subi, r28, lo8(-%4))  CR_TAB
+                     AS2 (sbci, r29, hi8(-%4)) CR_TAB
+                     AS2 (ld, %0,Y)              CR_TAB
+                     AS2 (subi, r28, lo8(%4))   CR_TAB
+                     AS2 (sbci, r29, hi8(%4)));
+           }
+       }
+      else if (REGNO (XEXP (x,0)) == REG_X)
+       {
+         op[4] = XEXP (x, 1);
+         /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
+            it but I have this situation with extremal optimizing options.  */
+         if (reg_overlap_mentioned_p (op[0],XEXP (x,0))
+             || reg_unused_after (insn, XEXP (x,0)))
+           {
+             *l = 2;
+             return (AS2 (adiw,r26,%4) CR_TAB
+                     AS2 (ld,%0,X));
+           }
+         *l = 3;
+         return (AS2 (adiw,r26,%4) CR_TAB
+                 AS2 (ld,%0,X)     CR_TAB
+                 AS2 (sbiw,r26,%4));
+       }
+      *l = 1;
+      return AS2 (ldd,%0,%1);
+    }
+  *l = 1;
+  return AS2 (ld,%0,%1);
 }
 
 char *
@@ -1427,121 +1783,143 @@ out_movhi_r_mr (insn, op, l)
      int *l; /* instruction length */
 {
   int reg_dest = true_regnum (op[0]);
-  int reg_base = true_regnum (XEXP (op[1],0));
-  int len_p = 1,tmp;
-  int *real_l=l;
+  int reg_base = true_regnum (XEXP (op[1], 0));
+  int tmp;
 
   if (!l)
-    l = &tmp, len_p = 0;
+    l = &tmp;
 
   if (reg_base > 0)
     {
       if (reg_dest == reg_base)         /* R = (R) */
-        return *l=3, (AS2 (ld,__tmp_reg__,%1+) CR_TAB
-                      AS2 (ld,%B0,%1) CR_TAB
-                      AS2 (mov,%A0,__tmp_reg__));
+       {
+         *l = 3;
+         return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
+                 AS2 (ld,%B0,%1) CR_TAB
+                 AS2 (mov,%A0,__tmp_reg__));
+       }
       else if (reg_base == REG_X)        /* (R26) */
         {
           if (reg_unused_after (insn, XEXP (op[1],0)))
-            return *l=2, (AS2 (ld,%A0,X+) CR_TAB
-                          AS2 (ld,%B0,X));
-          else
-            return *l=3, (AS2 (ld,%A0,X+) CR_TAB
-                          AS2 (ld,%B0,X) CR_TAB
-                          AS2 (sbiw,r26,1));
+           {
+             *l = 2;
+             return (AS2 (ld,%A0,X+) CR_TAB
+                     AS2 (ld,%B0,X));
+           }
+         *l  = 3;
+         return (AS2 (ld,%A0,X+) CR_TAB
+                 AS2 (ld,%B0,X) CR_TAB
+                 AS2 (sbiw,r26,1));
         }
       else                      /* (R)  */
-        return  *l=2, (AS2 (ld,%A0,%1)    CR_TAB
-                       AS2 (ldd,%B0,%1+1));
+       {
+         *l = 2;
+         return (AS2 (ld,%A0,%1)    CR_TAB
+                 AS2 (ldd,%B0,%1+1));
+       }
     }
   else if (GET_CODE (XEXP (op[1],0)) == PLUS) /* (R + i) */
     {
-      int disp = INTVAL(XEXP (XEXP (op[1],0), 1));
-      int reg_base = true_regnum (XEXP (XEXP (op[1],0), 0));
+      int disp = INTVAL(XEXP (XEXP (op[1], 0), 1));
+      int reg_base = true_regnum (XEXP (XEXP (op[1], 0), 0));
       
       if (disp > MAX_LD_OFFSET (GET_MODE (op[1])))
        {
-         rtx x = XEXP (op[1],0);
+         rtx x = XEXP (op[1], 0);
+         op[4] = XEXP (x, 1);
+
          if (REGNO (XEXP (x,0)) != REG_Y)
            fatal_insn ("Incorrect insn:",insn);
+         
          if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (op[1])))
            {
-             op[4] = GEN_INT (disp - 62);
-             return *l=4, (AS2 (adiw, r28, %4) CR_TAB
-                           AS2 (ldd, %A0,Y+62)       CR_TAB
-                           AS2 (ldd, %B0,Y+63)     CR_TAB
-                           AS2 (sbiw, r28, %4));
+             *l = 4;
+             return (AS2 (adiw,r28,%4-62) CR_TAB
+                     AS2 (ldd,%A0,Y+62)   CR_TAB
+                     AS2 (ldd,%B0,Y+63)   CR_TAB
+                     AS2 (sbiw,r28,%4-62));
            }
          else
            {
-             op[4] = XEXP (x,1);
-             return *l=6, (AS2 (subi, r28, lo8(-%4))  CR_TAB
-                           AS2 (sbci, r29, hi8(-%4)) CR_TAB
-                           AS2 (ld, %A0,Y)             CR_TAB
-                           AS2 (ldd, %B0,Y+1)          CR_TAB
-                           AS2 (subi, r28, lo8(%4))   CR_TAB
-                           AS2 (sbci, r29, hi8(%4)));
+             *l = 6;
+             return (AS2 (subi,r28,lo8(-%4)) CR_TAB
+                     AS2 (sbci,r29,hi8(-%4)) CR_TAB
+                     AS2 (ld,%A0,Y)          CR_TAB
+                     AS2 (ldd,%B0,Y+1)       CR_TAB
+                     AS2 (subi,r28,lo8(%4))  CR_TAB
+                     AS2 (sbci,r29,hi8(%4)));
            }
        }
       if (reg_base == REG_X)
        {
          /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
-            it but I have this situation with extremal optimization options
-          */
-         rtx ops[1];
-         ops[0] = XEXP (XEXP (op[1],0), 1);
-         if (real_l)
-           *l = 4;
-         else if (reg_base == reg_dest)
+            it but I have this situation with extremal
+            optimization options.  */
+         
+         op[4] = XEXP (XEXP (op[1],0), 1);
+         
+         if (reg_base == reg_dest)
            {
-             output_asm_insn (AS2 (adiw, r26, %0), ops);
-             output_asm_insn (AS2 (ld , __tmp_reg__, X+), op);
-             output_asm_insn (AS2 (ld , %B0, X), op);
-             output_asm_insn (AS2 (mov, %A0, __tmp_reg__),op);
+             *l = 4;
+             return (AS2 (adiw,r26,%4)       CR_TAB
+                     AS2 (ld,__tmp_reg__,X+) CR_TAB
+                     AS2 (ld,%B0,X)          CR_TAB
+                     AS2 (mov,%A0,__tmp_reg__));
            }
-         else
+
+         if (INTVAL (op[4]) == 63)
            {
-             output_asm_insn (AS2 (adiw, r26, %0), ops);
-             output_asm_insn (AS2 (ld , %A0, X+), op);
-             output_asm_insn (AS2 (ld , %B0, X), op);
-             if (INTVAL (ops[0]) == 63)
-               {
-                 output_asm_insn (AS2 (subi, r26, %0+1), ops);
-                 output_asm_insn (AS2 (sbci, r26, 0), ops);
-               }
-             else
-               output_asm_insn (AS2 (sbiw, r26, %0+1), ops);
+             *l = 5;
+             return (AS2 (adiw,r26,%4)   CR_TAB
+                     AS2 (ld,%A0,X+)     CR_TAB
+                     AS2 (ld,%B0,X)      CR_TAB
+                     AS2 (subi,r26,%4+1) CR_TAB
+                     AS2 (sbci,r27,0));
            }
-         return "";
+         *l = 4;
+         return (AS2 (adiw,r26,%4) CR_TAB
+                 AS2 (ld,%A0,X+)   CR_TAB
+                 AS2 (ld,%B0,X)    CR_TAB
+                 AS2 (sbiw,r26,%4+1));
+       }
+
+      if (reg_base == reg_dest)
+       {
+         *l = 3;
+         return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
+                 AS2 (ldd,%B0,%B1)         CR_TAB
+                 AS2 (mov,%A0,__tmp_reg__));
        }
       
-      if (reg_base == reg_dest)        
-       return *l=3, (AS2 (ldd,__tmp_reg__,%A1)    CR_TAB
-                     AS2 (ldd,%B0,%B1)   CR_TAB
-                     AS2 (mov,%A0,__tmp_reg__));
-      else
-       return *l=2, (AS2 (ldd,%A0,%A1)    CR_TAB
-                     AS2 (ldd,%B0,%B1));
+      *l = 2;
+      return (AS2 (ldd,%A0,%A1) CR_TAB
+             AS2 (ldd,%B0,%B1));
     }
   else if (GET_CODE (XEXP (op[1],0)) == PRE_DEC) /* (--R) */
     {
       if (reg_overlap_mentioned_p (op[0], XEXP (XEXP (op[1],0),0)))
        fatal_insn ("Incorrect insn:", insn);
-      
-      return *l=2, (AS2 (ld,%B0,%1) CR_TAB
-                   AS2 (ld,%A0,%1));
+
+      *l = 2;
+      return (AS2 (ld,%B0,%1) CR_TAB
+             AS2 (ld,%A0,%1));
     }
   else if (GET_CODE (XEXP (op[1],0)) == POST_INC) /* (R++) */
     {
       if (reg_overlap_mentioned_p (op[0], XEXP (XEXP (op[1],0),0)))
        fatal_insn ("Incorrect insn:", insn);
-      
-      return *l=2, (AS2 (ld,%A0,%1)  CR_TAB
-                   AS2 (ld,%B0,%1));
+
+      *l = 2;
+      return (AS2 (ld,%A0,%1)  CR_TAB
+             AS2 (ld,%B0,%1));
     }
   else if (CONSTANT_ADDRESS_P (XEXP (op[1],0)))
-        return *l=4, (AS2 (lds,%A0,%A1) CR_TAB
-                     AS2 (lds,%B0,%B1));
+    {
+      *l = 4;
+      return (AS2 (lds,%A0,%A1) CR_TAB
+             AS2 (lds,%B0,%B1));
+    }
+  
   fatal_insn ("Unknown move insn:",insn);
   return "";
 }
@@ -1555,8 +1933,10 @@ out_movsi_r_mr (insn,op,l)
   int reg_dest=true_regnum (op[0]);
   int reg_base=true_regnum (XEXP (op[1],0));
   int tmp;
+
   if (!l)
-    l=&tmp;
+    l = &tmp;
+  
   if (reg_base > 0)
     {
       if (reg_base == REG_X)        /* (R26) */
@@ -1687,8 +2067,10 @@ out_movsi_mr_r (insn,op,l)
   int reg_base = true_regnum (XEXP (op[0],0));
   int reg_dest = true_regnum (op[1]);
   int tmp;
+  
   if (!l)
     l = &tmp;
+  
   if (CONSTANT_ADDRESS_P (XEXP (op[0],0)))
     return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
                 AS2 (sts,%B0,%B1) CR_TAB
@@ -1797,81 +2179,192 @@ out_movsi_mr_r (insn,op,l)
 }
 
 char *
-output_movsisf(insn, operands, which_alternative)
+output_movsisf(insn, operands, l)
      rtx insn;
      rtx operands[];
-     int which_alternative;
+     int *l;
 {
-  rtx link;
-  switch (which_alternative)
+  int dummy;
+  rtx dest = operands[0];
+  rtx src = operands[1];
+  int *real_l = l;
+  
+  if (!l)
+    l = &dummy;
+  
+  if (register_operand (dest, VOIDmode))
     {
-    case 0: /* mov r,r */
-      if (true_regnum (operands[0]) > true_regnum (operands[1]))
+      if (register_operand (src, VOIDmode)) /* mov r,r */
        {
-         if (TARGET_ENHANCED)
-           return (AS2 (movw,%C0,%C1) CR_TAB
-                   AS2 (movw,%A0,%A1));  /* FIXME: length = 4 -> 2 */
+         if (true_regnum (dest) > true_regnum (src))
+           {
+             if (AVR_ENHANCED)
+               {
+                 *l = 2;
+                 return (AS2 (movw,%C0,%C1) CR_TAB
+                         AS2 (movw,%A0,%A1));
+               }
+             *l = 4;
+             return (AS2 (mov,%D0,%D1) CR_TAB
+                     AS2 (mov,%C0,%C1) CR_TAB
+                     AS2 (mov,%B0,%B1) CR_TAB
+                     AS2 (mov,%A0,%A1));
+           }
          else
-           return (AS2 (mov,%D0,%D1) CR_TAB
-                   AS2 (mov,%C0,%C1) CR_TAB
-                   AS2 (mov,%B0,%B1) CR_TAB
-                   AS2 (mov,%A0,%A1));
+           {
+             if (AVR_ENHANCED)
+               {
+                 *l = 2;
+                 return (AS2 (movw,%A0,%A1) CR_TAB
+                         AS2 (movw,%C0,%C1));
+               }
+             *l = 4;
+             return (AS2 (mov,%A0,%A1) CR_TAB
+                     AS2 (mov,%B0,%B1) CR_TAB
+                     AS2 (mov,%C0,%C1) CR_TAB
+                     AS2 (mov,%D0,%D1));
+           }
        }
-      else
+      else if (CONSTANT_P (src))
        {
-         if (TARGET_ENHANCED)
-           return (AS2 (movw,%A0,%A1) CR_TAB
-                   AS2 (movw,%C0,%C1));  /* FIXME: length = 4 -> 2 */
-         else
-           return (AS2 (mov,%A0,%A1) CR_TAB
-                   AS2 (mov,%B0,%B1) CR_TAB
-                   AS2 (mov,%C0,%C1) CR_TAB
-                   AS2 (mov,%D0,%D1));
-       }
-    case 1:  /* mov r,L */
-      if (TARGET_ENHANCED)
-       return (AS1 (clr,%A0) CR_TAB
-               AS1 (clr,%B0) CR_TAB
-               AS2 (movw,%C0,%A0));  /* FIXME: length = 4 -> 3 */
-
-      return (AS1 (clr,%A0) CR_TAB
-             AS1 (clr,%B0) CR_TAB
-             AS1 (clr,%C0) CR_TAB
-             AS1 (clr,%D0));
-    case 2: /* mov r,d */
-      if (GET_MODE (operands[0]) == SImode
-         && operands[1] == const1_rtx
-         && (link = find_reg_note (insn, REG_WAS_0, 0))
-         /* Make sure the insn that stored the 0 is still present.  */
-         && ! INSN_DELETED_P (XEXP (link, 0))
-         && GET_CODE (XEXP (link, 0)) != NOTE
-         /* Make sure cross jumping didn't happen here.  */
-         && no_labels_between_p (XEXP (link, 0), insn)
-         /* Make sure the reg hasn't been clobbered.  */
-         && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
-      /* Fastest way to change a 0 to a 1.  */
-        return AS1 (inc,%A0 ; reg_was_0);
-      return (AS2 (ldi,%A0,lo8(%1))  CR_TAB
-             AS2 (ldi,%B0,hi8(%1)) CR_TAB
-             AS2 (ldi,%C0,hlo8(%1)) CR_TAB
-             AS2 (ldi,%D0,hhi8(%1)));
-    case 3: /* mov r,m*/
-    case 5:
-      return out_movsi_r_mr (insn, operands, NULL);
-    case 4: /* mov m,r*/
-    case 6:
-      {
-       rtx save1=NULL;
-       if (operands[1] == const0_rtx)
-         {
-           save1 = operands[1];
-           operands[1] = zero_reg_rtx;
-         }
-       output_asm_insn (out_movsi_mr_r (insn,operands,NULL), operands);
-       if (save1)
-         operands[1] = save1;
-      }
+         if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
+           {
+             *l = 4;
+             return (AS2 (ldi,%A0,lo8(%1))  CR_TAB
+                     AS2 (ldi,%B0,hi8(%1))  CR_TAB
+                     AS2 (ldi,%C0,hlo8(%1)) CR_TAB
+                     AS2 (ldi,%D0,hhi8(%1)));
+           }
+         
+         if (GET_CODE (src) == CONST_INT)
+           {
+             if (src == const0_rtx) /* mov r,L */
+               {
+                 if (AVR_ENHANCED)
+                   {
+                     *l = 3;
+                     return (AS1 (clr,%A0) CR_TAB
+                             AS1 (clr,%B0) CR_TAB
+                             AS2 (movw,%C0,%A0));
+                   }
+                 *l = 4;
+                 return (AS1 (clr,%A0) CR_TAB
+                         AS1 (clr,%B0) CR_TAB
+                         AS1 (clr,%C0) CR_TAB
+                         AS1 (clr,%D0));
+               }
+             else if (src == const1_rtx)
+               {
+                 if (reg_was_0 (insn, operands[0]))
+                   {
+                     *l = 1;
+                     return AS1 (inc,%A0 ; reg_was_0);
+                   }
+
+                 *l = 4;
+                 return (AS1 (clr,%D0) CR_TAB
+                         AS1 (clr,%B0) CR_TAB
+                         AS1 (clr,%C0) CR_TAB
+                         AS1 (inc,%A0));
+               }
+             else if (src == const2_rtx)
+               {
+                 if (reg_was_0 (insn, operands[0]))
+                   {
+                     *l = 2;
+                     return (AS1 (inc,%A0 ; reg_was_0) CR_TAB
+                             AS1 (inc,%A0));
+                   }
+
+                 if (AVR_ENHANCED)
+                   {
+                     *l = 5;
+                     return (AS1 (clr,%D0)      CR_TAB
+                             AS1 (clr,%C0)      CR_TAB
+                             AS2 (movw,%A0,%C0) CR_TAB
+                             AS1 (inc,%A0)      CR_TAB
+                             AS1 (inc,%A0));
+                   }
+                 *l = 6;
+                 return (AS1 (clr,%D0) CR_TAB
+                         AS1 (clr,%B0) CR_TAB
+                         AS1 (clr,%C0) CR_TAB
+                         AS1 (clr,%A0) CR_TAB
+                         AS1 (inc,%A0) CR_TAB
+                         AS1 (inc,%A0));
+               }
+             else if (src == constm1_rtx)
+               {
+                 /* Immediate constants -1 to any register */
+                 if (reg_was_0 (insn, operands[0]))
+                   {
+                     if (AVR_ENHANCED)
+                       {
+                         *l = 3;
+                         return (AS1 (dec,%A0) CR_TAB
+                                 AS1 (dec,%B0) CR_TAB
+                                 AS2 (movw,%C0,%A0));
+                       }
+                     *l = 4;
+                     return (AS1 (dec,%D0 ; reg_was_0) CR_TAB
+                             AS1 (dec,%C0)             CR_TAB
+                             AS1 (dec,%B0)             CR_TAB
+                             AS1 (dec,%A0));
+                   }
+                 if (AVR_ENHANCED)
+                   {
+                     *l = 4;
+                     return (AS1 (clr,%A0)     CR_TAB
+                             AS1 (dec,%A0)     CR_TAB
+                             AS2 (mov,%B0,%A0) CR_TAB
+                             AS2 (movw,%C0,%A0));
+                   }
+                 *l = 5;
+                 return (AS1 (clr,%A0)     CR_TAB
+                         AS1 (dec,%A0)     CR_TAB
+                         AS2 (mov,%B0,%A0) CR_TAB
+                         AS2 (mov,%C0,%A0) CR_TAB
+                         AS2 (mov,%D0,%A0));
+               }
+           }
+         
+         /* Last resort, better than loading from memory.  */
+         *l = 10;
+         return (AS2 (mov,__tmp_reg__,r31) CR_TAB
+                 AS2 (ldi,r31,lo8(%1))     CR_TAB
+                 AS2 (mov,%A0,r31)         CR_TAB
+                 AS2 (ldi,r31,hi8(%1))     CR_TAB
+                 AS2 (mov,%B0,r31)         CR_TAB
+                 AS2 (ldi,r31,hlo8(%1))    CR_TAB
+                 AS2 (mov,%C0,r31)         CR_TAB
+                 AS2 (ldi,r31,hhi8(%1))    CR_TAB
+                 AS2 (mov,%D0,r31)         CR_TAB
+                 AS2 (mov,r31,__tmp_reg__));
+       }
+      else if (GET_CODE (src) == MEM)
+       return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
+    }
+  else if (GET_CODE (dest) == MEM)
+    {
+      int save = 0;
+      char *template;
+      
+      if (operands[1] == const0_rtx)
+       {
+         operands[1] = zero_reg_rtx;
+         save = 1;
+       }
+      
+      template = out_movsi_mr_r (insn, operands, real_l);
+
+      if (!real_l)
+       output_asm_insn (template, operands);
+      
+      if (save)
+       operands[1] = const0_rtx;
+      return "";
     }
+  fatal_insn ("Invalid insn:", insn);
   return "";
 }
 
@@ -1881,66 +2374,90 @@ out_movqi_mr_r (insn, op, l)
      rtx op[];
      int *l; /* instruction length */
 {
-  if (l) *l=1;
+  rtx x;
+  int dummy;
 
-  if (GET_CODE (op[0]) == MEM)
+  if (!l)
+    l = &dummy;
+    
+  x = XEXP (op[0],0);
+  
+  if (CONSTANT_ADDRESS_P (x))
     {
-      rtx x = XEXP (op[0],0);
-      if (GET_CODE (x) == PLUS
-         && REG_P (XEXP (x,0))
-         && GET_CODE (XEXP (x,1)) == CONST_INT)
+      if (io_address_p (x, 1))
+       {
+         *l = 1;
+         return AS2 (out,%0-0x20,%1);
+       }
+      *l = 2;
+      return AS2 (sts,%0,%1);
+    }
+  /* memory access by reg+disp */
+  else if (GET_CODE (x) == PLUS        
+      && REG_P (XEXP (x,0))
+      && GET_CODE (XEXP (x,1)) == CONST_INT)
+    {
+      if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (op[0]))) >= 63)
        {
-         if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (op[0]))) >= 63)
+         int disp = INTVAL (XEXP (x,1));
+         if (REGNO (XEXP (x,0)) != REG_Y)
+           fatal_insn ("Incorrect insn:",insn);
+         if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (op[0])))
            {
-             int disp = INTVAL (XEXP (x,1));
-             if (REGNO (XEXP (x,0)) != REG_Y)
-               fatal_insn ("Incorrect insn:",insn);
-             if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (op[0])))
-               {
-                 if (l)
-                   *l = 3;
-                 else
-                   {
-                     op[4] = GEN_INT (disp - 63);
-                     return (AS2 (adiw, r28, %4) CR_TAB
-                             AS2 (std, Y+63,%1)        CR_TAB
-                             AS2 (sbiw, r28, %4));
-                   }
-               }
-             else
+             *l = 3;
+             op[4] = XEXP (x, 1);
+             return (AS2 (adiw, r28, %4-63) CR_TAB
+                     AS2 (std, Y+63,%1)        CR_TAB
+                     AS2 (sbiw, r28, %4-63));
+           }
+         else
+           {
+             *l = 5;
+             op[4] = XEXP (x,1);
+             return (AS2 (subi, r28, lo8(-%4))  CR_TAB
+                     AS2 (sbci, r29, hi8(-%4)) CR_TAB
+                     AS2 (st, Y,%1)              CR_TAB
+                     AS2 (subi, r28, lo8(%4))   CR_TAB
+                     AS2 (sbci, r29, hi8(%4)));
+           }
+       }
+      else if (REGNO (XEXP (x,0)) == REG_X)
+       {
+         op[4] = XEXP (x,1);
+         if (reg_overlap_mentioned_p (op[1],XEXP (x,0)))
+           {
+             if (reg_unused_after (insn, XEXP (x,0)))
                {
-                 op[4] = XEXP (x,1);
-                 if (l)
-                   *l = 5;
-                 else
-                   return (AS2 (subi, r28, lo8(-%4))  CR_TAB
-                           AS2 (sbci, r29, hi8(-%4)) CR_TAB
-                           AS2 (st, Y,%1)              CR_TAB
-                           AS2 (subi, r28, lo8(%4))   CR_TAB
-                           AS2 (sbci, r29, hi8(%4)));
+                 *l = 3;
+                 return (AS2 (mov,__tmp_reg__,%1) CR_TAB
+                         AS2 (adiw,r26,%4)        CR_TAB
+                         AS2 (st,X,__tmp_reg__));
                }
+             *l = 4;
+             return (AS2 (mov,__tmp_reg__,%1) CR_TAB
+                     AS2 (adiw,r26,%4)        CR_TAB
+                     AS2 (st,X,__tmp_reg__)   CR_TAB
+                     AS2 (sbiw,r26,%4));
            }
-         else if (REGNO (XEXP (x,0)) == REG_X)
+         else
            {
-             if (l)
-               *l=4;
-             else
+             if (reg_unused_after (insn, XEXP (x,0)))
                {
-                 int overlap_p = reg_overlap_mentioned_p (op[1],XEXP (x,0));
-                 if (!overlap_p)
-                   output_asm_insn (AS2 (mov, __tmp_reg__, %1),op);
-                 output_asm_insn (AS2 (adiw, r26,%0),&XEXP (x,1));
-                 if (overlap_p)
-                   output_asm_insn (AS2 (st ,X,__tmp_reg__),op);
-                 else
-                   output_asm_insn (AS2 (st ,X,%1),op);
-                 output_asm_insn (AS2 (sbiw ,r26,%0),&XEXP (x,1));
+                 *l = 2;
+                 return (AS2 (adiw,r26,%4) CR_TAB
+                         AS2 (st,X,%1));
                }
-             return "";
+             *l = 3;
+             return (AS2 (adiw,r26,%4) CR_TAB
+                     AS2 (st,X,%1)      CR_TAB
+                     AS2 (sbiw,r26,%4));
            }
        }
+      *l = 1;
+      return AS2 (std,%0,%1);
     }
-  return AS2 (st%K0, %0,%1);
+  *l = 1;
+  return AS2 (st,%0,%1);
 }
 
 char *
@@ -2017,7 +2534,7 @@ out_movhi_mr_r (insn,op,l)
        }
       return *l=2, (AS2 (std,%A0,%A1)    CR_TAB
                    AS2 (std,%B0,%B1));
-    }  
+    }
   else if (GET_CODE (XEXP (op[0],0)) == PRE_DEC) /* (--R) */
     return *l=2, (AS2 (st,%0,%B1) CR_TAB
                  AS2 (st,%0,%A1));
@@ -2412,7 +2929,7 @@ ashlsi3_out (insn,operands,len)
            int reg0 = true_regnum (operands[0]);
            int reg1 = true_regnum (operands[1]);
            *len = 4;
-           if (TARGET_ENHANCED && (reg0 + 2 != reg1))
+           if (AVR_ENHANCED && (reg0 + 2 != reg1))
              {
                *len = 3;
                return (AS2 (movw,%C0,%A1) CR_TAB
@@ -2653,7 +3170,7 @@ ashrsi3_out (insn,operands,len)
            int reg0 = true_regnum (operands[0]);
            int reg1 = true_regnum (operands[1]);
            *len=6;
-           if (TARGET_ENHANCED && (reg0 != reg1 + 2))
+           if (AVR_ENHANCED && (reg0 != reg1 + 2))
              {
                *len = 5;
                return (AS2 (movw,%A0,%C1) CR_TAB
@@ -2912,7 +3429,7 @@ lshrsi3_out (insn,operands,len)
            int reg0 = true_regnum (operands[0]);
            int reg1 = true_regnum (operands[1]);
            *len = 4;
-           if (TARGET_ENHANCED && (reg0 != reg1 + 2))
+           if (AVR_ENHANCED && (reg0 != reg1 + 2))
              {
                *len = 3;
                return (AS2 (movw,%A0,%C1) CR_TAB
@@ -2971,49 +3488,25 @@ adjust_insn_length (insn,len)
       rtx op[10];
       op[1] = SET_SRC (patt);
       op[0] = SET_DEST (patt);
-      if (REG_P (op[0]) && GET_CODE (op[1]) == MEM)
-        {
-         if (CONSTANT_ADDRESS_P (XEXP (op[1],0)))
-           switch (GET_MODE (op[0]))
-             {
-             case QImode: len = 2; break;
-             case HImode: len = 4; break;
-             case SImode:
-             case SFmode: len = 8; break;
-             default: break; 
-             }
-         else
-           switch (GET_MODE (op[0]))
-             {
-             case QImode: out_movqi_r_mr (insn,op,&len); break;
-             case HImode: out_movhi_r_mr (insn,op,&len); break;
-             case SImode:
-             case SFmode: out_movsi_r_mr (insn,op,&len); break;
-             default: break;
-             }
-        }
-      else if ((REG_P (op[1]) || const0_rtx == op[1])
-              && GET_CODE (op[0]) == MEM)
-        {
-         if (CONSTANT_ADDRESS_P (XEXP (op[0],0)))
-           switch (GET_MODE (op[0]))
-             {
-             case QImode: len = 2; break;
-             case HImode: len = 4; break;
-             case SImode:
-             case SFmode: len = 8; break;
-             default: break;
-             }
-         else if (GET_CODE (XEXP (op[0],0)) != POST_DEC)
-           switch (GET_MODE (op[0]))
-             {
-             case QImode: out_movqi_mr_r (insn,op,&len); break;
-             case HImode: out_movhi_mr_r (insn,op,&len); break;
-             case SImode:
-             case SFmode: out_movsi_mr_r (insn,op,&len); break;
-             default: break;
-             }
-        }
+      if (general_operand (op[1], VOIDmode)
+         && general_operand (op[0], VOIDmode))
+       {
+         switch (GET_MODE (op[0]))
+           {
+           case QImode:
+             output_movqi (insn, op, &len);
+             break;
+           case HImode:
+             output_movhi (insn, op, &len);
+             break;
+           case SImode:
+           case SFmode:
+             output_movsisf (insn, op, &len);
+             break;
+           default:
+             break;
+           }
+       }
       else if (op[0] == cc0_rtx && REG_P (op[1]))
        {
          switch (GET_MODE (op[1]))
@@ -3112,13 +3605,7 @@ reg_unused_after (insn, reg)
      rtx insn;
      rtx reg;
 {
-  return (0
-         /* In egcs 1.1.x dead_or_set_p give buggy result after reload 
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-         || dead_or_set_p (insn,reg)
-#endif
-         */
-         
+  return (dead_or_set_p (insn, reg)
          || (REG_P(reg) && _reg_unused_after (insn, reg)));
 }
 
@@ -3408,7 +3895,7 @@ gas_output_ascii(file, str, length)
              fprintf (file, "\"\n");
              bytes_in_chunk = 0;
            }
-         gas_output_limited_string (file, _ascii_bytes);
+         gas_output_limited_string (file, (char*)_ascii_bytes);
          _ascii_bytes = p;
        }
       else
@@ -3552,20 +4039,11 @@ asm_file_start (file)
      FILE *file;
 {
   output_file_directive (file, main_input_filename);
-  fprintf (file, "\t.arch %s\n", avr_mcu_type->name);
+  fprintf (file, "\t.arch %s\n", avr_mcu_name);
   fputs ("__SREG__ = 0x3f\n"
         "__SP_H__ = 0x3e\n"
         "__SP_L__ = 0x3d\n", file);
   
-  if (avr_ram_end)
-    initial_stack = avr_ram_end;
-  else
-    {
-      static char buf[30];
-      initial_stack = buf;
-      sprintf (buf, "0x%x", avr_mcu_type->stack);
-    }
-  
   fputs ("__tmp_reg__ = 0\n" 
         "__zero_reg__ = 1\n"
         "_PC_ = 2\n", file);
@@ -3953,17 +4431,9 @@ mask_one_bit_p (mask)
 
 enum reg_class
 preferred_reload_class (x, class)
-     rtx x;
+     rtx x ATTRIBUTE_UNUSED;
      enum reg_class class;
 {
-  if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0)
-    return class;
-  if (CONSTANT_P (x) && (class == NO_LD_REGS
-                        || class == ALL_REGS
-                        || class == GENERAL_REGS))
-    {
-      return LD_REGS;
-    }
   return class;
 }
 
@@ -3979,7 +4449,8 @@ test_hard_reg_class (class, x)
 }
 
 void
-debug_hard_reg_set (HARD_REG_SET set)
+debug_hard_reg_set (set)
+     HARD_REG_SET set;
 {
   int i;
   for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
@@ -4017,7 +4488,133 @@ avr_hard_regno_mode_ok (regno, mode)
 {
   if (mode == QImode)
     return 1;
-  if (regno < 24 && !TARGET_ENHANCED)
+  if (regno < 24 && !AVR_ENHANCED)
     return 1;
   return !(regno & 1);
 }
+
+/* Returns 1 if we know register operand OP was 0 before INSN.  */
+
+static int
+reg_was_0 (insn, op)
+     rtx insn;
+     rtx op;
+{
+  rtx link;
+  return (optimize > 0 && insn && op && REG_P (op)
+         && (link = find_reg_note (insn, REG_WAS_0, 0))
+         /* Make sure the insn that stored the 0 is still present.  */
+         && ! INSN_DELETED_P (XEXP (link, 0))
+         && GET_CODE (XEXP (link, 0)) != NOTE
+         /* Make sure cross jumping didn't happen here.  */
+         && no_labels_between_p (XEXP (link, 0), insn)
+         /* Make sure the reg hasn't been clobbered.  */
+         && ! reg_set_between_p (op, XEXP (link, 0), insn));
+}
+
+/* Returns 1 if X is a valid address for an I/O register of size SIZE
+   (1 or 2).  Used for lds/sts -> in/out optimization.  */
+
+static int
+io_address_p (x, size)
+     rtx x;
+     int size;
+{
+  return (optimize > 0 && GET_CODE (x) == CONST_INT
+         && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
+}
+
+/* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2.  */
+
+int
+const_int_pow2_p (x)
+     rtx x;
+{
+  if (GET_CODE (x) == CONST_INT)
+    {
+      HOST_WIDE_INT d = INTVAL (x);
+      HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
+      return exact_log2 (abs_d) + 1;
+    }
+  return 0;
+}
+
+char *
+output_reload_inhi (insn, operands, len)
+     rtx insn ATTRIBUTE_UNUSED;
+     rtx *operands;
+     int *len;
+{
+  if (GET_CODE (operands[1]) == CONST_INT)
+    {
+      int val = INTVAL (operands[1]);
+      if ((val & 0xff) == 0)
+       {
+         *len = 3;
+         return (AS2 (mov,%A0,__zero_reg__) CR_TAB
+                 AS2 (ldi,%2,hi8(%1))       CR_TAB
+                 AS2 (mov,%B0,%2));
+       }
+      else if ((val & 0xff00) == 0)
+       {
+         *len = 3;
+         return (AS2 (ldi,%2,lo8(%1)) CR_TAB
+                 AS2 (mov,%A0,%2)     CR_TAB
+                 AS2 (mov,%B0,__zero_reg__));
+       }
+      else if ((val & 0xff) == ((val & 0xff00) >> 8))
+       {
+         *len = 3;
+         return (AS2 (ldi,%2,lo8(%1)) CR_TAB
+                 AS2 (mov,%A0,%2)     CR_TAB
+                 AS2 (mov,%B0,%2));
+       }
+    }
+  *len = 4;
+  return (AS2 (ldi,%2,lo8(%1)) CR_TAB
+         AS2 (mov,%A0,%2)     CR_TAB
+         AS2 (ldi,%2,hi8(%1)) CR_TAB
+         AS2 (mov,%B0,%2));
+}
+
+
+char *
+output_reload_insisf (insn, operands, which_alternative)
+     rtx insn ATTRIBUTE_UNUSED;
+     rtx *operands;
+     int which_alternative ATTRIBUTE_UNUSED;
+{
+  int cnst = (GET_CODE (operands[1]) == CONST_INT);
+
+  if (cnst && ((INTVAL (operands[1]) & 0xff) == 0))
+    output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
+  else
+    {
+      output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
+      output_asm_insn (AS2 (mov, %A0, %2), operands);
+    }
+  if (cnst && ((INTVAL (operands[1]) & 0xff00) == 0))
+    output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
+  else
+    {
+      output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
+      output_asm_insn (AS2 (mov, %B0, %2), operands);
+    }
+  if (cnst && ((INTVAL (operands[1]) & 0xff0000) == 0))
+    output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
+  else
+    {
+      output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
+      output_asm_insn (AS2 (mov, %C0, %2), operands);
+    }
+  if (cnst && ((INTVAL (operands[1]) & 0xff000000U) == 0))
+    output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
+  else
+    {
+      output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
+      output_asm_insn (AS2 (mov, %D0, %2), operands);
+    }
+  return "";
+}
+
+
index b1e52cf..fa51e51 100644 (file)
@@ -56,7 +56,6 @@ extern int target_flags;
 #define MASK_CALL_PROLOGUES    0x00040000
 #define MASK_TINY_STACK                0x00080000
 #define MASK_PACK_ARGS         0x00100000
-#define MASK_ENHANCED          0x00200000
 
 #define TARGET_ORDER_1         (target_flags & MASK_ORDER_1)
 #define TARGET_ORDER_2         (target_flags & MASK_ORDER_2)
@@ -66,7 +65,6 @@ extern int target_flags;
 #define TARGET_CALL_PROLOGUES  (target_flags & MASK_CALL_PROLOGUES)
 #define TARGET_TINY_STACK      (target_flags & MASK_TINY_STACK)
 #define TARGET_PACK_ARGS       (target_flags & MASK_PACK_ARGS)
-#define TARGET_ENHANCED                (target_flags & MASK_ENHANCED)
 
 /* Dump each assembler insn's rtl into the output file.
    This is for debugging the compiler itself.  */
@@ -108,8 +106,6 @@ extern int target_flags;
     N_("Change only the low 8 bits of the stack pointer") },           \
   { "pack-args", MASK_PACK_ARGS,                                       \
     N_("Do not align function arguments on even numbered registers") },        \
-  { "enhanced", MASK_ENHANCED,                                         \
-    N_("Generate code for the enhanced AVR core") },                   \
   { "rtl", MASK_RTL_DUMP, NULL },                                      \
   { "size", MASK_INSN_SIZE_DUMP,                                       \
     N_("Output instruction sizes to the asm file") },                  \
@@ -137,20 +133,16 @@ extern int target_flags;
    { "68000", -1},     \
    { "", 1}}  */
 
-extern const char *avr_ram_end;
+extern const char *avr_init_stack;
 extern const char *avr_mcu_name;
+extern int avr_mega_p;
+extern int avr_enhanced_p;
 
-struct mcu_type_s {
-  char * name;
-  int stack;
-  int mega;
- };
-
-extern struct mcu_type_s *avr_mcu_type;
-#define AVR_MEGA (avr_mcu_type->mega)
+#define AVR_MEGA (avr_mega_p)
+#define AVR_ENHANCED (avr_enhanced_p)
 
 #define TARGET_OPTIONS {                                                     \
- { "init-stack=", &avr_ram_end, N_("Specify the initial stack address") },    \
+ { "init-stack=", &avr_init_stack, N_("Specify the initial stack address") }, \
  { "mcu=", &avr_mcu_name, N_("Specify the MCU name") } }
 /* This macro is similar to `TARGET_SWITCHES' but defines names of
    command options that have values.  Its definition is an
@@ -2246,7 +2238,7 @@ progmem_section (void)                                                          \
 do {                                                                      \
      fputs ("\t.comm ", (STREAM));                                        \
      assemble_name ((STREAM), (NAME));                                    \
-     fprintf ((STREAM), ",%d\n", (SIZE));                                 \
+     fprintf ((STREAM), ",%d,1\n", (SIZE));                               \
 } while (0)
 /* A C statement (sans semicolon) to output to the stdio stream
    STREAM the assembler definition of a common-label named NAME whose
@@ -2459,8 +2451,16 @@ while (0)
    and after that, output the additional assembler syntax for making
    that name global, and a newline.  */
 
-/* `ASM_WEAKEN_LABEL'
-   A C statement (sans semicolon) to output to the stdio stream
+#define ASM_WEAKEN_LABEL(FILE, NAME)   \
+  do                                   \
+    {                                  \
+      fputs ("\t.weak\t", (FILE));     \
+      assemble_name ((FILE), (NAME));  \
+      fputc ('\n', (FILE));            \
+    }                                  \
+  while (0)
+
+/* A C statement (sans semicolon) to output to the stdio stream
    STREAM some commands that will make the label NAME weak; that is,
    available for reference from other files but only used if no other
    definition is available.  Use the expression `assemble_name
@@ -2470,9 +2470,10 @@ while (0)
 
    If you don't define this macro, GNU CC will not support weak
    symbols and you should not define the `SUPPORTS_WEAK' macro.
+*/
 
-   `SUPPORTS_WEAK'
-   A C expression which evaluates to true if the target supports weak
+#define SUPPORTS_WEAK 1
+/* A C expression which evaluates to true if the target supports weak
    symbols.
 
    If you don't define this macro, `defaults.h' provides a default
@@ -2919,19 +2920,36 @@ valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
    the BSD functions `bcopy' and `bzero'.  */
 
 #define CPP_SPEC "\
-%{!mmcu=*:-DAVR_AT90S8515} \
-%{mmcu=at90s2313:-DAVR_AT90S2313} \
-%{mmcu=at90s2323:-DAVR_AT90S2323} \
-%{mmcu=at90s2333:-DAVR_AT90S2333} \
-%{mmcu=at90s2343:-DAVR_AT90S2343} \
-%{mmcu=attiny22:-DAVR_ATtiny22} \
-%{mmcu=at90s4433:-DAVR_AT90S4433} \
-%{mmcu=at90s4414:-DAVR_AT90S4414} \
-%{mmcu=at90s4434:-DAVR_AT90S4434} \
-%{mmcu=at90s8515:-DAVR_AT90S8515} \
-%{mmcu=at90s8535:-DAVR_AT90S8535} \
-%{mmcu=atmega603:-DAVR_ATmega603} \
-%{mmcu=atmega103:-DAVR_ATmega103} \
+%{!mmcu*|mmcu=avr2:%(cpp_avr2)} \
+%{mmcu=at90s2313:%(cpp_avr2) -D__AVR_AT90S2313__} \
+%{mmcu=at90s2323:%(cpp_avr2) -D__AVR_AT90S2323__} \
+%{mmcu=at90s2333:%(cpp_avr2) -D__AVR_AT90S2333__} \
+%{mmcu=at90s2343:%(cpp_avr2) -D__AVR_AT90S2343__} \
+%{mmcu=attiny22: %(cpp_avr2) -D__AVR_ATtiny22__} \
+%{mmcu=at90s4433:%(cpp_avr2) -D__AVR_AT90S4433__} \
+%{mmcu=at90s4414:%(cpp_avr2) -D__AVR_AT90S4414__} \
+%{mmcu=at90s4434:%(cpp_avr2) -D__AVR_AT90S4434__} \
+%{mmcu=at90s8515:%(cpp_avr2) -D__AVR_AT90S8515__} \
+%{mmcu=at90s8535:%(cpp_avr2) -D__AVR_AT90S8535__} \
+%{mmcu=at90c8534:%(cpp_avr2) -D__AVR_AT90C8534__} \
+%{mmcu=avr3:%(cpp_avr3)} \
+%{mmcu=atmega603:%(cpp_avr3) -D__AVR_ATmega603__} \
+%{mmcu=atmega103:%(cpp_avr3) -D__AVR_ATmega103__} \
+%{mmcu=avr4:%(cpp_avr4)} \
+%{mmcu=atmega83: %(cpp_avr4) -D__AVR_ATmega83__} \
+%{mmcu=atmega85: %(cpp_avr4) -D__AVR_ATmega85__} \
+%{mmcu=avr5:%(cpp_avr5)} \
+%{mmcu=atmega161:%(cpp_avr5) -D__AVR_ATmega161__} \
+%{mmcu=atmega163:%(cpp_avr5) -D__AVR_ATmega163__} \
+%{mmcu=atmega32: %(cpp_avr5) -D__AVR_ATmega32__} \
+%{mmcu=at94k:    %(cpp_avr5) -D__AVR_AT94K__} \
+%{mmcu=avr1:%(cpp_avr1)} \
+%{mmcu=at90s1200:%(cpp_avr1) -D__AVR_AT90S1200__} \
+%{mmcu=attiny10|mmcu=attiny11: %(cpp_avr1) -D__AVR_ATtiny11__} \
+%{mmcu=attiny12: %(cpp_avr1) -D__AVR_ATtiny12__} \
+%{mmcu=attiny15: %(cpp_avr1) -D__AVR_ATtiny15__} \
+%{mmcu=attiny28: %(cpp_avr1) -D__AVR_ATtiny28__} \
+%{mno-interrupts:-D__NO_INTERRUPTS__} \
 %{mint8:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long -D__INT_MAX__=127} \
 %{!mint*:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int -D__INT_MAX__=32767} \
 %{posix:-D_POSIX_SOURCE}"
@@ -2968,14 +2986,14 @@ valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
    Do not define this macro unless you need to override the default
    definition.  */
 
-#define CC1_SPEC "%{!mmcu*:-mmcu=at90s8515} %{profile:-p}"
+#define CC1_SPEC "%{profile:-p}"
 /* A C string constant that tells the GNU CC driver program options to
    pass to `cc1'.  It can also specify how to translate options you
    give to GNU CC into options for GNU CC to pass to the `cc1'.
 
    Do not define this macro if it does not need to do anything.  */
 
-#define ASM_SPEC ""
+#define ASM_SPEC "%{mmcu=*:-mmcu=%*}"
 /* A C string constant that tells the GNU CC driver program options to
    pass to the assembler.  It can also specify how to translate
    options you give to GNU CC into options for GNU CC to pass to the
@@ -2995,6 +3013,14 @@ valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
 %{!mmcu*:-m avr85xx} \
 %{mmcu=atmega603:-m avrmega603} \
 %{mmcu=atmega103:-m avrmega103} \
+%{mmcu=atmega161:-m avrmega161} \
+%{mmcu=atmega163:-m avrmega161} \
+%{mmcu=atmega32:-m avr5} \
+%{mmcu=at94k:-m avr5} \
+%{mmcu=atmega83:-m avr4} \
+%{mmcu=atmega85:-m avr4} \
+%{mmcu=at90s1200|mmcu=attiny1*:-m avr1200} \
+%{mmcu=attiny28:-m avr1} \
 %{mmcu=at90s2313:-m avr23xx} \
 %{mmcu=at90s2323:-m avr23xx} \
 %{mmcu=attiny22:-m avr23xx} \
@@ -3003,6 +3029,7 @@ valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
 %{mmcu=at90s4433:-m avr4433} \
 %{mmcu=at90s4414:-m avr44x4} \
 %{mmcu=at90s4434:-m avr44x4} \
+%{mmcu=at90c8534:-m avr85xx} \
 %{mmcu=at90s8535:-m avr85xx} \
 %{mmcu=at90s8515:-m avr85xx}"
 
@@ -3012,9 +3039,8 @@ valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
 
    Do not define this macro if it does not need to do anything.  */
 
-#define LIB_SPEC "\
-%{!mmcu*|mmcu=at90s*|mmcu=attiny22: -lc} \
-%{mmcu=atmega*: -lc-mega}"
+#define LIB_SPEC \
+  "%{!mmcu=at90s1*:%{!mmcu=attiny1*:%{!mmcu=attiny28: -lc }}}"
 /* Another C string constant used much like `LINK_SPEC'.  The
    difference between the two is that `LIB_SPEC' is used at the end
    of the command given to the linker.
@@ -3022,9 +3048,8 @@ valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
    If this macro is not defined, a default is provided that loads the
    standard C library from the usual place.  See `gcc.c'.  */
 
-#define LIBGCC_SPEC "\
-%{mmcu=atmega*:-lgcc} \
-%{!mmcu*|mmcu=at90s*|mmcu=attiny22:-lgcc}"
+#define LIBGCC_SPEC \
+  "%{!mmcu=at90s1*:%{!mmcu=attiny1*:%{!mmcu=attiny28: -lgcc }}}"
 /* Another C string constant that tells the GNU CC driver program how
    and when to place a reference to `libgcc.a' into the linker
    command line.  This constant is placed both before and after the
@@ -3050,21 +3075,43 @@ valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
    Do not define this macro if it does not need to do anything.  */
 
 #define CRT_BINUTILS_SPECS "\
-%{!mmcu*:gcrt1-8515.o%s} \
-%{mmcu=atmega603:gcrt1-mega603.o%s} \
-%{mmcu=atmega103:gcrt1-mega103.o%s} \
-%{mmcu=at90s2313:gcrt1-2313.o%s} \
-%{mmcu=at90s2323:gcrt1-2323.o%s} \
-%{mmcu=attiny22:gcrt1-tiny22.o%s} \
-%{mmcu=at90s2333:gcrt1-2333.o%s} \
-%{mmcu=at90s2343:gcrt1-2343.o%s} \
-%{mmcu=at90s4433:gcrt1-4433.o%s} \
-%{mmcu=at90s4414:gcrt1-4414.o%s} \
-%{mmcu=at90s4434:gcrt1-4434.o%s} \
-%{mmcu=at90s8535:gcrt1-8535.o%s} \
-%{mmcu=at90s8515:gcrt1-8515.o%s}"
-
-#define EXTRA_SPECS                            \
+%{mmcu=at90s1200|mmcu=avr1:crts1200.o%s} \
+%{mmcu=attiny10|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=attiny22:crttn22.o%s} \
+%{mmcu=at90s2333:crts2333.o%s} \
+%{mmcu=at90s2343:crts2343.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=atmega103|mmcu=avr3:crtm103.o%s} \
+%{mmcu=atmega603:crtm603.o%s} \
+%{mmcu=atmega83|mmcu=avr4:crtm83.o%s} \
+%{mmcu=atmega85:crtm85.o%s} \
+%{mmcu=atmega161|mmcu=avr5:crtm161.o%s} \
+%{mmcu=atmega163:crtm163.o%s} \
+%{mmcu=atmega32:crtm32.o%s} \
+%{mmcu=at94k:crtat94k.o%s}"
+
+#define CPP_AVR1_SPEC "-D__AVR_ARCH__=1 -D__AVR_ASM_ONLY__ "
+#define CPP_AVR2_SPEC "-D__AVR_ARCH__=2 "
+#define CPP_AVR3_SPEC "-D__AVR_ARCH__=3 -D__AVR_MEGA__ "
+#define CPP_AVR4_SPEC "-D__AVR_ARCH__=4 -D__AVR_ENHANCED__ "
+#define CPP_AVR5_SPEC "-D__AVR_ARCH__=5 -D__AVR_ENHANCED__ -D__AVR_MEGA__ "
+
+#define EXTRA_SPECS                           \
+{"cpp_avr1", CPP_AVR1_SPEC},                  \
+{"cpp_avr2", CPP_AVR2_SPEC},                  \
+{"cpp_avr3", CPP_AVR3_SPEC},                  \
+{"cpp_avr4", CPP_AVR4_SPEC},                  \
+{"cpp_avr5", CPP_AVR5_SPEC},                  \
 {"crt_binutils", CRT_BINUTILS_SPECS},
 /* Define this macro to provide additional specifications to put in
    the `specs' file that can be used in various specifications like
@@ -3110,6 +3157,9 @@ valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
    #undef CPP_SYSV_DEFAULT
    #define CPP_SYSV_DEFAULT "-D_CALL_AIX"  */
 
+/* This is the default without any -mmcu=* option (AT90S*).  */
+#define MULTILIB_DEFAULTS { "mmcu=avr2" }
+
 /* This is undefined macro for collect2 disabling */
 #define LINKER_NAME "ld"
 
@@ -3141,50 +3191,50 @@ valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
 #define INIT_TARGET_OPTABS                             \
 {                                                      \
   smul_optab->handlers[(int) QImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_mulqi3");          \
+    = gen_rtx (SYMBOL_REF, Pmode, "__mulqi3");         \
                                                        \
   sdiv_optab->handlers[(int) QImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_divqi3");          \
+    = gen_rtx (SYMBOL_REF, Pmode, "__divqi3");         \
                                                        \
   smod_optab->handlers[(int) QImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_modqi3");          \
+    = gen_rtx (SYMBOL_REF, Pmode, "__modqi3");         \
                                                        \
   udiv_optab->handlers[(int) QImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_udivqi3");         \
+    = gen_rtx (SYMBOL_REF, Pmode, "__udivqi3");                \
                                                        \
   umod_optab->handlers[(int) QImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_umodqi3");         \
+    = gen_rtx (SYMBOL_REF, Pmode, "__umodqi3");                \
                                                        \
   smul_optab->handlers[(int) HImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_mulhi3");          \
+    = gen_rtx (SYMBOL_REF, Pmode, "__mulhi3");         \
                                                        \
   sdiv_optab->handlers[(int) HImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_divhi3");          \
+    = gen_rtx (SYMBOL_REF, Pmode, "__divhi3");         \
                                                        \
   smod_optab->handlers[(int) HImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_modhi3");          \
+    = gen_rtx (SYMBOL_REF, Pmode, "__modhi3");         \
                                                        \
   udiv_optab->handlers[(int) HImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_udivhi3");         \
+    = gen_rtx (SYMBOL_REF, Pmode, "__udivhi3");                \
                                                        \
   umod_optab->handlers[(int) HImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_umodhi3");         \
+    = gen_rtx (SYMBOL_REF, Pmode, "__umodhi3");                \
                                                        \
   smul_optab->handlers[(int) SImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_mulsi3");          \
+    = gen_rtx (SYMBOL_REF, Pmode, "__mulsi3");         \
                                                        \
   sdiv_optab->handlers[(int) SImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_divsi3");          \
+    = gen_rtx (SYMBOL_REF, Pmode, "__divsi3");         \
                                                        \
   smod_optab->handlers[(int) SImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_modsi3");          \
+    = gen_rtx (SYMBOL_REF, Pmode, "__modsi3");         \
                                                        \
   udiv_optab->handlers[(int) SImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_udivsi3");         \
+    = gen_rtx (SYMBOL_REF, Pmode, "__udivsi3");                \
                                                        \
   umod_optab->handlers[(int) SImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "_umodsi3");         \
-  avr_init_once();                                     \
+    = gen_rtx (SYMBOL_REF, Pmode, "__umodsi3");                \
+  avr_init_once ();                                    \
 }
 
 /* Temporary register r0 */
@@ -3193,8 +3243,12 @@ valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
 /* zero register r1 */
 #define ZERO_REGNO 1
 
+/* Temporary register which used for load immediate values to r0-r15  */
+#define LDI_REG_REGNO 31
+
 extern struct rtx_def *tmp_reg_rtx;
 extern struct rtx_def *zero_reg_rtx;
+extern struct rtx_def *ldi_reg_rtx;
 
 #define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
 
index 1d8d100..ace4997 100644 (file)
        push %A0"
   [(set_attr "length" "4")])
 
-(define_insn "*mov_r_sp"
-  [(set (match_operand:HI 0 "register_operand" "=r")
-        (reg:HI 32))]
-  ""
-  "in %A0,__SP_L__
-       in %B0,__SP_H__"
-  [(set_attr "length" "2")])
-
-(define_insn "*mov_sp_r"
-  [(set (reg:HI 32)
-        (match_operand:HI 0 "register_operand" "r"))]
-  "(!TARGET_TINY_STACK && !TARGET_NO_INTERRUPTS)"
-  "in __tmp_reg__,__SREG__
-       cli
-       out __SP_H__,%B0
-       out __SREG__,__tmp_reg__
-       out __SP_L__,%A0"
-  [(set_attr "length" "5")])
-
-(define_insn "*mov_sp_r_no_interrupts"
-  [(set (reg:HI 32)
-        (match_operand:HI 0 "register_operand" "r"))]
-  "(!TARGET_TINY_STACK && TARGET_NO_INTERRUPTS)"
-  "out __SP_H__,%B0
-       out __SP_L__,%A0"
-  [(set_attr "length" "2")])
-
-(define_insn "*mov_sp_r_tiny"
-  [(set (reg:HI 32)
-        (match_operand:HI 0 "register_operand" "r"))]
-  "TARGET_TINY_STACK"
-  "out __SP_L__,%A0"
-  [(set_attr "length" "1")])
-
 ;;========================================================================
 ;; move byte
+;; The last alternative (any immediate constant to any register) is
+;; very expensive.  It should be optimized by peephole2 if a scratch
+;; register is available, but then that register could just as well be
+;; allocated for the variable we are loading.  But, most of NO_LD_REGS
+;; are call-saved registers, and most of LD_REGS are call-used registers,
+;; so this may still be a win for registers live across function calls.
+
 (define_expand "movqi"
   [(set (match_operand:QI 0 "nonimmediate_operand" "")
        (match_operand:QI 1 "general_operand" ""))]
   ""
-  "
-{
-  /* One of the ops has to be in a register */
-  if (!register_operand(operand0, QImode)
-      && ! (register_operand(operand1, QImode) || const0_rtx == operand1))
-    {
-      operands[1] = copy_to_mode_reg(QImode, operand1);
-    }
- }"); 
+  "/* One of the ops has to be in a register */
+   if (!register_operand(operand0, QImode)
+       && ! (register_operand(operand1, QImode) || const0_rtx == operand1))
+       operands[1] = copy_to_mode_reg(QImode, operand1);
+  ")
 
 (define_insn "*movqi"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,d,Qm,r,q")
-       (match_operand:QI 1 "general_operand"      "r,L,i,rL,Qm,r"))]
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,d,Qm,r,q,r,*r")
+       (match_operand:QI 1 "general_operand"       "r,i,rL,Qm,r,q,i"))]
   "(register_operand (operands[0],QImode)
     || register_operand (operands[1], QImode) || const0_rtx == operands[1])"
-  "*{
-    switch (which_alternative)
-      {
-      case 0:
-       return AS2 (mov, %0,%1);
-      case 1:
-       return AS1 (clr, %0);
-      case 2:
-       return AS2 (ldi, %0,lo8(%1));
-      case 3:
-        {
-          rtx save1=NULL;
-          if (operands[1] == const0_rtx)
-            {
-              save1 = operands[1];
-              operands[1] = zero_reg_rtx;
-            }
-          output_asm_insn (out_movqi_mr_r (insn,operands,NULL), operands);
-          if (save1)
-            operands[1] = save1;
-        }
-        return \"\";
-      case 4:
-        return out_movqi_r_mr (insn,operands,NULL);
-      case 5:
-        return (AS2 (out,%0,%1));
-      }
-}"
-  [(set_attr "length" "1,1,1,5,5,1")
-   (set_attr "cc" "none,clobber,none,clobber,clobber,none")])
+  "* return output_movqi (insn, operands, NULL);"
+  [(set_attr "length" "1,1,5,5,1,1,4")
+   (set_attr "cc" "none,none,clobber,clobber,none,none,clobber")])
+
+;; This is used in peephole2 to optimize loading immediate constants
+;; if a scratch register from LD_REGS happens to be available.
+
+(define_insn "*reload_inqi"
+  [(set (match_operand:QI 0 "register_operand" "=l")
+       (match_operand:QI 1 "immediate_operand" "i"))
+   (clobber (match_operand:QI 2 "register_operand" "=&d"))]
+  ""
+  "ldi %2,lo8(%1)
+       mov %0,%2"
+  [(set_attr "length" "2")
+   (set_attr "cc" "none")])
 
 ;;============================================================================
 ;; move word (16 bit)
     }
 }")
 
+
+(define_peephole2
+  [(match_scratch:QI 2 "d")
+   (set (match_operand:HI 0 "register_operand" "")
+       (match_operand:HI 1 "immediate_operand" ""))]
+  "(operands[1] != const0_rtx
+    && test_hard_reg_class (NO_LD_REGS, operands[0]))"
+  [(parallel [(set (match_dup 0) (match_dup 1))
+             (clobber (match_dup 2))])]
+  "")
+
+;; '*' because it is not used in rtl generation, only in above peephole
+(define_insn "*reload_inhi"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+        (match_operand:HI 1 "immediate_operand" "i"))
+   (clobber (match_operand:QI 2 "register_operand" "=&d"))]
+  ""
+  "* return output_reload_inhi (insn, operands, NULL);"
+  [(set_attr "length" "4")
+   (set_attr "cc" "none")])
+
 (define_insn "*movhi"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,d,r,m")
-        (match_operand:HI 1 "general_operand"       "r,L,i,m,rL"))]
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,d,*r,q,r")
+        (match_operand:HI 1 "general_operand"       "r,m,rL,i,i,r,q"))]
   "(register_operand (operands[0],HImode)
     || register_operand (operands[1],HImode) || const0_rtx == operands[1])"
-  "*{
-  rtx link;
-  switch (which_alternative)
-    {
-    case 0: /* mov r,r */
-      if (TARGET_ENHANCED)
-       return (AS2 (movw,%0,%1));  /* FIXME: length = 2 -> 1 */
-
-      if (true_regnum (operands[0]) > true_regnum (operands[1]))
-        return (AS2 (mov,%B0,%B1) CR_TAB
-               AS2 (mov,%A0,%A1));
-      else
-        return (AS2 (mov,%A0,%A1) CR_TAB
-               AS2 (mov,%B0,%B1));
-    case 1:  /* mov r,L */
-      return (AS1 (clr,%A0) CR_TAB
-             AS1 (clr,%B0));
-    case 2: /* ld d,i */
-      if (operands[1] == const1_rtx
-          && (link = find_reg_note (insn, REG_WAS_0, 0))
-         /* Make sure the insn that stored the 0 is still present.  */
-         && ! INSN_DELETED_P (XEXP (link, 0))
-         && GET_CODE (XEXP (link, 0)) != NOTE
-         /* Make sure cross jumping didn't happen here.  */
-         && no_labels_between_p (XEXP (link, 0), insn)
-         /* Make sure the reg hasn't been clobbered.  */
-         && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
-      /* Fastest way to change a 0 to a 1.  */
-        return AS1 (inc,%A0 ; reg_was_0);
-      return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
-             AS2 (ldi,%B0,hi8(%1)));
-    case 3: /* mov r,m*/
-      return out_movhi_r_mr (insn, operands, NULL);
-    case 4: /* mov m,r*/
-        {
-          rtx save1 = NULL;
-          if (operands[1] == const0_rtx)
-            {
-              save1 = operands[1];
-              operands[1] = zero_reg_rtx;
-            }
-          output_asm_insn (out_movhi_mr_r (insn,operands,NULL), operands);
-          if (save1)
-            operands[1] = save1;
-        }
-        return \"\";
-    }
-}"
-  [(set_attr "length" "2,2,2,4,4")
-   (set_attr "cc" "none,set_zn,none,clobber,clobber")])
+  "* return output_movhi (insn, operands, NULL);"
+  [(set_attr "length" "2,4,4,2,6,5,2")
+   (set_attr "cc" "none,clobber,clobber,none,clobber,none,none")])
 
 ;;==========================================================================
 ;; move double word (32 bit)
     }
 }")
 
+
+
+(define_peephole2
+  [(match_scratch:QI 2 "d")
+   (set (match_operand:SI 0 "register_operand" "")
+       (match_operand:SI 1 "immediate_operand" ""))]
+  "(operands[1] != const0_rtx
+    && test_hard_reg_class (NO_LD_REGS, operands[0]))"
+  [(parallel [(set (match_dup 0) (match_dup 1))
+             (clobber (match_dup 2))])]
+  "")
+
+;; '*' because it is not used in rtl generation.
+(define_insn "*reload_insi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (match_operand:SI 1 "immediate_operand" "i"))
+   (clobber (match_operand:QI 2 "register_operand" "=&d"))]
+  ""
+  "* return output_reload_insisf (insn, operands, NULL);"
+  [(set_attr "length" "8")
+   (set_attr "cc" "none")])
+
+
 (define_insn "*movsi"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,d,r,Qm")
-        (match_operand:SI 1 "general_operand"      "r,L,i,Qm,rL"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,Qm,!d,r")
+        (match_operand:SI 1 "general_operand"       "r,L,Qm,rL,i,i"))]
   "(register_operand (operands[0],SImode)
     || register_operand (operands[1],SImode) || const0_rtx == operands[1])"
   "* return output_movsisf (insn, operands, which_alternative);"
-  [(set_attr "length" "4,4,4,8,8")
-   (set_attr "cc" "none,set_zn,none,clobber,clobber")])
+  [(set_attr "length" "4,4,8,8,4,10")
+   (set_attr "cc" "none,set_zn,clobber,clobber,clobber,clobber")])
 
 ;; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
 ;; move floating point numbers (32 bit)
 }")
 
 (define_insn "*movsf"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,d,r,Qm")
-        (match_operand:SF 1 "general_operand"      "r,G,F,Qm,r"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,Qm,!d,r")
+        (match_operand:SF 1 "general_operand"       "r,G,Qm,r,F,F"))]
   "register_operand (operands[0], SFmode)
    || register_operand (operands[1], SFmode)"
   "* return output_movsisf (insn, operands, which_alternative);"
-  [(set_attr "length" "4,4,4,8,8")
-   (set_attr "cc" "none,set_zn,none,clobber,clobber")])
+  [(set_attr "length" "4,4,8,8,4,10")
+   (set_attr "cc" "none,set_zn,clobber,clobber,clobber,clobber")])
 
 ;;=========================================================================
 ;; move string (like memcpy)
   [(set (match_operand:QI 0 "register_operand" "=r")
        (mult:QI (match_operand:QI 1 "register_operand" "r")
                 (match_operand:QI 2 "register_operand" "r")))]
-  "TARGET_ENHANCED"
+  "AVR_ENHANCED"
   "mul %1,%2
        mov %0,r0
        clr r1"
   [(set (match_operand:HI 0 "register_operand" "=r")
        (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
                 (sign_extend:HI (match_operand:QI 2 "register_operand" "d"))))]
-  "TARGET_ENHANCED"
+  "AVR_ENHANCED"
   "muls %1,%2
        movw %0,r0
        clr r1"
   [(set (match_operand:HI 0 "register_operand" "=r")
        (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
                 (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
-  "TARGET_ENHANCED"
+  "AVR_ENHANCED"
   "mul %1,%2
        movw %0,r0
        clr r1"
   [(set (match_operand:HI 0 "register_operand" "=&r")
        (mult:HI (match_operand:HI 1 "register_operand" "r")
                 (match_operand:HI 2 "register_operand" "r")))]
-  "TARGET_ENHANCED"
+  "AVR_ENHANCED"
   "mul %A1,%A2
        movw %0,r0
        mul %A1,%B2
   [(set_attr "length" "3,4")
    (set_attr "cc" "set_czn,set_n")])
 
-(define_insn "negsi2"
-  [(set (match_operand:SI 0 "register_operand" "=!d,r")
-       (neg:SI (match_operand:SI 1 "register_operand" "0,0")))]
+(define_insn "*negsi2"
+  [(set (match_operand:SI 0 "register_operand"       "=!d,r,&r")
+       (neg:SI (match_operand:SI 1 "register_operand" "0,0,r")))]
   ""
   "@
        com %D0\;com %C0\;com %B0\;neg %A0\;sbci %B0,lo8(-1)\;sbci %C0,lo8(-1)\;sbci %D0,lo8(-1)
-       com %D0\;com %C0\;com %B0\;neg %A0\;brcs _PC_+8\;sec\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
-  [(set_attr "length" "7,9")
-   (set_attr "cc" "set_czn,clobber")])
+       com %D0\;com %C0\;com %B0\;com %A0\;adc %A0,%@\;adc %B0,%@\;adc %C0,%@\;adc %D0,%@
+       clr %A0\;clr %B0\;clr %C0\;clr %D0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1"
+  [(set_attr "length" "7,8,8")
+   (set_attr "cc" "set_czn,set_n,set_czn")])
+
+(define_insn "negsf2"
+  [(set (match_operand:SF 0 "register_operand" "=d,r")
+       (neg:SF (match_operand:SF 1 "register_operand" "0,0")))]
+  ""
+  "@
+       subi %D0,0x80
+       bst %D0,7\;com %D0\;bld %D0,7\;com %D0"
+  [(set_attr "length" "1,4")
+   (set_attr "cc" "set_n,set_n")])
 
 ;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 ;; not
      return \"icall\";
   else if (which_alternative==1)
     {
-      if (TARGET_ENHANCED)
+      if (AVR_ENHANCED)
        return (AS2 (movw, r30, %0) CR_TAB
                \"icall\");
       else
      return \"icall\";
   else if (which_alternative==1)
     {
-      if (TARGET_ENHANCED)
+      if (AVR_ENHANCED)
        return (AS2 (movw, r30, %1) CR_TAB
                \"icall\");
       else
               (plus:HI (match_operand:HI 0 "register_operand" "=&z")
                        (label_ref (match_operand 2 "" "")))))
     (use (label_ref (match_operand 1 "" "")))]
-  "TARGET_ENHANCED"
+  "AVR_ENHANCED"
   "subi r30,lo8(-(%2))
        sbci r31,hi8(-(%2))
        lpm __tmp_reg__,Z+
                      (pc)))]
   "jump_over_one_insn_p (insn, operands[1])"
   "sbrc %D0,7")
+
+(define_peephole
+  [(set (cc0) (match_operand:QI 0 "register_operand" ""))
+   (set (pc)
+       (if_then_else (eq (cc0) (const_int 0))
+                     (label_ref (match_operand 1 "" ""))
+                     (pc)))]
+  "jump_over_one_insn_p (insn, operands[1])"
+  "cpse %0,__zero_reg__")
+
+(define_peephole
+  [(set (cc0)
+        (compare (match_operand:QI 0 "register_operand" "")
+                (match_operand:QI 1 "register_operand" "")))
+   (set (pc)
+       (if_then_else (eq (cc0) (const_int 0))
+                     (label_ref (match_operand 2 "" ""))
+                     (pc)))]
+  "jump_over_one_insn_p (insn, operands[2])"
+  "cpse %0,%1")
index e5ecbff..dfc76d1 100644 (file)
@@ -621,18 +621,48 @@ __epilogue_restores__:
        out     __SP_H__,r29
        out     __SREG__,__tmp_reg__
        out     __SP_L__,r28
+#if defined (__AVR_ENHANCED__)
+       movw    r28, r26
+#else
        mov     r28,r26
        mov     r29,r27
+#endif
        ret
-#endif /* defined (Lepilogue) */
+.endfunc
+#endif /* defined (L_epilogue) */
 
-#ifdef L__exit
+#ifdef L_exit
        .weak   _exit
        .func   _exit
 _exit:
        rjmp    _exit
+.endfunc
+#endif /* defined (L_exit) */
+
+#ifdef L_cleanup
        .weak   _cleanup
+       .func   _cleanup
 _cleanup:
        ret
 .endfunc
+#endif /* defined (L_cleanup) */
+
+#ifdef L_tablejump
+       .global __tablejump__
+       .func   __tablejump__
+__tablejump__:
+#if defined (__AVR_ENHANCED__)
+       lpm     __tmp_reg__, Z+
+       lpm     r31, Z
+       mov     r30, __tmp_reg__
+       ijmp
+#else
+       lpm
+       push    r0
+       adiw    r30, 1
+       lpm
+       push    r0
+       ret
+.endfunc
 #endif
+#endif /* defined (L_tablejump) */
index 9f549f4..7e4d033 100644 (file)
@@ -5,31 +5,34 @@ RANLIB_FOR_TARGET = avr-ranlib
 CROSS_LIBGCC1 = libgcc1-asm.a
 LIB1ASMSRC = avr/libgcc.S
 LIB1ASMFUNCS = \
-       mulqi3 \
-       mulhi3 \
-       mulsi3 \
-       umodqi3 \
-       udivqi3 \
-       modqi3 \
-       divqi3 \
-       umodhi3 \
-       udivhi3 \
-       modhi3 \
-       divhi3 \
-       umodsi3 \
-       udivsi3 \
-       modsi3 \
-       divsi3 \
-       prologue \
-       epilogue \
-       __exit
+       _mulqi3 \
+       _mulhi3 \
+       _mulsi3 \
+       _umodqi3 \
+       _udivqi3 \
+       _modqi3 \
+       _divqi3 \
+       _umodhi3 \
+       _udivhi3 \
+       _modhi3 \
+       _divhi3 \
+       _umodsi3 \
+       _udivsi3 \
+       _modsi3 \
+       _divsi3 \
+       _prologue \
+       _epilogue \
+       _exit \
+       _cleanup \
+       _tablejump
 
 # libgcc...
 LIBGCC1_TEST =
 
-# We do not have DF type
-TARGET_LIBGCC2_CFLAGS = -DDF=SF -Dinhibit_libc
-#LIBGCC2 = $(LIBGCC1)
+# We do not have the DF type.
+# Most of the C functions in libgcc2 use almost all registers,
+# so use -mcall-prologues for smaller code size.
+TARGET_LIBGCC2_CFLAGS = -DDF=SF -Dinhibit_libc -mcall-prologues
 
 fp-bit.c: $(srcdir)/config/fp-bit.c $(srcdir)/config/avr/t-avr
        echo '#define FLOAT' > fp-bit.c
@@ -44,5 +47,17 @@ fp-bit.c: $(srcdir)/config/fp-bit.c $(srcdir)/config/avr/t-avr
 
 FPBIT = fp-bit.c
 
+MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr3/mmcu=avr4/mmcu=avr5
+MULTILIB_DIRNAMES = avr2 avr3 avr4 avr5
 
+# The many avr2 matches are not listed here - this is the default.
+MULTILIB_MATCHES = \
+       mmcu?avr3=mmcu?atmega103 mmcu?avr3=mmcu?atmega603 \
+       mmcu?avr4=mmcu?atmega83  mmcu?avr4=mmcu?atmega85  \
+       mmcu?avr5=mmcu?atmega161 mmcu?avr5=mmcu?atmega163 \
+       mmcu?avr5=mmcu?atmega32  mmcu?avr5=mmcu?at94k
 
+MULTILIB_EXCEPTIONS =
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib