]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
extend.texi (__builtin_mips_get_fcsr): Document.
authorRichard Sandiford <rdsandiford@googlemail.com>
Sun, 2 Feb 2014 16:05:09 +0000 (16:05 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sun, 2 Feb 2014 16:05:09 +0000 (16:05 +0000)
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

gcc/ChangeLog
gcc/config/mips/mips-ftypes.def
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.md
gcc/doc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/get-fcsr-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/get-fcsr-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/set-fcsr-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/set-fcsr-2.c [new file with mode: 0644]

index 3311e2b0a69dff807858283a31b0883f7db98c59..93433735f76915d75695eba5a3468d7106130360 100644 (file)
@@ -1,3 +1,27 @@
+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.
index 3198abf5f69c49c882c415d7ad0ba067cfbf637f..078a595a8b1cf157c47418bc9200a16d66bbccff 100644 (file)
@@ -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))
index 7f93f15c2aa29dd3416b84c222a0eb3a1cc65560..3d59b7b51e02f9505088f3592d649dcf1673739e 100644 (file)
@@ -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);
index 12cecde84736cd0c8e3b49f910c93de2f1400f2b..cd1710b58b62dd4f6b542b0fd569f1983847102d 100644 (file)
@@ -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]);
+}
 \f
 /* Return true if symbols of type TYPE require a GOT access.  */
 
@@ -3219,6 +3263,31 @@ mips_legitimize_tls_address (rtx loc)
   return dest;
 }
 \f
+/* 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)));
+}
+\f
 /* 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);
 }
 \f
 /* 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));
index 4f643604008a996a556da04156dde28a9cc344cf..1e3e9e6595780c80cddbf35495e84c781aa7739c 100644 (file)
   UNSPEC_MFHC1
   UNSPEC_MTHC1
 
+  ;; Floating-point environment.
+  UNSPEC_GET_FCSR
+  UNSPEC_SET_FCSR
+
   ;; HI/LO moves.
   UNSPEC_MFHI
   UNSPEC_MTHI
 
 (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)
   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")])
 \f
 ;; Synchronization instructions.
 
index ee98b2c09be670932c44255468c0de53a442b89a..48a8e990d1adc3ff5cf889d0485c3e669ed370ce 100644 (file)
@@ -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
index 3cce684d9c0596288f520417efa136bf893a19ea..1f27d7ea85fb6be66ec518dfdc356696362cd7b4 100644 (file)
@@ -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 (file)
index 0000000..46379b2
--- /dev/null
@@ -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 (file)
index 0000000..29a97d3
--- /dev/null
@@ -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 (file)
index 0000000..0237272
--- /dev/null
@@ -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 (file)
index 0000000..8269629
--- /dev/null
@@ -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" } } */