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.
This commit is contained in:
arbee 2024-05-27 20:40:42 -04:00
parent cd25f2de50
commit 6957c46998
18 changed files with 3046 additions and 432 deletions

View File

@ -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);
}

186
3rdparty/softfloat3/bochs_ext/f2xm1.c vendored Normal file
View File

@ -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;
}
}

326
3rdparty/softfloat3/bochs_ext/fpatan.c vendored Normal file
View File

@ -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);
}

255
3rdparty/softfloat3/bochs_ext/fprem.c vendored Normal file
View File

@ -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);
}

View File

@ -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

457
3rdparty/softfloat3/bochs_ext/fsincos.c vendored Normal file
View File

@ -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)
{
reg.signExp ^= 0x8000;
return reg;
}

409
3rdparty/softfloat3/bochs_ext/fyl2x.c vendored Normal file
View File

@ -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);
}

91
3rdparty/softfloat3/bochs_ext/poly.c vendored Normal file
View File

@ -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));
}

View File

@ -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 &reg);
extFloat80_t packToExtF80(uint16_t signExp, uint64_t sig);
extFloat80_t packToExtF80(bool sign, uint16_t exp, uint64_t sig);
#endif

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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"

View File

@ -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 * );

View File

@ -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

View File

@ -285,6 +285,7 @@ project "softfloat3"
MAME_DIR .. "3rdparty/softfloat3/source",
MAME_DIR .. "3rdparty/softfloat3/source/include",
MAME_DIR .. "3rdparty/softfloat3/source/8086",
MAME_DIR .. "3rdparty/softfloat3/bochs_ext"
}
configuration { "gmake or ninja" }
@ -313,6 +314,11 @@ end
"SOFTFLOAT_FAST_INT64"
}
if _OPTIONS["BIGENDIAN"]~="1" then
defines {
"LITTLEENDIAN=1"
}
end
files {
MAME_DIR .. "3rdparty/softfloat3/source/s_eq128.c",
MAME_DIR .. "3rdparty/softfloat3/source/s_le128.c",
@ -615,6 +621,13 @@ end
MAME_DIR .. "3rdparty/softfloat3/source/f128M_eq_signaling.c",
MAME_DIR .. "3rdparty/softfloat3/source/f128M_le_quiet.c",
MAME_DIR .. "3rdparty/softfloat3/source/f128M_lt_quiet.c",
MAME_DIR .. "3rdparty/softfloat3/bochs_ext/f2xm1.c",
MAME_DIR .. "3rdparty/softfloat3/bochs_ext/fpatan.c",
MAME_DIR .. "3rdparty/softfloat3/bochs_ext/fprem.c",
MAME_DIR .. "3rdparty/softfloat3/bochs_ext/fsincos.c",
MAME_DIR .. "3rdparty/softfloat3/bochs_ext/fyl2x.c",
MAME_DIR .. "3rdparty/softfloat3/bochs_ext/poly.c",
MAME_DIR .. "3rdparty/softfloat3/bochs_ext/extF80_scale.c",
}

File diff suppressed because it is too large Load Diff

View File

@ -7,15 +7,8 @@
#include "m68kcommon.h"
// SoftFloat 2 lacks an include guard
#ifndef softfloat2_h
#define softfloat2_h 1
#include "softfloat/milieu.h"
#include "softfloat/softfloat.h"
#endif
extern flag floatx80_is_nan(floatx80 a);
#include "softfloat3/source/include/softfloat.h"
#include "softfloat3/bochs_ext/softfloat3_ext.h"
/* MMU constants */
constexpr int MMU_ATC_ENTRIES = (22); // 68851 has 64, 030 has 22
@ -152,7 +145,7 @@ protected:
u32 m_cacr; /* Cache Control Register (m68020, unemulated) */
u32 m_caar; /* Cache Address Register (m68020, unemulated) */
u32 m_ir; /* Instruction Register */
floatx80 m_fpr[8]; /* FPU Data Register (m68030/040) */
extFloat80_t m_fpr[8]; /* FPU Data Register (m68030/040) */
u32 m_fpiar; /* FPU Instruction Address Register (m68040) */
u32 m_fpsr; /* FPU Status Register (m68040) */
u32 m_fpcr; /* FPU Control Register (m68040) */
@ -329,48 +322,45 @@ protected:
#include "m68kops.h"
#include "m68kmmu.h"
static double fx80_to_double(floatx80 fx)
static double fx80_to_double(extFloat80_t fx)
{
u64 d;
double *foo;
foo = (double *)&d;
d = floatx80_to_float64(fx);
const float64_t d = extF80_to_f64(fx);
const double *foo = (double *)&d;
return *foo;
}
static floatx80 double_to_fx80(double in)
static extFloat80_t double_to_fx80(double in)
{
u64 *d;
float64_t *d = (float64_t *)&in;
d = (u64 *)&in;
return float64_to_floatx80(*d);
return f64_to_extF80(*d);
}
// defined in m68kfpu.cpp
static const u32 pkmask2[18];
static const u32 pkmask3[18];
inline floatx80 load_extended_float80(u32 ea);
inline void store_extended_float80(u32 ea, floatx80 fpr);
inline floatx80 load_pack_float80(u32 ea);
inline void store_pack_float80(u32 ea, int k, floatx80 fpr);
inline void SET_CONDITION_CODES(floatx80 reg);
inline int TEST_CONDITION(int condition);
inline extFloat80_t load_extended_float80(u32 ea);
inline void store_extended_float80(u32 ea, extFloat80_t fpr);
inline extFloat80_t load_pack_float80(u32 ea);
inline void store_pack_float80(u32 ea, int k, extFloat80_t fpr);
void set_condition_codes(extFloat80_t reg);
int test_condition(int condition);
void clear_exception_flags();
void sync_exception_flags(extFloat80_t op1, extFloat80_t op2, u32 enables);
s32 convert_to_int(extFloat80_t source, s32 lowerLimit, s32 upperLimit);
u8 READ_EA_8(int ea);
u16 READ_EA_16(int ea);
u32 READ_EA_32(int ea);
u64 READ_EA_64(int ea);
floatx80 READ_EA_FPE(int mode, int reg, uint32 di_mode_ea);
floatx80 READ_EA_PACK(int ea);
extFloat80_t READ_EA_FPE(int mode, int reg, uint32_t di_mode_ea);
extFloat80_t READ_EA_PACK(int ea);
void WRITE_EA_8(int ea, u8 data);
void WRITE_EA_16(int ea, u16 data);
void WRITE_EA_32(int ea, u32 data);
void WRITE_EA_64(int ea, u64 data);
void WRITE_EA_FPE(int mode, int reg, floatx80 fpr, uint32 di_mode_ea);
void WRITE_EA_PACK(int ea, int k, floatx80 fpr);
void WRITE_EA_FPE(int mode, int reg, extFloat80_t fpr, uint32_t di_mode_ea);
void WRITE_EA_PACK(int ea, int k, extFloat80_t fpr);
void fpgen_rm_reg(u16 w2);
void fmove_reg_mem(u16 w2);
void fmove_fpcr(u16 w2);