diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 36867fc84ed..c97c1a394a6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,39 @@ +2008-03-15 Bjoern Haase + Anatoly Sokolov + + * gcc/gcc/config/avr/avr.c (avr_arch_types): Add avr6 entry. + (avr_arch): Add ARCH_AVR6. + (avr_mcu_types): Add 'atmega2560' and 'atmega2561' entry. + (initial_elimination_offset): Initialize and use 'avr_pc_size' + instead of fixed value 2. + (print_operand_address): Use gs() asm specifier instead of pm(). + (avr_assemble_integer): (Ditto.). + (avr_output_addr_vec_elt): (Ditto.). + (print_operand): Handle "!" code. + * gcc/gcc/config/avr/avr.h (TARGET_CPU_CPP_BUILTINS): Add + __AVR_3_BYTE_PC__, __AVR_2_BYTE_PC__ and __AVR_HAVE_JMP_CALL__. + (AVR_HAVE_EIJMP_EICALL): Define. + (AVR_3_BYTE_PC): Redefine. + (AVR_2_BYTE_PC): (Ditto.). + (PRINT_OPERAND_PUNCT_VALID_P): Add '!' code. + (LINK_SPEC): Add atmega2560 and atmega2561. + (CRT_BINUTILS_SPEC): Add atmega2560 (crtm2560.o) and atmega2561 + (crtm2561.o). + * gcc/gcc/config/avr/avr.md (call_insn): Use eicall instead of icall + for 3 byte PC devices. + (call_value_insn): (Ditto.). + (*tablejump_enh): Use eijmp instead of ijmp for 3 byte PC devices. + (indirect_jump): Use only for for 2 byte PC devices. + (*tablejump): (Ditto.). + (*indirect_jump_avr6): Add insn. + (*tablejump_rjmp): Don't use for 3 byte PC devices. + * gcc/gcc/config/avr/libgcc.S (__prologue_saves__): Use eijmp + instead of ijmp for 3 byte PC devices. + (__tablejump2__): (Ditto.). + * gcc/gcc/config/avr/t-avr (MULITLIB_OPTIONS): Add avr6 architecture. + (MULITLIB_DIRNAMES): (Ditto.). + (MULTILIB_MATCHES): Add atmega2560 and atmega2561 to list. + 2008-03-15 Uros Bizjak * config/i386/mmx.md ("sse2_umulv1siv2di3"): Rename from diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 68c0f18130a..8d9b00dde24 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -127,7 +127,8 @@ static const struct base_arch_s avr_arch_types[] = { { 0, 0, 1, 1, 0, 0, 0, 0, "__AVR_ARCH__=35" }, { 0, 1, 0, 1, 0, 0, 0, 0, "__AVR_ARCH__=4" }, { 0, 1, 1, 1, 0, 0, 0, 0, "__AVR_ARCH__=5" }, - { 0, 1, 1, 1, 1, 1, 0, 0, "__AVR_ARCH__=51" } + { 0, 1, 1, 1, 1, 1, 0, 0, "__AVR_ARCH__=51" }, + { 0, 1, 1, 1, 1, 1, 1, 0, "__AVR_ARCH__=6" } }; /* These names are used as the index into the avr_arch_types[] table @@ -144,7 +145,8 @@ enum avr_arch ARCH_AVR35, ARCH_AVR4, ARCH_AVR5, - ARCH_AVR51 + ARCH_AVR51, + ARCH_AVR6 }; struct mcu_type_s { @@ -273,6 +275,10 @@ static const struct mcu_type_s avr_mcu_types[] = { { "at90can128", ARCH_AVR51, "__AVR_AT90CAN128__" }, { "at90usb1286", ARCH_AVR51, "__AVR_AT90USB1286__" }, { "at90usb1287", ARCH_AVR51, "__AVR_AT90USB1287__" }, + /* 3-Byte PC. */ + { "avr6", ARCH_AVR6, NULL }, + { "atmega2560", ARCH_AVR6, "__AVR_ATmega2560__" }, + { "atmega2561", ARCH_AVR6, "__AVR_ATmega2561__" }, /* Assembler only. */ { "avr1", ARCH_AVR1, NULL }, { "at90s1200", ARCH_AVR1, "__AVR_AT90S1200__" }, @@ -511,9 +517,10 @@ initial_elimination_offset (int from, int to) else { int offset = frame_pointer_needed ? 2 : 0; + int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2; offset += avr_regs_to_save (NULL); - return get_frame_size () + 2 + 1 + offset; + return get_frame_size () + (avr_pc_size) + 1 + offset; } } @@ -1119,7 +1126,7 @@ print_operand_address (FILE *file, rtx addr) && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr)) || GET_CODE (addr) == LABEL_REF)) { - fprintf (file, "pm("); + fprintf (file, "gs("); output_addr_const (file,addr); fprintf (file ,")"); } @@ -1144,6 +1151,11 @@ print_operand (FILE *file, rtx x, int code) if (!AVR_MEGA) fputc ('r', file); } + else if (code == '!') + { + if (AVR_HAVE_EIJMP_EICALL) + fputc ('e', file); + } else if (REG_P (x)) { if (x == zero_reg_rtx) @@ -4468,7 +4480,7 @@ avr_assemble_integer (rtx x, unsigned int size, int aligned_p) && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x)) || GET_CODE (x) == LABEL_REF)) { - fputs ("\t.word\tpm(", asm_out_file); + fputs ("\t.word\tgs(", asm_out_file); output_addr_const (asm_out_file, x); fputs (")\n", asm_out_file); return true; @@ -5814,8 +5826,8 @@ void avr_output_addr_vec_elt (FILE *stream, int value) { switch_to_section (progmem_section); - if (AVR_MEGA) - fprintf (stream, "\t.word pm(.L%d)\n", value); + if (AVR_HAVE_JMP_CALL) + fprintf (stream, "\t.word gs(.L%d)\n", value); else fprintf (stream, "\trjmp .L%d\n", value); } diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index d28cc1f479b..72d08812e2c 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -80,6 +80,15 @@ extern const struct base_arch_s *avr_current_arch; builtin_define ("__AVR_MEGA__"); \ if (avr_current_arch->have_jmp_call) \ builtin_define ("__AVR_HAVE_JMP_CALL__"); \ + if (avr_current_arch->have_eijmp_eicall) \ + { \ + builtin_define ("__AVR_HAVE_JMP_CALL__"); \ + builtin_define ("__AVR_3_BYTE_PC__"); \ + } \ + else \ + { \ + builtin_define ("__AVR_2_BYTE_PC__"); \ + } \ if (TARGET_NO_INTERRUPTS) \ builtin_define ("__NO_INTERRUPTS__"); \ } \ @@ -96,13 +105,15 @@ extern GTY(()) section *progmem_section; #endif #define AVR_MEGA (avr_mega_p && !TARGET_SHORT_CALLS) +#define AVR_HAVE_JMP_CALL (avr_current_arch->have_jmp_call && !TARGET_SHORT_CALLS) #define AVR_HAVE_MUL (avr_have_mul_p) #define AVR_HAVE_MOVW (avr_have_movw_lpmx_p) #define AVR_HAVE_LPMX (avr_have_movw_lpmx_p) #define AVR_HAVE_RAMPZ (avr_current_arch->have_elpm) +#define AVR_HAVE_EIJMP_EICALL (avr_current_arch->have_eijmp_eicall) -#define AVR_2_BYTE_PC 1 -#define AVR_3_BYTE_PC 0 +#define AVR_2_BYTE_PC (!AVR_HAVE_EIJMP_EICALL) +#define AVR_3_BYTE_PC (AVR_HAVE_EIJMP_EICALL) #define TARGET_VERSION fprintf (stderr, " (GNU assembler syntax)"); @@ -671,7 +682,7 @@ sprintf (STRING, "*.%s%lu", PREFIX, (unsigned long)(NUM)) #define PRINT_OPERAND(STREAM, X, CODE) print_operand (STREAM, X, CODE) -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '~') +#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '~' || (CODE) == '!') #define PRINT_OPERAND_ADDRESS(STREAM, X) print_operand_address(STREAM, X) @@ -828,6 +839,7 @@ mmcu=*:-mmcu=%*}" mmcu=at90usb64*|\ mmcu=at90usb128*|\ mmcu=at94k: -m avr5}\ +%{mmcu=atmega256*:-m avr6}\ %{mmcu=atmega324*|\ mmcu=atmega325*|\ mmcu=atmega328p|\ @@ -856,7 +868,8 @@ mmcu=*:-mmcu=%*}" mmcu=at90usb*: -Tdata 0x800100}\ %{mmcu=atmega640|\ mmcu=atmega1280|\ - mmcu=atmega1281: -Tdata 0x800200} " + mmcu=atmega1281|\ + mmcu=atmega256*: -Tdata 0x800200} " #define LIB_SPEC \ "%{!mmcu=at90s1*:%{!mmcu=attiny11:%{!mmcu=attiny12:%{!mmcu=attiny15:%{!mmcu=attiny28: -lc }}}}}" @@ -968,6 +981,8 @@ mmcu=*:-mmcu=%*}" %{mmcu=atmega1280:crtm1280.o%s} \ %{mmcu=atmega1281:crtm1281.o%s} \ %{mmcu=atmega1284p:crtm1284p.o%s} \ +%{mmcu=atmega2560:crtm2560.o%s} \ +%{mmcu=atmega2561:crtm2561.o%s} \ %{mmcu=at90can128:crtcan128.o%s} \ %{mmcu=at90usb1286:crtusb1286.o%s} \ %{mmcu=at90usb1287:crtusb1287.o%s}" diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 68a6aa152e8..b8a8f0ec0eb 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -32,6 +32,7 @@ ;; p POST_INC or PRE_DEC address as a pointer (X, Y, Z) ;; r POST_INC or PRE_DEC address as a register (r26, r28, r30) ;; ~ Output 'r' if not AVR_MEGA. +;; ! Output 'e' if AVR_HAVE_EIJMP_EICALL. ;; UNSPEC usage: ;; 0 Length of a string, see "strlenhi". @@ -2301,22 +2302,22 @@ "(register_operand (operands[0], HImode) || CONSTANT_P (operands[0]))" "*{ if (which_alternative==0) - return \"icall\"; + return \"%!icall\"; else if (which_alternative==1) { if (AVR_HAVE_MOVW) return (AS2 (movw, r30, %0) CR_TAB - \"icall\"); + \"%!icall\"); else return (AS2 (mov, r30, %A0) CR_TAB AS2 (mov, r31, %B0) CR_TAB - \"icall\"); + \"%!icall\"); } else if (which_alternative==2) return AS1(%~call,%c0); return (AS2 (ldi,r30,lo8(%0)) CR_TAB AS2 (ldi,r31,hi8(%0)) CR_TAB - \"icall\"); + \"%!icall\"); }" [(set_attr "cc" "clobber,clobber,clobber,clobber") (set_attr_alternative "length" @@ -2338,22 +2339,22 @@ "(register_operand (operands[0], VOIDmode) || CONSTANT_P (operands[0]))" "*{ if (which_alternative==0) - return \"icall\"; + return \"%!icall\"; else if (which_alternative==1) { if (AVR_HAVE_MOVW) return (AS2 (movw, r30, %1) CR_TAB - \"icall\"); + \"%!icall\"); else return (AS2 (mov, r30, %A1) CR_TAB AS2 (mov, r31, %B1) CR_TAB - \"icall\"); + \"%!icall\"); } else if (which_alternative==2) return AS1(%~call,%c1); return (AS2 (ldi, r30, lo8(%1)) CR_TAB AS2 (ldi, r31, hi8(%1)) CR_TAB - \"icall\"); + \"%!icall\"); }" [(set_attr "cc" "clobber,clobber,clobber,clobber") (set_attr_alternative "length" @@ -2376,13 +2377,20 @@ ; indirect jump (define_insn "indirect_jump" [(set (pc) (match_operand:HI 0 "register_operand" "!z,*r"))] - "" + "!AVR_HAVE_EIJMP_EICALL" "@ ijmp push %A0\;push %B0\;ret" [(set_attr "length" "1,3") (set_attr "cc" "none,none")]) +(define_insn "*indirect_jump_avr6" + [(set (pc) (match_operand:HI 0 "register_operand" "z"))] + "AVR_HAVE_EIJMP_EICALL" + "eijmp" + [(set_attr "length" "1") + (set_attr "cc" "none")]) + ;; table jump ;; Table made from "rjmp" instructions for <=8K devices. @@ -2391,7 +2399,7 @@ UNSPEC_INDEX_JMP)) (use (label_ref (match_operand 1 "" ""))) (clobber (match_dup 0))] - "!AVR_MEGA" + "(!AVR_HAVE_JMP_CALL) && (!AVR_HAVE_EIJMP_EICALL)" "@ ijmp push %A0\;push %B0\;ret" @@ -2420,7 +2428,7 @@ lpm __tmp_reg__,Z+ lpm r31,Z mov r30,__tmp_reg__ - ijmp" + %!ijmp" [(set_attr "length" "6") (set_attr "cc" "clobber")]) @@ -2429,7 +2437,7 @@ UNSPEC_INDEX_JMP)) (use (label_ref (match_operand 1 "" ""))) (clobber (match_dup 0))] - "AVR_MEGA" + "AVR_HAVE_JMP_CALL && !AVR_HAVE_EIJMP_EICALL" "lsl r30 rol r31 lpm diff --git a/gcc/config/avr/libgcc.S b/gcc/config/avr/libgcc.S index 8fdba55f775..7879b18ea57 100644 --- a/gcc/config/avr/libgcc.S +++ b/gcc/config/avr/libgcc.S @@ -595,7 +595,12 @@ __prologue_saves__: out __SP_H__,r29 out __SREG__,__tmp_reg__ out __SP_L__,r28 +#if defined (__AVR_HAVE_EIJMP_EICALL__) + eijmp +#else ijmp +#endif + .endfunc #endif /* defined (L_prologue) */ @@ -675,13 +680,22 @@ __tablejump__: lpm __tmp_reg__, Z+ lpm r31, Z mov r30, __tmp_reg__ + +#if defined (__AVR_HAVE_EIJMP_EICALL__) + eijmp +#else ijmp +#endif + #else lpm adiw r30, 1 push r0 lpm push r0 +#if defined (__AVR_HAVE_EIJMP_EICALL__) + push __zero_reg__ +#endif ret #endif .endfunc diff --git a/gcc/config/avr/t-avr b/gcc/config/avr/t-avr index 0cafe4f6c98..5804400540a 100644 --- a/gcc/config/avr/t-avr +++ b/gcc/config/avr/t-avr @@ -37,8 +37,8 @@ fp-bit.c: $(srcdir)/config/fp-bit.c $(srcdir)/config/avr/t-avr FPBIT = fp-bit.c -MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51 -MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 +MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6 +MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 # The many avr2 matches are not listed here - this is the default. MULTILIB_MATCHES = \ @@ -123,7 +123,9 @@ MULTILIB_MATCHES = \ mmcu?avr51=mmcu?atmega1284p \ mmcu?avr51=mmcu?at90can128 \ mmcu?avr51=mmcu?at90usb1286 \ - mmcu?avr51=mmcu?at90usb1287 + mmcu?avr51=mmcu?at90usb1287 \ + mmcu?avr6=mmcu?atmega2560 \ + mmcu?avr6=mmcu?atmega2561 MULTILIB_EXCEPTIONS =