Please refer "MIPS RV64 P8700/P8700-F Multiprocessing System Programmer’s Guide" for more info on the extension at https://mips.com/wp-content/uploads/2025/06/P8700_Programmers_Reference_Manual_Rev1.84_5-31-2025.pdf
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.def: Likewise. * config/riscv/riscv-ext.opt: Generated file. * config/riscv/riscv.md (prefetch):. Added mips prefetch address operand constraint. * 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/riscv-ext-mips.def | 13 ++++++++ gcc/config/riscv/riscv-ext.opt | 3 ++ gcc/config/riscv/riscv-protos.h | 2 ++ gcc/config/riscv/riscv.cc | 30 +++++++++++++++++++ gcc/config/riscv/riscv.h | 9 ++++++ gcc/config/riscv/riscv.md | 14 +++++++-- gcc/doc/riscv-ext.texi | 4 +++ gcc/testsuite/gcc.target/riscv/mipsprefetch.c | 28 +++++++++++++++++ 9 files changed, 105 insertions(+), 2 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/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..11ed64c0ad5 100644 --- a/gcc/config/riscv/riscv-ext.opt +++ b/gcc/config/riscv/riscv-ext.opt @@ -449,3 +449,6 @@ 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 a41c4c299fa..a193b1f26d3 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -826,6 +826,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 1275b034cf8..c420e7a77ab 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -15389,6 +15389,36 @@ synthesize_and (rtx operands[3]) return true; } +/* Given that we have an rtx of the form (prefetch ... WRITE LOCALITY), + return the first operand of the associated PREF or PREFX insn. */ +rtx +riscv_prefetch_cookie (rtx write, rtx locality) +{ + /* store / load to data cache. */ + /* locality is unused. */ + return GEN_INT (INTVAL (write) + 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)); + else + return addr.offset == const0_rtx; + } + + return false; +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 45fa521f219..9f0087beb99 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -1319,4 +1319,13 @@ 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 hint cache type. */ +#define ICACHE_HINT (0 << 3) +#define DCACHE_HINT (1 << 3) +#define SCACHE_HINT (2 << 3) +#define TCACHE_HINT (3 << 3) + #endif /* ! GCC_RISCV_H */ diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index c3b504d0883..5a70e00401e 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -4402,11 +4402,21 @@ ) (define_insn "prefetch" - [(prefetch (match_operand 0 "prefetch_operand" "Qr") + [(prefetch (match_operand 0 "prefetch_operand" "ZD") (match_operand 1 "imm5_operand" "i") (match_operand 2 "const_int_operand" "n"))] - "TARGET_ZICBOP" + "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..2dbdb44b653 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/mipsprefetch.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32imafd_xmipscbop" { target { rv32 } } } */ +/* { dg-options "-march=rv64imafd_xmipscbop -mabi=lp64d" { target { rv64 } } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ + + +void prefetch_read(char *a) +{ + __builtin_prefetch (&a[0], 0, 0); +} + +void prefetch_write(char *a) +{ + __builtin_prefetch (&a[1], 1, 0); +} + +void prefetch_read_within_range_offset(char *a) +{ + __builtin_prefetch (&a[511], 0, 1); +} + +void prefetch_write_out_range_offset(char *a) +{ + __builtin_prefetch (&a[512], 1, 1); +} + +/* { dg-final { scan-assembler-times "mips.pref" 2 } } */ + -- 2.43.0