* [PATCH 0/3] RISC-V Zbr0p93 extension
@ 2026-03-04 12:11 James Wainwright
2026-03-04 12:11 ` [PATCH 1/3] util: export CRC32[C] lookup tables James Wainwright
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: James Wainwright @ 2026-03-04 12:11 UTC (permalink / raw)
To: qemu-riscv; +Cc: qemu-devel, alistair.francis, James Wainwright
This patch series adds support for the unratified RISC-V Zbr0p93
extension which is implemented by the Ibex core and used in the (now
taped-out) OpenTitan mask ROM.
Because this extension uses the standard reserved encoding space, it's
possible that it could conflict with a ratified extension in the future.
These patches were written by Rivos for the OpenTitan fork of QEMU, but
lowRISC is choosing to upstream them.
Emmanuel Blot (3):
util: export CRC32[C] lookup tables
target/riscv: add unratified RISC-V Zbr0p93 ext
disas: diassemble RISC-V Zbr0p93 instructions
MAINTAINERS | 2 +-
disas/meson.build | 3 +-
disas/riscv-zbr.c | 78 +++++++++++++++++++++
disas/riscv-zbr.h | 18 +++++
disas/riscv.c | 4 ++
include/qemu/crc32.h | 18 +++++
include/qemu/crc32c.h | 1 +
target/riscv/bitmanip_helper.c | 20 ++++++
target/riscv/cpu.c | 4 +-
target/riscv/cpu_cfg.h | 3 +
target/riscv/cpu_cfg_fields.h.inc | 1 +
target/riscv/helper.h | 2 +
target/riscv/insn32.decode | 12 ++++
target/riscv/insn_trans/trans_rvb.c.inc | 37 ++++++++++
tests/tcg/riscv64/Makefile.softmmu-target | 5 ++
tests/tcg/riscv64/test-crc32.S | 64 +++++++++++++++++
util/crc32.c | 85 +++++++++++++++++++++++
util/crc32c.c | 4 +-
util/meson.build | 1 +
19 files changed, 357 insertions(+), 5 deletions(-)
create mode 100644 disas/riscv-zbr.c
create mode 100644 disas/riscv-zbr.h
create mode 100644 include/qemu/crc32.h
create mode 100644 tests/tcg/riscv64/test-crc32.S
create mode 100644 util/crc32.c
--
2.48.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/3] util: export CRC32[C] lookup tables
2026-03-04 12:11 [PATCH 0/3] RISC-V Zbr0p93 extension James Wainwright
@ 2026-03-04 12:11 ` James Wainwright
2026-03-05 3:16 ` Alistair Francis
2026-03-04 12:11 ` [PATCH 2/3] target/riscv: add unratified RISC-V Zbr0p93 ext James Wainwright
2026-03-04 12:11 ` [PATCH 3/3] disas: diassemble RISC-V Zbr0p93 instructions James Wainwright
2 siblings, 1 reply; 8+ messages in thread
From: James Wainwright @ 2026-03-04 12:11 UTC (permalink / raw)
To: qemu-riscv; +Cc: qemu-devel, alistair.francis, James Wainwright
These are needed for the RISC-V Zbr0p93 CRC32 instructions which pre-XOR
the data into the CRC state before the instruction is executed, making
the zlib crc32 and QEMU crc32c implementations inappropriate.
https://github.com/riscv/riscv-bitmanip/releases/download/v0.93/bitmanip-0.93.pdf
Signed-off-by: James Wainwright <james.wainwright@lowrisc.org>
---
include/qemu/crc32.h | 18 +++++++++
include/qemu/crc32c.h | 1 +
util/crc32.c | 85 +++++++++++++++++++++++++++++++++++++++++++
util/crc32c.c | 4 +-
util/meson.build | 1 +
5 files changed, 107 insertions(+), 2 deletions(-)
create mode 100644 include/qemu/crc32.h
create mode 100644 util/crc32.c
diff --git a/include/qemu/crc32.h b/include/qemu/crc32.h
new file mode 100644
index 0000000000..a320151acc
--- /dev/null
+++ b/include/qemu/crc32.h
@@ -0,0 +1,18 @@
+/*
+ * CRC32 Checksum
+ *
+ * Copyright (c) 2026 QEMU contributors
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#ifndef QEMU_CRC32_H
+#define QEMU_CRC32_H
+
+extern const uint32_t crc32_table[256];
+
+#endif
diff --git a/include/qemu/crc32c.h b/include/qemu/crc32c.h
index 88b4d2b3b3..3d5ba189ef 100644
--- a/include/qemu/crc32c.h
+++ b/include/qemu/crc32c.h
@@ -28,6 +28,7 @@
#ifndef QEMU_CRC32C_H
#define QEMU_CRC32C_H
+extern const uint32_t crc32c_table[256];
uint32_t crc32c(uint32_t crc, const uint8_t *data, unsigned int length);
uint32_t iov_crc32c(uint32_t crc, const struct iovec *iov, size_t iov_cnt);
diff --git a/util/crc32.c b/util/crc32.c
new file mode 100644
index 0000000000..590dd6e3a2
--- /dev/null
+++ b/util/crc32.c
@@ -0,0 +1,85 @@
+/*
+ * Constants for computing CRC32 checksums
+ *
+ * Copyright (c) 2026 QEMU contributors
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/crc32.h"
+
+/*
+ * CRC-32 table (reversed; polynomial 0xEDB88320).
+ */
+
+const uint32_t crc32_table[256] = {
+ 0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau,
+ 0x076dc419u, 0x706af48fu, 0xe963a535u, 0x9e6495a3u,
+ 0x0edb8832u, 0x79dcb8a4u, 0xe0d5e91eu, 0x97d2d988u,
+ 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u, 0x90bf1d91u,
+ 0x1db71064u, 0x6ab020f2u, 0xf3b97148u, 0x84be41deu,
+ 0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u,
+ 0x136c9856u, 0x646ba8c0u, 0xfd62f97au, 0x8a65c9ecu,
+ 0x14015c4fu, 0x63066cd9u, 0xfa0f3d63u, 0x8d080df5u,
+ 0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u, 0xa2677172u,
+ 0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu,
+ 0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u,
+ 0x32d86ce3u, 0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u,
+ 0x26d930acu, 0x51de003au, 0xc8d75180u, 0xbfd06116u,
+ 0x21b4f4b5u, 0x56b3c423u, 0xcfba9599u, 0xb8bda50fu,
+ 0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u,
+ 0x2f6f7c87u, 0x58684c11u, 0xc1611dabu, 0xb6662d3du,
+ 0x76dc4190u, 0x01db7106u, 0x98d220bcu, 0xefd5102au,
+ 0x71b18589u, 0x06b6b51fu, 0x9fbfe4a5u, 0xe8b8d433u,
+ 0x7807c9a2u, 0x0f00f934u, 0x9609a88eu, 0xe10e9818u,
+ 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u,
+ 0x6b6b51f4u, 0x1c6c6162u, 0x856530d8u, 0xf262004eu,
+ 0x6c0695edu, 0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u,
+ 0x65b0d9c6u, 0x12b7e950u, 0x8bbeb8eau, 0xfcb9887cu,
+ 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u, 0xfbd44c65u,
+ 0x4db26158u, 0x3ab551ceu, 0xa3bc0074u, 0xd4bb30e2u,
+ 0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu,
+ 0x4369e96au, 0x346ed9fcu, 0xad678846u, 0xda60b8d0u,
+ 0x44042d73u, 0x33031de5u, 0xaa0a4c5fu, 0xdd0d7cc9u,
+ 0x5005713cu, 0x270241aau, 0xbe0b1010u, 0xc90c2086u,
+ 0x5768b525u, 0x206f85b3u, 0xb966d409u, 0xce61e49fu,
+ 0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u,
+ 0x59b33d17u, 0x2eb40d81u, 0xb7bd5c3bu, 0xc0ba6cadu,
+ 0xedb88320u, 0x9abfb3b6u, 0x03b6e20cu, 0x74b1d29au,
+ 0xead54739u, 0x9dd277afu, 0x04db2615u, 0x73dc1683u,
+ 0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u,
+ 0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u,
+ 0xf00f9344u, 0x8708a3d2u, 0x1e01f268u, 0x6906c2feu,
+ 0xf762575du, 0x806567cbu, 0x196c3671u, 0x6e6b06e7u,
+ 0xfed41b76u, 0x89d32be0u, 0x10da7a5au, 0x67dd4accu,
+ 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u,
+ 0xd6d6a3e8u, 0xa1d1937eu, 0x38d8c2c4u, 0x4fdff252u,
+ 0xd1bb67f1u, 0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu,
+ 0xd80d2bdau, 0xaf0a1b4cu, 0x36034af6u, 0x41047a60u,
+ 0xdf60efc3u, 0xa867df55u, 0x316e8eefu, 0x4669be79u,
+ 0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u,
+ 0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu,
+ 0xc5ba3bbeu, 0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u,
+ 0xc2d7ffa7u, 0xb5d0cf31u, 0x2cd99e8bu, 0x5bdeae1du,
+ 0x9b64c2b0u, 0xec63f226u, 0x756aa39cu, 0x026d930au,
+ 0x9c0906a9u, 0xeb0e363fu, 0x72076785u, 0x05005713u,
+ 0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u,
+ 0x92d28e9bu, 0xe5d5be0du, 0x7cdcefb7u, 0x0bdbdf21u,
+ 0x86d3d2d4u, 0xf1d4e242u, 0x68ddb3f8u, 0x1fda836eu,
+ 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u, 0x18b74777u,
+ 0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu,
+ 0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u,
+ 0xa00ae278u, 0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u,
+ 0xa7672661u, 0xd06016f7u, 0x4969474du, 0x3e6e77dbu,
+ 0xaed16a4au, 0xd9d65adcu, 0x40df0b66u, 0x37d83bf0u,
+ 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u,
+ 0xbdbdf21cu, 0xcabac28au, 0x53b39330u, 0x24b4a3a6u,
+ 0xbad03605u, 0xcdd70693u, 0x54de5729u, 0x23d967bfu,
+ 0xb3667a2eu, 0xc4614ab8u, 0x5d681b02u, 0x2a6f2b94u,
+ 0xb40bbe37u, 0xc30c8ea1u, 0x5a05df1bu, 0x2d02ef8du
+};
diff --git a/util/crc32c.c b/util/crc32c.c
index ea7f345de8..f40597f80d 100644
--- a/util/crc32c.c
+++ b/util/crc32c.c
@@ -1,7 +1,7 @@
/*
* Castagnoli CRC32C Checksum Algorithm
*
- * Polynomial: 0x11EDC6F41
+ * Polynomial: 0x1EDC6F41
*
* Castagnoli93: Guy Castagnoli and Stefan Braeuer and Martin Herrman
* "Optimization of Cyclic Redundancy-Check Codes with 24
@@ -37,7 +37,7 @@
* reflect output bytes = true
*/
-static const uint32_t crc32c_table[256] = {
+const uint32_t crc32c_table[256] = {
0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
diff --git a/util/meson.build b/util/meson.build
index e7a2a2a64c..d5789b1316 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -44,6 +44,7 @@ util_ss.add(files('id.c'))
util_ss.add(files('qemu-config.c', 'notify.c'))
util_ss.add(files('qemu-option.c', 'qemu-progress.c'))
util_ss.add(files('keyval.c'))
+util_ss.add(files('crc32.c'))
util_ss.add(files('crc32c.c'))
util_ss.add(files('uuid.c'))
util_ss.add(files('getauxval.c'))
--
2.48.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/3] target/riscv: add unratified RISC-V Zbr0p93 ext
2026-03-04 12:11 [PATCH 0/3] RISC-V Zbr0p93 extension James Wainwright
2026-03-04 12:11 ` [PATCH 1/3] util: export CRC32[C] lookup tables James Wainwright
@ 2026-03-04 12:11 ` James Wainwright
2026-03-05 3:14 ` Alistair Francis
2026-03-04 12:11 ` [PATCH 3/3] disas: diassemble RISC-V Zbr0p93 instructions James Wainwright
2 siblings, 1 reply; 8+ messages in thread
From: James Wainwright @ 2026-03-04 12:11 UTC (permalink / raw)
To: qemu-riscv; +Cc: qemu-devel, alistair.francis, James Wainwright
This extension was not ratified with the Zb[abcs] bitmanip extensions.
This is the latest draft version (0.93) as implemented by the Ibex core.
These instructions are in the reserved encoding space but have not been
ratified and could conflict with future ratified instructions.
Signed-off-by: James Wainwright <james.wainwright@lowrisc.org>
---
target/riscv/bitmanip_helper.c | 20 +++++++
target/riscv/cpu.c | 4 +-
target/riscv/cpu_cfg.h | 3 ++
target/riscv/cpu_cfg_fields.h.inc | 1 +
target/riscv/helper.h | 2 +
target/riscv/insn32.decode | 12 +++++
target/riscv/insn_trans/trans_rvb.c.inc | 37 +++++++++++++
tests/tcg/riscv64/Makefile.softmmu-target | 5 ++
tests/tcg/riscv64/test-crc32.S | 64 +++++++++++++++++++++++
9 files changed, 147 insertions(+), 1 deletion(-)
create mode 100644 tests/tcg/riscv64/test-crc32.S
diff --git a/target/riscv/bitmanip_helper.c b/target/riscv/bitmanip_helper.c
index e9c8d7f778..1156a87dd3 100644
--- a/target/riscv/bitmanip_helper.c
+++ b/target/riscv/bitmanip_helper.c
@@ -23,6 +23,8 @@
#include "exec/target_long.h"
#include "exec/helper-proto.h"
#include "tcg/tcg.h"
+#include "qemu/crc32.h"
+#include "qemu/crc32c.h"
target_ulong HELPER(clmul)(target_ulong rs1, target_ulong rs2)
{
@@ -129,3 +131,21 @@ target_ulong HELPER(xperm8)(target_ulong rs1, target_ulong rs2)
{
return do_xperm(rs1, rs2, 3);
}
+
+target_ulong HELPER(crc32)(target_ulong rs1, target_ulong sz)
+{
+ for (target_ulong i = 0; i < sz; i++) {
+ rs1 = crc32_table[rs1 & 0xFF] ^ (rs1 >> 8);
+ }
+
+ return rs1;
+}
+
+target_ulong HELPER(crc32c)(target_ulong rs1, target_ulong sz)
+{
+ for (target_ulong i = 0; i < sz; i++) {
+ rs1 = crc32c_table[rs1 & 0xFF] ^ (rs1 >> 8);
+ }
+
+ return rs1;
+}
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index e56470a374..b83efb210e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1377,6 +1377,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
/* These are experimental so mark with 'x-' */
const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
MULTI_EXT_CFG_BOOL("x-svukte", ext_svukte, false),
+ MULTI_EXT_CFG_BOOL("x-zbr", ext_zbr, false),
{ },
};
@@ -3056,7 +3057,8 @@ static const TypeInfo riscv_cpu_type_infos[] = {
.cfg.ext_zba = true,
.cfg.ext_zbb = true,
.cfg.ext_zbc = true,
- .cfg.ext_zbs = true
+ .cfg.ext_zbs = true,
+ .cfg.ext_zbr = true
),
DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E31, TYPE_RISCV_CPU_SIFIVE_E,
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index cd1cba797c..2f18d16de2 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -70,4 +70,7 @@ MATERIALISE_EXT_PREDICATE(xtheadmempair)
MATERIALISE_EXT_PREDICATE(xtheadsync)
MATERIALISE_EXT_PREDICATE(XVentanaCondOps)
+/* Extensions that are not yet upstream */
+MATERIALISE_EXT_PREDICATE(zbr);
+
#endif
diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc
index 70ec650abf..38cb512010 100644
--- a/target/riscv/cpu_cfg_fields.h.inc
+++ b/target/riscv/cpu_cfg_fields.h.inc
@@ -11,6 +11,7 @@ BOOL_FIELD(ext_zbc)
BOOL_FIELD(ext_zbkb)
BOOL_FIELD(ext_zbkc)
BOOL_FIELD(ext_zbkx)
+BOOL_FIELD(ext_zbr)
BOOL_FIELD(ext_zbs)
BOOL_FIELD(ext_zca)
BOOL_FIELD(ext_zcb)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index b785456ee0..7722c590bd 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -84,6 +84,8 @@ DEF_HELPER_FLAGS_1(unzip, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_1(zip, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_2(xperm4, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_2(xperm8, TCG_CALL_NO_RWG_SE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(crc32, TCG_CALL_NO_RWG_SE, tl, tl, tl)
+DEF_HELPER_FLAGS_2(crc32c, TCG_CALL_NO_RWG_SE, tl, tl, tl)
/* Floating Point - Half Precision */
DEF_HELPER_FLAGS_3(fadd_h, TCG_CALL_NO_RWG, i64, env, i64, i64)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 6e35c4b1e6..97bf9687b7 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -847,6 +847,18 @@ binvi 01101. ........... 001 ..... 0010011 @sh
bset 0010100 .......... 001 ..... 0110011 @r
bseti 00101. ........... 001 ..... 0010011 @sh
+# *** RV32 Zbr Experimental Extension ***
+crc32_b 0110000 10000 ..... 001 ..... 0010011 @r2
+crc32_h 0110000 10001 ..... 001 ..... 0010011 @r2
+crc32_w 0110000 10010 ..... 001 ..... 0010011 @r2
+crc32c_b 0110000 11000 ..... 001 ..... 0010011 @r2
+crc32c_h 0110000 11001 ..... 001 ..... 0010011 @r2
+crc32c_w 0110000 11010 ..... 001 ..... 0010011 @r2
+
+# *** RV64 Zbr Experimental Extension (in addition to RV32 Zbr) ***
+crc32_d 0110000 10011 ..... 001 ..... 0010011 @r2
+crc32c_d 0110000 11011 ..... 001 ..... 0010011 @r2
+
# *** Zfa Standard Extension ***
fli_s 1111000 00001 ..... 000 ..... 1010011 @r2
fli_d 1111001 00001 ..... 000 ..... 1010011 @r2
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc
index e4dcc7c991..59db8b047f 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -36,6 +36,12 @@
} \
} while (0)
+#define REQUIRE_ZBR(ctx) do { \
+ if (!ctx->cfg_ptr->ext_zbr) { \
+ return false; \
+ } \
+} while (0)
+
#define REQUIRE_ZBS(ctx) do { \
if (!ctx->cfg_ptr->ext_zbs) { \
return false; \
@@ -569,3 +575,34 @@ static bool trans_xperm8(DisasContext *ctx, arg_xperm8 *a)
REQUIRE_ZBKX(ctx);
return gen_arith(ctx, a, EXT_NONE, gen_helper_xperm8, NULL);
}
+
+static bool gen_crc(DisasContext *ctx, arg_r2 *a,
+ void (*func)(TCGv, TCGv, TCGv), TCGv tsz)
+{
+ REQUIRE_ZBR(ctx);
+ TCGv dest = dest_gpr(ctx, a->rd);
+ TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
+
+ func(dest, src1, tsz);
+ gen_set_gpr(ctx, a->rd, dest);
+
+ return true;
+}
+
+#define TRANS_CRC32(NAME, SIZE) \
+ static bool trans_crc32_##NAME(DisasContext *ctx, arg_r2 *a) \
+ { if (SIZE == 8) { REQUIRE_64BIT(ctx); }; \
+ return gen_crc(ctx, a, gen_helper_crc32, tcg_constant_tl(SIZE)); }
+#define TRANS_CRC32C(NAME, SIZE) \
+ static bool trans_crc32c_##NAME(DisasContext *ctx, arg_r2 *a) \
+ { if (SIZE == 8) { REQUIRE_64BIT(ctx); }; \
+ return gen_crc(ctx, a, gen_helper_crc32c, tcg_constant_tl(SIZE)); }
+
+TRANS_CRC32(b, 1);
+TRANS_CRC32(h, 2);
+TRANS_CRC32(w, 4);
+TRANS_CRC32(d, 8);
+TRANS_CRC32C(b, 1);
+TRANS_CRC32C(h, 2);
+TRANS_CRC32C(w, 4);
+TRANS_CRC32C(d, 8);
diff --git a/tests/tcg/riscv64/Makefile.softmmu-target b/tests/tcg/riscv64/Makefile.softmmu-target
index eb1ce6504a..f0bf4fa124 100644
--- a/tests/tcg/riscv64/Makefile.softmmu-target
+++ b/tests/tcg/riscv64/Makefile.softmmu-target
@@ -36,5 +36,10 @@ run-plugin-interruptedmemory: interruptedmemory
$(QEMU) -plugin ../plugins/libdiscons.so -d plugin -D $<.pout \
$(QEMU_OPTS)$<)
+EXTRA_RUNS += run-test-crc32
+comma:= ,
+run-test-crc32: test-crc32
+ $(call run-test, $<, $(QEMU) -cpu rv64$(comma)x-zbr=true $(QEMU_OPTS)$<)
+
# We don't currently support the multiarch system tests
undefine MULTIARCH_TESTS
diff --git a/tests/tcg/riscv64/test-crc32.S b/tests/tcg/riscv64/test-crc32.S
new file mode 100644
index 0000000000..70d70b16a9
--- /dev/null
+++ b/tests/tcg/riscv64/test-crc32.S
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2026 lowRISC CIC
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#define crc32(op, rd, rs1) .insn r 19, 1, 48, rd, rs1, x##op
+
+#define crc32_b(rd, rs1) crc32(16, rd, rs1)
+#define crc32_h(rd, rs1) crc32(17, rd, rs1)
+#define crc32_w(rd, rs1) crc32(18, rd, rs1)
+#define crc32_d(rd, rs1) crc32(19, rd, rs1)
+#define crc32c_b(rd, rs1) crc32(24, rd, rs1)
+#define crc32c_h(rd, rs1) crc32(25, rd, rs1)
+#define crc32c_w(rd, rs1) crc32(26, rd, rs1)
+#define crc32c_d(rd, rs1) crc32(27, rd, rs1)
+
+ .option norvc
+
+ .text
+ .globl _start
+_start:
+ lla t0, trap
+ csrw mtvec, t0
+
+ li t0, 0x34e24a2cd65650d4
+
+ crc32_b (t0, t0)
+ crc32_h (t0, t0)
+ crc32_w (t0, t0)
+ crc32_d (t0, t0)
+ crc32c_b (t0, t0)
+ crc32c_h (t0, t0)
+ crc32c_w (t0, t0)
+ crc32c_d (t0, t0)
+
+ li t1, 0x68167e78
+
+ li a0, 0
+ beq t0, t1, _exit
+fail:
+ li a0, 1
+_exit:
+ lla a1, semiargs
+ li t0, 0x20026 # ADP_Stopped_ApplicationExit
+ sd t0, 0(a1)
+ sd a0, 8(a1)
+ li a0, 0x20 # TARGET_SYS_EXIT_EXTENDED
+
+ # Semihosting call sequence
+ .balign 16
+ slli zero, zero, 0x1f
+ ebreak
+ srai zero, zero, 0x7
+ j .
+
+ .data
+ .balign 16
+semiargs:
+ .space 16
+
+trap:
+ csrr t0, mepc
+ addi t0, t0, 4
+ mret
--
2.48.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/3] disas: diassemble RISC-V Zbr0p93 instructions
2026-03-04 12:11 [PATCH 0/3] RISC-V Zbr0p93 extension James Wainwright
2026-03-04 12:11 ` [PATCH 1/3] util: export CRC32[C] lookup tables James Wainwright
2026-03-04 12:11 ` [PATCH 2/3] target/riscv: add unratified RISC-V Zbr0p93 ext James Wainwright
@ 2026-03-04 12:11 ` James Wainwright
2 siblings, 0 replies; 8+ messages in thread
From: James Wainwright @ 2026-03-04 12:11 UTC (permalink / raw)
To: qemu-riscv; +Cc: qemu-devel, alistair.francis, James Wainwright
Placed in a separate file as an unratified extension.
Signed-off-by: James Wainwright <james.wainwright@lowrisc.org>
---
MAINTAINERS | 2 +-
disas/meson.build | 3 +-
disas/riscv-zbr.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++
disas/riscv-zbr.h | 18 +++++++++++
disas/riscv.c | 4 +++
5 files changed, 103 insertions(+), 2 deletions(-)
create mode 100644 disas/riscv-zbr.c
create mode 100644 disas/riscv-zbr.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 6698e5ff69..a3b747148d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4144,7 +4144,7 @@ M: Alistair Francis <Alistair.Francis@wdc.com>
L: qemu-riscv@nongnu.org
S: Maintained
F: tcg/riscv64/
-F: disas/riscv.[ch]
+F: disas/riscv*.[ch]
S390 TCG target
M: Richard Henderson <richard.henderson@linaro.org>
diff --git a/disas/meson.build b/disas/meson.build
index bbfa119783..d549b9b072 100644
--- a/disas/meson.build
+++ b/disas/meson.build
@@ -7,7 +7,8 @@ common_ss.add(when: 'CONFIG_MIPS_DIS', if_true: files('mips.c', 'nanomips.c'))
common_ss.add(when: 'CONFIG_RISCV_DIS', if_true: files(
'riscv.c',
'riscv-xthead.c',
- 'riscv-xventana.c'
+ 'riscv-xventana.c',
+ 'riscv-zbr.c'
))
common_ss.add(when: 'CONFIG_SH4_DIS', if_true: files('sh4.c'))
common_ss.add(when: 'CONFIG_SPARC_DIS', if_true: files('sparc.c'))
diff --git a/disas/riscv-zbr.c b/disas/riscv-zbr.c
new file mode 100644
index 0000000000..b8bde6026a
--- /dev/null
+++ b/disas/riscv-zbr.c
@@ -0,0 +1,78 @@
+/*
+ * QEMU RISC-V Disassembler for Zbr v0.93 (unratified)
+ *
+ * Copyright (c) 2023 Rivos Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+
+#include "disas/riscv.h"
+#include "disas/riscv-zbr.h"
+
+typedef enum {
+ /* 0 is reserved for rv_op_illegal. */
+ rv_op_crc32_b = 1,
+ rv_op_crc32_h = 2,
+ rv_op_crc32_w = 3,
+ rv_op_crc32_d = 4,
+ rv_op_crc32c_b = 5,
+ rv_op_crc32c_h = 6,
+ rv_op_crc32c_w = 7,
+ rv_op_crc32c_d = 8,
+} rv_zbr_op;
+
+const rv_opcode_data rv_zbr_opcode_data[] = {
+ { "illegal", rv_codec_illegal, rv_fmt_none, NULL, 0, 0, 0 },
+ { "crc32.b", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
+ { "crc32.h", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
+ { "crc32.w", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
+ { "crc32.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
+ { "crc32c.b", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
+ { "crc32c.h", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
+ { "crc32c.w", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
+ { "crc32c.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
+};
+
+void decode_zbr(rv_decode *dec, rv_isa isa)
+{
+ rv_inst inst = dec->inst;
+ rv_opcode op = rv_op_illegal;
+
+ switch ((inst >> 0) & 0b1111111) {
+ case 0b0010011:
+ switch ((inst >> 12) & 0b111) {
+ case 0b001:
+ switch ((inst >> 20 & 0b111111111111)) {
+ case 0b011000010000:
+ op = rv_op_crc32_b;
+ break;
+ case 0b011000010001:
+ op = rv_op_crc32_h;
+ break;
+ case 0b011000010010:
+ op = rv_op_crc32_w;
+ break;
+ case 0b011000010011:
+ op = rv_op_crc32_d;
+ break;
+ case 0b011000011000:
+ op = rv_op_crc32c_b;
+ break;
+ case 0b011000011001:
+ op = rv_op_crc32c_h;
+ break;
+ case 0b011000011010:
+ op = rv_op_crc32c_w;
+ break;
+ case 0b011000011011:
+ op = rv_op_crc32c_d;
+ break;
+ }
+ break;
+ }
+ break;
+ }
+ dec->op = op;
+}
diff --git a/disas/riscv-zbr.h b/disas/riscv-zbr.h
new file mode 100644
index 0000000000..327cdaea17
--- /dev/null
+++ b/disas/riscv-zbr.h
@@ -0,0 +1,18 @@
+/*
+ * QEMU RISC-V Disassembler for Zbr v0.93 (unratified)
+ *
+ * Copyright (c) 2023 Rivos Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef DISAS_RISCV_ZBR_H
+#define DISAS_RISCV_ZBR_H
+
+#include "disas/riscv.h"
+
+extern const rv_opcode_data rv_zbr_opcode_data[];
+
+void decode_zbr(rv_decode *, rv_isa);
+
+#endif /* DISAS_RISCV_ZBR_H */
diff --git a/disas/riscv.c b/disas/riscv.c
index 6f2667482d..ebb77ea4ee 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -27,6 +27,9 @@
#include "disas/riscv-xthead.h"
#include "disas/riscv-xventana.h"
+/* Unratified extensions */
+#include "disas/riscv-zbr.h"
+
typedef enum {
/* 0 is reserved for rv_op_illegal. */
rv_op_lui = 1,
@@ -5434,6 +5437,7 @@ static GString *disasm_inst(rv_isa isa, uint64_t pc, rv_inst inst,
{ has_xtheadmempair_p, xthead_opcode_data, decode_xtheadmempair },
{ has_xtheadsync_p, xthead_opcode_data, decode_xtheadsync },
{ has_XVentanaCondOps_p, ventana_opcode_data, decode_xventanacondops },
+ { has_zbr_p, rv_zbr_opcode_data, decode_zbr },
};
for (size_t i = 0; i < ARRAY_SIZE(decoders); i++) {
--
2.48.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] target/riscv: add unratified RISC-V Zbr0p93 ext
2026-03-04 12:11 ` [PATCH 2/3] target/riscv: add unratified RISC-V Zbr0p93 ext James Wainwright
@ 2026-03-05 3:14 ` Alistair Francis
2026-03-05 17:59 ` James Wainwright
0 siblings, 1 reply; 8+ messages in thread
From: Alistair Francis @ 2026-03-05 3:14 UTC (permalink / raw)
To: James Wainwright; +Cc: qemu-riscv, qemu-devel, alistair.francis
On Thu, Mar 5, 2026 at 12:11 AM James Wainwright
<james.wainwright@lowrisc.org> wrote:
>
> This extension was not ratified with the Zb[abcs] bitmanip extensions.
> This is the latest draft version (0.93) as implemented by the Ibex core.
>
> These instructions are in the reserved encoding space but have not been
> ratified and could conflict with future ratified instructions.
Looking at https://github.com/riscv/riscv-bitmanip/issues/188 I assume
that these instructions will never be ratified.
We don't have a policy on what to do with deprecated draft extensions,
but I'm reluctant to add these. At some point in the future they will
conflict with a ratified extension, which will cause all sorts of
issues.
These should probably just be a vendor specific thing
Alistair
>
> Signed-off-by: James Wainwright <james.wainwright@lowrisc.org>
> ---
> target/riscv/bitmanip_helper.c | 20 +++++++
> target/riscv/cpu.c | 4 +-
> target/riscv/cpu_cfg.h | 3 ++
> target/riscv/cpu_cfg_fields.h.inc | 1 +
> target/riscv/helper.h | 2 +
> target/riscv/insn32.decode | 12 +++++
> target/riscv/insn_trans/trans_rvb.c.inc | 37 +++++++++++++
> tests/tcg/riscv64/Makefile.softmmu-target | 5 ++
> tests/tcg/riscv64/test-crc32.S | 64 +++++++++++++++++++++++
> 9 files changed, 147 insertions(+), 1 deletion(-)
> create mode 100644 tests/tcg/riscv64/test-crc32.S
>
> diff --git a/target/riscv/bitmanip_helper.c b/target/riscv/bitmanip_helper.c
> index e9c8d7f778..1156a87dd3 100644
> --- a/target/riscv/bitmanip_helper.c
> +++ b/target/riscv/bitmanip_helper.c
> @@ -23,6 +23,8 @@
> #include "exec/target_long.h"
> #include "exec/helper-proto.h"
> #include "tcg/tcg.h"
> +#include "qemu/crc32.h"
> +#include "qemu/crc32c.h"
>
> target_ulong HELPER(clmul)(target_ulong rs1, target_ulong rs2)
> {
> @@ -129,3 +131,21 @@ target_ulong HELPER(xperm8)(target_ulong rs1, target_ulong rs2)
> {
> return do_xperm(rs1, rs2, 3);
> }
> +
> +target_ulong HELPER(crc32)(target_ulong rs1, target_ulong sz)
> +{
> + for (target_ulong i = 0; i < sz; i++) {
> + rs1 = crc32_table[rs1 & 0xFF] ^ (rs1 >> 8);
> + }
> +
> + return rs1;
> +}
> +
> +target_ulong HELPER(crc32c)(target_ulong rs1, target_ulong sz)
> +{
> + for (target_ulong i = 0; i < sz; i++) {
> + rs1 = crc32c_table[rs1 & 0xFF] ^ (rs1 >> 8);
> + }
> +
> + return rs1;
> +}
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index e56470a374..b83efb210e 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1377,6 +1377,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
> /* These are experimental so mark with 'x-' */
> const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
> MULTI_EXT_CFG_BOOL("x-svukte", ext_svukte, false),
> + MULTI_EXT_CFG_BOOL("x-zbr", ext_zbr, false),
>
> { },
> };
> @@ -3056,7 +3057,8 @@ static const TypeInfo riscv_cpu_type_infos[] = {
> .cfg.ext_zba = true,
> .cfg.ext_zbb = true,
> .cfg.ext_zbc = true,
> - .cfg.ext_zbs = true
> + .cfg.ext_zbs = true,
> + .cfg.ext_zbr = true
> ),
>
> DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E31, TYPE_RISCV_CPU_SIFIVE_E,
> diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
> index cd1cba797c..2f18d16de2 100644
> --- a/target/riscv/cpu_cfg.h
> +++ b/target/riscv/cpu_cfg.h
> @@ -70,4 +70,7 @@ MATERIALISE_EXT_PREDICATE(xtheadmempair)
> MATERIALISE_EXT_PREDICATE(xtheadsync)
> MATERIALISE_EXT_PREDICATE(XVentanaCondOps)
>
> +/* Extensions that are not yet upstream */
> +MATERIALISE_EXT_PREDICATE(zbr);
> +
> #endif
> diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc
> index 70ec650abf..38cb512010 100644
> --- a/target/riscv/cpu_cfg_fields.h.inc
> +++ b/target/riscv/cpu_cfg_fields.h.inc
> @@ -11,6 +11,7 @@ BOOL_FIELD(ext_zbc)
> BOOL_FIELD(ext_zbkb)
> BOOL_FIELD(ext_zbkc)
> BOOL_FIELD(ext_zbkx)
> +BOOL_FIELD(ext_zbr)
> BOOL_FIELD(ext_zbs)
> BOOL_FIELD(ext_zca)
> BOOL_FIELD(ext_zcb)
> diff --git a/target/riscv/helper.h b/target/riscv/helper.h
> index b785456ee0..7722c590bd 100644
> --- a/target/riscv/helper.h
> +++ b/target/riscv/helper.h
> @@ -84,6 +84,8 @@ DEF_HELPER_FLAGS_1(unzip, TCG_CALL_NO_RWG_SE, tl, tl)
> DEF_HELPER_FLAGS_1(zip, TCG_CALL_NO_RWG_SE, tl, tl)
> DEF_HELPER_FLAGS_2(xperm4, TCG_CALL_NO_RWG_SE, tl, tl, tl)
> DEF_HELPER_FLAGS_2(xperm8, TCG_CALL_NO_RWG_SE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(crc32, TCG_CALL_NO_RWG_SE, tl, tl, tl)
> +DEF_HELPER_FLAGS_2(crc32c, TCG_CALL_NO_RWG_SE, tl, tl, tl)
>
> /* Floating Point - Half Precision */
> DEF_HELPER_FLAGS_3(fadd_h, TCG_CALL_NO_RWG, i64, env, i64, i64)
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index 6e35c4b1e6..97bf9687b7 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -847,6 +847,18 @@ binvi 01101. ........... 001 ..... 0010011 @sh
> bset 0010100 .......... 001 ..... 0110011 @r
> bseti 00101. ........... 001 ..... 0010011 @sh
>
> +# *** RV32 Zbr Experimental Extension ***
> +crc32_b 0110000 10000 ..... 001 ..... 0010011 @r2
> +crc32_h 0110000 10001 ..... 001 ..... 0010011 @r2
> +crc32_w 0110000 10010 ..... 001 ..... 0010011 @r2
> +crc32c_b 0110000 11000 ..... 001 ..... 0010011 @r2
> +crc32c_h 0110000 11001 ..... 001 ..... 0010011 @r2
> +crc32c_w 0110000 11010 ..... 001 ..... 0010011 @r2
> +
> +# *** RV64 Zbr Experimental Extension (in addition to RV32 Zbr) ***
> +crc32_d 0110000 10011 ..... 001 ..... 0010011 @r2
> +crc32c_d 0110000 11011 ..... 001 ..... 0010011 @r2
> +
> # *** Zfa Standard Extension ***
> fli_s 1111000 00001 ..... 000 ..... 1010011 @r2
> fli_d 1111001 00001 ..... 000 ..... 1010011 @r2
> diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc
> index e4dcc7c991..59db8b047f 100644
> --- a/target/riscv/insn_trans/trans_rvb.c.inc
> +++ b/target/riscv/insn_trans/trans_rvb.c.inc
> @@ -36,6 +36,12 @@
> } \
> } while (0)
>
> +#define REQUIRE_ZBR(ctx) do { \
> + if (!ctx->cfg_ptr->ext_zbr) { \
> + return false; \
> + } \
> +} while (0)
> +
> #define REQUIRE_ZBS(ctx) do { \
> if (!ctx->cfg_ptr->ext_zbs) { \
> return false; \
> @@ -569,3 +575,34 @@ static bool trans_xperm8(DisasContext *ctx, arg_xperm8 *a)
> REQUIRE_ZBKX(ctx);
> return gen_arith(ctx, a, EXT_NONE, gen_helper_xperm8, NULL);
> }
> +
> +static bool gen_crc(DisasContext *ctx, arg_r2 *a,
> + void (*func)(TCGv, TCGv, TCGv), TCGv tsz)
> +{
> + REQUIRE_ZBR(ctx);
> + TCGv dest = dest_gpr(ctx, a->rd);
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
> +
> + func(dest, src1, tsz);
> + gen_set_gpr(ctx, a->rd, dest);
> +
> + return true;
> +}
> +
> +#define TRANS_CRC32(NAME, SIZE) \
> + static bool trans_crc32_##NAME(DisasContext *ctx, arg_r2 *a) \
> + { if (SIZE == 8) { REQUIRE_64BIT(ctx); }; \
> + return gen_crc(ctx, a, gen_helper_crc32, tcg_constant_tl(SIZE)); }
> +#define TRANS_CRC32C(NAME, SIZE) \
> + static bool trans_crc32c_##NAME(DisasContext *ctx, arg_r2 *a) \
> + { if (SIZE == 8) { REQUIRE_64BIT(ctx); }; \
> + return gen_crc(ctx, a, gen_helper_crc32c, tcg_constant_tl(SIZE)); }
> +
> +TRANS_CRC32(b, 1);
> +TRANS_CRC32(h, 2);
> +TRANS_CRC32(w, 4);
> +TRANS_CRC32(d, 8);
> +TRANS_CRC32C(b, 1);
> +TRANS_CRC32C(h, 2);
> +TRANS_CRC32C(w, 4);
> +TRANS_CRC32C(d, 8);
> diff --git a/tests/tcg/riscv64/Makefile.softmmu-target b/tests/tcg/riscv64/Makefile.softmmu-target
> index eb1ce6504a..f0bf4fa124 100644
> --- a/tests/tcg/riscv64/Makefile.softmmu-target
> +++ b/tests/tcg/riscv64/Makefile.softmmu-target
> @@ -36,5 +36,10 @@ run-plugin-interruptedmemory: interruptedmemory
> $(QEMU) -plugin ../plugins/libdiscons.so -d plugin -D $<.pout \
> $(QEMU_OPTS)$<)
>
> +EXTRA_RUNS += run-test-crc32
> +comma:= ,
> +run-test-crc32: test-crc32
> + $(call run-test, $<, $(QEMU) -cpu rv64$(comma)x-zbr=true $(QEMU_OPTS)$<)
> +
> # We don't currently support the multiarch system tests
> undefine MULTIARCH_TESTS
> diff --git a/tests/tcg/riscv64/test-crc32.S b/tests/tcg/riscv64/test-crc32.S
> new file mode 100644
> index 0000000000..70d70b16a9
> --- /dev/null
> +++ b/tests/tcg/riscv64/test-crc32.S
> @@ -0,0 +1,64 @@
> +/*
> + * Copyright (c) 2026 lowRISC CIC
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#define crc32(op, rd, rs1) .insn r 19, 1, 48, rd, rs1, x##op
> +
> +#define crc32_b(rd, rs1) crc32(16, rd, rs1)
> +#define crc32_h(rd, rs1) crc32(17, rd, rs1)
> +#define crc32_w(rd, rs1) crc32(18, rd, rs1)
> +#define crc32_d(rd, rs1) crc32(19, rd, rs1)
> +#define crc32c_b(rd, rs1) crc32(24, rd, rs1)
> +#define crc32c_h(rd, rs1) crc32(25, rd, rs1)
> +#define crc32c_w(rd, rs1) crc32(26, rd, rs1)
> +#define crc32c_d(rd, rs1) crc32(27, rd, rs1)
> +
> + .option norvc
> +
> + .text
> + .globl _start
> +_start:
> + lla t0, trap
> + csrw mtvec, t0
> +
> + li t0, 0x34e24a2cd65650d4
> +
> + crc32_b (t0, t0)
> + crc32_h (t0, t0)
> + crc32_w (t0, t0)
> + crc32_d (t0, t0)
> + crc32c_b (t0, t0)
> + crc32c_h (t0, t0)
> + crc32c_w (t0, t0)
> + crc32c_d (t0, t0)
> +
> + li t1, 0x68167e78
> +
> + li a0, 0
> + beq t0, t1, _exit
> +fail:
> + li a0, 1
> +_exit:
> + lla a1, semiargs
> + li t0, 0x20026 # ADP_Stopped_ApplicationExit
> + sd t0, 0(a1)
> + sd a0, 8(a1)
> + li a0, 0x20 # TARGET_SYS_EXIT_EXTENDED
> +
> + # Semihosting call sequence
> + .balign 16
> + slli zero, zero, 0x1f
> + ebreak
> + srai zero, zero, 0x7
> + j .
> +
> + .data
> + .balign 16
> +semiargs:
> + .space 16
> +
> +trap:
> + csrr t0, mepc
> + addi t0, t0, 4
> + mret
> --
> 2.48.1
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] util: export CRC32[C] lookup tables
2026-03-04 12:11 ` [PATCH 1/3] util: export CRC32[C] lookup tables James Wainwright
@ 2026-03-05 3:16 ` Alistair Francis
0 siblings, 0 replies; 8+ messages in thread
From: Alistair Francis @ 2026-03-05 3:16 UTC (permalink / raw)
To: James Wainwright; +Cc: qemu-riscv, qemu-devel, alistair.francis
On Thu, Mar 5, 2026 at 12:11 AM James Wainwright
<james.wainwright@lowrisc.org> wrote:
>
> These are needed for the RISC-V Zbr0p93 CRC32 instructions which pre-XOR
> the data into the CRC state before the instruction is executed, making
> the zlib crc32 and QEMU crc32c implementations inappropriate.
>
> https://github.com/riscv/riscv-bitmanip/releases/download/v0.93/bitmanip-0.93.pdf
>
> Signed-off-by: James Wainwright <james.wainwright@lowrisc.org>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Alistair
> ---
> include/qemu/crc32.h | 18 +++++++++
> include/qemu/crc32c.h | 1 +
> util/crc32.c | 85 +++++++++++++++++++++++++++++++++++++++++++
> util/crc32c.c | 4 +-
> util/meson.build | 1 +
> 5 files changed, 107 insertions(+), 2 deletions(-)
> create mode 100644 include/qemu/crc32.h
> create mode 100644 util/crc32.c
>
> diff --git a/include/qemu/crc32.h b/include/qemu/crc32.h
> new file mode 100644
> index 0000000000..a320151acc
> --- /dev/null
> +++ b/include/qemu/crc32.h
> @@ -0,0 +1,18 @@
> +/*
> + * CRC32 Checksum
> + *
> + * Copyright (c) 2026 QEMU contributors
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the Free
> + * Software Foundation; either version 2 of the License, or (at your option)
> + * any later version.
> + *
> + */
> +
> +#ifndef QEMU_CRC32_H
> +#define QEMU_CRC32_H
> +
> +extern const uint32_t crc32_table[256];
> +
> +#endif
> diff --git a/include/qemu/crc32c.h b/include/qemu/crc32c.h
> index 88b4d2b3b3..3d5ba189ef 100644
> --- a/include/qemu/crc32c.h
> +++ b/include/qemu/crc32c.h
> @@ -28,6 +28,7 @@
> #ifndef QEMU_CRC32C_H
> #define QEMU_CRC32C_H
>
> +extern const uint32_t crc32c_table[256];
>
> uint32_t crc32c(uint32_t crc, const uint8_t *data, unsigned int length);
> uint32_t iov_crc32c(uint32_t crc, const struct iovec *iov, size_t iov_cnt);
> diff --git a/util/crc32.c b/util/crc32.c
> new file mode 100644
> index 0000000000..590dd6e3a2
> --- /dev/null
> +++ b/util/crc32.c
> @@ -0,0 +1,85 @@
> +/*
> + * Constants for computing CRC32 checksums
> + *
> + * Copyright (c) 2026 QEMU contributors
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the Free
> + * Software Foundation; either version 2 of the License, or (at your option)
> + * any later version.
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/crc32.h"
> +
> +/*
> + * CRC-32 table (reversed; polynomial 0xEDB88320).
> + */
> +
> +const uint32_t crc32_table[256] = {
> + 0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau,
> + 0x076dc419u, 0x706af48fu, 0xe963a535u, 0x9e6495a3u,
> + 0x0edb8832u, 0x79dcb8a4u, 0xe0d5e91eu, 0x97d2d988u,
> + 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u, 0x90bf1d91u,
> + 0x1db71064u, 0x6ab020f2u, 0xf3b97148u, 0x84be41deu,
> + 0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u,
> + 0x136c9856u, 0x646ba8c0u, 0xfd62f97au, 0x8a65c9ecu,
> + 0x14015c4fu, 0x63066cd9u, 0xfa0f3d63u, 0x8d080df5u,
> + 0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u, 0xa2677172u,
> + 0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu,
> + 0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u,
> + 0x32d86ce3u, 0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u,
> + 0x26d930acu, 0x51de003au, 0xc8d75180u, 0xbfd06116u,
> + 0x21b4f4b5u, 0x56b3c423u, 0xcfba9599u, 0xb8bda50fu,
> + 0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u,
> + 0x2f6f7c87u, 0x58684c11u, 0xc1611dabu, 0xb6662d3du,
> + 0x76dc4190u, 0x01db7106u, 0x98d220bcu, 0xefd5102au,
> + 0x71b18589u, 0x06b6b51fu, 0x9fbfe4a5u, 0xe8b8d433u,
> + 0x7807c9a2u, 0x0f00f934u, 0x9609a88eu, 0xe10e9818u,
> + 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u,
> + 0x6b6b51f4u, 0x1c6c6162u, 0x856530d8u, 0xf262004eu,
> + 0x6c0695edu, 0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u,
> + 0x65b0d9c6u, 0x12b7e950u, 0x8bbeb8eau, 0xfcb9887cu,
> + 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u, 0xfbd44c65u,
> + 0x4db26158u, 0x3ab551ceu, 0xa3bc0074u, 0xd4bb30e2u,
> + 0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu,
> + 0x4369e96au, 0x346ed9fcu, 0xad678846u, 0xda60b8d0u,
> + 0x44042d73u, 0x33031de5u, 0xaa0a4c5fu, 0xdd0d7cc9u,
> + 0x5005713cu, 0x270241aau, 0xbe0b1010u, 0xc90c2086u,
> + 0x5768b525u, 0x206f85b3u, 0xb966d409u, 0xce61e49fu,
> + 0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u,
> + 0x59b33d17u, 0x2eb40d81u, 0xb7bd5c3bu, 0xc0ba6cadu,
> + 0xedb88320u, 0x9abfb3b6u, 0x03b6e20cu, 0x74b1d29au,
> + 0xead54739u, 0x9dd277afu, 0x04db2615u, 0x73dc1683u,
> + 0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u,
> + 0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u,
> + 0xf00f9344u, 0x8708a3d2u, 0x1e01f268u, 0x6906c2feu,
> + 0xf762575du, 0x806567cbu, 0x196c3671u, 0x6e6b06e7u,
> + 0xfed41b76u, 0x89d32be0u, 0x10da7a5au, 0x67dd4accu,
> + 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u,
> + 0xd6d6a3e8u, 0xa1d1937eu, 0x38d8c2c4u, 0x4fdff252u,
> + 0xd1bb67f1u, 0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu,
> + 0xd80d2bdau, 0xaf0a1b4cu, 0x36034af6u, 0x41047a60u,
> + 0xdf60efc3u, 0xa867df55u, 0x316e8eefu, 0x4669be79u,
> + 0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u,
> + 0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu,
> + 0xc5ba3bbeu, 0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u,
> + 0xc2d7ffa7u, 0xb5d0cf31u, 0x2cd99e8bu, 0x5bdeae1du,
> + 0x9b64c2b0u, 0xec63f226u, 0x756aa39cu, 0x026d930au,
> + 0x9c0906a9u, 0xeb0e363fu, 0x72076785u, 0x05005713u,
> + 0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u,
> + 0x92d28e9bu, 0xe5d5be0du, 0x7cdcefb7u, 0x0bdbdf21u,
> + 0x86d3d2d4u, 0xf1d4e242u, 0x68ddb3f8u, 0x1fda836eu,
> + 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u, 0x18b74777u,
> + 0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu,
> + 0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u,
> + 0xa00ae278u, 0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u,
> + 0xa7672661u, 0xd06016f7u, 0x4969474du, 0x3e6e77dbu,
> + 0xaed16a4au, 0xd9d65adcu, 0x40df0b66u, 0x37d83bf0u,
> + 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u,
> + 0xbdbdf21cu, 0xcabac28au, 0x53b39330u, 0x24b4a3a6u,
> + 0xbad03605u, 0xcdd70693u, 0x54de5729u, 0x23d967bfu,
> + 0xb3667a2eu, 0xc4614ab8u, 0x5d681b02u, 0x2a6f2b94u,
> + 0xb40bbe37u, 0xc30c8ea1u, 0x5a05df1bu, 0x2d02ef8du
> +};
> diff --git a/util/crc32c.c b/util/crc32c.c
> index ea7f345de8..f40597f80d 100644
> --- a/util/crc32c.c
> +++ b/util/crc32c.c
> @@ -1,7 +1,7 @@
> /*
> * Castagnoli CRC32C Checksum Algorithm
> *
> - * Polynomial: 0x11EDC6F41
> + * Polynomial: 0x1EDC6F41
> *
> * Castagnoli93: Guy Castagnoli and Stefan Braeuer and Martin Herrman
> * "Optimization of Cyclic Redundancy-Check Codes with 24
> @@ -37,7 +37,7 @@
> * reflect output bytes = true
> */
>
> -static const uint32_t crc32c_table[256] = {
> +const uint32_t crc32c_table[256] = {
> 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
> 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
> 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
> diff --git a/util/meson.build b/util/meson.build
> index e7a2a2a64c..d5789b1316 100644
> --- a/util/meson.build
> +++ b/util/meson.build
> @@ -44,6 +44,7 @@ util_ss.add(files('id.c'))
> util_ss.add(files('qemu-config.c', 'notify.c'))
> util_ss.add(files('qemu-option.c', 'qemu-progress.c'))
> util_ss.add(files('keyval.c'))
> +util_ss.add(files('crc32.c'))
> util_ss.add(files('crc32c.c'))
> util_ss.add(files('uuid.c'))
> util_ss.add(files('getauxval.c'))
> --
> 2.48.1
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] target/riscv: add unratified RISC-V Zbr0p93 ext
2026-03-05 3:14 ` Alistair Francis
@ 2026-03-05 17:59 ` James Wainwright
2026-03-06 0:38 ` Alistair Francis
0 siblings, 1 reply; 8+ messages in thread
From: James Wainwright @ 2026-03-05 17:59 UTC (permalink / raw)
To: Alistair Francis; +Cc: qemu-riscv, qemu-devel, alistair.francis
[-- Attachment #1: Type: text/plain, Size: 951 bytes --]
> We don't have a policy on what to do with deprecated draft extensions,
but I'm reluctant to add these. At some point in the future they will
conflict with a ratified extension, which will cause all sorts of
issues.
Agreed, it's not ideal. FWIW it looks like OpenTitan is moving to use the
ratified `clmul` instructions to implement CRC32 going forward (
https://github.com/lowRISC/opentitan/pull/28511 and
https://github.com/lowRISC/opentitan/pull/29200) but the Earl Grey chip has
already been taped out with Zbr instructions in the ROM, so it would be
nice if we could emulate that upstream.
Does the extension being implemented as experimental and opt-in help,
similar to how `X` extensions share an encoding space? It seems unlikely
for machines other than Earl Grey to use Zbr0p93.
> These should probably just be a vendor specific thing
It's a shame that it's in the ratified encoding space or it would already
be like a vendor extension.
[-- Attachment #2: Type: text/html, Size: 1310 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] target/riscv: add unratified RISC-V Zbr0p93 ext
2026-03-05 17:59 ` James Wainwright
@ 2026-03-06 0:38 ` Alistair Francis
0 siblings, 0 replies; 8+ messages in thread
From: Alistair Francis @ 2026-03-06 0:38 UTC (permalink / raw)
To: James Wainwright; +Cc: qemu-riscv, qemu-devel, alistair.francis
On Fri, Mar 6, 2026 at 4:00 AM James Wainwright
<james.wainwright@lowrisc.org> wrote:
>
> > We don't have a policy on what to do with deprecated draft extensions,
> but I'm reluctant to add these. At some point in the future they will
> conflict with a ratified extension, which will cause all sorts of
> issues.
>
> Agreed, it's not ideal. FWIW it looks like OpenTitan is moving to use the ratified `clmul` instructions to implement CRC32 going forward (https://github.com/lowRISC/opentitan/pull/28511 and https://github.com/lowRISC/opentitan/pull/29200) but the Earl Grey chip has already been taped out with Zbr instructions in the ROM, so it would be nice if we could emulate that upstream.
>
> Does the extension being implemented as experimental and opt-in help, similar to how `X` extensions share an encoding space? It seems unlikely for machines other than Earl Grey to use Zbr0p93.
>
> > These should probably just be a vendor specific thing
>
> It's a shame that it's in the ratified encoding space or it would already be like a vendor extension.
You should still be able to support it, just structure it and name it
as a vendor extension in QEMU instead of a standard RISC-V extension.
Alistair
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-03-06 0:39 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-04 12:11 [PATCH 0/3] RISC-V Zbr0p93 extension James Wainwright
2026-03-04 12:11 ` [PATCH 1/3] util: export CRC32[C] lookup tables James Wainwright
2026-03-05 3:16 ` Alistair Francis
2026-03-04 12:11 ` [PATCH 2/3] target/riscv: add unratified RISC-V Zbr0p93 ext James Wainwright
2026-03-05 3:14 ` Alistair Francis
2026-03-05 17:59 ` James Wainwright
2026-03-06 0:38 ` Alistair Francis
2026-03-04 12:11 ` [PATCH 3/3] disas: diassemble RISC-V Zbr0p93 instructions James Wainwright
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox