This commit provides the basic operation support for the OCP float4 data type(e2m1).
Signed-off-by: Max Chou <[email protected]> --- fpu/softfloat.c | 29 +++++++++++++++++++++++ include/fpu/softfloat-types.h | 5 ++++ include/fpu/softfloat.h | 43 +++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 533f96dcda..96845e86df 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -595,6 +595,13 @@ static inline bool fmt_has_nan_encoding(const FloatFmt *fmt) .frac_shift = (-F - 1) & 63, \ .round_mask = (1ull << ((-F - 1) & 63)) - 1 +static const FloatFmt float4_e2m1_params = { + FLOAT_PARAMS(2, 1), + .no_infinity = true, + .limited_nan = true, + .normal_frac_max = NORMAL_FRAC_MAX_ALL, +}; + static const FloatFmt float8_e4m3_params = { FLOAT_PARAMS(4, 3), .no_infinity = true, @@ -663,6 +670,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); @@ -1745,6 +1757,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) { @@ -2938,6 +2957,16 @@ 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, &float8_e4m3_params, false); +} + bfloat16 float8_e4m3_to_bfloat16(float8_e4m3 a, float_status *s) { FloatParts64 p; diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h index b781bf10b7..f8cadffff4 100644 --- a/include/fpu/softfloat-types.h +++ b/include/fpu/softfloat-types.h @@ -131,6 +131,11 @@ typedef uint8_t float8_e5m2; #define const_float8_e4m3(x) (x) #define const_float8_e5m2(x) (x) +typedef uint8_t float4_e2m1; +#define float4_e2m1_val(x) ((x) & 0xf) +#define make_float4_e2m1(x) ((x) & 0xf) +#define const_float4_e2m1(x) ((x) & 0xf) + /* * Software IEC/IEEE floating-point underflow tininess-detection mode. */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 30aca23057..4566257c09 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -200,6 +200,8 @@ float8_e5m2 bfloat16_to_float8_e5m2(bfloat16, bool saturate, float_status *statu float8_e4m3 float32_to_float8_e4m3(float32, bool saturate, float_status *status); float8_e5m2 float32_to_float8_e5m2(float32, bool saturate, float_status *status); +float8_e4m3 float4_e2m1_to_float8_e4m3(float4_e2m1, float_status *status); + /*---------------------------------------------------------------------------- | Software OCP operations. *----------------------------------------------------------------------------*/ @@ -270,6 +272,47 @@ static inline bool float8_e5m2_is_normal(float8_e5m2 a) return (((float8_e5m2_val(a) >> 2) + 1) & 0x1f) >= 2; } +static inline bool float4_e2m1_is_quiet_nan(float4_e2m1 a, float_status *status) +{ + return false; +} + +static inline bool float4_e2m1_is_signaling_nan(float4_e2m1 a, float_status *status) +{ + return false; +} + +static inline bool float4_e2m1_is_any_nan(float4_e2m1 a) +{ + return false; +} + +static inline bool float4_e2m1_is_neg(float4_e2m1 a) +{ + return float4_e2m1_val(a) >> 3; +} + +static inline bool float4_e2m1_is_infinity(float4_e2m1 a) +{ + return false; +} + +static inline bool float4_e2m1_is_zero(float4_e2m1 a) +{ + return (float4_e2m1_val(a) & 0x7) == 0; +} + +static inline bool float4_e2m1_is_zero_or_denormal(float4_e2m1 a) +{ + return (float4_e2m1_val(a) & 0x6) == 0; +} + +static inline bool float4_e2m1_is_normal(float4_e2m1 a) +{ + uint8_t em = float4_e2m1_val(a) & 0x7; + return em >= 0x2 && em <= 0x7; +} + /*---------------------------------------------------------------------------- | Software half-precision conversion routines. *----------------------------------------------------------------------------*/ -- 2.52.0
