summaryrefslogtreecommitdiff
path: root/target-arm/helper-a64.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-03-17 16:31:53 +0000
committerPeter Maydell <peter.maydell@linaro.org>2014-03-17 16:31:53 +0000
commit5553955eb6ec890f324a2ff6c6cc1365b98b981f (patch)
treed17b9d97dff33b004c050cc155366b70566fbf13 /target-arm/helper-a64.c
parent5201c13654c35e5e0173a9947848f3a9f9a5a8bc (diff)
downloadqemu-5553955eb6ec890f324a2ff6c6cc1365b98b981f.zip
target-arm: A64: Implement FCVTXN
Implement the FCVTXN operation, which does a narrowing fp precision conversion using the "round to odd" (von Neumann) mode. This can conveniently be implemented as "do operation using round to zero; then set the LSB of the mantissa to 1 if the Inexact flag was set". Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <rth@twiddle.net> Message-id: 1394822294-14837-24-git-send-email-peter.maydell@linaro.org
Diffstat (limited to 'target-arm/helper-a64.c')
-rw-r--r--target-arm/helper-a64.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index cea2468b30..ec0258295f 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -413,3 +413,26 @@ float64 HELPER(frecpx_f64)(float64 a, void *fpstp)
return make_float64(sbit | (~exp & 0x7ffULL) << 52);
}
}
+
+float32 HELPER(fcvtx_f64_to_f32)(float64 a, CPUARMState *env)
+{
+ /* Von Neumann rounding is implemented by using round-to-zero
+ * and then setting the LSB of the result if Inexact was raised.
+ */
+ float32 r;
+ float_status *fpst = &env->vfp.fp_status;
+ float_status tstat = *fpst;
+ int exflags;
+
+ set_float_rounding_mode(float_round_to_zero, &tstat);
+ set_float_exception_flags(0, &tstat);
+ r = float64_to_float32(a, &tstat);
+ r = float32_maybe_silence_nan(r);
+ exflags = get_float_exception_flags(&tstat);
+ if (exflags & float_flag_inexact) {
+ r = make_float32(float32_val(r) | 1);
+ }
+ exflags |= get_float_exception_flags(fpst);
+ set_float_exception_flags(exflags, fpst);
+ return r;
+}