From a144b109d21e6269a7e3358e6c1b0f565f13e71c Mon Sep 17 00:00:00 2001 From: ZERICO2005 <71151164+ZERICO2005@users.noreply.github.com> Date: Fri, 10 Jan 2025 03:40:17 -0700 Subject: [PATCH 1/7] Implemented float64 long double using Berkeley SoftFloat 3e. --- .gitignore | 1 + docs/static/asm.rst | 88 +- docs/static/hardware.rst | 2 +- makefile | 2 +- src/common.mk | 1 + src/crt/dcmp.c | 40 + src/crt/dcmp.src | 50 + src/crt/dneg.c | 16 + src/crt/dneg.src | 14 + src/crt/float64_runtime.c | 138 ++ src/crt/float64_runtime.src | 146 +++ src/crt/os.src | 8 - src/libc/copysign.c | 21 + src/libc/fabs.c | 20 + src/libc/float64_math.c | 43 + src/libc/float64_rounding.c | 104 ++ src/libc/include/math.h | 12 + src/libc/iszero.c | 29 + src/linker.mk | 2 + src/softfloat/doc/COPYING.txt | 37 + src/softfloat/doc/README.html | 49 + src/softfloat/doc/README.txt | 21 + src/softfloat/doc/SoftFloat-history.html | 258 ++++ src/softfloat/doc/SoftFloat-source.html | 686 ++++++++++ src/softfloat/doc/SoftFloat.html | 1527 ++++++++++++++++++++++ src/softfloat/doc/eZ80-SoftFloat.txt | 40 + src/softfloat/f32_mulAdd.c | 60 + src/softfloat/f32_to_f64.c | 93 ++ src/softfloat/f64_add.c | 74 ++ src/softfloat/f64_div.c | 172 +++ src/softfloat/f64_mul.c | 150 +++ src/softfloat/f64_mulAdd.c | 60 + src/softfloat/f64_rem.c | 189 +++ src/softfloat/f64_roundToInt.c | 120 ++ src/softfloat/f64_sqrt.c | 133 ++ src/softfloat/f64_sub.c | 74 ++ src/softfloat/f64_to_f32.c | 88 ++ src/softfloat/f64_to_i32.c | 82 ++ src/softfloat/f64_to_i32_r_minMag.c | 96 ++ src/softfloat/f64_to_i64.c | 103 ++ src/softfloat/f64_to_i64_r_minMag.c | 100 ++ src/softfloat/f64_to_ui32.c | 82 ++ src/softfloat/f64_to_ui32_r_minMag.c | 88 ++ src/softfloat/f64_to_ui64.c | 103 ++ src/softfloat/f64_to_ui64_r_minMag.c | 93 ++ src/softfloat/i32_to_f64.c | 65 + src/softfloat/i64_to_f64.c | 58 + src/softfloat/include/internals.h | 278 ++++ src/softfloat/include/opts-GCC.h | 114 ++ src/softfloat/include/platform.h | 8 + src/softfloat/include/primitiveTypes.h | 85 ++ src/softfloat/include/primitives.h | 1160 ++++++++++++++++ src/softfloat/include/softfloat.h | 372 ++++++ src/softfloat/include/softfloat_types.h | 81 ++ src/softfloat/include/specialize.h | 376 ++++++ src/softfloat/makefile | 52 + src/softfloat/s_addM.c | 70 + src/softfloat/s_addMagsF64.c | 128 ++ src/softfloat/s_approxRecip32_1.c | 66 + src/softfloat/s_approxRecipSqrt32_1.c | 73 ++ src/softfloat/s_approxRecipSqrt_1Ks.c | 49 + src/softfloat/s_approxRecip_1Ks.c | 49 + src/softfloat/s_commonNaNToF32UI.c | 51 + src/softfloat/s_commonNaNToF64UI.c | 53 + src/softfloat/s_countLeadingZeros16.c | 60 + src/softfloat/s_countLeadingZeros32.c | 64 + src/softfloat/s_countLeadingZeros64.c | 73 ++ src/softfloat/s_countLeadingZeros8.c | 59 + src/softfloat/s_f32UIToCommonNaN.c | 59 + src/softfloat/s_f64UIToCommonNaN.c | 59 + src/softfloat/s_mul64To128M.c | 68 + src/softfloat/s_mulAddF32.c | 224 ++++ src/softfloat/s_mulAddF64.c | 496 +++++++ src/softfloat/s_negXM.c | 63 + src/softfloat/s_normRoundPackToF64.c | 58 + src/softfloat/s_normSubnormalF32Sig.c | 52 + src/softfloat/s_normSubnormalF64Sig.c | 52 + src/softfloat/s_propagateNaNF32UI.c | 63 + src/softfloat/s_propagateNaNF64UI.c | 63 + src/softfloat/s_roundMToI64.c | 102 ++ src/softfloat/s_roundPackToF32.c | 113 ++ src/softfloat/s_roundPackToF64.c | 117 ++ src/softfloat/s_roundToI32.c | 98 ++ src/softfloat/s_shiftLeftM.c | 91 ++ src/softfloat/s_shiftRightJam32.c | 51 + src/softfloat/s_shiftRightJam64.c | 51 + src/softfloat/s_shiftRightJamM.c | 101 ++ src/softfloat/s_shortShiftLeftM.c | 70 + src/softfloat/s_shortShiftRightJam64.c | 50 + src/softfloat/s_shortShiftRightJamM.c | 72 + src/softfloat/s_shortShiftRightM.c | 70 + src/softfloat/s_subM.c | 70 + src/softfloat/s_subMagsF64.c | 141 ++ src/softfloat/softfloat_raiseFlags.c | 52 + src/softfloat/softfloat_state.c | 52 + src/softfloat/ui32_to_f64.c | 59 + src/softfloat/ui64_to_f64.c | 59 + 97 files changed, 11383 insertions(+), 52 deletions(-) create mode 100644 src/crt/dcmp.c create mode 100644 src/crt/dcmp.src create mode 100644 src/crt/dneg.c create mode 100644 src/crt/dneg.src create mode 100644 src/crt/float64_runtime.c create mode 100644 src/crt/float64_runtime.src create mode 100644 src/libc/copysign.c create mode 100644 src/libc/fabs.c create mode 100644 src/libc/float64_math.c create mode 100644 src/libc/float64_rounding.c create mode 100644 src/libc/iszero.c create mode 100644 src/softfloat/doc/COPYING.txt create mode 100644 src/softfloat/doc/README.html create mode 100644 src/softfloat/doc/README.txt create mode 100644 src/softfloat/doc/SoftFloat-history.html create mode 100644 src/softfloat/doc/SoftFloat-source.html create mode 100644 src/softfloat/doc/SoftFloat.html create mode 100644 src/softfloat/doc/eZ80-SoftFloat.txt create mode 100644 src/softfloat/f32_mulAdd.c create mode 100644 src/softfloat/f32_to_f64.c create mode 100644 src/softfloat/f64_add.c create mode 100644 src/softfloat/f64_div.c create mode 100644 src/softfloat/f64_mul.c create mode 100644 src/softfloat/f64_mulAdd.c create mode 100644 src/softfloat/f64_rem.c create mode 100644 src/softfloat/f64_roundToInt.c create mode 100644 src/softfloat/f64_sqrt.c create mode 100644 src/softfloat/f64_sub.c create mode 100644 src/softfloat/f64_to_f32.c create mode 100644 src/softfloat/f64_to_i32.c create mode 100644 src/softfloat/f64_to_i32_r_minMag.c create mode 100644 src/softfloat/f64_to_i64.c create mode 100644 src/softfloat/f64_to_i64_r_minMag.c create mode 100644 src/softfloat/f64_to_ui32.c create mode 100644 src/softfloat/f64_to_ui32_r_minMag.c create mode 100644 src/softfloat/f64_to_ui64.c create mode 100644 src/softfloat/f64_to_ui64_r_minMag.c create mode 100644 src/softfloat/i32_to_f64.c create mode 100644 src/softfloat/i64_to_f64.c create mode 100644 src/softfloat/include/internals.h create mode 100644 src/softfloat/include/opts-GCC.h create mode 100644 src/softfloat/include/platform.h create mode 100644 src/softfloat/include/primitiveTypes.h create mode 100644 src/softfloat/include/primitives.h create mode 100644 src/softfloat/include/softfloat.h create mode 100644 src/softfloat/include/softfloat_types.h create mode 100644 src/softfloat/include/specialize.h create mode 100644 src/softfloat/makefile create mode 100644 src/softfloat/s_addM.c create mode 100644 src/softfloat/s_addMagsF64.c create mode 100644 src/softfloat/s_approxRecip32_1.c create mode 100644 src/softfloat/s_approxRecipSqrt32_1.c create mode 100644 src/softfloat/s_approxRecipSqrt_1Ks.c create mode 100644 src/softfloat/s_approxRecip_1Ks.c create mode 100644 src/softfloat/s_commonNaNToF32UI.c create mode 100644 src/softfloat/s_commonNaNToF64UI.c create mode 100644 src/softfloat/s_countLeadingZeros16.c create mode 100644 src/softfloat/s_countLeadingZeros32.c create mode 100644 src/softfloat/s_countLeadingZeros64.c create mode 100644 src/softfloat/s_countLeadingZeros8.c create mode 100644 src/softfloat/s_f32UIToCommonNaN.c create mode 100644 src/softfloat/s_f64UIToCommonNaN.c create mode 100644 src/softfloat/s_mul64To128M.c create mode 100644 src/softfloat/s_mulAddF32.c create mode 100644 src/softfloat/s_mulAddF64.c create mode 100644 src/softfloat/s_negXM.c create mode 100644 src/softfloat/s_normRoundPackToF64.c create mode 100644 src/softfloat/s_normSubnormalF32Sig.c create mode 100644 src/softfloat/s_normSubnormalF64Sig.c create mode 100644 src/softfloat/s_propagateNaNF32UI.c create mode 100644 src/softfloat/s_propagateNaNF64UI.c create mode 100644 src/softfloat/s_roundMToI64.c create mode 100644 src/softfloat/s_roundPackToF32.c create mode 100644 src/softfloat/s_roundPackToF64.c create mode 100644 src/softfloat/s_roundToI32.c create mode 100644 src/softfloat/s_shiftLeftM.c create mode 100644 src/softfloat/s_shiftRightJam32.c create mode 100644 src/softfloat/s_shiftRightJam64.c create mode 100644 src/softfloat/s_shiftRightJamM.c create mode 100644 src/softfloat/s_shortShiftLeftM.c create mode 100644 src/softfloat/s_shortShiftRightJam64.c create mode 100644 src/softfloat/s_shortShiftRightJamM.c create mode 100644 src/softfloat/s_shortShiftRightM.c create mode 100644 src/softfloat/s_subM.c create mode 100644 src/softfloat/s_subMagsF64.c create mode 100644 src/softfloat/softfloat_raiseFlags.c create mode 100644 src/softfloat/softfloat_state.c create mode 100644 src/softfloat/ui32_to_f64.c create mode 100644 src/softfloat/ui64_to_f64.c diff --git a/.gitignore b/.gitignore index 8b22f6c8f..c9306d25e 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ doxygen/ obj/ release/ build/ +CEdev/ cmake-build-debug/ tools/fasmg/fasmg tools/fasmg/fasmg.exe diff --git a/docs/static/asm.rst b/docs/static/asm.rst index fea6190ec..f89e58001 100644 --- a/docs/static/asm.rst +++ b/docs/static/asm.rst @@ -126,27 +126,29 @@ For example, if a *short* type is used, the upper byte of the value pushed on th This table lists the locations relative to *sp* from within the called funciton. Note that :code:`sp + [0,2]` contains the return address. -+------------+------------+----------------------+ -| C/C++ Type | Size | Stack Location | -+============+============+======================+ -| char | 1 byte | sp + [3] | -+------------+------------+----------------------+ -| short | 2 bytes | sp + [3,4] | -+------------+------------+----------------------+ -| int | 3 bytes | sp + [3,5] | -+------------+------------+----------------------+ -| long | 4 bytes | sp + [3,6] | -+------------+------------+----------------------+ -| (u)int48_t | 6 bytes | sp + [3,8] | -+------------+------------+----------------------+ -| long long | 8 bytes | sp + [3,10] | -+------------+------------+----------------------+ -| float | 4 bytes | sp + [3,6] | -+------------+------------+----------------------+ -| double | 4 bytes | sp + [3,6] | -+------------+------------+----------------------+ -| pointer | 3 bytes | sp + [3,5] | -+------------+------------+----------------------+ ++-------------+------------+----------------------+ +| C/C++ Type | Size | Stack Location | ++=============+============+======================+ +| char | 1 byte | sp + [3] | ++-------------+------------+----------------------+ +| short | 2 bytes | sp + [3,4] | ++-------------+------------+----------------------+ +| int | 3 bytes | sp + [3,5] | ++-------------+------------+----------------------+ +| long | 4 bytes | sp + [3,6] | ++-------------+------------+----------------------+ +| (u)int48_t | 6 bytes | sp + [3,8] | ++-------------+------------+----------------------+ +| long long | 8 bytes | sp + [3,10] | ++-------------+------------+----------------------+ +| float | 4 bytes | sp + [3,6] | ++-------------+------------+----------------------+ +| double | 4 bytes | sp + [3,6] | ++-------------+------------+----------------------+ +| long double | 8 bytes | sp + [3,10] | ++-------------+------------+----------------------+ +| pointer | 3 bytes | sp + [3,5] | ++-------------+------------+----------------------+ Returns ^^^^^^^ @@ -155,24 +157,26 @@ This table lists which registers are used for return values from a function. The type's sign does not affect the registers used, but may affect the value returned. The LSB is located in the register on the far right of the expression, e.g. ``E:HL`` indicates register ``L`` stores the LSB. -+------------+-------------------+ -| C/C++ Type | Return Register | -+============+===================+ -| char | A | -+------------+-------------------+ -| short | HL | -+------------+-------------------+ -| int | UHL | -+------------+-------------------+ -| long | E:UHL | -+------------+-------------------+ -| (u)int48_t | UDE:UHL | -+------------+-------------------+ -| long long | BC:UDE:UHL | -+------------+-------------------+ -| float | E:UHL | -+------------+-------------------+ -| double | E:UHL | -+------------+-------------------+ -| pointer | UHL | -+------------+-------------------+ ++-------------+-------------------+ +| C/C++ Type | Return Register | ++=============+===================+ +| char | A | ++-------------+-------------------+ +| short | HL | ++-------------+-------------------+ +| int | UHL | ++-------------+-------------------+ +| long | E:UHL | ++-------------+-------------------+ +| (u)int48_t | UDE:UHL | ++-------------+-------------------+ +| long long | BC:UDE:UHL | ++-------------+-------------------+ +| float | E:UHL | ++-------------+-------------------+ +| double | E:UHL | ++-------------+-------------------+ +| long double | BC:UDE:UHL | ++-------------+-------------------+ +| pointer | UHL | ++-------------+-------------------+ diff --git a/docs/static/hardware.rst b/docs/static/hardware.rst index e57dfeddc..742f1926a 100644 --- a/docs/static/hardware.rst +++ b/docs/static/hardware.rst @@ -119,7 +119,7 @@ Therefore, software has to implement that functionality. Like the Z80, the eZ80 also lacks native support for float-point arithmetic, so :code:`float` is slower than :code:`int`. Furthermore, in the toolchain, :code:`float` and :code:`double` are actually treated the same (this is allowed by the C standard). -In the toolchain, :code:`float` is the standard IEEE 32-bit float. +In the toolchain, :code:`float` is the standard IEEE 32-bit float, and :code:`long double` is the standard IEEE 64-bit float. However, IEEE floats have limited precision and have unintuitive rouding behavior. So when TI designed the TI-81, they wrote their own special floating-point number format, which is much more suitable for precision scientific calculations. Unfortunately, it also much slower. diff --git a/makefile b/makefile index 3dfde62a7..b26ee5e65 100644 --- a/makefile +++ b/makefile @@ -20,7 +20,7 @@ PREFIX = CEdev include $(CURDIR)/src/common.mk LIBS := libload graphx fontlibc keypadc fileioc usbdrvce srldrvce msddrvce fatdrvce -SRCS := ce crt libc libcxx +SRCS := ce crt libc libcxx softfloat TOOLS := fasmg convbin convimg convfont cedev-config ifeq ($(OS),Windows_NT) diff --git a/src/common.mk b/src/common.mk index 0defc7035..b99467b94 100644 --- a/src/common.mk +++ b/src/common.mk @@ -82,6 +82,7 @@ INSTALL_LIB := $(call QUOTE_ARG,$(call NATIVEPATH,$(INSTALL_DIR)/lib/libload)) INSTALL_CRT := $(call QUOTE_ARG,$(call NATIVEPATH,$(INSTALL_DIR)/lib/crt)) INSTALL_LIBC := $(call QUOTE_ARG,$(call NATIVEPATH,$(INSTALL_DIR)/lib/libc)) INSTALL_LIBCXX := $(call QUOTE_ARG,$(call NATIVEPATH,$(INSTALL_DIR)/lib/libcxx)) +INSTALL_SOFTFLOAT := $(call QUOTE_ARG,$(call NATIVEPATH,$(INSTALL_DIR)/lib/softfloat)) INSTALL_CE := $(call QUOTE_ARG,$(call NATIVEPATH,$(INSTALL_DIR)/lib/ce)) INSTALL_BIN := $(call QUOTE_ARG,$(call NATIVEPATH,$(INSTALL_DIR)/bin)) INSTALL_H := $(call QUOTE_ARG,$(call NATIVEPATH,$(INSTALL_DIR)/include)) diff --git a/src/crt/dcmp.c b/src/crt/dcmp.c new file mode 100644 index 000000000..3f6faaa7e --- /dev/null +++ b/src/crt/dcmp.c @@ -0,0 +1,40 @@ +#include +#include +#include + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) + +#define F64_CMP_EQUAL 0 +#define F64_CMP_LESS -1 +#define F64_CMP_GREATER 1 +#define F64_CMP_UNORDERED 1 + +// assumes no NaN +int _dcmp_c(const long double* x, const long double *y) { + F64_pun arg_x, arg_y; + arg_x.flt = *x; + arg_y.flt = *y; + + // if (isunordered(x, y)) { + // return F64_CMP_UNORDERED; + // } + + bool x_sign = signbit(*x); + bool y_sign = signbit(*y); + if (x_sign != y_sign) { + if (iszero(*x) && iszero(*y)) { + return F64_CMP_EQUAL; + } + return (x_sign ? F64_CMP_LESS : F64_CMP_GREATER); + } + + if (arg_x.bin == arg_y.bin) { + return F64_CMP_EQUAL; + } + return ((arg_x.bin < arg_y.bin) != x_sign) ? F64_CMP_LESS : F64_CMP_GREATER; +} diff --git a/src/crt/dcmp.src b/src/crt/dcmp.src new file mode 100644 index 000000000..ee96974c2 --- /dev/null +++ b/src/crt/dcmp.src @@ -0,0 +1,50 @@ + assume adl=1 + + section .text + + public __dcmp + +#if 0 + +; This version of _dcmp does not save/restore the state of BC/DE/HL, the state +; of these registers may by modified by the C function + +; int _dcmp_c(long double x, const long double *y) +__dcmp: + ; f64_f64*_ret_i24 + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call __dcmp_c + pop af, af, af, af, iy, af + ; Set the comparison flags + add hl, de + or a, a + sbc hl, de + ret + +#else + +; Properly saves/restores the state of BC/DE/HL + +; int _dcmp_c(const long double *x, const long double *y) +__dcmp: + ; f64*_f64*_ret_i24 + push bc, de, hl, af, iy + ld iy, 6 + add iy, sp + pea iy + 12 + push iy + call __dcmp_c + pop af, af, iy, af + ; Set the comparison flags + add hl, de + or a, a + sbc hl, de + pop hl, de, bc + ret + +#end if + + extern __dcmp_c diff --git a/src/crt/dneg.c b/src/crt/dneg.c new file mode 100644 index 000000000..a2712c9fa --- /dev/null +++ b/src/crt/dneg.c @@ -0,0 +1,16 @@ +#include + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_signbit UINT64_C(0x8000000000000000) + +// Should be easy to implement in assembly +long double _dneg_c(long double x) { + F64_pun ret; + ret.flt = x; + ret.bin ^= Float64_signbit; + return ret.flt; +} diff --git a/src/crt/dneg.src b/src/crt/dneg.src new file mode 100644 index 000000000..72a79f3dc --- /dev/null +++ b/src/crt/dneg.src @@ -0,0 +1,14 @@ +assume adl=1 + +section .text + +public __dneg + +__dneg: + ; f64_ret_f64 + push af, iy, bc, de, hl + call __dneg_c + pop af, af, af, iy, af + ret + +extern __dneg_c diff --git a/src/crt/float64_runtime.c b/src/crt/float64_runtime.c new file mode 100644 index 000000000..111829398 --- /dev/null +++ b/src/crt/float64_runtime.c @@ -0,0 +1,138 @@ +#include +#include "../../softfloat/include/softfloat.h" + +//------------------------------------------------------------------------------ +// unions +//------------------------------------------------------------------------------ + +typedef union F64_pun { + long double flt; + float64_t soft; + uint64_t bin; +} F64_pun; + +typedef union F32_pun { + float flt; + float32_t soft; + uint32_t bin; +} F32_pun; + +//------------------------------------------------------------------------------ +// Arithmetic functions +//------------------------------------------------------------------------------ + +/* long double _dneg_c(long double x) */ + +long double _dadd_c(long double x, const long double *y) { + F64_pun arg_x, arg_y, ret; + arg_x.flt = x; + arg_y.flt = *y; + ret.soft = f64_add(arg_x.soft, arg_y.soft); + return ret.flt; +} + +long double _dsub_c(long double x, const long double *y) { + F64_pun arg_x, arg_y, ret; + arg_x.flt = x; + arg_y.flt = *y; + ret.soft = f64_sub(arg_x.soft, arg_y.soft); + return ret.flt; +} + +long double _dmul_c(long double x, const long double *y) { + F64_pun arg_x, arg_y, ret; + arg_x.flt = x; + arg_y.flt = *y; + ret.soft = f64_mul(arg_x.soft, arg_y.soft); + return ret.flt; +} + +long double _ddiv_c(long double x, const long double *y) { + F64_pun arg_x, arg_y, ret; + arg_x.flt = x; + arg_y.flt = *y; + ret.soft = f64_div(arg_x.soft, arg_y.soft); + return ret.flt; +} + +long double _drem_c(long double x, const long double *y) { + F64_pun arg_x, arg_y, ret; + arg_x.flt = x; + arg_y.flt = *y; + ret.soft = f64_rem(arg_x.soft, arg_y.soft); + return ret.flt; +} + +/* int _dcmp_c(const long double *x, const long double* y) */ + +//------------------------------------------------------------------------------ +// Convert to long double +//------------------------------------------------------------------------------ + +long double _ftod_c(float x) { + F32_pun arg_x; + F64_pun ret; + arg_x.flt = x; + ret.soft = f32_to_f64(arg_x.soft); + return ret.flt; +} + +long double _ltod_c(int32_t x) { + F64_pun ret; + ret.soft = i32_to_f64(x); + return ret.flt; +} + +long double _lltod_c(int64_t x) { + F64_pun ret; + ret.soft = i64_to_f64(x); + return ret.flt; +} + +long double _ultod_c(uint32_t x) { + F64_pun ret; + ret.soft = ui32_to_f64(x); + return ret.flt; +} + +long double _ulltod_c(uint64_t x) { + F64_pun ret; + ret.soft = ui64_to_f64(x); + return ret.flt; +} + +//------------------------------------------------------------------------------ +// Convert from long double +//------------------------------------------------------------------------------ + +float _dtof_c(long double x) { + F32_pun ret; + F64_pun arg_x; + arg_x.flt = x; + ret.soft = f64_to_f32(arg_x.soft); + return ret.flt; +} + +int32_t _dtol_c(long double x) { + F64_pun arg_x; + arg_x.flt = x; + return f64_to_i32_r_minMag(arg_x.soft, true); +} + +int64_t _dtoll_c(long double x) { + F64_pun arg_x; + arg_x.flt = x; + return f64_to_i64_r_minMag(arg_x.soft, true); +} + +uint32_t _dtoul_c(long double x) { + F64_pun arg_x; + arg_x.flt = x; + return f64_to_ui32_r_minMag(arg_x.soft, true); +} + +uint64_t _dtoull_c(long double x) { + F64_pun arg_x; + arg_x.flt = x; + return f64_to_ui64_r_minMag(arg_x.soft, true); +} diff --git a/src/crt/float64_runtime.src b/src/crt/float64_runtime.src new file mode 100644 index 000000000..699798ef4 --- /dev/null +++ b/src/crt/float64_runtime.src @@ -0,0 +1,146 @@ + assume adl=1 + + section .text + + public __dadd, __dsub, __dmul, __ddiv, __drem + public __ftod, __ltod, __lltod, __ultod, __ulltod + public __dtof, __dtol, __dtoll, __dtoul, __dtoull + +;------------------------------------------------------------------------------- +; Arithmetic functions +;------------------------------------------------------------------------------- + +__dadd: + ; f64_f64*_ret_f64 + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call __dadd_c + pop af, af, af, af, iy, af + ret + +__dsub: + ; f64_f64*_ret_f64 + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call __dsub_c + pop af, af, af, af, iy, af + ret + +__dmul: + ; f64_f64*_ret_f64 + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call __dmul_c + pop af, af, af, af, iy, af + ret + +__ddiv: + ; f64_f64*_ret_f64 + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call __ddiv_c + pop af, af, af, af, iy, af + ret + +__drem: + ; f64_f64*_ret_f64 + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call __drem_c + pop af, af, af, af, iy, af + ret + +;------------------------------------------------------------------------------- +; Convert to long double +;------------------------------------------------------------------------------- + +__ftod: + ; f32_ret_f64 + ld d, a + push iy, de, hl + call __ftod_c + pop af, af, iy + ret + +__ltod: + ; i32_ret_f64 + ld d, a + push iy, de, hl + call __ltod_c + pop af, af, iy + ret + +__lltod: + ; i64_ret_f64 + push af, iy, bc, de, hl + call __lltod_c + pop af, af, af, iy, af + ret + +__ultod: + ; u32_ret_f64 + ld d, a + push iy, de, hl + call __ultod_c + pop af, af, iy + ret + +__ulltod: + ; u64_ret_f64 + push af, iy, bc, de, hl + call __ulltod_c + pop af, af, af, iy, af + ret + +;------------------------------------------------------------------------------- +; Convert from long double +;------------------------------------------------------------------------------- + +__dtof: + ; f64_ret_f32 + push af, iy, bc, de, hl + call __dtof_c + pop af, af, af, iy, af + ret + +__dtol: + ; f64_ret_i32 + push af, iy, bc, de, hl + call __dtol_c + pop af, af, af, iy, af + ret + +__dtoll: + ; f64_ret_i64 + push af, iy, bc, de, hl + call __dtoll_c + pop af, af, af, iy, af + ret + +__dtoul: + ; f64_ret_u32 + push af, iy, bc, de, hl + call __dtoul_c + pop af, af, af, iy, af + ret + +__dtoull: + ; f64_ret_u64 + push af, iy, bc, de, hl + call __dtoull_c + pop af, af, af, iy, af + ret + + extern __dadd_c, __dsub_c, __dmul_c, __ddiv_c, __drem_c + extern __ftod_c, __ltod_c, __lltod_c, __ultod_c, __ulltod_c + extern __dtof_c, __dtol_c, __dtoll_c, __dtoul_c, __dtoull_c diff --git a/src/crt/os.src b/src/crt/os.src index e8e88b1be..edc78cd91 100644 --- a/src/crt/os.src +++ b/src/crt/os.src @@ -16,10 +16,6 @@ __fsub := 000290h __ftol := 00027Ch public __ftoul __ftoul := __ftol - public __dtol -__dtol := __ftol - public __dtoul -__dtoul := __ftoul public __imul_b __imul_b := 000150h public __indcall @@ -34,8 +30,6 @@ __ishru_b := 000188h __itol := 000194h public __ltof __ltof := 000284h - public __ltod -__ltod := __ltof public __setflag __setflag := 000218h public __sshl_b @@ -50,5 +44,3 @@ __stoi := 000260h __stoiu := 000264h public __ultof __ultof := 000280h - public __ultod -__ultod := __ultof diff --git a/src/libc/copysign.c b/src/libc/copysign.c new file mode 100644 index 000000000..c13ade349 --- /dev/null +++ b/src/libc/copysign.c @@ -0,0 +1,21 @@ +#include + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_signbit UINT64_C(0x8000000000000000) +#define Float64_fabs_mask UINT64_C(0x7FFFFFFFFFFFFFFF) + +// Should be easy to implement in assembly +long double copysignl(long double x, long double y) { + F64_pun arg_x, arg_y; + arg_x.flt = x; + arg_y.flt = y; + // clear the signbit of x + arg_x.bin &= Float64_fabs_mask; + // copy the signbit of y + arg_x.bin ^= arg_y.bin & Float64_signbit; + return arg_x.flt; +} diff --git a/src/libc/fabs.c b/src/libc/fabs.c new file mode 100644 index 000000000..2b7f71d91 --- /dev/null +++ b/src/libc/fabs.c @@ -0,0 +1,20 @@ +#include + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_fabs_mask UINT64_C(0x7FFFFFFFFFFFFFFF) + +// Should be easy to implement in assembly +long double fabsl(long double x) { + F64_pun ret; + ret.flt = x; + /** + * @remarks This can also be done by doing a leftshift to remove the + * signbit, and then doing a rightsift + */ + ret.bin &= Float64_fabs_mask; + return ret.flt; +} diff --git a/src/libc/float64_math.c b/src/libc/float64_math.c new file mode 100644 index 000000000..774934a9a --- /dev/null +++ b/src/libc/float64_math.c @@ -0,0 +1,43 @@ +#include +#include +#include "../../softfloat/include/softfloat.h" + +typedef union F64_pun { + long double flt; + float64_t soft; + uint64_t bin; +} F64_pun; + +long double fmal(long double x, long double y, long double z) { + F64_pun arg_x, arg_y, arg_z, ret; + arg_x.flt = x; + arg_y.flt = y; + arg_z.flt = z; + ret.soft = f64_mulAdd(arg_x.soft, arg_y.soft, arg_z.soft); + return ret.flt; +} + +long double sqrtl(long double x) { + F64_pun arg_x, ret; + arg_x.flt = x; + ret.soft = f64_sqrt(arg_x.soft); + return ret.flt; +} + +// _drem +long double fmodl(long double x, long double y) { + F64_pun arg_x, arg_y, ret; + arg_x.flt = x; + arg_y.flt = y; + ret.soft = f64_rem(arg_x.soft, arg_y.soft); + return ret.flt; +} + +long double modfl(long double x, long double *integral_part) { + F64_pun arg_x, arg_y, ret; + arg_x.flt = x; + arg_y.flt = 1.0L; + *integral_part = truncl(x); + ret.soft = f64_rem(arg_x.soft, arg_y.soft); + return ret.flt; +} diff --git a/src/libc/float64_rounding.c b/src/libc/float64_rounding.c new file mode 100644 index 000000000..fdc095a36 --- /dev/null +++ b/src/libc/float64_rounding.c @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include "../../softfloat/include/softfloat.h" + +typedef union F64_pun { + long double flt; + float64_t soft; + uint64_t bin; +} F64_pun; + +long double truncl(long double x) { + F64_pun arg_x, ret; + arg_x.flt = x; + ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_minMag, true); + return ret.flt; +} + +long double floorl(long double x) { + F64_pun arg_x, ret; + arg_x.flt = x; + ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_min, true); + return ret.flt; +} + +long double ceill(long double x) { + F64_pun arg_x, ret; + arg_x.flt = x; + ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_max, true); + return ret.flt; +} + +long double roundevenl(long double x) { + F64_pun arg_x, ret; + arg_x.flt = x; + ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_near_even, true); + return ret.flt; +} + +long double roundl(long double x) { + F64_pun arg_x, ret; + arg_x.flt = x; + ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_near_maxMag, true); + return ret.flt; +} + +long lroundl(long double x) { + F64_pun arg_x; + arg_x.flt = x; + return f64_to_i32(arg_x.soft, softfloat_round_near_maxMag, true); +} + +long long llroundl(long double x) { + F64_pun arg_x; + arg_x.flt = x; + return f64_to_i64(arg_x.soft, softfloat_round_near_maxMag, true); +} + +#if ( \ + FE_TONEAREST == softfloat_round_near_even && \ + FE_TOWARDZERO == softfloat_round_minMag && \ + FE_DOWNWARD == softfloat_round_min && \ + FE_UPWARD == softfloat_round_max) + +// assumes fenv.h macros match softfloat_roundingModes +#define GET_FENV_SOFTFLOAT_ROUNDING() (fegetround()) + +#else + static uint_fast8_t GET_FENV_SOFTFLOAT_ROUNDING(void) { + switch(fegetround()) { + default: + case FE_TONEAREST : return softfloat_round_near_even; + case FE_TOWARDZERO: return softfloat_round_minMag ; + case FE_DOWNWARD : return softfloat_round_min ; + case FE_UPWARD : return softfloat_round_max ; + } + } +#endif + +long double nearbyintl(long double x) { + F64_pun arg_x, ret; + arg_x.flt = x; + ret.soft = f64_roundToInt(arg_x.soft, GET_FENV_SOFTFLOAT_ROUNDING(), true); + return ret.flt; +} + +long double rintl(long double x) { + F64_pun arg_x, ret; + arg_x.flt = x; + ret.soft = f64_roundToInt(arg_x.soft, GET_FENV_SOFTFLOAT_ROUNDING(), true); + if (ret.bin != arg_x.bin) { + feraiseexcept(FE_INEXACT); + } + return ret.flt; +} + +long lrintl(long double x) { + return (int32_t)rintl(x); +} + +long long llrintl(long double x) { + return (int64_t)rintl(x); +} diff --git a/src/libc/include/math.h b/src/libc/include/math.h index cf7cdd5dd..f2ae7ee41 100644 --- a/src/libc/include/math.h +++ b/src/libc/include/math.h @@ -47,8 +47,16 @@ int _isinff(float n); int _isnanf(float n); int _isnormalf(float n); int _isfinitef(float n); +int _iszerof(float n); int _fpclassifyf(float n); +// int _isinfl(long double n); +// int _isnanl(long double n); +// int _isnormall(long double n); +// int _isfinitel(long double n); +int _iszerol(long double n); +// int _fpclassifyl(long double n); + #define isinf(x) ( \ sizeof((x)) == sizeof(float) ? _isinff((x)) : \ 0) @@ -61,6 +69,10 @@ int _fpclassifyf(float n); #define isfinite(x) ( \ sizeof((x)) == sizeof(float) ? _isfinitef((x)) : \ 1) +#define iszero(x) ( \ + sizeof((x)) == sizeof(float) ? _iszerof((x)) : \ + sizeof((x)) == sizeof(long double) ? _iszerol(x) : \ + (x) != 0) #define fpclassify(x) ( \ sizeof((x)) == sizeof(float) ? _fpclassifyf((x)) : \ 0) diff --git a/src/libc/iszero.c b/src/libc/iszero.c new file mode 100644 index 000000000..50dfa6779 --- /dev/null +++ b/src/libc/iszero.c @@ -0,0 +1,29 @@ +#include + +typedef union F32_pun { + long double flt; + uint64_t bin; +} F32_pun; + +int _iszerof(float x) { + F32_pun val; + val.flt = x; + // clears the signbit + val.bin <<= 1; + return (val.bin == 0); +} + +int _iszero(double) __attribute__((alias("_iszerof"))); + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +int _iszerol(long double x) { + F64_pun val; + val.flt = x; + // clears the signbit + val.bin <<= 1; + return (val.bin == 0); +} diff --git a/src/linker.mk b/src/linker.mk index d924552d7..2e0b0b7dc 100644 --- a/src/linker.mk +++ b/src/linker.mk @@ -22,6 +22,7 @@ APPEND_FILES = $(foreach file,$(addprefix ../lib/$2/,$(notdir $3)),$(call APPEND CRT_FILES := $(filter-out crt/crt0.src,$(wildcard crt/*.src) $(patsubst crt/%,crt/build/%.src,$(wildcard crt/*.c crt/*.cpp))) LIBC_FILES := $(wildcard libc/*.src) $(patsubst libc/%,libc/build/%.src,$(wildcard libc/*.c libc/*.cpp)) LIBCXX_FILES := $(wildcard libcxx/*.src) $(patsubst libcxx/%,libcxx/build/%.src,$(wildcard libcxx/*.c libcxx/*.cpp)) +SOFTFLOAT_FILES := $(wildcard softfloat/*.src) $(patsubst softfloat/%,softfloat/build/%.src,$(wildcard softfloat/*.c softfloat/*.cpp)) CE_FILES := $(wildcard ce/*.src) linker_script: $(STATIC_FILES) $(LINKED_FILES) $(SHARED_FILES) @@ -65,4 +66,5 @@ linker_script: $(STATIC_FILES) $(LINKED_FILES) $(SHARED_FILES) $(Q)$(call APPEND,end if) $(Q)$(call APPEND,if HAS_LIBCXX) $(Q)$(call APPEND_FILES, source ,libcxx,$(sort $(LIBCXX_FILES))) + $(Q)$(call APPEND_FILES, source ,softfloat,$(sort $(SOFTFLOAT_FILES))) $(Q)$(call APPEND,end if) diff --git a/src/softfloat/doc/COPYING.txt b/src/softfloat/doc/COPYING.txt new file mode 100644 index 000000000..b5690face --- /dev/null +++ b/src/softfloat/doc/COPYING.txt @@ -0,0 +1,37 @@ + +License for Berkeley SoftFloat Release 3e + +John R. Hauser +2018 January 20 + +The following applies to the whole of SoftFloat Release 3e as well as to +each source file individually. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/src/softfloat/doc/README.html b/src/softfloat/doc/README.html new file mode 100644 index 000000000..7989e0c26 --- /dev/null +++ b/src/softfloat/doc/README.html @@ -0,0 +1,49 @@ + + + + +Berkeley SoftFloat Package Overview + + + + +

Package Overview for Berkeley SoftFloat Release 3e

+ +

+John R. Hauser
+2018 January 20
+

+ +

+Berkeley SoftFloat is a software implementation of binary floating-point that +conforms to the IEEE Standard for Floating-Point Arithmetic. +SoftFloat is distributed in the form of C source code. +Building the SoftFloat sources generates a library file (typically +softfloat.a or libsoftfloat.a) containing the +floating-point subroutines. +

+ +

+The SoftFloat package is documented in the following files in the +doc subdirectory: +

+ + + + + + + + + + + + + +
SoftFloat.htmlDocumentation for using the SoftFloat functions.
SoftFloat-source.htmlDocumentation for building SoftFloat.
SoftFloat-history.html   History of the major changes to SoftFloat.
+
+Other files in the package comprise the source code for SoftFloat. +

+ + + diff --git a/src/softfloat/doc/README.txt b/src/softfloat/doc/README.txt new file mode 100644 index 000000000..1613c7671 --- /dev/null +++ b/src/softfloat/doc/README.txt @@ -0,0 +1,21 @@ + +Package Overview for Berkeley SoftFloat Release 3e + +John R. Hauser +2018 January 20 + +Berkeley SoftFloat is a software implementation of binary floating-point +that conforms to the IEEE Standard for Floating-Point Arithmetic. SoftFloat +is distributed in the form of C source code. Building the SoftFloat sources +generates a library file (typically "softfloat.a" or "libsoftfloat.a") +containing the floating-point subroutines. + +The SoftFloat package is documented in the following files in the "doc" +subdirectory: + + SoftFloat.html Documentation for using the SoftFloat functions. + SoftFloat-source.html Documentation for building SoftFloat. + SoftFloat-history.html History of the major changes to SoftFloat. + +Other files in the package comprise the source code for SoftFloat. + diff --git a/src/softfloat/doc/SoftFloat-history.html b/src/softfloat/doc/SoftFloat-history.html new file mode 100644 index 000000000..daa48ca3b --- /dev/null +++ b/src/softfloat/doc/SoftFloat-history.html @@ -0,0 +1,258 @@ + + + + +Berkeley SoftFloat History + + + + +

History of Berkeley SoftFloat, to Release 3e

+ +

+John R. Hauser
+2018 January 20
+

+ + +

Release 3e (2018 January)

+ +
    + +
  • +Changed the default numeric code for optional rounding mode odd +(round to odd, also known as jamming) from 5 to 6. + +
  • +Modified the behavior of rounding mode odd when rounding to an +integer value (either conversion to an integer format or a +‘roundToInt’ function). +Previously, for those cases only, rounding mode odd acted the same +as rounding to minimum magnitude. +Now all operations are rounded consistently. + +
  • +Fixed some errors in the specialization code modeling Intel x86 floating-point, +specifically the integers returned on invalid operations and the propagation of +NaN payloads in a few rare cases. + +
  • +Added specialization code modeling ARM floating-point, conforming to VFPv2 or +later. + +
  • +Added an example target for ARM processors. + +
  • +Fixed a minor bug whereby function f16_to_ui64 might return a +different integer than expected in the case that the floating-point operand is +negative. + +
  • +Added example target-specific optimization for GCC, employing GCC instrinsics +and support for 128-bit integer arithmetic. + +
  • +Made other minor improvements. + +
+ + +

Release 3d (2017 August)

+ +
    + +
  • +Fixed bugs in the square root functions for 64-bit +double-precision, 80-bit double-extended-precision, and +128-bit quadruple-precision. +For 64-bit double-precision (f64_sqrt), the result +could sometimes be off by 1 unit in the last place +(1 ulp) from what it should be. +For the larger formats, the square root could be wrong in a large portion of +the less-significant bits. +(A bug in f128_sqrt was first reported by Alexei Sibidanov.) + +
+ + +

Release 3c (2017 February)

+ +
    + +
  • +Added optional rounding mode odd (round to odd, also known as +jamming). + +
  • +Corrected the documentation concerning non-canonical representations in +80-bit double-extended-precision. + +
+ + +

Release 3b (2016 July)

+ +
    + +
  • +Implemented the common 16-bit “half-precision” +floating-point format (float16_t). + +
  • +Made the integer values returned on invalid conversions to integer formats +be determined by the port-specific specialization instead of being the same for +all ports. + +
  • +Added preprocessor macro THREAD_LOCAL to allow the floating-point +state (modes and exception flags) to be made per-thread. + +
  • +Modified the provided Makefiles to allow some options to be overridden from the +make command. + +
  • +Made other minor improvements. + +
+ + +

Release 3a (2015 October)

+ +
    + +
  • +Replaced the license text supplied by the University of California, Berkeley. + +
+ + +

Release 3 (2015 February)

+ +
    + +
  • +Complete rewrite, funded by the University of California, Berkeley, and +consequently having a different use license than earlier releases. +Major changes included renaming most types and functions, upgrading some +algorithms, restructuring the source files, and making SoftFloat into a true +library. + +
  • +Added functions to convert between floating-point and unsigned integers, both +32-bit and 64-bit (uint32_t and +uint64_t). + +
  • +Added functions for fused multiply-add, for all supported floating-point +formats except 80-bit double-extended-precision. + +
  • +Added support for a fifth rounding mode, near_maxMag (round to +nearest, with ties to maximum magnitude, away from zero). + +
  • +Dropped the timesoftfloat program (now part of the Berkeley +TestFloat package). + +
+ + +

Release 2c (2015 January)

+ +
    + +
  • +Fixed mistakes affecting some 64-bit processors. + +
  • +Further improved the documentation and the wording for the legal restrictions +on using SoftFloat releases through 2c (not applicable to +Release 3 or later). + +
+ + +

Release 2b (2002 May)

+ +
    + +
  • +Made minor updates to the documentation, including improved wording for the +legal restrictions on using SoftFloat. + +
+ + +

Release 2a (1998 December)

+ +
    + +
  • +Added functions to convert between 64-bit integers +(int64) and all supported floating-point formats. + +
  • +Fixed a bug in all 64-bit-version square root functions except +float32_sqrt that caused the result sometimes to be off by +1 unit in the last place (1 ulp) from what it should +be. +(Bug discovered by Paul Donahue.) + +
  • +Improved the Makefiles. +
+ + +

Release 2 (1997 June)

+ +
    + +
  • +Created the 64-bit (bits64) version, adding the +floatx80 and float128 formats. + +
  • +Changed the source directory structure, splitting the sources into a +bits32 and a bits64 version. +Renamed environment.h to milieu.h to avoid confusion +with environment variables. + +
  • +Fixed a small error that caused float64_round_to_int often to +round the wrong way in nearest/even mode when the operand was between +220 and 221 and halfway between two integers. + +
+ + +

Release 1a (1996 July)

+ +
    + +
  • +Corrected a mistake that caused borderline underflow cases not to raise the +underflow flag when they should have. +(Problem reported by Doug Priest.) + +
  • +Added the float_detect_tininess variable to control whether +tininess is detected before or after rounding. + +
+ + +

Release 1 (1996 July)

+ +
    + +
  • +Original release, based on work done for the International Computer Science +Institute (ICSI) in Berkeley, California. + +
+ + + + diff --git a/src/softfloat/doc/SoftFloat-source.html b/src/softfloat/doc/SoftFloat-source.html new file mode 100644 index 000000000..d4b85f7b0 --- /dev/null +++ b/src/softfloat/doc/SoftFloat-source.html @@ -0,0 +1,686 @@ + + + + +Berkeley SoftFloat Source Documentation + + + + +

Berkeley SoftFloat Release 3e: Source Documentation

+ +

+John R. Hauser
+2018 January 20
+

+ + +

Contents

+ +
+ +++ + + + + + + + + + + + + + + + + + + + +
1. Introduction
2. Limitations
3. Acknowledgments and License
4. SoftFloat Package Directory Structure
5. Issues for Porting SoftFloat to a New Target
5.1. Standard Headers <stdbool.h> and + <stdint.h>
5.2. Specializing Floating-Point Behavior
5.3. Macros for Build Options
5.4. Adapting a Template Target Directory
5.5. Target-Specific Optimization of Primitive Functions
6. Testing SoftFloat
7. Providing SoftFloat as a Common Library for Applications
8. Contact Information
+
+ + +

1. Introduction

+ +

+This document gives information needed for compiling and/or porting Berkeley +SoftFloat, a library of C functions implementing binary floating-point +conforming to the IEEE Standard for Floating-Point Arithmetic. +For basic documentation about SoftFloat refer to +SoftFloat.html. +

+ +

+The source code for SoftFloat is intended to be relatively machine-independent +and should be compilable with any ISO-Standard C compiler that also supports +64-bit integers. +SoftFloat has been successfully compiled with the GNU C Compiler +(gcc) for several platforms. +

+ +

+Release 3 of SoftFloat was a complete rewrite relative to +Release 2 or earlier. +Changes to the interface of SoftFloat functions are documented in +SoftFloat.html. +The current version of SoftFloat is Release 3e. +

+ + +

2. Limitations

+ +

+SoftFloat assumes the computer has an addressable byte size of either 8 or +16 bits. +(Nearly all computers in use today have 8-bit bytes.) +

+ +

+SoftFloat is written in C and is designed to work with other C code. +The C compiler used must conform at a minimum to the 1989 ANSI standard for the +C language (same as the 1990 ISO standard) and must in addition support basic +arithmetic on 64-bit integers. +Earlier releases of SoftFloat included implementations of 32-bit +single-precision and 64-bit double-precision floating-point that +did not require 64-bit integers, but this option is not supported +starting with Release 3. +Since 1999, ISO standards for C have mandated compiler support for +64-bit integers. +A compiler conforming to the 1999 C Standard or later is recommended but not +strictly required. +

+ +

+C Standard header files <stdbool.h> and +<stdint.h> are required for defining standard Boolean and +integer types. +If these headers are not supplied with the C compiler, minimal substitutes must +be provided. +SoftFloat’s dependence on these headers is detailed later in +section 5.1, Standard Headers <stdbool.h> +and <stdint.h>. +

+ + +

3. Acknowledgments and License

+ +

+The SoftFloat package was written by me, John R. Hauser. +Release 3 of SoftFloat was a completely new implementation +supplanting earlier releases. +The project to create Release 3 (now through 3e) was +done in the employ of the University of California, Berkeley, within the +Department of Electrical Engineering and Computer Sciences, first for the +Parallel Computing Laboratory (Par Lab) and then for the ASPIRE Lab. +The work was officially overseen by Prof. Krste Asanovic, with funding provided +by these sources: +

+ ++++ + + + + + + + + + +
Par Lab: +Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery +(Award #DIG07-10227), with additional support from Par Lab affiliates Nokia, +NVIDIA, Oracle, and Samsung. +
ASPIRE Lab: +DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from +ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA, +Oracle, and Samsung. +
+
+

+ +

+The following applies to the whole of SoftFloat Release 3e as well +as to each source file individually. +

+ +

+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the +University of California. +All rights reserved. +

+ +

+Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +

    + +
  1. +

    +Redistributions of source code must retain the above copyright notice, this +list of conditions, and the following disclaimer. +

    + +
  2. +

    +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions, and the following disclaimer in the documentation and/or +other materials provided with the distribution. +

    + +
  3. +

    +Neither the name of the University nor the names of its contributors may be +used to endorse or promote products derived from this software without specific +prior written permission. +

    + +
+

+ +

+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS”, +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. +IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +

+ + +

4. SoftFloat Package Directory Structure

+ +

+Because SoftFloat is targeted to multiple platforms, its source code is +slightly scattered between target-specific and target-independent directories +and files. +The supplied directory structure is as follows: +

+
+doc
+source
+    include
+    8086
+    8086-SSE
+    ARM-VFPv2
+    ARM-VFPv2-defaultNaN
+build
+    template-FAST_INT64
+    template-not-FAST_INT64
+    Linux-386-GCC
+    Linux-386-SSE2-GCC
+    Linux-x86_64-GCC
+    Linux-ARM-VFPv2-GCC
+    Win32-MinGW
+    Win32-SSE2-MinGW
+    Win64-MinGW-w64
+
+
+The majority of the SoftFloat sources are provided in the source +directory. +The include subdirectory contains several header files +(unsurprisingly), while the other subdirectories of source contain +source files that specialize the floating-point behavior to match particular +processor families: +
+
+
8086
+
+Intel’s older, 8087-derived floating-point, extended to all supported +floating-point types +
+
8086-SSE
+
+Intel’s x86 processors with Streaming SIMD Extensions (SSE) and later +compatible extensions, having 8087 behavior for 80-bit +double-extended-precision (extFloat80_t) and SSE behavior for +other floating-point types +
+
ARM-VFPv2
+
+ARM’s VFPv2 or later floating-point, with NaN payload propagation +
+
ARM-VFPv2-defaultNaN
+
+ARM’s VFPv2 or later floating-point, with the “default NaN” +option +
+
+
+If other specializations are attempted, these would be expected to be other +subdirectories of source alongside the ones listed above. +Specialization is covered later, in section 5.2, Specializing +Floating-Point Behavior. +

+ +

+The build directory is intended to contain a subdirectory for each +target platform for which a build of the SoftFloat library may be created. +For each build target, the target’s subdirectory is where all derived +object files and the completed SoftFloat library (typically +softfloat.a or libsoftfloat.a) are created. +The two template subdirectories are not actual build targets but +contain sample files for creating new target directories. +(The meaning of FAST_INT64 will be explained later.) +

+ +

+Ignoring the template directories, the supplied target directories +are intended to follow a naming system of +<execution-environment>-<compiler>. +For the example targets, +<execution-environment> is +Linux-386, Linux-386-SSE2, +Linux-x86_64, +Linux-ARM-VFPv2, Win32, +Win32-SSE2, or Win64, and +<compiler> is GCC, +MinGW, or MinGW-w64. +

+ +

+All of the supplied target directories are merely examples that may or may not +be correct for compiling on any particular system. +Despite requests, there are currently no plans to include and maintain in the +SoftFloat package the build files needed for a great many users’ +compilation environments, which can span a huge range of operating systems, +compilers, and other tools. +

+ +

+As supplied, each target directory contains two files: +

+
+Makefile
+platform.h
+
+
+The provided Makefile is written for GNU make. +A build of SoftFloat for the specific target is begun by executing the +make command with the target directory as the current directory. +A completely different build tool can be used if an appropriate +Makefile equivalent is created. +

+ +

+The platform.h header file exists to provide a location for +additional C declarations specific to the build target. +Every C source file of SoftFloat contains a #include for +platform.h. +In many cases, the contents of platform.h can be as simple as one +or two lines of code. +At the other extreme, to get maximal performance from SoftFloat, it may be +desirable to include in header platform.h (directly or via +#include) declarations for numerous target-specific optimizations. +Such possibilities are discussed in the next section, Issues for Porting +SoftFloat to a New Target. +If the target’s compiler or library has bugs or other shortcomings, +workarounds for these issues may also be possible with target-specific +declarations in platform.h, avoiding the need to modify the main +SoftFloat sources. +

+ + +

5. Issues for Porting SoftFloat to a New Target

+ +

5.1. Standard Headers <stdbool.h> and <stdint.h>

+ +

+The SoftFloat sources make use of standard headers +<stdbool.h> and <stdint.h>, which have +been part of the ISO C Standard Library since 1999. +With any recent compiler, these standard headers are likely to be supported, +even if the compiler does not claim complete conformance to the latest ISO C +Standard. +For older or nonstandard compilers, substitutes for +<stdbool.h> and <stdint.h> may need to be +created. +SoftFloat depends on these names from <stdbool.h>: +

+
+bool
+true
+false
+
+
+and on these names from <stdint.h>: +
+
+uint16_t
+uint32_t
+uint64_t
+int32_t
+int64_t
+UINT64_C
+INT64_C
+uint_least8_t
+uint_fast8_t
+uint_fast16_t
+uint_fast32_t
+uint_fast64_t
+int_fast8_t
+int_fast16_t
+int_fast32_t
+int_fast64_t
+
+
+

+ + +

5.2. Specializing Floating-Point Behavior

+ +

+The IEEE Floating-Point Standard allows for some flexibility in a conforming +implementation, particularly concerning NaNs. +The SoftFloat source directory is supplied with some +specialization subdirectories containing possible definitions for this +implementation-specific behavior. +For example, the 8086 and 8086-SSE +subdirectories have source files that specialize SoftFloat’s behavior to +match that of Intel’s x86 line of processors. +The files in a specialization subdirectory must determine: +

    +
  • +whether tininess for underflow is detected before or after rounding by default; +
  • +how signaling NaNs are distinguished from quiet NaNs; +
  • +what (if anything) special happens when exceptions are raised; +
  • +the default generated quiet NaNs; +
  • +how NaNs are propagated from function inputs to output; and +
  • +the integer results returned when conversions to integer type raise the +invalid exception. +
+

+ +

+As provided, the build process for a target expects to involve exactly +one specialization directory that defines all of these +implementation-specific details for the target. +A specialization directory such as 8086 is expected to contain a +header file called specialize.h, together with whatever other +source files are needed to complete the specialization. +

+ +

+A new build target may use an existing specialization, such as the ones +provided by the 8086 and 8086-SSE +subdirectories. +If a build target needs a new specialization, different from any existing ones, +it is recommended that a new specialization directory be created for this +purpose. +The specialize.h header file from any of the provided +specialization subdirectories can be used as a model for what definitions are +needed. +

+ + +

5.3. Macros for Build Options

+ +

+The SoftFloat source files adapt the floating-point implementation according to +several C preprocessor macros: +

+
+
LITTLEENDIAN +
+Must be defined for little-endian machines; must not be defined for big-endian +machines. +
INLINE +
+Specifies the sequence of tokens used to indicate that a C function should be +inlined. +If macro INLINE_LEVEL is defined with a value of 1 or higher, this +macro must be defined; otherwise, this macro is ignored and need not be +defined. +For compilers that conform to the C Standard’s rules for inline +functions, this macro can be defined as the single keyword inline. +For other compilers that follow a convention pre-dating the standardization of +inline, this macro may need to be defined to extern +inline. +
THREAD_LOCAL +
+Can be defined to a sequence of tokens that, when appearing at the start of a +variable declaration, indicates to the C compiler that the variable is +per-thread, meaning that each execution thread gets its own separate +instance of the variable. +This macro is used in header softfloat.h in the declarations of +variables softfloat_roundingMode, +softfloat_detectTininess, extF80_roundingPrecision, +and softfloat_exceptionFlags. +If macro THREAD_LOCAL is left undefined, these variables will +default to being ordinary global variables. +Depending on the compiler, possible valid definitions of this macro include +_Thread_local and __thread. +
+
+
SOFTFLOAT_ROUND_ODD +
+Can be defined to enable support for optional rounding mode +softfloat_round_odd. +
+
+
INLINE_LEVEL +
+Can be defined to an integer to determine the degree of inlining requested of +the compiler. +Larger numbers request that more inlining be done. +If this macro is not defined or is defined to a value less than 1 +(zero or negative), no inlining is requested. +The maximum effective value is no higher than 5. +Defining this macro to a value greater than 5 is the same as defining it +to 5. +
SOFTFLOAT_FAST_INT64 +
+Can be defined to indicate that the build target’s implementation of +64-bit arithmetic is efficient. +For newer 64-bit processors, this macro should usually be defined. +For very small microprocessors whose buses and registers are 8-bit +or 16-bit in size, this macro should usually not be defined. +Whether this macro should be defined for a 32-bit processor may +depend on the target machine and the applications that will use SoftFloat. +
SOFTFLOAT_FAST_DIV32TO16 +
+Can be defined to indicate that the target’s division operator +in C (written as /) is reasonably efficient for +dividing a 32-bit unsigned integer by a 16-bit +unsigned integer. +Setting this macro may affect the performance of function f16_div. +
SOFTFLOAT_FAST_DIV64TO32 +
+Can be defined to indicate that the target’s division operator +in C (written as /) is reasonably efficient for +dividing a 64-bit unsigned integer by a 32-bit +unsigned integer. +Setting this macro may affect the performance of division, remainder, and +square root operations other than f16_div. +
+
+

+ +

+Following the usual custom for C, for most of these macros (all +except INLINE, THREAD_LOCAL, and +INLINE_LEVEL), the content of any definition is irrelevant; +what matters is a macro’s effect on #ifdef directives. +

+ +

+It is recommended that any definitions of macros LITTLEENDIAN, +INLINE, and THREAD_LOCAL be made in a build +target’s platform.h header file, because these macros are +expected to be determined inflexibly by the target machine and compiler. +The other five macros select options and control optimization, and thus might +be better located in the target’s Makefile (or its equivalent). +

+ + +

5.4. Adapting a Template Target Directory

+ +

+In the build directory, two template subdirectories +provide models for new target directories. +Two different templates exist because different functions are needed in the +SoftFloat library depending on whether macro SOFTFLOAT_FAST_INT64 +is defined. +If macro SOFTFLOAT_FAST_INT64 will be defined, +template-FAST_INT64 is the template to use; +otherwise, template-not-FAST_INT64 is the appropriate +template. +A new target directory can be created by copying the correct template directory +and editing the files inside. +To avoid confusion, it would be wise to refrain from editing the files within a +template directory directly. +

+ + +

5.5. Target-Specific Optimization of Primitive Functions

+ +

+Header file primitives.h (in directory +source/include) declares macros and functions for numerous +underlying arithmetic operations upon which many of SoftFloat’s +floating-point functions are ultimately built. +The SoftFloat sources include implementations of all of these functions/macros, +written as standard C code, so a complete and correct SoftFloat library can be +created using only the supplied code for all functions. +However, for many targets, SoftFloat’s performance can be improved by +substituting target-specific implementations of some of the functions/macros +declared in primitives.h. +

+ +

+For example, primitives.h declares a function called +softfloat_countLeadingZeros32 that takes an unsigned +32-bit integer as an argument and returns the number of the +integer’s most-significant bits that are zeros. +While the SoftFloat sources include an implementation of this function written +in standard C, many processors can perform this same function +directly in only one or two machine instructions. +An alternative, target-specific implementation that maps to those instructions +is likely to be more efficient than the generic C code from the SoftFloat +package. +

+ +

+A build target can replace the supplied version of any function or macro of +primitives.h by defining a macro with the same name in the +target’s platform.h header file. +For this purpose, it may be helpful for platform.h to +#include header file primitiveTypes.h, which defines +types used for arguments and results of functions declared in +primitives.h. +When a desired replacement implementation is a function, not a macro, it is +sufficient for platform.h to include the line +

+
+#define <function-name> <function-name>
+
+
+where <function-name> is the name of the +function. +This technically defines <function-name> +as a macro, but one that resolves to the same name, which may then be a +function. +(A preprocessor that conforms to the C Standard is required to limit recursive +macro expansion from being applied more than once.) +

+ +

+The supplied header file opts-GCC.h (in directory +source/include) provides an example of target-specific +optimization for the GCC compiler. +Each GCC target example in the build directory has +

+#include "opts-GCC.h" +
+in its platform.h header file. +Before opts-GCC.h is included, the following macros must be +defined (or not) to control which features are invoked: +
+
+
SOFTFLOAT_BUILTIN_CLZ
+
+If defined, SoftFloat’s internal +‘countLeadingZeros’ functions use intrinsics +__builtin_clz and __builtin_clzll. +
+
SOFTFLOAT_INTRINSIC_INT128
+
+If defined, SoftFloat makes use of GCC’s nonstandard 128-bit +integer type __int128. +
+
+
+On some machines, these improvements are observed to increase the speeds of +f64_mul and f128_mul by around 20 to 25%, although +other functions receive less dramatic boosts, or none at all. +Results can vary greatly across different platforms. +

+ + +

6. Testing SoftFloat

+ +

+SoftFloat can be tested using the testsoftfloat program by the +same author. +This program is part of the Berkeley TestFloat package available at the Web +page +http://www.jhauser.us/arithmetic/TestFloat.html. +The TestFloat package also has a program called timesoftfloat that +measures the speed of SoftFloat’s floating-point functions. +

+ + +

7. Providing SoftFloat as a Common Library for Applications

+ +

+Header file softfloat.h defines the SoftFloat interface as seen by +clients. +If the SoftFloat library will be made a common library for programs on a +system, the supplied softfloat.h has a couple of deficiencies for +this purpose: +

    +
  • +As supplied, softfloat.h depends on another header, +softfloat_types.h, that is not intended for public use but which +must also be visible to the programmer’s compiler. +
  • +More troubling, at the time softfloat.h is included in a C source +file, macros SOFTFLOAT_FAST_INT64 and THREAD_LOCAL +must be defined, or not defined, consistent with how these macro were defined +when the SoftFloat library was built. +
+In the situation that new programs may regularly #include header +file softfloat.h, it is recommended that a custom, self-contained +version of this header file be created that eliminates these issues. +

+ + +

8. 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.jhauser.us/arithmetic/SoftFloat.html. +

+ + + + diff --git a/src/softfloat/doc/SoftFloat.html b/src/softfloat/doc/SoftFloat.html new file mode 100644 index 000000000..bb41770ec --- /dev/null +++ b/src/softfloat/doc/SoftFloat.html @@ -0,0 +1,1527 @@ + + + + +Berkeley SoftFloat Library Interface + + + + +

Berkeley SoftFloat Release 3e: Library Interface

+ +

+John R. Hauser
+2018 January 20
+

+ + +

Contents

+ +
+ +++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1. Introduction
2. Limitations
3. Acknowledgments and License
4. Types and Functions
4.1. Boolean and Integer Types
4.2. Floating-Point Types
4.3. Supported Floating-Point Functions
4.4. Non-canonical Representations in extFloat80_t
4.5. Conventions for Passing Arguments and Results
5. Reserved Names
6. Mode Variables
6.1. Rounding Mode
6.2. Underflow Detection
6.3. Rounding Precision for the 80-Bit Extended Format
7. Exceptions and Exception Flags
8. Function Details
8.1. Conversions from Integer to Floating-Point
8.2. Conversions from Floating-Point to Integer
8.3. Conversions Among Floating-Point Types
8.4. Basic Arithmetic Functions
8.5. Fused Multiply-Add Functions
8.6. Remainder Functions
8.7. Round-to-Integer Functions
8.8. Comparison Functions
8.9. Signaling NaN Test Functions
8.10. Raise-Exception Function
9. Changes from SoftFloat Release 2
9.1. Name Changes
9.2. Changes to Function Arguments
9.3. Added Capabilities
9.4. Better Compatibility with the C Language
9.5. New Organization as a Library
9.6. Optimization Gains (and Losses)
10. Future Directions
11. Contact Information
+
+ + +

1. Introduction

+ +

+Berkeley SoftFloat is a software implementation of binary floating-point that +conforms to the IEEE Standard for Floating-Point Arithmetic. +The current release supports five binary formats: 16-bit +half-precision, 32-bit single-precision, 64-bit +double-precision, 80-bit double-extended-precision, and +128-bit quadruple-precision. +The following functions are supported for each format: +

    +
  • +addition, subtraction, multiplication, division, and square root; +
  • +fused multiply-add as defined by the IEEE Standard, except for +80-bit double-extended-precision; +
  • +remainder as defined by the IEEE Standard; +
  • +round to integral value; +
  • +comparisons; +
  • +conversions to/from other supported formats; and +
  • +conversions to/from 32-bit and 64-bit integers, +signed and unsigned. +
+All operations required by the original 1985 version of the IEEE Floating-Point +Standard are implemented, except for conversions to and from decimal. +

+ +

+This document gives information about the types defined and the routines +implemented by SoftFloat. +It does not attempt to define or explain the IEEE Floating-Point Standard. +Information about the standard is available elsewhere. +

+ +

+The current version of SoftFloat is Release 3e. +This release modifies the behavior of the rarely used odd rounding mode +(round to odd, also known as jamming), and also adds some new +specialization and optimization examples for those compiling SoftFloat. +

+ +

+The previous Release 3d fixed bugs that were found in the square +root functions for the 64-bit, 80-bit, and +128-bit floating-point formats. +(Thanks to Alexei Sibidanov at the University of Victoria for reporting an +incorrect result.) +The bugs affected all prior Release-3 versions of SoftFloat +through 3c. +The flaw in the 64-bit floating-point square root function was of +very minor impact, causing a 1-ulp error (1 unit in +the last place) a few times out of a billion. +The bugs in the 80-bit and 128-bit square root +functions were more serious. +Although incorrect results again occurred only a few times out of a billion, +when they did occur a large portion of the less-significant bits could be +wrong. +

+ +

+Among earlier releases, 3b was notable for adding support for the +16-bit half-precision format. +For more about the evolution of SoftFloat releases, see +SoftFloat-history.html. +

+ +

+The functional interface of SoftFloat Release 3 and later differs +in many details from the releases that came before. +For specifics of these differences, see section 9 below, +Changes from SoftFloat Release 2. +

+ + +

2. Limitations

+ +

+SoftFloat assumes the computer has an addressable byte size of 8 or +16 bits. +(Nearly all computers in use today have 8-bit bytes.) +

+ +

+SoftFloat is written in C and is designed to work with other C code. +The C compiler used must conform at a minimum to the 1989 ANSI standard for the +C language (same as the 1990 ISO standard) and must in addition support basic +arithmetic on 64-bit integers. +Earlier releases of SoftFloat included implementations of 32-bit +single-precision and 64-bit double-precision floating-point that +did not require 64-bit integers, but this option is not supported +starting with Release 3. +Since 1999, ISO standards for C have mandated compiler support for +64-bit integers. +A compiler conforming to the 1999 C Standard or later is recommended but not +strictly required. +

+ +

+Most operations not required by the original 1985 version of the IEEE +Floating-Point Standard but added in the 2008 version are not yet supported in +SoftFloat Release 3e. +

+ + +

3. Acknowledgments and License

+ +

+The SoftFloat package was written by me, John R. Hauser. +Release 3 of SoftFloat was a completely new implementation +supplanting earlier releases. +The project to create Release 3 (now through 3e) was +done in the employ of the University of California, Berkeley, within the +Department of Electrical Engineering and Computer Sciences, first for the +Parallel Computing Laboratory (Par Lab) and then for the ASPIRE Lab. +The work was officially overseen by Prof. Krste Asanovic, with funding provided +by these sources: +

+ ++++ + + + + + + + + + +
Par Lab: +Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery +(Award #DIG07-10227), with additional support from Par Lab affiliates Nokia, +NVIDIA, Oracle, and Samsung. +
ASPIRE Lab: +DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from +ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA, +Oracle, and Samsung. +
+
+

+ +

+The following applies to the whole of SoftFloat Release 3e as well +as to each source file individually. +

+ +

+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the +University of California. +All rights reserved. +

+ +

+Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +

    + +
  1. +

    +Redistributions of source code must retain the above copyright notice, this +list of conditions, and the following disclaimer. +

    + +
  2. +

    +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions, and the following disclaimer in the documentation and/or +other materials provided with the distribution. +

    + +
  3. +

    +Neither the name of the University nor the names of its contributors may be +used to endorse or promote products derived from this software without specific +prior written permission. +

    + +
+

+ +

+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS”, +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. +IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +

+ + +

4. Types and Functions

+ +

+The types and functions of SoftFloat are declared in header file +softfloat.h. +

+ +

4.1. Boolean and Integer Types

+ +

+Header file softfloat.h depends on standard headers +<stdbool.h> and <stdint.h> to define type +bool and several integer types. +These standard headers have been part of the ISO C Standard Library since 1999. +With any recent compiler, they are likely to be supported, even if the compiler +does not claim complete conformance to the latest ISO C Standard. +For older or nonstandard compilers, a port of SoftFloat may have substitutes +for these headers. +Header softfloat.h depends only on the name bool from +<stdbool.h> and on these type names from +<stdint.h>: +

+
+uint16_t
+uint32_t
+uint64_t
+int32_t
+int64_t
+uint_fast8_t
+uint_fast32_t
+uint_fast64_t
+int_fast32_t
+int_fast64_t
+
+
+

+ + +

4.2. Floating-Point Types

+ +

+The softfloat.h header defines five floating-point types: +

+ + + + + + + + + + + + + + + + + + + + + +
float16_t16-bit half-precision binary format
float32_t32-bit single-precision binary format
float64_t64-bit double-precision binary format
extFloat80_t   80-bit double-extended-precision binary format (old Intel or +Motorola format)
float128_t128-bit quadruple-precision binary format
+
+The non-extended types are each exactly the size specified: +16 bits for float16_t, 32 bits for +float32_t, 64 bits for float64_t, and +128 bits for float128_t. +Aside from these size requirements, the definitions of all these types may +differ for different ports of SoftFloat to specific systems. +A given port of SoftFloat may or may not define some of the floating-point +types as aliases for the C standard types float, +double, and long double. +

+ +

+Header file softfloat.h also defines a structure, +struct extFloat80M, for the representation of +80-bit double-extended-precision floating-point values in memory. +This structure is the same size as type extFloat80_t and contains +at least these two fields (not necessarily in this order): +

+
+uint16_t signExp;
+uint64_t signif;
+
+
+Field signExp contains the sign and exponent of the floating-point +value, with the sign in the most significant bit (bit 15) and the +encoded exponent in the other 15 bits. +Field signif is the complete 64-bit significand of +the floating-point value. +(In the usual encoding for 80-bit extended floating-point, the +leading 1 bit of normalized numbers is not implicit but is stored +in the most significant bit of the significand.) +

+ +

4.3. Supported Floating-Point Functions

+ +

+SoftFloat implements these arithmetic operations for its floating-point types: +

    +
  • +conversions between any two floating-point formats; +
  • +for each floating-point format, conversions to and from signed and unsigned +32-bit and 64-bit integers; +
  • +for each format, the usual addition, subtraction, multiplication, division, and +square root operations; +
  • +for each format except extFloat80_t, the fused multiply-add +operation defined by the IEEE Standard; +
  • +for each format, the floating-point remainder operation defined by the IEEE +Standard; +
  • +for each format, a “round to integer” operation that rounds to the +nearest integer value in the same format; and +
  • +comparisons between two values in the same floating-point format. +
+

+ +

+The following operations required by the 2008 IEEE Floating-Point Standard are +not supported in SoftFloat Release 3e: +

    +
  • +nextUp, nextDown, minNum, maxNum, minNumMag, +maxNumMag, scaleB, and logB; +
  • +conversions between floating-point formats and decimal or hexadecimal character +sequences; +
  • +all “quiet-computation” operations (copy, negate, +abs, and copySign, which all involve only simple copying and/or +manipulation of the floating-point sign bit); and +
  • +all “non-computational” operations other than isSignaling +(which is supported). +
+

+ +

4.4. Non-canonical Representations in extFloat80_t

+ +

+Because the 80-bit double-extended-precision format, +extFloat80_t, stores an explicit leading significand bit, many +finite floating-point numbers are encodable in this type in multiple equivalent +forms. +Of these multiple encodings, there is always a unique one with the least +encoded exponent value, and this encoding is considered the canonical +representation of the floating-point number. +Any other equivalent representations (having a higher encoded exponent value) +are non-canonical. +For a value in the subnormal range (including zero), the canonical +representation always has an encoded exponent of zero and a leading significand +bit of 0. +For finite values outside the subnormal range, the canonical representation +always has an encoded exponent that is nonzero and a leading significand bit +of 1. +

+ +

+For an infinity or NaN, the leading significand bit is similarly expected to +be 1. +An infinity or NaN with a leading significand bit of 0 is again +considered non-canonical. +Hence, altogether, to be canonical, a value of type extFloat80_t +must have a leading significand bit of 1, unless the value is +subnormal or zero, in which case the leading significand bit and the encoded +exponent must both be zero. +

+ +

+SoftFloat’s functions are not guaranteed to operate as expected when +inputs of type extFloat80_t are non-canonical. +Assuming all of a function’s extFloat80_t inputs (if any) +are canonical, function outputs of type extFloat80_t will always +be canonical. +

+ +

4.5. Conventions for Passing Arguments and Results

+ +

+Values that are at most 64 bits in size (i.e., not the +80-bit or 128-bit floating-point formats) are in all +cases passed as function arguments by value. +Likewise, when an output of a function is no more than 64 bits, it +is always returned directly as the function result. +Thus, for example, the SoftFloat function for adding two 64-bit +floating-point values has this simple signature: +

+float64_t f64_add( float64_t, float64_t ); +
+

+ +

+The story is more complex when function inputs and outputs are +80-bit and 128-bit floating-point. +For these types, SoftFloat always provides a function that passes these larger +values into or out of the function indirectly, via pointers. +For example, for adding two 128-bit floating-point values, +SoftFloat supplies this function: +

+void f128M_add( const float128_t *, const float128_t *, float128_t * ); +
+The first two arguments point to the values to be added, and the last argument +points to the location where the sum will be stored. +The M in the name f128M_add is mnemonic for the fact +that the 128-bit inputs and outputs are “in memory”, +pointed to by pointer arguments. +

+ +

+All ports of SoftFloat implement these pass-by-pointer functions for +types extFloat80_t and float128_t. +At the same time, SoftFloat ports may also implement alternate versions of +these same functions that pass extFloat80_t and +float128_t by value, like the smaller formats. +Thus, besides the function with name f128M_add shown above, a +SoftFloat port may also supply an equivalent function with this signature: +

+float128_t f128_add( float128_t, float128_t ); +
+

+ +

+As a general rule, on computers where the machine word size is +32 bits or smaller, only the pass-by-pointer versions of functions +(e.g., f128M_add) are provided for types extFloat80_t +and float128_t, because passing such large types directly can have +significant extra cost. +On computers where the word size is 64 bits or larger, both +function versions (f128M_add and f128_add) are +provided, because the cost of passing by value is then more reasonable. +Applications that must be portable accross both classes of computers must use +the pointer-based functions, as these are always implemented. +However, if it is known that SoftFloat includes the by-value functions for all +platforms of interest, programmers can use whichever version they prefer. +

+ + +

5. Reserved Names

+ +

+In addition to the variables and functions documented here, SoftFloat defines +some symbol names for its own private use. +These private names always begin with the prefix +‘softfloat_’. +When a program includes header softfloat.h or links with the +SoftFloat library, all names with prefix ‘softfloat_’ +are reserved for possible use by SoftFloat. +Applications that use SoftFloat should not define their own names with this +prefix, and should reference only such names as are documented. +

+ + +

6. Mode Variables

+ +

+The following global variables control rounding mode, underflow detection, and +the 80-bit extended format’s rounding precision: +

+softfloat_roundingMode
+softfloat_detectTininess
+extF80_roundingPrecision +
+These mode variables are covered in the next several subsections. +For some SoftFloat ports, these variables may be per-thread (declared +thread_local), meaning that different execution threads have their +own separate copies of the variables. +

+ +

6.1. Rounding Mode

+ +

+All five rounding modes defined by the 2008 IEEE Floating-Point Standard are +implemented for all operations that require rounding. +Some ports of SoftFloat may also implement the round-to-odd mode. +

+ +

+The rounding mode is selected by the global variable +

+uint_fast8_t softfloat_roundingMode; +
+This variable may be set to one of the values +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
softfloat_round_near_evenround to nearest, with ties to even
softfloat_round_near_maxMag  round to nearest, with ties to maximum magnitude (away from zero)
softfloat_round_minMaground to minimum magnitude (toward zero)
softfloat_round_minround to minimum (down)
softfloat_round_maxround to maximum (up)
softfloat_round_oddround to odd (jamming), if supported by the SoftFloat port
+
+Variable softfloat_roundingMode is initialized to +softfloat_round_near_even. +

+ +

+When softfloat_round_odd is the rounding mode for a function that +rounds to an integer value (either conversion to an integer format or a +‘roundToInt’ function), if the input is not already an +integer, the rounded result is the closest odd integer. +For other operations, this rounding mode acts as though the floating-point +result is first rounded to minimum magnitude, the same as +softfloat_round_minMag, and then, if the result is inexact, the +least-significant bit of the result is set to 1. +Rounding to odd is also known as jamming. +

+ +

6.2. Underflow Detection

+ +

+In the terminology of the IEEE Standard, SoftFloat can detect tininess for +underflow either before or after rounding. +The choice is made by the global variable +

+uint_fast8_t softfloat_detectTininess; +
+which can be set to either +
+softfloat_tininess_beforeRounding
+softfloat_tininess_afterRounding +
+Detecting tininess after rounding is usually better because it results in fewer +spurious underflow signals. +The other option is provided for compatibility with some systems. +Like most systems (and as required by the newer 2008 IEEE Standard), SoftFloat +always detects loss of accuracy for underflow as an inexact result. +

+ +

6.3. Rounding Precision for the 80-Bit Extended Format

+ +

+For extFloat80_t only, the rounding precision of the basic +arithmetic operations is controlled by the global variable +

+uint_fast8_t extF80_roundingPrecision; +
+The operations affected are: +
+extF80_add
+extF80_sub
+extF80_mul
+extF80_div
+extF80_sqrt +
+When extF80_roundingPrecision is set to its default value of 80, +these operations are rounded to the full precision of the 80-bit +double-extended-precision format, like occurs for other formats. +Setting extF80_roundingPrecision to 32 or to 64 causes the +operations listed to be rounded to 32-bit precision (equivalent to +float32_t) or to 64-bit precision (equivalent to +float64_t), respectively. +When rounding to reduced precision, additional bits in the result significand +beyond the rounding point are set to zero. +The consequences of setting extF80_roundingPrecision to a value +other than 32, 64, or 80 is not specified. +Operations other than the ones listed above are not affected by +extF80_roundingPrecision. +

+ + +

7. Exceptions and Exception Flags

+ +

+All five exception flags required by the IEEE Floating-Point Standard are +implemented. +Each flag is stored as a separate bit in the global variable +

+uint_fast8_t softfloat_exceptionFlags; +
+The positions of the exception flag bits within this variable are determined by +the bit masks +
+softfloat_flag_inexact
+softfloat_flag_underflow
+softfloat_flag_overflow
+softfloat_flag_infinite
+softfloat_flag_invalid +
+Variable softfloat_exceptionFlags is initialized to all zeros, +meaning no exceptions. +

+ +

+For some SoftFloat ports, softfloat_exceptionFlags may be +per-thread (declared thread_local), meaning that different +execution threads have their own separate instances of it. +

+ +

+An individual exception flag can be cleared with the statement +

+softfloat_exceptionFlags &= ~softfloat_flag_<exception>; +
+where <exception> is the appropriate name. +To raise a floating-point exception, function softfloat_raiseFlags +should normally be used. +

+ +

+When SoftFloat detects an exception other than inexact, it calls +softfloat_raiseFlags. +The default version of this function simply raises the corresponding exception +flags. +Particular ports of SoftFloat may support alternate behavior, such as exception +traps, by modifying the default softfloat_raiseFlags. +A program may also supply its own softfloat_raiseFlags function to +override the one from the SoftFloat library. +

+ +

+Because inexact results occur frequently under most circumstances (and thus are +hardly exceptional), SoftFloat does not ordinarily call +softfloat_raiseFlags for inexact exceptions. +It does always raise the inexact exception flag as required. +

+ + +

8. Function Details

+ +

+In this section, <float> appears in function names as +a substitute for one of these abbreviations: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
f16indicates float16_t, passed by value
f32indicates float32_t, passed by value
f64indicates float64_t, passed by value
extF80M   indicates extFloat80_t, passed indirectly via pointers
extF80indicates extFloat80_t, passed by value
f128Mindicates float128_t, passed indirectly via pointers
f128indicates float128_t, passed by value
+
+The circumstances under which values of floating-point types +extFloat80_t and float128_t may be passed either by +value or indirectly via pointers was discussed earlier in +section 4.5, Conventions for Passing Arguments and Results. +

+ +

8.1. Conversions from Integer to Floating-Point

+ +

+All conversions from a 32-bit or 64-bit integer, +signed or unsigned, to a floating-point format are supported. +Functions performing these conversions have these names: +

+ui32_to_<float>
+ui64_to_<float>
+i32_to_<float>
+i64_to_<float> +
+Conversions from 32-bit integers to 64-bit +double-precision and larger formats are always exact, and likewise conversions +from 64-bit integers to 80-bit +double-extended-precision and 128-bit quadruple-precision are also +always exact. +

+ +

+Each conversion function takes one input of the appropriate type and generates +one output. +The following illustrates the signatures of these functions in cases when the +floating-point result is passed either by value or via pointers: +

+
+float64_t i32_to_f64( int32_t a );
+
+
+void i32_to_f128M( int32_t a, float128_t *destPtr );
+
+
+

+ +

8.2. Conversions from Floating-Point to Integer

+ +

+Conversions from a floating-point format to a 32-bit or +64-bit integer, signed or unsigned, are supported with these +functions: +

+<float>_to_ui32
+<float>_to_ui64
+<float>_to_i32
+<float>_to_i64 +
+The functions have signatures as follows, depending on whether the +floating-point input is passed by value or via pointers: +
+
+int_fast32_t f64_to_i32( float64_t a, uint_fast8_t roundingMode, bool exact );
+
+
+int_fast32_t
+ f128M_to_i32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact );
+
+
+

+ +

+The roundingMode argument specifies the rounding mode for +the conversion. +The variable that usually indicates rounding mode, +softfloat_roundingMode, is ignored. +Argument exact determines whether the inexact +exception flag is raised if the conversion is not exact. +If exact is true, the inexact flag may +be raised; +otherwise, it will not be, even if the conversion is inexact. +

+ +

+A conversion from floating-point to integer format raises the invalid +exception if the source value cannot be rounded to a representable integer of +the desired size (32 or 64 bits). +In such circumstances, the integer result returned is determined by the +particular port of SoftFloat, although typically this value will be either the +maximum or minimum value of the integer format. +The functions that convert to integer types never raise the floating-point +overflow exception. +

+ +

+Because languages such as C require that conversions to integers +be rounded toward zero, the following functions are provided for improved speed +and convenience: +

+<float>_to_ui32_r_minMag
+<float>_to_ui64_r_minMag
+<float>_to_i32_r_minMag
+<float>_to_i64_r_minMag +
+These functions round only toward zero (to minimum magnitude). +The signatures for these functions are the same as above without the redundant +roundingMode argument: +
+
+int_fast32_t f64_to_i32_r_minMag( float64_t a, bool exact );
+
+
+int_fast32_t f128M_to_i32_r_minMag( const float128_t *aPtr, bool exact );
+
+
+

+ +

8.3. Conversions Among Floating-Point Types

+ +

+Conversions between floating-point formats are done by functions with these +names: +

+<float>_to_<float> +
+All combinations of source and result type are supported where the source and +result are different formats. +There are four different styles of signature for these functions, depending on +whether the input and the output floating-point values are passed by value or +via pointers: +
+
+float32_t f64_to_f32( float64_t a );
+
+
+float32_t f128M_to_f32( const float128_t *aPtr );
+
+
+void f32_to_f128M( float32_t a, float128_t *destPtr );
+
+
+void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *destPtr );
+
+
+

+ +

+Conversions from a smaller to a larger floating-point format are always exact +and so require no rounding. +

+ +

8.4. Basic Arithmetic Functions

+ +

+The following basic arithmetic functions are provided: +

+<float>_add
+<float>_sub
+<float>_mul
+<float>_div
+<float>_sqrt +
+Each floating-point operation takes two operands, except for sqrt +(square root) which takes only one. +The operands and result are all of the same floating-point format. +Signatures for these functions take the following forms: +
+
+float64_t f64_add( float64_t a, float64_t b );
+
+
+void
+ f128M_add(
+     const float128_t *aPtr, const float128_t *bPtr, float128_t *destPtr );
+
+
+float64_t f64_sqrt( float64_t a );
+
+
+void f128M_sqrt( const float128_t *aPtr, float128_t *destPtr );
+
+
+When floating-point values are passed indirectly through pointers, arguments +aPtr and bPtr point to the input +operands, and the last argument, destPtr, points to the +location where the result is stored. +

+ +

+Rounding of the 80-bit double-extended-precision +(extFloat80_t) functions is affected by variable +extF80_roundingPrecision, as explained earlier in +section 6.3, +Rounding Precision for the 80-Bit Extended Format. +

+ +

8.5. Fused Multiply-Add Functions

+ +

+The 2008 version of the IEEE Floating-Point Standard defines a fused +multiply-add operation that does a combined multiplication and addition +with only a single rounding. +SoftFloat implements fused multiply-add with functions +

+<float>_mulAdd +
+Unlike other operations, fused multiple-add is not supported for the +80-bit double-extended-precision format, +extFloat80_t. +

+ +

+Depending on whether floating-point values are passed by value or via pointers, +the fused multiply-add functions have signatures of these forms: +

+
+float64_t f64_mulAdd( float64_t a, float64_t b, float64_t c );
+
+
+void
+ f128M_mulAdd(
+     const float128_t *aPtr,
+     const float128_t *bPtr,
+     const float128_t *cPtr,
+     float128_t *destPtr
+ );
+
+
+The functions compute +(a × b) + + c +with a single rounding. +When floating-point values are passed indirectly through pointers, arguments +aPtr, bPtr, and +cPtr point to operands a, +b, and c respectively, and +destPtr points to the location where the result is stored. +

+ +

+If one of the multiplication operands a and +b is infinite and the other is zero, these functions raise +the invalid exception even if operand c is a quiet NaN. +

+ +

8.6. Remainder Functions

+ +

+For each format, SoftFloat implements the remainder operation defined by the +IEEE Floating-Point Standard. +The remainder functions have names +

+<float>_rem +
+Each remainder operation takes two floating-point operands of the same format +and returns a result in the same format. +Depending on whether floating-point values are passed by value or via pointers, +the remainder functions have signatures of these forms: +
+
+float64_t f64_rem( float64_t a, float64_t b );
+
+
+void
+ f128M_rem(
+     const float128_t *aPtr, const float128_t *bPtr, float128_t *destPtr );
+
+
+When floating-point values are passed indirectly through pointers, arguments +aPtr and bPtr point to operands +a and b respectively, and +destPtr points to the location where the result is stored. +

+ +

+The IEEE Standard remainder operation computes the value +a + − n × b, +where n is the integer closest to +a ÷ b. +If a ÷ b is exactly +halfway between two integers, n is the even integer closest to +a ÷ b. +The IEEE Standard’s remainder operation is always exact and so requires +no rounding. +

+ +

+Depending on the relative magnitudes of the operands, the remainder +functions can take considerably longer to execute than the other SoftFloat +functions. +This is an inherent characteristic of the remainder operation itself and is not +a flaw in the SoftFloat implementation. +

+ +

8.7. Round-to-Integer Functions

+ +

+For each format, SoftFloat implements the round-to-integer operation specified +by the IEEE Floating-Point Standard. +These functions are named +

+<float>_roundToInt +
+Each round-to-integer operation takes a single floating-point operand. +This operand is rounded to an integer according to a specified rounding mode, +and the resulting integer value is returned in the same floating-point format. +(Note that the result is not an integer type.) +

+ +

+The signatures of the round-to-integer functions are similar to those for +conversions to an integer type: +

+
+float64_t f64_roundToInt( float64_t a, uint_fast8_t roundingMode, bool exact );
+
+
+void
+ f128M_roundToInt(
+     const float128_t *aPtr,
+     uint_fast8_t roundingMode,
+     bool exact,
+     float128_t *destPtr
+ );
+
+
+When floating-point values are passed indirectly through pointers, +aPtr points to the input operand and +destPtr points to the location where the result is stored. +

+ +

+The roundingMode argument specifies the rounding mode to +apply. +The variable that usually indicates rounding mode, +softfloat_roundingMode, is ignored. +Argument exact determines whether the inexact +exception flag is raised if the conversion is not exact. +If exact is true, the inexact flag may +be raised; +otherwise, it will not be, even if the conversion is inexact. +

+ +

8.8. Comparison Functions

+ +

+For each format, the following floating-point comparison functions are +provided: +

+<float>_eq
+<float>_le
+<float>_lt +
+Each comparison takes two operands of the same type and returns a Boolean. +The abbreviation eq stands for “equal” (=); +le stands for “less than or equal” (≤); +and lt stands for “less than” (<). +Depending on whether the floating-point operands are passed by value or via +pointers, the comparison functions have signatures of these forms: +
+
+bool f64_eq( float64_t a, float64_t b );
+
+
+bool f128M_eq( const float128_t *aPtr, const float128_t *bPtr );
+
+
+

+ +

+The usual greater-than (>), greater-than-or-equal (≥), and not-equal +(≠) comparisons are easily obtained from the functions provided. +The not-equal function is just the logical complement of the equal function. +The greater-than-or-equal function is identical to the less-than-or-equal +function with the arguments in reverse order, and likewise the greater-than +function is identical to the less-than function with the arguments reversed. +

+ +

+The IEEE Floating-Point Standard specifies that the less-than-or-equal and +less-than comparisons by default raise the invalid exception if either +operand is any kind of NaN. +Equality comparisons, on the other hand, are defined by default to raise the +invalid exception only for signaling NaNs, not quiet NaNs. +For completeness, SoftFloat provides these complementary functions: +

+<float>_eq_signaling
+<float>_le_quiet
+<float>_lt_quiet +
+The signaling equality comparisons are identical to the default +equality comparisons except that the invalid exception is raised for any +NaN input, not just for signaling NaNs. +Similarly, the quiet comparison functions are identical to their +default counterparts except that the invalid exception is not raised for +quiet NaNs. +

+ +

8.9. Signaling NaN Test Functions

+ +

+Functions for testing whether a floating-point value is a signaling NaN are +provided with these names: +

+<float>_isSignalingNaN +
+The functions take one floating-point operand and return a Boolean indicating +whether the operand is a signaling NaN. +Accordingly, the functions have the forms +
+
+bool f64_isSignalingNaN( float64_t a );
+
+
+bool f128M_isSignalingNaN( const float128_t *aPtr );
+
+
+

+ +

8.10. Raise-Exception Function

+ +

+SoftFloat provides a single function for raising floating-point exceptions: +

+
+void softfloat_raiseFlags( uint_fast8_t exceptions );
+
+
+The exceptions argument is a mask indicating the set of +exceptions to raise. +(See earlier section 7, Exceptions and Exception Flags.) +In addition to setting the specified exception flags in variable +softfloat_exceptionFlags, the softfloat_raiseFlags +function may cause a trap or abort appropriate for the current system. +

+ + +

9. Changes from SoftFloat Release 2

+ +

+Apart from a change in the legal use license, Release 3 of +SoftFloat introduced numerous technical differences compared to earlier +releases. +

+ +

9.1. Name Changes

+ +

+The most obvious and pervasive difference compared to Release 2 +is that the names of most functions and variables have changed, even when the +behavior has not. +First, the floating-point types, the mode variables, the exception flags +variable, the function to raise exceptions, and various associated constants +have been renamed as follows: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
old name, Release 2:new name, Release 3:
float32float32_t
float64float64_t
floatx80extFloat80_t
float128float128_t
float_rounding_modesoftfloat_roundingMode
float_round_nearest_evensoftfloat_round_near_even
float_round_to_zerosoftfloat_round_minMag
float_round_downsoftfloat_round_min
float_round_upsoftfloat_round_max
float_detect_tininesssoftfloat_detectTininess
float_tininess_before_rounding    softfloat_tininess_beforeRounding
float_tininess_after_roundingsoftfloat_tininess_afterRounding
floatx80_rounding_precisionextF80_roundingPrecision
float_exception_flagssoftfloat_exceptionFlags
float_flag_inexactsoftfloat_flag_inexact
float_flag_underflowsoftfloat_flag_underflow
float_flag_overflowsoftfloat_flag_overflow
float_flag_divbyzerosoftfloat_flag_infinite
float_flag_invalidsoftfloat_flag_invalid
float_raisesoftfloat_raiseFlags
+
+

+ +

+Furthermore, Release 3 adopted the following new abbreviations for +function names: +

+ + + + + + + + + + + +
used in names in Release 2:    used in names in Release 3:
int32 i32
int64 i64
float32 f32
float64 f64
floatx80 extF80
float128 f128
+
+Thus, for example, the function to add two 32-bit floating-point +numbers, previously called float32_add in Release 2, +is now f32_add. +Lastly, there have been a few other changes to function names: +
+ + + + + + + + + + + + + + + + + + + + + +
used in names in Release 2:   used in names in Release 3:   relevant functions:
_round_to_zero_r_minMagconversions from floating-point to integer (section 8.2)
round_to_introundToIntround-to-integer functions (section 8.7)
is_signaling_nan    isSignalingNaNsignaling NaN test functions (section 8.9)
+
+

+ +

9.2. Changes to Function Arguments

+ +

+Besides simple name changes, some operations were given a different interface +in Release 3 than they had in Release 2: +

    + +
  • +

    +Since Release 3, integer arguments and results of functions have +standard types from header <stdint.h>, such as +uint32_t, whereas previously their types could be defined +differently for each port of SoftFloat, usually using traditional C types such +as unsigned int. +Likewise, functions in Release 3 and later pass Booleans as +standard type bool from <stdbool.h>, whereas +previously these were again passed as a port-specific type (usually +int). +

    + +
  • +

    +As explained earlier in section 4.5, Conventions for Passing +Arguments and Results, SoftFloat functions in Release 3 and +later may pass 80-bit and 128-bit floating-point +values through pointers, meaning that functions take pointer arguments and then +read or write floating-point values at the locations indicated by the pointers. +In Release 2, floating-point arguments and results were always +passed by value, regardless of their size. +

    + +
  • +

    +Functions that round to an integer have additional +roundingMode and exact arguments that +they did not have in Release 2. +Refer to sections 8.2 and 8.7 for descriptions of these functions +since Release 3. +For Release 2, the rounding mode, when needed, was taken from the +same global variable that affects the basic arithmetic operations (now called +softfloat_roundingMode but previously known as +float_rounding_mode). +Also, for Release 2, if the original floating-point input was not +an exact integer value, and if the invalid exception was not raised by +the function, the inexact exception was always raised. +Release 2 had no option to suppress raising inexact in this +case. +Applications using SoftFloat Release 3 or later can get the same +effect as Release 2 by passing variable +softfloat_roundingMode for argument +roundingMode and true for argument +exact. +

    + +
+

+ +

9.3. Added Capabilities

+ +

+With Release 3, some new features have been added that were not +present in Release 2: +

    + +
  • +

    +A port of SoftFloat can now define any of the floating-point types +float32_t, float64_t, extFloat80_t, and +float128_t as aliases for C’s standard floating-point types +float, double, and long +double, using either #define or typedef. +This potential convenience was not supported under Release 2. +

    + +

    +(Note, however, that there may be a performance cost to defining +SoftFloat’s floating-point types this way, depending on the platform and +the applications using SoftFloat. +Ports of SoftFloat may choose to forgo the convenience in favor of better +speed.) +

    + +

    +

  • +As of Release 3b, 16-bit half-precision, +float16_t, is supported. +

    + +

    +

  • +Functions have been added for converting between the floating-point types and +unsigned integers. +Release 2 supported only signed integers, not unsigned. +

    + +

    +

  • +Fused multiply-add functions have been added for all floating-point formats +except 80-bit double-extended-precision, +extFloat80_t. +

    + +

    +

  • +New rounding modes are supported: +softfloat_round_near_maxMag (round to nearest, with ties to +maximum magnitude, away from zero), and, as of Release 3c, +optional softfloat_round_odd (round to odd, also known as +jamming). +

    + +
+

+ +

9.4. Better Compatibility with the C Language

+ +

+Release 3 of SoftFloat was written to conform better to the ISO C +Standard’s rules for portability. +For example, older releases of SoftFloat employed type conversions in ways +that, while commonly practiced, are not fully defined by the C Standard. +Such problematic type conversions have generally been replaced by the use of +unions, the behavior around which is more strictly regulated these days. +

+ +

9.5. New Organization as a Library

+ +

+Starting with Release 3, SoftFloat now builds as a library. +Previously, SoftFloat compiled into a single, monolithic object file containing +all the SoftFloat functions, with the consequence that a program linking with +SoftFloat would get every SoftFloat function in its binary file even if only a +few functions were actually used. +With SoftFloat in the form of a library, a program that is linked by a standard +linker will include only those functions of SoftFloat that it needs and no +others. +

+ +

9.6. Optimization Gains (and Losses)

+ +

+Individual SoftFloat functions have been variously improved in +Release 3 compared to earlier releases. +In particular, better, faster algorithms have been deployed for the operations +of division, square root, and remainder. +For functions operating on the larger 80-bit and +128-bit formats, extFloat80_t and +float128_t, code size has also generally been reduced. +

+ +

+However, because Release 2 compiled all of SoftFloat together as a +single object file, compilers could make optimizations across function calls +when one SoftFloat function calls another. +Now that the functions of SoftFloat are compiled separately and only afterward +linked together into a program, there is not usually the same opportunity to +optimize across function calls. +Some loss of speed has been observed due to this change. +

+ + +

10. Future Directions

+ +

+The following improvements are anticipated for future releases of SoftFloat: +

    +
  • +more functions from the 2008 version of the IEEE Floating-Point Standard; +
  • +consistent, defined behavior for non-canonical representations of extended +format extFloat80_t (discussed in section 4.4, +Non-canonical Representations in extFloat80_t). + +
+

+ + +

11. 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.jhauser.us/arithmetic/SoftFloat.html. +

+ + + + diff --git a/src/softfloat/doc/eZ80-SoftFloat.txt b/src/softfloat/doc/eZ80-SoftFloat.txt new file mode 100644 index 000000000..cd9ff2197 --- /dev/null +++ b/src/softfloat/doc/eZ80-SoftFloat.txt @@ -0,0 +1,40 @@ +Berkeley SoftFloat-3e is an IEEE conformant software floating-point library. It is written in C89, and supports 16, 32, 64, 80, and 128bit floating-point formats. + +It has been choosen to implement 64bit `long double` on the Ti84CE, using the following functions: +Arithmetic: +* f64_add +* f64_sub +* f64_mul +* f64_div +* f64_rem +* f64_mulAdd (Fused-multiply add) +* f64_sqrt +Conversion: +* f32_to_f64 +* f64_to_f32 +* f64_to_i32_r_minMag +* f64_to_i64_r_minMag +* f64_to_ui32_r_minMag +* f64_to_ui64_r_minMag +* f64_to_i32 +* f64_to_i64 +* i32_to_f64 +* i64_to_f64 +* ui32_to_f64 +* ui64_to_f64 +* f64_roundToInt + +The SoftFloat library is configured to use the `8086-SSE` rules for NaN propagation, but this can customized, and possibly disabled to reduce binary size. A program using all of the above routines compiled to ~30kb with `-Oz -flto` (~34kb with `fmaf`). SoftFloat also supports an `INLINE_LEVEL` macro, setting it to `0-1` gave a binary size of 34449 bytes, and setting it to `2-5` gave a binary size of 34837 bytes. The size difference in `lto.src` comes from `_f64_add`, `_f64_sub`, `_dadd`, and `_dsub`. + +Every unused source file from `SoftFloat-3e/source` has been exlucded to speed up compile times. + +The following files are used for implementing `float fmaf(float, float, float)`, but are not needed for `long double`: +* SoftFloat-3e/source/f32_mulAdd.c +* SoftFloat-3e/source/s_mulAddF32.c +* SoftFloat-3e/source/8086-SSE/s_propagateNaNF32UI.c + +The following files may or may not be needed at -O0, or when `SOFTFLOAT_BUILTIN_CLZ` is not defined in `platform.h`: +* SoftFloat-3e/source/s_countLeadingZeros8.c +* SoftFloat-3e/source/s_countLeadingZeros16.c +* SoftFloat-3e/source/s_countLeadingZeros32.c +* SoftFloat-3e/source/s_countLeadingZeros64.c diff --git a/src/softfloat/f32_mulAdd.c b/src/softfloat/f32_mulAdd.c new file mode 100644 index 000000000..b77777e4e --- /dev/null +++ b/src/softfloat/f32_mulAdd.c @@ -0,0 +1,60 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float32_t f32_mulAdd( float32_t a, float32_t b, float32_t c ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + union ui32_f32 uC; + uint_fast32_t uiC; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + uC.f = c; + uiC = uC.ui; + return softfloat_mulAddF32( uiA, uiB, uiC, 0 ); + +} + diff --git a/src/softfloat/f32_to_f64.c b/src/softfloat/f32_to_f64.c new file mode 100644 index 000000000..6cd08eddb --- /dev/null +++ b/src/softfloat/f32_to_f64.c @@ -0,0 +1,93 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f32_to_f64( float32_t a ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool sign; + int_fast16_t exp; + uint_fast32_t frac; + struct commonNaN commonNaN; + uint_fast64_t uiZ; + struct exp16_sig32 normExpSig; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + frac = fracF32UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp == 0xFF ) { + if ( frac ) { + softfloat_f32UIToCommonNaN( uiA, &commonNaN ); + uiZ = softfloat_commonNaNToF64UI( &commonNaN ); + } else { + uiZ = packToF64UI( sign, 0x7FF, 0 ); + } + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! exp ) { + if ( ! frac ) { + uiZ = packToF64UI( sign, 0, 0 ); + goto uiZ; + } + normExpSig = softfloat_normSubnormalF32Sig( frac ); + exp = normExpSig.exp - 1; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ = packToF64UI( sign, exp + 0x380, (uint_fast64_t) frac<<29 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/src/softfloat/f64_add.c b/src/softfloat/f64_add.c new file mode 100644 index 000000000..878f6da75 --- /dev/null +++ b/src/softfloat/f64_add.c @@ -0,0 +1,74 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t f64_add( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool signA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) + float64_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, bool ); +#endif + + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF64UI( uiB ); +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) + if ( signA == signB ) { + return softfloat_addMagsF64( uiA, uiB, signA ); + } else { + return softfloat_subMagsF64( uiA, uiB, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_addMagsF64 : softfloat_subMagsF64; + return (*magsFuncPtr)( uiA, uiB, signA ); +#endif + +} + diff --git a/src/softfloat/f64_div.c b/src/softfloat/f64_div.c new file mode 100644 index 000000000..7f5eddd4a --- /dev/null +++ b/src/softfloat/f64_div.c @@ -0,0 +1,172 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f64_div( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool signA; + int_fast16_t expA; + uint_fast64_t sigA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signB; + int_fast16_t expB; + uint_fast64_t sigB; + bool signZ; + struct exp16_sig64 normExpSig; + int_fast16_t expZ; + uint32_t recip32, sig32Z, doubleTerm; + uint_fast64_t rem; + uint32_t q; + uint_fast64_t sigZ; + uint_fast64_t uiZ; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF64UI( uiB ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA ) goto propagateNaN; + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + goto invalid; + } + goto infinity; + } + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expB ) { + if ( ! sigB ) { + if ( ! (expA | sigA) ) goto invalid; + softfloat_raiseFlags( softfloat_flag_infinite ); + goto infinity; + } + normExpSig = softfloat_normSubnormalF64Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if ( ! expA ) { + if ( ! sigA ) goto zero; + normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x3FE; + sigA |= UINT64_C( 0x0010000000000000 ); + sigB |= UINT64_C( 0x0010000000000000 ); + if ( sigA < sigB ) { + --expZ; + sigA <<= 11; + } else { + sigA <<= 10; + } + sigB <<= 11; + recip32 = softfloat_approxRecip32_1( sigB>>32 ) - 2; + sig32Z = ((uint32_t) (sigA>>32) * (uint_fast64_t) recip32)>>32; + doubleTerm = sig32Z<<1; + rem = + ((sigA - (uint_fast64_t) doubleTerm * (uint32_t) (sigB>>32))<<28) + - (uint_fast64_t) doubleTerm * ((uint32_t) sigB>>4); + q = (((uint32_t) (rem>>32) * (uint_fast64_t) recip32)>>32) + 4; + sigZ = ((uint_fast64_t) sig32Z<<32) + ((uint_fast64_t) q<<4); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (sigZ & 0x1FF) < 4<<4 ) { + q &= ~7; + sigZ &= ~(uint_fast64_t) 0x7F; + doubleTerm = q<<1; + rem = + ((rem - (uint_fast64_t) doubleTerm * (uint32_t) (sigB>>32))<<28) + - (uint_fast64_t) doubleTerm * ((uint32_t) sigB>>4); + if ( rem & UINT64_C( 0x8000000000000000 ) ) { + sigZ -= 1<<7; + } else { + if ( rem ) sigZ |= 1; + } + } + return softfloat_roundPackToF64( signZ, expZ, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + uiZ = packToF64UI( signZ, 0x7FF, 0 ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ = packToF64UI( signZ, 0, 0 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/src/softfloat/f64_mul.c b/src/softfloat/f64_mul.c new file mode 100644 index 000000000..38bdc852a --- /dev/null +++ b/src/softfloat/f64_mul.c @@ -0,0 +1,150 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f64_mul( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool signA; + int_fast16_t expA; + uint_fast64_t sigA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signB; + int_fast16_t expB; + uint_fast64_t sigB; + bool signZ; + uint_fast64_t magBits; + struct exp16_sig64 normExpSig; + int_fast16_t expZ; +#ifdef SOFTFLOAT_FAST_INT64 + struct uint128 sig128Z; +#else + uint32_t sig128Z[4]; +#endif + uint_fast64_t sigZ, uiZ; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF64UI( uiB ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN; + magBits = expB | sigB; + goto infArg; + } + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + magBits = expA | sigA; + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! sigA ) goto zero; + normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) { + if ( ! sigB ) goto zero; + normExpSig = softfloat_normSubnormalF64Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FF; + sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10; + sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<11; +#ifdef SOFTFLOAT_FAST_INT64 + sig128Z = softfloat_mul64To128( sigA, sigB ); + sigZ = sig128Z.v64 | (sig128Z.v0 != 0); +#else + softfloat_mul64To128M( sigA, sigB, sig128Z ); + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; + if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) sigZ |= 1; +#endif + if ( sigZ < UINT64_C( 0x4000000000000000 ) ) { + --expZ; + sigZ <<= 1; + } + return softfloat_roundPackToF64( signZ, expZ, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if ( ! magBits ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + } else { + uiZ = packToF64UI( signZ, 0x7FF, 0 ); + } + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ = packToF64UI( signZ, 0, 0 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/src/softfloat/f64_mulAdd.c b/src/softfloat/f64_mulAdd.c new file mode 100644 index 000000000..13fc38287 --- /dev/null +++ b/src/softfloat/f64_mulAdd.c @@ -0,0 +1,60 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t f64_mulAdd( float64_t a, float64_t b, float64_t c ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + union ui64_f64 uC; + uint_fast64_t uiC; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + uC.f = c; + uiC = uC.ui; + return softfloat_mulAddF64( uiA, uiB, uiC, 0 ); + +} + diff --git a/src/softfloat/f64_rem.c b/src/softfloat/f64_rem.c new file mode 100644 index 000000000..ca5350c94 --- /dev/null +++ b/src/softfloat/f64_rem.c @@ -0,0 +1,189 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f64_rem( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool signA; + int_fast16_t expA; + uint_fast64_t sigA; + union ui64_f64 uB; + uint_fast64_t uiB; + int_fast16_t expB; + uint_fast64_t sigB; + struct exp16_sig64 normExpSig; + uint64_t rem; + int_fast16_t expDiff; + uint32_t q, recip32; + uint_fast64_t q64; + uint64_t altRem, meanRem; + bool signRem; + uint_fast64_t uiZ; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + uB.f = b; + uiB = uB.ui; + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN; + goto invalid; + } + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA < expB - 1 ) return a; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expB ) { + if ( ! sigB ) goto invalid; + normExpSig = softfloat_normSubnormalF64Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if ( ! expA ) { + if ( ! sigA ) return a; + normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + rem = sigA | UINT64_C( 0x0010000000000000 ); + sigB |= UINT64_C( 0x0010000000000000 ); + expDiff = expA - expB; + if ( expDiff < 1 ) { + if ( expDiff < -1 ) return a; + sigB <<= 9; + if ( expDiff ) { + rem <<= 8; + q = 0; + } else { + rem <<= 9; + q = (sigB <= rem); + if ( q ) rem -= sigB; + } + } else { + recip32 = softfloat_approxRecip32_1( sigB>>21 ); + /*-------------------------------------------------------------------- + | Changing the shift of `rem' here requires also changing the initial + | subtraction from `expDiff'. + *--------------------------------------------------------------------*/ + rem <<= 9; + expDiff -= 30; + /*-------------------------------------------------------------------- + | The scale of `sigB' affects how many bits are obtained during each + | cycle of the loop. Currently this is 29 bits per loop iteration, + | the maximum possible. + *--------------------------------------------------------------------*/ + sigB <<= 9; + for (;;) { + q64 = (uint32_t) (rem>>32) * (uint_fast64_t) recip32; + if ( expDiff < 0 ) break; + q = (q64 + 0x80000000)>>32; +#ifdef SOFTFLOAT_FAST_INT64 + rem <<= 29; +#else + rem = (uint_fast64_t) (uint32_t) (rem>>3)<<32; +#endif + rem -= q * (uint64_t) sigB; + if ( rem & UINT64_C( 0x8000000000000000 ) ) rem += sigB; + expDiff -= 29; + } + /*-------------------------------------------------------------------- + | (`expDiff' cannot be less than -29 here.) + *--------------------------------------------------------------------*/ + q = (uint32_t) (q64>>32)>>(~expDiff & 31); + rem = (rem<<(expDiff + 30)) - q * (uint64_t) sigB; + if ( rem & UINT64_C( 0x8000000000000000 ) ) { + altRem = rem + sigB; + goto selectRem; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + do { + altRem = rem; + ++q; + rem -= sigB; + } while ( ! (rem & UINT64_C( 0x8000000000000000 )) ); + selectRem: + meanRem = rem + altRem; + if ( + (meanRem & UINT64_C( 0x8000000000000000 )) || (! meanRem && (q & 1)) + ) { + rem = altRem; + } + signRem = signA; + if ( rem & UINT64_C( 0x8000000000000000 ) ) { + signRem = ! signRem; + rem = -rem; + } + return softfloat_normRoundPackToF64( signRem, expB, rem ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + goto uiZ; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/src/softfloat/f64_roundToInt.c b/src/softfloat/f64_roundToInt.c new file mode 100644 index 000000000..c5f08ae16 --- /dev/null +++ b/src/softfloat/f64_roundToInt.c @@ -0,0 +1,120 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f64_roundToInt( float64_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + int_fast16_t exp; + uint_fast64_t uiZ, lastBitMask, roundBitsMask; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + exp = expF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp <= 0x3FE ) { + if ( !(uiA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) return a; + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + uiZ = uiA & packToF64UI( 1, 0, 0 ); + switch ( roundingMode ) { + case softfloat_round_near_even: + if ( !fracF64UI( uiA ) ) break; + case softfloat_round_near_maxMag: + if ( exp == 0x3FE ) uiZ |= packToF64UI( 0, 0x3FF, 0 ); + break; + case softfloat_round_min: + if ( uiZ ) uiZ = packToF64UI( 1, 0x3FF, 0 ); + break; + case softfloat_round_max: + if ( !uiZ ) uiZ = packToF64UI( 0, 0x3FF, 0 ); + break; +#ifdef SOFTFLOAT_ROUND_ODD + case softfloat_round_odd: + uiZ |= packToF64UI( 0, 0x3FF, 0 ); + break; +#endif + } + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( 0x433 <= exp ) { + if ( (exp == 0x7FF) && fracF64UI( uiA ) ) { + uiZ = softfloat_propagateNaNF64UI( uiA, 0 ); + goto uiZ; + } + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ = uiA; + lastBitMask = (uint_fast64_t) 1<<(0x433 - exp); + roundBitsMask = lastBitMask - 1; + if ( roundingMode == softfloat_round_near_maxMag ) { + uiZ += lastBitMask>>1; + } else if ( roundingMode == softfloat_round_near_even ) { + uiZ += lastBitMask>>1; + if ( !(uiZ & roundBitsMask) ) uiZ &= ~lastBitMask; + } else if ( + roundingMode + == (signF64UI( uiZ ) ? softfloat_round_min : softfloat_round_max) + ) { + uiZ += roundBitsMask; + } + uiZ &= ~roundBitsMask; + if ( uiZ != uiA ) { +#ifdef SOFTFLOAT_ROUND_ODD + if ( roundingMode == softfloat_round_odd ) uiZ |= lastBitMask; +#endif + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + } + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/src/softfloat/f64_sqrt.c b/src/softfloat/f64_sqrt.c new file mode 100644 index 000000000..f12acdb41 --- /dev/null +++ b/src/softfloat/f64_sqrt.c @@ -0,0 +1,133 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f64_sqrt( float64_t a ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool signA; + int_fast16_t expA; + uint_fast64_t sigA, uiZ; + struct exp16_sig64 normExpSig; + int_fast16_t expZ; + uint32_t sig32A, recipSqrt32, sig32Z; + uint_fast64_t rem; + uint32_t q; + uint_fast64_t sigZ, shiftedSigZ; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA ) { + uiZ = softfloat_propagateNaNF64UI( uiA, 0 ); + goto uiZ; + } + if ( ! signA ) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( signA ) { + if ( ! (expA | sigA) ) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! sigA ) return a; + normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + | (`sig32Z' is guaranteed to be a lower bound on the square root of + | `sig32A', which makes `sig32Z' also a lower bound on the square root of + | `sigA'.) + *------------------------------------------------------------------------*/ + expZ = ((expA - 0x3FF)>>1) + 0x3FE; + expA &= 1; + sigA |= UINT64_C( 0x0010000000000000 ); + sig32A = sigA>>21; + recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A ); + sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32; + if ( expA ) { + sigA <<= 8; + sig32Z >>= 1; + } else { + sigA <<= 9; + } + rem = sigA - (uint_fast64_t) sig32Z * sig32Z; + q = ((uint32_t) (rem>>2) * (uint_fast64_t) recipSqrt32)>>32; + sigZ = ((uint_fast64_t) sig32Z<<32 | 1<<5) + ((uint_fast64_t) q<<3); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (sigZ & 0x1FF) < 0x22 ) { + sigZ &= ~(uint_fast64_t) 0x3F; + shiftedSigZ = sigZ>>6; + rem = (sigA<<52) - shiftedSigZ * shiftedSigZ; + if ( rem & UINT64_C( 0x8000000000000000 ) ) { + --sigZ; + } else { + if ( rem ) sigZ |= 1; + } + } + return softfloat_roundPackToF64( 0, expZ, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/src/softfloat/f64_sub.c b/src/softfloat/f64_sub.c new file mode 100644 index 000000000..74158bec1 --- /dev/null +++ b/src/softfloat/f64_sub.c @@ -0,0 +1,74 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t f64_sub( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool signA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) + float64_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, bool ); +#endif + + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF64UI( uiB ); +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) + if ( signA == signB ) { + return softfloat_subMagsF64( uiA, uiB, signA ); + } else { + return softfloat_addMagsF64( uiA, uiB, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_subMagsF64 : softfloat_addMagsF64; + return (*magsFuncPtr)( uiA, uiB, signA ); +#endif + +} + diff --git a/src/softfloat/f64_to_f32.c b/src/softfloat/f64_to_f32.c new file mode 100644 index 000000000..6074bb845 --- /dev/null +++ b/src/softfloat/f64_to_f32.c @@ -0,0 +1,88 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t f64_to_f32( float64_t a ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t frac; + struct commonNaN commonNaN; + uint_fast32_t uiZ, frac32; + union ui32_f32 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + frac = fracF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp == 0x7FF ) { + if ( frac ) { + softfloat_f64UIToCommonNaN( uiA, &commonNaN ); + uiZ = softfloat_commonNaNToF32UI( &commonNaN ); + } else { + uiZ = packToF32UI( sign, 0xFF, 0 ); + } + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + frac32 = softfloat_shortShiftRightJam64( frac, 22 ); + if ( ! (exp | frac32) ) { + uiZ = packToF32UI( sign, 0, 0 ); + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return softfloat_roundPackToF32( sign, exp - 0x381, frac32 | 0x40000000 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/src/softfloat/f64_to_i32.c b/src/softfloat/f64_to_i32.c new file mode 100644 index 000000000..2cf260304 --- /dev/null +++ b/src/softfloat/f64_to_i32.c @@ -0,0 +1,82 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int_fast32_t f64_to_i32( float64_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow) + if ( (exp == 0x7FF) && sig ) { +#if (i32_fromNaN == i32_fromPosOverflow) + sign = 0; +#elif (i32_fromNaN == i32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags( softfloat_flag_invalid ); + return i32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); + shiftDist = 0x427 - exp; + if ( 0 < shiftDist ) sig = softfloat_shiftRightJam64( sig, shiftDist ); + return softfloat_roundToI32( sign, sig, roundingMode, exact ); + +} + diff --git a/src/softfloat/f64_to_i32_r_minMag.c b/src/softfloat/f64_to_i32_r_minMag.c new file mode 100644 index 000000000..8cccb8efd --- /dev/null +++ b/src/softfloat/f64_to_i32_r_minMag.c @@ -0,0 +1,96 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int_fast32_t f64_to_i32_r_minMag( float64_t a, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftDist; + bool sign; + int_fast32_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x433 - exp; + if ( 53 <= shiftDist ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI( uiA ); + if ( shiftDist < 22 ) { + if ( + sign && (exp == 0x41E) && (sig < UINT64_C( 0x0000000000200000 )) + ) { + if ( exact && sig ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return -0x7FFFFFFF - 1; + } + softfloat_raiseFlags( softfloat_flag_invalid ); + return + (exp == 0x7FF) && sig ? i32_fromNaN + : sign ? i32_fromNegOverflow : i32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig |= UINT64_C( 0x0010000000000000 ); + absZ = sig>>shiftDist; + if ( exact && ((uint_fast64_t) (uint_fast32_t) absZ< +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int_fast64_t f64_to_i64( float64_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftDist; +#ifdef SOFTFLOAT_FAST_INT64 + struct uint64_extra sigExtra; +#else + uint32_t extSig[3]; +#endif + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); + shiftDist = 0x433 - exp; +#ifdef SOFTFLOAT_FAST_INT64 + if ( shiftDist <= 0 ) { + if ( shiftDist < -11 ) goto invalid; + sigExtra.v = sig<<-shiftDist; + sigExtra.extra = 0; + } else { + sigExtra = softfloat_shiftRightJam64Extra( sig, 0, shiftDist ); + } + return + softfloat_roundToI64( + sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); +#else + extSig[indexWord( 3, 0 )] = 0; + if ( shiftDist <= 0 ) { + if ( shiftDist < -11 ) goto invalid; + sig <<= -shiftDist; + extSig[indexWord( 3, 2 )] = sig>>32; + extSig[indexWord( 3, 1 )] = sig; + } else { + extSig[indexWord( 3, 2 )] = sig>>32; + extSig[indexWord( 3, 1 )] = sig; + softfloat_shiftRightJam96M( extSig, shiftDist, extSig ); + } + return softfloat_roundMToI64( sign, extSig, roundingMode, exact ); +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return + (exp == 0x7FF) && fracF64UI( uiA ) ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + +} + diff --git a/src/softfloat/f64_to_i64_r_minMag.c b/src/softfloat/f64_to_i64_r_minMag.c new file mode 100644 index 000000000..4fcc52c56 --- /dev/null +++ b/src/softfloat/f64_to_i64_r_minMag.c @@ -0,0 +1,100 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int_fast64_t f64_to_i64_r_minMag( float64_t a, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftDist; + int_fast64_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x433 - exp; + if ( shiftDist <= 0 ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( shiftDist < -10 ) { + if ( uiA == packToF64UI( 1, 0x43E, 0 ) ) { + return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + softfloat_raiseFlags( softfloat_flag_invalid ); + return + (exp == 0x7FF) && sig ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig |= UINT64_C( 0x0010000000000000 ); + absZ = sig<<-shiftDist; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( 53 <= shiftDist ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig |= UINT64_C( 0x0010000000000000 ); + absZ = sig>>shiftDist; + if ( exact && (absZ< +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint_fast32_t f64_to_ui32( float64_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow) + if ( (exp == 0x7FF) && sig ) { +#if (ui32_fromNaN == ui32_fromPosOverflow) + sign = 0; +#elif (ui32_fromNaN == ui32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags( softfloat_flag_invalid ); + return ui32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); + shiftDist = 0x427 - exp; + if ( 0 < shiftDist ) sig = softfloat_shiftRightJam64( sig, shiftDist ); + return softfloat_roundToUI32( sign, sig, roundingMode, exact ); + +} + diff --git a/src/softfloat/f64_to_ui32_r_minMag.c b/src/softfloat/f64_to_ui32_r_minMag.c new file mode 100644 index 000000000..01758dc54 --- /dev/null +++ b/src/softfloat/f64_to_ui32_r_minMag.c @@ -0,0 +1,88 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint_fast32_t f64_to_ui32_r_minMag( float64_t a, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftDist; + bool sign; + uint_fast32_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x433 - exp; + if ( 53 <= shiftDist ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI( uiA ); + if ( sign || (shiftDist < 21) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return + (exp == 0x7FF) && sig ? ui32_fromNaN + : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig |= UINT64_C( 0x0010000000000000 ); + z = sig>>shiftDist; + if ( exact && ((uint_fast64_t) z< +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint_fast64_t f64_to_ui64( float64_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftDist; +#ifdef SOFTFLOAT_FAST_INT64 + struct uint64_extra sigExtra; +#else + uint32_t extSig[3]; +#endif + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); + shiftDist = 0x433 - exp; +#ifdef SOFTFLOAT_FAST_INT64 + if ( shiftDist <= 0 ) { + if ( shiftDist < -11 ) goto invalid; + sigExtra.v = sig<<-shiftDist; + sigExtra.extra = 0; + } else { + sigExtra = softfloat_shiftRightJam64Extra( sig, 0, shiftDist ); + } + return + softfloat_roundToUI64( + sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); +#else + extSig[indexWord( 3, 0 )] = 0; + if ( shiftDist <= 0 ) { + if ( shiftDist < -11 ) goto invalid; + sig <<= -shiftDist; + extSig[indexWord( 3, 2 )] = sig>>32; + extSig[indexWord( 3, 1 )] = sig; + } else { + extSig[indexWord( 3, 2 )] = sig>>32; + extSig[indexWord( 3, 1 )] = sig; + softfloat_shiftRightJam96M( extSig, shiftDist, extSig ); + } + return softfloat_roundMToUI64( sign, extSig, roundingMode, exact ); +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return + (exp == 0x7FF) && fracF64UI( uiA ) ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + +} + diff --git a/src/softfloat/f64_to_ui64_r_minMag.c b/src/softfloat/f64_to_ui64_r_minMag.c new file mode 100644 index 000000000..e1d81a018 --- /dev/null +++ b/src/softfloat/f64_to_ui64_r_minMag.c @@ -0,0 +1,93 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint_fast64_t f64_to_ui64_r_minMag( float64_t a, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftDist; + bool sign; + uint_fast64_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x433 - exp; + if ( 53 <= shiftDist ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI( uiA ); + if ( sign ) goto invalid; + if ( shiftDist <= 0 ) { + if ( shiftDist < -11 ) goto invalid; + z = (sig | UINT64_C( 0x0010000000000000 ))<<-shiftDist; + } else { + sig |= UINT64_C( 0x0010000000000000 ); + z = sig>>shiftDist; + if ( exact && (uint64_t) (sig<<(-shiftDist & 63)) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + } + return z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return + (exp == 0x7FF) && sig ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + +} + diff --git a/src/softfloat/i32_to_f64.c b/src/softfloat/i32_to_f64.c new file mode 100644 index 000000000..64662bb22 --- /dev/null +++ b/src/softfloat/i32_to_f64.c @@ -0,0 +1,65 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t i32_to_f64( int32_t a ) +{ + uint_fast64_t uiZ; + bool sign; + uint_fast32_t absA; + int_fast8_t shiftDist; + union ui64_f64 uZ; + + if ( ! a ) { + uiZ = 0; + } else { + sign = (a < 0); + absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; + shiftDist = softfloat_countLeadingZeros32( absA ) + 21; + uiZ = + packToF64UI( + sign, 0x432 - shiftDist, (uint_fast64_t) absA< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t i64_to_f64( int64_t a ) +{ + bool sign; + union ui64_f64 uZ; + uint_fast64_t absA; + + sign = (a < 0); + if ( ! (a & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) { + uZ.ui = sign ? packToF64UI( 1, 0x43E, 0 ) : 0; + return uZ.f; + } + absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a; + return softfloat_normRoundPackToF64( sign, 0x43C, absA ); + +} + diff --git a/src/softfloat/include/internals.h b/src/softfloat/include/internals.h new file mode 100644 index 000000000..f8eac0530 --- /dev/null +++ b/src/softfloat/include/internals.h @@ -0,0 +1,278 @@ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef internals_h +#define internals_h 1 + +#include +#include +#include "primitives.h" +#include "softfloat_types.h" + +union ui16_f16 { uint16_t ui; float16_t f; }; +union ui32_f32 { uint32_t ui; float32_t f; }; +union ui64_f64 { uint64_t ui; float64_t f; }; + +#ifdef SOFTFLOAT_FAST_INT64 +union extF80M_extF80 { struct extFloat80M fM; extFloat80_t f; }; +union ui128_f128 { struct uint128 ui; float128_t f; }; +#endif + +enum { + softfloat_mulAdd_subC = 1, + softfloat_mulAdd_subProd = 2 +}; + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +uint_fast32_t softfloat_roundToUI32( bool, uint_fast64_t, uint_fast8_t, bool ); + +#ifdef SOFTFLOAT_FAST_INT64 +uint_fast64_t + softfloat_roundToUI64( + bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool ); +#else +uint_fast64_t softfloat_roundMToUI64( bool, uint32_t *, uint_fast8_t, bool ); +#endif + +int_fast32_t softfloat_roundToI32( bool, uint_fast64_t, uint_fast8_t, bool ); + +#ifdef SOFTFLOAT_FAST_INT64 +int_fast64_t + softfloat_roundToI64( + bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool ); +#else +int_fast64_t softfloat_roundMToI64( bool, uint32_t *, uint_fast8_t, bool ); +#endif + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF16UI( a ) ((bool) ((uint16_t) (a)>>15)) +#define expF16UI( a ) ((int_fast8_t) ((a)>>10) & 0x1F) +#define fracF16UI( a ) ((a) & 0x03FF) +#define packToF16UI( sign, exp, sig ) (((uint16_t) (sign)<<15) + ((uint16_t) (exp)<<10) + (sig)) + +#define isNaNF16UI( a ) (((~(a) & 0x7C00) == 0) && ((a) & 0x03FF)) + +struct exp8_sig16 { int_fast8_t exp; uint_fast16_t sig; }; +struct exp8_sig16 softfloat_normSubnormalF16Sig( uint_fast16_t ); + +float16_t softfloat_roundPackToF16( bool, int_fast16_t, uint_fast16_t ); +float16_t softfloat_normRoundPackToF16( bool, int_fast16_t, uint_fast16_t ); + +float16_t softfloat_addMagsF16( uint_fast16_t, uint_fast16_t ); +float16_t softfloat_subMagsF16( uint_fast16_t, uint_fast16_t ); +float16_t + softfloat_mulAddF16( + uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_fast8_t ); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF32UI( a ) ((bool) ((uint32_t) (a)>>31)) +#define expF32UI( a ) ((int_fast16_t) ((a)>>23) & 0xFF) +#define fracF32UI( a ) ((a) & 0x007FFFFF) +#define packToF32UI( sign, exp, sig ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig)) + +#define isNaNF32UI( a ) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF)) + +struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; }; +struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t ); + +float32_t softfloat_roundPackToF32( bool, int_fast16_t, uint_fast32_t ); +float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t ); + +float32_t softfloat_addMagsF32( uint_fast32_t, uint_fast32_t ); +float32_t softfloat_subMagsF32( uint_fast32_t, uint_fast32_t ); +float32_t + softfloat_mulAddF32( + uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t ); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF64UI( a ) ((bool) ((uint64_t) (a)>>63)) +#define expF64UI( a ) ((int_fast16_t) ((a)>>52) & 0x7FF) +#define fracF64UI( a ) ((a) & UINT64_C( 0x000FFFFFFFFFFFFF )) +#define packToF64UI( sign, exp, sig ) ((uint64_t) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<52) + (sig))) + +#define isNaNF64UI( a ) (((~(a) & UINT64_C( 0x7FF0000000000000 )) == 0) && ((a) & UINT64_C( 0x000FFFFFFFFFFFFF ))) + +struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; }; +struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t ); + +float64_t softfloat_roundPackToF64( bool, int_fast16_t, uint_fast64_t ); +float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t ); + +float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool ); +float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool ); +float64_t + softfloat_mulAddF64( + uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signExtF80UI64( a64 ) ((bool) ((uint16_t) (a64)>>15)) +#define expExtF80UI64( a64 ) ((a64) & 0x7FFF) +#define packToExtF80UI64( sign, exp ) ((uint_fast16_t) (sign)<<15 | (exp)) + +#define isNaNExtF80UI( a64, a0 ) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) + +#ifdef SOFTFLOAT_FAST_INT64 + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ + +struct exp32_sig64 { int_fast32_t exp; uint64_t sig; }; +struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t ); + +extFloat80_t + softfloat_roundPackToExtF80( + bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); +extFloat80_t + softfloat_normRoundPackToExtF80( + bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); + +extFloat80_t + softfloat_addMagsExtF80( + uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); +extFloat80_t + softfloat_subMagsExtF80( + uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF128UI64( a64 ) ((bool) ((uint64_t) (a64)>>63)) +#define expF128UI64( a64 ) ((int_fast32_t) ((a64)>>48) & 0x7FFF) +#define fracF128UI64( a64 ) ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF )) +#define packToF128UI64( sign, exp, sig64 ) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<48) + (sig64)) + +#define isNaNF128UI( a64, a0 ) (((~(a64) & UINT64_C( 0x7FFF000000000000 )) == 0) && (a0 || ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF )))) + +struct exp32_sig128 { int_fast32_t exp; struct uint128 sig; }; +struct exp32_sig128 + softfloat_normSubnormalF128Sig( uint_fast64_t, uint_fast64_t ); + +float128_t + softfloat_roundPackToF128( + bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t ); +float128_t + softfloat_normRoundPackToF128( + bool, int_fast32_t, uint_fast64_t, uint_fast64_t ); + +float128_t + softfloat_addMagsF128( + uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); +float128_t + softfloat_subMagsF128( + uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); +float128_t + softfloat_mulAddF128( + uint_fast64_t, + uint_fast64_t, + uint_fast64_t, + uint_fast64_t, + uint_fast64_t, + uint_fast64_t, + uint_fast8_t + ); + +#else + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ + +bool + softfloat_tryPropagateNaNExtF80M( + const struct extFloat80M *, + const struct extFloat80M *, + struct extFloat80M * + ); +void softfloat_invalidExtF80M( struct extFloat80M * ); + +int softfloat_normExtF80SigM( uint64_t * ); + +void + softfloat_roundPackMToExtF80M( + bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); +void + softfloat_normRoundPackMToExtF80M( + bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); + +void + softfloat_addExtF80M( + const struct extFloat80M *, + const struct extFloat80M *, + struct extFloat80M *, + bool + ); + +int + softfloat_compareNonnormExtF80M( + const struct extFloat80M *, const struct extFloat80M * ); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF128UI96( a96 ) ((bool) ((uint32_t) (a96)>>31)) +#define expF128UI96( a96 ) ((int32_t) ((a96)>>16) & 0x7FFF) +#define fracF128UI96( a96 ) ((a96) & 0x0000FFFF) +#define packToF128UI96( sign, exp, sig96 ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<16) + (sig96)) + +bool softfloat_isNaNF128M( const uint32_t * ); + +bool + softfloat_tryPropagateNaNF128M( + const uint32_t *, const uint32_t *, uint32_t * ); +void softfloat_invalidF128M( uint32_t * ); + +int softfloat_shiftNormSigF128M( const uint32_t *, uint_fast8_t, uint32_t * ); + +void softfloat_roundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * ); +void softfloat_normRoundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * ); + +void + softfloat_addF128M( const uint32_t *, const uint32_t *, uint32_t *, bool ); +void + softfloat_mulAddF128M( + const uint32_t *, + const uint32_t *, + const uint32_t *, + uint32_t *, + uint_fast8_t + ); + +#endif + +#endif + diff --git a/src/softfloat/include/opts-GCC.h b/src/softfloat/include/opts-GCC.h new file mode 100644 index 000000000..192cb58ca --- /dev/null +++ b/src/softfloat/include/opts-GCC.h @@ -0,0 +1,114 @@ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2017 The Regents of the University of California. All rights +reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef opts_GCC_h +#define opts_GCC_h 1 + +#ifdef INLINE + +#include +#include "primitiveTypes.h" + +#ifdef SOFTFLOAT_BUILTIN_CLZ + +INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ) + { return a ? __builtin_clz( a ) - 16 : 16; } +#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16 + +INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) + { return a ? __builtin_clz( a ) : 32; } +#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 + +INLINE uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ) + { return a ? __builtin_clzll( a ) : 64; } +#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64 + +#endif + +#ifdef SOFTFLOAT_INTRINSIC_INT128 + +INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ) +{ + union { unsigned __int128 ui; struct uint128 s; } uZ; + uZ.ui = (unsigned __int128) a * ((uint_fast64_t) b<<32); + return uZ.s; +} +#define softfloat_mul64ByShifted32To128 softfloat_mul64ByShifted32To128 + +INLINE struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ) +{ + union { unsigned __int128 ui; struct uint128 s; } uZ; + uZ.ui = (unsigned __int128) a * b; + return uZ.s; +} +#define softfloat_mul64To128 softfloat_mul64To128 + +INLINE +struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ) +{ + union { unsigned __int128 ui; struct uint128 s; } uZ; + uZ.ui = ((unsigned __int128) a64<<64 | a0) * b; + return uZ.s; +} +#define softfloat_mul128By32 softfloat_mul128By32 + +INLINE +void + softfloat_mul128To256M( + uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr ) +{ + unsigned __int128 z0, mid1, mid, z128; + z0 = (unsigned __int128) a0 * b0; + mid1 = (unsigned __int128) a64 * b0; + mid = mid1 + (unsigned __int128) a0 * b64; + z128 = (unsigned __int128) a64 * b64; + z128 += (unsigned __int128) (mid < mid1)<<64 | mid>>64; + mid <<= 64; + z0 += mid; + z128 += (z0 < mid); + zPtr[indexWord( 4, 0 )] = z0; + zPtr[indexWord( 4, 1 )] = z0>>64; + zPtr[indexWord( 4, 2 )] = z128; + zPtr[indexWord( 4, 3 )] = z128>>64; +} +#define softfloat_mul128To256M softfloat_mul128To256M + +#endif + +#endif + +#endif + diff --git a/src/softfloat/include/platform.h b/src/softfloat/include/platform.h new file mode 100644 index 000000000..37b3ab4b3 --- /dev/null +++ b/src/softfloat/include/platform.h @@ -0,0 +1,8 @@ + +#define LITTLEENDIAN 1 + +#define INLINE inline + +#define SOFTFLOAT_BUILTIN_CLZ 1 + +#include diff --git a/src/softfloat/include/primitiveTypes.h b/src/softfloat/include/primitiveTypes.h new file mode 100644 index 000000000..e30540068 --- /dev/null +++ b/src/softfloat/include/primitiveTypes.h @@ -0,0 +1,85 @@ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef primitiveTypes_h +#define primitiveTypes_h 1 + +#include + +#ifdef SOFTFLOAT_FAST_INT64 + +#ifdef LITTLEENDIAN +struct uint128 { uint64_t v0, v64; }; +struct uint64_extra { uint64_t extra, v; }; +struct uint128_extra { uint64_t extra; struct uint128 v; }; +#else +struct uint128 { uint64_t v64, v0; }; +struct uint64_extra { uint64_t v, extra; }; +struct uint128_extra { struct uint128 v; uint64_t extra; }; +#endif + +#endif + +/*---------------------------------------------------------------------------- +| These macros are used to isolate the differences in word order between big- +| endian and little-endian platforms. +*----------------------------------------------------------------------------*/ +#ifdef LITTLEENDIAN +#define wordIncr 1 +#define indexWord( total, n ) (n) +#define indexWordHi( total ) ((total) - 1) +#define indexWordLo( total ) 0 +#define indexMultiword( total, m, n ) (n) +#define indexMultiwordHi( total, n ) ((total) - (n)) +#define indexMultiwordLo( total, n ) 0 +#define indexMultiwordHiBut( total, n ) (n) +#define indexMultiwordLoBut( total, n ) 0 +#define INIT_UINTM4( v3, v2, v1, v0 ) { v0, v1, v2, v3 } +#else +#define wordIncr -1 +#define indexWord( total, n ) ((total) - 1 - (n)) +#define indexWordHi( total ) 0 +#define indexWordLo( total ) ((total) - 1) +#define indexMultiword( total, m, n ) ((total) - 1 - (m)) +#define indexMultiwordHi( total, n ) 0 +#define indexMultiwordLo( total, n ) ((total) - (n)) +#define indexMultiwordHiBut( total, n ) 0 +#define indexMultiwordLoBut( total, n ) (n) +#define INIT_UINTM4( v3, v2, v1, v0 ) { v3, v2, v1, v0 } +#endif + +#endif + diff --git a/src/softfloat/include/primitives.h b/src/softfloat/include/primitives.h new file mode 100644 index 000000000..10847817a --- /dev/null +++ b/src/softfloat/include/primitives.h @@ -0,0 +1,1160 @@ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef primitives_h +#define primitives_h 1 + +#include +#include +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftRightJam64 +/*---------------------------------------------------------------------------- +| Shifts 'a' right by the number of bits given in 'dist', which must be in +| the range 1 to 63. If any nonzero bits are shifted off, they are "jammed" +| into the least-significant bit of the shifted value by setting the least- +| significant bit to 1. This shifted-and-jammed value is returned. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE +uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist ) + { return a>>dist | ((a & (((uint_fast64_t) 1<>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0); +} +#else +uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist ); +#endif +#endif + +#ifndef softfloat_shiftRightJam64 +/*---------------------------------------------------------------------------- +| Shifts 'a' right by the number of bits given in 'dist', which must not +| be zero. If any nonzero bits are shifted off, they are "jammed" into the +| least-significant bit of the shifted value by setting the least-significant +| bit to 1. This shifted-and-jammed value is returned. +| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is +| greater than 64, the result will be either 0 or 1, depending on whether 'a' +| is zero or nonzero. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) +INLINE uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist ) +{ + return + (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0); +} +#else +uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist ); +#endif +#endif + +/*---------------------------------------------------------------------------- +| A constant table that translates an 8-bit unsigned integer (the array index) +| into the number of leading 0 bits before the most-significant 1 of that +| integer. For integer zero (index 0), the corresponding table element is 8. +*----------------------------------------------------------------------------*/ +extern const uint_least8_t softfloat_countLeadingZeros8[256]; + +#ifndef softfloat_countLeadingZeros16 +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| 'a'. If 'a' is zero, 16 is returned. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ) +{ + uint_fast8_t count = 8; + if ( 0x100 <= a ) { + count = 0; + a >>= 8; + } + count += softfloat_countLeadingZeros8[a]; + return count; +} +#else +uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ); +#endif +#endif + +#ifndef softfloat_countLeadingZeros32 +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| 'a'. If 'a' is zero, 32 is returned. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) +INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) +{ + uint_fast8_t count = 0; + if ( a < 0x10000 ) { + count = 16; + a <<= 16; + } + if ( a < 0x1000000 ) { + count += 8; + a <<= 8; + } + count += softfloat_countLeadingZeros8[a>>24]; + return count; +} +#else +uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ); +#endif +#endif + +#ifndef softfloat_countLeadingZeros64 +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| 'a'. If 'a' is zero, 64 is returned. +*----------------------------------------------------------------------------*/ +uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ); +#endif + +extern const uint16_t softfloat_approxRecip_1k0s[16]; +extern const uint16_t softfloat_approxRecip_1k1s[16]; + +#ifndef softfloat_approxRecip32_1 +/*---------------------------------------------------------------------------- +| Returns an approximation to the reciprocal of the number represented by 'a', +| where 'a' is interpreted as an unsigned fixed-point number with one integer +| bit and 31 fraction bits. The 'a' input must be "normalized", meaning that +| its most-significant bit (bit 31) must be 1. Thus, if A is the value of +| the fixed-point interpretation of 'a', then 1 <= A < 2. The returned value +| is interpreted as a pure unsigned fraction, having no integer bits and 32 +| fraction bits. The approximation returned is never greater than the true +| reciprocal 1/A, and it differs from the true reciprocal by at most 2.006 ulp +| (units in the last place). +*----------------------------------------------------------------------------*/ +#ifdef SOFTFLOAT_FAST_DIV64TO32 +#define softfloat_approxRecip32_1( a ) ((uint32_t) (UINT64_C( 0x7FFFFFFFFFFFFFFF ) / (uint32_t) (a))) +#else +uint32_t softfloat_approxRecip32_1( uint32_t a ); +#endif +#endif + +extern const uint16_t softfloat_approxRecipSqrt_1k0s[16]; +extern const uint16_t softfloat_approxRecipSqrt_1k1s[16]; + +#ifndef softfloat_approxRecipSqrt32_1 +/*---------------------------------------------------------------------------- +| Returns an approximation to the reciprocal of the square root of the number +| represented by 'a', where 'a' is interpreted as an unsigned fixed-point +| number either with one integer bit and 31 fraction bits or with two integer +| bits and 30 fraction bits. The format of 'a' is determined by 'oddExpA', +| which must be either 0 or 1. If 'oddExpA' is 1, 'a' is interpreted as +| having one integer bit, and if 'oddExpA' is 0, 'a' is interpreted as having +| two integer bits. The 'a' input must be "normalized", meaning that its +| most-significant bit (bit 31) must be 1. Thus, if A is the value of the +| fixed-point interpretation of 'a', it follows that 1 <= A < 2 when 'oddExpA' +| is 1, and 2 <= A < 4 when 'oddExpA' is 0. +| The returned value is interpreted as a pure unsigned fraction, having +| no integer bits and 32 fraction bits. The approximation returned is never +| greater than the true reciprocal 1/sqrt(A), and it differs from the true +| reciprocal by at most 2.06 ulp (units in the last place). The approximation +| returned is also always within the range 0.5 to 1; thus, the most- +| significant bit of the result is always set. +*----------------------------------------------------------------------------*/ +uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a ); +#endif + +#ifdef SOFTFLOAT_FAST_INT64 + +/*---------------------------------------------------------------------------- +| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is +| defined. +*----------------------------------------------------------------------------*/ + +#ifndef softfloat_eq128 +/*---------------------------------------------------------------------------- +| Returns true if the 128-bit unsigned integer formed by concatenating 'a64' +| and 'a0' is equal to the 128-bit unsigned integer formed by concatenating +| 'b64' and 'b0'. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL) +INLINE +bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) + { return (a64 == b64) && (a0 == b0); } +#else +bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +#endif +#endif + +#ifndef softfloat_le128 +/*---------------------------------------------------------------------------- +| Returns true if the 128-bit unsigned integer formed by concatenating 'a64' +| and 'a0' is less than or equal to the 128-bit unsigned integer formed by +| concatenating 'b64' and 'b0'. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE +bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) + { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); } +#else +bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +#endif +#endif + +#ifndef softfloat_lt128 +/*---------------------------------------------------------------------------- +| Returns true if the 128-bit unsigned integer formed by concatenating 'a64' +| and 'a0' is less than the 128-bit unsigned integer formed by concatenating +| 'b64' and 'b0'. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE +bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) + { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); } +#else +bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +#endif +#endif + +#ifndef softfloat_shortShiftLeft128 +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating 'a64' and 'a0' left by the +| number of bits given in 'dist', which must be in the range 1 to 63. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE +struct uint128 + softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist ) +{ + struct uint128 z; + z.v64 = a64<>(-dist & 63); + z.v0 = a0<>dist; + z.v0 = a64<<(-dist & 63) | a0>>dist; + return z; +} +#else +struct uint128 + softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist ); +#endif +#endif + +#ifndef softfloat_shortShiftRightJam64Extra +/*---------------------------------------------------------------------------- +| This function is the same as 'softfloat_shiftRightJam64Extra' (below), +| except that 'dist' must be in the range 1 to 63. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE +struct uint64_extra + softfloat_shortShiftRightJam64Extra( + uint64_t a, uint64_t extra, uint_fast8_t dist ) +{ + struct uint64_extra z; + z.v = a>>dist; + z.extra = a<<(-dist & 63) | (extra != 0); + return z; +} +#else +struct uint64_extra + softfloat_shortShiftRightJam64Extra( + uint64_t a, uint64_t extra, uint_fast8_t dist ); +#endif +#endif + +#ifndef softfloat_shortShiftRightJam128 +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the +| number of bits given in 'dist', which must be in the range 1 to 63. If any +| nonzero bits are shifted off, they are "jammed" into the least-significant +| bit of the shifted value by setting the least-significant bit to 1. This +| shifted-and-jammed value is returned. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) +INLINE +struct uint128 + softfloat_shortShiftRightJam128( + uint64_t a64, uint64_t a0, uint_fast8_t dist ) +{ + uint_fast8_t negDist = -dist; + struct uint128 z; + z.v64 = a64>>dist; + z.v0 = + a64<<(negDist & 63) | a0>>dist + | ((uint64_t) (a0<<(negDist & 63)) != 0); + return z; +} +#else +struct uint128 + softfloat_shortShiftRightJam128( + uint64_t a64, uint64_t a0, uint_fast8_t dist ); +#endif +#endif + +#ifndef softfloat_shortShiftRightJam128Extra +/*---------------------------------------------------------------------------- +| This function is the same as 'softfloat_shiftRightJam128Extra' (below), +| except that 'dist' must be in the range 1 to 63. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) +INLINE +struct uint128_extra + softfloat_shortShiftRightJam128Extra( + uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist ) +{ + uint_fast8_t negDist = -dist; + struct uint128_extra z; + z.v.v64 = a64>>dist; + z.v.v0 = a64<<(negDist & 63) | a0>>dist; + z.extra = a0<<(negDist & 63) | (extra != 0); + return z; +} +#else +struct uint128_extra + softfloat_shortShiftRightJam128Extra( + uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist ); +#endif +#endif + +#ifndef softfloat_shiftRightJam64Extra +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating 'a' and 'extra' right by 64 +| _plus_ the number of bits given in 'dist', which must not be zero. This +| shifted value is at most 64 nonzero bits and is returned in the 'v' field +| of the 'struct uint64_extra' result. The 64-bit 'extra' field of the result +| contains a value formed as follows from the bits that were shifted off: The +| _last_ bit shifted off is the most-significant bit of the 'extra' field, and +| the other 63 bits of the 'extra' field are all zero if and only if _all_but_ +| _the_last_ bits shifted off were all zero. +| (This function makes more sense if 'a' and 'extra' are considered to form +| an unsigned fixed-point number with binary point between 'a' and 'extra'. +| This fixed-point value is shifted right by the number of bits given in +| 'dist', and the integer part of this shifted value is returned in the 'v' +| field of the result. The fractional part of the shifted value is modified +| as described above and returned in the 'extra' field of the result.) +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL) +INLINE +struct uint64_extra + softfloat_shiftRightJam64Extra( + uint64_t a, uint64_t extra, uint_fast32_t dist ) +{ + struct uint64_extra z; + if ( dist < 64 ) { + z.v = a>>dist; + z.extra = a<<(-dist & 63); + } else { + z.v = 0; + z.extra = (dist == 64) ? a : (a != 0); + } + z.extra |= (extra != 0); + return z; +} +#else +struct uint64_extra + softfloat_shiftRightJam64Extra( + uint64_t a, uint64_t extra, uint_fast32_t dist ); +#endif +#endif + +#ifndef softfloat_shiftRightJam128 +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the +| number of bits given in 'dist', which must not be zero. If any nonzero bits +| are shifted off, they are "jammed" into the least-significant bit of the +| shifted value by setting the least-significant bit to 1. This shifted-and- +| jammed value is returned. +| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is +| greater than 128, the result will be either 0 or 1, depending on whether the +| original 128 bits are all zeros. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t dist ); +#endif + +#ifndef softfloat_shiftRightJam128Extra +/*---------------------------------------------------------------------------- +| Shifts the 192 bits formed by concatenating 'a64', 'a0', and 'extra' right +| by 64 _plus_ the number of bits given in 'dist', which must not be zero. +| This shifted value is at most 128 nonzero bits and is returned in the 'v' +| field of the 'struct uint128_extra' result. The 64-bit 'extra' field of the +| result contains a value formed as follows from the bits that were shifted +| off: The _last_ bit shifted off is the most-significant bit of the 'extra' +| field, and the other 63 bits of the 'extra' field are all zero if and only +| if _all_but_the_last_ bits shifted off were all zero. +| (This function makes more sense if 'a64', 'a0', and 'extra' are considered +| to form an unsigned fixed-point number with binary point between 'a0' and +| 'extra'. This fixed-point value is shifted right by the number of bits +| given in 'dist', and the integer part of this shifted value is returned +| in the 'v' field of the result. The fractional part of the shifted value +| is modified as described above and returned in the 'extra' field of the +| result.) +*----------------------------------------------------------------------------*/ +struct uint128_extra + softfloat_shiftRightJam128Extra( + uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist ); +#endif + +#ifndef softfloat_shiftRightJam256M +/*---------------------------------------------------------------------------- +| Shifts the 256-bit unsigned integer pointed to by 'aPtr' right by the number +| of bits given in 'dist', which must not be zero. If any nonzero bits are +| shifted off, they are "jammed" into the least-significant bit of the shifted +| value by setting the least-significant bit to 1. This shifted-and-jammed +| value is stored at the location pointed to by 'zPtr'. Each of 'aPtr' and +| 'zPtr' points to an array of four 64-bit elements that concatenate in the +| platform's normal endian order to form a 256-bit integer. +| The value of 'dist' can be arbitrarily large. In particular, if 'dist' +| is greater than 256, the stored result will be either 0 or 1, depending on +| whether the original 256 bits are all zeros. +*----------------------------------------------------------------------------*/ +void + softfloat_shiftRightJam256M( + const uint64_t *aPtr, uint_fast32_t dist, uint64_t *zPtr ); +#endif + +#ifndef softfloat_add128 +/*---------------------------------------------------------------------------- +| Returns the sum of the 128-bit integer formed by concatenating 'a64' and +| 'a0' and the 128-bit integer formed by concatenating 'b64' and 'b0'. The +| addition is modulo 2^128, so any carry out is lost. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE +struct uint128 + softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) +{ + struct uint128 z; + z.v0 = a0 + b0; + z.v64 = a64 + b64 + (z.v0 < a0); + return z; +} +#else +struct uint128 + softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +#endif +#endif + +#ifndef softfloat_add256M +/*---------------------------------------------------------------------------- +| Adds the two 256-bit integers pointed to by 'aPtr' and 'bPtr'. The addition +| is modulo 2^256, so any carry out is lost. The sum is stored at the +| location pointed to by 'zPtr'. Each of 'aPtr', 'bPtr', and 'zPtr' points to +| an array of four 64-bit elements that concatenate in the platform's normal +| endian order to form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_add256M( + const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ); +#endif + +#ifndef softfloat_sub128 +/*---------------------------------------------------------------------------- +| Returns the difference of the 128-bit integer formed by concatenating 'a64' +| and 'a0' and the 128-bit integer formed by concatenating 'b64' and 'b0'. +| The subtraction is modulo 2^128, so any borrow out (carry out) is lost. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE +struct uint128 + softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) +{ + struct uint128 z; + z.v0 = a0 - b0; + z.v64 = a64 - b64; + z.v64 -= (a0 < b0); + return z; +} +#else +struct uint128 + softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +#endif +#endif + +#ifndef softfloat_sub256M +/*---------------------------------------------------------------------------- +| Subtracts the 256-bit integer pointed to by 'bPtr' from the 256-bit integer +| pointed to by 'aPtr'. The addition is modulo 2^256, so any borrow out +| (carry out) is lost. The difference is stored at the location pointed to +| by 'zPtr'. Each of 'aPtr', 'bPtr', and 'zPtr' points to an array of four +| 64-bit elements that concatenate in the platform's normal endian order to +| form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_sub256M( + const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ); +#endif + +#ifndef softfloat_mul64ByShifted32To128 +/*---------------------------------------------------------------------------- +| Returns the 128-bit product of 'a', 'b', and 2^32. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) +INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ) +{ + uint_fast64_t mid; + struct uint128 z; + mid = (uint_fast64_t) (uint32_t) a * b; + z.v0 = mid<<32; + z.v64 = (uint_fast64_t) (uint32_t) (a>>32) * b + (mid>>32); + return z; +} +#else +struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ); +#endif +#endif + +#ifndef softfloat_mul64To128 +/*---------------------------------------------------------------------------- +| Returns the 128-bit product of 'a' and 'b'. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ); +#endif + +#ifndef softfloat_mul128By32 +/*---------------------------------------------------------------------------- +| Returns the product of the 128-bit integer formed by concatenating 'a64' and +| 'a0', multiplied by 'b'. The multiplication is modulo 2^128; any overflow +| bits are discarded. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL) +INLINE +struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ) +{ + struct uint128 z; + uint_fast64_t mid; + uint_fast32_t carry; + z.v0 = a0 * b; + mid = (uint_fast64_t) (uint32_t) (a0>>32) * b; + carry = (uint32_t) ((uint_fast32_t) (z.v0>>32) - (uint_fast32_t) mid); + z.v64 = a64 * b + (uint_fast32_t) ((mid + carry)>>32); + return z; +} +#else +struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ); +#endif +#endif + +#ifndef softfloat_mul128To256M +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit unsigned integer formed by concatenating 'a64' and +| 'a0' by the 128-bit unsigned integer formed by concatenating 'b64' and +| 'b0'. The 256-bit product is stored at the location pointed to by 'zPtr'. +| Argument 'zPtr' points to an array of four 64-bit elements that concatenate +| in the platform's normal endian order to form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_mul128To256M( + uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr ); +#endif + +#else + +/*---------------------------------------------------------------------------- +| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is not +| defined. +*----------------------------------------------------------------------------*/ + +#ifndef softfloat_compare96M +/*---------------------------------------------------------------------------- +| Compares the two 96-bit unsigned integers pointed to by 'aPtr' and 'bPtr'. +| Returns -1 if the first integer (A) is less than the second (B); returns 0 +| if the two integers are equal; and returns +1 if the first integer (A) +| is greater than the second (B). (The result is thus the signum of A - B.) +| Each of 'aPtr' and 'bPtr' points to an array of three 32-bit elements that +| concatenate in the platform's normal endian order to form a 96-bit integer. +*----------------------------------------------------------------------------*/ +int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr ); +#endif + +#ifndef softfloat_compare128M +/*---------------------------------------------------------------------------- +| Compares the two 128-bit unsigned integers pointed to by 'aPtr' and 'bPtr'. +| Returns -1 if the first integer (A) is less than the second (B); returns 0 +| if the two integers are equal; and returns +1 if the first integer (A) +| is greater than the second (B). (The result is thus the signum of A - B.) +| Each of 'aPtr' and 'bPtr' points to an array of four 32-bit elements that +| concatenate in the platform's normal endian order to form a 128-bit integer. +*----------------------------------------------------------------------------*/ +int_fast8_t + softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr ); +#endif + +#ifndef softfloat_shortShiftLeft64To96M +/*---------------------------------------------------------------------------- +| Extends 'a' to 96 bits and shifts the value left by the number of bits given +| in 'dist', which must be in the range 1 to 31. The result is stored at the +| location pointed to by 'zPtr'. Argument 'zPtr' points to an array of three +| 32-bit elements that concatenate in the platform's normal endian order to +| form a 96-bit integer. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE +void + softfloat_shortShiftLeft64To96M( + uint64_t a, uint_fast8_t dist, uint32_t *zPtr ) +{ + zPtr[indexWord( 3, 0 )] = (uint32_t) a<>= 32 - dist; + zPtr[indexWord( 3, 2 )] = a>>32; + zPtr[indexWord( 3, 1 )] = a; +} +#else +void + softfloat_shortShiftLeft64To96M( + uint64_t a, uint_fast8_t dist, uint32_t *zPtr ); +#endif +#endif + +#ifndef softfloat_shortShiftLeftM +/*---------------------------------------------------------------------------- +| Shifts the N-bit unsigned integer pointed to by 'aPtr' left by the number +| of bits given in 'dist', where N = 'size_words' * 32. The value of 'dist' +| must be in the range 1 to 31. Any nonzero bits shifted off are lost. The +| shifted N-bit result is stored at the location pointed to by 'zPtr'. Each +| of 'aPtr' and 'zPtr' points to a 'size_words'-long array of 32-bit elements +| that concatenate in the platform's normal endian order to form an N-bit +| integer. +*----------------------------------------------------------------------------*/ +void + softfloat_shortShiftLeftM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint_fast8_t dist, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_shortShiftLeft96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_shortShiftLeftM' with +| 'size_words' = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_shortShiftLeft96M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 3, aPtr, dist, zPtr ) +#endif + +#ifndef softfloat_shortShiftLeft128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_shortShiftLeftM' with +| 'size_words' = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_shortShiftLeft128M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 4, aPtr, dist, zPtr ) +#endif + +#ifndef softfloat_shortShiftLeft160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_shortShiftLeftM' with +| 'size_words' = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_shortShiftLeft160M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 5, aPtr, dist, zPtr ) +#endif + +#ifndef softfloat_shiftLeftM +/*---------------------------------------------------------------------------- +| Shifts the N-bit unsigned integer pointed to by 'aPtr' left by the number +| of bits given in 'dist', where N = 'size_words' * 32. The value of 'dist' +| must not be zero. Any nonzero bits shifted off are lost. The shifted +| N-bit result is stored at the location pointed to by 'zPtr'. Each of 'aPtr' +| and 'zPtr' points to a 'size_words'-long array of 32-bit elements that +| concatenate in the platform's normal endian order to form an N-bit integer. +| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is +| greater than N, the stored result will be 0. +*----------------------------------------------------------------------------*/ +void + softfloat_shiftLeftM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint32_t dist, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_shiftLeft96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_shiftLeftM' with +| 'size_words' = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftLeft96M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 3, aPtr, dist, zPtr ) +#endif + +#ifndef softfloat_shiftLeft128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_shiftLeftM' with +| 'size_words' = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftLeft128M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 4, aPtr, dist, zPtr ) +#endif + +#ifndef softfloat_shiftLeft160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_shiftLeftM' with +| 'size_words' = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftLeft160M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 5, aPtr, dist, zPtr ) +#endif + +#ifndef softfloat_shortShiftRightM +/*---------------------------------------------------------------------------- +| Shifts the N-bit unsigned integer pointed to by 'aPtr' right by the number +| of bits given in 'dist', where N = 'size_words' * 32. The value of 'dist' +| must be in the range 1 to 31. Any nonzero bits shifted off are lost. The +| shifted N-bit result is stored at the location pointed to by 'zPtr'. Each +| of 'aPtr' and 'zPtr' points to a 'size_words'-long array of 32-bit elements +| that concatenate in the platform's normal endian order to form an N-bit +| integer. +*----------------------------------------------------------------------------*/ +void + softfloat_shortShiftRightM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint_fast8_t dist, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_shortShiftRight128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_shortShiftRightM' with +| 'size_words' = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_shortShiftRight128M( aPtr, dist, zPtr ) softfloat_shortShiftRightM( 4, aPtr, dist, zPtr ) +#endif + +#ifndef softfloat_shortShiftRight160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_shortShiftRightM' with +| 'size_words' = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_shortShiftRight160M( aPtr, dist, zPtr ) softfloat_shortShiftRightM( 5, aPtr, dist, zPtr ) +#endif + +#ifndef softfloat_shortShiftRightJamM +/*---------------------------------------------------------------------------- +| Shifts the N-bit unsigned integer pointed to by 'aPtr' right by the number +| of bits given in 'dist', where N = 'size_words' * 32. The value of 'dist' +| must be in the range 1 to 31. If any nonzero bits are shifted off, they are +| "jammed" into the least-significant bit of the shifted value by setting the +| least-significant bit to 1. This shifted-and-jammed N-bit result is stored +| at the location pointed to by 'zPtr'. Each of 'aPtr' and 'zPtr' points +| to a 'size_words'-long array of 32-bit elements that concatenate in the +| platform's normal endian order to form an N-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_shortShiftRightJamM( + uint_fast8_t, const uint32_t *, uint_fast8_t, uint32_t * ); +#endif + +#ifndef softfloat_shortShiftRightJam160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_shortShiftRightJamM' with +| 'size_words' = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_shortShiftRightJam160M( aPtr, dist, zPtr ) softfloat_shortShiftRightJamM( 5, aPtr, dist, zPtr ) +#endif + +#ifndef softfloat_shiftRightM +/*---------------------------------------------------------------------------- +| Shifts the N-bit unsigned integer pointed to by 'aPtr' right by the number +| of bits given in 'dist', where N = 'size_words' * 32. The value of 'dist' +| must not be zero. Any nonzero bits shifted off are lost. The shifted +| N-bit result is stored at the location pointed to by 'zPtr'. Each of 'aPtr' +| and 'zPtr' points to a 'size_words'-long array of 32-bit elements that +| concatenate in the platform's normal endian order to form an N-bit integer. +| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is +| greater than N, the stored result will be 0. +*----------------------------------------------------------------------------*/ +void + softfloat_shiftRightM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint32_t dist, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_shiftRight96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_shiftRightM' with +| 'size_words' = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftRight96M( aPtr, dist, zPtr ) softfloat_shiftRightM( 3, aPtr, dist, zPtr ) +#endif + +#ifndef softfloat_shiftRightJamM +/*---------------------------------------------------------------------------- +| Shifts the N-bit unsigned integer pointed to by 'aPtr' right by the number +| of bits given in 'dist', where N = 'size_words' * 32. The value of 'dist' +| must not be zero. If any nonzero bits are shifted off, they are "jammed" +| into the least-significant bit of the shifted value by setting the least- +| significant bit to 1. This shifted-and-jammed N-bit result is stored +| at the location pointed to by 'zPtr'. Each of 'aPtr' and 'zPtr' points +| to a 'size_words'-long array of 32-bit elements that concatenate in the +| platform's normal endian order to form an N-bit integer. +| The value of 'dist' can be arbitrarily large. In particular, if 'dist' +| is greater than N, the stored result will be either 0 or 1, depending on +| whether the original N bits are all zeros. +*----------------------------------------------------------------------------*/ +void + softfloat_shiftRightJamM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint32_t dist, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_shiftRightJam96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_shiftRightJamM' with +| 'size_words' = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftRightJam96M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 3, aPtr, dist, zPtr ) +#endif + +#ifndef softfloat_shiftRightJam128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_shiftRightJamM' with +| 'size_words' = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftRightJam128M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 4, aPtr, dist, zPtr ) +#endif + +#ifndef softfloat_shiftRightJam160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_shiftRightJamM' with +| 'size_words' = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftRightJam160M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 5, aPtr, dist, zPtr ) +#endif + +#ifndef softfloat_addM +/*---------------------------------------------------------------------------- +| Adds the two N-bit integers pointed to by 'aPtr' and 'bPtr', where N = +| 'size_words' * 32. The addition is modulo 2^N, so any carry out is lost. +| The N-bit sum is stored at the location pointed to by 'zPtr'. Each of +| 'aPtr', 'bPtr', and 'zPtr' points to a 'size_words'-long array of 32-bit +| elements that concatenate in the platform's normal endian order to form an +| N-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_addM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_add96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_addM' with 'size_words' +| = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_add96M( aPtr, bPtr, zPtr ) softfloat_addM( 3, aPtr, bPtr, zPtr ) +#endif + +#ifndef softfloat_add128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_addM' with 'size_words' +| = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_add128M( aPtr, bPtr, zPtr ) softfloat_addM( 4, aPtr, bPtr, zPtr ) +#endif + +#ifndef softfloat_add160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_addM' with 'size_words' +| = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_add160M( aPtr, bPtr, zPtr ) softfloat_addM( 5, aPtr, bPtr, zPtr ) +#endif + +#ifndef softfloat_addCarryM +/*---------------------------------------------------------------------------- +| Adds the two N-bit unsigned integers pointed to by 'aPtr' and 'bPtr', where +| N = 'size_words' * 32, plus 'carry', which must be either 0 or 1. The N-bit +| sum (modulo 2^N) is stored at the location pointed to by 'zPtr', and any +| carry out is returned as the result. Each of 'aPtr', 'bPtr', and 'zPtr' +| points to a 'size_words'-long array of 32-bit elements that concatenate in +| the platform's normal endian order to form an N-bit integer. +*----------------------------------------------------------------------------*/ +uint_fast8_t + softfloat_addCarryM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint_fast8_t carry, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_addComplCarryM +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_addCarryM', except that +| the value of the unsigned integer pointed to by 'bPtr' is bit-wise completed +| before the addition. +*----------------------------------------------------------------------------*/ +uint_fast8_t + softfloat_addComplCarryM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint_fast8_t carry, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_addComplCarry96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_addComplCarryM' with +| 'size_words' = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_addComplCarry96M( aPtr, bPtr, carry, zPtr ) softfloat_addComplCarryM( 3, aPtr, bPtr, carry, zPtr ) +#endif + +#ifndef softfloat_negXM +/*---------------------------------------------------------------------------- +| Replaces the N-bit unsigned integer pointed to by 'zPtr' by the +| 2s-complement of itself, where N = 'size_words' * 32. Argument 'zPtr' +| points to a 'size_words'-long array of 32-bit elements that concatenate in +| the platform's normal endian order to form an N-bit integer. +*----------------------------------------------------------------------------*/ +void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); +#endif + +#ifndef softfloat_negX96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_negXM' with 'size_words' +| = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_negX96M( zPtr ) softfloat_negXM( 3, zPtr ) +#endif + +#ifndef softfloat_negX128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_negXM' with 'size_words' +| = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_negX128M( zPtr ) softfloat_negXM( 4, zPtr ) +#endif + +#ifndef softfloat_negX160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_negXM' with 'size_words' +| = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_negX160M( zPtr ) softfloat_negXM( 5, zPtr ) +#endif + +#ifndef softfloat_negX256M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_negXM' with 'size_words' +| = 8 (N = 256). +*----------------------------------------------------------------------------*/ +#define softfloat_negX256M( zPtr ) softfloat_negXM( 8, zPtr ) +#endif + +#ifndef softfloat_sub1XM +/*---------------------------------------------------------------------------- +| Subtracts 1 from the N-bit integer pointed to by 'zPtr', where N = +| 'size_words' * 32. The subtraction is modulo 2^N, so any borrow out (carry +| out) is lost. Argument 'zPtr' points to a 'size_words'-long array of 32-bit +| elements that concatenate in the platform's normal endian order to form an +| N-bit integer. +*----------------------------------------------------------------------------*/ +void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ); +#endif + +#ifndef softfloat_sub1X96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_sub1XM' with 'size_words' +| = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_sub1X96M( zPtr ) softfloat_sub1XM( 3, zPtr ) +#endif + +#ifndef softfloat_sub1X160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_sub1XM' with 'size_words' +| = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_sub1X160M( zPtr ) softfloat_sub1XM( 5, zPtr ) +#endif + +#ifndef softfloat_subM +/*---------------------------------------------------------------------------- +| Subtracts the two N-bit integers pointed to by 'aPtr' and 'bPtr', where N = +| 'size_words' * 32. The subtraction is modulo 2^N, so any borrow out (carry +| out) is lost. The N-bit difference is stored at the location pointed to by +| 'zPtr'. Each of 'aPtr', 'bPtr', and 'zPtr' points to a 'size_words'-long +| array of 32-bit elements that concatenate in the platform's normal endian +| order to form an N-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_subM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_sub96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_subM' with 'size_words' +| = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_sub96M( aPtr, bPtr, zPtr ) softfloat_subM( 3, aPtr, bPtr, zPtr ) +#endif + +#ifndef softfloat_sub128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_subM' with 'size_words' +| = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_sub128M( aPtr, bPtr, zPtr ) softfloat_subM( 4, aPtr, bPtr, zPtr ) +#endif + +#ifndef softfloat_sub160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_subM' with 'size_words' +| = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_sub160M( aPtr, bPtr, zPtr ) softfloat_subM( 5, aPtr, bPtr, zPtr ) +#endif + +#ifndef softfloat_mul64To128M +/*---------------------------------------------------------------------------- +| Multiplies 'a' and 'b' and stores the 128-bit product at the location +| pointed to by 'zPtr'. Argument 'zPtr' points to an array of four 32-bit +| elements that concatenate in the platform's normal endian order to form a +| 128-bit integer. +*----------------------------------------------------------------------------*/ +void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr ); +#endif + +#ifndef softfloat_mul128MTo256M +/*---------------------------------------------------------------------------- +| Multiplies the two 128-bit unsigned integers pointed to by 'aPtr' and +| 'bPtr', and stores the 256-bit product at the location pointed to by 'zPtr'. +| Each of 'aPtr' and 'bPtr' points to an array of four 32-bit elements that +| concatenate in the platform's normal endian order to form a 128-bit integer. +| Argument 'zPtr' points to an array of eight 32-bit elements that concatenate +| to form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_mul128MTo256M( + const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr ); +#endif + +#ifndef softfloat_remStepMBy32 +/*---------------------------------------------------------------------------- +| Performs a "remainder reduction step" as follows: Arguments 'remPtr' and +| 'bPtr' both point to N-bit unsigned integers, where N = 'size_words' * 32. +| Defining R and B as the values of those integers, the expression (R<<'dist') +| - B * q is computed modulo 2^N, and the N-bit result is stored at the +| location pointed to by 'zPtr'. Each of 'remPtr', 'bPtr', and 'zPtr' points +| to a 'size_words'-long array of 32-bit elements that concatenate in the +| platform's normal endian order to form an N-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_remStepMBy32( + uint_fast8_t size_words, + const uint32_t *remPtr, + uint_fast8_t dist, + const uint32_t *bPtr, + uint32_t q, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_remStep96MBy32 +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_remStepMBy32' with +| 'size_words' = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_remStep96MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 3, remPtr, dist, bPtr, q, zPtr ) +#endif + +#ifndef softfloat_remStep128MBy32 +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_remStepMBy32' with +| 'size_words' = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_remStep128MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 4, remPtr, dist, bPtr, q, zPtr ) +#endif + +#ifndef softfloat_remStep160MBy32 +/*---------------------------------------------------------------------------- +| This function or macro is the same as 'softfloat_remStepMBy32' with +| 'size_words' = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_remStep160MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 5, remPtr, dist, bPtr, q, zPtr ) +#endif + +#endif + +#endif + diff --git a/src/softfloat/include/softfloat.h b/src/softfloat/include/softfloat.h new file mode 100644 index 000000000..9ed17c1b9 --- /dev/null +++ b/src/softfloat/include/softfloat.h @@ -0,0 +1,372 @@ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + + +/*============================================================================ +| Note: If SoftFloat is made available as a general library for programs to +| use, it is strongly recommended that a platform-specific version of this +| header, "softfloat.h", be created that folds in "softfloat_types.h" and that +| eliminates all dependencies on compile-time macros. +*============================================================================*/ + + +#ifndef softfloat_h +#define softfloat_h 1 + +#include +#include +#include "softfloat_types.h" + +#ifndef THREAD_LOCAL +#define THREAD_LOCAL +#endif + +/*---------------------------------------------------------------------------- +| Software floating-point underflow tininess-detection mode. +*----------------------------------------------------------------------------*/ +extern THREAD_LOCAL uint_fast8_t softfloat_detectTininess; +enum { + softfloat_tininess_beforeRounding = 0, + softfloat_tininess_afterRounding = 1 +}; + +/*---------------------------------------------------------------------------- +| Software floating-point rounding mode. (Mode "odd" is supported only if +| SoftFloat is compiled with macro 'SOFTFLOAT_ROUND_ODD' defined.) +*----------------------------------------------------------------------------*/ +extern THREAD_LOCAL uint_fast8_t softfloat_roundingMode; +enum { + softfloat_round_near_even = 0, + softfloat_round_minMag = 1, + softfloat_round_min = 2, + softfloat_round_max = 3, + softfloat_round_near_maxMag = 4, + softfloat_round_odd = 6 +}; + +/*---------------------------------------------------------------------------- +| Software floating-point exception flags. +*----------------------------------------------------------------------------*/ +extern THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags; +enum { + softfloat_flag_inexact = 1, + softfloat_flag_underflow = 2, + softfloat_flag_overflow = 4, + softfloat_flag_infinite = 8, + softfloat_flag_invalid = 16 +}; + +/*---------------------------------------------------------------------------- +| Routine to raise any or all of the software floating-point exception flags. +*----------------------------------------------------------------------------*/ +void softfloat_raiseFlags( uint_fast8_t ); + +/*---------------------------------------------------------------------------- +| Integer-to-floating-point conversion routines. +*----------------------------------------------------------------------------*/ +float16_t ui32_to_f16( uint32_t ); +float32_t ui32_to_f32( uint32_t ); +float64_t ui32_to_f64( uint32_t ); +#ifdef SOFTFLOAT_FAST_INT64 +extFloat80_t ui32_to_extF80( uint32_t ); +float128_t ui32_to_f128( uint32_t ); +#endif +void ui32_to_extF80M( uint32_t, extFloat80_t * ); +void ui32_to_f128M( uint32_t, float128_t * ); +float16_t ui64_to_f16( uint64_t ); +float32_t ui64_to_f32( uint64_t ); +float64_t ui64_to_f64( uint64_t ); +#ifdef SOFTFLOAT_FAST_INT64 +extFloat80_t ui64_to_extF80( uint64_t ); +float128_t ui64_to_f128( uint64_t ); +#endif +void ui64_to_extF80M( uint64_t, extFloat80_t * ); +void ui64_to_f128M( uint64_t, float128_t * ); +float16_t i32_to_f16( int32_t ); +float32_t i32_to_f32( int32_t ); +float64_t i32_to_f64( int32_t ); +#ifdef SOFTFLOAT_FAST_INT64 +extFloat80_t i32_to_extF80( int32_t ); +float128_t i32_to_f128( int32_t ); +#endif +void i32_to_extF80M( int32_t, extFloat80_t * ); +void i32_to_f128M( int32_t, float128_t * ); +float16_t i64_to_f16( int64_t ); +float32_t i64_to_f32( int64_t ); +float64_t i64_to_f64( int64_t ); +#ifdef SOFTFLOAT_FAST_INT64 +extFloat80_t i64_to_extF80( int64_t ); +float128_t i64_to_f128( int64_t ); +#endif +void i64_to_extF80M( int64_t, extFloat80_t * ); +void i64_to_f128M( int64_t, float128_t * ); + +/*---------------------------------------------------------------------------- +| 16-bit (half-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +uint_fast32_t f16_to_ui32( float16_t, uint_fast8_t, bool ); +uint_fast64_t f16_to_ui64( float16_t, uint_fast8_t, bool ); +int_fast32_t f16_to_i32( float16_t, uint_fast8_t, bool ); +int_fast64_t f16_to_i64( float16_t, uint_fast8_t, bool ); +uint_fast32_t f16_to_ui32_r_minMag( float16_t, bool ); +uint_fast64_t f16_to_ui64_r_minMag( float16_t, bool ); +int_fast32_t f16_to_i32_r_minMag( float16_t, bool ); +int_fast64_t f16_to_i64_r_minMag( float16_t, bool ); +float32_t f16_to_f32( float16_t ); +float64_t f16_to_f64( float16_t ); +#ifdef SOFTFLOAT_FAST_INT64 +extFloat80_t f16_to_extF80( float16_t ); +float128_t f16_to_f128( float16_t ); +#endif +void f16_to_extF80M( float16_t, extFloat80_t * ); +void f16_to_f128M( float16_t, float128_t * ); +float16_t f16_roundToInt( float16_t, uint_fast8_t, bool ); +float16_t f16_add( float16_t, float16_t ); +float16_t f16_sub( float16_t, float16_t ); +float16_t f16_mul( float16_t, float16_t ); +float16_t f16_mulAdd( float16_t, float16_t, float16_t ); +float16_t f16_div( float16_t, float16_t ); +float16_t f16_rem( float16_t, float16_t ); +float16_t f16_sqrt( float16_t ); +bool f16_eq( float16_t, float16_t ); +bool f16_le( float16_t, float16_t ); +bool f16_lt( float16_t, float16_t ); +bool f16_eq_signaling( float16_t, float16_t ); +bool f16_le_quiet( float16_t, float16_t ); +bool f16_lt_quiet( float16_t, float16_t ); +bool f16_isSignalingNaN( float16_t ); + +/*---------------------------------------------------------------------------- +| 32-bit (single-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +uint_fast32_t f32_to_ui32( float32_t, uint_fast8_t, bool ); +uint_fast64_t f32_to_ui64( float32_t, uint_fast8_t, bool ); +int_fast32_t f32_to_i32( float32_t, uint_fast8_t, bool ); +int_fast64_t f32_to_i64( float32_t, uint_fast8_t, bool ); +uint_fast32_t f32_to_ui32_r_minMag( float32_t, bool ); +uint_fast64_t f32_to_ui64_r_minMag( float32_t, bool ); +int_fast32_t f32_to_i32_r_minMag( float32_t, bool ); +int_fast64_t f32_to_i64_r_minMag( float32_t, bool ); +float16_t f32_to_f16( float32_t ); +float64_t f32_to_f64( float32_t ); +#ifdef SOFTFLOAT_FAST_INT64 +extFloat80_t f32_to_extF80( float32_t ); +float128_t f32_to_f128( float32_t ); +#endif +void f32_to_extF80M( float32_t, extFloat80_t * ); +void f32_to_f128M( float32_t, float128_t * ); +float32_t f32_roundToInt( float32_t, uint_fast8_t, bool ); +float32_t f32_add( float32_t, float32_t ); +float32_t f32_sub( float32_t, float32_t ); +float32_t f32_mul( float32_t, float32_t ); +float32_t f32_mulAdd( float32_t, float32_t, float32_t ); +float32_t f32_div( float32_t, float32_t ); +float32_t f32_rem( float32_t, float32_t ); +float32_t f32_sqrt( float32_t ); +bool f32_eq( float32_t, float32_t ); +bool f32_le( float32_t, float32_t ); +bool f32_lt( float32_t, float32_t ); +bool f32_eq_signaling( float32_t, float32_t ); +bool f32_le_quiet( float32_t, float32_t ); +bool f32_lt_quiet( float32_t, float32_t ); +bool f32_isSignalingNaN( float32_t ); + +/*---------------------------------------------------------------------------- +| 64-bit (double-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +uint_fast32_t f64_to_ui32( float64_t, uint_fast8_t, bool ); +uint_fast64_t f64_to_ui64( float64_t, uint_fast8_t, bool ); +int_fast32_t f64_to_i32( float64_t, uint_fast8_t, bool ); +int_fast64_t f64_to_i64( float64_t, uint_fast8_t, bool ); +uint_fast32_t f64_to_ui32_r_minMag( float64_t, bool ); +uint_fast64_t f64_to_ui64_r_minMag( float64_t, bool ); +int_fast32_t f64_to_i32_r_minMag( float64_t, bool ); +int_fast64_t f64_to_i64_r_minMag( float64_t, bool ); +float16_t f64_to_f16( float64_t ); +float32_t f64_to_f32( float64_t ); +#ifdef SOFTFLOAT_FAST_INT64 +extFloat80_t f64_to_extF80( float64_t ); +float128_t f64_to_f128( float64_t ); +#endif +void f64_to_extF80M( float64_t, extFloat80_t * ); +void f64_to_f128M( float64_t, float128_t * ); +float64_t f64_roundToInt( float64_t, uint_fast8_t, bool ); +float64_t f64_add( float64_t, float64_t ); +float64_t f64_sub( float64_t, float64_t ); +float64_t f64_mul( float64_t, float64_t ); +float64_t f64_mulAdd( float64_t, float64_t, float64_t ); +float64_t f64_div( float64_t, float64_t ); +float64_t f64_rem( float64_t, float64_t ); +float64_t f64_sqrt( float64_t ); +bool f64_eq( float64_t, float64_t ); +bool f64_le( float64_t, float64_t ); +bool f64_lt( float64_t, float64_t ); +bool f64_eq_signaling( float64_t, float64_t ); +bool f64_le_quiet( float64_t, float64_t ); +bool f64_lt_quiet( float64_t, float64_t ); +bool f64_isSignalingNaN( float64_t ); + +/*---------------------------------------------------------------------------- +| Rounding precision for 80-bit extended double-precision floating-point. +| Valid values are 32, 64, and 80. +*----------------------------------------------------------------------------*/ +extern THREAD_LOCAL uint_fast8_t extF80_roundingPrecision; + +/*---------------------------------------------------------------------------- +| 80-bit extended double-precision floating-point operations. +*----------------------------------------------------------------------------*/ +#ifdef SOFTFLOAT_FAST_INT64 +uint_fast32_t extF80_to_ui32( extFloat80_t, uint_fast8_t, bool ); +uint_fast64_t extF80_to_ui64( extFloat80_t, uint_fast8_t, bool ); +int_fast32_t extF80_to_i32( extFloat80_t, uint_fast8_t, bool ); +int_fast64_t extF80_to_i64( extFloat80_t, uint_fast8_t, bool ); +uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t, bool ); +uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t, bool ); +int_fast32_t extF80_to_i32_r_minMag( extFloat80_t, bool ); +int_fast64_t extF80_to_i64_r_minMag( extFloat80_t, bool ); +float16_t extF80_to_f16( extFloat80_t ); +float32_t extF80_to_f32( extFloat80_t ); +float64_t extF80_to_f64( extFloat80_t ); +float128_t extF80_to_f128( extFloat80_t ); +extFloat80_t extF80_roundToInt( extFloat80_t, uint_fast8_t, bool ); +extFloat80_t extF80_add( extFloat80_t, extFloat80_t ); +extFloat80_t extF80_sub( extFloat80_t, extFloat80_t ); +extFloat80_t extF80_mul( extFloat80_t, extFloat80_t ); +extFloat80_t extF80_div( extFloat80_t, extFloat80_t ); +extFloat80_t extF80_rem( extFloat80_t, extFloat80_t ); +extFloat80_t extF80_sqrt( extFloat80_t ); +bool extF80_eq( extFloat80_t, extFloat80_t ); +bool extF80_le( extFloat80_t, extFloat80_t ); +bool extF80_lt( extFloat80_t, extFloat80_t ); +bool extF80_eq_signaling( extFloat80_t, extFloat80_t ); +bool extF80_le_quiet( extFloat80_t, extFloat80_t ); +bool extF80_lt_quiet( extFloat80_t, extFloat80_t ); +bool extF80_isSignalingNaN( extFloat80_t ); +#endif +uint_fast32_t extF80M_to_ui32( const extFloat80_t *, uint_fast8_t, bool ); +uint_fast64_t extF80M_to_ui64( const extFloat80_t *, uint_fast8_t, bool ); +int_fast32_t extF80M_to_i32( const extFloat80_t *, uint_fast8_t, bool ); +int_fast64_t extF80M_to_i64( const extFloat80_t *, uint_fast8_t, bool ); +uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *, bool ); +uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *, bool ); +int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *, bool ); +int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *, bool ); +float16_t extF80M_to_f16( const extFloat80_t * ); +float32_t extF80M_to_f32( const extFloat80_t * ); +float64_t extF80M_to_f64( const extFloat80_t * ); +void extF80M_to_f128M( const extFloat80_t *, float128_t * ); +void + extF80M_roundToInt( + const extFloat80_t *, uint_fast8_t, bool, extFloat80_t * ); +void extF80M_add( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); +void extF80M_sub( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); +void extF80M_mul( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); +void extF80M_div( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); +void extF80M_rem( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); +void extF80M_sqrt( const extFloat80_t *, extFloat80_t * ); +bool extF80M_eq( const extFloat80_t *, const extFloat80_t * ); +bool extF80M_le( const extFloat80_t *, const extFloat80_t * ); +bool extF80M_lt( const extFloat80_t *, const extFloat80_t * ); +bool extF80M_eq_signaling( const extFloat80_t *, const extFloat80_t * ); +bool extF80M_le_quiet( const extFloat80_t *, const extFloat80_t * ); +bool extF80M_lt_quiet( const extFloat80_t *, const extFloat80_t * ); +bool extF80M_isSignalingNaN( const extFloat80_t * ); + +/*---------------------------------------------------------------------------- +| 128-bit (quadruple-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +#ifdef SOFTFLOAT_FAST_INT64 +uint_fast32_t f128_to_ui32( float128_t, uint_fast8_t, bool ); +uint_fast64_t f128_to_ui64( float128_t, uint_fast8_t, bool ); +int_fast32_t f128_to_i32( float128_t, uint_fast8_t, bool ); +int_fast64_t f128_to_i64( float128_t, uint_fast8_t, bool ); +uint_fast32_t f128_to_ui32_r_minMag( float128_t, bool ); +uint_fast64_t f128_to_ui64_r_minMag( float128_t, bool ); +int_fast32_t f128_to_i32_r_minMag( float128_t, bool ); +int_fast64_t f128_to_i64_r_minMag( float128_t, bool ); +float16_t f128_to_f16( float128_t ); +float32_t f128_to_f32( float128_t ); +float64_t f128_to_f64( float128_t ); +extFloat80_t f128_to_extF80( float128_t ); +float128_t f128_roundToInt( float128_t, uint_fast8_t, bool ); +float128_t f128_add( float128_t, float128_t ); +float128_t f128_sub( float128_t, float128_t ); +float128_t f128_mul( float128_t, float128_t ); +float128_t f128_mulAdd( float128_t, float128_t, float128_t ); +float128_t f128_div( float128_t, float128_t ); +float128_t f128_rem( float128_t, float128_t ); +float128_t f128_sqrt( float128_t ); +bool f128_eq( float128_t, float128_t ); +bool f128_le( float128_t, float128_t ); +bool f128_lt( float128_t, float128_t ); +bool f128_eq_signaling( float128_t, float128_t ); +bool f128_le_quiet( float128_t, float128_t ); +bool f128_lt_quiet( float128_t, float128_t ); +bool f128_isSignalingNaN( float128_t ); +#endif +uint_fast32_t f128M_to_ui32( const float128_t *, uint_fast8_t, bool ); +uint_fast64_t f128M_to_ui64( const float128_t *, uint_fast8_t, bool ); +int_fast32_t f128M_to_i32( const float128_t *, uint_fast8_t, bool ); +int_fast64_t f128M_to_i64( const float128_t *, uint_fast8_t, bool ); +uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *, bool ); +uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *, bool ); +int_fast32_t f128M_to_i32_r_minMag( const float128_t *, bool ); +int_fast64_t f128M_to_i64_r_minMag( const float128_t *, bool ); +float16_t f128M_to_f16( const float128_t * ); +float32_t f128M_to_f32( const float128_t * ); +float64_t f128M_to_f64( const float128_t * ); +void f128M_to_extF80M( const float128_t *, extFloat80_t * ); +void f128M_roundToInt( const float128_t *, uint_fast8_t, bool, float128_t * ); +void f128M_add( const float128_t *, const float128_t *, float128_t * ); +void f128M_sub( const float128_t *, const float128_t *, float128_t * ); +void f128M_mul( const float128_t *, const float128_t *, float128_t * ); +void + f128M_mulAdd( + const float128_t *, const float128_t *, const float128_t *, float128_t * + ); +void f128M_div( const float128_t *, const float128_t *, float128_t * ); +void f128M_rem( const float128_t *, const float128_t *, float128_t * ); +void f128M_sqrt( const float128_t *, float128_t * ); +bool f128M_eq( const float128_t *, const float128_t * ); +bool f128M_le( const float128_t *, const float128_t * ); +bool f128M_lt( const float128_t *, const float128_t * ); +bool f128M_eq_signaling( const float128_t *, const float128_t * ); +bool f128M_le_quiet( const float128_t *, const float128_t * ); +bool f128M_lt_quiet( const float128_t *, const float128_t * ); +bool f128M_isSignalingNaN( const float128_t * ); + +#endif + diff --git a/src/softfloat/include/softfloat_types.h b/src/softfloat/include/softfloat_types.h new file mode 100644 index 000000000..b92d24625 --- /dev/null +++ b/src/softfloat/include/softfloat_types.h @@ -0,0 +1,81 @@ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef softfloat_types_h +#define softfloat_types_h 1 + +#include + +/*---------------------------------------------------------------------------- +| Types used to pass 16-bit, 32-bit, 64-bit, and 128-bit floating-point +| arguments and results to/from functions. These types must be exactly +| 16 bits, 32 bits, 64 bits, and 128 bits in size, respectively. Where a +| platform has "native" support for IEEE-Standard floating-point formats, +| the types below may, if desired, be defined as aliases for the native types +| (typically 'float' and 'double', and possibly 'long double'). +*----------------------------------------------------------------------------*/ +typedef struct { uint16_t v; } float16_t; +typedef struct { uint32_t v; } float32_t; +typedef struct { uint64_t v; } float64_t; +typedef struct { uint64_t v[2]; } float128_t; + +/*---------------------------------------------------------------------------- +| The format of an 80-bit extended floating-point number in memory. This +| structure must contain a 16-bit field named 'signExp' and a 64-bit field +| named 'signif'. +*----------------------------------------------------------------------------*/ +#ifdef LITTLEENDIAN +struct extFloat80M { uint64_t signif; uint16_t signExp; }; +#else +struct extFloat80M { uint16_t signExp; uint64_t signif; }; +#endif + +/*---------------------------------------------------------------------------- +| The type used to pass 80-bit extended floating-point arguments and +| results to/from functions. This type must have size identical to +| 'struct extFloat80M'. Type 'extFloat80_t' can be defined as an alias for +| 'struct extFloat80M'. Alternatively, if a platform has "native" support +| for IEEE-Standard 80-bit extended floating-point, it may be possible, +| if desired, to define 'extFloat80_t' as an alias for the native type +| (presumably either 'long double' or a nonstandard compiler-intrinsic type). +| In that case, the 'signif' and 'signExp' fields of 'struct extFloat80M' +| must align exactly with the locations in memory of the sign, exponent, and +| significand of the native type. +*----------------------------------------------------------------------------*/ +typedef struct extFloat80M extFloat80_t; + +#endif + diff --git a/src/softfloat/include/specialize.h b/src/softfloat/include/specialize.h new file mode 100644 index 000000000..a9166e170 --- /dev/null +++ b/src/softfloat/include/specialize.h @@ -0,0 +1,376 @@ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2018 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef specialize_h +#define specialize_h 1 + +#include +#include +#include "primitiveTypes.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Default value for 'softfloat_detectTininess'. +*----------------------------------------------------------------------------*/ +#define init_detectTininess softfloat_tininess_afterRounding + +/*---------------------------------------------------------------------------- +| The values to return on conversions to 32-bit integer formats that raise an +| invalid exception. +*----------------------------------------------------------------------------*/ +#define ui32_fromPosOverflow 0xFFFFFFFF +#define ui32_fromNegOverflow 0xFFFFFFFF +#define ui32_fromNaN 0xFFFFFFFF +#define i32_fromPosOverflow (-0x7FFFFFFF - 1) +#define i32_fromNegOverflow (-0x7FFFFFFF - 1) +#define i32_fromNaN (-0x7FFFFFFF - 1) + +/*---------------------------------------------------------------------------- +| The values to return on conversions to 64-bit integer formats that raise an +| invalid exception. +*----------------------------------------------------------------------------*/ +#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) +#define ui64_fromNegOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) +#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF ) +#define i64_fromPosOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) +#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) +#define i64_fromNaN (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) + +/*---------------------------------------------------------------------------- +| "Common NaN" structure, used to transfer NaN representations from one format +| to another. +*----------------------------------------------------------------------------*/ +struct commonNaN { + bool sign; +#ifdef LITTLEENDIAN + uint64_t v0, v64; +#else + uint64_t v64, v0; +#endif +}; + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 16-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF16UI 0xFE00 + +/*---------------------------------------------------------------------------- +| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a +| 16-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF)) + +/*---------------------------------------------------------------------------- +| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); + +/*---------------------------------------------------------------------------- +| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast16_t + softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 32-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF32UI 0xFFC00000 + +/*---------------------------------------------------------------------------- +| Returns true when 32-bit unsigned integer 'uiA' has the bit pattern of a +| 32-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) + +/*---------------------------------------------------------------------------- +| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); + +/*---------------------------------------------------------------------------- +| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast32_t + softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 64-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 ) + +/*---------------------------------------------------------------------------- +| Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a +| 64-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) + +/*---------------------------------------------------------------------------- +| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); + +/*---------------------------------------------------------------------------- +| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast64_t + softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 80-bit extended floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNExtF80UI64 0xFFFF +#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) + +/*---------------------------------------------------------------------------- +| Returns true when the 80-bit unsigned integer formed from concatenating +| 16-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of an 80-bit extended +| floating-point signaling NaN. +| Note: This macro evaluates its arguments more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) + +#ifdef SOFTFLOAT_FAST_INT64 + +/*---------------------------------------------------------------------------- +| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is +| defined. +*----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' +| has the bit pattern of an 80-bit extended floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_extF80UIToCommonNaN( + uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended +| floating-point NaN, and returns the bit pattern of this value as an unsigned +| integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating 'uiA64' and +| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting +| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another +| 80-bit extended floating-point value, and assuming at least on of these +| floating-point values is a NaN, returns the bit pattern of the combined NaN +| result. If either original floating-point value is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNExtF80UI( + uint_fast16_t uiA64, + uint_fast64_t uiA0, + uint_fast16_t uiB64, + uint_fast64_t uiB0 + ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 128-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 ) +#define defaultNaNF128UI0 UINT64_C( 0 ) + +/*---------------------------------------------------------------------------- +| Returns true when the 128-bit unsigned integer formed from concatenating +| 64-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of a 128-bit floating- +| point signaling NaN. +| Note: This macro evaluates its arguments more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' +| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to +| the common NaN form, and stores the resulting common NaN at the location +| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception +| is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_f128UIToCommonNaN( + uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating 'uiA64' and +| 'uiA0' as a 128-bit floating-point value, and likewise interpreting the +| unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another +| 128-bit floating-point value, and assuming at least on of these floating- +| point values is a NaN, returns the bit pattern of the combined NaN result. +| If either original floating-point value is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNF128UI( + uint_fast64_t uiA64, + uint_fast64_t uiA0, + uint_fast64_t uiB64, + uint_fast64_t uiB0 + ); + +#else + +/*---------------------------------------------------------------------------- +| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is not +| defined. +*----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +| Assuming the 80-bit extended floating-point value pointed to by 'aSPtr' is +| a NaN, converts this NaN to the common NaN form, and stores the resulting +| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling +| NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_extF80MToCommonNaN( + const struct extFloat80M *aSPtr, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended +| floating-point NaN, and stores this NaN at the location pointed to by +| 'zSPtr'. +*----------------------------------------------------------------------------*/ +void + softfloat_commonNaNToExtF80M( + const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); + +/*---------------------------------------------------------------------------- +| Assuming at least one of the two 80-bit extended floating-point values +| pointed to by 'aSPtr' and 'bSPtr' is a NaN, stores the combined NaN result +| at the location pointed to by 'zSPtr'. If either original floating-point +| value is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_propagateNaNExtF80M( + const struct extFloat80M *aSPtr, + const struct extFloat80M *bSPtr, + struct extFloat80M *zSPtr + ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 128-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF128UI96 0xFFFF8000 +#define defaultNaNF128UI64 0 +#define defaultNaNF128UI32 0 +#define defaultNaNF128UI0 0 + +/*---------------------------------------------------------------------------- +| Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN, +| converts this NaN to the common NaN form, and stores the resulting common +| NaN at the location pointed to by 'zPtr'. If the NaN is a signaling NaN, +| the invalid exception is raised. Argument 'aWPtr' points to an array of +| four 32-bit elements that concatenate in the platform's normal endian order +| to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point +| NaN, and stores this NaN at the location pointed to by 'zWPtr'. Argument +| 'zWPtr' points to an array of four 32-bit elements that concatenate in the +| platform's normal endian order to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); + +/*---------------------------------------------------------------------------- +| Assuming at least one of the two 128-bit floating-point values pointed to by +| 'aWPtr' and 'bWPtr' is a NaN, stores the combined NaN result at the location +| pointed to by 'zWPtr'. If either original floating-point value is a +| signaling NaN, the invalid exception is raised. Each of 'aWPtr', 'bWPtr', +| and 'zWPtr' points to an array of four 32-bit elements that concatenate in +| the platform's normal endian order to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_propagateNaNF128M( + const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); + +#endif + +#endif + diff --git a/src/softfloat/makefile b/src/softfloat/makefile new file mode 100644 index 000000000..97fbdd938 --- /dev/null +++ b/src/softfloat/makefile @@ -0,0 +1,52 @@ +# Copyright (C) 2015-2024 CE Programming +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(CURDIR)/../common.mk + +BUILD_SRC := $(patsubst %,build/%.src,$(wildcard *.c *.cpp)) + +EZCFLAGS := -S -Wall -Wextra -Wshadow -Oz +EZCFLAGS += -D_EZ80 -isystem ../libc/include -I ./include +EZCXXFLAGS := $(EZCFLAGS) -fno-exceptions -fno-rtti + +WILDCARD_SRC = $(wildcard *.src) $(BUILD_SRC) +WILDCARD_H := $(wildcard include/*.h) + +all: $(BUILD_SRC) + +build/%.c.src: %.c + $(Q)$(call MKDIR,build) + $(Q)$(EZCC) $(EZCFLAGS) $< -o $@ + +build/%.cpp.src: %.cpp + $(Q)$(call MKDIR,build) + $(Q)$(EZCC) $(EZCXXFLAGS) $< -o $@ + +clean: + $(Q)$(call RMDIR,build) + +# install: all +# $(Q)$(call MKDIR,$(INSTALL_H)) +# $(Q)$(call MKDIR,$(INSTALL_SOFTFLOAT)) +# $(Q)$(call COPY,$(call NATIVEPATH,$(WILDCARD_SRC)),$(INSTALL_SOFTFLOAT)) +# $(Q)$(call COPY,$(foreach file,$(call NATIVEPATH,$(WILDCARD_H)),$(call QUOTE_ARG,$(file))),$(INSTALL_H)) + +install: all + $(Q)$(call MKDIR,$(INSTALL_SOFTFLOAT)) + $(Q)$(call COPY,$(call NATIVEPATH,$(WILDCARD_SRC)),$(INSTALL_SOFTFLOAT)) + +.PHONY: all clean + diff --git a/src/softfloat/s_addM.c b/src/softfloat/s_addM.c new file mode 100644 index 000000000..e1cc66bf0 --- /dev/null +++ b/src/softfloat/s_addM.c @@ -0,0 +1,70 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_addM + +void + softfloat_addM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint32_t *zPtr + ) +{ + unsigned int index, lastIndex; + uint_fast8_t carry; + uint32_t wordA, wordZ; + + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + carry = 0; + for (;;) { + wordA = aPtr[index]; + wordZ = wordA + bPtr[index] + carry; + zPtr[index] = wordZ; + if ( index == lastIndex ) break; + if ( wordZ != wordA ) carry = (wordZ < wordA); + index += wordIncr; + } + +} + +#endif + diff --git a/src/softfloat/s_addMagsF64.c b/src/softfloat/s_addMagsF64.c new file mode 100644 index 000000000..25b8f386e --- /dev/null +++ b/src/softfloat/s_addMagsF64.c @@ -0,0 +1,128 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" + +float64_t + softfloat_addMagsF64( uint_fast64_t uiA, uint_fast64_t uiB, bool signZ ) +{ + int_fast16_t expA; + uint_fast64_t sigA; + int_fast16_t expB; + uint_fast64_t sigB; + int_fast16_t expDiff; + uint_fast64_t uiZ; + int_fast16_t expZ; + uint_fast64_t sigZ; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if ( ! expDiff ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( ! expA ) { + uiZ = uiA + sigB; + goto uiZ; + } + if ( expA == 0x7FF ) { + if ( sigA | sigB ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + expZ = expA; + sigZ = UINT64_C( 0x0020000000000000 ) + sigA + sigB; + sigZ <<= 9; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sigA <<= 9; + sigB <<= 9; + if ( expDiff < 0 ) { + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + uiZ = packToF64UI( signZ, 0x7FF, 0 ); + goto uiZ; + } + expZ = expB; + if ( expA ) { + sigA += UINT64_C( 0x2000000000000000 ); + } else { + sigA <<= 1; + } + sigA = softfloat_shiftRightJam64( sigA, -expDiff ); + } else { + if ( expA == 0x7FF ) { + if ( sigA ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + expZ = expA; + if ( expB ) { + sigB += UINT64_C( 0x2000000000000000 ); + } else { + sigB <<= 1; + } + sigB = softfloat_shiftRightJam64( sigB, expDiff ); + } + sigZ = UINT64_C( 0x2000000000000000 ) + sigA + sigB; + if ( sigZ < UINT64_C( 0x4000000000000000 ) ) { + --expZ; + sigZ <<= 1; + } + } + return softfloat_roundPackToF64( signZ, expZ, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/src/softfloat/s_approxRecip32_1.c b/src/softfloat/s_approxRecip32_1.c new file mode 100644 index 000000000..f4fdbfe5b --- /dev/null +++ b/src/softfloat/s_approxRecip32_1.c @@ -0,0 +1,66 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" + +#ifndef softfloat_approxRecip32_1 + +extern const uint16_t softfloat_approxRecip_1k0s[16]; +extern const uint16_t softfloat_approxRecip_1k1s[16]; + +uint32_t softfloat_approxRecip32_1( uint32_t a ) +{ + int index; + uint16_t eps, r0; + uint32_t sigma0; + uint_fast32_t r; + uint32_t sqrSigma0; + + index = a>>27 & 0xF; + eps = (uint16_t) (a>>11); + r0 = softfloat_approxRecip_1k0s[index] + - ((softfloat_approxRecip_1k1s[index] * (uint_fast32_t) eps)>>20); + sigma0 = ~(uint_fast32_t) ((r0 * (uint_fast64_t) a)>>7); + r = ((uint_fast32_t) r0<<16) + ((r0 * (uint_fast64_t) sigma0)>>24); + sqrSigma0 = ((uint_fast64_t) sigma0 * sigma0)>>32; + r += ((uint32_t) r * (uint_fast64_t) sqrSigma0)>>48; + return r; + +} + +#endif + diff --git a/src/softfloat/s_approxRecipSqrt32_1.c b/src/softfloat/s_approxRecipSqrt32_1.c new file mode 100644 index 000000000..28eca6495 --- /dev/null +++ b/src/softfloat/s_approxRecipSqrt32_1.c @@ -0,0 +1,73 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" + +#ifndef softfloat_approxRecipSqrt32_1 + +extern const uint16_t softfloat_approxRecipSqrt_1k0s[]; +extern const uint16_t softfloat_approxRecipSqrt_1k1s[]; + +uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a ) +{ + int index; + uint16_t eps, r0; + uint_fast32_t ESqrR0; + uint32_t sigma0; + uint_fast32_t r; + uint32_t sqrSigma0; + + index = (a>>27 & 0xE) + oddExpA; + eps = (uint16_t) (a>>12); + r0 = softfloat_approxRecipSqrt_1k0s[index] + - ((softfloat_approxRecipSqrt_1k1s[index] * (uint_fast32_t) eps) + >>20); + ESqrR0 = (uint_fast32_t) r0 * r0; + if ( ! oddExpA ) ESqrR0 <<= 1; + sigma0 = ~(uint_fast32_t) (((uint32_t) ESqrR0 * (uint_fast64_t) a)>>23); + r = ((uint_fast32_t) r0<<16) + ((r0 * (uint_fast64_t) sigma0)>>25); + sqrSigma0 = ((uint_fast64_t) sigma0 * sigma0)>>32; + r += ((uint32_t) ((r>>1) + (r>>3) - ((uint_fast32_t) r0<<14)) + * (uint_fast64_t) sqrSigma0) + >>48; + if ( ! (r & 0x80000000) ) r = 0x80000000; + return r; + +} + +#endif + diff --git a/src/softfloat/s_approxRecipSqrt_1Ks.c b/src/softfloat/s_approxRecipSqrt_1Ks.c new file mode 100644 index 000000000..7a8663b51 --- /dev/null +++ b/src/softfloat/s_approxRecipSqrt_1Ks.c @@ -0,0 +1,49 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "primitives.h" + +const uint16_t softfloat_approxRecipSqrt_1k0s[16] = { + 0xB4C9, 0xFFAB, 0xAA7D, 0xF11C, 0xA1C5, 0xE4C7, 0x9A43, 0xDA29, + 0x93B5, 0xD0E5, 0x8DED, 0xC8B7, 0x88C6, 0xC16D, 0x8424, 0xBAE1 +}; +const uint16_t softfloat_approxRecipSqrt_1k1s[16] = { + 0xA5A5, 0xEA42, 0x8C21, 0xC62D, 0x788F, 0xAA7F, 0x6928, 0x94B6, + 0x5CC7, 0x8335, 0x52A6, 0x74E2, 0x4A3E, 0x68FE, 0x432B, 0x5EFD +}; + diff --git a/src/softfloat/s_approxRecip_1Ks.c b/src/softfloat/s_approxRecip_1Ks.c new file mode 100644 index 000000000..54b1b0fab --- /dev/null +++ b/src/softfloat/s_approxRecip_1Ks.c @@ -0,0 +1,49 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "primitives.h" + +const uint16_t softfloat_approxRecip_1k0s[16] = { + 0xFFC4, 0xF0BE, 0xE363, 0xD76F, 0xCCAD, 0xC2F0, 0xBA16, 0xB201, + 0xAA97, 0xA3C6, 0x9D7A, 0x97A6, 0x923C, 0x8D32, 0x887E, 0x8417 +}; +const uint16_t softfloat_approxRecip_1k1s[16] = { + 0xF0F1, 0xD62C, 0xBFA1, 0xAC77, 0x9C0A, 0x8DDB, 0x8185, 0x76BA, + 0x6D3B, 0x64D4, 0x5D5C, 0x56B1, 0x50B6, 0x4B55, 0x4679, 0x4211 +}; + diff --git a/src/softfloat/s_commonNaNToF32UI.c b/src/softfloat/s_commonNaNToF32UI.c new file mode 100644 index 000000000..982c1edf6 --- /dev/null +++ b/src/softfloat/s_commonNaNToF32UI.c @@ -0,0 +1,51 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ) +{ + + return (uint_fast32_t) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41; + +} + diff --git a/src/softfloat/s_commonNaNToF64UI.c b/src/softfloat/s_commonNaNToF64UI.c new file mode 100644 index 000000000..d88c68ade --- /dev/null +++ b/src/softfloat/s_commonNaNToF64UI.c @@ -0,0 +1,53 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ) +{ + + return + (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FF8000000000000 ) + | aPtr->v64>>12; + +} + diff --git a/src/softfloat/s_countLeadingZeros16.c b/src/softfloat/s_countLeadingZeros16.c new file mode 100644 index 000000000..af2831cc9 --- /dev/null +++ b/src/softfloat/s_countLeadingZeros16.c @@ -0,0 +1,60 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" + +#ifndef softfloat_countLeadingZeros16 + +#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16 +#include "primitives.h" + +uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ) +{ + uint_fast8_t count; + + count = 8; + if ( 0x100 <= a ) { + count = 0; + a >>= 8; + } + count += softfloat_countLeadingZeros8[a]; + return count; + +} + +#endif + diff --git a/src/softfloat/s_countLeadingZeros32.c b/src/softfloat/s_countLeadingZeros32.c new file mode 100644 index 000000000..a7c50cd45 --- /dev/null +++ b/src/softfloat/s_countLeadingZeros32.c @@ -0,0 +1,64 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" + +#ifndef softfloat_countLeadingZeros32 + +#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 +#include "primitives.h" + +uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) +{ + uint_fast8_t count; + + count = 0; + if ( a < 0x10000 ) { + count = 16; + a <<= 16; + } + if ( a < 0x1000000 ) { + count += 8; + a <<= 8; + } + count += softfloat_countLeadingZeros8[a>>24]; + return count; + +} + +#endif + diff --git a/src/softfloat/s_countLeadingZeros64.c b/src/softfloat/s_countLeadingZeros64.c new file mode 100644 index 000000000..34745b12e --- /dev/null +++ b/src/softfloat/s_countLeadingZeros64.c @@ -0,0 +1,73 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" + +#ifndef softfloat_countLeadingZeros64 + +#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64 +#include "primitives.h" + +uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ) +{ + uint_fast8_t count; + uint32_t a32; + + count = 0; + a32 = a>>32; + if ( ! a32 ) { + count = 32; + a32 = a; + } + /*------------------------------------------------------------------------ + | From here, result is current count + count leading zeros of `a32'. + *------------------------------------------------------------------------*/ + if ( a32 < 0x10000 ) { + count += 16; + a32 <<= 16; + } + if ( a32 < 0x1000000 ) { + count += 8; + a32 <<= 8; + } + count += softfloat_countLeadingZeros8[a32>>24]; + return count; + +} + +#endif + diff --git a/src/softfloat/s_countLeadingZeros8.c b/src/softfloat/s_countLeadingZeros8.c new file mode 100644 index 000000000..0cc60a110 --- /dev/null +++ b/src/softfloat/s_countLeadingZeros8.c @@ -0,0 +1,59 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "primitives.h" + +const uint_least8_t softfloat_countLeadingZeros8[256] = { + 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, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 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, + 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, + 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, + 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 +}; + diff --git a/src/softfloat/s_f32UIToCommonNaN.c b/src/softfloat/s_f32UIToCommonNaN.c new file mode 100644 index 000000000..f4734db7a --- /dev/null +++ b/src/softfloat/s_f32UIToCommonNaN.c @@ -0,0 +1,59 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ) +{ + + if ( softfloat_isSigNaNF32UI( uiA ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + zPtr->sign = uiA>>31; + zPtr->v64 = (uint_fast64_t) uiA<<41; + zPtr->v0 = 0; + +} + diff --git a/src/softfloat/s_f64UIToCommonNaN.c b/src/softfloat/s_f64UIToCommonNaN.c new file mode 100644 index 000000000..9a481a74f --- /dev/null +++ b/src/softfloat/s_f64UIToCommonNaN.c @@ -0,0 +1,59 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ) +{ + + if ( softfloat_isSigNaNF64UI( uiA ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + zPtr->sign = uiA>>63; + zPtr->v64 = uiA<<12; + zPtr->v0 = 0; + +} + diff --git a/src/softfloat/s_mul64To128M.c b/src/softfloat/s_mul64To128M.c new file mode 100644 index 000000000..cd1528978 --- /dev/null +++ b/src/softfloat/s_mul64To128M.c @@ -0,0 +1,68 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_mul64To128M + +void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr ) +{ + uint32_t a32, a0, b32, b0; + uint64_t z0, mid1, z64, mid; + + a32 = a>>32; + a0 = a; + b32 = b>>32; + b0 = b; + z0 = (uint64_t) a0 * b0; + mid1 = (uint64_t) a32 * b0; + mid = mid1 + (uint64_t) a0 * b32; + z64 = (uint64_t) a32 * b32; + z64 += (uint64_t) (mid < mid1)<<32 | mid>>32; + mid <<= 32; + z0 += mid; + zPtr[indexWord( 4, 1 )] = z0>>32; + zPtr[indexWord( 4, 0 )] = z0; + z64 += (z0 < mid); + zPtr[indexWord( 4, 3 )] = z64>>32; + zPtr[indexWord( 4, 2 )] = z64; + +} + +#endif + diff --git a/src/softfloat/s_mulAddF32.c b/src/softfloat/s_mulAddF32.c new file mode 100644 index 000000000..805517c55 --- /dev/null +++ b/src/softfloat/s_mulAddF32.c @@ -0,0 +1,224 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t + softfloat_mulAddF32( + uint_fast32_t uiA, uint_fast32_t uiB, uint_fast32_t uiC, uint_fast8_t op ) +{ + bool signA; + int_fast16_t expA; + uint_fast32_t sigA; + bool signB; + int_fast16_t expB; + uint_fast32_t sigB; + bool signC; + int_fast16_t expC; + uint_fast32_t sigC; + bool signProd; + uint_fast32_t magBits, uiZ; + struct exp16_sig32 normExpSig; + int_fast16_t expProd; + uint_fast64_t sigProd; + bool signZ; + int_fast16_t expZ; + uint_fast32_t sigZ; + int_fast16_t expDiff; + uint_fast64_t sig64Z, sig64C; + int_fast8_t shiftDist; + union ui32_f32 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI( uiA ); + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + signB = signF32UI( uiB ); + expB = expF32UI( uiB ); + sigB = fracF32UI( uiB ); + signC = signF32UI( uiC ) ^ (op == softfloat_mulAdd_subC); + expC = expF32UI( uiC ); + sigC = fracF32UI( uiC ); + signProd = signA ^ signB ^ (op == softfloat_mulAdd_subProd); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0xFF ) { + if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN_ABC; + magBits = expB | sigB; + goto infProdArg; + } + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN_ABC; + magBits = expA | sigA; + goto infProdArg; + } + if ( expC == 0xFF ) { + if ( sigC ) { + uiZ = 0; + goto propagateNaN_ZC; + } + uiZ = uiC; + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! sigA ) goto zeroProd; + normExpSig = softfloat_normSubnormalF32Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) { + if ( ! sigB ) goto zeroProd; + normExpSig = softfloat_normSubnormalF32Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expProd = expA + expB - 0x7E; + sigA = (sigA | 0x00800000)<<7; + sigB = (sigB | 0x00800000)<<7; + sigProd = (uint_fast64_t) sigA * sigB; + if ( sigProd < UINT64_C( 0x2000000000000000 ) ) { + --expProd; + sigProd <<= 1; + } + signZ = signProd; + if ( ! expC ) { + if ( ! sigC ) { + expZ = expProd - 1; + sigZ = softfloat_shortShiftRightJam64( sigProd, 31 ); + goto roundPack; + } + normExpSig = softfloat_normSubnormalF32Sig( sigC ); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | 0x00800000)<<6; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expProd - expC; + if ( signProd == signC ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( expDiff <= 0 ) { + expZ = expC; + sigZ = sigC + softfloat_shiftRightJam64( sigProd, 32 - expDiff ); + } else { + expZ = expProd; + sig64Z = + sigProd + + softfloat_shiftRightJam64( + (uint_fast64_t) sigC<<32, expDiff ); + sigZ = softfloat_shortShiftRightJam64( sig64Z, 32 ); + } + if ( sigZ < 0x40000000 ) { + --expZ; + sigZ <<= 1; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig64C = (uint_fast64_t) sigC<<32; + if ( expDiff < 0 ) { + signZ = signC; + expZ = expC; + sig64Z = sig64C - softfloat_shiftRightJam64( sigProd, -expDiff ); + } else if ( ! expDiff ) { + expZ = expProd; + sig64Z = sigProd - sig64C; + if ( ! sig64Z ) goto completeCancellation; + if ( sig64Z & UINT64_C( 0x8000000000000000 ) ) { + signZ = ! signZ; + sig64Z = -sig64Z; + } + } else { + expZ = expProd; + sig64Z = sigProd - softfloat_shiftRightJam64( sig64C, expDiff ); + } + shiftDist = softfloat_countLeadingZeros64( sig64Z ) - 1; + expZ -= shiftDist; + shiftDist -= 32; + if ( shiftDist < 0 ) { + sigZ = softfloat_shortShiftRightJam64( sig64Z, -shiftDist ); + } else { + sigZ = (uint_fast32_t) sig64Z< +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +float64_t + softfloat_mulAddF64( + uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC, uint_fast8_t op ) +{ + bool signA; + int_fast16_t expA; + uint_fast64_t sigA; + bool signB; + int_fast16_t expB; + uint_fast64_t sigB; + bool signC; + int_fast16_t expC; + uint_fast64_t sigC; + bool signZ; + uint_fast64_t magBits, uiZ; + struct exp16_sig64 normExpSig; + int_fast16_t expZ; + struct uint128 sig128Z; + uint_fast64_t sigZ; + int_fast16_t expDiff; + struct uint128 sig128C; + int_fast8_t shiftDist; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + signB = signF64UI( uiB ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + signC = signF64UI( uiC ) ^ (op == softfloat_mulAdd_subC); + expC = expF64UI( uiC ); + sigC = fracF64UI( uiC ); + signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN_ABC; + magBits = expB | sigB; + goto infProdArg; + } + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN_ABC; + magBits = expA | sigA; + goto infProdArg; + } + if ( expC == 0x7FF ) { + if ( sigC ) { + uiZ = 0; + goto propagateNaN_ZC; + } + uiZ = uiC; + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! sigA ) goto zeroProd; + normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) { + if ( ! sigB ) goto zeroProd; + normExpSig = softfloat_normSubnormalF64Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FE; + sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10; + sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<10; + sig128Z = softfloat_mul64To128( sigA, sigB ); + if ( sig128Z.v64 < UINT64_C( 0x2000000000000000 ) ) { + --expZ; + sig128Z = + softfloat_add128( + sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0 ); + } + if ( ! expC ) { + if ( ! sigC ) { + --expZ; + sigZ = sig128Z.v64<<1 | (sig128Z.v0 != 0); + goto roundPack; + } + normExpSig = softfloat_normSubnormalF64Sig( sigC ); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | UINT64_C( 0x0010000000000000 ))<<9; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expZ - expC; + if ( expDiff < 0 ) { + expZ = expC; + if ( (signZ == signC) || (expDiff < -1) ) { + sig128Z.v64 = softfloat_shiftRightJam64( sig128Z.v64, -expDiff ); + } else { + sig128Z = + softfloat_shortShiftRightJam128( sig128Z.v64, sig128Z.v0, 1 ); + } + } else if ( expDiff ) { + sig128C = softfloat_shiftRightJam128( sigC, 0, expDiff ); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( signZ == signC ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( expDiff <= 0 ) { + sigZ = (sigC + sig128Z.v64) | (sig128Z.v0 != 0); + } else { + sig128Z = + softfloat_add128( + sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0 ); + sigZ = sig128Z.v64 | (sig128Z.v0 != 0); + } + if ( sigZ < UINT64_C( 0x4000000000000000 ) ) { + --expZ; + sigZ <<= 1; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( expDiff < 0 ) { + signZ = signC; + sig128Z = softfloat_sub128( sigC, 0, sig128Z.v64, sig128Z.v0 ); + } else if ( ! expDiff ) { + sig128Z.v64 = sig128Z.v64 - sigC; + if ( ! (sig128Z.v64 | sig128Z.v0) ) goto completeCancellation; + if ( sig128Z.v64 & UINT64_C( 0x8000000000000000 ) ) { + signZ = ! signZ; + sig128Z = softfloat_sub128( 0, 0, sig128Z.v64, sig128Z.v0 ); + } + } else { + sig128Z = + softfloat_sub128( + sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0 ); + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( ! sig128Z.v64 ) { + expZ -= 64; + sig128Z.v64 = sig128Z.v0; + sig128Z.v0 = 0; + } + shiftDist = softfloat_countLeadingZeros64( sig128Z.v64 ) - 1; + expZ -= shiftDist; + if ( shiftDist < 0 ) { + sigZ = softfloat_shortShiftRightJam64( sig128Z.v64, -shiftDist ); + } else { + sig128Z = + softfloat_shortShiftLeft128( + sig128Z.v64, sig128Z.v0, shiftDist ); + sigZ = sig128Z.v64; + } + sigZ |= (sig128Z.v0 != 0); + } + roundPack: + return softfloat_roundPackToF64( signZ, expZ, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN_ABC: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + goto propagateNaN_ZC; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infProdArg: + if ( magBits ) { + uiZ = packToF64UI( signZ, 0x7FF, 0 ); + if ( expC != 0x7FF ) goto uiZ; + if ( sigC ) goto propagateNaN_ZC; + if ( signZ == signC ) goto uiZ; + } + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + propagateNaN_ZC: + uiZ = softfloat_propagateNaNF64UI( uiZ, uiC ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zeroProd: + uiZ = uiC; + if ( ! (expC | sigC) && (signZ != signC) ) { + completeCancellation: + uiZ = + packToF64UI( + (softfloat_roundingMode == softfloat_round_min), 0, 0 ); + } + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + +#else + +float64_t + softfloat_mulAddF64( + uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC, uint_fast8_t op ) +{ + bool signA; + int_fast16_t expA; + uint64_t sigA; + bool signB; + int_fast16_t expB; + uint64_t sigB; + bool signC; + int_fast16_t expC; + uint64_t sigC; + bool signZ; + uint64_t magBits, uiZ; + struct exp16_sig64 normExpSig; + int_fast16_t expZ; + uint32_t sig128Z[4]; + uint64_t sigZ; + int_fast16_t shiftDist, expDiff; + uint32_t sig128C[4]; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + signB = signF64UI( uiB ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + signC = signF64UI( uiC ) ^ (op == softfloat_mulAdd_subC); + expC = expF64UI( uiC ); + sigC = fracF64UI( uiC ); + signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN_ABC; + magBits = expB | sigB; + goto infProdArg; + } + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN_ABC; + magBits = expA | sigA; + goto infProdArg; + } + if ( expC == 0x7FF ) { + if ( sigC ) { + uiZ = 0; + goto propagateNaN_ZC; + } + uiZ = uiC; + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! sigA ) goto zeroProd; + normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) { + if ( ! sigB ) goto zeroProd; + normExpSig = softfloat_normSubnormalF64Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FE; + sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10; + sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<11; + softfloat_mul64To128M( sigA, sigB, sig128Z ); + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; + shiftDist = 0; + if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) { + --expZ; + shiftDist = -1; + } + if ( ! expC ) { + if ( ! sigC ) { + if ( shiftDist ) sigZ <<= 1; + goto sigZ; + } + normExpSig = softfloat_normSubnormalF64Sig( sigC ); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | UINT64_C( 0x0010000000000000 ))<<10; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expZ - expC; + if ( expDiff < 0 ) { + expZ = expC; + if ( (signZ == signC) || (expDiff < -1) ) { + shiftDist -= expDiff; + if ( shiftDist) { + sigZ = softfloat_shiftRightJam64( sigZ, shiftDist ); + } + } else { + if ( ! shiftDist ) { + softfloat_shortShiftRight128M( sig128Z, 1, sig128Z ); + } + } + } else { + if ( shiftDist ) softfloat_add128M( sig128Z, sig128Z, sig128Z ); + if ( ! expDiff ) { + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 + | sig128Z[indexWord( 4, 2 )]; + } else { + sig128C[indexWord( 4, 3 )] = sigC>>32; + sig128C[indexWord( 4, 2 )] = sigC; + sig128C[indexWord( 4, 1 )] = 0; + sig128C[indexWord( 4, 0 )] = 0; + softfloat_shiftRightJam128M( sig128C, expDiff, sig128C ); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( signZ == signC ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( expDiff <= 0 ) { + sigZ += sigC; + } else { + softfloat_add128M( sig128Z, sig128C, sig128Z ); + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 + | sig128Z[indexWord( 4, 2 )]; + } + if ( sigZ & UINT64_C( 0x8000000000000000 ) ) { + ++expZ; + sigZ = softfloat_shortShiftRightJam64( sigZ, 1 ); + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( expDiff < 0 ) { + signZ = signC; + if ( expDiff < -1 ) { + sigZ = sigC - sigZ; + if ( + sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] + ) { + sigZ = (sigZ - 1) | 1; + } + if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) { + --expZ; + sigZ <<= 1; + } + goto roundPack; + } else { + sig128C[indexWord( 4, 3 )] = sigC>>32; + sig128C[indexWord( 4, 2 )] = sigC; + sig128C[indexWord( 4, 1 )] = 0; + sig128C[indexWord( 4, 0 )] = 0; + softfloat_sub128M( sig128C, sig128Z, sig128Z ); + } + } else if ( ! expDiff ) { + sigZ -= sigC; + if ( + ! sigZ && ! sig128Z[indexWord( 4, 1 )] + && ! sig128Z[indexWord( 4, 0 )] + ) { + goto completeCancellation; + } + sig128Z[indexWord( 4, 3 )] = sigZ>>32; + sig128Z[indexWord( 4, 2 )] = sigZ; + if ( sigZ & UINT64_C( 0x8000000000000000 ) ) { + signZ = ! signZ; + softfloat_negX128M( sig128Z ); + } + } else { + softfloat_sub128M( sig128Z, sig128C, sig128Z ); + if ( 1 < expDiff ) { + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 + | sig128Z[indexWord( 4, 2 )]; + if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) { + --expZ; + sigZ <<= 1; + } + goto sigZ; + } + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + shiftDist = 0; + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 + | sig128Z[indexWord( 4, 2 )]; + if ( ! sigZ ) { + shiftDist = 64; + sigZ = + (uint64_t) sig128Z[indexWord( 4, 1 )]<<32 + | sig128Z[indexWord( 4, 0 )]; + } + shiftDist += softfloat_countLeadingZeros64( sigZ ) - 1; + if ( shiftDist ) { + expZ -= shiftDist; + softfloat_shiftLeft128M( sig128Z, shiftDist, sig128Z ); + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 + | sig128Z[indexWord( 4, 2 )]; + } + } + sigZ: + if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) sigZ |= 1; + roundPack: + return softfloat_roundPackToF64( signZ, expZ - 1, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN_ABC: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + goto propagateNaN_ZC; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infProdArg: + if ( magBits ) { + uiZ = packToF64UI( signZ, 0x7FF, 0 ); + if ( expC != 0x7FF ) goto uiZ; + if ( sigC ) goto propagateNaN_ZC; + if ( signZ == signC ) goto uiZ; + } + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + propagateNaN_ZC: + uiZ = softfloat_propagateNaNF64UI( uiZ, uiC ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zeroProd: + uiZ = uiC; + if ( ! (expC | sigC) && (signZ != signC) ) { + completeCancellation: + uiZ = + packToF64UI( + (softfloat_roundingMode == softfloat_round_min), 0, 0 ); + } + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + +#endif + diff --git a/src/softfloat/s_negXM.c b/src/softfloat/s_negXM.c new file mode 100644 index 000000000..bb1c5a1f4 --- /dev/null +++ b/src/softfloat/s_negXM.c @@ -0,0 +1,63 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_negXM + +void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ) +{ + unsigned int index, lastIndex; + uint_fast8_t carry; + uint32_t word; + + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + carry = 1; + for (;;) { + word = ~zPtr[index] + carry; + zPtr[index] = word; + if ( index == lastIndex ) break; + index += wordIncr; + if ( word ) carry = 0; + } + +} + +#endif + diff --git a/src/softfloat/s_normRoundPackToF64.c b/src/softfloat/s_normRoundPackToF64.c new file mode 100644 index 000000000..8c19ad852 --- /dev/null +++ b/src/softfloat/s_normRoundPackToF64.c @@ -0,0 +1,58 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" + +float64_t + softfloat_normRoundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig ) +{ + int_fast8_t shiftDist; + union ui64_f64 uZ; + + shiftDist = softfloat_countLeadingZeros64( sig ) - 1; + exp -= shiftDist; + if ( (10 <= shiftDist) && ((unsigned int) exp < 0x7FD) ) { + uZ.ui = packToF64UI( sign, sig ? exp : 0, sig<<(shiftDist - 10) ); + return uZ.f; + } else { + return softfloat_roundPackToF64( sign, exp, sig< +#include "platform.h" +#include "internals.h" + +struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t sig ) +{ + int_fast8_t shiftDist; + struct exp16_sig32 z; + + shiftDist = softfloat_countLeadingZeros32( sig ) - 8; + z.exp = 1 - shiftDist; + z.sig = sig< +#include "platform.h" +#include "internals.h" + +struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t sig ) +{ + int_fast8_t shiftDist; + struct exp16_sig64 z; + + shiftDist = softfloat_countLeadingZeros64( sig ) - 11; + z.exp = 1 - shiftDist; + z.sig = sig< +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast32_t + softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ) +{ + bool isSigNaNA; + + isSigNaNA = softfloat_isSigNaNF32UI( uiA ); + if ( isSigNaNA || softfloat_isSigNaNF32UI( uiB ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) return uiA | 0x00400000; + } + return (isNaNF32UI( uiA ) ? uiA : uiB) | 0x00400000; + +} + diff --git a/src/softfloat/s_propagateNaNF64UI.c b/src/softfloat/s_propagateNaNF64UI.c new file mode 100644 index 000000000..474c1967d --- /dev/null +++ b/src/softfloat/s_propagateNaNF64UI.c @@ -0,0 +1,63 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast64_t + softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ) +{ + bool isSigNaNA; + + isSigNaNA = softfloat_isSigNaNF64UI( uiA ); + if ( isSigNaNA || softfloat_isSigNaNF64UI( uiB ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) return uiA | UINT64_C( 0x0008000000000000 ); + } + return (isNaNF64UI( uiA ) ? uiA : uiB) | UINT64_C( 0x0008000000000000 ); + +} + diff --git a/src/softfloat/s_roundMToI64.c b/src/softfloat/s_roundMToI64.c new file mode 100644 index 000000000..557a532d6 --- /dev/null +++ b/src/softfloat/s_roundMToI64.c @@ -0,0 +1,102 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int_fast64_t + softfloat_roundMToI64( + bool sign, uint32_t *extSigPtr, uint_fast8_t roundingMode, bool exact ) +{ + uint64_t sig; + uint32_t sigExtra; + union { uint64_t ui; int64_t i; } uZ; + int64_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig = + (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32 + | extSigPtr[indexWord( 3, 1 )]; + sigExtra = extSigPtr[indexWordLo( 3 )]; + if ( + (roundingMode == softfloat_round_near_maxMag) + || (roundingMode == softfloat_round_near_even) + ) { + if ( 0x80000000 <= sigExtra ) goto increment; + } else { + if ( + sigExtra + && (sign + ? (roundingMode == softfloat_round_min) +#ifdef SOFTFLOAT_ROUND_ODD + || (roundingMode == softfloat_round_odd) +#endif + : (roundingMode == softfloat_round_max)) + ) { + increment: + ++sig; + if ( !sig ) goto invalid; + if ( + (sigExtra == 0x80000000) + && (roundingMode == softfloat_round_near_even) + ) { + sig &= ~(uint_fast64_t) 1; + } + } + } + uZ.ui = sign ? -sig : sig; + z = uZ.i; + if ( z && ((z < 0) ^ sign) ) goto invalid; + if ( sigExtra ) { +#ifdef SOFTFLOAT_ROUND_ODD + if ( roundingMode == softfloat_round_odd ) z |= 1; +#endif + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return sign ? i64_fromNegOverflow : i64_fromPosOverflow; + +} + diff --git a/src/softfloat/s_roundPackToF32.c b/src/softfloat/s_roundPackToF32.c new file mode 100644 index 000000000..f1eb0c2ab --- /dev/null +++ b/src/softfloat/s_roundPackToF32.c @@ -0,0 +1,113 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float32_t + softfloat_roundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig ) +{ + uint_fast8_t roundingMode; + bool roundNearEven; + uint_fast8_t roundIncrement, roundBits; + bool isTiny; + uint_fast32_t uiZ; + union ui32_f32 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundingMode = softfloat_roundingMode; + roundNearEven = (roundingMode == softfloat_round_near_even); + roundIncrement = 0x40; + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + roundIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + ? 0x7F + : 0; + } + roundBits = sig & 0x7F; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( 0xFD <= (unsigned int) exp ) { + if ( exp < 0 ) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = + (softfloat_detectTininess == softfloat_tininess_beforeRounding) + || (exp < -1) || (sig + roundIncrement < 0x80000000); + sig = softfloat_shiftRightJam32( sig, -exp ); + exp = 0; + roundBits = sig & 0x7F; + if ( isTiny && roundBits ) { + softfloat_raiseFlags( softfloat_flag_underflow ); + } + } else if ( (0xFD < exp) || (0x80000000 <= sig + roundIncrement) ) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + softfloat_raiseFlags( + softfloat_flag_overflow | softfloat_flag_inexact ); + uiZ = packToF32UI( sign, 0xFF, 0 ) - ! roundIncrement; + goto uiZ; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig = (sig + roundIncrement)>>7; + if ( roundBits ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; +#ifdef SOFTFLOAT_ROUND_ODD + if ( roundingMode == softfloat_round_odd ) { + sig |= 1; + goto packReturn; + } +#endif + } + sig &= ~(uint_fast32_t) (! (roundBits ^ 0x40) & roundNearEven); + if ( ! sig ) exp = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + packReturn: + uiZ = packToF32UI( sign, exp, sig ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/src/softfloat/s_roundPackToF64.c b/src/softfloat/s_roundPackToF64.c new file mode 100644 index 000000000..98c1639a4 --- /dev/null +++ b/src/softfloat/s_roundPackToF64.c @@ -0,0 +1,117 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t + softfloat_roundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig ) +{ + uint_fast8_t roundingMode; + bool roundNearEven; + uint_fast16_t roundIncrement, roundBits; + bool isTiny; + uint_fast64_t uiZ; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundingMode = softfloat_roundingMode; + roundNearEven = (roundingMode == softfloat_round_near_even); + roundIncrement = 0x200; + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + roundIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + ? 0x3FF + : 0; + } + roundBits = sig & 0x3FF; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( 0x7FD <= (uint16_t) exp ) { + if ( exp < 0 ) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = + (softfloat_detectTininess == softfloat_tininess_beforeRounding) + || (exp < -1) + || (sig + roundIncrement < UINT64_C( 0x8000000000000000 )); + sig = softfloat_shiftRightJam64( sig, -exp ); + exp = 0; + roundBits = sig & 0x3FF; + if ( isTiny && roundBits ) { + softfloat_raiseFlags( softfloat_flag_underflow ); + } + } else if ( + (0x7FD < exp) + || (UINT64_C( 0x8000000000000000 ) <= sig + roundIncrement) + ) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + softfloat_raiseFlags( + softfloat_flag_overflow | softfloat_flag_inexact ); + uiZ = packToF64UI( sign, 0x7FF, 0 ) - ! roundIncrement; + goto uiZ; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig = (sig + roundIncrement)>>10; + if ( roundBits ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; +#ifdef SOFTFLOAT_ROUND_ODD + if ( roundingMode == softfloat_round_odd ) { + sig |= 1; + goto packReturn; + } +#endif + } + sig &= ~(uint_fast64_t) (! (roundBits ^ 0x200) & roundNearEven); + if ( ! sig ) exp = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + packReturn: + uiZ = packToF64UI( sign, exp, sig ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/src/softfloat/s_roundToI32.c b/src/softfloat/s_roundToI32.c new file mode 100644 index 000000000..1999dcf56 --- /dev/null +++ b/src/softfloat/s_roundToI32.c @@ -0,0 +1,98 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int_fast32_t + softfloat_roundToI32( + bool sign, uint_fast64_t sig, uint_fast8_t roundingMode, bool exact ) +{ + uint_fast16_t roundIncrement, roundBits; + uint_fast32_t sig32; + union { uint32_t ui; int32_t i; } uZ; + int_fast32_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundIncrement = 0x800; + if ( + (roundingMode != softfloat_round_near_maxMag) + && (roundingMode != softfloat_round_near_even) + ) { + roundIncrement = 0; + if ( + sign + ? (roundingMode == softfloat_round_min) +#ifdef SOFTFLOAT_ROUND_ODD + || (roundingMode == softfloat_round_odd) +#endif + : (roundingMode == softfloat_round_max) + ) { + roundIncrement = 0xFFF; + } + } + roundBits = sig & 0xFFF; + sig += roundIncrement; + if ( sig & UINT64_C( 0xFFFFF00000000000 ) ) goto invalid; + sig32 = sig>>12; + if ( + (roundBits == 0x800) && (roundingMode == softfloat_round_near_even) + ) { + sig32 &= ~(uint_fast32_t) 1; + } + uZ.ui = sign ? -sig32 : sig32; + z = uZ.i; + if ( z && ((z < 0) ^ sign) ) goto invalid; + if ( roundBits ) { +#ifdef SOFTFLOAT_ROUND_ODD + if ( roundingMode == softfloat_round_odd ) z |= 1; +#endif + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return sign ? i32_fromNegOverflow : i32_fromPosOverflow; + +} + diff --git a/src/softfloat/s_shiftLeftM.c b/src/softfloat/s_shiftLeftM.c new file mode 100644 index 000000000..feafc67bf --- /dev/null +++ b/src/softfloat/s_shiftLeftM.c @@ -0,0 +1,91 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" + +#ifndef softfloat_shiftLeftM + +#define softfloat_shiftLeftM softfloat_shiftLeftM +#include "primitives.h" + +void + softfloat_shiftLeftM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint32_t dist, + uint32_t *zPtr + ) +{ + uint32_t wordDist; + uint_fast8_t innerDist; + uint32_t *destPtr; + uint_fast8_t i; + + wordDist = dist>>5; + if ( wordDist < size_words ) { + aPtr += indexMultiwordLoBut( size_words, wordDist ); + innerDist = dist & 31; + if ( innerDist ) { + softfloat_shortShiftLeftM( + size_words - wordDist, + aPtr, + innerDist, + zPtr + indexMultiwordHiBut( size_words, wordDist ) + ); + if ( ! wordDist ) return; + } else { + aPtr += indexWordHi( size_words - wordDist ); + destPtr = zPtr + indexWordHi( size_words ); + for ( i = size_words - wordDist; i; --i ) { + *destPtr = *aPtr; + aPtr -= wordIncr; + destPtr -= wordIncr; + } + } + zPtr += indexMultiwordLo( size_words, wordDist ); + } else { + wordDist = size_words; + } + do { + *zPtr++ = 0; + --wordDist; + } while ( wordDist ); + +} + +#endif + diff --git a/src/softfloat/s_shiftRightJam32.c b/src/softfloat/s_shiftRightJam32.c new file mode 100644 index 000000000..be4622abe --- /dev/null +++ b/src/softfloat/s_shiftRightJam32.c @@ -0,0 +1,51 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" + +#ifndef softfloat_shiftRightJam32 + +uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist ) +{ + + return + (dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0); + +} + +#endif + diff --git a/src/softfloat/s_shiftRightJam64.c b/src/softfloat/s_shiftRightJam64.c new file mode 100644 index 000000000..733c1736c --- /dev/null +++ b/src/softfloat/s_shiftRightJam64.c @@ -0,0 +1,51 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" + +#ifndef softfloat_shiftRightJam64 + +uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist ) +{ + + return + (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0); + +} + +#endif + diff --git a/src/softfloat/s_shiftRightJamM.c b/src/softfloat/s_shiftRightJamM.c new file mode 100644 index 000000000..0a0dd7d75 --- /dev/null +++ b/src/softfloat/s_shiftRightJamM.c @@ -0,0 +1,101 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" + +#ifndef softfloat_shiftRightJamM + +#define softfloat_shiftRightJamM softfloat_shiftRightJamM +#include "primitives.h" + +void + softfloat_shiftRightJamM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint32_t dist, + uint32_t *zPtr + ) +{ + uint32_t wordJam, wordDist, *ptr; + uint_fast8_t i, innerDist; + + wordJam = 0; + wordDist = dist>>5; + if ( wordDist ) { + if ( size_words < wordDist ) wordDist = size_words; + ptr = (uint32_t *) (aPtr + indexMultiwordLo( size_words, wordDist )); + i = wordDist; + do { + wordJam = *ptr++; + if ( wordJam ) break; + --i; + } while ( i ); + ptr = zPtr; + } + if ( wordDist < size_words ) { + aPtr += indexMultiwordHiBut( size_words, wordDist ); + innerDist = dist & 31; + if ( innerDist ) { + softfloat_shortShiftRightJamM( + size_words - wordDist, + aPtr, + innerDist, + zPtr + indexMultiwordLoBut( size_words, wordDist ) + ); + if ( ! wordDist ) goto wordJam; + } else { + aPtr += indexWordLo( size_words - wordDist ); + ptr = zPtr + indexWordLo( size_words ); + for ( i = size_words - wordDist; i; --i ) { + *ptr = *aPtr; + aPtr += wordIncr; + ptr += wordIncr; + } + } + ptr = zPtr + indexMultiwordHi( size_words, wordDist ); + } + do { + *ptr++ = 0; + --wordDist; + } while ( wordDist ); + wordJam: + if ( wordJam ) zPtr[indexWordLo( size_words )] |= 1; + +} + +#endif + diff --git a/src/softfloat/s_shortShiftLeftM.c b/src/softfloat/s_shortShiftLeftM.c new file mode 100644 index 000000000..b947c63ce --- /dev/null +++ b/src/softfloat/s_shortShiftLeftM.c @@ -0,0 +1,70 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftLeftM + +void + softfloat_shortShiftLeftM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint_fast8_t dist, + uint32_t *zPtr + ) +{ + uint_fast8_t uNegDist; + unsigned int index, lastIndex; + uint32_t partWordZ, wordA; + + uNegDist = -dist; + index = indexWordHi( size_words ); + lastIndex = indexWordLo( size_words ); + partWordZ = aPtr[index]<>(uNegDist & 31); + index -= wordIncr; + partWordZ = wordA< +#include "platform.h" + +#ifndef softfloat_shortShiftRightJam64 + +uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist ) +{ + + return a>>dist | ((a & (((uint_fast64_t) 1< +#include "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftRightJamM + +void + softfloat_shortShiftRightJamM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint_fast8_t dist, + uint32_t *zPtr + ) +{ + uint_fast8_t uNegDist; + unsigned int index, lastIndex; + uint32_t partWordZ, wordA; + + uNegDist = -dist; + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + wordA = aPtr[index]; + partWordZ = wordA>>dist; + if ( partWordZ<>dist; + } + zPtr[index] = partWordZ; + +} + +#endif + diff --git a/src/softfloat/s_shortShiftRightM.c b/src/softfloat/s_shortShiftRightM.c new file mode 100644 index 000000000..8a165fe45 --- /dev/null +++ b/src/softfloat/s_shortShiftRightM.c @@ -0,0 +1,70 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftRightM + +void + softfloat_shortShiftRightM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint_fast8_t dist, + uint32_t *zPtr + ) +{ + uint_fast8_t uNegDist; + unsigned int index, lastIndex; + uint32_t partWordZ, wordA; + + uNegDist = -dist; + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + partWordZ = aPtr[index]>>dist; + while ( index != lastIndex ) { + wordA = aPtr[index + wordIncr]; + zPtr[index] = wordA<<(uNegDist & 31) | partWordZ; + index += wordIncr; + partWordZ = wordA>>dist; + } + zPtr[index] = partWordZ; + +} + +#endif + diff --git a/src/softfloat/s_subM.c b/src/softfloat/s_subM.c new file mode 100644 index 000000000..213b0bf6d --- /dev/null +++ b/src/softfloat/s_subM.c @@ -0,0 +1,70 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_subM + +void + softfloat_subM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint32_t *zPtr + ) +{ + unsigned int index, lastIndex; + uint_fast8_t borrow; + uint32_t wordA, wordB; + + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + borrow = 0; + for (;;) { + wordA = aPtr[index]; + wordB = bPtr[index]; + zPtr[index] = wordA - wordB - borrow; + if ( index == lastIndex ) break; + borrow = borrow ? (wordA <= wordB) : (wordA < wordB); + index += wordIncr; + } + +} + +#endif + diff --git a/src/softfloat/s_subMagsF64.c b/src/softfloat/s_subMagsF64.c new file mode 100644 index 000000000..3a4acb104 --- /dev/null +++ b/src/softfloat/s_subMagsF64.c @@ -0,0 +1,141 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t + softfloat_subMagsF64( uint_fast64_t uiA, uint_fast64_t uiB, bool signZ ) +{ + int_fast16_t expA; + uint_fast64_t sigA; + int_fast16_t expB; + uint_fast64_t sigB; + int_fast16_t expDiff; + uint_fast64_t uiZ; + int_fast64_t sigDiff; + int_fast8_t shiftDist; + int_fast16_t expZ; + uint_fast64_t sigZ; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if ( ! expDiff ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA | sigB ) goto propagateNaN; + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + goto uiZ; + } + sigDiff = sigA - sigB; + if ( ! sigDiff ) { + uiZ = + packToF64UI( + (softfloat_roundingMode == softfloat_round_min), 0, 0 ); + goto uiZ; + } + if ( expA ) --expA; + if ( sigDiff < 0 ) { + signZ = ! signZ; + sigDiff = -sigDiff; + } + shiftDist = softfloat_countLeadingZeros64( sigDiff ) - 11; + expZ = expA - shiftDist; + if ( expZ < 0 ) { + shiftDist = expA; + expZ = 0; + } + uiZ = packToF64UI( signZ, expZ, sigDiff< +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifndef THREAD_LOCAL +#define THREAD_LOCAL +#endif + +THREAD_LOCAL uint_fast8_t softfloat_roundingMode = softfloat_round_near_even; +THREAD_LOCAL uint_fast8_t softfloat_detectTininess = init_detectTininess; +THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags = 0; + +THREAD_LOCAL uint_fast8_t extF80_roundingPrecision = 80; + diff --git a/src/softfloat/ui32_to_f64.c b/src/softfloat/ui32_to_f64.c new file mode 100644 index 000000000..11050c100 --- /dev/null +++ b/src/softfloat/ui32_to_f64.c @@ -0,0 +1,59 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t ui32_to_f64( uint32_t a ) +{ + uint_fast64_t uiZ; + int_fast8_t shiftDist; + union ui64_f64 uZ; + + if ( ! a ) { + uiZ = 0; + } else { + shiftDist = softfloat_countLeadingZeros32( a ) + 21; + uiZ = + packToF64UI( 0, 0x432 - shiftDist, (uint_fast64_t) a< +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t ui64_to_f64( uint64_t a ) +{ + union ui64_f64 uZ; + + if ( ! a ) { + uZ.ui = 0; + return uZ.f; + } + if ( a & UINT64_C( 0x8000000000000000 ) ) { + return + softfloat_roundPackToF64( + 0, 0x43D, softfloat_shortShiftRightJam64( a, 1 ) ); + } else { + return softfloat_normRoundPackToF64( 0, 0x43C, a ); + } + +} + From 9ef64d8abc400bf7e1afa53c8dd5d383a92a96b3 Mon Sep 17 00:00:00 2001 From: ZERICO2005 <71151164+ZERICO2005@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:47:42 -0700 Subject: [PATCH 2/7] Added float64 (long double) classification functions and fixed some float64 behaviour/bugs --- src/crt/float64_runtime.c | 10 ++-- src/crt/ftoll.src | 4 +- src/crt/lltof.src | 3 +- src/crt/ulltof.src | 3 +- src/libc/float64_math.c | 23 +++++++- src/libc/float64_rounding.c | 63 +++++++++++++++++----- src/libc/fpclassify.c | 101 ++++++++++++++++++++---------------- src/libc/include/math.h | 47 ++++++++++------- src/libc/isfinite.c | 17 ++++++ src/libc/isinf.c | 17 ++++++ src/libc/isnan.c | 17 ++++++ src/libc/isnormal.c | 37 +++++++++---- src/libc/issubnormal.c | 43 +++++++++++++++ src/libc/iszero.c | 5 +- src/libc/roundeven.c | 6 +++ 15 files changed, 294 insertions(+), 102 deletions(-) create mode 100644 src/libc/isfinite.c create mode 100644 src/libc/isinf.c create mode 100644 src/libc/isnan.c create mode 100644 src/libc/issubnormal.c diff --git a/src/crt/float64_runtime.c b/src/crt/float64_runtime.c index 111829398..a4209217a 100644 --- a/src/crt/float64_runtime.c +++ b/src/crt/float64_runtime.c @@ -1,5 +1,5 @@ #include -#include "../../softfloat/include/softfloat.h" +#include "../softfloat/include/softfloat.h" //------------------------------------------------------------------------------ // unions @@ -116,23 +116,23 @@ float _dtof_c(long double x) { int32_t _dtol_c(long double x) { F64_pun arg_x; arg_x.flt = x; - return f64_to_i32_r_minMag(arg_x.soft, true); + return f64_to_i32_r_minMag(arg_x.soft, false); } int64_t _dtoll_c(long double x) { F64_pun arg_x; arg_x.flt = x; - return f64_to_i64_r_minMag(arg_x.soft, true); + return f64_to_i64_r_minMag(arg_x.soft, false); } uint32_t _dtoul_c(long double x) { F64_pun arg_x; arg_x.flt = x; - return f64_to_ui32_r_minMag(arg_x.soft, true); + return f64_to_ui32_r_minMag(arg_x.soft, false); } uint64_t _dtoull_c(long double x) { F64_pun arg_x; arg_x.flt = x; - return f64_to_ui64_r_minMag(arg_x.soft, true); + return f64_to_ui64_r_minMag(arg_x.soft, false); } diff --git a/src/crt/ftoll.src b/src/crt/ftoll.src index 24d0a242f..d140ebb47 100644 --- a/src/crt/ftoll.src +++ b/src/crt/ftoll.src @@ -1,11 +1,9 @@ assume adl=1 section .text - public __ftoll, __ftoull, __dtoll, __dtoull + public __ftoll, __ftoull __ftoll: __ftoull: -__dtoll: -__dtoull: ld d, a push iy, de, hl call __ftoll_c diff --git a/src/crt/lltof.src b/src/crt/lltof.src index 79d0139f4..c99868c30 100644 --- a/src/crt/lltof.src +++ b/src/crt/lltof.src @@ -1,8 +1,7 @@ assume adl=1 section .text - public __lltof, __lltod -__lltof: + public __lltof __lltod: push af, iy, bc, de, hl call __lltof_c diff --git a/src/crt/ulltof.src b/src/crt/ulltof.src index 0ac5d12d1..9b3c9667a 100644 --- a/src/crt/ulltof.src +++ b/src/crt/ulltof.src @@ -1,9 +1,8 @@ assume adl=1 section .text - public __ulltof, __ulltod + public __ulltof __ulltof: -__ulltod: push af, iy, bc, de, hl call __ulltof_c pop af, af, af, iy, af diff --git a/src/libc/float64_math.c b/src/libc/float64_math.c index 774934a9a..2752af544 100644 --- a/src/libc/float64_math.c +++ b/src/libc/float64_math.c @@ -1,6 +1,7 @@ +#include #include #include -#include "../../softfloat/include/softfloat.h" +#include "../softfloat/include/softfloat.h" typedef union F64_pun { long double flt; @@ -20,7 +21,13 @@ long double fmal(long double x, long double y, long double z) { long double sqrtl(long double x) { F64_pun arg_x, ret; arg_x.flt = x; + + softfloat_exceptionFlags = 0; ret.soft = f64_sqrt(arg_x.soft); + if (softfloat_exceptionFlags & softfloat_flag_invalid) { + feraiseexcept(FE_INVALID); + } + return ret.flt; } @@ -29,11 +36,25 @@ long double fmodl(long double x, long double y) { F64_pun arg_x, arg_y, ret; arg_x.flt = x; arg_y.flt = y; + + softfloat_exceptionFlags = 0; ret.soft = f64_rem(arg_x.soft, arg_y.soft); + if (softfloat_exceptionFlags & softfloat_flag_invalid) { + feraiseexcept(FE_INVALID); + } + return ret.flt; } long double modfl(long double x, long double *integral_part) { + if (iszero(x)) { + *integral_part = x; + return x; + } + if (isinf(x)) { + *integral_part = x; + return copysignl(0.0L, x); + } F64_pun arg_x, arg_y, ret; arg_x.flt = x; arg_y.flt = 1.0L; diff --git a/src/libc/float64_rounding.c b/src/libc/float64_rounding.c index fdc095a36..b4e65c86c 100644 --- a/src/libc/float64_rounding.c +++ b/src/libc/float64_rounding.c @@ -2,7 +2,7 @@ #include #include #include -#include "../../softfloat/include/softfloat.h" +#include "../softfloat/include/softfloat.h" typedef union F64_pun { long double flt; @@ -13,48 +13,62 @@ typedef union F64_pun { long double truncl(long double x) { F64_pun arg_x, ret; arg_x.flt = x; - ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_minMag, true); + ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_minMag, false); return ret.flt; } long double floorl(long double x) { F64_pun arg_x, ret; arg_x.flt = x; - ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_min, true); + ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_min, false); return ret.flt; } long double ceill(long double x) { F64_pun arg_x, ret; arg_x.flt = x; - ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_max, true); + ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_max, false); return ret.flt; } long double roundevenl(long double x) { F64_pun arg_x, ret; arg_x.flt = x; - ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_near_even, true); + ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_near_even, false); return ret.flt; } long double roundl(long double x) { F64_pun arg_x, ret; arg_x.flt = x; - ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_near_maxMag, true); + ret.soft = f64_roundToInt(arg_x.soft, softfloat_round_near_maxMag, false); return ret.flt; } long lroundl(long double x) { F64_pun arg_x; arg_x.flt = x; - return f64_to_i32(arg_x.soft, softfloat_round_near_maxMag, true); + + softfloat_exceptionFlags = 0; + int32_t ret = f64_to_i32(arg_x.soft, softfloat_round_near_maxMag, false); + + if (softfloat_exceptionFlags & softfloat_flag_invalid) { + feraiseexcept(FE_INVALID); + } + return ret; } long long llroundl(long double x) { F64_pun arg_x; arg_x.flt = x; - return f64_to_i64(arg_x.soft, softfloat_round_near_maxMag, true); + + softfloat_exceptionFlags = 0; + int64_t ret = f64_to_i64(arg_x.soft, softfloat_round_near_maxMag, false); + + if (softfloat_exceptionFlags & softfloat_flag_invalid) { + feraiseexcept(FE_INVALID); + } + return ret; } #if ( \ @@ -81,24 +95,49 @@ long long llroundl(long double x) { long double nearbyintl(long double x) { F64_pun arg_x, ret; arg_x.flt = x; - ret.soft = f64_roundToInt(arg_x.soft, GET_FENV_SOFTFLOAT_ROUNDING(), true); + ret.soft = f64_roundToInt(arg_x.soft, GET_FENV_SOFTFLOAT_ROUNDING(), false); return ret.flt; } long double rintl(long double x) { F64_pun arg_x, ret; arg_x.flt = x; + + softfloat_exceptionFlags = 0; ret.soft = f64_roundToInt(arg_x.soft, GET_FENV_SOFTFLOAT_ROUNDING(), true); - if (ret.bin != arg_x.bin) { + + if (softfloat_exceptionFlags & softfloat_flag_inexact) { feraiseexcept(FE_INEXACT); } return ret.flt; } long lrintl(long double x) { - return (int32_t)rintl(x); + F64_pun arg_x; + arg_x.flt = x; + + softfloat_exceptionFlags = 0; + int32_t ret = f64_to_i32(arg_x.soft, softfloat_round_near_maxMag, true); + + if (softfloat_exceptionFlags & softfloat_flag_inexact) { + feraiseexcept(FE_INEXACT); + } else if (softfloat_exceptionFlags & softfloat_flag_invalid) { + feraiseexcept(FE_INVALID); + } + return ret; } long long llrintl(long double x) { - return (int64_t)rintl(x); + F64_pun arg_x; + arg_x.flt = x; + + softfloat_exceptionFlags = 0; + int32_t ret = f64_to_i32(arg_x.soft, softfloat_round_near_maxMag, true); + + if (softfloat_exceptionFlags & softfloat_flag_inexact) { + feraiseexcept(FE_INEXACT); + } else if (softfloat_exceptionFlags & softfloat_flag_invalid) { + feraiseexcept(FE_INVALID); + } + return ret; } diff --git a/src/libc/fpclassify.c b/src/libc/fpclassify.c index 8a7ac2370..cddd315a5 100644 --- a/src/libc/fpclassify.c +++ b/src/libc/fpclassify.c @@ -1,56 +1,65 @@ #include #include -#if 0 +typedef union Float32_Bitwise { + float flt_part; + uint32_t u32_part; + uint24_t u24_part; +} Float32_Bitwise; - /* Portable version */ +#define Float32_Exponent_Mask INT32_C(0x7F800000) +#define Float32_Mantissa_Mask INT32_C(0x007FFFFF) - int _fpclassifyf(float x) - { - return - isnan(x) ? FP_NAN : - isinf(x) ? FP_INFINITE : - (x == 0.0f) ? FP_ZERO : - isnormal(x) ? FP_NORMAL : - FP_SUBNORMAL; - } - -#else +int _fpclassifyf(float x) +{ + Float32_Bitwise x_bin; + x_bin.flt_part = x; + + const uint32_t exp_mask = x_bin.u32_part & Float32_Exponent_Mask; + + // Both of these compile to the same lto.src as of 2024-Oct-10 + #if 1 + uint24_t mantissa = x_bin.u24_part; + // bit 23 is part of the exponent, so it must be cleared + mantissa += mantissa; + #else + uint32_t mantissa = x_bin.u32_part & Float32_Mantissa_Mask; + #endif + + return ( + (exp_mask == 0) ? FP_ZERO : + (exp_mask == Float32_Exponent_Mask) ? FP_INFINITE : + FP_NORMAL + ) | (mantissa != 0); +} - /* Bitwise version */ +int _fpclassify(double) __attribute__((alias("_fpclassifyf"))); - typedef union Float32_Bitwise { - float flt_part; - uint32_t u32_part; - uint24_t u24_part; - } Float32_Bitwise; +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; - #define Float32_Exponent_Mask INT32_C(0x7F800000) - #define Float32_Mantissa_Mask INT32_C(0x007FFFFF) +#define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) +#define Float64_norm_min_lsh_1 UINT64_C(0x0020000000000000) - int _fpclassifyf(float x) - { - Float32_Bitwise x_bin; - x_bin.flt_part = x; - - const uint32_t exp_mask = x_bin.u32_part & Float32_Exponent_Mask; - - // Both of these compile to the same lto.src as of 2024-Oct-10 - #if 1 - uint24_t mantissa = x_bin.u24_part; - // bit 23 is part of the exponent, so it must be cleared - mantissa += mantissa; - #else - uint32_t mantissa = x_bin.u32_part & Float32_Mantissa_Mask; - #endif - - return ( - (exp_mask == 0) ? FP_ZERO : - (exp_mask == Float32_Exponent_Mask) ? FP_INFINITE : - FP_NORMAL - ) | (mantissa != 0); +int _fpclassifyl(long double x) { + F64_pun val; + val.flt = x; + // clears the signbit + val.bin <<= 1; + if (val.bin == 0) { + return FP_ZERO; } - -#endif - -int _fpclassify(double) __attribute__((alias("_fpclassifyf"))); + if (val.bin == Float64_inf_lsh_1) { + return FP_INFINITE; + } + // positive NaN is greater than positive infinity + if (val.bin > Float64_inf_lsh_1) { + return FP_NAN; + } + if (val.bin >= Float64_norm_min_lsh_1) { + return FP_NORMAL; + } + return FP_SUBNORMAL; +} diff --git a/src/libc/include/math.h b/src/libc/include/math.h index f2ae7ee41..60cb7c4e3 100644 --- a/src/libc/include/math.h +++ b/src/libc/include/math.h @@ -48,34 +48,45 @@ int _isnanf(float n); int _isnormalf(float n); int _isfinitef(float n); int _iszerof(float n); +int _issubnormalf(float n); int _fpclassifyf(float n); -// int _isinfl(long double n); -// int _isnanl(long double n); -// int _isnormall(long double n); -// int _isfinitel(long double n); +int _isinfl(long double n); +int _isnanl(long double n); +int _isnormall(long double n); +int _isfinitel(long double n); int _iszerol(long double n); -// int _fpclassifyl(long double n); +int _issubnormall(long double n); +int _fpclassifyl(long double n); #define isinf(x) ( \ - sizeof((x)) == sizeof(float) ? _isinff((x)) : \ - 0) + sizeof((x)) == sizeof(float) ? _isinff((x)) : \ + sizeof((x)) == sizeof(long double) ? _isinfl((x)) : \ + 0) #define isnan(x) ( \ - sizeof((x)) == sizeof(float) ? _isnanf((x)) : \ - 0) + sizeof((x)) == sizeof(float) ? _isnanf((x)) : \ + sizeof((x)) == sizeof(long double) ? _isnanl((x)) : \ + 0) #define isnormal(x) ( \ - sizeof((x)) == sizeof(float) ? _isnormalf((x)) : \ - (x) != 0) + sizeof((x)) == sizeof(float) ? _isnormalf((x)) : \ + sizeof((x)) == sizeof(long double) ? _isnormall((x)) : \ + (x) != 0) #define isfinite(x) ( \ - sizeof((x)) == sizeof(float) ? _isfinitef((x)) : \ - 1) + sizeof((x)) == sizeof(float) ? _isfinitef((x)) : \ + sizeof((x)) == sizeof(long double) ? _isfinitel((x)) : \ + 1) #define iszero(x) ( \ - sizeof((x)) == sizeof(float) ? _iszerof((x)) : \ - sizeof((x)) == sizeof(long double) ? _iszerol(x) : \ - (x) != 0) + sizeof((x)) == sizeof(float) ? _iszerof((x)) : \ + sizeof((x)) == sizeof(long double) ? _iszerol(x) : \ + (x) == 0) +#define issubnormal(x) ( \ + sizeof((x)) == sizeof(float) ? _issubnormalf((x)) : \ + sizeof((x)) == sizeof(long double) ? _issubnormall(x) : \ + (x) == 0) #define fpclassify(x) ( \ - sizeof((x)) == sizeof(float) ? _fpclassifyf((x)) : \ - 0) + sizeof((x)) == sizeof(float) ? _fpclassifyf((x)) : \ + sizeof((x)) == sizeof(long double) ? _fpclassifyl((x)) : \ + 0) double acos(double); float acosf(float); diff --git a/src/libc/isfinite.c b/src/libc/isfinite.c new file mode 100644 index 000000000..b61427c49 --- /dev/null +++ b/src/libc/isfinite.c @@ -0,0 +1,17 @@ +#include + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) + +int _isfinitel(long double x) { + F64_pun val; + val.flt = x; + // clears the signbit + val.bin <<= 1; + // Check if fabs(x) < infinity/NaN + return (val.bin < Float64_inf_lsh_1); +} diff --git a/src/libc/isinf.c b/src/libc/isinf.c new file mode 100644 index 000000000..8ab98ee45 --- /dev/null +++ b/src/libc/isinf.c @@ -0,0 +1,17 @@ +#include + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) + +int _isinfl(long double x) { + F64_pun val; + val.flt = x; + // clears the signbit + val.bin <<= 1; + // Check if fabs(x) == infinity + return (val.bin == Float64_inf_lsh_1); +} diff --git a/src/libc/isnan.c b/src/libc/isnan.c new file mode 100644 index 000000000..4c9768c0d --- /dev/null +++ b/src/libc/isnan.c @@ -0,0 +1,17 @@ +#include + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) + +int _isnanl(long double x) { + F64_pun val; + val.flt = x; + // clears the signbit + val.bin <<= 1; + // positive NaN is greater than positive infinity + return (val.bin > Float64_inf_lsh_1); +} diff --git a/src/libc/isnormal.c b/src/libc/isnormal.c index a3b921205..99847b9ba 100644 --- a/src/libc/isnormal.c +++ b/src/libc/isnormal.c @@ -1,23 +1,38 @@ #include #include -typedef union Float32_Bitwise { - float flt_part; - uint32_t u32_part; - uint24_t u24_part; -} Float32_Bitwise; +typedef union F32_pun { + float flt; + uint32_t bin; +} F32_pun; -#define Float32_Exponent_Mask INT32_C(0x7F800000) +#define Float32_exp_mask INT32_C(0x7F800000) int _isnormalf(float x) { - Float32_Bitwise x_bin; - x_bin.flt_part = x; - - const int32_t exp_mask = x_bin.u32_part & Float32_Exponent_Mask; + F32_pun val; + val.flt = x; + val.bin &= Float32_exp_mask; // Check that the exponent isn't all zeros (subnormal) or all ones (nan/inf) - return (exp_mask != 0 && exp_mask != Float32_Exponent_Mask); + return (val.bin != 0 && val.bin != Float32_exp_mask); } int _isnormal(double) __attribute__((alias("_isnormalf"))); + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_exp_mask UINT64_C(0x7FF0000000000000) + +int _isnormall(long double x) +{ + F64_pun val; + val.flt = x; + val.bin &= Float64_exp_mask; + + // Check that the exponent isn't all zeros (subnormal) or all ones (nan/inf) + return (val.bin != 0 && val.bin != Float64_exp_mask); +} diff --git a/src/libc/issubnormal.c b/src/libc/issubnormal.c new file mode 100644 index 000000000..0b73e355b --- /dev/null +++ b/src/libc/issubnormal.c @@ -0,0 +1,43 @@ +#include +#include +#include + +typedef union F32_pun { + float flt; + uint32_t bin; +} F32_pun; + +#define Float32_exp_mask UINT32_C(0x7F800000) + +int _issubnormalf(float x) { + // zero is not a subnormal number + if (iszero(x)) { + return false; + } + F32_pun val; + val.flt = x; + val.bin &= Float32_exp_mask; + // check if the exponent is all zeros + return (val.bin == 0); +} + +int _issubnormal(double) __attribute__((alias("_issubnormalf"))); + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_exp_mask UINT64_C(0x7FF0000000000000) + +int _issubnormall(long double x) { + // zero is not a subnormal number + if (iszero(x)) { + return false; + } + F64_pun val; + val.flt = x; + val.bin &= Float64_exp_mask; + // check if the exponent is all zeros + return (val.bin == 0); +} diff --git a/src/libc/iszero.c b/src/libc/iszero.c index 50dfa6779..108bda718 100644 --- a/src/libc/iszero.c +++ b/src/libc/iszero.c @@ -1,8 +1,9 @@ #include +#include typedef union F32_pun { - long double flt; - uint64_t bin; + float flt; + uint32_t bin; } F32_pun; int _iszerof(float x) { diff --git a/src/libc/roundeven.c b/src/libc/roundeven.c index 6ea360734..957a401a9 100644 --- a/src/libc/roundeven.c +++ b/src/libc/roundeven.c @@ -13,6 +13,10 @@ float roundevenf(float x) double roundeven(double x) __attribute__((alias("roundevenf"))); +#if 0 + +// conflicts with roundevenl in float64_rounding.c + long double roundevenl(long double x) { long double i, f = modfl(x, &i); @@ -23,3 +27,5 @@ long double roundevenl(long double x) } return signbit(i) ? i - 1 : i + 1; } + +#endif From ccdbc5cf6704b3d1802befd7f909fada04670b07 Mon Sep 17 00:00:00 2001 From: ZERICO2005 <71151164+ZERICO2005@users.noreply.github.com> Date: Sat, 11 Jan 2025 23:13:07 -0700 Subject: [PATCH 3/7] Added ilogbl, frexpl, and ldexpl float64 routines. Also added nextafter, nextup, nextdown, and nexttoward for float32 and float64. --- src/libc/frexp.c | 78 +++++++++++++++++++++ src/libc/ilogb.c | 47 +++++++++++++ src/libc/include/math.h | 14 +++- src/libc/ldexp.c | 143 +++++++++++++++++++++++++++++++++++++-- src/libc/nextafter.c | 116 +++++++++++++++++++++++++++++-- src/libc/nexttoward.c | 74 ++++++++++++++++++++ src/libc/nextupdown.c | 128 +++++++++++++++++++++++++++++++++++ src/libc/scalbln.c | 9 ++- src/libc/scalbn.c | 8 --- src/libcxx/include/cmath | 24 +++++++ 10 files changed, 616 insertions(+), 25 deletions(-) create mode 100644 src/libc/nexttoward.c create mode 100644 src/libc/nextupdown.c delete mode 100644 src/libc/scalbn.c diff --git a/src/libc/frexp.c b/src/libc/frexp.c index 934b93263..a47250458 100644 --- a/src/libc/frexp.c +++ b/src/libc/frexp.c @@ -7,6 +7,7 @@ /************************************************************************/ #include +#include typedef union { @@ -62,3 +63,80 @@ float _frexpf_c(float value, int *pExponent) } double _frexp_c(double, int *) __attribute__((alias("_frexpf_c"))); + + + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) +#define Float64_norm_min_lsh_1 UINT64_C(0x0020000000000000) +#define Float64_frexp_mask UINT64_C(0x800FFFFFFFFFFFFF) +#define Float64_pos_one UINT64_C(0x3FF0000000000000) +#define Float64_frexp_subnorm_mask Float64_pos_one +#define Float64_one_half_exp UINT64_C(0x3FE0000000000000) + +#define Float64_mantissa_bits 52 +#define Float64_exp_bias 1023 +#define Float64_ilogb_subnorm_max -1023 + +#define Float64_exponent_bits 11 +#define Float64_sign_bits 1 + +long double frexpl(long double x, int *expon) { + F64_pun val; + val.flt = x; + // clears the signbit + val.bin <<= 1; + /* iszero(x) */ + if (val.bin == 0) { + // return unmodified + *expon = 0; + return x; + } + /* isinf(x) || isnan(x) */ + if (val.bin >= Float64_inf_lsh_1) { + // Unspecified return value for inf and NaN + *expon = FP_ILOGBNAN; + return x; + } + /* isnormal(x) */ + if (val.bin >= Float64_norm_min_lsh_1) { + // shift an additional bit to account for the signbit clear shift + int x_exp = (int)(val.bin >> (Float64_mantissa_bits + 1)); + // frexp is ilogb(x) + 1 + x_exp -= (Float64_exp_bias - 1); + *expon = x_exp; + F64_pun ret; + ret.flt = x; + // Clear the exponent bits + ret.bin &= Float64_frexp_mask; + // Copy the exponent of 0.5 to normalize the value to [0.5, 1.0) + ret.bin |= Float64_one_half_exp; + return ret.flt; + } + /* issubnormal(x) */ + // val.bin was already shifted by one, so subtract one from the clz_offset + const int clz_offset = Float64_exponent_bits + Float64_sign_bits - 1; + int clz_result = __builtin_clzll(val.bin); + // frexp is ilogb(x) + 1 + *expon = (Float64_ilogb_subnorm_max + clz_offset + 1) - clz_result; + // Shift everything such that the MSB of the mantissa is in the LSB of the exponent + val.bin <<= clz_result - clz_offset; + #if 0 + // Clear the exponent bits + val.bin &= Float64_frexp_mask; + // Copy the exponent of 0.5 to normalize the value to [0.5, 1.0) + val.bin |= Float64_one_half_exp; + #else + /** + * At this point, the exponent bits are exactly equal to `0x001`, this + * allows us to set the exponent of 0.5 with an XOR. The XOR value is + * `0.5_exponent ^ 0x001` which is also the exponent value for 1.0 + */ + val.bin ^= Float64_frexp_subnorm_mask; + #endif + return copysignl(val.flt, x); +} diff --git a/src/libc/ilogb.c b/src/libc/ilogb.c index c68ed6edc..1c7f0a7a0 100644 --- a/src/libc/ilogb.c +++ b/src/libc/ilogb.c @@ -29,3 +29,50 @@ int ilogbf(float x) } int ilogb(double) __attribute__((alias("ilogbf"))); + + + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_ilogb_subnorm_max -1023 +#define Float64_exp_bias 1023 +#define Float64_mantissa_bits 52 +#define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) +#define Float64_norm_min_lsh_1 UINT64_C(0x0020000000000000) + +#define Float64_exponent_bits 11 +#define Float64_sign_bits 1 + +int ilogbl(long double x) { + F64_pun val; + val.flt = x; + // clears the signbit + val.bin <<= 1; + /* iszero(x) */ + if (val.bin == 0) { + errno = EDOM; + feraiseexcept(FE_INVALID); + return FP_ILOGB0; + } + /* isinf(x) || isnan(x) */ + if (val.bin >= Float64_inf_lsh_1) { + errno = EDOM; + feraiseexcept(FE_INVALID); + // Assumes FP_ILOGBNAN == INT_MAX + return FP_ILOGBNAN; + } + /* isnormal(x) */ + if (val.bin >= Float64_norm_min_lsh_1) { + // shift an additional bit to account for the signbit clear shift + int x_exp = (int)(val.bin >> (Float64_mantissa_bits + 1)); + x_exp -= Float64_exp_bias; + return x_exp; + } + /* issubnormal(x) */ + // val.bin was already shifted by one, so subtract one from the clz_offset + const int clz_offset = Float64_exponent_bits + Float64_sign_bits - 1; + return (Float64_ilogb_subnorm_max + clz_offset) - __builtin_clzll(val.bin); +} diff --git a/src/libc/include/math.h b/src/libc/include/math.h index 60cb7c4e3..2003f48eb 100644 --- a/src/libc/include/math.h +++ b/src/libc/include/math.h @@ -77,12 +77,12 @@ int _fpclassifyl(long double n); 1) #define iszero(x) ( \ sizeof((x)) == sizeof(float) ? _iszerof((x)) : \ - sizeof((x)) == sizeof(long double) ? _iszerol(x) : \ + sizeof((x)) == sizeof(long double) ? _iszerol((x)) : \ (x) == 0) #define issubnormal(x) ( \ sizeof((x)) == sizeof(float) ? _issubnormalf((x)) : \ - sizeof((x)) == sizeof(long double) ? _issubnormall(x) : \ - (x) == 0) + sizeof((x)) == sizeof(long double) ? _issubnormall((x)) : \ + 0) #define fpclassify(x) ( \ sizeof((x)) == sizeof(float) ? _fpclassifyf((x)) : \ sizeof((x)) == sizeof(long double) ? _fpclassifyl((x)) : \ @@ -256,10 +256,18 @@ double nextafter(double, double); float nextafterf(float, float); long double nextafterl(long double, long double); +double nextdown(double); +float nextdownf(float); +long double nextdownl(long double); + double nexttoward(double, long double); float nexttowardf(float, long double); long double nexttowardl(long double, long double); +double nextup(double); +float nextupf(float); +long double nextupl(long double); + double pow(double, double); float powf(float, float); long double powl(long double, long double); diff --git a/src/libc/ldexp.c b/src/libc/ldexp.c index 5e79d5358..ff55a1bf5 100644 --- a/src/libc/ldexp.c +++ b/src/libc/ldexp.c @@ -8,6 +8,7 @@ /************************************************************************/ #include #include +#include typedef union { @@ -45,22 +46,22 @@ float _ldexpf_c(float value, int power) { Ieee754 floating; int exponent; - int powerplusexponent; + int powerplusexponent; - if ( value == 0.0 || !isfinite(value) ) return value; + if ( value == 0.0 || !isfinite(value) ) return value; - floating.value = value; + floating.value = value; exponent = (floating.bits >> exponent_shift) & exponent_mask; - powerplusexponent = power + exponent; + powerplusexponent = power + exponent; if ( powerplusexponent > exponent_max ) { - errno = ERANGE; + errno = ERANGE; return (floating.bits & (1L << sign_shift)) == 0 ? HUGE_VALF : - HUGE_VALF; } if ( powerplusexponent <= exponent_min ) // CR 3964 { - errno = ERANGE; + errno = ERANGE; return 0.0; } floating.bits += (long) power << exponent_shift; // adjust exponent @@ -68,3 +69,133 @@ float _ldexpf_c(float value, int power) } double _ldexp_c(double, int) __attribute__((alias("_ldexpf_c"))); + +// when FLT_RADIX == 2, scalbn is equivilent to ldexp +float scalbnf(float, int) __attribute__((alias("_ldexpf_c"))); +double scalbn(double, int) __attribute__((alias("_ldexpf_c"))); + + + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_pos_inf UINT64_C(0x7FF0000000000000) +#define Float64_norm_min_exp_mask UINT64_C(0x0010000000000000) +#define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) +#define Float64_norm_min_lsh_1 UINT64_C(0x0020000000000000) +#define Float64_frexp_mask UINT64_C(0x800FFFFFFFFFFFFF) + +#define Float64_huge_val Float64_pos_inf + +#define Float64_mantissa_bits 52 +#define Float64_exp_bias 1023 +#define Float64_max_exp 1023 +#define Float64_norm_min_exp -1022 + +#define Float64_exponent_bits 11 +#define Float64_sign_bits 1 + +/** Generates a normalized constant that is 2^expon */ +static long double generate_ldexpl_mult(int expon) { + F64_pun ret; + ret.bin = (uint64_t)(expon + Float64_exp_bias) << Float64_mantissa_bits; + return ret.flt; +} + +/** + * @remarks Assumes round to nearest ties to even for correct rounding of + * subnormal values. + */ +long double ldexpl(long double x, int expon) { + F64_pun val; + val.flt = x; + // clears the signbit + val.bin <<= 1; + /* expon == 0 || iszero(x) || isinf(x) || isnan(x) */ + if (expon == 0 || val.bin == 0 || val.bin >= Float64_inf_lsh_1) { + // return unmodifed + return x; + } + /* isnormal(x) */ + if (val.bin >= Float64_norm_min_lsh_1) { + // shift an additional bit to account for the signbit clear shift + int x_exp = (int)(val.bin >> (Float64_mantissa_bits + 1)); + x_exp -= Float64_exp_bias; + x_exp += expon; + // overflow + if (x_exp > Float64_max_exp) { + errno = ERANGE; + F64_pun ret; + ret.bin = Float64_huge_val; + return copysignl(ret.flt, x); + } + // normalized + if (x_exp >= Float64_norm_min_exp) { + F64_pun ret; + ret.flt = x; + // Clear the exponent bits + ret.bin &= Float64_frexp_mask; + x_exp += Float64_exp_bias; + ret.bin |= ((uint64_t)x_exp) << Float64_mantissa_bits; + return ret.flt; + } + // make subnormal (with correct rounding) + int subnorm_exp = x_exp - Float64_norm_min_exp; + if (subnorm_exp < -53) { + // rounds to zero (round to nearest ties to even) + errno = ERANGE; + return copysignl(0.0L, x); + } + F64_pun ret; + ret.flt = x; + // Clear the exponent bits + ret.bin &= Float64_frexp_mask; + // Copy the exponent of the minimum normalized value + ret.bin |= Float64_norm_min_exp_mask; + // precision may be lost + ret.flt *= generate_ldexpl_mult(subnorm_exp); + return ret.flt; + } + // make normalized (with correct rounding) + if (expon < -52) { + // rounds to zero (round to nearest ties to even) + errno = ERANGE; + return copysignl(0.0L, x); + } + /** + * fallsback to multiplication if there is a chance the subnormal value + * wont't be normalized + */ + if (expon < Float64_mantissa_bits) { + // precision may be lost when expon < 0 + x *= generate_ldexpl_mult(expon); + return x; + } + // val.bin was already shifted by one, so subtract one from the clz_offset + const int clz_offset = Float64_exponent_bits + Float64_sign_bits - 1; + int clz_result = __builtin_clzll(val.bin); + expon -= clz_result - clz_offset + 1; + /** + * 2045 is the largest power of 2 that you can multiply the smallest + * normalized number by without overflowing the expoenent field + * (creating infinity/NaN). Any lower, and floats will be wrongly rounded + * to infinty. + */ + if (expon > 2045) { + // overflow + errno = ERANGE; + F64_pun ret; + ret.bin = Float64_huge_val; + return copysignl(ret.flt, x); + } + // Shift everything such that the MSB of the mantissa is in the LSB of the exponent + val.bin <<= clz_result - clz_offset; + // Add the exponent + val.bin += ((uint64_t)expon) << Float64_mantissa_bits; + return copysignl(val.flt, x); +} + +// when FLT_RADIX == 2, scalbn is equivilent to ldexp +long double scalbnl(long double, int) __attribute__((alias("ldexpl"))); diff --git a/src/libc/nextafter.c b/src/libc/nextafter.c index 962ddc231..056755aa0 100644 --- a/src/libc/nextafter.c +++ b/src/libc/nextafter.c @@ -1,11 +1,115 @@ -#include +#include #include +#include -float nextafterf(float x, float y) -{ - if (x == y) return y; - if (x == 0.f) return copysignf(FLT_TRUE_MIN, y); - return x - nearbyintf(x / y) * y; +typedef union F32_pun { + float flt; + uint32_t bin; +} F32_pun; + +#define Float32_pos_subnorm_min UINT32_C(0x00000001) +#define Float32_neg_subnorm_min UINT32_C(0x80000001) + +float nextafterf(float x, float y) { + F32_pun arg_x, arg_y; + arg_x.flt = x; + arg_y.flt = y; + + if (isnan(y)) { + return y; + } + if (isnan(x)) { + return x; + } + if (arg_x.bin == arg_y.bin) { + return y; + } + + if (iszero(x)) { + if (iszero(y)) { + // special case where `+0.0 --> -0.0` and `-0.0 --> +0.0` + return y; + } + feraiseexcept(FE_INEXACT | FE_UNDERFLOW); + F32_pun ret; + ret.bin = signbit(y) ? Float32_neg_subnorm_min : Float32_pos_subnorm_min; + return ret.flt; + } + if (isless(x, y) != signbit(x)) { + // Towards positive/negative infinity + arg_x.bin++; + } else { + // Towards negative/positive zero + arg_x.bin--; + } + if (isnormal(arg_x.flt)) { + return arg_x.flt; + } + if (isinf(arg_x.flt)) { + // overflow to infinity + feraiseexcept(FE_INEXACT | FE_OVERFLOW); + } else { + // result is subnormal or zero + feraiseexcept(FE_INEXACT | FE_UNDERFLOW); + } + return arg_x.flt; } double nextafter(double, double) __attribute__((alias("nextafterf"))); + + + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_pos_subnorm_min UINT64_C(0x0000000000000001) +#define Float64_neg_subnorm_min UINT64_C(0x8000000000000001) + +long double nextafterl(long double x, long double y) { + F64_pun arg_x, arg_y; + arg_x.flt = x; + arg_y.flt = y; + + if (isnan(y)) { + return y; + } + if (isnan(x)) { + return x; + } + if (arg_x.bin == arg_y.bin) { + return y; + } + + if (iszero(x)) { + if (iszero(y)) { + // special case where `+0.0 --> -0.0` and `-0.0 --> +0.0` + return y; + } + feraiseexcept(FE_INEXACT | FE_UNDERFLOW); + F64_pun ret; + ret.bin = signbit(y) ? Float64_neg_subnorm_min : Float64_pos_subnorm_min; + return ret.flt; + } + if (isless(x, y) != signbit(x)) { + // Towards positive/negative infinity + arg_x.bin++; + } else { + // Towards negative/positive zero + arg_x.bin--; + } + if (isnormal(arg_x.flt)) { + return arg_x.flt; + } + if (isinf(arg_x.flt)) { + // overflow to infinity + feraiseexcept(FE_INEXACT | FE_OVERFLOW); + } else { + // result is subnormal or zero + feraiseexcept(FE_INEXACT | FE_UNDERFLOW); + } + return arg_x.flt; +} + +long double nexttowardl(long double, long double) __attribute__((alias("nextafterl"))); diff --git a/src/libc/nexttoward.c b/src/libc/nexttoward.c new file mode 100644 index 000000000..a31eaba8c --- /dev/null +++ b/src/libc/nexttoward.c @@ -0,0 +1,74 @@ +#include +#include +#include + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +typedef union F32_pun { + float flt; + uint32_t bin; +} F32_pun; + +#define Float32_pos_subnorm_min UINT32_C(0x00000001) +#define Float32_neg_subnorm_min UINT32_C(0x80000001) +#define Float32_pos_nan UINT32_C(0x7FC00000) + +float nexttowardf(float x, long double y) { + F32_pun arg_x; + arg_x.flt = x; + + if (isnan(x)) { + return x; + } + + if (isnan(y)) { + F32_pun ret; + ret.bin = Float32_pos_nan; + return ret.flt; + } + + F64_pun x_f64, y_f64; + x_f64.flt = (long double)x; + y_f64.flt = y; + if (x_f64.bin == y_f64.bin) { + // return unmodified + return x; + } + + if (iszero(x)) { + F32_pun ret; + ret.bin = signbit(y) ? Float32_neg_subnorm_min : Float32_pos_subnorm_min; + if (iszero(y)) { + // pos_subnorm_min becomes +0.0, and neg_subnorm_min becomes -0.0 + ret.bin--; + } else { + feraiseexcept(FE_INEXACT | FE_UNDERFLOW); + } + return ret.flt; + } + if (isless(x_f64.flt, y) != signbit(x)) { + // Towards positive/negative infinity + arg_x.bin++; + } else { + // Towards negative/positive zero + arg_x.bin--; + } + if (isnormal(arg_x.flt)) { + return arg_x.flt; + } + if (isinf(arg_x.flt)) { + // overflow to infinity + feraiseexcept(FE_INEXACT | FE_OVERFLOW); + } else { + // result is subnormal or zero + feraiseexcept(FE_INEXACT | FE_UNDERFLOW); + } + return arg_x.flt; +} + +double nexttoward(double, long double) __attribute__((alias("nexttowardf"))); + +/* nexttowardl is aliased in nextafter.c */ diff --git a/src/libc/nextupdown.c b/src/libc/nextupdown.c new file mode 100644 index 000000000..f171c1407 --- /dev/null +++ b/src/libc/nextupdown.c @@ -0,0 +1,128 @@ +#include +#include +#include + +typedef union F32_pun { + float flt; + uint32_t bin; +} F32_pun; + +#define Float32_pos_subnorm_min UINT32_C(0x00000001) +#define Float32_neg_subnorm_min UINT32_C(0x80000001) +#define Float32_pos_inf UINT32_C(0x7F800000) +#define Float32_neg_inf UINT32_C(0xFF800000) + +float nextupf(float x) { + F32_pun arg_x; + arg_x.flt = x; + + if (isnan(x) || arg_x.bin == Float32_pos_inf) { + // return unmodified + return x; + } + + if (iszero(x)) { + F32_pun ret; + ret.bin = Float32_pos_subnorm_min; + return ret.flt; + } + + if (signbit(x)) { + // Towards negative zero + arg_x.bin--; + } else { + // Towards positive infinity + arg_x.bin++; + } + return arg_x.flt; +} + +float nextdownf(float x) { + F32_pun arg_x; + arg_x.flt = x; + + if (isnan(x) || arg_x.bin == Float32_neg_inf) { + // return unmodified + return x; + } + + if (iszero(x)) { + F32_pun ret; + ret.bin = Float32_neg_subnorm_min; + return ret.flt; + } + + if (signbit(x)) { + // Towards negative infinity + arg_x.bin++; + } else { + // Towards positive zero + arg_x.bin--; + } + return arg_x.flt; +} + +double nextup(double) __attribute__((alias("nextupf"))); +double nextdown(double) __attribute__((alias("nextdownf"))); + + + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define Float64_pos_subnorm_min UINT64_C(0x0000000000000001) +#define Float64_neg_subnorm_min UINT64_C(0x8000000000000001) +#define Float64_pos_inf UINT64_C(0x7FF0000000000000) +#define Float64_neg_inf UINT64_C(0xFFF0000000000000) + +long double nextupl(long double x) { + F64_pun arg_x; + arg_x.flt = x; + + if (isnan(x) || arg_x.bin == Float64_pos_inf) { + // return unmodified + return x; + } + + if (iszero(x)) { + F64_pun ret; + ret.bin = Float64_pos_subnorm_min; + return ret.flt; + } + + if (signbit(x)) { + // Towards negative zero + arg_x.bin--; + } else { + // Towards positive infinity + arg_x.bin++; + } + return arg_x.flt; +} + +long double nextdownl(long double x) { + F64_pun arg_x; + arg_x.flt = x; + + if (isnan(x) || arg_x.bin == Float64_neg_inf) { + // return unmodified + return x; + } + + if (iszero(x)) { + F64_pun ret; + ret.bin = Float64_neg_subnorm_min; + return ret.flt; + } + + if (signbit(x)) { + // Towards negative infinity + arg_x.bin++; + } else { + // Towards positive zero + arg_x.bin--; + } + return arg_x.flt; +} diff --git a/src/libc/scalbln.c b/src/libc/scalbln.c index 0dea9dd34..46db02b7b 100644 --- a/src/libc/scalbln.c +++ b/src/libc/scalbln.c @@ -1,8 +1,13 @@ #include -float scalblnf(float x, long exp) +float scalblnf(float x, long expon) { - return x * exp2f(exp); + return scalbnf(x, (int)expon); } double scalbln(double, long) __attribute__((alias("scalblnf"))); + +long double scalblnl(long double x, long expon) +{ + return scalbnl(x, (int)expon); +} diff --git a/src/libc/scalbn.c b/src/libc/scalbn.c deleted file mode 100644 index b94488127..000000000 --- a/src/libc/scalbn.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -float scalbnf(float x, int exp) -{ - return x * exp2f(exp); -} - -double scalbn(double, int) __attribute__((alias("scalbnf"))); diff --git a/src/libcxx/include/cmath b/src/libcxx/include/cmath index ee327eb3d..bc5638692 100644 --- a/src/libcxx/include/cmath +++ b/src/libcxx/include/cmath @@ -348,6 +348,14 @@ template inline constexpr enable_if_t, double> nextafter(_Tp __x, _Up __y) { return nextafter(__x, __y); } +using ::nextup; +using ::nextupf; +using ::nextupl; +inline constexpr float nextup(float __x) { return nextupf(__x); } +inline constexpr long double nextup(long double __x) { return nextupl(__x); } +template inline constexpr enable_if_t, double> +nextup(_Tp __x) { return nextup(__x); } + using ::nexttoward; using ::nexttowardf; using ::nexttowardl; @@ -357,6 +365,14 @@ template inline constexpr enable_if_t, double> nexttoward(_Tp __x, _Up __y) { return nexttoward(__x, __y); } +using ::nextdown; +using ::nextdownf; +using ::nextdownl; +inline constexpr float nextdown(float __x) { return nextdownf(__x); } +inline constexpr long double nextdown(long double __x) { return nextdownl(__x); } +template inline constexpr enable_if_t, double> +nextdown(_Tp __x) { return nextdown(__x); } + using ::pow; using ::powf; using ::powl; @@ -400,6 +416,14 @@ inline constexpr long double round(long double __x) { return roundl(__x); } template inline constexpr enable_if_t, double> round(_Tp __x) { return round(__x); } +using ::roundeven; +using ::roundevenf; +using ::roundevenl; +inline constexpr float roundeven(float __x) { return roundevenf(__x); } +inline constexpr long double roundeven(long double __x) { return roundevenl(__x); } +template inline constexpr enable_if_t, double> +roundeven(_Tp __x) { return roundeven(__x); } + using ::scalbln; using ::scalblnf; using ::scalblnl; From 18fbe4e6e73ba5a0653e09c7a257e35667d1d0b2 Mon Sep 17 00:00:00 2001 From: ZERICO2005 <71151164+ZERICO2005@users.noreply.github.com> Date: Tue, 14 Jan 2025 23:20:22 -0700 Subject: [PATCH 4/7] rewrote the float64-to-integer functions, and inlined some softfloat functions to reduce overhead --- src/crt/float64_runtime.c | 69 ++++++++--------- src/crt/float64_runtime.src | 44 ----------- src/crt/float64_to_int.c | 147 ++++++++++++++++++++++++++++++++++++ src/crt/float64_to_int.src | 35 +++++++++ src/crt/ftod.c | 91 ++++++++++++++++++++++ src/crt/ftod.src | 15 ++++ src/crt/ltod.c | 68 +++++++++++++++++ src/crt/ultod.c | 63 ++++++++++++++++ src/libc/float64_math.c | 15 ++++ src/libc/float64_rounding.c | 2 +- 10 files changed, 468 insertions(+), 81 deletions(-) create mode 100644 src/crt/float64_to_int.c create mode 100644 src/crt/float64_to_int.src create mode 100644 src/crt/ftod.c create mode 100644 src/crt/ftod.src create mode 100644 src/crt/ltod.c create mode 100644 src/crt/ultod.c diff --git a/src/crt/float64_runtime.c b/src/crt/float64_runtime.c index a4209217a..a095012d7 100644 --- a/src/crt/float64_runtime.c +++ b/src/crt/float64_runtime.c @@ -1,4 +1,5 @@ #include +#include #include "../softfloat/include/softfloat.h" //------------------------------------------------------------------------------ @@ -23,6 +24,7 @@ typedef union F32_pun { /* long double _dneg_c(long double x) */ +#if 0 long double _dadd_c(long double x, const long double *y) { F64_pun arg_x, arg_y, ret; arg_x.flt = x; @@ -38,68 +40,63 @@ long double _dsub_c(long double x, const long double *y) { ret.soft = f64_sub(arg_x.soft, arg_y.soft); return ret.flt; } +#else +float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool ); +float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool ); -long double _dmul_c(long double x, const long double *y) { +long double _dadd_c(long double x, const long double *y) { F64_pun arg_x, arg_y, ret; arg_x.flt = x; arg_y.flt = *y; - ret.soft = f64_mul(arg_x.soft, arg_y.soft); + bool sign_x = signbit(arg_x.flt); + if (sign_x == signbit(arg_y.flt)) { + ret.soft = softfloat_addMagsF64(arg_x.bin, arg_y.bin, sign_x); + } else { + ret.soft = softfloat_subMagsF64(arg_x.bin, arg_y.bin, sign_x); + } return ret.flt; } -long double _ddiv_c(long double x, const long double *y) { +long double _dsub_c(long double x, const long double *y) { F64_pun arg_x, arg_y, ret; arg_x.flt = x; arg_y.flt = *y; - ret.soft = f64_div(arg_x.soft, arg_y.soft); + bool sign_x = signbit(arg_x.flt); + if (sign_x == signbit(arg_y.flt)) { + ret.soft = softfloat_subMagsF64(arg_x.bin, arg_y.bin, sign_x); + } else { + ret.soft = softfloat_addMagsF64(arg_x.bin, arg_y.bin, sign_x); + } return ret.flt; } -long double _drem_c(long double x, const long double *y) { +#endif + +long double _dmul_c(long double x, const long double *y) { F64_pun arg_x, arg_y, ret; arg_x.flt = x; arg_y.flt = *y; - ret.soft = f64_rem(arg_x.soft, arg_y.soft); + ret.soft = f64_mul(arg_x.soft, arg_y.soft); return ret.flt; } -/* int _dcmp_c(const long double *x, const long double* y) */ - -//------------------------------------------------------------------------------ -// Convert to long double -//------------------------------------------------------------------------------ - -long double _ftod_c(float x) { - F32_pun arg_x; - F64_pun ret; +long double _ddiv_c(long double x, const long double *y) { + F64_pun arg_x, arg_y, ret; arg_x.flt = x; - ret.soft = f32_to_f64(arg_x.soft); - return ret.flt; -} - -long double _ltod_c(int32_t x) { - F64_pun ret; - ret.soft = i32_to_f64(x); - return ret.flt; -} - -long double _lltod_c(int64_t x) { - F64_pun ret; - ret.soft = i64_to_f64(x); + arg_y.flt = *y; + ret.soft = f64_div(arg_x.soft, arg_y.soft); return ret.flt; } -long double _ultod_c(uint32_t x) { - F64_pun ret; - ret.soft = ui32_to_f64(x); +long double _drem_c(long double x, const long double *y) { + F64_pun arg_x, arg_y, ret; + arg_x.flt = x; + arg_y.flt = *y; + ret.soft = f64_rem(arg_x.soft, arg_y.soft); return ret.flt; } -long double _ulltod_c(uint64_t x) { - F64_pun ret; - ret.soft = ui64_to_f64(x); - return ret.flt; -} +/* int _dcmp_c(const long double *x, const long double* y) */ //------------------------------------------------------------------------------ // Convert from long double diff --git a/src/crt/float64_runtime.src b/src/crt/float64_runtime.src index 699798ef4..48dd13fc6 100644 --- a/src/crt/float64_runtime.src +++ b/src/crt/float64_runtime.src @@ -3,7 +3,6 @@ section .text public __dadd, __dsub, __dmul, __ddiv, __drem - public __ftod, __ltod, __lltod, __ultod, __ulltod public __dtof, __dtol, __dtoll, __dtoul, __dtoull ;------------------------------------------------------------------------------- @@ -60,48 +59,6 @@ __drem: pop af, af, af, af, iy, af ret -;------------------------------------------------------------------------------- -; Convert to long double -;------------------------------------------------------------------------------- - -__ftod: - ; f32_ret_f64 - ld d, a - push iy, de, hl - call __ftod_c - pop af, af, iy - ret - -__ltod: - ; i32_ret_f64 - ld d, a - push iy, de, hl - call __ltod_c - pop af, af, iy - ret - -__lltod: - ; i64_ret_f64 - push af, iy, bc, de, hl - call __lltod_c - pop af, af, af, iy, af - ret - -__ultod: - ; u32_ret_f64 - ld d, a - push iy, de, hl - call __ultod_c - pop af, af, iy - ret - -__ulltod: - ; u64_ret_f64 - push af, iy, bc, de, hl - call __ulltod_c - pop af, af, af, iy, af - ret - ;------------------------------------------------------------------------------- ; Convert from long double ;------------------------------------------------------------------------------- @@ -142,5 +99,4 @@ __dtoull: ret extern __dadd_c, __dsub_c, __dmul_c, __ddiv_c, __drem_c - extern __ftod_c, __ltod_c, __lltod_c, __ultod_c, __ulltod_c extern __dtof_c, __dtol_c, __dtoll_c, __dtoul_c, __dtoull_c diff --git a/src/crt/float64_to_int.c b/src/crt/float64_to_int.c new file mode 100644 index 000000000..8d1a8aebc --- /dev/null +++ b/src/crt/float64_to_int.c @@ -0,0 +1,147 @@ +#include +#include + +typedef union F64_pun { + long double flt; + uint64_t bin; + struct { + uint24_t UHL; + uint24_t UDE; + uint16_t BC; + } reg; +} F64_pun; + +#define Float64_pos_one UINT64_C(0x3FF0000000000000) + +#define Float64_bias 1023 +#define Float64_mant_bits 52 +#define Float64_u64_max_exp 64 +#define Float64_u32_max_exp 32 +#define Float64_i64_max_exp 63 +#define Float64_i32_max_exp 31 +#define Float64_exp_BC_shift 4 + +#if 0 +/** + * This routine can be used for specifically _dtoul and _dtoull + */ +uint64_t _dtoull_c(long double x) { + F64_pun val; + val.flt = x; + // if trunc(x) is zero or x is negative + if ((int64_t)val.bin < (int64_t)Float64_pos_one) { + #if 0 + if (iszero(x)) { + return 0; + } + return UINT32_MAX; + #else + /* undefined behaviour for negative values of x */ + return 0; + #endif + } + unsigned expon = val.reg.BC; + // exponent is stored in bits [4, 14], so we shift it to be bits [0, 10]. + expon >>= 4; + // doesn't underflow since 1.0 - Float64_bias gives us an exponent of zero + expon -= Float64_bias; + if (expon >= Float64_u64_max_exp) { + /* undefined return value for overflow */ + return UINT64_MAX; + } + // clears the exponent field without touching the mantissa + val.reg.BC &= 0x000F; + // sets the LSB of the exponent since x is normalized + val.reg.BC |= 0x0010; + if (expon < Float64_mant_bits) { + val.bin >>= Float64_mant_bits - expon; + return val.bin; + } + /* expon >= 52 or [52, 63] */ + val.bin <<= expon - 52; + return val.bin; +} +#endif + +/** + * @note val must have the signbit cleared + */ +static uint64_t f64_to_unsigned(F64_pun val) { + // if trunc(x) is zero + if (val.bin < Float64_pos_one) { + return 0; + } + unsigned expon = val.reg.BC; + // exponent is stored in bits [4, 14], so we shift it to be bits [0, 10]. + expon >>= Float64_exp_BC_shift; + // doesn't underflow since 1.0 - Float64_bias gives us an exponent of zero + expon -= Float64_bias; + // clears the exponent field without touching the mantissa + val.reg.BC &= 0x000F; + // sets the LSB of the exponent since x is normalized + val.reg.BC |= 0x0010; + if (expon < Float64_mant_bits) { + /* expon is [0, 51] */ + val.bin >>= Float64_mant_bits - expon; + return val.bin; + } + /* expon >= 52 or [52, 63] */ + val.bin <<= expon - 52; + return val.bin; +} + +uint64_t _dtoull_c(long double x) { + F64_pun val; + val.flt = x; + /* overflow || signbit(x) || isinf(x) || isnan(x) */ + if (val.reg.BC >= ((Float64_bias + Float64_u64_max_exp) << Float64_exp_BC_shift)) { + /* undefined return value for negative/inf/NaN values of x */ + return UINT64_MAX; + } + return f64_to_unsigned(val); +} + +uint32_t _dtoul_c(long double x) { + F64_pun val; + val.flt = x; + /* overflow || signbit(x) || isinf(x) || isnan(x) */ + if (val.reg.BC >= ((Float64_bias + Float64_u32_max_exp) << Float64_exp_BC_shift)) { + /* undefined return value for negative/inf/NaN values of x */ + return UINT32_MAX; + } + return (uint32_t)f64_to_unsigned(val); +} + +int64_t _dtoll_c(long double x) { + F64_pun val; + val.flt = x; + // tests for signbit(x) + bool x_sign = (val.reg.BC >= 0x8000); + // clears the signbit + val.reg.BC &= 0x7FFF; + /* overflow || isinf(x) || isnan(x) */ + if (val.reg.BC >= ((Float64_bias + Float64_i64_max_exp) << Float64_exp_BC_shift)) { + /* undefined return value for inf/NaN values of x */ + return x_sign ? INT64_MIN : INT64_MAX; + } + int64_t ret = (int64_t)f64_to_unsigned(val); + ret = x_sign ? -ret : ret; + return ret; +} + +int32_t _dtol_c(long double x) { + F64_pun val; + val.flt = x; + // tests for signbit(x) + bool x_sign = (val.reg.BC >= 0x8000); + // clears the signbit + val.reg.BC &= 0x7FFF; + /* overflow || isinf(x) || isnan(x) */ + if (val.reg.BC >= ((Float64_bias + Float64_i32_max_exp) << Float64_exp_BC_shift)) { + /* undefined return value for inf/NaN values of x */ + return x_sign ? INT32_MIN : INT32_MAX; + } + int32_t ret = (int32_t)f64_to_unsigned(val); + ret = x_sign ? -ret : ret; + return ret; +} diff --git a/src/crt/float64_to_int.src b/src/crt/float64_to_int.src new file mode 100644 index 000000000..c233cd3ba --- /dev/null +++ b/src/crt/float64_to_int.src @@ -0,0 +1,35 @@ + assume adl=1 + + section .text + + public __dtoull, __dtoul, __dtoll, __dtol + +__dtoull: + ; f64_ret_u64 + push af, iy, bc, de, hl + call __dtoull_c + pop af, af, af, iy, af + ret + +__dtoul: + ; f64_ret_u32 + push af, iy, bc, de, hl + call __dtoul_c + pop af, af, af, iy, af + ret + +__dtol: + ; f64_ret_u32 + push af, iy, bc, de, hl + call __dtol_c + pop af, af, af, iy, af + ret + +__dtoll: + ; f64_ret_u64 + push af, iy, bc, de, hl + call __dtoll_c + pop af, af, af, iy, af + ret + + extern __dtoull_c, __dtoul_c, __dtoll_c, __dtol_c diff --git a/src/crt/ftod.c b/src/crt/ftod.c new file mode 100644 index 000000000..9c89d6dd7 --- /dev/null +++ b/src/crt/ftod.c @@ -0,0 +1,91 @@ +#include +#include +#include + +typedef union F32_pun { + float flt; + uint32_t bin; + struct { + uint24_t mant; + uint8_t expon; + } split; +} F32_pun; + +typedef union F64_pun { + long double flt; + uint64_t bin; + struct { + uint24_t lo; + uint24_t hi; + } u24; +} F64_pun; + +#define Float64_pos_zero UINT64_C(0x0000000000000000) +#define Float64_neg_zero UINT64_C(0x8000000000000000) +#define Float64_pos_inf UINT64_C(0x7FF0000000000000) +#define Float64_neg_inf UINT64_C(0xFFF0000000000000) +#define Float64_pos_nan UINT64_C(0x7FF8000000000000) +#define Float64_neg_nan UINT64_C(0xFFF8000000000000) + +#define Float64_mant_bits 52 +#define Float32_mant_bits 23 +#define Float64_expon_bits 11 +#define Float32_expon_bits 8 +#define Float64_bias 1023 +#define Float32_bias 127 + +long double _ftod_c(float x) { + bool x_sign = signbit(x); + F32_pun val; + F64_pun ret; + val.flt = x; + + /* common path */ + if (isnormal(val.flt)) { + uint24_t mantissa = val.split.mant; + uint24_t expon = + (val.split.expon + ((Float64_bias - Float32_bias) >> 1)) + + (x_sign ? (((1 << Float64_expon_bits) - (1 << Float32_expon_bits)) >> 1) : (0)); + ret.u24.hi = expon; + ret.u24.lo = mantissa; + // mantissa[0, 22] exponent[23, 33] signbit[34] + ret.bin <<= Float64_mant_bits - Float32_mant_bits; + return ret.flt; + } + if (issubnormal(val.flt)) { + // since this is subnormal, the LSB of the exponent is already zero + uint24_t mantissa = val.split.mant; + + // shift until the MSB of the mantissa is the LSB of the exponent + uint8_t clz_result = (uint8_t)__builtin_clz(mantissa); + mantissa <<= clz_result; + + /** + * Sets the LSB of the exponent. If the clz_result is odd, then the + * exponent will also be odd + */ + mantissa += (clz_result & 0x1) ? 0x800000 : 0x000000; + + uint24_t expon = + (((Float64_bias - Float32_bias) >> 1) - + (clz_result >> 1)) + + (x_sign ? ((1 << Float64_expon_bits) >> 1) : 0); + + ret.u24.hi = expon; + ret.u24.lo = mantissa; + // mantissa[0, 22] exponent[23, 33] signbit[34] + ret.bin <<= Float64_mant_bits - Float32_mant_bits; + return ret.flt; + } + if (iszero(val.flt)) { + ret.bin = x_sign ? Float64_neg_zero : Float64_pos_zero; + return ret.flt; + } + if (isinf(val.flt)) { + ret.bin = x_sign ? Float64_neg_inf : Float64_pos_inf; + return ret.flt; + } + /* isnan(val.flt) */ + ret.bin = x_sign ? Float64_neg_nan : Float64_pos_nan; + return ret.flt; +} diff --git a/src/crt/ftod.src b/src/crt/ftod.src new file mode 100644 index 000000000..9f9413e8a --- /dev/null +++ b/src/crt/ftod.src @@ -0,0 +1,15 @@ + assume adl=1 + + section .text + + public __ftod + +__ftod: + ; f32_ret_f64 + ld d, a + push iy, de, hl + call __ftod_c + pop af, af, iy + ret + +extern __ftod_c \ No newline at end of file diff --git a/src/crt/ltod.c b/src/crt/ltod.c new file mode 100644 index 000000000..d46d1d95a --- /dev/null +++ b/src/crt/ltod.c @@ -0,0 +1,68 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include + +union ui64_f64 { uint64_t ui; long double f; }; + +#define packToF64UI( sign, exp, sig ) ((uint64_t) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<52) + (sig))) + +/** + * @remarks inlined version of `float64_t i32_to_f64(int32_t)` from + * `i32_to_f64.c` + */ +long double _ltod_c( int32_t a ) +{ + uint_fast64_t uiZ; + bool sign; + uint_fast32_t absA; + int_fast8_t shiftDist; + union ui64_f64 uZ; + + if ( ! a ) { + uiZ = 0; + } else { + sign = (a < 0); + absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; + shiftDist = __builtin_clzl( absA ) + 21; + uiZ = + packToF64UI( + sign, 0x432 - shiftDist, (uint_fast64_t) absA< +#include + +union ui64_f64 { uint64_t ui; long double f; }; + +#define packToF64UI( sign, exp, sig ) ((uint64_t) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<52) + (sig))) + +/** + * @remarks inlined version of `float64_t ui32_to_f64(int32_t)` from + * `ui32_to_f64.c` + */ +long double _ultod_c( uint32_t a ) +{ + uint_fast64_t uiZ; + int_fast8_t shiftDist; + union ui64_f64 uZ; + + if ( ! a ) { + uiZ = 0; + } else { + shiftDist = __builtin_clzl( a ) + 21; + uiZ = + packToF64UI( 0, 0x432 - shiftDist, (uint_fast64_t) a< Date: Fri, 17 Jan 2025 12:52:10 -0700 Subject: [PATCH 5/7] Added assembly routines for floating point classification --- src/crt/dcmp.src | 26 --------- src/crt/dneg.c | 16 ------ src/crt/dneg.src | 26 ++++----- src/crt/float64_runtime.c | 30 +++------- src/crt/float64_runtime.src | 32 +++-------- src/crt/lltof.src | 2 +- src/crt/ltod.c | 99 +++++++++++--------------------- src/crt/ltod.src | 15 +++++ src/crt/ultod.c | 91 +++++++++++------------------ src/crt/ultod.src | 15 +++++ src/libc/copysign.c | 21 ------- src/libc/copysign.src | 14 +++++ src/libc/fabs.c | 20 ------- src/libc/fabs.src | 22 ++++--- src/libc/fpclassify.c | 65 --------------------- src/libc/fpclassifyf.src | 29 ++++++++++ src/libc/fpclassifyl.src | 38 ++++++++++++ src/libc/include/math.h | 13 +++-- src/libc/isfinite.c | 17 ------ src/libc/isfinitel.src | 17 ++++++ src/libc/isinf.c | 17 ------ src/libc/isinfl.src | 39 +++++++++++++ src/libc/isnan.c | 17 ------ src/libc/isnanf.src | 2 + src/libc/isnanl.src | 79 +++++++++++++++++++++++++ src/libc/isnormal.c | 38 ------------ src/libc/isnormalf.src | 18 ++++++ src/libc/isnormall.src | 29 ++++++++++ src/libc/issubnormal.c | 43 -------------- src/libc/issubnormalf.src | 19 ++++++ src/libc/issubnormall.src | 79 +++++++++++++++++++++++++ src/libc/iszero.c | 30 ---------- src/libc/iszerof.src | 20 +++++++ src/libc/iszerol.src | 34 +++++++++++ src/softfloat/include/opts-GCC.h | 4 +- 35 files changed, 568 insertions(+), 508 deletions(-) delete mode 100644 src/crt/dneg.c create mode 100644 src/crt/ltod.src create mode 100644 src/crt/ultod.src delete mode 100644 src/libc/copysign.c delete mode 100644 src/libc/fabs.c delete mode 100644 src/libc/fpclassify.c create mode 100644 src/libc/fpclassifyf.src create mode 100644 src/libc/fpclassifyl.src delete mode 100644 src/libc/isfinite.c create mode 100644 src/libc/isfinitel.src delete mode 100644 src/libc/isinf.c create mode 100644 src/libc/isinfl.src delete mode 100644 src/libc/isnan.c create mode 100644 src/libc/isnanl.src delete mode 100644 src/libc/isnormal.c create mode 100644 src/libc/isnormalf.src create mode 100644 src/libc/isnormall.src delete mode 100644 src/libc/issubnormal.c create mode 100644 src/libc/issubnormalf.src create mode 100644 src/libc/issubnormall.src delete mode 100644 src/libc/iszero.c create mode 100644 src/libc/iszerof.src create mode 100644 src/libc/iszerol.src diff --git a/src/crt/dcmp.src b/src/crt/dcmp.src index ee96974c2..10bed0f1a 100644 --- a/src/crt/dcmp.src +++ b/src/crt/dcmp.src @@ -4,30 +4,6 @@ public __dcmp -#if 0 - -; This version of _dcmp does not save/restore the state of BC/DE/HL, the state -; of these registers may by modified by the C function - -; int _dcmp_c(long double x, const long double *y) -__dcmp: - ; f64_f64*_ret_i24 - push af, iy - ld iy, 9 - add iy, sp - push iy, bc, de, hl - call __dcmp_c - pop af, af, af, af, iy, af - ; Set the comparison flags - add hl, de - or a, a - sbc hl, de - ret - -#else - -; Properly saves/restores the state of BC/DE/HL - ; int _dcmp_c(const long double *x, const long double *y) __dcmp: ; f64*_f64*_ret_i24 @@ -45,6 +21,4 @@ __dcmp: pop hl, de, bc ret -#end if - extern __dcmp_c diff --git a/src/crt/dneg.c b/src/crt/dneg.c deleted file mode 100644 index a2712c9fa..000000000 --- a/src/crt/dneg.c +++ /dev/null @@ -1,16 +0,0 @@ -#include - -typedef union F64_pun { - long double flt; - uint64_t bin; -} F64_pun; - -#define Float64_signbit UINT64_C(0x8000000000000000) - -// Should be easy to implement in assembly -long double _dneg_c(long double x) { - F64_pun ret; - ret.flt = x; - ret.bin ^= Float64_signbit; - return ret.flt; -} diff --git a/src/crt/dneg.src b/src/crt/dneg.src index 72a79f3dc..914428616 100644 --- a/src/crt/dneg.src +++ b/src/crt/dneg.src @@ -1,14 +1,12 @@ -assume adl=1 - -section .text - -public __dneg - -__dneg: - ; f64_ret_f64 - push af, iy, bc, de, hl - call __dneg_c - pop af, af, af, iy, af - ret - -extern __dneg_c + assume adl=1 + + section .text + + public __dneg + +; assumes BC:UDE:UHL +__dneg: + rl b + ccf + rr b + ret diff --git a/src/crt/float64_runtime.c b/src/crt/float64_runtime.c index a095012d7..b58c31da1 100644 --- a/src/crt/float64_runtime.c +++ b/src/crt/float64_runtime.c @@ -99,7 +99,7 @@ long double _drem_c(long double x, const long double *y) { /* int _dcmp_c(const long double *x, const long double* y) */ //------------------------------------------------------------------------------ -// Convert from long double +// Conversion functions //------------------------------------------------------------------------------ float _dtof_c(long double x) { @@ -110,26 +110,14 @@ float _dtof_c(long double x) { return ret.flt; } -int32_t _dtol_c(long double x) { - F64_pun arg_x; - arg_x.flt = x; - return f64_to_i32_r_minMag(arg_x.soft, false); -} - -int64_t _dtoll_c(long double x) { - F64_pun arg_x; - arg_x.flt = x; - return f64_to_i64_r_minMag(arg_x.soft, false); -} - -uint32_t _dtoul_c(long double x) { - F64_pun arg_x; - arg_x.flt = x; - return f64_to_ui32_r_minMag(arg_x.soft, false); +long double _lltod_c(int64_t x) { + F64_pun ret; + ret.soft = i64_to_f64(x); + return ret.flt; } -uint64_t _dtoull_c(long double x) { - F64_pun arg_x; - arg_x.flt = x; - return f64_to_ui64_r_minMag(arg_x.soft, false); +long double _ulltod_c(uint64_t x) { + F64_pun ret; + ret.soft = ui64_to_f64(x); + return ret.flt; } diff --git a/src/crt/float64_runtime.src b/src/crt/float64_runtime.src index 48dd13fc6..1546600b3 100644 --- a/src/crt/float64_runtime.src +++ b/src/crt/float64_runtime.src @@ -3,7 +3,7 @@ section .text public __dadd, __dsub, __dmul, __ddiv, __drem - public __dtof, __dtol, __dtoll, __dtoul, __dtoull + public __lltod,__ulltod, __dtof ;------------------------------------------------------------------------------- ; Arithmetic functions @@ -60,7 +60,7 @@ __drem: ret ;------------------------------------------------------------------------------- -; Convert from long double +; Conversion functions ;------------------------------------------------------------------------------- __dtof: @@ -70,33 +70,19 @@ __dtof: pop af, af, af, iy, af ret -__dtol: - ; f64_ret_i32 +__lltod: + ; i64_ret_f64 push af, iy, bc, de, hl - call __dtol_c + call __lltod_c pop af, af, af, iy, af ret -__dtoll: - ; f64_ret_i64 +__ulltod: + ; u64_ret_f64 push af, iy, bc, de, hl - call __dtoll_c - pop af, af, af, iy, af - ret - -__dtoul: - ; f64_ret_u32 - push af, iy, bc, de, hl - call __dtoul_c - pop af, af, af, iy, af - ret - -__dtoull: - ; f64_ret_u64 - push af, iy, bc, de, hl - call __dtoull_c + call __ulltod_c pop af, af, af, iy, af ret extern __dadd_c, __dsub_c, __dmul_c, __ddiv_c, __drem_c - extern __dtof_c, __dtol_c, __dtoll_c, __dtoul_c, __dtoull_c + extern __dtof_c, __lltod_c, __ulltod_c diff --git a/src/crt/lltof.src b/src/crt/lltof.src index c99868c30..7904c8e75 100644 --- a/src/crt/lltof.src +++ b/src/crt/lltof.src @@ -2,7 +2,7 @@ section .text public __lltof -__lltod: +__lltof: push af, iy, bc, de, hl call __lltof_c pop af, af, af, iy, af diff --git a/src/crt/ltod.c b/src/crt/ltod.c index d46d1d95a..2025cec07 100644 --- a/src/crt/ltod.c +++ b/src/crt/ltod.c @@ -1,68 +1,39 @@ - -/*============================================================================ - -This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic -Package, Release 3e, by John R. Hauser. - -Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of -California. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions, and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions, and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - 3. Neither the name of the University nor the names of its contributors may - be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE -DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -=============================================================================*/ - #include #include -union ui64_f64 { uint64_t ui; long double f; }; - -#define packToF64UI( sign, exp, sig ) ((uint64_t) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<52) + (sig))) - -/** - * @remarks inlined version of `float64_t i32_to_f64(int32_t)` from - * `i32_to_f64.c` - */ -long double _ltod_c( int32_t a ) -{ - uint_fast64_t uiZ; - bool sign; - uint_fast32_t absA; - int_fast8_t shiftDist; - union ui64_f64 uZ; - - if ( ! a ) { - uiZ = 0; - } else { - sign = (a < 0); - absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; - shiftDist = __builtin_clzl( absA ) + 21; - uiZ = - packToF64UI( - sign, 0x432 - shiftDist, (uint_fast64_t) absA< #include -union ui64_f64 { uint64_t ui; long double f; }; - -#define packToF64UI( sign, exp, sig ) ((uint64_t) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<52) + (sig))) - -/** - * @remarks inlined version of `float64_t ui32_to_f64(int32_t)` from - * `ui32_to_f64.c` - */ -long double _ultod_c( uint32_t a ) -{ - uint_fast64_t uiZ; - int_fast8_t shiftDist; - union ui64_f64 uZ; - - if ( ! a ) { - uiZ = 0; - } else { - shiftDist = __builtin_clzl( a ) + 21; - uiZ = - packToF64UI( 0, 0x432 - shiftDist, (uint_fast64_t) a< - -typedef union F64_pun { - long double flt; - uint64_t bin; -} F64_pun; - -#define Float64_signbit UINT64_C(0x8000000000000000) -#define Float64_fabs_mask UINT64_C(0x7FFFFFFFFFFFFFFF) - -// Should be easy to implement in assembly -long double copysignl(long double x, long double y) { - F64_pun arg_x, arg_y; - arg_x.flt = x; - arg_y.flt = y; - // clear the signbit of x - arg_x.bin &= Float64_fabs_mask; - // copy the signbit of y - arg_x.bin ^= arg_y.bin & Float64_signbit; - return arg_x.flt; -} diff --git a/src/libc/copysign.src b/src/libc/copysign.src index d10a73f08..ca284b85f 100644 --- a/src/libc/copysign.src +++ b/src/libc/copysign.src @@ -1,6 +1,7 @@ assume adl=1 section .text + public _copysign, _copysignf _copysign: _copysignf: @@ -20,3 +21,16 @@ _copysignf: ld l,a ex de,hl ret + + public _copysignl +_copysignl: + ld hl, 19 ; upper 8 bits of y + add hl, sp + ld a, (hl) + ld de, -9 ; upper 8 bits of x + add hl, de + xor a, (hl) + and a, $80 + xor a, (hl) + ld (hl), a + ret diff --git a/src/libc/fabs.c b/src/libc/fabs.c deleted file mode 100644 index 2b7f71d91..000000000 --- a/src/libc/fabs.c +++ /dev/null @@ -1,20 +0,0 @@ -#include - -typedef union F64_pun { - long double flt; - uint64_t bin; -} F64_pun; - -#define Float64_fabs_mask UINT64_C(0x7FFFFFFFFFFFFFFF) - -// Should be easy to implement in assembly -long double fabsl(long double x) { - F64_pun ret; - ret.flt = x; - /** - * @remarks This can also be done by doing a leftshift to remove the - * signbit, and then doing a rightsift - */ - ret.bin &= Float64_fabs_mask; - return ret.flt; -} diff --git a/src/libc/fabs.src b/src/libc/fabs.src index 66f00a706..743864bfb 100644 --- a/src/libc/fabs.src +++ b/src/libc/fabs.src @@ -1,7 +1,7 @@ assume adl=1 section .text - public _fabs, _fabsf + public _fabs, _fabsf, _fabsl if PREFER_OS_LIBC @@ -10,15 +10,21 @@ _fabs := _fabsf else +; CC: 2 + 8F + 4R + 1W +; 8 bytes _fabs: _fabsf: - pop bc - pop hl - pop de - push de - push hl - push bc - res 7,e + ld hl, 6 + add hl, sp + res 7, (hl) ret end if + +; CC: 2 + 8F + 4R + 1W +; 8 bytes +_fabsl: + ld hl, 10 + add hl, sp + res 7, (hl) + ret diff --git a/src/libc/fpclassify.c b/src/libc/fpclassify.c deleted file mode 100644 index cddd315a5..000000000 --- a/src/libc/fpclassify.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -typedef union Float32_Bitwise { - float flt_part; - uint32_t u32_part; - uint24_t u24_part; -} Float32_Bitwise; - -#define Float32_Exponent_Mask INT32_C(0x7F800000) -#define Float32_Mantissa_Mask INT32_C(0x007FFFFF) - -int _fpclassifyf(float x) -{ - Float32_Bitwise x_bin; - x_bin.flt_part = x; - - const uint32_t exp_mask = x_bin.u32_part & Float32_Exponent_Mask; - - // Both of these compile to the same lto.src as of 2024-Oct-10 - #if 1 - uint24_t mantissa = x_bin.u24_part; - // bit 23 is part of the exponent, so it must be cleared - mantissa += mantissa; - #else - uint32_t mantissa = x_bin.u32_part & Float32_Mantissa_Mask; - #endif - - return ( - (exp_mask == 0) ? FP_ZERO : - (exp_mask == Float32_Exponent_Mask) ? FP_INFINITE : - FP_NORMAL - ) | (mantissa != 0); -} - -int _fpclassify(double) __attribute__((alias("_fpclassifyf"))); - -typedef union F64_pun { - long double flt; - uint64_t bin; -} F64_pun; - -#define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) -#define Float64_norm_min_lsh_1 UINT64_C(0x0020000000000000) - -int _fpclassifyl(long double x) { - F64_pun val; - val.flt = x; - // clears the signbit - val.bin <<= 1; - if (val.bin == 0) { - return FP_ZERO; - } - if (val.bin == Float64_inf_lsh_1) { - return FP_INFINITE; - } - // positive NaN is greater than positive infinity - if (val.bin > Float64_inf_lsh_1) { - return FP_NAN; - } - if (val.bin >= Float64_norm_min_lsh_1) { - return FP_NORMAL; - } - return FP_SUBNORMAL; -} diff --git a/src/libc/fpclassifyf.src b/src/libc/fpclassifyf.src new file mode 100644 index 000000000..a24343745 --- /dev/null +++ b/src/libc/fpclassifyf.src @@ -0,0 +1,29 @@ + assume adl=1 + + section .text + + public __fpclassifyf + +; FP_ZERO := 0 +; FP_INFINITE := 1 +; FP_SUBNORMAL := 2 +; FP_NAN := 3 +; FP_NORMAL := 4 + +; int _fpclassifyf(float) +__fpclassifyf: + pop bc, hl, de + push de, hl, bc + or a, a + adc hl, hl + jr z, .mant_zero ; normal, zero, or inf + ld hl, 2 + ; normal, subnormal, or NaN +.mant_zero: + rl e + ret z ; subnormal or zero + inc hl + inc e + ret z ; inf or NaN + ld l, 4 + ret ; normal diff --git a/src/libc/fpclassifyl.src b/src/libc/fpclassifyl.src new file mode 100644 index 000000000..35724d23b --- /dev/null +++ b/src/libc/fpclassifyl.src @@ -0,0 +1,38 @@ + assume adl=1 + + section .text + + public __fpclassifyl + +; FP_ZERO := 0 +; FP_INFINITE := 1 +; FP_SUBNORMAL := 2 +; FP_NAN := 3 +; FP_NORMAL := 4 + +; int _fpclassifyl(long double) +__fpclassifyl: + pop bc, hl, de + or a, a + adc hl, de + pop de + push bc, bc, bc, bc + ld a, e + jr nz, .mant_nonzero ; normal, subnormal, or NaN + jr c, .mant_nonzero ; normal, subnormal, or NaN + tst a, $0F + jr z, .mant_zero ; normal, zero, or inf +.mant_nonzero: + ; normal, subnormal, or NaN + ld hl, 2 +.mant_zero: + rra + and a, $78 + res 7, d + add a, d + ret z ; subnormal or zero + inc l + add a, -($78 + $7F) + ret z ; inf or NaN + ld l, 4 ; normal + ret diff --git a/src/libc/include/math.h b/src/libc/include/math.h index 2003f48eb..caf6a8365 100644 --- a/src/libc/include/math.h +++ b/src/libc/include/math.h @@ -10,6 +10,7 @@ extern "C" { #define HUGE_VALF __builtin_inff() #define HUGE_VAL __builtin_inf() +#define HUGE_VALL __builtin_infl() #define M_E 2.71828182845904523536 /* e */ #define M_LOG2E 1.44269504088896340736 /* log2(e) */ @@ -24,16 +25,16 @@ extern "C" { #define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ #define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ #define M_SQRT1_2 0.707106781186547524401 /* 1/sqrt(2) */ -#define M_LOG_2M_PI 1.83787706640934548 /* log2(M_PI) */ +#define M_LOG_2M_PI 1.83787706640934548 /* log(2*M_PI) */ #define FP_ILOGB0 (~__INT_MAX__) #define FP_ILOGBNAN __INT_MAX__ -#define FP_NORMAL 0x1 -#define FP_ZERO 0x2 -#define FP_SUBNORMAL (FP_NORMAL | FP_ZERO) /* 0x3 */ -#define FP_INFINITE 0x4 -#define FP_NAN (FP_NORMAL | FP_INFINITE) /* 0x5 */ +#define FP_ZERO 0x0 +#define FP_INFINITE 0x1 +#define FP_SUBNORMAL 0x2 +#define FP_NAN 0x3 +#define FP_NORMAL 0x4 #define signbit(x) __builtin_signbit(x) #define isgreater(x, y) __builtin_isgreater(x, y) diff --git a/src/libc/isfinite.c b/src/libc/isfinite.c deleted file mode 100644 index b61427c49..000000000 --- a/src/libc/isfinite.c +++ /dev/null @@ -1,17 +0,0 @@ -#include - -typedef union F64_pun { - long double flt; - uint64_t bin; -} F64_pun; - -#define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) - -int _isfinitel(long double x) { - F64_pun val; - val.flt = x; - // clears the signbit - val.bin <<= 1; - // Check if fabs(x) < infinity/NaN - return (val.bin < Float64_inf_lsh_1); -} diff --git a/src/libc/isfinitel.src b/src/libc/isfinitel.src new file mode 100644 index 000000000..1baaca0b1 --- /dev/null +++ b/src/libc/isfinitel.src @@ -0,0 +1,17 @@ + assume adl=1 + + section .text + + public __isfinitel + +; int _isfinitel(long double) +__isfinitel: + ld hl, 8 + add hl, sp + ld hl, (hl) ; load the upper 24bits + add hl, hl ; clears signbit + ld de, $2000 ; (1 << (5 + 8)) + add hl, de ; attempts to overflow the exponent + sbc hl, hl + inc hl + ret diff --git a/src/libc/isinf.c b/src/libc/isinf.c deleted file mode 100644 index 8ab98ee45..000000000 --- a/src/libc/isinf.c +++ /dev/null @@ -1,17 +0,0 @@ -#include - -typedef union F64_pun { - long double flt; - uint64_t bin; -} F64_pun; - -#define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) - -int _isinfl(long double x) { - F64_pun val; - val.flt = x; - // clears the signbit - val.bin <<= 1; - // Check if fabs(x) == infinity - return (val.bin == Float64_inf_lsh_1); -} diff --git a/src/libc/isinfl.src b/src/libc/isinfl.src new file mode 100644 index 000000000..b246440d0 --- /dev/null +++ b/src/libc/isinfl.src @@ -0,0 +1,39 @@ + assume adl=1 + + section .text + + public __isinfl + +; int _isinfl(long double) +__isinfl: + ; load upper 24bits + ld hl, 8 + add hl, sp + ld hl, (hl) + ; clear signbit + add hl, hl + or a, a + ld bc, $FFE000 + sbc hl, bc + jr z, .mantissa_check + ; finite and common NaN +.mant_non_zero: + or a, a + sbc hl, hl + ret + +.mantissa_check: + pop bc, hl, de + push de, hl, bc + ; __i40cmpzero + add hl, de + or a, a + sbc hl, de + jr nz, .mant_non_zero + ; hl was zero, so the carry flag cannot have been set + ex de, hl + sbc hl, de + jr nz, .mant_non_zero + ; both hl and de are zero + inc hl + ret diff --git a/src/libc/isnan.c b/src/libc/isnan.c deleted file mode 100644 index 4c9768c0d..000000000 --- a/src/libc/isnan.c +++ /dev/null @@ -1,17 +0,0 @@ -#include - -typedef union F64_pun { - long double flt; - uint64_t bin; -} F64_pun; - -#define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) - -int _isnanl(long double x) { - F64_pun val; - val.flt = x; - // clears the signbit - val.bin <<= 1; - // positive NaN is greater than positive infinity - return (val.bin > Float64_inf_lsh_1); -} diff --git a/src/libc/isnanf.src b/src/libc/isnanf.src index 54fcd7f35..d71f93d9c 100644 --- a/src/libc/isnanf.src +++ b/src/libc/isnanf.src @@ -1,7 +1,9 @@ assume adl=1 section .text + public __isnanf + __isnanf: ld iy,0 add iy,sp diff --git a/src/libc/isnanl.src b/src/libc/isnanl.src new file mode 100644 index 000000000..13e62beaf --- /dev/null +++ b/src/libc/isnanl.src @@ -0,0 +1,79 @@ + assume adl=1 + + section .text + + public __isnanl + +; adapted from fpclassify.src + +if 1 +; int _isnanl(long double) +__isnanl: + pop bc, hl, de + or a, a + adc hl, de + pop de + push bc, bc, bc, bc + ld a, e + jr nz, .mant_nonzero ; normal, subnormal, or NaN + jr c, .mant_nonzero ; normal, subnormal, or NaN + tst a, $0F + jr nz, .mant_nonzero ; normal, subnormal, or NaN + sbc hl, hl ; normal, or subnormal + ret +.mant_nonzero: + or a, a + sbc hl, hl + rra + and a, $78 + res 7, d + add a, d + ret z ; subnormal + inc l + add a, -($78 + $7F) + ret z ; NaN + dec l ; normal + ret + +else + +; int _isnanl(long double) +__isnanl: + ; load upper 24bits + ld hl, 8 + add hl, sp + ld hl, (hl) + ; clear signbit + add hl, hl + ; test for inf/NaN + ld de, $2000 + add hl, de + jr c, .exp_all_ones + sbc hl, hl + ret +.exp_all_ones: + ld a, h + and a, $1E ; most common NaN + jr nz, .upper_mantissa_nan + ; infinity or uncommon NaN + pop bc, hl, de + push de, hl, bc + ; __i48cmpzero + add hl, de + or a, a + sbc hl, de + jr nz, .lower_mantissa_nan + ex de, hl + ; hl was zero, so the carry flag cannot have been set + sbc hl, de + jr nz, .lower_mantissa_nan + ret ; infinity + +.lower_mantissa_nan: + or a, a +.upper_mantissa_nan: + sbc hl, hl + inc hl + ret + +end if diff --git a/src/libc/isnormal.c b/src/libc/isnormal.c deleted file mode 100644 index 99847b9ba..000000000 --- a/src/libc/isnormal.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -typedef union F32_pun { - float flt; - uint32_t bin; -} F32_pun; - -#define Float32_exp_mask INT32_C(0x7F800000) - -int _isnormalf(float x) -{ - F32_pun val; - val.flt = x; - val.bin &= Float32_exp_mask; - - // Check that the exponent isn't all zeros (subnormal) or all ones (nan/inf) - return (val.bin != 0 && val.bin != Float32_exp_mask); -} - -int _isnormal(double) __attribute__((alias("_isnormalf"))); - -typedef union F64_pun { - long double flt; - uint64_t bin; -} F64_pun; - -#define Float64_exp_mask UINT64_C(0x7FF0000000000000) - -int _isnormall(long double x) -{ - F64_pun val; - val.flt = x; - val.bin &= Float64_exp_mask; - - // Check that the exponent isn't all zeros (subnormal) or all ones (nan/inf) - return (val.bin != 0 && val.bin != Float64_exp_mask); -} diff --git a/src/libc/isnormalf.src b/src/libc/isnormalf.src new file mode 100644 index 000000000..a9aad813d --- /dev/null +++ b/src/libc/isnormalf.src @@ -0,0 +1,18 @@ + assume adl=1 + + section .text + + public __isnormalf + +; int _isnormalf(float) +__isnormalf: + ld hl, 5 + add hl, sp + ld hl, (hl) + add hl, hl ; clears signbit + ld a, h + dec a + cp a, -2 ; overflows on zero/denormal/inf/NaN exponents + sbc hl, hl ; hl is -1 or 0 + inc hl ; hl is 0 or 1 + ret diff --git a/src/libc/isnormall.src b/src/libc/isnormall.src new file mode 100644 index 000000000..b907190e0 --- /dev/null +++ b/src/libc/isnormall.src @@ -0,0 +1,29 @@ + assume adl=1 + + section .text + + public __isnormall + +; int _isnormall(long double) +__isnormall: + ; load upper 24bits + ld hl, 8 + add hl, sp + ld hl, (hl) + ; clear signbit + add hl, hl + ; test for inf/NaN + ld de, $2000 + add hl, de + jr c, .exp_all_ones + ; double de + ld d, $40 + ; test for zero/subnormal + sbc hl, de + jr c, .exp_all_zero + +.exp_all_ones: +.exp_all_zero: + sbc hl, hl + inc hl + ret diff --git a/src/libc/issubnormal.c b/src/libc/issubnormal.c deleted file mode 100644 index 0b73e355b..000000000 --- a/src/libc/issubnormal.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -typedef union F32_pun { - float flt; - uint32_t bin; -} F32_pun; - -#define Float32_exp_mask UINT32_C(0x7F800000) - -int _issubnormalf(float x) { - // zero is not a subnormal number - if (iszero(x)) { - return false; - } - F32_pun val; - val.flt = x; - val.bin &= Float32_exp_mask; - // check if the exponent is all zeros - return (val.bin == 0); -} - -int _issubnormal(double) __attribute__((alias("_issubnormalf"))); - -typedef union F64_pun { - long double flt; - uint64_t bin; -} F64_pun; - -#define Float64_exp_mask UINT64_C(0x7FF0000000000000) - -int _issubnormall(long double x) { - // zero is not a subnormal number - if (iszero(x)) { - return false; - } - F64_pun val; - val.flt = x; - val.bin &= Float64_exp_mask; - // check if the exponent is all zeros - return (val.bin == 0); -} diff --git a/src/libc/issubnormalf.src b/src/libc/issubnormalf.src new file mode 100644 index 000000000..c2bf4416d --- /dev/null +++ b/src/libc/issubnormalf.src @@ -0,0 +1,19 @@ + assume adl=1 + + section .text + + public __issubnormalf + +; int _issubnormalf(float) +__issubnormalf: + pop bc, hl, de + push de, hl, bc + or a, a + adc hl, hl + ret z ; zero mantissa is not subnormal + ld a, e + adc a, a + ret z ; zero exponent is subnormal + or a, a + sbc hl, hl + ret diff --git a/src/libc/issubnormall.src b/src/libc/issubnormall.src new file mode 100644 index 000000000..c9b65caa3 --- /dev/null +++ b/src/libc/issubnormall.src @@ -0,0 +1,79 @@ + assume adl=1 + + section .text + + public __issubnormall + + + +if 0 + +; int _fpclassifyl(long double) +__fpclassifyl: + pop bc, hl, de + or a, a + adc hl, de + pop de + push bc, bc, bc, bc + ld a, e + jr nz, .mant_nonzero ; normal, subnormal, or NaN + jr c, .mant_nonzero ; normal, subnormal, or NaN + tst a, $0F + jr z, .mant_zero ; normal, zero, or inf +.mant_nonzero: + ; normal, subnormal, or NaN + ld hl, 2 +.mant_zero: + rra + and a, $78 + res 7, d + add a, d + ret z ; subnormal or zero + inc l + add a, -($78 + $7F) + ret z ; inf or NaN + ld l, 4 ; normal + ret + +else + +; int _issubnormall(long double) +__issubnormall: + pop iy, de, hl, bc + push bc, hl, de, iy + + ld a, b ; upper 8bits of the exponent + add a, a + jr z, .upper_exp_all_zero + ; most common path + or a, a +.exp_non_zero: + sbc hl, hl + ret + +; normal, zero, or subnormal +.upper_exp_all_zero: + ld a, c ; lower 8bits of the exponent + tst a, $F0 + jr nz, .exp_non_zero + and a, $0F + jr nz, .upper_mant_non_zero + + ; __i48cmpzero + add hl, de + or a, a + sbc hl, de + jr nz, .mant_non_zero + ex de, hl + ; hl was zero, so the carry flag cannot have been set + sbc hl, de + jr nz, .mant_non_zero + ret +.mant_non_zero: + or a, a +.upper_mant_non_zero: + sbc hl, hl + inc hl + ret + +end if \ No newline at end of file diff --git a/src/libc/iszero.c b/src/libc/iszero.c deleted file mode 100644 index 108bda718..000000000 --- a/src/libc/iszero.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - -typedef union F32_pun { - float flt; - uint32_t bin; -} F32_pun; - -int _iszerof(float x) { - F32_pun val; - val.flt = x; - // clears the signbit - val.bin <<= 1; - return (val.bin == 0); -} - -int _iszero(double) __attribute__((alias("_iszerof"))); - -typedef union F64_pun { - long double flt; - uint64_t bin; -} F64_pun; - -int _iszerol(long double x) { - F64_pun val; - val.flt = x; - // clears the signbit - val.bin <<= 1; - return (val.bin == 0); -} diff --git a/src/libc/iszerof.src b/src/libc/iszerof.src new file mode 100644 index 000000000..165c86d45 --- /dev/null +++ b/src/libc/iszerof.src @@ -0,0 +1,20 @@ + assume adl=1 + + section .text + + public __iszerof + +; int iszerof(float) +__iszerof: + pop bc, hl, de + push de, hl, bc + add hl, hl + jr nz, .not_zero_f32 + rl e + jr nz, .not_zero_f32 + inc hl + ret +.not_zero_f32: + or a, a + sbc hl, hl + ret diff --git a/src/libc/iszerol.src b/src/libc/iszerol.src new file mode 100644 index 000000000..4db2f3175 --- /dev/null +++ b/src/libc/iszerol.src @@ -0,0 +1,34 @@ + assume adl=1 + + section .text + + public __iszerol + +; int iszerol(long double) +__iszerol: + pop iy, de, hl, bc + push bc, hl, de, iy + ; normal, inf, and NaN have non-zero exponents + ld a, b + add a, a ; clears the signbit + or a, c + jr z, .exp_zero_f64 + sbc hl, hl + ret +.exp_zero_f64: + ; __i48cmpzero + add hl, de + or a, a + sbc hl, de + jr nz, .mant_non_zero_f64 + ex de, hl + ; hl was zero, so the carry flag cannot have been set + sbc hl, de + jr nz, .mant_non_zero_f64 + inc hl + ret + +.mant_non_zero_f64: + or a, a + sbc hl, hl + ret diff --git a/src/softfloat/include/opts-GCC.h b/src/softfloat/include/opts-GCC.h index 192cb58ca..82376ece3 100644 --- a/src/softfloat/include/opts-GCC.h +++ b/src/softfloat/include/opts-GCC.h @@ -45,11 +45,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef SOFTFLOAT_BUILTIN_CLZ INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ) - { return a ? __builtin_clz( a ) - 16 : 16; } + { return a ? __builtin_clz( a ) - (sizeof(int) * 8 - 16) : 16; } #define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16 INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) - { return a ? __builtin_clz( a ) : 32; } + { return a ? __builtin_clzl( a ) : 32; } #define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 INLINE uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ) From d52cc0c6b5109225d966c23b03623b3826f682eb Mon Sep 17 00:00:00 2001 From: ZERICO2005 <71151164+ZERICO2005@users.noreply.github.com> Date: Tue, 21 Jan 2025 21:41:24 -0700 Subject: [PATCH 6/7] added C++20 numbers, merged ultod and ltod, along with some float64 math.h functions --- src/crt/dcmp.c | 18 +-- src/crt/ftod.c | 28 ++-- src/crt/ftod.src | 16 ++- src/crt/ltod.c | 48 ++++--- src/crt/ltod.src | 37 ++++- src/crt/ultod.c | 36 ----- src/crt/ultod.src | 15 -- src/libc/fdim.c | 17 ++- src/libc/fmax.c | 24 +++- src/libc/fmin.c | 24 +++- src/libc/include/stdlib.h | 3 + src/libc/logb.c | 26 +++- src/libc/nan.c | 10 ++ src/libc/strtold.c | 284 +++++++++++++++++++++++++++++++++++++ src/libcxx/include/cmath | 18 +-- src/libcxx/include/cstdlib | 1 + src/libcxx/include/numbers | 137 ++++++++++++++++++ 17 files changed, 617 insertions(+), 125 deletions(-) delete mode 100644 src/crt/ultod.c delete mode 100644 src/crt/ultod.src create mode 100644 src/libc/strtold.c create mode 100644 src/libcxx/include/numbers diff --git a/src/crt/dcmp.c b/src/crt/dcmp.c index 3f6faaa7e..f988615d2 100644 --- a/src/crt/dcmp.c +++ b/src/crt/dcmp.c @@ -9,21 +9,17 @@ typedef union F64_pun { #define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) -#define F64_CMP_EQUAL 0 -#define F64_CMP_LESS -1 -#define F64_CMP_GREATER 1 -#define F64_CMP_UNORDERED 1 +#define F64_CMP_EQUAL 0 /* sets the Z flag */ +#define F64_CMP_LESS -1 /* sets the S flag */ +#define F64_CMP_GREATER 1 /* doesn't trigger flags */ +#define F64_CMP_UNORDERED 1 /* doesn't trigger flags */ // assumes no NaN -int _dcmp_c(const long double* x, const long double *y) { - F64_pun arg_x, arg_y; +int _dcmp_c(const long double * x, const long double * y) { + F64_pun arg_x, arg_y; arg_x.flt = *x; arg_y.flt = *y; - // if (isunordered(x, y)) { - // return F64_CMP_UNORDERED; - // } - bool x_sign = signbit(*x); bool y_sign = signbit(*y); if (x_sign != y_sign) { @@ -32,7 +28,7 @@ int _dcmp_c(const long double* x, const long double *y) { } return (x_sign ? F64_CMP_LESS : F64_CMP_GREATER); } - + if (arg_x.bin == arg_y.bin) { return F64_CMP_EQUAL; } diff --git a/src/crt/ftod.c b/src/crt/ftod.c index 9c89d6dd7..c9afe48d0 100644 --- a/src/crt/ftod.c +++ b/src/crt/ftod.c @@ -27,6 +27,8 @@ typedef union F64_pun { #define Float64_pos_nan UINT64_C(0x7FF8000000000000) #define Float64_neg_nan UINT64_C(0xFFF8000000000000) +#define Float32_pos_inf UINT32_C(0x7F800000) + #define Float64_mant_bits 52 #define Float32_mant_bits 23 #define Float64_expon_bits 11 @@ -34,8 +36,10 @@ typedef union F64_pun { #define Float64_bias 1023 #define Float32_bias 127 +/** + * @note x must be positive + */ long double _ftod_c(float x) { - bool x_sign = signbit(x); F32_pun val; F64_pun ret; val.flt = x; @@ -44,8 +48,7 @@ long double _ftod_c(float x) { if (isnormal(val.flt)) { uint24_t mantissa = val.split.mant; uint24_t expon = - (val.split.expon + ((Float64_bias - Float32_bias) >> 1)) + - (x_sign ? (((1 << Float64_expon_bits) - (1 << Float32_expon_bits)) >> 1) : (0)); + (val.split.expon + ((Float64_bias - Float32_bias) >> 1)); ret.u24.hi = expon; ret.u24.lo = mantissa; // mantissa[0, 22] exponent[23, 33] signbit[34] @@ -66,10 +69,7 @@ long double _ftod_c(float x) { */ mantissa += (clz_result & 0x1) ? 0x800000 : 0x000000; - uint24_t expon = - (((Float64_bias - Float32_bias) >> 1) - - (clz_result >> 1)) + - (x_sign ? ((1 << Float64_expon_bits) >> 1) : 0); + uint24_t expon = ((Float64_bias - Float32_bias) >> 1) - (clz_result >> 1); ret.u24.hi = expon; ret.u24.lo = mantissa; @@ -77,15 +77,15 @@ long double _ftod_c(float x) { ret.bin <<= Float64_mant_bits - Float32_mant_bits; return ret.flt; } - if (iszero(val.flt)) { - ret.bin = x_sign ? Float64_neg_zero : Float64_pos_zero; - return ret.flt; + /* iszero(val.flt) */ + if (val.bin == 0) { + return 0.0L; } - if (isinf(val.flt)) { - ret.bin = x_sign ? Float64_neg_inf : Float64_pos_inf; - return ret.flt; + /* isinf(val.flt) */ + if (val.bin == Float32_pos_inf) { + return HUGE_VALL; } /* isnan(val.flt) */ - ret.bin = x_sign ? Float64_neg_nan : Float64_pos_nan; + ret.bin = Float64_pos_nan; return ret.flt; } diff --git a/src/crt/ftod.src b/src/crt/ftod.src index 9f9413e8a..be7150a90 100644 --- a/src/crt/ftod.src +++ b/src/crt/ftod.src @@ -7,9 +7,21 @@ __ftod: ; f32_ret_f64 ld d, a - push iy, de, hl + push iy + bit 7, e + jr nz, .negative_arg + ; positive + push de, hl call __ftod_c pop af, af, iy ret +.negative_arg: + ; return -_ftod_c(fabsf(x)) + res 7, e + push de, hl + call __ftod_c + set 7, b + pop af, af, iy + ret -extern __ftod_c \ No newline at end of file +extern __ftod_c diff --git a/src/crt/ltod.c b/src/crt/ltod.c index 2025cec07..4d850795f 100644 --- a/src/crt/ltod.c +++ b/src/crt/ltod.c @@ -1,4 +1,5 @@ #include +#include #include typedef union F64_pun { @@ -7,33 +8,40 @@ typedef union F64_pun { struct { uint16_t low16; uint32_t mid32; - uint16_t exp16; + uint16_t exp16; } split; } F64_pun; #define Float64_bias 1023 #define Float64_mant_bits 52 -#define Float64_expon_bits 11 #define uint32_max_exp 31 #define uint48_bits 48 +long double _ultod_c(uint32_t x) { + if (x == 0) { + return 0.0L; + } + F64_pun ret; + uint8_t clz_result = __builtin_clzl(x); + // clears the MSB since the float will be normalized + x <<= clz_result + 1; /* shift by 32 is UB */ + + ret.split.low16 = 0; + ret.split.mid32 = x; + ret.split.exp16 = Float64_bias + (uint32_max_exp - clz_result); + + ret.bin <<= Float64_mant_bits - uint48_bits; + + return ret.flt; +} + +#if 0 + +/* implemented in assembly */ long double _ltod_c(int32_t x) { - if (x == 0) { - return 0.0L; - } - F64_pun ret; - bool x_sign = (x < 0); - uint32_t val = (uint32_t)(x_sign ? -x : x); - unsigned clz_result = __builtin_clzl(val); - // clears the MSB since the float will be normalized - val <<= clz_result + 1; - - ret.split.low16 = 0; - ret.split.mid32 = val; - ret.split.exp16 = - Float64_bias + (uint32_max_exp - clz_result) + (x_sign ? (1 << Float64_expon_bits) : 0); - - ret.bin <<= Float64_mant_bits - uint48_bits; - - return ret.flt; + bool x_sign = (x < 0); + long double ret = _ultod_c((uint32_t)labs(x)); + return x_sign ? -ret : ret; } + +#endif diff --git a/src/crt/ltod.src b/src/crt/ltod.src index 7c5c87d57..3e10dc5cb 100644 --- a/src/crt/ltod.src +++ b/src/crt/ltod.src @@ -2,14 +2,43 @@ section .text - public __ltod + public __ultod, __ltod +; public __utod, __itod + +; __utod: +; ; u24_ret_f64 +; ld e, 0 +__ultod: + ; u32_ret_f64 + ld d, a +.ultod_skip: + push iy, de, hl + call __ultod_c + pop af, af, iy + ret + +; __itod: +; ; i24_ret_f64 +; ld d, a +; push hl +; add hl, hl +; sbc a, a +; ld e, a +; pop hl +; jr .ltod_skip __ltod: ; i32_ret_f64 ld d, a + bit 7, e +.ltod_skip: + jr z, .ultod_skip ; positive argument + ; return -_ultod_c(labs(x)) + call __lneg push iy, de, hl - call __ltod_c + call __ultod_c + set 7, b ; negative result pop af, af, iy ret - - extern __ltod_c + + extern __ultod_c, __lneg diff --git a/src/crt/ultod.c b/src/crt/ultod.c deleted file mode 100644 index 93fabc511..000000000 --- a/src/crt/ultod.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -typedef union F64_pun { - long double flt; - uint64_t bin; - struct { - uint16_t low16; - uint32_t mid32; - uint16_t exp16; - } split; -} F64_pun; - -#define Float64_bias 1023 -#define Float64_mant_bits 52 -#define uint32_max_exp 31 -#define uint48_bits 48 - -long double _ultod_c(uint32_t x) { - if (x == 0) { - return 0.0L; - } - F64_pun ret; - uint32_t val = (uint32_t)(x); - unsigned clz_result = __builtin_clzl(val); - // clears the MSB since the float will be normalized - val <<= clz_result + 1; - - ret.split.low16 = 0; - ret.split.mid32 = val; - ret.split.exp16 = Float64_bias + (uint32_max_exp - clz_result); - - ret.bin <<= Float64_mant_bits - uint48_bits; - - return ret.flt; -} diff --git a/src/crt/ultod.src b/src/crt/ultod.src deleted file mode 100644 index 870049998..000000000 --- a/src/crt/ultod.src +++ /dev/null @@ -1,15 +0,0 @@ - assume adl=1 - - section .text - - public __ultod - -__ultod: - ; u32_ret_f64 - ld d, a - push iy, de, hl - call __ultod_c - pop af, af, iy - ret - - extern __ultod_c diff --git a/src/libc/fdim.c b/src/libc/fdim.c index 43822ed7a..c110ba811 100644 --- a/src/libc/fdim.c +++ b/src/libc/fdim.c @@ -1,8 +1,19 @@ #include -float fdimf(float x, float y) -{ - return fmaxf(x - y, 0); +float fdimf(float x, float y) { + /** + * returns `x - y` when `x > y` or if one of the arguments is NaN. + * Otherwise returns positive zero. + */ + return islessequal(x, y) ? 0.0f : (x - y); } double fdim(double, double) __attribute__((alias("fdimf"))); + +long double fdiml(long double x, long double y) { + /** + * returns `x - y` when `x > y` or if one of the arguments is NaN. + * Otherwise returns positive zero. + */ + return islessequal(x, y) ? 0.0L : (x - y); +} diff --git a/src/libc/fmax.c b/src/libc/fmax.c index b8267c34a..256d7901c 100644 --- a/src/libc/fmax.c +++ b/src/libc/fmax.c @@ -1,9 +1,25 @@ #include -float fmaxf(float x, float y) -{ - if (x != y) return x < y ? y : x; - return signbit(x) || isnan(x) ? y : x; +float fmaxf(float x, float y) { + return + isless(x, y) ? y : + isless(y, x) ? x : + /* attempts to return a non-NaN value */ + isnan(x) ? y : + isnan(y) ? x : + /* arguments are equal or signed zero */ + signbit(x) ? y : x; } double fmax(double, double) __attribute__((alias("fmaxf"))); + +long double fmaxl(long double x, long double y) { + return + isless(x, y) ? y : + isless(y, x) ? x : + /* attempts to return a non-NaN value */ + isnan(x) ? y : + isnan(y) ? x : + /* arguments are equal or signed zero */ + signbit(x) ? y : x; +} diff --git a/src/libc/fmin.c b/src/libc/fmin.c index 8db439107..7ba5a084b 100644 --- a/src/libc/fmin.c +++ b/src/libc/fmin.c @@ -1,9 +1,25 @@ #include -float fminf(float x, float y) -{ - if (x != y) return x < y ? x : y; - return !signbit(x) || isnan(x) ? y : x; +float fminf(float x, float y) { + return + isless(x, y) ? x : + isless(y, x) ? y : + /* attempts to return a non-NaN value */ + isnan(x) ? y : + isnan(y) ? x : + /* arguments are equal or signed zero */ + signbit(x) ? x : y; } double fmin(double, double) __attribute__((alias("fminf"))); + +long double fminl(long double x, long double y) { + return + isless(x, y) ? x : + isless(y, x) ? y : + /* attempts to return a non-NaN value */ + isnan(x) ? y : + isnan(y) ? x : + /* arguments are equal or signed zero */ + signbit(x) ? x : y; +} diff --git a/src/libc/include/stdlib.h b/src/libc/include/stdlib.h index e9a942463..9ca7d4c94 100644 --- a/src/libc/include/stdlib.h +++ b/src/libc/include/stdlib.h @@ -49,6 +49,9 @@ float strtof(const char *__restrict nptr, double strtod(const char *__restrict nptr, char **__restrict endptr) __attribute__((nonnull(1))); +long double strtold(const char *__restrict nptr, + char **__restrict endptr) __attribute__((nonnull(1))); + long strtol(const char *__restrict nptr, char **__restrict endptr, int base) __attribute__((nonnull(1))); diff --git a/src/libc/logb.c b/src/libc/logb.c index b682b8784..96d07789e 100644 --- a/src/libc/logb.c +++ b/src/libc/logb.c @@ -1,8 +1,28 @@ +#include #include -float logbf(float x) -{ - return floorf(log2f(x)); +float logbf(float x) { + if (isfinite(x)) { + if (iszero(x)) { + feraiseexcept(FE_DIVBYZERO); + return -HUGE_VALF; + } + return (float)ilogbf(x); + } + // infinity and NaN + return fabsf(x); } double logb(double) __attribute__((alias("logbf"))); + +long double logbl(long double x) { + if (isfinite(x)) { + if (iszero(x)) { + feraiseexcept(FE_DIVBYZERO); + return -HUGE_VALL; + } + return (long double)ilogbl(x); + } + // infinity and NaN + return fabsl(x); +} diff --git a/src/libc/nan.c b/src/libc/nan.c index 82c911e23..c9a82a13c 100644 --- a/src/libc/nan.c +++ b/src/libc/nan.c @@ -10,3 +10,13 @@ float nanf(const char *tag) } double nan(const char *) __attribute__((alias("nanf"))); + +#define Float64_nan_mask UINT64_C(0x0007FFFFFFFFFFFF) +#define Float64_pos_nan UINT64_C(0x7FF8000000000000) + +long double nanl(const char *tag) +{ + return (union { uint64_t u; long double f; }) { + .u = (strtoll(tag, NULL, 0) & Float64_nan_mask) | Float64_pos_nan, + }.f; +} diff --git a/src/libc/strtold.c b/src/libc/strtold.c new file mode 100644 index 000000000..fa4a2e2bb --- /dev/null +++ b/src/libc/strtold.c @@ -0,0 +1,284 @@ +#if 1 + +/************************************************************************/ +/* */ +/* Copyright (C)1987-2008 by */ +/* Zilog, Inc. */ +/* */ +/* San Jose, California */ +/* */ +/************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +/************************************************* +* +* strtold - string to long double conversion +* +* Inputs: +* str - pointer to the character string +* endptr - pointer to pointer to char to +* put address of first char past +* the end of the string -- or NULL +* Returns: +* the value of the number +* +*************************************************/ +long double strtold(const char *__restrict nptr, char **__restrict endptr) +{ + F64_pun val; + int frac = 0; + int exp = 0; + int8_t sign = 1; + int8_t exp_sign = 1; + const char *str = (const char*)nptr; + + while (isspace(*str)) { + ++str; + } + + if (*str == '-') { + sign = -1; + ++str; + } + else if (*str == '+') { + ++str; + } + + val.flt = 0.0L; + while (isdigit(*str)) { + val.flt = val.flt * 10.0L + (*str - '0'); + ++str; + } + + if (*str == '.') { + ++str; + while (isdigit(*str)) { + val.flt = val.flt * 10.0L + (*str - '0'); + ++frac; + ++str; + } + } + + if (*str == 'e' || *str == 'E') { + ++str; + if (*str == '-') { + exp_sign = -1; + ++str; + } + else if (*str == '+') { + exp_sign = 1; + ++str; + } + while (isdigit(*str)) { + exp = exp * 10 + (*str - '0'); + ++str; + } + } + + if (endptr) { + *endptr = (char*)str; + } + + if (exp_sign < 0 ) { + exp = -exp; + } + exp -= frac; + if (val.bin != 0) + { + while (exp > 0 ) + { + val.flt *= 10.0L; + if (!isfinite(val.flt)) + { + errno = ERANGE; + val.flt = HUGE_VALL; + break; + } + --exp; + } + while (exp < 0 ) + { + val.flt /= 10.0L; + if (val.bin == 0) + { + errno = ERANGE; + break; + } + ++exp; + } + if (sign < 0 ) { + val.flt = -val.flt; + } + } + return val.flt; +} + +#else + +/* unfinished routine */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef union F64_pun { + long double flt; + uint64_t bin; +} F64_pun; + +#define INF_TEXT (('i' << 0) | ('n' << 8) | ('f' << 16)) +#define NAN_TEXT (('n' << 0) | ('a' << 8) | ('n' << 16)) + +#define Float64_pos_nan UINT64_C(0x7FF8000000000000) + +long double strtold(const char *__restrict nPtr, char **__restrict endPtr) { + const char* str = nPtr; + while(isspace(*str)) { + str++; + } + bool negative_sign = (*str == '-'); + if (*str == '+' || *str == '-') { + str++; + } + + // converts to lowercase via a bitwise OR + uint24_t text_compare = *((const uint24_t*)((const void*)str)) | 0x202020; + if (text_compare == INF_TEXT) { + str += 3; + *endPtr = (char*)str; + long double ret = HUGE_VALL; + return negative_sign ? -ret : ret; + } + if (text_compare == NAN_TEXT) { + str += 3; + *endPtr = (char*)str; + F64_pun ret; + ret.bin = Float64_pos_nan; + return negative_sign ? -ret.flt : ret.flt; + } + while (*str == '0') { + str++; + } + /* insert hexadecimal float here */ + bool u64_overflow = false; + long double ret = 0.0L; + { + uint64_t int_part = 0; + uint8_t digit_count = 0; + while (isdigit(*str)) { + int_part *= 10; + int_part += *str - '0'; + str++; + digit_count++; + if (digit_count >= 19) { + // 9'999'999'999'999'999'999 + u64_overflow = true; + break; + } + } + ret = (long double)int_part; + } + if (u64_overflow) { + /** + * we already read at least 59.7 bits of precision, which is more + * than enough for rounding purposes. Skip the rest of the digits. + */ + while (isdigit(*str)) { + #if 0 + #ifdef FP_FAST_FMAL + ret = fmal(ret, 10.0L, (long double)(*str - '0')); + #else + ret *= 10.0L; + ret += (long double)(*str - '0'); + #endif + #else + ret *= 10.0L; + #endif + str++; + } + if (!isfinite(ret)) { + long double ret = HUGE_VALL; + } + if (*str == '.') { + str++; + } + while (isdigit(*str)) { + str++; + } + } else if (*str == '.') { + str++; + uint64_t frac_part = 0; + bool decimal_overflow = false; + uint8_t digit_count = 0; + while (isdigit(*str)) { + frac_part *= 10; + frac_part += *str - '0'; + str++; + digit_count++; + if (digit_count >= 19) { + // 9'999'999'999'999'999'999 + decimal_overflow = true; + break; + } + } + long double decimal_part = (long double)frac_part; + while (digit_count --> 0) { + decimal_part /= 10.0L; + } + if (decimal_overflow) { + while (isdigit(*str)) { + str++; + } + } + } + if (*str == 'E' || *str == 'e') { + bool expon_sign = false; + if (*str == '-') { + expon_sign = true; + } + if (*str == '+' || *str == '-') { + str++; + } + while (*str == '0') { + str++; + } + uint24_t expon = 0; + expon += *str - '0'; str++; + if (isdigit(*str)) { + expon *= 10; + expon += *str - '0'; str++; + } + if (isdigit(*str)) { + expon *= 10; + expon += *str - '0'; str++; + } + // LDBL_MAX / LDBL_TRUE_MIN == around 10^630 + if (isdigit(*str)) { + ret = expon_sign ? 0.0L : HUGE_VALL; + goto final_ret; + } + } + final_ret: + *endPtr = (char*)str; + return negative_sign ? -ret : ret; +} + +#endif diff --git a/src/libcxx/include/cmath b/src/libcxx/include/cmath index bc5638692..8639a61e8 100644 --- a/src/libcxx/include/cmath +++ b/src/libcxx/include/cmath @@ -351,9 +351,9 @@ nextafter(_Tp __x, _Up __y) { return nextafter(__x, __y); } using ::nextup; using ::nextupf; using ::nextupl; -inline constexpr float nextup(float __x) { return nextupf(__x); } -inline constexpr long double nextup(long double __x) { return nextupl(__x); } -template inline constexpr enable_if_t, double> +inline float nextup(float __x) { return nextupf(__x); } +inline long double nextup(long double __x) { return nextupl(__x); } +template inline enable_if_t, double> nextup(_Tp __x) { return nextup(__x); } using ::nexttoward; @@ -368,9 +368,9 @@ nexttoward(_Tp __x, _Up __y) { return nexttoward(__x, __y); } using ::nextdown; using ::nextdownf; using ::nextdownl; -inline constexpr float nextdown(float __x) { return nextdownf(__x); } -inline constexpr long double nextdown(long double __x) { return nextdownl(__x); } -template inline constexpr enable_if_t, double> +inline float nextdown(float __x) { return nextdownf(__x); } +inline long double nextdown(long double __x) { return nextdownl(__x); } +template inline enable_if_t, double> nextdown(_Tp __x) { return nextdown(__x); } using ::pow; @@ -419,9 +419,9 @@ round(_Tp __x) { return round(__x); } using ::roundeven; using ::roundevenf; using ::roundevenl; -inline constexpr float roundeven(float __x) { return roundevenf(__x); } -inline constexpr long double roundeven(long double __x) { return roundevenl(__x); } -template inline constexpr enable_if_t, double> +inline float roundeven(float __x) { return roundevenf(__x); } +inline long double roundeven(long double __x) { return roundevenl(__x); } +template inline enable_if_t, double> roundeven(_Tp __x) { return roundeven(__x); } using ::scalbln; diff --git a/src/libcxx/include/cstdlib b/src/libcxx/include/cstdlib index bc43af6ff..72f756480 100644 --- a/src/libcxx/include/cstdlib +++ b/src/libcxx/include/cstdlib @@ -18,6 +18,7 @@ using ::atol; using ::atoll; using ::strtof; using ::strtod; +using ::strtold; using ::strtol; using ::strtoll; using ::strtoul; diff --git a/src/libcxx/include/numbers b/src/libcxx/include/numbers new file mode 100644 index 000000000..134c3194f --- /dev/null +++ b/src/libcxx/include/numbers @@ -0,0 +1,137 @@ +// -*- C++ -*- +#ifndef _EZCXX_NUMBERS +#define _EZCXX_NUMBERS + +#include + +#if __cplusplus >= 201907L + #include +#endif + +#pragma clang system_header + +namespace std { + +namespace numbers { + +#if __cplusplus >= 201907L + +// implemented with C++20 + +template +inline constexpr bool __false = false; + +template +struct __illformed { + static_assert( + __false<_Tp>, + "A program that instantiates a primary template of a mathematical constant variable template is ill-formed." + ); +}; + +template +inline constexpr _Tp e_v = __illformed<_Tp>{}; +template +inline constexpr _Tp log2e_v = __illformed<_Tp>{}; +template +inline constexpr _Tp log10e_v = __illformed<_Tp>{}; +template +inline constexpr _Tp pi_v = __illformed<_Tp>{}; +template +inline constexpr _Tp inv_pi_v = __illformed<_Tp>{}; +template +inline constexpr _Tp inv_sqrtpi_v = __illformed<_Tp>{}; +template +inline constexpr _Tp ln2_v = __illformed<_Tp>{}; +template +inline constexpr _Tp ln10_v = __illformed<_Tp>{}; +template +inline constexpr _Tp sqrt2_v = __illformed<_Tp>{}; +template +inline constexpr _Tp sqrt3_v = __illformed<_Tp>{}; +template +inline constexpr _Tp inv_sqrt3_v = __illformed<_Tp>{}; +template +inline constexpr _Tp egamma_v = __illformed<_Tp>{}; +template +inline constexpr _Tp phi_v = __illformed<_Tp>{}; + +template +inline constexpr _Tp e_v<_Tp> = 2.718281828459045235360287471352662L; +template +inline constexpr _Tp log2e_v<_Tp> = 1.442695040888963407359924681001892L; +template +inline constexpr _Tp log10e_v<_Tp> = 0.434294481903251827651128918916605L; +template +inline constexpr _Tp pi_v<_Tp> = 3.141592653589793238462643383279502L; +template +inline constexpr _Tp inv_pi_v<_Tp> = 0.318309886183790671537767526745028L; +template +inline constexpr _Tp inv_sqrtpi_v<_Tp> = 0.564189583547756286948079451560772L; +template +inline constexpr _Tp ln2_v<_Tp> = 0.693147180559945309417232121458176L; +template +inline constexpr _Tp ln10_v<_Tp> = 2.302585092994045684017991454684364L; +template +inline constexpr _Tp sqrt2_v<_Tp> = 1.414213562373095048801688724209698L; +template +inline constexpr _Tp sqrt3_v<_Tp> = 1.732050807568877293527446341505872L; +template +inline constexpr _Tp inv_sqrt3_v<_Tp> = 0.577350269189625764509148780501957L; +template +inline constexpr _Tp egamma_v<_Tp> = 0.577215664901532860606512090082402L; +template +inline constexpr _Tp phi_v<_Tp> = 1.618033988749894848204586834365638L; + +#else + +// backwards compatible with C++14 + +template , int> = 0> +inline constexpr _Tp e_v = static_cast<_Tp>(2.718281828459045235360287471352662L); +template , int> = 0> +inline constexpr _Tp log2e_v = static_cast<_Tp>(1.442695040888963407359924681001892L); +template , int> = 0> +inline constexpr _Tp log10e_v = static_cast<_Tp>(0.434294481903251827651128918916605L); +template , int> = 0> +inline constexpr _Tp pi_v = static_cast<_Tp>(3.141592653589793238462643383279502L); +template , int> = 0> +inline constexpr _Tp inv_pi_v = static_cast<_Tp>(0.318309886183790671537767526745028L); +template , int> = 0> +inline constexpr _Tp inv_sqrtpi_v = static_cast<_Tp>(0.564189583547756286948079451560772L); +template , int> = 0> +inline constexpr _Tp ln2_v = static_cast<_Tp>(0.693147180559945309417232121458176L); +template , int> = 0> +inline constexpr _Tp ln10_v = static_cast<_Tp>(2.302585092994045684017991454684364L); +template , int> = 0> +inline constexpr _Tp sqrt2_v = static_cast<_Tp>(1.414213562373095048801688724209698L); +template , int> = 0> +inline constexpr _Tp sqrt3_v = static_cast<_Tp>(1.732050807568877293527446341505872L); +template , int> = 0> +inline constexpr _Tp inv_sqrt3_v = static_cast<_Tp>(0.577350269189625764509148780501957L); +template , int> = 0> +inline constexpr _Tp egamma_v = static_cast<_Tp>(0.577215664901532860606512090082402L); +template , int> = 0> +inline constexpr _Tp phi_v = static_cast<_Tp>(1.618033988749894848204586834365638L); + +#endif + +inline constexpr double e = e_v; +inline constexpr double log2e = log2e_v; +inline constexpr double log10e = log10e_v; +inline constexpr double pi = pi_v; +inline constexpr double inv_pi = inv_pi_v; +inline constexpr double inv_sqrtpi = inv_sqrtpi_v; +inline constexpr double ln2 = ln2_v; +inline constexpr double ln10 = ln10_v; +inline constexpr double sqrt2 = sqrt2_v; +inline constexpr double sqrt3 = sqrt3_v; +inline constexpr double inv_sqrt3 = inv_sqrt3_v; +inline constexpr double egamma = egamma_v; +inline constexpr double phi = phi_v; + +} // namespace numbers + +} // namespace std + +#endif // _EZCXX_NUMBERS From 8cf655414ad2033c0c4f314f074d4c5752a05820 Mon Sep 17 00:00:00 2001 From: unknown <71151164+ZERICO2005@users.noreply.github.com> Date: Thu, 23 Jan 2025 22:48:35 -0700 Subject: [PATCH 7/7] optimized and tested float64 arithmetic and classification routines --- src/crt/dcmp.c | 14 +- src/crt/dcmp.src | 2 +- src/crt/float64_runtime.c | 123 ---------- src/crt/float64_runtime.src | 284 ++++++++++++++++-------- src/crt/ltod.src | 4 +- src/libc/difftime.c | 3 +- src/libc/erfc.c | 6 +- src/libc/float64_math.c | 4 +- src/libc/isinfl.src | 45 ++-- src/libc/isnanl.src | 70 +----- src/libc/isnormalf.src | 8 +- src/libc/issubnormall.src | 73 +----- src/libc/iszerof.src | 3 +- src/libc/iszerol.src | 37 ++- src/libc/makefile | 2 +- src/softfloat/f64_add.c | 3 + src/softfloat/f64_div.c | 4 +- src/softfloat/f64_mul.c | 4 +- src/softfloat/f64_rem.c | 4 +- src/softfloat/f64_sub.c | 3 + src/softfloat/include/internals.h | 5 + src/softfloat/include/softfloat.h | 8 +- src/softfloat/include/softfloat_types.h | 6 + src/softfloat/s_addMagsF64.c | 4 +- src/softfloat/s_subMagsF64.c | 4 +- 25 files changed, 311 insertions(+), 412 deletions(-) delete mode 100644 src/crt/float64_runtime.c diff --git a/src/crt/dcmp.c b/src/crt/dcmp.c index f988615d2..101c1e047 100644 --- a/src/crt/dcmp.c +++ b/src/crt/dcmp.c @@ -7,28 +7,26 @@ typedef union F64_pun { uint64_t bin; } F64_pun; -#define Float64_inf_lsh_1 UINT64_C(0xFFE0000000000000) - #define F64_CMP_EQUAL 0 /* sets the Z flag */ #define F64_CMP_LESS -1 /* sets the S flag */ #define F64_CMP_GREATER 1 /* doesn't trigger flags */ #define F64_CMP_UNORDERED 1 /* doesn't trigger flags */ // assumes no NaN -int _dcmp_c(const long double * x, const long double * y) { - F64_pun arg_x, arg_y; +int _dcmp_c(const long double *__restrict x, const long double *__restrict y) { + F64_pun arg_x, arg_y; arg_x.flt = *x; arg_y.flt = *y; - bool x_sign = signbit(*x); - bool y_sign = signbit(*y); + bool x_sign = signbit(arg_x.flt); + bool y_sign = signbit(arg_y.flt); if (x_sign != y_sign) { - if (iszero(*x) && iszero(*y)) { + if (iszero(arg_x.flt) && iszero(arg_y.flt)) { return F64_CMP_EQUAL; } return (x_sign ? F64_CMP_LESS : F64_CMP_GREATER); } - + if (arg_x.bin == arg_y.bin) { return F64_CMP_EQUAL; } diff --git a/src/crt/dcmp.src b/src/crt/dcmp.src index 10bed0f1a..e090c5bed 100644 --- a/src/crt/dcmp.src +++ b/src/crt/dcmp.src @@ -4,7 +4,7 @@ public __dcmp -; int _dcmp_c(const long double *x, const long double *y) +; int _dcmp_c(const long double *__restrict x, const long double *__restrict y) __dcmp: ; f64*_f64*_ret_i24 push bc, de, hl, af, iy diff --git a/src/crt/float64_runtime.c b/src/crt/float64_runtime.c deleted file mode 100644 index b58c31da1..000000000 --- a/src/crt/float64_runtime.c +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include -#include "../softfloat/include/softfloat.h" - -//------------------------------------------------------------------------------ -// unions -//------------------------------------------------------------------------------ - -typedef union F64_pun { - long double flt; - float64_t soft; - uint64_t bin; -} F64_pun; - -typedef union F32_pun { - float flt; - float32_t soft; - uint32_t bin; -} F32_pun; - -//------------------------------------------------------------------------------ -// Arithmetic functions -//------------------------------------------------------------------------------ - -/* long double _dneg_c(long double x) */ - -#if 0 -long double _dadd_c(long double x, const long double *y) { - F64_pun arg_x, arg_y, ret; - arg_x.flt = x; - arg_y.flt = *y; - ret.soft = f64_add(arg_x.soft, arg_y.soft); - return ret.flt; -} - -long double _dsub_c(long double x, const long double *y) { - F64_pun arg_x, arg_y, ret; - arg_x.flt = x; - arg_y.flt = *y; - ret.soft = f64_sub(arg_x.soft, arg_y.soft); - return ret.flt; -} -#else -float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool ); -float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool ); - -long double _dadd_c(long double x, const long double *y) { - F64_pun arg_x, arg_y, ret; - arg_x.flt = x; - arg_y.flt = *y; - bool sign_x = signbit(arg_x.flt); - if (sign_x == signbit(arg_y.flt)) { - ret.soft = softfloat_addMagsF64(arg_x.bin, arg_y.bin, sign_x); - } else { - ret.soft = softfloat_subMagsF64(arg_x.bin, arg_y.bin, sign_x); - } - return ret.flt; -} - -long double _dsub_c(long double x, const long double *y) { - F64_pun arg_x, arg_y, ret; - arg_x.flt = x; - arg_y.flt = *y; - bool sign_x = signbit(arg_x.flt); - if (sign_x == signbit(arg_y.flt)) { - ret.soft = softfloat_subMagsF64(arg_x.bin, arg_y.bin, sign_x); - } else { - ret.soft = softfloat_addMagsF64(arg_x.bin, arg_y.bin, sign_x); - } - return ret.flt; -} - -#endif - -long double _dmul_c(long double x, const long double *y) { - F64_pun arg_x, arg_y, ret; - arg_x.flt = x; - arg_y.flt = *y; - ret.soft = f64_mul(arg_x.soft, arg_y.soft); - return ret.flt; -} - -long double _ddiv_c(long double x, const long double *y) { - F64_pun arg_x, arg_y, ret; - arg_x.flt = x; - arg_y.flt = *y; - ret.soft = f64_div(arg_x.soft, arg_y.soft); - return ret.flt; -} - -long double _drem_c(long double x, const long double *y) { - F64_pun arg_x, arg_y, ret; - arg_x.flt = x; - arg_y.flt = *y; - ret.soft = f64_rem(arg_x.soft, arg_y.soft); - return ret.flt; -} - -/* int _dcmp_c(const long double *x, const long double* y) */ - -//------------------------------------------------------------------------------ -// Conversion functions -//------------------------------------------------------------------------------ - -float _dtof_c(long double x) { - F32_pun ret; - F64_pun arg_x; - arg_x.flt = x; - ret.soft = f64_to_f32(arg_x.soft); - return ret.flt; -} - -long double _lltod_c(int64_t x) { - F64_pun ret; - ret.soft = i64_to_f64(x); - return ret.flt; -} - -long double _ulltod_c(uint64_t x) { - F64_pun ret; - ret.soft = ui64_to_f64(x); - return ret.flt; -} diff --git a/src/crt/float64_runtime.src b/src/crt/float64_runtime.src index 1546600b3..e948a0876 100644 --- a/src/crt/float64_runtime.src +++ b/src/crt/float64_runtime.src @@ -1,88 +1,196 @@ - assume adl=1 - - section .text - - public __dadd, __dsub, __dmul, __ddiv, __drem - public __lltod,__ulltod, __dtof - -;------------------------------------------------------------------------------- -; Arithmetic functions -;------------------------------------------------------------------------------- - -__dadd: - ; f64_f64*_ret_f64 - push af, iy - ld iy, 9 - add iy, sp - push iy, bc, de, hl - call __dadd_c - pop af, af, af, af, iy, af - ret - -__dsub: - ; f64_f64*_ret_f64 - push af, iy - ld iy, 9 - add iy, sp - push iy, bc, de, hl - call __dsub_c - pop af, af, af, af, iy, af - ret - -__dmul: - ; f64_f64*_ret_f64 - push af, iy - ld iy, 9 - add iy, sp - push iy, bc, de, hl - call __dmul_c - pop af, af, af, af, iy, af - ret - -__ddiv: - ; f64_f64*_ret_f64 - push af, iy - ld iy, 9 - add iy, sp - push iy, bc, de, hl - call __ddiv_c - pop af, af, af, af, iy, af - ret - -__drem: - ; f64_f64*_ret_f64 - push af, iy - ld iy, 9 - add iy, sp - push iy, bc, de, hl - call __drem_c - pop af, af, af, af, iy, af - ret - -;------------------------------------------------------------------------------- -; Conversion functions -;------------------------------------------------------------------------------- - -__dtof: - ; f64_ret_f32 - push af, iy, bc, de, hl - call __dtof_c - pop af, af, af, iy, af - ret - -__lltod: - ; i64_ret_f64 - push af, iy, bc, de, hl - call __lltod_c - pop af, af, af, iy, af - ret - -__ulltod: - ; u64_ret_f64 - push af, iy, bc, de, hl - call __ulltod_c - pop af, af, af, iy, af - ret - - extern __dadd_c, __dsub_c, __dmul_c, __ddiv_c, __drem_c - extern __dtof_c, __lltod_c, __ulltod_c + assume adl=1 + + section .text + + public __dadd, __dsub, __dmul, __ddiv, __drem + public __lltod, __ulltod, __dtof + +if 1 + +; reduces binary size by directly calling SoftFloat functions + +;------------------------------------------------------------------------------- +; Addition and Subtraction +;------------------------------------------------------------------------------- + +; float64_t softfloat_addMagsF64(float64_t x, const float64_t *y, bool sign_x) +__dadd: + push af + ld a, b + jr __daddsub + +; float64_t softfloat_subMagsF64(float64_t x, const float64_t *y, bool sign_x) +__dsub: + push af + ld a, b + cpl + jr __daddsub + +__daddsub: + push iy + ld iy, 9 + add iy, sp + + rlc b + push af ; sign_x + rrc b + + push iy ; address of y + push bc, de, hl ; pass x by value + + xor a, (iy + 7) + rla + + jr nc, .__daddmags ; same signs +; .__dsubmags: + call _softfloat_subMagsF64 + jr .__daddsub_ret +.__daddmags: + call _softfloat_addMagsF64 +.__daddsub_ret: + pop af, af, af, af, af + pop iy, af + ret + +;------------------------------------------------------------------------------- +; Other Arithmetic +;------------------------------------------------------------------------------- + +; float64_t f64_mul(float64_t, const float64_t*) +__dmul: + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call _f64_mul + pop af, af, af, af, iy, af + ret + +; float64_t f64_div(float64_t, const float64_t*) +__ddiv: + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call _f64_div + pop af, af, af, af, iy, af + ret + +; float64_t f64_rem(float64_t, const float64_t*) +__drem: + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call _f64_rem + pop af, af, af, af, iy, af + ret + +;------------------------------------------------------------------------------- +; Conversion +;------------------------------------------------------------------------------- + +__dtof: + ; f64_ret_f32 + push af, iy, bc, de, hl + call _f64_to_f32 + pop af, af, af, iy, af + ret + +__lltod: + ; i64_ret_f64 + push af, iy, bc, de, hl + call _i64_to_f64 + pop af, af, af, iy, af + ret + +__ulltod: + ; u64_ret_f64 + push af, iy, bc, de, hl + call _ui64_to_f64 + pop af, af, af, iy, af + ret + + extern _softfloat_addMagsF64, _softfloat_subMagsF64 + extern _f64_mul, _f64_div, _f64_rem + extern _f64_to_f32, _i64_to_f64, _ui64_to_f64 + +else + +; wraps C functions + +__dadd: + ; f64_f64*_ret_f64 + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call __dadd_c + pop af, af, af, af, iy, af + ret + +__dsub: + ; f64_f64*_ret_f64 + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call __dsub_c + pop af, af, af, af, iy, af + ret + +__dmul: + ; f64_f64*_ret_f64 + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call __dmul_c + pop af, af, af, af, iy, af + ret + +__ddiv: + ; f64_f64*_ret_f64 + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call __ddiv_c + pop af, af, af, af, iy, af + ret + +__drem: + ; f64_f64*_ret_f64 + push af, iy + ld iy, 9 + add iy, sp + push iy, bc, de, hl + call __drem_c + pop af, af, af, af, iy, af + ret + +__dtof: + ; f64_ret_f32 + push af, iy, bc, de, hl + call __dtof_c + pop af, af, af, iy, af + ret + +__lltod: + ; i64_ret_f64 + push af, iy, bc, de, hl + call __lltod_c + pop af, af, af, iy, af + ret + +__ulltod: + ; u64_ret_f64 + push af, iy, bc, de, hl + call __ulltod_c + pop af, af, af, iy, af + ret + + extern __dadd_c, __dsub_c, __dmul_c, __ddiv_c, __drem_c + extern __dtof_c, __lltod_c, __ulltod_c + +end if diff --git a/src/crt/ltod.src b/src/crt/ltod.src index 3e10dc5cb..356293ebc 100644 --- a/src/crt/ltod.src +++ b/src/crt/ltod.src @@ -25,14 +25,14 @@ __ultod: ; sbc a, a ; ld e, a ; pop hl -; jr .ltod_skip +; jr __ltod.ltod_skip __ltod: ; i32_ret_f64 ld d, a bit 7, e .ltod_skip: - jr z, .ultod_skip ; positive argument + jr z, __ultod.ultod_skip ; positive argument ; return -_ultod_c(labs(x)) call __lneg push iy, de, hl diff --git a/src/libc/difftime.c b/src/libc/difftime.c index be1ced523..26e6a6807 100644 --- a/src/libc/difftime.c +++ b/src/libc/difftime.c @@ -3,5 +3,6 @@ double difftime(time_t end, time_t beginning) { - return end - beginning; + /* assuming typedef unsigned long time_t */ + return (double)((signed long)(end - beginning)); } diff --git a/src/libc/erfc.c b/src/libc/erfc.c index 7f6419b0f..a6ca51406 100644 --- a/src/libc/erfc.c +++ b/src/libc/erfc.c @@ -3,7 +3,7 @@ float erfcf(float x) { static const float p = 0.47047f, a1 = 0.3480242f, a2 = -0.0958798f, a3 = 0.7478556f; - const float t = 1 / (1 + p * fabs(x)); + const float t = 1.0f / (1.0f + p * fabsf(x)); return copysignf(t * (a1 + t * (a2 + t * a3)) * expf(-x * x), x); } @@ -12,6 +12,6 @@ double erfc(double) __attribute__((alias("erfcf"))); long double erfcl(long double x) { static const long double p = 0.3275911l, a1 = 0.254829592l, a2 = -0.284496736l, a3 = 1.421413741l, a4 = -1.453152027l, a5 = 1.061405429l; - const long double t = 1 / (1 + p * fabs(x)); - return copysignf(t * (a1 + t * (a2 + t * (a3 + t * (a4 + t * a5)))) * expl(-x * x), x); + const long double t = 1.0l / (1.0l + p * fabsl(x)); + return copysignl(t * (a1 + t * (a2 + t * (a3 + t * (a4 + t * a5)))) * expl(-x * x), x); } diff --git a/src/libc/float64_math.c b/src/libc/float64_math.c index c5c9b851d..eb3d76da4 100644 --- a/src/libc/float64_math.c +++ b/src/libc/float64_math.c @@ -53,7 +53,7 @@ long double fmodl(long double x, long double y) { arg_y.flt = y; softfloat_exceptionFlags = 0; - ret.soft = f64_rem(arg_x.soft, arg_y.soft); + ret.soft = f64_rem(arg_x.soft, &arg_y.soft); if (softfloat_exceptionFlags & softfloat_flag_invalid) { feraiseexcept(FE_INVALID); } @@ -74,6 +74,6 @@ long double modfl(long double x, long double *integral_part) { arg_x.flt = x; arg_y.flt = 1.0L; *integral_part = truncl(x); - ret.soft = f64_rem(arg_x.soft, arg_y.soft); + ret.soft = f64_rem(arg_x.soft, &arg_y.soft); return ret.flt; } diff --git a/src/libc/isinfl.src b/src/libc/isinfl.src index b246440d0..0d2fd19d8 100644 --- a/src/libc/isinfl.src +++ b/src/libc/isinfl.src @@ -3,37 +3,28 @@ section .text public __isinfl - + ; int _isinfl(long double) __isinfl: - ; load upper 24bits - ld hl, 8 - add hl, sp - ld hl, (hl) - ; clear signbit - add hl, hl - or a, a - ld bc, $FFE000 - sbc hl, bc - jr z, .mantissa_check - ; finite and common NaN -.mant_non_zero: + pop bc, hl, de or a, a - sbc hl, hl + adc hl, de + pop de + push bc, bc, bc, bc + jr nz, .mant_nonzero + jr c, .mant_carry + ld a, e + xor a, $F0 + ret nz ; mantissa is non-zero + ; A is zero here + set 7, d + inc d + ret nz + inc hl ret -.mantissa_check: - pop bc, hl, de - push de, hl, bc - ; __i40cmpzero - add hl, de +.mant_nonzero: +.mant_carry: or a, a - sbc hl, de - jr nz, .mant_non_zero - ; hl was zero, so the carry flag cannot have been set - ex de, hl - sbc hl, de - jr nz, .mant_non_zero - ; both hl and de are zero - inc hl + sbc hl, hl ret diff --git a/src/libc/isnanl.src b/src/libc/isnanl.src index 13e62beaf..fcddcbcc3 100644 --- a/src/libc/isnanl.src +++ b/src/libc/isnanl.src @@ -4,9 +4,6 @@ public __isnanl -; adapted from fpclassify.src - -if 1 ; int _isnanl(long double) __isnanl: pop bc, hl, de @@ -17,63 +14,20 @@ __isnanl: ld a, e jr nz, .mant_nonzero ; normal, subnormal, or NaN jr c, .mant_nonzero ; normal, subnormal, or NaN - tst a, $0F - jr nz, .mant_nonzero ; normal, subnormal, or NaN - sbc hl, hl ; normal, or subnormal + ; common NaN, inf, normal, or subnormal + add a, 15 ; overflows 0xF1 + jr c, .skip_exp_check ret .mant_nonzero: or a, a sbc hl, hl - rra - and a, $78 - res 7, d - add a, d - ret z ; subnormal - inc l - add a, -($78 + $7F) - ret z ; NaN - dec l ; normal + add a, 16 ; overflows 0xF0 + ret nc +.skip_exp_check: + ; carry is set here + ld a, d + rla ; A should be all ones if D was all ones + inc a + ret nz + inc hl ret - -else - -; int _isnanl(long double) -__isnanl: - ; load upper 24bits - ld hl, 8 - add hl, sp - ld hl, (hl) - ; clear signbit - add hl, hl - ; test for inf/NaN - ld de, $2000 - add hl, de - jr c, .exp_all_ones - sbc hl, hl - ret -.exp_all_ones: - ld a, h - and a, $1E ; most common NaN - jr nz, .upper_mantissa_nan - ; infinity or uncommon NaN - pop bc, hl, de - push de, hl, bc - ; __i48cmpzero - add hl, de - or a, a - sbc hl, de - jr nz, .lower_mantissa_nan - ex de, hl - ; hl was zero, so the carry flag cannot have been set - sbc hl, de - jr nz, .lower_mantissa_nan - ret ; infinity - -.lower_mantissa_nan: - or a, a -.upper_mantissa_nan: - sbc hl, hl - inc hl - ret - -end if diff --git a/src/libc/isnormalf.src b/src/libc/isnormalf.src index a9aad813d..fa5407540 100644 --- a/src/libc/isnormalf.src +++ b/src/libc/isnormalf.src @@ -8,11 +8,11 @@ __isnormalf: ld hl, 5 add hl, sp - ld hl, (hl) + ld hl, (hl) ; load the upper 16 bits add hl, hl ; clears signbit ld a, h dec a - cp a, -2 ; overflows on zero/denormal/inf/NaN exponents - sbc hl, hl ; hl is -1 or 0 - inc hl ; hl is 0 or 1 + cp a, $FE ; tests for zero/denormal/inf/NaN exponents + sbc hl, hl ; -1 if normal, 0 otherwise ret + diff --git a/src/libc/issubnormall.src b/src/libc/issubnormall.src index c9b65caa3..60926c470 100644 --- a/src/libc/issubnormall.src +++ b/src/libc/issubnormall.src @@ -4,76 +4,27 @@ public __issubnormall - - -if 0 - -; int _fpclassifyl(long double) -__fpclassifyl: +; int _issubnormall(long double) +__issubnormall: pop bc, hl, de or a, a adc hl, de pop de push bc, bc, bc, bc + ; zero is not subnormal + jr nz, .mant_nonzero + jr c, .mant_carry ld a, e - jr nz, .mant_nonzero ; normal, subnormal, or NaN - jr c, .mant_nonzero ; normal, subnormal, or NaN - tst a, $0F - jr z, .mant_zero ; normal, zero, or inf + and a, $0F + ret z ; mantissa is zero .mant_nonzero: - ; normal, subnormal, or NaN - ld hl, 2 -.mant_zero: +.mant_carry: + ld a, e + and a, $F0 + sbc hl, hl rra - and a, $78 res 7, d add a, d - ret z ; subnormal or zero - inc l - add a, -($78 + $7F) - ret z ; inf or NaN - ld l, 4 ; normal - ret - -else - -; int _issubnormall(long double) -__issubnormall: - pop iy, de, hl, bc - push bc, hl, de, iy - - ld a, b ; upper 8bits of the exponent - add a, a - jr z, .upper_exp_all_zero - ; most common path - or a, a -.exp_non_zero: - sbc hl, hl - ret - -; normal, zero, or subnormal -.upper_exp_all_zero: - ld a, c ; lower 8bits of the exponent - tst a, $F0 - jr nz, .exp_non_zero - and a, $0F - jr nz, .upper_mant_non_zero - - ; __i48cmpzero - add hl, de - or a, a - sbc hl, de - jr nz, .mant_non_zero - ex de, hl - ; hl was zero, so the carry flag cannot have been set - sbc hl, de - jr nz, .mant_non_zero - ret -.mant_non_zero: - or a, a -.upper_mant_non_zero: - sbc hl, hl + ret nz inc hl ret - -end if \ No newline at end of file diff --git a/src/libc/iszerof.src b/src/libc/iszerof.src index 165c86d45..02dcbad1d 100644 --- a/src/libc/iszerof.src +++ b/src/libc/iszerof.src @@ -8,7 +8,8 @@ __iszerof: pop bc, hl, de push de, hl, bc - add hl, hl + or a, a + adc hl, hl jr nz, .not_zero_f32 rl e jr nz, .not_zero_f32 diff --git a/src/libc/iszerol.src b/src/libc/iszerol.src index 4db2f3175..9c3bd6f4b 100644 --- a/src/libc/iszerol.src +++ b/src/libc/iszerol.src @@ -6,29 +6,24 @@ ; int iszerol(long double) __iszerol: - pop iy, de, hl, bc - push bc, hl, de, iy - ; normal, inf, and NaN have non-zero exponents - ld a, b - add a, a ; clears the signbit - or a, c - jr z, .exp_zero_f64 - sbc hl, hl - ret -.exp_zero_f64: - ; __i48cmpzero - add hl, de + pop bc, hl, de or a, a - sbc hl, de - jr nz, .mant_non_zero_f64 - ex de, hl - ; hl was zero, so the carry flag cannot have been set - sbc hl, de - jr nz, .mant_non_zero_f64 + adc hl, de + pop de + push bc, bc, bc, bc + ; return if mantissa is non-zero + jr nz, .mant_nonzero + jr c, .mant_carry + ld a, d + rla ; clear the signbit + or a, e inc hl - ret - -.mant_non_zero_f64: + ret z + ; upper 16 bits non-zero +; dec hl +; ret +.mant_nonzero: +.mant_carry: or a, a sbc hl, hl ret diff --git a/src/libc/makefile b/src/libc/makefile index 129270312..ec5e8258c 100644 --- a/src/libc/makefile +++ b/src/libc/makefile @@ -18,7 +18,7 @@ include $(CURDIR)/../common.mk BUILD_SRC := $(patsubst %,build/%.src,$(wildcard *.c *.cpp)) -EZCFLAGS := -S -ffreestanding -Wall -Wextra -Oz +EZCFLAGS := -S -ffreestanding -Wall -Wextra -Wshadow -Wimplicit-float-conversion -Wimplicit-int-float-conversion -Oz EZCFLAGS += -D_EZ80 -isystem ../libc/include -isystem ../ce/include -isystem ../fileioc -mllvm -profile-guided-section-prefix=false EZCXXFLAGS := $(EZCFLAGS) -fno-exceptions -fno-rtti EZCXXFLAGS += -isystem ../libcxx/include diff --git a/src/softfloat/f64_add.c b/src/softfloat/f64_add.c index 878f6da75..fabaf5812 100644 --- a/src/softfloat/f64_add.c +++ b/src/softfloat/f64_add.c @@ -34,6 +34,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ +#if 0 + #include #include #include "platform.h" @@ -72,3 +74,4 @@ float64_t f64_add( float64_t a, float64_t b ) } +#endif diff --git a/src/softfloat/f64_div.c b/src/softfloat/f64_div.c index 7f5eddd4a..92ff214f5 100644 --- a/src/softfloat/f64_div.c +++ b/src/softfloat/f64_div.c @@ -41,7 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -float64_t f64_div( float64_t a, float64_t b ) +float64_t f64_div( float64_t a, const float64_t *b ) { union ui64_f64 uA; uint_fast64_t uiA; @@ -70,7 +70,7 @@ float64_t f64_div( float64_t a, float64_t b ) signA = signF64UI( uiA ); expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); - uB.f = b; + uB.f = *b; uiB = uB.ui; signB = signF64UI( uiB ); expB = expF64UI( uiB ); diff --git a/src/softfloat/f64_mul.c b/src/softfloat/f64_mul.c index 38bdc852a..661fb94b8 100644 --- a/src/softfloat/f64_mul.c +++ b/src/softfloat/f64_mul.c @@ -41,7 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -float64_t f64_mul( float64_t a, float64_t b ) +float64_t f64_mul( float64_t a, const float64_t *b ) { union ui64_f64 uA; uint_fast64_t uiA; @@ -72,7 +72,7 @@ float64_t f64_mul( float64_t a, float64_t b ) signA = signF64UI( uiA ); expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); - uB.f = b; + uB.f = *b; uiB = uB.ui; signB = signF64UI( uiB ); expB = expF64UI( uiB ); diff --git a/src/softfloat/f64_rem.c b/src/softfloat/f64_rem.c index ca5350c94..9f0ee6f73 100644 --- a/src/softfloat/f64_rem.c +++ b/src/softfloat/f64_rem.c @@ -41,7 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" #include "softfloat.h" -float64_t f64_rem( float64_t a, float64_t b ) +float64_t f64_rem( float64_t a, const float64_t *b ) { union ui64_f64 uA; uint_fast64_t uiA; @@ -69,7 +69,7 @@ float64_t f64_rem( float64_t a, float64_t b ) signA = signF64UI( uiA ); expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); - uB.f = b; + uB.f = *b; uiB = uB.ui; expB = expF64UI( uiB ); sigB = fracF64UI( uiB ); diff --git a/src/softfloat/f64_sub.c b/src/softfloat/f64_sub.c index 74158bec1..91c960f06 100644 --- a/src/softfloat/f64_sub.c +++ b/src/softfloat/f64_sub.c @@ -34,6 +34,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ +#if 0 + #include #include #include "platform.h" @@ -72,3 +74,4 @@ float64_t f64_sub( float64_t a, float64_t b ) } +#endif diff --git a/src/softfloat/include/internals.h b/src/softfloat/include/internals.h index f8eac0530..b8cef5a55 100644 --- a/src/softfloat/include/internals.h +++ b/src/softfloat/include/internals.h @@ -135,8 +135,13 @@ struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t ); float64_t softfloat_roundPackToF64( bool, int_fast16_t, uint_fast64_t ); float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t ); +#if 0 float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool ); float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool ); +#else +float64_t softfloat_addMagsF64( uint_fast64_t, const uint_fast64_t*, bool ); +float64_t softfloat_subMagsF64( uint_fast64_t, const uint_fast64_t*, bool ); +#endif float64_t softfloat_mulAddF64( uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); diff --git a/src/softfloat/include/softfloat.h b/src/softfloat/include/softfloat.h index 9ed17c1b9..33b554ac8 100644 --- a/src/softfloat/include/softfloat.h +++ b/src/softfloat/include/softfloat.h @@ -224,12 +224,14 @@ float128_t f64_to_f128( float64_t ); void f64_to_extF80M( float64_t, extFloat80_t * ); void f64_to_f128M( float64_t, float128_t * ); float64_t f64_roundToInt( float64_t, uint_fast8_t, bool ); +#if 0 float64_t f64_add( float64_t, float64_t ); float64_t f64_sub( float64_t, float64_t ); -float64_t f64_mul( float64_t, float64_t ); +#endif +float64_t f64_mul( float64_t, const float64_t* ); float64_t f64_mulAdd( float64_t, float64_t, float64_t ); -float64_t f64_div( float64_t, float64_t ); -float64_t f64_rem( float64_t, float64_t ); +float64_t f64_div( float64_t, const float64_t* ); +float64_t f64_rem( float64_t, const float64_t* ); float64_t f64_sqrt( float64_t ); bool f64_eq( float64_t, float64_t ); bool f64_le( float64_t, float64_t ); diff --git a/src/softfloat/include/softfloat_types.h b/src/softfloat/include/softfloat_types.h index b92d24625..9b5c6d22a 100644 --- a/src/softfloat/include/softfloat_types.h +++ b/src/softfloat/include/softfloat_types.h @@ -47,9 +47,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | the types below may, if desired, be defined as aliases for the native types | (typically 'float' and 'double', and possibly 'long double'). *----------------------------------------------------------------------------*/ +#if 0 typedef struct { uint16_t v; } float16_t; typedef struct { uint32_t v; } float32_t; typedef struct { uint64_t v; } float64_t; +#else +typedef uint16_t float16_t; +typedef uint32_t float32_t; +typedef uint64_t float64_t; +#endif typedef struct { uint64_t v[2]; } float128_t; /*---------------------------------------------------------------------------- diff --git a/src/softfloat/s_addMagsF64.c b/src/softfloat/s_addMagsF64.c index 25b8f386e..f1730e746 100644 --- a/src/softfloat/s_addMagsF64.c +++ b/src/softfloat/s_addMagsF64.c @@ -41,8 +41,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "specialize.h" float64_t - softfloat_addMagsF64( uint_fast64_t uiA, uint_fast64_t uiB, bool signZ ) + softfloat_addMagsF64( uint_fast64_t uiA, const uint_fast64_t *uiB_ptr, bool signZ ) { + uint_fast64_t uiB; int_fast16_t expA; uint_fast64_t sigA; int_fast16_t expB; @@ -55,6 +56,7 @@ float64_t /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ + uiB = *uiB_ptr; expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); expB = expF64UI( uiB ); diff --git a/src/softfloat/s_subMagsF64.c b/src/softfloat/s_subMagsF64.c index 3a4acb104..a32085cdc 100644 --- a/src/softfloat/s_subMagsF64.c +++ b/src/softfloat/s_subMagsF64.c @@ -42,8 +42,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "softfloat.h" float64_t - softfloat_subMagsF64( uint_fast64_t uiA, uint_fast64_t uiB, bool signZ ) + softfloat_subMagsF64( uint_fast64_t uiA, const uint_fast64_t *uiB_ptr, bool signZ ) { + uint_fast64_t uiB; int_fast16_t expA; uint_fast64_t sigA; int_fast16_t expB; @@ -58,6 +59,7 @@ float64_t /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ + uiB = *uiB_ptr; expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); expB = expF64UI( uiB );