Commit df770e04 by David Daney Committed by David Daney

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
parent f8335a4f
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> 2007-07-10 Ian Lance Taylor <iant@google.com>
* emit-rtl.c (gen_reg_rtx): Check can_create_pseudo_p rather than * emit-rtl.c (gen_reg_rtx): Check can_create_pseudo_p rather than
......
/* Prototypes of target machine for GNU compiler. MIPS version. /* Prototypes of target machine for GNU compiler. MIPS version.
Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 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). Contributed by A. Lichnewsky (lich@inria.inria.fr).
Changed by Michael Meissner (meissner@osf.org). Changed by Michael Meissner (meissner@osf.org).
64-bit r4000 support by Ian Lance Taylor (ian@cygnus.com) and 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); ...@@ -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_emit_fcc_reload (rtx, rtx, rtx);
extern void mips_set_return_address (rtx, rtx); extern void mips_set_return_address (rtx, rtx);
extern bool mips_expand_block_move (rtx, 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 init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
......
...@@ -3883,6 +3883,33 @@ mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length) ...@@ -3883,6 +3883,33 @@ mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length)
mips_block_move_straight (dest, src, leftover); 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. */ /* Expand a movmemsi instruction. */
bool bool
......
...@@ -804,6 +804,10 @@ extern const struct mips_rtx_cost_data *mips_cost; ...@@ -804,6 +804,10 @@ extern const struct mips_rtx_cost_data *mips_cost;
|| ISA_MIPS32R2 \ || ISA_MIPS32R2 \
|| ISA_MIPS64 \ || ISA_MIPS64 \
|| TARGET_MIPS5500) || TARGET_MIPS5500)
/* ISA includes synci, jr.hb and jalr.hb. */
#define ISA_HAS_SYNCI ISA_MIPS32R2
/* Add -G xx support. */ /* Add -G xx support. */
...@@ -2151,21 +2155,16 @@ typedef struct mips_args { ...@@ -2151,21 +2155,16 @@ typedef struct mips_args {
#define INITIALIZE_TRAMPOLINE(ADDR, FUNC, CHAIN) \ #define INITIALIZE_TRAMPOLINE(ADDR, FUNC, CHAIN) \
{ \ { \
rtx func_addr, chain_addr; \ rtx func_addr, chain_addr, end_addr; \
\ \
func_addr = plus_constant (ADDR, 32); \ func_addr = plus_constant (ADDR, 32); \
chain_addr = plus_constant (func_addr, GET_MODE_SIZE (ptr_mode)); \ 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, func_addr), FUNC); \
emit_move_insn (gen_rtx_MEM (ptr_mode, chain_addr), CHAIN); \ emit_move_insn (gen_rtx_MEM (ptr_mode, chain_addr), CHAIN); \
\ end_addr = gen_reg_rtx (Pmode); \
/* Flush both caches. We need to flush the data cache in case \ emit_insn (gen_add3_insn (end_addr, copy_rtx (ADDR), \
the system has a write-back cache. */ \ GEN_INT (TRAMPOLINE_SIZE))); \
/* ??? Should check the return value for errors. */ \ emit_insn (gen_clear_cache (copy_rtx (ADDR), end_addr)); \
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)); \
} }
/* Addressing modes, and classification of registers for them. */ /* Addressing modes, and classification of registers for them. */
......
...@@ -50,6 +50,10 @@ ...@@ -50,6 +50,10 @@
(UNSPEC_TLS_GET_TP 28) (UNSPEC_TLS_GET_TP 28)
(UNSPEC_MFHC1 31) (UNSPEC_MFHC1 31)
(UNSPEC_MTHC1 32) (UNSPEC_MTHC1 32)
(UNSPEC_CLEAR_HAZARD 33)
(UNSPEC_RDHWR 34)
(UNSPEC_SYNCI 35)
(UNSPEC_SYNC 36)
(UNSPEC_ADDRESS_FIRST 100) (UNSPEC_ADDRESS_FIRST 100)
...@@ -4221,6 +4225,69 @@ ...@@ -4221,6 +4225,69 @@
} }
[(set_attr "type" "store") [(set_attr "type" "store")
(set_attr "length" "4,12")]) (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. ;; Block moves, see mips.c for more details.
;; Argument 0 is the destination ;; Argument 0 is the destination
......
/* { 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);
}
/* { 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment