mirror of
https://github.com/captain-amygdala/pistorm.git
synced 2026-01-28 20:41:08 +00:00
Merge pull request #19 from beeanyew/wip-crap
Full FPU, PiSCSI readme update
This commit is contained in:
2
Makefile
2
Makefile
@@ -21,7 +21,7 @@ MAINFILES = emulator.c \
|
||||
platforms/amiga/net/pi-net.c \
|
||||
platforms/shared/rtc.c
|
||||
|
||||
MUSASHIFILES = m68kcpu.c m68kdasm.c softfloat/softfloat.c softfloat/fsincos.c softfloat/fyl2x.c
|
||||
MUSASHIFILES = m68kcpu.c m68kdasm.c softfloat/softfloat.c softfloat/softfloat_fpsp.c
|
||||
MUSASHIGENCFILES = m68kops.c
|
||||
MUSASHIGENHFILES = m68kops.h
|
||||
MUSASHIGENERATOR = m68kmake
|
||||
|
||||
221
m68kfpu.c
221
m68kfpu.c
@@ -3,6 +3,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "softfloat/softfloat.h"
|
||||
float_status status;
|
||||
|
||||
extern void exit(int);
|
||||
|
||||
static void fatalerror(char *format, ...) {
|
||||
@@ -25,7 +28,18 @@ static void fatalerror(char *format, ...) {
|
||||
#define DOUBLE_EXPONENT (unsigned long long)(0x7ff0000000000000)
|
||||
#define DOUBLE_MANTISSA (unsigned long long)(0x000fffffffffffff)
|
||||
|
||||
extern flag floatx80_is_nan( floatx80 a );
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the extended double-precision floating-point value `a' is a
|
||||
| NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag floatx80_is_nan( floatx80 a )
|
||||
{
|
||||
|
||||
return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (uint64_t) ( a.low<<1 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// masks for packed dwords, positive k-factor
|
||||
static uint32 pkmask2[18] =
|
||||
@@ -50,7 +64,7 @@ static inline double fx80_to_double(floatx80 fx)
|
||||
|
||||
foo = (double *)&d;
|
||||
|
||||
d = floatx80_to_float64(fx);
|
||||
d = floatx80_to_float64(fx, &status);
|
||||
|
||||
return *foo;
|
||||
}
|
||||
@@ -61,7 +75,7 @@ static inline floatx80 double_to_fx80(double in)
|
||||
|
||||
d = (uint64 *)∈
|
||||
|
||||
return float64_to_floatx80(*d);
|
||||
return float64_to_floatx80(*d, &status);
|
||||
}
|
||||
|
||||
static inline floatx80 load_extended_float80(uint32 ea)
|
||||
@@ -1229,7 +1243,7 @@ static void fpgen_rm_reg(uint16 w2)
|
||||
case 1: // Single-precision Real
|
||||
{
|
||||
uint32 d = READ_EA_32(ea);
|
||||
source = float32_to_floatx80(d);
|
||||
source = float32_to_floatx80(d, &status);
|
||||
break;
|
||||
}
|
||||
case 2: // Extended-precision Real
|
||||
@@ -1252,7 +1266,7 @@ static void fpgen_rm_reg(uint16 w2)
|
||||
{
|
||||
uint64 d = READ_EA_64(ea);
|
||||
|
||||
source = float64_to_floatx80(d);
|
||||
source = float64_to_floatx80(d, &status);
|
||||
break;
|
||||
}
|
||||
case 6: // Byte Integer
|
||||
@@ -1403,16 +1417,24 @@ static void fpgen_rm_reg(uint16 w2)
|
||||
case 0x01: // FINT
|
||||
{
|
||||
sint32 temp;
|
||||
temp = floatx80_to_int32(source);
|
||||
temp = floatx80_to_int32(source, &status);
|
||||
REG_FP[dst] = int32_to_floatx80(temp);
|
||||
//FIXME mame doesn't use SET_CONDITION_CODES here
|
||||
SET_CONDITION_CODES(REG_FP[dst]); // JFF needs update condition codes
|
||||
USE_CYCLES(4);
|
||||
break;
|
||||
}
|
||||
case 0x02: // FSINH
|
||||
{
|
||||
REG_FP[dst] = floatx80_sinh(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(75);
|
||||
break;
|
||||
}
|
||||
case 0x03: // FINTRZ
|
||||
{
|
||||
sint32 temp;
|
||||
temp = floatx80_to_int32_round_to_zero(source);
|
||||
temp = floatx80_to_int32_round_to_zero(source, &status);
|
||||
REG_FP[dst] = int32_to_floatx80(temp);
|
||||
//FIXME mame doesn't use SET_CONDITION_CODES here
|
||||
SET_CONDITION_CODES(REG_FP[dst]); // JFF needs update condition codes
|
||||
@@ -1420,51 +1442,105 @@ static void fpgen_rm_reg(uint16 w2)
|
||||
}
|
||||
case 0x04: // FSQRT
|
||||
{
|
||||
REG_FP[dst] = floatx80_sqrt(source);
|
||||
REG_FP[dst] = floatx80_sqrt(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(109);
|
||||
break;
|
||||
}
|
||||
case 0x06: // FLOGNP1
|
||||
{
|
||||
REG_FP[dst] = floatx80_flognp1 (source);
|
||||
REG_FP[dst] = floatx80_lognp1 (source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(594); // for MC68881
|
||||
break;
|
||||
}
|
||||
case 0x08: // FETOXM1
|
||||
{
|
||||
REG_FP[dst] = floatx80_etoxm1(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(6);
|
||||
break;
|
||||
}
|
||||
case 0x09: // FTANH
|
||||
{
|
||||
REG_FP[dst] = floatx80_tanh(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(75);
|
||||
break;
|
||||
}
|
||||
case 0x0a: // FATAN
|
||||
{
|
||||
REG_FP[dst] = floatx80_atan(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(75);
|
||||
break;
|
||||
}
|
||||
case 0x0c: // FASIN
|
||||
{
|
||||
REG_FP[dst] = floatx80_asin(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(75);
|
||||
break;
|
||||
}
|
||||
case 0x0d: // FATANH
|
||||
{
|
||||
REG_FP[dst] = floatx80_atanh(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(75);
|
||||
break;
|
||||
}
|
||||
case 0x0e: // FSIN
|
||||
{
|
||||
REG_FP[dst] = source;
|
||||
floatx80_fsin(®_FP[dst]);
|
||||
REG_FP[dst] = floatx80_sin(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(75);
|
||||
break;
|
||||
}
|
||||
case 0x0f: // FTAN
|
||||
{
|
||||
REG_FP[dst] = source;
|
||||
floatx80_ftan(®_FP[dst]);
|
||||
REG_FP[dst] = floatx80_tan(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(75);
|
||||
break;
|
||||
}
|
||||
case 0x10: // FETOX
|
||||
{
|
||||
REG_FP[dst] = floatx80_etox(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(75);
|
||||
break;
|
||||
}
|
||||
case 0x11: // FTWOTOX
|
||||
{
|
||||
REG_FP[dst] = floatx80_twotox(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(75);
|
||||
break;
|
||||
}
|
||||
case 0x12: // FTENTOX
|
||||
{
|
||||
REG_FP[dst] = floatx80_tentox(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(75);
|
||||
break;
|
||||
}
|
||||
case 0x14: // FLOGN
|
||||
{
|
||||
REG_FP[dst] = floatx80_flogn (source);
|
||||
REG_FP[dst] = floatx80_logn(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(548); // for MC68881
|
||||
break;
|
||||
}
|
||||
case 0x15: // FLOG10
|
||||
{
|
||||
REG_FP[dst] = floatx80_flog10 (source);
|
||||
REG_FP[dst] = floatx80_log10(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(604); // for MC68881
|
||||
break;
|
||||
}
|
||||
case 0x16: // FLOG2
|
||||
{
|
||||
REG_FP[dst] = floatx80_flog2 (source);
|
||||
REG_FP[dst] = floatx80_log2(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(604); // for MC68881
|
||||
break;
|
||||
@@ -1477,6 +1553,13 @@ static void fpgen_rm_reg(uint16 w2)
|
||||
USE_CYCLES(3);
|
||||
break;
|
||||
}
|
||||
case 0x19: // FCOSH
|
||||
{
|
||||
REG_FP[dst] = floatx80_cosh(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(64);
|
||||
break;
|
||||
}
|
||||
case 0x1a: // FNEG
|
||||
{
|
||||
REG_FP[dst] = source;
|
||||
@@ -1485,21 +1568,31 @@ static void fpgen_rm_reg(uint16 w2)
|
||||
USE_CYCLES(3);
|
||||
break;
|
||||
}
|
||||
case 0x1c: // FACOS
|
||||
{
|
||||
REG_FP[dst] = floatx80_acos(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(604); // for MC68881
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case 0x1d: // FCOS
|
||||
{
|
||||
REG_FP[dst] = source;
|
||||
floatx80_fcos(®_FP[dst]);
|
||||
REG_FP[dst] = floatx80_cos(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(75);
|
||||
break;
|
||||
}
|
||||
case 0x1e: // FGETEXP
|
||||
{
|
||||
sint16 temp2;
|
||||
|
||||
temp2 = source.high; // get the exponent
|
||||
temp2 -= 0x3fff; // take off the bias
|
||||
REG_FP[dst] = double_to_fx80((double)temp2);
|
||||
REG_FP[dst] = floatx80_getexp(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(6);
|
||||
break;
|
||||
}
|
||||
case 0x1f: // FGETMAN
|
||||
{
|
||||
REG_FP[dst] = floatx80_getman(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(6);
|
||||
break;
|
||||
@@ -1507,7 +1600,7 @@ static void fpgen_rm_reg(uint16 w2)
|
||||
case 0x60: // FSDIVS (JFF) (source has already been converted to floatx80)
|
||||
case 0x20: // FDIV
|
||||
{
|
||||
REG_FP[dst] = floatx80_div(REG_FP[dst], source);
|
||||
REG_FP[dst] = floatx80_div(REG_FP[dst], source, &status);
|
||||
//FIXME mame doesn't use SET_CONDITION_CODES here
|
||||
SET_CONDITION_CODES(REG_FP[dst]); // JFF
|
||||
USE_CYCLES(43);
|
||||
@@ -1515,17 +1608,19 @@ static void fpgen_rm_reg(uint16 w2)
|
||||
}
|
||||
case 0x21: // FMOD
|
||||
{
|
||||
sint8 const mode = float_rounding_mode;
|
||||
float_rounding_mode = float_round_to_zero;
|
||||
REG_FP[dst] = floatx80_rem(REG_FP[dst], source);
|
||||
sint8 const mode = status.float_rounding_mode;
|
||||
status.float_rounding_mode = float_round_to_zero;
|
||||
uint64_t q;
|
||||
flag s;
|
||||
REG_FP[dst] = floatx80_rem(REG_FP[dst], source, &q, &s, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
float_rounding_mode = mode;
|
||||
status.float_rounding_mode = mode;
|
||||
USE_CYCLES(43); // guess
|
||||
break;
|
||||
}
|
||||
case 0x22: // FADD
|
||||
{
|
||||
REG_FP[dst] = floatx80_add(REG_FP[dst], source);
|
||||
REG_FP[dst] = floatx80_add(REG_FP[dst], source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(9);
|
||||
break;
|
||||
@@ -1533,56 +1628,70 @@ static void fpgen_rm_reg(uint16 w2)
|
||||
case 0x63: // FSMULS (JFF) (source has already been converted to floatx80)
|
||||
case 0x23: // FMUL
|
||||
{
|
||||
REG_FP[dst] = floatx80_mul(REG_FP[dst], source);
|
||||
REG_FP[dst] = floatx80_mul(REG_FP[dst], source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(11);
|
||||
break;
|
||||
}
|
||||
case 0x24: // FSGLDIV
|
||||
{
|
||||
float32 a = floatx80_to_float32( REG_FP[dst] );
|
||||
float32 b = floatx80_to_float32( source );
|
||||
REG_FP[dst] = float32_to_floatx80( float32_div(a, b) );
|
||||
REG_FP[dst] = floatx80_sgldiv(REG_FP[dst], source, &status);
|
||||
USE_CYCLES(43); // // ? (value is from FDIV)
|
||||
break;
|
||||
}
|
||||
case 0x25: // FREM
|
||||
{
|
||||
sint8 const mode = float_rounding_mode;
|
||||
float_rounding_mode = float_round_nearest_even;
|
||||
REG_FP[dst] = floatx80_rem(REG_FP[dst], source);
|
||||
sint8 const mode = status.float_rounding_mode;
|
||||
status.float_rounding_mode = float_round_nearest_even;
|
||||
uint64_t q;
|
||||
flag s;
|
||||
REG_FP[dst] = floatx80_rem(REG_FP[dst], source, &q, &s, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
float_rounding_mode = mode;
|
||||
status.float_rounding_mode = mode;
|
||||
USE_CYCLES(43); // guess
|
||||
break;
|
||||
}
|
||||
case 0x26: // FSCALE
|
||||
{
|
||||
REG_FP[dst] = floatx80_scale(REG_FP[dst], source);
|
||||
REG_FP[dst] = floatx80_scale(REG_FP[dst], source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(46); // (better?) guess
|
||||
break;
|
||||
}
|
||||
case 0x27: // FSGLMUL
|
||||
{
|
||||
float32 a = floatx80_to_float32( REG_FP[dst] );
|
||||
float32 b = floatx80_to_float32( source );
|
||||
REG_FP[dst] = float32_to_floatx80( float32_mul(a, b) );
|
||||
REG_FP[dst] = floatx80_sglmul(REG_FP[dst], source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(11); // ? (value is from FMUL)
|
||||
break;
|
||||
}
|
||||
case 0x28: // FSUB
|
||||
{
|
||||
REG_FP[dst] = floatx80_sub(REG_FP[dst], source);
|
||||
REG_FP[dst] = floatx80_sub(REG_FP[dst], source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(9);
|
||||
break;
|
||||
}
|
||||
case 0x30: // FSINCOS
|
||||
case 0x31: // FSINCOS
|
||||
case 0x32: // FSINCOS
|
||||
case 0x33: // FSINCOS
|
||||
case 0x34: // FSINCOS
|
||||
case 0x35: // FSINCOS
|
||||
case 0x36: // FSINCOS
|
||||
case 0x37: // FSINCOS
|
||||
{
|
||||
REG_FP[dst] = floatx80_cos(source, &status);
|
||||
REG_FP[w2&7] = floatx80_sin(source, &status);
|
||||
SET_CONDITION_CODES(REG_FP[dst]);
|
||||
USE_CYCLES(75);
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x38: // FCMP
|
||||
{
|
||||
floatx80 res;
|
||||
res = floatx80_sub(REG_FP[dst], source);
|
||||
res = floatx80_sub(REG_FP[dst], source, &status);
|
||||
SET_CONDITION_CODES(res);
|
||||
USE_CYCLES(7);
|
||||
break;
|
||||
@@ -1611,13 +1720,13 @@ static void fmove_reg_mem(uint16 w2)
|
||||
{
|
||||
case 0: // Long-Word Integer
|
||||
{
|
||||
sint32 d = (sint32)floatx80_to_int32(REG_FP[src]);
|
||||
sint32 d = (sint32)floatx80_to_int32(REG_FP[src], &status);
|
||||
WRITE_EA_32(ea, d);
|
||||
break;
|
||||
}
|
||||
case 1: // Single-precision Real
|
||||
{
|
||||
uint32 d = floatx80_to_float32(REG_FP[src]);
|
||||
uint32 d = floatx80_to_float32(REG_FP[src], &status);
|
||||
WRITE_EA_32(ea, d);
|
||||
break;
|
||||
}
|
||||
@@ -1635,7 +1744,7 @@ static void fmove_reg_mem(uint16 w2)
|
||||
}
|
||||
case 4: // Word Integer
|
||||
{
|
||||
sint32 value = floatx80_to_int32(REG_FP[src]);
|
||||
sint32 value = floatx80_to_int32(REG_FP[src], &status);
|
||||
if (value > 0x7fff || value < -0x8000 )
|
||||
{
|
||||
REG_FPSR |= FPES_OE | FPAE_IOP;
|
||||
@@ -1647,14 +1756,14 @@ static void fmove_reg_mem(uint16 w2)
|
||||
{
|
||||
uint64 d;
|
||||
|
||||
d = floatx80_to_float64(REG_FP[src]);
|
||||
d = floatx80_to_float64(REG_FP[src], &status);
|
||||
|
||||
WRITE_EA_64(ea, d);
|
||||
break;
|
||||
}
|
||||
case 6: // Byte Integer
|
||||
{
|
||||
sint32 value = floatx80_to_int32(REG_FP[src]);
|
||||
sint32 value = floatx80_to_int32(REG_FP[src], &status);
|
||||
if (value > 127 || value < -128)
|
||||
{
|
||||
REG_FPSR |= FPES_OE | FPAE_IOP;
|
||||
@@ -1738,16 +1847,16 @@ static void fmove_fpcr(uint16 w2)
|
||||
switch (prec)
|
||||
{
|
||||
case 0: // Extend (X)
|
||||
floatx80_rounding_precision = 80;
|
||||
status.floatx80_rounding_precision = 80;
|
||||
break;
|
||||
case 1: // Single (S)
|
||||
floatx80_rounding_precision = 32;
|
||||
status.floatx80_rounding_precision = 32;
|
||||
break;
|
||||
case 2: // Double (D)
|
||||
floatx80_rounding_precision = 64;
|
||||
status.floatx80_rounding_precision = 64;
|
||||
break;
|
||||
case 3: // Undefined
|
||||
floatx80_rounding_precision = 80;
|
||||
status.floatx80_rounding_precision = 80;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -1755,16 +1864,16 @@ static void fmove_fpcr(uint16 w2)
|
||||
switch (rnd)
|
||||
{
|
||||
case 0: // To Nearest (RN)
|
||||
float_rounding_mode = float_round_nearest_even;
|
||||
status.float_rounding_mode = float_round_nearest_even;
|
||||
break;
|
||||
case 1: // To Zero (RZ)
|
||||
float_rounding_mode = float_round_to_zero;
|
||||
status.float_rounding_mode = float_round_to_zero;
|
||||
break;
|
||||
case 2: // To Minus Infinitiy (RM)
|
||||
float_rounding_mode = float_round_down;
|
||||
status.float_rounding_mode = float_round_down;
|
||||
break;
|
||||
case 3: // To Plus Infinitiy (RP)
|
||||
float_rounding_mode = float_round_up;
|
||||
status.float_rounding_mode = float_round_up;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,18 @@
|
||||
|
||||
A high performance replacement for scsi.device, allowing automatic booting and mounting of raw hard disk (RDB/RDSK) images.
|
||||
|
||||
This driver and interface is work in progress, do not use it in conjunction with any critical data that you need to survive.
|
||||
While this driver is considered mostly stable, it's still work in progress. Do not use it in conjunction with any critical one of a kind data that you need to survive.
|
||||
|
||||
# Compatibility
|
||||
|
||||
* PiSCSI **requires** some Fast RAM to be mapped on your PiStorm to work.
|
||||
* This may change at some point, but for now make sure that you configure at the very least a few megabytes of Fast RAM so that the boot ROM can load and initialize properly.
|
||||
* Autobooting, Kickstart 2.0 and up
|
||||
* PiSCSI does NOT work with Kickstart 1.3 yet, as it is missing some code needed to properly add boot nodes with old Kickstarts.
|
||||
* Mounting RDSK/RDB disk images, physical devices with a file system the Amiga can use
|
||||
* PiSCSI does NOT work with UAE single partition disk images prepared and formatted using WinUAE yet. You can check what type the disk image is using a hex editor, if it starts with `RDSK`, it is a full drive RDSK/RDB image, if it starts with `DOS` it is most likely a UAE single partition disk image.
|
||||
* When mounting a physical drive for use with PiSCSI, please read the `A big word of caution` at the bottom of this page
|
||||
* TrackDisk, TrackDisk64 and Direct SCSI
|
||||
|
||||
# Instructions
|
||||
|
||||
@@ -10,17 +21,21 @@ To use the PiSCSI interface, simply enable it by uncommenting the `setvar piscsi
|
||||
|
||||
Add disk images to the PiSCSI interface by uncommenting the `piscsi0` and `piscsi1` lines and editing them to point at the disk image(s) you want to use.
|
||||
|
||||
Physical drives can also be mounted using their mount point files on Linux, such as `/dev/sda` for a USB stick, but keep in mind that this is dangerous as it can destroy the contents of the disk.
|
||||
Physical drives can also be mounted using their mount point files on Linux, such as `/dev/sda` for a USB stick, but keep in mind that this is dangerous as it can destroy the contents of the disk if you're unluck or you repartition it.
|
||||
|
||||
You can mount up to 7 disk images using setvar `piscsi0` through `piscsi6`.
|
||||
|
||||
If you want EVEN MORE speed, either adjust the size of your hard drive image so that it gets properly detected with 16 heads in HDToolBox or manually edit the Cylinders/Heads settings when setting up your drive.
|
||||
For preparing a disk image on your Amiga, you can for instance make a copy of the Workbench tool `HDToolBox`, and then edit the tooltypes (`Icon -> Information` menu) to use `pi-scsi.device` instead of `scsi.device`.
|
||||
|
||||
**No copying of the pi-scsi.device driver to `DEVS:` or anything like that is necessary, as the driver is loaded from ROM on boot/config time.**
|
||||
|
||||
If you want EVEN MORE speed, either adjust the size of your hard drive image so that it gets properly detected with 16 heads in HDToolBox or manually edit the Cylinders/Heads settings when setting up your drive. Creating a disk image that is a multiple of **504 megabytes** seems suitable for this purpose.
|
||||
|
||||
(The trackdisk device on the Amiga seems to enable transfers bigger than 512 bytes (one sector) only if the drive is identified as having more than one drive head/surface.)
|
||||
|
||||
# Making changes to the driver
|
||||
|
||||
If you make changes to the driver, you can always test these on the Amiga as a regular file in `DEVS:`, but the Z2 device has to be disabled for this to work properly.
|
||||
If you make changes to the driver, you can always test these on the Amiga as a regular file in `DEVS:`, but the Z2 device has to be disabled for this to work properly. Disabling the Z2 device requires you to comment out the line `ac_z2_type[ac_z2_pic_count] = ACTYPE_PISCSI;` in `amiga-platform.c`.
|
||||
|
||||
Steps to create an updated boot ROM, all of these are done in the `device_driver_amiga` directory:
|
||||
|
||||
@@ -30,7 +45,7 @@ Steps to create an updated boot ROM, all of these are done in the `device_driver
|
||||
* (Optional) If you haven't previously compiled the `makerom` binary, or the code for it has been updated since last time, simply run `gcc makerom.c -o makerom`
|
||||
* Run `./makerom` to assemble the boot ROM file, it's automatically in the correct place for the emulator to find it.
|
||||
|
||||
# If you for instance want to mount a FAT32 disk with fat95, these old instructions may be of some use:
|
||||
# Some quick instructions for mounting a FAT32 disk image or disk using PiSCSI
|
||||
|
||||
* Download giggledisk from http://www.geit.de/eng_giggledisk.html or https://aminet.net/package/disk/misc/giggledisk to make MountLists for attached devices.
|
||||
Place the giggledisk binary in `C:` or something so that it's available in the search path.
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
MAME note: this package is derived from the following original SoftFloat
|
||||
package and has been "re-packaged" to work with MAME's conventions and
|
||||
build system. The source files come from bits64/ and bits64/templates
|
||||
in the original distribution as MAME requires a compiler with a 64-bit
|
||||
integer type.
|
||||
|
||||
|
||||
Package Overview for SoftFloat Release 2b
|
||||
|
||||
John R. Hauser
|
||||
2002 May 27
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Overview
|
||||
|
||||
SoftFloat is a software implementation of floating-point that conforms to
|
||||
the IEC/IEEE Standard for Binary Floating-Point Arithmetic. SoftFloat is
|
||||
distributed in the form of C source code. Compiling the SoftFloat sources
|
||||
generates two things:
|
||||
|
||||
-- A SoftFloat object file (typically `softfloat.o') containing the complete
|
||||
set of IEC/IEEE floating-point routines.
|
||||
|
||||
-- A `timesoftfloat' program for evaluating the speed of the SoftFloat
|
||||
routines. (The SoftFloat module is linked into this program.)
|
||||
|
||||
The SoftFloat package is documented in four text files:
|
||||
|
||||
SoftFloat.txt Documentation for using the SoftFloat functions.
|
||||
SoftFloat-source.txt Documentation for compiling SoftFloat.
|
||||
SoftFloat-history.txt History of major changes to SoftFloat.
|
||||
timesoftfloat.txt Documentation for using `timesoftfloat'.
|
||||
|
||||
Other files in the package comprise the source code for SoftFloat.
|
||||
|
||||
Please be aware that some work is involved in porting this software to other
|
||||
targets. It is not just a matter of getting `make' to complete without
|
||||
error messages. I would have written the code that way if I could, but
|
||||
there are fundamental differences between systems that can't be hidden.
|
||||
You should not attempt to compile SoftFloat without first reading both
|
||||
`SoftFloat.txt' and `SoftFloat-source.txt'.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Legal Notice
|
||||
|
||||
SoftFloat was written by me, 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.
|
||||
|
||||
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, provided
|
||||
that the minimal documentation requirements stated in the source code are
|
||||
satisfied.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Contact Information
|
||||
|
||||
At the time of this writing, the most up-to-date information about
|
||||
SoftFloat and the latest release can be found at the Web page `http://
|
||||
www.cs.berkeley.edu/~jhauser/arithmetic/SoftFloat.html'.
|
||||
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/*============================================================================
|
||||
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 (0xc90fdaa22168c234U)
|
||||
#define FLOAT_PI_LO (0xc4c6628b80dc1cd1U)
|
||||
#else
|
||||
#define FLOAT_PI_HI (0xc90fdaa22168c234U)
|
||||
#define FLOAT_PI_LO (0xC000000000000000U)
|
||||
#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 (0x96cbe3f9990e91a7U)
|
||||
#define FLOAT_3PI4_LO (0x9394c9e8a0a5159cU)
|
||||
#else
|
||||
#define FLOAT_3PI4_HI (0x96cbe3f9990e91a7U)
|
||||
#define FLOAT_3PI4_LO (0x9000000000000000U)
|
||||
#endif
|
||||
|
||||
//////////////////////////////
|
||||
// 1/LN2 constant
|
||||
//////////////////////////////
|
||||
|
||||
#define FLOAT_LN2INV_EXP (0x3FFF)
|
||||
|
||||
// 128-bit 1/LN2 fraction
|
||||
#ifdef BETTER_THAN_PENTIUM
|
||||
#define FLOAT_LN2INV_HI (0xb8aa3b295c17f0bbU)
|
||||
#define FLOAT_LN2INV_LO (0xbe87fed0691d3e89U)
|
||||
#else
|
||||
#define FLOAT_LN2INV_HI (0xb8aa3b295c17f0bbU)
|
||||
#define FLOAT_LN2INV_LO (0xC000000000000000U)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,647 +0,0 @@
|
||||
/*============================================================================
|
||||
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
|
||||
|
||||
#include "m68kcpu.h" // which includes softfloat.h after defining the basic types
|
||||
#include "assert.h"
|
||||
|
||||
//#include "softfloat-specialize"
|
||||
#include "fpu_constant.h"
|
||||
|
||||
#define floatx80_one packFloatx80(0, 0x3fff, 0x8000000000000000U)
|
||||
#define floatx80_default_nan packFloatx80(0, 0xffff, 0xffffffffffffffffU)
|
||||
|
||||
#define packFloat2x128m(zHi, zLo) {(zHi), (zLo)}
|
||||
#define PACK_FLOAT_128(hi,lo) packFloat2x128m(LIT64(hi),LIT64(lo))
|
||||
|
||||
#define EXP_BIAS 0x3FFF
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the fraction bits of the extended double-precision floating-point
|
||||
| value `a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline bits64 extractFloatx80Frac( floatx80 a )
|
||||
{
|
||||
return a.low;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the exponent bits of the extended double-precision floating-point
|
||||
| value `a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline int32 extractFloatx80Exp( floatx80 a )
|
||||
{
|
||||
return a.high & 0x7FFF;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the sign bit of the extended double-precision floating-point value
|
||||
| `a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag extractFloatx80Sign( floatx80 a )
|
||||
{
|
||||
return a.high>>15;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes extended double-precision floating-point NaN `a' and returns the
|
||||
| appropriate NaN result. If `a' is a signaling NaN, the invalid exception
|
||||
| is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline floatx80 propagateFloatx80NaNOneArg(floatx80 a)
|
||||
{
|
||||
if (floatx80_is_signaling_nan(a))
|
||||
float_raise(float_flag_invalid);
|
||||
|
||||
a.low |= 0xC000000000000000U;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Normalizes the subnormal extended double-precision floating-point value
|
||||
| represented by the denormalized significand `aSig'. The normalized exponent
|
||||
| and significand are stored at the locations pointed to by `zExpPtr' and
|
||||
| `zSigPtr', respectively.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr, uint64_t *zSigPtr)
|
||||
{
|
||||
int shiftCount = countLeadingZeros64(aSig);
|
||||
*zSigPtr = aSig<<shiftCount;
|
||||
*zExpPtr = 1 - shiftCount;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
shift128Right(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;
|
||||
}
|
||||
}
|
||||
|
||||
shift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1);
|
||||
if (! lt128(aSig0, aSig1, term0, term1))
|
||||
{
|
||||
int lt = lt128(term0, term1, aSig0, aSig1);
|
||||
int eq = 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 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 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 OddPoly (float128 x, float128 *arr, unsigned n);
|
||||
|
||||
/* 0 <= x <= pi/4 */
|
||||
static inline float128 poly_sin(float128 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, sin_arr, SIN_ARR_SIZE);
|
||||
}
|
||||
|
||||
extern float128 EvenPoly(float128 x, float128 *arr, unsigned n);
|
||||
|
||||
/* 0 <= x <= pi/4 */
|
||||
static inline float128 poly_cos(float128 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, cos_arr, COS_ARR_SIZE);
|
||||
}
|
||||
|
||||
static inline void sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a)
|
||||
{
|
||||
if (sin_a) *sin_a = a;
|
||||
if (cos_a) *cos_a = a;
|
||||
}
|
||||
|
||||
static inline void sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx80 a)
|
||||
{
|
||||
if (sin_a) *sin_a = a;
|
||||
if (cos_a) *cos_a = floatx80_one;
|
||||
}
|
||||
|
||||
static floatx80 sincos_approximation(int neg, float128 r, uint64_t quotient)
|
||||
{
|
||||
if (quotient & 0x1) {
|
||||
r = poly_cos(r);
|
||||
neg = 0;
|
||||
} else {
|
||||
r = poly_sin(r);
|
||||
}
|
||||
|
||||
floatx80 result = float128_to_floatx80(r);
|
||||
if (quotient & 0x2)
|
||||
neg = ! neg;
|
||||
|
||||
if (neg)
|
||||
result = floatx80_chs(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// =================================================
|
||||
// SFFSINCOS 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 sf_fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a)
|
||||
{
|
||||
uint64_t aSig0, aSig1 = 0;
|
||||
int32_t aExp, zExp, expDiff;
|
||||
int aSign, zSign;
|
||||
int q = 0;
|
||||
|
||||
aSig0 = extractFloatx80Frac(a);
|
||||
aExp = extractFloatx80Exp(a);
|
||||
aSign = extractFloatx80Sign(a);
|
||||
|
||||
/* invalid argument */
|
||||
if (aExp == 0x7FFF) {
|
||||
if ((uint64_t) (aSig0<<1)) {
|
||||
sincos_invalid(sin_a, cos_a, propagateFloatx80NaNOneArg(a));
|
||||
return 0;
|
||||
}
|
||||
|
||||
float_raise(float_flag_invalid);
|
||||
sincos_invalid(sin_a, cos_a, floatx80_default_nan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (aExp == 0) {
|
||||
if (aSig0 == 0) {
|
||||
sincos_tiny_argument(sin_a, cos_a, a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// float_raise(float_flag_denormal);
|
||||
|
||||
/* handle pseudo denormals */
|
||||
if (! (aSig0 & 0x8000000000000000U))
|
||||
{
|
||||
float_raise(float_flag_inexact);
|
||||
if (sin_a)
|
||||
float_raise(float_flag_underflow);
|
||||
sincos_tiny_argument(sin_a, cos_a, a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
|
||||
}
|
||||
|
||||
zSign = aSign;
|
||||
zExp = EXP_BIAS;
|
||||
expDiff = aExp - zExp;
|
||||
|
||||
/* argument is out-of-range */
|
||||
if (expDiff >= 63)
|
||||
return -1;
|
||||
|
||||
float_raise(float_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 r = normalizeRoundAndPackFloat128(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 floatx80_fsin(floatx80 *a)
|
||||
{
|
||||
return sf_fsincos(*a, a, 0);
|
||||
}
|
||||
|
||||
int floatx80_fcos(floatx80 *a)
|
||||
{
|
||||
return sf_fsincos(*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 floatx80_ftan(floatx80 *a)
|
||||
{
|
||||
uint64_t aSig0, aSig1 = 0;
|
||||
int32_t aExp, zExp, expDiff;
|
||||
int aSign, zSign;
|
||||
int q = 0;
|
||||
|
||||
aSig0 = extractFloatx80Frac(*a);
|
||||
aExp = extractFloatx80Exp(*a);
|
||||
aSign = extractFloatx80Sign(*a);
|
||||
|
||||
/* invalid argument */
|
||||
if (aExp == 0x7FFF) {
|
||||
if ((uint64_t) (aSig0<<1))
|
||||
{
|
||||
*a = propagateFloatx80NaNOneArg(*a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float_raise(float_flag_invalid);
|
||||
*a = floatx80_default_nan;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (aExp == 0) {
|
||||
if (aSig0 == 0) return 0;
|
||||
// float_raise(float_flag_denormal);
|
||||
/* handle pseudo denormals */
|
||||
if (! (aSig0 & 0x8000000000000000U))
|
||||
{
|
||||
float_raise(float_flag_inexact | float_flag_underflow);
|
||||
return 0;
|
||||
}
|
||||
normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
|
||||
}
|
||||
|
||||
zSign = aSign;
|
||||
zExp = EXP_BIAS;
|
||||
expDiff = aExp - zExp;
|
||||
|
||||
/* argument is out-of-range */
|
||||
if (expDiff >= 63)
|
||||
return -1;
|
||||
|
||||
float_raise(float_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 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1);
|
||||
|
||||
float128 sin_r = poly_sin(r);
|
||||
float128 cos_r = poly_cos(r);
|
||||
|
||||
if (q & 0x1) {
|
||||
r = float128_div(cos_r, sin_r);
|
||||
zSign = ! zSign;
|
||||
} else {
|
||||
r = float128_div(sin_r, cos_r);
|
||||
}
|
||||
|
||||
*a = float128_to_floatx80(r);
|
||||
if (zSign)
|
||||
*a = floatx80_chs(*a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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 EvalPoly(float128 x, float128 *arr, unsigned n)
|
||||
{
|
||||
float128 x2 = float128_mul(x, x);
|
||||
unsigned i;
|
||||
|
||||
assert(n > 1);
|
||||
|
||||
float128 r1 = arr[--n];
|
||||
i = n;
|
||||
while(i >= 2) {
|
||||
r1 = float128_mul(r1, x2);
|
||||
i -= 2;
|
||||
r1 = float128_add(r1, arr[i]);
|
||||
}
|
||||
if (i) r1 = float128_mul(r1, x);
|
||||
|
||||
float128 r2 = arr[--n];
|
||||
i = n;
|
||||
while(i >= 2) {
|
||||
r2 = float128_mul(r2, x2);
|
||||
i -= 2;
|
||||
r2 = float128_add(r2, arr[i]);
|
||||
}
|
||||
if (i) r2 = float128_mul(r2, x);
|
||||
|
||||
return float128_add(r1, r2);
|
||||
}
|
||||
|
||||
// 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 EvenPoly(float128 x, float128 *arr, unsigned n)
|
||||
{
|
||||
return EvalPoly(float128_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 OddPoly(float128 x, float128 *arr, unsigned n)
|
||||
{
|
||||
return float128_mul(x, EvenPoly(x, arr, n));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| 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.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
extern floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b );
|
||||
|
||||
floatx80 floatx80_scale(floatx80 a, floatx80 b)
|
||||
{
|
||||
sbits32 aExp, bExp;
|
||||
bits64 aSig, bSig;
|
||||
|
||||
// handle unsupported extended double-precision floating encodings
|
||||
/* if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b))
|
||||
{
|
||||
float_raise(float_flag_invalid);
|
||||
return floatx80_default_nan;
|
||||
}*/
|
||||
|
||||
aSig = extractFloatx80Frac(a);
|
||||
aExp = extractFloatx80Exp(a);
|
||||
int aSign = extractFloatx80Sign(a);
|
||||
bSig = extractFloatx80Frac(b);
|
||||
bExp = extractFloatx80Exp(b);
|
||||
int bSign = extractFloatx80Sign(b);
|
||||
|
||||
if (aExp == 0x7FFF) {
|
||||
if ((bits64) (aSig<<1) || ((bExp == 0x7FFF) && (bits64) (bSig<<1)))
|
||||
{
|
||||
return propagateFloatx80NaN(a, b);
|
||||
}
|
||||
if ((bExp == 0x7FFF) && bSign) {
|
||||
float_raise(float_flag_invalid);
|
||||
return floatx80_default_nan;
|
||||
}
|
||||
if (bSig && (bExp == 0)) float_raise(float_flag_denormal);
|
||||
return a;
|
||||
}
|
||||
if (bExp == 0x7FFF) {
|
||||
if ((bits64) (bSig<<1)) return propagateFloatx80NaN(a, b);
|
||||
if ((aExp | aSig) == 0) {
|
||||
if (! bSign) {
|
||||
float_raise(float_flag_invalid);
|
||||
return floatx80_default_nan;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
if (aSig && (aExp == 0)) float_raise(float_flag_denormal);
|
||||
if (bSign) return packFloatx80(aSign, 0, 0);
|
||||
return packFloatx80(aSign, 0x7FFF, 0x8000000000000000U);
|
||||
}
|
||||
if (aExp == 0) {
|
||||
if (aSig == 0) return a;
|
||||
float_raise(float_flag_denormal);
|
||||
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
|
||||
}
|
||||
if (bExp == 0) {
|
||||
if (bSig == 0) return a;
|
||||
float_raise(float_flag_denormal);
|
||||
normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
|
||||
}
|
||||
|
||||
if (bExp > 0x400E) {
|
||||
/* generate appropriate overflow/underflow */
|
||||
return roundAndPackFloatx80(80, aSign,
|
||||
bSign ? -0x3FFF : 0x7FFF, aSig, 0);
|
||||
}
|
||||
if (bExp < 0x3FFF) return a;
|
||||
|
||||
int shiftCount = 0x403E - bExp;
|
||||
bSig >>= shiftCount;
|
||||
sbits32 scale = bSig;
|
||||
if (bSign) scale = -scale; /* -32768..32767 */
|
||||
return
|
||||
roundAndPackFloatx80(80, aSign, aExp+scale, aSig, 0);
|
||||
}
|
||||
@@ -1,487 +0,0 @@
|
||||
/*============================================================================
|
||||
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.
|
||||
float_raise(float_flag_invalid)
|
||||
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]
|
||||
* Adapted for lib/softfloat in MESS by Hans Ostermeyer (03/2012)
|
||||
* ==========================================================================*/
|
||||
|
||||
#define FLOAT128
|
||||
|
||||
#define USE_estimateDiv128To64
|
||||
|
||||
#include "m68kcpu.h" // which includes softfloat.h after defining the basic types
|
||||
|
||||
//#include "softfloat-specialize"
|
||||
#include "fpu_constant.h"
|
||||
|
||||
#define floatx80_log10_2 packFloatx80(0, 0x3ffd, 0x9a209a84fbcff798U)
|
||||
#define floatx80_ln_2 packFloatx80(0, 0x3ffe, 0xb17217f7d1cf79acU)
|
||||
#define floatx80_one packFloatx80(0, 0x3fff, 0x8000000000000000U)
|
||||
#define floatx80_default_nan packFloatx80(0, 0xffff, 0xffffffffffffffffU)
|
||||
|
||||
#define packFloat_128(zHi, zLo) {(zHi), (zLo)}
|
||||
#define PACK_FLOAT_128(hi,lo) packFloat_128(LIT64(hi),LIT64(lo))
|
||||
|
||||
#define EXP_BIAS 0x3FFF
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the fraction bits of the extended double-precision floating-point
|
||||
| value `a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline bits64 extractFloatx80Frac( floatx80 a )
|
||||
{
|
||||
return a.low;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the exponent bits of the extended double-precision floating-point
|
||||
| value `a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline int32 extractFloatx80Exp( floatx80 a )
|
||||
{
|
||||
return a.high & 0x7FFF;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the sign bit of the extended double-precision floating-point value
|
||||
| `a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag extractFloatx80Sign( floatx80 a )
|
||||
{
|
||||
return a.high>>15;
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes extended double-precision floating-point NaN `a' and returns the
|
||||
| appropriate NaN result. If `a' is a signaling NaN, the invalid exception
|
||||
| is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline floatx80 propagateFloatx80NaNOneArg(floatx80 a)
|
||||
{
|
||||
if (floatx80_is_signaling_nan(a))
|
||||
float_raise(float_flag_invalid);
|
||||
|
||||
a.low |= 0xC000000000000000U;
|
||||
|
||||
return a;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Normalizes the subnormal extended double-precision floating-point value
|
||||
| represented by the denormalized significand `aSig'. The normalized exponent
|
||||
| and significand are stored at the locations pointed to by `zExpPtr' and
|
||||
| `zSigPtr', respectively.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr, uint64_t *zSigPtr)
|
||||
{
|
||||
int shiftCount = countLeadingZeros64(aSig);
|
||||
*zSigPtr = aSig<<shiftCount;
|
||||
*zExpPtr = 1 - shiftCount;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the extended double-precision floating-point value `a' is a
|
||||
| NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline int floatx80_is_nan(floatx80 a)
|
||||
{
|
||||
return ((a.high & 0x7FFF) == 0x7FFF) && (int64_t) (a.low<<1);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes two extended double-precision floating-point values `a' and `b', one
|
||||
| of which is a NaN, and returns the appropriate NaN result. If either `a' or
|
||||
| `b' is a signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b)
|
||||
{
|
||||
int aIsNaN = floatx80_is_nan(a);
|
||||
int aIsSignalingNaN = floatx80_is_signaling_nan(a);
|
||||
int bIsNaN = floatx80_is_nan(b);
|
||||
int bIsSignalingNaN = floatx80_is_signaling_nan(b);
|
||||
a.low |= 0xC000000000000000U;
|
||||
b.low |= 0xC000000000000000U;
|
||||
if (aIsSignalingNaN | bIsSignalingNaN) float_raise(float_flag_invalid);
|
||||
if (aIsSignalingNaN) {
|
||||
if (bIsSignalingNaN) goto returnLargerSignificand;
|
||||
return bIsNaN ? b : a;
|
||||
}
|
||||
else if (aIsNaN) {
|
||||
if (bIsSignalingNaN | ! bIsNaN) return a;
|
||||
returnLargerSignificand:
|
||||
if (a.low < b.low) return b;
|
||||
if (b.low < a.low) return a;
|
||||
return (a.high < b.high) ? a : b;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
static const float128 float128_one =
|
||||
packFloat_128(0x3fff000000000000U, 0x0000000000000000U);
|
||||
static const float128 float128_two =
|
||||
packFloat_128(0x4000000000000000U, 0x0000000000000000U);
|
||||
|
||||
static const float128 float128_ln2inv2 =
|
||||
packFloat_128(0x400071547652b82fU, 0xe1777d0ffda0d23aU);
|
||||
|
||||
#define SQRT2_HALF_SIG 0xb504f333f9de6484U
|
||||
|
||||
extern float128 OddPoly(float128 x, float128 *arr, unsigned n);
|
||||
|
||||
#define L2_ARR_SIZE 9
|
||||
|
||||
static float128 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 poly_ln(float128 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, ln_arr, L2_ARR_SIZE);
|
||||
}
|
||||
|
||||
/* required sqrt(2)/2 < x < sqrt(2) */
|
||||
static float128 poly_l2(float128 x)
|
||||
{
|
||||
/* using float128 for approximation */
|
||||
float128 x_p1 = float128_add(x, float128_one);
|
||||
float128 x_m1 = float128_sub(x, float128_one);
|
||||
x = float128_div(x_m1, x_p1);
|
||||
x = poly_ln(x);
|
||||
x = float128_mul(x, float128_ln2inv2);
|
||||
return x;
|
||||
}
|
||||
|
||||
static float128 poly_l2p1(float128 x)
|
||||
{
|
||||
/* using float128 for approximation */
|
||||
float128 x_p2 = float128_add(x, float128_two);
|
||||
x = float128_div(x, x_p2);
|
||||
x = poly_ln(x);
|
||||
x = float128_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
|
||||
//
|
||||
|
||||
static floatx80 fyl2x(floatx80 a, floatx80 b)
|
||||
{
|
||||
uint64_t aSig = extractFloatx80Frac(a);
|
||||
int32_t aExp = extractFloatx80Exp(a);
|
||||
int aSign = extractFloatx80Sign(a);
|
||||
uint64_t bSig = extractFloatx80Frac(b);
|
||||
int32_t bExp = extractFloatx80Exp(b);
|
||||
int bSign = extractFloatx80Sign(b);
|
||||
|
||||
int zSign = bSign ^ 1;
|
||||
|
||||
if (aExp == 0x7FFF) {
|
||||
if ((uint64_t) (aSig<<1)
|
||||
|| ((bExp == 0x7FFF) && (uint64_t) (bSig<<1)))
|
||||
{
|
||||
return propagateFloatx80NaN(a, b);
|
||||
}
|
||||
if (aSign)
|
||||
{
|
||||
invalid:
|
||||
float_raise(float_flag_invalid);
|
||||
return floatx80_default_nan;
|
||||
}
|
||||
else {
|
||||
if (bExp == 0) {
|
||||
if (bSig == 0) goto invalid;
|
||||
float_raise(float_flag_denormal);
|
||||
}
|
||||
return packFloatx80(bSign, 0x7FFF, 0x8000000000000000U);
|
||||
}
|
||||
}
|
||||
if (bExp == 0x7FFF)
|
||||
{
|
||||
if ((uint64_t) (bSig<<1)) return propagateFloatx80NaN(a, b);
|
||||
if (aSign && (uint64_t)(aExp | aSig)) goto invalid;
|
||||
if (aSig && (aExp == 0))
|
||||
float_raise(float_flag_denormal);
|
||||
if (aExp < 0x3FFF) {
|
||||
return packFloatx80(zSign, 0x7FFF, 0x8000000000000000U);
|
||||
}
|
||||
if (aExp == 0x3FFF && ((uint64_t) (aSig<<1) == 0)) goto invalid;
|
||||
return packFloatx80(bSign, 0x7FFF, 0x8000000000000000U);
|
||||
}
|
||||
if (aExp == 0) {
|
||||
if (aSig == 0) {
|
||||
if ((bExp | bSig) == 0) goto invalid;
|
||||
float_raise(float_flag_divbyzero);
|
||||
return packFloatx80(zSign, 0x7FFF, 0x8000000000000000U);
|
||||
}
|
||||
if (aSign) goto invalid;
|
||||
float_raise(float_flag_denormal);
|
||||
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
|
||||
}
|
||||
if (aSign) goto invalid;
|
||||
if (bExp == 0) {
|
||||
if (bSig == 0) {
|
||||
if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0);
|
||||
return packFloatx80(bSign, 0, 0);
|
||||
}
|
||||
float_raise(float_flag_denormal);
|
||||
normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
|
||||
}
|
||||
if (aExp == 0x3FFF && ((uint64_t) (aSig<<1) == 0))
|
||||
return packFloatx80(bSign, 0, 0);
|
||||
|
||||
float_raise(float_flag_inexact);
|
||||
|
||||
int ExpDiff = aExp - 0x3FFF;
|
||||
aExp = 0;
|
||||
if (aSig >= SQRT2_HALF_SIG) {
|
||||
ExpDiff++;
|
||||
aExp--;
|
||||
}
|
||||
|
||||
/* ******************************** */
|
||||
/* using float128 for approximation */
|
||||
/* ******************************** */
|
||||
|
||||
uint64_t zSig0, zSig1;
|
||||
shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
|
||||
float128 x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1);
|
||||
x = poly_l2(x);
|
||||
x = float128_add(x, int64_to_float128((int64_t) ExpDiff));
|
||||
return floatx80_mul(b, float128_to_floatx80(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
|
||||
//
|
||||
|
||||
floatx80 fyl2xp1(floatx80 a, floatx80 b)
|
||||
{
|
||||
int32_t aExp, bExp;
|
||||
uint64_t aSig, bSig, zSig0, zSig1, zSig2;
|
||||
int aSign, bSign;
|
||||
|
||||
aSig = extractFloatx80Frac(a);
|
||||
aExp = extractFloatx80Exp(a);
|
||||
aSign = extractFloatx80Sign(a);
|
||||
bSig = extractFloatx80Frac(b);
|
||||
bExp = extractFloatx80Exp(b);
|
||||
bSign = extractFloatx80Sign(b);
|
||||
int zSign = aSign ^ bSign;
|
||||
|
||||
if (aExp == 0x7FFF) {
|
||||
if ((uint64_t) (aSig<<1)
|
||||
|| ((bExp == 0x7FFF) && (uint64_t) (bSig<<1)))
|
||||
{
|
||||
return propagateFloatx80NaN(a, b);
|
||||
}
|
||||
if (aSign)
|
||||
{
|
||||
invalid:
|
||||
float_raise(float_flag_invalid);
|
||||
return floatx80_default_nan;
|
||||
}
|
||||
else {
|
||||
if (bExp == 0) {
|
||||
if (bSig == 0) goto invalid;
|
||||
float_raise(float_flag_denormal);
|
||||
}
|
||||
return packFloatx80(bSign, 0x7FFF, 0x8000000000000000U);
|
||||
}
|
||||
}
|
||||
if (bExp == 0x7FFF)
|
||||
{
|
||||
if ((uint64_t) (bSig<<1))
|
||||
return propagateFloatx80NaN(a, b);
|
||||
|
||||
if (aExp == 0) {
|
||||
if (aSig == 0) goto invalid;
|
||||
float_raise(float_flag_denormal);
|
||||
}
|
||||
|
||||
return packFloatx80(zSign, 0x7FFF, 0x8000000000000000U);
|
||||
}
|
||||
if (aExp == 0) {
|
||||
if (aSig == 0) {
|
||||
if (bSig && (bExp == 0)) float_raise(float_flag_denormal);
|
||||
return packFloatx80(zSign, 0, 0);
|
||||
}
|
||||
float_raise(float_flag_denormal);
|
||||
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
|
||||
}
|
||||
if (bExp == 0) {
|
||||
if (bSig == 0) return packFloatx80(zSign, 0, 0);
|
||||
float_raise(float_flag_denormal);
|
||||
normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
|
||||
}
|
||||
|
||||
float_raise(float_flag_inexact);
|
||||
|
||||
if (aSign && aExp >= 0x3FFF)
|
||||
return a;
|
||||
|
||||
if (aExp >= 0x3FFC) // big argument
|
||||
{
|
||||
return fyl2x(floatx80_add(a, floatx80_one), b);
|
||||
}
|
||||
|
||||
// handle tiny argument
|
||||
if (aExp < 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
|
||||
roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1);
|
||||
}
|
||||
|
||||
/* ******************************** */
|
||||
/* using float128 for approximation */
|
||||
/* ******************************** */
|
||||
|
||||
shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
|
||||
float128 x = packFloat128(aSign, aExp, zSig0, zSig1);
|
||||
x = poly_l2p1(x);
|
||||
return floatx80_mul(b, float128_to_floatx80(x));
|
||||
}
|
||||
|
||||
floatx80 floatx80_flognp1(floatx80 a)
|
||||
{
|
||||
return fyl2xp1(a, floatx80_ln_2);
|
||||
}
|
||||
|
||||
floatx80 floatx80_flogn(floatx80 a)
|
||||
{
|
||||
return fyl2x(a, floatx80_ln_2);
|
||||
}
|
||||
|
||||
floatx80 floatx80_flog2(floatx80 a)
|
||||
{
|
||||
return fyl2x(a, floatx80_one);
|
||||
}
|
||||
|
||||
floatx80 floatx80_flog10(floatx80 a)
|
||||
{
|
||||
return fyl2x(a, floatx80_log10_2);
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
| to the same as `int'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
typedef sint8 flag;
|
||||
typedef uint64_t flag;
|
||||
typedef sint8 int8;
|
||||
typedef sint16 int16;
|
||||
typedef sint32 int32;
|
||||
|
||||
@@ -1,8 +1,24 @@
|
||||
/*
|
||||
* QEMU float support macros
|
||||
*
|
||||
* The code in this source file is derived from release 2a of the SoftFloat
|
||||
* IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and
|
||||
* some later contributions) are provided under that license, as detailed below.
|
||||
* It has subsequently been modified by contributors to the QEMU Project,
|
||||
* so some portions are provided under:
|
||||
* the SoftFloat-2a license
|
||||
* the BSD license
|
||||
* GPL-v2-or-later
|
||||
*
|
||||
* Any future contributions to this file after December 1st 2014 will be
|
||||
* taken to be licensed under the Softfloat-2a license unless specifically
|
||||
* indicated otherwise.
|
||||
*/
|
||||
|
||||
/*============================================================================
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
|
||||
Arithmetic Package, Release 2b.
|
||||
Arithmetic Package, Release 2a.
|
||||
|
||||
Written by John R. Hauser. This work was made possible in part by the
|
||||
International Computer Science Institute, located at Suite 600, 1947 Center
|
||||
@@ -11,24 +27,68 @@ 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/
|
||||
is available through the Web page `http://HTTP.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 notice) AGAINST ALL LOSSES, COSTS, OR
|
||||
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
|
||||
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 ANY
|
||||
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
|
||||
|
||||
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.
|
||||
(1) they include prominent notice that the work is derivative, and (2) they
|
||||
include prominent notice akin to these four paragraphs for those parts of
|
||||
this code that are retained.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/* BSD licensing:
|
||||
* Copyright (c) 2006, Fabrice Bellard
|
||||
* 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 copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
|
||||
/* Portions of this work are licensed under the terms of the GNU GPL,
|
||||
* version 2 or later. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| This macro tests for minimum version of the GNU C compiler.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define SOFTFLOAT_GNUC_PREREQ(maj, min) \
|
||||
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
||||
#else
|
||||
# define SOFTFLOAT_GNUC_PREREQ(maj, min) 0
|
||||
#endif
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Shifts `a' right by the number of bits given in `count'. If any nonzero
|
||||
@@ -39,9 +99,9 @@ these four paragraphs for those parts of this code that are retained.
|
||||
| The result is stored in the location pointed to by `zPtr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
|
||||
static inline void shift32RightJamming(uint32_t a, int count, uint32_t *zPtr)
|
||||
{
|
||||
bits32 z;
|
||||
uint32_t z;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z = a;
|
||||
@@ -65,9 +125,9 @@ static inline void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
|
||||
| The result is stored in the location pointed to by `zPtr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr )
|
||||
static inline void shift64RightJamming(uint64_t a, int count, uint64_t *zPtr)
|
||||
{
|
||||
bits64 z;
|
||||
uint64_t z;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z = a;
|
||||
@@ -91,20 +151,20 @@ static inline void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr )
|
||||
| 63 bits of the extra result are all zero if and only if _all_but_the_last_
|
||||
| bits shifted off were all zero. This extra result is stored in the location
|
||||
| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large.
|
||||
| (This routine makes more sense if `a0' and `a1' are considered to form
|
||||
| a fixed-point value with binary point between `a0' and `a1'. This fixed-
|
||||
| point value is shifted right by the number of bits given in `count', and
|
||||
| the integer part of the result is returned at the location pointed to by
|
||||
| (This routine makes more sense if `a0' and `a1' are considered to form a
|
||||
| fixed-point value with binary point between `a0' and `a1'. This fixed-point
|
||||
| value is shifted right by the number of bits given in `count', and the
|
||||
| integer part of the result is returned at the location pointed to by
|
||||
| `z0Ptr'. The fractional part of the result may be slightly corrupted as
|
||||
| described above, and is returned at the location pointed to by `z1Ptr'.)
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline void
|
||||
shift64ExtraRightJamming(
|
||||
bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr)
|
||||
{
|
||||
bits64 z0, z1;
|
||||
int8 negCount = ( - count ) & 63;
|
||||
uint64_t z0, z1;
|
||||
int8_t negCount = ( - count ) & 63;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z1 = a1;
|
||||
@@ -138,10 +198,10 @@ static inline void
|
||||
|
||||
static inline void
|
||||
shift128Right(
|
||||
bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr)
|
||||
{
|
||||
bits64 z0, z1;
|
||||
int8 negCount = ( - count ) & 63;
|
||||
uint64_t z0, z1;
|
||||
int8_t negCount = ( - count ) & 63;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z1 = a1;
|
||||
@@ -152,7 +212,7 @@ static inline void
|
||||
z0 = a0>>count;
|
||||
}
|
||||
else {
|
||||
z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0;
|
||||
z1 = (count < 128) ? (a0 >> (count & 63)) : 0;
|
||||
z0 = 0;
|
||||
}
|
||||
*z1Ptr = z1;
|
||||
@@ -173,10 +233,10 @@ static inline void
|
||||
|
||||
static inline void
|
||||
shift128RightJamming(
|
||||
bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr)
|
||||
{
|
||||
bits64 z0, z1;
|
||||
int8 negCount = ( - count ) & 63;
|
||||
uint64_t z0, z1;
|
||||
int8_t negCount = ( - count ) & 63;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z1 = a1;
|
||||
@@ -224,17 +284,17 @@ static inline void
|
||||
|
||||
static inline void
|
||||
shift128ExtraRightJamming(
|
||||
bits64 a0,
|
||||
bits64 a1,
|
||||
bits64 a2,
|
||||
int16 count,
|
||||
bits64 *z0Ptr,
|
||||
bits64 *z1Ptr,
|
||||
bits64 *z2Ptr
|
||||
uint64_t a0,
|
||||
uint64_t a1,
|
||||
uint64_t a2,
|
||||
int count,
|
||||
uint64_t *z0Ptr,
|
||||
uint64_t *z1Ptr,
|
||||
uint64_t *z2Ptr
|
||||
)
|
||||
{
|
||||
bits64 z0, z1, z2;
|
||||
int8 negCount = ( - count ) & 63;
|
||||
uint64_t z0, z1, z2;
|
||||
int8_t negCount = ( - count ) & 63;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z2 = a2;
|
||||
@@ -282,7 +342,7 @@ static inline void
|
||||
|
||||
static inline void
|
||||
shortShift128Left(
|
||||
bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr)
|
||||
{
|
||||
|
||||
*z1Ptr = a1<<count;
|
||||
@@ -301,17 +361,17 @@ static inline void
|
||||
|
||||
static inline void
|
||||
shortShift192Left(
|
||||
bits64 a0,
|
||||
bits64 a1,
|
||||
bits64 a2,
|
||||
int16 count,
|
||||
bits64 *z0Ptr,
|
||||
bits64 *z1Ptr,
|
||||
bits64 *z2Ptr
|
||||
uint64_t a0,
|
||||
uint64_t a1,
|
||||
uint64_t a2,
|
||||
int count,
|
||||
uint64_t *z0Ptr,
|
||||
uint64_t *z1Ptr,
|
||||
uint64_t *z2Ptr
|
||||
)
|
||||
{
|
||||
bits64 z0, z1, z2;
|
||||
int8 negCount;
|
||||
uint64_t z0, z1, z2;
|
||||
int8_t negCount;
|
||||
|
||||
z2 = a2<<count;
|
||||
z1 = a1<<count;
|
||||
@@ -336,9 +396,9 @@ static inline void
|
||||
|
||||
static inline void
|
||||
add128(
|
||||
bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr )
|
||||
{
|
||||
bits64 z1;
|
||||
uint64_t z1;
|
||||
|
||||
z1 = a1 + b1;
|
||||
*z1Ptr = z1;
|
||||
@@ -356,19 +416,19 @@ static inline void
|
||||
|
||||
static inline void
|
||||
add192(
|
||||
bits64 a0,
|
||||
bits64 a1,
|
||||
bits64 a2,
|
||||
bits64 b0,
|
||||
bits64 b1,
|
||||
bits64 b2,
|
||||
bits64 *z0Ptr,
|
||||
bits64 *z1Ptr,
|
||||
bits64 *z2Ptr
|
||||
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
|
||||
)
|
||||
{
|
||||
bits64 z0, z1, z2;
|
||||
uint8 carry0, carry1;
|
||||
uint64_t z0, z1, z2;
|
||||
uint8_t carry0, carry1;
|
||||
|
||||
z2 = a2 + b2;
|
||||
carry1 = ( z2 < a2 );
|
||||
@@ -394,7 +454,7 @@ static inline void
|
||||
|
||||
static inline void
|
||||
sub128(
|
||||
bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr )
|
||||
{
|
||||
|
||||
*z1Ptr = a1 - b1;
|
||||
@@ -412,19 +472,19 @@ static inline void
|
||||
|
||||
static inline void
|
||||
sub192(
|
||||
bits64 a0,
|
||||
bits64 a1,
|
||||
bits64 a2,
|
||||
bits64 b0,
|
||||
bits64 b1,
|
||||
bits64 b2,
|
||||
bits64 *z0Ptr,
|
||||
bits64 *z1Ptr,
|
||||
bits64 *z2Ptr
|
||||
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
|
||||
)
|
||||
{
|
||||
bits64 z0, z1, z2;
|
||||
uint8 borrow0, borrow1;
|
||||
uint64_t z0, z1, z2;
|
||||
uint8_t borrow0, borrow1;
|
||||
|
||||
z2 = a2 - b2;
|
||||
borrow1 = ( a2 < b2 );
|
||||
@@ -446,21 +506,21 @@ static inline void
|
||||
| `z0Ptr' and `z1Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr )
|
||||
static inline void mul64To128( uint64_t a, uint64_t b, uint64_t *z0Ptr, uint64_t *z1Ptr )
|
||||
{
|
||||
bits32 aHigh, aLow, bHigh, bLow;
|
||||
bits64 z0, zMiddleA, zMiddleB, z1;
|
||||
uint32_t aHigh, aLow, bHigh, bLow;
|
||||
uint64_t z0, zMiddleA, zMiddleB, z1;
|
||||
|
||||
aLow = a;
|
||||
aHigh = a>>32;
|
||||
bLow = b;
|
||||
bHigh = b>>32;
|
||||
z1 = ( (bits64) aLow ) * bLow;
|
||||
zMiddleA = ( (bits64) aLow ) * bHigh;
|
||||
zMiddleB = ( (bits64) aHigh ) * bLow;
|
||||
z0 = ( (bits64) aHigh ) * bHigh;
|
||||
z1 = ( (uint64_t) aLow ) * bLow;
|
||||
zMiddleA = ( (uint64_t) aLow ) * bHigh;
|
||||
zMiddleB = ( (uint64_t) aHigh ) * bLow;
|
||||
z0 = ( (uint64_t) aHigh ) * bHigh;
|
||||
zMiddleA += zMiddleB;
|
||||
z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 );
|
||||
z0 += ( ( (uint64_t) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 );
|
||||
zMiddleA <<= 32;
|
||||
z1 += zMiddleA;
|
||||
z0 += ( z1 < zMiddleA );
|
||||
@@ -478,15 +538,15 @@ static inline void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr
|
||||
|
||||
static inline void
|
||||
mul128By64To192(
|
||||
bits64 a0,
|
||||
bits64 a1,
|
||||
bits64 b,
|
||||
bits64 *z0Ptr,
|
||||
bits64 *z1Ptr,
|
||||
bits64 *z2Ptr
|
||||
uint64_t a0,
|
||||
uint64_t a1,
|
||||
uint64_t b,
|
||||
uint64_t *z0Ptr,
|
||||
uint64_t *z1Ptr,
|
||||
uint64_t *z2Ptr
|
||||
)
|
||||
{
|
||||
bits64 z0, z1, z2, more1;
|
||||
uint64_t z0, z1, z2, more1;
|
||||
|
||||
mul64To128( a1, b, &z1, &z2 );
|
||||
mul64To128( a0, b, &z0, &more1 );
|
||||
@@ -506,18 +566,18 @@ static inline void
|
||||
|
||||
static inline void
|
||||
mul128To256(
|
||||
bits64 a0,
|
||||
bits64 a1,
|
||||
bits64 b0,
|
||||
bits64 b1,
|
||||
bits64 *z0Ptr,
|
||||
bits64 *z1Ptr,
|
||||
bits64 *z2Ptr,
|
||||
bits64 *z3Ptr
|
||||
uint64_t a0,
|
||||
uint64_t a1,
|
||||
uint64_t b0,
|
||||
uint64_t b1,
|
||||
uint64_t *z0Ptr,
|
||||
uint64_t *z1Ptr,
|
||||
uint64_t *z2Ptr,
|
||||
uint64_t *z3Ptr
|
||||
)
|
||||
{
|
||||
bits64 z0, z1, z2, z3;
|
||||
bits64 more1, more2;
|
||||
uint64_t z0, z1, z2, z3;
|
||||
uint64_t more1, more2;
|
||||
|
||||
mul64To128( a1, b1, &z2, &z3 );
|
||||
mul64To128( a1, b0, &z1, &more2 );
|
||||
@@ -543,18 +603,18 @@ static inline void
|
||||
| unsigned integer is returned.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b )
|
||||
static uint64_t estimateDiv128To64( uint64_t a0, uint64_t a1, uint64_t b )
|
||||
{
|
||||
bits64 b0, b1;
|
||||
bits64 rem0, rem1, term0, term1;
|
||||
bits64 z;
|
||||
uint64_t b0, b1;
|
||||
uint64_t rem0, rem1, term0, term1;
|
||||
uint64_t z;
|
||||
|
||||
if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF );
|
||||
b0 = b>>32;
|
||||
z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32;
|
||||
mul64To128( b, z, &term0, &term1 );
|
||||
sub128( a0, a1, term0, term1, &rem0, &rem1 );
|
||||
while ( ( (sbits64) rem0 ) < 0 ) {
|
||||
while ( ( (int64_t) rem0 ) < 0 ) {
|
||||
z -= LIT64( 0x100000000 );
|
||||
b1 = b<<32;
|
||||
add128( rem0, rem1, b0, b1, &rem0, &rem1 );
|
||||
@@ -575,32 +635,32 @@ static inline bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b )
|
||||
| value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline bits32 estimateSqrt32( int16 aExp, bits32 a )
|
||||
static uint32_t estimateSqrt32(int aExp, uint32_t a)
|
||||
{
|
||||
static const bits16 sqrtOddAdjustments[] = {
|
||||
static const uint16_t sqrtOddAdjustments[] = {
|
||||
0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
|
||||
0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
|
||||
};
|
||||
static const bits16 sqrtEvenAdjustments[] = {
|
||||
static const uint16_t sqrtEvenAdjustments[] = {
|
||||
0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
|
||||
0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
|
||||
};
|
||||
int8 index;
|
||||
bits32 z;
|
||||
int8_t index;
|
||||
uint32_t z;
|
||||
|
||||
index = ( a>>27 ) & 15;
|
||||
if ( aExp & 1 ) {
|
||||
z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ];
|
||||
z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ (int)index ];
|
||||
z = ( ( a / z )<<14 ) + ( z<<15 );
|
||||
a >>= 1;
|
||||
}
|
||||
else {
|
||||
z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ];
|
||||
z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ (int)index ];
|
||||
z = a / z + z;
|
||||
z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
|
||||
if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
|
||||
if ( z <= a ) return (uint32_t) ( ( (int32_t) a )>>1 );
|
||||
}
|
||||
return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 );
|
||||
return ( (uint32_t) ( ( ( (uint64_t) a )<<31 ) / z ) ) + ( z>>1 );
|
||||
|
||||
}
|
||||
|
||||
@@ -609,9 +669,16 @@ static inline bits32 estimateSqrt32( int16 aExp, bits32 a )
|
||||
| `a'. If `a' is zero, 32 is returned.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static int8 countLeadingZeros32( bits32 a )
|
||||
static inline int8_t countLeadingZeros32( uint32_t a )
|
||||
{
|
||||
static const int8 countLeadingZerosHigh[] = {
|
||||
#if SOFTFLOAT_GNUC_PREREQ(3, 4)
|
||||
if (a) {
|
||||
return __builtin_clz(a);
|
||||
} else {
|
||||
return 32;
|
||||
}
|
||||
#else
|
||||
static const int8_t countLeadingZerosHigh[] = {
|
||||
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
@@ -629,7 +696,7 @@ static int8 countLeadingZeros32( bits32 a )
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
int8 shiftCount;
|
||||
int8_t shiftCount;
|
||||
|
||||
shiftCount = 0;
|
||||
if ( a < 0x10000 ) {
|
||||
@@ -642,7 +709,7 @@ static int8 countLeadingZeros32( bits32 a )
|
||||
}
|
||||
shiftCount += countLeadingZerosHigh[ a>>24 ];
|
||||
return shiftCount;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
@@ -650,12 +717,19 @@ static int8 countLeadingZeros32( bits32 a )
|
||||
| `a'. If `a' is zero, 64 is returned.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static int8 countLeadingZeros64( bits64 a )
|
||||
static inline int8_t countLeadingZeros64( uint64_t a )
|
||||
{
|
||||
int8 shiftCount;
|
||||
#if SOFTFLOAT_GNUC_PREREQ(3, 4)
|
||||
if (a) {
|
||||
return __builtin_clzll(a);
|
||||
} else {
|
||||
return 64;
|
||||
}
|
||||
#else
|
||||
int8_t shiftCount;
|
||||
|
||||
shiftCount = 0;
|
||||
if ( a < ( (bits64) 1 )<<32 ) {
|
||||
if ( a < ( (uint64_t) 1 )<<32 ) {
|
||||
shiftCount += 32;
|
||||
}
|
||||
else {
|
||||
@@ -663,7 +737,7 @@ static int8 countLeadingZeros64( bits64 a )
|
||||
}
|
||||
shiftCount += countLeadingZeros32( a );
|
||||
return shiftCount;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
@@ -672,7 +746,7 @@ static int8 countLeadingZeros64( bits64 a )
|
||||
| Otherwise, returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
|
||||
static inline flag eq128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
|
||||
{
|
||||
|
||||
return ( a0 == b0 ) && ( a1 == b1 );
|
||||
@@ -685,7 +759,7 @@ static inline flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
|
||||
| Otherwise, returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
|
||||
static inline flag le128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
|
||||
{
|
||||
|
||||
return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
|
||||
@@ -698,7 +772,7 @@ static inline flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
|
||||
| returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
|
||||
static inline flag lt128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
|
||||
{
|
||||
|
||||
return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
|
||||
@@ -711,22 +785,9 @@ static inline flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
|
||||
| Otherwise, returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
|
||||
static inline flag ne128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
|
||||
{
|
||||
|
||||
return ( a0 != b0 ) || ( a1 != b1 );
|
||||
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
| Changes the sign of the extended double-precision floating-point value 'a'.
|
||||
| The operation is performed according to the IEC/IEEE Standard for Binary
|
||||
| Floating-Point Arithmetic.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline floatx80 floatx80_chs(floatx80 reg)
|
||||
{
|
||||
reg.high ^= 0x8000;
|
||||
return reg;
|
||||
}
|
||||
|
||||
@@ -1,470 +0,0 @@
|
||||
|
||||
/*============================================================================
|
||||
|
||||
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.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Underflow tininess-detection mode, statically initialized to default value.
|
||||
| (The declaration in `softfloat.h' must match the `int8' type here.)
|
||||
*----------------------------------------------------------------------------*/
|
||||
int8 float_detect_tininess = float_tininess_after_rounding;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Raises the exceptions specified by `flags'. Floating-point traps can be
|
||||
| defined here if desired. It is currently not possible for such a trap to
|
||||
| substitute a result value. If traps are not implemented, this routine
|
||||
| should be simply `float_exception_flags |= flags;'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void float_raise( int8 flags )
|
||||
{
|
||||
|
||||
float_exception_flags |= flags;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Internal canonical NaN format.
|
||||
*----------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
flag sign;
|
||||
bits64 high, low;
|
||||
} commonNaNT;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated single-precision NaN.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define float32_default_nan 0xFFFFFFFF
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the single-precision floating-point value `a' is a NaN;
|
||||
| otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag float32_is_nan( float32 a )
|
||||
{
|
||||
|
||||
return ( 0xFF000000 < (bits32) ( a<<1 ) );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the single-precision floating-point value `a' is a signaling
|
||||
| NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag float32_is_signaling_nan( float32 a )
|
||||
{
|
||||
|
||||
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the single-precision floating-point NaN
|
||||
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static commonNaNT float32ToCommonNaN( float32 a )
|
||||
{
|
||||
commonNaNT z;
|
||||
|
||||
if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
|
||||
z.sign = a>>31;
|
||||
z.low = 0;
|
||||
z.high = ( (bits64) a )<<41;
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the canonical NaN `a' to the single-
|
||||
| precision floating-point format.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static float32 commonNaNToFloat32( commonNaNT a )
|
||||
{
|
||||
|
||||
return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes two single-precision floating-point values `a' and `b', one of which
|
||||
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
|
||||
| signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static float32 propagateFloat32NaN( float32 a, float32 b )
|
||||
{
|
||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
||||
|
||||
aIsNaN = float32_is_nan( a );
|
||||
aIsSignalingNaN = float32_is_signaling_nan( a );
|
||||
bIsNaN = float32_is_nan( b );
|
||||
bIsSignalingNaN = float32_is_signaling_nan( b );
|
||||
a |= 0x00400000;
|
||||
b |= 0x00400000;
|
||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
|
||||
if ( aIsNaN ) {
|
||||
return ( aIsSignalingNaN & bIsNaN ) ? b : a;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated double-precision NaN.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the double-precision floating-point value `a' is a NaN;
|
||||
| otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag float64_is_nan( float64 a )
|
||||
{
|
||||
|
||||
return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the double-precision floating-point value `a' is a signaling
|
||||
| NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag float64_is_signaling_nan( float64 a )
|
||||
{
|
||||
|
||||
return
|
||||
( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
|
||||
&& ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the double-precision floating-point NaN
|
||||
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static commonNaNT float64ToCommonNaN( float64 a )
|
||||
{
|
||||
commonNaNT z;
|
||||
|
||||
if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
|
||||
z.sign = a>>63;
|
||||
z.low = 0;
|
||||
z.high = a<<12;
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the canonical NaN `a' to the double-
|
||||
| precision floating-point format.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static float64 commonNaNToFloat64( commonNaNT a )
|
||||
{
|
||||
|
||||
return
|
||||
( ( (bits64) a.sign )<<63 )
|
||||
| LIT64( 0x7FF8000000000000 )
|
||||
| ( a.high>>12 );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes two double-precision floating-point values `a' and `b', one of which
|
||||
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
|
||||
| signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static float64 propagateFloat64NaN( float64 a, float64 b )
|
||||
{
|
||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
||||
|
||||
aIsNaN = float64_is_nan( a );
|
||||
aIsSignalingNaN = float64_is_signaling_nan( a );
|
||||
bIsNaN = float64_is_nan( b );
|
||||
bIsSignalingNaN = float64_is_signaling_nan( b );
|
||||
a |= LIT64( 0x0008000000000000 );
|
||||
b |= LIT64( 0x0008000000000000 );
|
||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
|
||||
if ( aIsNaN ) {
|
||||
return ( aIsSignalingNaN & bIsNaN ) ? b : a;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef FLOATX80
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| 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_high 0xFFFF
|
||||
#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the extended double-precision floating-point value `a' is a
|
||||
| NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag floatx80_is_nan( floatx80 a )
|
||||
{
|
||||
|
||||
return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the extended double-precision floating-point value `a' is a
|
||||
| signaling NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag floatx80_is_signaling_nan( floatx80 a )
|
||||
{
|
||||
bits64 aLow;
|
||||
|
||||
aLow = a.low & ~ LIT64( 0x4000000000000000 );
|
||||
return
|
||||
( ( a.high & 0x7FFF ) == 0x7FFF )
|
||||
&& (bits64) ( aLow<<1 )
|
||||
&& ( a.low == aLow );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the extended double-precision floating-
|
||||
| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
|
||||
| invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static commonNaNT floatx80ToCommonNaN( floatx80 a )
|
||||
{
|
||||
commonNaNT z;
|
||||
|
||||
if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
|
||||
z.sign = a.high>>15;
|
||||
z.low = 0;
|
||||
z.high = a.low<<1;
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the canonical NaN `a' to the extended
|
||||
| double-precision floating-point format.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static floatx80 commonNaNToFloatx80( commonNaNT a )
|
||||
{
|
||||
floatx80 z;
|
||||
|
||||
z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
|
||||
z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes two extended double-precision floating-point values `a' and `b', one
|
||||
| of which is a NaN, and returns the appropriate NaN result. If either `a' or
|
||||
| `b' is a signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
|
||||
{
|
||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
||||
|
||||
aIsNaN = floatx80_is_nan( a );
|
||||
aIsSignalingNaN = floatx80_is_signaling_nan( a );
|
||||
bIsNaN = floatx80_is_nan( b );
|
||||
bIsSignalingNaN = floatx80_is_signaling_nan( b );
|
||||
a.low |= LIT64( 0xC000000000000000 );
|
||||
b.low |= LIT64( 0xC000000000000000 );
|
||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
|
||||
if ( aIsNaN ) {
|
||||
return ( aIsSignalingNaN & bIsNaN ) ? b : a;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define EXP_BIAS 0x3FFF
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the fraction bits of the extended double-precision floating-point
|
||||
| value `a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline bits64 extractFloatx80Frac( floatx80 a )
|
||||
{
|
||||
|
||||
return a.low;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the exponent bits of the extended double-precision floating-point
|
||||
| value `a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline int32 extractFloatx80Exp( floatx80 a )
|
||||
{
|
||||
|
||||
return a.high & 0x7FFF;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the sign bit of the extended double-precision floating-point value
|
||||
| `a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag extractFloatx80Sign( floatx80 a )
|
||||
{
|
||||
|
||||
return a.high>>15;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FLOAT128
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated quadruple-precision NaN. The `high' and
|
||||
| `low' values hold the most- and least-significant bits, respectively.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
|
||||
#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
|
||||
| otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag float128_is_nan( float128 a )
|
||||
{
|
||||
|
||||
return
|
||||
( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
|
||||
&& ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the quadruple-precision floating-point value `a' is a
|
||||
| signaling NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag float128_is_signaling_nan( float128 a )
|
||||
{
|
||||
|
||||
return
|
||||
( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
|
||||
&& ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the quadruple-precision floating-point NaN
|
||||
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static commonNaNT float128ToCommonNaN( float128 a )
|
||||
{
|
||||
commonNaNT z;
|
||||
|
||||
if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
|
||||
z.sign = a.high>>63;
|
||||
shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the canonical NaN `a' to the quadruple-
|
||||
| precision floating-point format.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static float128 commonNaNToFloat128( commonNaNT a )
|
||||
{
|
||||
float128 z;
|
||||
|
||||
shift128Right( a.high, a.low, 16, &z.high, &z.low );
|
||||
z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes two quadruple-precision floating-point values `a' and `b', one of
|
||||
| which is a NaN, and returns the appropriate NaN result. If either `a' or
|
||||
| `b' is a signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static float128 propagateFloat128NaN( float128 a, float128 b )
|
||||
{
|
||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
||||
|
||||
aIsNaN = float128_is_nan( a );
|
||||
aIsSignalingNaN = float128_is_signaling_nan( a );
|
||||
bIsNaN = float128_is_nan( b );
|
||||
bIsSignalingNaN = float128_is_signaling_nan( b );
|
||||
a.high |= LIT64( 0x0000800000000000 );
|
||||
b.high |= LIT64( 0x0000800000000000 );
|
||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
|
||||
if ( aIsNaN ) {
|
||||
return ( aIsSignalingNaN & bIsNaN ) ? b : a;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
438
softfloat/softfloat-specialize.h
Normal file
438
softfloat/softfloat-specialize.h
Normal file
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
* QEMU float support
|
||||
*
|
||||
* The code in this source file is derived from release 2a of the SoftFloat
|
||||
* IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and
|
||||
* some later contributions) are provided under that license, as detailed below.
|
||||
* It has subsequently been modified by contributors to the QEMU Project,
|
||||
* so some portions are provided under:
|
||||
* the SoftFloat-2a license
|
||||
* the BSD license
|
||||
* GPL-v2-or-later
|
||||
*
|
||||
* Any future contributions to this file after December 1st 2014 will be
|
||||
* taken to be licensed under the Softfloat-2a license unless specifically
|
||||
* indicated otherwise.
|
||||
*/
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
|
||||
Arithmetic Package, Release 2a.
|
||||
|
||||
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://HTTP.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 ANY
|
||||
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
|
||||
|
||||
Derivative works are acceptable, even for commercial purposes, so long as
|
||||
(1) they include prominent notice that the work is derivative, and (2) they
|
||||
include prominent notice akin to these four paragraphs for those parts of
|
||||
this code that are retained.
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/* BSD licensing:
|
||||
* Copyright (c) 2006, Fabrice Bellard
|
||||
* 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 copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
|
||||
/* Portions of this work are licensed under the terms of the GNU GPL,
|
||||
* version 2 or later. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the extended double-precision floating-point value `a' is a
|
||||
| NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag floatx80_is_nan( floatx80 a );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated extended double-precision NaN.
|
||||
*----------------------------------------------------------------------------*/
|
||||
static inline floatx80 floatx80_default_nan(float_status *status)
|
||||
{
|
||||
(void)status;
|
||||
floatx80 r;
|
||||
r.high = 0x7FFF;
|
||||
r.low = LIT64( 0xFFFFFFFFFFFFFFFF );
|
||||
return r;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Raises the exceptions specified by `flags'. Floating-point traps can be
|
||||
| defined here if desired. It is currently not possible for such a trap
|
||||
| to substitute a result value. If traps are not implemented, this routine
|
||||
| should be simply `float_exception_flags |= flags;'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void float_raise(uint8_t flags, float_status *status);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Internal canonical NaN format.
|
||||
*----------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
flag sign;
|
||||
uint64_t high, low;
|
||||
} commonNaNT;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the single-precision floating-point value `a' is a NaN;
|
||||
| otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag float32_is_nan( float32 a )
|
||||
{
|
||||
|
||||
return ( 0xFF000000 < (uint32_t) ( a<<1 ) );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the single-precision floating-point value `a' is a signaling
|
||||
| NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag float32_is_signaling_nan( float32 a )
|
||||
{
|
||||
|
||||
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the single-precision floating-point NaN
|
||||
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline commonNaNT float32ToCommonNaN( float32 a, float_status *status )
|
||||
{
|
||||
commonNaNT z;
|
||||
|
||||
if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_signaling, status );
|
||||
z.sign = a>>31;
|
||||
z.low = 0;
|
||||
z.high = ( (uint64_t) a )<<41;
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the canonical NaN `a' to the single-
|
||||
| precision floating-point format.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline float32 commonNaNToFloat32( commonNaNT a )
|
||||
{
|
||||
|
||||
return ( ( (uint32_t) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes two single-precision floating-point values `a' and `b', one of which
|
||||
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
|
||||
| signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline float32 propagateFloat32NaN( float32 a, float32 b, float_status *status )
|
||||
{
|
||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
||||
|
||||
aIsNaN = float32_is_nan( a );
|
||||
aIsSignalingNaN = float32_is_signaling_nan( a );
|
||||
bIsNaN = float32_is_nan( b );
|
||||
bIsSignalingNaN = float32_is_signaling_nan( b );
|
||||
a |= 0x00400000;
|
||||
b |= 0x00400000;
|
||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling, status );
|
||||
if ( aIsNaN ) {
|
||||
return ( aIsSignalingNaN & bIsNaN ) ? b : a;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the double-precision floating-point value `a' is a NaN;
|
||||
| otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag float64_is_nan( float64 a )
|
||||
{
|
||||
|
||||
return ( LIT64( 0xFFE0000000000000 ) < (uint64_t) ( a<<1 ) );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the double-precision floating-point value `a' is a signaling
|
||||
| NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag float64_is_signaling_nan( float64 a )
|
||||
{
|
||||
|
||||
return
|
||||
( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
|
||||
&& ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the double-precision floating-point NaN
|
||||
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline commonNaNT float64ToCommonNaN(float64 a, float_status *status)
|
||||
{
|
||||
commonNaNT z;
|
||||
|
||||
if (float64_is_signaling_nan(a)) {
|
||||
float_raise(float_flag_invalid, status);
|
||||
}
|
||||
z.sign = float64_val(a) >> 63;
|
||||
z.low = 0;
|
||||
z.high = float64_val(a) << 12;
|
||||
return z;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the canonical NaN `a' to the double-
|
||||
| precision floating-point format.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline float64 commonNaNToFloat64(commonNaNT a, float_status *status)
|
||||
{
|
||||
(void)status;
|
||||
return
|
||||
( ( (uint64_t) a.sign )<<63 )
|
||||
| LIT64( 0x7FF8000000000000 )
|
||||
| ( a.high>>12 );
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the extended double-precision floating-point value `a' is a
|
||||
| signaling NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag floatx80_is_signaling_nan( floatx80 a )
|
||||
{
|
||||
uint64_t aLow;
|
||||
|
||||
aLow = a.low & ~ LIT64( 0x4000000000000000 );
|
||||
return
|
||||
( ( a.high & 0x7FFF ) == 0x7FFF )
|
||||
&& (uint64_t) ( aLow<<1 )
|
||||
&& ( a.low == aLow );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the extended double-precision floating-
|
||||
| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
|
||||
| invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline commonNaNT floatx80ToCommonNaN( floatx80 a, float_status *status )
|
||||
{
|
||||
commonNaNT z;
|
||||
|
||||
if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_signaling, status );
|
||||
z.sign = a.high>>15;
|
||||
z.low = 0;
|
||||
z.high = a.low<<1;
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the canonical NaN `a' to the extended
|
||||
| double-precision floating-point format.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline floatx80 commonNaNToFloatx80(commonNaNT a, float_status *status)
|
||||
{
|
||||
(void)status;
|
||||
floatx80 z;
|
||||
#ifdef SOFTFLOAT_68K
|
||||
z.low = LIT64( 0x4000000000000000 ) | ( a.high>>1 );
|
||||
#else
|
||||
z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
|
||||
#endif
|
||||
z.high = ( ( (int16_t) a.sign )<<15 ) | 0x7FFF;
|
||||
return z;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes two extended double-precision floating-point values `a' and `b', one
|
||||
| of which is a NaN, and returns the appropriate NaN result. If either `a' or
|
||||
| `b' is a signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b, float_status *status )
|
||||
{
|
||||
flag aIsNaN, aIsSignalingNaN, bIsSignalingNaN;
|
||||
#ifndef SOFTFLOAT_68K
|
||||
flag bIsNaN;
|
||||
#endif
|
||||
|
||||
aIsNaN = floatx80_is_nan( a );
|
||||
aIsSignalingNaN = floatx80_is_signaling_nan( a );
|
||||
bIsSignalingNaN = floatx80_is_signaling_nan( b );
|
||||
#ifdef SOFTFLOAT_68K
|
||||
a.low |= LIT64( 0x4000000000000000 );
|
||||
b.low |= LIT64( 0x4000000000000000 );
|
||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling, status );
|
||||
return aIsNaN ? a : b;
|
||||
#else
|
||||
bIsNaN = floatx80_is_nan( b );
|
||||
a.low |= LIT64( 0xC000000000000000 );
|
||||
b.low |= LIT64( 0xC000000000000000 );
|
||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling, status );
|
||||
if ( aIsNaN ) {
|
||||
return ( aIsSignalingNaN & bIsNaN ) ? b : a;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef SOFTFLOAT_68K
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes extended double-precision floating-point NaN `a' and returns the
|
||||
| appropriate NaN result. If `a' is a signaling NaN, the invalid exception
|
||||
| is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status)
|
||||
{
|
||||
if ( floatx80_is_signaling_nan( a ) )
|
||||
float_raise( float_flag_signaling, status );
|
||||
a.low |= LIT64( 0x4000000000000000 );
|
||||
|
||||
return a;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 28-12-2016: Added for Previous:
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the extended double-precision floating-point value `a' is
|
||||
| zero; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag floatx80_is_zero( floatx80 a )
|
||||
{
|
||||
|
||||
return ( ( a.high & 0x7FFF ) < 0x7FFF ) && ( a.low == 0 );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the extended double-precision floating-point value `a' is
|
||||
| infinity; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag floatx80_is_infinity( floatx80 a )
|
||||
{
|
||||
|
||||
return ( ( a.high & 0x7FFF ) == 0x7FFF ) && ( (uint64_t) ( a.low<<1 ) == 0 );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the extended double-precision floating-point value `a' is
|
||||
| negative; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag floatx80_is_negative( floatx80 a )
|
||||
{
|
||||
|
||||
return ( ( a.high & 0x8000 ) == 0x8000 );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the extended double-precision floating-point value `a' is
|
||||
| unnormal; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
static inline flag floatx80_is_unnormal( floatx80 a )
|
||||
{
|
||||
return
|
||||
( ( a.high & 0x7FFF ) > 0 )
|
||||
&& ( ( a.high & 0x7FFF ) < 0x7FFF)
|
||||
&& ( (uint64_t) ( a.low & LIT64( 0x8000000000000000 ) ) == LIT64( 0x0000000000000000 ) );
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the extended double-precision floating-point value `a' is
|
||||
| denormal; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag floatx80_is_denormal( floatx80 a )
|
||||
{
|
||||
return
|
||||
( ( a.high & 0x7FFF ) == 0 )
|
||||
&& ( (uint64_t) ( a.low & LIT64( 0x8000000000000000 ) ) == LIT64( 0x0000000000000000 ) )
|
||||
&& (uint64_t) ( a.low<<1 );
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the extended double-precision floating-point value `a' is
|
||||
| normal; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline flag floatx80_is_normal( floatx80 a )
|
||||
{
|
||||
return
|
||||
( ( a.high & 0x7FFF ) < 0x7FFF )
|
||||
&& ( (uint64_t) ( a.low & LIT64( 0x8000000000000000 ) ) == LIT64( 0x8000000000000000 ) );
|
||||
}
|
||||
// End of addition for Previous
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,27 @@
|
||||
#define SOFTFLOAT_68K
|
||||
#define FLOATX80
|
||||
#define FLOAT128
|
||||
/*
|
||||
* QEMU float support
|
||||
*
|
||||
* The code in this source file is derived from release 2a of the SoftFloat
|
||||
* IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and
|
||||
* some later contributions) are provided under that license, as detailed below.
|
||||
* It has subsequently been modified by contributors to the QEMU Project,
|
||||
* so some portions are provided under:
|
||||
* the SoftFloat-2a license
|
||||
* the BSD license
|
||||
* GPL-v2-or-later
|
||||
*
|
||||
* Any future contributions to this file after December 1st 2014 will be
|
||||
* taken to be licensed under the Softfloat-2a license unless specifically
|
||||
* indicated otherwise.
|
||||
*/
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
|
||||
Package, Release 2b.
|
||||
/*
|
||||
===============================================================================
|
||||
This C header file is part of the SoftFloat IEC/IEEE Floating-point
|
||||
Arithmetic Package, Release 2a.
|
||||
|
||||
Written by John R. Hauser. This work was made possible in part by the
|
||||
International Computer Science Institute, located at Suite 600, 1947 Center
|
||||
@@ -11,450 +30,487 @@ 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/
|
||||
is available through the Web page `http://HTTP.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.
|
||||
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 ANY
|
||||
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
|
||||
|
||||
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.
|
||||
(1) they include prominent notice that the work is derivative, and (2) they
|
||||
include prominent notice akin to these four paragraphs for those parts of
|
||||
this code that are retained.
|
||||
|
||||
=============================================================================*/
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/* BSD licensing:
|
||||
* Copyright (c) 2006, Fabrice Bellard
|
||||
* 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 copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
|
||||
/* Portions of this work are licensed under the terms of the GNU GPL,
|
||||
* version 2 or later. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef SOFTFLOAT_H
|
||||
#define SOFTFLOAT_H
|
||||
|
||||
#if defined(CONFIG_SOLARIS) && defined(CONFIG_NEEDS_LIBSUNMATH)
|
||||
#include <sunmath.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* This 'flag' type must be able to hold at least 0 and 1. It should
|
||||
* probably be replaced with 'bool' but the uses would need to be audited
|
||||
* to check that they weren't accidentally relying on it being a larger type.
|
||||
*/
|
||||
|
||||
typedef uint64_t flag;
|
||||
typedef uint8_t bool;
|
||||
|
||||
#define LIT64( a ) a##ULL
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The macro `FLOATX80' must be defined to enable the extended double-precision
|
||||
| floating-point format `floatx80'. If this macro is not defined, the
|
||||
| `floatx80' type will not be defined, and none of the functions that either
|
||||
| input or output the `floatx80' type will be defined. The same applies to
|
||||
| the `FLOAT128' macro and the quadruple-precision format `float128'.
|
||||
| Software IEC/IEEE floating-point ordering relations
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define FLOATX80
|
||||
#define FLOAT128
|
||||
enum {
|
||||
float_relation_less = -1,
|
||||
float_relation_equal = 0,
|
||||
float_relation_greater = 1,
|
||||
float_relation_unordered = 2
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE floating-point types.
|
||||
*----------------------------------------------------------------------------*/
|
||||
typedef bits32 float32;
|
||||
typedef bits64 float64;
|
||||
#ifdef FLOATX80
|
||||
/* Use structures for soft-float types. This prevents accidentally mixing
|
||||
them with native int/float types. A sufficiently clever compiler and
|
||||
sane ABI should be able to see though these structs. However
|
||||
x86/gcc 3.x seems to struggle a bit, so leave them disabled by default. */
|
||||
//#define USE_SOFTFLOAT_STRUCT_TYPES
|
||||
#ifdef USE_SOFTFLOAT_STRUCT_TYPES
|
||||
typedef struct {
|
||||
bits16 high;
|
||||
bits64 low;
|
||||
uint16_t v;
|
||||
} float16;
|
||||
#define float16_val(x) (((float16)(x)).v)
|
||||
#define make_float16(x) __extension__ ({ float16 f16_val = {x}; f16_val; })
|
||||
#define const_float16(x) { x }
|
||||
typedef struct {
|
||||
uint32_t v;
|
||||
} float32;
|
||||
/* The cast ensures an error if the wrong type is passed. */
|
||||
#define float32_val(x) (((float32)(x)).v)
|
||||
#define make_float32(x) __extension__ ({ float32 f32_val = {x}; f32_val; })
|
||||
#define const_float32(x) { x }
|
||||
typedef struct {
|
||||
uint64_t v;
|
||||
} float64;
|
||||
#define float64_val(x) (((float64)(x)).v)
|
||||
#define make_float64(x) __extension__ ({ float64 f64_val = {x}; f64_val; })
|
||||
#define const_float64(x) { x }
|
||||
#else
|
||||
typedef uint16_t float16;
|
||||
typedef uint32_t float32;
|
||||
typedef uint64_t float64;
|
||||
#define float16_val(x) (x)
|
||||
#define float32_val(x) (x)
|
||||
#define float64_val(x) (x)
|
||||
#define make_float16(x) (x)
|
||||
#define make_float32(x) (x)
|
||||
#define make_float64(x) (x)
|
||||
#define const_float16(x) (x)
|
||||
#define const_float32(x) (x)
|
||||
#define const_float64(x) (x)
|
||||
#endif
|
||||
typedef struct {
|
||||
uint16_t high;
|
||||
uint64_t low;
|
||||
} floatx80;
|
||||
#endif
|
||||
#ifdef FLOAT128
|
||||
typedef struct {
|
||||
bits64 high, low;
|
||||
} float128;
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
uint64_t high, low;
|
||||
#else
|
||||
uint64_t low, high;
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Primitive arithmetic functions, including multi-word arithmetic, and
|
||||
| division and square root approximations. (Can be specialized to target if
|
||||
| desired.)
|
||||
*----------------------------------------------------------------------------*/
|
||||
#include "softfloat-macros"
|
||||
} float128;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE floating-point underflow tininess-detection mode.
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern int8 float_detect_tininess;
|
||||
enum {
|
||||
float_tininess_after_rounding = 0,
|
||||
float_tininess_before_rounding = 1
|
||||
float_tininess_after_rounding = 0,
|
||||
float_tininess_before_rounding = 1
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE floating-point rounding mode.
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern int8 float_rounding_mode;
|
||||
enum {
|
||||
float_round_nearest_even = 0,
|
||||
float_round_to_zero = 1,
|
||||
float_round_down = 2,
|
||||
float_round_up = 3
|
||||
float_round_nearest_even = 0,
|
||||
float_round_down = 1,
|
||||
float_round_up = 2,
|
||||
float_round_to_zero = 3,
|
||||
float_round_ties_away = 4,
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE floating-point exception flags.
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern int8 float_exception_flags;
|
||||
enum {
|
||||
float_flag_invalid = 0x01, float_flag_denormal = 0x02, float_flag_divbyzero = 0x04, float_flag_overflow = 0x08,
|
||||
float_flag_underflow = 0x10, float_flag_inexact = 0x20
|
||||
float_flag_invalid = 0x01,
|
||||
float_flag_denormal = 0x02,
|
||||
float_flag_divbyzero = 0x04,
|
||||
float_flag_overflow = 0x08,
|
||||
float_flag_underflow = 0x10,
|
||||
float_flag_inexact = 0x20,
|
||||
float_flag_signaling = 0x40,
|
||||
float_flag_decimal = 0x80
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Variables for storing sign, exponent and significand of overflowed or
|
||||
| underflowed extended double-precision floating-point value.
|
||||
| Variables for storing sign, exponent and significand of internal extended
|
||||
| double-precision floating-point value for external use.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
extern flag floatx80_internal_sign;
|
||||
extern int32_t floatx80_internal_exp;
|
||||
extern uint64_t floatx80_internal_sig;
|
||||
extern int32_t floatx80_internal_exp0;
|
||||
extern uint64_t floatx80_internal_sig0;
|
||||
extern uint64_t floatx80_internal_sig1;
|
||||
extern int8_t floatx80_internal_precision;
|
||||
extern int8_t floatx80_internal_mode;
|
||||
|
||||
typedef struct float_status {
|
||||
signed char float_detect_tininess;
|
||||
signed char float_rounding_mode;
|
||||
uint8_t float_exception_flags;
|
||||
signed char floatx80_rounding_precision;
|
||||
/* should denormalised results go to zero and set the inexact flag? */
|
||||
flag flush_to_zero;
|
||||
/* should denormalised inputs go to zero and set the input_denormal flag? */
|
||||
flag flush_inputs_to_zero;
|
||||
flag default_nan_mode;
|
||||
flag snan_bit_is_one;
|
||||
flag floatx80_special_flags;
|
||||
} float_status;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Function for getting sign, exponent and significand of extended
|
||||
| double-precision floating-point intermediate result for external use.
|
||||
*----------------------------------------------------------------------------*/
|
||||
floatx80 getFloatInternalOverflow( void );
|
||||
floatx80 getFloatInternalUnderflow( void );
|
||||
floatx80 getFloatInternalRoundedAll( void );
|
||||
floatx80 getFloatInternalRoundedSome( void );
|
||||
floatx80 getFloatInternalUnrounded( void );
|
||||
floatx80 getFloatInternalFloatx80( void );
|
||||
uint64_t getFloatInternalGRS( void );
|
||||
|
||||
static inline void set_float_detect_tininess(int val, float_status *status)
|
||||
{
|
||||
status->float_detect_tininess = val;
|
||||
}
|
||||
static inline void set_float_rounding_mode(int val, float_status *status)
|
||||
{
|
||||
status->float_rounding_mode = val;
|
||||
}
|
||||
static inline void set_float_exception_flags(int val, float_status *status)
|
||||
{
|
||||
status->float_exception_flags = val;
|
||||
}
|
||||
static inline void set_floatx80_rounding_precision(int val,
|
||||
float_status *status)
|
||||
{
|
||||
status->floatx80_rounding_precision = val;
|
||||
}
|
||||
static inline void set_flush_to_zero(flag val, float_status *status)
|
||||
{
|
||||
status->flush_to_zero = val;
|
||||
}
|
||||
static inline void set_flush_inputs_to_zero(flag val, float_status *status)
|
||||
{
|
||||
status->flush_inputs_to_zero = val;
|
||||
}
|
||||
static inline void set_default_nan_mode(flag val, float_status *status)
|
||||
{
|
||||
status->default_nan_mode = val;
|
||||
}
|
||||
static inline void set_snan_bit_is_one(flag val, float_status *status)
|
||||
{
|
||||
status->snan_bit_is_one = val;
|
||||
}
|
||||
static inline int get_float_detect_tininess(float_status *status)
|
||||
{
|
||||
return status->float_detect_tininess;
|
||||
}
|
||||
static inline int get_float_rounding_mode(float_status *status)
|
||||
{
|
||||
return status->float_rounding_mode;
|
||||
}
|
||||
static inline int get_float_exception_flags(float_status *status)
|
||||
{
|
||||
return status->float_exception_flags;
|
||||
}
|
||||
static inline int get_floatx80_rounding_precision(float_status *status)
|
||||
{
|
||||
return status->floatx80_rounding_precision;
|
||||
}
|
||||
static inline flag get_flush_to_zero(float_status *status)
|
||||
{
|
||||
return status->flush_to_zero;
|
||||
}
|
||||
static inline flag get_flush_inputs_to_zero(float_status *status)
|
||||
{
|
||||
return status->flush_inputs_to_zero;
|
||||
}
|
||||
static inline flag get_default_nan_mode(float_status *status)
|
||||
{
|
||||
return status->default_nan_mode;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Special flags for indicating some unique behavior is required.
|
||||
*----------------------------------------------------------------------------*/
|
||||
enum {
|
||||
cmp_signed_nan = 0x01, addsub_swap_inf = 0x02, infinity_clear_intbit = 0x04
|
||||
};
|
||||
|
||||
static inline void set_special_flags(uint8_t flags, float_status *status)
|
||||
{
|
||||
status->floatx80_special_flags = flags;
|
||||
}
|
||||
static inline int8_t fcmp_signed_nan(float_status *status)
|
||||
{
|
||||
return status->floatx80_special_flags & cmp_signed_nan;
|
||||
}
|
||||
static inline int8_t faddsub_swap_inf(float_status *status)
|
||||
{
|
||||
return status->floatx80_special_flags & addsub_swap_inf;
|
||||
}
|
||||
static inline int8_t inf_clear_intbit(float_status *status)
|
||||
{
|
||||
return status->floatx80_special_flags & infinity_clear_intbit;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Routine to raise any or all of the software IEC/IEEE floating-point
|
||||
| exception flags.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void float_raise( int8 );
|
||||
void float_raise(uint8_t flags, float_status *status);
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated single-precision NaN.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define float32_default_nan 0x7FFFFFFF
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated double-precision NaN.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define float64_default_nan LIT64( 0x7FFFFFFFFFFFFFFF )
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| 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_high 0x7FFF
|
||||
#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated extended double-precision infinity.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define floatx80_default_infinity_low LIT64( 0x0000000000000000 )
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| If `a' is denormal and we are in flush-to-zero mode then set the
|
||||
| input-denormal exception and return zero. Otherwise just return the value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float64 float64_squash_input_denormal(float64 a, float_status *status);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Options to indicate which negations to perform in float*_muladd()
|
||||
| Using these differs from negating an input or output before calling
|
||||
| the muladd function in that this means that a NaN doesn't have its
|
||||
| sign bit inverted before it is propagated.
|
||||
| We also support halving the result before rounding, as a special
|
||||
| case to support the ARM fused-sqrt-step instruction FRSQRTS.
|
||||
*----------------------------------------------------------------------------*/
|
||||
enum {
|
||||
float_muladd_negate_c = 1,
|
||||
float_muladd_negate_product = 2,
|
||||
float_muladd_negate_result = 4,
|
||||
float_muladd_halve_result = 8,
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE integer-to-floating-point conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float32 int32_to_float32( int32 );
|
||||
float64 int32_to_float64( int32 );
|
||||
#ifdef FLOATX80
|
||||
floatx80 int32_to_floatx80( int32 );
|
||||
#endif
|
||||
#ifdef FLOAT128
|
||||
float128 int32_to_float128( int32 );
|
||||
#endif
|
||||
float32 int64_to_float32( int64 );
|
||||
float64 int64_to_float64( int64 );
|
||||
#ifdef FLOATX80
|
||||
floatx80 int64_to_floatx80( int64 );
|
||||
#endif
|
||||
#ifdef FLOAT128
|
||||
float128 int64_to_float128( int64 );
|
||||
#endif
|
||||
|
||||
floatx80 int32_to_floatx80(int32_t);
|
||||
floatx80 int64_to_floatx80(int64_t);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE single-precision conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
int32 float32_to_int32( float32 );
|
||||
int32 float32_to_int32_round_to_zero( float32 );
|
||||
int64 float32_to_int64( float32 );
|
||||
int64 float32_to_int64_round_to_zero( float32 );
|
||||
float64 float32_to_float64( float32 );
|
||||
#ifdef FLOATX80
|
||||
floatx80 float32_to_floatx80( float32 );
|
||||
#endif
|
||||
#ifdef FLOAT128
|
||||
float128 float32_to_float128( float32 );
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE single-precision operations.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float32 float32_round_to_int( float32 );
|
||||
float32 float32_add( float32, float32 );
|
||||
float32 float32_sub( float32, float32 );
|
||||
float32 float32_mul( float32, float32 );
|
||||
float32 float32_div( float32, float32 );
|
||||
float32 float32_rem( float32, float32 );
|
||||
float32 float32_sqrt( float32 );
|
||||
flag float32_eq( float32, float32 );
|
||||
flag float32_le( float32, float32 );
|
||||
flag float32_lt( float32, float32 );
|
||||
flag float32_eq_signaling( float32, float32 );
|
||||
flag float32_le_quiet( float32, float32 );
|
||||
flag float32_lt_quiet( float32, float32 );
|
||||
flag float32_is_signaling_nan( float32 );
|
||||
floatx80 float32_to_floatx80(float32, float_status *status);
|
||||
floatx80 float32_to_floatx80_allowunnormal(float32, float_status *status);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE double-precision conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
int32 float64_to_int32( float64 );
|
||||
int32 float64_to_int32_round_to_zero( float64 );
|
||||
int64 float64_to_int64( float64 );
|
||||
int64 float64_to_int64_round_to_zero( float64 );
|
||||
float32 float64_to_float32( float64 );
|
||||
#ifdef FLOATX80
|
||||
floatx80 float64_to_floatx80( float64 );
|
||||
#endif
|
||||
#ifdef FLOAT128
|
||||
float128 float64_to_float128( float64 );
|
||||
#endif
|
||||
floatx80 float64_to_floatx80(float64, float_status *status);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE double-precision operations.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float64 float64_round_to_int( float64 );
|
||||
float64 float64_add( float64, float64 );
|
||||
float64 float64_sub( float64, float64 );
|
||||
float64 float64_mul( float64, float64 );
|
||||
float64 float64_div( float64, float64 );
|
||||
float64 float64_rem( float64, float64 );
|
||||
float64 float64_sqrt( float64 );
|
||||
flag float64_eq( float64, float64 );
|
||||
flag float64_le( float64, float64 );
|
||||
flag float64_lt( float64, float64 );
|
||||
flag float64_eq_signaling( float64, float64 );
|
||||
flag float64_le_quiet( float64, float64 );
|
||||
flag float64_lt_quiet( float64, float64 );
|
||||
flag float64_is_signaling_nan( float64 );
|
||||
|
||||
#ifdef FLOATX80
|
||||
floatx80 float64_to_floatx80_allowunnormal( float64 a, float_status *status );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE extended double-precision conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
int32 floatx80_to_int32( floatx80 );
|
||||
int32 floatx80_to_int32_round_to_zero( floatx80 );
|
||||
int64 floatx80_to_int64( floatx80 );
|
||||
int64 floatx80_to_int64_round_to_zero( floatx80 );
|
||||
float32 floatx80_to_float32( floatx80 );
|
||||
float64 floatx80_to_float64( floatx80 );
|
||||
#ifdef FLOAT128
|
||||
float128 floatx80_to_float128( floatx80 );
|
||||
int32_t floatx80_to_int32(floatx80, float_status *status);
|
||||
#ifdef SOFTFLOAT_68K
|
||||
int16_t floatx80_to_int16(floatx80, float_status *status);
|
||||
int8_t floatx80_to_int8(floatx80, float_status *status);
|
||||
#endif
|
||||
int32_t floatx80_to_int32_round_to_zero(floatx80, float_status *status);
|
||||
int64_t floatx80_to_int64(floatx80, float_status *status);
|
||||
float32 floatx80_to_float32(floatx80, float_status *status);
|
||||
float64 floatx80_to_float64(floatx80, float_status *status);
|
||||
#ifdef SOFTFLOAT_68K
|
||||
floatx80 floatx80_to_floatx80( floatx80, float_status *status);
|
||||
floatx80 floatdecimal_to_floatx80(floatx80, float_status *status);
|
||||
floatx80 floatx80_to_floatdecimal(floatx80, int32_t*, float_status *status);
|
||||
#endif
|
||||
floatx80 floatx80_scale(floatx80 a, floatx80 b);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
|
||||
| extended double-precision floating-point value, returning the result.
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint64_t extractFloatx80Frac( floatx80 a );
|
||||
int32_t extractFloatx80Exp( floatx80 a );
|
||||
flag extractFloatx80Sign( floatx80 a );
|
||||
|
||||
static inline floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig )
|
||||
{
|
||||
floatx80 z;
|
||||
floatx80 floatx80_round_to_int_toward_zero( floatx80 a, float_status *status);
|
||||
floatx80 floatx80_round_to_float32( floatx80, float_status *status );
|
||||
floatx80 floatx80_round_to_float64( floatx80, float_status *status );
|
||||
floatx80 floatx80_round32( floatx80, float_status *status);
|
||||
floatx80 floatx80_round64( floatx80, float_status *status);
|
||||
|
||||
z.low = zSig;
|
||||
z.high = ( ( (bits16) zSign )<<15 ) + zExp;
|
||||
return z;
|
||||
flag floatx80_eq( floatx80, floatx80, float_status *status);
|
||||
flag floatx80_le( floatx80, floatx80, float_status *status);
|
||||
flag floatx80_lt( floatx80, floatx80, float_status *status);
|
||||
|
||||
}
|
||||
#ifdef SOFTFLOAT_68K
|
||||
// functions are in softfloat.c
|
||||
floatx80 floatx80_move( floatx80 a, float_status *status );
|
||||
floatx80 floatx80_abs( floatx80 a, float_status *status );
|
||||
floatx80 floatx80_neg( floatx80 a, float_status *status );
|
||||
floatx80 floatx80_getexp( floatx80 a, float_status *status );
|
||||
floatx80 floatx80_getman( floatx80 a, float_status *status );
|
||||
floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status );
|
||||
floatx80 floatx80_rem( floatx80 a, floatx80 b, uint64_t *q, flag *s, float_status *status );
|
||||
floatx80 floatx80_mod( floatx80 a, floatx80 b, uint64_t *q, flag *s, float_status *status );
|
||||
floatx80 floatx80_sglmul( floatx80 a, floatx80 b, float_status *status );
|
||||
floatx80 floatx80_sgldiv( floatx80 a, floatx80 b, float_status *status );
|
||||
floatx80 floatx80_cmp( floatx80 a, floatx80 b, float_status *status );
|
||||
floatx80 floatx80_tst( floatx80 a, float_status *status );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE extended double-precision rounding precision. Valid
|
||||
| values are 32, 64, and 80.
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern int8 floatx80_rounding_precision;
|
||||
// functions are in softfloat_fpsp.c
|
||||
floatx80 floatx80_acos(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_asin(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_atan(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_atanh(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_cos(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_cosh(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_etox(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_etoxm1(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_log10(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_log2(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_logn(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_lognp1(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_sin(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_sinh(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_tan(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_tanh(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_tentox(floatx80 a, float_status *status);
|
||||
floatx80 floatx80_twotox(floatx80 a, float_status *status);
|
||||
#endif
|
||||
|
||||
// functions originally internal to softfloat.c
|
||||
void normalizeFloatx80Subnormal( uint64_t aSig, int32_t *zExpPtr, uint64_t *zSigPtr );
|
||||
floatx80 packFloatx80( flag zSign, int32_t zExp, uint64_t zSig );
|
||||
floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, int32_t zExp, uint64_t zSig0, uint64_t zSig1, float_status *status);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE extended double-precision operations.
|
||||
*----------------------------------------------------------------------------*/
|
||||
floatx80 floatx80_round_to_int( floatx80 );
|
||||
floatx80 floatx80_add( floatx80, floatx80 );
|
||||
floatx80 floatx80_sub( floatx80, floatx80 );
|
||||
floatx80 floatx80_mul( floatx80, floatx80 );
|
||||
floatx80 floatx80_div( floatx80, floatx80 );
|
||||
floatx80 floatx80_rem( floatx80, floatx80 );
|
||||
floatx80 floatx80_sqrt( floatx80 );
|
||||
flag floatx80_eq( floatx80, floatx80 );
|
||||
flag floatx80_le( floatx80, floatx80 );
|
||||
flag floatx80_lt( floatx80, floatx80 );
|
||||
flag floatx80_eq_signaling( floatx80, floatx80 );
|
||||
flag floatx80_le_quiet( floatx80, floatx80 );
|
||||
flag floatx80_lt_quiet( floatx80, floatx80 );
|
||||
flag floatx80_is_signaling_nan( floatx80 );
|
||||
floatx80 floatx80_round_to_int(floatx80, float_status *status);
|
||||
floatx80 floatx80_add(floatx80, floatx80, float_status *status);
|
||||
floatx80 floatx80_sub(floatx80, floatx80, float_status *status);
|
||||
floatx80 floatx80_mul(floatx80, floatx80, float_status *status);
|
||||
floatx80 floatx80_div(floatx80, floatx80, float_status *status);
|
||||
floatx80 floatx80_sqrt(floatx80, float_status *status);
|
||||
floatx80 floatx80_normalize(floatx80);
|
||||
floatx80 floatx80_denormalize(floatx80, flag);
|
||||
|
||||
int floatx80_fsin(floatx80 *a);
|
||||
int floatx80_fcos(floatx80 *a);
|
||||
int floatx80_ftan(floatx80 *a);
|
||||
|
||||
floatx80 floatx80_flognp1(floatx80 a);
|
||||
floatx80 floatx80_flogn(floatx80 a);
|
||||
floatx80 floatx80_flog2(floatx80 a);
|
||||
floatx80 floatx80_flog10(floatx80 a);
|
||||
|
||||
// roundAndPackFloatx80 used to be in softfloat-round-pack, is now in softfloat.c
|
||||
floatx80 roundAndPackFloatx80(int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FLOAT128
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE quadruple-precision conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
int32 float128_to_int32( float128 );
|
||||
int32 float128_to_int32_round_to_zero( float128 );
|
||||
int64 float128_to_int64( float128 );
|
||||
int64 float128_to_int64_round_to_zero( float128 );
|
||||
float32 float128_to_float32( float128 );
|
||||
float64 float128_to_float64( float128 );
|
||||
#ifdef FLOATX80
|
||||
floatx80 float128_to_floatx80( float128 );
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE quadruple-precision operations.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float128 float128_round_to_int( float128 );
|
||||
float128 float128_add( float128, float128 );
|
||||
float128 float128_sub( float128, float128 );
|
||||
float128 float128_mul( float128, float128 );
|
||||
float128 float128_div( float128, float128 );
|
||||
float128 float128_rem( float128, float128 );
|
||||
float128 float128_sqrt( float128 );
|
||||
flag float128_eq( float128, float128 );
|
||||
flag float128_le( float128, float128 );
|
||||
flag float128_lt( float128, float128 );
|
||||
flag float128_eq_signaling( float128, float128 );
|
||||
flag float128_le_quiet( float128, float128 );
|
||||
flag float128_lt_quiet( float128, float128 );
|
||||
flag float128_is_signaling_nan( 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.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline float128
|
||||
packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 )
|
||||
static inline int floatx80_is_zero_or_denormal(floatx80 a)
|
||||
{
|
||||
float128 z;
|
||||
|
||||
z.low = zSig1;
|
||||
z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0;
|
||||
return z;
|
||||
return (a.high & 0x7fff) == 0;
|
||||
}
|
||||
|
||||
static inline int floatx80_is_any_nan(floatx80 a)
|
||||
{
|
||||
return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
|
||||
| and extended significand formed by the concatenation of `zSig0', `zSig1',
|
||||
| and `zSig2', and returns the proper quadruple-precision floating-point value
|
||||
| corresponding to the abstract input. Ordinarily, the abstract value is
|
||||
| simply rounded and packed into the quadruple-precision format, with the
|
||||
| inexact exception raised if the abstract input cannot be represented
|
||||
| exactly. However, if the abstract value is too large, the overflow and
|
||||
| inexact exceptions are raised and an infinity or maximal finite value is
|
||||
| returned. If the abstract value is too small, the input value is rounded to
|
||||
| a subnormal number, and the underflow and inexact exceptions are raised if
|
||||
| the abstract input cannot be represented exactly as a subnormal quadruple-
|
||||
| precision floating-point number.
|
||||
| The input significand must be normalized or smaller. If the input
|
||||
| significand is not normalized, `zExp' must be 0; in that case, the result
|
||||
| returned is a subnormal number, and it must not require rounding. In the
|
||||
| usual case that the input significand is normalized, `zExp' must be 1 less
|
||||
| than the ``true'' floating-point exponent. The handling of underflow and
|
||||
| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
|
||||
| Return whether the given value is an invalid floatx80 encoding.
|
||||
| Invalid floatx80 encodings arise when the integer bit is not set, but
|
||||
| the exponent is not zero. The only times the integer bit is permitted to
|
||||
| be zero is in subnormal numbers and the value zero.
|
||||
| This includes what the Intel software developer's manual calls pseudo-NaNs,
|
||||
| pseudo-infinities and un-normal numbers. It does not include
|
||||
| pseudo-denormals, which must still be correctly handled as inputs even
|
||||
| if they are never generated as outputs.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline float128
|
||||
roundAndPackFloat128(
|
||||
flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 )
|
||||
static inline bool floatx80_invalid_encoding(floatx80 a)
|
||||
{
|
||||
int8 roundingMode;
|
||||
flag roundNearestEven, increment, isTiny;
|
||||
|
||||
roundingMode = float_rounding_mode;
|
||||
roundNearestEven = ( roundingMode == float_round_nearest_even );
|
||||
increment = ( (sbits64) zSig2 < 0 );
|
||||
if ( ! roundNearestEven ) {
|
||||
if ( roundingMode == float_round_to_zero ) {
|
||||
increment = 0;
|
||||
}
|
||||
else {
|
||||
if ( zSign ) {
|
||||
increment = ( roundingMode == float_round_down ) && zSig2;
|
||||
}
|
||||
else {
|
||||
increment = ( roundingMode == float_round_up ) && zSig2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( 0x7FFD <= (bits32) zExp ) {
|
||||
if ( ( 0x7FFD < zExp )
|
||||
|| ( ( zExp == 0x7FFD )
|
||||
&& eq128(
|
||||
LIT64( 0x0001FFFFFFFFFFFF ),
|
||||
LIT64( 0xFFFFFFFFFFFFFFFF ),
|
||||
zSig0,
|
||||
zSig1
|
||||
)
|
||||
&& increment
|
||||
)
|
||||
) {
|
||||
float_raise( float_flag_overflow | float_flag_inexact );
|
||||
if ( ( roundingMode == float_round_to_zero )
|
||||
|| ( zSign && ( roundingMode == float_round_up ) )
|
||||
|| ( ! zSign && ( roundingMode == float_round_down ) )
|
||||
) {
|
||||
return
|
||||
packFloat128(
|
||||
zSign,
|
||||
0x7FFE,
|
||||
LIT64( 0x0000FFFFFFFFFFFF ),
|
||||
LIT64( 0xFFFFFFFFFFFFFFFF )
|
||||
);
|
||||
}
|
||||
return packFloat128( zSign, 0x7FFF, 0, 0 );
|
||||
}
|
||||
if ( zExp < 0 ) {
|
||||
isTiny =
|
||||
( float_detect_tininess == float_tininess_before_rounding )
|
||||
|| ( zExp < -1 )
|
||||
|| ! increment
|
||||
|| lt128(
|
||||
zSig0,
|
||||
zSig1,
|
||||
LIT64( 0x0001FFFFFFFFFFFF ),
|
||||
LIT64( 0xFFFFFFFFFFFFFFFF )
|
||||
);
|
||||
shift128ExtraRightJamming(
|
||||
zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 );
|
||||
zExp = 0;
|
||||
if ( isTiny && zSig2 ) float_raise( float_flag_underflow );
|
||||
if ( roundNearestEven ) {
|
||||
increment = ( (sbits64) zSig2 < 0 );
|
||||
}
|
||||
else {
|
||||
if ( zSign ) {
|
||||
increment = ( roundingMode == float_round_down ) && zSig2;
|
||||
}
|
||||
else {
|
||||
increment = ( roundingMode == float_round_up ) && zSig2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( zSig2 ) float_exception_flags |= float_flag_inexact;
|
||||
if ( increment ) {
|
||||
add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 );
|
||||
zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven );
|
||||
}
|
||||
else {
|
||||
if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0;
|
||||
}
|
||||
return packFloat128( zSign, zExp, zSig0, zSig1 );
|
||||
|
||||
return (a.low & (1ULL << 63)) == 0 && (a.high & 0x7FFF) != 0 && (a.high & 0x7FFF) != 0x7FFF;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
|
||||
| and significand formed by the concatenation of `zSig0' and `zSig1', and
|
||||
| returns the proper quadruple-precision floating-point value corresponding
|
||||
| to the abstract input. This routine is just like `roundAndPackFloat128'
|
||||
| except that the input significand has fewer bits and does not have to be
|
||||
| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
|
||||
| point exponent.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
|
||||
#define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL)
|
||||
#define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL)
|
||||
#define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL)
|
||||
#define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL)
|
||||
#define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)
|
||||
|
||||
static inline float128
|
||||
normalizeRoundAndPackFloat128(
|
||||
flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 )
|
||||
{
|
||||
int8 shiftCount;
|
||||
bits64 zSig2;
|
||||
|
||||
if ( zSig0 == 0 ) {
|
||||
zSig0 = zSig1;
|
||||
zSig1 = 0;
|
||||
zExp -= 64;
|
||||
}
|
||||
shiftCount = countLeadingZeros64( zSig0 ) - 15;
|
||||
if ( 0 <= shiftCount ) {
|
||||
zSig2 = 0;
|
||||
shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
|
||||
}
|
||||
else {
|
||||
shift128ExtraRightJamming(
|
||||
zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 );
|
||||
}
|
||||
zExp -= shiftCount;
|
||||
return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif /* SOFTFLOAT_H */
|
||||
|
||||
2154
softfloat/softfloat_fpsp.c
Normal file
2154
softfloat/softfloat_fpsp.c
Normal file
File diff suppressed because it is too large
Load Diff
528
softfloat/softfloat_fpsp_tables.h
Normal file
528
softfloat/softfloat_fpsp_tables.h
Normal file
@@ -0,0 +1,528 @@
|
||||
|
||||
static const floatx80 atan_tbl[128] = {
|
||||
{0x3FFB, LIT64(0x83D152C5060B7A51)},
|
||||
{0x3FFB, LIT64(0x8BC8544565498B8B)},
|
||||
{0x3FFB, LIT64(0x93BE406017626B0D)},
|
||||
{0x3FFB, LIT64(0x9BB3078D35AEC202)},
|
||||
{0x3FFB, LIT64(0xA3A69A525DDCE7DE)},
|
||||
{0x3FFB, LIT64(0xAB98E94362765619)},
|
||||
{0x3FFB, LIT64(0xB389E502F9C59862)},
|
||||
{0x3FFB, LIT64(0xBB797E436B09E6FB)},
|
||||
{0x3FFB, LIT64(0xC367A5C739E5F446)},
|
||||
{0x3FFB, LIT64(0xCB544C61CFF7D5C6)},
|
||||
{0x3FFB, LIT64(0xD33F62F82488533E)},
|
||||
{0x3FFB, LIT64(0xDB28DA8162404C77)},
|
||||
{0x3FFB, LIT64(0xE310A4078AD34F18)},
|
||||
{0x3FFB, LIT64(0xEAF6B0A8188EE1EB)},
|
||||
{0x3FFB, LIT64(0xF2DAF1949DBE79D5)},
|
||||
{0x3FFB, LIT64(0xFABD581361D47E3E)},
|
||||
{0x3FFC, LIT64(0x8346AC210959ECC4)},
|
||||
{0x3FFC, LIT64(0x8B232A08304282D8)},
|
||||
{0x3FFC, LIT64(0x92FB70B8D29AE2F9)},
|
||||
{0x3FFC, LIT64(0x9ACF476F5CCD1CB4)},
|
||||
{0x3FFC, LIT64(0xA29E76304954F23F)},
|
||||
{0x3FFC, LIT64(0xAA68C5D08AB85230)},
|
||||
{0x3FFC, LIT64(0xB22DFFFD9D539F83)},
|
||||
{0x3FFC, LIT64(0xB9EDEF453E900EA5)},
|
||||
{0x3FFC, LIT64(0xC1A85F1CC75E3EA5)},
|
||||
{0x3FFC, LIT64(0xC95D1BE828138DE6)},
|
||||
{0x3FFC, LIT64(0xD10BF300840D2DE4)},
|
||||
{0x3FFC, LIT64(0xD8B4B2BA6BC05E7A)},
|
||||
{0x3FFC, LIT64(0xE0572A6BB42335F6)},
|
||||
{0x3FFC, LIT64(0xE7F32A70EA9CAA8F)},
|
||||
{0x3FFC, LIT64(0xEF88843264ECEFAA)},
|
||||
{0x3FFC, LIT64(0xF7170A28ECC06666)},
|
||||
{0x3FFD, LIT64(0x812FD288332DAD32)},
|
||||
{0x3FFD, LIT64(0x88A8D1B1218E4D64)},
|
||||
{0x3FFD, LIT64(0x9012AB3F23E4AEE8)},
|
||||
{0x3FFD, LIT64(0x976CC3D411E7F1B9)},
|
||||
{0x3FFD, LIT64(0x9EB689493889A227)},
|
||||
{0x3FFD, LIT64(0xA5EF72C34487361B)},
|
||||
{0x3FFD, LIT64(0xAD1700BAF07A7227)},
|
||||
{0x3FFD, LIT64(0xB42CBCFAFD37EFB7)},
|
||||
{0x3FFD, LIT64(0xBB303A940BA80F89)},
|
||||
{0x3FFD, LIT64(0xC22115C6FCAEBBAF)},
|
||||
{0x3FFD, LIT64(0xC8FEF3E686331221)},
|
||||
{0x3FFD, LIT64(0xCFC98330B4000C70)},
|
||||
{0x3FFD, LIT64(0xD6807AA1102C5BF9)},
|
||||
{0x3FFD, LIT64(0xDD2399BC31252AA3)},
|
||||
{0x3FFD, LIT64(0xE3B2A8556B8FC517)},
|
||||
{0x3FFD, LIT64(0xEA2D764F64315989)},
|
||||
{0x3FFD, LIT64(0xF3BF5BF8BAD1A21D)},
|
||||
{0x3FFE, LIT64(0x801CE39E0D205C9A)},
|
||||
{0x3FFE, LIT64(0x8630A2DADA1ED066)},
|
||||
{0x3FFE, LIT64(0x8C1AD445F3E09B8C)},
|
||||
{0x3FFE, LIT64(0x91DB8F1664F350E2)},
|
||||
{0x3FFE, LIT64(0x97731420365E538C)},
|
||||
{0x3FFE, LIT64(0x9CE1C8E6A0B8CDBA)},
|
||||
{0x3FFE, LIT64(0xA22832DBCADAAE09)},
|
||||
{0x3FFE, LIT64(0xA746F2DDB7602294)},
|
||||
{0x3FFE, LIT64(0xAC3EC0FB997DD6A2)},
|
||||
{0x3FFE, LIT64(0xB110688AEBDC6F6A)},
|
||||
{0x3FFE, LIT64(0xB5BCC49059ECC4B0)},
|
||||
{0x3FFE, LIT64(0xBA44BC7DD470782F)},
|
||||
{0x3FFE, LIT64(0xBEA94144FD049AAC)},
|
||||
{0x3FFE, LIT64(0xC2EB4ABB661628B6)},
|
||||
{0x3FFE, LIT64(0xC70BD54CE602EE14)},
|
||||
{0x3FFE, LIT64(0xCD000549ADEC7159)},
|
||||
{0x3FFE, LIT64(0xD48457D2D8EA4EA3)},
|
||||
{0x3FFE, LIT64(0xDB948DA712DECE3B)},
|
||||
{0x3FFE, LIT64(0xE23855F969E8096A)},
|
||||
{0x3FFE, LIT64(0xE8771129C4353259)},
|
||||
{0x3FFE, LIT64(0xEE57C16E0D379C0D)},
|
||||
{0x3FFE, LIT64(0xF3E10211A87C3779)},
|
||||
{0x3FFE, LIT64(0xF919039D758B8D41)},
|
||||
{0x3FFE, LIT64(0xFE058B8F64935FB3)},
|
||||
{0x3FFF, LIT64(0x8155FB497B685D04)},
|
||||
{0x3FFF, LIT64(0x83889E3549D108E1)},
|
||||
{0x3FFF, LIT64(0x859CFA76511D724B)},
|
||||
{0x3FFF, LIT64(0x87952ECFFF8131E7)},
|
||||
{0x3FFF, LIT64(0x89732FD19557641B)},
|
||||
{0x3FFF, LIT64(0x8B38CAD101932A35)},
|
||||
{0x3FFF, LIT64(0x8CE7A8D8301EE6B5)},
|
||||
{0x3FFF, LIT64(0x8F46A39E2EAE5281)},
|
||||
{0x3FFF, LIT64(0x922DA7D791888487)},
|
||||
{0x3FFF, LIT64(0x94D19FCBDEDF5241)},
|
||||
{0x3FFF, LIT64(0x973AB94419D2A08B)},
|
||||
{0x3FFF, LIT64(0x996FF00E08E10B96)},
|
||||
{0x3FFF, LIT64(0x9B773F9512321DA7)},
|
||||
{0x3FFF, LIT64(0x9D55CC320F935624)},
|
||||
{0x3FFF, LIT64(0x9F100575006CC571)},
|
||||
{0x3FFF, LIT64(0xA0A9C290D97CC06C)},
|
||||
{0x3FFF, LIT64(0xA22659EBEBC0630A)},
|
||||
{0x3FFF, LIT64(0xA388B4AFF6EF0EC9)},
|
||||
{0x3FFF, LIT64(0xA4D35F1061D292C4)},
|
||||
{0x3FFF, LIT64(0xA60895DCFBE3187E)},
|
||||
{0x3FFF, LIT64(0xA72A51DC7367BEAC)},
|
||||
{0x3FFF, LIT64(0xA83A51530956168F)},
|
||||
{0x3FFF, LIT64(0xA93A20077539546E)},
|
||||
{0x3FFF, LIT64(0xAA9E7245023B2605)},
|
||||
{0x3FFF, LIT64(0xAC4C84BA6FE4D58F)},
|
||||
{0x3FFF, LIT64(0xADCE4A4A606B9712)},
|
||||
{0x3FFF, LIT64(0xAF2A2DCD8D263C9C)},
|
||||
{0x3FFF, LIT64(0xB0656F81F22265C7)},
|
||||
{0x3FFF, LIT64(0xB18465150F71496A)},
|
||||
{0x3FFF, LIT64(0xB28AAA156F9ADA35)},
|
||||
{0x3FFF, LIT64(0xB37B44FF3766B895)},
|
||||
{0x3FFF, LIT64(0xB458C3DCE9630433)},
|
||||
{0x3FFF, LIT64(0xB525529D562246BD)},
|
||||
{0x3FFF, LIT64(0xB5E2CCA95F9D88CC)},
|
||||
{0x3FFF, LIT64(0xB692CADA7ACA1ADA)},
|
||||
{0x3FFF, LIT64(0xB736AEA7A6925838)},
|
||||
{0x3FFF, LIT64(0xB7CFAB287E9F7B36)},
|
||||
{0x3FFF, LIT64(0xB85ECC66CB219835)},
|
||||
{0x3FFF, LIT64(0xB8E4FD5A20A593DA)},
|
||||
{0x3FFF, LIT64(0xB99F41F64AFF9BB5)},
|
||||
{0x3FFF, LIT64(0xBA7F1E17842BBE7B)},
|
||||
{0x3FFF, LIT64(0xBB4712857637E17D)},
|
||||
{0x3FFF, LIT64(0xBBFABE8A4788DF6F)},
|
||||
{0x3FFF, LIT64(0xBC9D0FAD2B689D79)},
|
||||
{0x3FFF, LIT64(0xBD306A39471ECD86)},
|
||||
{0x3FFF, LIT64(0xBDB6C731856AF18A)},
|
||||
{0x3FFF, LIT64(0xBE31CAC502E80D70)},
|
||||
{0x3FFF, LIT64(0xBEA2D55CE33194E2)},
|
||||
{0x3FFF, LIT64(0xBF0B10B7C03128F0)},
|
||||
{0x3FFF, LIT64(0xBF6B7A18DACB778D)},
|
||||
{0x3FFF, LIT64(0xBFC4EA4663FA18F6)},
|
||||
{0x3FFF, LIT64(0xC0181BDE8B89A454)},
|
||||
{0x3FFF, LIT64(0xC065B066CFBF6439)},
|
||||
{0x3FFF, LIT64(0xC0AE345F56340AE6)},
|
||||
{0x3FFF, LIT64(0xC0F222919CB9E6A7)}
|
||||
};
|
||||
|
||||
|
||||
static const floatx80 exp_tbl[64] = {
|
||||
{0x3FFF, LIT64(0x8000000000000000)},
|
||||
{0x3FFF, LIT64(0x8164D1F3BC030774)},
|
||||
{0x3FFF, LIT64(0x82CD8698AC2BA1D8)},
|
||||
{0x3FFF, LIT64(0x843A28C3ACDE4048)},
|
||||
{0x3FFF, LIT64(0x85AAC367CC487B14)},
|
||||
{0x3FFF, LIT64(0x871F61969E8D1010)},
|
||||
{0x3FFF, LIT64(0x88980E8092DA8528)},
|
||||
{0x3FFF, LIT64(0x8A14D575496EFD9C)},
|
||||
{0x3FFF, LIT64(0x8B95C1E3EA8BD6E8)},
|
||||
{0x3FFF, LIT64(0x8D1ADF5B7E5BA9E4)},
|
||||
{0x3FFF, LIT64(0x8EA4398B45CD53C0)},
|
||||
{0x3FFF, LIT64(0x9031DC431466B1DC)},
|
||||
{0x3FFF, LIT64(0x91C3D373AB11C338)},
|
||||
{0x3FFF, LIT64(0x935A2B2F13E6E92C)},
|
||||
{0x3FFF, LIT64(0x94F4EFA8FEF70960)},
|
||||
{0x3FFF, LIT64(0x96942D3720185A00)},
|
||||
{0x3FFF, LIT64(0x9837F0518DB8A970)},
|
||||
{0x3FFF, LIT64(0x99E0459320B7FA64)},
|
||||
{0x3FFF, LIT64(0x9B8D39B9D54E5538)},
|
||||
{0x3FFF, LIT64(0x9D3ED9A72CFFB750)},
|
||||
{0x3FFF, LIT64(0x9EF5326091A111AC)},
|
||||
{0x3FFF, LIT64(0xA0B0510FB9714FC4)},
|
||||
{0x3FFF, LIT64(0xA27043030C496818)},
|
||||
{0x3FFF, LIT64(0xA43515AE09E680A0)},
|
||||
{0x3FFF, LIT64(0xA5FED6A9B15138EC)},
|
||||
{0x3FFF, LIT64(0xA7CD93B4E9653568)},
|
||||
{0x3FFF, LIT64(0xA9A15AB4EA7C0EF8)},
|
||||
{0x3FFF, LIT64(0xAB7A39B5A93ED338)},
|
||||
{0x3FFF, LIT64(0xAD583EEA42A14AC8)},
|
||||
{0x3FFF, LIT64(0xAF3B78AD690A4374)},
|
||||
{0x3FFF, LIT64(0xB123F581D2AC2590)},
|
||||
{0x3FFF, LIT64(0xB311C412A9112488)},
|
||||
{0x3FFF, LIT64(0xB504F333F9DE6484)},
|
||||
{0x3FFF, LIT64(0xB6FD91E328D17790)},
|
||||
{0x3FFF, LIT64(0xB8FBAF4762FB9EE8)},
|
||||
{0x3FFF, LIT64(0xBAFF5AB2133E45FC)},
|
||||
{0x3FFF, LIT64(0xBD08A39F580C36C0)},
|
||||
{0x3FFF, LIT64(0xBF1799B67A731084)},
|
||||
{0x3FFF, LIT64(0xC12C4CCA66709458)},
|
||||
{0x3FFF, LIT64(0xC346CCDA24976408)},
|
||||
{0x3FFF, LIT64(0xC5672A115506DADC)},
|
||||
{0x3FFF, LIT64(0xC78D74C8ABB9B15C)},
|
||||
{0x3FFF, LIT64(0xC9B9BD866E2F27A4)},
|
||||
{0x3FFF, LIT64(0xCBEC14FEF2727C5C)},
|
||||
{0x3FFF, LIT64(0xCE248C151F8480E4)},
|
||||
{0x3FFF, LIT64(0xD06333DAEF2B2594)},
|
||||
{0x3FFF, LIT64(0xD2A81D91F12AE45C)},
|
||||
{0x3FFF, LIT64(0xD4F35AABCFEDFA20)},
|
||||
{0x3FFF, LIT64(0xD744FCCAD69D6AF4)},
|
||||
{0x3FFF, LIT64(0xD99D15C278AFD7B4)},
|
||||
{0x3FFF, LIT64(0xDBFBB797DAF23754)},
|
||||
{0x3FFF, LIT64(0xDE60F4825E0E9124)},
|
||||
{0x3FFF, LIT64(0xE0CCDEEC2A94E110)},
|
||||
{0x3FFF, LIT64(0xE33F8972BE8A5A50)},
|
||||
{0x3FFF, LIT64(0xE5B906E77C8348A8)},
|
||||
{0x3FFF, LIT64(0xE8396A503C4BDC68)},
|
||||
{0x3FFF, LIT64(0xEAC0C6E7DD243930)},
|
||||
{0x3FFF, LIT64(0xED4F301ED9942B84)},
|
||||
{0x3FFF, LIT64(0xEFE4B99BDCDAF5CC)},
|
||||
{0x3FFF, LIT64(0xF281773C59FFB138)},
|
||||
{0x3FFF, LIT64(0xF5257D152486CC2C)},
|
||||
{0x3FFF, LIT64(0xF7D0DF730AD13BB8)},
|
||||
{0x3FFF, LIT64(0xFA83B2DB722A033C)},
|
||||
{0x3FFF, LIT64(0xFD3E0C0CF486C174)}
|
||||
};
|
||||
|
||||
static const float32 exp_tbl2[64] = {
|
||||
0x00000000, 0x9F841A9B, 0x9FC1D5B9, 0xA0728369,
|
||||
0x1FC5C95C, 0x1EE85C9F, 0x9FA20729, 0xA07BF9AF,
|
||||
0xA0020DCF, 0x205A63DA, 0x1EB70051, 0x1F6EB029,
|
||||
0xA0781494, 0x9EB319B0, 0x2017457D, 0x1F11D537,
|
||||
0x9FB952DD, 0x1FE43087, 0x1FA2A818, 0x1FDE494D,
|
||||
0x20504890, 0xA073691C, 0x1F9B7A05, 0xA0797126,
|
||||
0xA071A140, 0x204F62DA, 0x1F283C4A, 0x9F9A7FDC,
|
||||
0xA05B3FAC, 0x1FDF2610, 0x9F705F90, 0x201F678A,
|
||||
0x1F32FB13, 0x20038B30, 0x200DC3CC, 0x9F8B2AE6,
|
||||
0xA02BBF70, 0xA00BF518, 0xA041DD41, 0x9FDF137B,
|
||||
0x201F1568, 0x1FC13A2E, 0xA03F8F03, 0x1FF4907D,
|
||||
0x9E6E53E4, 0x1FD6D45C, 0xA076EDB9, 0x9FA6DE21,
|
||||
0x1EE69A2F, 0x207F439F, 0x201EC207, 0x9E8BE175,
|
||||
0x20032C4B, 0x2004DFF5, 0x1E72F47A, 0x1F722F22,
|
||||
0xA017E945, 0x1F401A5B, 0x9FB9A9E3, 0x20744C05,
|
||||
0x1F773A19, 0x1FFE90D5, 0xA041ED22, 0x1F853F3A
|
||||
};
|
||||
|
||||
|
||||
static const floatx80 exp2_tbl[64] = {
|
||||
{0x3FFF, LIT64(0x8000000000000000)},
|
||||
{0x3FFF, LIT64(0x8164D1F3BC030773)},
|
||||
{0x3FFF, LIT64(0x82CD8698AC2BA1D7)},
|
||||
{0x3FFF, LIT64(0x843A28C3ACDE4046)},
|
||||
{0x3FFF, LIT64(0x85AAC367CC487B15)},
|
||||
{0x3FFF, LIT64(0x871F61969E8D1010)},
|
||||
{0x3FFF, LIT64(0x88980E8092DA8527)},
|
||||
{0x3FFF, LIT64(0x8A14D575496EFD9A)},
|
||||
{0x3FFF, LIT64(0x8B95C1E3EA8BD6E7)},
|
||||
{0x3FFF, LIT64(0x8D1ADF5B7E5BA9E6)},
|
||||
{0x3FFF, LIT64(0x8EA4398B45CD53C0)},
|
||||
{0x3FFF, LIT64(0x9031DC431466B1DC)},
|
||||
{0x3FFF, LIT64(0x91C3D373AB11C336)},
|
||||
{0x3FFF, LIT64(0x935A2B2F13E6E92C)},
|
||||
{0x3FFF, LIT64(0x94F4EFA8FEF70961)},
|
||||
{0x3FFF, LIT64(0x96942D3720185A00)},
|
||||
{0x3FFF, LIT64(0x9837F0518DB8A96F)},
|
||||
{0x3FFF, LIT64(0x99E0459320B7FA65)},
|
||||
{0x3FFF, LIT64(0x9B8D39B9D54E5539)},
|
||||
{0x3FFF, LIT64(0x9D3ED9A72CFFB751)},
|
||||
{0x3FFF, LIT64(0x9EF5326091A111AE)},
|
||||
{0x3FFF, LIT64(0xA0B0510FB9714FC2)},
|
||||
{0x3FFF, LIT64(0xA27043030C496819)},
|
||||
{0x3FFF, LIT64(0xA43515AE09E6809E)},
|
||||
{0x3FFF, LIT64(0xA5FED6A9B15138EA)},
|
||||
{0x3FFF, LIT64(0xA7CD93B4E965356A)},
|
||||
{0x3FFF, LIT64(0xA9A15AB4EA7C0EF8)},
|
||||
{0x3FFF, LIT64(0xAB7A39B5A93ED337)},
|
||||
{0x3FFF, LIT64(0xAD583EEA42A14AC6)},
|
||||
{0x3FFF, LIT64(0xAF3B78AD690A4375)},
|
||||
{0x3FFF, LIT64(0xB123F581D2AC2590)},
|
||||
{0x3FFF, LIT64(0xB311C412A9112489)},
|
||||
{0x3FFF, LIT64(0xB504F333F9DE6484)},
|
||||
{0x3FFF, LIT64(0xB6FD91E328D17791)},
|
||||
{0x3FFF, LIT64(0xB8FBAF4762FB9EE9)},
|
||||
{0x3FFF, LIT64(0xBAFF5AB2133E45FB)},
|
||||
{0x3FFF, LIT64(0xBD08A39F580C36BF)},
|
||||
{0x3FFF, LIT64(0xBF1799B67A731083)},
|
||||
{0x3FFF, LIT64(0xC12C4CCA66709456)},
|
||||
{0x3FFF, LIT64(0xC346CCDA24976407)},
|
||||
{0x3FFF, LIT64(0xC5672A115506DADD)},
|
||||
{0x3FFF, LIT64(0xC78D74C8ABB9B15D)},
|
||||
{0x3FFF, LIT64(0xC9B9BD866E2F27A3)},
|
||||
{0x3FFF, LIT64(0xCBEC14FEF2727C5D)},
|
||||
{0x3FFF, LIT64(0xCE248C151F8480E4)},
|
||||
{0x3FFF, LIT64(0xD06333DAEF2B2595)},
|
||||
{0x3FFF, LIT64(0xD2A81D91F12AE45A)},
|
||||
{0x3FFF, LIT64(0xD4F35AABCFEDFA1F)},
|
||||
{0x3FFF, LIT64(0xD744FCCAD69D6AF4)},
|
||||
{0x3FFF, LIT64(0xD99D15C278AFD7B6)},
|
||||
{0x3FFF, LIT64(0xDBFBB797DAF23755)},
|
||||
{0x3FFF, LIT64(0xDE60F4825E0E9124)},
|
||||
{0x3FFF, LIT64(0xE0CCDEEC2A94E111)},
|
||||
{0x3FFF, LIT64(0xE33F8972BE8A5A51)},
|
||||
{0x3FFF, LIT64(0xE5B906E77C8348A8)},
|
||||
{0x3FFF, LIT64(0xE8396A503C4BDC68)},
|
||||
{0x3FFF, LIT64(0xEAC0C6E7DD24392F)},
|
||||
{0x3FFF, LIT64(0xED4F301ED9942B84)},
|
||||
{0x3FFF, LIT64(0xEFE4B99BDCDAF5CB)},
|
||||
{0x3FFF, LIT64(0xF281773C59FFB13A)},
|
||||
{0x3FFF, LIT64(0xF5257D152486CC2C)},
|
||||
{0x3FFF, LIT64(0xF7D0DF730AD13BB9)},
|
||||
{0x3FFF, LIT64(0xFA83B2DB722A033A)},
|
||||
{0x3FFF, LIT64(0xFD3E0C0CF486C175)}
|
||||
};
|
||||
|
||||
|
||||
static const float32 exp2_tbl2[64] = {
|
||||
0x3F738000, 0x3FBEF7CA, 0x3FBDF8A9, 0x3FBCD7C9,
|
||||
0xBFBDE8DA, 0x3FBDE85C, 0x3FBEBBF1, 0x3FBB80CA,
|
||||
0xBFBA8373, 0xBFBE9670, 0x3FBDB700, 0x3FBEEEB0,
|
||||
0x3FBBFD6D, 0xBFBDB319, 0x3FBDBA2B, 0x3FBE91D5,
|
||||
0x3FBE8D5A, 0xBFBCDE7B, 0xBFBEBAAF, 0xBFBD86DA,
|
||||
0xBFBEBEDD, 0x3FBCC96E, 0xBFBEC90B, 0x3FBBD1DB,
|
||||
0x3FBCE5EB, 0xBFBEC274, 0x3FBEA83C, 0x3FBECB00,
|
||||
0x3FBE9301, 0xBFBD8367, 0xBFBEF05F, 0x3FBDFB3C,
|
||||
0x3FBEB2FB, 0x3FBAE2CB, 0x3FBCDC3C, 0x3FBEE9AA,
|
||||
0xBFBEAEFD, 0xBFBCBF51, 0x3FBEF88A, 0x3FBD83B2,
|
||||
0x3FBDF8AB, 0xBFBDFB17, 0xBFBEFE3C, 0xBFBBB6F8,
|
||||
0xBFBCEE53, 0xBFBDA4AE, 0x3FBC9124, 0x3FBEB243,
|
||||
0x3FBDE69A, 0xBFB8BC61, 0x3FBDF610, 0xBFBD8BE1,
|
||||
0x3FBACB12, 0x3FBB9BFE, 0x3FBCF2F4, 0x3FBEF22F,
|
||||
0xBFBDBF4A, 0x3FBEC01A, 0x3FBE8CAC, 0xBFBCBB3F,
|
||||
0x3FBEF73A, 0xBFB8B795, 0x3FBEF84B, 0xBFBEF581
|
||||
};
|
||||
|
||||
|
||||
static const floatx80 log_tbl[128] = {
|
||||
{0x3FFE, LIT64(0xFE03F80FE03F80FE)},
|
||||
{0x3FF7, LIT64(0xFF015358833C47E2)},
|
||||
{0x3FFE, LIT64(0xFA232CF252138AC0)},
|
||||
{0x3FF9, LIT64(0xBDC8D83EAD88D549)},
|
||||
{0x3FFE, LIT64(0xF6603D980F6603DA)},
|
||||
{0x3FFA, LIT64(0x9CF43DCFF5EAFD48)},
|
||||
{0x3FFE, LIT64(0xF2B9D6480F2B9D65)},
|
||||
{0x3FFA, LIT64(0xDA16EB88CB8DF614)},
|
||||
{0x3FFE, LIT64(0xEF2EB71FC4345238)},
|
||||
{0x3FFB, LIT64(0x8B29B7751BD70743)},
|
||||
{0x3FFE, LIT64(0xEBBDB2A5C1619C8C)},
|
||||
{0x3FFB, LIT64(0xA8D839F830C1FB49)},
|
||||
{0x3FFE, LIT64(0xE865AC7B7603A197)},
|
||||
{0x3FFB, LIT64(0xC61A2EB18CD907AD)},
|
||||
{0x3FFE, LIT64(0xE525982AF70C880E)},
|
||||
{0x3FFB, LIT64(0xE2F2A47ADE3A18AF)},
|
||||
{0x3FFE, LIT64(0xE1FC780E1FC780E2)},
|
||||
{0x3FFB, LIT64(0xFF64898EDF55D551)},
|
||||
{0x3FFE, LIT64(0xDEE95C4CA037BA57)},
|
||||
{0x3FFC, LIT64(0x8DB956A97B3D0148)},
|
||||
{0x3FFE, LIT64(0xDBEB61EED19C5958)},
|
||||
{0x3FFC, LIT64(0x9B8FE100F47BA1DE)},
|
||||
{0x3FFE, LIT64(0xD901B2036406C80E)},
|
||||
{0x3FFC, LIT64(0xA9372F1D0DA1BD17)},
|
||||
{0x3FFE, LIT64(0xD62B80D62B80D62C)},
|
||||
{0x3FFC, LIT64(0xB6B07F38CE90E46B)},
|
||||
{0x3FFE, LIT64(0xD3680D3680D3680D)},
|
||||
{0x3FFC, LIT64(0xC3FD032906488481)},
|
||||
{0x3FFE, LIT64(0xD0B69FCBD2580D0B)},
|
||||
{0x3FFC, LIT64(0xD11DE0FF15AB18CA)},
|
||||
{0x3FFE, LIT64(0xCE168A7725080CE1)},
|
||||
{0x3FFC, LIT64(0xDE1433A16C66B150)},
|
||||
{0x3FFE, LIT64(0xCB8727C065C393E0)},
|
||||
{0x3FFC, LIT64(0xEAE10B5A7DDC8ADD)},
|
||||
{0x3FFE, LIT64(0xC907DA4E871146AD)},
|
||||
{0x3FFC, LIT64(0xF7856E5EE2C9B291)},
|
||||
{0x3FFE, LIT64(0xC6980C6980C6980C)},
|
||||
{0x3FFD, LIT64(0x82012CA5A68206D7)},
|
||||
{0x3FFE, LIT64(0xC4372F855D824CA6)},
|
||||
{0x3FFD, LIT64(0x882C5FCD7256A8C5)},
|
||||
{0x3FFE, LIT64(0xC1E4BBD595F6E947)},
|
||||
{0x3FFD, LIT64(0x8E44C60B4CCFD7DE)},
|
||||
{0x3FFE, LIT64(0xBFA02FE80BFA02FF)},
|
||||
{0x3FFD, LIT64(0x944AD09EF4351AF6)},
|
||||
{0x3FFE, LIT64(0xBD69104707661AA3)},
|
||||
{0x3FFD, LIT64(0x9A3EECD4C3EAA6B2)},
|
||||
{0x3FFE, LIT64(0xBB3EE721A54D880C)},
|
||||
{0x3FFD, LIT64(0xA0218434353F1DE8)},
|
||||
{0x3FFE, LIT64(0xB92143FA36F5E02E)},
|
||||
{0x3FFD, LIT64(0xA5F2FCABBBC506DA)},
|
||||
{0x3FFE, LIT64(0xB70FBB5A19BE3659)},
|
||||
{0x3FFD, LIT64(0xABB3B8BA2AD362A5)},
|
||||
{0x3FFE, LIT64(0xB509E68A9B94821F)},
|
||||
{0x3FFD, LIT64(0xB1641795CE3CA97B)},
|
||||
{0x3FFE, LIT64(0xB30F63528917C80B)},
|
||||
{0x3FFD, LIT64(0xB70475515D0F1C61)},
|
||||
{0x3FFE, LIT64(0xB11FD3B80B11FD3C)},
|
||||
{0x3FFD, LIT64(0xBC952AFEEA3D13E1)},
|
||||
{0x3FFE, LIT64(0xAF3ADDC680AF3ADE)},
|
||||
{0x3FFD, LIT64(0xC2168ED0F458BA4A)},
|
||||
{0x3FFE, LIT64(0xAD602B580AD602B6)},
|
||||
{0x3FFD, LIT64(0xC788F439B3163BF1)},
|
||||
{0x3FFE, LIT64(0xAB8F69E28359CD11)},
|
||||
{0x3FFD, LIT64(0xCCECAC08BF04565D)},
|
||||
{0x3FFE, LIT64(0xA9C84A47A07F5638)},
|
||||
{0x3FFD, LIT64(0xD24204872DD85160)},
|
||||
{0x3FFE, LIT64(0xA80A80A80A80A80B)},
|
||||
{0x3FFD, LIT64(0xD78949923BC3588A)},
|
||||
{0x3FFE, LIT64(0xA655C4392D7B73A8)},
|
||||
{0x3FFD, LIT64(0xDCC2C4B49887DACC)},
|
||||
{0x3FFE, LIT64(0xA4A9CF1D96833751)},
|
||||
{0x3FFD, LIT64(0xE1EEBD3E6D6A6B9E)},
|
||||
{0x3FFE, LIT64(0xA3065E3FAE7CD0E0)},
|
||||
{0x3FFD, LIT64(0xE70D785C2F9F5BDC)},
|
||||
{0x3FFE, LIT64(0xA16B312EA8FC377D)},
|
||||
{0x3FFD, LIT64(0xEC1F392C5179F283)},
|
||||
{0x3FFE, LIT64(0x9FD809FD809FD80A)},
|
||||
{0x3FFD, LIT64(0xF12440D3E36130E6)},
|
||||
{0x3FFE, LIT64(0x9E4CAD23DD5F3A20)},
|
||||
{0x3FFD, LIT64(0xF61CCE92346600BB)},
|
||||
{0x3FFE, LIT64(0x9CC8E160C3FB19B9)},
|
||||
{0x3FFD, LIT64(0xFB091FD38145630A)},
|
||||
{0x3FFE, LIT64(0x9B4C6F9EF03A3CAA)},
|
||||
{0x3FFD, LIT64(0xFFE97042BFA4C2AD)},
|
||||
{0x3FFE, LIT64(0x99D722DABDE58F06)},
|
||||
{0x3FFE, LIT64(0x825EFCED49369330)},
|
||||
{0x3FFE, LIT64(0x9868C809868C8098)},
|
||||
{0x3FFE, LIT64(0x84C37A7AB9A905C9)},
|
||||
{0x3FFE, LIT64(0x97012E025C04B809)},
|
||||
{0x3FFE, LIT64(0x87224C2E8E645FB7)},
|
||||
{0x3FFE, LIT64(0x95A02568095A0257)},
|
||||
{0x3FFE, LIT64(0x897B8CAC9F7DE298)},
|
||||
{0x3FFE, LIT64(0x9445809445809446)},
|
||||
{0x3FFE, LIT64(0x8BCF55DEC4CD05FE)},
|
||||
{0x3FFE, LIT64(0x92F113840497889C)},
|
||||
{0x3FFE, LIT64(0x8E1DC0FB89E125E5)},
|
||||
{0x3FFE, LIT64(0x91A2B3C4D5E6F809)},
|
||||
{0x3FFE, LIT64(0x9066E68C955B6C9B)},
|
||||
{0x3FFE, LIT64(0x905A38633E06C43B)},
|
||||
{0x3FFE, LIT64(0x92AADE74C7BE59E0)},
|
||||
{0x3FFE, LIT64(0x8F1779D9FDC3A219)},
|
||||
{0x3FFE, LIT64(0x94E9BFF615845643)},
|
||||
{0x3FFE, LIT64(0x8DDA520237694809)},
|
||||
{0x3FFE, LIT64(0x9723A1B720134203)},
|
||||
{0x3FFE, LIT64(0x8CA29C046514E023)},
|
||||
{0x3FFE, LIT64(0x995899C890EB8990)},
|
||||
{0x3FFE, LIT64(0x8B70344A139BC75A)},
|
||||
{0x3FFE, LIT64(0x9B88BDAA3A3DAE2F)},
|
||||
{0x3FFE, LIT64(0x8A42F8705669DB46)},
|
||||
{0x3FFE, LIT64(0x9DB4224FFFE1157C)},
|
||||
{0x3FFE, LIT64(0x891AC73AE9819B50)},
|
||||
{0x3FFE, LIT64(0x9FDADC268B7A12DA)},
|
||||
{0x3FFE, LIT64(0x87F78087F78087F8)},
|
||||
{0x3FFE, LIT64(0xA1FCFF17CE733BD4)},
|
||||
{0x3FFE, LIT64(0x86D905447A34ACC6)},
|
||||
{0x3FFE, LIT64(0xA41A9E8F5446FB9F)},
|
||||
{0x3FFE, LIT64(0x85BF37612CEE3C9B)},
|
||||
{0x3FFE, LIT64(0xA633CD7E6771CD8B)},
|
||||
{0x3FFE, LIT64(0x84A9F9C8084A9F9D)},
|
||||
{0x3FFE, LIT64(0xA8489E600B435A5E)},
|
||||
{0x3FFE, LIT64(0x839930523FBE3368)},
|
||||
{0x3FFE, LIT64(0xAA59233CCCA4BD49)},
|
||||
{0x3FFE, LIT64(0x828CBFBEB9A020A3)},
|
||||
{0x3FFE, LIT64(0xAC656DAE6BCC4985)},
|
||||
{0x3FFE, LIT64(0x81848DA8FAF0D277)},
|
||||
{0x3FFE, LIT64(0xAE6D8EE360BB2468)},
|
||||
{0x3FFE, LIT64(0x8080808080808081)},
|
||||
{0x3FFE, LIT64(0xB07197A23C46C654)}
|
||||
};
|
||||
|
||||
|
||||
static const floatx80 pi_tbl[65] = {
|
||||
{0xC004, LIT64(0xC90FDAA22168C235)},
|
||||
{0xC004, LIT64(0xC2C75BCD105D7C23)},
|
||||
{0xC004, LIT64(0xBC7EDCF7FF523611)},
|
||||
{0xC004, LIT64(0xB6365E22EE46F000)},
|
||||
{0xC004, LIT64(0xAFEDDF4DDD3BA9EE)},
|
||||
{0xC004, LIT64(0xA9A56078CC3063DD)},
|
||||
{0xC004, LIT64(0xA35CE1A3BB251DCB)},
|
||||
{0xC004, LIT64(0x9D1462CEAA19D7B9)},
|
||||
{0xC004, LIT64(0x96CBE3F9990E91A8)},
|
||||
{0xC004, LIT64(0x9083652488034B96)},
|
||||
{0xC004, LIT64(0x8A3AE64F76F80584)},
|
||||
{0xC004, LIT64(0x83F2677A65ECBF73)},
|
||||
{0xC003, LIT64(0xFB53D14AA9C2F2C2)},
|
||||
{0xC003, LIT64(0xEEC2D3A087AC669F)},
|
||||
{0xC003, LIT64(0xE231D5F66595DA7B)},
|
||||
{0xC003, LIT64(0xD5A0D84C437F4E58)},
|
||||
{0xC003, LIT64(0xC90FDAA22168C235)},
|
||||
{0xC003, LIT64(0xBC7EDCF7FF523611)},
|
||||
{0xC003, LIT64(0xAFEDDF4DDD3BA9EE)},
|
||||
{0xC003, LIT64(0xA35CE1A3BB251DCB)},
|
||||
{0xC003, LIT64(0x96CBE3F9990E91A8)},
|
||||
{0xC003, LIT64(0x8A3AE64F76F80584)},
|
||||
{0xC002, LIT64(0xFB53D14AA9C2F2C2)},
|
||||
{0xC002, LIT64(0xE231D5F66595DA7B)},
|
||||
{0xC002, LIT64(0xC90FDAA22168C235)},
|
||||
{0xC002, LIT64(0xAFEDDF4DDD3BA9EE)},
|
||||
{0xC002, LIT64(0x96CBE3F9990E91A8)},
|
||||
{0xC001, LIT64(0xFB53D14AA9C2F2C2)},
|
||||
{0xC001, LIT64(0xC90FDAA22168C235)},
|
||||
{0xC001, LIT64(0x96CBE3F9990E91A8)},
|
||||
{0xC000, LIT64(0xC90FDAA22168C235)},
|
||||
{0xBFFF, LIT64(0xC90FDAA22168C235)},
|
||||
{0x0000, LIT64(0x0000000000000000)},
|
||||
{0x3FFF, LIT64(0xC90FDAA22168C235)},
|
||||
{0x4000, LIT64(0xC90FDAA22168C235)},
|
||||
{0x4001, LIT64(0x96CBE3F9990E91A8)},
|
||||
{0x4001, LIT64(0xC90FDAA22168C235)},
|
||||
{0x4001, LIT64(0xFB53D14AA9C2F2C2)},
|
||||
{0x4002, LIT64(0x96CBE3F9990E91A8)},
|
||||
{0x4002, LIT64(0xAFEDDF4DDD3BA9EE)},
|
||||
{0x4002, LIT64(0xC90FDAA22168C235)},
|
||||
{0x4002, LIT64(0xE231D5F66595DA7B)},
|
||||
{0x4002, LIT64(0xFB53D14AA9C2F2C2)},
|
||||
{0x4003, LIT64(0x8A3AE64F76F80584)},
|
||||
{0x4003, LIT64(0x96CBE3F9990E91A8)},
|
||||
{0x4003, LIT64(0xA35CE1A3BB251DCB)},
|
||||
{0x4003, LIT64(0xAFEDDF4DDD3BA9EE)},
|
||||
{0x4003, LIT64(0xBC7EDCF7FF523611)},
|
||||
{0x4003, LIT64(0xC90FDAA22168C235)},
|
||||
{0x4003, LIT64(0xD5A0D84C437F4E58)},
|
||||
{0x4003, LIT64(0xE231D5F66595DA7B)},
|
||||
{0x4003, LIT64(0xEEC2D3A087AC669F)},
|
||||
{0x4003, LIT64(0xFB53D14AA9C2F2C2)},
|
||||
{0x4004, LIT64(0x83F2677A65ECBF73)},
|
||||
{0x4004, LIT64(0x8A3AE64F76F80584)},
|
||||
{0x4004, LIT64(0x9083652488034B96)},
|
||||
{0x4004, LIT64(0x96CBE3F9990E91A8)},
|
||||
{0x4004, LIT64(0x9D1462CEAA19D7B9)},
|
||||
{0x4004, LIT64(0xA35CE1A3BB251DCB)},
|
||||
{0x4004, LIT64(0xA9A56078CC3063DD)},
|
||||
{0x4004, LIT64(0xAFEDDF4DDD3BA9EE)},
|
||||
{0x4004, LIT64(0xB6365E22EE46F000)},
|
||||
{0x4004, LIT64(0xBC7EDCF7FF523611)},
|
||||
{0x4004, LIT64(0xC2C75BCD105D7C23)},
|
||||
{0x4004, LIT64(0xC90FDAA22168C235)}
|
||||
};
|
||||
|
||||
|
||||
static const float32 pi_tbl2[65] = {
|
||||
0x21800000, 0xA0D00000, 0xA1E80000, 0x21480000,
|
||||
0xA1200000, 0x21FC0000, 0x21100000, 0xA1580000,
|
||||
0x21E00000, 0x20B00000, 0xA1880000, 0x21C40000,
|
||||
0x20000000, 0x21380000, 0xA1300000, 0x9FC00000,
|
||||
0x21000000, 0xA1680000, 0xA0A00000, 0x20900000,
|
||||
0x21600000, 0xA1080000, 0x1F800000, 0xA0B00000,
|
||||
0x20800000, 0xA0200000, 0x20E00000, 0x1F000000,
|
||||
0x20000000, 0x20600000, 0x1F800000, 0x1F000000,
|
||||
0x00000000,
|
||||
0x9F000000, 0x9F800000, 0xA0600000, 0xA0000000,
|
||||
0x9F000000, 0xA0E00000, 0x20200000, 0xA0800000,
|
||||
0x20B00000, 0x9F800000, 0x21080000, 0xA1600000,
|
||||
0xA0900000, 0x20A00000, 0x21680000, 0xA1000000,
|
||||
0x1FC00000, 0x21300000, 0xA1380000, 0xA0000000,
|
||||
0xA1C40000, 0x21880000, 0xA0B00000, 0xA1E00000,
|
||||
0x21580000, 0xA1100000, 0xA1FC0000, 0x21200000,
|
||||
0xA1480000, 0x21E80000, 0x20D00000, 0xA1800000
|
||||
};
|
||||
Reference in New Issue
Block a user