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.
(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)"))
(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"))
(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))")))
/* 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)
Mask(XVENTANACONDOPS) Var(riscv_xventana_subext)
Mask(XMIPSCMOV) Var(riscv_xmips_subext)
+
+Mask(XMIPSCBOP) Var(riscv_xmips_subext)
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. */
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"
#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 */
)
(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:
@tab 1.0
@tab Mips conditional move extension
+@item xmipscbop
+@tab 1.0
+@tab Mips Prefetch extension
+
@end multitable
--- /dev/null
+/* 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 } } */
+