[v4] RISC-V: Add Zcmt instructions and csr.

Message ID 20240911073908.405807-1-jiawei@iscas.ac.cn
State New
Headers
Series [v4] RISC-V: Add Zcmt instructions and csr. |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

Jiawei Sept. 11, 2024, 7:39 a.m. UTC
  This patch supports Zcmt instruction 'cm.jt' and 'cm.jalt'.
Add new CSR jvt for tablejump using.

Version log: update `-march=help` supports,
             update format,
             update test cases.

Co-Authored by: Charlie Keaney <charlie.keaney@embecosm.com>
Co-Authored by: Mary Bennett <mary.bennett@embecosm.com>
Co-Authored by: Nandni Jamnadas <nandni.jamnadas@embecosm.com>
Co-Authored by: Sinan Lin <sinan.lin@linux.alibaba.com>
Co-Authored by: Simon Cook <simon.cook@embecosm.com>
Co-Authored by: Shihua Liao <shihua@iscas.ac.cn>
Co-Authored by: Yulong Shi <yulong@iscas.ac.cn>

bfd/ChangeLog:

	* elfxx-riscv.c (riscv_multi_subset_supports): New extension.
	(riscv_multi_subset_supports_ext): Ditto.

gas/ChangeLog:

	* config/tc-riscv.c (enum riscv_csr_class): New CSR.
	(riscv_csr_address): Ditto.
	(validate_riscv_insn): New operand.
	(riscv_ip): Ditto.
	* testsuite/gas/riscv/csr-version-1p10.d: New CSR.
	* testsuite/gas/riscv/csr-version-1p10.l: Ditto.
	* testsuite/gas/riscv/csr-version-1p11.d: Ditto.
	* testsuite/gas/riscv/csr-version-1p11.l: Ditto.
	* testsuite/gas/riscv/csr-version-1p12.d: Ditto.
	* testsuite/gas/riscv/csr-version-1p12.l: Ditto.
	* testsuite/gas/riscv/csr.s: Ditto.
	* testsuite/gas/riscv/march-help.l: New extension.
	* testsuite/gas/riscv/zcmt-fail.d: New test.
	* testsuite/gas/riscv/zcmt-fail.l: New test.
	* testsuite/gas/riscv/zcmt-fail.s: New test.
	* testsuite/gas/riscv/zcmt.d: New test.
	* testsuite/gas/riscv/zcmt.s: New test.

include/ChangeLog:

	* opcode/riscv-opc.h (MATCH_CM_JT): New opcode.
	(MASK_CM_JT): New mask.
	(MATCH_CM_JALT): New opcode.
	(MASK_CM_JALT): New mask.
	(CSR_JVT): New CSR.
	(DECLARE_INSN): New declaration.
	(DECLARE_CSR): Ditto.
	* opcode/riscv.h (EXTRACT_ZCMT_INDEX): New marco.
	(ENCODE_ZCMT_INDEX): Ditto.
	(enum riscv_insn_class): New class.

opcodes/ChangeLog:

	* riscv-dis.c (struct riscv_private_data): New data.
	(print_jvt_index): New function.
	(print_insn_args): New operand.
	* riscv-opc.c (match_cm_jt): New function.
	(match_cm_jalt): Ditto.

---
 bfd/elfxx-riscv.c                          |  6 ++++
 gas/config/tc-riscv.c                      | 29 ++++++++++++++++++++
 gas/testsuite/gas/riscv/csr-version-1p10.d |  2 ++
 gas/testsuite/gas/riscv/csr-version-1p10.l |  4 +++
 gas/testsuite/gas/riscv/csr-version-1p11.d |  2 ++
 gas/testsuite/gas/riscv/csr-version-1p11.l |  4 +++
 gas/testsuite/gas/riscv/csr-version-1p12.d |  2 ++
 gas/testsuite/gas/riscv/csr-version-1p12.l |  4 +++
 gas/testsuite/gas/riscv/csr.s              |  3 ++
 gas/testsuite/gas/riscv/march-help.l       |  1 +
 gas/testsuite/gas/riscv/zcmt-fail.d        |  3 ++
 gas/testsuite/gas/riscv/zcmt-fail.l        | 13 +++++++++
 gas/testsuite/gas/riscv/zcmt-fail.s        |  7 +++++
 gas/testsuite/gas/riscv/zcmt.d             | 14 ++++++++++
 gas/testsuite/gas/riscv/zcmt.s             |  5 ++++
 include/opcode/riscv-opc.h                 | 12 ++++++++
 include/opcode/riscv.h                     |  5 ++++
 opcodes/riscv-dis.c                        | 32 ++++++++++++++++++++++
 opcodes/riscv-opc.c                        | 23 ++++++++++++++++
 19 files changed, 171 insertions(+)
 create mode 100644 gas/testsuite/gas/riscv/zcmt-fail.d
 create mode 100644 gas/testsuite/gas/riscv/zcmt-fail.l
 create mode 100644 gas/testsuite/gas/riscv/zcmt-fail.s
 create mode 100644 gas/testsuite/gas/riscv/zcmt.d
 create mode 100644 gas/testsuite/gas/riscv/zcmt.s
  

Comments

Nelson Chu Sept. 24, 2024, 6:45 a.m. UTC | #1
Does this patch refer to the spec,
https://github.com/riscvarchive/riscv-code-size-reduction/releases?

On Wed, Sep 11, 2024 at 3:39 PM Jiawei <jiawei@iscas.ac.cn> wrote:

> @@ -3914,6 +3921,28 @@ riscv_ip (char *str, struct riscv_cl_insn *ip,
> expressionS *imm_expr,
>                         break;
>                       INSERT_OPERAND (SREG2, *ip, regno % 8);
>                       continue;
> +                   case 'I': /* index operand of cm.jt. The range is from
> 0 to 31.  */
> +                     my_getSmallExpression (imm_expr, imm_reloc, asarg,
> p);
> +                     if (imm_expr->X_op != O_constant
> +                         || imm_expr->X_add_number < 0
> +                         || imm_expr->X_add_number > 31)
> +                       {
> +                         as_bad ("bad index value for cm.jt, range: [0,
> 31]");
> +                         break;
> +                       }
> +                     ip->insn_opcode |= ENCODE_ZCMT_INDEX
> (imm_expr->X_add_number);
> +                     goto rvc_imm_done;
> +                   case 'i': /* index operand of cm.jalt. The range is
> from 32 to 255.  */
> +                     my_getSmallExpression (imm_expr, imm_reloc, asarg,
> p);
> +                     if (imm_expr->X_op != O_constant
> +                         || imm_expr->X_add_number < 32
> +                         || imm_expr->X_add_number > 255)
> +                       {
> +                         as_bad ("bad index value for cm.jalt, range:
> [32, 255]");
> +                         break;
> +                       }
> +                     ip->insn_opcode |= ENCODE_ZCMT_INDEX
> (imm_expr->X_add_number);
> +                     goto rvc_imm_done;
>

Since we already have the range check of the immediate field here, I think
we don't need to check them again in the match_cm_jt and match_cm_jalt.
That is - we don't need the match_cm* functions.


> diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
> index 73ee81158ae..5cc5e6e1eb5 100644
> --- a/include/opcode/riscv-opc.h
> +++ b/include/opcode/riscv-opc.h
> +/* Zcmt instructions.  */
> +#define MATCH_CM_JT 0xa002
> +#define MASK_CM_JT 0xff03
> +#define MATCH_CM_JALT 0xa002
> +#define MASK_CM_JALT 0xfc03


0xfc03 also for MASK_CM_JT?


> diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
> index 8ab138e45ce..ec12f488858 100644
> --- a/opcodes/riscv-dis.c
> +++ b/opcodes/riscv-dis.c
> @@ -61,6 +61,8 @@ struct riscv_private_data
>  {
>    bfd_vma gp;
>    bfd_vma print_addr;
> +  bfd_vma jvt_base;
> +  bfd_vma jvt_end;
>

How do these two variables actually work?


> +/* Print table jump index.  */
> +
> +static bool
> +print_jvt_index (disassemble_info *info, unsigned int index)
> +{
> +  bfd_vma entry_value;
> +  bfd_vma memaddr;
> +  int status;
> +
> +  bfd_byte packet[8] = { 0 };
> +  struct riscv_private_data *pd = info->private_data;
> +
> +  memaddr = pd->jvt_base + index * (xlen / 8);
> +  status = (*info->read_memory_func) (memaddr, packet, xlen / 8, info);
> +  if (status != 0)
> +    return false;
> +
> +  entry_value = xlen == 32 ? bfd_getl32 (packet)
> +                           : bfd_getl64 (packet);
> +
> +  maybe_print_address (pd, 0, entry_value, 0);
> +  return true;
> +}
>

How/When/Who to set the value of jvt_base?  Maybe they are in a different
patch or code?  If that is so then the code here should be moved to there
:-)

Thanks
Nelson
  
Jiawei Sept. 29, 2024, 3:22 a.m. UTC | #2
-----原始邮件-----
发件人:"Nelson Chu" <nelson@rivosinc.com>
发送时间:2024-09-24 14:45:12 (星期二)
收件人: Jiawei <jiawei@iscas.ac.cn>
抄送: binutils@sourceware.org, jbeulich@suse.com, kito.cheng@gmail.com, palmer@rivosinc.com, christoph.muellner@vrull.eu
主题: Re: [PATCH v4] RISC-V: Add Zcmt instructions and csr.



Does this patch refer to the spec, https://github.com/riscvarchive/riscv-code-size-reduction/releases?




Yes, it’s. I will mention this in the new version patch.




On Wed, Sep 11, 2024 at 3:39 PM Jiawei <jiawei@iscas.ac.cn> wrote:     
@@ -3914,6 +3921,28 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
                        break;
                      INSERT_OPERAND (SREG2, *ip, regno % 8);
                      continue;
+                   case 'I': /* index operand of cm.jt. The range is from 0 to 31.  */
+                     my_getSmallExpression (imm_expr, imm_reloc, asarg, p);
+                     if (imm_expr->X_op != O_constant
+                         || imm_expr->X_add_number < 0
+                         || imm_expr->X_add_number > 31)
+                       {
+                         as_bad ("bad index value for cm.jt, range: [0, 31]");
+                         break;
+                       }
+                     ip->insn_opcode |= ENCODE_ZCMT_INDEX (imm_expr->X_add_number);
+                     goto rvc_imm_done;
+                   case 'i': /* index operand of cm.jalt. The range is from 32 to 255.  */
+                     my_getSmallExpression (imm_expr, imm_reloc, asarg, p);
+                     if (imm_expr->X_op != O_constant
+                         || imm_expr->X_add_number < 32
+                         || imm_expr->X_add_number > 255)
+                       {
+                         as_bad ("bad index value for cm.jalt, range: [32, 255]");
+                         break;
+                       }
+                     ip->insn_opcode |= ENCODE_ZCMT_INDEX (imm_expr->X_add_number);
+                     goto rvc_imm_done;




Since we already have the range check of the immediate field here, I think we don't need to check them again in the match_cm_jt and match_cm_jalt.  That is - we don't need the match_cm* functions.




Okay, I will update the implement.

 
diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
index 73ee81158ae..5cc5e6e1eb5 100644
--- a/include/opcode/riscv-opc.h
+++ b/include/opcode/riscv-opc.h
+/* Zcmt instructions.  */
+#define MATCH_CM_JT 0xa002
+#define MASK_CM_JT 0xff03
+#define MATCH_CM_JALT 0xa002
+#define MASK_CM_JALT 0xfc03



0xfc03 also for MASK_CM_JT?




Thanks for you point it out, will fix in next version.

 
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 8ab138e45ce..ec12f488858 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -61,6 +61,8 @@ struct riscv_private_data
 {
   bfd_vma gp;
   bfd_vma print_addr;
+  bfd_vma jvt_base;
+  bfd_vma jvt_end;




How do these two variables actually work?




They are two index to keep the info in jvt register table.

 
+/* Print table jump index.  */
+
+static bool
+print_jvt_index (disassemble_info *info, unsigned int index)
+{
+  bfd_vma entry_value;
+  bfd_vma memaddr;
+  int status;
+
+  bfd_byte packet[8] = { 0 };
+  struct riscv_private_data *pd = info->private_data;
+
+  memaddr = pd->jvt_base + index * (xlen / 8);
+  status = (*info->read_memory_func) (memaddr, packet, xlen / 8, info);
+  if (status != 0)
+    return false;
+
+  entry_value = xlen == 32 ? bfd_getl32 (packet)
+                           : bfd_getl64 (packet);
+
+  maybe_print_address (pd, 0, entry_value, 0);
+  return true;
+}




How/When/Who to set the value of jvt_base?  Maybe they are in a different patch or code?  If that is so then the code here should be moved to there :-)




You are totally right, it dominated by linker relocation part of patch, I will make it clear up.



Thanks
Nelson
  

Patch

diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 64b7d71f2cb..609f00bcdee 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1214,6 +1214,7 @@  static struct riscv_implicit_subset riscv_implicit_subsets[] =
   {"zcf", "+f,+zca", check_implicit_always},
   {"zcmp", "+zca", check_implicit_always},
   {"zcmop", "+zca", check_implicit_always},
+  {"zcmt", "+zca,+zicsr",	check_implicit_always},
 
   {"shcounterenw", "+h", check_implicit_always},
   {"shgatpa", "+h", check_implicit_always},
@@ -1424,6 +1425,7 @@  static struct riscv_supported_ext riscv_supported_std_z_ext[] =
   {"zcd",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
   {"zcmop",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
   {"zcmp",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
+  {"zcmt",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
   {NULL, 0, 0, 0, 0}
 };
 
@@ -2719,6 +2721,8 @@  riscv_multi_subset_supports (riscv_parse_subset_t *rps,
       return riscv_subset_supports (rps, "zcmop");
     case INSN_CLASS_ZCMP:
       return riscv_subset_supports (rps, "zcmp");
+    case INSN_CLASS_ZCMT:
+      return riscv_subset_supports (rps, "zcmt");
     case INSN_CLASS_SVINVAL:
       return riscv_subset_supports (rps, "svinval");
     case INSN_CLASS_H:
@@ -3001,6 +3005,8 @@  riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
       return "zcmop";
     case INSN_CLASS_ZCMP:
       return "zcmp";
+    case INSN_CLASS_ZCMT:
+      return "zcmt";
     case INSN_CLASS_SVINVAL:
       return "svinval";
     case INSN_CLASS_H:
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index bf2020d656b..a843cb0eca6 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -71,6 +71,7 @@  enum riscv_csr_class
   CSR_CLASS_I_32,	/* rv32 only */
   CSR_CLASS_F,		/* f-ext only */
   CSR_CLASS_ZKR,	/* zkr only */
+  CSR_CLASS_ZCMT,	/* zcmt only */
   CSR_CLASS_V,		/* rvv only */
   CSR_CLASS_DEBUG,	/* debug CSR */
   CSR_CLASS_H,		/* hypervisor */
@@ -1060,6 +1061,9 @@  riscv_csr_address (const char *csr_name,
     case CSR_CLASS_ZKR:
       extension = "zkr";
       break;
+    case CSR_CLASS_ZCMT:
+      extension = "zcmt";
+      break;
     case CSR_CLASS_V:
       extension = "zve32x";
       break;
@@ -1637,6 +1641,9 @@  validate_riscv_insn (const struct riscv_opcode *opc, int length)
 		case 'p': used_bits |= ENCODE_ZCMP_SPIMM (-1U); break;
 		/* Register list operand for cm.push and cm.pop.  */
 		case 'r': USE_BITS (OP_MASK_REG_LIST, OP_SH_REG_LIST); break;
+		/* Table jump used by cm.jt or cm.jalt.  */
+		case 'i':
+		case 'I': used_bits |= ENCODE_ZCMT_INDEX (-1U); break;
 		case 'f': break;
 		default:
 		  goto unknown_validate_operand;
@@ -3914,6 +3921,28 @@  riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
 			break;
 		      INSERT_OPERAND (SREG2, *ip, regno % 8);
 		      continue;
+		    case 'I': /* index operand of cm.jt. The range is from 0 to 31.  */
+		      my_getSmallExpression (imm_expr, imm_reloc, asarg, p);
+		      if (imm_expr->X_op != O_constant
+			  || imm_expr->X_add_number < 0
+			  || imm_expr->X_add_number > 31)
+			{
+			  as_bad ("bad index value for cm.jt, range: [0, 31]");
+			  break;
+			}
+		      ip->insn_opcode |= ENCODE_ZCMT_INDEX (imm_expr->X_add_number);
+		      goto rvc_imm_done;
+		    case 'i': /* index operand of cm.jalt. The range is from 32 to 255.  */
+		      my_getSmallExpression (imm_expr, imm_reloc, asarg, p);
+		      if (imm_expr->X_op != O_constant
+			  || imm_expr->X_add_number < 32
+			  || imm_expr->X_add_number > 255)
+			{
+			  as_bad ("bad index value for cm.jalt, range: [32, 255]");
+			  break;
+			}
+		      ip->insn_opcode |= ENCODE_ZCMT_INDEX (imm_expr->X_add_number);
+		      goto rvc_imm_done;
 		    default:
 		      goto unknown_riscv_ip_operand;
 		    }
diff --git a/gas/testsuite/gas/riscv/csr-version-1p10.d b/gas/testsuite/gas/riscv/csr-version-1p10.d
index 5165f4bea0d..acf64e129b9 100644
--- a/gas/testsuite/gas/riscv/csr-version-1p10.d
+++ b/gas/testsuite/gas/riscv/csr-version-1p10.d
@@ -911,3 +911,5 @@  Disassembly of section .text:
 [ 	]+[0-9a-f]+:[ 	]+c2159073[ 	]+csrw[ 	]+vtype,a1
 [ 	]+[0-9a-f]+:[ 	]+c2202573[ 	]+csrr[ 	]+a0,vlenb
 [ 	]+[0-9a-f]+:[ 	]+c2259073[ 	]+csrw[ 	]+vlenb,a1
+[ 	]+[0-9a-f]+:[ 	]+01702573[ 	]+csrr[ 	]+a0,jvt
+[ 	]+[0-9a-f]+:[ 	]+01759073[ 	]+csrw[ 	]+jvt,a1
diff --git a/gas/testsuite/gas/riscv/csr-version-1p10.l b/gas/testsuite/gas/riscv/csr-version-1p10.l
index 17a8bb638e8..c9546b07593 100644
--- a/gas/testsuite/gas/riscv/csr-version-1p10.l
+++ b/gas/testsuite/gas/riscv/csr-version-1p10.l
@@ -1673,3 +1673,7 @@ 
 .*Info: macro .*
 .*Warning: read-only CSR is written `csrw vlenb,a1'
 .*Info: macro .*
+.*Warning: invalid CSR `jvt', needs `zcmt' extension
+.*Info: macro .*
+.*Warning: invalid CSR `jvt', needs `zcmt' extension
+.*Info: macro .*
diff --git a/gas/testsuite/gas/riscv/csr-version-1p11.d b/gas/testsuite/gas/riscv/csr-version-1p11.d
index 1cb5a917f1a..39d77c113a4 100644
--- a/gas/testsuite/gas/riscv/csr-version-1p11.d
+++ b/gas/testsuite/gas/riscv/csr-version-1p11.d
@@ -911,3 +911,5 @@  Disassembly of section .text:
 [ 	]+[0-9a-f]+:[ 	]+c2159073[ 	]+csrw[ 	]+vtype,a1
 [ 	]+[0-9a-f]+:[ 	]+c2202573[ 	]+csrr[ 	]+a0,vlenb
 [ 	]+[0-9a-f]+:[ 	]+c2259073[ 	]+csrw[ 	]+vlenb,a1
+[ 	]+[0-9a-f]+:[ 	]+01702573[ 	]+csrr[ 	]+a0,jvt
+[ 	]+[0-9a-f]+:[ 	]+01759073[ 	]+csrw[ 	]+jvt,a1
diff --git a/gas/testsuite/gas/riscv/csr-version-1p11.l b/gas/testsuite/gas/riscv/csr-version-1p11.l
index 8b797e8893e..feb61b287d6 100644
--- a/gas/testsuite/gas/riscv/csr-version-1p11.l
+++ b/gas/testsuite/gas/riscv/csr-version-1p11.l
@@ -1669,3 +1669,7 @@ 
 .*Info: macro .*
 .*Warning: read-only CSR is written `csrw vlenb,a1'
 .*Info: macro .*
+.*Warning: invalid CSR `jvt', needs `zcmt' extension
+.*Info: macro .*
+.*Warning: invalid CSR `jvt', needs `zcmt' extension
+.*Info: macro .*
diff --git a/gas/testsuite/gas/riscv/csr-version-1p12.d b/gas/testsuite/gas/riscv/csr-version-1p12.d
index ac88d9370f8..5afdaff596c 100644
--- a/gas/testsuite/gas/riscv/csr-version-1p12.d
+++ b/gas/testsuite/gas/riscv/csr-version-1p12.d
@@ -911,3 +911,5 @@  Disassembly of section .text:
 [ 	]+[0-9a-f]+:[ 	]+c2159073[ 	]+csrw[ 	]+vtype,a1
 [ 	]+[0-9a-f]+:[ 	]+c2202573[ 	]+csrr[ 	]+a0,vlenb
 [ 	]+[0-9a-f]+:[ 	]+c2259073[ 	]+csrw[ 	]+vlenb,a1
+[ 	]+[0-9a-f]+:[ 	]+01702573[ 	]+csrr[ 	]+a0,jvt
+[ 	]+[0-9a-f]+:[ 	]+01759073[ 	]+csrw[ 	]+jvt,a1
diff --git a/gas/testsuite/gas/riscv/csr-version-1p12.l b/gas/testsuite/gas/riscv/csr-version-1p12.l
index 81a7aba25c8..5a72f448c71 100644
--- a/gas/testsuite/gas/riscv/csr-version-1p12.l
+++ b/gas/testsuite/gas/riscv/csr-version-1p12.l
@@ -1433,3 +1433,7 @@ 
 .*Info: macro .*
 .*Warning: read-only CSR is written `csrw vlenb,a1'
 .*Info: macro .*
+.*Warning: invalid CSR `jvt', needs `zcmt' extension
+.*Info: macro .*
+.*Warning: invalid CSR `jvt', needs `zcmt' extension
+.*Info: macro .*
diff --git a/gas/testsuite/gas/riscv/csr.s b/gas/testsuite/gas/riscv/csr.s
index 378caef35b0..faccbde78a5 100644
--- a/gas/testsuite/gas/riscv/csr.s
+++ b/gas/testsuite/gas/riscv/csr.s
@@ -522,3 +522,6 @@ 
 	csr vl
 	csr vtype
 	csr vlenb
+
+	# Zcmt
+	csr jvt
diff --git a/gas/testsuite/gas/riscv/march-help.l b/gas/testsuite/gas/riscv/march-help.l
index 0c33d1ee76d..4798232ee95 100644
--- a/gas/testsuite/gas/riscv/march-help.l
+++ b/gas/testsuite/gas/riscv/march-help.l
@@ -104,6 +104,7 @@  All available -march extensions for RISC-V:
 	zcd                                     1.0
 	zcmop                                   1.0
 	zcmp                                    1.0
+	zcmt                                    1.0
 	shcounterenw                            1.0
 	shgatpa                                 1.0
 	shtvala                                 1.0
diff --git a/gas/testsuite/gas/riscv/zcmt-fail.d b/gas/testsuite/gas/riscv/zcmt-fail.d
new file mode 100644
index 00000000000..c66e723d05b
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcmt-fail.d
@@ -0,0 +1,3 @@ 
+#as: -march=rv64i_zcmt
+#source: zcmt-fail.s
+#error_output: zcmt-fail.l
diff --git a/gas/testsuite/gas/riscv/zcmt-fail.l b/gas/testsuite/gas/riscv/zcmt-fail.l
new file mode 100644
index 00000000000..f67ac3eb5ac
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcmt-fail.l
@@ -0,0 +1,13 @@ 
+.*: Assembler messages:
+.*: Error: bad index value for cm.jt, range: \[0, 31\]
+.*: Error: illegal operands `cm.jt -1'
+.*: Error: bad index value for cm.jt, range: \[0, 31\]
+.*: Error: illegal operands `cm.jt 256'
+.*: Error: bad index value for cm.jt, range: \[0, 31\]
+.*: Error: illegal operands `cm.jt x0'
+.*: Error: bad index value for cm.jalt, range: \[32, 255\]
+.*: Error: illegal operands `cm.jalt -1'
+.*: Error: bad index value for cm.jalt, range: \[32, 255\]
+.*: Error: illegal operands `cm.jalt 256'
+.*: Error: bad index value for cm.jalt, range: \[32, 255\]
+.*: Error: illegal operands `cm.jalt x0'
diff --git a/gas/testsuite/gas/riscv/zcmt-fail.s b/gas/testsuite/gas/riscv/zcmt-fail.s
new file mode 100644
index 00000000000..200b4602e74
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcmt-fail.s
@@ -0,0 +1,7 @@ 
+target:
+	cm.jt -1
+	cm.jt 256
+	cm.jt x0
+	cm.jalt -1
+	cm.jalt 256
+	cm.jalt x0
diff --git a/gas/testsuite/gas/riscv/zcmt.d b/gas/testsuite/gas/riscv/zcmt.d
new file mode 100644
index 00000000000..d37e4644869
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcmt.d
@@ -0,0 +1,14 @@ 
+#as: -march=rv32i_zcmt
+#source: zcmt.s
+#objdump: -dr -Mno-aliases
+
+.*:[	 ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[	 ]*[0-9a-f]+:[	 ]+a002[	 ]+cm.jt[	 ]+0 # a07ea002 <target\+0xa07ea002>
+[	 ]*[0-9a-f]+:[	 ]+a07e[	 ]+cm.jt[	 ]+31
+[	 ]*[0-9a-f]+:[	 ]+a102[	 ]+cm.jalt[	 ]+64
+[	 ]*[0-9a-f]+:[	 ]+a3fe[	 ]+cm.jalt[	 ]+255
diff --git a/gas/testsuite/gas/riscv/zcmt.s b/gas/testsuite/gas/riscv/zcmt.s
new file mode 100644
index 00000000000..0392eea9846
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcmt.s
@@ -0,0 +1,5 @@ 
+target:
+	cm.jt 0
+	cm.jt 31
+	cm.jalt 64
+	cm.jalt 255
diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
index 73ee81158ae..5cc5e6e1eb5 100644
--- a/include/opcode/riscv-opc.h
+++ b/include/opcode/riscv-opc.h
@@ -2305,6 +2305,11 @@ 
 #define MASK_CM_MVA01S 0xfc63
 #define MATCH_CM_MVSA01 0xac22
 #define MASK_CM_MVSA01 0xfc63
+/* Zcmt instructions.  */
+#define MATCH_CM_JT 0xa002
+#define MASK_CM_JT 0xff03
+#define MATCH_CM_JALT 0xa002
+#define MASK_CM_JALT 0xfc03
 /* Svinval instruction.  */
 #define MATCH_SINVAL_VMA 0x16000073
 #define MASK_SINVAL_VMA 0xfe007fff
@@ -4185,6 +4190,8 @@ 
 #define CSR_MSCONTEXT 0x7aa
 /* Unprivileged Scalar Crypto CSR addresses.  */
 #define CSR_SEED 0x015
+/* Unprivileged Zcmt CSR addresses.  */
+#define CSR_JVT 0x017
 /* Unprivileged Vector CSR addresses.  */
 #define CSR_VSTART 0x008
 #define CSR_VXSAT 0x009
@@ -4726,6 +4733,9 @@  DECLARE_INSN(cm_popret, MATCH_CM_POPRET, MASK_CM_POPRET)
 DECLARE_INSN(cm_popretz, MATCH_CM_POPRETZ, MASK_CM_POPRETZ)
 DECLARE_INSN(cm_mvsa01, MATCH_CM_MVSA01, MASK_CM_MVSA01)
 DECLARE_INSN(cm_mva01s, MATCH_CM_MVA01S, MASK_CM_MVA01S)
+/* Zcmt instructions.  */
+DECLARE_INSN(cm_jt, MATCH_CM_JT, MASK_CM_JT)
+DECLARE_INSN(cm_jalt, MATCH_CM_JALT, MASK_CM_JALT)
 /* Vendor-specific (T-Head) XTheadBa instructions.  */
 DECLARE_INSN(th_addsl, MATCH_TH_ADDSL, MASK_TH_ADDSL)
 /* Vendor-specific (T-Head) XTheadBb instructions.  */
@@ -5294,6 +5304,8 @@  DECLARE_CSR(mcontext, CSR_MCONTEXT, CSR_CLASS_DEBUG, PRIV_SPEC_CLASS_NONE, PRIV_
 DECLARE_CSR(mscontext, CSR_MSCONTEXT, CSR_CLASS_DEBUG, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE)
 /* Unprivileged Scalar Crypto CSRs.  */
 DECLARE_CSR(seed, CSR_SEED, CSR_CLASS_ZKR, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE)
+/* Unprivileged Zcmt CSRs.  */
+DECLARE_CSR(jvt, CSR_JVT, CSR_CLASS_ZCMT, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE)
 /* Unprivileged Vector CSRs.  */
 DECLARE_CSR(vstart, CSR_VSTART, CSR_CLASS_V, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE)
 DECLARE_CSR(vxsat, CSR_VXSAT, CSR_CLASS_V, PRIV_SPEC_CLASS_NONE, PRIV_SPEC_CLASS_NONE)
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index 7df15174d60..5e5131e2d40 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -115,6 +115,8 @@  static inline unsigned int riscv_insn_length (insn_t insn)
   (RV_X(x, 5, 1) << 1)
 #define EXTRACT_ZCMP_SPIMM(x) \
   (RV_X(x, 2, 2) << 4)
+#define EXTRACT_ZCMT_INDEX(x) \
+  (RV_X(x, 2, 8))
 /* Vendor-specific (CORE-V) extract macros.  */
 #define EXTRACT_CV_IS2_UIMM5(x) \
   (RV_X(x, 20, 5))
@@ -183,6 +185,8 @@  static inline unsigned int riscv_insn_length (insn_t insn)
   (RV_X(x, 1, 1) << 5)
 #define ENCODE_ZCMP_SPIMM(x) \
   (RV_X(x, 4, 2) << 2)
+#define ENCODE_ZCMT_INDEX(x) \
+  (RV_X(x, 0, 8) << 2)
 /* Vendor-specific (CORE-V) encode macros.  */
 #define ENCODE_CV_IS2_UIMM5(x) \
   (RV_X(x, 0, 5) << 20)
@@ -517,6 +521,7 @@  enum riscv_insn_class
   INSN_CLASS_ZCB_AND_ZMMUL,
   INSN_CLASS_ZCMOP,
   INSN_CLASS_ZCMP,
+  INSN_CLASS_ZCMT,
   INSN_CLASS_SVINVAL,
   INSN_CLASS_ZICBOM,
   INSN_CLASS_ZICBOP,
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 8ab138e45ce..ec12f488858 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -61,6 +61,8 @@  struct riscv_private_data
 {
   bfd_vma gp;
   bfd_vma print_addr;
+  bfd_vma jvt_base;
+  bfd_vma jvt_end;
   bfd_vma hi_addr[OP_MASK_RD + 1];
   bool to_print_addr;
   bool has_gp;
@@ -296,6 +298,30 @@  riscv_zcmp_get_sregno (unsigned sreg_idx)
       sreg_idx + 16 : sreg_idx + 8;
 }
 
+/* Print table jump index.  */
+
+static bool
+print_jvt_index (disassemble_info *info, unsigned int index)
+{
+  bfd_vma entry_value;
+  bfd_vma memaddr;
+  int status;
+
+  bfd_byte packet[8] = { 0 };
+  struct riscv_private_data *pd = info->private_data;
+
+  memaddr = pd->jvt_base + index * (xlen / 8);
+  status = (*info->read_memory_func) (memaddr, packet, xlen / 8, info);
+  if (status != 0)
+    return false;
+
+  entry_value = xlen == 32 ? bfd_getl32 (packet)
+			    : bfd_getl64 (packet);
+
+  maybe_print_address (pd, 0, entry_value, 0);
+  return true;
+}
+
 /* Print insn arguments for 32/64-bit code.  */
 
 static void
@@ -732,6 +758,12 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 		  print (info->stream, dis_style_immediate, "%d",
 			 riscv_get_spimm (l));
 		  break;
+		case 'i':
+		case 'I':
+		  print (info->stream, dis_style_address_offset,
+			 "%lu", EXTRACT_ZCMT_INDEX (l));
+		  print_jvt_index (info, EXTRACT_ZCMT_INDEX (l));
+		  break;
 		default:
 		  goto undefined_modifier;
 		}
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index 8d5c574da6e..787beb7c029 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -362,6 +362,25 @@  match_sreg1_not_eq_sreg2 (const struct riscv_opcode *op, insn_t insn)
       && (EXTRACT_OPERAND (SREG1, insn) != EXTRACT_OPERAND (SREG2, insn));
 }
 
+/* This is used for cm.jt. This requires index operand to be less than 32.  */
+
+static int
+match_cm_jt (const struct riscv_opcode *op, insn_t insn)
+{
+  return match_opcode (op, insn)
+    && EXTRACT_ZCMT_INDEX (insn) < 32;
+}
+
+/* This is used for cm.jalt. This requires index operand to be in 32 to 255.  */
+
+static int
+match_cm_jalt (const struct riscv_opcode *op, insn_t insn)
+{
+  return match_opcode (op, insn)
+    && EXTRACT_ZCMT_INDEX (insn) >= 32
+    && EXTRACT_ZCMT_INDEX (insn) < 256;
+}
+
 /* The order of overloaded instructions matters.  Label arguments and
    register arguments look the same. Instructions that can have either
    for arguments must apear in the correct order in this table for the
@@ -2196,6 +2215,10 @@  const struct riscv_opcode riscv_opcodes[] =
 {"cm.mva01s",  0,  INSN_CLASS_ZCMP, "Wc1,Wc2",    MATCH_CM_MVA01S, MASK_CM_MVA01S, match_opcode, 0 },
 {"cm.mvsa01",  0,  INSN_CLASS_ZCMP, "Wc1,Wc2",    MATCH_CM_MVSA01, MASK_CM_MVSA01, match_sreg1_not_eq_sreg2, 0 },
 
+/* Zcmt instructions */
+{"cm.jt",      0,  INSN_CLASS_ZCMT, "WcI", MATCH_CM_JT, MASK_CM_JT, match_cm_jt, 0 },
+{"cm.jalt",    0,  INSN_CLASS_ZCMT, "Wci", MATCH_CM_JALT, MASK_CM_JALT, match_cm_jalt, 0 },
+
 /* Supervisor instructions.  */
 {"csrr",       0, INSN_CLASS_ZICSR, "d,E",   MATCH_CSRRS, MASK_CSRRS|MASK_RS1, match_opcode, INSN_ALIAS },
 {"csrwi",      0, INSN_CLASS_ZICSR, "E,Z",   MATCH_CSRRWI, MASK_CSRRWI|MASK_RD, match_opcode, INSN_ALIAS },