Hi, Max:

On 1/8/2026 11:16 PM, Max Chou wrote:
> This commit provides the implementation defined behavior flags and the basic
> operation support for the OCP float8 data types(E4M3 & E5M2).
>
> Signed-off-by: Max Chou <[email protected]>
> ---
>  fpu/softfloat-specialize.c.inc  | 57 ++++++++++++++++++++++++++-
>  include/fpu/softfloat-helpers.h | 20 ++++++++++
>  include/fpu/softfloat-types.h   | 23 +++++++++++
>  include/fpu/softfloat.h         | 70 +++++++++++++++++++++++++++++++++
>  4 files changed, 169 insertions(+), 1 deletion(-)
>
> diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
> index ba4fa08b7b..3a3bcd22ae 100644
> --- a/fpu/softfloat-specialize.c.inc
> +++ b/fpu/softfloat-specialize.c.inc
> @@ -226,6 +226,30 @@ floatx80 floatx80_default_inf(bool zSign, float_status 
> *status)
>      return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
>  }
>
> +/*----------------------------------------------------------------------------
> +| Returns 1 if the OCP(Open Compute Platform) FP8 value `a' is a quiet NaN;
Open Compute Platform -> Open Compute Project

> +| otherwise returns 0.
> +*----------------------------------------------------------------------------*/
> +
> +bool float8_e4m3_is_quiet_nan(float8_e4m3 a_, float_status *status)
> +{
> +    return float8_e4m3_is_any_nan(a_);
> +}
> +
...
> +/*----------------------------------------------------------------------------
> +| Returns 1 if the OCP(Open Compute Platform) FP8 value `a' is a signaling 
> NaN;
Open Compute Platform -> Open Compute Project

Thanks,
Chao

> +| otherwise returns 0.
> +*----------------------------------------------------------------------------*/
> +
> +bool float8_e4m3_is_signaling_nan(float8_e4m3 a_, float_status *status)
> +{
> +    if (no_signaling_nans(status)) {
> +        return false;
> +    } else {
> +        if (snan_bit_is_one(status)) {
> +            return float8_e4m3_is_any_nan(a_);
> +        } else {
> +            return false;
> +        }
> +    }
> +}
> +
> +bool float8_e5m2_is_signaling_nan(float8_e5m2 a_, float_status *status)
> +{
> +    if (no_signaling_nans(status)) {
> +        return false;
> +    } else {
> +        uint8_t a = float8_e5m2_val(a_);
> +        if (snan_bit_is_one(status)) {
> +            return ((a >> 1) & 0x3F) == 0x3F;
> +        } else {
> +            return (((a >> 1) & 0x3F) == 0x3E && (a & 0x1));
> +        }
> +    }
> +}
> +
>  
> /*----------------------------------------------------------------------------
>  | Returns 1 if the half-precision floating-point value `a' is a signaling
>  | NaN; otherwise returns 0.
> diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
> index 90862f5cd2..4e278a3ee3 100644
> --- a/include/fpu/softfloat-helpers.h
> +++ b/include/fpu/softfloat-helpers.h
> @@ -136,6 +136,26 @@ static inline void set_no_signaling_nans(bool val, 
> float_status *status)
>      status->no_signaling_nans = val;
>  }
>
> +static inline void set_ocp_fp8e5m2_no_signal_nan(bool val, float_status 
> *status)
> +{
> +    status->ocp_fp8e5m2_no_signal_nan = val;
> +}
> +
> +static inline bool get_ocp_fp8e5m2_no_signal_nan(const float_status *status)
> +{
> +    return status->ocp_fp8e5m2_no_signal_nan;
> +}
> +
> +static inline void set_ocp_fp8_same_canonical_nan(bool val, float_status 
> *status)
> +{
> +    status->ocp_fp8_same_canonical_nan = val;
> +}
> +
> +static inline bool get_ocp_fp8_same_canonical_nan(const float_status *status)
> +{
> +    return status->ocp_fp8_same_canonical_nan;
> +}
> +
>  static inline bool get_float_detect_tininess(const float_status *status)
>  {
>      return status->tininess_before_rounding;
> diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
> index 8f82fdfc97..835dd33bf1 100644
> --- a/include/fpu/softfloat-types.h
> +++ b/include/fpu/softfloat-types.h
> @@ -119,6 +119,18 @@ typedef struct {
>   */
>  typedef uint16_t bfloat16;
>
> +/*
> + * Software OCP(Open Compute Project) 8-bit floating point types
> + */
> +typedef uint8_t float8_e4m3;
> +typedef uint8_t float8_e5m2;
> +#define float8_e4m3_val(x) (x)
> +#define float8_e5m2_val(x) (x)
> +#define make_float8_e4m3(x) (x)
> +#define make_float8_e5m2(x) (x)
> +#define const_float8_e4m3(x) (x)
> +#define const_float8_e5m2(x) (x)
> +
>  /*
>   * Software IEC/IEEE floating-point underflow tininess-detection mode.
>   */
> @@ -410,6 +422,17 @@ typedef struct float_status {
>       */
>      bool snan_bit_is_one;
>      bool no_signaling_nans;
> +    /*
> +     * When true, OCP FP8 E5M2 format does not generate signaling NaNs.
> +     * RISC-V uses only quiet NaNs in its OCP FP8 implementation.
> +     */
> +    bool ocp_fp8e5m2_no_signal_nan;
> +    /*
> +     * When true, OCP FP8 formats use the same canonical NaN representation
> +     * (0x7F) for all NaN outputs. RISC-V specifies a single canonical NaN
> +     * for both E4M3 and E5M2.
> +     */
> +    bool ocp_fp8_same_canonical_nan;
>      /* should overflowed results subtract re_bias to its exponent? */
>      bool rebias_overflow;
>      /* should underflowed results add re_bias to its exponent? */
> diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
> index c18ab2cb60..6f7259f9dd 100644
> --- a/include/fpu/softfloat.h
> +++ b/include/fpu/softfloat.h
> @@ -189,6 +189,76 @@ float128 int128_to_float128(Int128, float_status 
> *status);
>  float128 uint64_to_float128(uint64_t, float_status *status);
>  float128 uint128_to_float128(Int128, float_status *status);
>
> +/*----------------------------------------------------------------------------
> +| Software OCP FP8 operations.
> +*----------------------------------------------------------------------------*/
> +
> +bool float8_e4m3_is_quiet_nan(float8_e4m3, float_status *status);
> +bool float8_e4m3_is_signaling_nan(float8_e4m3, float_status *status);
> +bool float8_e5m2_is_quiet_nan(float8_e5m2, float_status *status);
> +bool float8_e5m2_is_signaling_nan(float8_e5m2, float_status *status);
> +
> +static inline bool float8_e4m3_is_any_nan(float8_e4m3 a)
> +{
> +    return ((float8_e4m3_val(a) & ~0x80) == 0x7f);
> +}
> +
> +static inline bool float8_e5m2_is_any_nan(float8_e5m2 a)
> +{
> +    return ((float8_e5m2_val(a) & ~0x80) > 0x7c);
> +}
> +
> +static inline bool float8_e4m3_is_neg(float8_e4m3 a)
> +{
> +    return float8_e4m3_val(a) >> 7;
> +}
> +
> +static inline bool float8_e5m2_is_neg(float8_e5m2 a)
> +{
> +    return float8_e5m2_val(a) >> 7;
> +}
> +
> +static inline bool float8_e4m3_is_infinity(float8_e4m3 a)
> +{
> +    return false;
> +}
> +
> +static inline bool float8_e5m2_is_infinity(float8_e5m2 a)
> +{
> +    return (float8_e5m2_val(a) & 0x7f) == 0x7c;
> +}
> +
> +static inline bool float8_e4m3_is_zero(float8_e4m3 a)
> +{
> +    return (float8_e4m3_val(a) & 0x7f) == 0;
> +}
> +
> +static inline bool float8_e5m2_is_zero(float8_e5m2 a)
> +{
> +    return (float8_e5m2_val(a) & 0x7f) == 0;
> +}
> +
> +static inline bool float8_e4m3_is_zero_or_denormal(float8_e4m3 a)
> +{
> +    return (float8_e4m3_val(a) & 0x78) == 0;
> +}
> +
> +static inline bool float8_e5m2_is_zero_or_denormal(float8_e5m2 a)
> +{
> +    return (float8_e5m2_val(a) & 0x7c) == 0;
> +}
> +
> +static inline bool float8_e4m3_is_normal(float8_e4m3 a)
> +{
> +    uint8_t em = float8_e4m3_val(a) & 0x7f;
> +    return em >= 0x8 && em <= 0x7e;
> +}
> +
> +static inline bool float8_e5m2_is_normal(float8_e5m2 a)
> +{
> +    return (((float8_e5m2_val(a) >> 2) + 1) & 0x1f) >= 2;
> +}
> +
>  
> /*----------------------------------------------------------------------------
>  | Software half-precision conversion routines.
>  
> *----------------------------------------------------------------------------*/

Reply via email to