aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiawei <jiawei@iscas.ac.cn>2023-07-12 20:40:36 +0800
committerNelson Chu <nelson@rivosinc.com>2023-07-18 11:45:58 +0800
commitb0a101c53a1caa3f2a9fc2032f703ca4465cfbbb (patch)
tree1f982cef3e1a4560c482629eece82363cea2f46f
parent7ab8bf1c777644f834ccbc5d1e83d721859ca1ba (diff)
downloadbinutils-b0a101c53a1caa3f2a9fc2032f703ca4465cfbbb.zip
binutils-b0a101c53a1caa3f2a9fc2032f703ca4465cfbbb.tar.gz
binutils-b0a101c53a1caa3f2a9fc2032f703ca4465cfbbb.tar.bz2
RISC-V: Supports Zcb extension.
This patch support Zcb extension, contains new compressed instructions, some instructions depend on other existed extension, like 'zba', 'zbb' and 'zmmul'. Zcb also imply Zca extension to enable the compressing features. 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 (validate_riscv_insn): New operators. (riscv_ip): Ditto. * testsuite/gas/riscv/zcb.d: New test. * testsuite/gas/riscv/zcb.s: New test. include/ChangeLog: * opcode/riscv-opc.h (MATCH_C_LBU): New opcode. (MASK_C_LBU): New mask. (MATCH_C_LHU): New opcode. (MASK_C_LHU): New mask. (MATCH_C_LH): New opcode. (MASK_C_LH): New mask. (MATCH_C_SB): New opcode. (MASK_C_SB): New mask. (MATCH_C_SH): New opcode. (MASK_C_SH): New mask. (MATCH_C_ZEXT_B): New opcode. (MASK_C_ZEXT_B): New mask. (MATCH_C_SEXT_B): New opcode. (MASK_C_SEXT_B): New mask. (MATCH_C_ZEXT_H): New opcode. (MASK_C_ZEXT_H): New mask. (MATCH_C_SEXT_H): New opcode. (MASK_C_SEXT_H): New mask. (MATCH_C_ZEXT_W): New opcode. (MASK_C_ZEXT_W): New mask. (MATCH_C_NOT): New opcode. (MASK_C_NOT): New mask. (MATCH_C_MUL): New opcode. (MASK_C_MUL): New mask. (DECLARE_INSN): New opcode. * opcode/riscv.h (EXTRACT_ZCB_BYTE_UIMM): New inline func. (EXTRACT_ZCB_HALFWORD_UIMM): Ditto. (ENCODE_ZCB_BYTE_UIMM): Ditto. (ENCODE_ZCB_HALFWORD_UIMM): Ditto. (VALID_ZCB_BYTE_UIMM): Ditto. (VALID_ZCB_HALFWORD_UIMM): Ditto. (enum riscv_insn_class): New extension class. opcodes/ChangeLog: * riscv-dis.c (print_insn_args): New operators. * riscv-opc.c: New instructions.
-rw-r--r--bfd/elfxx-riscv.c21
-rw-r--r--gas/config/tc-riscv.c53
-rw-r--r--gas/testsuite/gas/riscv/zcb.d32
-rw-r--r--gas/testsuite/gas/riscv/zcb.s25
-rw-r--r--include/opcode/riscv-opc.h38
-rw-r--r--include/opcode/riscv.h14
-rw-r--r--opcodes/riscv-dis.c14
-rw-r--r--opcodes/riscv-opc.c28
8 files changed, 225 insertions, 0 deletions
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 8635187..ee96608 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1173,6 +1173,7 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
{"zvksc", "zvbc", check_implicit_always},
{"zcf", "zca", check_implicit_always},
{"zcd", "zca", check_implicit_always},
+ {"zcb", "zca", check_implicit_always},
{"smaia", "ssaia", check_implicit_always},
{"smstateen", "ssstateen", check_implicit_always},
{"smepmp", "zicsr", check_implicit_always},
@@ -1307,6 +1308,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
{"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"ztso", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
{"zca", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zcb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zcf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zcd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{NULL, 0, 0, 0, 0}
@@ -2494,6 +2496,17 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
return riscv_subset_supports (rps, "zvksed");
case INSN_CLASS_ZVKSH:
return riscv_subset_supports (rps, "zvksh");
+ case INSN_CLASS_ZCB:
+ return riscv_subset_supports (rps, "zcb");
+ case INSN_CLASS_ZCB_AND_ZBB:
+ return (riscv_subset_supports (rps, "zcb")
+ && riscv_subset_supports (rps, "zbb"));
+ case INSN_CLASS_ZCB_AND_ZBA:
+ return (riscv_subset_supports (rps, "zcb")
+ && riscv_subset_supports (rps, "zba"));
+ case INSN_CLASS_ZCB_AND_ZMMUL:
+ return (riscv_subset_supports (rps, "zcb")
+ && riscv_subset_supports (rps, "zmmul"));
case INSN_CLASS_SVINVAL:
return riscv_subset_supports (rps, "svinval");
case INSN_CLASS_H:
@@ -2702,6 +2715,14 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
return _("zvksed");
case INSN_CLASS_ZVKSH:
return _("zvksh");
+ case INSN_CLASS_ZCB:
+ return "zcb";
+ case INSN_CLASS_ZCB_AND_ZBA:
+ return _("zcb' and `zba");
+ case INSN_CLASS_ZCB_AND_ZBB:
+ return _("zcb' and `zbb");
+ case INSN_CLASS_ZCB_AND_ZMMUL:
+ return _("zcb' and `zmmul', or `zcb' and `m");
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 8c23c6a..80c14a3 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1426,6 +1426,18 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
goto unknown_validate_operand;
}
break;
+ case 'c':
+ switch (*++oparg)
+ {
+ /* byte immediate operators, load/store byte insns. */
+ 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;
+ case 'f': break;
+ default:
+ goto unknown_validate_operand;
+ }
+ break;
default:
goto unknown_validate_operand;
}
@@ -3559,6 +3571,47 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
goto unknown_riscv_ip_operand;
}
break;
+
+ case 'c':
+ switch (*++oparg)
+ {
+ case 'h': /* Immediate field for c.lh/c.lhu/c.sh. */
+ /* Handle cases, such as c.sh rs2', (rs1'). */
+ if (riscv_handle_implicit_zero_offset (imm_expr, asarg))
+ continue;
+ if (my_getSmallExpression (imm_expr, imm_reloc, asarg, p)
+ || imm_expr->X_op != O_constant
+ || !VALID_ZCB_HALFWORD_UIMM ((valueT) imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_ZCB_HALFWORD_UIMM (imm_expr->X_add_number);
+ goto rvc_imm_done;
+
+ case 'b': /* Immediate field for c.lbu/c.sb. */
+ /* Handle cases, such as c.lbu rd', (rs1'). */
+ if (riscv_handle_implicit_zero_offset (imm_expr, asarg))
+ continue;
+ if (my_getSmallExpression (imm_expr, imm_reloc, asarg, p)
+ || imm_expr->X_op != O_constant
+ || !VALID_ZCB_BYTE_UIMM ((valueT) imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_ZCB_BYTE_UIMM (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
+ || imm_expr->X_add_number != 255)
+ break;
+ /* This operand is used for matching immediate 255, and
+ we do not write anything to encoding by this operand. */
+ asarg = expr_parse_end;
+ imm_expr->X_op = O_absent;
+ continue;
+
+ default:
+ goto unknown_riscv_ip_operand;
+ }
+ break;
default:
goto unknown_riscv_ip_operand;
}
diff --git a/gas/testsuite/gas/riscv/zcb.d b/gas/testsuite/gas/riscv/zcb.d
new file mode 100644
index 0000000..26a122b
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcb.d
@@ -0,0 +1,32 @@
+#as: -march=rv64im_zba_zbb_zcb
+#objdump: -d -Mno-aliases
+
+.*:[ ]+file format .*
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ ]+[0-9a-f]+:[ ]+8020[ ]+c.lbu[ ]+s0,2\(s0\)
+[ ]+[0-9a-f]+:[ ]+8380[ ]+c.lbu[ ]+s0,0\(a5\)
+[ ]+[0-9a-f]+:[ ]+8420[ ]+c.lhu[ ]+s0,2\(s0\)
+[ ]+[0-9a-f]+:[ ]+8780[ ]+c.lhu[ ]+s0,0\(a5\)
+[ ]+[0-9a-f]+:[ ]+8460[ ]+c.lh[ ]+s0,2\(s0\)
+[ ]+[0-9a-f]+:[ ]+87c0[ ]+c.lh[ ]+s0,0\(a5\)
+[ ]+[0-9a-f]+:[ ]+8820[ ]+c.sb[ ]+s0,2\(s0\)
+[ ]+[0-9a-f]+:[ ]+8b80[ ]+c.sb[ ]+s0,0\(a5\)
+[ ]+[0-9a-f]+:[ ]+8c20[ ]+c.sh[ ]+s0,2\(s0\)
+[ ]+[0-9a-f]+:[ ]+8f80[ ]+c.sh[ ]+s0,0\(a5\)
+[ ]+[0-9a-f]+:[ ]+9c61[ ]+c.zext.b[ ]+s0
+[ ]+[0-9a-f]+:[ ]+9fe1[ ]+c.zext.b[ ]+a5
+[ ]+[0-9a-f]+:[ ]+9c65[ ]+c.sext.b[ ]+s0
+[ ]+[0-9a-f]+:[ ]+9fe5[ ]+c.sext.b[ ]+a5
+[ ]+[0-9a-f]+:[ ]+9c69[ ]+c.zext.h[ ]+s0
+[ ]+[0-9a-f]+:[ ]+9fe9[ ]+c.zext.h[ ]+a5
+[ ]+[0-9a-f]+:[ ]+9c6d[ ]+c.sext.h[ ]+s0
+[ ]+[0-9a-f]+:[ ]+9fed[ ]+c.sext.h[ ]+a5
+[ ]+[0-9a-f]+:[ ]+9c71[ ]+c.zext.w[ ]+s0
+[ ]+[0-9a-f]+:[ ]+9ff1[ ]+c.zext.w[ ]+a5
+[ ]+[0-9a-f]+:[ ]+9c75[ ]+c.not[ ]+s0
+[ ]+[0-9a-f]+:[ ]+9ff5[ ]+c.not[ ]+a5
+[ ]+[0-9a-f]+:[ ]+9c5d[ ]+c.mul[ ]+s0,a5
+[ ]+[0-9a-f]+:[ ]+9cd1[ ]+c.mul[ ]+s1,a2
diff --git a/gas/testsuite/gas/riscv/zcb.s b/gas/testsuite/gas/riscv/zcb.s
new file mode 100644
index 0000000..2e70ab2
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zcb.s
@@ -0,0 +1,25 @@
+target:
+ lbu x8,2(x8)
+ c.lbu x8,(x15)
+ lhu x8,2(x8)
+ c.lhu x8,(x15)
+ lh x8,2(x8)
+ c.lh x8,(x15)
+ sb x8,2(x8)
+ c.sb x8,(x15)
+ sh x8,2(x8)
+ c.sh x8,(x15)
+ zext.b x8,x8
+ c.zext.b x15
+ sext.b x8,x8
+ c.sext.b x15
+ zext.h x8,x8
+ c.zext.h x15
+ sext.h x8,x8
+ c.sext.h x15
+ zext.w x8,x8
+ c.zext.w x15
+ not x8,x8
+ c.not x15
+ mul x8,x8,x15
+ c.mul x9,x12
diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
index 90f4415..53f5f20 100644
--- a/include/opcode/riscv-opc.h
+++ b/include/opcode/riscv-opc.h
@@ -2210,6 +2210,31 @@
#define MASK_VSM3C_VI 0xfe00707f
#define MATCH_VSM3ME_VV 0x82002077
#define MASK_VSM3ME_VV 0xfe00707f
+/* Zcb instructions. */
+#define MATCH_C_LBU 0x8000
+#define MASK_C_LBU 0xfc03
+#define MATCH_C_LHU 0x8400
+#define MASK_C_LHU 0xfc43
+#define MATCH_C_LH 0x8440
+#define MASK_C_LH 0xfc43
+#define MATCH_C_SB 0x8800
+#define MASK_C_SB 0xfc03
+#define MATCH_C_SH 0x8c00
+#define MASK_C_SH 0xfc43
+#define MATCH_C_ZEXT_B 0x9c61
+#define MASK_C_ZEXT_B 0xfc7f
+#define MATCH_C_SEXT_B 0x9c65
+#define MASK_C_SEXT_B 0xfc7f
+#define MATCH_C_ZEXT_H 0x9c69
+#define MASK_C_ZEXT_H 0xfc7f
+#define MATCH_C_SEXT_H 0x9c6d
+#define MASK_C_SEXT_H 0xfc7f
+#define MATCH_C_ZEXT_W 0x9c71
+#define MASK_C_ZEXT_W 0xfc7f
+#define MATCH_C_NOT 0x9c75
+#define MASK_C_NOT 0xfc7f
+#define MATCH_C_MUL 0x9c41
+#define MASK_C_MUL 0xfc63
/* Svinval instruction. */
#define MATCH_SINVAL_VMA 0x16000073
#define MASK_SINVAL_VMA 0xfe007fff
@@ -3367,6 +3392,19 @@ DECLARE_INSN(vsm4r_vv, MATCH_VSM4R_VV, MASK_VSM4R_VV)
/* Zvksh instructions. */
DECLARE_INSN(vsm3c_vi, MATCH_VSM3C_VI, MASK_VSM3C_VI)
DECLARE_INSN(vsm3me_vv, MATCH_VSM3ME_VV, MASK_VSM3ME_VV)
+/* Zcb instructions. */
+DECLARE_INSN(c_sext_b, MATCH_C_SEXT_B, MASK_C_SEXT_B)
+DECLARE_INSN(c_sext_h, MATCH_C_SEXT_H, MASK_C_SEXT_H)
+DECLARE_INSN(c_zext_b, MATCH_C_ZEXT_B, MASK_C_ZEXT_B)
+DECLARE_INSN(c_zext_h, MATCH_C_ZEXT_H, MASK_C_ZEXT_H)
+DECLARE_INSN(c_zext_w, MATCH_C_ZEXT_W, MASK_C_ZEXT_W)
+DECLARE_INSN(c_mul, MATCH_C_MUL, MASK_C_MUL)
+DECLARE_INSN(c_not, MATCH_C_NOT, MASK_C_NOT)
+DECLARE_INSN(c_lbu, MATCH_C_LBU, MASK_C_LBU)
+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)
/* 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 739d6da..808f365 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -108,6 +108,10 @@ static inline unsigned int riscv_insn_length (insn_t insn)
(RV_X(x, 20, 10))
#define EXTRACT_RVV_VC_IMM(x) \
(RV_X(x, 20, 11))
+#define EXTRACT_ZCB_BYTE_UIMM(x) \
+ (RV_X(x, 6, 1) | (RV_X(x, 5, 1) << 1))
+#define EXTRACT_ZCB_HALFWORD_UIMM(x) \
+ (RV_X(x, 5, 1) << 1)
#define ENCODE_ITYPE_IMM(x) \
(RV_X(x, 0, 12) << 20)
@@ -155,6 +159,10 @@ static inline unsigned int riscv_insn_length (insn_t insn)
(RV_X(x, 0, 11) << 20)
#define ENCODE_RVV_VI_UIMM6(x) \
(RV_X(x, 0, 5) << 15 | RV_X(x, 5, 1) << 26)
+#define ENCODE_ZCB_BYTE_UIMM(x) \
+ ((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 VALID_ITYPE_IMM(x) (EXTRACT_ITYPE_IMM(ENCODE_ITYPE_IMM(x)) == (x))
#define VALID_STYPE_IMM(x) (EXTRACT_STYPE_IMM(ENCODE_STYPE_IMM(x)) == (x))
@@ -180,6 +188,8 @@ static inline unsigned int riscv_insn_length (insn_t insn)
#define VALID_CJTYPE_IMM(x) (EXTRACT_CJTYPE_IMM(ENCODE_CJTYPE_IMM(x)) == (x))
#define VALID_RVV_VB_IMM(x) (EXTRACT_RVV_VB_IMM(ENCODE_RVV_VB_IMM(x)) == (x))
#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 RISCV_RTYPE(insn, rd, rs1, rs2) \
((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2))
@@ -421,6 +431,10 @@ enum riscv_insn_class
INSN_CLASS_ZVKNHA_OR_ZVKNHB,
INSN_CLASS_ZVKSED,
INSN_CLASS_ZVKSH,
+ INSN_CLASS_ZCB,
+ INSN_CLASS_ZCB_AND_ZBA,
+ INSN_CLASS_ZCB_AND_ZBB,
+ INSN_CLASS_ZCB_AND_ZMMUL,
INSN_CLASS_SVINVAL,
INSN_CLASS_ZICBOM,
INSN_CLASS_ZICBOP,
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 827d9b6..2826248 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -614,6 +614,20 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
goto undefined_modifier;
}
break;
+ case 'c': /* Zcb extension 16 bits length instruction fields. */
+ switch (*++oparg)
+ {
+ case 'b':
+ print (info->stream, dis_style_immediate, "%d",
+ (int)EXTRACT_ZCB_BYTE_UIMM (l));
+ break;
+ case 'h':
+ print (info->stream, dis_style_immediate, "%d",
+ (int)EXTRACT_ZCB_HALFWORD_UIMM (l));
+ break;
+ default: break;
+ }
+ break;
default:
goto undefined_modifier;
}
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index 533e3f4..6a85473 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -380,12 +380,14 @@ const struct riscv_opcode riscv_opcodes[] =
{"mv", 0, INSN_CLASS_I, "d,s", MATCH_ADDI, MASK_ADDI|MASK_IMM, match_opcode, INSN_ALIAS },
{"move", 0, INSN_CLASS_C, "d,CV", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS },
{"move", 0, INSN_CLASS_I, "d,s", MATCH_ADDI, MASK_ADDI|MASK_IMM, match_opcode, INSN_ALIAS },
+{"zext.b", 0, INSN_CLASS_ZCB, "Cs,Cw", MATCH_C_ZEXT_B, MASK_C_ZEXT_B, match_opcode, INSN_ALIAS },
{"zext.b", 0, INSN_CLASS_I, "d,s", MATCH_ANDI|ENCODE_ITYPE_IMM (255), MASK_ANDI | MASK_IMM, match_opcode, INSN_ALIAS },
{"and", 0, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_AND, MASK_C_AND, match_opcode, INSN_ALIAS },
{"and", 0, INSN_CLASS_C, "Cs,Ct,Cw", MATCH_C_AND, MASK_C_AND, match_opcode, INSN_ALIAS },
{"and", 0, INSN_CLASS_C, "Cs,Cw,Co", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, INSN_ALIAS },
{"and", 0, INSN_CLASS_I, "d,s,t", MATCH_AND, MASK_AND, match_opcode, 0 },
{"and", 0, INSN_CLASS_I, "d,s,j", MATCH_ANDI, MASK_ANDI, match_opcode, INSN_ALIAS },
+{"andi", 0, INSN_CLASS_ZCB, "Cs,Cw,Wcf",MATCH_C_ZEXT_B, MASK_C_ZEXT_B, match_opcode, INSN_ALIAS },
{"andi", 0, INSN_CLASS_C, "Cs,Cw,Co", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, INSN_ALIAS },
{"andi", 0, INSN_CLASS_I, "d,s,j", MATCH_ANDI, MASK_ANDI, match_opcode, 0 },
{"beqz", 0, INSN_CLASS_C, "Cs,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, INSN_ALIAS|INSN_CONDBRANCH },
@@ -449,16 +451,20 @@ const struct riscv_opcode riscv_opcodes[] =
{"sub", 0, INSN_CLASS_I, "d,s,t", MATCH_SUB, MASK_SUB, match_opcode, 0 },
{"lb", 0, INSN_CLASS_I, "d,o(s)", MATCH_LB, MASK_LB, match_opcode, INSN_DREF|INSN_1_BYTE },
{"lb", 0, INSN_CLASS_I, "d,A", 0, (int) M_LB, match_never, INSN_MACRO },
+{"lbu", 0, INSN_CLASS_ZCB, "Ct,Wcb(Cs)", MATCH_C_LBU, MASK_C_LBU, match_opcode, INSN_ALIAS|INSN_DREF|INSN_1_BYTE },
{"lbu", 0, INSN_CLASS_I, "d,o(s)", MATCH_LBU, MASK_LBU, match_opcode, INSN_DREF|INSN_1_BYTE },
{"lbu", 0, INSN_CLASS_I, "d,A", 0, (int) M_LBU, match_never, INSN_MACRO },
+{"lh", 0, INSN_CLASS_ZCB, "Ct,Wch(Cs)", MATCH_C_LH, MASK_C_LH, match_opcode, INSN_ALIAS|INSN_DREF|INSN_2_BYTE },
{"lh", 0, INSN_CLASS_I, "d,o(s)", MATCH_LH, MASK_LH, match_opcode, INSN_DREF|INSN_2_BYTE },
{"lh", 0, INSN_CLASS_I, "d,A", 0, (int) M_LH, match_never, INSN_MACRO },
+{"lhu", 0, INSN_CLASS_ZCB, "Ct,Wch(Cs)", MATCH_C_LHU, MASK_C_LHU, match_opcode, INSN_ALIAS|INSN_DREF|INSN_2_BYTE },
{"lhu", 0, INSN_CLASS_I, "d,o(s)", MATCH_LHU, MASK_LHU, match_opcode, INSN_DREF|INSN_2_BYTE },
{"lhu", 0, INSN_CLASS_I, "d,A", 0, (int) M_LHU, match_never, INSN_MACRO },
{"lw", 0, INSN_CLASS_C, "d,Cm(Cc)", MATCH_C_LWSP, MASK_C_LWSP, match_rd_nonzero, INSN_ALIAS|INSN_DREF|INSN_4_BYTE },
{"lw", 0, INSN_CLASS_C, "Ct,Ck(Cs)", MATCH_C_LW, MASK_C_LW, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE },
{"lw", 0, INSN_CLASS_I, "d,o(s)", MATCH_LW, MASK_LW, match_opcode, INSN_DREF|INSN_4_BYTE },
{"lw", 0, INSN_CLASS_I, "d,A", 0, (int) M_LW, match_never, INSN_MACRO },
+{"not", 0, INSN_CLASS_ZCB, "Cs,Cw", MATCH_C_NOT, MASK_C_NOT, match_opcode, INSN_ALIAS },
{"not", 0, INSN_CLASS_I, "d,s", MATCH_XORI|MASK_IMM, MASK_XORI|MASK_IMM, match_opcode, INSN_ALIAS },
{"or", 0, INSN_CLASS_I, "d,s,j", MATCH_ORI, MASK_ORI, match_opcode, INSN_ALIAS },
{"or", 0, INSN_CLASS_C, "Cs,Cw,Ct", MATCH_C_OR, MASK_C_OR, match_opcode, INSN_ALIAS },
@@ -478,8 +484,10 @@ const struct riscv_opcode riscv_opcodes[] =
{"sltu", 0, INSN_CLASS_I, "d,s,j", MATCH_SLTIU, MASK_SLTIU, match_opcode, INSN_ALIAS },
{"sgt", 0, INSN_CLASS_I, "d,t,s", MATCH_SLT, MASK_SLT, match_opcode, INSN_ALIAS },
{"sgtu", 0, INSN_CLASS_I, "d,t,s", MATCH_SLTU, MASK_SLTU, match_opcode, INSN_ALIAS },
+{"sb", 0, INSN_CLASS_ZCB, "Ct,Wcb(Cs)", MATCH_C_SB, MASK_C_SB, match_opcode, INSN_DREF|INSN_1_BYTE|INSN_ALIAS },
{"sb", 0, INSN_CLASS_I, "t,q(s)", MATCH_SB, MASK_SB, match_opcode, INSN_DREF|INSN_1_BYTE },
{"sb", 0, INSN_CLASS_I, "t,A,s", 0, (int) M_SB, match_never, INSN_MACRO },
+{"sh", 0, INSN_CLASS_ZCB, "Ct,Wch(Cs)", MATCH_C_SH, MASK_C_SH, match_opcode, INSN_DREF|INSN_2_BYTE|INSN_ALIAS },
{"sh", 0, INSN_CLASS_I, "t,q(s)", MATCH_SH, MASK_SH, match_opcode, INSN_DREF|INSN_2_BYTE },
{"sh", 0, INSN_CLASS_I, "t,A,s", 0, (int) M_SH, match_never, INSN_MACRO },
{"sw", 0, INSN_CLASS_C, "CV,CM(Cc)", MATCH_C_SWSP, MASK_C_SWSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE },
@@ -626,6 +634,7 @@ const struct riscv_opcode riscv_opcodes[] =
{"amominu.d.aqrl", 64, INSN_CLASS_A, "d,t,0(s)", MATCH_AMOMINU_D|MASK_AQRL, MASK_AMOMINU_D|MASK_AQRL, match_opcode, INSN_DREF|INSN_8_BYTE },
/* Multiply/Divide instruction subset. */
+{"mul", 0, INSN_CLASS_ZCB_AND_ZMMUL, "Cs,Cw,Ct", MATCH_C_MUL, MASK_C_MUL, match_opcode, INSN_ALIAS },
{"mul", 0, INSN_CLASS_ZMMUL, "d,s,t", MATCH_MUL, MASK_MUL, match_opcode, 0 },
{"mulh", 0, INSN_CLASS_ZMMUL, "d,s,t", MATCH_MULH, MASK_MULH, match_opcode, 0 },
{"mulhu", 0, INSN_CLASS_ZMMUL, "d,s,t", MATCH_MULHU, MASK_MULHU, match_opcode, 0 },
@@ -1016,10 +1025,13 @@ const struct riscv_opcode riscv_opcodes[] =
{"max", 0, INSN_CLASS_ZBB, "d,s,t", MATCH_MAX, MASK_MAX, match_opcode, 0 },
{"minu", 0, INSN_CLASS_ZBB, "d,s,t", MATCH_MINU, MASK_MINU, match_opcode, 0 },
{"maxu", 0, INSN_CLASS_ZBB, "d,s,t", MATCH_MAXU, MASK_MAXU, match_opcode, 0 },
+{"sext.b", 0, INSN_CLASS_ZCB_AND_ZBB, "Cs,Cw", MATCH_C_SEXT_B, MASK_C_SEXT_B, match_opcode, INSN_ALIAS },
{"sext.b", 0, INSN_CLASS_ZBB, "d,s", MATCH_SEXT_B, MASK_SEXT_B, match_opcode, 0 },
{"sext.b", 0, INSN_CLASS_I, "d,s", 0, (int) M_SEXTB, match_never, INSN_MACRO },
+{"sext.h", 0, INSN_CLASS_ZCB_AND_ZBB, "Cs,Cw", MATCH_C_SEXT_H, MASK_C_SEXT_H, match_opcode, INSN_ALIAS },
{"sext.h", 0, INSN_CLASS_ZBB, "d,s", MATCH_SEXT_H, MASK_SEXT_H, match_opcode, 0 },
{"sext.h", 0, INSN_CLASS_I, "d,s", 0, (int) M_SEXTH, match_never, INSN_MACRO },
+{"zext.h", 0, INSN_CLASS_ZCB_AND_ZBB, "Cs,Cw", MATCH_C_ZEXT_H, MASK_C_ZEXT_H, match_opcode, INSN_ALIAS },
{"zext.h", 32, INSN_CLASS_ZBB, "d,s", MATCH_PACK, MASK_PACK | MASK_RS2, match_opcode, 0 },
{"zext.h", 64, INSN_CLASS_ZBB, "d,s", MATCH_PACKW, MASK_PACKW | MASK_RS2, match_opcode, 0 },
{"zext.h", 0, INSN_CLASS_I, "d,s", 0, (int) M_ZEXTH, match_never, INSN_MACRO },
@@ -1055,6 +1067,7 @@ const struct riscv_opcode riscv_opcodes[] =
{"sh1add.uw", 64, INSN_CLASS_ZBA, "d,s,t", MATCH_SH1ADD_UW, MASK_SH1ADD_UW, match_opcode, 0 },
{"sh2add.uw", 64, INSN_CLASS_ZBA, "d,s,t", MATCH_SH2ADD_UW, MASK_SH2ADD_UW, match_opcode, 0 },
{"sh3add.uw", 64, INSN_CLASS_ZBA, "d,s,t", MATCH_SH3ADD_UW, MASK_SH3ADD_UW, match_opcode, 0 },
+{"zext.w", 64, INSN_CLASS_ZCB_AND_ZBA, "Cs,Cw", MATCH_C_ZEXT_W, MASK_C_ZEXT_W, match_opcode, INSN_ALIAS },
{"zext.w", 64, INSN_CLASS_ZBA, "d,s", MATCH_ADD_UW, MASK_ADD_UW | MASK_RS2, match_opcode, INSN_ALIAS },
{"zext.w", 64, INSN_CLASS_I, "d,s", 0, (int) M_ZEXTW, match_never, INSN_MACRO },
{"add.uw", 64, INSN_CLASS_ZBA, "d,s,t", MATCH_ADD_UW, MASK_ADD_UW, match_opcode, 0 },
@@ -1939,6 +1952,21 @@ const struct riscv_opcode riscv_opcodes[] =
{"vsm3c.vi", 0, INSN_CLASS_ZVKSH, "Vd,Vt,Vj", MATCH_VSM3C_VI, MASK_VSM3C_VI, match_opcode, 0},
{"vsm3me.vv", 0, INSN_CLASS_ZVKSH, "Vd,Vt,Vs", MATCH_VSM3ME_VV, MASK_VSM3ME_VV, match_opcode, 0},
+/* ZCB instructions. */
+{"c.lbu", 0, INSN_CLASS_ZCB, "Ct,Wcb(Cs)", MATCH_C_LBU, MASK_C_LBU, match_opcode, INSN_DREF|INSN_1_BYTE },
+{"c.lhu", 0, INSN_CLASS_ZCB, "Ct,Wch(Cs)", MATCH_C_LHU, MASK_C_LHU, match_opcode, INSN_DREF|INSN_2_BYTE },
+{"c.lh", 0, INSN_CLASS_ZCB, "Ct,Wch(Cs)", MATCH_C_LH, MASK_C_LH, match_opcode, INSN_DREF|INSN_2_BYTE },
+{"c.sb", 0, INSN_CLASS_ZCB, "Ct,Wcb(Cs)", MATCH_C_SB, MASK_C_SB, match_opcode, INSN_DREF|INSN_1_BYTE },
+{"c.sh", 0, INSN_CLASS_ZCB, "Ct,Wch(Cs)", MATCH_C_SH, MASK_C_SH, match_opcode, INSN_DREF|INSN_2_BYTE },
+{"c.not", 0, INSN_CLASS_ZCB, "Cs", MATCH_C_NOT, MASK_C_NOT, match_opcode, 0 },
+{"c.mul", 0, INSN_CLASS_ZCB_AND_ZMMUL, "Cs,Ct", MATCH_C_MUL, MASK_C_MUL, match_opcode, 0 },
+{"c.sext.b", 0, INSN_CLASS_ZCB_AND_ZBB, "Cs", MATCH_C_SEXT_B, MASK_C_SEXT_B, match_opcode, 0 },
+{"c.sext.h", 0, INSN_CLASS_ZCB_AND_ZBB, "Cs", MATCH_C_SEXT_H, MASK_C_SEXT_H, match_opcode, 0 },
+{"c.zext.h", 0, INSN_CLASS_ZCB_AND_ZBB, "Cs", MATCH_C_ZEXT_H, MASK_C_ZEXT_H, match_opcode, 0 },
+{"c.zext.w", 64, INSN_CLASS_ZCB_AND_ZBA, "Cs", MATCH_C_ZEXT_W, MASK_C_ZEXT_W, match_opcode, 0 },
+{"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 },
+
/* Supervisor instructions. */
{"csrr", 0, INSN_CLASS_ZICSR, "d,E", MATCH_CSRRS, MASK_CSRRS|MASK_RS1, match_opcode, INSN_ALIAS },
{"csrw", 0, INSN_CLASS_ZICSR, "E,s", MATCH_CSRRW, MASK_CSRRW|MASK_RD, match_opcode, INSN_ALIAS },