This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[committed] Patch for PR 33635 (mips-sgi-irix6.5 bootstrap)


"François-Xavier Coudert" <fxcoudert@gmail.com> writes:
> Mainline currently doesn't bootstrap on mips-sgi-irix6.5 due to an ICE
> while compiling mips-sgi-irix6.5/64/libgcc/_powitf2.o at stage 1. This
> happens, afaict, with any use of the TF mode with either -mabi=64 or
> -mabi=n32:
>
> $ cat foo.i
> void __powitf2 (float x __attribute__ ((mode (TF)))) {}
> $ /usr/people/francois/devel/ibin/./gcc/cc1 -fpreprocessed foo.i -quiet
> zsh: segmentation fault  /usr/people/francois/devel/ibin/./gcc/cc1
> -fpreprocessed foo.i -quiet
>
> The backtrace for the segfault is:
>
> Program received signal SIGSEGV, Segmentation fault.
> 0x104d7d50 in reg_classes_intersect_p (c1=32, c2=MD0_REG)
>     at ../../trunk/gcc/regclass.c:2481
> 2481    {
> (gdb) where
> #0  0x104d7d50 in reg_classes_intersect_p (c1=32, c2=MD0_REG)
>     at ../../trunk/gcc/regclass.c:2481
> #1  0x102323cc in mips_cannot_change_mode_class (from=TFmode, to=DImode,
>     class=FP_REGS) at ../../trunk/gcc/config/mips/mips.c:9346
> #2  0x10823a38 in simplify_subreg (outermode=DImode, op=0x40b4c80,
>     innermode=TFmode, byte=0) at ../../trunk/gcc/simplify-rtx.c:5014
> [...]
> #10 0x1027a7cc in operand_subword_force (op=0x40b4c80, offset=0, mode=TFmode)
>     at ../../trunk/gcc/emit-rtl.c:1448

Sorry, this was fallout from my 2007-09-30 patch.  Although I still
think that patch is doing the right thing in itself, I'd forgotten that
we'd then need to have a movtf pattern, rather than relying on the moves
being decomposed into smaller moves.

The patch below adds the patterns and generalises the handling
of 64-bit FPR moves so that it handles 128-bit moves too.
This generalisation removes the DI->DF type punning for mxhc1
and the use of direct moves for low-word stores, both of which
(as per the previous patch) were theoretically unsafe.

The mips.exp change adds support for -EL and removes some unnecessary
restrictions on when -mfp64 tests were run.  I also noticed that
-mipsXrY options weren't handled quite right, which again led to
some tests being unnecessarily treated as unsupported for certain
non-default test flags.

I've regression-tested this on mipsisa32-elf with r128908 reverted.
The new fpr-moves-[56].c tests failed before the patch and pass
afterwards.

FX: I don't have access to IRIX any more, but based on the fpr-moves-*.c
results, I think this is going to be better than the status quo.  Let me
know if it doesn't fix the problem completely though.  Note that you might
need to revert r128908 too, or apply Alex's follow-on patch (which
I haven't tested yet).

Thanks for the report, and sorry for the breakage.

Richard


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

Index: gcc/config/mips/mips-protos.h
===================================================================
--- gcc/config/mips/mips-protos.h	2007-10-03 14:40:07.000000000 +0100
+++ gcc/config/mips/mips-protos.h	2007-10-03 14:41:59.000000000 +0100
@@ -201,7 +201,7 @@ extern int m16_nsimm8_8 (rtx, enum machi
 
 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
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2007-10-03 14:40:07.000000000 +0100
+++ gcc/config/mips/mips.c	2007-10-03 14:57:40.000000000 +0100
@@ -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 s
 }
 
 
-/* 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))
-    {
-      /* 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)));
-	}
-      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))
+  if (FP_REG_RTX_P (dest) || 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));
-	}
+      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
-	{
-	  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_cl
 	/* 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 (FP_REG_P (regno))
-	    /* In this case we can use mov.fmt.  */
-	    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) && 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;
Index: gcc/config/mips/mips.md
===================================================================
--- gcc/config/mips/mips.md	2007-10-03 14:40:07.000000000 +0100
+++ gcc/config/mips/mips.md	2007-10-03 14:41:59.000000000 +0100
@@ -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 ANYF [(SF "TARGET_
 (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 @@ (define_mode_attr IMODE [(QQ "QI") (HQ "
 			 (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 @@ (define_insn "*movdf_mips16"
    (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 @@ (define_split
    && 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 @@ (define_split
    && 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 @@ (define_insn "*mfhilo_<mode>_macc"
   [(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"
Index: gcc/testsuite/gcc.target/mips/mips.exp
===================================================================
--- gcc/testsuite/gcc.target/mips/mips.exp	2007-10-03 14:40:07.000000000 +0100
+++ gcc/testsuite/gcc.target/mips/mips.exp	2007-10-03 14:41:59.000000000 +0100
@@ -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
@@ -198,6 +218,20 @@ proc dg-mips-options {args} {
 
     # 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
 		|| ($mips_fp64 && [lsearch $flags -mfp64] < 0)) } {
@@ -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} {
Index: gcc/testsuite/gcc.target/mips/fpr-moves-1.c
===================================================================
--- /dev/null	2007-10-02 08:22:32.556097250 +0100
+++ gcc/testsuite/gcc.target/mips/fpr-moves-1.c	2007-10-03 19:28:33.000000000 +0100
@@ -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" } } */
Index: gcc/testsuite/gcc.target/mips/fpr-moves-2.c
===================================================================
--- /dev/null	2007-10-02 08:22:32.556097250 +0100
+++ gcc/testsuite/gcc.target/mips/fpr-moves-2.c	2007-10-03 19:28:45.000000000 +0100
@@ -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" } } */
Index: gcc/testsuite/gcc.target/mips/fpr-moves-3.c
===================================================================
--- /dev/null	2007-10-02 08:22:32.556097250 +0100
+++ gcc/testsuite/gcc.target/mips/fpr-moves-3.c	2007-10-03 19:28:54.000000000 +0100
@@ -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" } } */
Index: gcc/testsuite/gcc.target/mips/fpr-moves-4.c
===================================================================
--- /dev/null	2007-10-02 08:22:32.556097250 +0100
+++ gcc/testsuite/gcc.target/mips/fpr-moves-4.c	2007-10-03 14:41:59.000000000 +0100
@@ -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" } } */
Index: gcc/testsuite/gcc.target/mips/fpr-moves-5.c
===================================================================
--- /dev/null	2007-10-02 08:22:32.556097250 +0100
+++ gcc/testsuite/gcc.target/mips/fpr-moves-5.c	2007-10-03 19:29:03.000000000 +0100
@@ -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" } } */
Index: gcc/testsuite/gcc.target/mips/fpr-moves-6.c
===================================================================
--- /dev/null	2007-10-02 08:22:32.556097250 +0100
+++ gcc/testsuite/gcc.target/mips/fpr-moves-6.c	2007-10-03 19:29:09.000000000 +0100
@@ -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" } } */
Index: gcc/testsuite/gcc.target/mips/mips32r2-mxhc1.c
===================================================================
--- gcc/testsuite/gcc.target/mips/mips32r2-mxhc1.c	2007-10-03 14:40:07.000000000 +0100
+++ gcc/testsuite/gcc.target/mips/mips32r2-mxhc1.c	2007-10-03 14:41:59.000000000 +0100
@@ -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" } } */
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]