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
This commit is contained in:
Richard Sandiford 2014-02-02 16:05:09 +00:00 committed by Richard Sandiford
parent 6d51cc9010
commit a90c02456f
11 changed files with 240 additions and 4 deletions

View 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.

View 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))

View 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);

View 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]);
}
/* 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));

View file

@ -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.

View 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

View 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

View file

@ -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" } } */

View file

@ -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" } } */

View file

@ -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" } } */

View file

@ -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" } } */