/* 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
+ 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).
#include "config/vxworks-dummy.h"
-/* MIPS external variables defined in mips.c. */
-
-/* Which processor to schedule for. Since there is no difference between
- a R2000 and R3000 in terms of the scheduler, we collapse them into
- just an R3000. The elements of the enumeration must match exactly
- the cpu attribute in the mips.md machine description. */
-
-enum processor_type {
- PROCESSOR_R3000,
- PROCESSOR_4KC,
- PROCESSOR_4KP,
- PROCESSOR_5KC,
- PROCESSOR_5KF,
- PROCESSOR_20KC,
- PROCESSOR_24KC,
- PROCESSOR_24KF2_1,
- PROCESSOR_24KF1_1,
- PROCESSOR_74KC,
- PROCESSOR_74KF2_1,
- PROCESSOR_74KF1_1,
- PROCESSOR_74KF3_2,
- PROCESSOR_LOONGSON_2E,
- PROCESSOR_LOONGSON_2F,
- PROCESSOR_M4K,
- PROCESSOR_OCTEON,
- PROCESSOR_R3900,
- PROCESSOR_R6000,
- PROCESSOR_R4000,
- PROCESSOR_R4100,
- PROCESSOR_R4111,
- PROCESSOR_R4120,
- PROCESSOR_R4130,
- PROCESSOR_R4300,
- PROCESSOR_R4600,
- PROCESSOR_R4650,
- PROCESSOR_R5000,
- PROCESSOR_R5400,
- PROCESSOR_R5500,
- PROCESSOR_R7000,
- PROCESSOR_R8000,
- PROCESSOR_R9000,
- PROCESSOR_SB1,
- PROCESSOR_SB1A,
- PROCESSOR_SR71000,
- PROCESSOR_XLR,
- PROCESSOR_MAX
-};
-
-/* Costs of various operations on the different architectures. */
+#ifdef GENERATOR_FILE
+/* This is used in some insn conditions, so needs to be declared, but
+ does not need to be defined. */
+extern int target_flags_explicit;
+#endif
-struct mips_rtx_cost_data
-{
- unsigned short fp_add;
- unsigned short fp_mult_sf;
- unsigned short fp_mult_df;
- unsigned short fp_div_sf;
- unsigned short fp_div_df;
- unsigned short int_mult_si;
- unsigned short int_mult_di;
- unsigned short int_div_si;
- unsigned short int_div_di;
- unsigned short branch_cost;
- unsigned short memory_latency;
-};
+/* MIPS external variables defined in mips.c. */
/* Which ABI to use. ABI_32 (original 32, or o32), ABI_N32 (n32),
ABI_64 (n64) are all defined by SGI. ABI_O64 is o32 extended
/* The internal processor number that most closely matches this
entry. Several processors can have the same value, if there's no
difference between them from GCC's point of view. */
- enum processor_type cpu;
+ enum processor cpu;
/* The ISA level that the processor implements. */
int isa;
/* True if the call patterns should be split into a jalr followed by
an instruction to restore $gp. It is only safe to split the load
- from the call when every use of $gp is explicit. */
+ from the call when every use of $gp is explicit.
+
+ See mips_must_initialize_gp_p for details about how we manage the
+ global pointer. */
#define TARGET_SPLIT_CALLS \
- (TARGET_EXPLICIT_RELOCS && TARGET_CALL_CLOBBERED_GP)
+ (TARGET_EXPLICIT_RELOCS && TARGET_CALL_CLOBBERED_GP && epilogue_completed)
/* True if we're generating a form of -mabicalls in which we can use
operators like %hi and %lo to refer to locally-binding symbols.
/* True if TARGET_USE_GOT and if $gp is a call-saved register. */
#define TARGET_CALL_SAVED_GP (TARGET_USE_GOT && !TARGET_CALL_CLOBBERED_GP)
+/* True if we should use .cprestore to store to the cprestore slot.
+
+ We continue to use .cprestore for explicit-reloc code so that JALs
+ inside inline asms will work correctly. */
+#define TARGET_CPRESTORE_DIRECTIVE \
+ (TARGET_ABICALLS_PIC2 && !TARGET_MIPS16)
+
+/* True if we can use the J and JAL instructions. */
+#define TARGET_ABSOLUTE_JUMPS \
+ (!flag_pic || TARGET_ABSOLUTE_ABICALLS)
+
/* True if indirect calls must use register class PIC_FN_ADDR_REG.
This is true for both the PIC and non-PIC VxWorks RTP modes. */
#define TARGET_USE_PIC_FN_ADDR_REG (TARGET_ABICALLS || TARGET_VXWORKS_RTP)
#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)
in use. */
#define TARGET_HARD_FLOAT (TARGET_HARD_FLOAT_ABI && !TARGET_MIPS16)
#define TARGET_SOFT_FLOAT (TARGET_SOFT_FLOAT_ABI || TARGET_MIPS16)
-
+
+/* False if SC acts as a memory barrier with respect to itself,
+ otherwise a SYNC will be emitted after SC for atomic operations
+ that require ordering between the SC and following loads and
+ stores. It does not tell anything about ordering of loads and
+ stores prior to and following the SC, only about the SC itself and
+ those loads and stores follow it. */
+#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 \
\
/* These defines reflect the ABI in use, not whether the \
FPU is directly accessible. */ \
- if (TARGET_HARD_FLOAT_ABI) \
+ if (TARGET_NO_FLOAT) \
+ builtin_define ("__mips_no_float"); \
+ else if (TARGET_HARD_FLOAT_ABI) \
builtin_define ("__mips_hard_float"); \
else \
builtin_define ("__mips_soft_float"); \
builtin_define ("_MIPSEL"); \
} \
\
+ /* Whether calls should go through $25. The separate __PIC__ \
+ macro indicates whether abicalls code might use a GOT. */ \
+ if (TARGET_ABICALLS) \
+ builtin_define ("__mips_abicalls"); \
+ \
/* Whether Loongson vector modes are enabled. */ \
if (TARGET_LOONGSON_VECTORS) \
builtin_define ("__mips_loongson_vector_rev"); \
# endif
#endif
+#ifndef MIPS_ABI_DEFAULT
+#define MIPS_ABI_DEFAULT ABI_32
+#endif
+
+/* Use the most portable ABI flag for the ASM specs. */
+
+#if MIPS_ABI_DEFAULT == ABI_32
+#define MULTILIB_ABI_DEFAULT "mabi=32"
+#endif
+
+#if MIPS_ABI_DEFAULT == ABI_O64
+#define MULTILIB_ABI_DEFAULT "mabi=o64"
+#endif
+
+#if MIPS_ABI_DEFAULT == ABI_N32
+#define MULTILIB_ABI_DEFAULT "mabi=n32"
+#endif
+
+#if MIPS_ABI_DEFAULT == ABI_64
+#define MULTILIB_ABI_DEFAULT "mabi=64"
+#endif
+
+#if MIPS_ABI_DEFAULT == ABI_EABI
+#define MULTILIB_ABI_DEFAULT "mabi=eabi"
+#endif
+
#ifndef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS \
{ MULTILIB_ENDIAN_DEFAULT, MULTILIB_ISA_DEFAULT, MULTILIB_ABI_DEFAULT }
%{march=mips1|march=r2000|march=r3000|march=r3900:-mips1} \
%{march=mips2|march=r6000:-mips2} \
%{march=mips3|march=r4*|march=vr4*|march=orion|march=loongson2*:-mips3} \
- %{march=mips4|march=r8000|march=vr5*|march=rm7000|march=rm9000:-mips4} \
+ %{march=mips4|march=r8000|march=vr5*|march=rm7000|march=rm9000 \
+ |march=r10000|march=r12000|march=r14000|march=r16000:-mips4} \
%{march=mips32|march=4kc|march=4km|march=4kp|march=4ksc:-mips32} \
%{march=mips32r2|march=m4k|march=4ke*|march=4ksd|march=24k* \
- |march=34k*|march=74k*: -mips32r2} \
- %{march=mips64|march=5k*|march=20k*|march=sb1*|march=sr71000: -mips64} \
+ |march=34k*|march=74k*|march=1004k*: -mips32r2} \
+ %{march=mips64|march=5k*|march=20k*|march=sb1*|march=sr71000 \
+ |march=xlr: -mips64} \
%{march=mips64r2|march=octeon: -mips64r2} \
%{!march=*: -" MULTILIB_ISA_DEFAULT "}}"
#define MIPS_ARCH_FLOAT_SPEC \
"%{mhard-float|msoft-float|march=mips*:; \
march=vr41*|march=m4k|march=4k*|march=24kc|march=24kec \
- |march=34kc|march=74kc|march=5kc|march=octeon: -msoft-float; \
+ |march=34kc|march=74kc|march=1004kc|march=5kc \
+ |march=octeon|march=xlr: -msoft-float; \
march=*: -mhard-float}"
/* A spec condition that matches 32-bit options. It only works if
#define MIPS_32BIT_OPTION_SPEC \
"mips1|mips2|mips32*|mgp32"
+#if MIPS_ABI_DEFAULT == ABI_O64 \
+ || MIPS_ABI_DEFAULT == ABI_N32 \
+ || MIPS_ABI_DEFAULT == ABI_64
+#define OPT_ARCH64 "mabi=32|mgp32:;"
+#define OPT_ARCH32 "mabi=32|mgp32"
+#else
+#define OPT_ARCH64 "mabi=o64|mabi=n32|mabi=64|mgp64"
+#define OPT_ARCH32 "mabi=o64|mabi=n32|mabi=64|mgp64:;"
+#endif
+
/* Support for a compile-time default CPU, et cetera. The rules are:
--with-arch is ignored if -march is specified or a -mips is specified
- (other than -mips16).
- --with-tune is ignored if -mtune is specified.
+ (other than -mips16); likewise --with-arch-32 and --with-arch-64.
+ --with-tune is ignored if -mtune is specified; likewise
+ --with-tune-32 and --with-tune-64.
--with-abi is ignored if -mabi is specified.
--with-float is ignored if -mhard-float or -msoft-float are
specified.
specified. */
#define OPTION_DEFAULT_SPECS \
{"arch", "%{" MIPS_ARCH_OPTION_SPEC ":;: -march=%(VALUE)}" }, \
+ {"arch_32", "%{" OPT_ARCH32 ":%{" MIPS_ARCH_OPTION_SPEC ":;: -march=%(VALUE)}}" }, \
+ {"arch_64", "%{" OPT_ARCH64 ":%{" MIPS_ARCH_OPTION_SPEC ":;: -march=%(VALUE)}}" }, \
{"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \
+ {"tune_32", "%{" OPT_ARCH32 ":%{!mtune=*:-mtune=%(VALUE)}}" }, \
+ {"tune_64", "%{" OPT_ARCH64 ":%{!mtune=*:-mtune=%(VALUE)}}" }, \
{"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
{"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" }, \
{"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }, \
{"llsc", "%{!mllsc:%{!mno-llsc:-m%(VALUE)}}" }, \
- {"mips-plt", "%{!mplt:%{!mno-plt:-m%(VALUE)}}" }
+ {"mips-plt", "%{!mplt:%{!mno-plt:-m%(VALUE)}}" }, \
+ {"synci", "%{!msynci:%{!mno-synci:-m%(VALUE)}}" }
+
+
+/* A spec that infers the -mdsp setting from an -march argument. */
+#define BASE_DRIVER_SELF_SPECS \
+ "%{!mno-dsp: \
+ %{march=24ke*|march=34k*|march=1004k*: -mdsp} \
+ %{march=74k*:%{!mno-dspr2: -mdspr2 -mdsp}}}"
+#define DRIVER_SELF_SPECS BASE_DRIVER_SELF_SPECS
#define GENERATE_DIVIDE_TRAPS (TARGET_DIVIDE_TRAPS \
&& ISA_HAS_COND_TRAP)
/* Likewise for 32-bit regs. */
#define ABI_NEEDS_32BIT_REGS (mips_abi == ABI_32)
-/* True if symbols are 64 bits wide. At present, n64 is the only
- ABI for which this is true. */
-#define ABI_HAS_64BIT_SYMBOLS (mips_abi == ABI_64 && !TARGET_SYM32)
+/* True if the file format uses 64-bit symbols. At present, this is
+ only true for n64, which uses 64-bit ELF. */
+#define FILE_HAS_64BIT_SYMBOLS (mips_abi == ABI_64)
+
+/* True if symbols are 64 bits wide. This is usually determined by
+ the ABI's file format, but it can be overridden by -msym32. Note that
+ overriding the size with -msym32 changes the ABI of relocatable objects,
+ although it doesn't change the ABI of a fully-linked object. */
+#define ABI_HAS_64BIT_SYMBOLS (FILE_HAS_64BIT_SYMBOLS && !TARGET_SYM32)
/* ISA has instructions for managing 64-bit fp and gp regs (e.g. mips3). */
#define ISA_HAS_64BIT_REGS (ISA_MIPS3 \
&& !TARGET_MIPS16)
/* ISA has a three-operand multiplication instruction. */
-#define ISA_HAS_DMUL3 (TARGET_64BIT && TARGET_OCTEON)
+#define ISA_HAS_DMUL3 (TARGET_64BIT \
+ && TARGET_OCTEON \
+ && !TARGET_MIPS16)
/* ISA has the floating-point conditional move instructions introduced
in mips4. */
/* ISA has data prefetch instructions. This controls use of 'pref'. */
#define ISA_HAS_PREFETCH ((ISA_MIPS4 \
+ || TARGET_LOONGSON_2EF \
|| ISA_MIPS32 \
|| ISA_MIPS32R2 \
|| ISA_MIPS64 \
: ISA_HAS_LL_SC)
/* ISA includes the baddu instruction. */
-#define ISA_HAS_BADDU TARGET_OCTEON
+#define ISA_HAS_BADDU (TARGET_OCTEON && !TARGET_MIPS16)
/* ISA includes the bbit* instructions. */
-#define ISA_HAS_BBIT TARGET_OCTEON
+#define ISA_HAS_BBIT (TARGET_OCTEON && !TARGET_MIPS16)
/* ISA includes the cins instruction. */
-#define ISA_HAS_CINS TARGET_OCTEON
+#define ISA_HAS_CINS (TARGET_OCTEON && !TARGET_MIPS16)
/* ISA includes the exts instruction. */
-#define ISA_HAS_EXTS TARGET_OCTEON
+#define ISA_HAS_EXTS (TARGET_OCTEON && !TARGET_MIPS16)
/* ISA includes the seq and sne instructions. */
-#define ISA_HAS_SEQ_SNE TARGET_OCTEON
+#define ISA_HAS_SEQ_SNE (TARGET_OCTEON && !TARGET_MIPS16)
/* ISA includes the pop instruction. */
-#define ISA_HAS_POP TARGET_OCTEON
+#define ISA_HAS_POP (TARGET_OCTEON && !TARGET_MIPS16)
/* The CACHE instruction is available in non-MIPS16 code. */
#define TARGET_CACHE_BUILTIN (mips_isa >= 3)
#define SWITCH_TAKES_ARG(CHAR) \
(DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G')
-#define OVERRIDE_OPTIONS mips_override_options ()
-
#define CONDITIONAL_REGISTER_USAGE mips_conditional_register_usage ()
-
-/* Show we can debug even without a frame pointer. */
-#define CAN_DEBUG_WITHOUT_FP
\f
/* Tell collect what flags to pass to nm. */
#ifndef NM_FLAGS
#endif
\f
-#ifndef MIPS_ABI_DEFAULT
-#define MIPS_ABI_DEFAULT ABI_32
-#endif
-
-/* Use the most portable ABI flag for the ASM specs. */
-
-#if MIPS_ABI_DEFAULT == ABI_32
-#define MULTILIB_ABI_DEFAULT "mabi=32"
-#endif
-
-#if MIPS_ABI_DEFAULT == ABI_O64
-#define MULTILIB_ABI_DEFAULT "mabi=o64"
-#endif
-
-#if MIPS_ABI_DEFAULT == ABI_N32
-#define MULTILIB_ABI_DEFAULT "mabi=n32"
-#endif
-
-#if MIPS_ABI_DEFAULT == ABI_64
-#define MULTILIB_ABI_DEFAULT "mabi=64"
-#endif
-
-#if MIPS_ABI_DEFAULT == ABI_EABI
-#define MULTILIB_ABI_DEFAULT "mabi=eabi"
-#endif
-
/* SUBTARGET_ASM_OPTIMIZING_SPEC handles passing optimization options
to the assembler. It may be overridden by subtargets. */
#ifndef SUBTARGET_ASM_OPTIMIZING_SPEC
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
#endif
-#define DWARF2_ADDR_SIZE (ABI_HAS_64BIT_SYMBOLS ? 8 : 4)
+/* The size of DWARF addresses should be the same as the size of symbols
+ in the target file format. They shouldn't depend on things like -msym32,
+ because many DWARF consumers do not allow the mixture of address sizes
+ that one would then get from linking -msym32 code with -msym64 code.
+
+ Note that the default POINTER_SIZE test is not appropriate for MIPS.
+ EABI64 has 64-bit pointers but uses 32-bit ELF. */
+#define DWARF2_ADDR_SIZE (FILE_HAS_64BIT_SYMBOLS ? 8 : 4)
/* By default, turn on GDB extensions. */
#define DEFAULT_GDB_EXTENSIONS 1
#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 EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_REG_FIRST + 3)
+#define EH_USES(N) mips_eh_uses (N)
+
/* Offsets recorded in opcodes are a multiple of this alignment factor.
The default for this in 64-bit mode is 8, which causes problems with
SFmode register saves. */
#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
-/* Define this to set the endianness to use in libgcc2.c, which can
- not depend on target_flags. */
-#if !defined(MIPSEL) && !defined(__MIPSEL__)
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
#define MAX_BITS_PER_WORD 64
/* Width of a word, in units (bytes). */
/* The number of bytes in a double. */
#define UNITS_PER_DOUBLE (TYPE_PRECISION (double_type_node) / BITS_PER_UNIT)
-#define UNITS_PER_SIMD_WORD(MODE) \
- (TARGET_PAIRED_SINGLE_FLOAT ? 8 : UNITS_PER_WORD)
-
/* Set the sizes of the core types. */
#define SHORT_TYPE_SIZE 16
#define INT_TYPE_SIZE 32
- 8 condition code registers
- 2 accumulator registers (hi and lo)
- 32 registers each for coprocessors 0, 2 and 3
- - 3 fake registers:
+ - 4 fake registers:
- ARG_POINTER_REGNUM
- FRAME_POINTER_REGNUM
- GOT_VERSION_REGNUM (see the comment above load_call<mode> for details)
- - 3 dummy entries that were used at various times in the past.
+ - CPRESTORE_SLOT_REGNUM
+ - 2 dummy entries that were used at various times in the past.
- 6 DSP accumulator registers (3 hi-lo pairs) for MIPS DSP ASE
- 6 DSP control registers */
Regarding coprocessor registers: without evidence to the contrary,
it's best to assume that each coprocessor register has a unique
- use. This can be overridden, in, e.g., mips_override_options or
+ use. This can be overridden, in, e.g., mips_option_override or
CONDITIONAL_REGISTER_USAGE should the assumption be inappropriate
for a particular target. */
#define GP_REG_LAST 31
#define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1)
#define GP_DBX_FIRST 0
+#define K0_REG_NUM (GP_REG_FIRST + 26)
+#define K1_REG_NUM (GP_REG_FIRST + 27)
+#define KERNEL_REG_P(REGNO) (IN_RANGE (REGNO, K0_REG_NUM, K1_REG_NUM))
#define FP_REG_FIRST 32
#define FP_REG_LAST 63
#define COP0_REG_LAST 111
#define COP0_REG_NUM (COP0_REG_LAST - COP0_REG_FIRST + 1)
+#define COP0_STATUS_REG_NUM (COP0_REG_FIRST + 12)
+#define COP0_CAUSE_REG_NUM (COP0_REG_FIRST + 13)
+#define COP0_EPC_REG_NUM (COP0_REG_FIRST + 14)
+
#define COP2_REG_FIRST 112
#define COP2_REG_LAST 143
#define COP2_REG_NUM (COP2_REG_LAST - COP2_REG_FIRST + 1)
#define HI_REGNUM (TARGET_BIG_ENDIAN ? MD_REG_FIRST : MD_REG_FIRST + 1)
#define LO_REGNUM (TARGET_BIG_ENDIAN ? MD_REG_FIRST + 1 : MD_REG_FIRST)
+/* A few bitfield locations for the coprocessor registers. */
+/* Request Interrupt Priority Level is from bit 10 to bit 15 of
+ the cause register for the EIC interrupt mode. */
+#define CAUSE_IPL 10
+/* Interrupt Priority Level is from bit 10 to bit 15 of the status register. */
+#define SR_IPL 10
+/* Exception Level is at bit 1 of the status register. */
+#define SR_EXL 1
+/* Interrupt Enable is at bit 0 of the status register. */
+#define SR_IE 0
+
/* FPSW_REGNUM is the single condition code used if !ISA_HAS_8CC.
If ISA_HAS_8CC, it should not be used, and an arbitrary ST_REG
should be used instead. */
#define HARD_FRAME_POINTER_REGNUM \
(TARGET_MIPS16 ? GP_REG_FIRST + 17 : GP_REG_FIRST + 30)
-#define FRAME_POINTER_REQUIRED (mips_frame_pointer_required ())
+#define HARD_FRAME_POINTER_IS_FRAME_POINTER 0
+#define HARD_FRAME_POINTER_IS_ARG_POINTER 0
/* Register in which static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM (GP_REG_FIRST + 15)
incoming arguments, the static chain pointer, or the frame pointer.
The epilogue temporary mustn't conflict with the return registers,
the PIC call register ($25), the frame pointer, the EH stack adjustment,
- or the EH data registers. */
+ or the EH data registers.
+
+ If we're generating interrupt handlers, we use K0 as a temporary register
+ in prologue/epilogue code. */
#define MIPS16_PIC_TEMP_REGNUM (GP_REG_FIRST + 2)
-#define MIPS_PROLOGUE_TEMP_REGNUM (GP_REG_FIRST + 3)
-#define MIPS_EPILOGUE_TEMP_REGNUM (GP_REG_FIRST + (TARGET_MIPS16 ? 6 : 8))
+#define MIPS_PROLOGUE_TEMP_REGNUM \
+ (cfun->machine->interrupt_handler_p ? K0_REG_NUM : GP_REG_FIRST + 3)
+#define MIPS_EPILOGUE_TEMP_REGNUM \
+ (cfun->machine->interrupt_handler_p \
+ ? K0_REG_NUM \
+ : GP_REG_FIRST + (TARGET_MIPS16 ? 6 : 8))
#define MIPS16_PIC_TEMP gen_rtx_REG (Pmode, MIPS16_PIC_TEMP_REGNUM)
#define MIPS_PROLOGUE_TEMP(MODE) gen_rtx_REG (MODE, MIPS_PROLOGUE_TEMP_REGNUM)
COP0_REGS, /* generic coprocessor classes */
COP2_REGS,
COP3_REGS,
- HI_AND_GR_REGS, /* union classes */
- LO_AND_GR_REGS,
- HI_AND_FP_REGS,
- COP0_AND_GR_REGS,
- COP2_AND_GR_REGS,
- COP3_AND_GR_REGS,
- ALL_COP_REGS,
- ALL_COP_AND_GR_REGS,
ST_REGS, /* status registers (fp status) */
DSP_ACC_REGS, /* DSP accumulator registers */
ACC_REGS, /* Hi/Lo and DSP accumulator registers */
FRAME_REGS, /* $arg and $frame */
+ GR_AND_MD0_REGS, /* union classes */
+ GR_AND_MD1_REGS,
+ GR_AND_MD_REGS,
+ GR_AND_ACC_REGS,
ALL_REGS, /* all registers */
LIM_REG_CLASSES /* max value + 1 */
};
"COP0_REGS", \
"COP2_REGS", \
"COP3_REGS", \
- "HI_AND_GR_REGS", \
- "LO_AND_GR_REGS", \
- "HI_AND_FP_REGS", \
- "COP0_AND_GR_REGS", \
- "COP2_AND_GR_REGS", \
- "COP3_AND_GR_REGS", \
- "ALL_COP_REGS", \
- "ALL_COP_AND_GR_REGS", \
"ST_REGS", \
"DSP_ACC_REGS", \
"ACC_REGS", \
"FRAME_REGS", \
+ "GR_AND_MD0_REGS", \
+ "GR_AND_MD1_REGS", \
+ "GR_AND_MD_REGS", \
+ "GR_AND_ACC_REGS", \
"ALL_REGS" \
}
#define REG_CLASS_CONTENTS \
{ \
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* no registers */ \
- { 0x000300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 registers */ \
- { 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 T register */ \
- { 0x010300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 and T regs */ \
- { 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* SVR4 PIC function address register */ \
- { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* only $v1 */ \
- { 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* Every other GPR except $25 */ \
- { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* integer registers */ \
- { 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* floating registers*/ \
- { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 }, /* hi register */ \
- { 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000 }, /* lo register */ \
- { 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000 }, /* mul/div registers */ \
- { 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000, 0x00000000 }, /* cop0 registers */ \
- { 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000 }, /* cop2 registers */ \
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff }, /* cop3 registers */ \
- { 0xffffffff, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 }, /* union classes */ \
- { 0xffffffff, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000 }, \
- { 0x00000000, 0xffffffff, 0x00000001, 0x00000000, 0x00000000, 0x00000000 }, \
- { 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000, 0x00000000 }, \
- { 0xffffffff, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000 }, \
- { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff }, \
- { 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x0000ffff }, \
- { 0xffffffff, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x0000ffff }, \
- { 0x00000000, 0x00000000, 0x000007f8, 0x00000000, 0x00000000, 0x00000000 }, /* status registers */ \
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x003f0000 }, /* dsp accumulator registers */ \
- { 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x003f0000 }, /* hi/lo and dsp accumulator registers */ \
- { 0x00000000, 0x00000000, 0x00006000, 0x00000000, 0x00000000, 0x00000000 }, /* frame registers */ \
- { 0xffffffff, 0xffffffff, 0xffff67ff, 0xffffffff, 0xffffffff, 0x0fffffff } /* all registers */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
+ { 0x000300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* M16_REGS */ \
+ { 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* T_REG */ \
+ { 0x010300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* M16_T_REGS */ \
+ { 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* PIC_FN_ADDR_REG */ \
+ { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* V1_REG */ \
+ { 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* LEA_REGS */ \
+ { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* GR_REGS */ \
+ { 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* FP_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 }, /* MD0_REG */ \
+ { 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000 }, /* MD1_REG */ \
+ { 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000 }, /* MD_REGS */ \
+ { 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000, 0x00000000 }, /* COP0_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000 }, /* COP2_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff }, /* COP3_REGS */ \
+ { 0x00000000, 0x00000000, 0x000007f8, 0x00000000, 0x00000000, 0x00000000 }, /* ST_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x003f0000 }, /* DSP_ACC_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x003f0000 }, /* ACC_REGS */ \
+ { 0x00000000, 0x00000000, 0x00006000, 0x00000000, 0x00000000, 0x00000000 }, /* FRAME_REGS */ \
+ { 0xffffffff, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 }, /* GR_AND_MD0_REGS */ \
+ { 0xffffffff, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000 }, /* GR_AND_MD1_REGS */ \
+ { 0xffffffff, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000 }, /* GR_AND_MD_REGS */ \
+ { 0xffffffff, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x003f0000 }, /* GR_AND_ACC_REGS */ \
+ { 0xffffffff, 0xffffffff, 0xffff67ff, 0xffffffff, 0xffffffff, 0x0fffffff } /* ALL_REGS */ \
}
#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)
-
-/* REG_ALLOC_ORDER is to order in which to allocate registers. This
- is the default value (allocate the registers in numeric order). We
- define it just so that we can override it for the mips16 target in
- ORDER_REGS_FOR_LOCAL_ALLOC. */
+/* We generally want to put call-clobbered registers ahead of
+ call-saved ones. (IRA expects this.) */
#define REG_ALLOC_ORDER \
-{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, \
+{ /* Accumulator registers. When GPRs and accumulators have equal \
+ cost, we generally prefer to use accumulators. For example, \
+ a division of multiplication result is better allocated to LO, \
+ so that we put the MFLO at the point of use instead of at the \
+ point of definition. It's also needed if we're to take advantage \
+ of the extra accumulators available with -mdspr2. In some cases, \
+ it can also help to reduce register pressure. */ \
+ 64, 65,176,177,178,179,180,181, \
+ /* Call-clobbered GPRs. */ \
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \
+ 24, 25, 31, \
+ /* The global pointer. This is call-clobbered for o32 and o64 \
+ abicalls, call-saved for n32 and n64 abicalls, and a program \
+ invariant otherwise. Putting it between the call-clobbered \
+ and call-saved registers should cope with all eventualities. */ \
+ 28, \
+ /* Call-saved GPRs. */ \
+ 16, 17, 18, 19, 20, 21, 22, 23, 30, \
+ /* GPRs that can never be exposed to the register allocator. */ \
+ 0, 26, 27, 29, \
+ /* Call-clobbered FPRs. */ \
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \
+ 48, 49, 50, 51, \
+ /* FPRs that are usually call-saved. The odd ones are actually \
+ call-clobbered for n32, but listing them ahead of the even \
+ registers might encourage the register allocator to fragment \
+ the available FPR pairs. We need paired FPRs to store long \
+ doubles, so it isn't clear that using a different order \
+ for n32 would be a win. */ \
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \
+ /* None of the remaining classes have defined call-saved \
+ registers. */ \
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, \
96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111, \
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, \
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, \
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, \
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, \
- 176,177,178,179,180,181,182,183,184,185,186,187 \
+ 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. */
#define STACK_GROWS_DOWNWARD
-/* The offset of the first local variable from the beginning of the frame.
- See mips_compute_frame_info for details about the frame layout. */
+#define FRAME_GROWS_DOWNWARD flag_stack_protect
+
+/* Size of the area allocated in the frame to save the GP. */
+
+#define MIPS_GP_SAVE_AREA_SIZE \
+ (TARGET_CALL_CLOBBERED_GP ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0)
-#define STARTING_FRAME_OFFSET \
- (crtl->outgoing_args_size \
- + (TARGET_CALL_CLOBBERED_GP ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0))
+/* The offset of the first local variable from the frame pointer. See
+ mips_compute_frame_info for details about the frame layout. */
+
+#define STARTING_FRAME_OFFSET \
+ (FRAME_GROWS_DOWNWARD \
+ ? 0 \
+ : crtl->outgoing_args_size + MIPS_GP_SAVE_AREA_SIZE)
#define RETURN_ADDR_RTX mips_return_addr
{ FRAME_POINTER_REGNUM, GP_REG_FIRST + 30}, \
{ FRAME_POINTER_REGNUM, GP_REG_FIRST + 17}}
-/* Make sure that we're not trying to eliminate to the wrong hard frame
- pointer. */
-#define CAN_ELIMINATE(FROM, TO) \
- ((TO) == HARD_FRAME_POINTER_REGNUM || (TO) == STACK_POINTER_REGNUM)
-
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
(OFFSET) = mips_initial_elimination_offset ((FROM), (TO))
#define STACK_BOUNDARY (TARGET_NEWABI ? 128 : 64)
\f
-#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
-
/* Symbolic macros for the registers used to return integer and floating
point values. */
#define FP_ARG_LAST (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
#define LIBCALL_VALUE(MODE) \
- mips_function_value (NULL_TREE, MODE)
+ mips_function_value (NULL_TREE, NULL_TREE, MODE)
#define FUNCTION_VALUE(VALTYPE, FUNC) \
- mips_function_value (VALTYPE, VOIDmode)
+ mips_function_value (VALTYPE, FUNC, VOIDmode)
/* 1 if N is a possible register number for a function value.
On the MIPS, R2 R3 and F0 F2 are the only register thus used.
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
mips_init_cumulative_args (&CUM, FNTYPE)
-/* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be available.) */
-
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- mips_function_arg_advance (&CUM, MODE, TYPE, NAMED)
-
-/* Determine where to put an argument to a function.
- Value is zero to push the argument on the stack,
- or a hard register in which to store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis). */
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- mips_function_arg (&CUM, MODE, TYPE, NAMED)
-
#define FUNCTION_ARG_BOUNDARY mips_function_arg_boundary
#define FUNCTION_ARG_PADDING(MODE, TYPE) \
(mips_abi == ABI_EABI && UNITS_PER_FPVALUE >= UNITS_PER_DOUBLE)
\f
-/* Say that the epilogue uses the return address register. Note that
- in the case of sibcalls, the values "used by the epilogue" are
- considered live at the start of the called function.
-
- If using a GOT, say that the epilogue also uses GOT_VERSION_REGNUM.
- See the comment above load_call<mode> for details. */
-#define EPILOGUE_USES(REGNO) \
- ((REGNO) == 31 || (TARGET_USE_GOT && (REGNO) == GOT_VERSION_REGNUM))
+#define EPILOGUE_USES(REGNO) mips_epilogue_uses (REGNO)
/* Treat LOC as a byte offset from the stack pointer and round it up
to the next fully-aligned offset. */
/* 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]); \
- } \
- fprintf (FILE, "\t.set\tnoat\n"); \
- 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"); \
- fprintf (FILE, "\t.set\tat\n"); \
- /* _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 (ptr_mode == DImode ? 48 : 36)
+#define TRAMPOLINE_SIZE \
+ (mips_trampoline_code_size () + GET_MODE_SIZE (ptr_mode) * 2)
-/* Alignment required for trampolines, in bits. */
+/* Forcing a 64-bit alignment for 32-bit targets allows us to load two
+ pointers from a single LUI base. */
-#define TRAMPOLINE_ALIGNMENT GET_MODE_BITSIZE (ptr_mode)
+#define TRAMPOLINE_ALIGNMENT 64
-/* 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
/* Flush both caches. We need to flush the data cache in case \
the system has a write-back cache. */ \
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mips_cache_flush_func), \
- 0, VOIDmode, 3, ADDR, Pmode, SIZE, Pmode, \
+ 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. */
#define MAX_REGS_PER_ADDRESS 1
-#ifdef REG_OK_STRICT
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ \
- if (mips_legitimate_address_p (MODE, X, 1)) \
- goto ADDR; \
-}
-#else
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ \
- if (mips_legitimate_address_p (MODE, X, 0)) \
- goto ADDR; \
-}
-#endif
-
/* Check for constness inline but use mips_legitimate_address_p
to check whether a constant really is an address. */
#define CONSTANT_ADDRESS_P(X) \
- (CONSTANT_P (X) && mips_legitimate_address_p (SImode, X, 0))
+ (CONSTANT_P (X) && memory_address_p (SImode, X))
#define LEGITIMATE_CONSTANT_P(X) (mips_const_insns (X) > 0)
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
- do { \
- if (mips_legitimize_address (&(X), MODE)) \
- goto WIN; \
- } while (0)
-
-
-/* A C statement or compound statement with a conditional `goto
- LABEL;' executed if memory address X (an RTX) can have different
- meanings depending on the machine mode of the memory reference it
- is used for.
-
- Autoincrement and autodecrement addresses typically have
- mode-dependent effects because the amount of the increment or
- decrement is the size of the operand being addressed. Some
- machines have other mode-dependent addresses. Many RISC machines
- have no mode-dependent addresses.
-
- You may assume that ADDR is a valid address for the machine. */
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {}
-
/* This handles the magic '..CURRENT_FUNCTION' symbol, which means
'the start of the function that this code is output in'. */
(often extended) would be needed for byte accesses. */
#define SLOW_BYTE_ACCESS (!TARGET_MIPS16)
-/* Define this to be nonzero if shift instructions ignore all but the low-order
- few bits. */
-#define SHIFT_COUNT_TRUNCATED 1
+/* Standard MIPS integer shifts truncate the shift amount to the
+ width of the shifted operand. However, Loongson vector shifts
+ do not truncate the shift amount at all. */
+#define SHIFT_COUNT_TRUNCATED (!TARGET_LOONGSON_2EF)
/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
is done just by pretending it is already truncated. */
#define FUNCTION_MODE SImode
\f
-/* A C expression for the cost of moving data from a register in
- class FROM to one in class TO. The classes are expressed using
- the enumeration values such as `GENERAL_REGS'. A value of 2 is
- the default; other values are interpreted relative to that.
-
- It is not required that the cost always equal 2 when FROM is the
- same as TO; on some machines it is expensive to move between
- registers if they are not general registers.
-
- If reload sees an insn consisting of a single `set' between two
- hard registers, and if `REGISTER_MOVE_COST' applied to their
- classes returns a value of 2, reload does not check to ensure
- that the constraints of the insn are met. Setting a cost of
- other than 2 will allow reload to verify that the constraints are
- met. You should do this if the `movM' pattern's constraints do
- not allow such copying. */
-
-#define REGISTER_MOVE_COST(MODE, FROM, TO) \
- mips_register_move_cost (MODE, FROM, TO)
-
-#define MEMORY_MOVE_COST(MODE,CLASS,TO_P) \
- (mips_cost->memory_latency \
- + memory_move_secondary_cost ((MODE), (CLASS), (TO_P)))
/* Define if copies to/from condition code registers should be avoided.
#define MIPS_BRANCH(OPCODE, OPERANDS) \
"%*" OPCODE "%?\t" OPERANDS "%/"
+/* Return an asm string that forces INSN to be treated as an absolute
+ J or JAL instruction instead of an assembler macro. */
+#define MIPS_ABSOLUTE_JUMP(INSN) \
+ (TARGET_ABICALLS_PIC2 \
+ ? ".option\tpic0\n\t" INSN "\n\t.option\tpic2" \
+ : 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 "%/" \
- : TARGET_ABICALLS_PIC2 \
- ? (".option\tpic0\n\t" \
- "%*" INSN "\t%" #OPNO "%/\n\t" \
- ".option\tpic2") \
- : "%*" 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. */
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", \
"$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", \
"hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4", \
- "$fcc5","$fcc6","$fcc7","", "", "$arg", "$frame", "$fakec", \
+ "$fcc5","$fcc6","$fcc7","", "$cprestore", "$arg", "$frame", "$fakec", \
"$c0r0", "$c0r1", "$c0r2", "$c0r3", "$c0r4", "$c0r5", "$c0r6", "$c0r7", \
"$c0r8", "$c0r9", "$c0r10","$c0r11","$c0r12","$c0r13","$c0r14","$c0r15", \
"$c0r16","$c0r17","$c0r18","$c0r19","$c0r20","$c0r21","$c0r22","$c0r23", \
#define ALL_COP_ADDITIONAL_REGISTER_NAMES
-#define PRINT_OPERAND mips_print_operand
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) mips_print_operand_punct[CODE]
-#define PRINT_OPERAND_ADDRESS mips_print_operand_address
-
-/* A C statement, to be executed after all slot-filler instructions
- have been output. If necessary, call `dbr_sequence_length' to
- determine the number of slots filled in a sequence (zero if not
- currently outputting a sequence), to decide how many no-ops to
- output, or whatever.
-
- Don't define this macro if it has nothing to do, but it is
- helpful in reading assembly output if the extent of the delay
- sequence is made explicit (e.g. with white space).
-
- Note that output routines for instructions with delay slots must
- be prepared to deal with not being output as part of a sequence
- (i.e. when the scheduling pass is not run, or when no slot
- fillers could be found.) The variable `final_sequence' is null
- when not processing a sequence, otherwise it contains the
- `sequence' rtx being output. */
-
#define DBR_OUTPUT_SEQEND(STREAM) \
do \
{ \
- if (set_nomacro > 0 && --set_nomacro == 0) \
- fputs ("\t.set\tmacro\n", STREAM); \
- \
- if (set_noreorder > 0 && --set_noreorder == 0) \
- fputs ("\t.set\treorder\n", STREAM); \
- \
+ /* Undo the effect of '%*'. */ \
+ mips_pop_asm_switch (&mips_nomacro); \
+ mips_pop_asm_switch (&mips_noreorder); \
+ /* Emit a blank line after the delay slot for emphasis. */ \
fputs ("\n", STREAM); \
} \
while (0)
-/* How to tell the debugger about changes of source files. */
-#define ASM_OUTPUT_SOURCE_FILENAME mips_output_filename
-
/* mips-tfile does not understand .stabd directives. */
#define DBX_OUTPUT_SOURCE_LINE(STREAM, LINE, COUNTER) do { \
dbxout_begin_stabn_sline (LINE); \
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
sprintf ((LABEL), "*%s%s%ld", (LOCAL_LABEL_PREFIX), (PREFIX), (long)(NUM))
+/* Print debug labels as "foo = ." rather than "foo:" because they should
+ represent a byte pointer rather than an ISA-encoded address. This is
+ particularly important for code like:
+
+ $LFBxxx = .
+ .cfi_startproc
+ ...
+ .section .gcc_except_table,...
+ ...
+ .uleb128 foo-$LFBxxx
+
+ The .uleb128 requies $LFBxxx to match the FDE start address, which is
+ likewise a byte pointer rather than an ISA-encoded address.
+
+ At the time of writing, this hook is not used for the function end
+ label:
+
+ $LFExxx:
+ .end foo
+
+ But this doesn't matter, because GAS doesn't treat a pre-.end label
+ as a MIPS16 one anyway. */
+
+#define ASM_OUTPUT_DEBUG_LABEL(FILE, PREFIX, NUM) \
+ fprintf (FILE, "%s%s%d = .\n", LOCAL_LABEL_PREFIX, PREFIX, NUM)
+
/* This is how to output an element of a case-vector that is absolute. */
#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \
do \
{ \
- if (! set_noreorder) \
- fprintf (STREAM, "\t.set\tnoreorder\n"); \
- \
+ mips_push_asm_switch (&mips_noreorder); \
fprintf (STREAM, "\t%s\t%s,0(%s)\n\t%s\t%s,%s,8\n", \
TARGET_64BIT ? "ld" : "lw", \
reg_names[REGNO], \
TARGET_64BIT ? "daddu" : "addu", \
reg_names[STACK_POINTER_REGNUM], \
reg_names[STACK_POINTER_REGNUM]); \
- \
- if (! set_noreorder) \
- fprintf (STREAM, "\t.set\treorder\n"); \
+ mips_pop_asm_switch (&mips_noreorder); \
} \
while (0)
#define HAVE_AS_TLS 0
#endif
-/* Return an asm string that atomically:
-
- - Compares memory reference %1 to register %2 and, if they are
- equal, changes %1 to %3.
-
- - Sets register %0 to the old value of memory reference %1.
-
- SUFFIX is the suffix that should be added to "ll" and "sc" instructions
- and OP is the instruction that should be used to load %3 into a
- register. */
-#define MIPS_COMPARE_AND_SWAP(SUFFIX, OP) \
- "%(%<%[%|sync\n" \
- "1:\tll" SUFFIX "\t%0,%1\n" \
- "\tbne\t%0,%z2,2f\n" \
- "\t" OP "\t%@,%3\n" \
- "\tsc" SUFFIX "\t%@,%1\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\tnop\n" \
- "\tsync%-%]%>%)\n" \
- "2:\n"
-
-/* Return an asm string that atomically:
-
- - Given that %2 contains a bit mask and %3 the inverted mask and
- that %4 and %5 have already been ANDed with %2.
-
- - Compares the bits in memory reference %1 selected by mask %2 to
- register %4 and, if they are equal, changes the selected bits
- in memory to %5.
-
- - Sets register %0 to the old value of memory reference %1.
-
- OPS are the instructions needed to OR %5 with %@. */
-#define MIPS_COMPARE_AND_SWAP_12(OPS) \
- "%(%<%[%|sync\n" \
- "1:\tll\t%0,%1\n" \
- "\tand\t%@,%0,%2\n" \
- "\tbne\t%@,%z4,2f\n" \
- "\tand\t%@,%0,%3\n" \
- OPS \
- "\tsc\t%@,%1\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\tnop\n" \
- "\tsync%-%]%>%)\n" \
- "2:\n"
-
-#define MIPS_COMPARE_AND_SWAP_12_ZERO_OP ""
-#define MIPS_COMPARE_AND_SWAP_12_NONZERO_OP "\tor\t%@,%@,%5\n"
-
-
-/* Return an asm string that atomically:
-
- - Sets memory reference %0 to %0 INSN %1.
-
- SUFFIX is the suffix that should be added to "ll" and "sc"
- instructions. */
-#define MIPS_SYNC_OP(SUFFIX, INSN) \
- "%(%<%[%|sync\n" \
- "1:\tll" SUFFIX "\t%@,%0\n" \
- "\t" INSN "\t%@,%@,%1\n" \
- "\tsc" SUFFIX "\t%@,%0\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\tnop\n" \
- "\tsync%-%]%>%)"
-
-/* Return an asm string that atomically:
-
- - Given that %1 contains a bit mask and %2 the inverted mask and
- that %3 has already been ANDed with %1.
-
- - Sets the selected bits of memory reference %0 to %0 INSN %3.
-
- - Uses scratch register %4.
-
- NOT_OP are the optional instructions to do a bit-wise not
- operation in conjunction with an AND INSN to generate a sync_nand
- operation. */
-#define MIPS_SYNC_OP_12(INSN, NOT_OP) \
- "%(%<%[%|sync\n" \
- "1:\tll\t%4,%0\n" \
- "\tand\t%@,%4,%2\n" \
- NOT_OP \
- "\t" INSN "\t%4,%4,%z3\n" \
- "\tand\t%4,%4,%1\n" \
- "\tor\t%@,%@,%4\n" \
- "\tsc\t%@,%0\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\tnop\n" \
- "\tsync%-%]%>%)"
-
-#define MIPS_SYNC_OP_12_NOT_NOP ""
-#define MIPS_SYNC_OP_12_NOT_NOT "\tnor\t%4,%4,%.\n"
-
-/* Return an asm string that atomically:
-
- - Given that %2 contains a bit mask and %3 the inverted mask and
- that %4 has already been ANDed with %2.
-
- - Sets the selected bits of memory reference %1 to %1 INSN %4.
-
- - Sets %0 to the original value of %1.
-
- - Uses scratch register %5.
-
- NOT_OP are the optional instructions to do a bit-wise not
- operation in conjunction with an AND INSN to generate a sync_nand
- operation.
-
- REG is used in conjunction with NOT_OP and is used to select the
- register operated on by the INSN. */
-#define MIPS_SYNC_OLD_OP_12(INSN, NOT_OP, REG) \
- "%(%<%[%|sync\n" \
- "1:\tll\t%0,%1\n" \
- "\tand\t%@,%0,%3\n" \
- NOT_OP \
- "\t" INSN "\t%5," REG ",%z4\n" \
- "\tand\t%5,%5,%2\n" \
- "\tor\t%@,%@,%5\n" \
- "\tsc\t%@,%1\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\tnop\n" \
- "\tsync%-%]%>%)"
-
-#define MIPS_SYNC_OLD_OP_12_NOT_NOP ""
-#define MIPS_SYNC_OLD_OP_12_NOT_NOP_REG "%0"
-#define MIPS_SYNC_OLD_OP_12_NOT_NOT "\tnor\t%5,%0,%.\n"
-#define MIPS_SYNC_OLD_OP_12_NOT_NOT_REG "%5"
-
-/* Return an asm string that atomically:
-
- - Given that %2 contains a bit mask and %3 the inverted mask and
- that %4 has already been ANDed with %2.
-
- - Sets the selected bits of memory reference %1 to %1 INSN %4.
-
- - Sets %0 to the new value of %1.
-
- NOT_OP are the optional instructions to do a bit-wise not
- operation in conjunction with an AND INSN to generate a sync_nand
- operation. */
-#define MIPS_SYNC_NEW_OP_12(INSN, NOT_OP) \
- "%(%<%[%|sync\n" \
- "1:\tll\t%0,%1\n" \
- "\tand\t%@,%0,%3\n" \
- NOT_OP \
- "\t" INSN "\t%0,%0,%z4\n" \
- "\tand\t%0,%0,%2\n" \
- "\tor\t%@,%@,%0\n" \
- "\tsc\t%@,%1\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\tnop\n" \
- "\tsync%-%]%>%)"
-
-#define MIPS_SYNC_NEW_OP_12_NOT_NOP ""
-#define MIPS_SYNC_NEW_OP_12_NOT_NOT "\tnor\t%0,%0,%.\n"
-
-/* Return an asm string that atomically:
-
- - Sets memory reference %1 to %1 INSN %2.
-
- - Sets register %0 to the old value of memory reference %1.
-
- SUFFIX is the suffix that should be added to "ll" and "sc"
- instructions. */
-#define MIPS_SYNC_OLD_OP(SUFFIX, INSN) \
- "%(%<%[%|sync\n" \
- "1:\tll" SUFFIX "\t%0,%1\n" \
- "\t" INSN "\t%@,%0,%2\n" \
- "\tsc" SUFFIX "\t%@,%1\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\tnop\n" \
- "\tsync%-%]%>%)"
-
-/* Return an asm string that atomically:
-
- - Sets memory reference %1 to %1 INSN %2.
-
- - Sets register %0 to the new value of memory reference %1.
+#ifndef USED_FOR_TARGET
+/* Information about ".set noFOO; ...; .set FOO" blocks. */
+struct mips_asm_switch {
+ /* The FOO in the description above. */
+ const char *name;
- SUFFIX is the suffix that should be added to "ll" and "sc"
- instructions. */
-#define MIPS_SYNC_NEW_OP(SUFFIX, INSN) \
- "%(%<%[%|sync\n" \
- "1:\tll" SUFFIX "\t%0,%1\n" \
- "\t" INSN "\t%@,%0,%2\n" \
- "\tsc" SUFFIX "\t%@,%1\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\t" INSN "\t%0,%0,%2\n" \
- "\tsync%-%]%>%)"
-
-/* Return an asm string that atomically:
-
- - Sets memory reference %0 to ~%0 AND %1.
-
- SUFFIX is the suffix that should be added to "ll" and "sc"
- instructions. INSN is the and instruction needed to and a register
- with %2. */
-#define MIPS_SYNC_NAND(SUFFIX, INSN) \
- "%(%<%[%|sync\n" \
- "1:\tll" SUFFIX "\t%@,%0\n" \
- "\tnor\t%@,%@,%.\n" \
- "\t" INSN "\t%@,%@,%1\n" \
- "\tsc" SUFFIX "\t%@,%0\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\tnop\n" \
- "\tsync%-%]%>%)"
-
-/* Return an asm string that atomically:
-
- - Sets memory reference %1 to ~%1 AND %2.
-
- - Sets register %0 to the old value of memory reference %1.
-
- SUFFIX is the suffix that should be added to "ll" and "sc"
- instructions. INSN is the and instruction needed to and a register
- with %2. */
-#define MIPS_SYNC_OLD_NAND(SUFFIX, INSN) \
- "%(%<%[%|sync\n" \
- "1:\tll" SUFFIX "\t%0,%1\n" \
- "\tnor\t%@,%0,%.\n" \
- "\t" INSN "\t%@,%@,%2\n" \
- "\tsc" SUFFIX "\t%@,%1\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\tnop\n" \
- "\tsync%-%]%>%)"
-
-/* Return an asm string that atomically:
-
- - Sets memory reference %1 to ~%1 AND %2.
-
- - Sets register %0 to the new value of memory reference %1.
-
- SUFFIX is the suffix that should be added to "ll" and "sc"
- instructions. INSN is the and instruction needed to and a register
- with %2. */
-#define MIPS_SYNC_NEW_NAND(SUFFIX, INSN) \
- "%(%<%[%|sync\n" \
- "1:\tll" SUFFIX "\t%0,%1\n" \
- "\tnor\t%0,%0,%.\n" \
- "\t" INSN "\t%@,%0,%2\n" \
- "\tsc" SUFFIX "\t%@,%1\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\t" INSN "\t%0,%0,%2\n" \
- "\tsync%-%]%>%)"
-
-/* Return an asm string that atomically:
-
- - Sets memory reference %1 to %2.
-
- - Sets register %0 to the old value of memory reference %1.
-
- SUFFIX is the suffix that should be added to "ll" and "sc"
- instructions. OP is the and instruction that should be used to
- load %2 into a register. */
-#define MIPS_SYNC_EXCHANGE(SUFFIX, OP) \
- "%(%<%[%|\n" \
- "1:\tll" SUFFIX "\t%0,%1\n" \
- "\t" OP "\t%@,%2\n" \
- "\tsc" SUFFIX "\t%@,%1\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\tnop\n" \
- "\tsync%-%]%>%)"
-
-/* Return an asm string that atomically:
-
- - Given that %2 contains an inclusive mask, %3 and exclusive mask
- and %4 has already been ANDed with the inclusive mask.
-
- - Sets bits selected by the inclusive mask of memory reference %1
- to %4.
-
- - Sets register %0 to the old value of memory reference %1.
-
- OPS are the instructions needed to OR %4 with %@.
-
- Operand %2 is unused, but needed as to give the test_and_set_12
- insn the five operands expected by the expander. */
-#define MIPS_SYNC_EXCHANGE_12(OPS) \
- "%(%<%[%|\n" \
- "1:\tll\t%0,%1\n" \
- "\tand\t%@,%0,%3\n" \
- OPS \
- "\tsc\t%@,%1\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\tnop\n" \
- "\tsync%-%]%>%)"
-
-#define MIPS_SYNC_EXCHANGE_12_ZERO_OP ""
-#define MIPS_SYNC_EXCHANGE_12_NONZERO_OP "\tor\t%@,%@,%4\n"
+ /* The current block nesting level, or 0 if we aren't in a block. */
+ int nesting_level;
+};
-#ifndef USED_FOR_TARGET
extern const enum reg_class mips_regno_to_class[];
extern bool mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
-extern bool mips_print_operand_punct[256];
extern const char *current_function_file; /* filename current function is in */
extern int num_source_filenames; /* current .file # */
-extern int set_noreorder; /* # of nested .set noreorder's */
-extern int set_nomacro; /* # of nested .set nomacro's */
+extern struct mips_asm_switch mips_noreorder;
+extern struct mips_asm_switch mips_nomacro;
+extern struct mips_asm_switch mips_noat;
extern int mips_dbx_regno[];
extern int mips_dwarf_regno[];
extern bool mips_split_p[];
extern bool mips_split_hi_p[];
-extern GTY(()) rtx cmp_operands[2];
-extern enum processor_type mips_arch; /* which cpu to codegen for */
-extern enum processor_type mips_tune; /* which cpu to schedule for */
+extern enum processor mips_arch; /* which cpu to codegen for */
+extern enum processor mips_tune; /* which cpu to schedule for */
extern int mips_isa; /* architectural level */
extern int mips_abi; /* which ABI to use */
extern const struct mips_cpu_info *mips_arch_info;
extern const struct mips_cpu_info *mips_tune_info;
-extern const struct mips_rtx_cost_data *mips_cost;
extern bool mips_base_mips16;
extern enum mips_code_readable_setting mips_code_readable;
+extern GTY(()) struct target_globals *mips16_globals;
#endif
/* Enable querying of DFA units. */
#define CPU_UNITS_QUERY 1
+
+#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
+ mips_final_prescan_insn (INSN, OPVEC, NOPERANDS)
+
+/* 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)
+
+/* For switching between MIPS16 and non-MIPS16 modes. */
+#define SWITCHABLE_TARGET 1