[PATCH v2] RISC-V: Add support for XW extension on some WCH cores
Andy Lin
andylinpersonal@gmail.com
Mon Nov 24 11:56:21 GMT 2025
v1 -> v2:
xw -> xwchc to align with LLVM's existing patch.
---
This patch implements the `Xwchc' 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 _xwchc':
After `.option rvc', Xwchc opcodes are not available implicitly.
But the user can still add `.option arch,+xwchc' 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
Xwchc extension.
* (riscv_multi_subset_supports_ext): Likewise.
* (riscv_update_subset_norvc): Xwchc opcodes should not be
emitted under `norvc' mode.
gas/ChangeLog:
* config/tc-riscv.c (riscv_ip): Add Xwchc to assembler.
* config/tc-riscv.c (validate_riscv_insn): Add Xwchc.
* doc/c-riscv.texi: Note Xwchc as an additional ISA extension for some
WCH's QingKe RISC-V MCU cores.
* testsuite/gas/riscv/march-help.l: Add '-xwchc' string.
* testsuite/gas/riscv/x-wchc.d: New tests.
* testsuite/gas/riscv/x-wchc.s: Likewise.
* testsuite/gas/riscv/x-wchc-fail.d: Likewise.
* testsuite/gas/riscv/x-wchc-fail.l: Likewise.
* testsuite/gas/riscv/x-wchc-fail.s: Likewise.
* testsuite/gas/riscv/x-wchc-norvc.d: New test for `norvc'.
* testsuite/gas/riscv/x-wchc-norvc.s: Likewise.
include/ChangeLog:
* opcode/riscv-opc.h: Add MATCH and MASK opcode macros for Xwchc.
* opcode/riscv.h (riscv_insn_class): Add INSN_CLASS_XWCHC.
opcodes/ChangeLog:
* riscv-opc.c (riscv_opcodes): Add Xwchc opcodes and aliases.
* riscv-dis.c (print_insn_args): Add Xwchc 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-wchc-fail.d | 3 +
gas/testsuite/gas/riscv/x-wchc-fail.l | 33 ++++++++++
gas/testsuite/gas/riscv/x-wchc-fail.s | 39 ++++++++++++
gas/testsuite/gas/riscv/x-wchc-norvc.d | 26 ++++++++
gas/testsuite/gas/riscv/x-wchc-norvc.s | 20 ++++++
gas/testsuite/gas/riscv/x-wchc.d | 81 ++++++++++++++++++++++++
gas/testsuite/gas/riscv/x-wchc.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-wchc-fail.d
create mode 100644 gas/testsuite/gas/riscv/x-wchc-fail.l
create mode 100644 gas/testsuite/gas/riscv/x-wchc-fail.s
create mode 100644 gas/testsuite/gas/riscv/x-wchc-norvc.d
create mode 100644 gas/testsuite/gas/riscv/x-wchc-norvc.s
create mode 100644 gas/testsuite/gas/riscv/x-wchc.d
create mode 100644 gas/testsuite/gas/riscv/x-wchc.s
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1bd99a9b042..390b81dd9c4 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
+ Xwchc extension.
+ * (riscv_multi_subset_supports_ext): Likewise.
+ * (riscv_update_subset_norvc): Xwchc opcodes 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 27d439adebe..29163642263 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 },
+ {"xwchc", 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, "xwchc")
+ && (riscv_subset_supports (rps, "d") || riscv_subset_supports (rps, "zcb")))
+ {
+ rps->error_handler (_("xwchc' 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,-xwchc");
}
/* 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_XWCHC:
+ return riscv_subset_supports (rps, "xwchc");
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_XWCHC:
+ return "xwchc";
default:
rps->error_handler
(_("internal: unreachable INSN_CLASS_*"));
diff --git a/gas/ChangeLog b/gas/ChangeLog
index dd7691593f1..df2fd5789c8 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 Xwchc to assembler.
+ * config/tc-riscv.c (validate_riscv_insn): Add Xwchc.
+ * doc/c-riscv.texi: Note Xwchc as an additional ISA extension for some
+ WCH's QingKe RISC-V MCU cores.
+ * testsuite/gas/riscv/march-help.l: Add '-xwchc' string.
+ * testsuite/gas/riscv/x-wchc.d: New tests.
+ * testsuite/gas/riscv/x-wchc.s: Likewise.
+ * testsuite/gas/riscv/x-wchc-fail.d: Likewise.
+ * testsuite/gas/riscv/x-wchc-fail.l: Likewise.
+ * testsuite/gas/riscv/x-wchc-fail.s: Likewise.
+ * testsuite/gas/riscv/x-wchc-norvc.d: New test for `norvc'.
+ * testsuite/gas/riscv/x-wchc-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..6cbf1d9fd00 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,8 @@
-*- text -*-
+* Add support for RISC-V vendor extension:
+ QinHeng (WCH): Xwchc 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 f298bd855b2..b0139afcc7e 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 Xwchc) operands. */
+ switch(*++oparg)
+ {
+ case 'b': used_bits |= ENCODE_XWCHC_UIMM5 (-1); break; /* Xwb */
+ case '6': used_bits |= ENCODE_XWCHC_UIMM6_LSB0 (-1); break; /* Xw6 */
+ case '4': used_bits |= ENCODE_XWCHC_UIMM4 (-1); break; /* Xw4 */
+ case '5': used_bits |= ENCODE_XWCHC_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 Xwchc) 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_XWCHC_UIMM5 ((valueT) imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_XWCHC_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_XWCHC_UIMM6_LSB0 ((valueT) imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_XWCHC_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_XWCHC_UIMM4 ((valueT) imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_XWCHC_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_XWCHC_UIMM5_LSB0 ((valueT) imm_expr->X_add_number))
+ break;
+ ip->insn_opcode |= ENCODE_XWCHC_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, "xwchc"));
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..052abe989cf 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 Xwchc
+
+The Xwchc 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..149038eea1a 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
+ xwchc 1.0
diff --git a/gas/testsuite/gas/riscv/x-wchc-fail.d b/gas/testsuite/gas/riscv/x-wchc-fail.d
new file mode 100644
index 00000000000..1d3a36a631b
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wchc-fail.d
@@ -0,0 +1,3 @@
+#as: -march=rv32ic_xwchc
+#source: x-wchc-fail.s
+#error_output: x-wchc-fail.l
diff --git a/gas/testsuite/gas/riscv/x-wchc-fail.l b/gas/testsuite/gas/riscv/x-wchc-fail.l
new file mode 100644
index 00000000000..e840a3bf044
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wchc-fail.l
@@ -0,0 +1,33 @@
+.*: Assembler messages:
+.*: Error: unrecognized opcode `qk.c.lbu x8,0\(x8\)', extension `xwchc' required
+.*: Error: unrecognized opcode `qk.c.sb x8,0\(x8\)', extension `xwchc' required
+.*: Error: unrecognized opcode `qk.c.sb x8,-2\(x8\)', extension `xwchc' required
+.*: Error: unrecognized opcode `qk.c.sb x8,0\(x7\)', extension `xwchc' required
+.*: Error: illegal operands `qk.c.sb x7,0\(x8\)'
+.*: Error: illegal operands `qk.c.sb x7,-2\(x20\)'
+.*: Error: illegal operands `qk.c.lhu x8,1\(x8\)'
+.*: Error: illegal operands `qk.c.lhu x8,64\(x8\)'
+.*: Error: illegal operands `qk.c.sh x8,1\(x8\)'
+.*: Error: illegal operands `qk.c.sh x8,64\(x8\)'
+.*: Error: illegal operands `qk.c.sh x8,-1\(x8\)'
+.*: Error: illegal operands `qk.c.sh x8,-2\(x8\)'
+.*: Error: illegal operands `qk.c.sh x8,0\(x7\)'
+.*: Error: illegal operands `qk.c.sh x7,0\(x8\)'
+.*: Error: illegal operands `qk.c.sh x7,-2\(x20\)'
+.*: Error: illegal operands `qk.c.lbusp x8,0\(x8\)'
+.*: Error: illegal operands `qk.c.lbusp x8,32\(sp\)'
+.*: Error: illegal operands `qk.c.sbsp x8,0\(x8\)'
+.*: Error: illegal operands `qk.c.sbsp x8,32\(sp\)'
+.*: Error: illegal operands `qk.c.sbsp x8,-2\(sp\)'
+.*: Error: illegal operands `qk.c.sbsp x7,0\(sp\)'
+.*: Error: illegal operands `qk.c.sbsp x7,-2\(sp\)'
+.*: Error: illegal operands `qk.c.lhusp x8,0\(x8\)'
+.*: Error: illegal operands `qk.c.lhusp x8,1\(sp\)'
+.*: Error: illegal operands `qk.c.lhusp x8,32\(sp\)'
+.*: Error: illegal operands `qk.c.shsp x8,0\(x8\)'
+.*: Error: illegal operands `qk.c.shsp x8,1\(sp\)'
+.*: Error: illegal operands `qk.c.shsp x8,32\(sp\)'
+.*: Error: illegal operands `qk.c.shsp x8,-1\(sp\)'
+.*: Error: illegal operands `qk.c.shsp x8,-2\(sp\)'
+.*: Error: illegal operands `qk.c.shsp x7,0\(sp\)'
+.*: Error: illegal operands `qk.c.shsp x7,-2\(sp\)'
diff --git a/gas/testsuite/gas/riscv/x-wchc-fail.s b/gas/testsuite/gas/riscv/x-wchc-fail.s
new file mode 100644
index 00000000000..a79fcfa008f
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wchc-fail.s
@@ -0,0 +1,39 @@
+target:
+.option norvc
+ qk.c.lbu x8, 0(x8)
+ qk.c.sb x8, 0(x8)
+.option rvc
+ qk.c.sb x8, -2(x8)
+ qk.c.sb x8, 0(x7)
+.option arch,+xwchc
+ qk.c.sb x7, 0(x8)
+ qk.c.sb x7, -2(x20)
+
+ qk.c.lhu x8, 1(x8)
+ qk.c.lhu x8, 64(x8)
+ qk.c.sh x8, 1(x8)
+ qk.c.sh x8, 64(x8)
+ qk.c.sh x8, -1(x8)
+ qk.c.sh x8, -2(x8)
+ qk.c.sh x8, 0(x7)
+ qk.c.sh x7, 0(x8)
+ qk.c.sh x7, -2(x20)
+
+ qk.c.lbusp x8, 0(x8)
+ qk.c.lbusp x8, 32(sp)
+ qk.c.sbsp x8, 0(x8)
+ qk.c.sbsp x8, 32(sp)
+ qk.c.sbsp x8, -2(sp)
+ qk.c.sbsp x7, 0(sp)
+ qk.c.sbsp x7, -2(sp)
+
+ qk.c.lhusp x8, 0(x8)
+ qk.c.lhusp x8, 1(sp)
+ qk.c.lhusp x8, 32(sp)
+ qk.c.shsp x8, 0(x8)
+ qk.c.shsp x8, 1(sp)
+ qk.c.shsp x8, 32(sp)
+ qk.c.shsp x8, -1(sp)
+ qk.c.shsp x8, -2(sp)
+ qk.c.shsp x7, 0(sp)
+ qk.c.shsp x7, -2(sp)
diff --git a/gas/testsuite/gas/riscv/x-wchc-norvc.d b/gas/testsuite/gas/riscv/x-wchc-norvc.d
new file mode 100644
index 00000000000..692b0d74008
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wchc-norvc.d
@@ -0,0 +1,26 @@
+#as: -march=rv32ic_xwchc
+#source: x-wchc-norvc.s
+#objdump: -d -Mno-aliases
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ ]+[0-9a-f]+:[ ]+30c0[ ]+qk.c.lbu[ ]+s0,5\(s1\)
+[ ]+[0-9a-f]+:[ ]+3d60[ ]+qk.c.lbu[ ]+s0,31\(a0\)
+[ ]+[0-9a-f]+:[ ]+2000[ ]+qk.c.lbu[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+3000[ ]+qk.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_xwchc>:
+[ ]+[0-9a-f]+:[ ]+30c0[ ]+qk.c.lbu[ ]+s0,5\(s1\)
+[ ]+[0-9a-f]+:[ ]+3d60[ ]+qk.c.lbu[ ]+s0,31\(a0\)
diff --git a/gas/testsuite/gas/riscv/x-wchc-norvc.s b/gas/testsuite/gas/riscv/x-wchc-norvc.s
new file mode 100644
index 00000000000..17f86711b6f
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wchc-norvc.s
@@ -0,0 +1,20 @@
+target:
+ lbu s0, 5(s1)
+ lbu s0, 31(a0)
+ qk.c.lbu s0, 0(s0)
+ qk.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_xwchc:
+.option arch,+xwchc
+ lbu s0, 5(s1)
+ lbu s0, 31(a0)
diff --git a/gas/testsuite/gas/riscv/x-wchc.d b/gas/testsuite/gas/riscv/x-wchc.d
new file mode 100644
index 00000000000..4c162cb4ea1
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wchc.d
@@ -0,0 +1,81 @@
+#as: -march=rv32ic_xwchc
+#source: x-wchc.s
+#objdump: -d -Mno-aliases
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <implicit_xwchc>:
+[ ]+[0-9a-f]+:[ ]+30c0[ ]+qk.c.lbu[ ]+s0,5\(s1\)
+[ ]+[0-9a-f]+:[ ]+3d60[ ]+qk.c.lbu[ ]+s0,31\(a0\)
+[ ]+[0-9a-f]+:[ ]+2100[ ]+qk.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[ ]+qk.c.sb[ ]+s0,5\(s1\)
+[ ]+[0-9a-f]+:[ ]+bd60[ ]+qk.c.sb[ ]+s0,31\(a0\)
+[ ]+[0-9a-f]+:[ ]+a100[ ]+qk.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[ ]+qk.c.lhu[ ]+s0,10\(s1\)
+[ ]+[0-9a-f]+:[ ]+3d62[ ]+qk.c.lhu[ ]+s0,62\(a0\)
+[ ]+[0-9a-f]+:[ ]+2102[ ]+qk.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[ ]+qk.c.sh[ ]+s0,10\(s1\)
+[ ]+[0-9a-f]+:[ ]+bd62[ ]+qk.c.sh[ ]+s0,62\(a0\)
+[ ]+[0-9a-f]+:[ ]+a102[ ]+qk.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[ ]+qk.c.lbusp[ ]+a2,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8390[ ]+qk.c.lbusp[ ]+a2,7\(sp\)
+[ ]+[0-9a-f]+:[ ]+8790[ ]+qk.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[ ]+qk.c.sbsp[ ]+a2,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+83d0[ ]+qk.c.sbsp[ ]+a2,7\(sp\)
+[ ]+[0-9a-f]+:[ ]+87d0[ ]+qk.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[ ]+qk.c.lhusp[ ]+a2,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8730[ ]+qk.c.lhusp[ ]+a2,14\(sp\)
+[ ]+[0-9a-f]+:[ ]+87b0[ ]+qk.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[ ]+qk.c.shsp[ ]+a2,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8770[ ]+qk.c.shsp[ ]+a2,14\(sp\)
+[ ]+[0-9a-f]+:[ ]+87f0[ ]+qk.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_xwchc>:
+[ ]+[0-9a-f]+:[ ]+2000[ ]+qk.c.lbu[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+2000[ ]+qk.c.lbu[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+3000[ ]+qk.c.lbu[ ]+s0,1\(s0\)
+[ ]+[0-9a-f]+:[ ]+2800[ ]+qk.c.lbu[ ]+s0,16\(s0\)
+[ ]+[0-9a-f]+:[ ]+a000[ ]+qk.c.sb[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+a000[ ]+qk.c.sb[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+a800[ ]+qk.c.sb[ ]+s0,16\(s0\)
+[ ]+[0-9a-f]+:[ ]+2002[ ]+qk.c.lhu[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+2002[ ]+qk.c.lhu[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+3002[ ]+qk.c.lhu[ ]+s0,32\(s0\)
+[ ]+[0-9a-f]+:[ ]+a002[ ]+qk.c.sh[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+a002[ ]+qk.c.sh[ ]+s0,0\(s0\)
+[ ]+[0-9a-f]+:[ ]+b002[ ]+qk.c.sh[ ]+s0,32\(s0\)
+[ ]+[0-9a-f]+:[ ]+8000[ ]+qk.c.lbusp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8000[ ]+qk.c.lbusp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8400[ ]+qk.c.lbusp[ ]+s0,8\(sp\)
+[ ]+[0-9a-f]+:[ ]+8040[ ]+qk.c.sbsp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8040[ ]+qk.c.sbsp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8440[ ]+qk.c.sbsp[ ]+s0,8\(sp\)
+[ ]+[0-9a-f]+:[ ]+8020[ ]+qk.c.lhusp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8020[ ]+qk.c.lhusp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+80a0[ ]+qk.c.lhusp[ ]+s0,16\(sp\)
+[ ]+[0-9a-f]+:[ ]+8060[ ]+qk.c.shsp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+8060[ ]+qk.c.shsp[ ]+s0,0\(sp\)
+[ ]+[0-9a-f]+:[ ]+80e0[ ]+qk.c.shsp[ ]+s0,16\(sp\)
diff --git a/gas/testsuite/gas/riscv/x-wchc.s b/gas/testsuite/gas/riscv/x-wchc.s
new file mode 100644
index 00000000000..50474a84965
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-wchc.s
@@ -0,0 +1,86 @@
+implicit_xwchc:
+ 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_xwchc:
+ qk.c.lbu s0, (s0)
+ qk.c.lbu s0, 0(s0)
+ qk.c.lbu s0, 1(s0)
+ qk.c.lbu s0, 16(s0)
+
+ qk.c.sb s0, (s0)
+ qk.c.sb s0, 0(s0)
+ qk.c.sb s0, 16(s0)
+
+ qk.c.lhu s0, (s0)
+ qk.c.lhu s0, 0(s0)
+ qk.c.lhu s0, 32(s0)
+
+ qk.c.sh s0, (s0)
+ qk.c.sh s0, 0(s0)
+ qk.c.sh s0, 32(s0)
+
+ qk.c.lbusp s0, (sp)
+ qk.c.lbusp s0, 0(sp)
+ qk.c.lbusp s0, 8(sp)
+
+ qk.c.sbsp s0, (sp)
+ qk.c.sbsp s0, 0(sp)
+ qk.c.sbsp s0, 8(sp)
+
+ qk.c.lhusp s0, (sp)
+ qk.c.lhusp s0, 0(sp)
+ qk.c.lhusp s0, 16(sp)
+
+ qk.c.shsp s0, (sp)
+ qk.c.shsp s0, 0(sp)
+ qk.c.shsp s0, 16(sp)
diff --git a/include/ChangeLog b/include/ChangeLog
index 6ef4b590930..6dc61453b78 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 Xwchc.
+ * opcode/riscv.h (riscv_insn_class): Add INSN_CLASS_XWCHC.
+
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..990dc25a8bd 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_XWCHC_LBU 0x2000
+#define MASK_XWCHC_LBU 0xe003
+#define MATCH_XWCHC_LHU 0x2002
+#define MASK_XWCHC_LHU 0xe003
+#define MATCH_XWCHC_SB 0xa000
+#define MASK_XWCHC_SB 0xe003
+#define MATCH_XWCHC_SH 0xa002
+#define MASK_XWCHC_SH 0xe003
+#define MATCH_XWCHC_LBUSP 0x8000
+#define MASK_XWCHC_LBUSP 0xf863
+#define MATCH_XWCHC_LHUSP 0x8020
+#define MASK_XWCHC_LHUSP 0xf863
+#define MATCH_XWCHC_SBSP 0x8040
+#define MASK_XWCHC_SBSP 0xf863
+#define MATCH_XWCHC_SHSP 0x8060
+#define MASK_XWCHC_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_XWCHC_LBU, MASK_XWCHC_LBU)
+DECLARE_INSN(qk_c_lhu, MATCH_XWCHC_LHU, MASK_XWCHC_LHU)
+DECLARE_INSN(qk_c_sb, MATCH_XWCHC_SB, MASK_XWCHC_SB)
+DECLARE_INSN(qk_c_sh, MATCH_XWCHC_SH, MASK_XWCHC_SH)
+DECLARE_INSN(qk_c_lbusp, MATCH_XWCHC_LBUSP, MASK_XWCHC_LBUSP)
+DECLARE_INSN(qk_c_lhusp, MATCH_XWCHC_LHUSP, MASK_XWCHC_LHUSP)
+DECLARE_INSN(qk_c_sbsp, MATCH_XWCHC_SBSP, MASK_XWCHC_SBSP)
+DECLARE_INSN(qk_c_shsp, MATCH_XWCHC_SHSP, MASK_XWCHC_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..cb2683087d2 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_XWCHC_UIMM5(x) \
+ ((RV_X(x, 12, 1)) | (RV_X(x, 10, 2) << 3) | (RV_X(x, 5, 2) << 1))
+#define EXTRACT_XWCHC_UIMM6_LSB0(x) \
+ ((RV_X(x, 10, 3) << 3) | (RV_X(x, 5, 2) << 1))
+#define EXTRACT_XWCHC_UIMM4(x) \
+ (RV_X(x, 7, 4))
+#define EXTRACT_XWCHC_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_XWCHC_UIMM5(x) \
+ ((RV_X(x, 0, 1) << 12) | (RV_X(x, 3, 2) << 10) | (RV_X(x, 1, 2) << 5))
+#define ENCODE_XWCHC_UIMM6_LSB0(x) \
+ ((RV_X(x, 5, 1) << 12) | (RV_X(x, 3, 2) << 10) | (RV_X(x, 1, 2) << 5))
+#define ENCODE_XWCHC_UIMM4(x) \
+ (RV_X(x, 0, 4) << 7)
+#define ENCODE_XWCHC_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_XWCHC_UIMM5(x) (EXTRACT_XWCHC_UIMM5(ENCODE_XWCHC_UIMM5(x)) == (x))
+#define VALID_XWCHC_UIMM6_LSB0(x) (EXTRACT_XWCHC_UIMM6_LSB0(ENCODE_XWCHC_UIMM6_LSB0(x)) == (x))
+#define VALID_XWCHC_UIMM4(x) (EXTRACT_XWCHC_UIMM4(ENCODE_XWCHC_UIMM4(x)) == (x))
+#define VALID_XWCHC_UIMM5_LSB0(x) (EXTRACT_XWCHC_UIMM5_LSB0(ENCODE_XWCHC_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_XWCHC,
};
/* This structure holds information for a particular instruction. */
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 13659e317eb..9a05b0142d3 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 Xwchc opcodes and aliases.
+ * riscv-dis.c (print_insn_args): Add Xwchc 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..ba4257d4262 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 Xwchc) operands. */
+ switch (*++oparg)
+ {
+ case 'b':
+ print (info->stream, dis_style_immediate, "%d",
+ (unsigned)EXTRACT_XWCHC_UIMM5 (l));
+ break;
+ case '6':
+ print (info->stream, dis_style_immediate, "%d",
+ (unsigned)EXTRACT_XWCHC_UIMM6_LSB0 (l));
+ break;
+ case '4':
+ print (info->stream, dis_style_immediate, "%d",
+ (unsigned)EXTRACT_XWCHC_UIMM4 (l));
+ break;
+ case '5':
+ print (info->stream, dis_style_immediate, "%d",
+ (unsigned)EXTRACT_XWCHC_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..eb9f0e50c76 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_XWCHC, "Ct,Xw4(Cc)", MATCH_XWCHC_LBUSP, MASK_XWCHC_LBUSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_1_BYTE },
+{"lbu", 32, INSN_CLASS_XWCHC, "Ct,Xwb(Cs)", MATCH_XWCHC_LBU, MASK_XWCHC_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_XWCHC, "Ct,Xw5(Cc)", MATCH_XWCHC_LHUSP, MASK_XWCHC_LHUSP, match_opcode, INSN_ALIAS|INSN_DREF|INSN_2_BYTE },
+{"lhu", 32, INSN_CLASS_XWCHC, "Ct,Xw6(Cs)", MATCH_XWCHC_LHU, MASK_XWCHC_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_XWCHC, "Ct,Xw4(Cc)", MATCH_XWCHC_SBSP, MASK_XWCHC_SBSP, match_opcode, INSN_DREF|INSN_1_BYTE|INSN_ALIAS },
+{"sb", 32, INSN_CLASS_XWCHC, "Ct,Xwb(Cs)", MATCH_XWCHC_SB, MASK_XWCHC_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_XWCHC, "Ct,Xw5(Cc)", MATCH_XWCHC_SHSP, MASK_XWCHC_SHSP, match_opcode, INSN_DREF|INSN_2_BYTE|INSN_ALIAS },
+{"sh", 32, INSN_CLASS_XWCHC, "Ct,Xw6(Cs)", MATCH_XWCHC_SH, MASK_XWCHC_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. */
+{"qk.c.lbu", 32, INSN_CLASS_XWCHC, "Ct,Xwb(Cs)", MATCH_XWCHC_LBU, MASK_XWCHC_LBU, match_opcode, INSN_DREF|INSN_1_BYTE },
+{"qk.c.lhu", 32, INSN_CLASS_XWCHC, "Ct,Xw6(Cs)", MATCH_XWCHC_LHU, MASK_XWCHC_LHU, match_opcode, INSN_DREF|INSN_2_BYTE },
+{"qk.c.sb", 32, INSN_CLASS_XWCHC, "Ct,Xwb(Cs)", MATCH_XWCHC_SB, MASK_XWCHC_SB, match_opcode, INSN_DREF|INSN_1_BYTE },
+{"qk.c.sh", 32, INSN_CLASS_XWCHC, "Ct,Xw6(Cs)", MATCH_XWCHC_SH, MASK_XWCHC_SH, match_opcode, INSN_DREF|INSN_2_BYTE },
+{"qk.c.lbusp", 32, INSN_CLASS_XWCHC, "Ct,Xw4(Cc)", MATCH_XWCHC_LBUSP, MASK_XWCHC_LBUSP, match_opcode, INSN_DREF|INSN_1_BYTE },
+{"qk.c.lhusp", 32, INSN_CLASS_XWCHC, "Ct,Xw5(Cc)", MATCH_XWCHC_LHUSP, MASK_XWCHC_LHUSP, match_opcode, INSN_DREF|INSN_2_BYTE },
+{"qk.c.sbsp", 32, INSN_CLASS_XWCHC, "Ct,Xw4(Cc)", MATCH_XWCHC_SBSP, MASK_XWCHC_SBSP, match_opcode, INSN_DREF|INSN_1_BYTE },
+{"qk.c.shsp", 32, INSN_CLASS_XWCHC, "Ct,Xw5(Cc)", MATCH_XWCHC_SHSP, MASK_XWCHC_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