/* Definitions of target machine for GNU compiler,
for ATMEL AVR at90s8515, ATmega103/103L, ATmega603/603L microcontrollers.
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
- Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+ 2008, 2009 Free Software Foundation, Inc.
Contributed by Denis Chertykov (denisc@overta.ru)
This file is part of GCC.
/* Names to predefine in the preprocessor for this target machine. */
+struct base_arch_s {
+ /* Assembler only. */
+ int asm_only;
+
+ /* Core have 'MUL*' instructions. */
+ int have_mul;
+
+ /* Core have 'CALL' and 'JMP' instructions. */
+ int have_jmp_call;
+
+ /* Core have 'MOVW' and 'LPM Rx,Z' instructions. */
+ int have_movw_lpmx;
+
+ /* Core have 'ELPM' instructions. */
+ int have_elpm;
+
+ /* Core have 'ELPM Rx,Z' instructions. */
+ int have_elpmx;
+
+ /* Core have 'EICALL' and 'EIJMP' instructions. */
+ int have_eijmp_eicall;
+
+ /* Reserved. */
+ int reserved;
+
+ const char *const macro;
+};
+
+extern const struct base_arch_s *avr_current_arch;
+
#define TARGET_CPU_CPP_BUILTINS() \
do \
{ \
builtin_define_std ("AVR"); \
- if (avr_base_arch_macro) \
- builtin_define (avr_base_arch_macro); \
+ if (avr_current_arch->macro) \
+ builtin_define (avr_current_arch->macro); \
if (avr_extra_arch_macro) \
builtin_define (avr_extra_arch_macro); \
- if (avr_have_movw_lpmx_p) \
- builtin_define ("__AVR_HAVE_MOVW__"); \
- if (avr_have_movw_lpmx_p) \
- builtin_define ("__AVR_HAVE_LPMX__"); \
- if (avr_asm_only_p) \
+ if (avr_current_arch->have_elpm) \
+ builtin_define ("__AVR_HAVE_RAMPZ__"); \
+ if (avr_current_arch->have_elpm) \
+ builtin_define ("__AVR_HAVE_ELPM__"); \
+ if (avr_current_arch->have_elpmx) \
+ builtin_define ("__AVR_HAVE_ELPMX__"); \
+ if (avr_current_arch->have_movw_lpmx) \
+ { \
+ builtin_define ("__AVR_HAVE_MOVW__"); \
+ builtin_define ("__AVR_HAVE_LPMX__"); \
+ } \
+ if (avr_current_arch->asm_only) \
builtin_define ("__AVR_ASM_ONLY__"); \
- if (avr_have_mul_p) \
- builtin_define ("__AVR_ENHANCED__"); \
- if (avr_have_mul_p) \
- builtin_define ("__AVR_HAVE_MUL__"); \
- if (avr_mega_p) \
- builtin_define ("__AVR_MEGA__"); \
+ if (avr_current_arch->have_mul) \
+ { \
+ builtin_define ("__AVR_ENHANCED__"); \
+ builtin_define ("__AVR_HAVE_MUL__"); \
+ } \
+ if (avr_current_arch->have_jmp_call) \
+ { \
+ builtin_define ("__AVR_MEGA__"); \
+ builtin_define ("__AVR_HAVE_JMP_CALL__"); \
+ } \
+ if (avr_current_arch->have_eijmp_eicall) \
+ { \
+ builtin_define ("__AVR_HAVE_EIJMP_EICALL__"); \
+ builtin_define ("__AVR_3_BYTE_PC__"); \
+ } \
+ else \
+ { \
+ builtin_define ("__AVR_2_BYTE_PC__"); \
+ } \
if (TARGET_NO_INTERRUPTS) \
builtin_define ("__NO_INTERRUPTS__"); \
} \
while (0)
-extern const char *avr_base_arch_macro;
extern const char *avr_extra_arch_macro;
-extern int avr_mega_p;
-extern int avr_have_mul_p;
-extern int avr_asm_only_p;
-extern int avr_have_movw_lpmx_p;
+
#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS)
extern GTY(()) section *progmem_section;
#endif
-#define AVR_MEGA (avr_mega_p && !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_JMP_CALL (avr_current_arch->have_jmp_call && !TARGET_SHORT_CALLS)
+#define AVR_HAVE_MUL (avr_current_arch->have_mul)
+#define AVR_HAVE_MOVW (avr_current_arch->have_movw_lpmx)
+#define AVR_HAVE_LPMX (avr_current_arch->have_movw_lpmx)
+#define AVR_HAVE_RAMPZ (avr_current_arch->have_elpm)
+#define AVR_HAVE_EIJMP_EICALL (avr_current_arch->have_eijmp_eicall)
-#define AVR_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)");
/* No data type wants to be aligned rounder than this. */
#define BIGGEST_ALIGNMENT 8
+#define MAX_OFILE_ALIGNMENT (32768 * 8)
+
#define TARGET_VTABLE_ENTRY_ALIGN 8
#define STRICT_ALIGNMENT 0
#define REGNO_REG_CLASS(R) avr_regno_reg_class(R)
+/* The following macro defines cover classes for Integrated Register
+ Allocator. Cover classes is a set of non-intersected register
+ classes covering all hard registers used for register allocation
+ purpose. Any move between two registers of a cover class should be
+ cheaper than load or store of the registers. The macro value is
+ array of register classes with LIM_REG_CLASSES used as the end
+ marker. */
+
+#define IRA_COVER_CLASSES \
+{ \
+ GENERAL_REGS, LIM_REG_CLASSES \
+}
+
#define BASE_REG_CLASS (reload_completed ? BASE_POINTER_REGS : POINTER_REGS)
#define INDEX_REG_CLASS NO_REGS
#define STATIC_CHAIN_REGNUM 2
-#define FRAME_POINTER_REQUIRED frame_pointer_required_p()
+#define FRAME_POINTER_REQUIRED avr_frame_pointer_required_p()
/* Offset from the frame pointer register value to the top of the stack. */
#define FRAME_POINTER_CFA_OFFSET(FNDECL) 0
{FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \
,{FRAME_POINTER_REGNUM+1,STACK_POINTER_REGNUM+1}}
-#define CAN_ELIMINATE(FROM, TO) (((FROM) == ARG_POINTER_REGNUM \
- && (TO) == FRAME_POINTER_REGNUM) \
- || (((FROM) == FRAME_POINTER_REGNUM \
- || (FROM) == FRAME_POINTER_REGNUM+1) \
- && ! FRAME_POINTER_REQUIRED \
- ))
+#define CAN_ELIMINATE(FROM, TO) avr_can_eliminate (FROM, TO)
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
- OFFSET = initial_elimination_offset (FROM, TO)
+ OFFSET = avr_initial_elimination_offset (FROM, TO)
#define RETURN_ADDR_RTX(count, x) \
gen_rtx_MEM (Pmode, memory_address (Pmode, plus_constant (tem, 1)))
-#define PUSH_ROUNDING(NPUSHED) (NPUSHED)
+/* Don't use Push rounding. expr.c: emit_single_push_insn is broken
+ for POST_DEC targets (PR27386). */
+/*#define PUSH_ROUNDING(NPUSHED) (NPUSHED)*/
#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
#define RET_REGISTER avr_ret_register ()
-#define FUNCTION_VALUE(VALTYPE, FUNC) avr_function_value (VALTYPE, FUNC)
-
#define LIBCALL_VALUE(MODE) avr_libcall_value (MODE)
#define FUNCTION_VALUE_REGNO_P(N) ((int) (N) == RET_REGISTER)
#define MAX_REGS_PER_ADDRESS 1
-#ifdef REG_OK_STRICT
-# define GO_IF_LEGITIMATE_ADDRESS(mode, operand, ADDR) \
-{ \
- if (legitimate_address_p (mode, operand, 1)) \
- goto ADDR; \
-}
-# else
-# define GO_IF_LEGITIMATE_ADDRESS(mode, operand, ADDR) \
-{ \
- if (legitimate_address_p (mode, operand, 0)) \
- goto ADDR; \
-}
-#endif
-
#define REG_OK_FOR_BASE_NOSTRICT_P(X) \
(REGNO (X) >= FIRST_PSEUDO_REGISTER || REG_OK_FOR_BASE_STRICT_P(X))
#define REG_OK_FOR_INDEX_P(X) 0
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
-{ \
- (X) = legitimize_address (X, OLDX, MODE); \
- if (memory_address_p (MODE, X)) \
- goto WIN; \
-}
-
#define XEXP_(X,Y) (X)
+
+/* LEGITIMIZE_RELOAD_ADDRESS will allow register R26/27 to be used, where it
+ is no worse than normal base pointers R28/29 and R30/31. For example:
+ If base offset is greater than 63 bytes or for R++ or --R addressing. */
+
#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN) \
do { \
if (1&&(GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC)) \
} \
if (GET_CODE (X) == PLUS \
&& REG_P (XEXP (X, 0)) \
+ && reg_equiv_constant[REGNO (XEXP (X, 0))] == 0 \
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
&& INTVAL (XEXP (X, 1)) >= 1) \
{ \
OPNUM, TYPE); \
goto WIN; \
} \
- push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \
- BASE_POINTER_REGS, GET_MODE (X), VOIDmode, 0, 0, \
- OPNUM, TYPE); \
- goto WIN; \
} \
else if (! (frame_pointer_needed && XEXP (X,0) == frame_pointer_rtx)) \
{ \
} \
} while(0)
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
-
#define LEGITIMATE_CONSTANT_P(X) 1
#define REGISTER_MOVE_COST(MODE, FROM, TO) ((FROM) == STACK_REG ? 6 \
(MODE)==SImode ? 8 : \
(MODE)==SFmode ? 8 : 16)
-#define BRANCH_COST 0
+#define BRANCH_COST(speed_p, predictable_p) 0
#define SLOW_BYTE_ACCESS 0
#define TARGET_ASM_DESTRUCTOR avr_asm_out_dtor
+#define SUPPORTS_INIT_PRIORITY 0
+
#define JUMP_TABLES_IN_TEXT_SECTION 0
#define ASM_COMMENT_START " ; "
specific tm.h file (depending upon the particulars of your assembler). */
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
-do { \
- ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
- ASM_OUTPUT_LABEL (FILE, NAME); \
-} while (0)
+avr_asm_declare_function_name ((FILE), (NAME), (DECL))
#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
do { \
#define PRINT_OPERAND(STREAM, X, CODE) print_operand (STREAM, X, CODE)
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '~')
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '~' || (CODE) == '!')
#define PRINT_OPERAND_ADDRESS(STREAM, X) print_operand_address(STREAM, X)
#define CASE_VECTOR_MODE HImode
-extern int avr_case_values_threshold;
-
-#define CASE_VALUES_THRESHOLD avr_case_values_threshold
-
#undef WORD_REGISTER_OPERATIONS
#define MOVE_MAX 4
/* A C string constant that tells the GCC driver program options to
pass to `cc1plus'. */
-#define ASM_SPEC "%{mmcu=avr25:-mmcu=avr2;\
+#define ASM_SPEC "%{mmcu=avr25:-mmcu=avr2;mmcu=avr35:-mmcu=avr3;mmcu=avr31:-mmcu=avr3;mmcu=avr51:-mmcu=avr5;\
mmcu=*:-mmcu=%*}"
-#define LINK_SPEC " %{!mmcu*:-m avr2}\
+#define LINK_SPEC "\
+%{mrelax:--relax\
+ %{mpmem-wrap-around:%{mmcu=at90usb8*:--pmem-wrap-around=8k}\
+ %{mmcu=atmega16*:--pmem-wrap-around=16k}\
+ %{mmcu=atmega32*|\
+ mmcu=at90can32*:--pmem-wrap-around=32k}\
+ %{mmcu=atmega64*|\
+ mmcu=at90can64*|\
+ mmcu=at90usb64*:--pmem-wrap-around=64k}}}\
+%{!mmcu*: -m avr2}\
%{mmcu=at90s1200|\
mmcu=attiny11|\
mmcu=attiny12|\
mmcu=attiny15|\
- mmcu=attiny28:-m avr1}\
+ mmcu=attiny28: -m avr1}\
%{mmcu=attiny22|\
mmcu=attiny26|\
mmcu=at90s2*|\
mmcu=at90s8*|\
mmcu=at90c8*|\
mmcu=at86rf401|\
- mmcu=attiny13|\
+ mmcu=ata6289|\
+ mmcu=attiny13*|\
mmcu=attiny2313|\
mmcu=attiny24|\
mmcu=attiny25|\
mmcu=attiny261|\
mmcu=attiny4*|\
- mmcu=attiny8*:-m avr2}\
+ mmcu=attiny8*: -m avr2}\
%{mmcu=atmega103|\
mmcu=at43*|\
- mmcu=at76*:-m avr3}\
+ mmcu=at76*|\
+ mmcu=at90usb82|\
+ mmcu=at90usb162|\
+ mmcu=attiny16*|\
+ mmcu=attiny32*: -m avr3}\
%{mmcu=atmega8*|\
- mmcu=atmega48*|\
+ mmcu=atmega4*|\
mmcu=at90pwm1|\
mmcu=at90pwm2|\
mmcu=at90pwm2b|\
mmcu=at90pwm3|\
- mmcu=at90pwm3b:-m avr4}\
+ mmcu=at90pwm3b|\
+ mmcu=at90pwm81: -m avr4}\
%{mmcu=atmega16*|\
mmcu=atmega32*|\
mmcu=atmega406|\
mmcu=at90can*|\
mmcu=at90pwm216|\
mmcu=at90pwm316|\
- mmcu=at90usb*|\
- mmcu=at94k:-m avr5}\
+ mmcu=at90scr100|\
+ mmcu=at90usb64*|\
+ mmcu=at90usb128*|\
+ mmcu=at94k|\
+ mmcu=m3000*|\
+ mmcu=m3001*: -m avr5}\
+%{mmcu=atmega256*:-m avr6}\
%{mmcu=atmega324*|\
mmcu=atmega325*|\
mmcu=atmega328p|\
mmcu=atmega645*|\
mmcu=atmega649*|\
mmcu=atmega128|\
+ mmcu=atmega1284p|\
mmcu=atmega162|\
mmcu=atmega164*|\
mmcu=atmega165*|\
mmcu=atmega168*|\
mmcu=atmega169*|\
- mmcu=atmega8hva|\
- mmcu=atmega16hva|\
+ mmcu=atmega4hv*|\
+ mmcu=atmega8hv*|\
+ mmcu=atmega16hv*|\
+ mmcu=atmega32hv*|\
mmcu=attiny48|\
+ mmcu=attiny88|\
+ mmcu=attiny87|\
+ mmcu=attiny167|\
+ mmcu=attiny327|\
mmcu=at90can*|\
mmcu=at90pwm*|\
+ mmcu=atmega8c1|\
+ mmcu=atmega16c1|\
+ mmcu=atmega32c1|\
+ mmcu=atmega64c1|\
+ mmcu=atmega8m1|\
+ mmcu=atmega16m1|\
+ mmcu=atmega32m1|\
+ mmcu=atmega64m1|\
+ mmcu=atmega16u4|\
+ mmcu=atmega32u*|\
+ mmcu=at90scr100|\
+ mmcu=ata6289|\
mmcu=at90usb*: -Tdata 0x800100}\
%{mmcu=atmega640|\
mmcu=atmega1280|\
- mmcu=atmega1281: -Tdata 0x800200} "
+ mmcu=atmega1281|\
+ mmcu=atmega256*|\
+ mmcu=atmega128rfa1: -Tdata 0x800200}\
+%{mmcu=m3000*|\
+ mmcu=m3001*: -Tdata 0x801000}"
#define LIB_SPEC \
"%{!mmcu=at90s1*:%{!mmcu=attiny11:%{!mmcu=attiny12:%{!mmcu=attiny15:%{!mmcu=attiny28: -lc }}}}}"
%{mmcu=at90s8535:crts8535.o%s} \
%{mmcu=at86rf401:crt86401.o%s} \
%{mmcu=attiny13:crttn13.o%s} \
+%{mmcu=attiny13a:crttn13a.o%s} \
%{mmcu=attiny2313|mmcu=avr25:crttn2313.o%s} \
%{mmcu=attiny24:crttn24.o%s} \
%{mmcu=attiny44:crttn44.o%s} \
%{mmcu=attiny461:crttn461.o%s} \
%{mmcu=attiny861:crttn861.o%s} \
%{mmcu=attiny43u:crttn43u.o%s} \
+%{mmcu=attiny87:crttn87.o%s} \
%{mmcu=attiny48:crttn48.o%s} \
-%{mmcu=atmega103|mmcu=avr3:crtm103.o%s} \
-%{mmcu=at43usb320:crt43320.o%s} \
-%{mmcu=at43usb355:crt43355.o%s} \
+%{mmcu=attiny88:crttn88.o%s} \
+%{mmcu=ata6289:crta6289.o%s} \
+%{mmcu=at43usb355|mmcu=avr3:crt43355.o%s} \
%{mmcu=at76c711:crt76711.o%s} \
+%{mmcu=atmega103|mmcu=avr31:crtm103.o%s} \
+%{mmcu=at43usb320:crt43320.o%s} \
+%{mmcu=at90usb162|mmcu=avr35:crtusb162.o%s} \
+%{mmcu=at90usb82:crtusb82.o%s} \
+%{mmcu=attiny167:crttn167.o%s} \
+%{mmcu=attiny327:crttn327.o%s} \
%{mmcu=atmega8|mmcu=avr4:crtm8.o%s} \
%{mmcu=atmega48:crtm48.o%s} \
%{mmcu=atmega48p:crtm48p.o%s} \
%{mmcu=atmega88p:crtm88p.o%s} \
%{mmcu=atmega8515:crtm8515.o%s} \
%{mmcu=atmega8535:crtm8535.o%s} \
+%{mmcu=atmega8c1:crtm8c1.o%s} \
+%{mmcu=atmega8m1:crtm8m1.o%s} \
%{mmcu=at90pwm1:crt90pwm1.o%s} \
%{mmcu=at90pwm2:crt90pwm2.o%s} \
%{mmcu=at90pwm2b:crt90pwm2b.o%s} \
%{mmcu=at90pwm3:crt90pwm3.o%s} \
%{mmcu=at90pwm3b:crt90pwm3b.o%s} \
+%{mmcu=at90pwm81:crt90pwm81.o%s} \
%{mmcu=atmega16:crtm16.o%s} \
%{mmcu=atmega161|mmcu=avr5:crtm161.o%s} \
%{mmcu=atmega162:crtm162.o%s} \
%{mmcu=atmega6450:crtm6450.o%s} \
%{mmcu=atmega649:crtm649.o%s} \
%{mmcu=atmega6490:crtm6490.o%s} \
-%{mmcu=atmega128:crtm128.o%s} \
-%{mmcu=atmega1280:crtm1280.o%s} \
-%{mmcu=atmega1281:crtm1281.o%s} \
%{mmcu=atmega8hva:crtm8hva.o%s} \
%{mmcu=atmega16hva:crtm16hva.o%s} \
+%{mmcu=atmega16hvb:crtm16hvb.o%s} \
+%{mmcu=atmega32hvb:crtm32hvb.o%s} \
+%{mmcu=atmega4hvd:crtm4hvd.o%s} \
+%{mmcu=atmega8hvd:crtm8hvd.o%s} \
%{mmcu=at90can32:crtcan32.o%s} \
%{mmcu=at90can64:crtcan64.o%s} \
-%{mmcu=at90can128:crtcan128.o%s} \
%{mmcu=at90pwm216:crt90pwm216.o%s} \
%{mmcu=at90pwm316:crt90pwm316.o%s} \
-%{mmcu=at90usb82:crtusb82.o%s} \
-%{mmcu=at90usb162:crtusb162.o%s} \
+%{mmcu=atmega16c1:crtm16c1.o%s} \
+%{mmcu=atmega32c1:crtm32c1.o%s} \
+%{mmcu=atmega64c1:crtm64c1.o%s} \
+%{mmcu=atmega16m1:crtm16m1.o%s} \
+%{mmcu=atmega32m1:crtm32m1.o%s} \
+%{mmcu=atmega64m1:crtm64m1.o%s} \
+%{mmcu=atmega16u4:crtm16u4.o%s} \
+%{mmcu=atmega32u4:crtm32u4.o%s} \
+%{mmcu=atmega32u6:crtm32u6.o%s} \
+%{mmcu=at90scr100:crt90scr100.o%s} \
%{mmcu=at90usb646:crtusb646.o%s} \
%{mmcu=at90usb647:crtusb647.o%s} \
+%{mmcu=at94k:crtat94k.o%s} \
+%{mmcu=atmega128|mmcu=avr51:crtm128.o%s} \
+%{mmcu=atmega1280:crtm1280.o%s} \
+%{mmcu=atmega1281:crtm1281.o%s} \
+%{mmcu=atmega1284p:crtm1284p.o%s} \
+%{mmcu=at90can128:crtcan128.o%s} \
+%{mmcu=atmega128rfa1:crtm128rfa1.o%s} \
%{mmcu=at90usb1286:crtusb1286.o%s} \
%{mmcu=at90usb1287:crtusb1287.o%s} \
-%{mmcu=at94k:crtat94k.o%s}"
+%{mmcu=m3000f:crtm3000f.o%s} \
+%{mmcu=m3000s:crtm3000s.o%s} \
+%{mmcu=m3001b:crtm3001b.o%s} \
+%{mmcu=atmega2560|mmcu=avr6:crtm2560.o%s} \
+%{mmcu=atmega2561:crtm2561.o%s}"
#define EXTRA_SPECS {"crt_binutils", CRT_BINUTILS_SPECS},
#define OBJECT_FORMAT_ELF
+#define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \
+ avr_hard_regno_rename_ok (OLD_REG, NEW_REG)
+
/* A C structure for machine-specific, per-function data.
This is added to the cfun structure. */
-struct machine_function GTY(())
+struct GTY(()) machine_function
{
+ /* 'true' - if the current function is a leaf function. */
+ int is_leaf;
+
/* 'true' - if current function is a naked function. */
int is_naked;
as specified by the "signal" attribute. */
int is_signal;
- /* 'true' - if current function is a signal function
+ /* 'true' - if current function is a 'task' function
as specified by the "OS_task" attribute. */
int is_OS_task;
+
+ /* 'true' - if current function is a 'main' function
+ as specified by the "OS_main" attribute. */
+ int is_OS_main;
};