re PR target/33635 (Bootstrap broken on mips-sgi-irix6.5)

gcc/
	PR target/33635
	* config/mips/mips-protos.h (mips_split_64bit_move): Rename to...
	(mips_split_doubleword_move): ...this.
	* config/mips/mips.c (mips_subword): Extend to handle 64-bit words;
	use natural endianness for multi-format FPR values.
	(mips_split_64bit_move): Rename to...
	(mips_split_doubleword_move): ...this and extend to 64-bit words.
	Use move_doubleword_fpr* patterns for moves involving FPRs.
	(mips_save_reg): Update the call to mips_split_64bit_move.
	(mips_secondary_reload_class): Return NO_REGS for any reload of a
	nonzero constant into an FPR if the constant can be forced to memory.
	* config/mips/mips.md: Update the splitter calls to
	mips_split_64bit_move.
	(UNSPEC_LOAD_DF_LOW): Rename to...
	(UNSPEC_LOAD_LOW): ...this.
	(UNSPEC_LOAD_DF_HIGH): Rename to...
	(UNSPEC_LOAD_HIGH): ...this.
	(UNSPEC_STORE_DF_HIGH): Rename to...
	(UNSPEC_STORE_WORD): ...this.
	(SPLITF): New mode iterator.
	(HALFMODE): New mode attribute.
	(movtf): New expander.
	(*movtf_internal): New define_insn_and_split.
	(move_doubleword_fpr<mode>): New expander.
	(load_df_low, load_df_high, store_df_high, mthc1, mfhc1): Replace
	with...
	(load_low<mode>, load_high<mode>, store_word<mode>, mthc1<mode>)
	(mfhc1<mode>): ...these more general patterns.

gcc/testsuite/
	PR target/33635
	* gcc.target/mips/mips.exp (setup_mips_tests): Set mips_isa_rev
	and mips_forced_be.
	(dg-mips-options): Handle -EL and -mel.  Make -mfp64 imply
	-mhard-float and a suitable ISA.  Improve handling of -mipsXrY
	options.
	* gcc.target/mips/fpr-moves-1.c: New test.
	* gcc.target/mips/fpr-moves-2.c: Likewise.
	* gcc.target/mips/fpr-moves-3.c: Likewise.
	* gcc.target/mips/fpr-moves-4.c: Likewise.
	* gcc.target/mips/fpr-moves-5.c: Likewise.
	* gcc.target/mips/fpr-moves-6.c: Likewise.
	* gcc.target/mips/mips32r2-mxhc1.c: Remove -march=mips32r2

From-SVN: r128991
This commit is contained in:
Richard Sandiford 2007-10-03 18:39:30 +00:00 committed by Richard Sandiford
parent f5783e34f9
commit 0064fbe9b6
13 changed files with 394 additions and 122 deletions

View File

@ -1,3 +1,34 @@
2007-10-03 Richard Sandiford <rsandifo@nildram.co.uk>
PR target/33635
* config/mips/mips-protos.h (mips_split_64bit_move): Rename to...
(mips_split_doubleword_move): ...this.
* config/mips/mips.c (mips_subword): Extend to handle 64-bit words;
use natural endianness for multi-format FPR values.
(mips_split_64bit_move): Rename to...
(mips_split_doubleword_move): ...this and extend to 64-bit words.
Use move_doubleword_fpr* patterns for moves involving FPRs.
(mips_save_reg): Update the call to mips_split_64bit_move.
(mips_secondary_reload_class): Return NO_REGS for any reload of a
nonzero constant into an FPR if the constant can be forced to memory.
* config/mips/mips.md: Update the splitter calls to
mips_split_64bit_move.
(UNSPEC_LOAD_DF_LOW): Rename to...
(UNSPEC_LOAD_LOW): ...this.
(UNSPEC_LOAD_DF_HIGH): Rename to...
(UNSPEC_LOAD_HIGH): ...this.
(UNSPEC_STORE_DF_HIGH): Rename to...
(UNSPEC_STORE_WORD): ...this.
(SPLITF): New mode iterator.
(HALFMODE): New mode attribute.
(movtf): New expander.
(*movtf_internal): New define_insn_and_split.
(move_doubleword_fpr<mode>): New expander.
(load_df_low, load_df_high, store_df_high, mthc1, mfhc1): Replace
with...
(load_low<mode>, load_high<mode>, store_word<mode>, mthc1<mode>)
(mfhc1<mode>): ...these more general patterns.
2007-10-03 Alexandre Oliva <aoliva@redhat.com>
* cfgrtl.c (rtl_block_ends_with_call_p): Skip notes at the end.

View File

@ -201,7 +201,7 @@ extern int m16_nsimm8_8 (rtx, enum machine_mode);
extern rtx mips_subword (rtx, int);
extern bool mips_split_64bit_move_p (rtx, rtx);
extern void mips_split_64bit_move (rtx, rtx);
extern void mips_split_doubleword_move (rtx, rtx);
extern const char *mips_output_move (rtx, rtx);
extern void mips_restore_gp (void);
#ifdef RTX_CODE

View File

@ -3477,7 +3477,7 @@ mips_address_cost (rtx addr)
rtx
mips_subword (rtx op, int high_p)
{
unsigned int byte;
unsigned int byte, offset;
enum machine_mode mode;
mode = GET_MODE (op);
@ -3490,7 +3490,11 @@ mips_subword (rtx op, int high_p)
byte = 0;
if (FP_REG_RTX_P (op))
return gen_rtx_REG (word_mode, high_p ? REGNO (op) + 1 : REGNO (op));
{
/* Paired FPRs are always ordered little-endian. */
offset = (UNITS_PER_WORD < UNITS_PER_HWFPVALUE ? high_p : byte != 0);
return gen_rtx_REG (word_mode, REGNO (op) + offset);
}
if (MEM_P (op))
return mips_rewrite_small_data (adjust_address (op, word_mode, byte));
@ -3524,58 +3528,23 @@ mips_split_64bit_move_p (rtx dest, rtx src)
}
/* Split a 64-bit move from SRC to DEST assuming that
mips_split_64bit_move_p holds.
Moves into and out of FPRs cause some difficulty here. Such moves
will always be DFmode, since paired FPRs are not allowed to store
DImode values. The most natural representation would be two separate
32-bit moves, such as:
(set (reg:SI $f0) (mem:SI ...))
(set (reg:SI $f1) (mem:SI ...))
However, the second insn is invalid because odd-numbered FPRs are
not allowed to store independent values. Use the patterns load_df_low,
load_df_high and store_df_high instead. */
/* Split a doubleword move from SRC to DEST. On 32-bit targets,
this function handles 64-bit moves for which mips_split_64bit_move_p
holds. For 64-bit targets, this function handles 128-bit moves. */
void
mips_split_64bit_move (rtx dest, rtx src)
mips_split_doubleword_move (rtx dest, rtx src)
{
if (FP_REG_RTX_P (dest))
if (FP_REG_RTX_P (dest) || FP_REG_RTX_P (src))
{
/* Loading an FPR from memory or from GPRs. */
if (ISA_HAS_MXHC1)
{
if (GET_MODE (dest) != DFmode)
dest = gen_rtx_REG_offset (dest, DFmode, REGNO (dest), 0);
emit_insn (gen_load_df_low (dest, mips_subword (src, 0)));
emit_insn (gen_mthc1 (dest, mips_subword (src, 1),
copy_rtx (dest)));
}
if (!TARGET_64BIT && GET_MODE (dest) == DImode)
emit_insn (gen_move_doubleword_fprdi (dest, src));
else if (!TARGET_64BIT && GET_MODE (dest) == DFmode)
emit_insn (gen_move_doubleword_fprdf (dest, src));
else if (TARGET_64BIT && GET_MODE (dest) == TFmode)
emit_insn (gen_move_doubleword_fprtf (dest, src));
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. */
if (ISA_HAS_MXHC1)
{
if (GET_MODE (src) != DFmode)
src = gen_rtx_REG_offset (src, DFmode, REGNO (src), 0);
mips_emit_move (mips_subword (dest, 0), mips_subword (src, 0));
emit_insn (gen_mfhc1 (mips_subword (dest, 1), src));
}
else
{
mips_emit_move (mips_subword (dest, 0), mips_subword (src, 0));
emit_insn (gen_store_df_high (mips_subword (dest, 1), src));
}
gcc_unreachable ();
}
else
{
@ -8042,7 +8011,7 @@ mips_save_reg (rtx reg, rtx mem)
rtx x1, x2;
if (mips_split_64bit_move_p (mem, reg))
mips_split_64bit_move (mem, reg);
mips_split_doubleword_move (mem, reg);
else
mips_emit_move (mem, reg);
@ -9472,18 +9441,15 @@ mips_secondary_reload_class (enum reg_class class,
/* In this case we can use mtc1, mfc1, dmtc1 or dmfc1. */
return NO_REGS;
if (mips_mode_ok_for_mov_fmt_p (mode))
{
if (CONSTANT_P (x))
/* We can force the constants to memory and use lwc1
and ldc1. As above, we will use pairs of lwc1s if
ldc1 is not supported. */
return NO_REGS;
if (CONSTANT_P (x) && !targetm.cannot_force_const_mem (x))
/* We can force the constant to memory and use lwc1
and ldc1. As above, we will use pairs of lwc1s if
ldc1 is not supported. */
return NO_REGS;
if (FP_REG_P (regno))
/* In this case we can use mov.fmt. */
return NO_REGS;
}
if (FP_REG_P (regno) && mips_mode_ok_for_mov_fmt_p (mode))
/* In this case we can use mov.fmt. */
return NO_REGS;
/* Otherwise, we need to reload through an integer register. */
return GR_REGS;

View File

@ -24,9 +24,9 @@
;; <http://www.gnu.org/licenses/>.
(define_constants
[(UNSPEC_LOAD_DF_LOW 0)
(UNSPEC_LOAD_DF_HIGH 1)
(UNSPEC_STORE_DF_HIGH 2)
[(UNSPEC_LOAD_LOW 0)
(UNSPEC_LOAD_HIGH 1)
(UNSPEC_STORE_WORD 2)
(UNSPEC_GET_FNADDR 3)
(UNSPEC_BLOCKAGE 4)
(UNSPEC_CPRESTORE 5)
@ -498,6 +498,11 @@
(define_mode_iterator SCALARF [(SF "TARGET_HARD_FLOAT")
(DF "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT")])
;; A floating-point mode for which moves involving FPRs may need to be split.
(define_mode_iterator SPLITF [(DF "!TARGET_64BIT")
(DI "!TARGET_64BIT")
(TF "TARGET_64BIT")])
;; In GPR templates, a string like "<d>subu" will expand to "subu" in the
;; 32-bit version and "dsubu" in the 64-bit version.
(define_mode_attr d [(SI "") (DI "d")
@ -546,6 +551,10 @@
(V4UQQ "SI") (V2UHQ "SI") (V2UHA "SI")
(V2HQ "SI") (V2HA "SI")])
;; This attribute gives the integer mode that has half the size of
;; the controlling mode.
(define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")])
;; This attribute works around the early SB-1 rev2 core "F2" erratum:
;;
;; In certain cases, div.s and div.ps may have a rounding error
@ -3999,6 +4008,32 @@
(set_attr "mode" "DF")
(set_attr "length" "8,8,8,*,*")])
;; 128-bit floating point moves
(define_expand "movtf"
[(set (match_operand:TF 0 "")
(match_operand:TF 1 ""))]
""
{
if (mips_legitimize_move (TFmode, operands[0], operands[1]))
DONE;
})
;; This pattern handles both hard- and soft-float cases.
(define_insn_and_split "*movtf_internal"
[(set (match_operand:TF 0 "nonimmediate_operand" "=d,R,f,dR")
(match_operand:TF 1 "move_operand" "dGR,dG,dGR,f"))]
""
"#"
"&& reload_completed"
[(const_int 0)]
{
mips_split_doubleword_move (operands[0], operands[1]);
DONE;
}
[(set_attr "type" "multi")
(set_attr "length" "16")])
(define_split
[(set (match_operand:DI 0 "nonimmediate_operand")
(match_operand:DI 1 "move_operand"))]
@ -4006,7 +4041,7 @@
&& mips_split_64bit_move_p (operands[0], operands[1])"
[(const_int 0)]
{
mips_split_64bit_move (operands[0], operands[1]);
mips_split_doubleword_move (operands[0], operands[1]);
DONE;
})
@ -4017,7 +4052,7 @@
&& mips_split_64bit_move_p (operands[0], operands[1])"
[(const_int 0)]
{
mips_split_64bit_move (operands[0], operands[1]);
mips_split_doubleword_move (operands[0], operands[1]);
DONE;
})
@ -4099,74 +4134,105 @@
[(set_attr "type" "mfhilo")
(set_attr "mode" "<MODE>")])
;; Patterns for loading or storing part of a paired floating point
;; register. We need them because odd-numbered floating-point registers
;; are not fully independent: see mips_split_64bit_move.
;; Emit a doubleword move in which exactly one of the operands is
;; a floating-point register. We can't just emit two normal moves
;; because of the constraints imposed by the FPU register model;
;; see mips_cannot_change_mode_class for details. Instead, we keep
;; the FPR whole and use special patterns to refer to each word of
;; the other operand.
(define_expand "move_doubleword_fpr<mode>"
[(set (match_operand:SPLITF 0)
(match_operand:SPLITF 1))]
""
{
if (FP_REG_RTX_P (operands[0]))
{
rtx low = mips_subword (operands[1], 0);
rtx high = mips_subword (operands[1], 1);
emit_insn (gen_load_low<mode> (operands[0], low));
if (ISA_HAS_MXHC1)
emit_insn (gen_mthc1<mode> (operands[0], high, operands[0]));
else
emit_insn (gen_load_high<mode> (operands[0], high, operands[0]));
}
else
{
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 (ISA_HAS_MXHC1)
emit_insn (gen_mfhc1<mode> (high, operands[1]));
else
emit_insn (gen_store_word<mode> (high, operands[1], const1_rtx));
}
DONE;
})
;; Load the low word of operand 0 with operand 1.
(define_insn "load_df_low"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(unspec:DF [(match_operand:SI 1 "general_operand" "dJ,m")]
UNSPEC_LOAD_DF_LOW))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT"
(define_insn "load_low<mode>"
[(set (match_operand:SPLITF 0 "register_operand" "=f,f")
(unspec:SPLITF [(match_operand:<HALFMODE> 1 "general_operand" "dJ,m")]
UNSPEC_LOAD_LOW))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
{
operands[0] = mips_subword (operands[0], 0);
return mips_output_move (operands[0], operands[1]);
}
[(set_attr "type" "mtc,fpload")
(set_attr "mode" "SF")])
[(set_attr "type" "mtc,fpload")
(set_attr "mode" "<HALFMODE>")])
;; Load the high word of operand 0 from operand 1, preserving the value
;; in the low word.
(define_insn "load_df_high"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(unspec:DF [(match_operand:SI 1 "general_operand" "dJ,m")
(match_operand:DF 2 "register_operand" "0,0")]
UNSPEC_LOAD_DF_HIGH))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT"
(define_insn "load_high<mode>"
[(set (match_operand:SPLITF 0 "register_operand" "=f,f")
(unspec:SPLITF [(match_operand:<HALFMODE> 1 "general_operand" "dJ,m")
(match_operand:SPLITF 2 "register_operand" "0,0")]
UNSPEC_LOAD_HIGH))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
{
operands[0] = mips_subword (operands[0], 1);
return mips_output_move (operands[0], operands[1]);
}
[(set_attr "type" "mtc,fpload")
(set_attr "mode" "SF")])
[(set_attr "type" "mtc,fpload")
(set_attr "mode" "<HALFMODE>")])
;; Store the high word of operand 1 in operand 0. The corresponding
;; low-word move is done in the normal way.
(define_insn "store_df_high"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,m")
(unspec:SI [(match_operand:DF 1 "register_operand" "f,f")]
UNSPEC_STORE_DF_HIGH))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT"
;; Store one word of operand 1 in operand 0. Operand 2 is 1 to store the
;; high word and 0 to store the low word.
(define_insn "store_word<mode>"
[(set (match_operand:<HALFMODE> 0 "nonimmediate_operand" "=d,m")
(unspec:<HALFMODE> [(match_operand:SPLITF 1 "register_operand" "f,f")
(match_operand 2 "const_int_operand")]
UNSPEC_STORE_WORD))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
{
operands[1] = mips_subword (operands[1], 1);
operands[1] = mips_subword (operands[1], INTVAL (operands[2]));
return mips_output_move (operands[0], operands[1]);
}
[(set_attr "type" "mfc,fpstore")
(set_attr "mode" "SF")])
[(set_attr "type" "mfc,fpstore")
(set_attr "mode" "<HALFMODE>")])
;; 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"
(define_insn "mthc1<mode>"
[(set (match_operand:SPLITF 0 "register_operand" "=f")
(unspec:SPLITF [(match_operand:<HALFMODE> 1 "general_operand" "dJ")
(match_operand:SPLITF 2 "register_operand" "0")]
UNSPEC_MTHC1))]
"TARGET_HARD_FLOAT && ISA_HAS_MXHC1"
"mthc1\t%z1,%0"
[(set_attr "type" "mtc")
(set_attr "mode" "SF")])
[(set_attr "type" "mtc")
(set_attr "mode" "<HALFMODE>")])
;; 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"
;; Move high word of operand 1 to operand 0 using mfhc1.
(define_insn "mfhc1<mode>"
[(set (match_operand:<HALFMODE> 0 "register_operand" "=d")
(unspec:<HALFMODE> [(match_operand:SPLITF 1 "register_operand" "f")]
UNSPEC_MFHC1))]
"TARGET_HARD_FLOAT && ISA_HAS_MXHC1"
"mfhc1\t%0,%1"
[(set_attr "type" "mfc")
(set_attr "mode" "SF")])
[(set_attr "type" "mfc")
(set_attr "mode" "<HALFMODE>")])
;; Move a constant that satisfies CONST_GP_P into operand 0.
(define_expand "load_const_gp"

View File

@ -1,3 +1,19 @@
2007-10-03 Richard Sandiford <rsandifo@nildram.co.uk>
PR target/33635
* gcc.target/mips/mips.exp (setup_mips_tests): Set mips_isa_rev
and mips_forced_be.
(dg-mips-options): Handle -EL and -mel. Make -mfp64 imply
-mhard-float and a suitable ISA. Improve handling of -mipsXrY
options.
* gcc.target/mips/fpr-moves-1.c: New test.
* gcc.target/mips/fpr-moves-2.c: Likewise.
* gcc.target/mips/fpr-moves-3.c: Likewise.
* gcc.target/mips/fpr-moves-4.c: Likewise.
* gcc.target/mips/fpr-moves-5.c: Likewise.
* gcc.target/mips/fpr-moves-6.c: Likewise.
* gcc.target/mips/mips32r2-mxhc1.c: Remove -march=mips32r2
2007-10-03 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
* gfortran.dg/default_format_1.f90: XFAIL on all darwin targets.

View File

@ -0,0 +1,26 @@
/* { dg-mips-options "-mabi=32 -mhard-float -mips1 -O2 -EL" } */
NOMIPS16 void
foo (double d, double *x)
{
*x = d;
}
NOMIPS16 double
bar (double d)
{
register double l1 asm ("$8") = d;
register double l2 asm ("$f20") = 0.0;
asm ("#foo" : "=d" (l1) : "d" (l1));
asm volatile ("#foo" :: "f" (l2));
return l1;
}
/* { dg-final { scan-assembler "\tswc1\t\\\$f12,0\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tswc1\t\\\$f13,4\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tmfc1\t\\\$8,\\\$f12\n" } } */
/* { dg-final { scan-assembler "\tmfc1\t\\\$9,\\\$f13\n" } } */
/* { dg-final { scan-assembler "\tmtc1\t\\\$0,\\\$f20\n" } } */
/* { dg-final { scan-assembler "\tmtc1\t\\\$0,\\\$f21\n" } } */
/* { dg-final { scan-assembler "\tmtc1\t\\\$8,\\\$f0\n" } } */
/* { dg-final { scan-assembler "\tmtc1\t\\\$9,\\\$f1\n" } } */

View File

@ -0,0 +1,26 @@
/* { dg-mips-options "-mabi=32 -mhard-float -mips1 -O2 -EB" } */
NOMIPS16 void
foo (double d, double *x)
{
*x = d;
}
NOMIPS16 double
bar (double d)
{
register double l1 asm ("$8") = d;
register double l2 asm ("$f20") = 0.0;
asm ("#foo" : "=d" (l1) : "d" (l1));
asm volatile ("#foo" :: "f" (l2));
return l1;
}
/* { dg-final { scan-assembler "\tswc1\t\\\$f12,4\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tswc1\t\\\$f13,0\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tmfc1\t\\\$9,\\\$f12\n" } } */
/* { dg-final { scan-assembler "\tmfc1\t\\\$8,\\\$f13\n" } } */
/* { dg-final { scan-assembler "\tmtc1\t\\\$0,\\\$f20\n" } } */
/* { dg-final { scan-assembler "\tmtc1\t\\\$0,\\\$f21\n" } } */
/* { dg-final { scan-assembler "\tmtc1\t\\\$9,\\\$f0\n" } } */
/* { dg-final { scan-assembler "\tmtc1\t\\\$8,\\\$f1\n" } } */

View File

@ -0,0 +1,18 @@
/* { dg-mips-options "-mabi=32 -mfp64 -O2 -EL" } */
NOMIPS16 double
foo (double d)
{
register double l1 asm ("$8") = d;
register double l2 asm ("$f20") = 0.0;
asm ("#foo" : "=d" (l1) : "d" (l1));
asm volatile ("#foo" :: "f" (l2));
return l1;
}
/* { dg-final { scan-assembler "\tmfc1\t\\\$8,\\\$f12\n" } } */
/* { dg-final { scan-assembler "\tmfhc1\t\\\$9,\\\$f12\n" } } */
/* { dg-final { scan-assembler "\tmtc1\t\\\$0,\\\$f20\n" } } */
/* { dg-final { scan-assembler "\tmthc1\t\\\$0,\\\$f20\n" } } */
/* { dg-final { scan-assembler "\tmtc1\t\\\$8,\\\$f0\n" } } */
/* { dg-final { scan-assembler "\tmthc1\t\\\$9,\\\$f0\n" } } */

View File

@ -0,0 +1,18 @@
/* { dg-mips-options "-mabi=32 -mfp64 -O2 -EB" } */
NOMIPS16 double
foo (double d)
{
register double l1 asm ("$8") = d;
register double l2 asm ("$f20") = 0.0;
asm ("#foo" : "=d" (l1) : "d" (l1));
asm volatile ("#foo" :: "f" (l2));
return l1;
}
/* { dg-final { scan-assembler "\tmfc1\t\\\$9,\\\$f12\n" } } */
/* { dg-final { scan-assembler "\tmfhc1\t\\\$8,\\\$f12\n" } } */
/* { dg-final { scan-assembler "\tmtc1\t\\\$0,\\\$f20\n" } } */
/* { dg-final { scan-assembler "\tmthc1\t\\\$0,\\\$f20\n" } } */
/* { dg-final { scan-assembler "\tmtc1\t\\\$9,\\\$f0\n" } } */
/* { dg-final { scan-assembler "\tmthc1\t\\\$8,\\\$f0\n" } } */

View File

@ -0,0 +1,33 @@
/* { dg-mips-options "-mabi=64 -mhard-float -O2 -EL" } */
NOMIPS16 void
foo (long double d, long double *x)
{
*x = d;
}
NOMIPS16 long double
bar (long double d, long double *x)
{
register long double l1 asm ("$8") = d;
register long double l2 asm ("$10") = x[1];
register long double l3 asm ("$f20") = 0.0;
asm ("#foo" : "=d" (l1) : "d" (l1));
asm ("#foo" : "=d" (l2) : "d" (l2));
asm volatile ("#foo" :: "f" (l3));
x[1] = l1;
return l2;
}
/* { dg-final { scan-assembler "\tsdc1\t\\\$f12,0\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tsdc1\t\\\$f13,8\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tdmfc1\t\\\$8,\\\$f12\n" } } */
/* { dg-final { scan-assembler "\tdmfc1\t\\\$9,\\\$f13\n" } } */
/* { dg-final { scan-assembler "\tld\t\\\$10,16\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tld\t\\\$11,24\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tdmtc1\t\\\$0,\\\$f20\n" } } */
/* { dg-final { scan-assembler "\tdmtc1\t\\\$0,\\\$f21\n" } } */
/* { dg-final { scan-assembler "\tsd\t\\\$8,16\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tsd\t\\\$9,24\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tdmtc1\t\\\$10,\\\$f0\n" } } */
/* { dg-final { scan-assembler "\tdmtc1\t\\\$11,\\\$f2\n" } } */

View File

@ -0,0 +1,34 @@
/* { dg-mips-options "-mabi=64 -mhard-float -O2 -EB" } */
NOMIPS16 void
foo (long double d, long double *x)
{
*x = d;
}
NOMIPS16 long double
bar (long double d, long double *x)
{
register long double l1 asm ("$8") = d;
register long double l2 asm ("$10") = x[1];
register long double l3 asm ("$f20") = 0.0;
asm ("#foo" : "=d" (l1) : "d" (l1));
asm ("#foo" : "=d" (l2) : "d" (l2));
asm volatile ("#foo" :: "f" (l3));
x[1] = l1;
return l2;
}
/* { dg-final { scan-assembler "\tsdc1\t\\\$f12,0\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tsdc1\t\\\$f13,8\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tdmfc1\t\\\$8,\\\$f12\n" } } */
/* { dg-final { scan-assembler "\tdmfc1\t\\\$9,\\\$f13\n" } } */
/* { dg-final { scan-assembler "\tld\t\\\$10,16\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tld\t\\\$11,24\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tdmtc1\t\\\$0,\\\$f20\n" } } */
/* { dg-final { scan-assembler "\tdmtc1\t\\\$0,\\\$f21\n" } } */
/* { dg-final { scan-assembler "\tsd\t\\\$8,16\\\(\\\$6\\\)\n" } } */
/* { dg-final { scan-assembler "\tsd\t\\\$9,24\\\(\\\$6\\\)\n" } } */
/* We currently move this through a temporary. */
/* { dg-final { scan-assembler "\tdmtc1\t\\\$10,\\\$f0\n" { xfail mips*-*-* } } } */
/* { dg-final { scan-assembler "\tdmtc1\t\\\$11,\\\$f2\n" } } */

View File

@ -29,6 +29,7 @@ load_lib gcc-dg.exp
# line (as opposed to being overridable defaults).
#
# $mips_isa: the ISA level specified by __mips
# $mips_isa_rev: the ISA revision specified by __mips_isa_rev
# $mips_arch: the architecture specified by _MIPS_ARCH
# $mips_gp64: true if 64-bit output is selected
# $mips_fp64: true if 64-bit FPRs are selected
@ -39,11 +40,13 @@ load_lib gcc-dg.exp
# $mips_forced_abi: true if the command line uses -mabi=*
# $mips_forced_regs: true if the command line uses -mgp* or -mfp*
# $mips_forced_float: true if the command line uses -mhard/soft-float
# $mips_forced_be true if the command line uses -EB or -meb
# $mips_forced_le true if the command line uses -EL or -mel
# $mips_forced_gp true if the command line forces a particular GP mode
# $mips_forced_no_er true if the command line contains -mno-explicit-relocs
proc setup_mips_tests {} {
global mips_isa
global mips_isa_rev
global mips_arch
global mips_gp64
global mips_fp64
@ -53,6 +56,7 @@ proc setup_mips_tests {} {
global mips_forced_isa
global mips_forced_abi
global mips_forced_float
global mips_forced_be
global mips_forced_le
global mips_forced_gp
global mips_forced_no_er
@ -65,6 +69,11 @@ proc setup_mips_tests {} {
set f [open $src "w"]
puts $f {
int isa = __mips;
#ifdef __mips_isa_rev
int isa_rev = __mips_isa_rev;
#else
int isa_rev = 1;
#endif
const char *arch = _MIPS_ARCH;
#ifdef __mips64
int gp64 = 1;
@ -94,6 +103,7 @@ proc setup_mips_tests {} {
file delete $src
regexp {isa = ([^;]*)} $output dummy mips_isa
regexp {isa_rev = ([^;]*)} $output dummy mips_isa_rev
regexp {arch = "([^"]*)} $output dummy mips_arch
set mips_gp64 [regexp {gp64 = 1} $output]
set mips_fp64 [regexp {fp64 = 1} $output]
@ -104,6 +114,7 @@ proc setup_mips_tests {} {
set mips_forced_abi [regexp -- {-mabi} $compiler_flags]
set mips_forced_regs [regexp -- {(-mgp|-mfp)} $compiler_flags]
set mips_forced_float [regexp -- {-m(hard|soft)-float} $compiler_flags]
set mips_forced_be [regexp -- {-(EB|meb)[[:>:]]} $compiler_flags]
set mips_forced_le [regexp -- {-(EL|mel)[[:>:]]} $compiler_flags]
set mips_forced_gp [regexp -- {-(G|m(|no-)((extern|local)-sdata|gpopt)|mabicalls|mrtp)} $compiler_flags]
set mips_forced_no_er [regexp -- {-mno-explicit-relocs} $compiler_flags]
@ -145,6 +156,12 @@ proc is_gp64_flag {flag} {
# if the other flags don't do so. Skip the test if the multilib
# flags force a 32-bit ABI or a 32-bit architecture.
#
# -mfp64
# Force the use of 64-bit floating-point registers on a 32-bit target.
# Also force -mhard-float and an architecture that supports such a
# combination, unless these things are already specified by other
# parts of the given flags.
#
# -mabi=*
# Force a particular ABI. Skip the test if the multilib flags
# force a specific ABI or a different register size.
@ -160,8 +177,9 @@ proc is_gp64_flag {flag} {
# multilib flags force a different selection.
#
# -EB
# Select big-endian code. Skip the test if the multilib flags
# force a little-endian target.
# -EL
# Select the given endianness. Skip the test if the multilib flags
# force the opposite endianness.
#
# -G*
# -m(no-)extern-sdata
@ -179,6 +197,7 @@ proc dg-mips-options {args} {
upvar dg-do-what do_what
global mips_isa
global mips_isa_rev
global mips_arch
global mips_gp64
global mips_fp64
@ -189,6 +208,7 @@ proc dg-mips-options {args} {
global mips_forced_abi
global mips_forced_regs
global mips_forced_float
global mips_forced_be
global mips_forced_le
global mips_forced_gp
global mips_forced_no_er
@ -197,6 +217,20 @@ proc dg-mips-options {args} {
set matches 1
# First handle the -mgp* options. Add an architecture option if necessary.
foreach flag $flags {
if {$flag == "-mfp64"} {
if {!$mips_fp64 && $mips_forced_regs} {
set matches 0
} else {
if {[lsearch -regexp $flags {^-m(hard|soft)-float$}] < 0} {
append flags " -mhard-float"
}
if {[lsearch -regexp $flags {^(-mips|-march)}] < 0} {
append flags " -mips32r2"
}
}
}
}
foreach flag $flags {
if {[is_gp32_flag $flag]
&& ($mips_gp64
@ -221,11 +255,7 @@ proc dg-mips-options {args} {
}
# Handle the other options.
foreach flag $flags {
if {$flag == "-mfp64"} {
if {$mips_isa < 33 || $mips_float != "hard"} {
set matches 0
}
} elseif {[regexp -- {^-mabi=(.*)} $flag dummy abi]} {
if {[regexp -- {^-mabi=(.*)} $flag dummy abi]} {
if {$abi != $mips_abi && $mips_forced_abi} {
set matches 0
}
@ -233,8 +263,12 @@ proc dg-mips-options {args} {
if {$arch != $mips_arch && $mips_forced_isa} {
set matches 0
}
} elseif {[regexp -- {^-mips(.*)} $flag dummy isa] && $isa != 16} {
if {$isa != $mips_isa && $mips_forced_isa} {
} elseif {[regexp -- {^-mips(.*)} $flag dummy isa]} {
if {![regexp {(.*)r(.*)} $isa dummy isa isa_rev]} {
set isa_rev 1
}
if {($isa != $mips_isa || $isa_rev != $mips_isa_rev)
&& $mips_forced_isa} {
set matches 0
}
} elseif {[regexp -- {^-m(hard|soft)-float} $flag dummy float]} {
@ -245,6 +279,10 @@ proc dg-mips-options {args} {
if {$mips_forced_le} {
set matches 0
}
} elseif {[regexp -- {^-(EL|mel)$} $flag]} {
if {$mips_forced_be} {
set matches 0
}
} elseif {[regexp -- {^-(G|m(|no-)((extern|local)-sdata|gpopt))} $flag]} {
append flags " -mno-abicalls"
if {$mips_forced_gp} {

View File

@ -1,5 +1,5 @@
/* { dg-do compile } */
/* { dg-mips-options "-O -march=mips32r2 -mabi=32 -mfp64" } */
/* { dg-mips-options "-O -mabi=32 -mfp64" } */
/* { dg-final { scan-assembler "mthc1" } } */
/* { dg-final { scan-assembler "mfhc1" } } */