summaryrefslogtreecommitdiff
path: root/gcc/config/mips/mips.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/mips/mips.h')
-rw-r--r--gcc/config/mips/mips.h77
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