/* Definitions of target machine for GNU compiler. MIPS version.
Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by A. Lichnewsky (lich@inria.inria.fr).
Changed by Michael Meissner (meissner@osf.org).
#define TARGET_GPWORD \
(TARGET_ABICALLS \
&& !TARGET_ABSOLUTE_ABICALLS \
- && !(mips_abi == ABI_64 && TARGET_IRIX))
+ && !(mips_abi == ABI_64 && TARGET_IRIX6))
+
+/* True if the output must have a writable .eh_frame.
+ See ASM_PREFERRED_EH_DATA_FORMAT for details. */
+#ifdef HAVE_LD_PERSONALITY_RELAXATION
+#define TARGET_WRITABLE_EH_FRAME 0
+#else
+#define TARGET_WRITABLE_EH_FRAME (flag_pic && TARGET_SHARED)
+#endif
/* Generate mips16 code */
#define TARGET_MIPS16 ((target_flags & MASK_MIPS16) != 0)
#define TARGET_SYNC_AFTER_SC (!TARGET_OCTEON)
/* IRIX specific stuff. */
-#define TARGET_IRIX 0
#define TARGET_IRIX6 0
/* Define preprocessor macros for the -march and -mtune options.
do \
{ \
/* Everyone but IRIX defines this to mips. */ \
- if (!TARGET_IRIX) \
+ if (!TARGET_IRIX6) \
builtin_assert ("machine=mips"); \
\
builtin_assert ("cpu=mips"); \
if (TARGET_64BIT) \
builtin_define ("__mips64"); \
\
- if (!TARGET_IRIX) \
+ if (!TARGET_IRIX6) \
{ \
/* Treat _R3000 and _R4000 like register-size \
defines, which is how they've historically \
#define DWARF_FRAME_REGNUM(REGNO) mips_dwarf_regno[REGNO]
/* The DWARF 2 CFA column which tracks the return address. */
-#define DWARF_FRAME_RETURN_COLUMN (GP_REG_FIRST + 31)
+#define DWARF_FRAME_RETURN_COLUMN RETURN_ADDR_REGNUM
/* Before the prologue, RA lives in r31. */
-#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, GP_REG_FIRST + 31)
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, RETURN_ADDR_REGNUM)
/* Describe how we implement __builtin_eh_return. */
#define EH_RETURN_DATA_REGNO(N) \
#define INDEX_REG_CLASS NO_REGS
-/* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows
- registers explicitly used in the rtl to be used as spill registers
- but prevents the compiler from extending the lifetime of these
- registers. */
-
-#define SMALL_REGISTER_CLASSES (TARGET_MIPS16)
-
/* We generally want to put call-clobbered registers ahead of
call-saved ones. (IRA expects this.) */
182,183,184,185,186,187 \
}
-/* ORDER_REGS_FOR_LOCAL_ALLOC is a macro which permits reg_alloc_order
+/* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order
to be rearranged based on a particular function. On the mips16, we
want to allocate $24 (T_REG) before other registers for
instructions for which it is possible. */
-#define ORDER_REGS_FOR_LOCAL_ALLOC mips_order_regs_for_local_alloc ()
+#define ADJUST_REG_ALLOC_ORDER mips_order_regs_for_local_alloc ()
/* True if VALUE is an unsigned 6-bit number. */
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
-#define FUNCTION_PROFILER(FILE, LABELNO) \
-{ \
- if (TARGET_MIPS16) \
- sorry ("mips16 function profiling"); \
- if (TARGET_LONG_CALLS) \
- { \
- /* For TARGET_LONG_CALLS use $3 for the address of _mcount. */ \
- if (Pmode == DImode) \
- fprintf (FILE, "\tdla\t%s,_mcount\n", reg_names[GP_REG_FIRST + 3]); \
- else \
- fprintf (FILE, "\tla\t%s,_mcount\n", reg_names[GP_REG_FIRST + 3]); \
- } \
- mips_push_asm_switch (&mips_noat); \
- fprintf (FILE, "\tmove\t%s,%s\t\t# save current return address\n", \
- reg_names[GP_REG_FIRST + 1], reg_names[GP_REG_FIRST + 31]); \
- /* _mcount treats $2 as the static chain register. */ \
- if (cfun->static_chain_decl != NULL) \
- fprintf (FILE, "\tmove\t%s,%s\n", reg_names[2], \
- reg_names[STATIC_CHAIN_REGNUM]); \
- if (!TARGET_NEWABI) \
- { \
- fprintf (FILE, \
- "\t%s\t%s,%s,%d\t\t# _mcount pops 2 words from stack\n", \
- TARGET_64BIT ? "dsubu" : "subu", \
- reg_names[STACK_POINTER_REGNUM], \
- reg_names[STACK_POINTER_REGNUM], \
- Pmode == DImode ? 16 : 8); \
- } \
- if (TARGET_LONG_CALLS) \
- fprintf (FILE, "\tjalr\t%s\n", reg_names[GP_REG_FIRST + 3]); \
- else \
- fprintf (FILE, "\tjal\t_mcount\n"); \
- mips_pop_asm_switch (&mips_noat); \
- /* _mcount treats $2 as the static chain register. */ \
- if (cfun->static_chain_decl != NULL) \
- fprintf (FILE, "\tmove\t%s,%s\n", reg_names[STATIC_CHAIN_REGNUM], \
- reg_names[2]); \
-}
+#define FUNCTION_PROFILER(FILE, LABELNO) mips_function_profiler ((FILE))
/* The profiler preserves all interesting registers, including $31. */
#define MIPS_SAVE_REG_FOR_PROFILING_P(REGNO) false
#define EXIT_IGNORE_STACK 1
\f
-/* A C statement to output, on the stream FILE, assembler code for a
- block of data that contains the constant parts of a trampoline.
- This code should not include a label--the label is taken care of
- automatically. */
+/* Trampolines are a block of code followed by two pointers. */
-#define TRAMPOLINE_TEMPLATE(STREAM) \
-{ \
- if (ptr_mode == DImode) \
- fprintf (STREAM, "\t.word\t0x03e0082d\t\t# dmove $1,$31\n"); \
- else \
- fprintf (STREAM, "\t.word\t0x03e00821\t\t# move $1,$31\n"); \
- fprintf (STREAM, "\t.word\t0x04110001\t\t# bgezal $0,.+8\n"); \
- fprintf (STREAM, "\t.word\t0x00000000\t\t# nop\n"); \
- if (ptr_mode == DImode) \
- { \
- fprintf (STREAM, "\t.word\t0xdff90014\t\t# ld $25,20($31)\n"); \
- fprintf (STREAM, "\t.word\t0xdfef001c\t\t# ld $15,28($31)\n"); \
- } \
- else \
- { \
- fprintf (STREAM, "\t.word\t0x8ff90010\t\t# lw $25,16($31)\n"); \
- fprintf (STREAM, "\t.word\t0x8fef0014\t\t# lw $15,20($31)\n"); \
- } \
- fprintf (STREAM, "\t.word\t0x03200008\t\t# jr $25\n"); \
- if (ptr_mode == DImode) \
- { \
- fprintf (STREAM, "\t.word\t0x0020f82d\t\t# dmove $31,$1\n"); \
- fprintf (STREAM, "\t.word\t0x00000000\t\t# <padding>\n"); \
- fprintf (STREAM, "\t.dword\t0x00000000\t\t# <function address>\n"); \
- fprintf (STREAM, "\t.dword\t0x00000000\t\t# <static chain value>\n"); \
- } \
- else \
- { \
- fprintf (STREAM, "\t.word\t0x0020f821\t\t# move $31,$1\n"); \
- fprintf (STREAM, "\t.word\t0x00000000\t\t# <function address>\n"); \
- fprintf (STREAM, "\t.word\t0x00000000\t\t# <static chain value>\n"); \
- } \
-}
-
-/* A C expression for the size in bytes of the trampoline, as an
- integer. */
+#define TRAMPOLINE_SIZE \
+ (mips_trampoline_code_size () + GET_MODE_SIZE (ptr_mode) * 2)
-#define TRAMPOLINE_SIZE (ptr_mode == DImode ? 48 : 36)
+/* Forcing a 64-bit alignment for 32-bit targets allows us to load two
+ pointers from a single LUI base. */
-/* Alignment required for trampolines, in bits. */
+#define TRAMPOLINE_ALIGNMENT 64
-#define TRAMPOLINE_ALIGNMENT GET_MODE_BITSIZE (ptr_mode)
-
-/* INITIALIZE_TRAMPOLINE calls this library function to flush
+/* mips_trampoline_init calls this library function to flush
program and data caches. */
#ifndef CACHE_FLUSH_FUNC
LCT_NORMAL, VOIDmode, 3, ADDR, Pmode, SIZE, Pmode, \
GEN_INT (3), TYPE_MODE (integer_type_node))
-/* A C statement to initialize the variable parts of a trampoline.
- ADDR is an RTX for the address of the trampoline; FNADDR is an
- RTX for the address of the nested function; STATIC_CHAIN is an
- RTX for the static chain value that should be passed to the
- function when it is called. */
-
-#define INITIALIZE_TRAMPOLINE(ADDR, FUNC, CHAIN) \
-{ \
- rtx func_addr, chain_addr, end_addr; \
- \
- func_addr = plus_constant (ADDR, ptr_mode == DImode ? 32 : 28); \
- chain_addr = plus_constant (func_addr, GET_MODE_SIZE (ptr_mode)); \
- mips_emit_move (gen_rtx_MEM (ptr_mode, func_addr), FUNC); \
- mips_emit_move (gen_rtx_MEM (ptr_mode, chain_addr), CHAIN); \
- end_addr = gen_reg_rtx (Pmode); \
- emit_insn (gen_add3_insn (end_addr, copy_rtx (ADDR), \
- GEN_INT (TRAMPOLINE_SIZE))); \
- emit_insn (gen_clear_cache (copy_rtx (ADDR), end_addr)); \
-}
\f
/* Addressing modes, and classification of registers for them. */
: INSN)
/* Return the asm template for a call. INSN is the instruction's mnemonic
- ("j" or "jal"), OPERANDS are its operands, and OPNO is the operand number
- of the target.
+ ("j" or "jal"), OPERANDS are its operands, TARGET_OPNO is the operand
+ number of the target. SIZE_OPNO is the operand number of the argument size
+ operand that can optionally hold the call attributes. If SIZE_OPNO is not
+ -1 and the call is indirect, use the function symbol from the call
+ attributes to attach a R_MIPS_JALR relocation to the call.
When generating GOT code without explicit relocation operators,
all calls should use assembly macros. Otherwise, all indirect
calls should use "jr" or "jalr"; we will arrange to restore $gp
afterwards if necessary. Finally, we can only generate direct
calls for -mabicalls by temporarily switching to non-PIC mode. */
-#define MIPS_CALL(INSN, OPERANDS, OPNO) \
+#define MIPS_CALL(INSN, OPERANDS, TARGET_OPNO, SIZE_OPNO) \
(TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS \
- ? "%*" INSN "\t%" #OPNO "%/" \
- : REG_P (OPERANDS[OPNO]) \
- ? "%*" INSN "r\t%" #OPNO "%/" \
- : MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #OPNO "%/"))
+ ? "%*" INSN "\t%" #TARGET_OPNO "%/" \
+ : (REG_P (OPERANDS[TARGET_OPNO]) \
+ && mips_get_pic_call_symbol (OPERANDS, SIZE_OPNO)) \
+ ? ("%*.reloc\t1f,R_MIPS_JALR,%" #SIZE_OPNO "\n" \
+ "1:\t" INSN "r\t%" #TARGET_OPNO "%/") \
+ : REG_P (OPERANDS[TARGET_OPNO]) \
+ ? "%*" INSN "r\t%" #TARGET_OPNO "%/" \
+ : MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #TARGET_OPNO "%/"))
\f
/* Control the assembler format that we output. */
/* This is necessary to avoid a warning about comparing different enum
types. */
#define mips_tune_attr ((enum attr_cpu) mips_tune)
+
+/* As on most targets, we want the .eh_frame section to be read-only where
+ possible. And as on most targets, this means two things:
+
+ (a) Non-locally-binding pointers must have an indirect encoding,
+ so that the addresses in the .eh_frame section itself become
+ locally-binding.
+
+ (b) A shared library's .eh_frame section must encode locally-binding
+ pointers in a relative (relocation-free) form.
+
+ However, MIPS has traditionally not allowed directives like:
+
+ .long x-.
+
+ in cases where "x" is in a different section, or is not defined in the
+ same assembly file. We are therefore unable to emit the PC-relative
+ form required by (b) at assembly time.
+
+ Fortunately, the linker is able to convert absolute addresses into
+ PC-relative addresses on our behalf. Unfortunately, only certain
+ versions of the linker know how to do this for indirect pointers,
+ and for personality data. We must fall back on using writable
+ .eh_frame sections for shared libraries if the linker does not
+ support this feature. */
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+ (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_absptr)