RISC-V: Add T-Head CMO vendor extension
authorChristoph Müllner <christoph.muellner@vrull.eu>
Tue, 28 Jun 2022 15:43:20 +0000 (17:43 +0200)
committerPhilipp Tomsich <philipp.tomsich@vrull.eu>
Thu, 22 Sep 2022 16:06:09 +0000 (18:06 +0200)
T-Head has a range of vendor-specific instructions.
Therefore it makes sense to group them into smaller chunks
in form of vendor extensions.

This patch adds the XTheadCmo extension, a collection of T-Head specific
cache management operations.
The 'th' prefix and the "XTheadCmo" extension are documented in a PR
for the RISC-V toolchain conventions ([1]).

In total XTheadCmo introduces the following 21 instructions:

* DCACHE.{C,CI,I}ALL
* DCACHE.{C,CI,I}{PA,VA,SW} rs1
* DCACHE.C{PAL1,VAL1} rs1
* ICACHE.I{ALL,ALLS}
* ICACHE.I{PA,VA} rs1
* L2CACHE.{C,CI,I}ALL

Contrary to Zicbom, the XTheadCmo instructions don't have a constant
displacement, therefore we have a different syntax for the arguments.
To clarify this is intended behaviour, there is a set of negative test
for Zicbom-style arguments in x-thead-cmo-fail.s.

[1] https://github.com/riscv-non-isa/riscv-toolchain-conventions/pull/19

v2:
- Add missing DECLARE_INSN() list
- Fix ordering

Co-developed-by: Lifang Xia <lifang_xia@linux.alibaba.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
bfd/elfxx-riscv.c
gas/doc/c-riscv.texi
gas/testsuite/gas/riscv/x-thead-cmo-fail.d [new file with mode: 0644]
gas/testsuite/gas/riscv/x-thead-cmo-fail.l [new file with mode: 0644]
gas/testsuite/gas/riscv/x-thead-cmo-fail.s [new file with mode: 0644]
gas/testsuite/gas/riscv/x-thead-cmo.d [new file with mode: 0644]
gas/testsuite/gas/riscv/x-thead-cmo.s [new file with mode: 0644]
include/opcode/riscv-opc.h
include/opcode/riscv.h
opcodes/riscv-opc.c

index cb3a980936d0122a6e7cf3e593795a40097ada4a..82891f3747e04fc812873b34bf401a57086f7a00 100644 (file)
@@ -1224,6 +1224,7 @@ static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
 
 static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
 {
+  {"xtheadcmo",                ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
   {NULL, 0, 0, 0, 0}
 };
 
@@ -2386,6 +2387,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
       return riscv_subset_supports (rps, "svinval");
     case INSN_CLASS_H:
       return riscv_subset_supports (rps, "h");
+    case INSN_CLASS_XTHEADCMO:
+      return riscv_subset_supports (rps, "xtheadcmo");
     default:
       rps->error_handler
         (_("internal: unreachable INSN_CLASS_*"));
@@ -2513,6 +2516,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
       return "svinval";
     case INSN_CLASS_H:
       return _("h");
+    case INSN_CLASS_XTHEADCMO:
+      return "xtheadcmo";
     default:
       rps->error_handler
         (_("internal: unreachable INSN_CLASS_*"));
index 30afd200b7db9ad920ff943c658f6dd3c6ea083e..10e9429c83e913e50ea178773b0f886859ef57e2 100644 (file)
@@ -704,5 +704,9 @@ extensions supported and provides the location of their
 publicly-released documentation:
 
 @table @r
+@item XTheadCmo
+The XTheadCmo extension provides instructions for cache management.
+
+It is documented in @url{https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.0.0/xthead-2022-09-05-2.0.0.pdf}.
 
 @end table
diff --git a/gas/testsuite/gas/riscv/x-thead-cmo-fail.d b/gas/testsuite/gas/riscv/x-thead-cmo-fail.d
new file mode 100644 (file)
index 0000000..de794ea
--- /dev/null
@@ -0,0 +1,3 @@
+#as: -march=rv64i_xtheadcmo
+#source: x-thead-cmo-fail.s
+#error_output: x-thead-cmo-fail.l
diff --git a/gas/testsuite/gas/riscv/x-thead-cmo-fail.l b/gas/testsuite/gas/riscv/x-thead-cmo-fail.l
new file mode 100644 (file)
index 0000000..4381fe1
--- /dev/null
@@ -0,0 +1,22 @@
+.*: Assembler messages:
+.*: Error: illegal operands `th.dcache.call x1'
+.*: Error: illegal operands `th.dcache.ciall x1'
+.*: Error: illegal operands `th.dcache.iall x1'
+.*: Error: illegal operands `th.dcache.cpa 0\(x1\)'
+.*: Error: illegal operands `th.dcache.cipa 0\(x1\)'
+.*: Error: illegal operands `th.dcache.ipa 0\(x1\)'
+.*: Error: illegal operands `th.dcache.cva 0\(x1\)'
+.*: Error: illegal operands `th.dcache.civa 0\(x1\)'
+.*: Error: illegal operands `th.dcache.iva 0\(x1\)'
+.*: Error: illegal operands `th.dcache.csw 0\(x1\)'
+.*: Error: illegal operands `th.dcache.cisw 0\(x1\)'
+.*: Error: illegal operands `th.dcache.isw 0\(x1\)'
+.*: Error: illegal operands `th.dcache.cpal1 0\(x1\)'
+.*: Error: illegal operands `th.dcache.cval1 0\(x1\)'
+.*: Error: illegal operands `th.icache.iall x1'
+.*: Error: illegal operands `th.icache.ialls x1'
+.*: Error: illegal operands `th.icache.ipa 0\(x1\)'
+.*: Error: illegal operands `th.icache.iva 0\(x1\)'
+.*: Error: illegal operands `th.l2cache.call x1'
+.*: Error: illegal operands `th.l2cache.ciall x1'
+.*: Error: illegal operands `th.l2cache.iall x1'
diff --git a/gas/testsuite/gas/riscv/x-thead-cmo-fail.s b/gas/testsuite/gas/riscv/x-thead-cmo-fail.s
new file mode 100644 (file)
index 0000000..591d982
--- /dev/null
@@ -0,0 +1,22 @@
+target:
+       th.dcache.call  x1
+       th.dcache.ciall x1
+       th.dcache.iall  x1
+       th.dcache.cpa   0(x1)
+       th.dcache.cipa  0(x1)
+       th.dcache.ipa   0(x1)
+       th.dcache.cva   0(x1)
+       th.dcache.civa  0(x1)
+       th.dcache.iva   0(x1)
+       th.dcache.csw   0(x1)
+       th.dcache.cisw  0(x1)
+       th.dcache.isw   0(x1)
+       th.dcache.cpal1 0(x1)
+       th.dcache.cval1 0(x1)
+       th.icache.iall  x1
+       th.icache.ialls x1
+       th.icache.ipa   0(x1)
+       th.icache.iva   0(x1)
+       th.l2cache.call x1
+       th.l2cache.ciall        x1
+       th.l2cache.iall x1
diff --git a/gas/testsuite/gas/riscv/x-thead-cmo.d b/gas/testsuite/gas/riscv/x-thead-cmo.d
new file mode 100644 (file)
index 0000000..f482ddc
--- /dev/null
@@ -0,0 +1,30 @@
+#as: -march=rv64i_xtheadcmo
+#source: x-thead-cmo.s
+#objdump: -dr
+
+.*:[   ]+file format .*
+
+Disassembly of section .text:
+
+0+000 <target>:
+[      ]+[0-9a-f]+:[   ]+0010000b[     ]+th.dcache.call
+[      ]+[0-9a-f]+:[   ]+0030000b[     ]+th.dcache.ciall
+[      ]+[0-9a-f]+:[   ]+0020000b[     ]+th.dcache.iall
+[      ]+[0-9a-f]+:[   ]+0295000b[     ]+th.dcache.cpa[        ]+a0
+[      ]+[0-9a-f]+:[   ]+02b5800b[     ]+th.dcache.cipa[       ]+a1
+[      ]+[0-9a-f]+:[   ]+02a6000b[     ]+th.dcache.ipa[        ]+a2
+[      ]+[0-9a-f]+:[   ]+0256800b[     ]+th.dcache.cva[        ]+a3
+[      ]+[0-9a-f]+:[   ]+0277000b[     ]+th.dcache.civa[       ]+a4
+[      ]+[0-9a-f]+:[   ]+0267800b[     ]+th.dcache.iva[        ]+a5
+[      ]+[0-9a-f]+:[   ]+0218000b[     ]+th.dcache.csw[        ]+a6
+[      ]+[0-9a-f]+:[   ]+0238800b[     ]+th.dcache.cisw[       ]+a7
+[      ]+[0-9a-f]+:[   ]+0222800b[     ]+th.dcache.isw[        ]+t0
+[      ]+[0-9a-f]+:[   ]+0283000b[     ]+th.dcache.cpal1[      ]+t1
+[      ]+[0-9a-f]+:[   ]+0243800b[     ]+th.dcache.cval1[      ]+t2
+[      ]+[0-9a-f]+:[   ]+0100000b[     ]+th.icache.iall
+[      ]+[0-9a-f]+:[   ]+0110000b[     ]+th.icache.ialls
+[      ]+[0-9a-f]+:[   ]+038e000b[     ]+th.icache.ipa[        ]+t3
+[      ]+[0-9a-f]+:[   ]+030e800b[     ]+th.icache.iva[        ]+t4
+[      ]+[0-9a-f]+:[   ]+0150000b[     ]+th.l2cache.call
+[      ]+[0-9a-f]+:[   ]+0170000b[     ]+th.l2cache.ciall
+[      ]+[0-9a-f]+:[   ]+0160000b[     ]+th.l2cache.iall
diff --git a/gas/testsuite/gas/riscv/x-thead-cmo.s b/gas/testsuite/gas/riscv/x-thead-cmo.s
new file mode 100644 (file)
index 0000000..2a4b54a
--- /dev/null
@@ -0,0 +1,22 @@
+target:
+       th.dcache.call
+       th.dcache.ciall
+       th.dcache.iall
+       th.dcache.cpa   a0
+       th.dcache.cipa  a1
+       th.dcache.ipa   a2
+       th.dcache.cva   a3
+       th.dcache.civa  a4
+       th.dcache.iva   a5
+       th.dcache.csw   a6
+       th.dcache.cisw  a7
+       th.dcache.isw   t0
+       th.dcache.cpal1 t1
+       th.dcache.cval1 t2
+       th.icache.iall
+       th.icache.ialls
+       th.icache.ipa   t3
+       th.icache.iva   t4
+       th.l2cache.call
+       th.l2cache.ciall
+       th.l2cache.iall
index 88b8d7ff5951357d4995bcd7ba80d8025b7abfa6..53b1c224518be6c0cdbe38c1bb672d2d3e07bea8 100644 (file)
 #define MASK_CBO_INVAL 0xfff07fff
 #define MATCH_CBO_ZERO 0x40200f
 #define MASK_CBO_ZERO 0xfff07fff
+/* Vendor-specific (T-Head) XTheadCmo instructions.  */
+#define MATCH_TH_DCACHE_CALL 0x0010000b
+#define MASK_TH_DCACHE_CALL 0xffffffff
+#define MATCH_TH_DCACHE_CIALL 0x0030000b
+#define MASK_TH_DCACHE_CIALL 0xffffffff
+#define MATCH_TH_DCACHE_IALL 0x0020000b
+#define MASK_TH_DCACHE_IALL 0xffffffff
+#define MATCH_TH_DCACHE_CPA 0x0290000b
+#define MASK_TH_DCACHE_CPA 0xfff07fff
+#define MATCH_TH_DCACHE_CIPA 0x02b0000b
+#define MASK_TH_DCACHE_CIPA 0xfff07fff
+#define MATCH_TH_DCACHE_IPA 0x02a0000b
+#define MASK_TH_DCACHE_IPA 0xfff07fff
+#define MATCH_TH_DCACHE_CVA 0x0250000b
+#define MASK_TH_DCACHE_CVA 0xfff07fff
+#define MATCH_TH_DCACHE_CIVA 0x0270000b
+#define MASK_TH_DCACHE_CIVA 0xfff07fff
+#define MATCH_TH_DCACHE_IVA 0x0260000b
+#define MASK_TH_DCACHE_IVA 0xfff07fff
+#define MATCH_TH_DCACHE_CSW 0x0210000b
+#define MASK_TH_DCACHE_CSW 0xfff07fff
+#define MATCH_TH_DCACHE_CISW 0x0230000b
+#define MASK_TH_DCACHE_CISW 0xfff07fff
+#define MATCH_TH_DCACHE_ISW 0x0220000b
+#define MASK_TH_DCACHE_ISW 0xfff07fff
+#define MATCH_TH_DCACHE_CPAL1 0x0280000b
+#define MASK_TH_DCACHE_CPAL1 0xfff07fff
+#define MATCH_TH_DCACHE_CVAL1 0x0240000b
+#define MASK_TH_DCACHE_CVAL1 0xfff07fff
+#define MATCH_TH_ICACHE_IALL 0x0100000b
+#define MASK_TH_ICACHE_IALL 0xffffffff
+#define MATCH_TH_ICACHE_IALLS 0x0110000b
+#define MASK_TH_ICACHE_IALLS 0xffffffff
+#define MATCH_TH_ICACHE_IPA 0x0380000b
+#define MASK_TH_ICACHE_IPA 0xfff07fff
+#define MATCH_TH_ICACHE_IVA 0x0300000b
+#define MASK_TH_ICACHE_IVA 0xfff07fff
+#define MATCH_TH_L2CACHE_CALL 0x0150000b
+#define MASK_TH_L2CACHE_CALL 0xffffffff
+#define MATCH_TH_L2CACHE_CIALL 0x0170000b
+#define MASK_TH_L2CACHE_CIALL 0xffffffff
+#define MATCH_TH_L2CACHE_IALL 0x0160000b
+#define MASK_TH_L2CACHE_IALL 0xffffffff
 /* Unprivileged Counter/Timers CSR addresses.  */
 #define CSR_CYCLE 0xc00
 #define CSR_TIME 0xc01
@@ -2852,6 +2895,28 @@ DECLARE_INSN(cbo_clean, MATCH_CBO_CLEAN, MASK_CBO_CLEAN);
 DECLARE_INSN(cbo_flush, MATCH_CBO_FLUSH, MASK_CBO_FLUSH);
 DECLARE_INSN(cbo_inval, MATCH_CBO_INVAL, MASK_CBO_INVAL);
 DECLARE_INSN(cbo_zero, MATCH_CBO_ZERO, MASK_CBO_ZERO);
+/* Vendor-specific (T-Head) XTheadCmo instructions.  */
+DECLARE_INSN(th_dcache_call, MATCH_TH_DCACHE_CALL, MASK_TH_DCACHE_CALL)
+DECLARE_INSN(th_dcache_ciall, MATCH_TH_DCACHE_CIALL, MASK_TH_DCACHE_CIALL)
+DECLARE_INSN(th_dcache_iall, MATCH_TH_DCACHE_IALL, MASK_TH_DCACHE_IALL)
+DECLARE_INSN(th_dcache_cpa, MATCH_TH_DCACHE_CPA, MASK_TH_DCACHE_CPA)
+DECLARE_INSN(th_dcache_cipa, MATCH_TH_DCACHE_CIPA, MASK_TH_DCACHE_CIPA)
+DECLARE_INSN(th_dcache_ipa, MATCH_TH_DCACHE_IPA, MASK_TH_DCACHE_IPA)
+DECLARE_INSN(th_dcache_cva, MATCH_TH_DCACHE_CVA, MASK_TH_DCACHE_CVA)
+DECLARE_INSN(th_dcache_civa, MATCH_TH_DCACHE_CIVA, MASK_TH_DCACHE_CIVA)
+DECLARE_INSN(th_dcache_iva, MATCH_TH_DCACHE_IVA, MASK_TH_DCACHE_IVA)
+DECLARE_INSN(th_dcache_csw, MATCH_TH_DCACHE_CSW, MASK_TH_DCACHE_CSW)
+DECLARE_INSN(th_dcache_cisw, MATCH_TH_DCACHE_CISW, MASK_TH_DCACHE_CISW)
+DECLARE_INSN(th_dcache_isw, MATCH_TH_DCACHE_ISW, MASK_TH_DCACHE_ISW)
+DECLARE_INSN(th_dcache_cpal1, MATCH_TH_DCACHE_CPAL1, MASK_TH_DCACHE_CPAL1)
+DECLARE_INSN(th_dcache_cval1, MATCH_TH_DCACHE_CVAL1, MASK_TH_DCACHE_CVAL1)
+DECLARE_INSN(th_icache_iall, MATCH_TH_ICACHE_IALL, MASK_TH_ICACHE_IALL)
+DECLARE_INSN(th_icache_ialls, MATCH_TH_ICACHE_IALLS, MASK_TH_ICACHE_IALLS)
+DECLARE_INSN(th_icache_ipa, MATCH_TH_ICACHE_IPA, MASK_TH_ICACHE_IPA)
+DECLARE_INSN(th_icache_iva, MATCH_TH_ICACHE_IVA, MASK_TH_ICACHE_IVA)
+DECLARE_INSN(th_l2cache_call, MATCH_TH_L2CACHE_CALL, MASK_TH_L2CACHE_CALL)
+DECLARE_INSN(th_l2cache_ciall, MATCH_TH_L2CACHE_CIALL, MASK_TH_L2CACHE_CIALL)
+DECLARE_INSN(th_l2cache_iall, MATCH_TH_L2CACHE_IALL, MASK_TH_L2CACHE_IALL)
 #endif /* DECLARE_INSN */
 #ifdef DECLARE_CSR
 /* Unprivileged Counter/Timers CSRs.  */
index f1dabeaab8e4f929e9121fcb9e51dd4e11cdbfbb..d36983140a204c5cc7b7d4b6eb0dfd01737f1401 100644 (file)
@@ -398,6 +398,7 @@ enum riscv_insn_class
   INSN_CLASS_ZICBOP,
   INSN_CLASS_ZICBOZ,
   INSN_CLASS_H,
+  INSN_CLASS_XTHEADCMO,
 };
 
 /* This structure holds information for a particular instruction.  */
index 79be78eb367f1d4dd7ce1a05116fa9f408ef5867..bf073f20e71f0fd59cbda0c0fa535089b6df4708 100644 (file)
@@ -1825,6 +1825,31 @@ const struct riscv_opcode riscv_opcodes[] =
 {"hsv.w",       0, INSN_CLASS_H, "t,0(s)", MATCH_HSV_W, MASK_HSV_W, match_opcode, INSN_DREF|INSN_4_BYTE },
 {"hsv.d",      64, INSN_CLASS_H, "t,0(s)", MATCH_HSV_D, MASK_HSV_D, match_opcode, INSN_DREF|INSN_8_BYTE },
 
+/* Vendor-specific (T-Head) XTheadCmo instructions.  */
+{"th.dcache.call",   0, INSN_CLASS_XTHEADCMO,   "",   MATCH_TH_DCACHE_CALL,   MASK_TH_DCACHE_CALL,   match_opcode, 0},
+{"th.dcache.ciall",  0, INSN_CLASS_XTHEADCMO,   "",   MATCH_TH_DCACHE_CIALL,  MASK_TH_DCACHE_CIALL,  match_opcode, 0},
+{"th.dcache.iall",   0, INSN_CLASS_XTHEADCMO,   "",   MATCH_TH_DCACHE_IALL,   MASK_TH_DCACHE_IALL,   match_opcode, 0},
+{"th.dcache.cpa",    0, INSN_CLASS_XTHEADCMO,   "s",  MATCH_TH_DCACHE_CPA,    MASK_TH_DCACHE_CPA,    match_opcode, 0},
+{"th.dcache.cipa",   0, INSN_CLASS_XTHEADCMO,   "s",  MATCH_TH_DCACHE_CIPA,   MASK_TH_DCACHE_CIPA,   match_opcode, 0},
+{"th.dcache.ipa",    0, INSN_CLASS_XTHEADCMO,   "s",  MATCH_TH_DCACHE_IPA,    MASK_TH_DCACHE_IPA,    match_opcode, 0},
+{"th.dcache.cva",    0, INSN_CLASS_XTHEADCMO,   "s",  MATCH_TH_DCACHE_CVA,    MASK_TH_DCACHE_CVA,    match_opcode, 0},
+{"th.dcache.civa",   0, INSN_CLASS_XTHEADCMO,   "s",  MATCH_TH_DCACHE_CIVA,   MASK_TH_DCACHE_CIVA,   match_opcode, 0},
+{"th.dcache.iva",    0, INSN_CLASS_XTHEADCMO,   "s",  MATCH_TH_DCACHE_IVA,    MASK_TH_DCACHE_IVA,    match_opcode, 0},
+{"th.dcache.csw",    0, INSN_CLASS_XTHEADCMO,   "s",  MATCH_TH_DCACHE_CSW,    MASK_TH_DCACHE_CSW,    match_opcode, 0},
+{"th.dcache.cisw",   0, INSN_CLASS_XTHEADCMO,   "s",  MATCH_TH_DCACHE_CISW,   MASK_TH_DCACHE_CISW,   match_opcode, 0},
+{"th.dcache.isw",    0, INSN_CLASS_XTHEADCMO,   "s",  MATCH_TH_DCACHE_ISW,    MASK_TH_DCACHE_ISW,    match_opcode, 0},
+{"th.dcache.cpal1",  0, INSN_CLASS_XTHEADCMO,   "s",  MATCH_TH_DCACHE_CPAL1,  MASK_TH_DCACHE_CPAL1,  match_opcode, 0},
+{"th.dcache.cval1",  0, INSN_CLASS_XTHEADCMO,   "s",  MATCH_TH_DCACHE_CVAL1,  MASK_TH_DCACHE_CVAL1,  match_opcode, 0},
+
+{"th.icache.iall",   0, INSN_CLASS_XTHEADCMO,   "",   MATCH_TH_ICACHE_IALL,   MASK_TH_ICACHE_IALL,   match_opcode, 0},
+{"th.icache.ialls",  0, INSN_CLASS_XTHEADCMO,   "",   MATCH_TH_ICACHE_IALLS,  MASK_TH_ICACHE_IALLS,  match_opcode, 0},
+{"th.icache.ipa",    0, INSN_CLASS_XTHEADCMO,   "s",  MATCH_TH_ICACHE_IPA,    MASK_TH_ICACHE_IPA,    match_opcode, 0},
+{"th.icache.iva",    0, INSN_CLASS_XTHEADCMO,   "s",  MATCH_TH_ICACHE_IVA,    MASK_TH_ICACHE_IVA,    match_opcode, 0},
+
+{"th.l2cache.call",  0, INSN_CLASS_XTHEADCMO,   "",   MATCH_TH_L2CACHE_CALL,  MASK_TH_L2CACHE_CALL,  match_opcode, 0},
+{"th.l2cache.ciall", 0, INSN_CLASS_XTHEADCMO,   "",   MATCH_TH_L2CACHE_CIALL, MASK_TH_L2CACHE_CIALL, match_opcode, 0},
+{"th.l2cache.iall",  0, INSN_CLASS_XTHEADCMO,   "",   MATCH_TH_L2CACHE_IALL,  MASK_TH_L2CACHE_IALL,  match_opcode, 0},
+
 /* Terminate the list.  */
 {0, 0, INSN_CLASS_NONE, 0, 0, 0, 0, 0}
 };