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:
+
+
+
+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:
+
+
+-
+
+Redistributions of source code must retain the above copyright notice, this
+list of conditions, and the following disclaimer.
+
+
+ -
+
+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.
+
+
+ -
+
+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:
+
+
+-
+
+Redistributions of source code must retain the above copyright notice, this
+list of conditions, and the following disclaimer.
+
+
+ -
+
+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.
+
+
+ -
+
+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_t |
+16-bit half-precision binary format |
+
+
+float32_t |
+32-bit single-precision binary format |
+
+
+float64_t |
+64-bit double-precision binary format |
+
+
+extFloat80_t |
+80-bit double-extended-precision binary format (old Intel or
+Motorola format) |
+
+
+float128_t |
+128-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_even |
+round to nearest, with ties to even |
+
+
+softfloat_round_near_maxMag |
+round to nearest, with ties to maximum magnitude (away from zero) |
+
+
+softfloat_round_minMag |
+round to minimum magnitude (toward zero) |
+
+
+softfloat_round_min |
+round to minimum (down) |
+
+
+softfloat_round_max |
+round to maximum (up) |
+
+
+softfloat_round_odd |
+round 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:
+
+
+
+f16 |
+indicates float16_t , passed by value |
+
+
+f32 |
+indicates float32_t , passed by value |
+
+
+f64 |
+indicates float64_t , passed by value |
+
+
+extF80M |
+indicates extFloat80_t , passed indirectly via pointers |
+
+
+extF80 |
+indicates extFloat80_t , passed by value |
+
+
+f128M |
+indicates float128_t , passed indirectly via pointers |
+
+
+f128 |
+indicates 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: |
+
+
+float32 |
+float32_t |
+
+
+float64 |
+float64_t |
+
+
+floatx80 |
+extFloat80_t |
+
+
+float128 |
+float128_t |
+
+
+float_rounding_mode |
+softfloat_roundingMode |
+
+
+float_round_nearest_even |
+softfloat_round_near_even |
+
+
+float_round_to_zero |
+softfloat_round_minMag |
+
+
+float_round_down |
+softfloat_round_min |
+
+
+float_round_up |
+softfloat_round_max |
+
+
+float_detect_tininess |
+softfloat_detectTininess |
+
+
+float_tininess_before_rounding |
+softfloat_tininess_beforeRounding |
+
+
+float_tininess_after_rounding |
+softfloat_tininess_afterRounding |
+
+
+floatx80_rounding_precision |
+extF80_roundingPrecision |
+
+
+float_exception_flags |
+softfloat_exceptionFlags |
+
+
+float_flag_inexact |
+softfloat_flag_inexact |
+
+
+float_flag_underflow |
+softfloat_flag_underflow |
+
+
+float_flag_overflow |
+softfloat_flag_overflow |
+
+
+float_flag_divbyzero |
+softfloat_flag_infinite |
+
+
+float_flag_invalid |
+softfloat_flag_invalid |
+
+
+float_raise |
+softfloat_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_minMag |
+conversions from floating-point to integer (section 8.2) |
+
+
+round_to_int |
+roundToInt |
+round-to-integer functions (section 8.7) |
+
+
+is_signaling_nan |
+isSignalingNaN |
+signaling 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