diff options
Diffstat (limited to 'gcc/config/mips/mips.h')
-rw-r--r-- | gcc/config/mips/mips.h | 77 |
1 files changed, 70 insertions, 7 deletions
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index dd67f11fe03..8a388294219 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -323,6 +323,15 @@ struct mips_cpu_info { #define TARGET_HARD_FLOAT (TARGET_HARD_FLOAT_ABI && !TARGET_MIPS16) #define TARGET_SOFT_FLOAT (TARGET_SOFT_FLOAT_ABI || TARGET_MIPS16) +/* TARGET_FLOAT64 represents -mfp64 and TARGET_FLOATXX represents + -mfpxx, derive TARGET_FLOAT32 to represent -mfp32. */ +#define TARGET_FLOAT32 (!TARGET_FLOAT64 && !TARGET_FLOATXX) + +/* TARGET_O32_FP64A_ABI represents all the conditions that form the + o32 FP64A ABI extension (-mabi=32 -mfp64 -mno-odd-spreg). */ +#define TARGET_O32_FP64A_ABI (mips_abi == ABI_32 && TARGET_FLOAT64 \ + && !TARGET_ODD_SPREG) + /* 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 @@ -391,6 +400,8 @@ struct mips_cpu_info { \ if (TARGET_FLOAT64) \ builtin_define ("__mips_fpr=64"); \ + else if (TARGET_FLOATXX) \ + builtin_define ("__mips_fpr=0"); \ else \ builtin_define ("__mips_fpr=32"); \ \ @@ -519,6 +530,8 @@ struct mips_cpu_info { builtin_define_with_int_value ("_MIPS_SZPTR", POINTER_SIZE); \ builtin_define_with_int_value ("_MIPS_FPSET", \ 32 / MAX_FPRS_PER_FMT); \ + builtin_define_with_int_value ("_MIPS_SPFPSET", \ + TARGET_ODD_SPREG ? 32 : 16); \ \ /* These defines reflect the ABI in use, not whether the \ FPU is directly accessible. */ \ @@ -754,6 +767,12 @@ struct mips_cpu_info { #define MIPS_32BIT_OPTION_SPEC \ "mips1|mips2|mips32*|mgp32" +/* A spec condition that matches architectures should be targeted with + o32 FPXX for compatibility reasons. */ +#define MIPS_FPXX_OPTION_SPEC \ + "mips2|mips3|mips4|mips5|mips32|mips32r2|mips32r3|mips32r5| \ + mips64|mips64r2|mips64r3|mips64r5" + /* Infer a -msynci setting from a -mips argument, on the assumption that -msynci is desired where possible. */ #define MIPS_ISA_SYNCI_SPEC \ @@ -778,7 +797,12 @@ struct mips_cpu_info { --with-abi is ignored if -mabi is specified. --with-float is ignored if -mhard-float or -msoft-float are specified. + --with-fpu is ignored if -msoft-float, -msingle-float or -mdouble-float are + specified. --with-nan is ignored if -mnan is specified. + --with-fp-32 is ignored if -msoft-float, -msingle-float or -mfp are specified. + --with-odd-spreg-32 is ignored if -msoft-float, -msingle-float, -modd-spreg + or -mno-odd-spreg are specified. --with-divide is ignored if -mdivide-traps or -mdivide-breaks are specified. */ #define OPTION_DEFAULT_SPECS \ @@ -790,8 +814,12 @@ struct mips_cpu_info { {"tune_64", "%{" OPT_ARCH64 ":%{!mtune=*:-mtune=%(VALUE)}}" }, \ {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \ {"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" }, \ - {"fpu", "%{!msingle-float:%{!mdouble-float:-m%(VALUE)-float}}" }, \ + {"fpu", "%{!msoft-float:%{!msingle-float:%{!mdouble-float:-m%(VALUE)-float}}}" }, \ {"nan", "%{!mnan=*:-mnan=%(VALUE)}" }, \ + {"fp_32", "%{" OPT_ARCH32 \ + ":%{!msoft-float:%{!msingle-float:%{!mfp*:-mfp%(VALUE)}}}}" }, \ + {"odd_spreg_32", "%{" OPT_ARCH32 ":%{!msoft-float:%{!msingle-float:" \ + "%{!modd-spreg:%{!mno-odd-spreg:-m%(VALUE)}}}}}" }, \ {"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }, \ {"llsc", "%{!mllsc:%{!mno-llsc:-m%(VALUE)}}" }, \ {"mips-plt", "%{!mplt:%{!mno-plt:-m%(VALUE)}}" }, \ @@ -843,6 +871,12 @@ struct mips_cpu_info { been generated up to this point. */ #define ISA_HAS_BRANCHLIKELY (!ISA_MIPS1) +/* ISA has 32 single-precision registers. */ +#define ISA_HAS_ODD_SPREG ((mips_isa_rev >= 1 \ + && !TARGET_LOONGSON_3A) \ + || TARGET_FLOAT64 \ + || TARGET_MIPS5900) + /* ISA has a three-operand multiplication instruction (usually spelt "mul"). */ #define ISA_HAS_MUL3 ((TARGET_MIPS3900 \ || TARGET_MIPS5400 \ @@ -1030,7 +1064,8 @@ struct mips_cpu_info { #define ISA_HAS_EXT_INS (mips_isa_rev >= 2 && !TARGET_MIPS16) /* ISA has instructions for accessing top part of 64-bit fp regs. */ -#define ISA_HAS_MXHC1 (TARGET_FLOAT64 && mips_isa_rev >= 2) +#define ISA_HAS_MXHC1 (!TARGET_FLOAT32 \ + && mips_isa_rev >= 2) /* ISA has lwxs instruction (load w/scaled index address. */ #define ISA_HAS_LWXS ((TARGET_SMARTMIPS || TARGET_MICROMIPS) \ @@ -1186,7 +1221,8 @@ struct mips_cpu_info { %(subtarget_asm_debugging_spec) \ %{mabi=*} %{!mabi=*: %(asm_abi_default_spec)} \ %{mgp32} %{mgp64} %{march=*} %{mxgot:-xgot} \ -%{mfp32} %{mfp64} %{mnan=*} \ +%{mfp32} %{mfpxx} %{mfp64} %{mnan=*} \ +%{modd-spreg} %{mno-odd-spreg} \ %{mshared} %{mno-shared} \ %{msym32} %{mno-sym32} \ %{mtune=*} \ @@ -1358,7 +1394,7 @@ struct mips_cpu_info { /* The number of consecutive floating-point registers needed to store the smallest format supported by the FPU. */ #define MIN_FPRS_PER_FMT \ - (mips_isa_rev >= 1 ? 1 : MAX_FPRS_PER_FMT) + (TARGET_ODD_SPREG ? 1 : MAX_FPRS_PER_FMT) /* The largest size of value that can be held in floating-point registers and moved with a single instruction. */ @@ -1764,6 +1800,16 @@ struct mips_cpu_info { #define HARD_REGNO_MODE_OK(REGNO, MODE) \ mips_hard_regno_mode_ok[ (int)(MODE) ][ (REGNO) ] +/* Select a register mode required for caller save of hard regno REGNO. */ +#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \ + mips_hard_regno_caller_save_mode (REGNO, NREGS, MODE) + +/* Odd-numbered single-precision registers are not considered callee-saved + for o32 FPXX as they will be clobbered when run on an FR=1 FPU. */ +#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \ + (TARGET_FLOATXX && hard_regno_nregs[REGNO][MODE] == 1 \ + && FP_REG_P (REGNO) && ((REGNO) & 1)) + #define MODES_TIEABLE_P mips_modes_tieable_p /* Register to use for pushing function arguments. */ @@ -2097,6 +2143,19 @@ enum reg_class #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \ mips_secondary_reload_class (CLASS, MODE, X, false) +/* When targeting the o32 FPXX ABI, all moves with a length of doubleword + or greater must be performed by FR-mode-aware instructions. + This can be achieved using MFHC1/MTHC1 when these instructions are + available but otherwise moves must go via memory. + For the o32 FP64A ABI, all odd-numbered moves with a length of + doubleword or greater are required to use memory. Using MTC1/MFC1 + to access the lower-half of these registers would require a forbidden + single-precision access. We require all double-word moves to use + memory because adding even and odd floating-point registers classes + would have a significant impact on the backend. */ +#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ + mips_secondary_memory_needed ((CLASS1), (CLASS2), (MODE)) + /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. */ @@ -2218,12 +2277,16 @@ enum reg_class (TARGET_MIPS16 ? GP_ARG_FIRST + 2 : PIC_OFFSET_TABLE_REGNUM) /* 1 if N is a possible register number for function argument passing. - We have no FP argument registers when soft-float. When FP registers - are 32 bits, we can't directly reference the odd numbered ones. */ + We have no FP argument registers when soft-float. Special handling + is required for O32 where only even numbered registers are used for + O32-FPXX and O32-FP64. */ #define FUNCTION_ARG_REGNO_P(N) \ ((IN_RANGE((N), GP_ARG_FIRST, GP_ARG_LAST) \ - || (IN_RANGE((N), FP_ARG_FIRST, FP_ARG_LAST))) \ + || (IN_RANGE((N), FP_ARG_FIRST, FP_ARG_LAST) \ + && (mips_abi != ABI_32 \ + || TARGET_FLOAT32 \ + || ((N) % 2 == 0)))) \ && !fixed_regs[N]) /* This structure has to cope with two different argument allocation |