public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v4 1/2] RISC-V: Support Zcmp push/pop instructions.
@ 2024-01-24  9:37 Jiawei
  2024-01-24  9:37 ` [PATCH v4 2/2] RISC-V: Support Zcmp cm.mv instructions Jiawei
  2024-01-26  8:33 ` [PATCH v4 1/2] RISC-V: Support Zcmp push/pop instructions Kito Cheng
  0 siblings, 2 replies; 3+ messages in thread
From: Jiawei @ 2024-01-24  9:37 UTC (permalink / raw)
  To: binutils
  Cc: nelson, kito.cheng, palmer, jbeulich, research_trasio,
	christoph.muellner, jeremy.bennett, nandni.jamnadas,
	mary.bennett, charlie.keaney, simon.cook, sinan.lin, gaofei,
	fujin.zhao, wuwei2016, shihua, shiyulong, chenyixuan, Jiawei

Support zcmp extension push/pop/popret and popret zero instructions.
`reg_list` is a list containing 1 to 13 registers, we can use: "{ra}, {ra,
s0}, {ra, s0-s1}, {ra, s0-s2}, …, {ra, s0-sN}" to present this feature.
`stack_adj` is the total size of the stack frame, use
`riscv_get_sp_base` function to calculate it.
Most work was finished by Sinan Lin.

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>

Version log:

Fixes format issues, rename 'rlist' to 'reg_list', 'SP_ALIGNMENT'to
'ZCMP_SP_ALIGNMENT', use 'strtok' in reglist parser, adds conflict 
check with 'Zcd' extension.

bfd/ChangeLog:

        * elfxx-riscv.c (riscv_parse_check_conflicts): New function.
        (riscv_multi_subset_supports): New extension.
        (riscv_multi_subset_supports_ext): Ditto.
        * elfxx-riscv.h (ZCMP_SP_ALIGNMENT): New macro.

gas/ChangeLog:

        * config/tc-riscv.c (regno_to_reg_list): New function.
        (reglist_lookup): Ditto.
        (validate_riscv_insn): New operators.
        (riscv_ip): Ditto.
        * testsuite/gas/riscv/zcmp-push-pop-fail.d: New test.
        * testsuite/gas/riscv/zcmp-push-pop-fail.l: New test.
        * testsuite/gas/riscv/zcmp-push-pop-fail.s: New test.
        * testsuite/gas/riscv/zcmp-push-pop.d: New test.
        * testsuite/gas/riscv/zcmp-push-pop.s: New test.

include/ChangeLog:

        * opcode/riscv-opc.h (MATCH_CM_PUSH): New opcode.
        (MASK_CM_PUSH): New mask.
        (MATCH_CM_POP): New opcode.
        (MASK_CM_POP): New mask.
        (MATCH_CM_POPRET): New opcode.
        (MASK_CM_POPRET): New mask.
        (MATCH_CM_POPRETZ): New opcode.
        (MASK_CM_POPRETZ): New mask.
        (DECLARE_INSN): New declarations.
        * opcode/riscv.h (EXTRACT_ZCMP_SPIMM): New inline function.
        (ENCODE_ZCMP_SPIMM): Ditto.
        (VALID_ZCMP_SPIMM): Ditto.
        (OP_MASK_REG_LIST): New mask.
        (OP_SH_REG_LIST): New operand code.
        (ZCMP_SP_ALIGNMENT): New argument.
        (X_S0): New reg number.
        (X_S1): Ditto.
        (X_S2): Ditto.
        (X_S10): Ditto.
        (X_S11): Ditto. 
        (enum riscv_insn_class): New extension class.
        (riscv_get_sp_base): New function.

opcodes/ChangeLog:

        * riscv-dis.c (set_default_riscv_dis_options):
        (parse_riscv_dis_option_without_args):
        (print_reg_list):
        (riscv_get_spimm):
        (print_insn_args):
        * riscv-opc.c:

---
 bfd/elfxx-riscv.c                            |  13 ++
 bfd/elfxx-riscv.h                            |   1 +
 gas/config/tc-riscv.c                        | 148 +++++++++++++++++
 gas/testsuite/gas/riscv/zcmp-push-pop-fail.d |   3 +
 gas/testsuite/gas/riscv/zcmp-push-pop-fail.l |   9 ++
 gas/testsuite/gas/riscv/zcmp-push-pop-fail.s |  13 ++
 gas/testsuite/gas/riscv/zcmp-push-pop.d      | 154 ++++++++++++++++++
 gas/testsuite/gas/riscv/zcmp-push-pop.s      | 162 +++++++++++++++++++
 include/opcode/riscv-opc.h                   |  14 ++
 include/opcode/riscv.h                       |  29 ++++
 opcodes/riscv-dis.c                          |  57 +++++++
 opcodes/riscv-opc.c                          |   6 +
 12 files changed, 609 insertions(+)
 create mode 100644 gas/testsuite/gas/riscv/zcmp-push-pop-fail.d
 create mode 100644 gas/testsuite/gas/riscv/zcmp-push-pop-fail.l
 create mode 100644 gas/testsuite/gas/riscv/zcmp-push-pop-fail.s
 create mode 100644 gas/testsuite/gas/riscv/zcmp-push-pop.d
 create mode 100644 gas/testsuite/gas/riscv/zcmp-push-pop.s

diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 9a121b47121..2ad4682f19f 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1193,6 +1193,7 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
   {"zcf", "zca",	check_implicit_always},
   {"zcd", "zca",	check_implicit_always},
   {"zcb", "zca",	check_implicit_always},
+  {"zcmp", "zca",	check_implicit_always},
   {"smaia", "ssaia",		check_implicit_always},
   {"smcntrpmf", "zicsr",	check_implicit_always},
   {"smstateen", "ssstateen",	check_implicit_always},
@@ -1340,6 +1341,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
   {"zcb",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
   {"zcf",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
   {"zcd",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
+  {"zcmp",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
   {NULL, 0, 0, 0, 0}
 };
 
@@ -1981,6 +1983,13 @@ riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
       rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
       no_conflict = false;
     }
+  if (riscv_subset_supports (rps, "zcmp")
+      && riscv_subset_supports (rps, "zcd"))
+    {
+      rps->error_handler
+	(_("zcmp' is incompatible with `d/zcd' extension"));
+      no_conflict = false;
+    }
   if (riscv_lookup_subset (rps->subset_list, "zcf", &subset)
       && xlen > 32)
     {
@@ -2568,6 +2577,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
     case INSN_CLASS_ZCB_AND_ZMMUL:
       return (riscv_subset_supports (rps, "zcb")
 	      && riscv_subset_supports (rps, "zmmul"));
+    case INSN_CLASS_ZCMP:
+      return riscv_subset_supports (rps, "zcmp");
     case INSN_CLASS_SVINVAL:
       return riscv_subset_supports (rps, "svinval");
     case INSN_CLASS_H:
@@ -2820,6 +2831,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
       return _("zcb' and `zbb");
     case INSN_CLASS_ZCB_AND_ZMMUL:
       return _("zcb' and `zmmul', or `zcb' and `m");
+    case INSN_CLASS_ZCMP:
+      return "zcmp";
     case INSN_CLASS_SVINVAL:
       return "svinval";
     case INSN_CLASS_H:
diff --git a/bfd/elfxx-riscv.h b/bfd/elfxx-riscv.h
index ae4cbee7bc3..e60a40f63bb 100644
--- a/bfd/elfxx-riscv.h
+++ b/bfd/elfxx-riscv.h
@@ -26,6 +26,7 @@
 #include "cpu-riscv.h"
 
 #define RISCV_UNKNOWN_VERSION -1
+#define ZCMP_SP_ALIGNMENT 16
 
 struct riscv_elf_params
 {
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index a4161420128..a9f0b90af71 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1253,6 +1253,125 @@ flt_lookup (float f, const float *array, size_t size, unsigned *regnop)
   return false;
 }
 
+/* Map ra and s-register to [4,15], so that we can check if the
+   reg2 in register list reg1-reg2 or single reg2 is valid or not,
+   and obtain the corresponding reg_list value.
+
+   ra - 4
+   s0 - 5
+   s1 - 6
+    ....
+   s10 - 0 (invalid)
+   s11 - 15.  */
+
+static int
+regno_to_reg_list (unsigned regno)
+{
+  if (regno == X_RA)
+    return 4;
+  else if (regno == X_S0 || regno == X_S1)
+    return 5 + regno - X_S0;
+  else if (regno >= X_S2 && regno < X_S10)
+    return 7 + regno - X_S2;
+  else if (regno == X_S11)
+    return 15;
+
+  return 0; /* invalid symbol */
+}
+
+/* Parse register list, and the parsed reg_list value is stored in reg_list
+   argument.
+
+   If ABI register names are used (e.g. ra and s0), the register
+   list could be "{ra}", "{ra, s0}", "{ra, s0-sN}", where 0 < N < 10 or
+   N == 11.
+
+   If numeric register names are used (e.g. x1 and x8), the register list
+   could be "{x1}", "{x1,x8}", "{x1,x8-x9}", "{x1,x8-x9,x18}" and
+   "{x1,x8-x9,x18-xN}", where 19 < N < 25 or N == 27.
+
+   It will fail if numeric register names and ABI register names are used
+   at the same time.
+*/
+
+static bool
+reglist_lookup (char **s, unsigned *reg_list)
+{
+  unsigned regno = 0;
+  unsigned regnum = 0;
+  char *reglist = strdup (*s);
+  char *regname[3];
+
+  if (reglist == NULL)
+    return false;
+
+  reglist = strtok (reglist, "}");
+  for(reglist = strtok (reglist, ",");reglist;reglist = strtok(NULL, ",")){
+    regname[regnum] = reglist;
+    regnum++;
+  }
+
+  /* Use to check if the register format is xreg.  */
+  bool use_xreg = **s == 'x';
+
+  /* The first register in the register list should be ra.  */
+  if (!reg_lookup (s, RCLASS_GPR, &regno)
+     || !(*reg_list = regno_to_reg_list (regno)) /* update reg_list */
+     || regno != X_RA)
+    return false;
+
+  if (regnum == 1)
+    return true;
+
+  /* Do not use numeric and abi names at the same time.  */
+  if ((*++*s != 'x') && use_xreg)
+    return false;
+  /* Reg1 should be s0 or its numeric names x8.  */
+  if (!reg_lookup (s, RCLASS_GPR, &regno)
+     || !(*reg_list = regno_to_reg_list (regno))
+     || regno != X_S0)
+    return false;
+
+  if (strlen (regname[1]) == 2)
+    return true;
+
+  if ((*++*s != 'x') && use_xreg)
+    return false;
+  /* Reg2 is x9 if the numeric name is used, otherwise,
+    it could be any other sN register, where N > 0.  */
+  if (!reg_lookup (s, RCLASS_GPR, &regno)
+     || !(*reg_list = regno_to_reg_list (regno))
+     || regno <= X_S0
+     || (use_xreg && regno != X_S1))
+    return false;
+
+  if (regnum == 2)
+    return true;
+
+  if (regnum == 3 && use_xreg) {
+    if ((*++*s != 'x') && use_xreg)
+      return false;
+    /* Reg3 should be s2.  */
+    if (!reg_lookup (s, RCLASS_GPR, &regno)
+       || !(*reg_list = regno_to_reg_list (regno))
+       || regno != X_S2)
+      return false;
+    if(strlen(regname[2]) == 3)
+      return true;
+    if ((*++*s != 'x') && use_xreg)
+      return false;
+    /* Reg4 could be any other sN register, where N > 1.  */
+    if (!reg_lookup (s, RCLASS_GPR, &regno)
+       || !(*reg_list = regno_to_reg_list (regno))
+       || regno <= X_S2)
+      return false;
+    return true;
+  }
+
+  free (reglist);
+  return false;
+}
+
 #define USE_BITS(mask,shift) (used_bits |= ((insn_t)(mask) << (shift)))
 #define USE_IMM(n, s) \
   (used_bits |= ((insn_t)((1ull<<n)-1) << (s)))
@@ -1369,6 +1488,8 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
 	case ',': break;
 	case '(': break;
 	case ')': break;
+	case '{': break;
+	case '}': break;
 	case '<': USE_BITS (OP_MASK_SHAMTW, OP_SH_SHAMTW); break;
 	case '>': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break;
 	case 'A': break; /* Macro operand, must be symbol.  */
@@ -1449,6 +1570,10 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
 		case 'h': used_bits |= ENCODE_ZCB_HALFWORD_UIMM (-1U); break;
 		/* halfword immediate operators, load/store halfword insns.  */
 		case 'b': used_bits |= ENCODE_ZCB_BYTE_UIMM (-1U); break;
+		/* immediate offset operand for cm.push and cm.pop.  */
+		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;
 		case 'f': break;
 		default:
 		  goto unknown_validate_operand;
@@ -3201,6 +3326,8 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
 	    case ')':
 	    case '[':
 	    case ']':
+	    case '{':
+	    case '}':
 	      if (*asarg++ == *oparg)
 		continue;
 	      break;
@@ -3656,6 +3783,27 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
 			break;
 		      ip->insn_opcode |= ENCODE_ZCB_BYTE_UIMM (imm_expr->X_add_number);
 		      goto rvc_imm_done;
+		    case 'r':
+		      /* we use regno to store reglist value here.  */
+		      if (!reglist_lookup (&asarg, &regno))
+			break;
+		      INSERT_OPERAND (REG_LIST, *ip, regno);
+			continue;
+		    case 'p':
+		      if (my_getSmallExpression (imm_expr, imm_reloc, asarg, p)
+			|| imm_expr->X_op != O_constant)
+			break;
+		      /* convert stack adjust of cm.push to a positive offset.  */
+		      if (ip->insn_mo->match == MATCH_CM_PUSH)
+			imm_expr->X_add_number *= -1;
+		      /* subtract base stack adjust and get spimm.  */
+		      imm_expr->X_add_number -=
+			      riscv_get_sp_base (ip->insn_opcode, *riscv_rps_as.xlen);
+		      if (!VALID_ZCMP_SPIMM (imm_expr->X_add_number))
+			break;
+		      ip->insn_opcode |=
+			ENCODE_ZCMP_SPIMM (imm_expr->X_add_number);
+		      goto rvc_imm_done;
 		    case 'f': /* Operand for matching immediate 255.  */
 		      if (my_getSmallExpression (imm_expr, imm_reloc, asarg, p)
 			  || imm_expr->X_op != O_constant
diff --git a/gas/testsuite/gas/riscv/zcmp-push-pop-fail.d b/gas/testsuite/gas/riscv/zcmp-push-pop-fail.d
new file mode 100644
index 00000000000..84ecf263c54
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcmp-push-pop-fail.d
@@ -0,0 +1,3 @@
+#as: -march=rv64i_zcmp
+#source: zcmp-push-pop-fail.s
+#error_output: zcmp-push-pop-fail.l
diff --git a/gas/testsuite/gas/riscv/zcmp-push-pop-fail.l b/gas/testsuite/gas/riscv/zcmp-push-pop-fail.l
new file mode 100644
index 00000000000..955e495d5bb
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcmp-push-pop-fail.l
@@ -0,0 +1,9 @@
+.*: Assembler messages:
+.*: Error: illegal operands `cm.push \{a0\},-64'
+.*: Error: illegal operands `cm.pop \{ra,s1\},-64'
+.*: Error: illegal operands `cm.popret \{ra,s2-s3\},-64'
+.*: Error: illegal operands `cm.popretz \{ra,s0-s10\},-112'
+.*: Error: illegal operands `cm.push \{ra\},0'
+.*: Error: illegal operands `cm.pop \{ra,s0\},-80'
+.*: Error: illegal operands `cm.popret \{ra,s0-s1\},-15'
+.*: Error: illegal operands `cm.popretz \{ra,s0-s11\},-165'
diff --git a/gas/testsuite/gas/riscv/zcmp-push-pop-fail.s b/gas/testsuite/gas/riscv/zcmp-push-pop-fail.s
new file mode 100644
index 00000000000..0e8df5800dd
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcmp-push-pop-fail.s
@@ -0,0 +1,13 @@
+target:
+
+	# reg_list
+	cm.push {a0}, -64
+	cm.pop {ra, s1}, -64
+	cm.popret {ra, s2-s3}, -64
+	cm.popretz {ra, s0-s10}, -112
+
+	# spimm
+	cm.push {ra}, 0
+	cm.pop {ra, s0}, -80
+	cm.popret {ra, s0-s1}, -15
+	cm.popretz {ra, s0-s11}, -165
diff --git a/gas/testsuite/gas/riscv/zcmp-push-pop.d b/gas/testsuite/gas/riscv/zcmp-push-pop.d
new file mode 100644
index 00000000000..e21295051ec
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcmp-push-pop.d
@@ -0,0 +1,154 @@
+#as: -march=rv64i_zcmp
+#source: zcmp-push-pop.s
+#objdump: -dr -Mno-aliases
+
+.*:[	 ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[	 ]*[0-9a-f]+:[	 ]+b84e[	 ]+cm.push[	 ]+\{ra\},-64
+[	 ]*[0-9a-f]+:[	 ]+b85e[	 ]+cm.push[	 ]+\{ra,s0\},-64
+[	 ]*[0-9a-f]+:[	 ]+b86a[	 ]+cm.push[	 ]+\{ra,s0-s1\},-64
+[	 ]*[0-9a-f]+:[	 ]+b87a[	 ]+cm.push[	 ]+\{ra,s0-s2\},-64
+[	 ]*[0-9a-f]+:[	 ]+b8da[	 ]+cm.push[	 ]+\{ra,s0-s8\},-112
+[	 ]*[0-9a-f]+:[	 ]+b8e6[	 ]+cm.push[	 ]+\{ra,s0-s9\},-112
+[	 ]*[0-9a-f]+:[	 ]+b8f2[	 ]+cm.push[	 ]+\{ra,s0-s11\},-112
+[	 ]*[0-9a-f]+:[	 ]+b84e[	 ]+cm.push[	 ]+\{ra\},-64
+[	 ]*[0-9a-f]+:[	 ]+b85e[	 ]+cm.push[	 ]+\{ra,s0\},-64
+[	 ]*[0-9a-f]+:[	 ]+b86a[	 ]+cm.push[	 ]+\{ra,s0-s1\},-64
+[	 ]*[0-9a-f]+:[	 ]+b87a[	 ]+cm.push[	 ]+\{ra,s0-s2\},-64
+[	 ]*[0-9a-f]+:[	 ]+b8da[	 ]+cm.push[	 ]+\{ra,s0-s8\},-112
+[	 ]*[0-9a-f]+:[	 ]+b8e6[	 ]+cm.push[	 ]+\{ra,s0-s9\},-112
+[	 ]*[0-9a-f]+:[	 ]+b8f2[	 ]+cm.push[	 ]+\{ra,s0-s11},-112
+[	 ]*[0-9a-f]+:[	 ]+b842[	 ]+cm.push[	 ]+\{ra\},-16
+[	 ]*[0-9a-f]+:[	 ]+b846[	 ]+cm.push[	 ]+\{ra\},-32
+[	 ]*[0-9a-f]+:[	 ]+b84e[	 ]+cm.push[	 ]+\{ra\},-64
+[	 ]*[0-9a-f]+:[	 ]+b872[	 ]+cm.push[	 ]+\{ra,s0-s2\},-32
+[	 ]*[0-9a-f]+:[	 ]+b87a[	 ]+cm.push[	 ]+\{ra,s0-s2\},-64
+[	 ]*[0-9a-f]+:[	 ]+b87e[	 ]+cm.push[	 ]+\{ra,s0-s2\},-80
+[	 ]*[0-9a-f]+:[	 ]+b882[	 ]+cm.push[	 ]+\{ra,s0-s3\},-48
+[	 ]*[0-9a-f]+:[	 ]+b886[	 ]+cm.push[	 ]+\{ra,s0-s3\},-64
+[	 ]*[0-9a-f]+:[	 ]+b88e[	 ]+cm.push[	 ]+\{ra,s0-s3\},-96
+[	 ]*[0-9a-f]+:[	 ]+b8b2[	 ]+cm.push[	 ]+\{ra,s0-s6\},-64
+[	 ]*[0-9a-f]+:[	 ]+b8b6[	 ]+cm.push[	 ]+\{ra,s0-s6\},-80
+[	 ]*[0-9a-f]+:[	 ]+b8be[	 ]+cm.push[	 ]+\{ra,s0-s6\},-112
+[	 ]*[0-9a-f]+:[	 ]+b8c2[	 ]+cm.push[	 ]+\{ra,s0-s7\},-80
+[	 ]*[0-9a-f]+:[	 ]+b8c6[	 ]+cm.push[	 ]+\{ra,s0-s7\},-96
+[	 ]*[0-9a-f]+:[	 ]+b8ce[	 ]+cm.push[	 ]+\{ra,s0-s7\},-128
+[	 ]*[0-9a-f]+:[	 ]+b8e2[	 ]+cm.push[	 ]+\{ra,s0-s9\},-96
+[	 ]*[0-9a-f]+:[	 ]+b8e6[	 ]+cm.push[	 ]+\{ra,s0-s9\},-112
+[	 ]*[0-9a-f]+:[	 ]+b8ee[	 ]+cm.push[	 ]+\{ra,s0-s9\},-144
+[	 ]*[0-9a-f]+:[	 ]+b8f2[	 ]+cm.push[	 ]+\{ra,s0-s11\},-112
+[	 ]*[0-9a-f]+:[	 ]+b8f6[	 ]+cm.push[	 ]+\{ra,s0-s11\},-128
+[	 ]*[0-9a-f]+:[	 ]+b8fa[	 ]+cm.push[	 ]+\{ra,s0-s11\},-144
+[	 ]*[0-9a-f]+:[	 ]+b8fe[	 ]+cm.push[	 ]+\{ra,s0-s11\},-160
+[	 ]*[0-9a-f]+:[	 ]+ba4e[	 ]+cm.pop[	 ]+\{ra\},64
+[	 ]*[0-9a-f]+:[	 ]+ba5e[	 ]+cm.pop[	 ]+\{ra,s0\},64
+[	 ]*[0-9a-f]+:[	 ]+ba6a[	 ]+cm.pop[	 ]+\{ra,s0-s1\},64
+[	 ]*[0-9a-f]+:[	 ]+ba7a[	 ]+cm.pop[	 ]+\{ra,s0-s2\},64
+[	 ]*[0-9a-f]+:[	 ]+bada[	 ]+cm.pop[	 ]+\{ra,s0-s8\},112
+[	 ]*[0-9a-f]+:[	 ]+bae6[	 ]+cm.pop[	 ]+\{ra,s0-s9\},112
+[	 ]*[0-9a-f]+:[	 ]+baf2[	 ]+cm.pop[	 ]+\{ra,s0-s11\},112
+[	 ]*[0-9a-f]+:[	 ]+ba4e[	 ]+cm.pop[	 ]+\{ra\},64
+[	 ]*[0-9a-f]+:[	 ]+ba5e[	 ]+cm.pop[	 ]+\{ra,s0\},64
+[	 ]*[0-9a-f]+:[	 ]+ba6a[	 ]+cm.pop[	 ]+\{ra,s0-s1\},64
+[	 ]*[0-9a-f]+:[	 ]+ba7a[	 ]+cm.pop[	 ]+\{ra,s0-s2\},64
+[	 ]*[0-9a-f]+:[	 ]+bada[	 ]+cm.pop[	 ]+\{ra,s0-s8\},112
+[	 ]*[0-9a-f]+:[	 ]+bae6[	 ]+cm.pop[	 ]+\{ra,s0-s9\},112
+[	 ]*[0-9a-f]+:[	 ]+baf2[	 ]+cm.pop[	 ]+\{ra,s0-s11},112
+[	 ]*[0-9a-f]+:[	 ]+ba42[	 ]+cm.pop[	 ]+\{ra\},16
+[	 ]*[0-9a-f]+:[	 ]+ba46[	 ]+cm.pop[	 ]+\{ra\},32
+[	 ]*[0-9a-f]+:[	 ]+ba4e[	 ]+cm.pop[	 ]+\{ra\},64
+[	 ]*[0-9a-f]+:[	 ]+ba72[	 ]+cm.pop[	 ]+\{ra,s0-s2\},32
+[	 ]*[0-9a-f]+:[	 ]+ba7a[	 ]+cm.pop[	 ]+\{ra,s0-s2\},64
+[	 ]*[0-9a-f]+:[	 ]+ba7e[	 ]+cm.pop[	 ]+\{ra,s0-s2\},80
+[	 ]*[0-9a-f]+:[	 ]+ba82[	 ]+cm.pop[	 ]+\{ra,s0-s3\},48
+[	 ]*[0-9a-f]+:[	 ]+ba86[	 ]+cm.pop[	 ]+\{ra,s0-s3\},64
+[	 ]*[0-9a-f]+:[	 ]+ba8e[	 ]+cm.pop[	 ]+\{ra,s0-s3\},96
+[	 ]*[0-9a-f]+:[	 ]+bab2[	 ]+cm.pop[	 ]+\{ra,s0-s6\},64
+[	 ]*[0-9a-f]+:[	 ]+bab6[	 ]+cm.pop[	 ]+\{ra,s0-s6\},80
+[	 ]*[0-9a-f]+:[	 ]+babe[	 ]+cm.pop[	 ]+\{ra,s0-s6\},112
+[	 ]*[0-9a-f]+:[	 ]+bac2[	 ]+cm.pop[	 ]+\{ra,s0-s7\},80
+[	 ]*[0-9a-f]+:[	 ]+bac6[	 ]+cm.pop[	 ]+\{ra,s0-s7\},96
+[	 ]*[0-9a-f]+:[	 ]+bace[	 ]+cm.pop[	 ]+\{ra,s0-s7\},128
+[	 ]*[0-9a-f]+:[	 ]+bae2[	 ]+cm.pop[	 ]+\{ra,s0-s9\},96
+[	 ]*[0-9a-f]+:[	 ]+bae6[	 ]+cm.pop[	 ]+\{ra,s0-s9\},112
+[	 ]*[0-9a-f]+:[	 ]+baee[	 ]+cm.pop[	 ]+\{ra,s0-s9\},144
+[	 ]*[0-9a-f]+:[	 ]+baf2[	 ]+cm.pop[	 ]+\{ra,s0-s11\},112
+[	 ]*[0-9a-f]+:[	 ]+baf6[	 ]+cm.pop[	 ]+\{ra,s0-s11\},128
+[	 ]*[0-9a-f]+:[	 ]+bafa[	 ]+cm.pop[	 ]+\{ra,s0-s11\},144
+[	 ]*[0-9a-f]+:[	 ]+bafe[	 ]+cm.pop[	 ]+\{ra,s0-s11\},160
+[	 ]*[0-9a-f]+:[	 ]+be4e[	 ]+cm.popret[	 ]+\{ra\},64
+[	 ]*[0-9a-f]+:[	 ]+be5e[	 ]+cm.popret[	 ]+\{ra,s0\},64
+[	 ]*[0-9a-f]+:[	 ]+be6a[	 ]+cm.popret[	 ]+\{ra,s0-s1\},64
+[	 ]*[0-9a-f]+:[	 ]+be7a[	 ]+cm.popret[	 ]+\{ra,s0-s2\},64
+[	 ]*[0-9a-f]+:[	 ]+beda[	 ]+cm.popret[	 ]+\{ra,s0-s8\},112
+[	 ]*[0-9a-f]+:[	 ]+bee6[	 ]+cm.popret[	 ]+\{ra,s0-s9\},112
+[	 ]*[0-9a-f]+:[	 ]+bef2[	 ]+cm.popret[	 ]+\{ra,s0-s11\},112
+[	 ]*[0-9a-f]+:[	 ]+be4e[	 ]+cm.popret[	 ]+\{ra\},64
+[	 ]*[0-9a-f]+:[	 ]+be5e[	 ]+cm.popret[	 ]+\{ra,s0\},64
+[	 ]*[0-9a-f]+:[	 ]+be6a[	 ]+cm.popret[	 ]+\{ra,s0-s1\},64
+[	 ]*[0-9a-f]+:[	 ]+be7a[	 ]+cm.popret[	 ]+\{ra,s0-s2\},64
+[	 ]*[0-9a-f]+:[	 ]+beda[	 ]+cm.popret[	 ]+\{ra,s0-s8\},112
+[	 ]*[0-9a-f]+:[	 ]+bee6[	 ]+cm.popret[	 ]+\{ra,s0-s9\},112
+[	 ]*[0-9a-f]+:[	 ]+bef2[	 ]+cm.popret[	 ]+\{ra,s0-s11},112
+[	 ]*[0-9a-f]+:[	 ]+be42[	 ]+cm.popret[	 ]+\{ra\},16
+[	 ]*[0-9a-f]+:[	 ]+be46[	 ]+cm.popret[	 ]+\{ra\},32
+[	 ]*[0-9a-f]+:[	 ]+be4e[	 ]+cm.popret[	 ]+\{ra\},64
+[	 ]*[0-9a-f]+:[	 ]+be72[	 ]+cm.popret[	 ]+\{ra,s0-s2\},32
+[	 ]*[0-9a-f]+:[	 ]+be7a[	 ]+cm.popret[	 ]+\{ra,s0-s2\},64
+[	 ]*[0-9a-f]+:[	 ]+be7e[	 ]+cm.popret[	 ]+\{ra,s0-s2\},80
+[	 ]*[0-9a-f]+:[	 ]+be82[	 ]+cm.popret[	 ]+\{ra,s0-s3\},48
+[	 ]*[0-9a-f]+:[	 ]+be86[	 ]+cm.popret[	 ]+\{ra,s0-s3\},64
+[	 ]*[0-9a-f]+:[	 ]+be8e[	 ]+cm.popret[	 ]+\{ra,s0-s3\},96
+[	 ]*[0-9a-f]+:[	 ]+beb2[	 ]+cm.popret[	 ]+\{ra,s0-s6\},64
+[	 ]*[0-9a-f]+:[	 ]+beb6[	 ]+cm.popret[	 ]+\{ra,s0-s6\},80
+[	 ]*[0-9a-f]+:[	 ]+bebe[	 ]+cm.popret[	 ]+\{ra,s0-s6\},112
+[	 ]*[0-9a-f]+:[	 ]+bec2[	 ]+cm.popret[	 ]+\{ra,s0-s7\},80
+[	 ]*[0-9a-f]+:[	 ]+bec6[	 ]+cm.popret[	 ]+\{ra,s0-s7\},96
+[	 ]*[0-9a-f]+:[	 ]+bece[	 ]+cm.popret[	 ]+\{ra,s0-s7\},128
+[	 ]*[0-9a-f]+:[	 ]+bee2[	 ]+cm.popret[	 ]+\{ra,s0-s9\},96
+[	 ]*[0-9a-f]+:[	 ]+bee6[	 ]+cm.popret[	 ]+\{ra,s0-s9\},112
+[	 ]*[0-9a-f]+:[	 ]+beee[	 ]+cm.popret[	 ]+\{ra,s0-s9\},144
+[	 ]*[0-9a-f]+:[	 ]+bef2[	 ]+cm.popret[	 ]+\{ra,s0-s11\},112
+[	 ]*[0-9a-f]+:[	 ]+bef6[	 ]+cm.popret[	 ]+\{ra,s0-s11\},128
+[	 ]*[0-9a-f]+:[	 ]+befa[	 ]+cm.popret[	 ]+\{ra,s0-s11\},144
+[	 ]*[0-9a-f]+:[	 ]+befe[	 ]+cm.popret[	 ]+\{ra,s0-s11\},160
+[	 ]*[0-9a-f]+:[	 ]+bc4e[	 ]+cm.popretz[	 ]+\{ra\},64
+[	 ]*[0-9a-f]+:[	 ]+bc5e[	 ]+cm.popretz[	 ]+\{ra,s0\},64
+[	 ]*[0-9a-f]+:[	 ]+bc6a[	 ]+cm.popretz[	 ]+\{ra,s0-s1\},64
+[	 ]*[0-9a-f]+:[	 ]+bc7a[	 ]+cm.popretz[	 ]+\{ra,s0-s2\},64
+[	 ]*[0-9a-f]+:[	 ]+bcda[	 ]+cm.popretz[	 ]+\{ra,s0-s8\},112
+[	 ]*[0-9a-f]+:[	 ]+bce6[	 ]+cm.popretz[	 ]+\{ra,s0-s9\},112
+[	 ]*[0-9a-f]+:[	 ]+bcf2[	 ]+cm.popretz[	 ]+\{ra,s0-s11\},112
+[	 ]*[0-9a-f]+:[	 ]+bc4e[	 ]+cm.popretz[	 ]+\{ra\},64
+[	 ]*[0-9a-f]+:[	 ]+bc5e[	 ]+cm.popretz[	 ]+\{ra,s0\},64
+[	 ]*[0-9a-f]+:[	 ]+bc6a[	 ]+cm.popretz[	 ]+\{ra,s0-s1\},64
+[	 ]*[0-9a-f]+:[	 ]+bc7a[	 ]+cm.popretz[	 ]+\{ra,s0-s2\},64
+[	 ]*[0-9a-f]+:[	 ]+bcda[	 ]+cm.popretz[	 ]+\{ra,s0-s8\},112
+[	 ]*[0-9a-f]+:[	 ]+bce6[	 ]+cm.popretz[	 ]+\{ra,s0-s9\},112
+[	 ]*[0-9a-f]+:[	 ]+bcf2[	 ]+cm.popretz[	 ]+\{ra,s0-s11},112
+[	 ]*[0-9a-f]+:[	 ]+bc42[	 ]+cm.popretz[	 ]+\{ra\},16
+[	 ]*[0-9a-f]+:[	 ]+bc46[	 ]+cm.popretz[	 ]+\{ra\},32
+[	 ]*[0-9a-f]+:[	 ]+bc4e[	 ]+cm.popretz[	 ]+\{ra\},64
+[	 ]*[0-9a-f]+:[	 ]+bc72[	 ]+cm.popretz[	 ]+\{ra,s0-s2\},32
+[	 ]*[0-9a-f]+:[	 ]+bc7a[	 ]+cm.popretz[	 ]+\{ra,s0-s2\},64
+[	 ]*[0-9a-f]+:[	 ]+bc7e[	 ]+cm.popretz[	 ]+\{ra,s0-s2\},80
+[	 ]*[0-9a-f]+:[	 ]+bc82[	 ]+cm.popretz[	 ]+\{ra,s0-s3\},48
+[	 ]*[0-9a-f]+:[	 ]+bc86[	 ]+cm.popretz[	 ]+\{ra,s0-s3\},64
+[	 ]*[0-9a-f]+:[	 ]+bc8e[	 ]+cm.popretz[	 ]+\{ra,s0-s3\},96
+[	 ]*[0-9a-f]+:[	 ]+bcb2[	 ]+cm.popretz[	 ]+\{ra,s0-s6\},64
+[	 ]*[0-9a-f]+:[	 ]+bcb6[	 ]+cm.popretz[	 ]+\{ra,s0-s6\},80
+[	 ]*[0-9a-f]+:[	 ]+bcbe[	 ]+cm.popretz[	 ]+\{ra,s0-s6\},112
+[	 ]*[0-9a-f]+:[	 ]+bcc2[	 ]+cm.popretz[	 ]+\{ra,s0-s7\},80
+[	 ]*[0-9a-f]+:[	 ]+bcc6[	 ]+cm.popretz[	 ]+\{ra,s0-s7\},96
+[	 ]*[0-9a-f]+:[	 ]+bcce[	 ]+cm.popretz[	 ]+\{ra,s0-s7\},128
+[	 ]*[0-9a-f]+:[	 ]+bce2[	 ]+cm.popretz[	 ]+\{ra,s0-s9\},96
+[	 ]*[0-9a-f]+:[	 ]+bce6[	 ]+cm.popretz[	 ]+\{ra,s0-s9\},112
+[	 ]*[0-9a-f]+:[	 ]+bcee[	 ]+cm.popretz[	 ]+\{ra,s0-s9\},144
+[	 ]*[0-9a-f]+:[	 ]+bcf2[	 ]+cm.popretz[	 ]+\{ra,s0-s11\},112
+[	 ]*[0-9a-f]+:[	 ]+bcf6[	 ]+cm.popretz[	 ]+\{ra,s0-s11\},128
+[	 ]*[0-9a-f]+:[	 ]+bcfa[	 ]+cm.popretz[	 ]+\{ra,s0-s11\},144
+[	 ]*[0-9a-f]+:[	 ]+bcfe[	 ]+cm.popretz[	 ]+\{ra,s0-s11\},160
diff --git a/gas/testsuite/gas/riscv/zcmp-push-pop.s b/gas/testsuite/gas/riscv/zcmp-push-pop.s
new file mode 100644
index 00000000000..dc441bc2776
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcmp-push-pop.s
@@ -0,0 +1,162 @@
+target:
+
+	# push
+	# abi names
+	cm.push {ra}, -64
+	cm.push {ra, s0}, -64
+	cm.push {ra, s0-s1}, -64
+	cm.push {ra, s0-s2}, -64
+	cm.push {ra, s0-s8}, -112
+	cm.push {ra, s0-s9}, -112
+	cm.push {ra, s0-s11}, -112
+	# numeric names
+	cm.push {x1}, -64
+	cm.push {x1, x8}, -64
+	cm.push {x1, x8-x9}, -64
+	cm.push {x1, x8-x9, x18}, -64
+	cm.push {x1, x8-x9, x18-x24}, -112
+	cm.push {x1, x8-x9, x18-x25}, -112
+	cm.push {x1, x8-x9, x18-x27}, -112
+	# spimm
+	cm.push {ra}, -16
+	cm.push {ra}, -32
+	cm.push {ra}, -64
+	cm.push {ra, s0-s2}, -32
+	cm.push {ra, s0-s2}, -64
+	cm.push {ra, s0-s2}, -80
+	cm.push {ra, s0-s3}, -48
+	cm.push {ra, s0-s3}, -64
+	cm.push {ra, s0-s3}, -96
+	cm.push {ra, s0-s6}, -64
+	cm.push {ra, s0-s6}, -80
+	cm.push {ra, s0-s6}, -112
+	cm.push {ra, s0-s7}, -80
+	cm.push {ra, s0-s7}, -96
+	cm.push {ra, s0-s7}, -128
+	cm.push {ra, s0-s9}, -96
+	cm.push {ra, s0-s9}, -112
+	cm.push {ra, s0-s9}, -144
+	cm.push {ra, s0-s11}, -112
+	cm.push {ra, s0-s11}, -128
+	cm.push {ra, s0-s11}, -144
+	cm.push {ra, s0-s11}, -160
+	# pop
+	# abi names
+	cm.pop {ra}, 64
+	cm.pop {ra, s0}, 64
+	cm.pop {ra, s0-s1}, 64
+	cm.pop {ra, s0-s2}, 64
+	cm.pop {ra, s0-s8}, 112
+	cm.pop {ra, s0-s9}, 112
+	cm.pop {ra, s0-s11}, 112
+	# numeric names
+	cm.pop {x1}, 64
+	cm.pop {x1, x8}, 64
+	cm.pop {x1, x8-x9}, 64
+	cm.pop {x1, x8-x9, x18}, 64
+	cm.pop {x1, x8-x9, x18-x24}, 112
+	cm.pop {x1, x8-x9, x18-x25}, 112
+	cm.pop {x1, x8-x9, x18-x27}, 112
+	# spimm
+	cm.pop {ra}, 16
+	cm.pop {ra}, 32
+	cm.pop {ra}, 64
+	cm.pop {ra, s0-s2}, 32
+	cm.pop {ra, s0-s2}, 64
+	cm.pop {ra, s0-s2}, 80
+	cm.pop {ra, s0-s3}, 48
+	cm.pop {ra, s0-s3}, 64
+	cm.pop {ra, s0-s3}, 96
+	cm.pop {ra, s0-s6}, 64
+	cm.pop {ra, s0-s6}, 80
+	cm.pop {ra, s0-s6}, 112
+	cm.pop {ra, s0-s7}, 80
+	cm.pop {ra, s0-s7}, 96
+	cm.pop {ra, s0-s7}, 128
+	cm.pop {ra, s0-s9}, 96
+	cm.pop {ra, s0-s9}, 112
+	cm.pop {ra, s0-s9}, 144
+	cm.pop {ra, s0-s11}, 112
+	cm.pop {ra, s0-s11}, 128
+	cm.pop {ra, s0-s11}, 144
+	cm.pop {ra, s0-s11}, 160
+	# popret
+	# abi names
+	cm.popret {ra}, 64
+	cm.popret {ra, s0}, 64
+	cm.popret {ra, s0-s1}, 64
+	cm.popret {ra, s0-s2}, 64
+	cm.popret {ra, s0-s8}, 112
+	cm.popret {ra, s0-s9}, 112
+	cm.popret {ra, s0-s11}, 112
+	# numeric names
+	cm.popret {x1}, 64
+	cm.popret {x1, x8}, 64
+	cm.popret {x1, x8-x9}, 64
+	cm.popret {x1, x8-x9, x18}, 64
+	cm.popret {x1, x8-x9, x18-x24}, 112
+	cm.popret {x1, x8-x9, x18-x25}, 112
+	cm.popret {x1, x8-x9, x18-x27}, 112
+	# spimm
+	cm.popret {ra}, 16
+	cm.popret {ra}, 32
+	cm.popret {ra}, 64
+	cm.popret {ra, s0-s2}, 32
+	cm.popret {ra, s0-s2}, 64
+	cm.popret {ra, s0-s2}, 80
+	cm.popret {ra, s0-s3}, 48
+	cm.popret {ra, s0-s3}, 64
+	cm.popret {ra, s0-s3}, 96
+	cm.popret {ra, s0-s6}, 64
+	cm.popret {ra, s0-s6}, 80
+	cm.popret {ra, s0-s6}, 112
+	cm.popret {ra, s0-s7}, 80
+	cm.popret {ra, s0-s7}, 96
+	cm.popret {ra, s0-s7}, 128
+	cm.popret {ra, s0-s9}, 96
+	cm.popret {ra, s0-s9}, 112
+	cm.popret {ra, s0-s9}, 144
+	cm.popret {ra, s0-s11}, 112
+	cm.popret {ra, s0-s11}, 128
+	cm.popret {ra, s0-s11}, 144
+	cm.popret {ra, s0-s11}, 160
+	# popretz
+	# abi names
+	cm.popretz {ra}, 64
+	cm.popretz {ra, s0}, 64
+	cm.popretz {ra, s0-s1}, 64
+	cm.popretz {ra, s0-s2}, 64
+	cm.popretz {ra, s0-s8}, 112
+	cm.popretz {ra, s0-s9}, 112
+	cm.popretz {ra, s0-s11}, 112
+	# numeric names
+	cm.popretz {x1}, 64
+	cm.popretz {x1, x8}, 64
+	cm.popretz {x1, x8-x9}, 64
+	cm.popretz {x1, x8-x9, x18}, 64
+	cm.popretz {x1, x8-x9, x18-x24}, 112
+	cm.popretz {x1, x8-x9, x18-x25}, 112
+	cm.popretz {x1, x8-x9, x18-x27}, 112
+	# spimm
+	cm.popretz {ra}, 16
+	cm.popretz {ra}, 32
+	cm.popretz {ra}, 64
+	cm.popretz {ra, s0-s2}, 32
+	cm.popretz {ra, s0-s2}, 64
+	cm.popretz {ra, s0-s2}, 80
+	cm.popretz {ra, s0-s3}, 48
+	cm.popretz {ra, s0-s3}, 64
+	cm.popretz {ra, s0-s3}, 96
+	cm.popretz {ra, s0-s6}, 64
+	cm.popretz {ra, s0-s6}, 80
+	cm.popretz {ra, s0-s6}, 112
+	cm.popretz {ra, s0-s7}, 80
+	cm.popretz {ra, s0-s7}, 96
+	cm.popretz {ra, s0-s7}, 128
+	cm.popretz {ra, s0-s9}, 96
+	cm.popretz {ra, s0-s9}, 112
+	cm.popretz {ra, s0-s9}, 144
+	cm.popretz {ra, s0-s11}, 112
+	cm.popretz {ra, s0-s11}, 128
+	cm.popretz {ra, s0-s11}, 144
+	cm.popretz {ra, s0-s11}, 160
diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
index e77b49a6298..d0f93b11f01 100644
--- a/include/opcode/riscv-opc.h
+++ b/include/opcode/riscv-opc.h
@@ -2235,6 +2235,15 @@
 #define MASK_C_NOT 0xfc7f
 #define MATCH_C_MUL 0x9c41
 #define MASK_C_MUL 0xfc63
+/* Zcmp instructions.  */
+#define MATCH_CM_PUSH 0xb802
+#define MASK_CM_PUSH 0xff03
+#define MATCH_CM_POP 0xba02
+#define MASK_CM_POP 0xff03
+#define MATCH_CM_POPRET 0xbe02
+#define MASK_CM_POPRET 0xff03
+#define MATCH_CM_POPRETZ 0xbc02
+#define MASK_CM_POPRETZ 0xff03
 /* Svinval instruction.  */
 #define MATCH_SINVAL_VMA 0x16000073
 #define MASK_SINVAL_VMA 0xfe007fff
@@ -3916,6 +3925,11 @@ DECLARE_INSN(c_lhu, MATCH_C_LHU, MASK_C_LHU)
 DECLARE_INSN(c_lh, MATCH_C_LH, MASK_C_LH)
 DECLARE_INSN(c_sb, MATCH_C_SB, MASK_C_SB)
 DECLARE_INSN(c_sh, MATCH_C_SH, MASK_C_SH)
+/* Zcmp instructions.  */
+DECLARE_INSN(cm_push, MATCH_CM_PUSH, MASK_CM_PUSH)
+DECLARE_INSN(cm_pop, MATCH_CM_POP, MASK_CM_POP)
+DECLARE_INSN(cm_popret, MATCH_CM_POPRET, MASK_CM_POPRET)
+DECLARE_INSN(cm_popretz, MATCH_CM_POPRETZ, MASK_CM_POPRETZ)
 /* Vendor-specific (T-Head) XTheadBa instructions.  */
 DECLARE_INSN(th_addsl, MATCH_TH_ADDSL, MASK_TH_ADDSL)
 /* Vendor-specific (T-Head) XTheadBb instructions.  */
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index adea7dbc794..630c9cf13ff 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -112,6 +112,8 @@ static inline unsigned int riscv_insn_length (insn_t insn)
   (RV_X(x, 6, 1) | (RV_X(x, 5, 1) << 1))
 #define EXTRACT_ZCB_HALFWORD_UIMM(x) \
   (RV_X(x, 5, 1) << 1)
+#define EXTRACT_ZCMP_SPIMM(x) \
+  (RV_X(x, 2, 2) << 4)
 /* Vendor-specific (CORE-V) extract macros.  */
 #define EXTRACT_CV_IS2_UIMM5(x) \
   (RV_X(x, 20, 5))
@@ -168,6 +170,8 @@ static inline unsigned int riscv_insn_length (insn_t insn)
   ((RV_X(x, 0, 1) << 6) | (RV_X(x, 1, 1) << 5))
 #define ENCODE_ZCB_HALFWORD_UIMM(x) \
   (RV_X(x, 1, 1) << 5)
+#define ENCODE_ZCMP_SPIMM(x) \
+  (RV_X(x, 4, 2) << 2)
 /* Vendor-specific (CORE-V) encode macros.  */
 #define ENCODE_CV_IS2_UIMM5(x) \
   (RV_X(x, 0, 5) << 20)
@@ -200,6 +204,7 @@ static inline unsigned int riscv_insn_length (insn_t insn)
 #define VALID_RVV_VC_IMM(x) (EXTRACT_RVV_VC_IMM(ENCODE_RVV_VC_IMM(x)) == (x))
 #define VALID_ZCB_BYTE_UIMM(x) (EXTRACT_ZCB_BYTE_UIMM(ENCODE_ZCB_BYTE_UIMM(x)) == (x))
 #define VALID_ZCB_HALFWORD_UIMM(x) (EXTRACT_ZCB_HALFWORD_UIMM(ENCODE_ZCB_HALFWORD_UIMM(x)) == (x))
+#define VALID_ZCMP_SPIMM(x) (EXTRACT_ZCMP_SPIMM(ENCODE_ZCMP_SPIMM(x)) == (x))
 
 #define RISCV_RTYPE(insn, rd, rs1, rs2) \
   ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2))
@@ -337,6 +342,11 @@ static inline unsigned int riscv_insn_length (insn_t insn)
 #define OP_MASK_XTHEADVTYPE_RES	0xf
 #define OP_SH_XTHEADVTYPE_RES	7
 
+/* Zc fields.  */
+#define OP_MASK_REG_LIST		0xf
+#define OP_SH_REG_LIST		4
+#define ZCMP_SP_ALIGNMENT 16
+
 #define NVECR 32
 #define NVECM 1
 
@@ -355,6 +365,11 @@ static inline unsigned int riscv_insn_length (insn_t insn)
 #define X_T0 5
 #define X_T1 6
 #define X_T2 7
+#define X_S0 8
+#define X_S1 9
+#define X_S2 18
+#define X_S10 26
+#define X_S11 27
 #define X_T3 28
 
 #define NGPR 32
@@ -464,6 +479,7 @@ enum riscv_insn_class
   INSN_CLASS_ZCB_AND_ZBA,
   INSN_CLASS_ZCB_AND_ZBB,
   INSN_CLASS_ZCB_AND_ZMMUL,
+  INSN_CLASS_ZCMP,
   INSN_CLASS_SVINVAL,
   INSN_CLASS_ZICBOM,
   INSN_CLASS_ZICBOP,
@@ -582,6 +598,19 @@ enum
   M_NUM_MACROS
 };
 
+/* get sp base adjustment */
+
+static inline unsigned int
+riscv_get_sp_base (insn_t opcode, unsigned int xlen)
+{
+  unsigned reg_size = xlen / 8;
+  unsigned reg_list = EXTRACT_BITS (opcode, OP_MASK_REG_LIST, OP_SH_REG_LIST);
+
+  unsigned min_sp_adj = (reg_list - 3) * reg_size + (reg_list == 15 ? reg_size : 0);
+  return ((min_sp_adj / ZCMP_SP_ALIGNMENT) + (min_sp_adj % ZCMP_SP_ALIGNMENT != 0))
+    * ZCMP_SP_ALIGNMENT;
+}
+
 /* The mapping symbol states.  */
 enum riscv_seg_mstate
 {
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 3019b9a5130..f1a7c975038 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -75,6 +75,8 @@ static const char (*riscv_fpr_names)[NRC];
 /* If set, disassemble as most general instruction.  */
 static bool no_aliases = false;
 
+/* If set, disassemble numeric register names instead of ABI names.  */
+static int numeric = false;
 
 /* Set default RISC-V disassembler options.  */
 
@@ -84,6 +86,7 @@ set_default_riscv_dis_options (void)
   riscv_gpr_names = riscv_gpr_names_abi;
   riscv_fpr_names = riscv_fpr_names_abi;
   no_aliases = false;
+  numeric = false;
 }
 
 /* Parse RISC-V disassembler option (without arguments).  */
@@ -97,6 +100,7 @@ parse_riscv_dis_option_without_args (const char *option)
     {
       riscv_gpr_names = riscv_gpr_names_numeric;
       riscv_fpr_names = riscv_fpr_names_numeric;
+      numeric = true;
     }
   else
     return false;
@@ -215,6 +219,50 @@ maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset,
     pd->print_addr = (bfd_vma)(uint32_t)pd->print_addr;
 }
 
+/* Get Zcmp reg_list field.  */
+
+static void
+print_reg_list (disassemble_info *info, insn_t l)
+{
+  unsigned reg_list = (int)EXTRACT_OPERAND (REG_LIST, l);
+  unsigned r_start = numeric ? X_S2 : X_S0;
+  info->fprintf_func (info->stream, "%s", riscv_gpr_names[X_RA]);
+
+  if (reg_list == 5)
+    info->fprintf_func (info->stream, ",%s", riscv_gpr_names[X_S0]);
+  else if (reg_list == 6 || (numeric && reg_list > 6))
+    info->fprintf_func (info->stream, ",%s-%s",
+	  riscv_gpr_names[X_S0],
+	  riscv_gpr_names[X_S1]);
+
+  if (reg_list == 15)
+    info->fprintf_func (info->stream, ",%s-%s",
+	  riscv_gpr_names[r_start],
+	  riscv_gpr_names[X_S11]);
+  else if (reg_list == 7 && numeric)
+    info->fprintf_func (info->stream, ",%s",
+	  riscv_gpr_names[X_S2]);
+  else if (reg_list > 6)
+    info->fprintf_func (info->stream, ",%s-%s",
+	  riscv_gpr_names[r_start],
+	  riscv_gpr_names[reg_list + 11]);
+}
+
+/* Get Zcmp sp adjustment immediate.  */
+
+static int
+riscv_get_spimm (insn_t l)
+{
+  int spimm = riscv_get_sp_base(l, *riscv_rps_dis.xlen);
+
+  spimm += EXTRACT_ZCMP_SPIMM (l);
+
+  if (((l ^ MATCH_CM_PUSH) & MASK_CM_PUSH) == 0)
+    spimm *= -1;
+
+  return spimm;
+}
+
 /* Print insn arguments for 32/64-bit code.  */
 
 static void
@@ -420,6 +468,8 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 	case ')':
 	case '[':
 	case ']':
+	case '{':
+	case '}':
 	  print (info->stream, dis_style_text, "%c", *oparg);
 	  break;
 
@@ -634,6 +684,13 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 		  print (info->stream, dis_style_immediate, "%d",
 			 (int)EXTRACT_ZCB_HALFWORD_UIMM (l));
 		  break;
+		case 'r':
+		  print_reg_list (info, l);
+		  break;
+		case 'p':
+		  print (info->stream, dis_style_immediate, "%d",
+			 riscv_get_spimm (l));
+		  break;
 		default:
 		  goto undefined_modifier;
 		}
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index fdd05ac75dc..3da75db6db1 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -1993,6 +1993,12 @@ const struct riscv_opcode riscv_opcodes[] =
 {"c.zext.b",   0, INSN_CLASS_ZCB, "Cs",  MATCH_C_ZEXT_B, MASK_C_ZEXT_B, match_opcode, 0 },
 {"c.sext.w",  64, INSN_CLASS_ZCB, "d",  MATCH_C_ADDIW, MASK_C_ADDIW|MASK_RVC_IMM, match_rd_nonzero, INSN_ALIAS },
 
+/* Zcmp instructions.  */
+{"cm.push",    0,  INSN_CLASS_ZCMP, "{Wcr},Wcp",  MATCH_CM_PUSH, MASK_CM_PUSH, match_opcode, 0 },
+{"cm.pop",     0,  INSN_CLASS_ZCMP, "{Wcr},Wcp",  MATCH_CM_POP, MASK_CM_POP, match_opcode, 0 },
+{"cm.popret",  0,  INSN_CLASS_ZCMP, "{Wcr},Wcp",  MATCH_CM_POPRET, MASK_CM_POPRET, match_opcode, 0 },
+{"cm.popretz", 0,  INSN_CLASS_ZCMP, "{Wcr},Wcp",  MATCH_CM_POPRETZ, MASK_CM_POPRETZ, match_opcode, 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 },
-- 
2.25.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v4 2/2] RISC-V: Support Zcmp cm.mv instructions.
  2024-01-24  9:37 [PATCH v4 1/2] RISC-V: Support Zcmp push/pop instructions Jiawei
@ 2024-01-24  9:37 ` Jiawei
  2024-01-26  8:33 ` [PATCH v4 1/2] RISC-V: Support Zcmp push/pop instructions Kito Cheng
  1 sibling, 0 replies; 3+ messages in thread
From: Jiawei @ 2024-01-24  9:37 UTC (permalink / raw)
  To: binutils
  Cc: nelson, kito.cheng, palmer, jbeulich, research_trasio,
	christoph.muellner, jeremy.bennett, nandni.jamnadas,
	mary.bennett, charlie.keaney, simon.cook, sinan.lin, gaofei,
	fujin.zhao, wuwei2016, shihua, shiyulong, chenyixuan, Jiawei

This patch supports Zcmp instruction 'cm.mva01s' and 'cm.mvsa01'.
All disassemble instructions use the sreg format.

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>

gas/ChangeLog:

        * config/tc-riscv.c (validate_riscv_insn): New operators.
        (riscv_ip): Ditto.
        * testsuite/gas/riscv/zcmp-mv.d: New test.
        * testsuite/gas/riscv/zcmp-mv.s: New test.

include/ChangeLog:

        * opcode/riscv-opc.h (MATCH_CM_MVA01S): New opcode.
        (MASK_CM_MVA01S): New mask.
        (MATCH_CM_MVSA01): New opcode.
        (MASK_CM_MVSA01): New mask.
        (DECLARE_INSN): New declarations.
        * opcode/riscv.h (OP_MASK_SREG1): New mask.
        (OP_SH_SREG1): New operand code.
        (OP_MASK_SREG2): New mask.
        (OP_SH_SREG2): New operand code.
        (X_A0): New reg number.
        (X_A1): Ditto.
        (X_S7): Ditto.
        (RISCV_SREG_0_7): New macro function.

opcodes/ChangeLog:

        * riscv-dis.c (riscv_zcmp_get_sregno): New function.
        (print_insn_args): New operators.
        * riscv-opc.c (match_sreg1_not_eq_sreg2): New match function.
---
 gas/config/tc-riscv.c             | 15 +++++++++++++++
 gas/testsuite/gas/riscv/zcmp-mv.d | 26 ++++++++++++++++++++++++++
 gas/testsuite/gas/riscv/zcmp-mv.s | 21 +++++++++++++++++++++
 include/opcode/riscv-opc.h        |  6 ++++++
 include/opcode/riscv.h            | 12 ++++++++++++
 opcodes/riscv-dis.c               | 19 +++++++++++++++++++
 opcodes/riscv-opc.c               |  9 +++++++++
 7 files changed, 108 insertions(+)
 create mode 100644 gas/testsuite/gas/riscv/zcmp-mv.d
 create mode 100644 gas/testsuite/gas/riscv/zcmp-mv.s

diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index a9f0b90af71..569bbbac3fd 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1566,6 +1566,9 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
 	    case 'c':
 	      switch (*++oparg)
 		{
+		/* sreg operators in cm.mvsa01 and cm.mva01s. */
+		case '1': USE_BITS (OP_MASK_SREG1, OP_SH_SREG1); break;
+		case '2': USE_BITS (OP_MASK_SREG2, OP_SH_SREG2); break;
 		/* byte immediate operators, load/store byte insns.  */
 		case 'h': used_bits |= ENCODE_ZCB_HALFWORD_UIMM (-1U); break;
 		/* halfword immediate operators, load/store halfword insns.  */
@@ -3814,6 +3817,18 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
 		      asarg = expr_parse_end;
 		      imm_expr->X_op = O_absent;
 		      continue;
+		    case '1':
+		      if (!reg_lookup (&asarg, RCLASS_GPR, &regno)
+			  || !RISCV_SREG_0_7 (regno))
+			break;
+		      INSERT_OPERAND (SREG1, *ip, regno % 8);
+		      continue;
+		    case '2':
+		      if (!reg_lookup (&asarg, RCLASS_GPR, &regno)
+			  || !RISCV_SREG_0_7 (regno))
+			break;
+		      INSERT_OPERAND (SREG2, *ip, regno % 8);
+		      continue;
 		    default:
 		      goto unknown_riscv_ip_operand;
 		    }
diff --git a/gas/testsuite/gas/riscv/zcmp-mv.d b/gas/testsuite/gas/riscv/zcmp-mv.d
new file mode 100644
index 00000000000..351d301dd3f
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcmp-mv.d
@@ -0,0 +1,26 @@
+#as: -march=rv64i_zcmp
+#source: zcmp-mv.s
+#objdump: -dr -Mno-aliases
+
+.*:[	 ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[	 ]*[0-9a-f]+:[	 ]+ac7e[	 ]+cm.mva01s[	 ]+s0,s7
+[	 ]*[0-9a-f]+:[	 ]+ac7a[	 ]+cm.mva01s[	 ]+s0,s6
+[	 ]*[0-9a-f]+:[	 ]+acfe[	 ]+cm.mva01s[	 ]+s1,s7
+[	 ]*[0-9a-f]+:[	 ]+acfa[	 ]+cm.mva01s[	 ]+s1,s6
+[	 ]*[0-9a-f]+:[	 ]+afee[	 ]+cm.mva01s[	 ]+s7,s3
+[	 ]*[0-9a-f]+:[	 ]+ade2[	 ]+cm.mva01s[	 ]+s3,s0
+[	 ]*[0-9a-f]+:[	 ]+aef2[	 ]+cm.mva01s[	 ]+s5,s4
+[	 ]*[0-9a-f]+:[	 ]+aefa[	 ]+cm.mva01s[	 ]+s5,s6
+[	 ]*[0-9a-f]+:[	 ]+afa2[	 ]+cm.mvsa01[	 ]+s7,s0
+[	 ]*[0-9a-f]+:[	 ]+af22[	 ]+cm.mvsa01[	 ]+s6,s0
+[	 ]*[0-9a-f]+:[	 ]+afa6[	 ]+cm.mvsa01[	 ]+s7,s1
+[	 ]*[0-9a-f]+:[	 ]+af26[	 ]+cm.mvsa01[	 ]+s6,s1
+[	 ]*[0-9a-f]+:[	 ]+adbe[	 ]+cm.mvsa01[	 ]+s3,s7
+[	 ]*[0-9a-f]+:[	 ]+ada2[	 ]+cm.mvsa01[	 ]+s3,s0
+[	 ]*[0-9a-f]+:[	 ]+aeb2[	 ]+cm.mvsa01[	 ]+s5,s4
+[	 ]*[0-9a-f]+:[	 ]+aeba[	 ]+cm.mvsa01[	 ]+s5,s6
diff --git a/gas/testsuite/gas/riscv/zcmp-mv.s b/gas/testsuite/gas/riscv/zcmp-mv.s
new file mode 100644
index 00000000000..0bcf2a6cd98
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcmp-mv.s
@@ -0,0 +1,21 @@
+target:
+
+	# cm.mva01s
+	cm.mva01s s0,s7
+	cm.mva01s s0,s6
+	cm.mva01s s1,s7
+	cm.mva01s s1,s6
+	cm.mva01s s7,s3
+	cm.mva01s x19,s0
+	cm.mva01s s5,x20
+	cm.mva01s x21,x22
+
+	# cm.mvsa01
+	cm.mvsa01 s7,s0
+	cm.mvsa01 s6,s0
+	cm.mvsa01 s7,s1
+	cm.mvsa01 s6,s1
+	cm.mvsa01 s3,s7
+	cm.mvsa01 x19,s0
+	cm.mvsa01 s5,x20
+	cm.mvsa01 x21,x22
diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
index d0f93b11f01..606982d7bb7 100644
--- a/include/opcode/riscv-opc.h
+++ b/include/opcode/riscv-opc.h
@@ -2244,6 +2244,10 @@
 #define MASK_CM_POPRET 0xff03
 #define MATCH_CM_POPRETZ 0xbc02
 #define MASK_CM_POPRETZ 0xff03
+#define MATCH_CM_MVA01S 0xac62
+#define MASK_CM_MVA01S 0xfc63
+#define MATCH_CM_MVSA01 0xac22
+#define MASK_CM_MVSA01 0xfc63
 /* Svinval instruction.  */
 #define MATCH_SINVAL_VMA 0x16000073
 #define MASK_SINVAL_VMA 0xfe007fff
@@ -3930,6 +3934,8 @@ DECLARE_INSN(cm_push, MATCH_CM_PUSH, MASK_CM_PUSH)
 DECLARE_INSN(cm_pop, MATCH_CM_POP, MASK_CM_POP)
 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)
 /* Vendor-specific (T-Head) XTheadBa instructions.  */
 DECLARE_INSN(th_addsl, MATCH_TH_ADDSL, MASK_TH_ADDSL)
 /* Vendor-specific (T-Head) XTheadBb instructions.  */
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index 630c9cf13ff..a12c6cc3b1e 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -346,6 +346,10 @@ static inline unsigned int riscv_insn_length (insn_t insn)
 #define OP_MASK_REG_LIST		0xf
 #define OP_SH_REG_LIST		4
 #define SP_ALIGNMENT 16
+#define OP_MASK_SREG1		0x7
+#define OP_SH_SREG1		7
+#define OP_MASK_SREG2		0x7
+#define OP_SH_SREG2		2
 
 #define NVECR 32
 #define NVECM 1
@@ -367,7 +371,10 @@ static inline unsigned int riscv_insn_length (insn_t insn)
 #define X_T2 7
 #define X_S0 8
 #define X_S1 9
+#define X_A0 10
+#define X_A1 11
 #define X_S2 18
+#define X_S7 23
 #define X_S10 26
 #define X_S11 27
 #define X_T3 28
@@ -415,6 +422,11 @@ static inline unsigned int riscv_insn_length (insn_t insn)
 /* The maximal number of subset can be required.  */
 #define MAX_SUBSET_NUM 4
 
+/* The range of sregs.  */
+#define RISCV_SREG_0_7(REGNO) \
+	((REGNO == X_S0 || REGNO == X_S1) \
+	 || (REGNO >= X_S2 && REGNO <= X_S7))
+
 /* All RISC-V instructions belong to at least one of these classes.  */
 enum riscv_insn_class
 {
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index f1a7c975038..c3be451ba4d 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -263,6 +263,17 @@ riscv_get_spimm (insn_t l)
   return spimm;
 }
 
+/* Get s-register regno by using sreg number.
+   e.g. the regno of s0 is 8, so
+   riscv_zcmp_get_sregno (0) equals 8. */
+
+static unsigned
+riscv_zcmp_get_sregno (unsigned sreg_idx)
+{
+  return sreg_idx > 1 ?
+      sreg_idx + 16 : sreg_idx + 8;
+}
+
 /* Print insn arguments for 32/64-bit code.  */
 
 static void
@@ -676,6 +687,14 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 	    case 'c': /* Zcb extension 16 bits length instruction fields. */
 	      switch (*++oparg)
 		{
+		case '1':
+		    print (info->stream, dis_style_register, "%s",
+		      riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG1, l))]);
+		    break;
+		case '2':
+		    print (info->stream, dis_style_register, "%s",
+		      riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG2, l))]);
+		    break;
 		case 'b':
 		  print (info->stream, dis_style_immediate, "%d",
 			 (int)EXTRACT_ZCB_BYTE_UIMM (l));
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index 3da75db6db1..9d61ce95433 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -333,6 +333,13 @@ match_th_load_pair(const struct riscv_opcode *op,
   return rd1 != rd2 && rd1 != rs && rd2 != rs && match_opcode (op, insn);
 }
 
+static int
+match_sreg1_not_eq_sreg2 (const struct riscv_opcode *op, insn_t insn)
+{
+  return match_opcode (op, insn)
+      && (EXTRACT_OPERAND (SREG1, insn) != EXTRACT_OPERAND (SREG2, insn));
+}
+
 /* 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
@@ -1998,6 +2005,8 @@ const struct riscv_opcode riscv_opcodes[] =
 {"cm.pop",     0,  INSN_CLASS_ZCMP, "{Wcr},Wcp",  MATCH_CM_POP, MASK_CM_POP, match_opcode, 0 },
 {"cm.popret",  0,  INSN_CLASS_ZCMP, "{Wcr},Wcp",  MATCH_CM_POPRET, MASK_CM_POPRET, match_opcode, 0 },
 {"cm.popretz", 0,  INSN_CLASS_ZCMP, "{Wcr},Wcp",  MATCH_CM_POPRETZ, MASK_CM_POPRETZ, match_opcode, 0 },
+{"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 },
 
 /* Supervisor instructions.  */
 {"csrr",       0, INSN_CLASS_ZICSR, "d,E",   MATCH_CSRRS, MASK_CSRRS|MASK_RS1, match_opcode, INSN_ALIAS },
-- 
2.25.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v4 1/2] RISC-V: Support Zcmp push/pop instructions.
  2024-01-24  9:37 [PATCH v4 1/2] RISC-V: Support Zcmp push/pop instructions Jiawei
  2024-01-24  9:37 ` [PATCH v4 2/2] RISC-V: Support Zcmp cm.mv instructions Jiawei
@ 2024-01-26  8:33 ` Kito Cheng
  1 sibling, 0 replies; 3+ messages in thread
From: Kito Cheng @ 2024-01-26  8:33 UTC (permalink / raw)
  To: Jiawei
  Cc: binutils, nelson, palmer, jbeulich, research_trasio,
	christoph.muellner, jeremy.bennett, nandni.jamnadas,
	mary.bennett, charlie.keaney, simon.cook, sinan.lin, gaofei,
	fujin.zhao, wuwei2016, shihua, shiyulong, chenyixuan

> +/* If set, disassemble numeric register names instead of ABI names.  */
> +static int numeric = false;
>
>  /* Set default RISC-V disassembler options.  */
>
> @@ -84,6 +86,7 @@ set_default_riscv_dis_options (void)
>    riscv_gpr_names = riscv_gpr_names_abi;
>    riscv_fpr_names = riscv_fpr_names_abi;
>    no_aliases = false;
> +  numeric = false;
>  }
>
>  /* Parse RISC-V disassembler option (without arguments).  */
> @@ -97,6 +100,7 @@ parse_riscv_dis_option_without_args (const char *option)
>      {
>        riscv_gpr_names = riscv_gpr_names_numeric;
>        riscv_fpr_names = riscv_fpr_names_numeric;
> +      numeric = true;
>      }
>    else
>      return false;
> @@ -215,6 +219,50 @@ maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset,
>      pd->print_addr = (bfd_vma)(uint32_t)pd->print_addr;
>  }
>
> +/* Get Zcmp reg_list field.  */
> +
> +static void
> +print_reg_list (disassemble_info *info, insn_t l)
> +{

bool numeric = riscv_gpr_names == riscv_gpr_names_numeric;

then you can drop numeric from global variables.

> +  unsigned reg_list = (int)EXTRACT_OPERAND (REG_LIST, l);
> +  unsigned r_start = numeric ? X_S2 : X_S0;
> +  info->fprintf_func (info->stream, "%s", riscv_gpr_names[X_RA]);
> +
> +  if (reg_list == 5)
> +    info->fprintf_func (info->stream, ",%s", riscv_gpr_names[X_S0]);
> +  else if (reg_list == 6 || (numeric && reg_list > 6))
> +    info->fprintf_func (info->stream, ",%s-%s",
> +         riscv_gpr_names[X_S0],
> +         riscv_gpr_names[X_S1]);
> +

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-01-26  8:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-24  9:37 [PATCH v4 1/2] RISC-V: Support Zcmp push/pop instructions Jiawei
2024-01-24  9:37 ` [PATCH v4 2/2] RISC-V: Support Zcmp cm.mv instructions Jiawei
2024-01-26  8:33 ` [PATCH v4 1/2] RISC-V: Support Zcmp push/pop instructions Kito Cheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).