| 1 | /* |
| 2 | * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. |
| 3 | * |
| 4 | * SPDX-License-Identifier: GPL-2.0-or-later |
| 5 | */ |
| 6 | |
| 7 | #ifndef HEXAGON_HVX_IEEE_H |
| 8 | #define HEXAGON_HVX_IEEE_H |
| 9 | |
| 10 | #include "fpu/softfloat.h" |
| 11 | |
| 12 | #define FP32_DEF_NAN 0x7FFFFFFF |
| 13 | |
| 14 | #define f16_to_f32(A) float16_to_float32((A), true, &env->hvx_fp_status) |
| 15 | #define f32_to_f16(A) float32_to_float16((A), true, &env->hvx_fp_status) |
| 16 | #define bf16_to_f32(A) bfloat16_to_float32(A, &env->hvx_fp_status) |
| 17 | |
| 18 | float32 fp_mult_sf_hf(float16 a1, float16 a2, float_status *fp_status); |
| 19 | float32 fp_vdmpy(float16 a1, float16 a2, float16 a3, float16 a4, |
| 20 | float_status *fp_status); |
| 21 | |
| 22 | /* Qfloat min/max treat +NaN as greater than +INF and -NaN as smaller than -INF */ |
| 23 | float32 qf_max_sf(float32 a1, float32 a2, float_status *fp_status); |
| 24 | float32 qf_min_sf(float32 a1, float32 a2, float_status *fp_status); |
| 25 | float16 qf_max_hf(float16 a1, float16 a2, float_status *fp_status); |
| 26 | float16 qf_min_hf(float16 a1, float16 a2, float_status *fp_status); |
| 27 | |
| 28 | int32_t conv_w_sf(float32 a, float_status *fp_status); |
| 29 | int16_t conv_h_hf(float16 a, float_status *fp_status); |
| 30 | |
| 31 | /* IEEE - FP compare instructions */ |
| 32 | uint32_t cmpgt_sf(float32 a1, float32 a2, float_status *fp_status); |
| 33 | uint16_t cmpgt_hf(float16 a1, float16 a2, float_status *fp_status); |
| 34 | |
| 35 | /* IEEE BFloat instructions */ |
| 36 | |
| 37 | #define fp_mult_sf_bf(A, B) \ |
| 38 | float32_mul(bf16_to_f32(A), bf16_to_f32(B), &env->hvx_fp_status) |
| 39 | |
| 40 | #define fp_add_sf_bf(A, B) \ |
| 41 | float32_add(bf16_to_f32(A), bf16_to_f32(B), &env->hvx_fp_status) |
| 42 | |
| 43 | #define fp_sub_sf_bf(A, B) \ |
| 44 | float32_sub(bf16_to_f32(A), bf16_to_f32(B), &env->hvx_fp_status) |
| 45 | |
| 46 | #define fp_mult_sf_bf_acc(f1, f2, f3) \ |
| 47 | float32_muladd(bf16_to_f32(f1), bf16_to_f32(f2), f3, 0, &env->hvx_fp_status) |
| 48 | |
| 49 | static inline bfloat16 f32_to_bf16(float32 A, float_status *fp_status) |
| 50 | { |
| 51 | uint32_t rslt = A; |
| 52 | if ((rslt & 0x1FFFF) == 0x08000) { |
| 53 | /* do not round up if exactly .5 and even already */ |
| 54 | } else if ((rslt & 0x8000) == 0x8000) { |
| 55 | rslt += 0x8000; /* rounding to nearest number */ |
| 56 | } |
| 57 | rslt = float32_is_any_nan(A) ? FP32_DEF_NAN : rslt; |
| 58 | return float32_to_bfloat16(rslt, fp_status); |
| 59 | } |
| 60 | |
| 61 | #define fp_min_bf(A, B) \ |
| 62 | f32_to_bf16(float32_min(bf16_to_f32(A), bf16_to_f32(B), &env->hvx_fp_status), \ |
| 63 | &env->hvx_fp_status); |
| 64 | |
| 65 | #define fp_max_bf(A, B) \ |
| 66 | f32_to_bf16(float32_max(bf16_to_f32(A), bf16_to_f32(B), &env->hvx_fp_status), \ |
| 67 | &env->hvx_fp_status); |
| 68 | |
| 69 | #endif |