Index: config/mips/mips.h =================================================================== --- config/mips/mips.h (revision 125997) +++ config/mips/mips.h (working copy) @@ -770,6 +770,10 @@ extern const struct mips_rtx_cost_data * || ISA_MIPS32R2 \ || ISA_MIPS64 \ || TARGET_MIPS5500) + +/* ISA includes synci, jr.hb and jalr.hb */ +#define ISA_HAS_SYNCI ISA_MIPS32R2 + /* Add -G xx support. */ @@ -2122,15 +2126,7 @@ typedef struct mips_args { 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)); \ + emit_insn (gen_flush_icache (copy_rtx (ADDR), GEN_INT (TRAMPOLINE_SIZE))); \ } /* Addressing modes, and classification of registers for them. */ Index: config/mips/mips.md =================================================================== --- config/mips/mips.md (revision 125997) +++ config/mips/mips.md (working copy) @@ -50,6 +50,8 @@ (define_constants (UNSPEC_TLS_GET_TP 28) (UNSPEC_MFHC1 31) (UNSPEC_MTHC1 32) + (UNSPEC_SYNCI_LOOP 33) + (UNSPEC_CLEAR_HAZARD 34) (UNSPEC_ADDRESS_FIRST 100) @@ -4171,6 +4173,72 @@ (define_insn "cprestore" } [(set_attr "type" "store") (set_attr "length" "4,12")]) + +(define_expand "flush_icache" + [(match_operand:SI 0 "general_operand" "r") + (match_operand:SI 1 "general_operand" "r")] + "" + " +{ + if (ISA_HAS_SYNCI) + { + emit_insn (gen_synci_loop (copy_rtx (operands[0]), + copy_rtx (operands[1]))); + emit_insn (gen_clear_hazard ()); + } + else + /* 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, copy_rtx (operands[0]), Pmode, + copy_rtx (operands[1]), TYPE_MODE (integer_type_node), + GEN_INT (3), TYPE_MODE (integer_type_node)); + DONE; +}") + +(define_insn "synci_loop" + [(unspec_volatile[(match_operand:SI 0 "general_operand" "r") + (match_operand:SI 1 "general_operand" "r") + (clobber (match_scratch:SI 2 "=0")) + (clobber (match_scratch:SI 3 "=1")) + (clobber (match_scratch:SI 4 "=r")) + (clobber (match_scratch:SI 5 "=r"))] + UNSPEC_SYNCI_LOOP)] + "ISA_HAS_SYNCI" +{ + return ".set\tpush\n" + "\t.set\tnoreorder\n" + "\t.set\tnomacro\n" + "\taddu\t%3,%0,%1\n" + "\trdhwr\t%4,$1\n" + "1:\tsynci\t0(%2)\n" + "\tsltu\t%5,%2,%3\n" + "\tbne\t%5,$0,1b\n" + "\taddu\t%2,%2,%4\n" + "\tsync\n" + "\t.set\tpop"; + } + [(set_attr "length" "28")]) + +(define_insn "clear_hazard" + [(unspec_volatile [(clobber (match_scratch:SI 0 "=r"))] 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%0,$31,12\n" + "\tjr.hb\t%0\n" + "\tnop\n" + "\t.set\tpop"; +} + [(set_attr "length" "20")]) + ;; Block moves, see mips.c for more details. ;; Argument 0 is the destination Index: testsuite/gcc.target/mips/flush-icache-2.c =================================================================== --- testsuite/gcc.target/mips/flush-icache-2.c (revision 0) +++ testsuite/gcc.target/mips/flush-icache-2.c (revision 0) @@ -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_flush_icache(memory, size); +} + Index: testsuite/gcc.target/mips/flush-icache-1.c =================================================================== --- testsuite/gcc.target/mips/flush-icache-1.c (revision 0) +++ testsuite/gcc.target/mips/flush-icache-1.c (revision 0) @@ -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_flush_icache(memory, size); +} + Index: testsuite/gcc.target/mips/flush-icache-3.c =================================================================== --- testsuite/gcc.target/mips/flush-icache-3.c (revision 0) +++ testsuite/gcc.target/mips/flush-icache-3.c (revision 0) @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-mips-options "-O2 -mips32r2" } */ +/* { dg-final { scan-assembler-not "synci" } } */ +/* { dg-final { scan-assembler-not "jr.hb" } } */ +/* { dg-final { scan-assembler-not "_flush_cache" } } */ + +void f() +{ + char *memory = __builtin_alloca(40); + __builtin_flush_icache(memory, 0); +} +