X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fconfig%2Fmips%2Fmips.h;h=55e240e5217ee91445a98f56211f97cf3547d2ae;hp=ca534bf3ff63c89141c2f1e9e11b54504863c00d;hb=ffdabaafdbbe46147f72c7240a87e73dfd8e0825;hpb=13c6ca886d3b443645abaa6f2be3ba029c783367 diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index ca534bf3ff6..55e240e5217 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1,6 +1,6 @@ /* 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 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc. Contributed by A. Lichnewsky (lich@inria.inria.fr). Changed by Michael Meissner (meissner@osf.org). @@ -47,7 +47,10 @@ enum processor_type { 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, @@ -67,6 +70,7 @@ enum processor_type { PROCESSOR_SB1, PROCESSOR_SB1A, PROCESSOR_SR71000, + PROCESSOR_XLR, PROCESSOR_MAX }; @@ -97,6 +101,14 @@ struct mips_rtx_cost_data #define ABI_EABI 3 #define ABI_O64 4 +/* Masks that affect tuning. + + PTF_AVOID_BRANCHLIKELY + Set if it is usually not profitable to use branch-likely instructions + for this target, typically because the branches are always predicted + taken and so incur a large overhead when not taken. */ +#define PTF_AVOID_BRANCHLIKELY 0x1 + /* Information about one recognized processor. Defined here for the benefit of TARGET_CPU_CPP_BUILTINS. */ struct mips_cpu_info { @@ -112,6 +124,9 @@ struct mips_cpu_info { /* The ISA level that the processor implements. */ int isa; + + /* A mask of PTF_* values. */ + unsigned int tune_flags; }; /* Enumerates the setting of the -mcode-readable option. */ @@ -121,32 +136,6 @@ enum mips_code_readable_setting { CODE_READABLE_YES }; -#ifndef USED_FOR_TARGET -extern char mips_print_operand_punct[256]; /* print_operand punctuation chars */ -extern const char *current_function_file; /* filename current function is in */ -extern int num_source_filenames; /* current .file # */ -extern int mips_section_threshold; /* # bytes of data/sdata cutoff */ -extern int sym_lineno; /* sgi next label # for each stmt */ -extern int set_noreorder; /* # of nested .set noreorder's */ -extern int set_nomacro; /* # of nested .set nomacro's */ -extern int set_noat; /* # of nested .set noat's */ -extern int set_volatile; /* # of nested .set volatile's */ -extern int mips_branch_likely; /* emit 'l' after br (branch likely) */ -extern int mips_dbx_regno[]; -extern int mips_dwarf_regno[]; -extern bool mips_split_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 int mips_isa; /* architectural level */ -extern int mips_abi; /* which ABI to use */ -extern const struct mips_cpu_info mips_cpu_info_table[]; -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 enum mips_code_readable_setting mips_code_readable; -#endif - /* Macros to silence warnings about numbers being signed in traditional C and unsigned in ISO C when compiled on 32-bit hosts. */ @@ -160,6 +149,15 @@ extern enum mips_code_readable_setting mips_code_readable; /* True if we are generating position-independent VxWorks RTP code. */ #define TARGET_RTP_PIC (TARGET_VXWORKS_RTP && flag_pic) +/* True if the output file is marked as ".abicalls; .option pic0" + (-call_nonpic). */ +#define TARGET_ABICALLS_PIC0 \ + (TARGET_ABSOLUTE_ABICALLS && TARGET_PLT) + +/* True if the output file is marked as ".abicalls; .option pic2" (-KPIC). */ +#define TARGET_ABICALLS_PIC2 \ + (TARGET_ABICALLS && !TARGET_ABICALLS_PIC0) + /* 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. */ @@ -212,11 +210,14 @@ extern enum mips_code_readable_setting mips_code_readable; Although GAS does understand .gpdword, the SGI linker mishandles the relocations GAS generates (R_MIPS_GPREL32 followed by R_MIPS_64). We therefore disable GP-relative switch tables for n64 on IRIX targets. */ -#define TARGET_GPWORD (TARGET_ABICALLS && !(mips_abi == ABI_64 && TARGET_IRIX)) +#define TARGET_GPWORD \ + (TARGET_ABICALLS \ + && !TARGET_ABSOLUTE_ABICALLS \ + && !(mips_abi == ABI_64 && TARGET_IRIX)) /* Generate mips16 code */ #define TARGET_MIPS16 ((target_flags & MASK_MIPS16) != 0) -/* Generate mips16e code. Default 16bit ASE for mips32/mips32r2/mips64 */ +/* Generate mips16e code. Default 16bit ASE for mips32* and mips64* */ #define GENERATE_MIPS16E (TARGET_MIPS16 && mips_isa >= 32) /* Generate mips16e register save/restore sequences. */ #define GENERATE_MIPS16E_SAVE_RESTORE (GENERATE_MIPS16E && mips_abi == ABI_32) @@ -239,8 +240,12 @@ extern enum mips_code_readable_setting mips_code_readable; #define ISA_MIPS32 (mips_isa == 32) #define ISA_MIPS32R2 (mips_isa == 33) #define ISA_MIPS64 (mips_isa == 64) +#define ISA_MIPS64R2 (mips_isa == 65) /* Architecture target defines. */ +#define TARGET_LOONGSON_2E (mips_arch == PROCESSOR_LOONGSON_2E) +#define TARGET_LOONGSON_2F (mips_arch == PROCESSOR_LOONGSON_2F) +#define TARGET_LOONGSON_2EF (TARGET_LOONGSON_2E || TARGET_LOONGSON_2F) #define TARGET_MIPS3900 (mips_arch == PROCESSOR_R3900) #define TARGET_MIPS4000 (mips_arch == PROCESSOR_R4000) #define TARGET_MIPS4120 (mips_arch == PROCESSOR_R4120) @@ -249,11 +254,22 @@ extern enum mips_code_readable_setting mips_code_readable; #define TARGET_MIPS5500 (mips_arch == PROCESSOR_R5500) #define TARGET_MIPS7000 (mips_arch == PROCESSOR_R7000) #define TARGET_MIPS9000 (mips_arch == PROCESSOR_R9000) +#define TARGET_OCTEON (mips_arch == PROCESSOR_OCTEON) #define TARGET_SB1 (mips_arch == PROCESSOR_SB1 \ || mips_arch == PROCESSOR_SB1A) #define TARGET_SR71K (mips_arch == PROCESSOR_SR71000) /* Scheduling target defines. */ +#define TUNE_20KC (mips_tune == PROCESSOR_20KC) +#define TUNE_24K (mips_tune == PROCESSOR_24KC \ + || mips_tune == PROCESSOR_24KF2_1 \ + || mips_tune == PROCESSOR_24KF1_1) +#define TUNE_74K (mips_tune == PROCESSOR_74KC \ + || mips_tune == PROCESSOR_74KF2_1 \ + || mips_tune == PROCESSOR_74KF1_1 \ + || mips_tune == PROCESSOR_74KF3_2) +#define TUNE_LOONGSON_2EF (mips_tune == PROCESSOR_LOONGSON_2E \ + || mips_tune == PROCESSOR_LOONGSON_2F) #define TUNE_MIPS3000 (mips_tune == PROCESSOR_R3000) #define TUNE_MIPS3900 (mips_tune == PROCESSOR_R3900) #define TUNE_MIPS4000 (mips_tune == PROCESSOR_R4000) @@ -265,16 +281,15 @@ extern enum mips_code_readable_setting mips_code_readable; #define TUNE_MIPS6000 (mips_tune == PROCESSOR_R6000) #define TUNE_MIPS7000 (mips_tune == PROCESSOR_R7000) #define TUNE_MIPS9000 (mips_tune == PROCESSOR_R9000) +#define TUNE_OCTEON (mips_tune == PROCESSOR_OCTEON) #define TUNE_SB1 (mips_tune == PROCESSOR_SB1 \ || mips_tune == PROCESSOR_SB1A) -#define TUNE_24K (mips_tune == PROCESSOR_24KC \ - || mips_tune == PROCESSOR_24KF2_1 \ - || mips_tune == PROCESSOR_24KF1_1) -#define TUNE_74K (mips_tune == PROCESSOR_74KC \ - || mips_tune == PROCESSOR_74KF2_1 \ - || mips_tune == PROCESSOR_74KF1_1 \ - || mips_tune == PROCESSOR_74KF3_2) -#define TUNE_20KC (mips_tune == PROCESSOR_20KC) + +/* Whether vector modes and intrinsics for ST Microelectronics + Loongson-2E/2F processors should be enabled. In o32 pairs of + floating-point registers provide 64-bit values. */ +#define TARGET_LOONGSON_VECTORS (TARGET_HARD_FLOAT_ABI \ + && TARGET_LOONGSON_2EF) /* True if the pre-reload scheduler should try to create chains of multiply-add or multiply-subtract instructions. For example, @@ -391,7 +406,7 @@ extern enum mips_code_readable_setting mips_code_readable; else \ builtin_define ("__mips_fpr=32"); \ \ - if (TARGET_MIPS16) \ + if (mips_base_mips16) \ builtin_define ("__mips16"); \ \ if (TARGET_MIPS3D) \ @@ -453,6 +468,12 @@ extern enum mips_code_readable_setting mips_code_readable; builtin_define ("__mips_isa_rev=1"); \ builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64"); \ } \ + else if (ISA_MIPS64R2) \ + { \ + builtin_define ("__mips=64"); \ + builtin_define ("__mips_isa_rev=2"); \ + builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64"); \ + } \ \ switch (mips_abi) \ { \ @@ -506,6 +527,14 @@ extern enum mips_code_readable_setting mips_code_readable; builtin_define_std ("MIPSEL"); \ builtin_define ("_MIPSEL"); \ } \ + \ + /* Whether Loongson vector modes are enabled. */ \ + if (TARGET_LOONGSON_VECTORS) \ + builtin_define ("__mips_loongson_vector_rev"); \ + \ + /* Historical Octeon macro. */ \ + if (TARGET_OCTEON) \ + builtin_define ("__OCTEON__"); \ \ /* Macros dependent on the C dialect. */ \ if (preprocessing_asm_p ()) \ @@ -535,6 +564,9 @@ extern enum mips_code_readable_setting mips_code_readable; \ if (mips_abi == ABI_EABI) \ builtin_define ("__mips_eabi"); \ + \ + if (TARGET_CACHE_BUILTIN) \ + builtin_define ("__GCC_HAVE_BUILTIN_MIPS_CACHE"); \ } \ while (0) @@ -573,6 +605,17 @@ extern enum mips_code_readable_setting mips_code_readable; #endif #endif /* IN_LIBGCC2 */ +/* Force the call stack unwinders in unwind.inc not to be MIPS16 code + when compiled with hardware floating point. This is because MIPS16 + code cannot save and restore the floating-point registers, which is + important if in a mixed MIPS16/non-MIPS16 environment. */ + +#ifdef IN_LIBGCC2 +#if __mips_hard_float +#define LIBGCC2_UNWIND_ATTRIBUTE __attribute__((__nomips16__)) +#endif +#endif /* IN_LIBGCC2 */ + #define TARGET_LIBGCC_SDATA_SECTION ".sdata" #ifndef MULTILIB_ENDIAN_DEFAULT @@ -605,7 +648,11 @@ extern enum mips_code_readable_setting mips_code_readable; # if MIPS_ISA_DEFAULT == 64 # define MULTILIB_ISA_DEFAULT "mips64" # else -# define MULTILIB_ISA_DEFAULT "mips1" +# if MIPS_ISA_DEFAULT == 65 +# define MULTILIB_ISA_DEFAULT "mips64r2" +# else +# define MULTILIB_ISA_DEFAULT "mips1" +# endif # endif # endif # endif @@ -650,12 +697,13 @@ extern enum mips_code_readable_setting mips_code_readable; "%{" MIPS_ISA_LEVEL_OPTION_SPEC ":;: \ %{march=mips1|march=r2000|march=r3000|march=r3900:-mips1} \ %{march=mips2|march=r6000:-mips2} \ - %{march=mips3|march=r4*|march=vr4*|march=orion:-mips3} \ + %{march=mips3|march=r4*|march=vr4*|march=orion|march=loongson2*:-mips3} \ %{march=mips4|march=r8000|march=vr5*|march=rm7000|march=rm9000:-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=mips64r2|march=octeon: -mips64r2} \ %{!march=*: -" MULTILIB_ISA_DEFAULT "}}" /* A spec that infers a -mhard-float or -msoft-float setting from an @@ -665,7 +713,7 @@ extern enum mips_code_readable_setting mips_code_readable; #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: -msoft-float; \ + |march=34kc|march=74kc|march=5kc|march=octeon: -msoft-float; \ march=*: -mhard-float}" /* A spec condition that matches 32-bit options. It only works if @@ -688,15 +736,15 @@ extern enum mips_code_readable_setting mips_code_readable; {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \ {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \ {"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" }, \ - {"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" } + {"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }, \ + {"llsc", "%{!mllsc:%{!mno-llsc:-m%(VALUE)}}" }, \ + {"mips-plt", "%{!mplt:%{!mno-plt:-m%(VALUE)}}" } #define GENERATE_DIVIDE_TRAPS (TARGET_DIVIDE_TRAPS \ && ISA_HAS_COND_TRAP) -#define GENERATE_BRANCHLIKELY (TARGET_BRANCHLIKELY \ - && !TARGET_SR71K \ - && !TARGET_MIPS16) +#define GENERATE_BRANCHLIKELY (TARGET_BRANCHLIKELY && !TARGET_MIPS16) /* True if the ABI can only work with 64-bit integer registers. We generally allow ad-hoc variations for TARGET_SINGLE_FLOAT, but @@ -713,7 +761,8 @@ extern enum mips_code_readable_setting mips_code_readable; /* ISA has instructions for managing 64-bit fp and gp regs (e.g. mips3). */ #define ISA_HAS_64BIT_REGS (ISA_MIPS3 \ || ISA_MIPS4 \ - || ISA_MIPS64) + || ISA_MIPS64 \ + || ISA_MIPS64R2) /* ISA has branch likely instructions (e.g. mips2). */ /* Disable branchlikely for tx39 until compare rewrite. They haven't @@ -729,32 +778,50 @@ extern enum mips_code_readable_setting mips_code_readable; || TARGET_MAD \ || ISA_MIPS32 \ || ISA_MIPS32R2 \ - || ISA_MIPS64) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS16) -/* ISA has the conditional move instructions introduced in mips4. */ -#define ISA_HAS_CONDMOVE ((ISA_MIPS4 \ +/* ISA has a three-operand multiplication instruction. */ +#define ISA_HAS_DMUL3 (TARGET_64BIT && TARGET_OCTEON) + +/* ISA has the floating-point conditional move instructions introduced + in mips4. */ +#define ISA_HAS_FP_CONDMOVE ((ISA_MIPS4 \ || ISA_MIPS32 \ || ISA_MIPS32R2 \ - || ISA_MIPS64) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS5500 \ && !TARGET_MIPS16) +/* ISA has the integer conditional move instructions introduced in mips4 and + ST Loongson 2E/2F. */ +#define ISA_HAS_CONDMOVE (ISA_HAS_FP_CONDMOVE || TARGET_LOONGSON_2EF) + +/* ISA has LDC1 and SDC1. */ +#define ISA_HAS_LDC1_SDC1 (!ISA_MIPS1 && !TARGET_MIPS16) + /* ISA has the mips4 FP condition code instructions: FP-compare to CC, branch on CC, and move (both FP and non-FP) on CC. */ #define ISA_HAS_8CC (ISA_MIPS4 \ || ISA_MIPS32 \ || ISA_MIPS32R2 \ - || ISA_MIPS64) + || ISA_MIPS64 \ + || ISA_MIPS64R2) /* This is a catch all for other mips4 instructions: indexed load, the FP madd and msub instructions, and the FP recip and recip sqrt instructions. */ #define ISA_HAS_FP4 ((ISA_MIPS4 \ || (ISA_MIPS32R2 && TARGET_FLOAT64) \ - || ISA_MIPS64) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS16) +/* ISA has paired-single instructions. */ +#define ISA_HAS_PAIRED_SINGLE (ISA_MIPS32R2 || ISA_MIPS64 || ISA_MIPS64R2) + /* ISA has conditional trap instructions. */ #define ISA_HAS_COND_TRAP (!ISA_MIPS1 \ && !TARGET_MIPS16) @@ -762,22 +829,39 @@ extern enum mips_code_readable_setting mips_code_readable; /* ISA has integer multiply-accumulate instructions, madd and msub. */ #define ISA_HAS_MADD_MSUB ((ISA_MIPS32 \ || ISA_MIPS32R2 \ - || ISA_MIPS64) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS16) /* Integer multiply-accumulate instructions should be generated. */ #define GENERATE_MADD_MSUB (ISA_HAS_MADD_MSUB && !TUNE_74K) -/* ISA has floating-point nmadd and nmsub instructions. */ -#define ISA_HAS_NMADD_NMSUB ((ISA_MIPS4 \ - || ISA_MIPS64) \ +/* ISA has floating-point madd and msub instructions 'd = a * b [+-] c'. */ +#define ISA_HAS_FP_MADD4_MSUB4 ISA_HAS_FP4 + +/* ISA has floating-point madd and msub instructions 'c = a * b [+-] c'. */ +#define ISA_HAS_FP_MADD3_MSUB3 TARGET_LOONGSON_2EF + +/* ISA has floating-point nmadd and nmsub instructions + 'd = -((a * b) [+-] c)'. */ +#define ISA_HAS_NMADD4_NMSUB4(MODE) \ + ((ISA_MIPS4 \ + || (ISA_MIPS32R2 && (MODE) == V2SFmode) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && (!TARGET_MIPS5400 || TARGET_MAD) \ && !TARGET_MIPS16) +/* ISA has floating-point nmadd and nmsub instructions + 'c = -((a * b) [+-] c)'. */ +#define ISA_HAS_NMADD3_NMSUB3(MODE) \ + TARGET_LOONGSON_2EF + /* ISA has count leading zeroes/ones instruction (not implemented). */ #define ISA_HAS_CLZ_CLO ((ISA_MIPS32 \ || ISA_MIPS32R2 \ - || ISA_MIPS64) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS16) /* ISA has three operand multiply instructions that put @@ -817,6 +901,7 @@ extern enum mips_code_readable_setting mips_code_readable; /* ISA has the "ror" (rotate right) instructions. */ #define ISA_HAS_ROR ((ISA_MIPS32R2 \ + || ISA_MIPS64R2 \ || TARGET_MIPS5400 \ || TARGET_MIPS5500 \ || TARGET_SR71K \ @@ -827,7 +912,8 @@ extern enum mips_code_readable_setting mips_code_readable; #define ISA_HAS_PREFETCH ((ISA_MIPS4 \ || ISA_MIPS32 \ || ISA_MIPS32R2 \ - || ISA_MIPS64) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS16) /* ISA has data indexed prefetch instructions. This controls use of @@ -836,7 +922,8 @@ extern enum mips_code_readable_setting mips_code_readable; enabled.) */ #define ISA_HAS_PREFETCHX ((ISA_MIPS4 \ || ISA_MIPS32R2 \ - || ISA_MIPS64) \ + || ISA_MIPS64 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS16) /* True if trunc.w.s and trunc.w.d are real (not synthetic) @@ -845,19 +932,29 @@ extern enum mips_code_readable_setting mips_code_readable; #define ISA_HAS_TRUNC_W (!ISA_MIPS1) /* ISA includes the MIPS32r2 seb and seh instructions. */ -#define ISA_HAS_SEB_SEH (ISA_MIPS32R2 \ +#define ISA_HAS_SEB_SEH ((ISA_MIPS32R2 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS16) /* ISA includes the MIPS32/64 rev 2 ext and ins instructions. */ -#define ISA_HAS_EXT_INS (ISA_MIPS32R2 \ +#define ISA_HAS_EXT_INS ((ISA_MIPS32R2 \ + || ISA_MIPS64R2) \ && !TARGET_MIPS16) /* ISA has instructions for accessing top part of 64-bit fp regs. */ -#define ISA_HAS_MXHC1 (TARGET_FLOAT64 && ISA_MIPS32R2) +#define ISA_HAS_MXHC1 (TARGET_FLOAT64 \ + && (ISA_MIPS32R2 \ + || ISA_MIPS64R2)) /* ISA has lwxs instruction (load w/scaled index address. */ #define ISA_HAS_LWXS (TARGET_SMARTMIPS && !TARGET_MIPS16) +/* The DSP ASE is available. */ +#define ISA_HAS_DSP (TARGET_DSP && !TARGET_MIPS16) + +/* Revision 2 of the DSP ASE is available. */ +#define ISA_HAS_DSPR2 (TARGET_DSPR2 && !TARGET_MIPS16) + /* True if the result of a load is not available to the next instruction. A nop will then be needed between instructions like "lw $4,..." and "addiu $4,$4,1". */ @@ -866,10 +963,12 @@ extern enum mips_code_readable_setting mips_code_readable; && !TARGET_MIPS16) /* Likewise mtc1 and mfc1. */ -#define ISA_HAS_XFER_DELAY (mips_isa <= 3) +#define ISA_HAS_XFER_DELAY (mips_isa <= 3 \ + && !TARGET_LOONGSON_2EF) /* Likewise floating-point comparisons. */ -#define ISA_HAS_FCMP_DELAY (mips_isa <= 3) +#define ISA_HAS_FCMP_DELAY (mips_isa <= 3 \ + && !TARGET_LOONGSON_2EF) /* True if mflo and mfhi can be immediately followed by instructions which write to the HI and LO registers. @@ -886,18 +985,54 @@ extern enum mips_code_readable_setting mips_code_readable; #define ISA_HAS_HILO_INTERLOCKS (ISA_MIPS32 \ || ISA_MIPS32R2 \ || ISA_MIPS64 \ - || TARGET_MIPS5500) + || ISA_MIPS64R2 \ + || TARGET_MIPS5500 \ + || TARGET_LOONGSON_2EF) /* ISA includes synci, jr.hb and jalr.hb. */ -#define ISA_HAS_SYNCI (ISA_MIPS32R2 && !TARGET_MIPS16) +#define ISA_HAS_SYNCI ((ISA_MIPS32R2 \ + || ISA_MIPS64R2) \ + && !TARGET_MIPS16) /* ISA includes sync. */ #define ISA_HAS_SYNC ((mips_isa >= 2 || TARGET_MIPS3900) && !TARGET_MIPS16) +#define GENERATE_SYNC \ + (target_flags_explicit & MASK_LLSC \ + ? TARGET_LLSC && !TARGET_MIPS16 \ + : ISA_HAS_SYNC) /* ISA includes ll and sc. Note that this implies ISA_HAS_SYNC because the expanders use both ISA_HAS_SYNC and ISA_HAS_LL_SC instructions. */ #define ISA_HAS_LL_SC (mips_isa >= 2 && !TARGET_MIPS16) +#define GENERATE_LL_SC \ + (target_flags_explicit & MASK_LLSC \ + ? TARGET_LLSC && !TARGET_MIPS16 \ + : ISA_HAS_LL_SC) + +/* ISA includes the baddu instruction. */ +#define ISA_HAS_BADDU TARGET_OCTEON + +/* ISA includes the bbit* instructions. */ +#define ISA_HAS_BBIT TARGET_OCTEON + +/* ISA includes the cins instruction. */ +#define ISA_HAS_CINS TARGET_OCTEON + +/* ISA includes the exts instruction. */ +#define ISA_HAS_EXTS TARGET_OCTEON + +/* ISA includes the seq and sne instructions. */ +#define ISA_HAS_SEQ_SNE TARGET_OCTEON + +/* ISA includes the pop instruction. */ +#define ISA_HAS_POP TARGET_OCTEON + +/* The CACHE instruction is available in non-MIPS16 code. */ +#define TARGET_CACHE_BUILTIN (mips_isa >= 3) + +/* The CACHE instruction is available. */ +#define ISA_HAS_CACHE (TARGET_CACHE_BUILTIN && !TARGET_MIPS16) /* Add -G xx support. */ @@ -905,7 +1040,7 @@ extern enum mips_code_readable_setting mips_code_readable; #define SWITCH_TAKES_ARG(CHAR) \ (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G') -#define OVERRIDE_OPTIONS override_options () +#define OVERRIDE_OPTIONS mips_override_options () #define CONDITIONAL_REGISTER_USAGE mips_conditional_register_usage () @@ -978,7 +1113,7 @@ extern enum mips_code_readable_setting mips_code_readable; #undef ASM_SPEC #define ASM_SPEC "\ %{G*} %(endian_spec) %{mips1} %{mips2} %{mips3} %{mips4} \ -%{mips32} %{mips32r2} %{mips64} \ +%{mips32*} %{mips64*} \ %{mips16} %{mno-mips16:-no-mips16} \ %{mips3d} %{mno-mips3d:-no-mips3d} \ %{mdmx} %{mno-mdmx:-no-mdmx} \ @@ -989,7 +1124,7 @@ extern enum mips_code_readable_setting mips_code_readable; %{mfix-vr4120} %{mfix-vr4130} \ %(subtarget_asm_optimizing_spec) \ %(subtarget_asm_debugging_spec) \ -%{mabi=*} %{!mabi*: %(asm_abi_default_spec)} \ +%{mabi=*} %{!mabi=*: %(asm_abi_default_spec)} \ %{mgp32} %{mgp64} %{march=*} %{mxgot:-xgot} \ %{mfp32} %{mfp64} \ %{mshared} %{mno-shared} \ @@ -1004,7 +1139,7 @@ extern enum mips_code_readable_setting mips_code_readable; #ifndef LINK_SPEC #define LINK_SPEC "\ %(endian_spec) \ -%{G*} %{mips1} %{mips2} %{mips3} %{mips4} %{mips32} %{mips32r2} %{mips64} \ +%{G*} %{mips1} %{mips2} %{mips3} %{mips4} %{mips32*} %{mips64*} \ %{bestGnum} %{shared} %{non_shared}" #endif /* LINK_SPEC defined */ @@ -1061,7 +1196,6 @@ extern enum mips_code_readable_setting mips_code_readable; #endif #define DBX_DEBUGGING_INFO 1 /* generate stabs (OSF/rose) */ -#define MIPS_DEBUGGING_INFO 1 /* MIPS specific debugging info */ #define DWARF2_DEBUGGING_INFO 1 /* dwarf2 debugging info */ #ifndef PREFERRED_DEBUGGING_TYPE @@ -1160,7 +1294,8 @@ extern enum mips_code_readable_setting mips_code_readable; /* The number of consecutive floating-point registers needed to store the smallest format supported by the FPU. */ #define MIN_FPRS_PER_FMT \ - (ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64 ? 1 : MAX_FPRS_PER_FMT) + (ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64 || ISA_MIPS64R2 \ + ? 1 : MAX_FPRS_PER_FMT) /* The largest size of value that can be held in floating-point registers and moved with a single instruction. */ @@ -1177,7 +1312,8 @@ extern enum mips_code_readable_setting mips_code_readable; /* The number of bytes in a double. */ #define UNITS_PER_DOUBLE (TYPE_PRECISION (double_type_node) / BITS_PER_UNIT) -#define UNITS_PER_SIMD_WORD (TARGET_PAIRED_SINGLE_FLOAT ? 8 : UNITS_PER_WORD) +#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 @@ -1296,7 +1432,13 @@ extern enum mips_code_readable_setting mips_code_readable; || TREE_CODE (TYPE) == UNION_TYPE \ || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN)) - +/* We need this for the same reason as DATA_ALIGNMENT, namely to cause + character arrays to be word-aligned so that `strcpy' calls that copy + constants to character arrays can be done inline, and 'strcmp' can be + optimised to use word loads. */ +#define LOCAL_ALIGNMENT(TYPE, ALIGN) \ + DATA_ALIGNMENT (TYPE, ALIGN) + #define PAD_VARARGS_DOWN \ (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward) @@ -1325,6 +1467,10 @@ extern enum mips_code_readable_setting mips_code_readable; (MODE) = Pmode; \ } +/* Pmode is always the same as ptr_mode, but not always the same as word_mode. + Extensions of pointers to word_mode must be signed. */ +#define POINTERS_EXTEND_UNSIGNED false + /* Define if loading short immediate values into registers sign extends. */ #define SHORT_IMMEDIATES_SIGN_EXTEND @@ -1345,7 +1491,7 @@ extern enum mips_code_readable_setting mips_code_readable; - 3 fake registers: - ARG_POINTER_REGNUM - FRAME_POINTER_REGNUM - - FAKE_CALL_REGNO (see the comment above load_callsi for details) + - GOT_VERSION_REGNUM (see the comment above load_call for details) - 3 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 */ @@ -1358,7 +1504,7 @@ extern enum mips_code_readable_setting mips_code_readable; 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., override_options() or + use. This can be overridden, in, e.g., mips_override_options or CONDITIONAL_REGISTER_USAGE should the assumption be inappropriate for a particular target. */ @@ -1425,7 +1571,7 @@ extern enum mips_code_readable_setting mips_code_readable; 1, 1, 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, \ /* Others. */ \ - 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, 0, \ /* COP0 registers */ \ 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, \ @@ -1540,25 +1686,10 @@ extern enum mips_code_readable_setting mips_code_readable; #define HARD_REGNO_NREGS(REGNO, MODE) mips_hard_regno_nregs (REGNO, MODE) -/* To make the code simpler, HARD_REGNO_MODE_OK just references an - array built in override_options. Because machmodes.h is not yet - included before this file is processed, the MODE bound can't be - expressed here. */ - -extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER]; - #define HARD_REGNO_MODE_OK(REGNO, MODE) \ mips_hard_regno_mode_ok[ (int)(MODE) ][ (REGNO) ] -/* Value is 1 if it is a good idea to tie two pseudo registers - when one has mode MODE1 and one has mode MODE2. - If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, - for any hard reg, then this must be 0 for correct output. */ -#define MODES_TIEABLE_P(MODE1, MODE2) \ - ((GET_MODE_CLASS (MODE1) == MODE_FLOAT || \ - GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT) \ - == (GET_MODE_CLASS (MODE2) == MODE_FLOAT || \ - GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT)) +#define MODES_TIEABLE_P mips_modes_tieable_p /* Register to use for pushing function arguments. */ #define STACK_POINTER_REGNUM (GP_REG_FIRST + 29) @@ -1573,25 +1704,34 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER]; #define HARD_FRAME_POINTER_REGNUM \ (TARGET_MIPS16 ? GP_REG_FIRST + 17 : GP_REG_FIRST + 30) -/* Value should be nonzero if functions must have frame pointers. - Zero means the frame pointer need not be set up (and parms - may be accessed via the stack pointer) in functions that seem suitable. - This is computed in `reload', in reload1.c. */ -#define FRAME_POINTER_REQUIRED (current_function_calls_alloca) +#define FRAME_POINTER_REQUIRED (mips_frame_pointer_required ()) /* Register in which static-chain is passed to a function. */ -#define STATIC_CHAIN_REGNUM (GP_REG_FIRST + 2) +#define STATIC_CHAIN_REGNUM (GP_REG_FIRST + 15) + +/* Registers used as temporaries in prologue/epilogue code: + + - If a MIPS16 PIC function needs access to _gp, it first loads + the value into MIPS16_PIC_TEMP and then copies it to $gp. -/* Registers used as temporaries in prologue/epilogue code. If we're - generating mips16 code, these registers must come from the core set - of 8. The prologue register mustn't conflict with any incoming - arguments, the static chain pointer, or the frame pointer. The - epilogue temporary mustn't conflict with the return registers, the - frame pointer, the EH stack adjustment, or the EH data registers. */ + - The prologue can use MIPS_PROLOGUE_TEMP as a general temporary + register. The register must not conflict with MIPS16_PIC_TEMP. + - The epilogue can use MIPS_EPILOGUE_TEMP as a general temporary + register. + + If we're generating MIPS16 code, these registers must come from the + core set of 8. The prologue registers mustn't conflict with any + 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. */ + +#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 MIPS16_PIC_TEMP gen_rtx_REG (Pmode, MIPS16_PIC_TEMP_REGNUM) #define MIPS_PROLOGUE_TEMP(MODE) gen_rtx_REG (MODE, MIPS_PROLOGUE_TEMP_REGNUM) #define MIPS_EPILOGUE_TEMP(MODE) gen_rtx_REG (MODE, MIPS_EPILOGUE_TEMP_REGNUM) @@ -1639,7 +1779,6 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER]; enum reg_class { NO_REGS, /* no registers in set */ - M16_NA_REGS, /* mips16 regs not used to pass args */ M16_REGS, /* mips16 directly accessible registers */ T_REG, /* mips16 T register ($24) */ M16_T_REGS, /* mips16 registers plus T register */ @@ -1665,6 +1804,7 @@ enum reg_class 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 */ ALL_REGS, /* all registers */ LIM_REG_CLASSES /* max value + 1 */ }; @@ -1680,7 +1820,6 @@ enum reg_class #define REG_CLASS_NAMES \ { \ "NO_REGS", \ - "M16_NA_REGS", \ "M16_REGS", \ "T_REG", \ "M16_T_REGS", \ @@ -1707,6 +1846,7 @@ enum reg_class "ST_REGS", \ "DSP_ACC_REGS", \ "ACC_REGS", \ + "FRAME_REGS", \ "ALL_REGS" \ } @@ -1724,7 +1864,6 @@ enum reg_class #define REG_CLASS_CONTENTS \ { \ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* no registers */ \ - { 0x0003000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 nonarg regs */\ { 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 */ \ @@ -1750,7 +1889,8 @@ enum reg_class { 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 */ \ - { 0xffffffff, 0xffffffff, 0xffff07ff, 0xffffffff, 0xffffffff, 0x0fffffff } /* all registers */ \ + { 0x00000000, 0x00000000, 0x00006000, 0x00000000, 0x00000000, 0x00000000 }, /* frame registers */ \ + { 0xffffffff, 0xffffffff, 0xffff67ff, 0xffffffff, 0xffffffff, 0x0fffffff } /* all registers */ \ } @@ -1759,8 +1899,6 @@ enum reg_class choose a class which is "minimal", meaning that no smaller class also contains the register. */ -extern const enum reg_class mips_regno_to_class[]; - #define REGNO_REG_CLASS(REGNO) mips_regno_to_class[ (REGNO) ] /* A macro whose definition is the name of the class to which a @@ -1858,9 +1996,9 @@ extern const enum reg_class mips_regno_to_class[]; general registers, and from the floating point registers. */ #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \ - mips_secondary_reload_class (CLASS, MODE, X, 1) + mips_secondary_reload_class (CLASS, MODE, X, true) #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \ - mips_secondary_reload_class (CLASS, MODE, X, 0) + mips_secondary_reload_class (CLASS, MODE, X, false) /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. */ @@ -1875,29 +2013,40 @@ extern const enum reg_class mips_regno_to_class[]; #define STACK_GROWS_DOWNWARD /* The offset of the first local variable from the beginning of the frame. - See compute_frame_size for details about the frame layout. - - ??? If flag_profile_values is true, and we are generating 32-bit code, then - we assume that we will need 16 bytes of argument space. This is because - the value profiling code may emit calls to cmpdi2 in leaf functions. - Without this hack, the local variables will start at sp+8 and the gp save - area will be at sp+16, and thus they will overlap. compute_frame_size is - OK because it uses STARTING_FRAME_OFFSET to compute cprestore_size, which - will end up as 24 instead of 8. This won't be needed if profiling code is - inserted before virtual register instantiation. */ + See mips_compute_frame_info for details about the frame layout. */ #define STARTING_FRAME_OFFSET \ - ((flag_profile_values && ! TARGET_64BIT \ - ? MAX (REG_PARM_STACK_SPACE(NULL), current_function_outgoing_args_size) \ - : current_function_outgoing_args_size) \ + (crtl->outgoing_args_size \ + (TARGET_CALL_CLOBBERED_GP ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0)) #define RETURN_ADDR_RTX mips_return_addr -/* Since the mips16 ISA mode is encoded in the least-significant bit - of the address, mask it off return addresses for purposes of - finding exception handling regions. */ +/* Mask off the MIPS16 ISA bit in unwind addresses. + + The reason for this is a little subtle. When unwinding a call, + we are given the call's return address, which on most targets + is the address of the following instruction. However, what we + actually want to find is the EH region for the call itself. + The target-independent unwind code therefore searches for "RA - 1". + In the MIPS16 case, RA is always an odd-valued (ISA-encoded) address. + RA - 1 is therefore the real (even-valued) start of the return + instruction. EH region labels are usually odd-valued MIPS16 symbols + too, so a search for an even address within a MIPS16 region would + usually work. + + However, there is an exception. If the end of an EH region is also + the end of a function, the end label is allowed to be even. This is + necessary because a following non-MIPS16 function may also need EH + information for its first instruction. + + Thus a MIPS16 region may be terminated by an ISA-encoded or a + non-ISA-encoded address. This probably isn't ideal, but it is + the traditional (legacy) behavior. It is therefore only safe + to search MIPS EH regions for an _odd-valued_ address. + + Masking off the ISA bit means that the target-independent code + will search for "(RA & -2) - 1", which is guaranteed to be odd. */ #define MASK_RETURN_ADDR GEN_INT (-2) @@ -1917,18 +2066,10 @@ extern const enum reg_class mips_regno_to_class[]; { FRAME_POINTER_REGNUM, GP_REG_FIRST + 30}, \ { FRAME_POINTER_REGNUM, GP_REG_FIRST + 17}} -/* We can always eliminate to the hard frame pointer. We can eliminate - to the stack pointer unless a frame pointer is needed. - - In mips16 mode, we need a frame pointer for a large frame; otherwise, - reload may be unable to compute the address of a local variable, - since there is no way to add a large constant to the stack pointer - without using a temporary register. */ -#define CAN_ELIMINATE(FROM, TO) \ - ((TO) == HARD_FRAME_POINTER_REGNUM \ - || ((TO) == STACK_POINTER_REGNUM && !frame_pointer_needed \ - && (!TARGET_MIPS16 \ - || compute_frame_size (get_frame_size ()) < 32768))) +/* 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)) @@ -1949,8 +2090,8 @@ extern const enum reg_class mips_regno_to_class[]; allocate the area reserved for arguments passed in registers. If `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect of this macro is to determine whether the space is included in - `current_function_outgoing_args_size'. */ -#define OUTGOING_REG_PARM_STACK_SPACE 1 + `crtl->outgoing_args_size'. */ +#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1 #define STACK_BOUNDARY (TARGET_NEWABI ? 128 : 64) @@ -1972,10 +2113,10 @@ extern const enum reg_class mips_regno_to_class[]; #define FP_ARG_LAST (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1) #define LIBCALL_VALUE(MODE) \ - mips_function_value (NULL_TREE, NULL, (MODE)) + mips_function_value (NULL_TREE, MODE) #define FUNCTION_VALUE(VALTYPE, FUNC) \ - mips_function_value ((VALTYPE), (FUNC), VOIDmode) + mips_function_value (VALTYPE, 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. @@ -2015,9 +2156,9 @@ extern const enum reg_class mips_regno_to_class[]; allocate floating-point registers. So for the standard ABIs, the first N words are allocated to integer - registers, and function_arg decides on an argument-by-argument basis - whether that argument should really go in an integer register, or in - a floating-point one. */ + registers, and mips_function_arg decides on an argument-by-argument + basis whether that argument should really go in an integer register, + or in a floating-point one. */ typedef struct mips_args { /* Always true for varargs functions. Otherwise true if at least @@ -2060,14 +2201,14 @@ typedef struct mips_args { For a library call, FNTYPE is 0. */ #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ - init_cumulative_args (&CUM, FNTYPE, LIBNAME) \ + 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) \ - function_arg_advance (&CUM, MODE, TYPE, NAMED) +#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, @@ -2083,14 +2224,14 @@ typedef struct mips_args { (otherwise it is an extra parameter matching an ellipsis). */ #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - function_arg( &CUM, MODE, TYPE, NAMED) + mips_function_arg (&CUM, MODE, TYPE, NAMED) -#define FUNCTION_ARG_BOUNDARY function_arg_boundary +#define FUNCTION_ARG_BOUNDARY mips_function_arg_boundary -#define FUNCTION_ARG_PADDING(MODE, TYPE) \ +#define FUNCTION_ARG_PADDING(MODE, TYPE) \ (mips_pad_arg_upward (MODE, TYPE) ? upward : downward) -#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \ +#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \ (mips_pad_reg_upward (MODE, TYPE) ? upward : downward) /* True if using EABI and varargs can be passed in floating-point @@ -2102,8 +2243,12 @@ typedef struct mips_args { /* 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. */ -#define EPILOGUE_USES(REGNO) ((REGNO) == 31) + 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 for details. */ +#define EPILOGUE_USES(REGNO) \ + ((REGNO) == 31 || (TARGET_USE_GOT && (REGNO) == GOT_VERSION_REGNUM)) /* Treat LOC as a byte offset from the stack pointer and round it up to the next fully-aligned offset. */ @@ -2111,10 +2256,6 @@ typedef struct mips_args { (TARGET_NEWABI ? ((LOC) + 15) & -16 : ((LOC) + 7) & -8) -/* Implement `va_start' for varargs and stdarg. */ -#define EXPAND_BUILTIN_VA_START(valist, nextarg) \ - mips_va_start (valist, nextarg) - /* Output assembler code to FILE to increment profiler label # LABELNO for profiling a function entry. */ @@ -2122,9 +2263,21 @@ typedef struct mips_args { { \ 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, \ @@ -2134,10 +2287,20 @@ typedef struct mips_args { reg_names[STACK_POINTER_REGNUM], \ Pmode == DImode ? 16 : 8); \ } \ - fprintf (FILE, "\tjal\t_mcount\n"); \ + 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]); \ } +/* The profiler preserves all interesting registers, including $31. */ +#define MIPS_SAVE_REG_FOR_PROFILING_P(REGNO) false + /* No mips port has ever used the profiler counter word, so don't emit it or the label for it. */ @@ -2172,20 +2335,19 @@ typedef struct mips_args { fprintf (STREAM, "\t.word\t0x00000000\t\t# nop\n"); \ if (ptr_mode == DImode) \ { \ - fprintf (STREAM, "\t.word\t0xdfe30014\t\t# ld $3,20($31)\n"); \ - fprintf (STREAM, "\t.word\t0xdfe2001c\t\t# ld $2,28($31)\n"); \ - fprintf (STREAM, "\t.word\t0x0060c82d\t\t# dmove $25,$3\n"); \ + 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\t0x8fe30014\t\t# lw $3,20($31)\n"); \ - fprintf (STREAM, "\t.word\t0x8fe20018\t\t# lw $2,24($31)\n"); \ - fprintf (STREAM, "\t.word\t0x0060c821\t\t# move $25,$3\n"); \ + 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\t0x00600008\t\t# jr $3\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# \n"); \ fprintf (STREAM, "\t.dword\t0x00000000\t\t# \n"); \ fprintf (STREAM, "\t.dword\t0x00000000\t\t# \n"); \ } \ @@ -2200,7 +2362,7 @@ typedef struct mips_args { /* A C expression for the size in bytes of the trampoline, as an integer. */ -#define TRAMPOLINE_SIZE (32 + GET_MODE_SIZE (ptr_mode) * 2) +#define TRAMPOLINE_SIZE (ptr_mode == DImode ? 48 : 36) /* Alignment required for trampolines, in bits. */ @@ -2213,6 +2375,13 @@ typedef struct mips_args { #define CACHE_FLUSH_FUNC "_flush_cache" #endif +#define MIPS_ICACHE_SYNC(ADDR, SIZE) \ + /* 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, \ + 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 @@ -2223,7 +2392,7 @@ typedef struct mips_args { { \ rtx func_addr, chain_addr, end_addr; \ \ - func_addr = plus_constant (ADDR, 32); \ + 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); \ @@ -2324,10 +2493,10 @@ typedef struct mips_args { #define SYMBOL_REF_LONG_CALL_P(X) \ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_LONG_CALL) != 0) -/* Flag to mark a function decl symbol a "mips16" function. */ -#define SYMBOL_FLAG_MIPS16_FUNC (SYMBOL_FLAG_MACH_DEP << 1) -#define SYMBOL_REF_MIPS16_FUNC_P(RTX) \ - ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_MIPS16_FUNC) != 0) +/* This flag marks functions that cannot be lazily bound. */ +#define SYMBOL_FLAG_BIND_NOW (SYMBOL_FLAG_MACH_DEP << 1) +#define SYMBOL_REF_BIND_NOW_P(RTX) \ + ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_BIND_NOW) != 0) /* True if we're generating a form of MIPS16 code in which jump tables are stored in the text section and encoded as 16-bit PC-relative @@ -2347,9 +2516,10 @@ typedef struct mips_args { #define DEFAULT_SIGNED_CHAR 1 #endif -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX (TARGET_64BIT ? 8 : 4) +/* Although LDC1 and SDC1 provide 64-bit moves on 32-bit targets, + we generally don't want to use them for copying arbitrary data. + A single N-word move is usually the same cost as N single-word moves. */ +#define MOVE_MAX UNITS_PER_WORD #define MAX_MOVE_MAX 8 /* Define this macro as a C expression which is nonzero if @@ -2423,7 +2593,7 @@ typedef struct mips_args { /* A C expression for the cost of a branch instruction. A value of 1 is the default; other values are interpreted relative to that. */ -#define BRANCH_COST mips_branch_cost +#define BRANCH_COST(speed_p, predictable_p) mips_branch_cost #define LOGICAL_OP_NON_SHORT_CIRCUIT 0 /* If defined, modifies the length assigned to instruction INSN as a @@ -2453,7 +2623,7 @@ typedef struct mips_args { ? "%*" INSN "\t%" #OPNO "%/" \ : REG_P (OPERANDS[OPNO]) \ ? "%*" INSN "r\t%" #OPNO "%/" \ - : TARGET_ABICALLS \ + : TARGET_ABICALLS_PIC2 \ ? (".option\tpic0\n\t" \ "%*" INSN "\t%" #OPNO "%/\n\t" \ ".option\tpic2") \ @@ -2547,44 +2717,9 @@ typedef struct mips_args { #define ALL_COP_ADDITIONAL_REGISTER_NAMES -/* A C compound statement to output to stdio stream STREAM the - assembler syntax for an instruction operand X. X is an RTL - expression. - - CODE is a value that can be used to specify one of several ways - of printing the operand. It is used when identical operands - must be printed differently depending on the context. CODE - comes from the `%' specification that was used to request - printing of the operand. If the specification was just `%DIGIT' - then CODE is 0; if the specification was `%LTR DIGIT' then CODE - is the ASCII code for LTR. - - If X is a register, this macro should print the register's name. - The names can be found in an array `reg_names' whose type is - `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'. - - When the machine description has a specification `%PUNCT' (a `%' - followed by a punctuation character), this macro is called with - a null pointer for X and the punctuation character for CODE. - - See mips.c for the MIPS specific codes. */ - -#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE) - -/* A C expression which evaluates to true if CODE is a valid - punctuation character for use in the `PRINT_OPERAND' macro. If - `PRINT_OPERAND_PUNCT_VALID_P' is not defined, it means that no - punctuation characters (except for the standard one, `%') are - used in this way. */ - +#define PRINT_OPERAND mips_print_operand #define PRINT_OPERAND_PUNCT_VALID_P(CODE) mips_print_operand_punct[CODE] - -/* A C compound statement to output to stdio stream STREAM the - assembler syntax for an instruction operand that is a memory - reference whose address is ADDR. ADDR is an RTL expression. */ - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) - +#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 @@ -2616,10 +2751,8 @@ do \ } \ while (0) - /* How to tell the debugger about changes of source files. */ -#define ASM_OUTPUT_SOURCE_FILENAME(STREAM, NAME) \ - mips_output_filename (STREAM, NAME) +#define ASM_OUTPUT_SOURCE_FILENAME mips_output_filename /* mips-tfile does not understand .stabd directives. */ #define DBX_OUTPUT_SOURCE_LINE(STREAM, LINE, COUNTER) do { \ @@ -2678,10 +2811,6 @@ while (0) #undef ASM_DECLARE_FUNCTION_NAME #define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) -#ifndef FUNCTION_NAME_ALREADY_DECLARED -#define FUNCTION_NAME_ALREADY_DECLARED 0 -#endif - /* This is how to store into the string LABEL the symbol_ref name of an internal numbered label where PREFIX is the class of label and NUM is the number within the class. @@ -2744,8 +2873,7 @@ do { \ /* This is how to output a string. */ #undef ASM_OUTPUT_ASCII -#define ASM_OUTPUT_ASCII(STREAM, STRING, LEN) \ - mips_output_ascii (STREAM, STRING, LEN, "\t.ascii\t") +#define ASM_OUTPUT_ASCII mips_output_ascii /* Output #ident as a in the read-only data section. */ #undef ASM_OUTPUT_IDENT @@ -2772,8 +2900,8 @@ do { \ #define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \ do \ { \ - fprintf (STREAM, "\t%s\t%s,%s,8\n\t%s\t%s,0(%s)\n", \ - TARGET_64BIT ? "dsubu" : "subu", \ + fprintf (STREAM, "\t%s\t%s,%s,-8\n\t%s\t%s,0(%s)\n", \ + TARGET_64BIT ? "daddiu" : "addiu", \ reg_names[STACK_POINTER_REGNUM], \ reg_names[STACK_POINTER_REGNUM], \ TARGET_64BIT ? "sd" : "sw", \ @@ -2816,6 +2944,18 @@ while (0) #undef PTRDIFF_TYPE #define PTRDIFF_TYPE (POINTER_SIZE == 64 ? "long int" : "int") +/* The maximum number of bytes that can be copied by one iteration of + a movmemsi loop; see mips_block_move_loop. */ +#define MIPS_MAX_MOVE_BYTES_PER_LOOP_ITER \ + (UNITS_PER_WORD * 4) + +/* The maximum number of bytes that can be copied by a straight-line + implementation of movmemsi; see mips_block_move_straight. We want + to make sure that any loop-based implementation will iterate at + least twice. */ +#define MIPS_MAX_MOVE_BYTES_STRAIGHT \ + (MIPS_MAX_MOVE_BYTES_PER_LOOP_ITER * 2) + /* The base cost of a memcpy call, for MOVE_RATIO and friends. These values were determined experimentally by benchmarking with CSiBE. In theory, the call overhead is higher for TARGET_ABICALLS (especially @@ -2825,36 +2965,52 @@ while (0) #define MIPS_CALL_RATIO 8 -/* Define MOVE_RATIO to encourage use of movmemsi when enabled, - since it should always generate code at least as good as - move_by_pieces(). But when inline movmemsi pattern is disabled - (i.e., with -mips16 or -mmemcpy), instead use a value approximating - the length of a memcpy call sequence, so that move_by_pieces will - generate inline code if it is shorter than a function call. - Since move_by_pieces_ninsns() counts memory-to-memory moves, but - we'll have to generate a load/store pair for each, halve the value of - MIPS_CALL_RATIO to take that into account. - The default value for MOVE_RATIO when HAVE_movmemsi is true is 2. - There is no point to setting it to less than this to try to disable - move_by_pieces entirely, because that also disables some desirable - tree-level optimizations, specifically related to optimizing a - one-byte string copy into a simple move byte operation. */ - -#define MOVE_RATIO \ - ((TARGET_MIPS16 || TARGET_MEMCPY) ? MIPS_CALL_RATIO / 2 : 2) +/* Any loop-based implementation of movmemsi will have at least + MIPS_MAX_MOVE_BYTES_STRAIGHT / UNITS_PER_WORD memory-to-memory + moves, so allow individual copies of fewer elements. + + When movmemsi is not available, use a value approximating + the length of a memcpy call sequence, so that move_by_pieces + will generate inline code if it is shorter than a function call. + Since move_by_pieces_ninsns counts memory-to-memory moves, but + we'll have to generate a load/store pair for each, halve the + value of MIPS_CALL_RATIO to take that into account. */ + +#define MOVE_RATIO(speed) \ + (HAVE_movmemsi \ + ? MIPS_MAX_MOVE_BYTES_STRAIGHT / MOVE_MAX \ + : MIPS_CALL_RATIO / 2) + +/* movmemsi is meant to generate code that is at least as good as + move_by_pieces. However, movmemsi effectively uses a by-pieces + implementation both for moves smaller than a word and for word-aligned + moves of no more than MIPS_MAX_MOVE_BYTES_STRAIGHT bytes. We should + allow the tree-level optimisers to do such moves by pieces, as it + often exposes other optimization opportunities. We might as well + continue to use movmemsi at the rtl level though, as it produces + better code when scheduling is disabled (such as at -O). */ + +#define MOVE_BY_PIECES_P(SIZE, ALIGN) \ + (HAVE_movmemsi \ + ? (!currently_expanding_to_rtl \ + && ((ALIGN) < BITS_PER_WORD \ + ? (SIZE) < UNITS_PER_WORD \ + : (SIZE) <= MIPS_MAX_MOVE_BYTES_STRAIGHT)) \ + : (move_by_pieces_ninsns (SIZE, ALIGN, MOVE_MAX_PIECES + 1) \ + < (unsigned int) MOVE_RATIO (false))) /* For CLEAR_RATIO, when optimizing for size, give a better estimate of the length of a memset call, but use the default otherwise. */ -#define CLEAR_RATIO \ - (optimize_size ? MIPS_CALL_RATIO : 15) +#define CLEAR_RATIO(speed)\ + ((speed) ? 15 : MIPS_CALL_RATIO) /* This is similar to CLEAR_RATIO, but for a non-zero constant, so when optimizing for size adjust the ratio to account for the overhead of loading the constant and replicating it across the word. */ -#define SET_RATIO \ - (optimize_size ? MIPS_CALL_RATIO - 2 : 15) +#define SET_RATIO(speed) \ + ((speed) ? 15 : MIPS_CALL_RATIO - 2) /* STORE_BY_PIECES_P can be used when copying a constant string, but in that case each word takes 3 insns (lui, ori, sw), or more in @@ -2913,14 +3069,44 @@ while (0) and OP is the instruction that should be used to load %3 into a register. */ #define MIPS_COMPARE_AND_SWAP(SUFFIX, OP) \ - "%(%<%[sync\n" \ + "%(%<%[%|sync\n" \ "1:\tll" SUFFIX "\t%0,%1\n" \ - "\tbne\t%0,%2,2f\n" \ + "\tbne\t%0,%z2,2f\n" \ "\t" OP "\t%@,%3\n" \ "\tsc" SUFFIX "\t%@,%1\n" \ "\tbeq\t%@,%.,1b\n" \ "\tnop\n" \ - "2:%]%>%)" + "\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: @@ -2929,12 +3115,104 @@ while (0) SUFFIX is the suffix that should be added to "ll" and "sc" instructions. */ #define MIPS_SYNC_OP(SUFFIX, INSN) \ - "%(%<%[sync\n" \ + "%(%<%[%|sync\n" \ "1:\tll" SUFFIX "\t%@,%0\n" \ "\t" INSN "\t%@,%@,%1\n" \ "\tsc" SUFFIX "\t%@,%0\n" \ "\tbeq\t%@,%.,1b\n" \ - "\tnop%]%>%)" + "\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: @@ -2945,12 +3223,13 @@ while (0) SUFFIX is the suffix that should be added to "ll" and "sc" instructions. */ #define MIPS_SYNC_OLD_OP(SUFFIX, INSN) \ - "%(%<%[sync\n" \ + "%(%<%[%|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%]%>%)" + "\tnop\n" \ + "\tsync%-%]%>%)" /* Return an asm string that atomically: @@ -2961,12 +3240,13 @@ while (0) SUFFIX is the suffix that should be added to "ll" and "sc" instructions. */ #define MIPS_SYNC_NEW_OP(SUFFIX, INSN) \ - "%(%<%[sync\n" \ + "%(%<%[%|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%]%>%)" + "\t" INSN "\t%0,%0,%2\n" \ + "\tsync%-%]%>%)" /* Return an asm string that atomically: @@ -2976,13 +3256,14 @@ while (0) instructions. INSN is the and instruction needed to and a register with %2. */ #define MIPS_SYNC_NAND(SUFFIX, INSN) \ - "%(%<%[sync\n" \ + "%(%<%[%|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%]%>%)" + "\tnop\n" \ + "\tsync%-%]%>%)" /* Return an asm string that atomically: @@ -2994,13 +3275,14 @@ while (0) instructions. INSN is the and instruction needed to and a register with %2. */ #define MIPS_SYNC_OLD_NAND(SUFFIX, INSN) \ - "%(%<%[sync\n" \ + "%(%<%[%|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%]%>%)" + "\tnop\n" \ + "\tsync%-%]%>%)" /* Return an asm string that atomically: @@ -3012,13 +3294,14 @@ while (0) instructions. INSN is the and instruction needed to and a register with %2. */ #define MIPS_SYNC_NEW_NAND(SUFFIX, INSN) \ - "%(%<%[sync\n" \ + "%(%<%[%|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%]%>%)" + "\t" INSN "\t%0,%0,%2\n" \ + "\tsync%-%]%>%)" /* Return an asm string that atomically: @@ -3030,11 +3313,64 @@ while (0) instructions. OP is the and instruction that should be used to load %2 into a register. */ #define MIPS_SYNC_EXCHANGE(SUFFIX, OP) \ - "%(%<%[\n" \ + "%(%<%[%|\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%]%>%)" + "\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" + +#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 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 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; +#endif +/* Enable querying of DFA units. */ +#define CPU_UNITS_QUERY 1