/* 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,
- 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 1998-2020 Free Software Foundation, Inc.
Contributed by Denis Chertykov (chertykov@gmail.com)
This file is part of GCC.
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-/* Names to predefine in the preprocessor for this target machine. */
-
-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;
+typedef struct
+{
+ /* Id of the address space as used in c_register_addr_space */
+ unsigned char id;
- /* Core have 'EICALL' and 'EIJMP' instructions. */
- int have_eijmp_eicall;
+ /* Flavour of memory: 0 = RAM, 1 = Flash */
+ int memory_class;
- /* Reserved for xmega architecture. */
- int reserved;
+ /* Width of pointer (in bytes) */
+ int pointer_size;
- /* Reserved for xmega architecture. */
- int reserved2;
-
- /* Default start of data section address for architecture. */
- int default_data_section_start;
+ /* Name of the address space as visible to the user */
+ const char *name;
- const char *const macro;
-
- /* Architecture name. */
- const char *const arch_name;
-};
+ /* Segment (i.e. 64k memory chunk) number. */
+ int segment;
-/* These names are used as the index into the avr_arch_types[] table
- above. */
+ /* Section prefix, e.g. ".progmem1.data" */
+ const char *section_name;
+} avr_addrspace_t;
-enum avr_arch
-{
- ARCH_UNKNOWN,
- ARCH_AVR1,
- ARCH_AVR2,
- ARCH_AVR25,
- ARCH_AVR3,
- ARCH_AVR31,
- ARCH_AVR35,
- ARCH_AVR4,
- ARCH_AVR5,
- ARCH_AVR51,
- ARCH_AVR6
-};
+extern const avr_addrspace_t avr_addrspace[];
-struct mcu_type_s {
- /* Device name. */
- const char *const name;
-
- /* Index in avr_arch_types[]. */
- int arch;
-
- /* Must lie outside user's namespace. NULL == no macro. */
- const char *const macro;
-
- /* Stack pointer have 8 bits width. */
- int short_sp;
-
- /* Start of data section. */
- int data_section_start;
-
- /* Name of device library. */
- const char *const library_name;
-};
+/* Known address spaces */
-/* Preprocessor macros to define depending on MCU type. */
-extern const char *avr_extra_arch_macro;
-extern const struct base_arch_s *avr_current_arch;
-extern const struct mcu_type_s *avr_current_device;
-extern const struct mcu_type_s avr_mcu_types[];
-extern const struct base_arch_s avr_arch_types[];
+enum
+ {
+ ADDR_SPACE_RAM, /* ADDR_SPACE_GENERIC */
+ ADDR_SPACE_FLASH,
+ ADDR_SPACE_FLASH1,
+ ADDR_SPACE_FLASH2,
+ ADDR_SPACE_FLASH3,
+ ADDR_SPACE_FLASH4,
+ ADDR_SPACE_FLASH5,
+ ADDR_SPACE_MEMX,
+ /* Sentinel */
+ ADDR_SPACE_COUNT
+ };
#define TARGET_CPU_CPP_BUILTINS() avr_cpu_cpp_builtins (pfile)
-#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS)
-extern GTY(()) section *progmem_section;
-#endif
-
-#define AVR_HAVE_JMP_CALL (avr_current_arch->have_jmp_call && !TARGET_SHORT_CALLS)
-#define AVR_HAVE_MUL (avr_current_arch->have_mul)
-#define AVR_HAVE_MOVW (avr_current_arch->have_movw_lpmx)
-#define AVR_HAVE_LPMX (avr_current_arch->have_movw_lpmx)
-#define AVR_HAVE_RAMPZ (avr_current_arch->have_elpm)
-#define AVR_HAVE_EIJMP_EICALL (avr_current_arch->have_eijmp_eicall)
-#define AVR_HAVE_8BIT_SP (avr_current_device->short_sp || TARGET_TINY_STACK)
+#define AVR_SHORT_CALLS (TARGET_SHORT_CALLS \
+ && avr_arch == &avr_arch_types[ARCH_AVRXMEGA3])
+#define AVR_HAVE_JMP_CALL (avr_arch->have_jmp_call && ! AVR_SHORT_CALLS)
+#define AVR_HAVE_MUL (avr_arch->have_mul)
+#define AVR_HAVE_MOVW (avr_arch->have_movw_lpmx)
+#define AVR_HAVE_LPM (!AVR_TINY)
+#define AVR_HAVE_LPMX (avr_arch->have_movw_lpmx)
+#define AVR_HAVE_ELPM (avr_arch->have_elpm)
+#define AVR_HAVE_ELPMX (avr_arch->have_elpmx)
+#define AVR_HAVE_RAMPD (avr_arch->have_rampd)
+#define AVR_HAVE_RAMPX (avr_arch->have_rampd)
+#define AVR_HAVE_RAMPY (avr_arch->have_rampd)
+#define AVR_HAVE_RAMPZ (avr_arch->have_elpm \
+ || avr_arch->have_rampd)
+#define AVR_HAVE_EIJMP_EICALL (avr_arch->have_eijmp_eicall)
+
+/* Handling of 8-bit SP versus 16-bit SP is as follows:
+
+FIXME: DRIVER_SELF_SPECS has changed.
+ -msp8 is used internally to select the right multilib for targets with
+ 8-bit SP. -msp8 is set automatically by DRIVER_SELF_SPECS for devices
+ with 8-bit SP or by multilib generation machinery. If a frame pointer is
+ needed and SP is only 8 bits wide, SP is zero-extended to get FP.
+
+ TARGET_TINY_STACK is triggered by -mtiny-stack which is a user option.
+ This option has no effect on multilib selection. It serves to save some
+ bytes on 16-bit SP devices by only changing SP_L and leaving SP_H alone.
+
+ These two properties are reflected by built-in macros __AVR_SP8__ resp.
+ __AVR_HAVE_8BIT_SP__ and __AVR_HAVE_16BIT_SP__. During multilib generation
+ there is always __AVR_SP8__ == __AVR_HAVE_8BIT_SP__. */
+
+#define AVR_HAVE_8BIT_SP \
+ (TARGET_TINY_STACK || avr_sp8)
+
+#define AVR_HAVE_SPH (!avr_sp8)
#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)");
+#define AVR_XMEGA (avr_arch->xmega_p)
+#define AVR_TINY (avr_arch->tiny_p)
#define BITS_BIG_ENDIAN 0
#define BYTES_BIG_ENDIAN 0
/* 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 LONG_TYPE_SIZE (INT_TYPE_SIZE == 8 ? 16 : 32)
#define LONG_LONG_TYPE_SIZE (INT_TYPE_SIZE == 8 ? 32 : 64)
#define FLOAT_TYPE_SIZE 32
-#define DOUBLE_TYPE_SIZE 32
-#define LONG_DOUBLE_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE (avr_double)
+#define LONG_DOUBLE_TYPE_SIZE (avr_long_double)
+
+#define LONG_LONG_ACCUM_TYPE_SIZE 64
#define DEFAULT_SIGNED_CHAR 1
#define FIRST_PSEUDO_REGISTER 36
+#define GENERAL_REGNO_P(N) IN_RANGE (N, 2, 31)
+#define GENERAL_REG_P(X) (REG_P (X) && GENERAL_REGNO_P (REGNO (X)))
+
#define FIXED_REGISTERS {\
1,1,/* r0 r1 */\
0,0,/* r2 r3 */\
32,33,34,35 \
}
-#define ADJUST_REG_ALLOC_ORDER order_regs_for_local_alloc ()
-
-
-#define HARD_REGNO_NREGS(REGNO, MODE) ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+#define ADJUST_REG_ALLOC_ORDER avr_adjust_reg_alloc_order()
-#define HARD_REGNO_MODE_OK(REGNO, MODE) avr_hard_regno_mode_ok(REGNO, MODE)
-
-#define MODES_TIEABLE_P(MODE1, MODE2) 1
enum reg_class {
NO_REGS,
#define REG_CLASS_CONTENTS { \
{0x00000000,0x00000000}, /* NO_REGS */ \
{0x00000001,0x00000000}, /* R0_REG */ \
- {3 << REG_X,0x00000000}, /* POINTER_X_REGS, r26 - r27 */ \
- {3 << REG_Y,0x00000000}, /* POINTER_Y_REGS, r28 - r29 */ \
- {3 << REG_Z,0x00000000}, /* POINTER_Z_REGS, r30 - r31 */ \
+ {3u << REG_X,0x00000000}, /* POINTER_X_REGS, r26 - r27 */ \
+ {3u << REG_Y,0x00000000}, /* POINTER_Y_REGS, r28 - r29 */ \
+ {3u << REG_Z,0x00000000}, /* POINTER_Z_REGS, r30 - r31 */ \
{0x00000000,0x00000003}, /* STACK_REG, STACK */ \
- {(3 << REG_Y) | (3 << REG_Z), \
+ {(3u << REG_Y) | (3u << REG_Z), \
0x00000000}, /* BASE_POINTER_REGS, r28 - r31 */ \
- {(3 << REG_X) | (3 << REG_Y) | (3 << REG_Z), \
+ {(3u << REG_X) | (3u << REG_Y) | (3u << REG_Z), \
0x00000000}, /* POINTER_REGS, r26 - r31 */ \
- {(3 << REG_X) | (3 << REG_Y) | (3 << REG_Z) | (3 << REG_W), \
+ {(3u << REG_X) | (3u << REG_Y) | (3u << REG_Z) | (3u << REG_W), \
0x00000000}, /* ADDW_REGS, r24 - r31 */ \
{0x00ff0000,0x00000000}, /* SIMPLE_LD_REGS r16 - r23 */ \
- {(3 << REG_X)|(3 << REG_Y)|(3 << REG_Z)|(3 << REG_W)|(0xff << 16), \
+ {(3u << REG_X)|(3u << REG_Y)|(3u << REG_Z)|(3u << REG_W)|(0xffu << 16),\
0x00000000}, /* LD_REGS, r16 - r31 */ \
{0x0000ffff,0x00000000}, /* NO_LD_REGS r0 - r15 */ \
{0xffffffff,0x00000000}, /* GENERAL_REGS, r0 - r31 */ \
#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 MODE_CODE_BASE_REG_CLASS(mode, as, outer_code, index_code) \
+ avr_mode_code_base_reg_class (mode, as, outer_code, index_code)
#define INDEX_REG_CLASS NO_REGS
-#define REGNO_OK_FOR_BASE_P(r) (((r) < FIRST_PSEUDO_REGISTER \
- && ((r) == REG_X \
- || (r) == REG_Y \
- || (r) == REG_Z \
- || (r) == ARG_POINTER_REGNUM)) \
- || (reg_renumber \
- && (reg_renumber[r] == REG_X \
- || reg_renumber[r] == REG_Y \
- || reg_renumber[r] == REG_Z \
- || (reg_renumber[r] \
- == ARG_POINTER_REGNUM))))
+#define REGNO_MODE_CODE_OK_FOR_BASE_P(num, mode, as, outer_code, index_code) \
+ avr_regno_mode_code_ok_for_base_p (num, mode, as, outer_code, index_code)
#define REGNO_OK_FOR_INDEX_P(NUM) 0
#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
-#define CLASS_MAX_NREGS(CLASS, MODE) class_max_nregs (CLASS, MODE)
-
#define STACK_PUSH_CODE POST_DEC
-#define STACK_GROWS_DOWNWARD
-
-#define STARTING_FRAME_OFFSET 1
+#define STACK_GROWS_DOWNWARD 1
#define STACK_POINTER_OFFSET 1
#define ARG_POINTER_REGNUM 34
-#define STATIC_CHAIN_REGNUM 2
+#define STATIC_CHAIN_REGNUM ((AVR_TINY) ? 18 :2)
#define ELIMINABLE_REGS { \
- {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
- {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \
- ,{FRAME_POINTER_REGNUM+1,STACK_POINTER_REGNUM+1}}
+ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
+ { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM }, \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
+ { FRAME_POINTER_REGNUM + 1, STACK_POINTER_REGNUM + 1 } }
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
OFFSET = avr_initial_elimination_offset (FROM, TO)
for POST_DEC targets (PR27386). */
/*#define PUSH_ROUNDING(NPUSHED) (NPUSHED)*/
-typedef struct avr_args {
- int nregs; /* # registers available for passing */
- int regno; /* next available register number */
+typedef struct avr_args
+{
+ /* # Registers available for passing */
+ int nregs;
+
+ /* Next available register number */
+ int regno;
} CUMULATIVE_ARGS;
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
- init_cumulative_args (&(CUM), FNTYPE, LIBNAME, FNDECL)
-
-#define FUNCTION_ARG_REGNO_P(r) function_arg_regno_p(r)
+ avr_init_cumulative_args (&(CUM), FNTYPE, LIBNAME, FNDECL)
-extern int avr_reg_order[];
+#define FUNCTION_ARG_REGNO_P(r) avr_function_arg_regno_p(r)
#define DEFAULT_PCC_STRUCT_RETURN 0
#define MAX_REGS_PER_ADDRESS 1
-#define REG_OK_FOR_BASE_NOSTRICT_P(X) \
- (REGNO (X) >= FIRST_PSEUDO_REGISTER || REG_OK_FOR_BASE_STRICT_P(X))
-
-#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_P (REGNO (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)) \
- { \
- push_reload (XEXP (X,0), XEXP (X,0), &XEXP (X,0), &XEXP (X,0), \
- POINTER_REGS, GET_MODE (X),GET_MODE (X) , 0, 0, \
- OPNUM, RELOAD_OTHER); \
- goto WIN; \
- } \
- 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) \
- { \
- int fit = INTVAL (XEXP (X, 1)) <= (64 - GET_MODE_SIZE (MODE)); \
- if (fit) \
- { \
- if (reg_equiv_address[REGNO (XEXP (X, 0))] != 0) \
- { \
- int regno = REGNO (XEXP (X, 0)); \
- rtx mem = make_memloc (X, regno); \
- push_reload (XEXP (mem,0), NULL, &XEXP (mem,0), NULL, \
- POINTER_REGS, Pmode, VOIDmode, 0, 0, \
- 1, ADDR_TYPE (TYPE)); \
- push_reload (mem, 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)) \
- { \
- push_reload (X, NULL_RTX, &X, NULL, \
- POINTER_REGS, GET_MODE (X), VOIDmode, 0, 0, \
- OPNUM, TYPE); \
- goto WIN; \
- } \
- } \
-} while(0)
-
-#define LEGITIMATE_CONSTANT_P(X) 1
-
-#define BRANCH_COST(speed_p, predictable_p) 0
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN) \
+ do { \
+ rtx new_x = avr_legitimize_reload_address (&(X), MODE, OPNUM, TYPE, \
+ ADDR_TYPE (TYPE), \
+ IND_L, make_memloc); \
+ if (new_x) \
+ { \
+ X = new_x; \
+ goto WIN; \
+ } \
+ } while (0)
+
+/* We increase branch costs after reload in order to keep basic-block
+ reordering from introducing out-of-line jumps and to prefer fall-through
+ edges instead. The default branch costs are 0, mainly because otherwise
+ do_store_flag might come up with bloated code. */
+#define BRANCH_COST(speed_p, predictable_p) \
+ (avr_branch_cost + (reload_completed ? 4 : 0))
#define SLOW_BYTE_ACCESS 0
-#define NO_FUNCTION_CSE
+#define NO_FUNCTION_CSE 1
+
+#define REGISTER_TARGET_PRAGMAS() \
+ do { \
+ avr_register_target_pragmas(); \
+ } while (0)
#define TEXT_SECTION_ASM_OP "\t.text"
#define SUPPORTS_INIT_PRIORITY 0
-#define JUMP_TABLES_IN_TEXT_SECTION 0
+/* We pretend jump tables are in text section because otherwise,
+ final.c will switch to .rodata before jump tables and thereby
+ triggers __do_copy_data. As we implement ASM_OUTPUT_ADDR_VEC,
+ we still have full control over the jump tables themselves. */
+#define JUMP_TABLES_IN_TEXT_SECTION 1
#define ASM_COMMENT_START " ; "
#define ASM_APP_OFF "/* #NOAPP */\n"
-/* Switch into a generic section. */
-#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
-#define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
-
-#define ASM_OUTPUT_ASCII(FILE, P, SIZE) gas_output_ascii (FILE,P,SIZE)
-
#define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) ((C) == '\n' || ((C) == '$'))
-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
-do { \
- fputs ("\t.comm ", (STREAM)); \
- assemble_name ((STREAM), (NAME)); \
- fprintf ((STREAM), ",%lu,1\n", (unsigned long)(SIZE)); \
-} while (0)
-
-#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ROUNDED) \
- asm_output_bss ((FILE), (DECL), (NAME), (SIZE), (ROUNDED))
-
-#define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) \
-do { \
- fputs ("\t.lcomm ", (STREAM)); \
- assemble_name ((STREAM), (NAME)); \
- fprintf ((STREAM), ",%d\n", (int)(SIZE)); \
-} while (0)
-
-#undef TYPE_ASM_OP
-#undef SIZE_ASM_OP
-#undef WEAK_ASM_OP
-#define TYPE_ASM_OP "\t.type\t"
-#define SIZE_ASM_OP "\t.size\t"
-#define WEAK_ASM_OP "\t.weak\t"
-/* Define the strings used for the special svr4 .type and .size directives.
- These strings generally do not vary from one system running svr4 to
- another, but if a given system (e.g. m88k running svr) needs to use
- different pseudo-op names for these, they may be overridden in the
- file which includes this one. */
-
-
-#undef TYPE_OPERAND_FMT
-#define TYPE_OPERAND_FMT "@%s"
-/* The following macro defines the format used to output the second
- operand of the .type assembler directive. Different svr4 assemblers
- expect various different forms for this operand. The one given here
- is just a default. You may need to override it in your machine-
- specific tm.h file (depending upon the particulars of your assembler). */
-
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
-avr_asm_declare_function_name ((FILE), (NAME), (DECL))
-
-#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
- do { \
- if (!flag_inhibit_size_directive) \
- ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
- } while (0)
+#define ASM_OUTPUT_ALIGNED_DECL_COMMON(STREAM, DECL, NAME, SIZE, ALIGN) \
+ avr_asm_output_aligned_decl_common (STREAM, DECL, NAME, SIZE, ALIGN, false)
+
+#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
+ avr_asm_asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN, \
+ asm_output_aligned_bss)
-#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
-do { \
- ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
- size_directive_output = 0; \
- if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
- { \
- size_directive_output = 1; \
- ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, \
- int_size_in_bytes (TREE_TYPE (DECL))); \
- } \
- ASM_OUTPUT_LABEL(FILE, NAME); \
-} while (0)
-
-#undef ASM_FINISH_DECLARE_OBJECT
-#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
-do { \
- const char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
- HOST_WIDE_INT size; \
- if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
- && ! AT_END && TOP_LEVEL \
- && DECL_INITIAL (DECL) == error_mark_node \
- && !size_directive_output) \
- { \
- size_directive_output = 1; \
- size = int_size_in_bytes (TREE_TYPE (DECL)); \
- ASM_OUTPUT_SIZE_DIRECTIVE (FILE, name, size); \
- } \
- } while (0)
-
-
-#define ESCAPES \
-"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
-\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\
-\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
-\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
-\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
-\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"
-/* A table of bytes codes used by the ASM_OUTPUT_ASCII and
- ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table
- corresponds to a particular byte value [0..255]. For any
- given byte value, if the value in the corresponding table
- position is zero, the given character can be output directly.
- If the table value is 1, the byte must be output as a \ooo
- octal escape. If the tables value is anything else, then the
- byte value should be output as a \ followed by the value
- in the table. Note that we can use standard UN*X escape
- sequences for many control characters, but we don't use
- \a to represent BEL because some svr4 assemblers (e.g. on
- the i386) don't know about that. Also, we don't use \v
- since some versions of gas, such as 2.2 did not accept it. */
-
-#define STRING_LIMIT ((unsigned) 64)
-#define STRING_ASM_OP "\t.string\t"
-/* Some svr4 assemblers have a limit on the number of characters which
- can appear in the operand of a .string directive. If your assembler
- has such a limitation, you should define STRING_LIMIT to reflect that
- limit. Note that at least some svr4 assemblers have a limit on the
- actual number of bytes in the double-quoted string, and that they
- count each character in an escape sequence as one byte. Thus, an
- escape sequence like \377 would count as four bytes.
-
- If your target assembler doesn't support the .string directive, you
- should define this to zero. */
+#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGN) \
+ avr_asm_output_aligned_decl_common (STREAM, DECL, NAME, SIZE, ALIGN, true)
/* Globalizing directive for a label. */
#define GLOBAL_ASM_OP ".global\t"
-#define SET_ASM_OP "\t.set\t"
-
-#define ASM_WEAKEN_LABEL(FILE, NAME) \
- do \
- { \
- fputs ("\t.weak\t", (FILE)); \
- assemble_name ((FILE), (NAME)); \
- fputc ('\n', (FILE)); \
- } \
- while (0)
-
#define SUPPORTS_WEAK 1
-#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \
-sprintf (STRING, "*.%s%lu", PREFIX, (unsigned long)(NUM))
-
#define HAS_INIT_SECTION 1
#define REGISTER_NAMES { \
"r24","r25","r26","r27","r28","r29","r30","r31", \
"__SP_L__","__SP_H__","argL","argH"}
-#define FINAL_PRESCAN_INSN(insn, operand, nop) final_prescan_insn (insn, operand,nop)
-
-#define PRINT_OPERAND(STREAM, X, CODE) print_operand (STREAM, X, CODE)
-
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '~' || (CODE) == '!')
-
-#define PRINT_OPERAND_ADDRESS(STREAM, X) print_operand_address(STREAM, X)
-
-#define USER_LABEL_PREFIX ""
-
-#define ASSEMBLER_DIALECT AVR_HAVE_MOVW
+#define FINAL_PRESCAN_INSN(insn, operand, nop) \
+ avr_final_prescan_insn (insn, operand,nop)
#define ASM_OUTPUT_REG_PUSH(STREAM, REGNO) \
{ \
fprintf (STREAM, "\tpop\tr%d", REGNO); \
}
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
- avr_output_addr_vec_elt(STREAM, VALUE)
+#define ASM_OUTPUT_ADDR_VEC(TLABEL, TDATA) \
+ avr_output_addr_vec (TLABEL, TDATA)
-#define ASM_OUTPUT_CASE_LABEL(STREAM, PREFIX, NUM, TABLE) \
- (switch_to_section (progmem_section), \
- (*targetm.asm_out.internal_label) (STREAM, PREFIX, NUM))
-
-#define ASM_OUTPUT_SKIP(STREAM, N) \
-fprintf (STREAM, "\t.skip %lu,0\n", (unsigned long)(N))
-
-#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
- do { \
- if ((POWER) > 1) \
- fprintf (STREAM, "\t.p2align\t%d\n", POWER); \
+#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
+ do { \
+ if ((POWER) > 0) \
+ fprintf (STREAM, "\t.p2align\t%d\n", POWER); \
} while (0)
-#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
- default_elf_asm_output_external (FILE, DECL, NAME)
-
#define CASE_VECTOR_MODE HImode
#undef WORD_REGISTER_OPERATIONS
-#define MOVE_MAX 4
+/* Can move only a single byte from memory to reg in a
+ single instruction. */
+
+#define MOVE_MAX 1
+
+/* Allow upto two bytes moves to occur using by_pieces
+ infrastructure */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+#define MOVE_MAX_PIECES 2
+
+/* Set MOVE_RATIO to 3 to allow memory moves upto 4 bytes to happen
+ by pieces when optimizing for speed, like it did when MOVE_MAX_PIECES
+ was 4. When optimizing for size, allow memory moves upto 2 bytes.
+ Also see avr_use_by_pieces_infrastructure_p. */
+
+#define MOVE_RATIO(speed) ((speed) ? 3 : 2)
#define Pmode HImode
#define DOLLARS_IN_IDENTIFIERS 0
-#define NO_DOLLAR_IN_LABEL 1
-
#define TRAMPOLINE_SIZE 4
/* Store in cc_status the expressions
after execution of an instruction whose pattern is EXP.
Do not alter them if the instruction would not alter the cc's. */
-#define NOTICE_UPDATE_CC(EXP, INSN) notice_update_cc(EXP, INSN)
+#define NOTICE_UPDATE_CC(EXP, INSN) avr_notice_update_cc (EXP, INSN)
/* The add insns don't set overflow in a usable way. */
#define CC_OVERFLOW_UNUSABLE 01000
#define FUNCTION_PROFILER(FILE, LABELNO) \
fprintf (FILE, "/* profiler %d */", (LABELNO))
-#define ADJUST_INSN_LENGTH(INSN, LENGTH) (LENGTH =\
- adjust_insn_length (INSN, LENGTH))
-
-extern const char *avr_device_to_arch (int argc, const char **argv);
-extern const char *avr_device_to_data_start (int argc, const char **argv);
-extern const char *avr_device_to_startfiles (int argc, const char **argv);
-extern const char *avr_device_to_devicelib (int argc, const char **argv);
+#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
+ (LENGTH = avr_adjust_insn_length (INSN, LENGTH))
-#define EXTRA_SPEC_FUNCTIONS \
- { "device_to_arch", avr_device_to_arch }, \
- { "device_to_data_start", avr_device_to_data_start }, \
- { "device_to_startfile", avr_device_to_startfiles }, \
- { "device_to_devicelib", avr_device_to_devicelib },
+extern const char *avr_devicespecs_file (int, const char**);
+extern const char *avr_double_lib (int, const char**);
-#define CPP_SPEC ""
+#define EXTRA_SPEC_FUNCTIONS \
+ { "double-lib", avr_double_lib }, \
+ { "device-specs-file", avr_devicespecs_file },
-#define CC1_SPEC ""
+/* Driver self specs has lmited functionality w.r.t. '%s' for dynamic specs.
+ Apply '%s' to a static string to inflate the file (directory) name which
+ is used to diagnose problems with reading the specs file. */
-#define CC1PLUS_SPEC "%{!frtti:-fno-rtti} \
- %{!fenforce-eh-specs:-fno-enforce-eh-specs} \
- %{!fexceptions:-fno-exceptions}"
-/* A C string constant that tells the GCC driver program options to
- pass to `cc1plus'. */
+#undef DRIVER_SELF_SPECS
+#define DRIVER_SELF_SPECS \
+ " %:double-lib(%{m*:m%*})" \
+ " %:device-specs-file(device-specs%s %{mmcu=*:%*})"
-#define ASM_SPEC "%{mmcu=avr25:-mmcu=avr2;mmcu=avr35:-mmcu=avr3;mmcu=avr31:-mmcu=avr3;mmcu=avr51:-mmcu=avr5;\
-mmcu=*:-mmcu=%*}"
-
-#define LINK_SPEC "\
-%{mrelax:--relax\
- %{mpmem-wrap-around:%{mmcu=at90usb8*:--pmem-wrap-around=8k}\
- %{mmcu=atmega16*:--pmem-wrap-around=16k}\
- %{mmcu=atmega32*|\
- mmcu=at90can32*:--pmem-wrap-around=32k}\
- %{mmcu=atmega64*|\
- mmcu=at90can64*|\
- mmcu=at90usb64*:--pmem-wrap-around=64k}}}\
-%:device_to_arch(%{mmcu=*:%*})\
-%:device_to_data_start(%{mmcu=*:%*})"
-
-#define LIB_SPEC \
- "%{!mmcu=at90s1*:%{!mmcu=attiny11:%{!mmcu=attiny12:%{!mmcu=attiny15:%{!mmcu=attiny28: -lc }}}}}"
-
-#define LIBSTDCXX "gcc"
/* No libstdc++ for now. Empty string doesn't work. */
+#define LIBSTDCXX "gcc"
-#define LIBGCC_SPEC \
- "%{!mmcu=at90s1*:%{!mmcu=attiny11:%{!mmcu=attiny12:%{!mmcu=attiny15:%{!mmcu=attiny28: -lgcc }}}}}"
-
-#define STARTFILE_SPEC "%:device_to_startfile(%{mmcu=*:%*})"
-
-#define ENDFILE_SPEC ""
-
-/* This is the default without any -mmcu=* option (AT90S*). */
-#define MULTILIB_DEFAULTS { "mmcu=avr2" }
+/* This is the default without any -mmcu=* option. */
+#define MULTILIB_DEFAULTS { "mmcu=" AVR_MMCU_DEFAULT }
#define TEST_HARD_REG_CLASS(CLASS, REGNO) \
TEST_HARD_REG_BIT (reg_class_contents[ (int) (CLASS)], REGNO)
-/* Note that the other files fail to use these
- in some of the places where they should. */
-
-#if defined(__STDC__) || defined(ALMOST_STDC)
-#define AS2(a,b,c) #a " " #b "," #c
-#define AS2C(b,c) " " #b "," #c
-#define AS3(a,b,c,d) #a " " #b "," #c "," #d
-#define AS1(a,b) #a " " #b
-#else
-#define AS1(a,b) "a b"
-#define AS2(a,b,c) "a b,c"
-#define AS2C(b,c) " b,c"
-#define AS3(a,b,c,d) "a b,c,d"
-#endif
-#define OUT_AS1(a,b) output_asm_insn (AS1(a,b), operands)
-#define OUT_AS2(a,b,c) output_asm_insn (AS2(a,b,c), operands)
#define CR_TAB "\n\t"
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
-#define DWARF2_DEBUGGING_INFO 1
-
#define DWARF2_ADDR_SIZE 4
-#define OBJECT_FORMAT_ELF
-
#define INCOMING_RETURN_ADDR_RTX avr_incoming_return_addr_rtx ()
#define INCOMING_FRAME_SP_OFFSET (AVR_3_BYTE_PC ? 3 : 2)
/* 'true' if a callee might be tail called */
int sibcall_fails;
+
+ /* 'true' if the above is_foo predicates are sanity-checked to avoid
+ multiple diagnose for the same function. */
+ int attributes_checked_p;
+
+ /* 'true' - if current function shall not use '__gcc_isr' pseudo
+ instructions as specified by the "no_gccisr" attribute. */
+ int is_no_gccisr;
+
+ /* Used for `__gcc_isr' pseudo instruction handling of
+ non-naked ISR prologue / epilogue(s). */
+ struct
+ {
+ /* 'true' if this function actually uses "*gasisr" insns. */
+ int yes;
+ /* 'true' if this function is allowed to use "*gasisr" insns. */
+ int maybe;
+ /* The register numer as printed by the Done chunk. */
+ int regno;
+ } gasisr;
+
+ /* 'true' if this function references .L__stack_usage like with
+ __builtin_return_address. */
+ int use_L__stack_usage;
};
+
+/* AVR does not round pushes, but the existence of this macro is
+ required in order for pushes to be generated. */
+#define PUSH_ROUNDING(X) (X)
+
+/* Define prototype here to avoid build warning. Some files using
+ ACCUMULATE_OUTGOING_ARGS (directly or indirectly) include
+ tm.h but not tm_p.h. */
+extern int avr_accumulate_outgoing_args (void);
+#define ACCUMULATE_OUTGOING_ARGS avr_accumulate_outgoing_args()
+
+#define INIT_EXPANDERS avr_init_expanders()
+
+/* Flags used for io and address attributes. */
+#define SYMBOL_FLAG_IO_LOW (SYMBOL_FLAG_MACH_DEP << 4)
+#define SYMBOL_FLAG_IO (SYMBOL_FLAG_MACH_DEP << 5)
+#define SYMBOL_FLAG_ADDRESS (SYMBOL_FLAG_MACH_DEP << 6)