Implement MIPS o32 FPXX, FP64, FP64A ABI extensions.

2014-11-12  Matthew Fortune  <matthew.fortune@imgtec.com>

gcc/
	* common/config/mips/mips-common.c (mips_handle_option): Ensure
	that -mfp32, -mfp64 disable -mfpxx and -mfpxx disables -mfp64.
	* config.gcc (--with-fp-32): New option.
	(--with-odd-spreg-32): Likewise.
	* config.in (HAVE_AS_DOT_MODULE): New config define.
	* config/mips/mips-protos.h
	(mips_secondary_memory_needed): New prototype.
	(mips_hard_regno_caller_save_mode): Likewise.
	* config/mips/mips.c (mips_get_reg_raw_mode): New static prototype.
	(mips_get_arg_info): Assert that V2SFmode is only handled specially
	with TARGET_PAIRED_SINGLE_FLOAT.
	(mips_return_mode_in_fpr_p): Likewise.
	(mips16_call_stub_mode_suffix): Likewise.
	(mips_get_reg_raw_mode): New static function.
	(mips_return_fpr_pair): O32 return values span two registers.
	(mips16_build_call_stub): Likewise.
	(mips_function_value_regno_p): Support both FP return registers.
	(mips_output_64bit_xfer): Use mthc1 whenever TARGET_HAS_MXHC1.  Add
	specific cases for TARGET_FPXX to move via memory.
	(mips_dwarf_register_span): For TARGET_FPXX pretend that modes larger
	than UNITS_PER_FPREG 'span' one register.
	(mips_dwarf_frame_reg_mode): New static function.
	(mips_file_start): Switch to using .module instead of .gnu_attribute.
	No longer support FP ABI 4 (-mips32r2 -mfp64), replace with FP ABI 6.
	Add FP ABI 5 (-mfpxx) and FP ABI 7 (-mfp64 -mno-odd-spreg).
	(mips_save_reg, mips_restore_reg): Always represent DFmode frame
	slots with two CFI directives even for O32 FP64.
	(mips_for_each_saved_gpr_and_fpr): Account for fixed_regs when
	saving/restoring callee-saved registers.
	(mips_hard_regno_mode_ok_p): Implement O32 FP64A extension.
	(mips_secondary_memory_needed): New function.
	(mips_option_override): ABI check for TARGET_FLOATXX.  Disable
	odd-numbered single-precision registers	when using TARGET_FLOATXX.
	Implement -modd-spreg and defaults.
	(mips_conditional_register_usage): Redefine O32 FP64 to match O32 FP32
	callee-saved behaviour.
	(mips_hard_regno_caller_save_mode): Implement.
	(TARGET_GET_RAW_RESULT_MODE): Define target hook.
	(TARGET_GET_RAW_ARG_MODE): Define target hook.
	(TARGET_DWARF_FRAME_REG_MODE): Define target hook.
	* config/mips/mips.h (TARGET_FLOAT32): New macro.
	(TARGET_O32_FP64A_ABI): Likewise.
	(TARGET_CPU_CPP_BUILTINS): TARGET_FPXX is __mips_fpr==0. Add
	_MIPS_SPFPSET builtin define.
	(MIPS_FPXX_OPTION_SPEC): New macro.
	(OPTION_DEFAULT_SPECS): Pass through --with-fp-32=* to -mfp and
	--with-odd-spreg-32=* to -m[no-]odd-spreg.
	(ISA_HAS_ODD_SPREG): New macro.
	(ISA_HAS_MXHC1): True for anything other than -mfp32.
	(ASM_SPEC): Pass through mfpxx, mfp64, -mno-odd-spreg and -modd-spreg.
	(MIN_FPRS_PER_FMT): Redefine in terms of TARGET_ODD_SPREG.
	(HARD_REGNO_CALLER_SAVE_MODE): Define.  Implement O32 FPXX extension
	(HARD_REGNO_CALL_PART_CLOBBERED): Likewise.
	(SECONDARY_MEMORY_NEEDED): Likewise.
	(FUNCTION_ARG_REGNO_P): Update for O32 FPXX and FP64 extensions.
	* config/mips/mips.md (define_attr enabled): Implement O32 FPXX and
	FP64A ABI extensions.
	(move_doubleword_fpr<mode>): Use ISA_HAS_MXHC1 instead of
	TARGET_FLOAT64.
	* config/mips/mips.opt (mfpxx): New target option.
	(modd-spreg): Likewise.
	* config/mips/mti-elf.h (DRIVER_SELF_SPECS): Infer FP ABI from arch.
	* config/mips/mti-linux.h (DRIVER_SELF_SPECS): Likewise and remove
	fp64 sysroot.
	* config/mips/t-mti-elf: Remove fp64 multilib.
	* config/mips/t-mti-linux: Likewise.
	* configure.ac: Detect .module support.
	* configure: Regenerate.
	* doc/invoke.texi: Document -mfpxx, -modd-spreg, -mno-odd-spreg option.
	* doc/install.texi (--with-fp-32, --with-odd-spreg-32): Document new
	options.

gcc/testsuite/
	* gcc.target/mips/args-1.c: Handle __mips_fpr == 0.
	* gcc.target/mips/call-clobbered-1.c: New.
	* gcc.target/mips/call-clobbered-2.c: New.
	* gcc.target/mips/call-clobbered-3.c: New.
	* gcc.target/mips/call-clobbered-4.c: New.
	* gcc.target/mips/call-clobbered-5.c: New.
	* gcc.target/mips/call-saved-4.c: New.
	* gcc.target/mips/call-saved-5.c: New.
	* gcc.target/mips/call-saved-6.c: New.
	* gcc.target/mips/mips.exp: Support -mfpxx, -ffixed-f*,
	and -m[no-]odd-spreg.  Use _MIPS_SPFPSET to determine default
	odd-spreg option.  Account for -modd-spreg in minimum arch code.
	* gcc.target/mips/movdf-1.c: New.
	* gcc.target/mips/movdf-2.c: New.
	* gcc.target/mips/movdf-3.c: New.
	* gcc.target/mips/oddspreg-1.c: New.
	* gcc.target/mips/oddspreg-2.c: New.
	* gcc.target/mips/oddspreg-3.c: New.
	* gcc.target/mips/oddspreg-4.c: New.
	* gcc.target/mips/oddspreg-5.c: New.
	* gcc.target/mips/oddspreg-6.c: New.

libgcc/
	* config/mips/mips16.S: Set .module when supported.  Update O32
	FP64 calling convention and use for FPXX when possible.  Add FPXX
	calling convention fallback case.

From-SVN: r217446
This commit is contained in:
Matthew Fortune 2014-11-12 21:39:46 +00:00 committed by Matthew Fortune
parent 21c767169b
commit 050af1445b
37 changed files with 955 additions and 52 deletions

View File

@ -1,3 +1,77 @@
2014-11-12 Matthew Fortune <matthew.fortune@imgtec.com>
* common/config/mips/mips-common.c (mips_handle_option): Ensure
that -mfp32, -mfp64 disable -mfpxx and -mfpxx disables -mfp64.
* config.gcc (--with-fp-32): New option.
(--with-odd-spreg-32): Likewise.
* config.in (HAVE_AS_DOT_MODULE): New config define.
* config/mips/mips-protos.h
(mips_secondary_memory_needed): New prototype.
(mips_hard_regno_caller_save_mode): Likewise.
* config/mips/mips.c (mips_get_reg_raw_mode): New static prototype.
(mips_get_arg_info): Assert that V2SFmode is only handled specially
with TARGET_PAIRED_SINGLE_FLOAT.
(mips_return_mode_in_fpr_p): Likewise.
(mips16_call_stub_mode_suffix): Likewise.
(mips_get_reg_raw_mode): New static function.
(mips_return_fpr_pair): O32 return values span two registers.
(mips16_build_call_stub): Likewise.
(mips_function_value_regno_p): Support both FP return registers.
(mips_output_64bit_xfer): Use mthc1 whenever TARGET_HAS_MXHC1. Add
specific cases for TARGET_FPXX to move via memory.
(mips_dwarf_register_span): For TARGET_FPXX pretend that modes larger
than UNITS_PER_FPREG 'span' one register.
(mips_dwarf_frame_reg_mode): New static function.
(mips_file_start): Switch to using .module instead of .gnu_attribute.
No longer support FP ABI 4 (-mips32r2 -mfp64), replace with FP ABI 6.
Add FP ABI 5 (-mfpxx) and FP ABI 7 (-mfp64 -mno-odd-spreg).
(mips_save_reg, mips_restore_reg): Always represent DFmode frame
slots with two CFI directives even for O32 FP64.
(mips_for_each_saved_gpr_and_fpr): Account for fixed_regs when
saving/restoring callee-saved registers.
(mips_hard_regno_mode_ok_p): Implement O32 FP64A extension.
(mips_secondary_memory_needed): New function.
(mips_option_override): ABI check for TARGET_FLOATXX. Disable
odd-numbered single-precision registers when using TARGET_FLOATXX.
Implement -modd-spreg and defaults.
(mips_conditional_register_usage): Redefine O32 FP64 to match O32 FP32
callee-saved behaviour.
(mips_hard_regno_caller_save_mode): Implement.
(TARGET_GET_RAW_RESULT_MODE): Define target hook.
(TARGET_GET_RAW_ARG_MODE): Define target hook.
(TARGET_DWARF_FRAME_REG_MODE): Define target hook.
* config/mips/mips.h (TARGET_FLOAT32): New macro.
(TARGET_O32_FP64A_ABI): Likewise.
(TARGET_CPU_CPP_BUILTINS): TARGET_FPXX is __mips_fpr==0. Add
_MIPS_SPFPSET builtin define.
(MIPS_FPXX_OPTION_SPEC): New macro.
(OPTION_DEFAULT_SPECS): Pass through --with-fp-32=* to -mfp and
--with-odd-spreg-32=* to -m[no-]odd-spreg.
(ISA_HAS_ODD_SPREG): New macro.
(ISA_HAS_MXHC1): True for anything other than -mfp32.
(ASM_SPEC): Pass through mfpxx, mfp64, -mno-odd-spreg and -modd-spreg.
(MIN_FPRS_PER_FMT): Redefine in terms of TARGET_ODD_SPREG.
(HARD_REGNO_CALLER_SAVE_MODE): Define. Implement O32 FPXX extension
(HARD_REGNO_CALL_PART_CLOBBERED): Likewise.
(SECONDARY_MEMORY_NEEDED): Likewise.
(FUNCTION_ARG_REGNO_P): Update for O32 FPXX and FP64 extensions.
* config/mips/mips.md (define_attr enabled): Implement O32 FPXX and
FP64A ABI extensions.
(move_doubleword_fpr<mode>): Use ISA_HAS_MXHC1 instead of
TARGET_FLOAT64.
* config/mips/mips.opt (mfpxx): New target option.
(modd-spreg): Likewise.
* config/mips/mti-elf.h (DRIVER_SELF_SPECS): Infer FP ABI from arch.
* config/mips/mti-linux.h (DRIVER_SELF_SPECS): Likewise and remove
fp64 sysroot.
* config/mips/t-mti-elf: Remove fp64 multilib.
* config/mips/t-mti-linux: Likewise.
* configure.ac: Detect .module support.
* configure: Regenerate.
* doc/invoke.texi: Document -mfpxx, -modd-spreg, -mno-odd-spreg option.
* doc/install.texi (--with-fp-32, --with-odd-spreg-32): Document new
options.
2014-11-12 H.J. Lu <hongjiu.lu@intel.com>
PR target/63815

View File

@ -42,6 +42,15 @@ mips_handle_option (struct gcc_options *opts,
opts->x_mips_cache_flush_func = NULL;
return true;
case OPT_mfp32:
case OPT_mfp64:
opts->x_target_flags &= ~MASK_FLOATXX;
return true;
case OPT_mfpxx:
opts->x_target_flags &= ~MASK_FLOAT64;
return true;
default:
return true;
}

View File

@ -3754,7 +3754,7 @@ case "${target}" in
;;
mips*-*-*)
supported_defaults="abi arch arch_32 arch_64 float fpu nan tune tune_32 tune_64 divide llsc mips-plt synci"
supported_defaults="abi arch arch_32 arch_64 float fpu nan fp_32 odd_spreg_32 tune tune_32 tune_64 divide llsc mips-plt synci"
case ${with_float} in
"" | soft | hard)
@ -3786,6 +3786,32 @@ case "${target}" in
;;
esac
case ${with_fp_32} in
"" | 32 | xx | 64)
# OK
;;
*)
echo "Unknown FP mode used in --with-fp-32=$with_fp_32" 1>&2
exit 1
;;
esac
case ${with_odd_spreg_32} in
yes)
with_odd_spreg_32="odd-spreg"
;;
no)
with_odd_spreg_32="no-odd-spreg"
;;
"")
# OK
;;
*)
echo "Unknown odd-spreg-32 type used in --with-odd-spreg-32=$with_odd_spreg_32" 1>&2
exit 1
;;
esac
case ${with_abi} in
"" | 32 | o64 | n32 | 64 | eabi)
# OK
@ -4213,7 +4239,7 @@ case ${target} in
esac
t=
all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu nan divide llsc mips-plt synci tls"
all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu nan fp_32 odd_spreg_32 divide llsc mips-plt synci tls"
for option in $all_defaults
do
eval "val=\$with_"`echo $option | sed s/-/_/g`

View File

@ -472,6 +472,12 @@
#endif
/* Define if the assembler understands .module. */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_DOT_MODULE
#endif
/* Define if your assembler supports the -no-mul-bug-abort option. */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_NO_MUL_BUG_ABORT_OPTION

View File

@ -278,6 +278,8 @@ extern void mips_expand_before_return (void);
extern void mips_expand_epilogue (bool);
extern bool mips_can_use_return_insn (void);
extern bool mips_secondary_memory_needed (enum reg_class, enum reg_class,
machine_mode);
extern bool mips_cannot_change_mode_class (machine_mode,
machine_mode, enum reg_class);
extern bool mips_dangerous_for_la25_p (rtx);
@ -287,6 +289,9 @@ extern enum reg_class mips_secondary_reload_class (enum reg_class,
rtx, bool);
extern int mips_class_max_nregs (enum reg_class, machine_mode);
extern machine_mode mips_hard_regno_caller_save_mode (unsigned int,
unsigned int,
machine_mode);
extern int mips_adjust_insn_length (rtx_insn *, int);
extern void mips_output_load_label (rtx);
extern const char *mips_output_conditional_branch (rtx_insn *, rtx *,

View File

@ -1232,6 +1232,7 @@ static rtx mips_find_pic_call_symbol (rtx_insn *, rtx, bool);
static int mips_register_move_cost (machine_mode, reg_class_t,
reg_class_t);
static unsigned int mips_function_arg_boundary (machine_mode, const_tree);
static machine_mode mips_get_reg_raw_mode (int regno);
struct mips16_flip_traits : default_hashmap_traits
{
@ -5160,6 +5161,7 @@ mips_get_arg_info (struct mips_arg_info *info, const CUMULATIVE_ARGS *cum,
/* Only leading floating-point scalars are passed in
floating-point registers. We also handle vector floats the same
say, which is OK because they are not covered by the standard ABI. */
gcc_assert (TARGET_PAIRED_SINGLE_FLOAT || mode != V2SFmode);
info->fpr_p = (!cum->gp_reg_found
&& cum->arg_number < 2
&& (type == 0
@ -5175,6 +5177,7 @@ mips_get_arg_info (struct mips_arg_info *info, const CUMULATIVE_ARGS *cum,
/* Scalar, complex and vector floating-point types are passed in
floating-point registers, as long as this is a named rather
than a variable argument. */
gcc_assert (TARGET_PAIRED_SINGLE_FLOAT || mode != V2SFmode);
info->fpr_p = (named
&& (type == 0 || FLOAT_TYPE_P (type))
&& (GET_MODE_CLASS (mode) == MODE_FLOAT
@ -5458,6 +5461,16 @@ mips_function_arg_boundary (machine_mode mode, const_tree type)
return alignment;
}
/* Implement TARGET_GET_RAW_RESULT_MODE and TARGET_GET_RAW_ARG_MODE. */
static machine_mode
mips_get_reg_raw_mode (int regno)
{
if (TARGET_FLOATXX && FP_REG_P (regno))
return DFmode;
return default_get_reg_raw_mode (regno);
}
/* Return true if FUNCTION_ARG_PADDING (MODE, TYPE) should return
upward rather than downward. In other words, return true if the
first byte of the stack slot has useful data, false if the last
@ -5615,6 +5628,7 @@ mips_return_in_msb (const_tree valtype)
static bool
mips_return_mode_in_fpr_p (machine_mode mode)
{
gcc_assert (TARGET_PAIRED_SINGLE_FLOAT || mode != V2SFmode);
return ((GET_MODE_CLASS (mode) == MODE_FLOAT
|| mode == V2SFmode
|| GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
@ -5661,7 +5675,7 @@ mips_return_fpr_pair (machine_mode mode,
{
int inc;
inc = (TARGET_NEWABI ? 2 : MAX_FPRS_PER_FMT);
inc = (TARGET_NEWABI || mips_abi == ABI_32 ? 2 : MAX_FPRS_PER_FMT);
return gen_rtx_PARALLEL
(mode,
gen_rtvec (2,
@ -5777,19 +5791,31 @@ mips_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
/* Implement TARGET_FUNCTION_VALUE_REGNO_P.
On the MIPS, R2 R3 and F0 F2 are the only register thus used.
Currently, R2 and F0 are only implemented here (C has no complex type). */
On the MIPS, R2 R3 and F0 F2 are the only register thus used. */
static bool
mips_function_value_regno_p (const unsigned int regno)
{
/* Most types only require one GPR or one FPR for return values but for
hard-float two FPRs can be used for _Complex types (for all ABIs)
and long doubles (for n64). */
if (regno == GP_RETURN
|| regno == FP_RETURN
|| (LONG_DOUBLE_TYPE_SIZE == 128
&& FP_RETURN != GP_RETURN
|| (FP_RETURN != GP_RETURN
&& regno == FP_RETURN + 2))
return true;
/* For o32 FP32, _Complex double will be returned in four 32-bit registers.
This does not apply to o32 FPXX as floating-point function argument and
return registers are described as 64-bit even though floating-point
registers are primarily described as 32-bit internally.
See: mips_get_reg_raw_mode. */
if ((mips_abi == ABI_32 && TARGET_FLOAT32)
&& FP_RETURN != GP_RETURN
&& (regno == FP_RETURN + 1
|| regno == FP_RETURN + 3))
return true;
return false;
}
@ -6497,7 +6523,10 @@ mips16_call_stub_mode_suffix (machine_mode mode)
else if (mode == DCmode)
return "dc";
else if (mode == V2SFmode)
return "df";
{
gcc_assert (TARGET_PAIRED_SINGLE_FLOAT);
return "df";
}
else
gcc_unreachable ();
}
@ -6521,13 +6550,27 @@ mips_output_64bit_xfer (char direction, unsigned int gpreg, unsigned int fpreg)
if (TARGET_64BIT)
fprintf (asm_out_file, "\tdm%cc1\t%s,%s\n", direction,
reg_names[gpreg], reg_names[fpreg]);
else if (TARGET_FLOAT64)
else if (ISA_HAS_MXHC1)
{
fprintf (asm_out_file, "\tm%cc1\t%s,%s\n", direction,
reg_names[gpreg + TARGET_BIG_ENDIAN], reg_names[fpreg]);
fprintf (asm_out_file, "\tm%chc1\t%s,%s\n", direction,
reg_names[gpreg + TARGET_LITTLE_ENDIAN], reg_names[fpreg]);
}
else if (TARGET_FLOATXX && direction == 't')
{
/* Use the argument save area to move via memory. */
fprintf (asm_out_file, "\tsw\t%s,0($sp)\n", reg_names[gpreg]);
fprintf (asm_out_file, "\tsw\t%s,4($sp)\n", reg_names[gpreg + 1]);
fprintf (asm_out_file, "\tldc1\t%s,0($sp)\n", reg_names[fpreg]);
}
else if (TARGET_FLOATXX && direction == 'f')
{
/* Use the argument save area to move via memory. */
fprintf (asm_out_file, "\tsdc1\t%s,0($sp)\n", reg_names[fpreg]);
fprintf (asm_out_file, "\tlw\t%s,0($sp)\n", reg_names[gpreg]);
fprintf (asm_out_file, "\tlw\t%s,4($sp)\n", reg_names[gpreg + 1]);
}
else
{
/* Move the least-significant word. */
@ -6935,11 +6978,11 @@ mips16_build_call_stub (rtx retval, rtx *fn_ptr, rtx args_size, int fp_code)
case SCmode:
mips_output_32bit_xfer ('f', GP_RETURN + TARGET_BIG_ENDIAN,
TARGET_BIG_ENDIAN
? FP_REG_FIRST + MAX_FPRS_PER_FMT
? FP_REG_FIRST + 2
: FP_REG_FIRST);
mips_output_32bit_xfer ('f', GP_RETURN + TARGET_LITTLE_ENDIAN,
TARGET_LITTLE_ENDIAN
? FP_REG_FIRST + MAX_FPRS_PER_FMT
? FP_REG_FIRST + 2
: FP_REG_FIRST);
if (GET_MODE (retval) == SCmode && TARGET_64BIT)
{
@ -6968,10 +7011,12 @@ mips16_build_call_stub (rtx retval, rtx *fn_ptr, rtx args_size, int fp_code)
case DCmode:
mips_output_64bit_xfer ('f', GP_RETURN + (8 / UNITS_PER_WORD),
FP_REG_FIRST + MAX_FPRS_PER_FMT);
FP_REG_FIRST + 2);
/* Fall though. */
case DFmode:
case V2SFmode:
gcc_assert (TARGET_PAIRED_SINGLE_FLOAT
|| GET_MODE (retval) != V2SFmode);
mips_output_64bit_xfer ('f', GP_RETURN, FP_REG_FIRST);
break;
@ -8682,14 +8727,28 @@ mips_dwarf_register_span (rtx reg)
rtx high, low;
machine_mode mode;
/* TARGET_FLOATXX is implemented as 32-bit floating-point registers but
ensures that double-precision registers are treated as if they were
64-bit physical registers. The code will run correctly with 32-bit or
64-bit registers which means that dwarf information cannot be precise
for all scenarios. We choose to state that the 64-bit values are stored
in a single 64-bit 'piece'. This slightly unusual construct can then be
interpreted as either a pair of registers if the registers are 32-bit or
a single 64-bit register depending on hardware. */
mode = GET_MODE (reg);
if (FP_REG_P (REGNO (reg))
&& TARGET_FLOATXX
&& GET_MODE_SIZE (mode) > UNITS_PER_FPREG)
{
return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, reg));
}
/* By default, GCC maps increasing register numbers to increasing
memory locations, but paired FPRs are always little-endian,
regardless of the prevailing endianness. */
mode = GET_MODE (reg);
if (FP_REG_P (REGNO (reg))
&& TARGET_BIG_ENDIAN
&& MAX_FPRS_PER_FMT > 1
&& GET_MODE_SIZE (mode) > UNITS_PER_FPREG)
else if (FP_REG_P (REGNO (reg))
&& TARGET_BIG_ENDIAN
&& MAX_FPRS_PER_FMT > 1
&& GET_MODE_SIZE (mode) > UNITS_PER_FPREG)
{
gcc_assert (GET_MODE_SIZE (mode) == UNITS_PER_HWFPVALUE);
high = mips_subword (reg, true);
@ -8700,6 +8759,19 @@ mips_dwarf_register_span (rtx reg)
return NULL_RTX;
}
/* Implement TARGET_DWARF_FRAME_REG_MODE. */
static machine_mode
mips_dwarf_frame_reg_mode (int regno)
{
machine_mode mode = default_dwarf_frame_reg_mode (regno);
if (FP_REG_P (regno) && mips_abi == ABI_32 && TARGET_FLOAT64)
mode = SImode;
return mode;
}
/* DSP ALU can bypass data with no delays for the following pairs. */
enum insn_code dspalu_bypass_table[][2] =
{
@ -8979,6 +9051,31 @@ mips_file_start (void)
fprintf (asm_out_file, "\t.nan\t%s\n",
mips_nan == MIPS_IEEE_754_2008 ? "2008" : "legacy");
#ifdef HAVE_AS_DOT_MODULE
/* Record the FP ABI. See below for comments. */
if (TARGET_NO_FLOAT)
#ifdef HAVE_AS_GNU_ATTRIBUTE
fputs ("\t.gnu_attribute 4, 0\n", asm_out_file);
#else
;
#endif
else if (!TARGET_HARD_FLOAT_ABI)
fputs ("\t.module\tsoftfloat\n", asm_out_file);
else if (!TARGET_DOUBLE_FLOAT)
fputs ("\t.module\tsinglefloat\n", asm_out_file);
else if (TARGET_FLOATXX)
fputs ("\t.module\tfp=xx\n", asm_out_file);
else if (TARGET_FLOAT64)
fputs ("\t.module\tfp=64\n", asm_out_file);
else
fputs ("\t.module\tfp=32\n", asm_out_file);
if (TARGET_ODD_SPREG)
fputs ("\t.module\toddspreg\n", asm_out_file);
else
fputs ("\t.module\tnooddspreg\n", asm_out_file);
#else
#ifdef HAVE_AS_GNU_ATTRIBUTE
{
int attr;
@ -8992,15 +9089,26 @@ mips_file_start (void)
/* Single-float code, -msingle-float. */
else if (!TARGET_DOUBLE_FLOAT)
attr = 2;
/* 64-bit FP registers on a 32-bit target, -mips32r2 -mfp64. */
else if (!TARGET_64BIT && TARGET_FLOAT64)
attr = 4;
/* 64-bit FP registers on a 32-bit target, -mips32r2 -mfp64.
Reserved attr=4.
This case used 12 callee-saved double-precision registers
and is deprecated. */
/* 64-bit or 32-bit FP registers on a 32-bit target, -mfpxx. */
else if (TARGET_FLOATXX)
attr = 5;
/* 64-bit FP registers on a 32-bit target, -mfp64 -modd-spreg. */
else if (mips_abi == ABI_32 && TARGET_FLOAT64 && TARGET_ODD_SPREG)
attr = 6;
/* 64-bit FP registers on a 32-bit target, -mfp64 -mno-odd-spreg. */
else if (mips_abi == ABI_32 && TARGET_FLOAT64)
attr = 7;
/* Regular FP code, FP regs same size as GP regs, -mdouble-float. */
else
attr = 1;
fprintf (asm_out_file, "\t.gnu_attribute 4, %d\n", attr);
}
#endif
#endif
/* If TARGET_ABICALLS, tell GAS to generate -KPIC code. */
@ -10491,7 +10599,9 @@ mips_for_each_saved_acc (HOST_WIDE_INT sp_offset, mips_save_restore_fn fn)
static void
mips_save_reg (rtx reg, rtx mem)
{
if (GET_MODE (reg) == DFmode && !TARGET_FLOAT64)
if (GET_MODE (reg) == DFmode
&& (!TARGET_FLOAT64
|| mips_abi == ABI_32))
{
rtx x1, x2;
@ -10649,7 +10759,16 @@ mips_for_each_saved_gpr_and_fpr (HOST_WIDE_INT sp_offset,
regno -= MAX_FPRS_PER_FMT)
if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
{
mips_save_restore_reg (fpr_mode, regno, offset, fn);
if (!TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT
&& (fixed_regs[regno] || fixed_regs[regno + 1]))
{
if (fixed_regs[regno])
mips_save_restore_reg (SFmode, regno + 1, offset, fn);
else
mips_save_restore_reg (SFmode, regno, offset, fn);
}
else
mips_save_restore_reg (fpr_mode, regno, offset, fn);
offset -= GET_MODE_SIZE (fpr_mode);
}
}
@ -11420,7 +11539,9 @@ mips_restore_reg (rtx reg, rtx mem)
$7 instead and adjust the return insn appropriately. */
if (TARGET_MIPS16 && REGNO (reg) == RETURN_ADDR_REGNUM)
reg = gen_rtx_REG (GET_MODE (reg), GP_REG_FIRST + 7);
else if (GET_MODE (reg) == DFmode && !TARGET_FLOAT64)
else if (GET_MODE (reg) == DFmode
&& (!TARGET_FLOAT64
|| mips_abi == ABI_32))
{
mips_add_cfa_restore (mips_subword (reg, true));
mips_add_cfa_restore (mips_subword (reg, false));
@ -11770,6 +11891,11 @@ mips_hard_regno_mode_ok_p (unsigned int regno, machine_mode mode)
&& (((regno - FP_REG_FIRST) % MAX_FPRS_PER_FMT) == 0
|| (MIN_FPRS_PER_FMT == 1 && size <= UNITS_PER_FPREG)))
{
/* Deny use of odd-numbered registers for 32-bit data for
the o32 FP64A ABI. */
if (TARGET_O32_FP64A_ABI && size <= 4 && (regno & 1) != 0)
return false;
/* Allow 64-bit vector modes for Loongson-2E/2F. */
if (TARGET_LOONGSON_VECTORS
&& (mode == V2SImode
@ -12124,6 +12250,25 @@ mips_memory_move_cost (machine_mode mode, reg_class_t rclass, bool in)
+ memory_move_secondary_cost (mode, rclass, in));
}
/* Implement SECONDARY_MEMORY_NEEDED. */
bool
mips_secondary_memory_needed (enum reg_class class1, enum reg_class class2,
machine_mode mode)
{
/* Ignore spilled pseudos. */
if (lra_in_progress && (class1 == NO_REGS || class2 == NO_REGS))
return false;
if (((class1 == FP_REGS) != (class2 == FP_REGS))
&& ((TARGET_FLOATXX && !ISA_HAS_MXHC1)
|| TARGET_O32_FP64A_ABI)
&& GET_MODE_SIZE (mode) >= 8)
return true;
return false;
}
/* Return the register class required for a secondary register when
copying between one of the registers in RCLASS and value X, which
has mode MODE. X is the source of the move if IN_P, otherwise it
@ -17041,6 +17186,13 @@ mips_option_override (void)
target_flags &= ~MASK_FLOAT64;
}
if (mips_abi != ABI_32 && TARGET_FLOATXX)
error ("%<-mfpxx%> can only be used with the o32 ABI");
else if (ISA_MIPS1 && !TARGET_FLOAT32)
error ("%<-march=%s%> requires %<-mfp32%>", mips_arch_info->name);
else if (TARGET_FLOATXX && !mips_lra_flag)
error ("%<-mfpxx%> requires %<-mlra%>");
/* End of code shared with GAS. */
/* The R5900 FPU only supports single precision. */
@ -17128,6 +17280,28 @@ mips_option_override (void)
warning (0, "the %qs architecture does not support madd or msub"
" instructions", mips_arch_info->name);
/* If neither -modd-spreg nor -mno-odd-spreg was given on the command
line, set MASK_ODD_SPREG based on the ISA and ABI. */
if ((target_flags_explicit & MASK_ODD_SPREG) == 0)
{
/* Disable TARGET_ODD_SPREG when using the o32 FPXX ABI. */
if (!ISA_HAS_ODD_SPREG || TARGET_FLOATXX)
target_flags &= ~MASK_ODD_SPREG;
else
target_flags |= MASK_ODD_SPREG;
}
else if (TARGET_ODD_SPREG && !ISA_HAS_ODD_SPREG)
warning (0, "the %qs architecture does not support odd single-precision"
" registers", mips_arch_info->name);
if (!TARGET_ODD_SPREG && TARGET_64BIT)
{
error ("unsupported combination: %s", "-mgp64 -mno-odd-spreg");
/* Allow compilation to continue further even though invalid output
will be produced. */
target_flags |= MASK_ODD_SPREG;
}
/* The effect of -mabicalls isn't defined for the EABI. */
if (mips_abi == ABI_EABI && TARGET_ABICALLS)
{
@ -17490,8 +17664,10 @@ mips_conditional_register_usage (void)
call_really_used_regs[regno] = call_used_regs[regno] = 1;
}
/* Odd registers in the range $f21-$f31 (inclusive) are call-clobbered
for n32. */
if (mips_abi == ABI_N32)
for n32 and o32 FP64. */
if (mips_abi == ABI_N32
|| (mips_abi == ABI_32
&& TARGET_FLOAT64))
{
int regno;
for (regno = FP_REG_FIRST + 21; regno <= FP_REG_FIRST + 31; regno+=2)
@ -18824,6 +19000,21 @@ mips_expand_vec_minmax (rtx target, rtx op0, rtx op1,
emit_insn (gen_rtx_SET (VOIDmode, target, x));
}
/* Implement HARD_REGNO_CALLER_SAVE_MODE. */
machine_mode
mips_hard_regno_caller_save_mode (unsigned int regno,
unsigned int nregs,
machine_mode mode)
{
/* For performance, avoid saving/restoring upper parts of a register
by returning MODE as save mode when the mode is known. */
if (mode == VOIDmode)
return choose_hard_reg_mode (regno, nregs, false);
else
return mode;
}
/* Implement TARGET_CASE_VALUES_THRESHOLD. */
unsigned int
@ -19043,6 +19234,10 @@ mips_lra_p (void)
#define TARGET_FUNCTION_ARG_ADVANCE mips_function_arg_advance
#undef TARGET_FUNCTION_ARG_BOUNDARY
#define TARGET_FUNCTION_ARG_BOUNDARY mips_function_arg_boundary
#undef TARGET_GET_RAW_RESULT_MODE
#define TARGET_GET_RAW_RESULT_MODE mips_get_reg_raw_mode
#undef TARGET_GET_RAW_ARG_MODE
#define TARGET_GET_RAW_ARG_MODE mips_get_reg_raw_mode
#undef TARGET_MODE_REP_EXTENDED
#define TARGET_MODE_REP_EXTENDED mips_mode_rep_extended
@ -19099,6 +19294,8 @@ mips_lra_p (void)
#endif
#undef TARGET_DWARF_REGISTER_SPAN
#define TARGET_DWARF_REGISTER_SPAN mips_dwarf_register_span
#undef TARGET_DWARF_FRAME_REG_MODE
#define TARGET_DWARF_FRAME_REG_MODE mips_dwarf_frame_reg_mode
#undef TARGET_ASM_FINAL_POSTSCAN_INSN
#define TARGET_ASM_FINAL_POSTSCAN_INSN mips_final_postscan_insn

View File

@ -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

View File

@ -433,11 +433,17 @@
(const_string "none"))
(define_attr "enabled" "no,yes"
(if_then_else (ior (eq_attr "compression" "all,none")
(and (eq_attr "compression" "micromips")
(match_test "TARGET_MICROMIPS")))
(const_string "yes")
(const_string "no")))
(cond [;; The o32 FPXX and FP64A ABI extensions prohibit direct moves between
;; GR_REG and FR_REG for 64-bit values.
(and (eq_attr "move_type" "mtc,mfc")
(match_test "(TARGET_FLOATXX && !ISA_HAS_MXHC1)
|| TARGET_O32_FP64A_ABI")
(eq_attr "dword_mode" "yes"))
(const_string "no")
(and (eq_attr "compression" "micromips")
(match_test "!TARGET_MICROMIPS"))
(const_string "no")]
(const_string "yes")))
;; The number of individual instructions that a non-branch pattern generates,
;; using units of BASE_INSN_LENGTH.
@ -4997,7 +5003,7 @@
rtx low = mips_subword (operands[1], 0);
rtx high = mips_subword (operands[1], 1);
emit_insn (gen_load_low<mode> (operands[0], low));
if (TARGET_FLOAT64 && !TARGET_64BIT)
if (ISA_HAS_MXHC1 && !TARGET_64BIT)
emit_insn (gen_mthc1<mode> (operands[0], high, operands[0]));
else
emit_insn (gen_load_high<mode> (operands[0], high, operands[0]));
@ -5007,7 +5013,7 @@
rtx low = mips_subword (operands[0], 0);
rtx high = mips_subword (operands[0], 1);
emit_insn (gen_store_word<mode> (low, operands[1], const0_rtx));
if (TARGET_FLOAT64 && !TARGET_64BIT)
if (ISA_HAS_MXHC1 && !TARGET_64BIT)
emit_insn (gen_mfhc1<mode> (high, operands[1]));
else
emit_insn (gen_store_word<mode> (high, operands[1], const1_rtx));

View File

@ -197,6 +197,10 @@ mfp32
Target Report RejectNegative InverseMask(FLOAT64)
Use 32-bit floating-point registers
mfpxx
Target Report RejectNegative Mask(FLOATXX)
Conform to the o32 FPXX ABI
mfp64
Target Report RejectNegative Mask(FLOAT64)
Use 64-bit floating-point registers
@ -408,5 +412,9 @@ mxgot
Target Report Var(TARGET_XGOT)
Lift restrictions on GOT size
modd-spreg
Target Report Mask(ODD_SPREG)
Enable use of odd-numbered single-precision registers
noasmopt
Driver

View File

@ -34,6 +34,11 @@ along with GCC; see the file COPYING3. If not see
or -mgp setting. */ \
"%{!mabi=*: %{" MIPS_32BIT_OPTION_SPEC ": -mabi=32;: -mabi=n32}}", \
\
/* If no FP ABI option is specified, infer one from the \
ABI/ISA level. */ \
"%{!msoft-float: %{!msingle-float: %{!mfp*: %{mabi=32: %{" \
MIPS_FPXX_OPTION_SPEC ": -mfpxx}}}}}", \
\
/* Make sure that an endian option is always present. This makes \
things like LINK_SPEC easier to write. */ \
"%{!EB:%{!EL:%(endian_spec)}}", \

View File

@ -39,6 +39,11 @@ along with GCC; see the file COPYING3. If not see
or -mgp setting. */ \
"%{!mabi=*: %{" MIPS_32BIT_OPTION_SPEC ": -mabi=32;: -mabi=n32}}", \
\
/* If no FP ABI option is specified, infer one from the \
ABI/ISA level. */ \
"%{!msoft-float: %{!msingle-float: %{!mfp*: %{mabi=32: %{" \
MIPS_FPXX_OPTION_SPEC ": -mfpxx}}}}}", \
\
/* Base SPECs. */ \
BASE_DRIVER_SELF_SPECS \
\

35
gcc/configure vendored
View File

@ -26152,6 +26152,41 @@ $as_echo "#define HAVE_AS_GNU_ATTRIBUTE 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .module support" >&5
$as_echo_n "checking assembler for .module support... " >&6; }
if test "${gcc_cv_as_mips_dot_module+set}" = set; then :
$as_echo_n "(cached) " >&6
else
gcc_cv_as_mips_dot_module=no
if test x$gcc_cv_as != x; then
$as_echo '.module fp=32' > conftest.s
if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
gcc_cv_as_mips_dot_module=yes
else
echo "configure: failed program was" >&5
cat conftest.s >&5
fi
rm -f conftest.o conftest.s
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_mips_dot_module" >&5
$as_echo "$gcc_cv_as_mips_dot_module" >&6; }
if test $gcc_cv_as_mips_dot_module = yes; then
$as_echo "#define HAVE_AS_DOT_MODULE 1" >>confdefs.h
fi
if test x$gcc_cv_as_mips_dot_module = xno \
&& test x$with_fp_32 != x; then
as_fn_error "Requesting --with-fp-32= requires assembler support for .module." "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .micromips support" >&5
$as_echo_n "checking assembler for .micromips support... " >&6; }
if test "${gcc_cv_as_micromips_support+set}" = set; then :

View File

@ -4241,6 +4241,17 @@ LCF0:
[AC_DEFINE(HAVE_AS_GNU_ATTRIBUTE, 1,
[Define if your assembler supports .gnu_attribute.])])
gcc_GAS_CHECK_FEATURE([.module support],
gcc_cv_as_mips_dot_module,,,
[.module fp=32],,
[AC_DEFINE(HAVE_AS_DOT_MODULE, 1,
[Define if your assembler supports .module.])])
if test x$gcc_cv_as_mips_dot_module = xno \
&& test x$with_fp_32 != x; then
AC_MSG_ERROR(
[Requesting --with-fp-32= requires assembler support for .module.])
fi
gcc_GAS_CHECK_FEATURE([.micromips support],
gcc_cv_as_micromips_support,,[--fatal-warnings],
[.set micromips],,

View File

@ -1261,6 +1261,32 @@ ISA for floating-point arithmetics. You can select either @samp{sse} which
enables @option{-msse2} or @samp{avx} which enables @option{-mavx} by default.
This option is only supported on i386 and x86-64 targets.
@item --with-fp-32=@var{mode}
On MIPS targets, set the default value for the @option{-mfp} option when using
the o32 ABI. The possibilities for @var{mode} are:
@table @code
@item 32
Use the o32 FP32 ABI extension, as with the @option{-mfp32} command-line
option.
@item xx
Use the o32 FPXX ABI extension, as with the @option{-mfpxx} command-line
option.
@item 64
Use the o32 FP64 ABI extension, as with the @option{-mfp64} command-line
option.
@end table
In the absence of this configuration option the default is to use the o32
FP32 ABI extension.
@item --with-odd-spreg-32
On MIPS targets, set the @option{-modd-spreg} option by default when using
the o32 ABI.
@item --without-odd-spreg-32
On MIPS targets, set the @option{-mno-odd-spreg} option by default when using
the o32 ABI. This is normally used in conjunction with
@option{--with-fp-32=64} in order to target the o32 FP64A ABI extension.
@item --with-nan=@var{encoding}
On MIPS targets, set the default encoding convention to use for the
special not-a-number (NaN) IEEE 754 floating-point data. The

View File

@ -788,8 +788,9 @@ Objective-C and Objective-C++ Dialects}.
-minterlink-mips16 -mno-interlink-mips16 @gol
-mabi=@var{abi} -mabicalls -mno-abicalls @gol
-mshared -mno-shared -mplt -mno-plt -mxgot -mno-xgot @gol
-mgp32 -mgp64 -mfp32 -mfp64 -mhard-float -msoft-float @gol
-mgp32 -mgp64 -mfp32 -mfpxx -mfp64 -mhard-float -msoft-float @gol
-mno-float -msingle-float -mdouble-float @gol
-modd-spreg -mno-odd-spreg @gol
-mabs=@var{mode} -mnan=@var{encoding} @gol
-mdsp -mno-dsp -mdspr2 -mno-dspr2 @gol
-mmcu -mmno-mcu @gol
@ -17745,7 +17746,20 @@ same, but each scalar value is passed in a single 64-bit register
rather than a pair of 32-bit registers. For example, scalar
floating-point values are returned in @samp{$f0} only, not a
@samp{$f0}/@samp{$f1} pair. The set of call-saved registers also
remains the same, but all 64 bits are saved.
remains the same in that the even-numbered double-precision registers
are saved.
Two additional variants of the o32 ABI are supported to enable
a transition from 32-bit to 64-bit registers. These are FPXX
(@option{-mfpxx}) and FP64A (@option{-mfp64} @option{-mno-odd-spreg}).
The FPXX extension mandates that all code must execute correctly
when run using 32-bit or 64-bit registers. The code can be interlinked
with either FP32 or FP64, but not both.
The FP64A extension is similar to the FP64 extension but forbids the
use of odd-numbered single-precision registers. This can be used
in conjunction with the @code{FRE} mode of FPUs in MIPS32R5
processors and allows both FP32 and FP64A code to interlink and
run in the same process without changing FPU modes.
@item -mabicalls
@itemx -mno-abicalls
@ -17834,6 +17848,10 @@ Assume that floating-point registers are 32 bits wide.
@opindex mfp64
Assume that floating-point registers are 64 bits wide.
@item -mfpxx
@opindex mfpxx
Do not assume the width of floating-point registers.
@item -mhard-float
@opindex mhard-float
Use floating-point coprocessor instructions.
@ -17865,6 +17883,15 @@ operations.
Assume that the floating-point coprocessor supports double-precision
operations. This is the default.
@item -modd-spreg
@itemx -mno-odd-spreg
@opindex modd-spreg
@opindex mno-odd-spreg
Enable the use of odd-numbered single-precision floating-point registers
for the o32 ABI. This is the default for processors that are known to
support these registers. When using the o32 FPXX ABI, @code{-mno-odd-spreg}
is set by default.
@item -mabs=2008
@itemx -mabs=legacy
@opindex mabs=2008

View File

@ -1,3 +1,27 @@
2014-11-12 Matthew Fortune <matthew.fortune@imgtec.com>
* gcc.target/mips/args-1.c: Handle __mips_fpr == 0.
* gcc.target/mips/call-clobbered-1.c: New.
* gcc.target/mips/call-clobbered-2.c: New.
* gcc.target/mips/call-clobbered-3.c: New.
* gcc.target/mips/call-clobbered-4.c: New.
* gcc.target/mips/call-clobbered-5.c: New.
* gcc.target/mips/call-saved-4.c: New.
* gcc.target/mips/call-saved-5.c: New.
* gcc.target/mips/call-saved-6.c: New.
* gcc.target/mips/mips.exp: Support -mfpxx, -ffixed-f*,
and -m[no-]odd-spreg. Use _MIPS_SPFPSET to determine default
odd-spreg option. Account for -modd-spreg in minimum arch code.
* gcc.target/mips/movdf-1.c: New.
* gcc.target/mips/movdf-2.c: New.
* gcc.target/mips/movdf-3.c: New.
* gcc.target/mips/oddspreg-1.c: New.
* gcc.target/mips/oddspreg-2.c: New.
* gcc.target/mips/oddspreg-3.c: New.
* gcc.target/mips/oddspreg-4.c: New.
* gcc.target/mips/oddspreg-5.c: New.
* gcc.target/mips/oddspreg-6.c: New.
2014-11-12 H.J. Lu <hongjiu.lu@intel.com>
PR target/63815

View File

@ -5,7 +5,7 @@
const char *compiled_for = _MIPS_ARCH;
const char *optimized_for = _MIPS_TUNE;
#if __mips_fpr != 32 && __mips_fpr != 64
#if __mips_fpr != 32 && __mips_fpr != 64 && __mips_fpr != 0
#error Bad __mips_fpr
#endif

View File

@ -0,0 +1,21 @@
/* Check that we handle call-clobbered FPRs correctly. */
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
/* { dg-options "isa>=2 -mabi=32 -ffixed-f0 -ffixed-f1 -ffixed-f2 -ffixed-f3 -ffixed-f4 -ffixed-f5 -ffixed-f6 -ffixed-f7 -ffixed-f8 -ffixed-f9 -ffixed-f10 -ffixed-f11 -ffixed-f12 -ffixed-f13 -ffixed-f14 -ffixed-f15 -ffixed-f16 -ffixed-f17 -ffixed-f18 -ffixed-f19" } */
void bar (void);
double a;
double
foo ()
{
double b = a + 1.0;
bar();
return b;
}
/* { dg-final { scan-assembler-not "lwc1" } } */
/* { dg-final { scan-assembler-not "swc1" } } */
/* { dg-final { scan-assembler-times "sdc1" 2 } } */
/* { dg-final { scan-assembler-times "ldc1" 4 } } */
/* { dg-final { scan-assembler-not "mtc" } } */
/* { dg-final { scan-assembler-not "mfc" } } */
/* { dg-final { scan-assembler-not "mthc" } } */
/* { dg-final { scan-assembler-not "mfhc" } } */

View File

@ -0,0 +1,21 @@
/* Check that we handle call-clobbered FPRs correctly. */
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
/* { dg-options "-mabi=32 -modd-spreg -mfp32 -ffixed-f0 -ffixed-f1 -ffixed-f2 -ffixed-f3 -ffixed-f4 -ffixed-f5 -ffixed-f6 -ffixed-f7 -ffixed-f8 -ffixed-f9 -ffixed-f10 -ffixed-f11 -ffixed-f12 -ffixed-f13 -ffixed-f14 -ffixed-f15 -ffixed-f16 -ffixed-f17 -ffixed-f18 -ffixed-f19 -ffixed-f20 -ffixed-f22 -ffixed-f24 -ffixed-f26 -ffixed-f28 -ffixed-f30" } */
void bar (void);
float a;
float
foo ()
{
float b = a + 1.0f;
bar();
return b;
}
/* { dg-final { scan-assembler-times "lwc1" 4 } } */
/* { dg-final { scan-assembler-times "swc1" 2 } } */
/* { dg-final { scan-assembler-not "mtc" } } */
/* { dg-final { scan-assembler-not "mfc" } } */
/* { dg-final { scan-assembler-not "mthc" } } */
/* { dg-final { scan-assembler-not "mfhc" } } */
/* { dg-final { scan-assembler-not "sdc1" } } */
/* { dg-final { scan-assembler-not "ldc1" } } */

View File

@ -0,0 +1,23 @@
/* Check that we handle call-clobbered FPRs correctly. */
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
/* Refer to call-clobbered-4.c to see the expected output from -Os builds. */
/* { dg-skip-if "uses callee-saved GPR" { *-*-* } { "-Os" } { "" } } */
/* { dg-options "-mabi=32 -modd-spreg -mfpxx -ffixed-f0 -ffixed-f1 -ffixed-f2 -ffixed-f3 -ffixed-f4 -ffixed-f5 -ffixed-f6 -ffixed-f7 -ffixed-f8 -ffixed-f9 -ffixed-f10 -ffixed-f11 -ffixed-f12 -ffixed-f13 -ffixed-f14 -ffixed-f15 -ffixed-f16 -ffixed-f17 -ffixed-f18 -ffixed-f19 -ffixed-f20 -ffixed-f22 -ffixed-f24 -ffixed-f26 -ffixed-f28 -ffixed-f30" } */
void bar (void);
float a;
float
foo ()
{
float b = a + 1.0f;
bar();
return b;
}
/* { dg-final { scan-assembler-times "lwc1" 5 } } */
/* { dg-final { scan-assembler-times "swc1" 3 } } */
/* { dg-final { scan-assembler-not "mtc" } } */
/* { dg-final { scan-assembler-not "mfc" } } */
/* { dg-final { scan-assembler-not "mthc" } } */
/* { dg-final { scan-assembler-not "mfhc" } } */
/* { dg-final { scan-assembler-not "ldc1" } } */
/* { dg-final { scan-assembler-not "sdc1" } } */

View File

@ -0,0 +1,23 @@
/* Check that we handle call-clobbered FPRs correctly.
This test differs from call-clobbered-3.c because when optimising for size
a callee-saved GPR is used for 'b' to cross the call. */
/* { dg-skip-if "code quality test" { *-*-* } { "*" } { "-Os" } } */
/* { dg-options "-mabi=32 -modd-spreg -mfpxx -ffixed-f0 -ffixed-f1 -ffixed-f2 -ffixed-f3 -ffixed-f4 -ffixed-f5 -ffixed-f6 -ffixed-f7 -ffixed-f8 -ffixed-f9 -ffixed-f10 -ffixed-f11 -ffixed-f12 -ffixed-f13 -ffixed-f14 -ffixed-f15 -ffixed-f16 -ffixed-f17 -ffixed-f18 -ffixed-f19 -ffixed-f20 -ffixed-f22 -ffixed-f24 -ffixed-f26 -ffixed-f28 -ffixed-f30" } */
void bar (void);
float a;
float
foo ()
{
float b = a + 1.0f;
bar();
return b;
}
/* { dg-final { scan-assembler-times "lwc1" 4 } } */
/* { dg-final { scan-assembler-times "swc1" 2 } } */
/* { dg-final { scan-assembler-times "mtc" 1 } } */
/* { dg-final { scan-assembler-times "mfc" 1 } } */
/* { dg-final { scan-assembler-not "mthc" } } */
/* { dg-final { scan-assembler-not "mfhc" } } */
/* { dg-final { scan-assembler-not "ldc1" } } */
/* { dg-final { scan-assembler-not "sdc1" } } */

View File

@ -0,0 +1,21 @@
/* Check that we handle call-clobbered FPRs correctly. */
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
/* { dg-options "-mabi=32 -mfp64 -ffixed-f0 -ffixed-f1 -ffixed-f2 -ffixed-f3 -ffixed-f4 -ffixed-f5 -ffixed-f6 -ffixed-f7 -ffixed-f8 -ffixed-f9 -ffixed-f10 -ffixed-f11 -ffixed-f12 -ffixed-f13 -ffixed-f14 -ffixed-f15 -ffixed-f16 -ffixed-f17 -ffixed-f18 -ffixed-f19 -ffixed-f20 -ffixed-f22 -ffixed-f24 -ffixed-f26 -ffixed-f28 -ffixed-f30" } */
void bar (void);
float a;
float
foo ()
{
float b = a + 1.0f;
bar();
return b;
}
/* { dg-final { scan-assembler-times "lwc1" 3 } } */
/* { dg-final { scan-assembler-times "swc1" 1 } } */
/* { dg-final { scan-assembler-not "sdc1" } } */
/* { dg-final { scan-assembler-not "ldc1" } } */
/* { dg-final { scan-assembler-not "mtc" } } */
/* { dg-final { scan-assembler-not "mfc" } } */
/* { dg-final { scan-assembler-not "mthc" } } */
/* { dg-final { scan-assembler-not "mfhc" } } */

View File

@ -0,0 +1,32 @@
/* Check that we save the correct call-saved GPRs and FPRs. */
/* { dg-options "isa>=2 -mabi=32 -mfp32" } */
void bar (void);
void
foo (int x)
{
__builtin_unwind_init ();
__builtin_eh_return (x, bar);
}
/* { dg-final { scan-assembler "\\\$16" } } */
/* { dg-final { scan-assembler "\\\$17" } } */
/* { dg-final { scan-assembler "\\\$18" } } */
/* { dg-final { scan-assembler "\\\$19" } } */
/* { dg-final { scan-assembler "\\\$20" } } */
/* { dg-final { scan-assembler "\\\$21" } } */
/* { dg-final { scan-assembler "\\\$22" } } */
/* { dg-final { scan-assembler "\\\$23" } } */
/* { dg-final { scan-assembler "\\\$(30|fp)" } } */
/* { dg-final { scan-assembler "\\\$f20" } } */
/* { dg-final { scan-assembler "\\\$f22" } } */
/* { dg-final { scan-assembler "\\\$f24" } } */
/* { dg-final { scan-assembler "\\\$f26" } } */
/* { dg-final { scan-assembler "\\\$f28" } } */
/* { dg-final { scan-assembler "\\\$f30" } } */
/* { dg-final { scan-assembler-not "\\\$f21" } } */
/* { dg-final { scan-assembler-not "\\\$f23" } } */
/* { dg-final { scan-assembler-not "\\\$f25" } } */
/* { dg-final { scan-assembler-not "\\\$f27" } } */
/* { dg-final { scan-assembler-not "\\\$f29" } } */
/* { dg-final { scan-assembler-not "\\\$f31" } } */

View File

@ -0,0 +1,32 @@
/* Check that we save the correct call-saved GPRs and FPRs. */
/* { dg-options "-mabi=32 -mfpxx" } */
void bar (void);
void
foo (int x)
{
__builtin_unwind_init ();
__builtin_eh_return (x, bar);
}
/* { dg-final { scan-assembler "\\\$16" } } */
/* { dg-final { scan-assembler "\\\$17" } } */
/* { dg-final { scan-assembler "\\\$18" } } */
/* { dg-final { scan-assembler "\\\$19" } } */
/* { dg-final { scan-assembler "\\\$20" } } */
/* { dg-final { scan-assembler "\\\$21" } } */
/* { dg-final { scan-assembler "\\\$22" } } */
/* { dg-final { scan-assembler "\\\$23" } } */
/* { dg-final { scan-assembler "\\\$(30|fp)" } } */
/* { dg-final { scan-assembler "\\\$f20" } } */
/* { dg-final { scan-assembler "\\\$f22" } } */
/* { dg-final { scan-assembler "\\\$f24" } } */
/* { dg-final { scan-assembler "\\\$f26" } } */
/* { dg-final { scan-assembler "\\\$f28" } } */
/* { dg-final { scan-assembler "\\\$f30" } } */
/* { dg-final { scan-assembler-not "\\\$f21" } } */
/* { dg-final { scan-assembler-not "\\\$f23" } } */
/* { dg-final { scan-assembler-not "\\\$f25" } } */
/* { dg-final { scan-assembler-not "\\\$f27" } } */
/* { dg-final { scan-assembler-not "\\\$f29" } } */
/* { dg-final { scan-assembler-not "\\\$f31" } } */

View File

@ -0,0 +1,32 @@
/* Check that we save the correct call-saved GPRs and FPRs. */
/* { dg-options "-mabi=32 -mfp64" } */
void bar (void);
void
foo (int x)
{
__builtin_unwind_init ();
__builtin_eh_return (x, bar);
}
/* { dg-final { scan-assembler "\\\$16" } } */
/* { dg-final { scan-assembler "\\\$17" } } */
/* { dg-final { scan-assembler "\\\$18" } } */
/* { dg-final { scan-assembler "\\\$19" } } */
/* { dg-final { scan-assembler "\\\$20" } } */
/* { dg-final { scan-assembler "\\\$21" } } */
/* { dg-final { scan-assembler "\\\$22" } } */
/* { dg-final { scan-assembler "\\\$23" } } */
/* { dg-final { scan-assembler "\\\$(30|fp)" } } */
/* { dg-final { scan-assembler "\\\$f20" } } */
/* { dg-final { scan-assembler "\\\$f22" } } */
/* { dg-final { scan-assembler "\\\$f24" } } */
/* { dg-final { scan-assembler "\\\$f26" } } */
/* { dg-final { scan-assembler "\\\$f28" } } */
/* { dg-final { scan-assembler "\\\$f30" } } */
/* { dg-final { scan-assembler-not "\\\$f21" } } */
/* { dg-final { scan-assembler-not "\\\$f23" } } */
/* { dg-final { scan-assembler-not "\\\$f25" } } */
/* { dg-final { scan-assembler-not "\\\$f27" } } */
/* { dg-final { scan-assembler-not "\\\$f29" } } */
/* { dg-final { scan-assembler-not "\\\$f31" } } */

View File

@ -235,7 +235,7 @@ set mips_option_groups {
endianness "-E(L|B)|-me(l|b)"
float "-m(hard|soft)-float"
forbid_cpu "forbid_cpu=.*"
fp "-mfp(32|64)"
fp "-mfp(32|xx|64)"
gp "-mgp(32|64)"
long "-mlong(32|64)"
micromips "-mmicromips|-mno-micromips"
@ -248,6 +248,10 @@ set mips_option_groups {
dump "-fdump-.*"
}
for { set option 0 } { $option < 32 } { incr option } {
lappend mips_option_groups "fixed-f$option" "-ffixed-f$option"
}
# Add -mfoo/-mno-foo options to mips_option_groups.
foreach option {
abicalls
@ -270,6 +274,7 @@ foreach option {
synci
relax-pic-calls
mcount-ra-address
odd-spreg
} {
lappend mips_option_groups $option "-m(no-|)$option"
}
@ -723,8 +728,12 @@ proc mips-dg-init {} {
#if __mips_fpr == 64
"-mfp64",
#else
#if __mips_fpr == 0
"-mfpxx",
#else
"-mfp32",
#endif
#endif
#ifdef __mips64
"-mgp64",
@ -756,6 +765,12 @@ proc mips-dg-init {} {
"-mno-paired-single",
#endif
#if _MIPS_SPFPSET == 32
"-modd-spreg",
#else
"-mno-odd-spreg",
#endif
#if __mips_abicalls
"-mabicalls",
#else
@ -841,6 +856,8 @@ proc mips-dg-finish {} {
# | |
# -mfp64 -mfp32
# | |
# -modd-spreg -mno-odd-spreg
# | |
# -mabs=2008/-mabs=legacy <no option>
# | |
# -mhard-float -msoft-float
@ -930,6 +947,7 @@ proc mips-dg-options { args } {
mips_option_dependency options "-mips3d" "-mpaired-single"
mips_option_dependency options "-mpaired-single" "-mfp64"
mips_option_dependency options "-mfp64" "-mhard-float"
mips_option_dependency options "-mfp64" "-modd-spreg"
mips_option_dependency options "-mabs=2008" "-mhard-float"
mips_option_dependency options "-mabs=legacy" "-mhard-float"
mips_option_dependency options "-mrelax-pic-calls" "-mno-plt"
@ -1046,10 +1064,13 @@ proc mips-dg-options { args } {
# We need a MIPS32 or MIPS64 ISA for:
#
# - paired-single instructions(*)
# - odd numbered single precision registers
#
# (*) Note that we don't support MIPS V at the moment.
} elseif { $isa_rev < 1
&& [mips_have_test_option_p options "-mpaired-single"] } {
&& ([mips_have_test_option_p options "-mpaired-single"]
|| ([mips_have_test_option_p options "-modd-spreg"]
&& ![mips_have_test_option_p options "-mfp64"]))} {
if { $gp_size == 32 } {
mips_make_test_option options "-mips32"
} else {
@ -1071,7 +1092,9 @@ proc mips-dg-options { args } {
# (*) needed by both -mbranch-likely and -mfix-r10000
} elseif { $isa < 2
&& ([mips_have_test_option_p options "-mbranch-likely"]
|| [mips_have_test_option_p options "-mfix-r10000"]) } {
|| [mips_have_test_option_p options "-mfix-r10000"]
|| ($gp_size == 32
&& [mips_have_test_option_p options "-mfpxx"])) } {
mips_make_test_option options "-mips2"
# Check whether we need to switch from a 32-bit processor to the
# "nearest" 64-bit processor.
@ -1122,6 +1145,9 @@ proc mips-dg-options { args } {
} elseif { [mips_have_test_option_p options "-mlong64"]
&& [mips_long32_abi_p $abi] } {
set force_abi 1
} elseif { [mips_have_test_option_p options "-mfpxx"]
&& ![mips_same_option_p $abi "-mabi=32"] } {
set force_abi 1
} else {
set force_abi 0
}
@ -1193,6 +1219,9 @@ proc mips-dg-options { args } {
}
if { $isa_rev < 1 } {
mips_make_test_option options "-mno-paired-single"
if { ![mips_have_test_option_p options "-mgp64"] } {
mips_make_test_option options "-mno-odd-spreg"
}
}
if { $isa_rev < 2 } {
if { $gp_size == 32 } {
@ -1223,6 +1252,7 @@ proc mips-dg-options { args } {
mips_option_dependency options "-mplt" "-mno-shared"
mips_option_dependency options "-mno-shared" "-fno-pic"
mips_option_dependency options "-mfp32" "-mno-paired-single"
mips_option_dependency options "-mfpxx" "-mno-paired-single"
mips_option_dependency options "-msoft-float" "-mno-paired-single"
mips_option_dependency options "-mno-paired-single" "-mno-mips3d"
@ -1244,7 +1274,9 @@ proc mips-dg-options { args } {
foreach group $mips_abi_groups {
set old_option [mips_original_option $group]
set new_option [mips_option options $group]
if { ![mips_same_option_p $old_option $new_option] } {
if { ![mips_same_option_p $old_option $new_option]
&& ![mips_same_option_p $old_option "-mfpxx"]
&& ![mips_same_option_p $new_option "-mfpxx"] } {
switch -- [lindex $do_what 0] {
link -
run {

View File

@ -0,0 +1,14 @@
/* Check that we move DFmode values via memory between FP and GP. */
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
/* { dg-options "-mabi=32 -mfpxx isa=2" } */
void bar (void);
double
foo (int x, double a)
{
return a;
}
/* { dg-final { scan-assembler-not "mthc1" } } */
/* { dg-final { scan-assembler-not "mtc1" } } */
/* { dg-final { scan-assembler-times "ldc1" 1 } } */

View File

@ -0,0 +1,14 @@
/* Check that we move DFmode values using mthc between FP and GP. */
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
/* { dg-options "-mabi=32 -mfpxx isa_rev=2" } */
void bar (void);
double
foo (int x, double a)
{
return a;
}
/* { dg-final { scan-assembler "mthc1" } } */
/* { dg-final { scan-assembler "mtc1" } } */
/* { dg-final { scan-assembler-not "ldc1" } } */

View File

@ -0,0 +1,13 @@
/* Check that we move DFmode values using mtc1 between FP and GP. */
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
/* { dg-options "-mabi=32 -mfp32 isa=2" } */
void bar (void);
double
foo (int x, double a)
{
return a;
}
/* { dg-final { scan-assembler-times "mtc1" 2 } } */
/* { dg-final { scan-assembler-not "ldc1" } } */

View File

@ -0,0 +1,13 @@
/* Check that we enable odd-numbered single precision registers. */
/* { dg-options "-mabi=32 -modd-spreg -mhard-float" } */
#if _MIPS_SPFPSET != 32
#error "Incorrect number of single-precision registers reported"
#endif
void
foo ()
{
register float foo asm ("$f1");
asm volatile ("" : "=f" (foo));
}

View File

@ -0,0 +1,10 @@
/* Check that we disable odd-numbered single precision registers. */
/* { dg-skip-if "needs asm output" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
/* { dg-options "-mabi=32 -mno-odd-spreg -mhard-float" } */
void
foo ()
{
register float foo asm ("$f1"); /* { dg-error "isn't suitable for" } */
asm volatile ("" : "=f" (foo));
}

View File

@ -0,0 +1,10 @@
/* Check that we disable odd-numbered single precision registers. */
/* { dg-skip-if "needs asm output" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
/* { dg-options "-mabi=32 -mfp32 -march=loongson3a -mhard-float" } */
void
foo ()
{
register float foo asm ("$f1"); /* { dg-error "isn't suitable for" } */
asm volatile ("" : "=f" (foo));
}

View File

@ -0,0 +1,15 @@
/* Check that we disable odd-numbered single precision registers and can
still generate code. */
/* { dg-options "-mabi=32 -mno-odd-spreg -mhard-float" } */
#if _MIPS_SPFPSET != 16
#error "Incorrect number of single-precision registers reported"
#endif
float a;
float
foo ()
{
float b = a + 1.0f;
return b;
}

View File

@ -0,0 +1,11 @@
/* Check that -mno-odd-spreg is not supported with -mabi=64. */
/* { dg-options "-mabi=64 -mno-odd-spreg -mhard-float" } */
/* { dg-error "unsupported combination" "" { target *-*-* } 0 } */
float a;
float
foo ()
{
float b = a + 1.0f;
return b;
}

View File

@ -0,0 +1,10 @@
/* Check that we disable odd-numbered single precision registers for FPXX. */
/* { dg-skip-if "needs asm output" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
/* { dg-options "-mabi=32 -mfpxx -mhard-float" } */
void
foo ()
{
register float foo asm ("$f1"); /* { dg-error "isn't suitable for" } */
asm volatile ("" : "=f" (foo));
}

View File

@ -1,3 +1,9 @@
2014-11-12 Matthew Fortune <matthew.fortune@imgtec.com>
* config/mips/mips16.S: Set .module when supported. Update O32
FP64 calling convention and use for FPXX when possible. Add FPXX
calling convention fallback case.
2014-11-06 Bernd Schmidt <bernds@codesourcery.com>
* config.host: Handle nvptx-*-*.

View File

@ -21,6 +21,8 @@ a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "auto-host.h"
#if defined(__mips_micromips) || defined(__mips_soft_float)
/* Do nothing because this code is only needed when linking
against mips16 hard-float objects. Neither micromips code
@ -29,6 +31,16 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
for those cases. */
#else
#if defined(HAVE_AS_MODULE)
#if __mips_fpr == 32
.module fp=32
#elif __mips_fpr == 0
.module fp=xx
#elif __mips_fpr == 64
.module fp=64
#endif
#endif
/* This file contains mips16 floating point support functions. These
functions are called by mips16 code to handle floating point when
-msoft-float is not used. They accept the arguments and return
@ -152,8 +164,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* The high 32 bits of $2 correspond to the second word in memory;
i.e. the imaginary part. */
#define MOVE_SC_RET(D, T) MERGE_GPR##D ($2, $f1, $f0); jr T
#elif __mips_fpr == 64
#define MOVE_SC_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f1)
#else
#define MOVE_SC_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f2)
#endif
@ -174,16 +184,29 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define MOVE_DF_BYTE8(D) dm##D##c1 $5,$f13
#define MOVE_DF_RET(D, T) DELAY##D (T, dm##D##c1 $2,$f0)
#define MOVE_DC_RET(D, T) dm##D##c1 $3,$f1; MOVE_DF_RET (D, T)
#elif __mips_fpr == 64 && defined(__MIPSEB__)
#elif __mips_fpr != 32 && __mips_isa_rev >= 2 && defined(__MIPSEB__)
#define MOVE_DF_BYTE0(D) m##D##c1 $5,$f12; m##D##hc1 $4,$f12
#define MOVE_DF_BYTE8(D) m##D##c1 $7,$f14; m##D##hc1 $6,$f14
#define MOVE_DF_RET(D, T) m##D##c1 $3,$f0; DELAY##D (T, m##D##hc1 $2,$f0)
#define MOVE_DC_RET(D, T) m##D##c1 $5,$f1; m##D##hc1 $4,$f1; MOVE_DF_RET (D, T)
#elif __mips_fpr == 64
#define MOVE_DC_RET(D, T) m##D##c1 $5,$f2; m##D##hc1 $4,$f2; MOVE_DF_RET (D, T)
#elif __mips_fpr != 32 && __mips_isa_rev >= 2
#define MOVE_DF_BYTE0(D) m##D##c1 $4,$f12; m##D##hc1 $5,$f12
#define MOVE_DF_BYTE8(D) m##D##c1 $6,$f14; m##D##hc1 $7,$f14
#define MOVE_DF_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##hc1 $3,$f0)
#define MOVE_DC_RET(D, T) m##D##c1 $4,$f1; m##D##hc1 $5,$f1; MOVE_DF_RET (D, T)
#define MOVE_DC_RET(D, T) m##D##c1 $4,$f2; m##D##hc1 $5,$f2; MOVE_DF_RET (D, T)
#elif __mips_fpr == 0
#define MOVE_DF_BYTE0t sw $4, 0($29); sw $5, 4($29); ldc1 $f12, 0($29)
#define MOVE_DF_BYTE0f sdc1 $f12, 0($29); lw $4, 0($29); lw $5, 4($29)
#define MOVE_DF_BYTE0(D) MOVE_DF_BYTE0##D
#define MOVE_DF_BYTE8t sw $6, 8($29); sw $7, 12($29); ldc1 $f14, 8($29)
#define MOVE_DF_BYTE8f sdc1 $f14, 8($29); lw $6, 8($29); lw $7, 12($29)
#define MOVE_DF_BYTE8(D) MOVE_DF_BYTE8##D
#define MOVE_DF_RETt(T) sw $2, 0($29); sw $3, 4($29); DELAYt (T, ldc1 $f0, 0($29))
#define MOVE_DF_RETf(T) sdc1 $f0, 0($29); lw $2, 0($29); DELAYf (T, lw $3, 4($29))
#define MOVE_DF_RET(D, T) MOVE_DF_RET##D(T)
#define MOVE_DC_RETt(T) sw $4, 8($29); sw $5, 12($29); ldc1 $f2, 8($29); MOVE_DF_RETt(T)
#define MOVE_DC_RETf(T) sdc1 $f2, 8($29); lw $4, 8($29); lw $5, 12($29); MOVE_DF_RETf(T)
#define MOVE_DC_RET(D, T) MOVE_DF_RET##D(T)
#elif defined(__MIPSEB__)
/* FPRs are little-endian. */
#define MOVE_DF_BYTE0(D) m##D##c1 $4,$f13; m##D##c1 $5,$f12