OSDN Git Service

2007-07-10 David Daney <ddaney@avtrex.com>
authordaney <daney@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 11 Jul 2007 05:14:35 +0000 (05:14 +0000)
committerdaney <daney@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 11 Jul 2007 05:14:35 +0000 (05:14 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@126537 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/testsuite/gcc.target/mips/clear-cache-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/clear-cache-2.c [new file with mode: 0644]

index 6634f68..4d99782 100644 (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
index 86b5f03..09d5d4a 100644 (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,
index c1cf631..e3100d1 100644 (file)
@@ -3883,6 +3883,33 @@ mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length)
     mips_block_move_straight (dest, src, leftover);
 }
 \f
+
+/* 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));
+}
+\f
 /* Expand a movmemsi instruction.  */
 
 bool
index 2425d13..38c8eda 100644 (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
+
 \f
 /* 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));                 \
 }
 \f
 /* Addressing modes, and classification of registers for them.  */
index 255d6e6..df4f80d 100644 (file)
    (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)
 
 }
   [(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")])
 \f
 ;; Block moves, see mips.c for more details.
 ;; Argument 0 is the destination
diff --git a/gcc/testsuite/gcc.target/mips/clear-cache-1.c b/gcc/testsuite/gcc.target/mips/clear-cache-1.c
new file mode 100644 (file)
index 0000000..ece1f50
--- /dev/null
@@ -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);
+}
+
diff --git a/gcc/testsuite/gcc.target/mips/clear-cache-2.c b/gcc/testsuite/gcc.target/mips/clear-cache-2.c
new file mode 100644 (file)
index 0000000..ee7c050
--- /dev/null
@@ -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);
+}
+