mips.h (ISA_HAS_SYNCI): New target capability predicate.

2007-07-10  David Daney  <ddaney@avtrex.com>

	* config/mips/mips.h (ISA_HAS_SYNCI): New target capability
	predicate.
	(INITIALIZE_TRAMPOLINE): Emit clear_cache insn instead of  library
	call.
	* config/mips/mips.c (mips_expand_synci_loop): New function.
	* config/mips/mips.md (UNSPEC_CLEAR_HAZARD): New constant.
	(UNSPEC_RDHWR): Same.
	(UNSPEC_SYNCI): Same.
	(UNSPEC_SYNC): Same.
	(clear_cache): New expand.
	(sync): New insn.
	(synci): Same.
	(rdhwr): Same.
	(clear_hazard): Same.
	* config/mips/mips-protos.h (mips_expand_synci_loop): Declare
	function.
	* testsuite/gcc.target/mips/clear-cache-1.c: New test.
	* testsuite/gcc.target/mips/clear-cache-2.c: New test.

From-SVN: r126537
This commit is contained in:
David Daney 2007-07-11 05:14:35 +00:00 committed by David Daney
parent f8335a4ff0
commit df770e0442
7 changed files with 152 additions and 11 deletions

View File

@ -1,3 +1,24 @@
2007-07-10 David Daney <ddaney@avtrex.com>
* config/mips/mips.h (ISA_HAS_SYNCI): New target capability
predicate.
(INITIALIZE_TRAMPOLINE): Emit clear_cache insn instead of library
call.
* config/mips/mips.c (mips_expand_synci_loop): New function.
* config/mips/mips.md (UNSPEC_CLEAR_HAZARD): New constant.
(UNSPEC_RDHWR): Same.
(UNSPEC_SYNCI): Same.
(UNSPEC_SYNC): Same.
(clear_cache): New expand.
(sync): New insn.
(synci): Same.
(rdhwr): Same.
(clear_hazard): Same.
* config/mips/mips-protos.h (mips_expand_synci_loop): Declare
function.
* testsuite/gcc.target/mips/clear-cache-1.c: New test.
* testsuite/gcc.target/mips/clear-cache-2.c: New test.
2007-07-10 Ian Lance Taylor <iant@google.com>
* emit-rtl.c (gen_reg_rtx): Check can_create_pseudo_p rather than

View File

@ -1,6 +1,6 @@
/* Prototypes of target machine for GNU compiler. MIPS version.
Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
1999, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
Contributed by A. Lichnewsky (lich@inria.inria.fr).
Changed by Michael Meissner (meissner@osf.org).
64-bit r4000 support by Ian Lance Taylor (ian@cygnus.com) and
@ -187,6 +187,7 @@ extern void mips_expand_call (rtx, rtx, rtx, rtx, int);
extern void mips_emit_fcc_reload (rtx, rtx, rtx);
extern void mips_set_return_address (rtx, rtx);
extern bool mips_expand_block_move (rtx, rtx, rtx);
extern void mips_expand_synci_loop (rtx, rtx);
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,

View File

@ -3883,6 +3883,33 @@ mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length)
mips_block_move_straight (dest, src, leftover);
}
/* Expand a loop of synci insns for the address range [BEGIN, END). */
void
mips_expand_synci_loop (rtx begin, rtx end)
{
rtx inc, label, cmp, cmp_result;
/* Load INC with the cache line size (rdhwr INC,$1). */
inc = gen_reg_rtx (SImode);
emit_insn (gen_rdhwr (inc, const1_rtx));
/* Loop back to here. */
label = gen_label_rtx ();
emit_label (label);
emit_insn (gen_synci (begin));
cmp = gen_reg_rtx (Pmode);
mips_emit_binary (GTU, cmp, begin, end);
mips_emit_binary (PLUS, begin, begin, inc);
cmp_result = gen_rtx_EQ (VOIDmode, cmp, const0_rtx);
emit_jump_insn (gen_condjump (cmp_result, label));
}
/* Expand a movmemsi instruction. */
bool

View File

@ -804,6 +804,10 @@ extern const struct mips_rtx_cost_data *mips_cost;
|| ISA_MIPS32R2 \
|| ISA_MIPS64 \
|| TARGET_MIPS5500)
/* ISA includes synci, jr.hb and jalr.hb. */
#define ISA_HAS_SYNCI ISA_MIPS32R2
/* Add -G xx support. */
@ -2151,21 +2155,16 @@ typedef struct mips_args {
#define INITIALIZE_TRAMPOLINE(ADDR, FUNC, CHAIN) \
{ \
rtx func_addr, chain_addr; \
rtx func_addr, chain_addr, end_addr; \
\
func_addr = plus_constant (ADDR, 32); \
chain_addr = plus_constant (func_addr, GET_MODE_SIZE (ptr_mode)); \
emit_move_insn (gen_rtx_MEM (ptr_mode, func_addr), FUNC); \
emit_move_insn (gen_rtx_MEM (ptr_mode, chain_addr), CHAIN); \
\
/* Flush both caches. We need to flush the data cache in case \
the system has a write-back cache. */ \
/* ??? Should check the return value for errors. */ \
if (mips_cache_flush_func && mips_cache_flush_func[0]) \
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mips_cache_flush_func), \
0, VOIDmode, 3, ADDR, Pmode, \
GEN_INT (TRAMPOLINE_SIZE), TYPE_MODE (integer_type_node),\
GEN_INT (3), TYPE_MODE (integer_type_node)); \
end_addr = gen_reg_rtx (Pmode); \
emit_insn (gen_add3_insn (end_addr, copy_rtx (ADDR), \
GEN_INT (TRAMPOLINE_SIZE))); \
emit_insn (gen_clear_cache (copy_rtx (ADDR), end_addr)); \
}
/* Addressing modes, and classification of registers for them. */

View File

@ -50,6 +50,10 @@
(UNSPEC_TLS_GET_TP 28)
(UNSPEC_MFHC1 31)
(UNSPEC_MTHC1 32)
(UNSPEC_CLEAR_HAZARD 33)
(UNSPEC_RDHWR 34)
(UNSPEC_SYNCI 35)
(UNSPEC_SYNC 36)
(UNSPEC_ADDRESS_FIRST 100)
@ -4221,6 +4225,69 @@
}
[(set_attr "type" "store")
(set_attr "length" "4,12")])
;; Expand in-line code to clear the instruction cache between operand[0] and
;; operand[1].
(define_expand "clear_cache"
[(match_operand 0 "pmode_register_operand")
(match_operand 1 "pmode_register_operand")]
""
"
{
if (ISA_HAS_SYNCI)
{
mips_expand_synci_loop (operands[0], operands[1]);
emit_insn (gen_sync ());
emit_insn (gen_clear_hazard ());
}
else if (mips_cache_flush_func && mips_cache_flush_func[0])
{
rtx len = gen_reg_rtx (Pmode);
emit_insn (gen_sub3_insn (len, operands[1], operands[0]));
/* Flush both caches. We need to flush the data cache in case
the system has a write-back cache. */
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mips_cache_flush_func),
0, VOIDmode, 3, operands[0], Pmode,
len, TYPE_MODE (integer_type_node),
GEN_INT (3), TYPE_MODE (integer_type_node));
}
DONE;
}")
(define_insn "sync"
[(unspec_volatile [(const_int 0)] UNSPEC_SYNC)]
"ISA_HAS_SYNCI"
"sync")
(define_insn "synci"
[(unspec_volatile [(match_operand 0 "pmode_register_operand" "d")]
UNSPEC_SYNCI)]
"ISA_HAS_SYNCI"
"synci\t0(%0)")
(define_insn "rdhwr"
[(set (match_operand:SI 0 "general_operand" "=d")
(unspec_volatile [(match_operand:SI 1 "const_int_operand" "n")]
UNSPEC_RDHWR))]
"ISA_HAS_SYNCI"
"rdhwr\t%0,$%1")
(define_insn "clear_hazard"
[(unspec_volatile [(const_int 0)] UNSPEC_CLEAR_HAZARD)
(clobber (reg:SI 31))]
"ISA_HAS_SYNCI"
{
return ".set\tpush\n"
"\t.set\tnoreorder\n"
"\t.set\tnomacro\n"
"\tbal\t1f\n"
"\tnop\n"
"1:\taddiu\t$31,$31,12\n"
"\tjr.hb\t$31\n"
"\tnop\n"
"\t.set\tpop";
}
[(set_attr "length" "20")])
;; Block moves, see mips.c for more details.
;; Argument 0 is the destination

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-mips-options "-O2 -mips32r2" } */
/* { dg-final { scan-assembler "synci" } } */
/* { dg-final { scan-assembler "jr.hb" } } */
/* { dg-final { scan-assembler-not "_flush_cache" } } */
void f()
{
int size = 40;
char *memory = __builtin_alloca(size);
__builtin___clear_cache(memory, memory + size);
}

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-mips-options "-O2 -mips32" } */
/* { dg-final { scan-assembler-not "synci" } } */
/* { dg-final { scan-assembler-not "jr.hb" } } */
/* { dg-final { scan-assembler "_flush_cache" } } */
void f()
{
int size = 40;
char *memory = __builtin_alloca(size);
__builtin___clear_cache(memory, memory + size);
}