Addressed the comments and tested "runtest --tool gcc 
--target_board='riscv-sim/-march=rv64gc_zba_zbb_zbc_zbs/-mabi=lp64/-mcmodel=medlow'
 riscv.exp" and 32 bit too

lint warnings can be ignored for riscv-ext.opt.

gcc/ChangeLog:

        * config/riscv/riscv-ext-mips.def (DEFINE_RISCV_EXT):
        Added mips prefetch extension.
        * config/riscv/riscv-ext.opt: Generated file.
        * config/riscv/riscv.md (prefetch):
        Added mips prefetch address operand constraint.
        * config/riscv/constraints.md: Added mips specific constraint.
        * config/riscv/predicates.md (prefetch_operand):
        Updated for mips nine bits offset.
        * config/riscv/riscv.cc (riscv_prefetch_offset_address_p):
        Legitimate address with offset for prefetch check.
        * config/riscv/riscv-protos.h: Likewise.
        * config/riscv/riscv.h:
        Macros to support for mips cached type.
        * doc/riscv-ext.texi: Updated for mips prefetch.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/mipsprefetch.c: Test file for mips.pref.
---
 gcc/config/riscv/constraints.md               |  4 +++
 gcc/config/riscv/predicates.md                | 20 +++++++++++-
 gcc/config/riscv/riscv-ext-mips.def           | 13 ++++++++
 gcc/config/riscv/riscv-ext.opt                |  2 ++
 gcc/config/riscv/riscv-protos.h               |  2 ++
 gcc/config/riscv/riscv.cc                     | 31 +++++++++++++++++++
 gcc/config/riscv/riscv.h                      | 11 +++++++
 gcc/config/riscv/riscv.md                     | 18 ++++++++---
 gcc/doc/riscv-ext.texi                        |  4 +++
 gcc/testsuite/gcc.target/riscv/mipsprefetch.c | 31 +++++++++++++++++++
 10 files changed, 131 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/mipsprefetch.c

diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index 5ecaa19eb01..979e0df06f1 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -330,3 +330,7 @@
 (define_constraint "Q"
   "An address operand that is valid for a prefetch instruction"
   (match_operand 0 "prefetch_operand"))
+
+(define_address_constraint "ZD"
+  "An address operand that is valid for a mips prefetch instruction"
+  (match_test "riscv_prefetch_offset_address_p (op, mode)"))
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 381f96c3e72..0f9b4039f1e 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -27,10 +27,14 @@
   (ior (match_operand 0 "const_arith_operand")
        (match_operand 0 "register_operand")))
 
+(define_predicate "prefetch_const_operand"
+  (and (match_code "const_int")
+       (match_test "(IN_RANGE (INTVAL (op),  0, 511))")))
+
 ;; REG or REG+D where D fits in a simm12 and has the low 5 bits
 ;; off.  The REG+D form can be reloaded into a temporary if needed
 ;; after FP elimination if that exposes an invalid offset.
-(define_predicate "prefetch_operand"
+(define_predicate "zicbop_prefetch_operand"
   (ior (match_operand 0 "register_operand")
        (and (match_test "const_arith_operand (op, VOIDmode)")
            (match_test "(INTVAL (op) & 0x1f) == 0"))
@@ -39,6 +43,20 @@
            (match_test "const_arith_operand (XEXP (op, 1), VOIDmode)")
            (match_test "(INTVAL (XEXP (op, 1)) & 0x1f) == 0"))))
 
+;; REG or REG+D where D fits in a uimm9
+(define_predicate "mips_prefetch_operand"
+  (ior (match_operand 0 "register_operand")
+       (match_test "prefetch_const_operand (op, VOIDmode)")
+       (and (match_code "plus")
+        (match_test "register_operand (XEXP (op, 0), word_mode)")
+        (match_test "prefetch_const_operand (XEXP (op, 1), VOIDmode)"))))
+
+;; MIPS specific or Standard RISCV Extension
+(define_predicate "prefetch_operand"
+  (if_then_else (match_test "TARGET_XMIPSCBOP")
+      (match_operand 0 "mips_prefetch_operand")
+      (match_operand 0 "zicbop_prefetch_operand")))
+
 (define_predicate "lui_operand"
   (and (match_code "const_int")
        (match_test "LUI_OPERAND (INTVAL (op))")))
diff --git a/gcc/config/riscv/riscv-ext-mips.def 
b/gcc/config/riscv/riscv-ext-mips.def
index 5d7836d5999..132f6c1060d 100644
--- a/gcc/config/riscv/riscv-ext-mips.def
+++ b/gcc/config/riscv/riscv-ext-mips.def
@@ -33,3 +33,16 @@ DEFINE_RISCV_EXT (
   /* BITMASK_GROUP_ID.  */ BITMASK_NOT_YET_ALLOCATED,
   /* BITMASK_BIT_POSITION.  */ BITMASK_NOT_YET_ALLOCATED,
   /* EXTRA_EXTENSION_FLAGS.  */ 0)
+
+DEFINE_RISCV_EXT (
+  /* NAME.  */ xmipscbop,
+  /* UPPERCASE_NAME.  */ XMIPSCBOP,
+  /* FULL_NAME.  */ "Mips Prefetch extension",
+  /* DESC.  */ "",
+  /* URL.  */ ,
+  /* DEP_EXTS.  */ ({}),
+  /* SUPPORTED_VERSIONS.  */ ({{1, 0}}),
+  /* FLAG_GROUP.  */ xmips,
+  /* BITMASK_GROUP_ID.  */ BITMASK_NOT_YET_ALLOCATED,
+  /* BITMASK_BIT_POSITION.  */ BITMASK_NOT_YET_ALLOCATED,
+  /* EXTRA_EXTENSION_FLAGS.  */ 0)
diff --git a/gcc/config/riscv/riscv-ext.opt b/gcc/config/riscv/riscv-ext.opt
index 26d6e683acd..ced05d22311 100644
--- a/gcc/config/riscv/riscv-ext.opt
+++ b/gcc/config/riscv/riscv-ext.opt
@@ -449,3 +449,5 @@ Mask(XTHEADVECTOR) Var(riscv_xthead_subext)
 Mask(XVENTANACONDOPS) Var(riscv_xventana_subext)
 
 Mask(XMIPSCMOV) Var(riscv_xmips_subext)
+
+Mask(XMIPSCBOP) Var(riscv_xmips_subext)
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index b4973251535..a3cb282dde0 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -841,6 +841,8 @@ riscv_process_target_version_attr (tree, location_t);
 extern void
 riscv_override_options_internal (struct gcc_options *);
 extern void riscv_option_override (void);
+extern rtx riscv_prefetch_cookie (rtx, rtx);
+extern bool riscv_prefetch_offset_address_p (rtx, machine_mode);
 
 struct riscv_tune_param;
 /* Information about one micro-arch we know about.  */
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index e9217dcb043..7722497289b 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -15449,6 +15449,37 @@ synthesize_add (rtx operands[3])
   return true;
 }
 
+/*
+    hint : argument specify the target cache
+
+    TODO : locality is unused.
+
+    Return the first operand of the associated PREF or PREFX insn.  */
+rtx
+riscv_prefetch_cookie (rtx hint, rtx locality)
+{
+  return (GEN_INT (INTVAL (hint)
+                 + CacheHint::DCACHE_HINT + INTVAL (locality) * 0));
+}
+
+/* Return true if X is a legitimate address with offset for prefetch.
+   MODE is the mode of the value being accessed.  */
+bool
+riscv_prefetch_offset_address_p (rtx x, machine_mode mode)
+{
+  struct riscv_address_info addr;
+
+  if (riscv_classify_address (&addr, x, mode, false)
+      && addr.type == ADDRESS_REG)
+    {
+      if (TARGET_XMIPSCBOP)
+       return (CONST_INT_P (addr.offset)
+                      && MIPS_RISCV_9BIT_OFFSET_P (INTVAL (addr.offset)));
+   }
+
+  return true;
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 29342d8a64c..a728de4391f 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -1325,4 +1325,15 @@ extern void riscv_remove_unneeded_save_restore_calls 
(void);
 
 #define TARGET_HAS_FMV_TARGET_ATTRIBUTE 0
 
+/* mips pref valid offset range.  */
+#define MIPS_RISCV_9BIT_OFFSET_P(OFFSET) (IN_RANGE (OFFSET, 0, 511))
+
+/* mips pref cache hint type.  */
+typedef enum {
+    ICACHE_HINT = 0 << 3,
+    DCACHE_HINT = 1 << 3,
+    SCACHE_HINT = 2 << 3,
+    TCACHE_HINT = 3 << 3
+} CacheHint;
+
 #endif /* ! GCC_RISCV_H */
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index a72604e2921..451467fc586 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -4422,11 +4422,21 @@
 )
 
 (define_insn "prefetch"
-  [(prefetch (match_operand 0 "prefetch_operand" "Qr")
-             (match_operand 1 "imm5_operand" "i")
-             (match_operand 2 "const_int_operand" "n"))]
-  "TARGET_ZICBOP"
+  [(prefetch (match_operand 0 "prefetch_operand" "Qr,ZD")
+             (match_operand 1 "imm5_operand" "i,i")
+             (match_operand 2 "const_int_operand" "n,n"))]
+  "TARGET_ZICBOP || TARGET_XMIPSCBOP"
 {
+  if (TARGET_XMIPSCBOP)
+    {
+      /* Mips Prefetch write is nop for p8700.  */
+      if (operands[1] != CONST0_RTX (GET_MODE (operands[1])))
+      return "nop";
+
+      operands[1] = riscv_prefetch_cookie (operands[1], operands[2]);
+      return "mips.pref\t%1,%a0";
+    }
+
   switch (INTVAL (operands[1]))
   {
     case 0:
diff --git a/gcc/doc/riscv-ext.texi b/gcc/doc/riscv-ext.texi
index 572b70e20fa..185084edde7 100644
--- a/gcc/doc/riscv-ext.texi
+++ b/gcc/doc/riscv-ext.texi
@@ -718,4 +718,8 @@
 @tab 1.0
 @tab Mips conditional move extension
 
+@item xmipscbop
+@tab 1.0
+@tab Mips Prefetch extension
+
 @end multitable
diff --git a/gcc/testsuite/gcc.target/riscv/mipsprefetch.c 
b/gcc/testsuite/gcc.target/riscv/mipsprefetch.c
new file mode 100644
index 00000000000..b58aa0fa085
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/mipsprefetch.c
@@ -0,0 +1,31 @@
+/* pic used here to prevent the assembler to emit .nopic directive.  */
+/* { dg-do compile } */
+/* { dg-options "-march=rv32imafd_xmipscbop -fpic" { target { rv32 } } } */
+/* { dg-options "-march=rv64imafd_xmipscbop -fpic -mabi=lp64d" { target { rv64 
} } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+
+void prefetch_read(char *a)
+{
+  __builtin_prefetch (&a[3], 0, 0);
+}
+
+void prefetch_write(char *a)
+{
+  __builtin_prefetch (&a[1], 1, 0);
+}
+
+void prefetch_read_out_range_offset(char *a)
+{
+  __builtin_prefetch (&a[512], 0, 1);
+}
+
+void prefetch_write_out_range_offset(char *a)
+{
+  __builtin_prefetch (&a[1024], 1, 1);
+}
+
+/* { dg-final { scan-assembler-times "mips.pref\t8,0\\(\[a-x0-9\]+\\)" 1 } } */
+/* { dg-final { scan-assembler-times "mips.pref\t8,3\\(\[a-x0-9\]+\\)" 1 } } */
+/* { dg-final { scan-assembler-times "nop" 2 } } */
+

base-commit: b1f9ab40cbcc6ecd53a2be3e01052cee096e1a00
-- 
2.43.0

Reply via email to