diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 11013a22..6d6c2ff5 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_aarch64 #define floatx80_lt floatx80_lt_aarch64 #define floatx80_lt_quiet floatx80_lt_quiet_aarch64 +#define floatx80_mod floatx80_mod_aarch64 +#define floatx80_modrem floatx80_modrem_aarch64 #define floatx80_mul floatx80_mul_aarch64 #define floatx80_rem floatx80_rem_aarch64 #define floatx80_round floatx80_round_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index edb24383..b04e69c0 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_aarch64eb #define floatx80_lt floatx80_lt_aarch64eb #define floatx80_lt_quiet floatx80_lt_quiet_aarch64eb +#define floatx80_mod floatx80_mod_aarch64eb +#define floatx80_modrem floatx80_modrem_aarch64eb #define floatx80_mul floatx80_mul_aarch64eb #define floatx80_rem floatx80_rem_aarch64eb #define floatx80_round floatx80_round_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index df3fb8d2..7924c55e 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_arm #define floatx80_lt floatx80_lt_arm #define floatx80_lt_quiet floatx80_lt_quiet_arm +#define floatx80_mod floatx80_mod_arm +#define floatx80_modrem floatx80_modrem_arm #define floatx80_mul floatx80_mul_arm #define floatx80_rem floatx80_rem_arm #define floatx80_round floatx80_round_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 9a93d4d5..2f6ba0a4 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_armeb #define floatx80_lt floatx80_lt_armeb #define floatx80_lt_quiet floatx80_lt_quiet_armeb +#define floatx80_mod floatx80_mod_armeb +#define floatx80_modrem floatx80_modrem_armeb #define floatx80_mul floatx80_mul_armeb #define floatx80_rem floatx80_rem_armeb #define floatx80_round floatx80_round_armeb diff --git a/qemu/fpu/softfloat.c b/qemu/fpu/softfloat.c index 564ff17c..15de9697 100644 --- a/qemu/fpu/softfloat.c +++ b/qemu/fpu/softfloat.c @@ -5659,10 +5659,13 @@ floatx80 floatx80_div(floatx80 a, floatx80 b, float_status *status) /*---------------------------------------------------------------------------- | Returns the remainder of the extended double-precision floating-point value | `a' with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic, +| if 'mod' is false; if 'mod' is true, return the remainder based on truncating +| the quotient toward zero instead. *----------------------------------------------------------------------------*/ -floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) +floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, + float_status *status) { bool aSign, zSign; int32_t aExp, bExp, expDiff; @@ -5708,7 +5711,7 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) expDiff = aExp - bExp; aSig1 = 0; if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; + if ( mod || expDiff < -1 ) return a; shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); expDiff = 0; } @@ -5740,14 +5743,16 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) term1 = 0; term0 = bSig; } - sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); - if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) - || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) - && ( q & 1 ) ) - ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - zSign = ! zSign; + if (!mod) { + sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); + if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) + || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) + && ( q & 1 ) ) + ) { + aSig0 = alternateASig0; + aSig1 = alternateASig1; + zSign = ! zSign; + } } return normalizeRoundAndPackFloatx80( @@ -5755,6 +5760,28 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) } +/*---------------------------------------------------------------------------- +| Returns the remainder of the extended double-precision floating-point value +| `a' with respect to the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status) +{ + return floatx80_modrem(a, b, false, status); +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the extended double-precision floating-point value +| `a' with respect to the corresponding value `b', with the quotient truncated +| toward zero. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status) +{ + return floatx80_modrem(a, b, true, status); +} + /*---------------------------------------------------------------------------- | Returns the square root of the extended double-precision floating-point | value `a'. The operation is performed according to the IEC/IEEE Standard diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 1e53dcda..f86bd564 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -684,6 +684,8 @@ symbols = ( 'floatx80_le_quiet', 'floatx80_lt', 'floatx80_lt_quiet', + 'floatx80_mod', + 'floatx80_modrem', 'floatx80_mul', 'floatx80_rem', 'floatx80_round', diff --git a/qemu/include/fpu/softfloat.h b/qemu/include/fpu/softfloat.h index 3884997e..cd8a3e6d 100644 --- a/qemu/include/fpu/softfloat.h +++ b/qemu/include/fpu/softfloat.h @@ -690,6 +690,8 @@ floatx80 floatx80_add(floatx80, floatx80, float_status *status); floatx80 floatx80_sub(floatx80, floatx80, float_status *status); floatx80 floatx80_mul(floatx80, floatx80, float_status *status); floatx80 floatx80_div(floatx80, floatx80, float_status *status); +floatx80 floatx80_modrem(floatx80, floatx80, bool, float_status *status); +floatx80 floatx80_mod(floatx80, floatx80, float_status *status); floatx80 floatx80_rem(floatx80, floatx80, float_status *status); floatx80 floatx80_sqrt(floatx80, float_status *status); FloatRelation floatx80_compare(floatx80, floatx80, float_status *status); diff --git a/qemu/m68k.h b/qemu/m68k.h index c9ddb7a4..b39e30be 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_m68k #define floatx80_lt floatx80_lt_m68k #define floatx80_lt_quiet floatx80_lt_quiet_m68k +#define floatx80_mod floatx80_mod_m68k +#define floatx80_modrem floatx80_modrem_m68k #define floatx80_mul floatx80_mul_m68k #define floatx80_rem floatx80_rem_m68k #define floatx80_round floatx80_round_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 950adea5..80b4d8e9 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_mips #define floatx80_lt floatx80_lt_mips #define floatx80_lt_quiet floatx80_lt_quiet_mips +#define floatx80_mod floatx80_mod_mips +#define floatx80_modrem floatx80_modrem_mips #define floatx80_mul floatx80_mul_mips #define floatx80_rem floatx80_rem_mips #define floatx80_round floatx80_round_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index ee78ef89..2d925d79 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_mips64 #define floatx80_lt floatx80_lt_mips64 #define floatx80_lt_quiet floatx80_lt_quiet_mips64 +#define floatx80_mod floatx80_mod_mips64 +#define floatx80_modrem floatx80_modrem_mips64 #define floatx80_mul floatx80_mul_mips64 #define floatx80_rem floatx80_rem_mips64 #define floatx80_round floatx80_round_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 16fcda96..53b9cf46 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_mips64el #define floatx80_lt floatx80_lt_mips64el #define floatx80_lt_quiet floatx80_lt_quiet_mips64el +#define floatx80_mod floatx80_mod_mips64el +#define floatx80_modrem floatx80_modrem_mips64el #define floatx80_mul floatx80_mul_mips64el #define floatx80_rem floatx80_rem_mips64el #define floatx80_round floatx80_round_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 9357185c..2fd410c1 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_mipsel #define floatx80_lt floatx80_lt_mipsel #define floatx80_lt_quiet floatx80_lt_quiet_mipsel +#define floatx80_mod floatx80_mod_mipsel +#define floatx80_modrem floatx80_modrem_mipsel #define floatx80_mul floatx80_mul_mipsel #define floatx80_rem floatx80_rem_mipsel #define floatx80_round floatx80_round_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 7939f57b..53cb087c 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_powerpc #define floatx80_lt floatx80_lt_powerpc #define floatx80_lt_quiet floatx80_lt_quiet_powerpc +#define floatx80_mod floatx80_mod_powerpc +#define floatx80_modrem floatx80_modrem_powerpc #define floatx80_mul floatx80_mul_powerpc #define floatx80_rem floatx80_rem_powerpc #define floatx80_round floatx80_round_powerpc diff --git a/qemu/riscv32.h b/qemu/riscv32.h index 40bd2cc1..ec2d8a9c 100644 --- a/qemu/riscv32.h +++ b/qemu/riscv32.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_riscv32 #define floatx80_lt floatx80_lt_riscv32 #define floatx80_lt_quiet floatx80_lt_quiet_riscv32 +#define floatx80_mod floatx80_mod_riscv32 +#define floatx80_modrem floatx80_modrem_riscv32 #define floatx80_mul floatx80_mul_riscv32 #define floatx80_rem floatx80_rem_riscv32 #define floatx80_round floatx80_round_riscv32 diff --git a/qemu/riscv64.h b/qemu/riscv64.h index a1bbc53d..9d7339c0 100644 --- a/qemu/riscv64.h +++ b/qemu/riscv64.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_riscv64 #define floatx80_lt floatx80_lt_riscv64 #define floatx80_lt_quiet floatx80_lt_quiet_riscv64 +#define floatx80_mod floatx80_mod_riscv64 +#define floatx80_modrem floatx80_modrem_riscv64 #define floatx80_mul floatx80_mul_riscv64 #define floatx80_rem floatx80_rem_riscv64 #define floatx80_round floatx80_round_riscv64 diff --git a/qemu/sparc.h b/qemu/sparc.h index b1f15104..7a8710f2 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_sparc #define floatx80_lt floatx80_lt_sparc #define floatx80_lt_quiet floatx80_lt_quiet_sparc +#define floatx80_mod floatx80_mod_sparc +#define floatx80_modrem floatx80_modrem_sparc #define floatx80_mul floatx80_mul_sparc #define floatx80_rem floatx80_rem_sparc #define floatx80_round floatx80_round_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 47d80a80..e77487d3 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_sparc64 #define floatx80_lt floatx80_lt_sparc64 #define floatx80_lt_quiet floatx80_lt_quiet_sparc64 +#define floatx80_mod floatx80_mod_sparc64 +#define floatx80_modrem floatx80_modrem_sparc64 #define floatx80_mul floatx80_mul_sparc64 #define floatx80_rem floatx80_rem_sparc64 #define floatx80_round floatx80_round_sparc64 diff --git a/qemu/target/m68k/softfloat.c b/qemu/target/m68k/softfloat.c index 9f120cf1..b6d0ed7a 100644 --- a/qemu/target/m68k/softfloat.c +++ b/qemu/target/m68k/softfloat.c @@ -42,89 +42,6 @@ static floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status) return a; } -/* - * Returns the modulo remainder of the extended double-precision floating-point - * value `a' with respect to the corresponding value `b'. - */ - -floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status) -{ - bool aSign, zSign; - int32_t aExp, bExp, expDiff; - uint64_t aSig0, aSig1, bSig; - uint64_t qTemp, term0, term1; - - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - - if (aExp == 0x7FFF) { - if ((uint64_t) (aSig0 << 1) - || ((bExp == 0x7FFF) && (uint64_t) (bSig << 1))) { - return propagateFloatx80NaN(a, b, status); - } - goto invalid; - } - if (bExp == 0x7FFF) { - if ((uint64_t) (bSig << 1)) { - return propagateFloatx80NaN(a, b, status); - } - return a; - } - if (bExp == 0) { - if (bSig == 0) { - invalid: - float_raise(float_flag_invalid, status); - return floatx80_default_nan(status); - } - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if ((uint64_t) (aSig0 << 1) == 0) { - return a; - } - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - } - bSig |= UINT64_C(0x8000000000000000); - zSign = aSign; - expDiff = aExp - bExp; - aSig1 = 0; - if (expDiff < 0) { - return a; - } - qTemp = (bSig <= aSig0); - if (qTemp) { - aSig0 -= bSig; - } - expDiff -= 64; - while (0 < expDiff) { - qTemp = estimateDiv128To64(aSig0, aSig1, bSig); - qTemp = (2 < qTemp) ? qTemp - 2 : 0; - mul64To128(bSig, qTemp, &term0, &term1); - sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1); - shortShift128Left(aSig0, aSig1, 62, &aSig0, &aSig1); - expDiff -= 62; - } - expDiff += 64; - if (0 < expDiff) { - qTemp = estimateDiv128To64(aSig0, aSig1, bSig); - qTemp = (2 < qTemp) ? qTemp - 2 : 0; - qTemp >>= 64 - expDiff; - mul64To128(bSig, qTemp << (64 - expDiff), &term0, &term1); - sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1); - shortShift128Left(0, bSig, 64 - expDiff, &term0, &term1); - while (le128(term0, term1, aSig0, aSig1)) { - ++qTemp; - sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1); - } - } - return - normalizeRoundAndPackFloatx80( - 80, zSign, bExp + expDiff, aSig0, aSig1, status); -} - /* * Returns the mantissa of the extended double-precision floating-point * value `a'. diff --git a/qemu/target/m68k/softfloat.h b/qemu/target/m68k/softfloat.h index 365ef6ac..4bb95671 100644 --- a/qemu/target/m68k/softfloat.h +++ b/qemu/target/m68k/softfloat.h @@ -23,7 +23,6 @@ #define TARGET_M68K_SOFTFLOAT_H #include "fpu/softfloat.h" -floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status); floatx80 floatx80_getman(floatx80 a, float_status *status); floatx80 floatx80_getexp(floatx80 a, float_status *status); floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status); diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 29f0699f..59f509f2 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -678,6 +678,8 @@ #define floatx80_le_quiet floatx80_le_quiet_x86_64 #define floatx80_lt floatx80_lt_x86_64 #define floatx80_lt_quiet floatx80_lt_quiet_x86_64 +#define floatx80_mod floatx80_mod_x86_64 +#define floatx80_modrem floatx80_modrem_x86_64 #define floatx80_mul floatx80_mul_x86_64 #define floatx80_rem floatx80_rem_x86_64 #define floatx80_round floatx80_round_x86_64