diff options
author | Richard Sandiford <rsandifo@nildram.co.uk> | 2007-10-03 18:39:30 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2007-10-03 18:39:30 +0000 |
commit | 0064fbe9b6d395c794fc021d6dc97b40f9d7ac92 (patch) | |
tree | facac44939a51a8591e7804d091bfb66aeb0c6f6 /gcc | |
parent | f5783e34f97cd9012ae3ee4118a5e3bf642d8aed (diff) | |
download | gcc-0064fbe9b6d395c794fc021d6dc97b40f9d7ac92.zip gcc-0064fbe9b6d395c794fc021d6dc97b40f9d7ac92.tar.gz gcc-0064fbe9b6d395c794fc021d6dc97b40f9d7ac92.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 31 | ||||
-rw-r--r-- | gcc/config/mips/mips-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 90 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 170 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/fpr-moves-1.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/fpr-moves-2.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/fpr-moves-3.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/fpr-moves-4.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/fpr-moves-5.c | 33 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/fpr-moves-6.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/mips.exp | 56 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/mips32r2-mxhc1.c | 2 |
13 files changed, 397 insertions, 125 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5d7d7a1..45a840f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 6237749..371fd93 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -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 diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 6ac976a..64377b5 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -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; diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 38800ed..f4b90eb 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -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")]) - -;; 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" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c6aec50..277c25d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..db2190d --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/fpr-moves-1.c @@ -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 index 0000000..fe21ee2 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/fpr-moves-2.c @@ -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 index 0000000..a32c687 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/fpr-moves-3.c @@ -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 index 0000000..4f26f06 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/fpr-moves-4.c @@ -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 index 0000000..7159d38 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/fpr-moves-5.c @@ -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 index 0000000..048987a --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/fpr-moves-6.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp index 7e2b781..68c67d3 100644 --- a/gcc/testsuite/gcc.target/mips/mips.exp +++ b/gcc/testsuite/gcc.target/mips/mips.exp @@ -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} { diff --git a/gcc/testsuite/gcc.target/mips/mips32r2-mxhc1.c b/gcc/testsuite/gcc.target/mips/mips32r2-mxhc1.c index 7a3b12d..9257612 100644 --- a/gcc/testsuite/gcc.target/mips/mips32r2-mxhc1.c +++ b/gcc/testsuite/gcc.target/mips/mips32r2-mxhc1.c @@ -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" } } */ |