aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2014-02-02 16:05:09 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2014-02-02 16:05:09 +0000
commita90c02456f4655254477e00e338163ffab9bd97b (patch)
treed3981bb890af724a896cc670725869d13eb00984
parent6d51cc90102eddcc8b988b400a70b015e69b2274 (diff)
downloadgcc-a90c02456f4655254477e00e338163ffab9bd97b.zip
gcc-a90c02456f4655254477e00e338163ffab9bd97b.tar.gz
gcc-a90c02456f4655254477e00e338163ffab9bd97b.tar.bz2
extend.texi (__builtin_mips_get_fcsr): Document.
gcc/ * doc/extend.texi (__builtin_mips_get_fcsr): Document. (__builtin_mips_set_fcsr): Likewise. * config/mips/mips-ftypes.def: Add MIPS_VOID_FTYPE_USI and MIPS_USI_FTYPE_VOID. * config/mips/mips-protos.h (mips16_expand_get_fcsr): Declare (mips16_expand_set_fcsr): Likewise. * config/mips/mips.c (mips16_get_fcsr_stub): New variable. (mips16_set_fcsr_stub): Likewise. (mips16_get_fcsr_one_only_stub): New class. (mips16_set_fcsr_one_only_stub): Likewise. (mips16_expand_get_fcsr, mips16_expand_set_fcsr): New functions. (mips_code_end): Output the get_fcsr and set_fcsr stubs, if needed. (BUILTIN_AVAIL_MIPS16, AVAIL_ALL): New macros. (hard_float): New availability predicate. (mips_builtins): Add get_fcsr and set_fcsr. (mips_expand_builtin): Check BUILTIN_AVAIL_MIPS16. * config/mips/mips.md (UNSPEC_GET_FCSR, UNSPEC_SET_FCSR): New unspecs. (GET_FCSR_REGNUM, SET_FCSR_REGNUM): New constants. (mips_get_fcsr, *mips_get_fcsr, mips_get_fcsr_mips16_<mode>) (mips_set_fcsr, *mips_set_fcsr, mips_set_fcsr_mips16_<mode>): New patterns. gcc/testsuite/ * gcc.target/mips/get-fcsr-1.c, gcc.target/mips/get-fcsr-2.c, gcc.target/mips/set-fcsr-1.c, gcc.target/mips/set-fcsr-2.c: New tests. From-SVN: r207401
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/config/mips/mips-ftypes.def3
-rw-r--r--gcc/config/mips/mips-protos.h2
-rw-r--r--gcc/config/mips/mips.c96
-rw-r--r--gcc/config/mips/mips.md66
-rw-r--r--gcc/doc/extend.texi9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/mips/get-fcsr-1.c9
-rw-r--r--gcc/testsuite/gcc.target/mips/get-fcsr-2.c10
-rw-r--r--gcc/testsuite/gcc.target/mips/set-fcsr-1.c10
-rw-r--r--gcc/testsuite/gcc.target/mips/set-fcsr-2.c10
11 files changed, 240 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3311e2b..9343373 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,29 @@
2014-02-02 Richard Sandiford <rdsandiford@googlemail.com>
+ * doc/extend.texi (__builtin_mips_get_fcsr): Document.
+ (__builtin_mips_set_fcsr): Likewise.
+ * config/mips/mips-ftypes.def: Add MIPS_VOID_FTYPE_USI and
+ MIPS_USI_FTYPE_VOID.
+ * config/mips/mips-protos.h (mips16_expand_get_fcsr): Declare
+ (mips16_expand_set_fcsr): Likewise.
+ * config/mips/mips.c (mips16_get_fcsr_stub): New variable.
+ (mips16_set_fcsr_stub): Likewise.
+ (mips16_get_fcsr_one_only_stub): New class.
+ (mips16_set_fcsr_one_only_stub): Likewise.
+ (mips16_expand_get_fcsr, mips16_expand_set_fcsr): New functions.
+ (mips_code_end): Output the get_fcsr and set_fcsr stubs, if needed.
+ (BUILTIN_AVAIL_MIPS16, AVAIL_ALL): New macros.
+ (hard_float): New availability predicate.
+ (mips_builtins): Add get_fcsr and set_fcsr.
+ (mips_expand_builtin): Check BUILTIN_AVAIL_MIPS16.
+ * config/mips/mips.md (UNSPEC_GET_FCSR, UNSPEC_SET_FCSR): New unspecs.
+ (GET_FCSR_REGNUM, SET_FCSR_REGNUM): New constants.
+ (mips_get_fcsr, *mips_get_fcsr, mips_get_fcsr_mips16_<mode>)
+ (mips_set_fcsr, *mips_set_fcsr, mips_set_fcsr_mips16_<mode>): New
+ patterns.
+
+2014-02-02 Richard Sandiford <rdsandiford@googlemail.com>
+
* config/mips/mips.c (mips_one_only_stub): New class.
(mips_need_mips16_rdhwr_p): Replace with...
(mips16_rdhwr_stub): ...this new variable.
diff --git a/gcc/config/mips/mips-ftypes.def b/gcc/config/mips/mips-ftypes.def
index 3198abf..078a595 100644
--- a/gcc/config/mips/mips-ftypes.def
+++ b/gcc/config/mips/mips-ftypes.def
@@ -69,6 +69,8 @@ DEF_MIPS_FTYPE (1, (SF, V2SF))
DEF_MIPS_FTYPE (2, (UDI, UDI, UDI))
DEF_MIPS_FTYPE (2, (UDI, UV2SI, UV2SI))
+DEF_MIPS_FTYPE (1, (USI, VOID))
+
DEF_MIPS_FTYPE (2, (UV2SI, UV2SI, UQI))
DEF_MIPS_FTYPE (2, (UV2SI, UV2SI, UV2SI))
@@ -122,5 +124,6 @@ DEF_MIPS_FTYPE (2, (V8QI, V8QI, V8QI))
DEF_MIPS_FTYPE (2, (VOID, SI, CVPOINTER))
DEF_MIPS_FTYPE (2, (VOID, SI, SI))
+DEF_MIPS_FTYPE (1, (VOID, USI))
DEF_MIPS_FTYPE (2, (VOID, V2HI, V2HI))
DEF_MIPS_FTYPE (2, (VOID, V4QI, V4QI))
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index 7f93f15..3d59b7b 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -345,6 +345,8 @@ extern bool lwsp_swsp_address_p (rtx, enum machine_mode);
extern bool m16_based_address_p (rtx, enum machine_mode,
int (*)(rtx_def*, machine_mode));
extern rtx mips_expand_thread_pointer (rtx);
+extern void mips16_expand_get_fcsr (rtx);
+extern void mips16_expand_set_fcsr (rtx);
extern bool mips_eh_uses (unsigned int);
extern bool mips_epilogue_uses (unsigned int);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 12cecde..cd1710b 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -641,8 +641,10 @@ struct target_globals *mips16_globals;
and returned from mips_sched_reorder2. */
static int cached_can_issue_more;
-/* The stub for __mips16_rdhwr, if used. */
+/* The stubs for various MIPS16 support functions, if used. */
static mips_one_only_stub *mips16_rdhwr_stub;
+static mips_one_only_stub *mips16_get_fcsr_stub;
+static mips_one_only_stub *mips16_set_fcsr_stub;
/* Index R is the smallest register class that contains register R. */
const enum reg_class mips_regno_to_class[FIRST_PSEUDO_REGISTER] = {
@@ -1660,6 +1662,48 @@ mips16_rdhwr_one_only_stub::output_body ()
"\t.set\tpop\n"
"\tj\t$31\n");
}
+
+/* A stub for moving the FCSR into GET_FCSR_REGNUM. */
+class mips16_get_fcsr_one_only_stub : public mips_one_only_stub
+{
+ virtual const char *get_name ();
+ virtual void output_body ();
+};
+
+const char *
+mips16_get_fcsr_one_only_stub::get_name ()
+{
+ return "__mips16_get_fcsr";
+}
+
+void
+mips16_get_fcsr_one_only_stub::output_body ()
+{
+ fprintf (asm_out_file,
+ "\tcfc1\t%s,$31\n"
+ "\tj\t$31\n", reg_names[GET_FCSR_REGNUM]);
+}
+
+/* A stub for moving SET_FCSR_REGNUM into the FCSR. */
+class mips16_set_fcsr_one_only_stub : public mips_one_only_stub
+{
+ virtual const char *get_name ();
+ virtual void output_body ();
+};
+
+const char *
+mips16_set_fcsr_one_only_stub::get_name ()
+{
+ return "__mips16_set_fcsr";
+}
+
+void
+mips16_set_fcsr_one_only_stub::output_body ()
+{
+ fprintf (asm_out_file,
+ "\tctc1\t%s,$31\n"
+ "\tj\t$31\n", reg_names[SET_FCSR_REGNUM]);
+}
/* Return true if symbols of type TYPE require a GOT access. */
@@ -3219,6 +3263,31 @@ mips_legitimize_tls_address (rtx loc)
return dest;
}
+/* Implement "TARGET = __builtin_mips_get_fcsr ()" for MIPS16,
+ using a stub. */
+
+void
+mips16_expand_get_fcsr (rtx target)
+{
+ if (!mips16_get_fcsr_stub)
+ mips16_get_fcsr_stub = new mips16_get_fcsr_one_only_stub ();
+ rtx fn = mips16_stub_call_address (mips16_get_fcsr_stub);
+ emit_insn (PMODE_INSN (gen_mips_get_fcsr_mips16, (fn)));
+ emit_move_insn (target, gen_rtx_REG (SImode, GET_FCSR_REGNUM));
+}
+
+/* Implement __builtin_mips_set_fcsr (TARGET) for MIPS16, using a stub. */
+
+void
+mips16_expand_set_fcsr (rtx newval)
+{
+ if (!mips16_set_fcsr_stub)
+ mips16_set_fcsr_stub = new mips16_set_fcsr_one_only_stub ();
+ rtx fn = mips16_stub_call_address (mips16_set_fcsr_stub);
+ emit_move_insn (gen_rtx_REG (SImode, SET_FCSR_REGNUM), newval);
+ emit_insn (PMODE_INSN (gen_mips_set_fcsr_mips16, (fn)));
+}
+
/* If X is not a valid address for mode MODE, force it into a register. */
static rtx
@@ -8958,6 +9027,8 @@ static void
mips_code_end (void)
{
mips_finish_stub (&mips16_rdhwr_stub);
+ mips_finish_stub (&mips16_get_fcsr_stub);
+ mips_finish_stub (&mips16_set_fcsr_stub);
}
/* Make the last instruction frame-related and note that it performs
@@ -13649,9 +13720,12 @@ mips_prefetch_cookie (rtx write, rtx locality)
/* Flags that indicate when a built-in function is available.
BUILTIN_AVAIL_NON_MIPS16
- The function is available on the current target, but only
- in non-MIPS16 mode. */
+ The function is available on the current target if !TARGET_MIPS16.
+
+ BUILTIN_AVAIL_MIPS16
+ The function is available on the current target if TARGET_MIPS16. */
#define BUILTIN_AVAIL_NON_MIPS16 1
+#define BUILTIN_AVAIL_MIPS16 2
/* Declare an availability predicate for built-in functions that
require non-MIPS16 mode and also require COND to be true.
@@ -13663,6 +13737,16 @@ mips_prefetch_cookie (rtx write, rtx locality)
return (COND) ? BUILTIN_AVAIL_NON_MIPS16 : 0; \
}
+/* Declare an availability predicate for built-in functions that
+ support both MIPS16 and non-MIPS16 code and also require COND
+ to be true. NAME is the main part of the predicate's name. */
+#define AVAIL_ALL(NAME, COND) \
+ static unsigned int \
+ mips_builtin_avail_##NAME (void) \
+ { \
+ return (COND) ? BUILTIN_AVAIL_NON_MIPS16 | BUILTIN_AVAIL_MIPS16 : 0; \
+ }
+
/* This structure describes a single built-in function. */
struct mips_builtin_description {
/* The code of the main .md file instruction. See mips_builtin_type
@@ -13685,6 +13769,7 @@ struct mips_builtin_description {
unsigned int (*avail) (void);
};
+AVAIL_ALL (hard_float, TARGET_HARD_FLOAT_ABI)
AVAIL_NON_MIPS16 (paired_single, TARGET_PAIRED_SINGLE_FLOAT)
AVAIL_NON_MIPS16 (sb1_paired_single, TARGET_SB1 && TARGET_PAIRED_SINGLE_FLOAT)
AVAIL_NON_MIPS16 (mips3d, TARGET_MIPS3D)
@@ -13852,6 +13937,9 @@ AVAIL_NON_MIPS16 (cache, TARGET_CACHE_BUILTIN)
#define CODE_FOR_loongson_psubusb CODE_FOR_ussubv8qi3
static const struct mips_builtin_description mips_builtins[] = {
+ DIRECT_BUILTIN (get_fcsr, MIPS_USI_FTYPE_VOID, hard_float),
+ DIRECT_NO_TARGET_BUILTIN (set_fcsr, MIPS_VOID_FTYPE_USI, hard_float),
+
DIRECT_BUILTIN (pll_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, paired_single),
DIRECT_BUILTIN (pul_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, paired_single),
DIRECT_BUILTIN (plu_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, paired_single),
@@ -14501,7 +14589,7 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
d = &mips_builtins[fcode];
avail = d->avail ();
gcc_assert (avail != 0);
- if (TARGET_MIPS16)
+ if (TARGET_MIPS16 && !(avail & BUILTIN_AVAIL_MIPS16))
{
error ("built-in function %qE not supported for MIPS16",
DECL_NAME (fndecl));
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 4f64360..1e3e9e6 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -86,6 +86,10 @@
UNSPEC_MFHC1
UNSPEC_MTHC1
+ ;; Floating-point environment.
+ UNSPEC_GET_FCSR
+ UNSPEC_SET_FCSR
+
;; HI/LO moves.
UNSPEC_MFHI
UNSPEC_MTHI
@@ -147,6 +151,8 @@
(define_constants
[(TLS_GET_TP_REGNUM 3)
+ (GET_FCSR_REGNUM 2)
+ (SET_FCSR_REGNUM 4)
(MIPS16_T_REGNUM 24)
(PIC_FUNCTION_ADDR_REGNUM 25)
(RETURN_ADDR_REGNUM 31)
@@ -7093,6 +7099,66 @@
DONE;
})
+;; __builtin_mips_get_fcsr: move the FCSR into operand 0.
+(define_expand "mips_get_fcsr"
+ [(set (match_operand:SI 0 "register_operand")
+ (unspec_volatile [(const_int 0)] UNSPEC_GET_FCSR))]
+ "TARGET_HARD_FLOAT_ABI"
+{
+ if (TARGET_MIPS16)
+ {
+ mips16_expand_get_fcsr (operands[0]);
+ DONE;
+ }
+})
+
+(define_insn "*mips_get_fcsr"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec_volatile [(const_int 0)] UNSPEC_GET_FCSR))]
+ "TARGET_HARD_FLOAT"
+ "cfc1\t%0,$31")
+
+;; See tls_get_tp_mips16_<mode> for why this form is used.
+(define_insn "mips_get_fcsr_mips16_<mode>"
+ [(set (reg:SI GET_FCSR_REGNUM)
+ (unspec:SI [(match_operand:P 0 "call_insn_operand" "dS")]
+ UNSPEC_GET_FCSR))
+ (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM))
+ (clobber (reg:P RETURN_ADDR_REGNUM))]
+ "TARGET_HARD_FLOAT_ABI && TARGET_MIPS16"
+ { return MIPS_CALL ("jal", operands, 0, -1); }
+ [(set_attr "type" "call")
+ (set_attr "insn_count" "3")])
+
+;; __builtin_mips_set_fcsr: move operand 0 into the FCSR.
+(define_expand "mips_set_fcsr"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand")]
+ UNSPEC_SET_FCSR)]
+ "TARGET_HARD_FLOAT_ABI"
+{
+ if (TARGET_MIPS16)
+ {
+ mips16_expand_set_fcsr (operands[0]);
+ DONE;
+ }
+})
+
+(define_insn "*mips_set_fcsr"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "d")]
+ UNSPEC_SET_FCSR)]
+ "TARGET_HARD_FLOAT"
+ "ctc1\t%0,$31")
+
+;; See tls_get_tp_mips16_<mode> for why this form is used.
+(define_insn "mips_set_fcsr_mips16_<mode>"
+ [(unspec_volatile:SI [(match_operand:P 0 "call_insn_operand" "dS")
+ (reg:SI SET_FCSR_REGNUM)] UNSPEC_SET_FCSR)
+ (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM))
+ (clobber (reg:P RETURN_ADDR_REGNUM))]
+ "TARGET_HARD_FLOAT_ABI && TARGET_MIPS16"
+ { return MIPS_CALL ("jal", operands, 0, -1); }
+ [(set_attr "type" "call")
+ (set_attr "insn_count" "3")])
;; Synchronization instructions.
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index ee98b2c..48a8e99 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -12617,6 +12617,15 @@ GCC provides other MIPS-specific built-in functions:
Insert a @samp{cache} instruction with operands @var{op} and @var{addr}.
GCC defines the preprocessor macro @code{___GCC_HAVE_BUILTIN_MIPS_CACHE}
when this function is available.
+
+@item unsigned int __builtin_mips_get_fcsr (void)
+@itemx void __builtin_mips_set_fcsr (unsigned int @var{value})
+Get and set the contents of the floating-point control and status register
+(FPU control register 31). These functions are only available in hard-float
+code but can be called in both MIPS16 and non-MIPS16 contexts.
+
+@code{__builtin_mips_set_fcsr} can be used to change any bit of the
+register except the condition codes, which GCC assumes are preserved.
@end table
@node MSP430 Built-in Functions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3cce684..1f27d7e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-02-02 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gcc.target/mips/get-fcsr-1.c, gcc.target/mips/get-fcsr-2.c,
+ gcc.target/mips/set-fcsr-1.c, gcc.target/mips/set-fcsr-2.c: New tests.
+
2014-02-02 Uros Bizjak <ubizjak@gmail.com>
PR target/60017
diff --git a/gcc/testsuite/gcc.target/mips/get-fcsr-1.c b/gcc/testsuite/gcc.target/mips/get-fcsr-1.c
new file mode 100644
index 0000000..46379b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/get-fcsr-1.c
@@ -0,0 +1,9 @@
+/* { dg-options "-mhard-float" } */
+
+NOMIPS16 unsigned int
+foo (void)
+{
+ return __builtin_mips_get_fcsr ();
+}
+
+/* { dg-final { scan-assembler "cfc1\t\\\$2,\\\$31" } } */
diff --git a/gcc/testsuite/gcc.target/mips/get-fcsr-2.c b/gcc/testsuite/gcc.target/mips/get-fcsr-2.c
new file mode 100644
index 0000000..29a97d3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/get-fcsr-2.c
@@ -0,0 +1,10 @@
+/* { dg-options "-mhard-float (-mips16)" } */
+
+MIPS16 unsigned int
+foo (void)
+{
+ return __builtin_mips_get_fcsr ();
+}
+
+/* { dg-final { scan-assembler "__mips16_get_fcsr" } } */
+/* { dg-final { scan-assembler "cfc1\t\\\$2,\\\$31" } } */
diff --git a/gcc/testsuite/gcc.target/mips/set-fcsr-1.c b/gcc/testsuite/gcc.target/mips/set-fcsr-1.c
new file mode 100644
index 0000000..0237272
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/set-fcsr-1.c
@@ -0,0 +1,10 @@
+/* { dg-options "-mhard-float" } */
+/* { dg-skip-if "requiring \$4 is a code-quality test" { *-*-* } { "-O0" } { "" } } */
+
+NOMIPS16 void
+foo (unsigned int x)
+{
+ __builtin_mips_set_fcsr (x);
+}
+
+/* { dg-final { scan-assembler "ctc1\t\\\$4,\\\$31" } } */
diff --git a/gcc/testsuite/gcc.target/mips/set-fcsr-2.c b/gcc/testsuite/gcc.target/mips/set-fcsr-2.c
new file mode 100644
index 0000000..8269629
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/set-fcsr-2.c
@@ -0,0 +1,10 @@
+/* { dg-options "-mhard-float (-mips16)" } */
+
+MIPS16 void
+foo (unsigned int x)
+{
+ __builtin_mips_set_fcsr (x);
+}
+
+/* { dg-final { scan-assembler "__mips16_set_fcsr" } } */
+/* { dg-final { scan-assembler "ctc1\t\\\$4,\\\$31" } } */