]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
fpu: Add conversion routines for OCP FP4 E2M1
authorMax Chou <max.chou@sifive.com>
Thu, 5 Feb 2026 11:10:46 +0000 (21:10 +1000)
committerRichard Henderson <richard.henderson@linaro.org>
Tue, 24 Feb 2026 05:21:18 +0000 (16:21 +1100)
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>
fpu/softfloat.c
include/fpu/softfloat-types.h
include/fpu/softfloat.h

index 6e21882ab2cb4b02f28fc5eb36d809fbfdbe7704..91c34307c8e50377711ea2a24c986d2118b2e180 100644 (file)
@@ -574,6 +574,11 @@ typedef struct {
     .frac_shift     = (-F - 1) & 63,                    \
     .round_mask     = (1ull << ((-F - 1) & 63)) - 1
 
+static const FloatFmt float4_e2m1_params = {
+    FLOAT_PARAMS(2, 1),
+    .exp_max_kind = float_expmax_normal,
+};
+
 static const FloatFmt float8_e4m3_params = {
     FLOAT_PARAMS(4, 3),
     .exp_max_kind = float_expmax_e4m3
@@ -641,6 +646,11 @@ static void unpack_raw64(FloatParts64 *r, const FloatFmt *fmt, uint64_t raw)
     };
 }
 
+static void QEMU_FLATTEN float4_e2m1_unpack_raw(FloatParts64 *p, float4_e2m1 f)
+{
+    unpack_raw64(p, &float4_e2m1_params, f);
+}
+
 static void QEMU_FLATTEN float8_e4m3_unpack_raw(FloatParts64 *p, float8_e4m3 f)
 {
     unpack_raw64(p, &float8_e4m3_params, f);
@@ -1709,6 +1719,13 @@ static const uint16_t rsqrt_tab[128] = {
  * Pack/unpack routines with a specific FloatFmt.
  */
 
+static void float4_e2m1_unpack_canonical(FloatParts64 *p, float4_e2m1 f,
+                                         float_status *s)
+{
+    float4_e2m1_unpack_raw(p, f);
+    parts_canonicalize(p, s, &float4_e2m1_params);
+}
+
 static void float8_e4m3_unpack_canonical(FloatParts64 *p, float8_e4m3 f,
                                          float_status *s)
 {
@@ -2929,6 +2946,15 @@ static void parts_float_to_float_widen(FloatParts128 *a, FloatParts64 *b,
     }
 }
 
+float8_e4m3 float4_e2m1_to_float8_e4m3(float4_e2m1 a, float_status *s)
+{
+    FloatParts64 p;
+
+    float4_e2m1_unpack_canonical(&p, a, s);
+    parts_float_to_float(&p, s);
+    return float8_e4m3_round_pack_canonical(&p, s, false);
+}
+
 bfloat16 float8_e4m3_to_bfloat16(float8_e4m3 a, float_status *s)
 {
     FloatParts64 p;
index 9c84a101e5d0fc490877366833c4c0341c1581f7..ead146c22d6c7f4cab7b0d9ab7c5d8ab8ca36d0d 100644 (file)
@@ -122,6 +122,7 @@ typedef uint16_t bfloat16;
 /*
  * Open Compute Project (OCP) Microscaling Formats
  */
+typedef uint8_t float4_e2m1;
 typedef uint8_t float8_e4m3;
 typedef uint8_t float8_e5m2;
 
index 31d3f76d3faec1a8f47166b92dc420dca02c63bd..8389a07b04b7402d9505a9b21c5f6951bdae3f8f 100644 (file)
@@ -190,9 +190,11 @@ float128 uint64_to_float128(uint64_t, float_status *status);
 float128 uint128_to_float128(Int128, float_status *status);
 
 /*----------------------------------------------------------------------------
-| OCP FP8 conversion routines.
+| OCP FP{4,8} conversion routines.
 *----------------------------------------------------------------------------*/
 
+float8_e4m3 float4_e2m1_to_float8_e4m3(float4_e2m1, float_status *status);
+
 bfloat16 float8_e4m3_to_bfloat16(float8_e4m3, float_status *status);
 float8_e4m3 bfloat16_to_float8_e4m3(bfloat16, bool sat, float_status *status);
 float8_e4m3 float32_to_float8_e4m3(float32, bool sat, float_status *status);