On Mon, Mar 23, 2026 at 6:26 PM Taylor Simpson <ltaylorsimpson@gmail.com> wrote:
>
>
>
> On Mon, Mar 23, 2026 at 7:16 AM Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com> wrote:
>>
>>
>> diff --git a/target/hexagon/mmvec/kvx_ieee.c b/target/hexagon/mmvec/kvx_ieee.c
>> index 33621a15f3..bbeec09707 100644
>> --- a/target/hexagon/mmvec/kvx_ieee.c
>> +++ b/target/hexagon/mmvec/kvx_ieee.c
>> @@ -131,3 +131,101 @@ uint16_t qf_min_hf(uint16_t a1, uint16_t a2, float_status *fp_status)
>> if (float16_is_pos_nan(f2) || float16_is_neg_nan(f1)) return a1;
>> return fp_min_hf(a1, a2, fp_status);
>> }
>> +
>> +uint16_t f16_to_uh(uint16_t op1, float_status *fp_status)
>> +{
>> + return float16_to_uint16_scalbn(make_float16(op1),
>> + float_round_nearest_even,
>
>
> Does HVX always use this rounding mode? The scalar core uses the rounding mode in USR.
Yeah, almost always this mode, with the exception of some
instructions. It's not configurable via USR (or anything else).
You can set that in the hvx_fp_status, and the softfloat lib will handle it from there.
>> +
>> +int32_t conv_w_sf(uint32_t a, float_status *fp_status)
>> +{
>> + float_status scratch_fpst = {};
>> + const float32 W_MAX = int32_to_float32(INT32_MAX, &scratch_fpst);
>> + const float32 W_MIN = int32_to_float32(INT32_MIN, &scratch_fpst);
>> + float32 f1 = make_float32(a);
>> +
>> + if (float32_is_any_nan(f1) || float32_is_infinity(f1) ||
>> + float32_le_quiet(W_MAX, f1, fp_status) ||
>> + float32_le_quiet(f1, W_MIN, fp_status)) {
>> + return float32_is_neg(f1) ? INT32_MIN : INT32_MAX;
>> + }
>
>
> Does float32_to_int32 handle these checks?
Hmm, I don't think they are exactly the same. For example,
float32_to_int32 will return INT32_MAX for any NAN. But the hexagon
implementation here returns INT32_MIN for negative NAN.
Look around in the softfloat code - especially fields in float_status. Ths scalar core has a few exceptions, but not alot.