aboutsummaryrefslogtreecommitdiff
path: root/target/m68k/fpu_helper.c
diff options
context:
space:
mode:
authorMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>2023-01-14 23:29:59 +0000
committerLaurent Vivier <laurent@vivier.eu>2023-01-16 09:47:31 +0100
commit1a282f60a971aa86e3cdd1b7ca000790e43bb310 (patch)
tree085450f7e196237764503a8f259c0e1a08ec5b7c /target/m68k/fpu_helper.c
parentad6dae3b3369433ab43a1b190bb3a8aacabb1bbf (diff)
target/m68k: fix FPSR quotient byte for frem instruction
The FPSR quotient byte should be set to the value of the quotient and not the result. Manually calculate the quotient in the frem helper in round to nearest even mode (note this is different from the quotient calculated internally for fmod), and use it to set the quotient byte accordingly. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Fixes: https://gitlab.com/qemu-project/qemu/-/issues/1314 Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230114232959.118224-5-mark.cave-ayland@ilande.co.uk> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Diffstat (limited to 'target/m68k/fpu_helper.c')
-rw-r--r--target/m68k/fpu_helper.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 5fd094a33c..3a37d8f584 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -538,18 +538,27 @@ void HELPER(fmod)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
void HELPER(frem)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
{
- uint32_t quotient;
- int sign;
-
- res->d = floatx80_rem(val1->d, val0->d, &env->fp_status);
-
- if (floatx80_is_any_nan(res->d)) {
- return;
+ FPReg fp_quot;
+ floatx80 fp_rem;
+
+ fp_rem = floatx80_rem(val1->d, val0->d, &env->fp_status);
+ if (!floatx80_is_any_nan(fp_rem)) {
+ float_status fp_status = { };
+ uint32_t quotient;
+ int sign;
+
+ /* Calculate quotient directly using round to nearest mode */
+ set_float_rounding_mode(float_round_nearest_even, &fp_status);
+ set_floatx80_rounding_precision(
+ get_floatx80_rounding_precision(&env->fp_status), &fp_status);
+ fp_quot.d = floatx80_div(val1->d, val0->d, &fp_status);
+
+ sign = extractFloatx80Sign(fp_quot.d);
+ quotient = floatx80_to_int32(floatx80_abs(fp_quot.d), &env->fp_status);
+ make_quotient(env, sign, quotient);
}
- sign = extractFloatx80Sign(res->d);
- quotient = floatx80_to_int32(floatx80_abs(res->d), &env->fp_status);
- make_quotient(env, sign, quotient);
+ res->d = fp_rem;
}
void HELPER(fgetexp)(CPUM68KState *env, FPReg *res, FPReg *val)