@@ -23,6 +23,7 @@
#include "exec/exec-all.h"
#include "qapi/error.h"
#include "hw/qdev-properties.h"
+#include "fpu/softfloat-helpers.h"
static void hexagon_v67_cpu_init(Object *obj)
{
@@ -205,8 +206,12 @@ static void hexagon_cpu_reset(DeviceState *dev)
CPUState *cs = CPU(dev);
HexagonCPU *cpu = HEXAGON_CPU(cs);
HexagonCPUClass *mcc = HEXAGON_CPU_GET_CLASS(cpu);
+ CPUHexagonState *env = &cpu->env;
mcc->parent_reset(dev);
+
+ set_default_nan_mode(1, &env->fp_status);
+ set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
}
static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
@@ -296,26 +296,6 @@ int32_t HELPER(fcircadd)(int32_t RxV, int32_t offset, int32_t M, int32_t CS)
return new_ptr;
}
-/*
- * Hexagon FP operations return ~0 instead of NaN
- * The hex_check_sfnan/hex_check_dfnan functions perform this check
- */
-static float32 hex_check_sfnan(float32 x)
-{
- if (float32_is_any_nan(x)) {
- return make_float32(0xFFFFFFFFU);
- }
- return x;
-}
-
-static float64 hex_check_dfnan(float64 x)
-{
- if (float64_is_any_nan(x)) {
- return make_float64(0xFFFFFFFFFFFFFFFFULL);
- }
- return x;
-}
-
/*
* mem_noshuf
* Section 5.5 of the Hexagon V67 Programmer's Reference Manual
@@ -373,7 +353,6 @@ float64 HELPER(conv_sf2df)(CPUHexagonState *env, float32 RsV)
float64 out_f64;
arch_fpop_start(env);
out_f64 = float32_to_float64(RsV, &env->fp_status);
- out_f64 = hex_check_dfnan(out_f64);
arch_fpop_end(env);
return out_f64;
}
@@ -383,7 +362,6 @@ float32 HELPER(conv_df2sf)(CPUHexagonState *env, float64 RssV)
float32 out_f32;
arch_fpop_start(env);
out_f32 = float64_to_float32(RssV, &env->fp_status);
- out_f32 = hex_check_sfnan(out_f32);
arch_fpop_end(env);
return out_f32;
}
@@ -393,7 +371,6 @@ float32 HELPER(conv_uw2sf)(CPUHexagonState *env, int32_t RsV)
float32 RdV;
arch_fpop_start(env);
RdV = uint32_to_float32(RsV, &env->fp_status);
- RdV = hex_check_sfnan(RdV);
arch_fpop_end(env);
return RdV;
}
@@ -403,7 +380,6 @@ float64 HELPER(conv_uw2df)(CPUHexagonState *env, int32_t RsV)
float64 RddV;
arch_fpop_start(env);
RddV = uint32_to_float64(RsV, &env->fp_status);
- RddV = hex_check_dfnan(RddV);
arch_fpop_end(env);
return RddV;
}
@@ -413,7 +389,6 @@ float32 HELPER(conv_w2sf)(CPUHexagonState *env, int32_t RsV)
float32 RdV;
arch_fpop_start(env);
RdV = int32_to_float32(RsV, &env->fp_status);
- RdV = hex_check_sfnan(RdV);
arch_fpop_end(env);
return RdV;
}
@@ -423,7 +398,6 @@ float64 HELPER(conv_w2df)(CPUHexagonState *env, int32_t RsV)
float64 RddV;
arch_fpop_start(env);
RddV = int32_to_float64(RsV, &env->fp_status);
- RddV = hex_check_dfnan(RddV);
arch_fpop_end(env);
return RddV;
}
@@ -433,7 +407,6 @@ float32 HELPER(conv_ud2sf)(CPUHexagonState *env, int64_t RssV)
float32 RdV;
arch_fpop_start(env);
RdV = uint64_to_float32(RssV, &env->fp_status);
- RdV = hex_check_sfnan(RdV);
arch_fpop_end(env);
return RdV;
}
@@ -443,7 +416,6 @@ float64 HELPER(conv_ud2df)(CPUHexagonState *env, int64_t RssV)
float64 RddV;
arch_fpop_start(env);
RddV = uint64_to_float64(RssV, &env->fp_status);
- RddV = hex_check_dfnan(RddV);
arch_fpop_end(env);
return RddV;
}
@@ -453,7 +425,6 @@ float32 HELPER(conv_d2sf)(CPUHexagonState *env, int64_t RssV)
float32 RdV;
arch_fpop_start(env);
RdV = int64_to_float32(RssV, &env->fp_status);
- RdV = hex_check_sfnan(RdV);
arch_fpop_end(env);
return RdV;
}
@@ -463,7 +434,6 @@ float64 HELPER(conv_d2df)(CPUHexagonState *env, int64_t RssV)
float64 RddV;
arch_fpop_start(env);
RddV = int64_to_float64(RssV, &env->fp_status);
- RddV = hex_check_dfnan(RddV);
arch_fpop_end(env);
return RddV;
}
@@ -625,7 +595,6 @@ float32 HELPER(sfadd)(CPUHexagonState *env, float32 RsV, float32 RtV)
float32 RdV;
arch_fpop_start(env);
RdV = float32_add(RsV, RtV, &env->fp_status);
- RdV = hex_check_sfnan(RdV);
arch_fpop_end(env);
return RdV;
}
@@ -635,7 +604,6 @@ float32 HELPER(sfsub)(CPUHexagonState *env, float32 RsV, float32 RtV)
float32 RdV;
arch_fpop_start(env);
RdV = float32_sub(RsV, RtV, &env->fp_status);
- RdV = hex_check_sfnan(RdV);
arch_fpop_end(env);
return RdV;
}
@@ -687,7 +655,6 @@ float32 HELPER(sfmax)(CPUHexagonState *env, float32 RsV, float32 RtV)
float32 RdV;
arch_fpop_start(env);
RdV = float32_maxnum(RsV, RtV, &env->fp_status);
- RdV = hex_check_sfnan(RdV);
arch_fpop_end(env);
return RdV;
}
@@ -697,7 +664,6 @@ float32 HELPER(sfmin)(CPUHexagonState *env, float32 RsV, float32 RtV)
float32 RdV;
arch_fpop_start(env);
RdV = float32_minnum(RsV, RtV, &env->fp_status);
- RdV = hex_check_sfnan(RdV);
arch_fpop_end(env);
return RdV;
}
@@ -764,7 +730,6 @@ float64 HELPER(dfadd)(CPUHexagonState *env, float64 RssV, float64 RttV)
float64 RddV;
arch_fpop_start(env);
RddV = float64_add(RssV, RttV, &env->fp_status);
- RddV = hex_check_dfnan(RddV);
arch_fpop_end(env);
return RddV;
}
@@ -774,7 +739,6 @@ float64 HELPER(dfsub)(CPUHexagonState *env, float64 RssV, float64 RttV)
float64 RddV;
arch_fpop_start(env);
RddV = float64_sub(RssV, RttV, &env->fp_status);
- RddV = hex_check_dfnan(RddV);
arch_fpop_end(env);
return RddV;
}
@@ -787,7 +751,6 @@ float64 HELPER(dfmax)(CPUHexagonState *env, float64 RssV, float64 RttV)
if (float64_is_any_nan(RssV) || float64_is_any_nan(RttV)) {
float_raise(float_flag_invalid, &env->fp_status);
}
- RddV = hex_check_dfnan(RddV);
arch_fpop_end(env);
return RddV;
}
@@ -800,7 +763,6 @@ float64 HELPER(dfmin)(CPUHexagonState *env, float64 RssV, float64 RttV)
if (float64_is_any_nan(RssV) || float64_is_any_nan(RttV)) {
float_raise(float_flag_invalid, &env->fp_status);
}
- RddV = hex_check_dfnan(RddV);
arch_fpop_end(env);
return RddV;
}
@@ -876,7 +838,6 @@ float32 HELPER(sfmpy)(CPUHexagonState *env, float32 RsV, float32 RtV)
float32 RdV;
arch_fpop_start(env);
RdV = internal_mpyf(RsV, RtV, &env->fp_status);
- RdV = hex_check_sfnan(RdV);
arch_fpop_end(env);
return RdV;
}
@@ -886,7 +847,6 @@ float32 HELPER(sffma)(CPUHexagonState *env, float32 RxV,
{
arch_fpop_start(env);
RxV = internal_fmafx(RsV, RtV, RxV, 0, &env->fp_status);
- RxV = hex_check_sfnan(RxV);
arch_fpop_end(env);
return RxV;
}
@@ -918,7 +878,6 @@ float32 HELPER(sffma_sc)(CPUHexagonState *env, float32 RxV,
RxV = check_nan(RxV, RsV, &env->fp_status);
RxV = check_nan(RxV, RtV, &env->fp_status);
tmp = internal_fmafx(RsV, RtV, RxV, fSXTN(8, 64, PuV), &env->fp_status);
- tmp = hex_check_sfnan(tmp);
if (!(float32_is_zero(RxV) && is_zero_prod(RsV, RtV))) {
RxV = tmp;
}
@@ -933,7 +892,6 @@ float32 HELPER(sffms)(CPUHexagonState *env, float32 RxV,
arch_fpop_start(env);
neg_RsV = float32_sub(float32_zero, RsV, &env->fp_status);
RxV = internal_fmafx(neg_RsV, RtV, RxV, 0, &env->fp_status);
- RxV = hex_check_sfnan(RxV);
arch_fpop_end(env);
return RxV;
}
@@ -964,7 +922,6 @@ float32 HELPER(sffma_lib)(CPUHexagonState *env, float32 RxV,
RxV = check_nan(RxV, RsV, &env->fp_status);
RxV = check_nan(RxV, RtV, &env->fp_status);
tmp = internal_fmafx(RsV, RtV, RxV, 0, &env->fp_status);
- tmp = hex_check_sfnan(tmp);
if (!(float32_is_zero(RxV) && is_zero_prod(RsV, RtV))) {
RxV = tmp;
}
@@ -999,7 +956,6 @@ float32 HELPER(sffms_lib)(CPUHexagonState *env, float32 RxV,
RxV = check_nan(RxV, RtV, &env->fp_status);
float32 minus_RsV = float32_sub(float32_zero, RsV, &env->fp_status);
tmp = internal_fmafx(minus_RsV, RtV, RxV, 0, &env->fp_status);
- tmp = hex_check_sfnan(tmp);
if (!(float32_is_zero(RxV) && is_zero_prod(RsV, RtV))) {
RxV = tmp;
}
@@ -1023,13 +979,11 @@ float64 HELPER(dfmpyfix)(CPUHexagonState *env, float64 RssV, float64 RttV)
float64_is_normal(RttV)) {
RddV = float64_mul(RssV, make_float64(0x4330000000000000),
&env->fp_status);
- RddV = hex_check_dfnan(RddV);
} else if (float64_is_denormal(RttV) &&
(float64_getexp(RssV) >= 512) &&
float64_is_normal(RssV)) {
RddV = float64_mul(RssV, make_float64(0x3cb0000000000000),
&env->fp_status);
- RddV = hex_check_dfnan(RddV);
} else {
RddV = RssV;
}
@@ -1042,7 +996,6 @@ float64 HELPER(dfmpyhh)(CPUHexagonState *env, float64 RxxV,
{
arch_fpop_start(env);
RxxV = internal_mpyhh(RssV, RttV, RxxV, &env->fp_status);
- RxxV = hex_check_dfnan(RxxV);
arch_fpop_end(env);
return RxxV;
}
@@ -145,6 +145,9 @@ static FloatParts parts_default_nan(float_status *status)
#elif defined(TARGET_HPPA)
/* snan_bit_is_one, set msb-1. */
frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2);
+#elif defined(TARGET_HEXAGON)
+ sign = 1;
+ frac = ~0ULL;
#else
/* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
* S390, SH4, TriCore, and Xtensa. I cannot find documentation