/* Definitions of target machine for GNU compiler, Argonaut EPIPHANY cpu.
- Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005,
- 2007, 2009, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1994-2020 Free Software Foundation, Inc.
Contributed by Embecosm on behalf of Adapteva, Inc.
This file is part of GCC.
} while (0)
/* Pick up the libgloss library. One day we may do this by linker script, but
- for now its static. */
+ for now its static.
+ libgloss might use errno/__errno, which might not have been needed when we
+ saw libc the first time, so link with libc a second time. */
#undef LIB_SPEC
-#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}} -lepiphany"
+#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}} -lepiphany %{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
#define LINK_SPEC "%{v}"
#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+#define EPIPHANY_LIBRARY_EXTRA_SPEC \
+ "-ffixed-r40 -ffixed-r41 -ffixed-r42 -ffixed-r43"
+
+/* In the "spec:" rule,, t-epiphany changes this to epiphany_library_stub_spec
+ and epiphany_library_extra_spec, respectively. */
+#define EXTRA_SPECS \
+ { "epiphany_library_extra_spec", "" }, \
+ { "epiphany_library_build_spec", EPIPHANY_LIBRARY_EXTRA_SPEC }, \
+
+#define DRIVER_SELF_SPECS " %(epiphany_library_extra_spec) "
+
#undef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX "_"
#define MALLOC_ABI_ALIGNMENT BIGGEST_ALIGNMENT
-/* Make strings dword-aligned so strcpy from constants will be faster. */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- ((TREE_CODE (EXP) == STRING_CST \
- && (ALIGN) < FASTEST_ALIGNMENT) \
- ? FASTEST_ALIGNMENT : (ALIGN))
-
/* Make arrays of chars dword-aligned for the same reasons.
Also, align arrays of SImode items. */
#define DATA_ALIGNMENT(TYPE, ALIGN) \
(SPECIFIED_ALIGN)) \
: MAX ((MANGLED_ALIGN), (SPECIFIED_ALIGN)))
-#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
- epiphany_adjust_field_align((FIELD), (COMPUTED))
+#define ADJUST_FIELD_ALIGN(FIELD, TYPE, COMPUTED) \
+ epiphany_adjust_field_align((TYPE), (COMPUTED))
\f
/* Layout of source language data types. */
0, 0, 0, 0, 0, 0, 0, 0, /* 016-023, gr16 - gr23 */ \
0, 0, 0, 0, 1, 1, 1, 1, /* 024-031, gr24 - gr31 */ \
0, 0, 0, 0, 0, 0, 0, 0, /* 032-039, gr32 - gr39 */ \
- 1, 1, 1, 1, 0, 0, 0, 0, /* 040-047, gr40 - gr47 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 040-047, gr40 - gr47 */ \
0, 0, 0, 0, 0, 0, 0, 0, /* 048-055, gr48 - gr55 */ \
0, 0, 0, 0, 0, 0, 0, 0, /* 056-063, gr56 - gr63 */ \
/* Other registers */ \
1, 1, 1, 1, 1, 1, 1, 1, /* 016-023, gr16 - gr23 */ \
1, 1, 1, 1, 1, 1, 1, 1, /* 024-031, gr24 - gr31 */ \
0, 0, 0, 0, 0, 0, 0, 0, /* 032-039, gr32 - gr38 */ \
- 1, 1, 1, 1, 1, 1, 1, 1, /* 040-047, gr40 - gr47 */ \
+ 0, 0, 0, 0, 1, 1, 1, 1, /* 040-047, gr40 - gr47 */ \
1, 1, 1, 1, 1, 1, 1, 1, /* 048-055, gr48 - gr55 */ \
1, 1, 1, 1, 1, 1, 1, 1, /* 056-063, gr56 - gr63 */ \
1, /* 64 AP - fake arg ptr */ \
4, 5, 6, 7, /* Calle-saved 'small' registers. */ \
15, /* Calle-saved unpaired register. */ \
8, 9, 10, 11, /* Calle-saved registers. */ \
- 32, 33, 34, 35, 36, 37, 38, 39, \
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, \
14, 13, /* Link register, stack pointer. */ \
- 40, 41, 42, 43, /* Usually constant, but might be made callee-saved. */ \
/* Can't allocate, but must name these... */ \
28, 29, 30, 31, \
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77 \
}
-/* Return number of consecutive hard regs needed starting at reg REGNO
- to hold something of mode MODE.
- This is ordinarily the length in words of a value of mode MODE
- but can be less for certain modes in special long registers. */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
-((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
-extern const unsigned int epiphany_hard_regno_mode_ok[];
-extern unsigned int epiphany_mode_class[];
-#define HARD_REGNO_MODE_OK(REGNO, MODE) hard_regno_mode_ok((REGNO), (MODE))
-
-/* A C expression that is nonzero if it is desirable to choose
- register allocation so as to avoid move instructions between a
- value of mode MODE1 and a value of mode MODE2.
-
- If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R,
- MODE2)' are ever different for any R, then `MODES_TIEABLE_P (MODE1,
- MODE2)' must be zero. */
-
-#define MODES_TIEABLE_P(MODE1, MODE2) 1
+#define HARD_REGNO_RENAME_OK(SRC, DST) epiphany_regno_rename_ok (SRC, DST)
/* Register classes and constants. */
They give nonzero only if REGNO is a hard reg of the suitable class
or a pseudo reg currently allocated to a suitable hard reg.
Since they use reg_renumber, they are safe only once reg_renumber
- has been allocated, which happens in local-alloc.c. */
+ has been allocated, which happens in reginfo.c during register
+ allocation. */
#define REGNO_OK_FOR_BASE_P(REGNO) \
((REGNO) < FIRST_PSEUDO_REGISTER || (unsigned) reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER)
#define REGNO_OK_FOR_INDEX_P(REGNO) \
unsigned pretend_args_odd : 1;
unsigned lr_clobbered : 1;
unsigned control_use_inserted : 1;
+ unsigned lr_slot_known : 1;
unsigned sw_entities_processed : 6;
long lr_slot_offset;
rtx and_mask;
/* Define this macro if pushing a word onto the stack moves the stack
pointer to a smaller address. */
-#define STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 1
/* Define this to nonzero if the nominal address of the stack frame
is at the high-address end of the local variables;
goes at a more negative offset in the frame. */
#define FRAME_GROWS_DOWNWARD 1
-/* Offset within stack frame to start allocating local variables at.
- If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
- first local allocated. Otherwise, it is the offset to the BEGINNING
- of the first local allocated. */
-#define STARTING_FRAME_OFFSET epiphany_stack_offset
-
/* Offset from the stack pointer register to the first location at which
outgoing arguments are placed. */
#define STACK_POINTER_OFFSET epiphany_stack_offset
#define FRAME_ADDR_RTX(frame) \
((frame) == hard_frame_pointer_rtx ? arg_pointer_rtx : NULL)
+#define EPIPHANY_RETURN_REGNO \
+ ((current_function_decl != NULL \
+ && epiphany_is_interrupt_p (current_function_decl)) \
+ ? IRET_REGNUM : GPR_LR)
/* This is not only for dwarf unwind info, but also for the benefit of
df-scan.c to tell it that LR is live at the function start. */
-#define INCOMING_RETURN_ADDR_RTX \
- gen_rtx_REG (Pmode, \
- (current_function_decl != NULL \
- && epiphany_is_interrupt_p (current_function_decl) \
- ? IRET_REGNUM : GPR_LR))
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, EPIPHANY_RETURN_REGNO)
/* However, we haven't implemented the rest needed for dwarf2 unwind info. */
#define DWARF2_UNWIND_INFO 0
#define RETURN_ADDR_RTX(count, frame) \
(count ? NULL_RTX \
: gen_rtx_UNSPEC (SImode, gen_rtvec (1, const0_rtx), UNSPEC_RETURN_ADDR))
+
+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (EPIPHANY_RETURN_REGNO)
\f
/* Trampolines.
An epiphany trampoline looks like this:
#define HAVE_POST_MODIFY_DISP TARGET_POST_MODIFY
#define HAVE_POST_MODIFY_REG TARGET_POST_MODIFY
+/* Currently, the only users of the USE_*CREMENT macros are
+ move_by_pieces / store_by_pieces_1 . We don't want them to use
+ POST_MODIFY modes, because we got ample addressing range for the
+ reg+offset addressing mode; besides, there are short index+offset loads,
+ but the only short post-modify load uses POST_MODIFY_REG.
+ Moreover, using auto-increment in move_by_pieces from structure copying
+ in the prologue causes confused debug output.
+ If another pass starts using these macros where the use of these
+ addressing modes would make more sense, we can try checking the
+ current pass. */
+#define USE_LOAD_POST_INCREMENT(MODE) 0
+#define USE_LOAD_POST_DECREMENT(MODE) 0
+#define USE_STORE_POST_INCREMENT(MODE) 0
+#define USE_STORE_POST_DECREMENT(MODE) 0
+
/* Recognize any constant value that is a valid address. */
#define CONSTANT_ADDRESS_P(X) \
(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
#define RTX_OK_FOR_OFFSET_P(MODE, X) \
RTX_OK_FOR_OFFSET_1 (GET_MODE_CLASS (MODE) == MODE_VECTOR_INT \
- && epiphany_vect_align == 4 ? SImode : (MODE), X)
+ && epiphany_vect_align == 4 \
+ ? (machine_mode) SImode : (machine_mode) (MODE), X)
#define RTX_OK_FOR_OFFSET_1(MODE, X) \
(GET_CODE (X) == CONST_INT \
&& !(INTVAL (X) & (GET_MODE_SIZE (MODE) - 1)) \
/* Define this macro if it is as good or better to call a constant
function address than to call an address kept in a register. */
/* On the EPIPHANY, calling through registers is slow. */
-#define NO_FUNCTION_CSE
+#define NO_FUNCTION_CSE 1
\f
/* Section selection. */
/* WARNING: These section names also appear in dwarf2out.c. */
/* This is how to output an assembler line
that says to advance the location counter
to a multiple of 2**LOG bytes. */
-#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+#define ASM_OUTPUT_ALIGN(FILE, LOG) \
do { if ((LOG) != 0) fprintf (FILE, "\t.balign %d\n", 1 << (LOG)); } while (0)
+
+/* Inside the text section, align with nops rather than zeros. */
+#define ASM_OUTPUT_ALIGN_WITH_NOP(FILE, LOG) \
+do \
+{ \
+ if ((LOG) != 0) fprintf (FILE, "\t.balignw %d,0x01a2\n", 1 << (LOG)); \
+} while (0)
+
+/* This is how to declare the size of a function. */
+#undef ASM_DECLARE_FUNCTION_SIZE
+#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
+ do \
+ { \
+ const char *__name = (FNAME); \
+ tree attrs = DECL_ATTRIBUTES ((DECL)); \
+ \
+ if (!flag_inhibit_size_directive) \
+ { \
+ if (lookup_attribute ("forwarder_section", attrs)) \
+ { \
+ const char *prefix = "__forwarder_dst_"; \
+ char *dst_name \
+ = (char *) alloca (strlen (prefix) + strlen (__name) + 1); \
+ \
+ strcpy (dst_name, prefix); \
+ strcat (dst_name, __name); \
+ __name = dst_name; \
+ } \
+ ASM_OUTPUT_MEASURED_SIZE ((FILE), __name); \
+ } \
+ } \
+ while (0)
\f
/* Debugging information. */
/* Define if operations between registers always perform the operation
on the full register even if a narrower mode is specified. */
-#define WORD_REGISTER_OPERATIONS
+#define WORD_REGISTER_OPERATIONS 1
/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
will either zero-extend or sign-extend. The value of this macro should
few bits. */
#define SHIFT_COUNT_TRUNCATED 1
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
- is done just by pretending it is already truncated. */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
/* Specify the machine mode that pointers have.
After generation of rtl, the compiler makes no further distinction
between pointers and any other objects of this machine mode. */
enum epiphany_function_type
{
EPIPHANY_FUNCTION_UNKNOWN, EPIPHANY_FUNCTION_NORMAL,
- /* These are interrupt handlers. The name corresponds to the register
- name that contains the return address. */
- EPIPHANY_FUNCTION_ILINK1, EPIPHANY_FUNCTION_ILINK2,
- /* These are interrupt handlers. The name corresponds to which type
- of interrupt handler we're dealing with. */
- EPIPHANY_FUNCTION_RESET, EPIPHANY_FUNCTION_SOFTWARE_EXCEPTION,
- EPIPHANY_FUNCTION_TIMER, EPIPHANY_FUNCTION_DMA0,
- EPIPHANY_FUNCTION_DMA1, EPIPHANY_FUNCTION_STATIC_FLAG,
- EPIPHANY_FUNCTION_SWI
+ EPIPHANY_FUNCTION_INTERRUPT
};
-#define EPIPHANY_INTERRUPT_P(TYPE) \
- ((TYPE) >= EPIPHANY_FUNCTION_RESET && (TYPE) <= EPIPHANY_FUNCTION_SWI)
+#define EPIPHANY_INTERRUPT_P(TYPE) ((TYPE) == EPIPHANY_FUNCTION_INTERRUPT)
/* Compute the type of a function from its DECL. */
finally an entity that runs in a second mode switching pass to
resolve FP_MODE_ROUND_UNKNOWN. */
#define NUM_MODES_FOR_MODE_SWITCHING \
- { 2, 2, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE }
-
-#define MODE_NEEDED(ENTITY, INSN) epiphany_mode_needed((ENTITY), (INSN))
-
-#define MODE_PRIORITY_TO_MODE(ENTITY, N) \
- (epiphany_mode_priority_to_mode ((ENTITY), (N)))
-
-#define EMIT_MODE_SET(ENTITY, MODE, HARD_REGS_LIVE) \
- emit_set_fp_mode ((ENTITY), (MODE), (HARD_REGS_LIVE))
-
-#define MODE_ENTRY(ENTITY) (epiphany_mode_entry_exit ((ENTITY), false))
-#define MODE_EXIT(ENTITY) (epiphany_mode_entry_exit ((ENTITY), true))
-#define MODE_AFTER(LAST_MODE, INSN) \
- (epiphany_mode_after (e, (LAST_MODE), (INSN)))
+ { 2, 2, 2, \
+ FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE }
#define TARGET_INSERT_MODE_SWITCH_USE epiphany_insert_mode_switch_use
{
EPIPHANY_MSW_ENTITY_AND,
EPIPHANY_MSW_ENTITY_OR,
+ EPIPHANY_MSW_ENTITY_CONFIG, /* 1 means config is known or saved. */
EPIPHANY_MSW_ENTITY_NEAREST,
EPIPHANY_MSW_ENTITY_TRUNC,
EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN,
EPIPHANY_MSW_ENTITY_ROUND_KNOWN,
- EPIPHANY_MSW_ENTITY_FPU_OMNIBUS
+ EPIPHANY_MSW_ENTITY_FPU_OMNIBUS,
+ EPIPHANY_MSW_ENTITY_NUM
};
extern int epiphany_normal_fp_rounding;
-extern struct rtl_opt_pass pass_mode_switch_use;
-extern struct rtl_opt_pass pass_resolve_sw_modes;
+#ifndef USED_FOR_TARGET
+extern rtl_opt_pass *make_pass_mode_switch_use (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_resolve_sw_modes (gcc::context *ctxt);
+#endif
/* This will need to be adjusted when FP_CONTRACT_ON is properly
implemented. */
#define TARGET_FUSED_MADD (flag_fp_contract_mode == FP_CONTRACT_FAST)
+#undef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ epiphany_start_function ((FILE), (NAME), (DECL))
+
+/* This is how we tell the assembler that two symbols have the same value. */
+#define ASM_OUTPUT_DEF(FILE, NAME1, NAME2) \
+ do \
+ { \
+ assemble_name (FILE, NAME1); \
+ fputs (" = ", FILE); \
+ assemble_name (FILE, NAME2); \
+ fputc ('\n', FILE); \
+ } \
+ while (0)
+
#endif /* !GCC_EPIPHANY_H */