From a90c02456f4655254477e00e338163ffab9bd97b Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sun, 2 Feb 2014 16:05:09 +0000 Subject: [PATCH] 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_) (mips_set_fcsr, *mips_set_fcsr, mips_set_fcsr_mips16_): 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 | 24 ++++++ gcc/config/mips/mips-ftypes.def | 3 + gcc/config/mips/mips-protos.h | 2 + gcc/config/mips/mips.c | 96 +++++++++++++++++++++- gcc/config/mips/mips.md | 66 +++++++++++++++ gcc/doc/extend.texi | 9 ++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.target/mips/get-fcsr-1.c | 9 ++ gcc/testsuite/gcc.target/mips/get-fcsr-2.c | 10 +++ gcc/testsuite/gcc.target/mips/set-fcsr-1.c | 10 +++ gcc/testsuite/gcc.target/mips/set-fcsr-2.c | 10 +++ 11 files changed, 240 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.target/mips/get-fcsr-1.c create mode 100644 gcc/testsuite/gcc.target/mips/get-fcsr-2.c create mode 100644 gcc/testsuite/gcc.target/mips/set-fcsr-1.c create mode 100644 gcc/testsuite/gcc.target/mips/set-fcsr-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3311e2b0a69..93433735f76 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +2014-02-02 Richard Sandiford + + * 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_) + (mips_set_fcsr, *mips_set_fcsr, mips_set_fcsr_mips16_): New + patterns. + 2014-02-02 Richard Sandiford * config/mips/mips.c (mips_one_only_stub): New class. diff --git a/gcc/config/mips/mips-ftypes.def b/gcc/config/mips/mips-ftypes.def index 3198abf5f69..078a595a8b1 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 7f93f15c2aa..3d59b7b51e0 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 12cecde8473..cd1710b58b6 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 4f643604008..1e3e9e65957 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_ for why this form is used. +(define_insn "mips_get_fcsr_mips16_" + [(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_ for why this form is used. +(define_insn "mips_set_fcsr_mips16_" + [(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 ee98b2c09be..48a8e990d1a 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 3cce684d9c0..1f27d7ea85f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-02-02 Richard Sandiford + + * 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 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 00000000000..46379b25752 --- /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 00000000000..29a97d30917 --- /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 00000000000..0237272cfc3 --- /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 00000000000..82696298f56 --- /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" } } */