diff options
author | 2024-05-27 20:40:42 -0400 | |
---|---|---|
committer | 2024-05-27 20:40:42 -0400 | |
commit | 6957c469983fe32c9725eb3787020b6cedd36b75 (patch) | |
tree | 7b12ba5d3d6b2a08ec63ae9c72badad521339beb /3rdparty | |
parent | cd25f2de50864c2897ca7f5aa604696c87a49807 (diff) |
cpu/m68000: Updated 680x0 FPU to Softfloat 3 from 2. (MT5411 and MT8793). [R. Belmont]
- Update to Softloat 3 from 2
- FREM and FMOD now generate the quotient bits in FPSR, required by Apple's SANE to do sin/cos/tan properly.
- FMOVE of a float to a Dx integer register generates the exception status bits, fixing square roots in SANE
- Rewrote how FMOVEM instructions are decoded and executed, fixing issues including skipping too few or too many
opcode bytes and causing serious weird behavior.
- FPU instructions all now have more realistic cycle timings for a 68881.
- All FPU instructions now generate exception bits in FPSR.
3rdparty/softfloat3: Updates [R. Belmont]
- Softfloat3 was always being built for a big-endian host, causing incorrect math on LE x64 and AArch64 machines.
- Fixed up Softfloat3 to build properly as part of MAME and up-ported the Bochs extensions. In latest Bochs, they
were only partially up-ported and Softfloat3 had been hacked up to be more like 2; here they're fixed to work
with stock Softfloat3.
Diffstat (limited to '3rdparty')
-rw-r--r-- | 3rdparty/softfloat3/bochs_ext/extF80_scale.c | 156 | ||||
-rw-r--r-- | 3rdparty/softfloat3/bochs_ext/f2xm1.c | 186 | ||||
-rw-r--r-- | 3rdparty/softfloat3/bochs_ext/fpatan.c | 326 | ||||
-rw-r--r-- | 3rdparty/softfloat3/bochs_ext/fprem.c | 255 | ||||
-rw-r--r-- | 3rdparty/softfloat3/bochs_ext/fpu_constant.h | 80 | ||||
-rw-r--r-- | 3rdparty/softfloat3/bochs_ext/fsincos.c | 457 | ||||
-rw-r--r-- | 3rdparty/softfloat3/bochs_ext/fyl2x.c | 409 | ||||
-rw-r--r-- | 3rdparty/softfloat3/bochs_ext/poly.c | 91 | ||||
-rw-r--r-- | 3rdparty/softfloat3/bochs_ext/softfloat-extra.h | 68 | ||||
-rw-r--r-- | 3rdparty/softfloat3/bochs_ext/softfloat-helpers.h | 159 | ||||
-rw-r--r-- | 3rdparty/softfloat3/bochs_ext/softfloat-specialize.h | 223 | ||||
-rw-r--r-- | 3rdparty/softfloat3/bochs_ext/softfloat3_ext.h | 17 | ||||
-rw-r--r-- | 3rdparty/softfloat3/build/MAME/platform.h | 10 | ||||
-rw-r--r-- | 3rdparty/softfloat3/source/include/softfloat.h | 46 | ||||
-rw-r--r-- | 3rdparty/softfloat3/source/include/softfloat_types.h | 7 |
15 files changed, 2468 insertions, 22 deletions
diff --git a/3rdparty/softfloat3/bochs_ext/extF80_scale.c b/3rdparty/softfloat3/bochs_ext/extF80_scale.c new file mode 100644 index 00000000000..6a25764f128 --- /dev/null +++ b/3rdparty/softfloat3/bochs_ext/extF80_scale.c @@ -0,0 +1,156 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include <stdbool.h> +#include <stdint.h> + +#include "../source/include/softfloat.h" +#include "../source/include/internals.h" +#include "../source/8086/specialize.h" + +#include "fpu_constant.h" +#include "softfloat-helpers.h" +#include "softfloat-extra.h" +#include "softfloat-specialize.h" + +/*---------------------------------------------------------------------------- +| Scales extended double-precision floating-point value in operand `a' by +| value `b'. The function truncates the value in the second operand 'b' to +| an integral value and adds that value to the exponent of the operand 'a'. +| The operation performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +extFloat80_t extFloat80_scale(extFloat80_t a, extFloat80_t b) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + uint16_t uiB64; + uint64_t uiB0; + bool signB; + int32_t expB; + uint64_t sigB; + struct exp32_sig64 normExpSig; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { +invalid: + softfloat_exceptionFlags |= softfloat_flag_invalid; + return packToExtF80(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + expB = expExtF80UI64(uiB64); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + + if (expA == 0x7FFF) { + if ((sigA<<1) || ((expB == 0x7FFF) && (sigB<<1))) { + const uint128 nan = softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0); + extFloat80_t rv; + rv.signExp = nan.v64; + rv.signif = nan.v0; + return rv; + } + if ((expB == 0x7FFF) && signB) goto invalid; + if (sigB && !expB) + softfloat_exceptionFlags |= softfloat_flag_invalid; // actally denormal + + return a; + } + if (expB == 0x7FFF) { + if (sigB<<1) { + const uint128 nan = softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0); + extFloat80_t rv; + rv.signExp = nan.v64; + rv.signif = nan.v0; + return rv; + } + if ((expA | sigA) == 0) { + if (! signB) goto invalid; + return a; + } + if (sigA && !expA) + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + + if (signB) return packToExtF80(signA, 0, 0); + return packToExtF80(signA, 0x7FFF, uint64_t(0x8000000000000000)); + } + if (! expA) { + if (sigB && !expB) + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + if (! sigA) return a; + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA = normExpSig.exp + 1; + sigA = normExpSig.sig; + if (expB < 0x3FFF) + return softfloat_normRoundPackToExtF80(signA, expA, sigA, 0, 80); + } + if (!expB) { + if (!sigB) return a; + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB = normExpSig.exp + 1; + sigB = normExpSig.sig; + } + + if (expB > 0x400E) { + /* generate appropriate overflow/underflow */ + return softfloat_roundPackToExtF80(signA, signB ? -0x3FFF : 0x7FFF, sigA, 0, 80); + } + + if (expB < 0x3FFF) return a; + + int shiftCount = 0x403E - expB; + sigB >>= shiftCount; + int32_t scale = (int32_t) sigB; + if (signB) scale = -scale; /* -32768..32767 */ + + return softfloat_roundPackToExtF80(signA, expA + scale, sigA, 0, 80); +} diff --git a/3rdparty/softfloat3/bochs_ext/f2xm1.c b/3rdparty/softfloat3/bochs_ext/f2xm1.c new file mode 100644 index 00000000000..a8201937660 --- /dev/null +++ b/3rdparty/softfloat3/bochs_ext/f2xm1.c @@ -0,0 +1,186 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#define FLOAT128 + +#include "../source/include/softfloat.h" +#include "../source/include/internals.h" +#include "softfloat-extra.h" +#include "softfloat-helpers.h" +#include "softfloat-specialize.h" + +static const extFloat80_t floatx80_negone = packFloatx80(1, 0x3fff, uint64_t(0x8000000000000000)); +static const extFloat80_t floatx80_neghalf = packFloatx80(1, 0x3ffe, uint64_t(0x8000000000000000)); +static const float128_t float128_ln2 = + packFloat128(uint64_t(0x3ffe62e42fefa39e), uint64_t(0xf35793c7673007e6)); + +#ifdef BETTER_THAN_PENTIUM + +#define LN2_SIG_HI uint64_t(0xb17217f7d1cf79ab) +#define LN2_SIG_LO uint64_t(0xc9e3b39800000000) /* 96 bit precision */ + +#else + +#define LN2_SIG_HI uint64_t(0xb17217f7d1cf79ab) +#define LN2_SIG_LO uint64_t(0xc000000000000000) /* 67-bit precision */ + +#endif + +#define EXP_ARR_SIZE 15 + +static float128_t exp_arr[EXP_ARR_SIZE] = +{ + PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ + PACK_FLOAT_128(0x3ffe000000000000, 0x0000000000000000), /* 2 */ + PACK_FLOAT_128(0x3ffc555555555555, 0x5555555555555555), /* 3 */ + PACK_FLOAT_128(0x3ffa555555555555, 0x5555555555555555), /* 4 */ + PACK_FLOAT_128(0x3ff8111111111111, 0x1111111111111111), /* 5 */ + PACK_FLOAT_128(0x3ff56c16c16c16c1, 0x6c16c16c16c16c17), /* 6 */ + PACK_FLOAT_128(0x3ff2a01a01a01a01, 0xa01a01a01a01a01a), /* 7 */ + PACK_FLOAT_128(0x3fefa01a01a01a01, 0xa01a01a01a01a01a), /* 8 */ + PACK_FLOAT_128(0x3fec71de3a556c73, 0x38faac1c88e50017), /* 9 */ + PACK_FLOAT_128(0x3fe927e4fb7789f5, 0xc72ef016d3ea6679), /* 10 */ + PACK_FLOAT_128(0x3fe5ae64567f544e, 0x38fe747e4b837dc7), /* 11 */ + PACK_FLOAT_128(0x3fe21eed8eff8d89, 0x7b544da987acfe85), /* 12 */ + PACK_FLOAT_128(0x3fde6124613a86d0, 0x97ca38331d23af68), /* 13 */ + PACK_FLOAT_128(0x3fda93974a8c07c9, 0xd20badf145dfa3e5), /* 14 */ + PACK_FLOAT_128(0x3fd6ae7f3e733b81, 0xf11d8656b0ee8cb0) /* 15 */ +}; + +extern float128_t EvalPoly(float128_t x, const float128_t *arr, int n); + +/* required -1 < x < 1 */ +static float128_t poly_exp(float128_t x) +{ +/* + // 2 3 4 5 6 7 8 9 + // x x x x x x x x x + // e - 1 ~ x + --- + --- + --- + --- + --- + --- + --- + --- + ... + // 2! 3! 4! 5! 6! 7! 8! 9! + // + // 2 3 4 5 6 7 8 + // x x x x x x x x + // = x [ 1 + --- + --- + --- + --- + --- + --- + --- + --- + ... ] + // 2! 3! 4! 5! 6! 7! 8! 9! + // + // 8 8 + // -- 2k -- 2k+1 + // p(x) = > C * x q(x) = > C * x + // -- 2k -- 2k+1 + // k=0 k=0 + // + // x + // e - 1 ~ x * [ p(x) + x * q(x) ] + // +*/ + float128_t t = EvalPoly(x, (const float128_t*) exp_arr, EXP_ARR_SIZE); + return f128_mul(t, x); +} + +// ================================================= +// x +// FX2M1 Compute 2 - 1 +// ================================================= + +// +// Uses the following identities: +// +// 1. ---------------------------------------------------------- +// x x*ln(2) +// 2 = e +// +// 2. ---------------------------------------------------------- +// 2 3 4 5 n +// x x x x x x x +// e = 1 + --- + --- + --- + --- + --- + ... + --- + ... +// 1! 2! 3! 4! 5! n! +// +extFloat80_t extFloat80_2xm1(extFloat80_t a) +{ + uint64_t zSig0, zSig1, zSig2; + struct exp32_sig64 normExpSig; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_exceptionFlags |= softfloat_flag_invalid; + return floatx80_default_nan; + } + + uint64_t aSig = extF80_fraction(a); + int32_t aExp = extF80_exp(a); + int aSign = extF80_sign(a); + + if (aExp == 0x7FFF) { + if (aSig << 1) { + const uint128 nan = softfloat_propagateNaNExtF80UI(a.signExp, aSig, 0, 0); + extFloat80_t rv; + rv.signExp = nan.v64; + rv.signif = nan.v0; + return rv; + } + + return (aSign) ? floatx80_negone : a; + } + + if (! aExp) { + if (! aSig) return a; + softfloat_exceptionFlags |= softfloat_flag_inexact; // denormal also + normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; + + tiny_argument: + mul128By64To192(LN2_SIG_HI, LN2_SIG_LO, aSig, &zSig0, &zSig1, &zSig2); + if (0 < (int64_t) zSig0) { + shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); + --aExp; + } + return softfloat_roundPackToExtF80(aSign, aExp, zSig0, zSig1, 80); + } + + softfloat_exceptionFlags |= softfloat_flag_inexact; + + if (aExp < 0x3FFF) + { + if (aExp < FLOATX80_EXP_BIAS-68) + goto tiny_argument; + + /* ******************************** */ + /* using float128 for approximation */ + /* ******************************** */ + + float128_t x = extF80_to_f128(a); + x = f128_mul(x, float128_ln2); + x = poly_exp(x); + return f128_to_extF80(x); + } + else + { + if (a.signExp == 0xBFFF && ! (aSig<<1)) + return floatx80_neghalf; + + return a; + } +} diff --git a/3rdparty/softfloat3/bochs_ext/fpatan.c b/3rdparty/softfloat3/bochs_ext/fpatan.c new file mode 100644 index 00000000000..88bced6bbd3 --- /dev/null +++ b/3rdparty/softfloat3/bochs_ext/fpatan.c @@ -0,0 +1,326 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#define FLOAT128 + +#include "../source/include/softfloat.h" +#include "../source/include/internals.h" +#include "../source/8086/specialize.h" + +#include "fpu_constant.h" +#include "softfloat-helpers.h" +#include "softfloat-extra.h" +#include "softfloat-specialize.h" + +#define FPATAN_ARR_SIZE 11 + +static const extFloat80_t floatx80_one = packFloatx80(0, 0x3fff, uint64_t(0x8000000000000000)); + +static const float128_t float128_one = + packFloat128(uint64_t(0x3fff000000000000), uint64_t(0x0000000000000000)); +static const float128_t float128_sqrt3 = + packFloat128(uint64_t(0x3fffbb67ae8584ca), uint64_t(0xa73b25742d7078b8)); +static const extFloat80_t floatx80_pi = + packFloatx80(0, 0x4000, uint64_t(0xc90fdaa22168c235)); + +static const float128_t float128_pi2 = + packFloat128(uint64_t(0x3fff921fb54442d1), uint64_t(0x8469898CC5170416)); +static const float128_t float128_pi4 = + packFloat128(uint64_t(0x3ffe921fb54442d1), uint64_t(0x8469898CC5170416)); +static const float128_t float128_pi6 = + packFloat128(uint64_t(0x3ffe0c152382d736), uint64_t(0x58465BB32E0F580F)); + +static float128_t atan_arr[FPATAN_ARR_SIZE] = +{ + PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ + PACK_FLOAT_128(0xbffd555555555555, 0x5555555555555555), /* 3 */ + PACK_FLOAT_128(0x3ffc999999999999, 0x999999999999999a), /* 5 */ + PACK_FLOAT_128(0xbffc249249249249, 0x2492492492492492), /* 7 */ + PACK_FLOAT_128(0x3ffbc71c71c71c71, 0xc71c71c71c71c71c), /* 9 */ + PACK_FLOAT_128(0xbffb745d1745d174, 0x5d1745d1745d1746), /* 11 */ + PACK_FLOAT_128(0x3ffb3b13b13b13b1, 0x3b13b13b13b13b14), /* 13 */ + PACK_FLOAT_128(0xbffb111111111111, 0x1111111111111111), /* 15 */ + PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2), /* 17 */ + PACK_FLOAT_128(0xbffaaf286bca1af2, 0x86bca1af286bca1b), /* 19 */ + PACK_FLOAT_128(0x3ffa861861861861, 0x8618618618618618) /* 21 */ +}; + +extern float128_t OddPoly(float128_t x, const float128_t *arr, int n); + +/* |x| < 1/4 */ +static float128_t poly_atan(float128_t x1) +{ +/* + // 3 5 7 9 11 13 15 17 + // x x x x x x x x + // atan(x) ~ x - --- + --- - --- + --- - ---- + ---- - ---- + ---- + // 3 5 7 9 11 13 15 17 + // + // 2 4 6 8 10 12 14 16 + // x x x x x x x x + // = x * [ 1 - --- + --- - --- + --- - ---- + ---- - ---- + ---- ] + // 3 5 7 9 11 13 15 17 + // + // 5 5 + // -- 4k -- 4k+2 + // p(x) = > C * x q(x) = > C * x + // -- 2k -- 2k+1 + // k=0 k=0 + // + // 2 + // atan(x) ~ x * [ p(x) + x * q(x) ] + // +*/ + return OddPoly(x1, (const float128_t*) atan_arr, FPATAN_ARR_SIZE); +} + +// ================================================= +// FPATAN Compute arctan(y/x) +// ================================================= + +// +// Uses the following identities: +// +// 1. ---------------------------------------------------------- +// +// atan(-x) = -atan(x) +// +// 2. ---------------------------------------------------------- +// +// x + y +// atan(x) + atan(y) = atan -------, xy < 1 +// 1-xy +// +// x + y +// atan(x) + atan(y) = atan ------- + PI, x > 0, xy > 1 +// 1-xy +// +// x + y +// atan(x) + atan(y) = atan ------- - PI, x < 0, xy > 1 +// 1-xy +// +// 3. ---------------------------------------------------------- +// +// atan(x) = atan(INF) + atan(- 1/x) +// +// x-1 +// atan(x) = PI/4 + atan( ----- ) +// x+1 +// +// x * sqrt(3) - 1 +// atan(x) = PI/6 + atan( ----------------- ) +// x + sqrt(3) +// +// 4. ---------------------------------------------------------- +// 3 5 7 9 2n+1 +// x x x x n x +// atan(x) = x - --- + --- - --- + --- - ... + (-1) ------ + ... +// 3 5 7 9 2n+1 +// + +extFloat80_t extFloat80_atan(extFloat80_t a, extFloat80_t b) +{ + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { + softfloat_exceptionFlags |= softfloat_flag_invalid; + return floatx80_default_nan; + } + + uint64_t aSig = extF80_fraction(a); + int32_t aExp = extF80_exp(a); + int aSign = extF80_sign(a); + uint64_t bSig = extF80_fraction(b); + int32_t bExp = extF80_exp(b); + int bSign = extF80_sign(b); + + int zSign = aSign ^ bSign; + + if (bExp == 0x7FFF) + { + extFloat80_t rv; + if (bSig<<1) { + const uint128 nan = softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig); + rv.signExp = nan.v64; + rv.signif = nan.v0; + return rv; + } + if (aExp == 0x7FFF) { + if (aSig<<1) { + const uint128 nan = softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig); + rv.signExp = nan.v64; + rv.signif = nan.v0; + return rv; + } + if (aSign) /* return 3PI/4 */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, 80); + else /* return PI/4 */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80); + } + + if (aSig && ! aExp) + softfloat_exceptionFlags |= softfloat_flag_invalid; // denormal actually + + /* return PI/2 */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80); + } + if (aExp == 0x7FFF) + { + if (aSig<<1) { + extFloat80_t rv; + const uint128 nan = softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig); + rv.signExp = nan.v64; + rv.signif = nan.v0; + return rv; + } + if (bSig && ! bExp) + softfloat_exceptionFlags |= softfloat_flag_invalid; // denormal actually + +return_PI_or_ZERO: + + if (aSign) /* return PI */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80); + else /* return 0 */ + return packToExtF80(bSign, 0, 0); + } + if (! bExp) + { + if (! bSig) { + if (aSig && ! aExp) + softfloat_exceptionFlags |= softfloat_flag_invalid; // denormal actually + + goto return_PI_or_ZERO; + } + + softfloat_exceptionFlags |= softfloat_flag_invalid; // denormal actually + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; + } + if (! aExp) + { + if (! aSig) /* return PI/2 */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80); + + softfloat_exceptionFlags |= softfloat_flag_invalid; // denormal actually + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; + } + + softfloat_exceptionFlags |= softfloat_flag_inexact; + + /* |a| = |b| ==> return PI/4 */ + if (aSig == bSig && aExp == bExp) { + if (aSign) + return softfloat_roundPackToExtF80(bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, 80); + else + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80); + } + + /* ******************************** */ + /* using float128 for approximation */ + /* ******************************** */ + + float128_t a128 = softfloat_normRoundPackToF128(0, aExp-0x10, aSig, 0); + float128_t b128 = softfloat_normRoundPackToF128(0, bExp-0x10, bSig, 0); + float128_t x; + int swap = 0, add_pi6 = 0, add_pi4 = 0; + + if (aExp > bExp || (aExp == bExp && aSig > bSig)) + { + x = f128_div(b128, a128); + } + else { + x = f128_div(a128, b128); + swap = 1; + } + + int32_t xExp = expF128UI64(x.v[1]); + + if (xExp <= FLOATX80_EXP_BIAS-40) + goto approximation_completed; + + if (x.v[1] >= uint64_t(0x3ffe800000000000)) // 3/4 < x < 1 + { + /* + arctan(x) = arctan((x-1)/(x+1)) + pi/4 + */ + float128_t t1 = f128_sub(x, float128_one); + float128_t t2 = f128_add(x, float128_one); + x = f128_div(t1, t2); + add_pi4 = 1; + } + else + { + /* argument correction */ + if (xExp >= 0x3FFD) // 1/4 < x < 3/4 + { + /* + arctan(x) = arctan((x*sqrt(3)-1)/(x+sqrt(3))) + pi/6 + */ + float128_t t1 = f128_mul(x, float128_sqrt3); + float128_t t2 = f128_add(x, float128_sqrt3); + x = f128_sub(t1, float128_one); + x = f128_div(x, t2); + add_pi6 = 1; + } + } + + x = poly_atan(x); + if (add_pi6) x = f128_add(x, float128_pi6); + if (add_pi4) x = f128_add(x, float128_pi4); + +approximation_completed: + if (swap) x = f128_sub(float128_pi2, x); + extFloat80_t result = f128_to_extF80(x); + if (zSign) floatx80_chs(result); + int rSign = extF80_sign(result); + if (!bSign && rSign) + return extF80_add(result, floatx80_pi); + if (bSign && !rSign) + return extF80_sub(result, floatx80_pi); + return result; +} + +extFloat80_t packToExtF80(uint16_t signExp, uint64_t sig) +{ + extFloat80_t z; + z.signExp = signExp; + z.signif = sig; + return z; +} + +extFloat80_t packToExtF80(bool sign, uint16_t exp, uint64_t sig) +{ + extFloat80_t z; + z.signExp = packToExtF80UI64(sign, exp); + z.signif = sig; + return z; +} + +extFloat80_t extFloat80_68katan(extFloat80_t a) +{ + return extFloat80_atan(a, floatx80_one); +} diff --git a/3rdparty/softfloat3/bochs_ext/fprem.c b/3rdparty/softfloat3/bochs_ext/fprem.c new file mode 100644 index 00000000000..16f6cccbc49 --- /dev/null +++ b/3rdparty/softfloat3/bochs_ext/fprem.c @@ -0,0 +1,255 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#define USE_estimateDiv128To64 +#define FLOAT128 + +#include <stdint.h> + +#include "../build/MAME/platform.h" +#include "../source/include/internals.h" +#include "../source/include/softfloat.h" + +#include "../source/8086/specialize.h" + +#include "fpu_constant.h" +#include "softfloat-extra.h" +#include "softfloat-helpers.h" +#include "softfloat-specialize.h" + +/* executes single exponent reduction cycle */ +static uint64_t remainder_kernel(uint64_t aSig0, uint64_t bSig, int expDiff, uint64_t *zSig0, uint64_t *zSig1) +{ + uint128 term, z; + uint64_t aSig1 = 0; + shortShift128Left(aSig1, aSig0, expDiff, &aSig1, &aSig0); + uint64_t q = estimateDiv128To64(aSig1, aSig0, bSig); + term = softfloat_mul64To128(bSig, q); + z = softfloat_sub128(aSig1, aSig0, term.v64, term.v0); + while ((int64_t) z.v64 < 0) { + --q; + z = softfloat_add128(z.v64, z.v0, 0, bSig); + } + *zSig0 = z.v0; + *zSig1 = z.v64; + return q; +} + +static int do_fprem(extFloat80_t a, extFloat80_t b, extFloat80_t &r, uint64_t &q, int rounding_mode) +{ + int32_t aExp, bExp, zExp, expDiff; + uint64_t aSig0, aSig1 = 0, bSig; + int aSign; + struct exp32_sig64 normExpSig; + uint128 term; + + q = 0; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { + softfloat_exceptionFlags |= softfloat_flag_invalid; + r = floatx80_default_nan; + return -1; + } + + aSig0 = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); + bSig = extF80_fraction(b); + bExp = extF80_exp(b); + + if (aExp == 0x7FFF) { + if ((aSig0<<1) || ((bExp == 0x7FFF) && (bSig<<1))) { + const uint128 nan = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, b.signExp, b.signif); + r.signExp = nan.v64; + r.signif = nan.v0; + return -1; + } + softfloat_exceptionFlags |= softfloat_flag_invalid; + r = floatx80_default_nan; + return -1; + } + if (bExp == 0x7FFF) { + if (bSig << 1) { + const uint128 nan = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, b.signExp, b.signif); + r.signExp = nan.v64; + r.signif = nan.v0; + return -1; + } + if (! aExp && aSig0) { + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; + r = (a.signif & uint64_t(0x8000000000000000)) ? packToExtF80(aSign, aExp, aSig0) : a; + return 0; + } + r = a; + return 0; + + } + if (! bExp) { + if (! bSig) { + softfloat_exceptionFlags |= softfloat_flag_invalid; + r = floatx80_default_nan; + return -1; + } + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; + } + if (! aExp) { + if (! aSig0) { + r = a; + return 0; + } + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; + } + + expDiff = aExp - bExp; + int overflow = 0; + + if (expDiff >= 64) { + int n = (expDiff & 0x1f) | 0x20; + remainder_kernel(aSig0, bSig, n, &aSig0, &aSig1); + zExp = aExp - n; + overflow = 1; + } + else { + zExp = bExp; + + if (expDiff < 0) { + if (expDiff < -1) { + r = (a.signif & uint64_t(0x8000000000000000)) ? packToExtF80(aSign, aExp, aSig0) : a; + return 0; + } + shortShift128Right(aSig0, 0, 1, &aSig0, &aSig1); + expDiff = 0; + } + + if (expDiff > 0) { + q = remainder_kernel(aSig0, bSig, expDiff, &aSig0, &aSig1); + } + else { + if (bSig <= aSig0) { + aSig0 -= bSig; + q = 1; + } + } + + if (rounding_mode == softfloat_round_near_even) { + uint64_t term0, term1; + shortShift128Right(bSig, 0, 1, &term0, &term1); + + if (! softfloat_lt128(aSig0, aSig1, term0, term1)) { + int lt = softfloat_lt128(term0, term1, aSig0, aSig1); + int eq = softfloat_eq128(aSig0, aSig1, term0, term1); + + if ((eq && (q & 1)) || lt) { + aSign = !aSign; + ++q; + } + if (lt) { + term = softfloat_sub128(bSig, 0, aSig0, aSig1); + aSig0 = term.v64; + aSig1 = term.v0; + } + } + } + } + + r = softfloat_normRoundPackToExtF80(aSign, zExp, aSig0, aSig1, 80); + return overflow; +} + +/*---------------------------------------------------------------------------- +| 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. +*----------------------------------------------------------------------------*/ + +int extFloat80_ieee754_remainder(extFloat80_t a, extFloat80_t b, extFloat80_t &r, uint64_t &q) +{ + return do_fprem(a, b, r, q, softfloat_round_near_even); +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the extended double-precision floating-point value +| `a' with respect to the corresponding value `b'. Unlike previous function +| the function does not compute the remainder specified in the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. This function operates +| differently from the previous function in the way that it rounds the +| quotient of 'a' divided by 'b' to an integer. +*----------------------------------------------------------------------------*/ + +int extFloat80_remainder(extFloat80_t a, extFloat80_t b, extFloat80_t &r, uint64_t &q) +{ + return do_fprem(a, b, r, q, softfloat_round_minMag); +} + +static extFloat80_t propagateFloatx80NaNOneArg(extFloat80_t a) +{ + a.signif |= uint64_t(0x4000000000000000); + return a; +} + +extFloat80_t extFloat80_getman(extFloat80_t a) +{ + const int aSign = (a.signExp >> 15); + int32_t aExp = a.signExp & 0x7fff; + uint64_t aFrac = a.signif; + + if (aExp == 0x7fff) + { + if ((uint64_t)(aFrac << 1)) + { + return propagateFloatx80NaNOneArg(a); + } + + softfloat_raiseFlags(softfloat_flag_invalid); + return floatx80_default_nan; + } + + if (!aExp) + { + if (!aSign) + { + return packFloatx80(aSign, 0, 0); + } + else + { + // normalize the subnormal value + const int leadingZeroes = softfloat_countLeadingZeros64(aFrac); + aFrac = aFrac << leadingZeroes; + aExp = -leadingZeroes; + } + } + + return packFloatx80(aSign, 0x3fff, aFrac); +} diff --git a/3rdparty/softfloat3/bochs_ext/fpu_constant.h b/3rdparty/softfloat3/bochs_ext/fpu_constant.h new file mode 100644 index 00000000000..827dbdec514 --- /dev/null +++ b/3rdparty/softfloat3/bochs_ext/fpu_constant.h @@ -0,0 +1,80 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +#ifndef _FPU_CONSTANTS_H_ +#define _FPU_CONSTANTS_H_ + +// Pentium CPU uses only 68-bit precision M_PI approximation +// #define BETTER_THAN_PENTIUM + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +////////////////////////////// +// PI, PI/2, PI/4 constants +////////////////////////////// + +#define FLOATX80_PI_EXP (0x4000) + +// 128-bit PI fraction +#ifdef BETTER_THAN_PENTIUM +#define FLOAT_PI_HI (uint64_t(0xc90fdaa22168c234)) +#define FLOAT_PI_LO (uint64_t(0xc4c6628b80dc1cd1)) +#else +#define FLOAT_PI_HI (uint64_t(0xc90fdaa22168c234)) +#define FLOAT_PI_LO (uint64_t(0xC000000000000000)) +#endif + +#define FLOATX80_PI2_EXP (0x3FFF) +#define FLOATX80_PI4_EXP (0x3FFE) + +////////////////////////////// +// 3PI/4 constant +////////////////////////////// + +#define FLOATX80_3PI4_EXP (0x4000) + +// 128-bit 3PI/4 fraction +#ifdef BETTER_THAN_PENTIUM +#define FLOAT_3PI4_HI (uint64_t(0x96cbe3f9990e91a7)) +#define FLOAT_3PI4_LO (uint64_t(0x9394c9e8a0a5159c)) +#else +#define FLOAT_3PI4_HI (uint64_t(0x96cbe3f9990e91a7)) +#define FLOAT_3PI4_LO (uint64_t(0x9000000000000000)) +#endif + +////////////////////////////// +// 1/LN2 constant +////////////////////////////// + +#define FLOAT_LN2INV_EXP (0x3FFF) + +// 128-bit 1/LN2 fraction +#ifdef BETTER_THAN_PENTIUM +#define FLOAT_LN2INV_HI (uint64_t(0xb8aa3b295c17f0bb)) +#define FLOAT_LN2INV_LO (uint64_t(0xbe87fed0691d3e89)) +#else +#define FLOAT_LN2INV_HI (uint64_t(0xb8aa3b295c17f0bb)) +#define FLOAT_LN2INV_LO (uint64_t(0xC000000000000000)) +#endif + +#endif diff --git a/3rdparty/softfloat3/bochs_ext/fsincos.c b/3rdparty/softfloat3/bochs_ext/fsincos.c new file mode 100644 index 00000000000..303d66cc5b8 --- /dev/null +++ b/3rdparty/softfloat3/bochs_ext/fsincos.c @@ -0,0 +1,457 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#define FLOAT128 + +#define USE_estimateDiv128To64 +#define FLOAT128 + +#include "../build/MAME/platform.h" +#include "../source/include/internals.h" +#include "../source/include/softfloat.h" + +#include "../source/8086/specialize.h" + +#include "fpu_constant.h" +#include "softfloat-extra.h" +#include "softfloat-helpers.h" +#include "softfloat-specialize.h" + +static const extFloat80_t floatx80_one = packFloatx80(0, 0x3fff, uint64_t(0x8000000000000000)); + +/* reduce trigonometric function argument using 128-bit precision + M_PI approximation */ +static uint64_t argument_reduction_kernel(uint64_t aSig0, int Exp, uint64_t *zSig0, uint64_t *zSig1) +{ + uint64_t term0, term1, term2; + uint64_t aSig1 = 0; + + shortShift128Left(aSig1, aSig0, Exp, &aSig1, &aSig0); + uint64_t q = estimateDiv128To64(aSig1, aSig0, FLOAT_PI_HI); + mul128By64To192(FLOAT_PI_HI, FLOAT_PI_LO, q, &term0, &term1, &term2); + sub128(aSig1, aSig0, term0, term1, zSig1, zSig0); + while ((int64_t)(*zSig1) < 0) { + --q; + add192(*zSig1, *zSig0, term2, 0, FLOAT_PI_HI, FLOAT_PI_LO, zSig1, zSig0, &term2); + } + *zSig1 = term2; + return q; +} + +static int reduce_trig_arg(int expDiff, int &zSign, uint64_t &aSig0, uint64_t &aSig1) +{ + uint64_t term0, term1, q = 0; + + if (expDiff < 0) { + shortShift128Right(aSig0, 0, 1, &aSig0, &aSig1); + expDiff = 0; + } + if (expDiff > 0) { + q = argument_reduction_kernel(aSig0, expDiff, &aSig0, &aSig1); + } + else { + if (FLOAT_PI_HI <= aSig0) { + aSig0 -= FLOAT_PI_HI; + q = 1; + } + } + + shortShift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1); + if (! softfloat_lt128(aSig0, aSig1, term0, term1)) + { + int lt = softfloat_lt128(term0, term1, aSig0, aSig1); + int eq = softfloat_eq128(aSig0, aSig1, term0, term1); + + if ((eq && (q & 1)) || lt) { + zSign = !zSign; + ++q; + } + if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, aSig0, aSig1, &aSig0, &aSig1); + } + + return (int)(q & 3); +} + +#define SIN_ARR_SIZE 11 +#define COS_ARR_SIZE 11 + +static float128_t sin_arr[SIN_ARR_SIZE] = +{ + PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ + PACK_FLOAT_128(0xbffc555555555555, 0x5555555555555555), /* 3 */ + PACK_FLOAT_128(0x3ff8111111111111, 0x1111111111111111), /* 5 */ + PACK_FLOAT_128(0xbff2a01a01a01a01, 0xa01a01a01a01a01a), /* 7 */ + PACK_FLOAT_128(0x3fec71de3a556c73, 0x38faac1c88e50017), /* 9 */ + PACK_FLOAT_128(0xbfe5ae64567f544e, 0x38fe747e4b837dc7), /* 11 */ + PACK_FLOAT_128(0x3fde6124613a86d0, 0x97ca38331d23af68), /* 13 */ + PACK_FLOAT_128(0xbfd6ae7f3e733b81, 0xf11d8656b0ee8cb0), /* 15 */ + PACK_FLOAT_128(0x3fce952c77030ad4, 0xa6b2605197771b00), /* 17 */ + PACK_FLOAT_128(0xbfc62f49b4681415, 0x724ca1ec3b7b9675), /* 19 */ + PACK_FLOAT_128(0x3fbd71b8ef6dcf57, 0x18bef146fcee6e45) /* 21 */ +}; + +static float128_t cos_arr[COS_ARR_SIZE] = +{ + PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 0 */ + PACK_FLOAT_128(0xbffe000000000000, 0x0000000000000000), /* 2 */ + PACK_FLOAT_128(0x3ffa555555555555, 0x5555555555555555), /* 4 */ + PACK_FLOAT_128(0xbff56c16c16c16c1, 0x6c16c16c16c16c17), /* 6 */ + PACK_FLOAT_128(0x3fefa01a01a01a01, 0xa01a01a01a01a01a), /* 8 */ + PACK_FLOAT_128(0xbfe927e4fb7789f5, 0xc72ef016d3ea6679), /* 10 */ + PACK_FLOAT_128(0x3fe21eed8eff8d89, 0x7b544da987acfe85), /* 12 */ + PACK_FLOAT_128(0xbfda93974a8c07c9, 0xd20badf145dfa3e5), /* 14 */ + PACK_FLOAT_128(0x3fd2ae7f3e733b81, 0xf11d8656b0ee8cb0), /* 16 */ + PACK_FLOAT_128(0xbfca6827863b97d9, 0x77bb004886a2c2ab), /* 18 */ + PACK_FLOAT_128(0x3fc1e542ba402022, 0x507a9cad2bf8f0bb) /* 20 */ +}; + +extern float128_t OddPoly (float128_t x, const float128_t *arr, int n); + +/* 0 <= x <= pi/4 */ +inline float128_t poly_sin(float128_t x) +{ + // 3 5 7 9 11 13 15 + // x x x x x x x + // sin (x) ~ x - --- + --- - --- + --- - ---- + ---- - ---- = + // 3! 5! 7! 9! 11! 13! 15! + // + // 2 4 6 8 10 12 14 + // x x x x x x x + // = x * [ 1 - --- + --- - --- + --- - ---- + ---- - ---- ] = + // 3! 5! 7! 9! 11! 13! 15! + // + // 3 3 + // -- 4k -- 4k+2 + // p(x) = > C * x > 0 q(x) = > C * x < 0 + // -- 2k -- 2k+1 + // k=0 k=0 + // + // 2 + // sin(x) ~ x * [ p(x) + x * q(x) ] + // + + return OddPoly(x, (const float128_t*) sin_arr, SIN_ARR_SIZE); +} + +extern float128_t EvenPoly(float128_t x, const float128_t *arr, int n); + +/* 0 <= x <= pi/4 */ +inline float128_t poly_cos(float128_t x) +{ + // 2 4 6 8 10 12 14 + // x x x x x x x + // cos (x) ~ 1 - --- + --- - --- + --- - ---- + ---- - ---- + // 2! 4! 6! 8! 10! 12! 14! + // + // 3 3 + // -- 4k -- 4k+2 + // p(x) = > C * x > 0 q(x) = > C * x < 0 + // -- 2k -- 2k+1 + // k=0 k=0 + // + // 2 + // cos(x) ~ [ p(x) + x * q(x) ] + // + + return EvenPoly(x, (const float128_t*) cos_arr, COS_ARR_SIZE); +} + +inline void sincos_invalid(extFloat80_t *sin_a, extFloat80_t *cos_a, extFloat80_t a) +{ + if (sin_a) *sin_a = a; + if (cos_a) *cos_a = a; +} + +inline void sincos_tiny_argument(extFloat80_t *sin_a, extFloat80_t *cos_a, extFloat80_t a) +{ + if (sin_a) *sin_a = a; + if (cos_a) *cos_a = floatx80_one; +} + +static extFloat80_t sincos_approximation(int neg, float128_t r, uint64_t quotient) +{ + if (quotient & 0x1) { + r = poly_cos(r); + neg = 0; + } else { + r = poly_sin(r); + } + + extFloat80_t result = f128_to_extF80(r); + if (quotient & 0x2) + neg = ! neg; + + if (neg) + floatx80_chs(result); + + return result; +} + +// ================================================= +// FSINCOS Compute sin(x) and cos(x) +// ================================================= + +// +// Uses the following identities: +// ---------------------------------------------------------- +// +// sin(-x) = -sin(x) +// cos(-x) = cos(x) +// +// sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y) +// cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y) +// +// sin(x+ pi/2) = cos(x) +// sin(x+ pi) = -sin(x) +// sin(x+3pi/2) = -cos(x) +// sin(x+2pi) = sin(x) +// + +int extFloat80_sincos(extFloat80_t a, extFloat80_t *sin_a, extFloat80_t *cos_a) +{ + uint64_t aSig0, aSig1 = 0; + int32_t aExp, zExp, expDiff; + int aSign, zSign; + int q = 0; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + goto invalid; + } + + aSig0 = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); + + /* invalid argument */ + if (aExp == 0x7FFF) { + if (aSig0 << 1) { + const uint128 nan = softfloat_propagateNaNExtF80UI(a.signExp, aSig0, 0, 0); + extFloat80_t rv; + rv.signExp = nan.v64; + rv.signif = nan.v0; + sincos_invalid(sin_a, cos_a, rv); + return 0; + } + + invalid: + softfloat_exceptionFlags |= softfloat_flag_invalid; + sincos_invalid(sin_a, cos_a, floatx80_default_nan); + return 0; + } + + if (! aExp) { + if (! aSig0) { + sincos_tiny_argument(sin_a, cos_a, a); + return 0; + } + + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + + /* handle pseudo denormals */ + if (! (aSig0 & uint64_t(0x8000000000000000))) + { + softfloat_exceptionFlags |= softfloat_flag_inexact; + if (sin_a) + softfloat_exceptionFlags |= softfloat_flag_underflow; + sincos_tiny_argument(sin_a, cos_a, a); + return 0; + } + + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; + } + + zSign = aSign; + zExp = FLOATX80_EXP_BIAS; + expDiff = aExp - zExp; + + /* argument is out-of-range */ + if (expDiff >= 63) + return -1; + + softfloat_exceptionFlags |= softfloat_flag_inexact; + + if (expDiff < -1) { // doesn't require reduction + if (expDiff <= -68) { + a = packFloatx80(aSign, aExp, aSig0); + sincos_tiny_argument(sin_a, cos_a, a); + return 0; + } + zExp = aExp; + } + else { + q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1); + } + + /* **************************** */ + /* argument reduction completed */ + /* **************************** */ + + /* using float128 for approximation */ + float128_t r = softfloat_normRoundPackToF128(0, zExp-0x10, aSig0, aSig1); + + if (aSign) q = -q; + if (sin_a) *sin_a = sincos_approximation(zSign, r, q); + if (cos_a) *cos_a = sincos_approximation(zSign, r, q+1); + + return 0; +} + +int extFloat80_sin(extFloat80_t &a) +{ + return extFloat80_sincos(a, &a, 0); +} + +int extFloat80_cos(extFloat80_t &a) +{ + return extFloat80_sincos(a, 0, &a); +} + +// ================================================= +// FPTAN Compute tan(x) +// ================================================= + +// +// Uses the following identities: +// +// 1. ---------------------------------------------------------- +// +// sin(-x) = -sin(x) +// cos(-x) = cos(x) +// +// sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y) +// cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y) +// +// sin(x+ pi/2) = cos(x) +// sin(x+ pi) = -sin(x) +// sin(x+3pi/2) = -cos(x) +// sin(x+2pi) = sin(x) +// +// 2. ---------------------------------------------------------- +// +// sin(x) +// tan(x) = ------ +// cos(x) +// + +int extFloat80_tan(extFloat80_t &a) +{ + uint64_t aSig0, aSig1 = 0; + int32_t aExp, zExp, expDiff; + int aSign, zSign; + int q = 0; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + goto invalid; + } + + aSig0 = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); + + /* invalid argument */ + if (aExp == 0x7FFF) { + if (aSig0 << 1) + { + const uint128 nan = softfloat_propagateNaNExtF80UI(a.signExp, aSig0, 0, 0); + a.signExp = nan.v64; + a.signif = nan.v0; + return 0; + } + + invalid: + softfloat_exceptionFlags |= softfloat_flag_invalid; + a = floatx80_default_nan; + return 0; + } + + if (! aExp) { + if (! aSig0) return 0; + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + /* handle pseudo denormals */ + if (! (aSig0 & uint64_t(0x8000000000000000))) + { + softfloat_exceptionFlags |= softfloat_flag_inexact | softfloat_flag_underflow; + return 0; + } + + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; + } + + zSign = aSign; + zExp = FLOATX80_EXP_BIAS; + expDiff = aExp - zExp; + + /* argument is out-of-range */ + if (expDiff >= 63) + return -1; + + softfloat_exceptionFlags |= softfloat_flag_inexact; + + if (expDiff < -1) { // doesn't require reduction + if (expDiff <= -68) { + a = packFloatx80(aSign, aExp, aSig0); + return 0; + } + zExp = aExp; + } + else { + q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1); + } + + /* **************************** */ + /* argument reduction completed */ + /* **************************** */ + + /* using float128 for approximation */ + float128_t r = softfloat_normRoundPackToF128(0, zExp-0x10, aSig0, aSig1); + + float128_t sin_r = poly_sin(r); + float128_t cos_r = poly_cos(r); + + if (q & 0x1) { + r = f128_div(cos_r, sin_r); + zSign = ! zSign; + } else { + r = f128_div(sin_r, cos_r); + } + + a = f128_to_extF80(r); + if (zSign) + floatx80_chs(a); + + return 0; +} + +extFloat80_t &floatx80_chs(extFloat80_t ®) +{ + reg.signExp ^= 0x8000; + return reg; +} diff --git a/3rdparty/softfloat3/bochs_ext/fyl2x.c b/3rdparty/softfloat3/bochs_ext/fyl2x.c new file mode 100644 index 00000000000..5b9f21bbf11 --- /dev/null +++ b/3rdparty/softfloat3/bochs_ext/fyl2x.c @@ -0,0 +1,409 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#define FLOAT128 + +#include "../build/MAME/platform.h" +#include "../source/include/internals.h" +#include "../source/include/softfloat.h" + +#include "fpu_constant.h" +#include "softfloat-extra.h" +#include "softfloat-helpers.h" +#include "softfloat-specialize.h" + +static const extFloat80_t floatx80_one = packFloatx80(0, 0x3fff, uint64_t(0x8000000000000000)); +static const extFloat80_t floatx80_ln_2 = packFloatx80(0, 0x3ffe, 0xb17217f7d1cf79acU); +static const extFloat80_t floatx80_log10_2 = packFloatx80(0, 0x3ffd, 0x9a209a84fbcff798U); + +static const float128_t float128_one = + packFloat128(uint64_t(0x3fff000000000000), uint64_t(0x0000000000000000)); +static const float128_t float128_two = + packFloat128(uint64_t(0x4000000000000000), uint64_t(0x0000000000000000)); + +static const float128_t float128_ln2inv2 = + packFloat128(uint64_t(0x400071547652b82f), uint64_t(0xe1777d0ffda0d23a)); + +#define SQRT2_HALF_SIG uint64_t(0xb504f333f9de6484) + +extern float128_t OddPoly(float128_t x, const float128_t *arr, int n); + +#define L2_ARR_SIZE 9 + +static float128_t ln_arr[L2_ARR_SIZE] = +{ + PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ + PACK_FLOAT_128(0x3ffd555555555555, 0x5555555555555555), /* 3 */ + PACK_FLOAT_128(0x3ffc999999999999, 0x999999999999999a), /* 5 */ + PACK_FLOAT_128(0x3ffc249249249249, 0x2492492492492492), /* 7 */ + PACK_FLOAT_128(0x3ffbc71c71c71c71, 0xc71c71c71c71c71c), /* 9 */ + PACK_FLOAT_128(0x3ffb745d1745d174, 0x5d1745d1745d1746), /* 11 */ + PACK_FLOAT_128(0x3ffb3b13b13b13b1, 0x3b13b13b13b13b14), /* 13 */ + PACK_FLOAT_128(0x3ffb111111111111, 0x1111111111111111), /* 15 */ + PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2) /* 17 */ +}; + +static float128_t poly_ln(float128_t x1) +{ +/* + // + // 3 5 7 9 11 13 15 + // 1+u u u u u u u u + // 1/2 ln --- ~ u + --- + --- + --- + --- + ---- + ---- + ---- = + // 1-u 3 5 7 9 11 13 15 + // + // 2 4 6 8 10 12 14 + // u u u u u u u + // = u * [ 1 + --- + --- + --- + --- + ---- + ---- + ---- ] = + // 3 5 7 9 11 13 15 + // + // 3 3 + // -- 4k -- 4k+2 + // p(u) = > C * u q(u) = > C * u + // -- 2k -- 2k+1 + // k=0 k=0 + // + // 1+u 2 + // 1/2 ln --- ~ u * [ p(u) + u * q(u) ] + // 1-u + // +*/ + return OddPoly(x1, (const float128_t*) ln_arr, L2_ARR_SIZE); +} + +/* required sqrt(2)/2 < x < sqrt(2) */ +static float128_t poly_l2(float128_t x) +{ + /* using float128 for approximation */ + float128_t x_p1 = f128_add(x, float128_one); + float128_t x_m1 = f128_sub(x, float128_one); + x = f128_div(x_m1, x_p1); + x = poly_ln(x); + x = f128_mul(x, float128_ln2inv2); + return x; +} + +static float128_t poly_l2p1(float128_t x) +{ + /* using float128 for approximation */ + float128_t x_plus2 = f128_add(x, float128_two); + x = f128_div(x, x_plus2); + x = poly_ln(x); + x = f128_mul(x, float128_ln2inv2); + return x; +} + +// ================================================= +// FYL2X Compute y * log (x) +// 2 +// ================================================= + +// +// Uses the following identities: +// +// 1. ---------------------------------------------------------- +// ln(x) +// log (x) = -------, ln (x*y) = ln(x) + ln(y) +// 2 ln(2) +// +// 2. ---------------------------------------------------------- +// 1+u x-1 +// ln (x) = ln -----, when u = ----- +// 1-u x+1 +// +// 3. ---------------------------------------------------------- +// 3 5 7 2n+1 +// 1+u u u u u +// ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ] +// 1-u 3 5 7 2n+1 +// + +extFloat80_t extFloat80_fyl2x(extFloat80_t a, extFloat80_t b) +{ + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { +invalid: + softfloat_exceptionFlags |= softfloat_flag_invalid; + return floatx80_default_nan; + } + + uint64_t aSig = extF80_fraction(a); + int32_t aExp = extF80_exp(a); + int aSign = extF80_sign(a); + uint64_t bSig = extF80_fraction(b); + int32_t bExp = extF80_exp(b); + int bSign = extF80_sign(b); + + int zSign = bSign ^ 1; + + if (aExp == 0x7FFF) { + if ((aSig<<1) || ((bExp == 0x7FFF) && (bSig<<1))) { + const uint128 nan = softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig); + extFloat80_t rv; + rv.signExp = nan.v64; + rv.signif = nan.v0; + return rv; + } + if (aSign) goto invalid; + else { + if (! bExp) { + if (! bSig) goto invalid; + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + } + return packFloatx80(bSign, 0x7FFF, uint64_t(0x8000000000000000)); + } + } + if (bExp == 0x7FFF) { + if (bSig << 1) { + const uint128 nan = softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig); + extFloat80_t rv; + rv.signExp = nan.v64; + rv.signif = nan.v0; + return rv; + } + if (aSign && (uint64_t)(aExp | aSig)) goto invalid; + if (aSig && ! aExp) + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + if (aExp < 0x3FFF) + { + return packFloatx80(zSign, 0x7FFF, uint64_t(0x8000000000000000)); + } + if (aExp == 0x3FFF && ! (aSig<<1)) goto invalid; + return packFloatx80(bSign, 0x7FFF, uint64_t(0x8000000000000000)); + } + if (! aExp) { + if (! aSig) { + if ((bExp | bSig) == 0) goto invalid; + softfloat_exceptionFlags |= softfloat_flag_invalid; // divide by zero + return packFloatx80(zSign, 0x7FFF, uint64_t(0x8000000000000000)); + } + if (aSign) goto invalid; + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; + } + if (aSign) goto invalid; + if (! bExp) { + if (! bSig) { + if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0); + return packFloatx80(bSign, 0, 0); + } + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; + } + if (aExp == 0x3FFF && ! (aSig<<1)) + return packFloatx80(bSign, 0, 0); + + softfloat_exceptionFlags |= softfloat_flag_inexact; + + int ExpDiff = aExp - 0x3FFF; + aExp = 0; + if (aSig >= SQRT2_HALF_SIG) { + ExpDiff++; + aExp--; + } + + /* ******************************** */ + /* using float128 for approximation */ + /* ******************************** */ + + float128_t b128 = softfloat_normRoundPackToF128(bSign, bExp-0x10, bSig, 0); + + uint64_t zSig0, zSig1; + shortShift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); + float128_t x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1); + x = poly_l2(x); + x = f128_add(x, i32_to_f128(ExpDiff)); + x = f128_mul(x, b128); + return f128_to_extF80(x); +} + +// ================================================= +// FYL2XP1 Compute y * log (x + 1) +// 2 +// ================================================= + +// +// Uses the following identities: +// +// 1. ---------------------------------------------------------- +// ln(x) +// log (x) = ------- +// 2 ln(2) +// +// 2. ---------------------------------------------------------- +// 1+u x +// ln (x+1) = ln -----, when u = ----- +// 1-u x+2 +// +// 3. ---------------------------------------------------------- +// 3 5 7 2n+1 +// 1+u u u u u +// ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ] +// 1-u 3 5 7 2n+1 +// + +extFloat80_t extFloat80_fyl2xp1(extFloat80_t a, extFloat80_t b) +{ + int32_t aExp, bExp; + uint64_t aSig, bSig, zSig0, zSig1, zSig2; + int aSign, bSign; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { +invalid: + softfloat_exceptionFlags |= softfloat_flag_invalid; + return floatx80_default_nan; + } + + + aSig = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); + bSig = extF80_fraction(b); + bExp = extF80_exp(b); + bSign = extF80_sign(b); + int zSign = aSign ^ bSign; + + if (aExp == 0x7FFF) { + if ((aSig<<1) != 0 || ((bExp == 0x7FFF) && (bSig<<1) != 0)) { + const uint128 nan = softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig); + extFloat80_t rv; + rv.signExp = nan.v64; + rv.signif = nan.v0; + return rv; + } + if (aSign) goto invalid; + else { + if (! bExp) { + if (! bSig) goto invalid; + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + } + return packFloatx80(bSign, 0x7FFF, uint64_t(0x8000000000000000)); + } + } + if (bExp == 0x7FFF) + { + if (bSig << 1) { + const uint128 nan = softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig); + extFloat80_t rv; + rv.signExp = nan.v64; + rv.signif = nan.v0; + return rv; + } + if (! aExp) { + if (! aSig) goto invalid; + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + } + + return packFloatx80(zSign, 0x7FFF, uint64_t(0x8000000000000000)); + } + if (! aExp) { + if (! aSig) { + if (bSig && ! bExp) + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + + return packFloatx80(zSign, 0, 0); + } + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; + } + if (! bExp) { + if (! bSig) return packFloatx80(zSign, 0, 0); + softfloat_exceptionFlags |= softfloat_flag_invalid; // actually denormal + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; + } + + softfloat_exceptionFlags |= softfloat_flag_inexact; + + if (aSign && aExp >= 0x3FFF) + return a; + + if (aExp >= 0x3FFC) // big argument + { + return extFloat80_fyl2x(extF80_add(a, floatx80_one), b); + } + + // handle tiny argument + if (aExp < FLOATX80_EXP_BIAS-70) + { + // first order approximation, return (a*b)/ln(2) + int32_t zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE; + + mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2); + if (0 < (int64_t) zSig0) { + shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); + --zExp; + } + + zExp = zExp + bExp - 0x3FFE; + mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2); + if (0 < (int64_t) zSig0) { + shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); + --zExp; + } + + return softfloat_roundPackToExtF80(aSign ^ bSign, zExp, zSig0, zSig1, 80); + } + + /* ******************************** */ + /* using float128 for approximation */ + /* ******************************** */ + + float128_t b128 = softfloat_normRoundPackToF128(bSign, bExp-0x10, bSig, 0); + + shortShift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); + float128_t x = packFloat128(aSign, aExp, zSig0, zSig1); + x = poly_l2p1(x); + x = f128_mul(x, b128); + return f128_to_extF80(x); +} + +extFloat80_t extFloat80_lognp1(extFloat80_t a) +{ + return extFloat80_fyl2x(a, floatx80_ln_2); +} + +extFloat80_t extFloat80_logn(extFloat80_t a) +{ + return extFloat80_fyl2x(a, floatx80_ln_2); +} + +extFloat80_t extFloat80_log2(extFloat80_t a) +{ + return extFloat80_fyl2x(a, floatx80_one); +} + +extFloat80_t extFloat80_log10(extFloat80_t a) +{ + return extFloat80_fyl2x(a, floatx80_log10_2); +} diff --git a/3rdparty/softfloat3/bochs_ext/poly.c b/3rdparty/softfloat3/bochs_ext/poly.c new file mode 100644 index 00000000000..3498e29ec4d --- /dev/null +++ b/3rdparty/softfloat3/bochs_ext/poly.c @@ -0,0 +1,91 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Written for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#include <assert.h> + +#include "../source/include/softfloat.h" + +// 2 3 4 n +// f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) +// 0 1 2 3 4 n +// +// -- 2k -- 2k+1 +// p(x) = > C * x q(x) = > C * x +// -- 2k -- 2k+1 +// +// f(x) ~ [ p(x) + x * q(x) ] +// + +float128_t EvalPoly(float128_t x, const float128_t *arr, int n) +{ + float128_t r = arr[--n]; + + do { + r = f128_mulAdd(r, x, arr[--n]); +// r = f128_mul(r, x); +// r = f128_add(r, arr[--n]); + + } while (n > 0); + + return r; +} + +// 2 4 6 8 2n +// f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) +// 0 1 2 3 4 n +// +// -- 4k -- 4k+2 +// p(x) = > C * x q(x) = > C * x +// -- 2k -- 2k+1 +// +// 2 +// f(x) ~ [ p(x) + x * q(x) ] +// + +float128_t EvenPoly(float128_t x, const float128_t *arr, int n) +{ + return EvalPoly(f128_mul(x, x), arr, n); +} + +// 3 5 7 9 2n+1 +// f(x) ~ (C * x) + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) +// 0 1 2 3 4 n +// 2 4 6 8 2n +// = x * [ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) +// 0 1 2 3 4 n +// +// -- 4k -- 4k+2 +// p(x) = > C * x q(x) = > C * x +// -- 2k -- 2k+1 +// +// 2 +// f(x) ~ x * [ p(x) + x * q(x) ] +// + +float128_t OddPoly(float128_t x, const float128_t *arr, int n) +{ + return f128_mul(x, EvenPoly(x, arr, n)); +} + diff --git a/3rdparty/softfloat3/bochs_ext/softfloat-extra.h b/3rdparty/softfloat3/bochs_ext/softfloat-extra.h new file mode 100644 index 00000000000..087656e5a58 --- /dev/null +++ b/3rdparty/softfloat3/bochs_ext/softfloat-extra.h @@ -0,0 +1,68 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef softfloat_extra_h +#define softfloat_extra_h 1 + +#include "../source/include/internals.h" + +// ======= floatx80 ======= // + +inline bool extF80_isUnsupported(extFloat80_t a) +{ + return ((a.signExp & 0x7FFF) && !(a.signif & uint64_t(0x8000000000000000))); +} + +inline bool extF80_sign(extFloat80_t a) +{ + return signExtF80UI64(a.signExp); +} + +inline int16_t extF80_exp(extFloat80_t a) +{ + return expExtF80UI64(a.signExp); +} + +inline uint64_t extF80_fraction(extFloat80_t a) +{ + return a.signif; +} + +extFloat80_t &floatx80_chs(extFloat80_t ®); + +extFloat80_t packToExtF80(uint16_t signExp, uint64_t sig); +extFloat80_t packToExtF80(bool sign, uint16_t exp, uint64_t sig); + +#endif diff --git a/3rdparty/softfloat3/bochs_ext/softfloat-helpers.h b/3rdparty/softfloat3/bochs_ext/softfloat-helpers.h new file mode 100644 index 00000000000..b8833a126e6 --- /dev/null +++ b/3rdparty/softfloat3/bochs_ext/softfloat-helpers.h @@ -0,0 +1,159 @@ +/*============================================================================ +This source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) +floating point emulation. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +#ifndef _SOFTFLOAT_HELPERS_H_ +#define _SOFTFLOAT_HELPERS_H_ + +#include <assert.h> +#include <stdint.h> + +#include "../source/include/primitives.h" +#include "../source/include/primitiveTypes.h" + +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by +| `b' to obtain a 192-bit product. The product is broken into three 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and +| `z2Ptr'. +*----------------------------------------------------------------------------*/ + +inline void mul128By64To192(uint64_t a64, uint64_t a0, uint64_t b, uint64_t *z0Ptr, uint64_t *z1Ptr, uint64_t *z2Ptr) +{ + uint64_t zPtr[4]; + + softfloat_mul128To256M(a64, a0, 0, b, (uint64_t*) zPtr); + + assert(zPtr[indexWord(4, 3)] == 0); + + *z0Ptr = zPtr[indexWord(4, 2)]; + *z1Ptr = zPtr[indexWord(4, 1)]; + *z2Ptr = zPtr[indexWord(4, 0)]; +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' must be less than 64. The result is broken into two 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +inline void shortShift128Left(uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr) +{ + *z1Ptr = a1<<count; + *z0Ptr = (count == 0) ? a0 : (a0<<count) | (a1>>((-count) & 63)); +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' must be less than 64. The result is broken into two 64-bit pieces +| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +inline void shortShift128Right(uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr) +{ + uint64_t z0 = a0, z1 = a1; + int negCount = (-count) & 63; + + if (count != 0) { + z1 = (a0<<negCount) | (a1>>count); + z0 = a0>>count; + } + *z1Ptr = z1; + *z0Ptr = z0; +} + +/*---------------------------------------------------------------------------- +| Returns an approximation to the 64-bit integer quotient obtained by dividing +| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The +| divisor `b' must be at least 2^63. If q is the exact quotient truncated +| toward zero, the approximation returned lies between q and q + 2 inclusive. +| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit +| unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +#ifdef USE_estimateDiv128To64 +static uint64_t estimateDiv128To64(uint64_t a0, uint64_t a1, uint64_t b) +{ + uint128 term, rem; + uint64_t b0, b1; + uint64_t z; + if (b <= a0) return uint64_t(0xFFFFFFFFFFFFFFFF); + b0 = b>>32; + z = (b0<<32 <= a0) ? uint64_t(0xFFFFFFFF00000000) : (a0 / b0)<<32; + term = softfloat_mul64To128(b, z); + rem = softfloat_sub128(a0, a1, term.v64, term.v0); + while (((int64_t) rem.v64) < 0) { + z -= UINT64_C(0x100000000); + b1 = b<<32; + rem = softfloat_add128(rem.v64, rem.v0, b0, b1); + } + rem.v64 = (rem.v64<<32) | (rem.v0>>32); + z |= (b0<<32 <= rem.v64) ? 0xFFFFFFFF : rem.v64 / b0; + return z; +} +#endif + +/*---------------------------------------------------------------------------- +| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the +| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is +| modulo 2^192, so any carry out is lost. The result is broken into three +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', +| `z1Ptr', and `z2Ptr'. +*----------------------------------------------------------------------------*/ + +inline void add192(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t b0, uint64_t b1, uint64_t b2, uint64_t *z0Ptr, uint64_t *z1Ptr, uint64_t *z2Ptr) +{ + uint64_t z0, z1, z2; + unsigned carry0, carry1; + + z2 = a2 + b2; + carry1 = (z2 < a2); + z1 = a1 + b1; + carry0 = (z1 < a1); + z0 = a0 + b0; + z1 += carry1; + z0 += (z1 < carry1); + z0 += carry0; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; +} + +/*---------------------------------------------------------------------------- +| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the +| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo +| 2^128, so any borrow out (carry out) is lost. The result is broken into two +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and +| `z1Ptr'. +*----------------------------------------------------------------------------*/ + +inline void sub128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr) +{ + *z1Ptr = a1 - b1; + *z0Ptr = a0 - b0 - (a1 < b1); +} + +#endif diff --git a/3rdparty/softfloat3/bochs_ext/softfloat-specialize.h b/3rdparty/softfloat3/bochs_ext/softfloat-specialize.h new file mode 100644 index 00000000000..f4c5bd2b2cd --- /dev/null +++ b/3rdparty/softfloat3/bochs_ext/softfloat-specialize.h @@ -0,0 +1,223 @@ +/*============================================================================ +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +#ifndef _SOFTFLOAT_SPECIALIZE_H_ +#define _SOFTFLOAT_SPECIALIZE_H_ + +#include "../source/include/softfloat_types.h" +#include "../source/8086/specialize.h" + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +const int16_t int16_indefinite = (int16_t) 0x8000; +const int32_t int32_indefinite = (int32_t) 0x80000000; +const int64_t int64_indefinite = (int64_t) uint64_t(0x8000000000000000); + +const uint16_t uint16_indefinite = 0xffff; +const uint32_t uint32_indefinite = 0xffffffff; +const uint64_t uint64_indefinite = uint64_t(0xffffffffffffffff); + +/*---------------------------------------------------------------------------- +| Commonly used half-precision floating point constants +*----------------------------------------------------------------------------*/ +const uint16_t float16_negative_inf = 0xfc00; +const uint16_t float16_positive_inf = 0x7c00; +const uint16_t float16_negative_zero = 0x8000; +const uint16_t float16_positive_zero = 0x0000; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated half-precision NaN. +*----------------------------------------------------------------------------*/ +const uint16_t float16_default_nan = 0xFE00; + +#define FLOAT16_EXP_BIAS 0xF + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| single-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +inline uint16_t packFloat16(int zSign, int zExp, uint16_t zSig) +{ + return (((uint16_t) zSign)<<15) + (((uint16_t) zExp)<<10) + zSig; +} + +/*---------------------------------------------------------------------------- +| Commonly used single-precision floating point constants +*----------------------------------------------------------------------------*/ +const uint32_t float32_negative_inf = 0xff800000; +const uint32_t float32_positive_inf = 0x7f800000; +const uint32_t float32_negative_zero = 0x80000000; +const uint32_t float32_positive_zero = 0x00000000; +const uint32_t float32_negative_one = 0xbf800000; +const uint32_t float32_positive_one = 0x3f800000; +const uint32_t float32_max_float = 0x7f7fffff; +const uint32_t float32_min_float = 0xff7fffff; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated single-precision NaN. +*----------------------------------------------------------------------------*/ +const uint32_t float32_default_nan = 0xffc00000; + +#define FLOAT32_EXP_BIAS 0x7F + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| single-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +inline uint32_t packFloat32(int zSign, int16_t zExp, uint32_t zSig) +{ + return (((uint32_t) zSign)<<31) + (((uint32_t) zExp)<<23) + zSig; +} + +/*---------------------------------------------------------------------------- +| Commonly used single-precision floating point constants +*----------------------------------------------------------------------------*/ +const uint64_t float64_negative_inf = uint64_t(0xfff0000000000000); +const uint64_t float64_positive_inf = uint64_t(0x7ff0000000000000); +const uint64_t float64_negative_zero = uint64_t(0x8000000000000000); +const uint64_t float64_positive_zero = uint64_t(0x0000000000000000); +const uint64_t float64_negative_one = uint64_t(0xbff0000000000000); +const uint64_t float64_positive_one = uint64_t(0x3ff0000000000000); +const uint64_t float64_max_float = uint64_t(0x7fefffffffffffff); +const uint64_t float64_min_float = uint64_t(0xffefffffffffffff); + +/*---------------------------------------------------------------------------- +| The pattern for a default generated double-precision NaN. +*----------------------------------------------------------------------------*/ +const uint64_t float64_default_nan = uint64_t(0xFFF8000000000000); + +#define FLOAT64_EXP_BIAS 0x3FF + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| double-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +inline uint64_t packFloat64(int zSign, int16_t zExp, uint64_t zSig) +{ + return (((uint64_t) zSign)<<63) + (((uint64_t) zExp)<<52) + zSig; +} + +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. The +| `high' and `low' values hold the most- and least-significant bits, +| respectively. +*----------------------------------------------------------------------------*/ +#define floatx80_default_nan_exp 0xFFFF +#define floatx80_default_nan_fraction uint64_t(0xC000000000000000) + +#define FLOATX80_EXP_BIAS 0x3FFF + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an +| extended double-precision floating-point value, returning the result. +*----------------------------------------------------------------------------*/ + +inline extFloat80_t packFloatx80(int zSign, int32_t zExp, uint64_t zSig) +{ + extFloat80_t z; + z.signif = zSig; + z.signExp = (zSign << 15) + zExp; + return z; +} + +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ +static const extFloat80_t floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', the exponent `zExp', and the significand formed +| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision +| floating-point value, returning the result. After being shifted into the +| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply +| added together to form the most significant 32 bits of the result. This +| means that any integer portion of `zSig0' will be added into the exponent. +| Since a properly normalized significand will have an integer portion equal +| to 1, the `zExp' input should be 1 less than the desired result exponent +| whenever `zSig0' and `zSig1' concatenated form a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +inline float128_t packFloat128(int zSign, int32_t zExp, uint64_t zSig0, uint64_t zSig1) +{ + float128_t z; + z.v[0] = zSig1; + z.v[1] = (((uint64_t) zSign)<<63) + (((uint64_t) zExp)<<48) + zSig0; + return z; +} + +/*---------------------------------------------------------------------------- +| Packs two 64-bit precision integers into into the quadruple-precision +| floating-point value, returning the result. +*----------------------------------------------------------------------------*/ + +inline float128_t packFloat128(uint64_t zHi, uint64_t zLo) +{ + float128_t z; + z.v[0] = zLo; + z.v[1] = zHi; + return z; +} + +#ifdef _MSC_VER +#define PACK_FLOAT_128(hi,lo) { lo, hi } +#else +#define PACK_FLOAT_128(hi,lo) packFloat128(uint64_t(hi),uint64_t(lo)) +#endif + +#endif /* FLOAT128 */ + +#endif diff --git a/3rdparty/softfloat3/bochs_ext/softfloat3_ext.h b/3rdparty/softfloat3/bochs_ext/softfloat3_ext.h new file mode 100644 index 00000000000..b6f560bb45a --- /dev/null +++ b/3rdparty/softfloat3/bochs_ext/softfloat3_ext.h @@ -0,0 +1,17 @@ +int extFloat80_ieee754_remainder(extFloat80_t a, extFloat80_t b, extFloat80_t &r, uint64_t &q); +int extFloat80_remainder(extFloat80_t a, extFloat80_t b, extFloat80_t &r, uint64_t &q); +int extFloat80_sincos(extFloat80_t a, extFloat80_t *sin_a, extFloat80_t *cos_a); +int extFloat80_sin(extFloat80_t &a); +int extFloat80_cos(extFloat80_t &a); +int extFloat80_tan(extFloat80_t &a); +extFloat80_t extFloat80_atan(extFloat80_t a, extFloat80_t b); +extFloat80_t extFloat80_68katan(extFloat80_t a); +extFloat80_t extFloat80_getman(extFloat80_t a); +extFloat80_t extFloat80_fyl2x(extFloat80_t a, extFloat80_t b); +extFloat80_t extFloat80_fyl2xp1(extFloat80_t a, extFloat80_t b); +extFloat80_t extFloat80_2xm1(extFloat80_t a); +extFloat80_t extFloat80_lognp1(extFloat80_t a); +extFloat80_t extFloat80_logn(extFloat80_t a); +extFloat80_t extFloat80_log2(extFloat80_t a); +extFloat80_t extFloat80_log10(extFloat80_t a); +extFloat80_t extFloat80_scale(extFloat80_t a, extFloat80_t b); diff --git a/3rdparty/softfloat3/build/MAME/platform.h b/3rdparty/softfloat3/build/MAME/platform.h index 5dfa704955c..6fd29db58fd 100644 --- a/3rdparty/softfloat3/build/MAME/platform.h +++ b/3rdparty/softfloat3/build/MAME/platform.h @@ -33,7 +33,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ - +# /*---------------------------------------------------------------------------- Softfloat 3 MAME modifications *----------------------------------------------------------------------------*/ @@ -45,11 +45,7 @@ Softfloat 3 MAME modifications /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ -#ifdef __GNUC_STDC_INLINE__ -#define INLINE inline -#else -#define INLINE extern inline -#endif +#define INLINE static inline /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ @@ -78,4 +74,4 @@ Softfloat 3 MAME modifications #endif // defined(_MSC_VER) -#include "opts-GCC.h" +#include "../../source/include/opts-GCC.h" diff --git a/3rdparty/softfloat3/source/include/softfloat.h b/3rdparty/softfloat3/source/include/softfloat.h index 9ed17c1b90d..863796d3b4b 100644 --- a/3rdparty/softfloat3/source/include/softfloat.h +++ b/3rdparty/softfloat3/source/include/softfloat.h @@ -46,6 +46,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef softfloat_h #define softfloat_h 1 +// copy config #defines from 3rdparty.lua to match the build configuration +#ifndef SOFTFLOAT_FAST_INT64 +#define SOFTFLOAT_FAST_INT64 +#define SOFTFLOAT_FAST_DIV32TO16 +#define SOFTFLOAT_FAST_DIV64TO32 +#define SOFTFLOAT_ROUND_ODD +#endif + +#ifndef INLINE_LEVEL +#define INLINE_LEVEL (5) +#endif + +#ifndef INLINE +#define INLINE static inline +#endif + #include <stdbool.h> #include <stdint.h> #include "softfloat_types.h" @@ -59,8 +75,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------*/ extern THREAD_LOCAL uint_fast8_t softfloat_detectTininess; enum { - softfloat_tininess_beforeRounding = 0, - softfloat_tininess_afterRounding = 1 + softfloat_tininess_beforeRounding = 0, + softfloat_tininess_afterRounding = 1 }; /*---------------------------------------------------------------------------- @@ -69,12 +85,12 @@ enum { *----------------------------------------------------------------------------*/ extern THREAD_LOCAL uint_fast8_t softfloat_roundingMode; enum { - softfloat_round_near_even = 0, - softfloat_round_minMag = 1, - softfloat_round_min = 2, - softfloat_round_max = 3, - softfloat_round_near_maxMag = 4, - softfloat_round_odd = 6 + softfloat_round_near_even = 0, + softfloat_round_minMag = 1, + softfloat_round_min = 2, + softfloat_round_max = 3, + softfloat_round_near_maxMag = 4, + softfloat_round_odd = 6 }; /*---------------------------------------------------------------------------- @@ -82,11 +98,11 @@ enum { *----------------------------------------------------------------------------*/ extern THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags; enum { - softfloat_flag_inexact = 1, - softfloat_flag_underflow = 2, - softfloat_flag_overflow = 4, - softfloat_flag_infinite = 8, - softfloat_flag_invalid = 16 + softfloat_flag_inexact = 1, + softfloat_flag_underflow = 2, + softfloat_flag_overflow = 4, + softfloat_flag_infinite = 8, + softfloat_flag_invalid = 16 }; /*---------------------------------------------------------------------------- @@ -290,7 +306,7 @@ float64_t extF80M_to_f64( const extFloat80_t * ); void extF80M_to_f128M( const extFloat80_t *, float128_t * ); void extF80M_roundToInt( - const extFloat80_t *, uint_fast8_t, bool, extFloat80_t * ); + const extFloat80_t *, uint_fast8_t, bool, extFloat80_t * ); void extF80M_add( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); void extF80M_sub( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); void extF80M_mul( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); @@ -355,7 +371,7 @@ void f128M_sub( const float128_t *, const float128_t *, float128_t * ); void f128M_mul( const float128_t *, const float128_t *, float128_t * ); void f128M_mulAdd( - const float128_t *, const float128_t *, const float128_t *, float128_t * + const float128_t *, const float128_t *, const float128_t *, float128_t * ); void f128M_div( const float128_t *, const float128_t *, float128_t * ); void f128M_rem( const float128_t *, const float128_t *, float128_t * ); diff --git a/3rdparty/softfloat3/source/include/softfloat_types.h b/3rdparty/softfloat3/source/include/softfloat_types.h index b92d24625eb..3657ac0483d 100644 --- a/3rdparty/softfloat3/source/include/softfloat_types.h +++ b/3rdparty/softfloat3/source/include/softfloat_types.h @@ -39,6 +39,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <stdint.h> +// MAME: when #included from actual MAME code, we need the endianness to match what the build system set +#ifdef LSB_FIRST +#ifndef LITTLEENDIAN +#define LITTLEENDIAN +#endif +#endif + /*---------------------------------------------------------------------------- | Types used to pass 16-bit, 32-bit, 64-bit, and 128-bit floating-point | arguments and results to/from functions. These types must be exactly |