@samitouri / QOSamiQemu / commits / b5fee33bbf

fpu: Add conversion routines for OCP FP4 E2M1

Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Signed-off-by: Max Chou <max.chou@sifive.com> [rth: Update for exp_max_kind] Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Max Chou committed Feb 5, 2026 at 21:10 UTC b5fee33bbf2764e9540ab5e6b6af4c9493f65677
3 files changed +30 -1
fpu/softfloat.c
+26
@@ -574,6 +574,11 @@ typedef struct {
574 .frac_shift = (-F - 1) & 63, \
575 .round_mask = (1ull << ((-F - 1) & 63)) - 1
576
577 +static const FloatFmt float4_e2m1_params = {
578 + FLOAT_PARAMS(2, 1),
579 + .exp_max_kind = float_expmax_normal,
580 +};
581 +
582 static const FloatFmt float8_e4m3_params = {
583 FLOAT_PARAMS(4, 3),
584 .exp_max_kind = float_expmax_e4m3
@@ -641,6 +646,11 @@ static void unpack_raw64(FloatParts64 *r, const FloatFmt *fmt, uint64_t raw)
646 };
647 }
648
649 +static void QEMU_FLATTEN float4_e2m1_unpack_raw(FloatParts64 *p, float4_e2m1 f)
650 +{
651 + unpack_raw64(p, &float4_e2m1_params, f);
652 +}
653 +
654 static void QEMU_FLATTEN float8_e4m3_unpack_raw(FloatParts64 *p, float8_e4m3 f)
655 {
656 unpack_raw64(p, &float8_e4m3_params, f);
@@ -1709,6 +1719,13 @@ static const uint16_t rsqrt_tab[128] = {
1719 * Pack/unpack routines with a specific FloatFmt.
1720 */
1721
1722 +static void float4_e2m1_unpack_canonical(FloatParts64 *p, float4_e2m1 f,
1723 + float_status *s)
1724 +{
1725 + float4_e2m1_unpack_raw(p, f);
1726 + parts_canonicalize(p, s, &float4_e2m1_params);
1727 +}
1728 +
1729 static void float8_e4m3_unpack_canonical(FloatParts64 *p, float8_e4m3 f,
1730 float_status *s)
1731 {
@@ -2929,6 +2946,15 @@ static void parts_float_to_float_widen(FloatParts128 *a, FloatParts64 *b,
2946 }
2947 }
2948
2949 +float8_e4m3 float4_e2m1_to_float8_e4m3(float4_e2m1 a, float_status *s)
2950 +{
2951 + FloatParts64 p;
2952 +
2953 + float4_e2m1_unpack_canonical(&p, a, s);
2954 + parts_float_to_float(&p, s);
2955 + return float8_e4m3_round_pack_canonical(&p, s, false);
2956 +}
2957 +
2958 bfloat16 float8_e4m3_to_bfloat16(float8_e4m3 a, float_status *s)
2959 {
2960 FloatParts64 p;
include/fpu/softfloat-types.h
+1
@@ -122,6 +122,7 @@ typedef uint16_t bfloat16;
122 /*
123 * Open Compute Project (OCP) Microscaling Formats
124 */
125 +typedef uint8_t float4_e2m1;
126 typedef uint8_t float8_e4m3;
127 typedef uint8_t float8_e5m2;
128
include/fpu/softfloat.h
+3 -1
@@ -190,9 +190,11 @@ float128 uint64_to_float128(uint64_t, float_status *status);
190 float128 uint128_to_float128(Int128, float_status *status);
191
192 /*----------------------------------------------------------------------------
193 -| OCP FP8 conversion routines.
193 +| OCP FP{4,8} conversion routines.
194 *----------------------------------------------------------------------------*/
195
196 +float8_e4m3 float4_e2m1_to_float8_e4m3(float4_e2m1, float_status *status);
197 +
198 bfloat16 float8_e4m3_to_bfloat16(float8_e4m3, float_status *status);
199 float8_e4m3 bfloat16_to_float8_e4m3(bfloat16, bool sat, float_status *status);
200 float8_e4m3 float32_to_float8_e4m3(float32, bool sat, float_status *status);