* [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support
@ 2026-07-08 16:18 Max Chou
2026-07-08 16:18 ` [PATCH v6 1/9] fpu: Fix biased exponent write in parts_float_to_e5m2 saturate path Max Chou
` (9 more replies)
0 siblings, 10 replies; 11+ messages in thread
From: Max Chou @ 2026-07-08 16:18 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Daniel Henrique Barboza,
Aurelien Jarno, Peter Maydell, Alex Bennée, Weiwei Li,
Liu Zhiwei, Chao Liu, Max Chou
This patchset adds support for the RISC-V Zvfofp8min ISA extension that
provides conversion operations for OCP FP8 formats which provide the
foundation for the future vector matrix extensions.
Ratification status:
- Zvfofp8min is currently v0.9 and is going through the RVIA ratification
process. This series tracks the v0.9 isa-manual tag below.
- riscv-isa-manual tag:
https://github.com/riscv/riscv-isa-manual/releases/tag/zvfofp8min-0.9
Zvfofp8min (v0.9):
- The Zvfofp8min extension provides minimal vector conversion support for
the OFP8 formats. It requires the Zve32f extension and leverages the
altfmt field in the VTYPE CSR (introduced by Zvfbfa) to select between
E4M3 (altfmt=0) and E5M2 (altfmt=1) formats. Per the OCP FP8 spec and
the extension definition:
- Canonical NaN for both E4M3 and E5M2 is 0x7f.
- All NaNs are treated as quiet NaNs.
- Widening conversions are exact: no rounding and no exception flags.
- These conversions are the data-movement primitives that feed and drain
the OFP8 vector/matrix compute pipeline.
- The LLVM RISC-V backend emits these instructions as of LLVM 22.1.0:
https://releases.llvm.org/22.1.0/docs/ReleaseNotes.html#changes-to-the-risc-v-backend
Instructions:
Extended (existing instructions taught to handle OFP8):
- vfwcvtbf16.f.f.v : OFP8 to BF16 widening conversion
- vfncvtbf16.f.f.w : BF16 to OFP8 narrowing conversion
New:
- vfncvtbf16.sat.f.f.w : BF16 to OFP8 narrowing with saturation
- vfncvt.f.f.q : FP32 to OFP8 quad-width (4x) narrowing conversion
- vfncvt.sat.f.f.q : FP32 to OFP8 quad-width narrowing with saturation
Verification:
- riscv-tests (fork https://github.com/riscv-software-src/riscv-tests):
https://github.com/rnax/riscv-tests/tree/dev/rnax/support_zvfofp8min
- Require LLVM 22.1.0
https://releases.llvm.org/22.1.0/docs/ReleaseNotes.html#changes-to-the-risc-v-backend
- Zvfofp8min test target: rv64uzvfofp8min/rv32uzvfofp8min
- Both Spike and QEMU applied this patchset could pass the riscv-tests
References:
- OCP FP8 specification:
https://www.opencompute.org/documents/ocp-8-bit-floating-point-specification-ofp8-revision-1-0-2023-12-01-pdf-1
Changes in v6
- Add patch 1 to fix the biased exponent write bug in the
parts_float_to_e5m2() saturate path. FloatParts64.exp holds an
unbiased exponent, so exp_bias must be subtracted when storing
the max-normal biased exponent value.
- Initialize float_e4m3_nan_is_snan to false in riscv_cpu_reset_hold()
to ensure consistent NaN handling for OFP8 E4M3 operations.
- Merge "Expose Zvfofp8min property" into "Add cfg property for
Zvfofp8min extension" to keep the property registration together
with the cfg field definition.
- Fix indentation of cbo.* opcode table entries in the disas patch.
- Rebase on riscv-to-apply.next (commit 267b5a2)
Changes in v5
- Drop Zvfofp4min which is not going through the RVIA ratification
process yet.
- Fix typos.
- Rebase on riscv-to-apply.next (commit bf76a00)
Changes in v4
- Rebase on riscv-to-apply.next (commit 21101a7)
- Remove the softfloat library related patches (Thanks for RH's help to
split this part)
- Add missing illegal ALTFMT SEW pattern checking for Zvfofp8min in
patch 4 (target/riscv: rvv: Make vfwcvtbf16.f.f.v support OFP8 to BF16
conversion for Zvfofp8min extension)
Changes in v3
- Add floatN_nan_is_snan to simply the quiet/signaling NaN checking flow
in patch 2 & 3
- Add patch 4 to fix pseudo-NaN handling in FPATAN/FYL2XP1/FYL2X helpers
Changes in v2
- Merged v1 patch 2 & 3 to v2 patch 3, v1 patch 4 & 5 to v2 patch 4
- Added new v2 patch 2 to refactor the IEEE format NaN classification
functions (float16, bfloat16, float32, float64) to use internal helper
functions, reducing code duplication and improving maintainability.
The OCP FP8 NaN classification functions follow the same pattern.
- Refactored softfloat implementation to use capability-based FloatFmt
flags (no_infinity, limited_nan, overflow_raises_invalid, normal_frac_max)
instead of monolithic flags
- Removed ocp_fp8e5m2_no_signal_nan and ocp_fp8_same_canonical_nan flags
from float_status; now using local float_status with no_signaling_nans
and default_nan_pattern for RISC-V Zvfofp8min instructions
- Rebased on latest riscv-to-apply.next with zvfbfa v3 patchset
v5: 20260427060928.2322570-1-max.chou@sifive.com
v4: 20260304134006.2908449-1-max.chou@sifive.com
v3: 20260204051756.667397-1-max.chou@sifive.com
v2: 20260127063723.442734-1-max.chou@sifive.com
v1: 20260108151650.16329-1-max.chou@sifive.com
Max Chou (9):
fpu: Fix biased exponent write in parts_float_to_e5m2 saturate path
target/riscv: rvv: Fix NOP_UU_B vs2 width
target/riscv: Add cfg property for Zvfofp8min extension
target/riscv: Add implied rules for Zvfofp8min extension
target/riscv: rvv: Make vfwcvtbf16.f.f.v support OFP8 to BF16
conversion for Zvfofp8min extension
target/riscv: rvv: Make vfncvtbf16.f.f.w support BF16 to OFP8
conversion for Zvfofp8min extension
target/riscv: rvv: Add vfncvtbf16.sat.f.f.w instruction for Zvfofp8min
extension
target/riscv: rvv: Add vfncvt.f.f.q and vfncvt.sat.f.f.q instructions
for Zvfofp8min extension
disas/riscv: Add support of Zvfofp8min extension
disas/riscv.c | 19 ++-
fpu/softfloat.c | 3 +-
target/riscv/cpu.c | 13 +-
target/riscv/cpu_cfg_fields.h.inc | 1 +
target/riscv/helper.h | 12 ++
target/riscv/insn32.decode | 5 +
.../riscv/tcg/insn_trans/trans_rvbf16.c.inc | 32 +++--
.../riscv/tcg/insn_trans/trans_rvofp8.c.inc | 105 +++++++++++++++
target/riscv/tcg/insn_trans/trans_rvv.c.inc | 40 ++++++
target/riscv/tcg/tcg-cpu.c | 5 +
target/riscv/tcg/translate.c | 1 +
target/riscv/tcg/vector_helper.c | 120 +++++++++++++++++-
12 files changed, 338 insertions(+), 18 deletions(-)
create mode 100644 target/riscv/tcg/insn_trans/trans_rvofp8.c.inc
--
2.55.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v6 1/9] fpu: Fix biased exponent write in parts_float_to_e5m2 saturate path
2026-07-08 16:18 [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
@ 2026-07-08 16:18 ` Max Chou
2026-07-08 16:18 ` [PATCH v6 2/9] target/riscv: rvv: Fix NOP_UU_B vs2 width Max Chou
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Max Chou @ 2026-07-08 16:18 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Daniel Henrique Barboza,
Aurelien Jarno, Peter Maydell, Alex Bennée, Weiwei Li,
Liu Zhiwei, Chao Liu, Max Chou
FloatParts64.exp holds an unbiased exponent. Subtract exp_bias to store
the unbiased equivalent of the max-normal biased exponent.
Fixes: d8be49537658 ("fpu: Add conversion routines for OCP FP8 E5M2")
Signed-off-by: Max Chou <max.chou@sifive.com>
---
fpu/softfloat.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index bc244a44ff..e2e53c1d68 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2435,7 +2435,8 @@ static void parts_float_to_e5m2(FloatParts64 *a, float_status *s, bool saturate)
/* Per OCP, conversion in SATURATE mode bounds Inf to MAX. */
if (saturate) {
a->cls = float_class_normal;
- a->exp = float8_e5m2_params.exp_max - 1;
+ a->exp = (float8_e5m2_params.exp_max - 1 -
+ float8_e5m2_params.exp_bias);
a->frac = MAKE_64BIT_MASK(float8_e5m2_params.frac_shift,
float8_e5m2_params.frac_size + 1);
}
--
2.55.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v6 2/9] target/riscv: rvv: Fix NOP_UU_B vs2 width
2026-07-08 16:18 [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
2026-07-08 16:18 ` [PATCH v6 1/9] fpu: Fix biased exponent write in parts_float_to_e5m2 saturate path Max Chou
@ 2026-07-08 16:18 ` Max Chou
2026-07-08 16:18 ` [PATCH v6 3/9] target/riscv: Add cfg property for Zvfofp8min extension Max Chou
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Max Chou @ 2026-07-08 16:18 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Daniel Henrique Barboza,
Aurelien Jarno, Peter Maydell, Alex Bennée, Weiwei Li,
Liu Zhiwei, Chao Liu, Max Chou, Alistair Francis
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
---
target/riscv/tcg/vector_helper.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/riscv/tcg/vector_helper.c b/target/riscv/tcg/vector_helper.c
index e321ca2616..944f176b74 100644
--- a/target/riscv/tcg/vector_helper.c
+++ b/target/riscv/tcg/vector_helper.c
@@ -5019,7 +5019,7 @@ GEN_VEXT_V_ENV(vfwcvtbf16_f_f_v, 4)
/* Narrowing Floating-Point/Integer Type-Convert Instructions */
/* (TD, T2, TX2) */
-#define NOP_UU_B uint8_t, uint16_t, uint32_t
+#define NOP_UU_B uint8_t, uint16_t, uint16_t
#define NOP_UU_H uint16_t, uint32_t, uint32_t
#define NOP_UU_W uint32_t, uint64_t, uint64_t
/* vfncvt.xu.f.v vd, vs2, vm # Convert float to unsigned integer. */
--
2.55.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v6 3/9] target/riscv: Add cfg property for Zvfofp8min extension
2026-07-08 16:18 [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
2026-07-08 16:18 ` [PATCH v6 1/9] fpu: Fix biased exponent write in parts_float_to_e5m2 saturate path Max Chou
2026-07-08 16:18 ` [PATCH v6 2/9] target/riscv: rvv: Fix NOP_UU_B vs2 width Max Chou
@ 2026-07-08 16:18 ` Max Chou
2026-07-08 16:18 ` [PATCH v6 4/9] target/riscv: Add implied rules " Max Chou
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Max Chou @ 2026-07-08 16:18 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Daniel Henrique Barboza,
Aurelien Jarno, Peter Maydell, Alex Bennée, Weiwei Li,
Liu Zhiwei, Chao Liu, Max Chou, Alistair Francis
According to the ISA spec of Zvfofp8min extension,
"The Zvfofp8min extension requires on the Zve32f extension."
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
---
target/riscv/cpu.c | 1 +
target/riscv/cpu_cfg_fields.h.inc | 1 +
target/riscv/tcg/tcg-cpu.c | 5 +++++
target/riscv/tcg/vector_helper.c | 3 ++-
4 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5a82e6563b..38c580a22a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -231,6 +231,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(zvfbfwma, PRIV_VERSION_1_12_0, ext_zvfbfwma),
ISA_EXT_DATA_ENTRY(zvfh, PRIV_VERSION_1_12_0, ext_zvfh),
ISA_EXT_DATA_ENTRY(zvfhmin, PRIV_VERSION_1_12_0, ext_zvfhmin),
+ ISA_EXT_DATA_ENTRY(zvfofp8min, PRIV_VERSION_1_12_0, ext_zvfofp8min),
ISA_EXT_DATA_ENTRY(zvkb, PRIV_VERSION_1_12_0, ext_zvkb),
ISA_EXT_DATA_ENTRY(zvkg, PRIV_VERSION_1_12_0, ext_zvkg),
ISA_EXT_DATA_ENTRY(zvkn, PRIV_VERSION_1_12_0, ext_zvkn),
diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc
index 9eb47af0a7..af78c19a9d 100644
--- a/target/riscv/cpu_cfg_fields.h.inc
+++ b/target/riscv/cpu_cfg_fields.h.inc
@@ -105,6 +105,7 @@ BOOL_FIELD(ext_zvfbfmin)
BOOL_FIELD(ext_zvfbfwma)
BOOL_FIELD(ext_zvfh)
BOOL_FIELD(ext_zvfhmin)
+BOOL_FIELD(ext_zvfofp8min)
BOOL_FIELD(ext_smaia)
BOOL_FIELD(ext_ssaia)
BOOL_FIELD(ext_smctr)
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 4af5cd9c73..5c3f79fbd5 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -639,6 +639,11 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
return;
}
+ if (cpu->cfg.ext_zvfofp8min && !cpu->cfg.ext_zve32f) {
+ error_setg(errp, "Zvfofp8min extension depends on Zve32f extension");
+ return;
+ }
+
if (cpu->cfg.ext_zvfh && !cpu->cfg.ext_zfhmin) {
error_setg(errp, "Zvfh extensions requires Zfhmin extension");
return;
diff --git a/target/riscv/tcg/vector_helper.c b/target/riscv/tcg/vector_helper.c
index 944f176b74..6b736948ff 100644
--- a/target/riscv/tcg/vector_helper.c
+++ b/target/riscv/tcg/vector_helper.c
@@ -38,7 +38,8 @@ static target_ulong vtype_reserved(CPURISCVState *env, target_ulong vtype)
int xlen = riscv_cpu_xlen(env);
target_ulong reserved = 0;
- if (riscv_cpu_cfg(env)->ext_zvfbfa) {
+ if (riscv_cpu_cfg(env)->ext_zvfbfa ||
+ riscv_cpu_cfg(env)->ext_zvfofp8min) {
reserved = vtype & MAKE_64BIT_MASK(R_VTYPE_RESERVED_SHIFT,
xlen - 1 - R_VTYPE_RESERVED_SHIFT);
} else {
--
2.55.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v6 4/9] target/riscv: Add implied rules for Zvfofp8min extension
2026-07-08 16:18 [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
` (2 preceding siblings ...)
2026-07-08 16:18 ` [PATCH v6 3/9] target/riscv: Add cfg property for Zvfofp8min extension Max Chou
@ 2026-07-08 16:18 ` Max Chou
2026-07-08 16:18 ` [PATCH v6 5/9] target/riscv: rvv: Make vfwcvtbf16.f.f.v support OFP8 to BF16 conversion " Max Chou
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Max Chou @ 2026-07-08 16:18 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Daniel Henrique Barboza,
Aurelien Jarno, Peter Maydell, Alex Bennée, Weiwei Li,
Liu Zhiwei, Chao Liu, Max Chou, Alistair Francis
Add implied rules to enable the implied extensions of Zvfofp8min
extension recursively.
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
---
target/riscv/cpu.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 38c580a22a..8cd1a5e056 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -2668,6 +2668,15 @@ static RISCVCPUImpliedExtsRule ZVFHMIN_IMPLIED = {
},
};
+static RISCVCPUImpliedExtsRule ZVFOFP8MIN_IMPLIED = {
+ .ext = CPU_CFG_OFFSET(ext_zvfofp8min),
+ .implied_multi_exts = {
+ CPU_CFG_OFFSET(ext_zve32f),
+
+ RISCV_IMPLIED_EXTS_RULE_END
+ },
+};
+
static RISCVCPUImpliedExtsRule ZVKN_IMPLIED = {
.ext = CPU_CFG_OFFSET(ext_zvkn),
.implied_multi_exts = {
@@ -2826,7 +2835,7 @@ RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[] = {
&ZKS_IMPLIED, &ZVBB_IMPLIED, &ZVE32F_IMPLIED,
&ZVE32X_IMPLIED, &ZVE64D_IMPLIED, &ZVE64F_IMPLIED, &ZVE64X_IMPLIED,
&ZVFBFA_IMPLIED, &ZVFBFMIN_IMPLIED, &ZVFBFWMA_IMPLIED,
- &ZVFH_IMPLIED, &ZVFHMIN_IMPLIED, &ZVKN_IMPLIED,
+ &ZVFH_IMPLIED, &ZVFHMIN_IMPLIED, &ZVFOFP8MIN_IMPLIED, &ZVKN_IMPLIED,
&ZVKNC_IMPLIED, &ZVKNG_IMPLIED, &ZVKNHB_IMPLIED,
&ZVKS_IMPLIED, &ZVKSC_IMPLIED, &ZVKSG_IMPLIED, &SHA_IMPLIED,
&SSCFG_IMPLIED, &SUPM_IMPLIED, &SSPM_IMPLIED, &SMCTR_IMPLIED,
--
2.55.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v6 5/9] target/riscv: rvv: Make vfwcvtbf16.f.f.v support OFP8 to BF16 conversion for Zvfofp8min extension
2026-07-08 16:18 [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
` (3 preceding siblings ...)
2026-07-08 16:18 ` [PATCH v6 4/9] target/riscv: Add implied rules " Max Chou
@ 2026-07-08 16:18 ` Max Chou
2026-07-08 16:18 ` [PATCH v6 6/9] target/riscv: rvv: Make vfncvtbf16.f.f.w support BF16 to OFP8 " Max Chou
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Max Chou @ 2026-07-08 16:18 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Daniel Henrique Barboza,
Aurelien Jarno, Peter Maydell, Alex Bennée, Weiwei Li,
Liu Zhiwei, Chao Liu, Max Chou, Alistair Francis
According to the Zvfofp8min extension, the vfwcvtbf16.f.f.v instruction
supports OFP8 to BF16 conversion when SEW is 8.
And the VTYPE.altfmt field is used to select the OFP8 format.
* altfmt = 0: OFP8.e4m3 to BF16
* altfmt = 1: OFP8.e5m2 to BF16
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
---
target/riscv/cpu.c | 1 +
target/riscv/helper.h | 12 ++
.../riscv/tcg/insn_trans/trans_rvbf16.c.inc | 16 ++-
target/riscv/tcg/vector_helper.c | 115 +++++++++++++++++-
4 files changed, 139 insertions(+), 5 deletions(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 8cd1a5e056..1cc5f33d63 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1076,6 +1076,7 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
set_default_nan_mode(1, &env->fp_status);
/* Default NaN value: sign bit clear, frac msb set */
set_float_default_nan_pattern(0b01000000, &env->fp_status);
+ set_float_e4m3_nan_is_snan(false, &env->fp_status);
env->vill = true;
#ifndef CONFIG_USER_ONLY
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 542b7c264f..3a2d692f9e 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1253,6 +1253,18 @@ DEF_HELPER_5(vfwcvtbf16_f_f_v, void, ptr, ptr, ptr, env, i32)
DEF_HELPER_6(vfwmaccbf16_vv, void, ptr, ptr, ptr, ptr, env, i32)
DEF_HELPER_6(vfwmaccbf16_vf, void, ptr, ptr, i64, ptr, env, i32)
+/* OFP8 functions */
+DEF_HELPER_5(vfwcvtbf16_f_f_v_ofp8e4m3, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(vfwcvtbf16_f_f_v_ofp8e5m2, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(vfncvtbf16_f_f_w_ofp8e4m3, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(vfncvtbf16_f_f_w_ofp8e5m2, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(vfncvtbf16_sat_f_f_w_ofp8e4m3, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(vfncvtbf16_sat_f_f_w_ofp8e5m2, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(vfncvt_f_f_q_ofp8e4m3, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(vfncvt_f_f_q_ofp8e5m2, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(vfncvt_sat_f_f_q_ofp8e4m3, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(vfncvt_sat_f_f_q_ofp8e5m2, void, ptr, ptr, ptr, env, i32)
+
/* Vector crypto functions */
DEF_HELPER_6(vclmul_vv, void, ptr, ptr, ptr, ptr, env, i32)
DEF_HELPER_6(vclmul_vx, void, ptr, ptr, tl, ptr, env, i32)
diff --git a/target/riscv/tcg/insn_trans/trans_rvbf16.c.inc b/target/riscv/tcg/insn_trans/trans_rvbf16.c.inc
index 066dc364c5..86eb86f615 100644
--- a/target/riscv/tcg/insn_trans/trans_rvbf16.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvbf16.c.inc
@@ -92,11 +92,20 @@ static bool trans_vfncvtbf16_f_f_w(DisasContext *ctx, arg_vfncvtbf16_f_f_w *a)
static bool trans_vfwcvtbf16_f_f_v(DisasContext *ctx, arg_vfwcvtbf16_f_f_v *a)
{
REQUIRE_FPU;
- REQUIRE_ZVFBFMIN(ctx);
- if (opfv_widen_check(ctx, a) && (ctx->sew == MO_16)) {
+ if (opfv_widen_check(ctx, a) &&
+ ((ctx->sew == MO_16 && ctx->cfg_ptr->ext_zvfbfmin) ||
+ (ctx->sew == MO_8 && ctx->cfg_ptr->ext_zvfofp8min))) {
+ gen_helper_gvec_3_ptr *fn;
uint32_t data = 0;
+ if (ctx->sew == MO_16) {
+ fn = gen_helper_vfwcvtbf16_f_f_v;
+ } else {
+ fn = ctx->altfmt ? gen_helper_vfwcvtbf16_f_f_v_ofp8e5m2 :
+ gen_helper_vfwcvtbf16_f_f_v_ofp8e4m3;
+ }
+
gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
data = FIELD_DP32(data, VDATA, VM, a->vm);
@@ -106,8 +115,7 @@ static bool trans_vfwcvtbf16_f_f_v(DisasContext *ctx, arg_vfwcvtbf16_f_f_v *a)
tcg_gen_gvec_3_ptr(vreg_ofs(ctx, a->rd), vreg_ofs(ctx, 0),
vreg_ofs(ctx, a->rs2), tcg_env,
ctx->cfg_ptr->vlenb,
- ctx->cfg_ptr->vlenb, data,
- gen_helper_vfwcvtbf16_f_f_v);
+ ctx->cfg_ptr->vlenb, data, fn);
finalize_rvv_inst(ctx);
return true;
}
diff --git a/target/riscv/tcg/vector_helper.c b/target/riscv/tcg/vector_helper.c
index 6b736948ff..306bda7951 100644
--- a/target/riscv/tcg/vector_helper.c
+++ b/target/riscv/tcg/vector_helper.c
@@ -88,7 +88,7 @@ target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1,
switch (vsew) {
case MO_8:
- ill_altfmt &= !(cpu->cfg.ext_zvfbfa);
+ ill_altfmt &= !(cpu->cfg.ext_zvfbfa || cpu->cfg.ext_zvfofp8min);
break;
case MO_16:
ill_altfmt &= !(cpu->cfg.ext_zvfbfa);
@@ -5071,6 +5071,119 @@ GEN_VEXT_V_ENV(vfncvt_f_f_w_w, 4)
RVVCALL(OPFVV1, vfncvtbf16_f_f_w, NOP_UU_H, H2, H4, float32_to_bfloat16)
GEN_VEXT_V_ENV(vfncvtbf16_f_f_w, 2)
+/*
+ * Initialize a local float_status for OCP FP8 narrowing conversions with
+ * RISC-V specific NaN handling: default_nan_pattern = 0x70 produces the
+ * canonical OCP FP8 NaN payload (0x7F) for both E4M3 and E5M2 in default-NaN
+ * mode, per the Zvfofp8min specification.
+ */
+static inline void riscv_ofp8_narrow_status_init(float_status *local,
+ float_status *s)
+{
+ *local = *s;
+ local->default_nan_pattern = 0x70;
+}
+
+/*
+ * OCP FP8 Narrowing Conversions (BF16/F32 -> FP8)
+ * 1. Initialize a local float_status with RISC-V specific NaN handling
+ * 2. Call the softfloat conversion function with saturation parameter
+ * 3. Force the canonical NaN to 0x7f for non-saturating overflow. Per
+ * Zvfofp8min, the canonical NaN for both E4M3 and E5M2 is 0x7f.
+ * 4. Merge exception flags back to the original status
+ */
+#define GEN_OCP_FP8_NARROW(NAME, CONVERT_FN, SATURATE, IN_TYPE) \
+static uint8_t NAME(IN_TYPE a, float_status *s) \
+{ \
+ float_status local; \
+ riscv_ofp8_narrow_status_init(&local, s); \
+ uint8_t result = CONVERT_FN(a, SATURATE, &local); \
+ if (!(SATURATE) && result == 0xff) { \
+ result = 0x7f; \
+ } \
+ s->float_exception_flags |= local.float_exception_flags; \
+ return result; \
+}
+
+/* BF16 -> E4M3/E5M2 conversions */
+GEN_OCP_FP8_NARROW(vfncvt_bf16_to_e4m3, bfloat16_to_float8_e4m3, false,
+ uint16_t)
+GEN_OCP_FP8_NARROW(vfncvt_bf16_to_e5m2, bfloat16_to_float8_e5m2, false,
+ uint16_t)
+GEN_OCP_FP8_NARROW(vfncvt_bf16_to_e4m3_sat, bfloat16_to_float8_e4m3, true,
+ uint16_t)
+GEN_OCP_FP8_NARROW(vfncvt_bf16_to_e5m2_sat, bfloat16_to_float8_e5m2, true,
+ uint16_t)
+
+/* F32 -> E4M3/E5M2 conversions */
+GEN_OCP_FP8_NARROW(vfncvt_f32_to_e4m3, float32_to_float8_e4m3, false, uint32_t)
+GEN_OCP_FP8_NARROW(vfncvt_f32_to_e5m2, float32_to_float8_e5m2, false, uint32_t)
+GEN_OCP_FP8_NARROW(vfncvt_f32_to_e4m3_sat, float32_to_float8_e4m3, true,
+ uint32_t)
+GEN_OCP_FP8_NARROW(vfncvt_f32_to_e5m2_sat, float32_to_float8_e5m2, true,
+ uint32_t)
+
+/*
+ * OCP FP8 Widening Conversions (FP8 -> BF16)
+ * According to Zvfofp8min isa specification: "No rounding occurs, and no
+ * floating-point exception flags are set."
+ * 1. Copy float_status into a local so exception flags can be discarded
+ * 2. Call the softfloat conversion function
+ * 3. Intentionally DISCARD exception flags (not merged back)
+ */
+#define GEN_OCP_FP8_WIDEN(NAME, CONVERT_FN) \
+static uint16_t NAME(uint8_t a, float_status *s) \
+{ \
+ float_status local = *s; \
+ return CONVERT_FN(a, &local); \
+}
+
+GEN_OCP_FP8_WIDEN(vfwcvt_e4m3_to_bf16, float8_e4m3_to_bfloat16)
+GEN_OCP_FP8_WIDEN(vfwcvt_e5m2_to_bf16, float8_e5m2_to_bfloat16)
+
+/* vfwcvtbf16.f.f.w vd, vs2, vm # Convert OFP8 to BF16. */
+RVVCALL(OPFVV1, vfwcvtbf16_f_f_v_ofp8e4m3, WOP_UU_B, H2, H1,
+ vfwcvt_e4m3_to_bf16)
+RVVCALL(OPFVV1, vfwcvtbf16_f_f_v_ofp8e5m2, WOP_UU_B, H2, H1,
+ vfwcvt_e5m2_to_bf16)
+GEN_VEXT_V_ENV(vfwcvtbf16_f_f_v_ofp8e4m3, 2)
+GEN_VEXT_V_ENV(vfwcvtbf16_f_f_v_ofp8e5m2, 2)
+
+/* vfncvtbf16.f.f.w vd, vs2, vm # Convert BF16 to OFP8 without saturation. */
+RVVCALL(OPFVV1, vfncvtbf16_f_f_w_ofp8e4m3, NOP_UU_B, H1, H2,
+ vfncvt_bf16_to_e4m3)
+RVVCALL(OPFVV1, vfncvtbf16_f_f_w_ofp8e5m2, NOP_UU_B, H1, H2,
+ vfncvt_bf16_to_e5m2)
+GEN_VEXT_V_ENV(vfncvtbf16_f_f_w_ofp8e4m3, 1)
+GEN_VEXT_V_ENV(vfncvtbf16_f_f_w_ofp8e5m2, 1)
+
+/* vfncvtbf16.sat.f.f.w vd, vs2, vm # Convert BF16 to OFP8 with saturation. */
+RVVCALL(OPFVV1, vfncvtbf16_sat_f_f_w_ofp8e4m3, NOP_UU_B, H1, H2,
+ vfncvt_bf16_to_e4m3_sat)
+RVVCALL(OPFVV1, vfncvtbf16_sat_f_f_w_ofp8e5m2, NOP_UU_B, H1, H2,
+ vfncvt_bf16_to_e5m2_sat)
+GEN_VEXT_V_ENV(vfncvtbf16_sat_f_f_w_ofp8e4m3, 1)
+GEN_VEXT_V_ENV(vfncvtbf16_sat_f_f_w_ofp8e5m2, 1)
+
+/* Quad-width narrowing type for FP32 to OFP8 */
+#define QOP_UU_B uint8_t, uint32_t, uint32_t
+
+/* vfncvt.f.f.q vd, vs2, vm # Convert FP32 to OFP8. */
+RVVCALL(OPFVV1, vfncvt_f_f_q_ofp8e4m3, QOP_UU_B, H1, H4,
+ vfncvt_f32_to_e4m3)
+RVVCALL(OPFVV1, vfncvt_f_f_q_ofp8e5m2, QOP_UU_B, H1, H4,
+ vfncvt_f32_to_e5m2)
+GEN_VEXT_V_ENV(vfncvt_f_f_q_ofp8e4m3, 1)
+GEN_VEXT_V_ENV(vfncvt_f_f_q_ofp8e5m2, 1)
+
+/* vfncvt.sat.f.f.q vd, vs2, vm # Convert FP32 to OFP8 with saturation. */
+RVVCALL(OPFVV1, vfncvt_sat_f_f_q_ofp8e4m3, QOP_UU_B, H1, H4,
+ vfncvt_f32_to_e4m3_sat)
+RVVCALL(OPFVV1, vfncvt_sat_f_f_q_ofp8e5m2, QOP_UU_B, H1, H4,
+ vfncvt_f32_to_e5m2_sat)
+GEN_VEXT_V_ENV(vfncvt_sat_f_f_q_ofp8e4m3, 1)
+GEN_VEXT_V_ENV(vfncvt_sat_f_f_q_ofp8e5m2, 1)
+
/*
* Vector Reduction Operations
*/
--
2.55.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v6 6/9] target/riscv: rvv: Make vfncvtbf16.f.f.w support BF16 to OFP8 conversion for Zvfofp8min extension
2026-07-08 16:18 [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
` (4 preceding siblings ...)
2026-07-08 16:18 ` [PATCH v6 5/9] target/riscv: rvv: Make vfwcvtbf16.f.f.v support OFP8 to BF16 conversion " Max Chou
@ 2026-07-08 16:18 ` Max Chou
2026-07-08 16:18 ` [PATCH v6 7/9] target/riscv: rvv: Add vfncvtbf16.sat.f.f.w instruction " Max Chou
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Max Chou @ 2026-07-08 16:18 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Daniel Henrique Barboza,
Aurelien Jarno, Peter Maydell, Alex Bennée, Weiwei Li,
Liu Zhiwei, Chao Liu, Max Chou, Alistair Francis
According to the Zvfofp8min extension, the vfncvtbf16.f.f.w instruction
supports BF16 to OFP8 conversion without saturation when SEW is 8.
And the VTYPE.altfmt field is used to select the OFP8 format.
* altfmt = 0: BF16 to OFP8.e4m3
* altfmt = 1: BF16 to OFP8.e5m2
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
---
target/riscv/tcg/insn_trans/trans_rvbf16.c.inc | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/target/riscv/tcg/insn_trans/trans_rvbf16.c.inc b/target/riscv/tcg/insn_trans/trans_rvbf16.c.inc
index 86eb86f615..7e9b0a53a4 100644
--- a/target/riscv/tcg/insn_trans/trans_rvbf16.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvbf16.c.inc
@@ -67,11 +67,20 @@ static bool trans_fcvt_s_bf16(DisasContext *ctx, arg_fcvt_s_bf16 *a)
static bool trans_vfncvtbf16_f_f_w(DisasContext *ctx, arg_vfncvtbf16_f_f_w *a)
{
REQUIRE_FPU;
- REQUIRE_ZVFBFMIN(ctx);
- if (opfv_narrow_check(ctx, a) && (ctx->sew == MO_16)) {
+ if (opfv_narrow_check(ctx, a) &&
+ ((ctx->sew == MO_16 && ctx->cfg_ptr->ext_zvfbfmin) ||
+ (ctx->sew == MO_8 && ctx->cfg_ptr->ext_zvfofp8min))) {
+ gen_helper_gvec_3_ptr *fn;
uint32_t data = 0;
+ if (ctx->sew == MO_16) {
+ fn = gen_helper_vfncvtbf16_f_f_w;
+ } else {
+ fn = ctx->altfmt ? gen_helper_vfncvtbf16_f_f_w_ofp8e5m2 :
+ gen_helper_vfncvtbf16_f_f_w_ofp8e4m3;
+ }
+
gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
data = FIELD_DP32(data, VDATA, VM, a->vm);
@@ -81,8 +90,7 @@ static bool trans_vfncvtbf16_f_f_w(DisasContext *ctx, arg_vfncvtbf16_f_f_w *a)
tcg_gen_gvec_3_ptr(vreg_ofs(ctx, a->rd), vreg_ofs(ctx, 0),
vreg_ofs(ctx, a->rs2), tcg_env,
ctx->cfg_ptr->vlenb,
- ctx->cfg_ptr->vlenb, data,
- gen_helper_vfncvtbf16_f_f_w);
+ ctx->cfg_ptr->vlenb, data, fn);
finalize_rvv_inst(ctx);
return true;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v6 7/9] target/riscv: rvv: Add vfncvtbf16.sat.f.f.w instruction for Zvfofp8min extension
2026-07-08 16:18 [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
` (5 preceding siblings ...)
2026-07-08 16:18 ` [PATCH v6 6/9] target/riscv: rvv: Make vfncvtbf16.f.f.w support BF16 to OFP8 " Max Chou
@ 2026-07-08 16:18 ` Max Chou
2026-07-08 16:18 ` [PATCH v6 8/9] target/riscv: rvv: Add vfncvt.f.f.q and vfncvt.sat.f.f.q instructions " Max Chou
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Max Chou @ 2026-07-08 16:18 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Daniel Henrique Barboza,
Aurelien Jarno, Peter Maydell, Alex Bennée, Weiwei Li,
Liu Zhiwei, Chao Liu, Max Chou, Alistair Francis
The vfncvtbf16.sat.f.f.w instruction converts a vector of 16-bit
floating-point numbers to a vector of 8-bit floating-point numbers with
saturation.
The VTYPE.altfmt field is used to select the format of the 8-bit floating-point
numbers.
* altfmt = 0: BF16 to OFP8.e4m3
* altfmt = 1: BF16 to OFP8.e5m2
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
---
target/riscv/insn32.decode | 3 ++
.../riscv/tcg/insn_trans/trans_rvofp8.c.inc | 42 +++++++++++++++++++
target/riscv/tcg/translate.c | 1 +
3 files changed, 46 insertions(+)
create mode 100644 target/riscv/tcg/insn_trans/trans_rvofp8.c.inc
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 21272fdb50..d690dc3bc1 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -973,6 +973,9 @@ vfwcvtbf16_f_f_v 010010 . ..... 01101 001 ..... 1010111 @r2_vm
vfwmaccbf16_vv 111011 . ..... ..... 001 ..... 1010111 @r_vm
vfwmaccbf16_vf 111011 . ..... ..... 101 ..... 1010111 @r_vm
+# *** Zvfofp8min Extension ***
+vfncvtbf16_sat_f_f_w 010010 . ..... 11111 001 ..... 1010111 @r2_vm
+
# *** Zvbc vector crypto extension ***
vclmul_vv 001100 . ..... ..... 010 ..... 1010111 @r_vm
vclmul_vx 001100 . ..... ..... 110 ..... 1010111 @r_vm
diff --git a/target/riscv/tcg/insn_trans/trans_rvofp8.c.inc b/target/riscv/tcg/insn_trans/trans_rvofp8.c.inc
new file mode 100644
index 0000000000..d28f92e050
--- /dev/null
+++ b/target/riscv/tcg/insn_trans/trans_rvofp8.c.inc
@@ -0,0 +1,42 @@
+/*
+ * RISC-V translation routines for the OFP8 Standard Extensions.
+ *
+ * Copyright (C) 2025 SiFive, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#define REQUIRE_ZVFOFP8MIN(ctx) do { \
+ if (!ctx->cfg_ptr->ext_zvfofp8min) { \
+ return false; \
+ } \
+} while (0)
+
+
+static bool trans_vfncvtbf16_sat_f_f_w(DisasContext *ctx, arg_rmr *a)
+{
+ REQUIRE_FPU;
+ REQUIRE_ZVFOFP8MIN(ctx);
+
+ if (opfv_narrow_check(ctx, a) && ctx->sew == MO_8) {
+ gen_helper_gvec_3_ptr *fn;
+ uint32_t data = 0;
+
+ fn = ctx->altfmt ? gen_helper_vfncvtbf16_sat_f_f_w_ofp8e5m2 :
+ gen_helper_vfncvtbf16_sat_f_f_w_ofp8e4m3;
+
+ gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
+
+ data = FIELD_DP32(data, VDATA, VM, a->vm);
+ data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
+ data = FIELD_DP32(data, VDATA, VTA, ctx->vta);
+ data = FIELD_DP32(data, VDATA, VMA, ctx->vma);
+ tcg_gen_gvec_3_ptr(vreg_ofs(ctx, a->rd), vreg_ofs(ctx, 0),
+ vreg_ofs(ctx, a->rs2), tcg_env,
+ ctx->cfg_ptr->vlenb,
+ ctx->cfg_ptr->vlenb, data, fn);
+ finalize_rvv_inst(ctx);
+ return true;
+ }
+ return false;
+}
diff --git a/target/riscv/tcg/translate.c b/target/riscv/tcg/translate.c
index 9684dbe752..aa96316a38 100644
--- a/target/riscv/tcg/translate.c
+++ b/target/riscv/tcg/translate.c
@@ -1213,6 +1213,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
#include "insn_trans/trans_privileged.c.inc"
#include "insn_trans/trans_svinval.c.inc"
#include "insn_trans/trans_rvbf16.c.inc"
+#include "insn_trans/trans_rvofp8.c.inc"
#include "decode-xthead.c.inc"
#include "decode-xmips.c.inc"
#include "decode-xlrbr.c.inc"
--
2.55.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v6 8/9] target/riscv: rvv: Add vfncvt.f.f.q and vfncvt.sat.f.f.q instructions for Zvfofp8min extension
2026-07-08 16:18 [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
` (6 preceding siblings ...)
2026-07-08 16:18 ` [PATCH v6 7/9] target/riscv: rvv: Add vfncvtbf16.sat.f.f.w instruction " Max Chou
@ 2026-07-08 16:18 ` Max Chou
2026-07-08 16:18 ` [PATCH v6 9/9] disas/riscv: Add support of " Max Chou
2026-07-20 7:25 ` [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
9 siblings, 0 replies; 11+ messages in thread
From: Max Chou @ 2026-07-08 16:18 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Daniel Henrique Barboza,
Aurelien Jarno, Peter Maydell, Alex Bennée, Weiwei Li,
Liu Zhiwei, Chao Liu, Max Chou, Alistair Francis
The vfncvt.f.f.q and vfncvt.sat.f.f.q instructions convert a vector of
FP32 elements to a vector of OFP8 elements. The vfncvt.sat.f.f.q instruction
converts a vector of FP32 elements to a vector of OFP8 elements with saturation.
The VTYPE.altfmt field is used to select the OFP8 format.
* altfmt = 0: FP32 to OFP8.e4m3
* altfmt = 1: FP32 to OFP8.e5m2
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
---
target/riscv/insn32.decode | 2 +
.../riscv/tcg/insn_trans/trans_rvofp8.c.inc | 63 +++++++++++++++++++
target/riscv/tcg/insn_trans/trans_rvv.c.inc | 40 ++++++++++++
3 files changed, 105 insertions(+)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index d690dc3bc1..8a0551abd7 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -974,6 +974,8 @@ vfwmaccbf16_vv 111011 . ..... ..... 001 ..... 1010111 @r_vm
vfwmaccbf16_vf 111011 . ..... ..... 101 ..... 1010111 @r_vm
# *** Zvfofp8min Extension ***
+vfncvt_f_f_q 010010 . ..... 11001 001 ..... 1010111 @r2_vm
+vfncvt_sat_f_f_q 010010 . ..... 11011 001 ..... 1010111 @r2_vm
vfncvtbf16_sat_f_f_w 010010 . ..... 11111 001 ..... 1010111 @r2_vm
# *** Zvbc vector crypto extension ***
diff --git a/target/riscv/tcg/insn_trans/trans_rvofp8.c.inc b/target/riscv/tcg/insn_trans/trans_rvofp8.c.inc
index d28f92e050..619ee4d773 100644
--- a/target/riscv/tcg/insn_trans/trans_rvofp8.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvofp8.c.inc
@@ -12,6 +12,13 @@
} \
} while (0)
+static bool zvfofp8min_narrow_quad_check(DisasContext *s, arg_rmr *a)
+{
+ return require_rvv(s) &&
+ vext_check_isa_ill(s) &&
+ vext_check_sq(s, a->rd, a->rs2, a->vm) &&
+ (s->sew == MO_8);
+}
static bool trans_vfncvtbf16_sat_f_f_w(DisasContext *ctx, arg_rmr *a)
{
@@ -40,3 +47,59 @@ static bool trans_vfncvtbf16_sat_f_f_w(DisasContext *ctx, arg_rmr *a)
}
return false;
}
+
+static bool trans_vfncvt_f_f_q(DisasContext *ctx, arg_rmr *a)
+{
+ REQUIRE_FPU;
+ REQUIRE_ZVFOFP8MIN(ctx);
+
+ if (zvfofp8min_narrow_quad_check(ctx, a)) {
+ gen_helper_gvec_3_ptr *fn;
+ uint32_t data = 0;
+
+ fn = ctx->altfmt ? gen_helper_vfncvt_f_f_q_ofp8e5m2 :
+ gen_helper_vfncvt_f_f_q_ofp8e4m3;
+
+ gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
+
+ data = FIELD_DP32(data, VDATA, VM, a->vm);
+ data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
+ data = FIELD_DP32(data, VDATA, VTA, ctx->vta);
+ data = FIELD_DP32(data, VDATA, VMA, ctx->vma);
+ tcg_gen_gvec_3_ptr(vreg_ofs(ctx, a->rd), vreg_ofs(ctx, 0),
+ vreg_ofs(ctx, a->rs2), tcg_env,
+ ctx->cfg_ptr->vlenb,
+ ctx->cfg_ptr->vlenb, data, fn);
+ finalize_rvv_inst(ctx);
+ return true;
+ }
+ return false;
+}
+
+static bool trans_vfncvt_sat_f_f_q(DisasContext *ctx, arg_rmr *a)
+{
+ REQUIRE_FPU;
+ REQUIRE_ZVFOFP8MIN(ctx);
+
+ if (zvfofp8min_narrow_quad_check(ctx, a)) {
+ gen_helper_gvec_3_ptr *fn;
+ uint32_t data = 0;
+
+ fn = ctx->altfmt ? gen_helper_vfncvt_sat_f_f_q_ofp8e5m2 :
+ gen_helper_vfncvt_sat_f_f_q_ofp8e4m3;
+
+ gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
+
+ data = FIELD_DP32(data, VDATA, VM, a->vm);
+ data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
+ data = FIELD_DP32(data, VDATA, VTA, ctx->vta);
+ data = FIELD_DP32(data, VDATA, VMA, ctx->vma);
+ tcg_gen_gvec_3_ptr(vreg_ofs(ctx, a->rd), vreg_ofs(ctx, 0),
+ vreg_ofs(ctx, a->rs2), tcg_env,
+ ctx->cfg_ptr->vlenb,
+ ctx->cfg_ptr->vlenb, data, fn);
+ finalize_rvv_inst(ctx);
+ return true;
+ }
+ return false;
+}
diff --git a/target/riscv/tcg/insn_trans/trans_rvv.c.inc b/target/riscv/tcg/insn_trans/trans_rvv.c.inc
index 23262b1d03..cccd0f5a25 100644
--- a/target/riscv/tcg/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvv.c.inc
@@ -621,6 +621,46 @@ static bool vext_check_sds(DisasContext *s, int vd, int vs1, int vs2, int vm)
require_align(vs1, s->lmul);
}
+/*
+ * Common check function for vector narrowing instructions
+ * of single-width result (SEW) and quad-width source (4*SEW).
+ *
+ * Rules to be checked here:
+ * 1. The largest vector register group used by an instruction
+ * can not be greater than 8 vector registers
+ * (Section 31.5.2)
+ * 2. Quad-width SEW cannot greater than ELEN.
+ * (Section 31.2)
+ * 3. Source vector register number is multiples of 4 * LMUL.
+ * (Section 31.3.4.2)
+ * 4. Destination vector register number is multiples of LMUL.
+ * (Section 31.3.4.2)
+ * 5. Destination vector register group for a masked vector
+ * instruction cannot overlap the source mask register (v0).
+ * (Section 31.5.3)
+ * risc-v unprivileged spec
+ */
+static bool vext_quad_narrow_check_common(DisasContext *s, int vd, int vs2,
+ int vm)
+{
+ return (s->lmul <= 1) &&
+ (s->sew < MO_32) &&
+ ((s->sew + 2) <= (s->cfg_ptr->elen >> 4)) &&
+ require_align(vs2, s->lmul + 2) &&
+ require_align(vd, s->lmul) &&
+ require_vm(vm, vd);
+}
+
+static bool vext_check_sq(DisasContext *s, int vd, int vs, int vm)
+{
+ bool ret = vext_quad_narrow_check_common(s, vd, vs, vm) &&
+ vext_check_input_eew(s, vs, s->sew + 2, -1, 0, vm);
+ if (vd != vs) {
+ ret &= require_noover(vd, s->lmul, vs, s->lmul + 2);
+ }
+ return ret;
+}
+
/*
* Check function for vector reduction instructions.
*
--
2.55.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v6 9/9] disas/riscv: Add support of Zvfofp8min extension
2026-07-08 16:18 [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
` (7 preceding siblings ...)
2026-07-08 16:18 ` [PATCH v6 8/9] target/riscv: rvv: Add vfncvt.f.f.q and vfncvt.sat.f.f.q instructions " Max Chou
@ 2026-07-08 16:18 ` Max Chou
2026-07-20 7:25 ` [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
9 siblings, 0 replies; 11+ messages in thread
From: Max Chou @ 2026-07-08 16:18 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Daniel Henrique Barboza,
Aurelien Jarno, Peter Maydell, Alex Bennée, Weiwei Li,
Liu Zhiwei, Chao Liu, Max Chou
This patch adds support to disassemble Zvfofp8min instructions.
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
---
disas/riscv.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/disas/riscv.c b/disas/riscv.c
index 7f1b262773..bcda21fb62 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -990,6 +990,9 @@ typedef enum {
rv_op_cbo_flush = 958,
rv_op_cbo_zero = 959,
rv_op_mnret = 960,
+ rv_op_vfncvtbf16_sat_f_f_w = 961,
+ rv_op_vfncvt_f_f_q = 962,
+ rv_op_vfncvt_sat_f_f_q = 963,
} rv_op;
/* register names */
@@ -2260,11 +2263,14 @@ const rv_opcode_data rvi_opcode_data[] = {
rv_op_sspush, 0 },
{ "c.sspopchk", rv_codec_cmop_ss, rv_fmt_rs1, NULL, rv_op_sspopchk,
rv_op_sspopchk, 0 },
- { "cbo.inval", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
- { "cbo.clean", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
- { "cbo.flush", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
- { "cbo.zero", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
- { "mnret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
+ { "cbo.inval", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
+ { "cbo.clean", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
+ { "cbo.flush", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
+ { "cbo.zero", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
+ { "mnret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
+ { "vfncvtbf16.sat.f.f.w", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, 0, 0, 0 },
+ { "vfncvt.f.f.q", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, 0, 0, 0 },
+ { "vfncvt.sat.f.f.q", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, 0, 0, 0 },
};
/* CSR names */
@@ -3660,7 +3666,10 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
case 21: op = rv_op_vfncvt_rod_f_f_w; break;
case 22: op = rv_op_vfncvt_rtz_xu_f_w; break;
case 23: op = rv_op_vfncvt_rtz_x_f_w; break;
+ case 25: op = rv_op_vfncvt_f_f_q; break;
+ case 27: op = rv_op_vfncvt_sat_f_f_q; break;
case 29: op = rv_op_vfncvtbf16_f_f_w; break;
+ case 31: op = rv_op_vfncvtbf16_sat_f_f_w; break;
}
break;
case 19:
--
2.55.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support
2026-07-08 16:18 [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
` (8 preceding siblings ...)
2026-07-08 16:18 ` [PATCH v6 9/9] disas/riscv: Add support of " Max Chou
@ 2026-07-20 7:25 ` Max Chou
9 siblings, 0 replies; 11+ messages in thread
From: Max Chou @ 2026-07-20 7:25 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Daniel Henrique Barboza,
Aurelien Jarno, Peter Maydell, Alex Bennée, Weiwei Li,
Liu Zhiwei, Chao Liu
Gental ping.
On 2026-07-09 00:18, Max Chou wrote:
> This patchset adds support for the RISC-V Zvfofp8min ISA extension that
> provides conversion operations for OCP FP8 formats which provide the
> foundation for the future vector matrix extensions.
>
> Ratification status:
> - Zvfofp8min is currently v0.9 and is going through the RVIA ratification
> process. This series tracks the v0.9 isa-manual tag below.
> - riscv-isa-manual tag:
> https://github.com/riscv/riscv-isa-manual/releases/tag/zvfofp8min-0.9
>
> Zvfofp8min (v0.9):
> - The Zvfofp8min extension provides minimal vector conversion support for
> the OFP8 formats. It requires the Zve32f extension and leverages the
> altfmt field in the VTYPE CSR (introduced by Zvfbfa) to select between
> E4M3 (altfmt=0) and E5M2 (altfmt=1) formats. Per the OCP FP8 spec and
> the extension definition:
> - Canonical NaN for both E4M3 and E5M2 is 0x7f.
> - All NaNs are treated as quiet NaNs.
> - Widening conversions are exact: no rounding and no exception flags.
> - These conversions are the data-movement primitives that feed and drain
> the OFP8 vector/matrix compute pipeline.
> - The LLVM RISC-V backend emits these instructions as of LLVM 22.1.0:
> https://releases.llvm.org/22.1.0/docs/ReleaseNotes.html#changes-to-the-risc-v-backend
>
> Instructions:
> Extended (existing instructions taught to handle OFP8):
> - vfwcvtbf16.f.f.v : OFP8 to BF16 widening conversion
> - vfncvtbf16.f.f.w : BF16 to OFP8 narrowing conversion
> New:
> - vfncvtbf16.sat.f.f.w : BF16 to OFP8 narrowing with saturation
> - vfncvt.f.f.q : FP32 to OFP8 quad-width (4x) narrowing conversion
> - vfncvt.sat.f.f.q : FP32 to OFP8 quad-width narrowing with saturation
>
> Verification:
> - riscv-tests (fork https://github.com/riscv-software-src/riscv-tests):
> https://github.com/rnax/riscv-tests/tree/dev/rnax/support_zvfofp8min
> - Require LLVM 22.1.0
> https://releases.llvm.org/22.1.0/docs/ReleaseNotes.html#changes-to-the-risc-v-backend
> - Zvfofp8min test target: rv64uzvfofp8min/rv32uzvfofp8min
> - Both Spike and QEMU applied this patchset could pass the riscv-tests
>
> References:
> - OCP FP8 specification:
> https://www.opencompute.org/documents/ocp-8-bit-floating-point-specification-ofp8-revision-1-0-2023-12-01-pdf-1
>
>
> Changes in v6
> - Add patch 1 to fix the biased exponent write bug in the
> parts_float_to_e5m2() saturate path. FloatParts64.exp holds an
> unbiased exponent, so exp_bias must be subtracted when storing
> the max-normal biased exponent value.
> - Initialize float_e4m3_nan_is_snan to false in riscv_cpu_reset_hold()
> to ensure consistent NaN handling for OFP8 E4M3 operations.
> - Merge "Expose Zvfofp8min property" into "Add cfg property for
> Zvfofp8min extension" to keep the property registration together
> with the cfg field definition.
> - Fix indentation of cbo.* opcode table entries in the disas patch.
> - Rebase on riscv-to-apply.next (commit 267b5a2)
>
> Changes in v5
> - Drop Zvfofp4min which is not going through the RVIA ratification
> process yet.
> - Fix typos.
> - Rebase on riscv-to-apply.next (commit bf76a00)
>
> Changes in v4
> - Rebase on riscv-to-apply.next (commit 21101a7)
> - Remove the softfloat library related patches (Thanks for RH's help to
> split this part)
> - Add missing illegal ALTFMT SEW pattern checking for Zvfofp8min in
> patch 4 (target/riscv: rvv: Make vfwcvtbf16.f.f.v support OFP8 to BF16
> conversion for Zvfofp8min extension)
>
> Changes in v3
> - Add floatN_nan_is_snan to simply the quiet/signaling NaN checking flow
> in patch 2 & 3
> - Add patch 4 to fix pseudo-NaN handling in FPATAN/FYL2XP1/FYL2X helpers
>
> Changes in v2
> - Merged v1 patch 2 & 3 to v2 patch 3, v1 patch 4 & 5 to v2 patch 4
> - Added new v2 patch 2 to refactor the IEEE format NaN classification
> functions (float16, bfloat16, float32, float64) to use internal helper
> functions, reducing code duplication and improving maintainability.
> The OCP FP8 NaN classification functions follow the same pattern.
> - Refactored softfloat implementation to use capability-based FloatFmt
> flags (no_infinity, limited_nan, overflow_raises_invalid, normal_frac_max)
> instead of monolithic flags
> - Removed ocp_fp8e5m2_no_signal_nan and ocp_fp8_same_canonical_nan flags
> from float_status; now using local float_status with no_signaling_nans
> and default_nan_pattern for RISC-V Zvfofp8min instructions
> - Rebased on latest riscv-to-apply.next with zvfbfa v3 patchset
>
> v5: 20260427060928.2322570-1-max.chou@sifive.com
> v4: 20260304134006.2908449-1-max.chou@sifive.com
> v3: 20260204051756.667397-1-max.chou@sifive.com
> v2: 20260127063723.442734-1-max.chou@sifive.com
> v1: 20260108151650.16329-1-max.chou@sifive.com
>
>
> Max Chou (9):
> fpu: Fix biased exponent write in parts_float_to_e5m2 saturate path
> target/riscv: rvv: Fix NOP_UU_B vs2 width
> target/riscv: Add cfg property for Zvfofp8min extension
> target/riscv: Add implied rules for Zvfofp8min extension
> target/riscv: rvv: Make vfwcvtbf16.f.f.v support OFP8 to BF16
> conversion for Zvfofp8min extension
> target/riscv: rvv: Make vfncvtbf16.f.f.w support BF16 to OFP8
> conversion for Zvfofp8min extension
> target/riscv: rvv: Add vfncvtbf16.sat.f.f.w instruction for Zvfofp8min
> extension
> target/riscv: rvv: Add vfncvt.f.f.q and vfncvt.sat.f.f.q instructions
> for Zvfofp8min extension
> disas/riscv: Add support of Zvfofp8min extension
>
> disas/riscv.c | 19 ++-
> fpu/softfloat.c | 3 +-
> target/riscv/cpu.c | 13 +-
> target/riscv/cpu_cfg_fields.h.inc | 1 +
> target/riscv/helper.h | 12 ++
> target/riscv/insn32.decode | 5 +
> .../riscv/tcg/insn_trans/trans_rvbf16.c.inc | 32 +++--
> .../riscv/tcg/insn_trans/trans_rvofp8.c.inc | 105 +++++++++++++++
> target/riscv/tcg/insn_trans/trans_rvv.c.inc | 40 ++++++
> target/riscv/tcg/tcg-cpu.c | 5 +
> target/riscv/tcg/translate.c | 1 +
> target/riscv/tcg/vector_helper.c | 120 +++++++++++++++++-
> 12 files changed, 338 insertions(+), 18 deletions(-)
> create mode 100644 target/riscv/tcg/insn_trans/trans_rvofp8.c.inc
>
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-07-20 7:26 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-08 16:18 [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
2026-07-08 16:18 ` [PATCH v6 1/9] fpu: Fix biased exponent write in parts_float_to_e5m2 saturate path Max Chou
2026-07-08 16:18 ` [PATCH v6 2/9] target/riscv: rvv: Fix NOP_UU_B vs2 width Max Chou
2026-07-08 16:18 ` [PATCH v6 3/9] target/riscv: Add cfg property for Zvfofp8min extension Max Chou
2026-07-08 16:18 ` [PATCH v6 4/9] target/riscv: Add implied rules " Max Chou
2026-07-08 16:18 ` [PATCH v6 5/9] target/riscv: rvv: Make vfwcvtbf16.f.f.v support OFP8 to BF16 conversion " Max Chou
2026-07-08 16:18 ` [PATCH v6 6/9] target/riscv: rvv: Make vfncvtbf16.f.f.w support BF16 to OFP8 " Max Chou
2026-07-08 16:18 ` [PATCH v6 7/9] target/riscv: rvv: Add vfncvtbf16.sat.f.f.w instruction " Max Chou
2026-07-08 16:18 ` [PATCH v6 8/9] target/riscv: rvv: Add vfncvt.f.f.q and vfncvt.sat.f.f.q instructions " Max Chou
2026-07-08 16:18 ` [PATCH v6 9/9] disas/riscv: Add support of " Max Chou
2026-07-20 7:25 ` [PATCH v6 0/9] target/riscv: Add RISC-V Zvfofp8min extension support Max Chou
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.