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:
parent
49bcb41649
commit
6f42806295
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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} \
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
14
gcc/testsuite/gcc.target/mips/mips32r2-mxhc1.c
Normal file
14
gcc/testsuite/gcc.target/mips/mips32r2-mxhc1.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user