On Mon, Feb 23, 2026 at 07:21:54PM +1100, Richard Henderson wrote:
> From: Max Chou <[email protected]>
> 
> Signed-off-by: Max Chou <[email protected]>
> [rth: Update for exp_max_kind]
> Signed-off-by: Richard Henderson <[email protected]>
> ---
>  include/fpu/softfloat-types.h |  1 +
>  include/fpu/softfloat.h       |  4 +++-
>  fpu/softfloat.c               | 26 ++++++++++++++++++++++++++
>  3 files changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
> index 9c84a101e5..ead146c22d 100644
> --- a/include/fpu/softfloat-types.h
> +++ b/include/fpu/softfloat-types.h
> @@ -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;
>  
> diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
> index 31d3f76d3f..8389a07b04 100644
> --- a/include/fpu/softfloat.h
> +++ b/include/fpu/softfloat.h
> @@ -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);
> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> index 6e21882ab2..91c34307c8 100644
> --- a/fpu/softfloat.c
> +++ b/fpu/softfloat.c
> @@ -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;
> -- 
> 2.43.0
> 

Reviewed-by: Chao Liu <[email protected]>

Thanks,
Chao

Reply via email to