mips.h (ISA_HAS_FP4): Add MIPS32R2 + 64bit fpu combination.

gcc:
	* config/mips/mips.h (ISA_HAS_FP4): Add MIPS32R2 + 64bit fpu
	combination.
	(ISA_HAS_MXHC1): True if ISA supports mfhc1 and mthc1 opcodes.
	(ASM_SPEC): Pass along -mfp32 and -mfp64.
	* config/mips/mips.c (mips_split_64bit_move): Use gen_mthc1 to set
	high part of FP register when in 64-bit FP register mode.  Similarly
	use gen_mfhc1 to load high part of FP register.
	(override_options): Allow -mgp32 and -mfp64 combination if
	ISA_HAS_MXHC1 (currently for O32 only).
	(mips_cannot_change_mode_class): If floating-point registers are
	bigger than word size. disallow conversion of float register from a
	large integer mode to a float mode smaller than the float register
	size.
	(mips_class_max_nregs): Handle float registers case seperately.
	* config/mips/mips.md (define_constants): Add UNSPEC_MFHC1,
	UNSPEC_MTHC1.
	(movdi_32bit): Use !TARGET_FLOAT64 in condition pattern.
	(movdf_hardfloat_32bit): Similarly.
	(movdi_gp32_fp64): New DImode pattern for MIPS32R2 which optionally
	support a full 64-bit fpu.
	(mthc1): New pattern to generate MTHC1 instruction.
	(mfhc1): New pattern to generate MFHC1 instruction.
	* doc/invoke.texi (MIPS Options): Document the -mgp32 -mfp64
	option for the MIPS32R2 and mention its use under O32 ABI.

gcc/testsuite:
	* gcc.target/mips/mips.exp (dg-mips-options): Handle parsing of
	-mfp64, allowable when ISA >= 33 and float is enabled.
	* gcc.target/mips/mips32r2-mxhc1.c: New test for checking the use
	of mthc1 and mfhc1 patterns.

From-SVN: r119124
This commit is contained in:
David Ung 2006-11-23 16:13:46 +00:00 committed by David Ung
parent 49bcb41649
commit 6f42806295
8 changed files with 162 additions and 16 deletions

View File

@ -1,3 +1,30 @@
2006-11-23 David Ung <davidu@mips.com>
* config/mips/mips.h (ISA_HAS_FP4): Add MIPS32R2 + 64bit fpu
combination.
(ISA_HAS_MXHC1): True if ISA supports mfhc1 and mthc1 opcodes.
(ASM_SPEC): Pass along -mfp32 and -mfp64.
* config/mips/mips.c (mips_split_64bit_move): Use gen_mthc1 to set
high part of FP register when in 64-bit FP register mode. Similarly
use gen_mfhc1 to load high part of FP register.
(override_options): Allow -mgp32 and -mfp64 combination if
ISA_HAS_MXHC1 (currently for O32 only).
(mips_cannot_change_mode_class): If floating-point registers are
bigger than word size. disallow conversion of float register from a
large integer mode to a float mode smaller than the float register
size.
(mips_class_max_nregs): Handle float registers case seperately.
* config/mips/mips.md (define_constants): Add UNSPEC_MFHC1,
UNSPEC_MTHC1.
(movdi_32bit): Use !TARGET_FLOAT64 in condition pattern.
(movdf_hardfloat_32bit): Similarly.
(movdi_gp32_fp64): New DImode pattern for MIPS32R2 which optionally
support a full 64-bit fpu.
(mthc1): New pattern to generate MTHC1 instruction.
(mfhc1): New pattern to generate MFHC1 instruction.
* doc/invoke.texi (MIPS Options): Document the -mgp32 -mfp64
option for the MIPS32R2 and mention its use under O32 ABI.
2006-11-23 Bernd Schmidt <bernd.schmidt@analog.com>
* var-tracking.c (emit_note_insn_var_location): Take care not to

View File

@ -2846,15 +2846,35 @@ mips_split_64bit_move (rtx dest, rtx src)
if (FP_REG_RTX_P (dest))
{
/* Loading an FPR from memory or from GPRs. */
emit_insn (gen_load_df_low (copy_rtx (dest), mips_subword (src, 0)));
emit_insn (gen_load_df_high (dest, mips_subword (src, 1),
copy_rtx (dest)));
if (ISA_HAS_MXHC1)
{
dest = gen_lowpart (DFmode, dest);
emit_insn (gen_load_df_low (dest, mips_subword (src, 0)));
emit_insn (gen_mthc1 (dest, mips_subword (src, 1),
copy_rtx (dest)));
}
else
{
emit_insn (gen_load_df_low (copy_rtx (dest),
mips_subword (src, 0)));
emit_insn (gen_load_df_high (dest, mips_subword (src, 1),
copy_rtx (dest)));
}
}
else if (FP_REG_RTX_P (src))
{
/* Storing an FPR into memory or GPRs. */
emit_move_insn (mips_subword (dest, 0), mips_subword (src, 0));
emit_insn (gen_store_df_high (mips_subword (dest, 1), src));
if (ISA_HAS_MXHC1)
{
src = gen_lowpart (DFmode, src);
emit_move_insn (mips_subword (dest, 0), mips_subword (src, 0));
emit_insn (gen_mfhc1 (mips_subword (dest, 1), src));
}
else
{
emit_move_insn (mips_subword (dest, 0), mips_subword (src, 0));
emit_insn (gen_store_df_high (mips_subword (dest, 1), src));
}
}
else
{
@ -4804,8 +4824,10 @@ override_options (void)
only one right answer here. */
if (TARGET_64BIT && TARGET_DOUBLE_FLOAT && !TARGET_FLOAT64)
error ("unsupported combination: %s", "-mgp64 -mfp32 -mdouble-float");
else if (!TARGET_64BIT && TARGET_FLOAT64)
error ("unsupported combination: %s", "-mgp32 -mfp64");
else if (!TARGET_64BIT && TARGET_FLOAT64
&& !(ISA_HAS_MXHC1 && mips_abi == ABI_32))
error ("-mgp32 and -mfp64 can only be combined if the target"
" supports the mfhc1 and mthc1 instructions");
else if (TARGET_SINGLE_FLOAT && TARGET_FLOAT64)
error ("unsupported combination: %s", "-mfp64 -msingle-float");
}
@ -7660,15 +7682,27 @@ mips_cannot_change_mode_class (enum machine_mode from,
return true;
}
}
/* gcc assumes that each word of a multiword register can be accessed
individually using SUBREGs. This is not true for floating-point
registers if they are bigger than a word. */
if (UNITS_PER_FPREG > UNITS_PER_WORD
&& GET_MODE_SIZE (from) > UNITS_PER_WORD
&& GET_MODE_SIZE (to) < UNITS_PER_FPREG
&& reg_classes_intersect_p (FP_REGS, class))
return true;
/* Loading a 32-bit value into a 64-bit floating-point register
will not sign-extend the value, despite what LOAD_EXTEND_OP says.
We can't allow 64-bit float registers to change from SImode to
to a wider mode. */
if (TARGET_FLOAT64
if (TARGET_64BIT
&& TARGET_FLOAT64
&& from == SImode
&& GET_MODE_SIZE (to) >= UNITS_PER_WORD
&& reg_classes_intersect_p (FP_REGS, class))
return true;
return false;
}
@ -7830,14 +7864,17 @@ mips_secondary_reload_class (enum reg_class class,
/* Implement CLASS_MAX_NREGS.
Usually all registers are word-sized. The only supported exception
is -mgp64 -msingle-float, which has 64-bit words but 32-bit float
registers. A word-based calculation is correct even in that case,
since -msingle-float disallows multi-FPR values.
- UNITS_PER_FPREG controls the number of registers needed by FP_REGS.
The FP status registers are an exception to this rule. They are always
4 bytes wide as they only hold condition code modes, and CCmode is always
considered to be 4 bytes wide. */
- ST_REGS are always hold CCmode values, and CCmode values are
considered to be 4 bytes wide.
All other register classes are covered by UNITS_PER_WORD. Note that
this is true even for unions of integer and float registers when the
latter are smaller than the former. The only supported combination
in which case this occurs is -mgp64 -msingle-float, which has 64-bit
words but 32-bit float registers. A word-based calculation is correct
in that case since -msingle-float disallows multi-FPR values. */
int
mips_class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,
@ -7845,6 +7882,8 @@ mips_class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,
{
if (class == ST_REGS)
return (GET_MODE_SIZE (mode) + 3) / 4;
else if (class == FP_REGS)
return (GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG;
else
return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
}

View File

@ -607,6 +607,7 @@ extern const struct mips_rtx_cost_data *mips_cost;
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) \
&& !TARGET_MIPS16)
@ -703,6 +704,9 @@ extern const struct mips_rtx_cost_data *mips_cost;
#define ISA_HAS_EXT_INS (ISA_MIPS32R2 \
&& !TARGET_MIPS16)
/* ISA has instructions for accessing top part of 64 bit fp regs */
#define ISA_HAS_MXHC1 (TARGET_FLOAT64 && ISA_MIPS32R2)
/* 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". */
@ -821,6 +825,7 @@ extern const struct mips_rtx_cost_data *mips_cost;
%(subtarget_asm_debugging_spec) \
%{mabi=*} %{!mabi*: %(asm_abi_default_spec)} \
%{mgp32} %{mgp64} %{march=*} %{mxgot:-xgot} \
%{mfp32} %{mfp64} \
%{mshared} %{mno-shared} \
%{msym32} %{mno-sym32} \
%{mtune=*} %{v} \

View File

@ -47,6 +47,8 @@
(UNSPEC_MFHILO 26)
(UNSPEC_TLS_LDM 27)
(UNSPEC_TLS_GET_TP 28)
(UNSPEC_MFHC1 31)
(UNSPEC_MTHC1 32)
(UNSPEC_ADDRESS_FIRST 100)
@ -3255,7 +3257,7 @@
(define_insn "*movdi_32bit"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*B*C*D,*B*C*D,*d,*m")
(match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))]
"!TARGET_64BIT && !TARGET_MIPS16
"!TARGET_64BIT && !TARGET_FLOAT64 && !TARGET_MIPS16
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); }
@ -3263,6 +3265,17 @@
(set_attr "mode" "DI")
(set_attr "length" "8,16,*,*,8,8,8,*,8,*")])
(define_insn "*movdi_gp32_fp64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*f,*f,*f,*d,*m")
(match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*f,*J*d,*m,*f,*f"))]
"!TARGET_64BIT && TARGET_FLOAT64 && !TARGET_MIPS16
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); }
[(set_attr "type" "arith,arith,load,store,mthilo,mfhilo,fmove,xfer,fpload,xfer,fpstore")
(set_attr "mode" "DI")
(set_attr "length" "8,16,*,*,8,8,4,8,*,8,*")])
(define_insn "*movdi_32bit_mips16"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d")
(match_operand:DI 1 "move_operand" "d,d,y,K,N,m,d,*x"))]
@ -3804,6 +3817,7 @@
(set_attr "mode" "DF")
(set_attr "length" "4,4,*,*,*,4,4,4,*,*")])
;; This pattern applies to both !TARGET_FLOAT64 and TARGET_FLOAT64.
(define_insn "*movdf_hardfloat_32bit"
[(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m")
(match_operand:DF 1 "move_operand" "f,G,m,f,G,*d,*f,*d*G,*m,*d"))]
@ -3985,6 +3999,29 @@
[(set_attr "type" "xfer,fpstore")
(set_attr "mode" "SF")])
;; Move operand 1 to the high word of operand 0 using mthc1, preserving the
;; value in the low word.
(define_insn "mthc1"
[(set (match_operand:DF 0 "register_operand" "=f")
(unspec:DF [(match_operand:SI 1 "general_operand" "dJ")
(match_operand:DF 2 "register_operand" "0")]
UNSPEC_MTHC1))]
"TARGET_HARD_FLOAT && !TARGET_64BIT && ISA_HAS_MXHC1"
"mthc1\t%z1,%0"
[(set_attr "type" "xfer")
(set_attr "mode" "SF")])
;; Move high word of operand 1 to operand 0 using mfhc1. The corresponding
;; low-word move is done in the normal way.
(define_insn "mfhc1"
[(set (match_operand:SI 0 "register_operand" "=d")
(unspec:SI [(match_operand:DF 1 "register_operand" "f")]
UNSPEC_MFHC1))]
"TARGET_HARD_FLOAT && !TARGET_64BIT && ISA_HAS_MXHC1"
"mfhc1\t%0,%1"
[(set_attr "type" "xfer")
(set_attr "mode" "SF")])
;; Insn to initialize $gp for n32/n64 abicalls. Operand 0 is the offset
;; of _gp from the start of this function. Operand 1 is the incoming
;; function address.

View File

@ -10657,6 +10657,19 @@ can use @option{-mgp32} to get 32-bit code instead.
For information about the O64 ABI, see
@w{@uref{http://gcc.gnu.org/projects/mipso64-abi.html}}.
GCC supports a variant of the o32 ABI in which floating-point registers
are 64 rather than 32 bits wide. You can select this combination with
@option{-mabi=32} @option{-mfp64}. This ABI relies on the @samp{mthc1}
and @samp{mfhc1} instructions and is therefore only supported for
MIPS32R2 processors.
The register assignments for arguments and return values remain the
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.
@item -mabicalls
@itemx -mno-abicalls
@opindex mabicalls

View File

@ -1,3 +1,10 @@
2006-11-23 David Ung <davidu@mips.com>
* gcc.target/mips/mips.exp (dg-mips-options): Handle parsing of
-mfp64, allowable when ISA >= 33 and float is enabled.
* gcc.target/mips/mips32r2-mxhc1.c: New test for checking the use
of mthc1 and mfhc1 patterns.
2006-11-23 Zdenek Dvorak <dvorakz@suse.cz>
PR tree-optimization/29921

View File

@ -158,6 +158,10 @@ proc dg-mips-options {args} {
if {$mips_mips16} {
set matches 0
}
} elseif {$flag == "-mfp64"} {
if {$mips_isa < 33 || $mips_float != "hard"} {
set matches 0
}
} elseif {[regexp -- {^-march=(.*)} $flag dummy arch]} {
if {$mips_mips16 || ($arch != $mips_arch && $mips_forced_isa)} {
set matches 0

View File

@ -0,0 +1,14 @@
/* { dg-do compile } */
/* { dg-mips-options "-O -march=mips32r2 -mabi=32 -mfp64" } */
/* { dg-final { scan-assembler "mthc1" } } */
/* { dg-final { scan-assembler "mfhc1" } } */
double func1 (long long a)
{
return a;
}
long long func2 (double b)
{
return b;
}