[PATCH] RISC-V: Add support for XW extension on some WCH cores
Andy Lin
andylinpersonal@gmail.com
Sun Nov 23 19:47:58 GMT 2025
This patch implements the xw extension found on some QingKe cores from
QinHeng (WCH). BTW, there is one divergence between this patch and vendor's
toolchain (based on older binutils 2.38.0) when using `norvc', `rvc' and
`arch' directives:
Vendor's toolchain:
`-march' with `_xw':
After `.option rvc', xw opcodes are available implicitly.
`-march' without `_xw':
After `.option rvc', xw opcodes are NOT available, even if we explicitly
add the `.option arch,+xw'.
This patch:
`-march' with or without `_xw':
After `.option rvc', xw opcodes are not available implicitly, but user
can add `.option arch,+xw' to enable it. This behavior is consistent
with other Zc* extensions not covered by the existing C extension.
[1] Specs: http://web.archive.org/web/20251121133229/https://discourse.llvm.org/t/rfc-supporting-wch-qingke-xw-compressed-opcodes/79392/12
[2] LLVM's merged patch: https://github.com/llvm/llvm-project/pull/97925/files
bfd/ChangeLog:
* elfxx-riscv.c (riscv_multi_subset_supports): Add support for
XW extension.
* (riscv_multi_subset_supports_ext): Likewise.
* (riscv_update_subset_norvc): XW should not be emitted
under `norvc' mode.
gas/ChangeLog:
* config/tc-riscv.c (riscv_ip): Add XW to assembler.
* config/tc-riscv.c (validate_riscv_insn): Add XW.
* doc/c-riscv.texi: Note XW as an additional ISA extension for some
WCH's QingKe RISC-V MCU cores.
* testsuite/gas/riscv/march-help.l: Add '-xw' string.
* testsuite/gas/riscv/x-wch-qk-xw.d: New tests.
* testsuite/gas/riscv/x-wch-qk-xw.s: Likewise.
* testsuite/gas/riscv/x-wch-qk-xw-fail.d: Likewise.
* testsuite/gas/riscv/x-wch-qk-xw-fail.l: Likewise.
* testsuite/gas/riscv/x-wch-qk-xw-fail.s: Likewise.
* testsuite/gas/riscv/x-wch-qk-xw-norvc.d: New test for `norvc'.
* testsuite/gas/riscv/x-wch-qk-xw-norvc.s: Likewise.
include/ChangeLog:
* opcode/riscv-opc.h: Add MATCH and MASK opcode macros for XW.
* opcode/riscv.h (riscv_insn_class): Add INSN_CLASS_XWCH_QK.
opcodes/ChangeLog:
* riscv-opc.c (riscv_opcodes): Add XW opcodes and aliases.
* riscv-dis.c (print_insn_args): Add XW opcode to disassembler.
Signed-off-by: Andy Lin <andylinpersonal@gmail.com>
---
bfd/ChangeLog | 8 ++
bfd/elfxx-riscv.c | 13 +++-
gas/ChangeLog | 15 ++++
gas/NEWS | 7 +-
gas/config/tc-riscv.c | 62 ++++++++++++++-
gas/doc/c-riscv.texi | 6 ++
gas/testsuite/gas/riscv/march-help.l | 1 +
gas/testsuite/gas/riscv/x-wch-qk-xw-fail.d | 3 +
gas/testsuite/gas/riscv/x-wch-qk-xw-fail.l | 33 ++++++++
gas/testsuite/gas/riscv/x-wch-qk-xw-fail.s | 39 ++++++++++
gas/testsuite/gas/riscv/x-wch-qk-xw-norvc.d | 26 +++++++
gas/testsuite/gas/riscv/x-wch-qk-xw-norvc.s | 20 +++++
gas/testsuite/gas/riscv/x-wch-qk-xw.d | 81 +++++++++++++++++++
gas/testsuite/gas/riscv/x-wch-qk-xw.s | 86 +++++++++++++++++++++
include/ChangeLog | 5 ++
include/opcode/riscv-opc.h | 26 +++++++
include/opcode/riscv.h | 24 ++++++
opcodes/ChangeLog | 5 ++
opcodes/riscv-dis.c | 23 ++++++
opcodes/riscv-opc.c | 18 +++++
20 files changed, 497 insertions(+), 4 deletions(-)
create mode 100644 gas/testsuite/gas/riscv/x-wch-qk-xw-fail.d
create mode 100644 gas/testsuite/gas/riscv/x-wch-qk-xw-fail.l
create mode 100644 gas/testsuite/gas/riscv/x-wch-qk-xw-fail.s
create mode 100644 gas/testsuite/gas/riscv/x-wch-qk-xw-norvc.d
create mode 100644 gas/testsuite/gas/riscv/x-wch-qk-xw-norvc.s
create mode 100644 gas/testsuite/gas/riscv/x-wch-qk-xw.d
create mode 100644 gas/testsuite/gas/riscv/x-wch-qk-xw.s
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1bd99a9b042..c41ae349f71 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,11 @@
+2025-11-23 Andy Lin <andylinpersonal@gmail.com>
+
+ * elfxx-riscv.c (riscv_multi_subset_supports): Add support for
+ XW extension.
+ * (riscv_multi_subset_supports_ext): Likewise.
+ * (riscv_update_subset_norvc): XW should not be emitted
+ under `norvc' mode.
+
2025-09-16 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* config.bfd <powerpc-*-solaris2*>: Remove.
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 3b92fbed5f0..5c2948b5b93 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1641,6 +1641,7 @@ static const struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
{"xmipscmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"xmipsexectl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"xmipslsp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xw", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{NULL, 0, 0, 0, 0}
};
@@ -2291,6 +2292,12 @@ riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
xlen);
no_conflict = false;
}
+ if (riscv_subset_supports (rps, "xw")
+ && (riscv_subset_supports (rps, "d") || riscv_subset_supports (rps, "zcb")))
+ {
+ rps->error_handler (_("xw' is conflict with the `d/zcb' extension"));
+ no_conflict = false;
+ }
bool support_zve = false;
bool support_zvl = false;
@@ -2776,7 +2783,7 @@ riscv_update_subset_norvc (riscv_parse_subset_t *rps)
{
return riscv_update_subset1 (rps, rps->subset_list->head,
"-c,-zca,-zcd,-zcf,-zcb,-zce,-zcmp,-zcmt,"
- "-zcmop,-zclsd");
+ "-zcmop,-zclsd,-xw");
}
/* Check if the FEATURE subset is supported or not in the subset list.
@@ -3059,6 +3066,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
return riscv_subset_supports (rps, "xmipsexectl");
case INSN_CLASS_XMIPSLSP:
return riscv_subset_supports (rps, "xmipslsp");
+ case INSN_CLASS_XWCH_QK:
+ return riscv_subset_supports (rps, "xw");
default:
rps->error_handler
(_("internal: unreachable INSN_CLASS_*"));
@@ -3362,6 +3371,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
return "xsfvqmaccdod";
case INSN_CLASS_XSFVFNRCLIPXFQF:
return "xsfvfnrclipxfqf";
+ case INSN_CLASS_XWCH_QK:
+ return "xw";
default:
rps->error_handler
(_("internal: unreachable INSN_CLASS_*"));
diff --git a/gas/ChangeLog b/gas/ChangeLog
index dd7691593f1..ff10bca004b 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,18 @@
+2025-11-23 Andy Lin <andylinpersonal@gmail.com>
+
+ * config/tc-riscv.c (riscv_ip): Add XW to assembler.
+ * config/tc-riscv.c (validate_riscv_insn): Add XW.
+ * doc/c-riscv.texi: Note XW as an additional ISA extension for some
+ WCH's QingKe RISC-V MCU cores.
+ * testsuite/gas/riscv/march-help.l: Add '-xw' string.
+ * testsuite/gas/riscv/x-wch-qk-xw.d: New tests.
+ * testsuite/gas/riscv/x-wch-qk-xw.s: Likewise.
+ * testsuite/gas/riscv/x-wch-qk-xw-fail.d: Likewise.
+ * testsuite/gas/riscv/x-wch-qk-xw-fail.l: Likewise.
+ * testsuite/gas/riscv/x-wch-qk-xw-fail.s: Likewise.
+ * testsuite/gas/riscv/x-wch-qk-xw-norvc.d: New test for `norvc'.
+ * testsuite/gas/riscv/x-wch-qk-xw-norvc.s: Likewise.
+
2025-09-16 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* NEWS: Mention Solaris/PowerPC removal.
diff --git a/gas/NEWS b/gas/NEWS
index 4bd3d747aa5..ffeeb93aad8 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,8 @@
-*- text -*-
+* Add support for RISC-V vendor extension:
+ QinHeng (WCH): xw v1.0.
+
* Emit an SFrame FRE with zero offsets to convey an undefined return address
in the SFrame stack trace format.
@@ -133,7 +136,7 @@ Changes in 2.43:
* Add a .base64 directive to the assembler which allows base64 encoded
binary data to be provided as strings.
-
+
* Add support for 'armv9.5-a' for -march in AArch64 GAS.
* In x86 Intel syntax undue mnemonic suffixes are now warned about. This is
@@ -143,7 +146,7 @@ Changes in 2.43:
the syntax \+ to access the number of times a given macro has been executed.
This is similar to the already existing \@ syntax, except that the count is
maintained on a per-macro basis.
-
+
* Support the NF feature in Intel APX.
* Remove KEYLOCKER and SHA promotions from EVEX MAP4.
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index df60c206b82..28bfc87a7f8 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1771,6 +1771,17 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
goto unknown_validate_operand;
}
break;
+ case 'w': /* Vendor-specific (Qinheng QingKe Xw) operands. */
+ switch(*++oparg)
+ {
+ case 'b': used_bits |= ENCODE_WCH_QK_UIMM5 (-1); break; /* Xwb */
+ case '6': used_bits |= ENCODE_WCH_QK_UIMM6_LSB0 (-1); break; /* Xw6 */
+ case '4': used_bits |= ENCODE_WCH_QK_UIMM4 (-1); break; /* Xw4 */
+ case '5': used_bits |= ENCODE_WCH_QK_UIMM5_LSB0 (-1); break; /* Xw5 */
+ default:
+ goto unknown_validate_operand;
+ }
+ break;
default:
goto unknown_validate_operand;
}
@@ -4287,6 +4298,54 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
}
break;
+ case 'w': /* Vendor-specific (Qinheng QingKe Xw) operands. */
+ switch (*++oparg)
+ {
+ case 'b': /* Xwb: uimm5 0-31. */
+ /* For qk.c.lbu and qk.c.sb. */
+ 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_WCH_QK_UIMM5 ((valueT) imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_WCH_QK_UIMM5(imm_expr->X_add_number);
+ goto rvc_imm_done;
+ case '6': /* Xw6: uimm6_lsb0 0-62. Must be multiple of 2. */
+ /* For qk.c.lhu and qk.c.sh. */
+ 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_WCH_QK_UIMM6_LSB0 ((valueT) imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_WCH_QK_UIMM6_LSB0(imm_expr->X_add_number);
+ goto rvc_imm_done;
+ case '4': /* Xw4: uimm4 0-15. */
+ /* For qk.c.lbusp and qk.c.sbsp. */
+ 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_WCH_QK_UIMM4 ((valueT) imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_WCH_QK_UIMM4(imm_expr->X_add_number);
+ goto rvc_imm_done;
+ case '5': /* Xw5: uimm5_lsb0 0-30. Must be multiple of 2. */
+ /* For qk.c.lhusp and qk.c.shsp. */
+ 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_WCH_QK_UIMM5_LSB0 ((valueT) imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_WCH_QK_UIMM5_LSB0(imm_expr->X_add_number);
+ goto rvc_imm_done;
+ default:
+ goto unknown_riscv_ip_operand;
+ }
+ break;
+
default:
goto unknown_riscv_ip_operand;
}
@@ -5109,7 +5168,8 @@ s_riscv_option (int x ATTRIBUTE_UNUSED)
riscv_arch_str (xlen, riscv_rps_as.subset_list, true/* update */);
riscv_set_rvc (riscv_subset_supports (&riscv_rps_as, "c")
- || riscv_subset_supports (&riscv_rps_as, "zca"));
+ || riscv_subset_supports (&riscv_rps_as, "zca")
+ || riscv_subset_supports (&riscv_rps_as, "xw"));
if (riscv_subset_supports (&riscv_rps_as, "ztso"))
riscv_set_tso ();
diff --git a/gas/doc/c-riscv.texi b/gas/doc/c-riscv.texi
index ea4be32a8ff..d843bfd9d50 100644
--- a/gas/doc/c-riscv.texi
+++ b/gas/doc/c-riscv.texi
@@ -918,4 +918,10 @@ The XMipsSlsp extension provides instructions mips.ldp, mips.lwp, mips.sdp and m
It is documented in @url{https://mips.com/wp-content/uploads/2025/03/P8700-F_Programmers_Reference_Manual_Rev1.82_3-19-2025.pdf}.
+@item XW
+
+The XW extension provide additional compressed opcodes present in some QingKe cores from Nanjing Qinheng Microelectronics Co., Ltd. (WCH).
+
+It is documented in @url{http://web.archive.org/web/20251121133229/https://discourse.llvm.org/t/rfc-supporting-wch-qingke-xw-compressed-opcodes/79392/12}
+
@end table
diff --git a/gas/testsuite/gas/riscv/march-help.l b/gas/testsuite/gas/riscv/march-help.l
index 0ce2f896735..aa1632ef606 100644
--- a/gas/testsuite/gas/riscv/march-help.l
+++ b/gas/testsuite/gas/riscv/march-help.l
@@ -186,3 +186,4 @@ All available -march extensions for RISC-V:
xmipscmov 1.0
xmipsexectl 1.0
xmipslsp 1.0
+ xw 1.0
diff --git a/gas/testsuite/gas/riscv/x-wch-qk-xw-fail.d b/gas/testsuite/gas/riscv/x-wch-qk-xw-fail.d
new file mode 100644
index 00000000000..322c943e00b
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wch-qk-xw-fail.d
@@ -0,0 +1,3 @@
+#as: -march=rv32ic_xw
+#source: x-wch-qk-xw-fail.s
+#error_output: x-wch-qk-xw-fail.l
diff --git a/gas/testsuite/gas/riscv/x-wch-qk-xw-fail.l b/gas/testsuite/gas/riscv/x-wch-qk-xw-fail.l
new file mode 100644
index 00000000000..8c17e84dc24
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wch-qk-xw-fail.l
@@ -0,0 +1,33 @@
+.*: Assembler messages:
+.*: Error: unrecognized opcode `wchqk.c.lbu x8,0\(x8\)', extension `xw' required
+.*: Error: unrecognized opcode `wchqk.c.sb x8,0\(x8\)', extension `xw' required
+.*: Error: unrecognized opcode `wchqk.c.sb x8,-2\(x8\)', extension `xw' required
+.*: Error: unrecognized opcode `wchqk.c.sb x8,0\(x7\)', extension `xw' required
+.*: Error: illegal operands `wchqk.c.sb x7,0\(x8\)'
+.*: Error: illegal operands `wchqk.c.sb x7,-2\(x20\)'
+.*: Error: illegal operands `wchqk.c.lhu x8,1\(x8\)'
+.*: Error: illegal operands `wchqk.c.lhu x8,64\(x8\)'
+.*: Error: illegal operands `wchqk.c.sh x8,1\(x8\)'
+.*: Error: illegal operands `wchqk.c.sh x8,64\(x8\)'
+.*: Error: illegal operands `wchqk.c.sh x8,-1\(x8\)'
+.*: Error: illegal operands `wchqk.c.sh x8,-2\(x8\)'
+.*: Error: illegal operands `wchqk.c.sh x8,0\(x7\)'
+.*: Error: illegal operands `wchqk.c.sh x7,0\(x8\)'
+.*: Error: illegal operands `wchqk.c.sh x7,-2\(x20\)'
+.*: Error: illegal operands `wchqk.c.lbusp x8,0\(x8\)'
+.*: Error: illegal operands `wchqk.c.lbusp x8,32\(sp\)'
+.*: Error: illegal operands `wchqk.c.sbsp x8,0\(x8\)'
+.*: Error: illegal operands `wchqk.c.sbsp x8,32\(sp\)'
+.*: Error: illegal operands `wchqk.c.sbsp x8,-2\(sp\)'
+.*: Error: illegal operands `wchqk.c.sbsp x7,0\(sp\)'
+.*: Error: illegal operands `wchqk.c.sbsp x7,-2\(sp\)'
+.*: Error: illegal operands `wchqk.c.lhusp x8,0\(x8\)'
+.*: Error: illegal operands `wchqk.c.lhusp x8,1\(sp\)'
+.*: Error: illegal operands `wchqk.c.lhusp x8,32\(sp\)'
+.*: Error: illegal operands `wchqk.c.shsp x8,0\(x8\)'
+.*: Error: illegal operands `wchqk.c.shsp x8,1\(sp\)'
+.*: Error: illegal operands `wchqk.c.shsp x8,32\(sp\)'
+.*: Error: illegal operands `wchqk.c.shsp x8,-1\(sp\)'
+.*: Error: illegal operands `wchqk.c.shsp x8,-2\(sp\)'
+.*: Error: illegal operands `wchqk.c.shsp x7,0\(sp\)'
+.*: Error: illegal operands `wchqk.c.shsp x7,-2\(sp\)'
diff --git a/gas/testsuite/gas/riscv/x-wch-qk-xw-fail.s b/gas/testsuite/gas/riscv/x-wch-qk-xw-fail.s
new file mode 100644
index 00000000000..0f2323ffe0c
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wch-qk-xw-fail.s
@@ -0,0 +1,39 @@
+target:
+.option norvc
+ wchqk.c.lbu x8, 0(x8)
+ wchqk.c.sb x8, 0(x8)
+.option rvc
+ wchqk.c.sb x8, -2(x8)
+ wchqk.c.sb x8, 0(x7)
+.option arch,+xw
+ wchqk.c.sb x7, 0(x8)
+ wchqk.c.sb x7, -2(x20)
+
+ wchqk.c.lhu x8, 1(x8)
+ wchqk.c.lhu x8, 64(x8)
+ wchqk.c.sh x8, 1(x8)
+ wchqk.c.sh x8, 64(x8)
+ wchqk.c.sh x8, -1(x8)
+ wchqk.c.sh x8, -2(x8)
+ wchqk.c.sh x8, 0(x7)
+ wchqk.c.sh x7, 0(x8)
+ wchqk.c.sh x7, -2(x20)
+
+ wchqk.c.lbusp x8, 0(x8)
+ wchqk.c.lbusp x8, 32(sp)
+ wchqk.c.sbsp x8, 0(x8)
+ wchqk.c.sbsp x8, 32(sp)
+ wchqk.c.sbsp x8, -2(sp)
+ wchqk.c.sbsp x7, 0(sp)
+ wchqk.c.sbsp x7, -2(sp)
+
+ wchqk.c.lhusp x8, 0(x8)
+ wchqk.c.lhusp x8, 1(sp)
+ wchqk.c.lhusp x8, 32(sp)
+ wchqk.c.shsp x8, 0(x8)
+ wchqk.c.shsp x8, 1(sp)
+ wchqk.c.shsp x8, 32(sp)
+ wchqk.c.shsp x8, -1(sp)
+ wchqk.c.shsp x8, -2(sp)
+ wchqk.c.shsp x7, 0(sp)
+ wchqk.c.shsp x7, -2(sp)
diff --git a/gas/testsuite/gas/riscv/x-wch-qk-xw-norvc.d b/gas/testsuite/gas/riscv/x-wch-qk-xw-norvc.d
new file mode 100644
index 00000000000..ab6518dc1e7
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wch-qk-xw-norvc.d
@@ -0,0 +1,26 @@
+#as: -march=rv32ic_xw
+#source: x-wch-qk-xw-norvc.s
+#objdump: -d -Mno-aliases
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ ]+[0-9a-f]+:[ ]+30c0[ ]+wchqk.c.lbu[ ]+s0,5\(s1\)
+[ ]+[0-9a-f]+:[ ]+3d60[ ]+wchqk.c.lbu[ ]+s0,31\(a0\)
+[ ]+[0-9a-f]+:[ ]+2000[ ]+wchqk.c.lbu[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+3000[ ]+wchqk.c.lbu[ ]+s0,1\(s0\)
+
+[0-9a-f]+ <norvc>:
+[ ]+[0-9a-f]+:[ ]+0054c403[ ]+lbu[ ]+s0,5\(s1\)
+[ ]+[0-9a-f]+:[ ]+01f54403[ ]+lbu[ ]+s0,31\(a0\)
+
+[0-9a-f]+ <rvc>:
+[ ]+[0-9a-f]+:[ ]+0054c403[ ]+lbu[ ]+s0,5\(s1\)
+[ ]+[0-9a-f]+:[ ]+01f54403[ ]+lbu[ ]+s0,31\(a0\)
+
+[0-9a-f]+ <rvc_xw>:
+[ ]+[0-9a-f]+:[ ]+30c0[ ]+wchqk.c.lbu[ ]+s0,5\(s1\)
+[ ]+[0-9a-f]+:[ ]+3d60[ ]+wchqk.c.lbu[ ]+s0,31\(a0\)
diff --git a/gas/testsuite/gas/riscv/x-wch-qk-xw-norvc.s b/gas/testsuite/gas/riscv/x-wch-qk-xw-norvc.s
new file mode 100644
index 00000000000..73ca3ac9e06
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wch-qk-xw-norvc.s
@@ -0,0 +1,20 @@
+target:
+ lbu s0, 5(s1)
+ lbu s0, 31(a0)
+ wchqk.c.lbu s0, 0(s0)
+ wchqk.c.lbu s0, 1(s0)
+
+norvc:
+.option norvc
+ lbu s0, 5(s1)
+ lbu s0, 31(a0)
+
+rvc:
+.option rvc
+ lbu s0, 5(s1)
+ lbu s0, 31(a0)
+
+rvc_xw:
+.option arch,+xw
+ lbu s0, 5(s1)
+ lbu s0, 31(a0)
diff --git a/gas/testsuite/gas/riscv/x-wch-qk-xw.d b/gas/testsuite/gas/riscv/x-wch-qk-xw.d
new file mode 100644
index 00000000000..510e04f1b47
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wch-qk-xw.d
@@ -0,0 +1,81 @@
+#as: -march=rv32ic_xw
+#source: x-wch-qk-xw.s
+#objdump: -d -Mno-aliases
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <implicit_xw>:
+[ ]+[0-9a-f]+:[ ]+30c0[ ]+wchqk.c.lbu[ ]+s0,5\(s1\)
+[ ]+[0-9a-f]+:[ ]+3d60[ ]+wchqk.c.lbu[ ]+s0,31\(a0\)
+[ ]+[0-9a-f]+:[ ]+2100[ ]+wchqk.c.lbu[ ]+s0,0\(a0\)
+[ ]+[0-9a-f]+:[ ]+00094403[ ]+lbu[ ]+s0,0\(s2\)
+[ ]+[0-9a-f]+:[ ]+02044403[ ]+lbu[ ]+s0,32\(s0\)
+[ ]+[0-9a-f]+:[ ]+b0c0[ ]+wchqk.c.sb[ ]+s0,5\(s1\)
+[ ]+[0-9a-f]+:[ ]+bd60[ ]+wchqk.c.sb[ ]+s0,31\(a0\)
+[ ]+[0-9a-f]+:[ ]+a100[ ]+wchqk.c.sb[ ]+s0,0\(a0\)
+[ ]+[0-9a-f]+:[ ]+00890023[ ]+sb[ ]+s0,0\(s2\)
+[ ]+[0-9a-f]+:[ ]+02840023[ ]+sb[ ]+s0,32\(s0\)
+[ ]+[0-9a-f]+:[ ]+24a2[ ]+wchqk.c.lhu[ ]+s0,10\(s1\)
+[ ]+[0-9a-f]+:[ ]+3d62[ ]+wchqk.c.lhu[ ]+s0,62\(a0\)
+[ ]+[0-9a-f]+:[ ]+2102[ ]+wchqk.c.lhu[ ]+s0,0\(a0\)
+[ ]+[0-9a-f]+:[ ]+00095403[ ]+lhu[ ]+s0,0\(s2\)
+[ ]+[0-9a-f]+:[ ]+00145403[ ]+lhu[ ]+s0,1\(s0\)
+[ ]+[0-9a-f]+:[ ]+04045403[ ]+lhu[ ]+s0,64\(s0\)
+[ ]+[0-9a-f]+:[ ]+a4a2[ ]+wchqk.c.sh[ ]+s0,10\(s1\)
+[ ]+[0-9a-f]+:[ ]+bd62[ ]+wchqk.c.sh[ ]+s0,62\(a0\)
+[ ]+[0-9a-f]+:[ ]+a102[ ]+wchqk.c.sh[ ]+s0,0\(a0\)
+[ ]+[0-9a-f]+:[ ]+00891023[ ]+sh[ ]+s0,0\(s2\)
+[ ]+[0-9a-f]+:[ ]+008410a3[ ]+sh[ ]+s0,1\(s0\)
+[ ]+[0-9a-f]+:[ ]+04841023[ ]+sh[ ]+s0,64\(s0\)
+[ ]+[0-9a-f]+:[ ]+8010[ ]+wchqk.c.lbusp[ ]+a2,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8390[ ]+wchqk.c.lbusp[ ]+a2,7\(sp\)
+[ ]+[0-9a-f]+:[ ]+8790[ ]+wchqk.c.lbusp[ ]+a2,15\(sp\)
+[ ]+[0-9a-f]+:[ ]+00014903[ ]+lbu[ ]+s2,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+01014403[ ]+lbu[ ]+s0,16\(sp\)
+[ ]+[0-9a-f]+:[ ]+8050[ ]+wchqk.c.sbsp[ ]+a2,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+83d0[ ]+wchqk.c.sbsp[ ]+a2,7\(sp\)
+[ ]+[0-9a-f]+:[ ]+87d0[ ]+wchqk.c.sbsp[ ]+a2,15\(sp\)
+[ ]+[0-9a-f]+:[ ]+01210023[ ]+sb[ ]+s2,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+00810823[ ]+sb[ ]+s0,16\(sp\)
+[ ]+[0-9a-f]+:[ ]+8030[ ]+wchqk.c.lhusp[ ]+a2,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8730[ ]+wchqk.c.lhusp[ ]+a2,14\(sp\)
+[ ]+[0-9a-f]+:[ ]+87b0[ ]+wchqk.c.lhusp[ ]+a2,30\(sp\)
+[ ]+[0-9a-f]+:[ ]+00015903[ ]+lhu[ ]+s2,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+00115903[ ]+lhu[ ]+s2,1\(sp\)
+[ ]+[0-9a-f]+:[ ]+02015403[ ]+lhu[ ]+s0,32\(sp\)
+[ ]+[0-9a-f]+:[ ]+8070[ ]+wchqk.c.shsp[ ]+a2,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8770[ ]+wchqk.c.shsp[ ]+a2,14\(sp\)
+[ ]+[0-9a-f]+:[ ]+87f0[ ]+wchqk.c.shsp[ ]+a2,30\(sp\)
+[ ]+[0-9a-f]+:[ ]+01211023[ ]+sh[ ]+s2,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+012110a3[ ]+sh[ ]+s2,1\(sp\)
+[ ]+[0-9a-f]+:[ ]+02811023[ ]+sh[ ]+s0,32\(sp\)
+
+[0-9a-f]+ <explicit_xw>:
+[ ]+[0-9a-f]+:[ ]+2000[ ]+wchqk.c.lbu[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+2000[ ]+wchqk.c.lbu[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+3000[ ]+wchqk.c.lbu[ ]+s0,1\(s0\)
+[ ]+[0-9a-f]+:[ ]+2800[ ]+wchqk.c.lbu[ ]+s0,16\(s0\)
+[ ]+[0-9a-f]+:[ ]+a000[ ]+wchqk.c.sb[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+a000[ ]+wchqk.c.sb[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+a800[ ]+wchqk.c.sb[ ]+s0,16\(s0\)
+[ ]+[0-9a-f]+:[ ]+2002[ ]+wchqk.c.lhu[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+2002[ ]+wchqk.c.lhu[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+3002[ ]+wchqk.c.lhu[ ]+s0,32\(s0\)
+[ ]+[0-9a-f]+:[ ]+a002[ ]+wchqk.c.sh[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+a002[ ]+wchqk.c.sh[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+b002[ ]+wchqk.c.sh[ ]+s0,32\(s0\)
+[ ]+[0-9a-f]+:[ ]+8000[ ]+wchqk.c.lbusp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8000[ ]+wchqk.c.lbusp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8400[ ]+wchqk.c.lbusp[ ]+s0,8\(sp\)
+[ ]+[0-9a-f]+:[ ]+8040[ ]+wchqk.c.sbsp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8040[ ]+wchqk.c.sbsp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8440[ ]+wchqk.c.sbsp[ ]+s0,8\(sp\)
+[ ]+[0-9a-f]+:[ ]+8020[ ]+wchqk.c.lhusp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8020[ ]+wchqk.c.lhusp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+80a0[ ]+wchqk.c.lhusp[ ]+s0,16\(sp\)
+[ ]+[0-9a-f]+:[ ]+8060[ ]+wchqk.c.shsp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8060[ ]+wchqk.c.shsp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+80e0[ ]+wchqk.c.shsp[ ]+s0,16\(sp\)
diff --git a/gas/testsuite/gas/riscv/x-wch-qk-xw.s b/gas/testsuite/gas/riscv/x-wch-qk-xw.s
new file mode 100644
index 00000000000..a85981371c6
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wch-qk-xw.s
@@ -0,0 +1,86 @@
+implicit_xw:
+ lbu s0, 5(s1)
+ lbu s0, 31(a0)
+ lbu s0, (a0)
+ lbu s0, 0(s2)
+ lbu s0, 32(s0)
+
+ sb s0, 5(s1)
+ sb s0, 31(a0)
+ sb s0, (a0)
+ sb s0, 0(s2)
+ sb s0, 32(s0)
+
+ lhu s0, 10(s1)
+ lhu s0, 62(a0)
+ lhu s0, (a0)
+ lhu s0, 0(s2)
+ lhu s0, 1(s0)
+ lhu s0, 64(s0)
+
+ sh s0, 10(s1)
+ sh s0, 62(a0)
+ sh s0, (a0)
+ sh s0, 0(s2)
+ sh s0, 1(s0)
+ sh s0, 64(s0)
+
+ lbu a2, (sp)
+ lbu a2, 7(sp)
+ lbu a2, 15(sp)
+ lbu s2, 0(sp)
+ lbu s0, 16(sp)
+
+ sb a2, (sp)
+ sb a2, 7(sp)
+ sb a2, 15(sp)
+ sb s2, 0(sp)
+ sb s0, 16(sp)
+
+ lhu a2, (sp)
+ lhu a2, 14(sp)
+ lhu a2, 30(sp)
+ lhu s2, 0(sp)
+ lhu s2, 1(sp)
+ lhu s0, 32(sp)
+
+ sh a2, (sp)
+ sh a2, 14(sp)
+ sh a2, 30(sp)
+ sh s2, 0(sp)
+ sh s2, 1(sp)
+ sh s0, 32(sp)
+
+explicit_xw:
+ wchqk.c.lbu s0, (s0)
+ wchqk.c.lbu s0, 0(s0)
+ wchqk.c.lbu s0, 1(s0)
+ wchqk.c.lbu s0, 16(s0)
+
+ wchqk.c.sb s0, (s0)
+ wchqk.c.sb s0, 0(s0)
+ wchqk.c.sb s0, 16(s0)
+
+ wchqk.c.lhu s0, (s0)
+ wchqk.c.lhu s0, 0(s0)
+ wchqk.c.lhu s0, 32(s0)
+
+ wchqk.c.sh s0, (s0)
+ wchqk.c.sh s0, 0(s0)
+ wchqk.c.sh s0, 32(s0)
+
+ wchqk.c.lbusp s0, (sp)
+ wchqk.c.lbusp s0, 0(sp)
+ wchqk.c.lbusp s0, 8(sp)
+
+ wchqk.c.sbsp s0, (sp)
+ wchqk.c.sbsp s0, 0(sp)
+ wchqk.c.sbsp s0, 8(sp)
+
+ wchqk.c.lhusp s0, (sp)
+ wchqk.c.lhusp s0, 0(sp)
+ wchqk.c.lhusp s0, 16(sp)
+
+ wchqk.c.shsp s0, (sp)
+ wchqk.c.shsp s0, 0(sp)
+ wchqk.c.shsp s0, 16(sp)
diff --git a/include/ChangeLog b/include/ChangeLog
index 6ef4b590930..e52dbe9e71f 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,8 @@
+2025-11-23 Andy Lin <andylinpersonal@gmail.com>
+
+ * opcode/riscv-opc.h: Add MATCH and MASK opcode macros for XW.
+ * opcode/riscv.h (riscv_insn_class): Add INSN_CLASS_XWCH_QK.
+
2025-07-13 Nick Clifton <nickc@redhat.com>
* 2.45 Branch point.
diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
index bce59c7e6f7..8f54973ed26 100644
--- a/include/opcode/riscv-opc.h
+++ b/include/opcode/riscv-opc.h
@@ -3811,6 +3811,23 @@
/* Vendor-specific (SiFive) cease instruction. */
#define MATCH_SF_CEASE 0x30500073
#define MASK_SF_CEASE 0xffffffff
+/* Qinheng QingKe Xw instructions. */
+#define MATCH_WCH_QK_C_LBU 0x2000
+#define MASK_WCH_QK_C_LBU 0xe003
+#define MATCH_WCH_QK_C_LHU 0x2002
+#define MASK_WCH_QK_C_LHU 0xe003
+#define MATCH_WCH_QK_C_SB 0xa000
+#define MASK_WCH_QK_C_SB 0xe003
+#define MATCH_WCH_QK_C_SH 0xa002
+#define MASK_WCH_QK_C_SH 0xe003
+#define MATCH_WCH_QK_C_LBUSP 0x8000
+#define MASK_WCH_QK_C_LBUSP 0xf863
+#define MATCH_WCH_QK_C_LHUSP 0x8020
+#define MASK_WCH_QK_C_LHUSP 0xf863
+#define MATCH_WCH_QK_C_SBSP 0x8040
+#define MASK_WCH_QK_C_SBSP 0xf863
+#define MATCH_WCH_QK_C_SHSP 0x8060
+#define MASK_WCH_QK_C_SHSP 0xf863
/* SiFive custom int8 matrix-multiply instruction. */
#define MATCH_SFVQMACCU4X8X4 0xf200205b
#define MASK_SFVQMACCU4X8X4 0xfe00707f
@@ -5022,6 +5039,15 @@ DECLARE_INSN(mips_ehb, MATCH_MIPS_EHB, MASK_MIPS_EHB)
DECLARE_INSN(mips_ihb, MATCH_MIPS_IHB, MASK_MIPS_IHB)
DECLARE_INSN(mips_pause, MATCH_MIPS_PAUSE, MASK_MIPS_PAUSE)
DECLARE_INSN(mips_pref, MATCH_MIPS_PREF, MASK_MIPS_PREF)
+/* Vendor-specific (Qinheng QingKe Xw) instructions. */
+DECLARE_INSN(qk_c_lbu, MATCH_WCH_QK_C_LBU, MASK_WCH_QK_C_LBU)
+DECLARE_INSN(qk_c_lhu, MATCH_WCH_QK_C_LHU, MASK_WCH_QK_C_LHU)
+DECLARE_INSN(qk_c_sb, MATCH_WCH_QK_C_SB, MASK_WCH_QK_C_SB)
+DECLARE_INSN(qk_c_sh, MATCH_WCH_QK_C_SH, MASK_WCH_QK_C_SH)
+DECLARE_INSN(qk_c_lbusp, MATCH_WCH_QK_C_LBUSP, MASK_WCH_QK_C_LBUSP)
+DECLARE_INSN(qk_c_lhusp, MATCH_WCH_QK_C_LHUSP, MASK_WCH_QK_C_LHUSP)
+DECLARE_INSN(qk_c_sbsp, MATCH_WCH_QK_C_SBSP, MASK_WCH_QK_C_SBSP)
+DECLARE_INSN(qk_c_shsp, MATCH_WCH_QK_C_SHSP, MASK_WCH_QK_C_SHSP)
#endif /* DECLARE_INSN */
#ifdef DECLARE_CSR
/* Unprivileged Counter/Timers CSRs. */
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index 858fcce6871..e0b6033ca5e 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -141,6 +141,15 @@ static inline unsigned int riscv_insn_length (insn_t insn)
((RV_X(x, 25, 2) << 5) | (RV_X(x, 9, 3) << 2))
#define EXTRACT_MIPS_SDP_IMM(x) \
((RV_X(x, 25, 2) << 5) | (RV_X(x, 10, 2) << 3))
+/* Vendor-specific (Qinheng QingKe Xw) extract macros. */
+#define EXTRACT_WCH_QK_UIMM5(x) \
+ ((RV_X(x, 12, 1)) | (RV_X(x, 10, 2) << 3) | (RV_X(x, 5, 2) << 1))
+#define EXTRACT_WCH_QK_UIMM6_LSB0(x) \
+ ((RV_X(x, 10, 3) << 3) | (RV_X(x, 5, 2) << 1))
+#define EXTRACT_WCH_QK_UIMM4(x) \
+ (RV_X(x, 7, 4))
+#define EXTRACT_WCH_QK_UIMM5_LSB0(x) \
+ ((RV_X(x, 8, 3) << 1) | (RV_X(x, 7, 1) << 4))
#define ENCODE_ITYPE_IMM(x) \
(RV_X(x, 0, 12) << 20)
@@ -218,6 +227,15 @@ static inline unsigned int riscv_insn_length (insn_t insn)
((RV_X(x, 5, 2) << 25) | (RV_X(x, 2, 3) << 9))
#define ENCODE_MIPS_SDP_IMM(x) \
((RV_X(x, 5, 2) << 25) | (RV_X(x, 3, 2) << 10))
+/* Vendor-specific (Qinheng QingKe Xw) encode macros. */
+#define ENCODE_WCH_QK_UIMM5(x) \
+ ((RV_X(x, 0, 1) << 12) | (RV_X(x, 3, 2) << 10) | (RV_X(x, 1, 2) << 5))
+#define ENCODE_WCH_QK_UIMM6_LSB0(x) \
+ ((RV_X(x, 5, 1) << 12) | (RV_X(x, 3, 2) << 10) | (RV_X(x, 1, 2) << 5))
+#define ENCODE_WCH_QK_UIMM4(x) \
+ (RV_X(x, 0, 4) << 7)
+#define ENCODE_WCH_QK_UIMM5_LSB0(x) \
+ ((RV_X(x, 1, 3) << 8) | (RV_X(x, 4, 1) << 7))
#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))
@@ -246,6 +264,11 @@ static inline unsigned int riscv_insn_length (insn_t insn)
#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))
+/* Vendor-specific (Qinheng QingKe Xw) validation macros. */
+#define VALID_WCH_QK_UIMM5(x) (EXTRACT_WCH_QK_UIMM5(ENCODE_WCH_QK_UIMM5(x)) == (x))
+#define VALID_WCH_QK_UIMM6_LSB0(x) (EXTRACT_WCH_QK_UIMM6_LSB0(ENCODE_WCH_QK_UIMM6_LSB0(x)) == (x))
+#define VALID_WCH_QK_UIMM4(x) (EXTRACT_WCH_QK_UIMM4(ENCODE_WCH_QK_UIMM4(x)) == (x))
+#define VALID_WCH_QK_UIMM5_LSB0(x) (EXTRACT_WCH_QK_UIMM5_LSB0(ENCODE_WCH_QK_UIMM5_LSB0(x)) == (x))
#define RISCV_RTYPE(insn, rd, rs1, rs2) \
((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2))
@@ -606,6 +629,7 @@ enum riscv_insn_class
INSN_CLASS_XMIPSCMOV,
INSN_CLASS_XMIPSEXECTL,
INSN_CLASS_XMIPSLSP,
+ INSN_CLASS_XWCH_QK,
};
/* This structure holds information for a particular instruction. */
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 13659e317eb..dc5839b83d5 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,8 @@
+2025-11-23 Andy Lin <andylinpersonal@gmail.com>
+
+ * riscv-opc.c (riscv_opcodes): Add XW opcodes and aliases.
+ * riscv-dis.c (print_insn_args): Add XW opcode to disassembler.
+
2025-07-13 Nick Clifton <nickc@redhat.com>
* 2.45 Branch point.
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index fa2d44af28f..4e92dcd41ac 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -917,6 +917,29 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
goto undefined_modifier;
}
break;
+ case 'w': /* Vendor-specific (Qinghen QingKe Xw) operands. */
+ switch (*++oparg)
+ {
+ case 'b':
+ print (info->stream, dis_style_immediate, "%d",
+ (unsigned)EXTRACT_WCH_QK_UIMM5 (l));
+ break;
+ case '6':
+ print (info->stream, dis_style_immediate, "%d",
+ (unsigned)EXTRACT_WCH_QK_UIMM6_LSB0 (l));
+ break;
+ case '4':
+ print (info->stream, dis_style_immediate, "%d",
+ (unsigned)EXTRACT_WCH_QK_UIMM4 (l));
+ break;
+ case '5':
+ print (info->stream, dis_style_immediate, "%d",
+ (unsigned)EXTRACT_WCH_QK_UIMM5_LSB0 (l));
+ break;
+ default:
+ goto undefined_modifier;
+ }
+ break;
default:
goto undefined_modifier;
}
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index e6fe5e9afba..69fe23fd553 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -589,12 +589,16 @@ const struct riscv_opcode riscv_opcodes[] =
{"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_Lx, match_rd_nonzero, 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", 32, INSN_CLASS_XWCH_QK, "Ct,Xw4(Cc)", MATCH_WCH_QK_C_LBUSP, MASK_WCH_QK_C_LBUSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_1_BYTE },
+{"lbu", 32, INSN_CLASS_XWCH_QK, "Ct,Xwb(Cs)", MATCH_WCH_QK_C_LBU, MASK_WCH_QK_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_Lx, match_rd_nonzero, 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_Lx, match_rd_nonzero, 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", 32, INSN_CLASS_XWCH_QK, "Ct,Xw5(Cc)", MATCH_WCH_QK_C_LHUSP, MASK_WCH_QK_C_LHUSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_2_BYTE },
+{"lhu", 32, INSN_CLASS_XWCH_QK, "Ct,Xw6(Cs)", MATCH_WCH_QK_C_LHU, MASK_WCH_QK_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_Lx, match_rd_nonzero, INSN_MACRO },
{"lw", 0, INSN_CLASS_ZCA, "d,Cm(Cc)", MATCH_C_LWSP, MASK_C_LWSP, match_rd_nonzero, INSN_ALIAS|INSN_DREF|INSN_4_BYTE },
@@ -626,9 +630,13 @@ const struct riscv_opcode riscv_opcodes[] =
{"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", 32, INSN_CLASS_XWCH_QK, "Ct,Xw4(Cc)", MATCH_WCH_QK_C_SBSP, MASK_WCH_QK_C_SBSP, match_opcode, INSN_DREF|INSN_1_BYTE|INSN_ALIAS },
+{"sb", 32, INSN_CLASS_XWCH_QK, "Ct,Xwb(Cs)", MATCH_WCH_QK_C_SB, MASK_WCH_QK_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_Sx_FSx, match_rs1_nonzero, 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", 32, INSN_CLASS_XWCH_QK, "Ct,Xw5(Cc)", MATCH_WCH_QK_C_SHSP, MASK_WCH_QK_C_SHSP, match_opcode, INSN_DREF|INSN_2_BYTE|INSN_ALIAS },
+{"sh", 32, INSN_CLASS_XWCH_QK, "Ct,Xw6(Cs)", MATCH_WCH_QK_C_SH, MASK_WCH_QK_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_Sx_FSx, match_rs1_nonzero, INSN_MACRO },
{"sw", 0, INSN_CLASS_ZCA, "CV,CM(Cc)", MATCH_C_SWSP, MASK_C_SWSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_4_BYTE },
@@ -3579,6 +3587,16 @@ const struct riscv_opcode riscv_opcodes[] =
{"mips.sdp", 0, INSN_CLASS_XMIPSLSP, "t,r,Xm^(s)", MATCH_MIPS_SDP, MASK_MIPS_SDP, match_opcode, 0 },
{"mips.swp", 0, INSN_CLASS_XMIPSLSP, "t,r,Xm&(s)", MATCH_MIPS_SWP, MASK_MIPS_SWP, match_opcode, 0 },
+/* Qinghen QingKe Xw instructions. */
+{"wchqk.c.lbu", 32, INSN_CLASS_XWCH_QK, "Ct,Xwb(Cs)", MATCH_WCH_QK_C_LBU, MASK_WCH_QK_C_LBU, match_opcode, INSN_DREF|INSN_1_BYTE },
+{"wchqk.c.lhu", 32, INSN_CLASS_XWCH_QK, "Ct,Xw6(Cs)", MATCH_WCH_QK_C_LHU, MASK_WCH_QK_C_LHU, match_opcode, INSN_DREF|INSN_2_BYTE },
+{"wchqk.c.sb", 32, INSN_CLASS_XWCH_QK, "Ct,Xwb(Cs)", MATCH_WCH_QK_C_SB, MASK_WCH_QK_C_SB, match_opcode, INSN_DREF|INSN_1_BYTE },
+{"wchqk.c.sh", 32, INSN_CLASS_XWCH_QK, "Ct,Xw6(Cs)", MATCH_WCH_QK_C_SH, MASK_WCH_QK_C_SH, match_opcode, INSN_DREF|INSN_2_BYTE },
+{"wchqk.c.lbusp", 32, INSN_CLASS_XWCH_QK, "Ct,Xw4(Cc)", MATCH_WCH_QK_C_LBUSP, MASK_WCH_QK_C_LBUSP, match_opcode, INSN_DREF|INSN_1_BYTE },
+{"wchqk.c.lhusp", 32, INSN_CLASS_XWCH_QK, "Ct,Xw5(Cc)", MATCH_WCH_QK_C_LHUSP, MASK_WCH_QK_C_LHUSP, match_opcode, INSN_DREF|INSN_2_BYTE },
+{"wchqk.c.sbsp", 32, INSN_CLASS_XWCH_QK, "Ct,Xw4(Cc)", MATCH_WCH_QK_C_SBSP, MASK_WCH_QK_C_SBSP, match_opcode, INSN_DREF|INSN_1_BYTE },
+{"wchqk.c.shsp", 32, INSN_CLASS_XWCH_QK, "Ct,Xw5(Cc)", MATCH_WCH_QK_C_SHSP, MASK_WCH_QK_C_SHSP, match_opcode, INSN_DREF|INSN_2_BYTE },
+
/* Terminate the list. */
{0, 0, INSN_CLASS_NONE, 0, 0, 0, 0, 0}
};
--
2.43.0
More information about the Binutils
mailing list