]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/33635 (Bootstrap broken on mips-sgi-irix6.5)
authorRichard Sandiford <rsandifo@nildram.co.uk>
Wed, 3 Oct 2007 18:39:30 +0000 (18:39 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 3 Oct 2007 18:39:30 +0000 (18:39 +0000)
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

13 files changed:
gcc/ChangeLog
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/fpr-moves-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fpr-moves-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fpr-moves-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fpr-moves-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fpr-moves-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fpr-moves-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/mips.exp
gcc/testsuite/gcc.target/mips/mips32r2-mxhc1.c

index 5d7d7a17313a00f701eb5b017bcd173649267ba8..45a840f72315b13bfd4bdf2f98d790c7fce47127 100644 (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.
index 623774961e2182b771abdd1124730100803a06eb..371fd93447e31ae32be54d635462f6dea8ef5108 100644 (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
index 6ac976abe6e9a83f1b59eeeadbf160e4d6403d97..64377b54d1d2de7f1ff58f07837ba81b2076d742 100644 (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))
-    {
-      /* 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_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 (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 38800ed15e76e1c962f82ce99895b40191fe6479..f4b90eb6ee051d3d1a66fc6deb5635cb6be5ca6f 100644 (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)
 (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")
                         (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
    (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"))]
    && 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;
 })
 
    && 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;
 })
 
   [(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")])
-
-;; 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"
+  [(set_attr "type" "mtc,fpload")
+   (set_attr "mode" "<HALFMODE>")])
+
+;; 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")])
-
-;; 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"
+  [(set_attr "type" "mtc")
+   (set_attr "mode" "<HALFMODE>")])
+
+;; 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 c6aec50eae7525611d1fdb836398427160387467..277c25d5e311992f0578a8d0bc5de5f8be4276e0 100644 (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.
diff --git a/gcc/testsuite/gcc.target/mips/fpr-moves-1.c b/gcc/testsuite/gcc.target/mips/fpr-moves-1.c
new file mode 100644 (file)
index 0000000..db2190d
--- /dev/null
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fpr-moves-2.c b/gcc/testsuite/gcc.target/mips/fpr-moves-2.c
new file mode 100644 (file)
index 0000000..fe21ee2
--- /dev/null
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fpr-moves-3.c b/gcc/testsuite/gcc.target/mips/fpr-moves-3.c
new file mode 100644 (file)
index 0000000..a32c687
--- /dev/null
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fpr-moves-4.c b/gcc/testsuite/gcc.target/mips/fpr-moves-4.c
new file mode 100644 (file)
index 0000000..4f26f06
--- /dev/null
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fpr-moves-5.c b/gcc/testsuite/gcc.target/mips/fpr-moves-5.c
new file mode 100644 (file)
index 0000000..7159d38
--- /dev/null
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fpr-moves-6.c b/gcc/testsuite/gcc.target/mips/fpr-moves-6.c
new file mode 100644 (file)
index 0000000..048987a
--- /dev/null
@@ -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 7e2b781456bf0dbbb3f4ea9d95f3fddf93b60c39..68c67d31287763a175aca2ce820dc2c342f7419c 100644 (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} {
index 7a3b12d55af63a235e4bba7687bc6eb6aac1dc26..9257612cc17194d7b73950dd7e46f979939ed914 100644 (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" } } */