From: Andrew Waterman Date: Wed, 18 Aug 2010 21:34:42 +0000 (-0700) Subject: [sim] integrated SoftFloat-3 with ISA sim; removed SoftFloat-2b X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=50ec828bafd154b5558c70ff46491193acf7f699;p=riscv-isa-sim.git [sim] integrated SoftFloat-3 with ISA sim; removed SoftFloat-2b --- diff --git a/configure b/configure index 5e9e2a3..30b9fc3 100755 --- a/configure +++ b/configure @@ -4169,6 +4169,51 @@ $as_echo "#define SOFTFLOAT_ENABLED /**/" >>confdefs.h + # Determine if this is a required or an optional subproject + + + + # Determine if there is a group with the same name + + + + # Create variations of the subproject name suitable for use as a CPP + # enabled define, a shell enabled variable, and a shell function + + + + + + + + + + + + # Add subproject to our running list + + subprojects="$subprojects softfloat_riscv" + + # Process the subproject appropriately. If enabled add it to the + # $enabled_subprojects running shell variable, set a + # SUBPROJECT_ENABLED C define, and include the appropriate + # 'subproject.ac'. + + + { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : softfloat_riscv" >&5 +$as_echo "$as_me: configuring default subproject : softfloat_riscv" >&6;} + ac_config_files="$ac_config_files softfloat_riscv.mk:softfloat_riscv/softfloat_riscv.mk.in" + + enable_softfloat_riscv_sproj="yes" + subprojects_enabled="$subprojects_enabled softfloat_riscv" + +$as_echo "#define SOFTFLOAT_RISCV_ENABLED /**/" >>confdefs.h + + + + + + # Output make variables @@ -4876,6 +4921,7 @@ do case $ac_config_target in "riscv.mk") CONFIG_FILES="$CONFIG_FILES riscv.mk:riscv/riscv.mk.in" ;; "softfloat.mk") CONFIG_FILES="$CONFIG_FILES softfloat.mk:softfloat/softfloat.mk.in" ;; + "softfloat_riscv.mk") CONFIG_FILES="$CONFIG_FILES softfloat_riscv.mk:softfloat_riscv/softfloat_riscv.mk.in" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; diff --git a/configure.ac b/configure.ac index 967e7c4..60abb71 100644 --- a/configure.ac +++ b/configure.ac @@ -81,7 +81,7 @@ AC_SUBST([CXXFLAGS],["-Wall -O2"]) # The '*' suffix indicates an optional subproject. The '**' suffix # indicates an optional subproject which is also the name of a group. -MCPPBS_SUBPROJECTS([ riscv, softfloat ]) +MCPPBS_SUBPROJECTS([ riscv, softfloat, softfloat_riscv ]) #------------------------------------------------------------------------- # MCPPBS subproject groups diff --git a/riscv/decode.h b/riscv/decode.h index 424ad7f..1b631ae 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -38,20 +38,21 @@ const int BIGIMM_BITS = 20; #define SR_IM 0x000000000000FF00ULL #define SR_ZERO ~(SR_ET | SR_PS | SR_S | SR_EF | SR_UX | SR_KX | SR_IM) -#define FP_RD_NE 0 -#define FP_RD_0 1 -#define FP_RD_UP 2 -#define FP_RD_DN 3 +#define FP_RD_NE 0 +#define FP_RD_0 1 +#define FP_RD_DN 2 +#define FP_RD_UP 3 +#define FP_RD_NMM 4 #define FSR_RD_SHIFT 10 -#define FSR_RD (0x3 << FSR_RD_SHIFT) +#define FSR_RD (0x7 << FSR_RD_SHIFT) -#define FPEXC_NV 0x10 -#define FPEXC_OF 0x08 -#define FPEXC_UF 0x04 -#define FPEXC_DZ 0x02 #define FPEXC_NX 0x01 +#define FPEXC_UF 0x02 +#define FPEXC_OF 0x04 +#define FPEXC_DZ 0x02 +#define FPEXC_NV 0x10 -#define FSR_AEXC_SHIFT 5 +#define FSR_AEXC_SHIFT 0 #define FSR_NVA (FPEXC_NV << FSR_AEXC_SHIFT) #define FSR_OFA (FPEXC_OF << FSR_AEXC_SHIFT) #define FSR_UFA (FPEXC_UF << FSR_AEXC_SHIFT) @@ -59,15 +60,7 @@ const int BIGIMM_BITS = 20; #define FSR_NXA (FPEXC_NX << FSR_AEXC_SHIFT) #define FSR_AEXC (FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA) -#define FSR_CEXC_SHIFT 0 -#define FSR_NVC (FPEXC_NV << FSR_AEXC_SHIFT) -#define FSR_OFC (FPEXC_OF << FSR_AEXC_SHIFT) -#define FSR_UFC (FPEXC_UF << FSR_AEXC_SHIFT) -#define FSR_DZC (FPEXC_DZ << FSR_AEXC_SHIFT) -#define FSR_NXC (FPEXC_NX << FSR_AEXC_SHIFT) -#define FSR_CEXC (FSR_NVC | FSR_OFC | FSR_UFC | FSR_DZC | FSR_NXC) - -#define FSR_ZERO ~(FSR_RD | FSR_AEXC | FSR_CEXC) +#define FSR_ZERO ~(FSR_RD | FSR_AEXC) // note: bit fields are in little-endian order struct itype_t @@ -143,10 +136,9 @@ union insn_t #define require64 if(gprlen != 64) throw trap_illegal_instruction #define require_fp if(!(sr & SR_EF)) throw trap_fp_disabled #define cmp_trunc(reg) (reg_t(reg) << (64-gprlen)) -#define set_fp_exceptions ({ set_fsr((fsr & ~FSR_CEXC) | \ - (float_exception_flags << FSR_AEXC_SHIFT) | \ - (float_exception_flags << FSR_CEXC_SHIFT)); \ - float_exception_flags = 0; }) +#define set_fp_exceptions ({ set_fsr(fsr | \ + (softfloat_exceptionFlags << FSR_AEXC_SHIFT)); \ + softfloat_exceptionFlags = 0; }) static inline sreg_t sext32(int32_t arg) { diff --git a/riscv/insns/add_d.h b/riscv/insns/add_d.h index bd0f55a..964aa20 100644 --- a/riscv/insns/add_d.h +++ b/riscv/insns/add_d.h @@ -1,3 +1,3 @@ require_fp; -FRC = float64_add(FRA, FRB); +FRC = f64_add(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/add_s.h b/riscv/insns/add_s.h index b4f98f6..d4d0cd6 100644 --- a/riscv/insns/add_s.h +++ b/riscv/insns/add_s.h @@ -1,3 +1,3 @@ require_fp; -FRC = float32_add(FRA, FRB); +FRC = f32_add(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/c_eq_d.h b/riscv/insns/c_eq_d.h index 4387ea3..cc7b77a 100644 --- a/riscv/insns/c_eq_d.h +++ b/riscv/insns/c_eq_d.h @@ -1,3 +1,3 @@ require_fp; -RC = float64_eq(FRA, FRB); +RC = f64_eq(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/c_eq_s.h b/riscv/insns/c_eq_s.h index 062fb74..5500c4c 100644 --- a/riscv/insns/c_eq_s.h +++ b/riscv/insns/c_eq_s.h @@ -1,3 +1,3 @@ require_fp; -RC = float32_eq(FRA, FRB); +RC = f32_eq(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/c_le_d.h b/riscv/insns/c_le_d.h index 24ea657..2fe6f32 100644 --- a/riscv/insns/c_le_d.h +++ b/riscv/insns/c_le_d.h @@ -1,3 +1,3 @@ require_fp; -RC = float64_le(FRA, FRB); +RC = f64_le(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/c_le_s.h b/riscv/insns/c_le_s.h index 107622f..e6e26b3 100644 --- a/riscv/insns/c_le_s.h +++ b/riscv/insns/c_le_s.h @@ -1,3 +1,3 @@ require_fp; -RC = float32_le(FRA, FRB); +RC = f32_le(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/c_lt_d.h b/riscv/insns/c_lt_d.h index 3d42500..3f3756d 100644 --- a/riscv/insns/c_lt_d.h +++ b/riscv/insns/c_lt_d.h @@ -1,3 +1,3 @@ require_fp; -RC = float64_lt(FRA, FRB); +RC = f64_lt(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/c_lt_s.h b/riscv/insns/c_lt_s.h index 1f7a0e1..aef7334 100644 --- a/riscv/insns/c_lt_s.h +++ b/riscv/insns/c_lt_s.h @@ -1,3 +1,3 @@ require_fp; -RC = float32_lt(FRA, FRB); +RC = f32_lt(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/cvt_d_l.h b/riscv/insns/cvt_d_l.h index 5246f6f..808d20c 100644 --- a/riscv/insns/cvt_d_l.h +++ b/riscv/insns/cvt_d_l.h @@ -1,3 +1,3 @@ require_fp; -FRC = int64_to_float64(FRA); +FRC = i64_to_f64(FRA); set_fp_exceptions; diff --git a/riscv/insns/cvt_d_s.h b/riscv/insns/cvt_d_s.h index 481a4d1..69206e1 100644 --- a/riscv/insns/cvt_d_s.h +++ b/riscv/insns/cvt_d_s.h @@ -1,3 +1,3 @@ require_fp; -FRC = float32_to_float64(FRA); +FRC = f32_to_f64(FRA); set_fp_exceptions; diff --git a/riscv/insns/cvt_d_w.h b/riscv/insns/cvt_d_w.h index 67702a2..e1c36f2 100644 --- a/riscv/insns/cvt_d_w.h +++ b/riscv/insns/cvt_d_w.h @@ -1,3 +1,3 @@ require_fp; -FRC = int32_to_float64(FRA); +FRC = i32_to_f64(FRA); set_fp_exceptions; diff --git a/riscv/insns/cvt_s_d.h b/riscv/insns/cvt_s_d.h index 528f11c..0ee755e 100644 --- a/riscv/insns/cvt_s_d.h +++ b/riscv/insns/cvt_s_d.h @@ -1,3 +1,3 @@ require_fp; -FRC = float64_to_float32(FRA); +FRC = f64_to_f32(FRA); set_fp_exceptions; diff --git a/riscv/insns/cvt_s_l.h b/riscv/insns/cvt_s_l.h index 2d1f93a..66e4566 100644 --- a/riscv/insns/cvt_s_l.h +++ b/riscv/insns/cvt_s_l.h @@ -1,3 +1,3 @@ require_fp; -FRC = int64_to_float32(FRA); +FRC = i64_to_f32(FRA); set_fp_exceptions; diff --git a/riscv/insns/cvt_s_w.h b/riscv/insns/cvt_s_w.h index c2d583f..5bbe61f 100644 --- a/riscv/insns/cvt_s_w.h +++ b/riscv/insns/cvt_s_w.h @@ -1,3 +1,3 @@ require_fp; -FRC = int32_to_float32(FRA); +FRC = i32_to_f32(FRA); set_fp_exceptions; diff --git a/riscv/insns/cvtu_d_l.h b/riscv/insns/cvtu_d_l.h index 5246f6f..808d20c 100644 --- a/riscv/insns/cvtu_d_l.h +++ b/riscv/insns/cvtu_d_l.h @@ -1,3 +1,3 @@ require_fp; -FRC = int64_to_float64(FRA); +FRC = i64_to_f64(FRA); set_fp_exceptions; diff --git a/riscv/insns/cvtu_d_w.h b/riscv/insns/cvtu_d_w.h index 67702a2..1a61ad6 100644 --- a/riscv/insns/cvtu_d_w.h +++ b/riscv/insns/cvtu_d_w.h @@ -1,3 +1,3 @@ require_fp; -FRC = int32_to_float64(FRA); +FRC = ui32_to_f64(FRA); set_fp_exceptions; diff --git a/riscv/insns/cvtu_s_l.h b/riscv/insns/cvtu_s_l.h index 2d1f93a..66e4566 100644 --- a/riscv/insns/cvtu_s_l.h +++ b/riscv/insns/cvtu_s_l.h @@ -1,3 +1,3 @@ require_fp; -FRC = int64_to_float32(FRA); +FRC = i64_to_f32(FRA); set_fp_exceptions; diff --git a/riscv/insns/cvtu_s_w.h b/riscv/insns/cvtu_s_w.h index c2d583f..8eaeca3 100644 --- a/riscv/insns/cvtu_s_w.h +++ b/riscv/insns/cvtu_s_w.h @@ -1,3 +1,3 @@ require_fp; -FRC = int32_to_float32(FRA); +FRC = ui32_to_f32(FRA); set_fp_exceptions; diff --git a/riscv/insns/div_d.h b/riscv/insns/div_d.h index 3b47563..884effc 100644 --- a/riscv/insns/div_d.h +++ b/riscv/insns/div_d.h @@ -1,3 +1,3 @@ require_fp; -FRC = float64_div(FRA, FRB); +FRC = f64_div(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/div_s.h b/riscv/insns/div_s.h index cb5c9bd..b2d0869 100644 --- a/riscv/insns/div_s.h +++ b/riscv/insns/div_s.h @@ -1,3 +1,3 @@ require_fp; -FRC = float32_div(FRA, FRB); +FRC = f32_div(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/mul_d.h b/riscv/insns/mul_d.h index b2a0dbf..d16e6c5 100644 --- a/riscv/insns/mul_d.h +++ b/riscv/insns/mul_d.h @@ -1,3 +1,3 @@ require_fp; -FRC = float64_mul(FRA, FRB); +FRC = f64_mul(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/mul_s.h b/riscv/insns/mul_s.h index e7d4f3f..d700d84 100644 --- a/riscv/insns/mul_s.h +++ b/riscv/insns/mul_s.h @@ -1,3 +1,3 @@ require_fp; -FRC = float32_mul(FRA, FRB); +FRC = f32_mul(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/sqrt_d.h b/riscv/insns/sqrt_d.h index 3f831f5..fdfc19a 100644 --- a/riscv/insns/sqrt_d.h +++ b/riscv/insns/sqrt_d.h @@ -1,3 +1,3 @@ require_fp; -FRC = float64_sqrt(FRA); +FRC = f64_sqrt(FRA); set_fp_exceptions; diff --git a/riscv/insns/sqrt_s.h b/riscv/insns/sqrt_s.h index 51b5892..5f2968c 100644 --- a/riscv/insns/sqrt_s.h +++ b/riscv/insns/sqrt_s.h @@ -1,3 +1,3 @@ require_fp; -FRC = float32_sqrt(FRA); +FRC = f32_sqrt(FRA); set_fp_exceptions; diff --git a/riscv/insns/sub_d.h b/riscv/insns/sub_d.h index 55d0e86..023a1f3 100644 --- a/riscv/insns/sub_d.h +++ b/riscv/insns/sub_d.h @@ -1,3 +1,3 @@ require_fp; -FRC = float64_sub(FRA, FRB); +FRC = f64_sub(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/sub_s.h b/riscv/insns/sub_s.h index 4a359bf..fd83da0 100644 --- a/riscv/insns/sub_s.h +++ b/riscv/insns/sub_s.h @@ -1,3 +1,3 @@ require_fp; -FRC = float32_sub(FRA, FRB); +FRC = f32_sub(FRA, FRB); set_fp_exceptions; diff --git a/riscv/insns/trunc_l_d.h b/riscv/insns/trunc_l_d.h index ecca8cd..0fad400 100644 --- a/riscv/insns/trunc_l_d.h +++ b/riscv/insns/trunc_l_d.h @@ -1,3 +1,3 @@ require_fp; -FRC = float64_to_int64_round_to_zero(FRA); +FRC = f64_to_i64_r_minMag(FRA,true); set_fp_exceptions; diff --git a/riscv/insns/trunc_l_s.h b/riscv/insns/trunc_l_s.h index 9dd0e51..5d5a940 100644 --- a/riscv/insns/trunc_l_s.h +++ b/riscv/insns/trunc_l_s.h @@ -1,3 +1,3 @@ require_fp; -FRC = float32_to_int64_round_to_zero(FRA); +FRC = f32_to_i64_r_minMag(FRA,true); set_fp_exceptions; diff --git a/riscv/insns/trunc_w_d.h b/riscv/insns/trunc_w_d.h index 9b7cdb0..b91640a 100644 --- a/riscv/insns/trunc_w_d.h +++ b/riscv/insns/trunc_w_d.h @@ -1,3 +1,3 @@ require_fp; -FRC = float64_to_int32_round_to_zero(FRA); +FRC = f64_to_i32_r_minMag(FRA,true); set_fp_exceptions; diff --git a/riscv/insns/trunc_w_s.h b/riscv/insns/trunc_w_s.h index 147ec8b..73974d1 100644 --- a/riscv/insns/trunc_w_s.h +++ b/riscv/insns/trunc_w_s.h @@ -1,3 +1,3 @@ require_fp; -FRC = float32_to_int32_round_to_zero(FRA); +FRC = f32_to_i32_r_minMag(FRA,true); set_fp_exceptions; diff --git a/riscv/insns/truncu_l_d.h b/riscv/insns/truncu_l_d.h index ecca8cd..0fad400 100644 --- a/riscv/insns/truncu_l_d.h +++ b/riscv/insns/truncu_l_d.h @@ -1,3 +1,3 @@ require_fp; -FRC = float64_to_int64_round_to_zero(FRA); +FRC = f64_to_i64_r_minMag(FRA,true); set_fp_exceptions; diff --git a/riscv/insns/truncu_l_s.h b/riscv/insns/truncu_l_s.h index 9dd0e51..5d5a940 100644 --- a/riscv/insns/truncu_l_s.h +++ b/riscv/insns/truncu_l_s.h @@ -1,3 +1,3 @@ require_fp; -FRC = float32_to_int64_round_to_zero(FRA); +FRC = f32_to_i64_r_minMag(FRA,true); set_fp_exceptions; diff --git a/riscv/insns/truncu_w_d.h b/riscv/insns/truncu_w_d.h index 9b7cdb0..255fba5 100644 --- a/riscv/insns/truncu_w_d.h +++ b/riscv/insns/truncu_w_d.h @@ -1,3 +1,3 @@ require_fp; -FRC = float64_to_int32_round_to_zero(FRA); +FRC = f64_to_ui32_r_minMag(FRA,true); set_fp_exceptions; diff --git a/riscv/insns/truncu_w_s.h b/riscv/insns/truncu_w_s.h index 147ec8b..337b9ea 100644 --- a/riscv/insns/truncu_w_s.h +++ b/riscv/insns/truncu_w_s.h @@ -1,3 +1,3 @@ require_fp; -FRC = float32_to_int32_round_to_zero(FRA); +FRC = f32_to_ui32_r_minMag(FRA,true); set_fp_exceptions; diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 3f6427d..6d55c80 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -1,4 +1,6 @@ -riscv_subproject_deps = softfloat \ +riscv_subproject_deps = \ + softfloat_riscv \ + softfloat \ riscv_hdrs = \ applink.h \ diff --git a/softfloat/8086/OLD-specialize.c b/softfloat/8086/OLD-specialize.c new file mode 100755 index 0000000..ffb306d --- /dev/null +++ b/softfloat/8086/OLD-specialize.c @@ -0,0 +1,40 @@ + +/*============================================================================ + +*** FIX. + +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +| Underflow tininess-detection mode, statically initialized to default value. +| (The declaration in `softfloat.h' must match the `int8' type here.) +*----------------------------------------------------------------------------*/ +bool float_detectTininess = float_tininess_afterRounding; + diff --git a/softfloat/8086/OLD-specialize.h b/softfloat/8086/OLD-specialize.h new file mode 100755 index 0000000..9e4461c --- /dev/null +++ b/softfloat/8086/OLD-specialize.h @@ -0,0 +1,379 @@ + +/*============================================================================ + +*** FIX. + +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +| Internal canonical NaN format. +*----------------------------------------------------------------------------*/ +*** COMMON +typedef struct { + flag sign; + uint128_t bits; +} commonNaNT; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated single-precision NaN. +*----------------------------------------------------------------------------*/ +#define float32Bits_defaultNaN 0xFFC00000 + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is a NaN; +| otherwise, returns 0. +*----------------------------------------------------------------------------*/ +*** COMMON +#define softfloat_isNaNFloat32Bits( a ) ( 0xFF000000 < (uint32_t) ( a )<<1 ) + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is a signaling +| NaN; otherwise, returns 0. +*----------------------------------------------------------------------------*/ +inline bool softfloat_isSigNaNFloat32Bits( uint32_t a ) + { return ( ( a>>22 & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); } + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +commonNaNT softfloat_NaNFromFloat32Bits( uint32_t ); +uint32_t softfloat_float32BitsFromNaN( commonNaNT ); +uint32_t softfloat_propNaNFloat32Bits( uint32_t, uint32_t ); + +/*---------------------------------------------------------------------------- +| The pattern for a default generated double-precision NaN. +*----------------------------------------------------------------------------*/ +#define float64Bits_defaultNaN 0xFFF8000000000000 + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is a NaN; +| otherwise, returns 0. +*----------------------------------------------------------------------------*/ +*** COMMON +#define softfloat_isNaNFloat64Bits( a ) ( 0xFFE0000000000000 < (uint64_t) ( a )<<1 ) + + + + + + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is a signaling +| NaN; otherwise, returns 0. +*----------------------------------------------------------------------------*/ + +flag float64_is_signaling_nan( float64 a ) +{ + + return + ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) + && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT float64ToCommonNaN( float64 a ) +{ + commonNaNT z; + + if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a>>63; + z.low = 0; + z.high = a<<12; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the double- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +static float64 commonNaNToFloat64( commonNaNT a ) +{ + + return + ( ( (bits64) a.sign )<<63 ) + | LIT64( 0x7FF8000000000000 ) + | ( a.high>>12 ); + +} + +/*---------------------------------------------------------------------------- +| Takes two double-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static float64 propagateFloat64NaN( float64 a, float64 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = float64_is_nan( a ); + aIsSignalingNaN = float64_is_signaling_nan( a ); + bIsNaN = float64_is_nan( b ); + bIsSignalingNaN = float64_is_signaling_nan( b ); + a |= LIT64( 0x0008000000000000 ); + b |= LIT64( 0x0008000000000000 ); + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsSignalingNaN ) { + if ( bIsSignalingNaN ) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if ( aIsNaN ) { + if ( bIsSignalingNaN | ! bIsNaN ) return a; + returnLargerSignificand: + if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b; + if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a; + return ( a < b ) ? a : b; + } + else { + return b; + } + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. The +| `high' and `low' values hold the most- and least-significant bits, +| respectively. +*----------------------------------------------------------------------------*/ +#define floatx80_default_nan_high 0xFFFF +#define floatx80_default_nan_low LIT64( 0xC000000000000000 ) + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is a +| NaN; otherwise, returns 0. +*----------------------------------------------------------------------------*/ + +flag floatx80_is_nan( floatx80 a ) +{ + + return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is a +| signaling NaN; otherwise, returns 0. +*----------------------------------------------------------------------------*/ + +flag floatx80_is_signaling_nan( floatx80 a ) +{ + bits64 aLow; + + aLow = a.low & ~ LIT64( 0x4000000000000000 ); + return + ( ( a.high & 0x7FFF ) == 0x7FFF ) + && (bits64) ( aLow<<1 ) + && ( a.low == aLow ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT floatx80ToCommonNaN( floatx80 a ) +{ + commonNaNT z; + + if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a.high>>15; + z.low = 0; + z.high = a.low<<1; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the extended +| double-precision floating-point format. +*----------------------------------------------------------------------------*/ + +static floatx80 commonNaNToFloatx80( commonNaNT a ) +{ + floatx80 z; + + z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); + z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; + return z; + +} + +/*---------------------------------------------------------------------------- +| Takes two extended double-precision floating-point values `a' and `b', one +| of which is a NaN, and returns the appropriate NaN result. If either `a' or +| `b' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = floatx80_is_nan( a ); + aIsSignalingNaN = floatx80_is_signaling_nan( a ); + bIsNaN = floatx80_is_nan( b ); + bIsSignalingNaN = floatx80_is_signaling_nan( b ); + a.low |= LIT64( 0xC000000000000000 ); + b.low |= LIT64( 0xC000000000000000 ); + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsSignalingNaN ) { + if ( bIsSignalingNaN ) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if ( aIsNaN ) { + if ( bIsSignalingNaN | ! bIsNaN ) return a; + returnLargerSignificand: + if ( a.low < b.low ) return b; + if ( b.low < a.low ) return a; + return ( a.high < b.high ) ? a : b; + } + else { + return b; + } + +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| The pattern for a default generated quadruple-precision NaN. The `high' and +| `low' values hold the most- and least-significant bits, respectively. +*----------------------------------------------------------------------------*/ +#define float128_default_nan_high LIT64( 0xFFFF800000000000 ) +#define float128_default_nan_low LIT64( 0x0000000000000000 ) + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; +| otherwise, returns 0. +*----------------------------------------------------------------------------*/ + +flag float128_is_nan( float128 a ) +{ + + return + ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) + && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is a +| signaling NaN; otherwise, returns 0. +*----------------------------------------------------------------------------*/ + +flag float128_is_signaling_nan( float128 a ) +{ + + return + ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) + && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT float128ToCommonNaN( float128 a ) +{ + commonNaNT z; + + if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a.high>>63; + shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the quadruple- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +static float128 commonNaNToFloat128( commonNaNT a ) +{ + float128 z; + + shift128Right( a.high, a.low, 16, &z.high, &z.low ); + z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); + return z; + +} + +/*---------------------------------------------------------------------------- +| Takes two quadruple-precision floating-point values `a' and `b', one of +| which is a NaN, and returns the appropriate NaN result. If either `a' or +| `b' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static float128 propagateFloat128NaN( float128 a, float128 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = float128_is_nan( a ); + aIsSignalingNaN = float128_is_signaling_nan( a ); + bIsNaN = float128_is_nan( b ); + bIsSignalingNaN = float128_is_signaling_nan( b ); + a.high |= LIT64( 0x0000800000000000 ); + b.high |= LIT64( 0x0000800000000000 ); + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsSignalingNaN ) { + if ( bIsSignalingNaN ) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if ( aIsNaN ) { + if ( bIsSignalingNaN | ! bIsNaN ) return a; + returnLargerSignificand: + if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b; + if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a; + return ( a.high < b.high ) ? a : b; + } + else { + return b; + } + +} + +#endif + diff --git a/softfloat/8086/platform.h b/softfloat/8086/platform.h new file mode 100755 index 0000000..9355edf --- /dev/null +++ b/softfloat/8086/platform.h @@ -0,0 +1,38 @@ + +/*============================================================================ + +*** FIX. + +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define LITTLEENDIAN + diff --git a/softfloat/8086/s_commonNaNToF32UI.c b/softfloat/8086/s_commonNaNToF32UI.c new file mode 100755 index 0000000..3b96c41 --- /dev/null +++ b/softfloat/8086/s_commonNaNToF32UI.c @@ -0,0 +1,17 @@ + +#include +#include "platform.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the single- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN a ) +{ + + return (uint_fast32_t) a.sign<<31 | 0x7FC00000 | a.v64>>41; + +} + diff --git a/softfloat/8086/s_commonNaNToF64UI.c b/softfloat/8086/s_commonNaNToF64UI.c new file mode 100755 index 0000000..474ceee --- /dev/null +++ b/softfloat/8086/s_commonNaNToF64UI.c @@ -0,0 +1,19 @@ + +#include +#include "platform.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the double- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +uint_fast64_t softfloat_commonNaNToF64UI( struct commonNaN a ) +{ + + return + (uint_fast64_t) a.sign<<63 | UINT64_C( 0x7FF8000000000000 ) + | a.v64>>12; + +} + diff --git a/softfloat/8086/s_f32UIToCommonNaN.c b/softfloat/8086/s_f32UIToCommonNaN.c new file mode 100755 index 0000000..067e8da --- /dev/null +++ b/softfloat/8086/s_f32UIToCommonNaN.c @@ -0,0 +1,25 @@ + +#include +#include "platform.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +struct commonNaN softfloat_f32UIToCommonNaN( uint_fast32_t uiA ) +{ + struct commonNaN z; + + if ( softfloat_isSigNaNF32UI( uiA ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + z.sign = uiA>>31; + z.v64 = (uint_fast64_t) uiA<<41; + z.v0 = 0; + return z; + +} + diff --git a/softfloat/8086/s_f64UIToCommonNaN.c b/softfloat/8086/s_f64UIToCommonNaN.c new file mode 100755 index 0000000..f933ded --- /dev/null +++ b/softfloat/8086/s_f64UIToCommonNaN.c @@ -0,0 +1,25 @@ + +#include +#include "platform.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +struct commonNaN softfloat_f64UIToCommonNaN( uint_fast64_t uiA ) +{ + struct commonNaN z; + + if ( softfloat_isSigNaNF64UI( uiA ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + z.sign = uiA>>63; + z.v64 = uiA<<12; + z.v0 = 0; + return z; + +} + diff --git a/softfloat/8086/s_isSigNaNF32UI.c b/softfloat/8086/s_isSigNaNF32UI.c new file mode 100755 index 0000000..0a9c33f --- /dev/null +++ b/softfloat/8086/s_isSigNaNF32UI.c @@ -0,0 +1,13 @@ + +#include +#include +#include "platform.h" +#include "specialize.h" + +bool softfloat_isSigNaNF32UI( uint_fast32_t ui ) +{ + + return ( ( ui>>22 & 0x1FF ) == 0x1FE ) && ( ui & 0x003FFFFF ); + +} + diff --git a/softfloat/8086/s_isSigNaNF64UI.c b/softfloat/8086/s_isSigNaNF64UI.c new file mode 100755 index 0000000..d255213 --- /dev/null +++ b/softfloat/8086/s_isSigNaNF64UI.c @@ -0,0 +1,15 @@ + +#include +#include +#include "platform.h" +#include "specialize.h" + +bool softfloat_isSigNaNF64UI( uint_fast64_t ui ) +{ + + return + ( ( ui>>51 & 0xFFF ) == 0xFFE ) + && ( ui & UINT64_C( 0x0007FFFFFFFFFFFF ) ); + +} + diff --git a/softfloat/8086/s_propagateNaNF32UI.c b/softfloat/8086/s_propagateNaNF32UI.c new file mode 100755 index 0000000..07774e8 --- /dev/null +++ b/softfloat/8086/s_propagateNaNF32UI.c @@ -0,0 +1,55 @@ + +/*** UPDATE COMMENTS. ***/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Takes two single-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +uint_fast32_t + softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ) +{ + bool isNaNA, isSigNaNA, isNaNB, isSigNaNB; + uint_fast32_t uiMagA, uiMagB; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + isNaNA = isNaNF32UI( uiA ); + isSigNaNA = softfloat_isSigNaNF32UI( uiA ); + isNaNB = isNaNF32UI( uiB ); + isSigNaNB = softfloat_isSigNaNF32UI( uiB ); + /*------------------------------------------------------------------------ + | Make NaNs non-signaling. + *------------------------------------------------------------------------*/ + uiA |= 0x00400000; + uiB |= 0x00400000; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isSigNaNA | isSigNaNB ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + if ( isSigNaNA ) { + if ( isSigNaNB ) goto returnLargerSignificand; + return isNaNB ? uiB : uiA; + } else if ( isNaNA ) { + if ( isSigNaNB || ! isNaNB ) return uiA; + returnLargerSignificand: + uiMagA = uiA<<1; + uiMagB = uiB<<1; + if ( uiMagA < uiMagB ) return uiB; + if ( uiMagB < uiMagA ) return uiA; + return ( uiA < uiB ) ? uiA : uiB; + } else { + return uiB; + } + +} + diff --git a/softfloat/8086/s_propagateNaNF64UI.c b/softfloat/8086/s_propagateNaNF64UI.c new file mode 100755 index 0000000..0ff6446 --- /dev/null +++ b/softfloat/8086/s_propagateNaNF64UI.c @@ -0,0 +1,55 @@ + +/*** UPDATE COMMENTS. ***/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Takes two double-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +uint_fast64_t + softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ) +{ + bool isNaNA, isSigNaNA, isNaNB, isSigNaNB; + uint_fast64_t uiMagA, uiMagB; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + isNaNA = isNaNF64UI( uiA ); + isSigNaNA = softfloat_isSigNaNF64UI( uiA ); + isNaNB = isNaNF64UI( uiB ); + isSigNaNB = softfloat_isSigNaNF64UI( uiB ); + /*------------------------------------------------------------------------ + | Make NaNs non-signaling. + *------------------------------------------------------------------------*/ + uiA |= UINT64_C( 0x0008000000000000 ); + uiB |= UINT64_C( 0x0008000000000000 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isSigNaNA | isSigNaNB ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + if ( isSigNaNA ) { + if ( isSigNaNB ) goto returnLargerSignificand; + return isNaNB ? uiB : uiA; + } else if ( isNaNA ) { + if ( isSigNaNB || ! isNaNB ) return uiA; + returnLargerSignificand: + uiMagA = uiA & UINT64_C( 0x7FFFFFFFFFFFFFFF ); + uiMagB = uiB & UINT64_C( 0x7FFFFFFFFFFFFFFF ); + if ( uiMagA < uiMagB ) return uiB; + if ( uiMagB < uiMagA ) return uiA; + return ( uiA < uiB ) ? uiA : uiB; + } else { + return uiB; + } + +} + diff --git a/softfloat/8086/softfloat_raiseFlags.c b/softfloat/8086/softfloat_raiseFlags.c new file mode 100755 index 0000000..c0c0dc8 --- /dev/null +++ b/softfloat/8086/softfloat_raiseFlags.c @@ -0,0 +1,51 @@ + +/*============================================================================ + +*** FIX. + +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +#include "platform.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Raises the exceptions specified by `flags'. Floating-point traps can be +| defined here if desired. It is currently not possible for such a trap +| to substitute a result value. If traps are not implemented, this routine +| should be simply `float_exception_flags |= flags;'. +*----------------------------------------------------------------------------*/ + +void softfloat_raiseFlags( int_fast8_t flags ) +{ + + softfloat_exceptionFlags |= flags; + +} + diff --git a/softfloat/8086/softfloat_types.h b/softfloat/8086/softfloat_types.h new file mode 100755 index 0000000..b5c1828 --- /dev/null +++ b/softfloat/8086/softfloat_types.h @@ -0,0 +1,16 @@ + +#ifndef softfloat_types_h +#define softfloat_types_h + +/*** COMMENTS. ***/ + +#include +#include + +typedef struct { uint32_t v; } float32_t; +typedef struct { uint64_t v; } float64_t; +typedef struct { uint64_t v; uint16_t x; } floatx80_t; +typedef struct { uint64_t v[ 2 ]; } float128_t; + +#endif + diff --git a/softfloat/8086/specialize.h b/softfloat/8086/specialize.h new file mode 100755 index 0000000..ca0bb1d --- /dev/null +++ b/softfloat/8086/specialize.h @@ -0,0 +1,113 @@ + +/*============================================================================ + +*** FIX. + +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +#include +#include + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define init_detectTininess softfloat_tininess_afterRounding; + +/*---------------------------------------------------------------------------- +| Structure used to transfer NaN representations from one format to another. +*----------------------------------------------------------------------------*/ +struct commonNaN { + bool sign; + uint64_t v64, v0; +}; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated single-precision NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF32UI 0xFFC00000 + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is a signaling +| NaN; otherwise, returns 0. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 1 <= INLINE_LEVEL ) +INLINE bool softfloat_isSigNaNF32UI( uint_fast32_t ui ) + { return ( ( ui>>22 & 0x1FF ) == 0x1FE ) && ( ui & 0x003FFFFF ); } +#else +bool softfloat_isSigNaNF32UI( uint_fast32_t ); +#endif + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +struct commonNaN softfloat_f32UIToCommonNaN( uint_fast32_t ); +#if defined INLINE_LEVEL && ( 1 <= INLINE_LEVEL ) +INLINE uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN a ) + { return (uint_fast32_t) a.sign<<31 | 0x7FC00000 | a.v64>>41; } +#else +uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN ); +#endif + +/*---------------------------------------------------------------------------- +| Takes two single-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast32_t softfloat_propagateNaNF32UI( uint_fast32_t, uint_fast32_t ); + +/*---------------------------------------------------------------------------- +| The pattern for a default generated double-precision NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF64UI UINT64_C(0xFFF8000000000000) + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 1 <= INLINE_LEVEL ) +INLINE bool softfloat_isSigNaNF64UI( uint_fast64_t ui ) +{ + return + ( ( ui>>51 & 0xFFF ) == 0xFFE ) + && ( ui & UINT64_C( 0x0007FFFFFFFFFFFF ) ); +} +#else +bool softfloat_isSigNaNF64UI( uint_fast64_t ); +#endif + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +/*** MIGHT BE INLINE'D. ***/ +struct commonNaN softfloat_f64UIToCommonNaN( uint_fast64_t ); +uint_fast64_t softfloat_commonNaNToF64UI( struct commonNaN ); + +/*---------------------------------------------------------------------------- +| Takes two double-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast64_t softfloat_propagateNaNF64UI( uint_fast64_t, uint_fast64_t ); + diff --git a/softfloat/SoftFloat-3/source/8086/OLD-specialize.c b/softfloat/SoftFloat-3/source/8086/OLD-specialize.c deleted file mode 100755 index ffb306d..0000000 --- a/softfloat/SoftFloat-3/source/8086/OLD-specialize.c +++ /dev/null @@ -1,40 +0,0 @@ - -/*============================================================================ - -*** FIX. - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Underflow tininess-detection mode, statically initialized to default value. -| (The declaration in `softfloat.h' must match the `int8' type here.) -*----------------------------------------------------------------------------*/ -bool float_detectTininess = float_tininess_afterRounding; - diff --git a/softfloat/SoftFloat-3/source/8086/OLD-specialize.h b/softfloat/SoftFloat-3/source/8086/OLD-specialize.h deleted file mode 100755 index 9e4461c..0000000 --- a/softfloat/SoftFloat-3/source/8086/OLD-specialize.h +++ /dev/null @@ -1,379 +0,0 @@ - -/*============================================================================ - -*** FIX. - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Internal canonical NaN format. -*----------------------------------------------------------------------------*/ -*** COMMON -typedef struct { - flag sign; - uint128_t bits; -} commonNaNT; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -#define float32Bits_defaultNaN 0xFFC00000 - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a NaN; -| otherwise, returns 0. -*----------------------------------------------------------------------------*/ -*** COMMON -#define softfloat_isNaNFloat32Bits( a ) ( 0xFF000000 < (uint32_t) ( a )<<1 ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise, returns 0. -*----------------------------------------------------------------------------*/ -inline bool softfloat_isSigNaNFloat32Bits( uint32_t a ) - { return ( ( a>>22 & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); } - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -commonNaNT softfloat_NaNFromFloat32Bits( uint32_t ); -uint32_t softfloat_float32BitsFromNaN( commonNaNT ); -uint32_t softfloat_propNaNFloat32Bits( uint32_t, uint32_t ); - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -#define float64Bits_defaultNaN 0xFFF8000000000000 - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a NaN; -| otherwise, returns 0. -*----------------------------------------------------------------------------*/ -*** COMMON -#define softfloat_isNaNFloat64Bits( a ) ( 0xFFE0000000000000 < (uint64_t) ( a )<<1 ) - - - - - - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a signaling -| NaN; otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -flag float64_is_signaling_nan( float64 a ) -{ - - return - ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) - && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float64ToCommonNaN( float64 a ) -{ - commonNaNT z; - - if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a>>63; - z.low = 0; - z.high = a<<12; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float64 commonNaNToFloat64( commonNaNT a ) -{ - - return - ( ( (bits64) a.sign )<<63 ) - | LIT64( 0x7FF8000000000000 ) - | ( a.high>>12 ); - -} - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float64 propagateFloat64NaN( float64 a, float64 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float64_is_nan( a ); - aIsSignalingNaN = float64_is_signaling_nan( a ); - bIsNaN = float64_is_nan( b ); - bIsSignalingNaN = float64_is_signaling_nan( b ); - a |= LIT64( 0x0008000000000000 ); - b |= LIT64( 0x0008000000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsSignalingNaN ) { - if ( bIsSignalingNaN ) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if ( aIsNaN ) { - if ( bIsSignalingNaN | ! bIsNaN ) return a; - returnLargerSignificand: - if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b; - if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a; - return ( a < b ) ? a : b; - } - else { - return b; - } - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. The -| `high' and `low' values hold the most- and least-significant bits, -| respectively. -*----------------------------------------------------------------------------*/ -#define floatx80_default_nan_high 0xFFFF -#define floatx80_default_nan_low LIT64( 0xC000000000000000 ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| NaN; otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -flag floatx80_is_nan( floatx80 a ) -{ - - return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| signaling NaN; otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -flag floatx80_is_signaling_nan( floatx80 a ) -{ - bits64 aLow; - - aLow = a.low & ~ LIT64( 0x4000000000000000 ); - return - ( ( a.high & 0x7FFF ) == 0x7FFF ) - && (bits64) ( aLow<<1 ) - && ( a.low == aLow ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the -| invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT floatx80ToCommonNaN( floatx80 a ) -{ - commonNaNT z; - - if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>15; - z.low = 0; - z.high = a.low<<1; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the extended -| double-precision floating-point format. -*----------------------------------------------------------------------------*/ - -static floatx80 commonNaNToFloatx80( commonNaNT a ) -{ - floatx80 z; - - z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); - z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two extended double-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = floatx80_is_nan( a ); - aIsSignalingNaN = floatx80_is_signaling_nan( a ); - bIsNaN = floatx80_is_nan( b ); - bIsSignalingNaN = floatx80_is_signaling_nan( b ); - a.low |= LIT64( 0xC000000000000000 ); - b.low |= LIT64( 0xC000000000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsSignalingNaN ) { - if ( bIsSignalingNaN ) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if ( aIsNaN ) { - if ( bIsSignalingNaN | ! bIsNaN ) return a; - returnLargerSignificand: - if ( a.low < b.low ) return b; - if ( b.low < a.low ) return a; - return ( a.high < b.high ) ? a : b; - } - else { - return b; - } - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. The `high' and -| `low' values hold the most- and least-significant bits, respectively. -*----------------------------------------------------------------------------*/ -#define float128_default_nan_high LIT64( 0xFFFF800000000000 ) -#define float128_default_nan_low LIT64( 0x0000000000000000 ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; -| otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -flag float128_is_nan( float128 a ) -{ - - return - ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) - && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a -| signaling NaN; otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -flag float128_is_signaling_nan( float128 a ) -{ - - return - ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) - && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float128ToCommonNaN( float128 a ) -{ - commonNaNT z; - - if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>63; - shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the quadruple- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float128 commonNaNToFloat128( commonNaNT a ) -{ - float128 z; - - shift128Right( a.high, a.low, 16, &z.high, &z.low ); - z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float128 propagateFloat128NaN( float128 a, float128 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float128_is_nan( a ); - aIsSignalingNaN = float128_is_signaling_nan( a ); - bIsNaN = float128_is_nan( b ); - bIsSignalingNaN = float128_is_signaling_nan( b ); - a.high |= LIT64( 0x0000800000000000 ); - b.high |= LIT64( 0x0000800000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsSignalingNaN ) { - if ( bIsSignalingNaN ) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if ( aIsNaN ) { - if ( bIsSignalingNaN | ! bIsNaN ) return a; - returnLargerSignificand: - if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b; - if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a; - return ( a.high < b.high ) ? a : b; - } - else { - return b; - } - -} - -#endif - diff --git a/softfloat/SoftFloat-3/source/8086/platform.h b/softfloat/SoftFloat-3/source/8086/platform.h deleted file mode 100755 index 9355edf..0000000 --- a/softfloat/SoftFloat-3/source/8086/platform.h +++ /dev/null @@ -1,38 +0,0 @@ - -/*============================================================================ - -*** FIX. - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define LITTLEENDIAN - diff --git a/softfloat/SoftFloat-3/source/8086/s_commonNaNToF32UI.c b/softfloat/SoftFloat-3/source/8086/s_commonNaNToF32UI.c deleted file mode 100755 index 3b96c41..0000000 --- a/softfloat/SoftFloat-3/source/8086/s_commonNaNToF32UI.c +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include "platform.h" -#include "specialize.h" - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the single- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN a ) -{ - - return (uint_fast32_t) a.sign<<31 | 0x7FC00000 | a.v64>>41; - -} - diff --git a/softfloat/SoftFloat-3/source/8086/s_commonNaNToF64UI.c b/softfloat/SoftFloat-3/source/8086/s_commonNaNToF64UI.c deleted file mode 100755 index 474ceee..0000000 --- a/softfloat/SoftFloat-3/source/8086/s_commonNaNToF64UI.c +++ /dev/null @@ -1,19 +0,0 @@ - -#include -#include "platform.h" -#include "specialize.h" - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -uint_fast64_t softfloat_commonNaNToF64UI( struct commonNaN a ) -{ - - return - (uint_fast64_t) a.sign<<63 | UINT64_C( 0x7FF8000000000000 ) - | a.v64>>12; - -} - diff --git a/softfloat/SoftFloat-3/source/8086/s_f32UIToCommonNaN.c b/softfloat/SoftFloat-3/source/8086/s_f32UIToCommonNaN.c deleted file mode 100755 index 067e8da..0000000 --- a/softfloat/SoftFloat-3/source/8086/s_f32UIToCommonNaN.c +++ /dev/null @@ -1,25 +0,0 @@ - -#include -#include "platform.h" -#include "specialize.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ -struct commonNaN softfloat_f32UIToCommonNaN( uint_fast32_t uiA ) -{ - struct commonNaN z; - - if ( softfloat_isSigNaNF32UI( uiA ) ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - z.sign = uiA>>31; - z.v64 = (uint_fast64_t) uiA<<41; - z.v0 = 0; - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/8086/s_f64UIToCommonNaN.c b/softfloat/SoftFloat-3/source/8086/s_f64UIToCommonNaN.c deleted file mode 100755 index f933ded..0000000 --- a/softfloat/SoftFloat-3/source/8086/s_f64UIToCommonNaN.c +++ /dev/null @@ -1,25 +0,0 @@ - -#include -#include "platform.h" -#include "specialize.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ -struct commonNaN softfloat_f64UIToCommonNaN( uint_fast64_t uiA ) -{ - struct commonNaN z; - - if ( softfloat_isSigNaNF64UI( uiA ) ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - z.sign = uiA>>63; - z.v64 = uiA<<12; - z.v0 = 0; - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/8086/s_isSigNaNF32UI.c b/softfloat/SoftFloat-3/source/8086/s_isSigNaNF32UI.c deleted file mode 100755 index 0a9c33f..0000000 --- a/softfloat/SoftFloat-3/source/8086/s_isSigNaNF32UI.c +++ /dev/null @@ -1,13 +0,0 @@ - -#include -#include -#include "platform.h" -#include "specialize.h" - -bool softfloat_isSigNaNF32UI( uint_fast32_t ui ) -{ - - return ( ( ui>>22 & 0x1FF ) == 0x1FE ) && ( ui & 0x003FFFFF ); - -} - diff --git a/softfloat/SoftFloat-3/source/8086/s_isSigNaNF64UI.c b/softfloat/SoftFloat-3/source/8086/s_isSigNaNF64UI.c deleted file mode 100755 index d255213..0000000 --- a/softfloat/SoftFloat-3/source/8086/s_isSigNaNF64UI.c +++ /dev/null @@ -1,15 +0,0 @@ - -#include -#include -#include "platform.h" -#include "specialize.h" - -bool softfloat_isSigNaNF64UI( uint_fast64_t ui ) -{ - - return - ( ( ui>>51 & 0xFFF ) == 0xFFE ) - && ( ui & UINT64_C( 0x0007FFFFFFFFFFFF ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/8086/s_propagateNaNF32UI.c b/softfloat/SoftFloat-3/source/8086/s_propagateNaNF32UI.c deleted file mode 100755 index 07774e8..0000000 --- a/softfloat/SoftFloat-3/source/8086/s_propagateNaNF32UI.c +++ /dev/null @@ -1,55 +0,0 @@ - -/*** UPDATE COMMENTS. ***/ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -uint_fast32_t - softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ) -{ - bool isNaNA, isSigNaNA, isNaNB, isSigNaNB; - uint_fast32_t uiMagA, uiMagB; - - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - isNaNA = isNaNF32UI( uiA ); - isSigNaNA = softfloat_isSigNaNF32UI( uiA ); - isNaNB = isNaNF32UI( uiB ); - isSigNaNB = softfloat_isSigNaNF32UI( uiB ); - /*------------------------------------------------------------------------ - | Make NaNs non-signaling. - *------------------------------------------------------------------------*/ - uiA |= 0x00400000; - uiB |= 0x00400000; - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if ( isSigNaNA | isSigNaNB ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - if ( isSigNaNA ) { - if ( isSigNaNB ) goto returnLargerSignificand; - return isNaNB ? uiB : uiA; - } else if ( isNaNA ) { - if ( isSigNaNB || ! isNaNB ) return uiA; - returnLargerSignificand: - uiMagA = uiA<<1; - uiMagB = uiB<<1; - if ( uiMagA < uiMagB ) return uiB; - if ( uiMagB < uiMagA ) return uiA; - return ( uiA < uiB ) ? uiA : uiB; - } else { - return uiB; - } - -} - diff --git a/softfloat/SoftFloat-3/source/8086/s_propagateNaNF64UI.c b/softfloat/SoftFloat-3/source/8086/s_propagateNaNF64UI.c deleted file mode 100755 index 0ff6446..0000000 --- a/softfloat/SoftFloat-3/source/8086/s_propagateNaNF64UI.c +++ /dev/null @@ -1,55 +0,0 @@ - -/*** UPDATE COMMENTS. ***/ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -uint_fast64_t - softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ) -{ - bool isNaNA, isSigNaNA, isNaNB, isSigNaNB; - uint_fast64_t uiMagA, uiMagB; - - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - isNaNA = isNaNF64UI( uiA ); - isSigNaNA = softfloat_isSigNaNF64UI( uiA ); - isNaNB = isNaNF64UI( uiB ); - isSigNaNB = softfloat_isSigNaNF64UI( uiB ); - /*------------------------------------------------------------------------ - | Make NaNs non-signaling. - *------------------------------------------------------------------------*/ - uiA |= UINT64_C( 0x0008000000000000 ); - uiB |= UINT64_C( 0x0008000000000000 ); - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if ( isSigNaNA | isSigNaNB ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - if ( isSigNaNA ) { - if ( isSigNaNB ) goto returnLargerSignificand; - return isNaNB ? uiB : uiA; - } else if ( isNaNA ) { - if ( isSigNaNB || ! isNaNB ) return uiA; - returnLargerSignificand: - uiMagA = uiA & UINT64_C( 0x7FFFFFFFFFFFFFFF ); - uiMagB = uiB & UINT64_C( 0x7FFFFFFFFFFFFFFF ); - if ( uiMagA < uiMagB ) return uiB; - if ( uiMagB < uiMagA ) return uiA; - return ( uiA < uiB ) ? uiA : uiB; - } else { - return uiB; - } - -} - diff --git a/softfloat/SoftFloat-3/source/8086/softfloat_raiseFlags.c b/softfloat/SoftFloat-3/source/8086/softfloat_raiseFlags.c deleted file mode 100755 index c0c0dc8..0000000 --- a/softfloat/SoftFloat-3/source/8086/softfloat_raiseFlags.c +++ /dev/null @@ -1,51 +0,0 @@ - -/*============================================================================ - -*** FIX. - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -#include "platform.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Raises the exceptions specified by `flags'. Floating-point traps can be -| defined here if desired. It is currently not possible for such a trap -| to substitute a result value. If traps are not implemented, this routine -| should be simply `float_exception_flags |= flags;'. -*----------------------------------------------------------------------------*/ - -void softfloat_raiseFlags( int_fast8_t flags ) -{ - - softfloat_exceptionFlags |= flags; - -} - diff --git a/softfloat/SoftFloat-3/source/8086/softfloat_types.h b/softfloat/SoftFloat-3/source/8086/softfloat_types.h deleted file mode 100755 index b5c1828..0000000 --- a/softfloat/SoftFloat-3/source/8086/softfloat_types.h +++ /dev/null @@ -1,16 +0,0 @@ - -#ifndef softfloat_types_h -#define softfloat_types_h - -/*** COMMENTS. ***/ - -#include -#include - -typedef struct { uint32_t v; } float32_t; -typedef struct { uint64_t v; } float64_t; -typedef struct { uint64_t v; uint16_t x; } floatx80_t; -typedef struct { uint64_t v[ 2 ]; } float128_t; - -#endif - diff --git a/softfloat/SoftFloat-3/source/8086/specialize.h b/softfloat/SoftFloat-3/source/8086/specialize.h deleted file mode 100755 index ca0bb1d..0000000 --- a/softfloat/SoftFloat-3/source/8086/specialize.h +++ /dev/null @@ -1,113 +0,0 @@ - -/*============================================================================ - -*** FIX. - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -#include -#include - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define init_detectTininess softfloat_tininess_afterRounding; - -/*---------------------------------------------------------------------------- -| Structure used to transfer NaN representations from one format to another. -*----------------------------------------------------------------------------*/ -struct commonNaN { - bool sign; - uint64_t v64, v0; -}; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -#define defaultNaNF32UI 0xFFC00000 - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise, returns 0. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 1 <= INLINE_LEVEL ) -INLINE bool softfloat_isSigNaNF32UI( uint_fast32_t ui ) - { return ( ( ui>>22 & 0x1FF ) == 0x1FE ) && ( ui & 0x003FFFFF ); } -#else -bool softfloat_isSigNaNF32UI( uint_fast32_t ); -#endif - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -struct commonNaN softfloat_f32UIToCommonNaN( uint_fast32_t ); -#if defined INLINE_LEVEL && ( 1 <= INLINE_LEVEL ) -INLINE uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN a ) - { return (uint_fast32_t) a.sign<<31 | 0x7FC00000 | a.v64>>41; } -#else -uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN ); -#endif - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ -uint_fast32_t softfloat_propagateNaNF32UI( uint_fast32_t, uint_fast32_t ); - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -#define defaultNaNF64UI UINT64_C(0xFFF8000000000000) - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 1 <= INLINE_LEVEL ) -INLINE bool softfloat_isSigNaNF64UI( uint_fast64_t ui ) -{ - return - ( ( ui>>51 & 0xFFF ) == 0xFFE ) - && ( ui & UINT64_C( 0x0007FFFFFFFFFFFF ) ); -} -#else -bool softfloat_isSigNaNF64UI( uint_fast64_t ); -#endif - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -/*** MIGHT BE INLINE'D. ***/ -struct commonNaN softfloat_f64UIToCommonNaN( uint_fast64_t ); -uint_fast64_t softfloat_commonNaNToF64UI( struct commonNaN ); - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ -uint_fast64_t softfloat_propagateNaNF64UI( uint_fast64_t, uint_fast64_t ); - diff --git a/softfloat/SoftFloat-3/source/OLD-softfloat.c b/softfloat/SoftFloat-3/source/OLD-softfloat.c deleted file mode 100755 index 0096550..0000000 --- a/softfloat/SoftFloat-3/source/OLD-softfloat.c +++ /dev/null @@ -1,2962 +0,0 @@ - -/*============================================================================ - -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -#include "milieu.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target if -| desired.) -*----------------------------------------------------------------------------*/ -#include "softfloat-macros" - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize" - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -INLINE bits64 extractFloatx80Frac( floatx80 a ) -{ - - return a.low; - -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -INLINE int32 extractFloatx80Exp( floatx80 a ) -{ - - return a.high & 0x7FFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the extended double-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -INLINE flag extractFloatx80Sign( floatx80 a ) -{ - - return a.high>>15; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal extended double-precision floating-point value -| represented by the denormalized significand `aSig'. The normalized exponent -| and significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloatx80Subnormal( bits64 aSig, int32 *zExpPtr, bits64 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( aSig ); - *zSigPtr = aSig<>48 ) & 0x7FFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the quadruple-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE flag extractFloat128Sign( float128 a ) -{ - - return a.high>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat128Subnormal( - bits64 aSig0, - bits64 aSig1, - int32 *zExpPtr, - bits64 *zSig0Ptr, - bits64 *zSig1Ptr - ) -{ - int8 shiftCount; - - if ( aSig0 == 0 ) { - shiftCount = countLeadingZeros64( aSig1 ) - 15; - if ( shiftCount < 0 ) { - *zSig0Ptr = aSig1>>( - shiftCount ); - *zSig1Ptr = aSig1<<( shiftCount & 63 ); - } - else { - *zSig0Ptr = aSig1<>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>( - shiftCount ); - if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the single-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 floatx80_to_float32( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat32( floatx80ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 33, &aSig ); - if ( aExp || aSig ) aExp -= 0x3F81; - return roundAndPackFloat32( aSign, aExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 floatx80_to_float64( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig, zSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat64( floatx80ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shift64RightJamming( aSig, 1, &zSig ); - if ( aExp || aSig ) aExp -= 0x3C01; - return roundAndPackFloat64( aSign, aExp, zSig ); - -} - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the quadruple-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 floatx80_to_float128( floatx80 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig, zSig0, zSig1; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat128( floatx80ToCommonNaN( a ) ); - } - shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp, zSig0, zSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the extended double-precision floating-point value `a' to an integer, -| and returns the result as an extended quadruple-precision floating-point -| value. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_round_to_int( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - floatx80 z; - - aExp = extractFloatx80Exp( a ); - if ( 0x403E <= aExp ) { - if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { - return propagateFloatx80NaN( a, a ); - } - return a; - } - if ( aExp < 0x3FFF ) { - if ( ( aExp == 0 ) - && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { - return a; - } - float_exception_flags |= float_flag_inexact; - aSign = extractFloatx80Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) - ) { - return - packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - break; - case float_round_down: - return - aSign ? - packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) ) - : packFloatx80( 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloatx80( 1, 0, 0 ) - : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - return packFloatx80( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x403E - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.low += lastBitMask>>1; - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z.low += roundBitsMask; - } - } - z.low &= ~ roundBitsMask; - if ( z.low == 0 ) { - ++z.high; - z.low = LIT64( 0x8000000000000000 ); - } - if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the extended double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is -| negated before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - return a; - } - zSig1 = 0; - zSig0 = aSig + bSig; - if ( aExp == 0 ) { - normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); - goto roundAndPack; - } - zExp = aExp; - goto shiftRight1; - } - zSig0 = aSig + bSig; - if ( (sbits64) zSig0 < 0 ) goto roundAndPack; - shiftRight1: - shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= LIT64( 0x8000000000000000 ); - ++zExp; - roundAndPack: - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the extended -| double-precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - zSig1 = 0; - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - bBigger: - sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - aBigger: - sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - return - normalizeRoundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the extended double-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_add( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return addFloatx80Sigs( a, b, aSign ); - } - else { - return subFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sub( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return subFloatx80Sigs( a, b, aSign ); - } - else { - return addFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_mul( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) goto invalid; - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FFE; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - if ( 0 < (sbits64) zSig0 ) { - shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); - --zExp; - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the extended double-precision floating-point -| value `a' by the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_div( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - bits64 rem0, rem1, rem2, term0, term1, term2; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - goto invalid; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FFE; - rem1 = 0; - if ( bSig <= aSig ) { - shift128Right( aSig, 0, 1, &aSig, &rem1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig, rem1, bSig ); - mul64To128( bSig, zSig0, &term0, &term1 ); - sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, bSig ); - if ( (bits64) ( zSig1<<1 ) <= 8 ) { - mul64To128( bSig, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); - } - zSig1 |= ( ( rem1 | rem2 ) != 0 ); - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the extended double-precision floating-point value -| `a' with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_rem( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig; - bits64 q, term0, term1, alternateASig0, alternateASig1; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( (bits64) ( aSig0<<1 ) == 0 ) return a; - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - bSig |= LIT64( 0x8000000000000000 ); - zSign = aSign; - expDiff = aExp - bExp; - aSig1 = 0; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); - expDiff = 0; - } - q = ( bSig <= aSig0 ); - if ( q ) aSig0 -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - mul64To128( bSig, q, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); - while ( le128( term0, term1, aSig0, aSig1 ) ) { - ++q; - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - } - } - else { - term1 = 0; - term0 = bSig; - } - sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); - if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) - || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) - && ( q & 1 ) ) - ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - zSign = ! zSign; - } - return - normalizeRoundAndPackFloatx80( - 80, zSign, bExp + expDiff, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sqrt( floatx80 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; - zSig0 = estimateSqrt32( aExp, aSig0>>32 ); - shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= doubleZSig0; - return - roundAndPackFloatx80( - floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq( floatx80 a, floatx80 b ) -{ - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than or equal to the corresponding value `b', and 0 otherwise. The -| comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is equal -| to the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq_signaling( floatx80 a, floatx80 b ) -{ - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs -| do not cause an exception. Otherwise, the comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause -| an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; - if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); - aSig0 |= ( aSig1 != 0 ); - shiftCount = 0x4028 - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 ); - return roundAndPackInt32( aSign, aSig0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32_round_to_zero( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1, savedASig; - int32 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - aSig0 |= ( aSig1 != 0 ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if ( aExp || aSig0 ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig0 |= LIT64( 0x0001000000000000 ); - shiftCount = 0x402F - aExp; - savedASig = aSig0; - aSig0 >>= shiftCount; - z = aSig0; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig0<>( ( - shiftCount ) & 63 ) ); - if ( (bits64) ( aSig1<>( - shiftCount ); - if ( aSig1 - || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) { - float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the single-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float128_to_float32( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - bits32 zSig; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat32( float128ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - aSig0 |= ( aSig1 != 0 ); - shift64RightJamming( aSig0, 18, &aSig0 ); - zSig = aSig0; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x3F81; - } - return roundAndPackFloat32( aSign, aExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float128_to_float64( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat64( float128ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - aSig0 |= ( aSig1 != 0 ); - if ( aExp || aSig0 ) { - aSig0 |= LIT64( 0x4000000000000000 ); - aExp -= 0x3C01; - } - return roundAndPackFloat64( aSign, aExp, aSig0 ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the extended double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float128_to_floatx80( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloatx80( float128ToCommonNaN( a ) ); - } - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); - return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the quadruple-precision floating-point value `a' to an integer, and -| returns the result as a quadruple-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_round_to_int( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - float128 z; - - aExp = extractFloat128Exp( a ); - if ( 0x402F <= aExp ) { - if ( 0x406F <= aExp ) { - if ( ( aExp == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) - ) { - return propagateFloat128NaN( a, a ); - } - return a; - } - lastBitMask = 1; - lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - if ( lastBitMask ) { - add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low ); - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else { - if ( (sbits64) z.low < 0 ) { - ++z.high; - if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1; - } - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low ); - } - } - z.low &= ~ roundBitsMask; - } - else { - if ( aExp < 0x3FFF ) { - if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat128Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) - && ( extractFloat128Frac0( a ) - | extractFloat128Frac1( a ) ) - ) { - return packFloat128( aSign, 0x3FFF, 0, 0 ); - } - break; - case float_round_down: - return - aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) - : packFloat128( 0, 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloat128( 1, 0, 0, 0 ) - : packFloat128( 0, 0x3FFF, 0, 0 ); - } - return packFloat128( aSign, 0, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x402F - aExp; - roundBitsMask = lastBitMask - 1; - z.low = 0; - z.high = a.high; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.high += lastBitMask>>1; - if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) { - z.high &= ~ lastBitMask; - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - z.high |= ( a.low != 0 ); - z.high += roundBitsMask; - } - } - z.high &= ~ roundBitsMask; - } - if ( ( z.low != a.low ) || ( z.high != a.high ) ) { - float_exception_flags |= float_flag_inexact; - } - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the quadruple-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 addFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - int32 expDiff; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - return a; - } - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); - zSig2 = 0; - zSig0 |= LIT64( 0x0002000000000000 ); - zExp = aExp; - goto shiftRight1; - } - aSig0 |= LIT64( 0x0001000000000000 ); - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - --zExp; - if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; - ++zExp; - shiftRight1: - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - roundAndPack: - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the quadruple- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 subFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; - int32 expDiff; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig0 < aSig0 ) goto aBigger; - if ( aSig0 < bSig0 ) goto bBigger; - if ( bSig1 < aSig1 ) goto aBigger; - if ( aSig1 < bSig1 ) goto bBigger; - return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - bSig0 |= LIT64( 0x4000000000000000 ); - bBigger: - sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); - aSig0 |= LIT64( 0x4000000000000000 ); - aBigger: - sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the quadruple-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_add( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return addFloat128Sigs( a, b, aSign ); - } - else { - return subFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sub( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return subFloat128Sigs( a, b, aSign ); - } - else { - return addFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_mul( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - zExp = aExp + bExp - 0x4000; - aSig0 |= LIT64( 0x0001000000000000 ); - shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); - mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); - add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zSig2 |= ( zSig3 != 0 ); - if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - ++zExp; - } - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the quadruple-precision floating-point value -| `a' by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_div( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - goto invalid; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0, 0, 0 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = aExp - bExp + 0x3FFD; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { - shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); - mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); - sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); - } - zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); - if ( ( zSig1 & 0x3FFF ) <= 4 ) { - mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); - sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the quadruple-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_rem( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2; - bits64 allZero, alternateASig0, alternateASig1, sigMean1; - sbits64 sigMean0; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return a; - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - expDiff = aExp - bExp; - if ( expDiff < -1 ) return a; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), - aSig1, - 15 - ( expDiff < 0 ), - &aSig0, - &aSig1 - ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - q = le128( bSig0, bSig1, aSig0, aSig1 ); - if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero ); - shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero ); - sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 ); - expDiff -= 61; - } - if ( -64 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - q >>= - expDiff; - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - expDiff += 52; - if ( expDiff < 0 ) { - shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - } - else { - shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 ); - } - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 ); - } - else { - shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 ); - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - } - do { - alternateASig0 = aSig0; - alternateASig1 = aSig1; - ++q; - sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - } while ( 0 <= (sbits64) aSig0 ); - add128( - aSig0, aSig1, alternateASig0, alternateASig1, &sigMean0, &sigMean1 ); - if ( ( sigMean0 < 0 ) - || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - } - zSign = ( (sbits64) aSig0 < 0 ); - if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 ); - return - normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the quadruple-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sqrt( float128 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE; - aSig0 |= LIT64( 0x0001000000000000 ); - zSig0 = estimateSqrt32( aExp, aSig0>>17 ); - shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & 0x1FFF ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq( float128 a, float128 b ) -{ - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq_signaling( float128 a, float128 b ) -{ - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif - diff --git a/softfloat/SoftFloat-3/source/f32_add.c b/softfloat/SoftFloat-3/source/f32_add.c deleted file mode 100755 index dc53d68..0000000 --- a/softfloat/SoftFloat-3/source/f32_add.c +++ /dev/null @@ -1,29 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -float32_t f32_add( float32_t a, float32_t b ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - bool signA; - union ui32_f32 uB; - uint_fast32_t uiB; - bool signB; - float32_t ( *magsRoutine )( uint_fast32_t, uint_fast32_t, bool ); - - uA.f = a; - uiA = uA.ui; - signA = signF32UI( uiA ); - uB.f = b; - uiB = uB.ui; - signB = signF32UI( uiB ); - magsRoutine = - ( signA == signB ) ? softfloat_addMagsF32 : softfloat_subMagsF32; - return magsRoutine( uiA, uiB, signA ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_div.c b/softfloat/SoftFloat-3/source/f32_div.c deleted file mode 100755 index 958b140..0000000 --- a/softfloat/SoftFloat-3/source/f32_div.c +++ /dev/null @@ -1,96 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float32_t f32_div( float32_t a, float32_t b ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - bool signA; - int_fast16_t expA; - uint_fast32_t sigA; - union ui32_f32 uB; - uint_fast32_t uiB; - bool signB; - int_fast16_t expB; - uint_fast32_t sigB; - bool signZ; - struct exp16_sig32 normExpSig; - int_fast16_t expZ; - uint_fast32_t sigZ; - uint_fast32_t uiZ; - union ui32_f32 uZ; - - uA.f = a; - uiA = uA.ui; - signA = signF32UI( uiA ); - expA = expF32UI( uiA ); - sigA = fracF32UI( uiA ); - uB.f = b; - uiB = uB.ui; - signB = signF32UI( uiB ); - expB = expF32UI( uiB ); - sigB = fracF32UI( uiB ); - signZ = signA ^ signB; - if ( expA == 0xFF ) { - if ( sigA ) goto propagateNaN; - if ( expB == 0xFF ) { - if ( sigB ) goto propagateNaN; - goto invalid; - } - goto infinity; - } - if ( expB == 0xFF ) { - if ( sigB ) goto propagateNaN; - goto zero; - } - if ( ! expB ) { - if ( ! sigB ) { - if ( ! ( expA | sigA ) ) goto invalid; - softfloat_raiseFlags( softfloat_flag_infinity ); - goto infinity; - } - normExpSig = softfloat_normSubnormalF32Sig( sigB ); - expB = normExpSig.exp; - sigB = normExpSig.sig; - } - if ( ! expA ) { - if ( ! sigA ) goto zero; - normExpSig = softfloat_normSubnormalF32Sig( sigA ); - expA = normExpSig.exp; - sigA = normExpSig.sig; - } - expZ = expA - expB + 0x7D; - sigA = ( sigA | 0x00800000 )<<7; - sigB = ( sigB | 0x00800000 )<<8; - if ( sigB <= ( sigA + sigA ) ) { - ++expZ; - sigA >>= 1; - } - sigZ = ( (uint_fast64_t) sigA<<32 ) / sigB; - if ( ! ( sigZ & 0x3F ) ) { - sigZ |= ( (uint_fast64_t) sigB * sigZ != (uint_fast64_t) sigA<<32 ); - } - return softfloat_roundPackToF32( signZ, expZ, sigZ ); - propagateNaN: - uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); - goto uiZ; - invalid: - softfloat_raiseFlags( softfloat_flag_invalid ); - uiZ = defaultNaNF32UI; - goto uiZ; - infinity: - uiZ = packToF32UI( signZ, 0xFF, 0 ); - goto uiZ; - zero: - uiZ = packToF32UI( signZ, 0, 0 ); - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/f32_eq.c b/softfloat/SoftFloat-3/source/f32_eq.c deleted file mode 100755 index 8f2306b..0000000 --- a/softfloat/SoftFloat-3/source/f32_eq.c +++ /dev/null @@ -1,34 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -bool f32_eq( float32_t a, float32_t b ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - union ui32_f32 uB; - uint_fast32_t uiB; - - uA.f = a; - uiA = uA.ui; - uB.f = b; - uiB = uB.ui; - if ( - ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) - || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) - ) { - if ( - softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) - ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - return false; - } - return ( uiA == uiB ) || ! (uint32_t) ( ( uiA | uiB )<<1 ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_eq_signaling.c b/softfloat/SoftFloat-3/source/f32_eq_signaling.c deleted file mode 100755 index bfba48a..0000000 --- a/softfloat/SoftFloat-3/source/f32_eq_signaling.c +++ /dev/null @@ -1,29 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -bool f32_eq_signaling( float32_t a, float32_t b ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - union ui32_f32 uB; - uint_fast32_t uiB; - - uA.f = a; - uiA = uA.ui; - uB.f = b; - uiB = uB.ui; - if ( - ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) - || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) - ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - return false; - } - return ( uiA == uiB ) || ! (uint32_t) ( ( uiA | uiB )<<1 ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_isSignalingNaN.c b/softfloat/SoftFloat-3/source/f32_isSignalingNaN.c deleted file mode 100755 index 09aaa82..0000000 --- a/softfloat/SoftFloat-3/source/f32_isSignalingNaN.c +++ /dev/null @@ -1,16 +0,0 @@ - -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -bool f32_isSignalingNaN( float32_t a ) -{ - union ui32_f32 uA; - - uA.f = a; - return softfloat_isSigNaNF32UI( uA.ui ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_le.c b/softfloat/SoftFloat-3/source/f32_le.c deleted file mode 100755 index 5f47be5..0000000 --- a/softfloat/SoftFloat-3/source/f32_le.c +++ /dev/null @@ -1,34 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -bool f32_le( float32_t a, float32_t b ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - union ui32_f32 uB; - uint_fast32_t uiB; - bool signA, signB; - - uA.f = a; - uiA = uA.ui; - uB.f = b; - uiB = uB.ui; - if ( - ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) - || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) - ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - return false; - } - signA = signF32UI( uiA ); - signB = signF32UI( uiB ); - return - ( signA != signB ) ? signA || ! (uint32_t) ( ( uiA | uiB )<<1 ) - : ( uiA == uiB ) || ( signA ^ ( uiA < uiB ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_le_quiet.c b/softfloat/SoftFloat-3/source/f32_le_quiet.c deleted file mode 100755 index 2b541da..0000000 --- a/softfloat/SoftFloat-3/source/f32_le_quiet.c +++ /dev/null @@ -1,39 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -bool f32_le_quiet( float32_t a, float32_t b ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - union ui32_f32 uB; - uint_fast32_t uiB; - bool signA, signB; - - uA.f = a; - uiA = uA.ui; - uB.f = b; - uiB = uB.ui; - if ( - ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) - || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) - ) { - if ( - softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) - ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - return false; - } - signA = signF32UI( uiA ); - signB = signF32UI( uiB ); - return - ( signA != signB ) ? signA || ! (uint32_t) ( ( uiA | uiB )<<1 ) - : ( uiA == uiB ) || ( signA ^ ( uiA < uiB ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_lt.c b/softfloat/SoftFloat-3/source/f32_lt.c deleted file mode 100755 index 753b28a..0000000 --- a/softfloat/SoftFloat-3/source/f32_lt.c +++ /dev/null @@ -1,34 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -bool f32_lt( float32_t a, float32_t b ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - union ui32_f32 uB; - uint_fast32_t uiB; - bool signA, signB; - - uA.f = a; - uiA = uA.ui; - uB.f = b; - uiB = uB.ui; - if ( - ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) - || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) - ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - return false; - } - signA = signF32UI( uiA ); - signB = signF32UI( uiB ); - return - ( signA != signB ) ? signA && ( (uint32_t) ( ( uiA | uiB )<<1 ) != 0 ) - : ( uiA != uiB ) && ( signA ^ ( uiA < uiB ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_lt_quiet.c b/softfloat/SoftFloat-3/source/f32_lt_quiet.c deleted file mode 100755 index ecd90bf..0000000 --- a/softfloat/SoftFloat-3/source/f32_lt_quiet.c +++ /dev/null @@ -1,39 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -bool f32_lt_quiet( float32_t a, float32_t b ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - union ui32_f32 uB; - uint_fast32_t uiB; - bool signA, signB; - - uA.f = a; - uiA = uA.ui; - uB.f = b; - uiB = uB.ui; - if ( - ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) - || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) - ) { - if ( - softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) - ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - return false; - } - signA = signF32UI( uiA ); - signB = signF32UI( uiB ); - return - ( signA != signB ) ? signA && ( (uint32_t) ( ( uiA | uiB )<<1 ) != 0 ) - : ( uiA != uiB ) && ( signA ^ ( uiA < uiB ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_mul.c b/softfloat/SoftFloat-3/source/f32_mul.c deleted file mode 100755 index d49c1dd..0000000 --- a/softfloat/SoftFloat-3/source/f32_mul.c +++ /dev/null @@ -1,89 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float32_t f32_mul( float32_t a, float32_t b ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - bool signA; - int_fast16_t expA; - uint_fast32_t sigA; - union ui32_f32 uB; - uint_fast32_t uiB; - bool signB; - int_fast16_t expB; - uint_fast32_t sigB; - bool signZ; - uint_fast32_t magBits; - struct exp16_sig32 normExpSig; - int_fast16_t expZ; - uint_fast32_t sigZ, uiZ; - union ui32_f32 uZ; - - uA.f = a; - uiA = uA.ui; - signA = signF32UI( uiA ); - expA = expF32UI( uiA ); - sigA = fracF32UI( uiA ); - uB.f = b; - uiB = uB.ui; - signB = signF32UI( uiB ); - expB = expF32UI( uiB ); - sigB = fracF32UI( uiB ); - signZ = signA ^ signB; - if ( expA == 0xFF ) { - if ( sigA || ( ( expB == 0xFF ) && sigB ) ) goto propagateNaN; - magBits = expB | sigB; - goto infArg; - } - if ( expB == 0xFF ) { - if ( sigB ) goto propagateNaN; - magBits = expA | sigA; - goto infArg; - } - if ( ! expA ) { - if ( ! sigA ) goto zero; - normExpSig = softfloat_normSubnormalF32Sig( sigA ); - expA = normExpSig.exp; - sigA = normExpSig.sig; - } - if ( ! expB ) { - if ( ! sigB ) goto zero; - normExpSig = softfloat_normSubnormalF32Sig( sigB ); - expB = normExpSig.exp; - sigB = normExpSig.sig; - } - expZ = expA + expB - 0x7F; - sigA = ( sigA | 0x00800000 )<<7; - sigB = ( sigB | 0x00800000 )<<8; - sigZ = softfloat_shortShift64RightJam( (uint_fast64_t) sigA * sigB, 32 ); - if ( sigZ < 0x40000000 ) { - --expZ; - sigZ <<= 1; - } - return softfloat_roundPackToF32( signZ, expZ, sigZ ); - propagateNaN: - uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); - goto uiZ; - infArg: - if ( ! magBits ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - uiZ = defaultNaNF32UI; - } else { - uiZ = packToF32UI( signZ, 0xFF, 0 ); - } - goto uiZ; - zero: - uiZ = packToF32UI( signZ, 0, 0 ); - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/f32_mulAdd.c b/softfloat/SoftFloat-3/source/f32_mulAdd.c deleted file mode 100755 index 3d4cee9..0000000 --- a/softfloat/SoftFloat-3/source/f32_mulAdd.c +++ /dev/null @@ -1,25 +0,0 @@ - -#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( 0, uiA, uiB, uiC ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_rem.c b/softfloat/SoftFloat-3/source/f32_rem.c deleted file mode 100755 index d29b840..0000000 --- a/softfloat/SoftFloat-3/source/f32_rem.c +++ /dev/null @@ -1,124 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float32_t f32_rem( float32_t a, float32_t b ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - bool signA; - int_fast16_t expA; - uint_fast32_t sigA; - union ui32_f32 uB; - uint_fast32_t uiB; - bool signB; - int_fast16_t expB; - uint_fast32_t sigB; - struct exp16_sig32 normExpSig; - int_fast16_t expDiff; - uint_fast32_t q; - uint_fast64_t sigA64, sigB64, q64; - uint_fast32_t alternateSigA; - uint32_t sigMean; - bool signZ; - uint_fast32_t uiZ; - union ui32_f32 uZ; - - uA.f = a; - uiA = uA.ui; - signA = signF32UI( uiA ); - expA = expF32UI( uiA ); - sigA = fracF32UI( uiA ); - uB.f = b; - uiB = uB.ui; - signB = signF32UI( uiB ); - expB = expF32UI( uiB ); - sigB = fracF32UI( uiB ); - if ( expA == 0xFF ) { - if ( sigA || ( ( expB == 0xFF ) && sigB ) ) goto propagateNaN; - goto invalid; - } - if ( expB == 0xFF ) { - if ( sigB ) goto propagateNaN; - return a; - } - if ( ! expB ) { - if ( ! sigB ) goto invalid; - normExpSig = softfloat_normSubnormalF32Sig( sigB ); - expB = normExpSig.exp; - sigB = normExpSig.sig; - } - if ( ! expA ) { - if ( ! sigA ) return a; - normExpSig = softfloat_normSubnormalF32Sig( sigA ); - expA = normExpSig.exp; - sigA = normExpSig.sig; - } - expDiff = expA - expB; - sigA |= 0x00800000; - sigB |= 0x00800000; - if ( expDiff < 32 ) { - sigA <<= 8; - sigB <<= 8; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - sigA >>= 1; - } - q = ( sigB <= sigA ); - if ( q ) sigA -= sigB; - if ( 0 < expDiff ) { - q = ( (uint_fast64_t) sigA<<32 ) / sigB; - q >>= 32 - expDiff; - sigB >>= 2; - sigA = ( ( sigA>>1 )<<( expDiff - 1 ) ) - sigB * q; - } else { - sigA >>= 2; - sigB >>= 2; - } - } else { - if ( sigB <= sigA ) sigA -= sigB; - sigA64 = (uint_fast64_t) sigA<<40; - sigB64 = (uint_fast64_t) sigB<<40; - expDiff -= 64; - while ( 0 < expDiff ) { - q64 = softfloat_estimateDiv128To64( sigA64, 0, sigB64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - sigA64 = - ( ( sigB * q64 )<<38 ); - expDiff -= 62; - } - expDiff += 64; - q64 = softfloat_estimateDiv128To64( sigA64, 0, sigB64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - q = q64>>( 64 - expDiff ); - sigB <<= 6; - sigA = ( ( sigA64>>33 )<<( expDiff - 1 ) ) - sigB * q; - } - do { - alternateSigA = sigA; - ++q; - sigA -= sigB; - } while ( sigA < 0x80000000 ); - sigMean = sigA + alternateSigA; - if ( ( 0x80000000 <= sigMean ) || ( ! sigMean && ( q & 1 ) ) ) { - sigA = alternateSigA; - } - signZ = ( 0x80000000 <= sigA ); - if ( signZ ) sigA = - sigA; - return softfloat_normRoundPackToF32( signA ^ signZ, expB, sigA ); - propagateNaN: - uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); - goto uiZ; - invalid: - softfloat_raiseFlags( softfloat_flag_invalid ); - uiZ = defaultNaNF32UI; - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/f32_roundToInt.c b/softfloat/SoftFloat-3/source/f32_roundToInt.c deleted file mode 100755 index f8f9114..0000000 --- a/softfloat/SoftFloat-3/source/f32_roundToInt.c +++ /dev/null @@ -1,78 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float32_t f32_roundToInt( float32_t a, int_fast8_t roundingMode, bool exact ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - int_fast16_t expA; - uint_fast32_t uiZ; - bool signA; - uint_fast32_t lastBitMask, roundBitsMask; - union ui32_f32 uZ; - - uA.f = a; - uiA = uA.ui; - expA = expF32UI( uiA ); - if ( 0x96 <= expA ) { - if ( ( expA == 0xFF ) && fracF32UI( uiA ) ) { - uiZ = softfloat_propagateNaNF32UI( uiA, 0 ); - goto uiZ; - } - return a; - } - if ( expA <= 0x7E ) { - if ( ! (uint32_t) ( uiA<<1 ) ) return a; - if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; - signA = signF32UI( uiA ); - switch ( roundingMode ) { - case softfloat_round_nearest_even: - if ( ( expA == 0x7E ) && fracF32UI( uiA ) ) { - uiZ = packToF32UI( signA, 0x7F, 0 ); - goto uiZ; - } - break; - case softfloat_round_min: - uiZ = signA ? 0xBF800000 : 0; - goto uiZ; - case softfloat_round_max: - uiZ = signA ? 0x80000000 : 0x3F800000; - goto uiZ; - case softfloat_round_nearest_maxMag: - if ( expA == 0x7E ) { - uiZ = packToF32UI( signA, 0x7F, 0 ); - goto uiZ; - } - break; - } - uiZ = packToF32UI( signA, 0, 0 ); - goto uiZ; - } - lastBitMask = (uint_fast32_t) 1<<( 0x96 - expA ); - roundBitsMask = lastBitMask - 1; - uiZ = uiA; - if ( roundingMode == softfloat_round_nearest_maxMag ) { - uiZ += lastBitMask>>1; - } else if ( roundingMode == softfloat_round_nearest_even ) { - uiZ += lastBitMask>>1; - if ( ! ( uiZ & roundBitsMask ) ) uiZ &= ~ lastBitMask; - } else if ( roundingMode != softfloat_round_minMag ) { - if ( signF32UI( uiZ ) ^ ( roundingMode == softfloat_round_max ) ) { - uiZ += roundBitsMask; - } - } - uiZ &= ~ roundBitsMask; - if ( exact && ( uiZ != uiA ) ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/f32_sqrt.c b/softfloat/SoftFloat-3/source/f32_sqrt.c deleted file mode 100755 index c9eb907..0000000 --- a/softfloat/SoftFloat-3/source/f32_sqrt.c +++ /dev/null @@ -1,74 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float32_t f32_sqrt( float32_t a ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - bool signA; - int_fast16_t expA; - uint_fast32_t sigA, uiZ; - struct exp16_sig32 normExpSig; - int_fast16_t expZ; - uint_fast32_t sigZ; - uint_fast64_t term, rem; - union ui32_f32 uZ; - - uA.f = a; - uiA = uA.ui; - signA = signF32UI( uiA ); - expA = expF32UI( uiA ); - sigA = fracF32UI( uiA ); - if ( expA == 0xFF ) { - if ( sigA ) { - uiZ = softfloat_propagateNaNF32UI( 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_normSubnormalF32Sig( sigA ); - expA = normExpSig.exp; - sigA = normExpSig.sig; - } - expZ = ( ( expA - 0x7F )>>1 ) + 0x7E; - sigA = ( sigA | 0x00800000 )<<8; - sigZ = softfloat_estimateSqrt32( expA, sigA ) + 2; - if ( ( sigZ & 0x7F ) <= 5 ) { - if ( sigZ < 2 ) { - sigZ = 0x7FFFFFFF; - goto roundPack; - } - sigA >>= expA & 1; - term = (uint_fast64_t) sigZ * sigZ; - rem = ( (uint_fast64_t) sigA<<32 ) - term; - while ( UINT64_C( 0x8000000000000000 ) <= rem ) { - --sigZ; - rem += ( (uint_fast64_t) sigZ<<1 ) | 1; - } - sigZ |= ( rem != 0 ); - } - sigZ = softfloat_shortShift32Right1Jam( sigZ ); - roundPack: - return softfloat_roundPackToF32( 0, expZ, sigZ ); - invalid: - softfloat_raiseFlags( softfloat_flag_invalid ); - uiZ = defaultNaNF32UI; - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/f32_sub.c b/softfloat/SoftFloat-3/source/f32_sub.c deleted file mode 100755 index c64df8e..0000000 --- a/softfloat/SoftFloat-3/source/f32_sub.c +++ /dev/null @@ -1,29 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -float32_t f32_sub( float32_t a, float32_t b ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - bool signA; - union ui32_f32 uB; - uint_fast32_t uiB; - bool signB; - float32_t ( *magsRoutine )( uint_fast32_t, uint_fast32_t, bool ); - - uA.f = a; - uiA = uA.ui; - signA = signF32UI( uiA ); - uB.f = b; - uiB = uB.ui; - signB = signF32UI( uiB ); - magsRoutine = - ( signA == signB ) ? softfloat_subMagsF32 : softfloat_addMagsF32; - return magsRoutine( uiA, uiB ^ 0x80000000, signA ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_to_f64.c b/softfloat/SoftFloat-3/source/f32_to_f64.c deleted file mode 100755 index 9f0ae5c..0000000 --- a/softfloat/SoftFloat-3/source/f32_to_f64.c +++ /dev/null @@ -1,47 +0,0 @@ - -#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 sig; - uint_fast64_t uiZ; - struct exp16_sig32 normExpSig; - union ui64_f64 uZ; - - uA.f = a; - uiA = uA.ui; - sign = signF32UI( uiA ); - exp = expF32UI( uiA ); - sig = fracF32UI( uiA ); - if ( exp == 0xFF ) { - uiZ = - sig ? softfloat_commonNaNToF64UI( - softfloat_f32UIToCommonNaN( uiA ) ) - : packToF64UI( sign, 0x7FF, 0 ); - goto uiZ; - } - if ( ! exp ) { - if ( ! sig ) { - uiZ = packToF64UI( sign, 0, 0 ); - goto uiZ; - } - normExpSig = softfloat_normSubnormalF32Sig( sig ); - exp = normExpSig.exp - 1; - sig = normExpSig.sig; - } - uiZ = packToF64UI( sign, exp + 0x380, (uint_fast64_t) sig<<29 ); - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/f32_to_i32.c b/softfloat/SoftFloat-3/source/f32_to_i32.c deleted file mode 100755 index bbbaee0..0000000 --- a/softfloat/SoftFloat-3/source/f32_to_i32.c +++ /dev/null @@ -1,34 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -int_fast32_t f32_to_i32( float32_t a, int_fast8_t roundingMode, bool exact ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - bool sign; - int_fast16_t exp; - uint_fast32_t sig; - uint_fast64_t sig64; - int_fast16_t shiftCount; - - uA.f = a; - uiA = uA.ui; - sign = signF32UI( uiA ); - exp = expF32UI( uiA ); - sig = fracF32UI( uiA ); - if ( ( exp == 0xFF ) && sig ) sign = 0; - if ( exp ) sig |= 0x00800000; - sig64 = (uint_fast64_t) sig<<32; - shiftCount = 0xAF - exp; - if ( 0 < shiftCount ) { - sig64 = softfloat_shift64RightJam( sig64, shiftCount ); - } - return softfloat_roundPackToI32( sign, sig64, roundingMode, exact ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_to_i32_r_minMag.c b/softfloat/SoftFloat-3/source/f32_to_i32_r_minMag.c deleted file mode 100755 index 63ff1e2..0000000 --- a/softfloat/SoftFloat-3/source/f32_to_i32_r_minMag.c +++ /dev/null @@ -1,45 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -int_fast32_t f32_to_i32_r_minMag( float32_t a, bool exact ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - int_fast16_t exp; - uint_fast32_t sig; - bool sign; - int_fast16_t shiftCount; - int_fast32_t absZ; - - uA.f = a; - uiA = uA.ui; - exp = expF32UI( uiA ); - sig = fracF32UI( uiA ); - if ( exp < 0x7F ) { - if ( exact && ( exp | sig ) ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - return 0; - } - sign = signF32UI( uiA ); - shiftCount = 0x9E - exp; - if ( shiftCount <= 0 ) { - if ( uiA != packToF32UI( 1, 0x9E, 0 ) ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - if ( ! sign || ( ( exp == 0xFF ) && sig ) ) return 0x7FFFFFFF; - } - return -0x7FFFFFFF - 1; - } - sig = ( sig | 0x00800000 )<<8; - absZ = sig>>shiftCount; - if ( exact && (uint32_t) ( sig<<( ( - shiftCount ) & 31 ) ) ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - return sign ? - absZ : absZ; - -} - diff --git a/softfloat/SoftFloat-3/source/f32_to_i64.c b/softfloat/SoftFloat-3/source/f32_to_i64.c deleted file mode 100755 index c0b8981..0000000 --- a/softfloat/SoftFloat-3/source/f32_to_i64.c +++ /dev/null @@ -1,44 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -int_fast64_t f32_to_i64( float32_t a, int_fast8_t roundingMode, bool exact ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - bool sign; - int_fast16_t exp; - uint_fast32_t sig; - int_fast16_t shiftCount; - uint_fast64_t sig64, extra; - struct uint64_extra sig64Extra; - - uA.f = a; - uiA = uA.ui; - sign = signF32UI( uiA ); - exp = expF32UI( uiA ); - sig = fracF32UI( uiA ); - shiftCount = 0xBE - exp; - if ( shiftCount < 0 ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - if ( ! sign || ( ( exp == 0xFF ) && sig ) ) { - return INT64_C( 0x7FFFFFFFFFFFFFFF ); - } - return - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; - } - if ( exp ) sig |= 0x00800000; - sig64 = (uint_fast64_t) sig<<40; - extra = 0; - if ( shiftCount ) { - sig64Extra = softfloat_shift64ExtraRightJam( sig64, 0, shiftCount ); - sig64 = sig64Extra.v; - extra = sig64Extra.extra; - } - return softfloat_roundPackToI64( sign, sig64, extra, roundingMode, exact ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_to_i64_r_minMag.c b/softfloat/SoftFloat-3/source/f32_to_i64_r_minMag.c deleted file mode 100755 index 33bff93..0000000 --- a/softfloat/SoftFloat-3/source/f32_to_i64_r_minMag.c +++ /dev/null @@ -1,52 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -int_fast64_t f32_to_i64_r_minMag( float32_t a, bool exact ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - int_fast16_t exp; - uint_fast32_t sig; - bool sign; - int_fast16_t shiftCount; - uint_fast64_t sig64; - int_fast64_t absZ; - - uA.f = a; - uiA = uA.ui; - exp = expF32UI( uiA ); - sig = fracF32UI( uiA ); - if ( exp < 0x7F ) { - if ( exact && ( exp | sig ) ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - return 0; - } - sign = signF32UI( uiA ); - shiftCount = 0xBE - exp; - if ( shiftCount <= 0 ) { - if ( uiA != packToF32UI( 1, 0xBE, 0 ) ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - if ( ! sign || ( ( exp == 0xFF ) && sig ) ) { - return INT64_C( 0x7FFFFFFFFFFFFFFF ); - } - } - return - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; - } - sig |= 0x00800000; - sig64 = (uint_fast64_t) sig<<40; - absZ = sig64>>shiftCount; - shiftCount = 40 - shiftCount; - if ( - exact && ( shiftCount < 0 ) && (uint32_t) ( sig<<( shiftCount & 31 ) ) - ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - return sign ? - absZ : absZ; - -} - diff --git a/softfloat/SoftFloat-3/source/f32_to_ui32.c b/softfloat/SoftFloat-3/source/f32_to_ui32.c deleted file mode 100755 index 3501db8..0000000 --- a/softfloat/SoftFloat-3/source/f32_to_ui32.c +++ /dev/null @@ -1,33 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -uint_fast32_t f32_to_ui32( float32_t a, int_fast8_t roundingMode, bool exact ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - bool sign; - int_fast16_t exp; - uint_fast32_t sig; - uint_fast64_t sig64; - int_fast16_t shiftCount; - - uA.f = a; - uiA = uA.ui; - sign = signF32UI( uiA ); - exp = expF32UI( uiA ); - sig = fracF32UI( uiA ); - if ( exp ) sig |= 0x00800000; - sig64 = (uint_fast64_t) sig<<32; - shiftCount = 0xAF - exp; - if ( 0 < shiftCount ) { - sig64 = softfloat_shift64RightJam( sig64, shiftCount ); - } - return softfloat_roundPackToUI32( sign, sig64, roundingMode, exact ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_to_ui32_r_minMag.c b/softfloat/SoftFloat-3/source/f32_to_ui32_r_minMag.c deleted file mode 100755 index edd858d..0000000 --- a/softfloat/SoftFloat-3/source/f32_to_ui32_r_minMag.c +++ /dev/null @@ -1,41 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -uint_fast32_t f32_to_ui32_r_minMag( float32_t a, bool exact ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - int_fast16_t exp; - uint_fast32_t sig; - int_fast16_t shiftCount; - uint_fast32_t z; - - uA.f = a; - uiA = uA.ui; - exp = expF32UI( uiA ); - sig = fracF32UI( uiA ); - if ( exp < 0x7F ) { - if ( exact && ( exp | sig ) ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - return 0; - } - if ( signF32UI( uiA ) ) goto invalid; - shiftCount = 0x9E - exp; - if ( shiftCount < 0 ) goto invalid; - sig = ( sig | 0x00800000 )<<8; - z = sig>>shiftCount; - if ( exact && ( sig & ( ( (uint_fast32_t) 1< -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -uint_fast64_t f32_to_ui64( float32_t a, int_fast8_t roundingMode, bool exact ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - bool sign; - int_fast16_t exp; - uint_fast32_t sig; - int_fast16_t shiftCount; - uint_fast64_t sig64, extra; - struct uint64_extra sig64Extra; - - uA.f = a; - uiA = uA.ui; - sign = signF32UI( uiA ); - exp = expF32UI( uiA ); - sig = fracF32UI( uiA ); - shiftCount = 0xBE - exp; - if ( shiftCount < 0 ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - return UINT64_C( 0xFFFFFFFFFFFFFFFF ); - } - if ( exp ) sig |= 0x00800000; - sig64 = (uint_fast64_t) sig<<40; - extra = 0; - if ( shiftCount ) { - sig64Extra = softfloat_shift64ExtraRightJam( sig64, 0, shiftCount ); - sig64 = sig64Extra.v; - extra = sig64Extra.extra; - } - return - softfloat_roundPackToUI64( sign, sig64, extra, roundingMode, exact ); - -} - diff --git a/softfloat/SoftFloat-3/source/f32_to_ui64_r_minMag.c b/softfloat/SoftFloat-3/source/f32_to_ui64_r_minMag.c deleted file mode 100755 index 738d6b1..0000000 --- a/softfloat/SoftFloat-3/source/f32_to_ui64_r_minMag.c +++ /dev/null @@ -1,45 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -uint_fast64_t f32_to_ui64_r_minMag( float32_t a, bool exact ) -{ - union ui32_f32 uA; - uint_fast32_t uiA; - int_fast16_t exp; - uint_fast32_t sig; - int_fast16_t shiftCount; - uint_fast64_t sig64, z; - - uA.f = a; - uiA = uA.ui; - exp = expF32UI( uiA ); - sig = fracF32UI( uiA ); - if ( exp < 0x7F ) { - if ( exact && ( exp | sig ) ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - return 0; - } - if ( signF32UI( uiA ) ) goto invalid; - shiftCount = 0xBE - exp; - if ( shiftCount < 0 ) goto invalid; - sig |= 0x00800000; - sig64 = (uint_fast64_t) sig<<40; - z = sig64>>shiftCount; - shiftCount = 40 - shiftCount; - if ( - exact && ( shiftCount < 0 ) && (uint32_t) ( sig<<( shiftCount & 31 ) ) - ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - return z; - invalid: - softfloat_raiseFlags( softfloat_flag_invalid ); - return UINT64_C( 0xFFFFFFFFFFFFFFFF ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_add.c b/softfloat/SoftFloat-3/source/f64_add.c deleted file mode 100755 index 9ec4b5f..0000000 --- a/softfloat/SoftFloat-3/source/f64_add.c +++ /dev/null @@ -1,29 +0,0 @@ - -#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; - float64_t ( *magsRoutine )( uint_fast64_t, uint_fast64_t, bool ); - - uA.f = a; - uiA = uA.ui; - signA = signF64UI( uiA ); - uB.f = b; - uiB = uB.ui; - signB = signF64UI( uiB ); - magsRoutine = - ( signA == signB ) ? softfloat_addMagsF64 : softfloat_subMagsF64; - return magsRoutine( uiA, uiB, signA ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_div.c b/softfloat/SoftFloat-3/source/f64_div.c deleted file mode 100755 index 9bc72b3..0000000 --- a/softfloat/SoftFloat-3/source/f64_div.c +++ /dev/null @@ -1,104 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.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; - uint_fast64_t sigZ; - struct uint128 term, rem; - 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_infinity ); - 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 + 0x3FD; - sigA = ( sigA | UINT64_C( 0x0010000000000000 ) )<<10; - sigB = ( sigB | UINT64_C( 0x0010000000000000 ) )<<11; - if ( sigB <= ( sigA + sigA ) ) { - ++expZ; - sigA >>= 1; - } - sigZ = softfloat_estimateDiv128To64( sigA, 0, sigB ); - if ( ( sigZ & 0x1FF ) <= 2 ) { - term = softfloat_mul64To128( sigB, sigZ ); - rem = softfloat_sub128( sigA, 0, term.v64, term.v0 ); - while ( UINT64_C( 0x8000000000000000 ) <= rem.v64 ) { - --sigZ; - rem = softfloat_add128( rem.v64, rem.v0, 0, sigB ); - } - sigZ |= ( rem.v0 != 0 ); - } - 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/softfloat/SoftFloat-3/source/f64_eq.c b/softfloat/SoftFloat-3/source/f64_eq.c deleted file mode 100755 index 925aabc..0000000 --- a/softfloat/SoftFloat-3/source/f64_eq.c +++ /dev/null @@ -1,35 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -bool f64_eq( float64_t a, float64_t b ) -{ - union ui64_f64 uA; - uint_fast64_t uiA; - union ui64_f64 uB; - uint_fast64_t uiB; - - uA.f = a; - uiA = uA.ui; - uB.f = b; - uiB = uB.ui; - if ( - ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) - || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) - ) { - if ( - softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) - ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - return false; - } - return - ( uiA == uiB ) || ! ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_eq_signaling.c b/softfloat/SoftFloat-3/source/f64_eq_signaling.c deleted file mode 100755 index 7a54dc1..0000000 --- a/softfloat/SoftFloat-3/source/f64_eq_signaling.c +++ /dev/null @@ -1,30 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -bool f64_eq_signaling( float64_t a, float64_t b ) -{ - union ui64_f64 uA; - uint_fast64_t uiA; - union ui64_f64 uB; - uint_fast64_t uiB; - - uA.f = a; - uiA = uA.ui; - uB.f = b; - uiB = uB.ui; - if ( - ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) - || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) - ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - return false; - } - return - ( uiA == uiB ) || ! ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_isSignalingNaN.c b/softfloat/SoftFloat-3/source/f64_isSignalingNaN.c deleted file mode 100755 index d720ac1..0000000 --- a/softfloat/SoftFloat-3/source/f64_isSignalingNaN.c +++ /dev/null @@ -1,16 +0,0 @@ - -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -bool f64_isSignalingNaN( float64_t a ) -{ - union ui64_f64 uA; - - uA.f = a; - return softfloat_isSigNaNF64UI( uA.ui ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_le.c b/softfloat/SoftFloat-3/source/f64_le.c deleted file mode 100755 index e6c5caf..0000000 --- a/softfloat/SoftFloat-3/source/f64_le.c +++ /dev/null @@ -1,35 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -bool f64_le( float64_t a, float64_t b ) -{ - union ui64_f64 uA; - uint_fast64_t uiA; - union ui64_f64 uB; - uint_fast64_t uiB; - bool signA, signB; - - uA.f = a; - uiA = uA.ui; - uB.f = b; - uiB = uB.ui; - if ( - ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) - || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) - ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - return false; - } - signA = signF64UI( uiA ); - signB = signF64UI( uiB ); - return - ( signA != signB ) - ? signA || ! ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) - : ( uiA == uiB ) || ( signA ^ ( uiA < uiB ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_le_quiet.c b/softfloat/SoftFloat-3/source/f64_le_quiet.c deleted file mode 100755 index e9b7ede..0000000 --- a/softfloat/SoftFloat-3/source/f64_le_quiet.c +++ /dev/null @@ -1,40 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -bool f64_le_quiet( float64_t a, float64_t b ) -{ - union ui64_f64 uA; - uint_fast64_t uiA; - union ui64_f64 uB; - uint_fast64_t uiB; - bool signA, signB; - - uA.f = a; - uiA = uA.ui; - uB.f = b; - uiB = uB.ui; - if ( - ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) - || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) - ) { - if ( - softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) - ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - return false; - } - signA = signF64UI( uiA ); - signB = signF64UI( uiB ); - return - ( signA != signB ) - ? signA || ! ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) - : ( uiA == uiB ) || ( signA ^ ( uiA < uiB ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_lt.c b/softfloat/SoftFloat-3/source/f64_lt.c deleted file mode 100755 index 1b2f696..0000000 --- a/softfloat/SoftFloat-3/source/f64_lt.c +++ /dev/null @@ -1,35 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -bool f64_lt( float64_t a, float64_t b ) -{ - union ui64_f64 uA; - uint_fast64_t uiA; - union ui64_f64 uB; - uint_fast64_t uiB; - bool signA, signB; - - uA.f = a; - uiA = uA.ui; - uB.f = b; - uiB = uB.ui; - if ( - ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) - || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) - ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - return false; - } - signA = signF64UI( uiA ); - signB = signF64UI( uiB ); - return - ( signA != signB ) - ? signA && ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) - : ( uiA != uiB ) && ( signA ^ ( uiA < uiB ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_lt_quiet.c b/softfloat/SoftFloat-3/source/f64_lt_quiet.c deleted file mode 100755 index f27e6da..0000000 --- a/softfloat/SoftFloat-3/source/f64_lt_quiet.c +++ /dev/null @@ -1,40 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -bool f64_lt_quiet( float64_t a, float64_t b ) -{ - union ui64_f64 uA; - uint_fast64_t uiA; - union ui64_f64 uB; - uint_fast64_t uiB; - bool signA, signB; - - uA.f = a; - uiA = uA.ui; - uB.f = b; - uiB = uB.ui; - if ( - ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) - || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) - ) { - if ( - softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) - ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - return false; - } - signA = signF64UI( uiA ); - signB = signF64UI( uiB ); - return - ( signA != signB ) - ? signA && ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) - : ( uiA != uiB ) && ( signA ^ ( uiA < uiB ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_mul.c b/softfloat/SoftFloat-3/source/f64_mul.c deleted file mode 100755 index 4b5dc4e..0000000 --- a/softfloat/SoftFloat-3/source/f64_mul.c +++ /dev/null @@ -1,91 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.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; - struct uint128 sigZ128; - 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; - sigZ128 = softfloat_mul64To128( sigA, sigB ); - sigZ = sigZ128.v64 | ( sigZ128.v0 != 0 ); - 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/softfloat/SoftFloat-3/source/f64_mulAdd.c b/softfloat/SoftFloat-3/source/f64_mulAdd.c deleted file mode 100755 index fa1669a..0000000 --- a/softfloat/SoftFloat-3/source/f64_mulAdd.c +++ /dev/null @@ -1,25 +0,0 @@ - -#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( 0, uiA, uiB, uiC ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_rem.c b/softfloat/SoftFloat-3/source/f64_rem.c deleted file mode 100755 index 08fcd78..0000000 --- a/softfloat/SoftFloat-3/source/f64_rem.c +++ /dev/null @@ -1,113 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.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; - bool signB; - int_fast16_t expB; - uint_fast64_t sigB; - struct exp16_sig64 normExpSig; - int_fast16_t expDiff; - uint_fast64_t q, alternateSigA; - uint64_t sigMean; - bool signZ; - 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 ); - if ( expA == 0x7FF ) { - if ( sigA || ( ( expB == 0x7FF ) && sigB ) ) goto propagateNaN; - goto invalid; - } - if ( expB == 0x7FF ) { - if ( sigB ) goto propagateNaN; - 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; - } - expDiff = expA - expB; - sigA = ( sigA | UINT64_C( 0x0010000000000000 ) )<<11; - sigB = ( sigB | UINT64_C( 0x0010000000000000 ) )<<11; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - sigA >>= 1; - } - q = ( sigB <= sigA ); - if ( q ) sigA -= sigB; - expDiff -= 64; - while ( 0 < expDiff ) { - q = softfloat_estimateDiv128To64( sigA, 0, sigB ); - q = ( 2 < q ) ? q - 2 : 0; - sigA = - ( ( sigB>>2 ) * q ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = softfloat_estimateDiv128To64( sigA, 0, sigB ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - sigB >>= 2; - sigA = ( ( sigA>>1 )<<( expDiff - 1 ) ) - sigB * q; - } else { - sigA >>= 2; - sigB >>= 2; - } - do { - alternateSigA = sigA; - ++q; - sigA -= sigB; - } while ( sigA < UINT64_C( 0x8000000000000000 ) ); - sigMean = sigA + alternateSigA; - if ( - ( UINT64_C( 0x8000000000000000 ) <= sigMean ) - || ( ! sigMean && ( q & 1 ) ) - ) { - sigA = alternateSigA; - } - signZ = ( UINT64_C( 0x8000000000000000 ) <= sigA ); - if ( signZ ) sigA = - sigA; - return softfloat_normRoundPackToF64( signA ^ signZ, expB, sigA ); - 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/softfloat/SoftFloat-3/source/f64_roundToInt.c b/softfloat/SoftFloat-3/source/f64_roundToInt.c deleted file mode 100755 index ef16dfa..0000000 --- a/softfloat/SoftFloat-3/source/f64_roundToInt.c +++ /dev/null @@ -1,80 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float64_t f64_roundToInt( float64_t a, int_fast8_t roundingMode, bool exact ) -{ - union ui64_f64 uA; - uint_fast64_t uiA; - int_fast16_t expA; - uint_fast64_t uiZ; - bool signA; - uint_fast64_t lastBitMask, roundBitsMask; - union ui64_f64 uZ; - - uA.f = a; - uiA = uA.ui; - expA = expF64UI( uiA ); - if ( 0x433 <= expA ) { - if ( ( expA == 0x7FF ) && fracF64UI( uiA ) ) { - uiZ = softfloat_propagateNaNF64UI( uiA, 0 ); - goto uiZ; - } - return a; - } - if ( expA <= 0x3FE ) { - if ( ! ( uiA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) ) return a; - if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; - signA = signF64UI( uiA ); - switch ( roundingMode ) { - case softfloat_round_nearest_even: - if ( ( expA == 0x3FE ) && fracF64UI( uiA ) ) { - uiZ = packToF64UI( signA, 0x3FF, 0 ); - goto uiZ; - } - break; - case softfloat_round_min: - uiZ = signA ? UINT64_C( 0xBFF0000000000000 ) : 0; - goto uiZ; - case softfloat_round_max: - uiZ = - signA ? UINT64_C( 0x8000000000000000 ) - : UINT64_C( 0x3FF0000000000000 ); - goto uiZ; - case softfloat_round_nearest_maxMag: - if ( expA == 0x3FE ) { - uiZ = packToF64UI( signA, 0x3FF, 0 ); - goto uiZ; - } - break; - } - uiZ = packToF64UI( signA, 0, 0 ); - goto uiZ; - } - lastBitMask = (uint_fast64_t) 1<<( 0x433 - expA ); - roundBitsMask = lastBitMask - 1; - uiZ = uiA; - if ( roundingMode == softfloat_round_nearest_maxMag ) { - uiZ += lastBitMask>>1; - } else if ( roundingMode == softfloat_round_nearest_even ) { - uiZ += lastBitMask>>1; - if ( ! ( uiZ & roundBitsMask ) ) uiZ &= ~ lastBitMask; - } else if ( roundingMode != softfloat_round_minMag ) { - if ( signF64UI( uiZ ) ^ ( roundingMode == softfloat_round_max ) ) { - uiZ += roundBitsMask; - } - } - uiZ &= ~ roundBitsMask; - if ( exact && ( uiZ != uiA ) ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/f64_sqrt.c b/softfloat/SoftFloat-3/source/f64_sqrt.c deleted file mode 100755 index cd91010..0000000 --- a/softfloat/SoftFloat-3/source/f64_sqrt.c +++ /dev/null @@ -1,74 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.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; - uint_fast32_t sigZ32; - uint_fast64_t sigZ; - struct uint128 term, rem; - 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; - } - expZ = ( ( expA - 0x3FF )>>1 ) + 0x3FE; - sigA |= UINT64_C( 0x0010000000000000 ); - sigZ32 = softfloat_estimateSqrt32( expA, sigA>>21 ); - sigA <<= 9 - ( expA & 1 ); - sigZ = - softfloat_estimateDiv128To64( sigA, 0, (uint_fast64_t) sigZ32<<32 ) - + ( (uint_fast64_t) sigZ32<<30 ); - if ( ( sigZ & 0x1FF ) <= 5 ) { - term = softfloat_mul64To128( sigZ, sigZ ); - rem = softfloat_sub128( sigA, 0, term.v64, term.v0 ); - while ( UINT64_C( 0x8000000000000000 ) <= rem.v64 ) { - --sigZ; - rem = - softfloat_add128( - rem.v64, rem.v0, sigZ>>63, (uint64_t) ( sigZ<<1 ) ); - } - sigZ |= ( ( rem.v64 | rem.v0 ) != 0 ); - } - return softfloat_roundPackToF64( 0, expZ, sigZ ); - invalid: - softfloat_raiseFlags( softfloat_flag_invalid ); - uiZ = defaultNaNF64UI; - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/f64_sub.c b/softfloat/SoftFloat-3/source/f64_sub.c deleted file mode 100755 index 38bd574..0000000 --- a/softfloat/SoftFloat-3/source/f64_sub.c +++ /dev/null @@ -1,29 +0,0 @@ - -#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; - float64_t ( *magsRoutine )( uint_fast64_t, uint_fast64_t, bool ); - - uA.f = a; - uiA = uA.ui; - signA = signF64UI( uiA ); - uB.f = b; - uiB = uB.ui; - signB = signF64UI( uiB ); - magsRoutine = - ( signA == signB ) ? softfloat_subMagsF64 : softfloat_addMagsF64; - return magsRoutine( uiA, uiB, signA ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_to_f32.c b/softfloat/SoftFloat-3/source/f64_to_f32.c deleted file mode 100755 index 395d6c6..0000000 --- a/softfloat/SoftFloat-3/source/f64_to_f32.c +++ /dev/null @@ -1,43 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.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 sig; - uint_fast32_t uiZ, sig32; - union ui32_f32 uZ; - - uA.f = a; - uiA = uA.ui; - sign = signF64UI( uiA ); - exp = expF64UI( uiA ); - sig = fracF64UI( uiA ); - if ( exp == 0x7FF ) { - uiZ = - sig ? softfloat_commonNaNToF32UI( - softfloat_f64UIToCommonNaN( uiA ) ) - : packToF32UI( sign, 0xFF, 0 ); - goto uiZ; - } - sig32 = softfloat_shortShift64RightJam( sig, 22 ); - if ( ! ( exp | sig32 ) ) { - uiZ = packToF32UI( sign, 0, 0 ); - goto uiZ; - } - return softfloat_roundPackToF32( sign, exp - 0x381, sig32 | 0x40000000 ); - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/f64_to_i32.c b/softfloat/SoftFloat-3/source/f64_to_i32.c deleted file mode 100755 index 0778a86..0000000 --- a/softfloat/SoftFloat-3/source/f64_to_i32.c +++ /dev/null @@ -1,30 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -int_fast32_t f64_to_i32( float64_t a, int_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 shiftCount; - - uA.f = a; - uiA = uA.ui; - sign = signF64UI( uiA ); - exp = expF64UI( uiA ); - sig = fracF64UI( uiA ); - if ( ( exp == 0x7FF ) && sig ) sign = 0; - if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); - shiftCount = 0x42C - exp; - if ( 0 < shiftCount ) sig = softfloat_shift64RightJam( sig, shiftCount ); - return softfloat_roundPackToI32( sign, sig, roundingMode, exact ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_to_i32_r_minMag.c b/softfloat/SoftFloat-3/source/f64_to_i32_r_minMag.c deleted file mode 100755 index 39246c2..0000000 --- a/softfloat/SoftFloat-3/source/f64_to_i32_r_minMag.c +++ /dev/null @@ -1,50 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.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; - bool sign; - int_fast16_t shiftCount; - uint_fast32_t absZ; - union { uint32_t ui; int32_t i; } uZ; - int_fast32_t z; - - uA.f = a; - uiA = uA.ui; - exp = expF64UI( uiA ); - sig = fracF64UI( uiA ); - if ( exp < 0x3FF ) { - if ( exact && ( exp | sig ) ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - return 0; - } - sign = signF64UI( uiA ); - if ( 0x41E < exp ) { - if ( ( exp == 0x7FF ) && sig ) sign = 0; - goto invalid; - } - sig |= UINT64_C( 0x0010000000000000 ); - shiftCount = 0x433 - exp; - absZ = sig>>shiftCount; - uZ.ui = sign ? - absZ : absZ; - z = uZ.i; - if ( ( z < 0 ) != sign ) goto invalid; - if ( exact && ( (uint_fast64_t) absZ< -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -int_fast64_t f64_to_i64( float64_t a, int_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 shiftCount; - struct uint64_extra sigExtra; - - uA.f = a; - uiA = uA.ui; - sign = signF64UI( uiA ); - exp = expF64UI( uiA ); - sig = fracF64UI( uiA ); - if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); - shiftCount = 0x433 - exp; - if ( shiftCount <= 0 ) { - if ( 0x43E < exp ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - return - ! sign - || ( ( exp == 0x7FF ) - && ( sig != UINT64_C( 0x0010000000000000 ) ) ) - ? INT64_C( 0x7FFFFFFFFFFFFFFF ) - : - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; - } - sigExtra.v = sig<<( - shiftCount ); - sigExtra.extra = 0; - } else { - sigExtra = softfloat_shift64ExtraRightJam( sig, 0, shiftCount ); - } - return - softfloat_roundPackToI64( - sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_to_i64_r_minMag.c b/softfloat/SoftFloat-3/source/f64_to_i64_r_minMag.c deleted file mode 100755 index 525705b..0000000 --- a/softfloat/SoftFloat-3/source/f64_to_i64_r_minMag.c +++ /dev/null @@ -1,52 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.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 shiftCount; - int_fast64_t absZ; - - uA.f = a; - uiA = uA.ui; - sign = signF64UI( uiA ); - exp = expF64UI( uiA ); - sig = fracF64UI( uiA ); - shiftCount = exp - 0x433; - if ( 0 <= shiftCount ) { - if ( 0x43E <= exp ) { - if ( uiA != packToF64UI( 1, 0x43E, 0 ) ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - if ( ! sign || ( ( exp == 0x7FF ) && sig ) ) { - return INT64_C( 0x7FFFFFFFFFFFFFFF ); - } - } - return - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; - } - sig |= UINT64_C( 0x0010000000000000 ); - absZ = sig<>( - shiftCount ); - if ( exact && (uint64_t) ( sig<<( shiftCount & 63 ) ) ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - } - return sign ? - absZ : absZ; - -} - diff --git a/softfloat/SoftFloat-3/source/f64_to_ui32.c b/softfloat/SoftFloat-3/source/f64_to_ui32.c deleted file mode 100755 index b186605..0000000 --- a/softfloat/SoftFloat-3/source/f64_to_ui32.c +++ /dev/null @@ -1,29 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -uint_fast32_t f64_to_ui32( float64_t a, int_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 shiftCount; - - uA.f = a; - uiA = uA.ui; - sign = signF64UI( uiA ); - exp = expF64UI( uiA ); - sig = fracF64UI( uiA ); - if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); - shiftCount = 0x42C - exp; - if ( 0 < shiftCount ) sig = softfloat_shift64RightJam( sig, shiftCount ); - return softfloat_roundPackToUI32( sign, sig, roundingMode, exact ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_to_ui32_r_minMag.c b/softfloat/SoftFloat-3/source/f64_to_ui32_r_minMag.c deleted file mode 100755 index 9f1dd4d..0000000 --- a/softfloat/SoftFloat-3/source/f64_to_ui32_r_minMag.c +++ /dev/null @@ -1,40 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.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 shiftCount; - uint_fast32_t z; - - uA.f = a; - uiA = uA.ui; - exp = expF64UI( uiA ); - sig = fracF64UI( uiA ); - if ( exp < 0x3FF ) { - if ( exact && ( exp | sig ) ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - return 0; - } - if ( signF64UI( uiA ) || ( 0x41E < exp ) ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - return 0xFFFFFFFF; - } - sig |= UINT64_C( 0x0010000000000000 ); - shiftCount = 0x433 - exp; - z = sig>>shiftCount; - if ( exact && ( (uint_fast64_t) z< -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -uint_fast64_t f64_to_ui64( float64_t a, int_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 shiftCount; - struct uint64_extra sigExtra; - - uA.f = a; - uiA = uA.ui; - sign = signF64UI( uiA ); - exp = expF64UI( uiA ); - sig = fracF64UI( uiA ); - if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); - shiftCount = 0x433 - exp; - if ( shiftCount <= 0 ) { - if ( 0x43E < exp ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - return UINT64_C( 0xFFFFFFFFFFFFFFFF ); - } - sigExtra.v = sig<<( - shiftCount ); - sigExtra.extra = 0; - } else { - sigExtra = softfloat_shift64ExtraRightJam( sig, 0, shiftCount ); - } - return - softfloat_roundPackToUI64( - sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); - -} - diff --git a/softfloat/SoftFloat-3/source/f64_to_ui64_r_minMag.c b/softfloat/SoftFloat-3/source/f64_to_ui64_r_minMag.c deleted file mode 100755 index a66d3ff..0000000 --- a/softfloat/SoftFloat-3/source/f64_to_ui64_r_minMag.c +++ /dev/null @@ -1,45 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.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 shiftCount; - uint_fast64_t z; - - uA.f = a; - uiA = uA.ui; - exp = expF64UI( uiA ); - sig = fracF64UI( uiA ); - if ( exp < 0x3FF ) { - if ( exact && ( exp | sig ) ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - return 0; - } - if ( signF64UI( uiA ) ) goto invalid; - shiftCount = exp - 0x433; - if ( 0 <= shiftCount ) { - if ( 0x43E < exp ) goto invalid; - z = ( sig | UINT64_C( 0x0010000000000000 ) )<>( - shiftCount ); - if ( exact && (uint64_t) ( sig<<( shiftCount & 63 ) ) ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - } - return z; - invalid: - softfloat_raiseFlags( softfloat_flag_invalid ); - return UINT64_C( 0xFFFFFFFFFFFFFFFF ); - -} - diff --git a/softfloat/SoftFloat-3/source/i32_to_f32.c b/softfloat/SoftFloat-3/source/i32_to_f32.c deleted file mode 100755 index f51facd..0000000 --- a/softfloat/SoftFloat-3/source/i32_to_f32.c +++ /dev/null @@ -1,21 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -float32_t i32_to_f32( int_fast32_t a ) -{ - bool sign; - union ui32_f32 uZ; - - sign = ( a < 0 ); - if ( ! ( a & 0x7FFFFFFF ) ) { - uZ.ui = sign ? packToF32UI( 1, 0x9E, 0 ) : 0; - return uZ.f; - } - return softfloat_normRoundPackToF32( sign, 0x9C, sign ? - a : a ); - -} - diff --git a/softfloat/SoftFloat-3/source/i32_to_f64.c b/softfloat/SoftFloat-3/source/i32_to_f64.c deleted file mode 100755 index d42cbe8..0000000 --- a/softfloat/SoftFloat-3/source/i32_to_f64.c +++ /dev/null @@ -1,31 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -float64_t i32_to_f64( int_fast32_t a ) -{ - uint_fast64_t uiZ; - bool sign; - uint_fast32_t absA; - int shiftCount; - union ui64_f64 uZ; - - if ( ! a ) { - uiZ = 0; - } else { - sign = ( a < 0 ); - absA = sign ? - a : a; - shiftCount = softfloat_countLeadingZeros32( absA ) + 21; - uiZ = - packToF64UI( - sign, 0x432 - shiftCount, (uint_fast64_t) absA< -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -float32_t i64_to_f32( int_fast64_t a ) -{ - bool sign; - uint_fast64_t absA; - int shiftCount; - union ui32_f32 u; - uint_fast32_t sig; - - sign = ( a < 0 ); - absA = sign ? - (uint_fast64_t) a : a; - shiftCount = softfloat_countLeadingZeros64( absA ) - 40; - if ( 0 <= shiftCount ) { - u.ui = - a ? packToF32UI( - sign, 0x95 - shiftCount, (uint_fast32_t) absA< -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -float64_t i64_to_f64( int_fast64_t a ) -{ - bool sign; - union ui64_f64 uZ; - - sign = ( a < 0 ); - if ( ! ( a & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) ) { - uZ.ui = sign ? packToF64UI( 1, 0x43E, 0 ) : 0; - return uZ.f; - } - return softfloat_normRoundPackToF64( sign, 0x43C, sign ? - a : a ); - -} - diff --git a/softfloat/SoftFloat-3/source/internals.h b/softfloat/SoftFloat-3/source/internals.h deleted file mode 100755 index cac0561..0000000 --- a/softfloat/SoftFloat-3/source/internals.h +++ /dev/null @@ -1,232 +0,0 @@ - -/*** UPDATE COMMENTS. ***/ - -#include "softfloat_types.h" - -union ui32_f32 { uint32_t ui; float32_t f; }; -union ui64_f64 { uint64_t ui; float64_t f; }; -#ifdef LITTLEENDIAN -union ui128_f128 { uint64_t ui0, ui64; float128_t f; }; -#else -union ui128_f128 { uint64_t ui64, ui0; float128_t f; }; -#endif - -enum { - softfloat_mulAdd_subC = 1, - softfloat_mulAdd_subProd = 2 -}; - -uint_fast32_t - softfloat_roundPackToUI32( bool, uint_fast64_t, int_fast8_t, bool ); -uint_fast64_t - softfloat_roundPackToUI64( - bool, uint_fast64_t, uint_fast64_t, int_fast8_t, bool ); -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the largest -| positive or negative integer is returned. -*----------------------------------------------------------------------------*/ -int_fast32_t - softfloat_roundPackToI32( bool, uint_fast64_t, int_fast8_t, bool ); -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit integer corresponding to the input. -| If `zSign' is 1, the input is negated before being converted to an integer. -| Ordinarily, the fixed-point input is simply rounded to an integer, with -| the inexact exception raised if the input cannot be represented exactly as -| an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest positive or negative integer is -| returned. -*----------------------------------------------------------------------------*/ -int_fast64_t - softfloat_roundPackToI64( - bool, uint_fast64_t, uint_fast64_t, int_fast8_t, bool ); - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a NaN; -| otherwise, returns 0. -*----------------------------------------------------------------------------*/ -#define isNaNF32UI( ui ) (0xFF000000<(uint32_t)((uint_fast32_t)(ui)<<1)) -/*---------------------------------------------------------------------------- -| Returns the sign bit of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ -#define signF32UI( a ) ((bool)((uint32_t)(a)>>31)) -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ -#define expF32UI( a ) ((int_fast16_t)((a)>>23)&0xFF) -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ -#define fracF32UI( a ) ((a)&0x007FFFFF) -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -| single-precision floating-point value, returning the result. After being -| shifted into the proper positions, the three fields are simply added -| together to form the result. This means that any integer portion of `zSig' -| will be added into the exponent. Since a properly normalized significand -| will have an integer portion equal to 1, the `zExp' input should be 1 less -| than the desired result exponent whenever `zSig' is a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ -#define packToF32UI( sign, exp, sig ) (((uint32_t)(sign)<<31)+((uint32_t)(exp)<<23)+(sig)) - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal single-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ -struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; } - softfloat_normSubnormalF32Sig( uint_fast32_t ); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. Ordinarily, the abstract -| value is simply rounded and packed into the single-precision format, with -| the inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal single- -| precision floating-point number. -| The input significand `zSig' has its binary point between bits 30 -| and 29, which is 7 bits to the left of the usual location. This shifted -| significand must be normalized or smaller. If `zSig' is not normalized, -| `zExp' must be 0; in that case, the result returned is a subnormal number, -| and it must not require rounding. In the usual case that `zSig' is -| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. -| The handling of underflow and overflow follows the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ -float32_t softfloat_roundPackToF32( bool, int_fast16_t, uint_fast32_t ); -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat32' except that `zSig' does not have to be normalized. -| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ -float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t ); - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the single-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ -float32_t softfloat_addMagsF32( uint_fast32_t, uint_fast32_t, bool ); -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the single- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ -float32_t softfloat_subMagsF32( uint_fast32_t, uint_fast32_t, bool ); -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -float32_t - softfloat_mulAddF32( int, uint_fast32_t, uint_fast32_t, uint_fast32_t ); - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a NaN; -| otherwise, returns 0. -*----------------------------------------------------------------------------*/ -#define isNaNF64UI( ui ) (UINT64_C(0xFFE0000000000000)<(uint64_t)((uint_fast64_t)(ui)<<1)) -/*---------------------------------------------------------------------------- -| Returns the sign bit of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ -#define signF64UI( a ) ((bool)((uint64_t)(a)>>63)) -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ -#define expF64UI( a ) ((int_fast16_t)((a)>>52)&0x7FF) -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ -#define fracF64UI( a ) ((a)&UINT64_C(0x000FFFFFFFFFFFFF)) -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -| double-precision floating-point value, returning the result. After being -| shifted into the proper positions, the three fields are simply added -| together to form the result. This means that any integer portion of `zSig' -| will be added into the exponent. Since a properly normalized significand -| will have an integer portion equal to 1, the `zExp' input should be 1 less -| than the desired result exponent whenever `zSig' is a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ -#define packToF64UI( sign, exp, sig ) (((uint64_t)(sign)<<63)+((uint64_t)(exp)<<52)+(sig)) - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal double-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ -struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; } - softfloat_normSubnormalF64Sig( uint_fast64_t ); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. Ordinarily, the abstract -| value is simply rounded and packed into the double-precision format, with -| the inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded -| to a subnormal number, and the underflow and inexact exceptions are raised -| if the abstract input cannot be represented exactly as a subnormal double- -| precision floating-point number. -| The input significand `zSig' has its binary point between bits 62 -| and 61, which is 10 bits to the left of the usual location. This shifted -| significand must be normalized or smaller. If `zSig' is not normalized, -| `zExp' must be 0; in that case, the result returned is a subnormal number, -| and it must not require rounding. In the usual case that `zSig' is -| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. -| The handling of underflow and overflow follows the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ -float64_t softfloat_roundPackToF64( bool, int_fast16_t, uint_fast64_t ); -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat64' except that `zSig' does not have to be normalized. -| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ -float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t ); - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the double-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ -float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool ); -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ -float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool ); -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -float64_t - softfloat_mulAddF64( int, uint_fast64_t, uint_fast64_t, uint_fast64_t ); - diff --git a/softfloat/SoftFloat-3/source/primitives.h b/softfloat/SoftFloat-3/source/primitives.h deleted file mode 100755 index 71038ea..0000000 --- a/softfloat/SoftFloat-3/source/primitives.h +++ /dev/null @@ -1,628 +0,0 @@ - -/*============================================================================ - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 3. - -*** UPDATE - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -#include -#include - -/*** CHANGE TO USE `fast' INTEGER TYPES? ***/ -/*** ADD 80-BIT FUNCTIONS? ***/ - -#ifdef LITTLEENDIAN -struct uintx80 { uint64_t v0; uint16_t v64; }; -struct uint128 { uint64_t v0, v64; }; -struct uint192 { uint64_t v0, v64, v128; }; -struct uint256 { uint64_t v0, v64, v128, v192; }; -#else -struct uintx80 { uint16_t v64; uint64_t v0; }; -struct uint128 { uint64_t v64, v0; }; -struct uint192 { uint64_t v128, v64, v0; }; -struct uint256 { uint64_t v256, v128, v64, v0; }; -#endif - -struct uint64_extra { uint64_t v, extra; }; -struct uint128_extra { uint64_t v64; uint64_t v0; uint64_t extra; }; - - -/*** SHIFT COUNTS CANNOT BE ZERO. MUST CHECK BEFORE CALLING! ***/ - - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' -| is equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ -#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, uint64_t, uint64_t, uint64_t ); -#endif - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 1 <= 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, uint64_t, uint64_t, uint64_t ); -#endif - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, -| returns 0. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 1 <= 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, uint64_t, uint64_t, uint64_t ); -#endif - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' must be less than 64. The result is broken into two 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 2 <= INLINE_LEVEL ) -INLINE struct uint128 - softfloat_shortShift128Left( uint64_t a64, uint64_t a0, unsigned int count ) -{ - struct uint128 z; - z.v64 = a64<>( ( - count ) & 63 ); - z.v0 = a0<>( negCount & 63 ); - z.v64 = a64<>( negCount & 63 ); - z.v0 = a0<>count | ( (uint32_t) ( a<<( ( - count ) & 31 ) ) != 0 ) - : ( a != 0 ); -} -#else -uint32_t softfloat_shift32RightJam( uint32_t, unsigned int ); -#endif - -/*---------------------------------------------------------------------------- -| Shift count is less than 32. -*----------------------------------------------------------------------------*/ -#if defined INLINE -INLINE uint32_t softfloat_shortShift32Right1Jam( uint32_t a ) - { return a>>1 | ( a & 1 ); } -#else -uint32_t softfloat_shortShift32Right1Jam( uint32_t ); -#endif - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 64, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 3 <= INLINE_LEVEL ) -INLINE uint64_t softfloat_shift64RightJam( uint64_t a, unsigned int count ) -{ - return - ( count < 64 ) - ? a>>count | ( (uint64_t) ( a<<( ( - count ) & 63 ) ) != 0 ) - : ( a != 0 ); -} -#else -uint64_t softfloat_shift64RightJam( uint64_t, unsigned int ); -#endif - -/*---------------------------------------------------------------------------- -| Shift count is less than 64. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 2 <= INLINE_LEVEL ) -INLINE uint64_t - softfloat_shortShift64RightJam( uint64_t a, unsigned int count ) - { return a>>count | ( ( a & ( ( (uint64_t) 1<>count; - z.extra = a<<( ( - count ) & 63 ); - } else { - z.v = 0; - z.extra = ( count == 64 ) ? a : ( a != 0 ); - } - z.extra |= ( extra != 0 ); - return z; -} -#else -struct uint64_extra - softfloat_shift64ExtraRightJam( uint64_t, uint64_t, unsigned int ); -#endif - -/*---------------------------------------------------------------------------- -| Shift count is less than 64. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 2 <= INLINE_LEVEL ) -INLINE struct uint64_extra - softfloat_shortShift64ExtraRightJam( - uint64_t a, uint64_t extra, unsigned int count ) -{ - struct uint64_extra z; - z.v = a>>count; - z.extra = a<<( ( - count ) & 63 ) | ( extra != 0 ); - return z; -} -#else -struct uint64_extra - softfloat_shortShift64ExtraRightJam( uint64_t, uint64_t, unsigned int ); -#endif - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' can be arbitrarily large; in particular, if `count' is greater -| than 128, the result will be 0. The result is broken into two 64-bit pieces -| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------- -| Shift count is less than 64. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 2 <= INLINE_LEVEL ) -INLINE struct uint128 - softfloat_shortShift128Right( uint64_t a64, uint64_t a0, unsigned int count ) -{ - struct uint128 z; - z.v64 = a64>>count; - z.v0 = a64<<( ( - count ) & 63 ) | a0>>count; - return z; -} -#else -struct uint128 - softfloat_shortShift128Right( uint64_t, uint64_t, unsigned int ); -#endif - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. If any nonzero bits are shifted off, they -| are ``jammed'' into the least significant bit of the result by setting the -| least significant bit to 1. The value of `count' can be arbitrarily large; -| in particular, if `count' is greater than 128, the result will be either -| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or -| nonzero. The result is broken into two 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 4 <= INLINE_LEVEL ) -INLINE struct uint128 - softfloat_shift128RightJam( uint64_t a64, uint64_t a0, unsigned int count ) -{ - unsigned int negCount; - struct uint128 z; - if ( count < 64 ) { - negCount = - count; - z.v64 = a64>>( count & 63 ); - z.v0 = - a64<<( negCount & 63 ) | a0>>count - | ( (uint64_t) ( a0<<( negCount & 63 ) ) != 0 ); - } else { - z.v64 = 0; - z.v0 = - ( count < 128 ) - ? a64>>( count & 63 ) - | ( ( ( a64 & ( ( (uint64_t) 1<<( count & 63 ) ) - 1 ) ) - | a0 ) - != 0 ) - : ( ( a64 | a0 ) != 0 ); - } - return z; -} -#else -struct uint128 - softfloat_shift128RightJam( uint64_t, uint64_t, unsigned int ); -#endif - -/*---------------------------------------------------------------------------- -| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right -| by 64 _plus_ the number of bits given in `count'. The shifted result is -| at most 128 nonzero bits; these are broken into two 64-bit pieces which are -| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted -| off form a third 64-bit result as follows: The _last_ bit shifted off is -| the most-significant bit of the extra result, and the other 63 bits of the -| extra result are all zero if and only if _all_but_the_last_ bits shifted off -| were all zero. This extra result is stored in the location pointed to by -| `z2Ptr'. The value of `count' can be arbitrarily large. -| (This routine makes more sense if `a0', `a1', and `a2' are considered -| to form a fixed-point value with binary point between `a1' and `a2'. This -| fixed-point value is shifted right by the number of bits given in `count', -| and the integer part of the result is returned at the locations pointed to -| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly -| corrupted as described above, and is returned at the location pointed to by -| `z2Ptr'.) -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 5 <= INLINE_LEVEL ) -INLINE struct uint128_extra - softfloat_shift128ExtraRightJam( - uint64_t a64, uint64_t a0, uint64_t extra, unsigned int count ) -{ - unsigned int negCount = - count; - struct uint128_extra z; - if ( count < 64 ) { - z.v64 = a64>>count; - z.v0 = a64<<( negCount & 63 ) | a0>>count; - z.extra = a0<<( negCount & 63 ); - } else { - z.v64 = 0; - if ( count == 64 ) { - z.v0 = a64; - z.extra = a0; - } else { - extra |= a0; - if ( count < 128 ) { - z.v0 = a64>>( count & 63 ); - z.extra = a64<<( negCount & 63 ); - } else { - z.v0 = 0; - z.extra = ( count == 128 ) ? a64 : ( a64 != 0 ); - } - } - } - z.extra |= ( extra != 0 ); - return z; -} -#else -struct uint128_extra - softfloat_shift128ExtraRightJam( uint64_t, uint64_t, uint64_t, unsigned int ); -#endif - -/*---------------------------------------------------------------------------- -| Shift count is less than 64. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 3 <= INLINE_LEVEL ) -INLINE struct uint128_extra - softfloat_shortShift128ExtraRightJam( - uint64_t a64, uint64_t a0, uint64_t extra, unsigned int count ) -{ - unsigned int negCount = - count; - struct uint128_extra z; - z.v64 = a64>>count; - z.v0 = a64<<( negCount & 63 ) | a0>>count; - z.extra = a0<<( negCount & 63 ) | ( extra != 0 ); - return z; -} -#else -struct uint128_extra - softfloat_shortShift128ExtraRightJam( - uint64_t, uint64_t, uint64_t, unsigned int ); -#endif - -extern const uint8_t softfloat_countLeadingZeros8[ 256 ]; - -/*---------------------------------------------------------------------------- -| 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 && ( 2 <= INLINE_LEVEL ) -INLINE int softfloat_countLeadingZeros32( uint32_t a ) -{ - int count = 0; - if ( a < 0x10000 ) { - count = 16; - a <<= 16; - } - if ( a < 0x1000000 ) { - count += 8; - a <<= 8; - } - count += softfloat_countLeadingZeros8[ a>>24 ]; - return count; -} -#else -int softfloat_countLeadingZeros32( uint32_t ); -#endif - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 64 is returned. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 4 <= INLINE_LEVEL ) -INLINE int softfloat_countLeadingZeros64( uint64_t a ) -{ - int count = 32; - uint32_t a32 = a; - if ( UINT64_C( 0x100000000 ) <= a ) { - count = 0; - a32 = a>>32; - } - /*------------------------------------------------------------------------ - | 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; -} -#else -int softfloat_countLeadingZeros64( uint64_t ); -#endif - -/*---------------------------------------------------------------------------- -| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit -| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so -| any carry out is lost. The result is broken into two 64-bit pieces which -| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ -#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.v64 += ( z.v0 < a0 ); - return z; -} -#else -struct uint128 softfloat_add128( uint64_t, uint64_t, uint64_t, uint64_t ); -#endif - -/*---------------------------------------------------------------------------- -| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the -| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is -| modulo 2^192, so any carry out is lost. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 3 <= INLINE_LEVEL ) -INLINE struct uint192 - softfloat_add192( - uint64_t a128, - uint64_t a64, - uint64_t a0, - uint64_t b128, - uint64_t b64, - uint64_t b0 - ) -{ - struct uint192 z; - unsigned int carry64, carry128; - z.v0 = a0 + b0; - carry64 = ( z.v0 < a0 ); - z.v64 = a64 + b64; - carry128 = ( z.v64 < a64 ); - z.v128 = a128 + b128; - z.v64 += carry64; - carry128 += ( z.v64 < carry64 ); - z.v128 += carry128; - return z; -} -#else -struct uint192 - softfloat_add192( - uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t ); -#endif - -/*---------------------------------------------------------------------------- -| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the -| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo -| 2^128, so any borrow out (carry out) is lost. The result is broken into two -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and -| `z1Ptr'. -*----------------------------------------------------------------------------*/ -#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, uint64_t, uint64_t, uint64_t ); -#endif - -/*---------------------------------------------------------------------------- -| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' -| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. -| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The -| result is broken into three 64-bit pieces which are stored at the locations -| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 3 <= INLINE_LEVEL ) -INLINE struct uint192 - softfloat_sub192( - uint64_t a128, - uint64_t a64, - uint64_t a0, - uint64_t b128, - uint64_t b64, - uint64_t b0 - ) -{ - struct uint192 z; - unsigned int borrow64, borrow128; - z.v0 = a0 - b0; - borrow64 = ( a0 < b0 ); - z.v64 = a64 - b64; - borrow128 = ( a64 < b64 ); - z.v128 = a128 - b128; - borrow128 += ( z.v64 < borrow64 ); - z.v64 -= borrow64; - z.v128 -= borrow128; - return z; -} -#else -struct uint192 - softfloat_sub192( - uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t ); -#endif - -/*---------------------------------------------------------------------------- -| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken -| into two 64-bit pieces which are stored at the locations pointed to by -| `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 4 <= INLINE_LEVEL ) -INLINE struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ) -{ - uint32_t a32 = a>>32; - uint32_t a0 = a; - uint32_t b32 = b>>32; - uint32_t b0 = b; - struct uint128 z; - uint64_t mid1, mid2, mid; - z.v0 = (uint64_t) a0 * b0; - mid1 = (uint64_t) a32 * b0; - mid2 = (uint64_t) a0 * b32; - z.v64 = (uint64_t) a32 * b32; - mid = mid1 + mid2; - z.v64 += ( (uint64_t) ( mid < mid1 ) )<<32 | mid>>32; - mid <<= 32; - z.v0 += mid; - z.v64 += ( z.v0 < mid ); - return z; -} -#else -struct uint128 softfloat_mul64To128( uint64_t, uint64_t ); -#endif - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by -| `b' to obtain a 192-bit product. The product is broken into three 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and -| `z2Ptr'. -*----------------------------------------------------------------------------*/ -struct uint192 softfloat_mul128By64To192( uint64_t, uint64_t, uint64_t ); -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the -| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit -| product. The product is broken into four 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. -*----------------------------------------------------------------------------*/ -struct uint256 softfloat_mul128To256( uint64_t, uint64_t, uint64_t, uint64_t ); - -/*---------------------------------------------------------------------------- -| Returns an approximation to the 64-bit integer quotient obtained by dividing -| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The -| divisor `b' must be at least 2^63. If q is the exact quotient truncated -| toward zero, the approximation returned lies between q and q + 2 inclusive. -| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit -| unsigned integer is returned. -*----------------------------------------------------------------------------*/ -uint64_t softfloat_estimateDiv128To64( uint64_t, uint64_t, uint64_t ); - -/*---------------------------------------------------------------------------- -| Returns an approximation to the square root of the 32-bit significand given -| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of -| `aExp' (the least significant bit) is 1, the integer returned approximates -| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' -| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either -| case, the approximation returned lies strictly within +/-2 of the exact -| value. -*----------------------------------------------------------------------------*/ -uint32_t softfloat_estimateSqrt32( unsigned int, uint32_t ); - diff --git a/softfloat/SoftFloat-3/source/riscv/platform.h b/softfloat/SoftFloat-3/source/riscv/platform.h deleted file mode 100755 index 9355edf..0000000 --- a/softfloat/SoftFloat-3/source/riscv/platform.h +++ /dev/null @@ -1,38 +0,0 @@ - -/*============================================================================ - -*** FIX. - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define LITTLEENDIAN - diff --git a/softfloat/SoftFloat-3/source/riscv/s_commonNaNToF32UI.c b/softfloat/SoftFloat-3/source/riscv/s_commonNaNToF32UI.c deleted file mode 100755 index 61f2735..0000000 --- a/softfloat/SoftFloat-3/source/riscv/s_commonNaNToF32UI.c +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include "platform.h" -#include "specialize.h" - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the single- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN a ) -{ - - return (uint_fast32_t) a.sign<<31 | 0x7FFFFFFF; - -} - diff --git a/softfloat/SoftFloat-3/source/riscv/s_commonNaNToF64UI.c b/softfloat/SoftFloat-3/source/riscv/s_commonNaNToF64UI.c deleted file mode 100755 index da36c04..0000000 --- a/softfloat/SoftFloat-3/source/riscv/s_commonNaNToF64UI.c +++ /dev/null @@ -1,18 +0,0 @@ - -#include -#include "platform.h" -#include "specialize.h" - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -uint_fast64_t softfloat_commonNaNToF64UI( struct commonNaN a ) -{ - - return - (uint_fast64_t) a.sign<<63 | UINT64_C( 0x7FFFFFFFFFFFFFFF ); - -} - diff --git a/softfloat/SoftFloat-3/source/riscv/s_f32UIToCommonNaN.c b/softfloat/SoftFloat-3/source/riscv/s_f32UIToCommonNaN.c deleted file mode 100755 index 9ee0db9..0000000 --- a/softfloat/SoftFloat-3/source/riscv/s_f32UIToCommonNaN.c +++ /dev/null @@ -1,25 +0,0 @@ - -#include -#include "platform.h" -#include "specialize.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ -struct commonNaN softfloat_f32UIToCommonNaN( uint_fast32_t uiA ) -{ - struct commonNaN z; - - if ( softfloat_isSigNaNF32UI( uiA ) ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - z.sign = uiA>>31; - z.v64 = (uint_fast64_t) 0x7FFFF <<41; - z.v0 = 0; - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/riscv/s_f64UIToCommonNaN.c b/softfloat/SoftFloat-3/source/riscv/s_f64UIToCommonNaN.c deleted file mode 100755 index 84d8ca0..0000000 --- a/softfloat/SoftFloat-3/source/riscv/s_f64UIToCommonNaN.c +++ /dev/null @@ -1,25 +0,0 @@ - -#include -#include "platform.h" -#include "specialize.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ -struct commonNaN softfloat_f64UIToCommonNaN( uint_fast64_t uiA ) -{ - struct commonNaN z; - - if ( softfloat_isSigNaNF64UI( uiA ) ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - z.sign = uiA>>63; - z.v64 = (uint_fast64_t) 0xFFFFFFFFFFFFF <<12; - z.v0 = 0; - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/riscv/s_isSigNaNF32UI.c b/softfloat/SoftFloat-3/source/riscv/s_isSigNaNF32UI.c deleted file mode 100755 index 0a9c33f..0000000 --- a/softfloat/SoftFloat-3/source/riscv/s_isSigNaNF32UI.c +++ /dev/null @@ -1,13 +0,0 @@ - -#include -#include -#include "platform.h" -#include "specialize.h" - -bool softfloat_isSigNaNF32UI( uint_fast32_t ui ) -{ - - return ( ( ui>>22 & 0x1FF ) == 0x1FE ) && ( ui & 0x003FFFFF ); - -} - diff --git a/softfloat/SoftFloat-3/source/riscv/s_isSigNaNF64UI.c b/softfloat/SoftFloat-3/source/riscv/s_isSigNaNF64UI.c deleted file mode 100755 index d255213..0000000 --- a/softfloat/SoftFloat-3/source/riscv/s_isSigNaNF64UI.c +++ /dev/null @@ -1,15 +0,0 @@ - -#include -#include -#include "platform.h" -#include "specialize.h" - -bool softfloat_isSigNaNF64UI( uint_fast64_t ui ) -{ - - return - ( ( ui>>51 & 0xFFF ) == 0xFFE ) - && ( ui & UINT64_C( 0x0007FFFFFFFFFFFF ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/riscv/s_propagateNaNF32UI.c b/softfloat/SoftFloat-3/source/riscv/s_propagateNaNF32UI.c deleted file mode 100755 index 07774e8..0000000 --- a/softfloat/SoftFloat-3/source/riscv/s_propagateNaNF32UI.c +++ /dev/null @@ -1,55 +0,0 @@ - -/*** UPDATE COMMENTS. ***/ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -uint_fast32_t - softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ) -{ - bool isNaNA, isSigNaNA, isNaNB, isSigNaNB; - uint_fast32_t uiMagA, uiMagB; - - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - isNaNA = isNaNF32UI( uiA ); - isSigNaNA = softfloat_isSigNaNF32UI( uiA ); - isNaNB = isNaNF32UI( uiB ); - isSigNaNB = softfloat_isSigNaNF32UI( uiB ); - /*------------------------------------------------------------------------ - | Make NaNs non-signaling. - *------------------------------------------------------------------------*/ - uiA |= 0x00400000; - uiB |= 0x00400000; - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if ( isSigNaNA | isSigNaNB ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - if ( isSigNaNA ) { - if ( isSigNaNB ) goto returnLargerSignificand; - return isNaNB ? uiB : uiA; - } else if ( isNaNA ) { - if ( isSigNaNB || ! isNaNB ) return uiA; - returnLargerSignificand: - uiMagA = uiA<<1; - uiMagB = uiB<<1; - if ( uiMagA < uiMagB ) return uiB; - if ( uiMagB < uiMagA ) return uiA; - return ( uiA < uiB ) ? uiA : uiB; - } else { - return uiB; - } - -} - diff --git a/softfloat/SoftFloat-3/source/riscv/s_propagateNaNF64UI.c b/softfloat/SoftFloat-3/source/riscv/s_propagateNaNF64UI.c deleted file mode 100755 index 0ff6446..0000000 --- a/softfloat/SoftFloat-3/source/riscv/s_propagateNaNF64UI.c +++ /dev/null @@ -1,55 +0,0 @@ - -/*** UPDATE COMMENTS. ***/ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -uint_fast64_t - softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ) -{ - bool isNaNA, isSigNaNA, isNaNB, isSigNaNB; - uint_fast64_t uiMagA, uiMagB; - - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - isNaNA = isNaNF64UI( uiA ); - isSigNaNA = softfloat_isSigNaNF64UI( uiA ); - isNaNB = isNaNF64UI( uiB ); - isSigNaNB = softfloat_isSigNaNF64UI( uiB ); - /*------------------------------------------------------------------------ - | Make NaNs non-signaling. - *------------------------------------------------------------------------*/ - uiA |= UINT64_C( 0x0008000000000000 ); - uiB |= UINT64_C( 0x0008000000000000 ); - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - if ( isSigNaNA | isSigNaNB ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - } - if ( isSigNaNA ) { - if ( isSigNaNB ) goto returnLargerSignificand; - return isNaNB ? uiB : uiA; - } else if ( isNaNA ) { - if ( isSigNaNB || ! isNaNB ) return uiA; - returnLargerSignificand: - uiMagA = uiA & UINT64_C( 0x7FFFFFFFFFFFFFFF ); - uiMagB = uiB & UINT64_C( 0x7FFFFFFFFFFFFFFF ); - if ( uiMagA < uiMagB ) return uiB; - if ( uiMagB < uiMagA ) return uiA; - return ( uiA < uiB ) ? uiA : uiB; - } else { - return uiB; - } - -} - diff --git a/softfloat/SoftFloat-3/source/riscv/softfloat_raiseFlags.c b/softfloat/SoftFloat-3/source/riscv/softfloat_raiseFlags.c deleted file mode 100755 index c0c0dc8..0000000 --- a/softfloat/SoftFloat-3/source/riscv/softfloat_raiseFlags.c +++ /dev/null @@ -1,51 +0,0 @@ - -/*============================================================================ - -*** FIX. - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -#include "platform.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Raises the exceptions specified by `flags'. Floating-point traps can be -| defined here if desired. It is currently not possible for such a trap -| to substitute a result value. If traps are not implemented, this routine -| should be simply `float_exception_flags |= flags;'. -*----------------------------------------------------------------------------*/ - -void softfloat_raiseFlags( int_fast8_t flags ) -{ - - softfloat_exceptionFlags |= flags; - -} - diff --git a/softfloat/SoftFloat-3/source/riscv/softfloat_types.h b/softfloat/SoftFloat-3/source/riscv/softfloat_types.h deleted file mode 100755 index b5c1828..0000000 --- a/softfloat/SoftFloat-3/source/riscv/softfloat_types.h +++ /dev/null @@ -1,16 +0,0 @@ - -#ifndef softfloat_types_h -#define softfloat_types_h - -/*** COMMENTS. ***/ - -#include -#include - -typedef struct { uint32_t v; } float32_t; -typedef struct { uint64_t v; } float64_t; -typedef struct { uint64_t v; uint16_t x; } floatx80_t; -typedef struct { uint64_t v[ 2 ]; } float128_t; - -#endif - diff --git a/softfloat/SoftFloat-3/source/riscv/specialize.h b/softfloat/SoftFloat-3/source/riscv/specialize.h deleted file mode 100755 index bf57bc9..0000000 --- a/softfloat/SoftFloat-3/source/riscv/specialize.h +++ /dev/null @@ -1,113 +0,0 @@ - -/*============================================================================ - -*** FIX. - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -#include -#include - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define init_detectTininess softfloat_tininess_beforeRounding; - -/*---------------------------------------------------------------------------- -| Structure used to transfer NaN representations from one format to another. -*----------------------------------------------------------------------------*/ -struct commonNaN { - bool sign; - uint64_t v64, v0; -}; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -#define defaultNaNF32UI 0xFFFFFFFF - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise, returns 0. -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 1 <= INLINE_LEVEL ) -INLINE bool softfloat_isSigNaNF32UI( uint_fast32_t ui ) - { return ( ( ui>>22 & 0x1FF ) == 0x1FE ) && ( ui & 0x003FFFFF ); } -#else -bool softfloat_isSigNaNF32UI( uint_fast32_t ); -#endif - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -struct commonNaN softfloat_f32UIToCommonNaN( uint_fast32_t ); -#if defined INLINE_LEVEL && ( 1 <= INLINE_LEVEL ) -INLINE uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN a ) - { return (uint_fast32_t) a.sign<<31 | 0x7FFFFFFF; } -#else -uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN ); -#endif - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ -uint_fast32_t softfloat_propagateNaNF32UI( uint_fast32_t, uint_fast32_t ); - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -#define defaultNaNF64UI UINT64_C(0xFFF8000000000000) - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#if defined INLINE_LEVEL && ( 1 <= INLINE_LEVEL ) -INLINE bool softfloat_isSigNaNF64UI( uint_fast64_t ui ) -{ - return - ( ( ui>>51 & 0xFFF ) == 0xFFE ) - && ( ui & UINT64_C( 0x0007FFFFFFFFFFFF ) ); -} -#else -bool softfloat_isSigNaNF64UI( uint_fast64_t ); -#endif - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -/*** MIGHT BE INLINE'D. ***/ -struct commonNaN softfloat_f64UIToCommonNaN( uint_fast64_t ); -uint_fast64_t softfloat_commonNaNToF64UI( struct commonNaN ); - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ -uint_fast64_t softfloat_propagateNaNF64UI( uint_fast64_t, uint_fast64_t ); - diff --git a/softfloat/SoftFloat-3/source/s_add128.c b/softfloat/SoftFloat-3/source/s_add128.c deleted file mode 100755 index 59c0348..0000000 --- a/softfloat/SoftFloat-3/source/s_add128.c +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -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.v64 += ( z.v0 < a0 ); - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/s_add192.c b/softfloat/SoftFloat-3/source/s_add192.c deleted file mode 100755 index 543eb5d..0000000 --- a/softfloat/SoftFloat-3/source/s_add192.c +++ /dev/null @@ -1,30 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -struct uint192 - softfloat_add192( - uint64_t a128, - uint64_t a64, - uint64_t a0, - uint64_t b128, - uint64_t b64, - uint64_t b0 - ) -{ - struct uint192 z; - unsigned int carry64, carry128; - - z.v0 = a0 + b0; - carry64 = ( z.v0 < a0 ); - z.v64 = a64 + b64; - carry128 = ( z.v64 < a64 ); - z.v128 = a128 + b128; - z.v64 += carry64; - carry128 += ( z.v64 < carry64 ); - z.v128 += carry128; - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/s_addMagsF32.c b/softfloat/SoftFloat-3/source/s_addMagsF32.c deleted file mode 100755 index f361e2b..0000000 --- a/softfloat/SoftFloat-3/source/s_addMagsF32.c +++ /dev/null @@ -1,75 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "specialize.h" - -float32_t - softfloat_addMagsF32( uint_fast32_t uiA, uint_fast32_t uiB, bool signZ ) -{ - int_fast16_t expA; - uint_fast32_t sigA; - int_fast16_t expB; - uint_fast32_t sigB; - int_fast16_t expDiff; - uint_fast32_t uiZ; - int_fast16_t expZ; - uint_fast32_t sigZ; - union ui32_f32 uZ; - - expA = expF32UI( uiA ); - sigA = fracF32UI( uiA ); - expB = expF32UI( uiB ); - sigB = fracF32UI( uiB ); - expDiff = expA - expB; - sigA <<= 6; - sigB <<= 6; - if ( ! expDiff ) { - if ( expA == 0xFF ) { - if ( sigA | sigB ) goto propagateNaN; - uiZ = uiA; - goto uiZ; - } - if ( ! expA ) { - uiZ = packToF32UI( signZ, 0, ( uiA + uiB ) & 0x7FFFFFFF ); - goto uiZ; - } - expZ = expA; - sigZ = 0x40000000 + sigA + sigB; - } else { - if ( expDiff < 0 ) { - if ( expB == 0xFF ) { - if ( sigB ) goto propagateNaN; - uiZ = packToF32UI( signZ, 0xFF, 0 ); - goto uiZ; - } - expZ = expB; - sigA += expA ? 0x20000000 : sigA; - sigA = softfloat_shift32RightJam( sigA, - expDiff ); - } else { - if ( expA == 0xFF ) { - if ( sigA ) goto propagateNaN; - uiZ = uiA; - goto uiZ; - } - expZ = expA; - sigB += expB ? 0x20000000 : sigB; - sigB = softfloat_shift32RightJam( sigB, expDiff ); - } - sigZ = 0x20000000 + sigA + sigB; - if ( sigZ < 0x40000000 ) { - --expZ; - sigZ <<= 1; - } - } - return softfloat_roundPackToF32( signZ, expZ, sigZ ); - propagateNaN: - uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/s_addMagsF64.c b/softfloat/SoftFloat-3/source/s_addMagsF64.c deleted file mode 100755 index a81c3e4..0000000 --- a/softfloat/SoftFloat-3/source/s_addMagsF64.c +++ /dev/null @@ -1,77 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.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; - sigA <<= 9; - sigB <<= 9; - if ( ! expDiff ) { - if ( expA == 0x7FF ) { - if ( sigA | sigB ) goto propagateNaN; - uiZ = uiA; - goto uiZ; - } - if ( ! expA ) { - uiZ = - packToF64UI( - signZ, 0, ( uiA + uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ); - goto uiZ; - } - expZ = expA; - sigZ = UINT64_C( 0x4000000000000000 ) + sigA + sigB; - } else { - if ( expDiff < 0 ) { - if ( expB == 0x7FF ) { - if ( sigB ) goto propagateNaN; - uiZ = packToF64UI( signZ, 0x7FF, 0 ); - goto uiZ; - } - expZ = expB; - sigA += expA ? UINT64_C( 0x2000000000000000 ) : sigA; - sigA = softfloat_shift64RightJam( sigA, - expDiff ); - } else { - if ( expA == 0x7FF ) { - if ( sigA ) goto propagateNaN; - uiZ = uiA; - goto uiZ; - } - expZ = expA; - sigB += expB ? UINT64_C( 0x2000000000000000 ) : sigB; - sigB = softfloat_shift64RightJam( 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/softfloat/SoftFloat-3/source/s_countLeadingZeros32.c b/softfloat/SoftFloat-3/source/s_countLeadingZeros32.c deleted file mode 100755 index 0bd17e1..0000000 --- a/softfloat/SoftFloat-3/source/s_countLeadingZeros32.c +++ /dev/null @@ -1,22 +0,0 @@ - -#include -#include "primitives.h" - -int softfloat_countLeadingZeros32( uint32_t a ) -{ - int count; - - count = 0; - if ( a < 0x10000 ) { - count = 16; - a <<= 16; - } - if ( a < 0x1000000 ) { - count += 8; - a <<= 8; - } - count += softfloat_countLeadingZeros8[ a>>24 ]; - return count; - -} - diff --git a/softfloat/SoftFloat-3/source/s_countLeadingZeros64.c b/softfloat/SoftFloat-3/source/s_countLeadingZeros64.c deleted file mode 100755 index 4a96cf6..0000000 --- a/softfloat/SoftFloat-3/source/s_countLeadingZeros64.c +++ /dev/null @@ -1,31 +0,0 @@ - -#include -#include "primitives.h" - -int softfloat_countLeadingZeros64( uint64_t a ) -{ - int count; - uint32_t a32; - - count = 32; - a32 = a; - if ( UINT64_C( 0x100000000 ) <= a ) { - count = 0; - a32 = a>>32; - } - /*------------------------------------------------------------------------ - | 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; - -} - diff --git a/softfloat/SoftFloat-3/source/s_countLeadingZeros8.c b/softfloat/SoftFloat-3/source/s_countLeadingZeros8.c deleted file mode 100755 index 4eca7e9..0000000 --- a/softfloat/SoftFloat-3/source/s_countLeadingZeros8.c +++ /dev/null @@ -1,24 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -const uint8_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/softfloat/SoftFloat-3/source/s_eq128.c b/softfloat/SoftFloat-3/source/s_eq128.c deleted file mode 100755 index 7261dc4..0000000 --- a/softfloat/SoftFloat-3/source/s_eq128.c +++ /dev/null @@ -1,13 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" - -bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) -{ - - return ( a64 == b64 ) && ( a0 == b0 ); - -} - diff --git a/softfloat/SoftFloat-3/source/s_estimateDiv128To64.c b/softfloat/SoftFloat-3/source/s_estimateDiv128To64.c deleted file mode 100755 index f8610a2..0000000 --- a/softfloat/SoftFloat-3/source/s_estimateDiv128To64.c +++ /dev/null @@ -1,28 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -uint64_t softfloat_estimateDiv128To64( uint64_t a64, uint64_t a0, uint64_t b ) -{ - uint32_t b32; - uint64_t z; - struct uint128 term, rem; - uint64_t rem32; - - if ( b <= a64 ) return UINT64_C( 0xFFFFFFFFFFFFFFFF ); - b32 = b>>32; - z = ( (uint64_t) b32<<32 <= a64 ) ? UINT64_C( 0xFFFFFFFF00000000 ) - : ( a64 / b32 )<<32; - term = softfloat_mul64To128( b, z ); - rem = softfloat_sub128( a64, a0, term.v64, term.v0 ); - while ( UINT64_C( 0x8000000000000000 ) <= rem.v64 ) { - z -= UINT64_C( 0x100000000 ); - rem = softfloat_add128( rem.v64, rem.v0, b32, (uint64_t) ( b<<32 ) ); - } - rem32 = ( rem.v64<<32 ) | ( rem.v0>>32 ); - z |= ( (uint64_t) b32<<32 <= rem32 ) ? 0xFFFFFFFF : rem32 / b32; - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/s_estimateSqrt32.c b/softfloat/SoftFloat-3/source/s_estimateSqrt32.c deleted file mode 100755 index e22a9dc..0000000 --- a/softfloat/SoftFloat-3/source/s_estimateSqrt32.c +++ /dev/null @@ -1,37 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -uint32_t softfloat_estimateSqrt32( unsigned int expA, uint32_t a ) -{ - static const uint16_t sqrtOddAdjustments[] = { - 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, - 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 - }; - static const uint16_t sqrtEvenAdjustments[] = { - 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, - 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 - }; - int index; - uint32_t z; - union { uint32_t ui; int32_t i; } u32; - - index = ( a>>27 ) & 15; - if ( expA & 1 ) { - z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; - z = ( ( a / z )<<14 ) + ( z<<15 ); - a >>= 1; - } else { - z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; - z = a / z + z; - z = ( 0x20000 <= z ) ? 0xFFFF8000 : z<<15; - if ( z <= a ) { - u32.ui = a; - return u32.i>>1; - } - } - return (uint32_t) ( ( (uint64_t) a<<31 ) / z ) + ( z>>1 ); - -} - diff --git a/softfloat/SoftFloat-3/source/s_le128.c b/softfloat/SoftFloat-3/source/s_le128.c deleted file mode 100755 index 83b1d7f..0000000 --- a/softfloat/SoftFloat-3/source/s_le128.c +++ /dev/null @@ -1,13 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" - -bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) -{ - - return ( a64 < b64 ) || ( ( a64 == b64 ) && ( a0 <= b0 ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/s_lt128.c b/softfloat/SoftFloat-3/source/s_lt128.c deleted file mode 100755 index 33a3df4..0000000 --- a/softfloat/SoftFloat-3/source/s_lt128.c +++ /dev/null @@ -1,13 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" - -bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) -{ - - return ( a64 < b64 ) || ( ( a64 == b64 ) && ( a0 < b0 ) ); - -} - diff --git a/softfloat/SoftFloat-3/source/s_mul128By64To192.c b/softfloat/SoftFloat-3/source/s_mul128By64To192.c deleted file mode 100755 index dfa8825..0000000 --- a/softfloat/SoftFloat-3/source/s_mul128By64To192.c +++ /dev/null @@ -1,20 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -struct uint192 - softfloat_mul128By64To192( uint64_t a64, uint64_t a0, uint64_t b ) -{ - struct uint128 p0, p64; - struct uint192 z; - - p0 = softfloat_mul64To128( a0, b ); - z.v0 = p0.v0; - p64 = softfloat_mul64To128( a64, b ); - z.v64 = p64.v0 + p0.v64; - z.v128 = p64.v64 + ( z.v64 < p64.v0 ); - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/s_mul128To256.c b/softfloat/SoftFloat-3/source/s_mul128To256.c deleted file mode 100755 index a96cd94..0000000 --- a/softfloat/SoftFloat-3/source/s_mul128To256.c +++ /dev/null @@ -1,28 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -struct uint256 - softfloat_mul128To256( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) -{ - struct uint128 p0, p64, p128; - struct uint256 z; - - p0 = softfloat_mul64To128( a0, b0 ); - z.v0 = p0.v0; - p64 = softfloat_mul64To128( a64, b0 ); - z.v64 = p64.v0 + p0.v64; - z.v128 = p64.v64 + ( z.v64 < p64.v0 ); - p128 = softfloat_mul64To128( a64, b64 ); - z.v128 += p128.v0; - z.v192 = p128.v64 + ( z.v128 < p128.v0 ); - p64 = softfloat_mul64To128( a0, b64 ); - z.v64 += p64.v0; - p64.v64 += ( z.v64 < p64.v0 ); - z.v128 += p64.v64; - z.v192 += ( z.v128 < p64.v64 ); - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/s_mul64To128.c b/softfloat/SoftFloat-3/source/s_mul64To128.c deleted file mode 100755 index c17780b..0000000 --- a/softfloat/SoftFloat-3/source/s_mul64To128.c +++ /dev/null @@ -1,28 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ) -{ - uint32_t a32, a0, b32, b0; - struct uint128 z; - uint64_t mid1, mid2, mid; - - a32 = a>>32; - a0 = a; - b32 = b>>32; - b0 = b; - z.v0 = (uint64_t) a0 * b0; - mid1 = (uint64_t) a32 * b0; - mid2 = (uint64_t) a0 * b32; - z.v64 = (uint64_t) a32 * b32; - mid = mid1 + mid2; - z.v64 += ( (uint64_t) ( mid < mid1 ) )<<32 | mid>>32; - mid <<= 32; - z.v0 += mid; - z.v64 += ( z.v0 < mid ); - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/s_mulAddF32.c b/softfloat/SoftFloat-3/source/s_mulAddF32.c deleted file mode 100755 index e55a0ba..0000000 --- a/softfloat/SoftFloat-3/source/s_mulAddF32.c +++ /dev/null @@ -1,171 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float32_t - softfloat_mulAddF32( - int op, uint_fast32_t uiA, uint_fast32_t uiB, uint_fast32_t uiC ) -{ - 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 sigZ64, sigC64; - int shiftCount; - 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_shortShift64RightJam( 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_shift64RightJam( sigProd, 32 - expDiff ); - } else { - expZ = expProd; - sigZ64 = - sigProd - + softfloat_shift64RightJam( - (uint_fast64_t) sigC<<32, expDiff ); - sigZ = softfloat_shortShift64RightJam( sigZ64, 32 ); - } - if ( sigZ < 0x40000000 ) { - --expZ; - sigZ <<= 1; - } - } else { -/*** OPTIMIZE BETTER? ***/ - sigC64 = (uint_fast64_t) sigC<<32; - if ( expDiff < 0 ) { - signZ = signC; - expZ = expC; - sigZ64 = sigC64 - softfloat_shift64RightJam( sigProd, - expDiff ); - } else if ( ! expDiff ) { - expZ = expProd; - sigZ64 = sigProd - sigC64; - if ( ! sigZ64 ) goto completeCancellation; - if ( sigZ64 & UINT64_C( 0x8000000000000000 ) ) { - signZ ^= 1; - sigZ64 = - sigZ64; - } - } else { - expZ = expProd; - sigZ64 = sigProd - softfloat_shift64RightJam( sigC64, expDiff ); - } - shiftCount = softfloat_countLeadingZeros64( sigZ64 ) - 1; - expZ -= shiftCount; - shiftCount -= 32; - if ( shiftCount < 0 ) { - sigZ = softfloat_shortShift64RightJam( sigZ64, - shiftCount ); - } else { - sigZ = (uint_fast32_t) sigZ64< -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float64_t - softfloat_mulAddF64( - int op, uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC ) -{ - 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 signProd; - uint_fast64_t magBits, uiZ; - struct exp16_sig64 normExpSig; - int_fast16_t expProd; - struct uint128 sigProd; - bool signZ; - int_fast16_t expZ; - uint_fast64_t sigZ; - int_fast16_t expDiff; - struct uint128 sigC128, sigZ128; - int shiftCount; - 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 ); - signProd = 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; - } - expProd = expA + expB - 0x3FE; - sigA = ( sigA | UINT64_C( 0x0010000000000000 ) )<<10; - sigB = ( sigB | UINT64_C( 0x0010000000000000 ) )<<10; - sigProd = softfloat_mul64To128( sigA, sigB ); - if ( sigProd.v64 < UINT64_C( 0x2000000000000000 ) ) { - --expProd; - sigProd = softfloat_shortShift128Left( sigProd.v64, sigProd.v0, 1 ); - } - signZ = signProd; - if ( ! expC ) { - if ( ! sigC ) { - expZ = expProd - 1; - sigZ = sigProd.v64<<1 | ( sigProd.v0 != 0 ); - goto roundPack; - } - normExpSig = softfloat_normSubnormalF64Sig( sigC ); - expC = normExpSig.exp; - sigC = normExpSig.sig; - } - sigC = ( sigC | UINT64_C( 0x0010000000000000 ) )<<9; - expDiff = expProd - expC; - if ( signProd == signC ) { - if ( expDiff <= 0 ) { - expZ = expC; - if ( expDiff ) { - sigProd.v64 = - softfloat_shift64RightJam( sigProd.v64, - expDiff ); - } - sigZ = ( sigC + sigProd.v64 ) | ( sigProd.v0 != 0 ); - } else { - expZ = expProd; - sigC128 = softfloat_shift128RightJam( sigC, 0, expDiff ); - sigZ128 = - softfloat_add128( - sigProd.v64, sigProd.v0, sigC128.v64, sigC128.v0 ); - sigZ = sigZ128.v64 | ( sigZ128.v0 != 0 ); - } - if ( sigZ < UINT64_C( 0x4000000000000000 ) ) { - --expZ; - sigZ <<= 1; - } - } else { -/*** OPTIMIZE BETTER? ***/ - if ( expDiff < 0 ) { - signZ = signC; - expZ = expC; - sigProd = - softfloat_shift128RightJam( - sigProd.v64, sigProd.v0, - expDiff ); - sigZ128 = softfloat_sub128( sigC, 0, sigProd.v64, sigProd.v0 ); - } else if ( ! expDiff ) { - expZ = expProd; - sigZ128 = softfloat_sub128( sigProd.v64, sigProd.v0, sigC, 0 ); - if ( ! ( sigZ128.v64 | sigZ128.v0 ) ) goto completeCancellation; - if ( sigZ128.v64 & UINT64_C( 0x8000000000000000 ) ) { - signZ ^= 1; - sigZ128 = softfloat_sub128( 0, 0, sigZ128.v64, sigZ128.v0 ); - } - } else { - expZ = expProd; - sigC128 = softfloat_shift128RightJam( sigC, 0, expDiff ); - sigZ128 = - softfloat_sub128( - sigProd.v64, sigProd.v0, sigC128.v64, sigC128.v0 ); - } - if ( ! sigZ128.v64 ) { - expZ -= 64; - sigZ128.v64 = sigZ128.v0; - sigZ128.v0 = 0; - } - shiftCount = softfloat_countLeadingZeros64( sigZ128.v64 ) - 1; - expZ -= shiftCount; - if ( shiftCount < 0 ) { - sigZ = softfloat_shortShift64RightJam( sigZ128.v64, - shiftCount ); - } else { - sigZ128 = - softfloat_shortShift128Left( - sigZ128.v64, sigZ128.v0, shiftCount ); - sigZ = sigZ128.v64; - } - sigZ |= ( sigZ128.v0 != 0 ); - } - roundPack: - return softfloat_roundPackToF64( signZ, expZ, sigZ ); - propagateNaN_ABC: - uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); - goto propagateNaN_ZC; - infProdArg: - if ( magBits ) { - uiZ = packToF64UI( signProd, 0x7FF, 0 ); - if ( expC != 0x7FF ) goto uiZ; - if ( sigC ) goto propagateNaN_ZC; - if ( signProd == signC ) goto uiZ; - } - invalid: - softfloat_raiseFlags( softfloat_flag_invalid ); - uiZ = defaultNaNF64UI; - propagateNaN_ZC: - uiZ = softfloat_propagateNaNF64UI( uiZ, uiC ); - goto uiZ; - zeroProd: - uiZ = uiC; - if ( ! ( expC | sigC ) && ( signProd != signC ) ) { - completeCancellation: - uiZ = - packToF64UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); - } - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/s_normRoundPackToF32.c b/softfloat/SoftFloat-3/source/s_normRoundPackToF32.c deleted file mode 100755 index 2e6f4b0..0000000 --- a/softfloat/SoftFloat-3/source/s_normRoundPackToF32.c +++ /dev/null @@ -1,24 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" - -float32_t - softfloat_normRoundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig ) -{ - int shiftCount; - union ui32_f32 uZ; - - shiftCount = softfloat_countLeadingZeros32( sig ) - 1; - exp -= shiftCount; - if ( ( 7 <= shiftCount ) && ( (uint16_t) exp < 0xFD ) ) { - uZ.ui = packToF32UI( sign, sig ? exp : 0, sig<<( shiftCount - 7 ) ); - return uZ.f; - } else { - return softfloat_roundPackToF32( sign, exp, sig< -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" - -float64_t - softfloat_normRoundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig ) -{ - int shiftCount; - union ui64_f64 uZ; - - shiftCount = softfloat_countLeadingZeros64( sig ) - 1; - exp -= shiftCount; - if ( ( 10 <= shiftCount ) && ( (uint16_t) exp < 0x7FD ) ) { - uZ.ui = packToF64UI( sign, sig ? exp : 0, sig<<( shiftCount - 10 ) ); - return uZ.f; - } else { - return softfloat_roundPackToF64( sign, exp, sig< -#include "platform.h" -#include "primitives.h" -#include "internals.h" - -struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t sig ) -{ - int shiftCount; - struct exp16_sig32 z; - - shiftCount = softfloat_countLeadingZeros32( sig ) - 8; - z.exp = 1 - shiftCount; - z.sig = sig< -#include "platform.h" -#include "primitives.h" -#include "internals.h" - -struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t sig ) -{ - int shiftCount; - struct exp16_sig64 z; - - shiftCount = softfloat_countLeadingZeros64( sig ) - 11; - z.exp = 1 - shiftCount; - z.sig = sig< -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -float32_t - softfloat_roundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig ) -{ - int roundingMode; - bool roundNearestEven; - int roundIncrement, roundBits; - bool isTiny; - uint_fast32_t uiZ; - union ui32_f32 uZ; - - roundingMode = softfloat_roundingMode; - roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); - roundIncrement = 0x40; - if ( - ! roundNearestEven - && ( roundingMode != softfloat_round_nearest_maxMag ) - ) { - roundIncrement = - ( roundingMode == softfloat_round_minMag ) - || ( roundingMode - == ( sign ? softfloat_round_max : softfloat_round_min ) ) - ? 0 - : 0x7F; - } - roundBits = sig & 0x7F; - if ( 0xFD <= (uint16_t) exp ) { - if ( exp < 0 ) { - isTiny = - ( softfloat_detectTininess - == softfloat_tininess_beforeRounding ) - || ( exp < -1 ) - || ( sig + roundIncrement < 0x80000000 ); - sig = softfloat_shift32RightJam( 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; - } - } - if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; - sig = ( sig + roundIncrement )>>7; - sig &= ~ ( ! ( roundBits ^ 0x40 ) & roundNearestEven ); - uiZ = packToF32UI( sign, sig ? exp : 0, sig ); - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/s_roundPackToF64.c b/softfloat/SoftFloat-3/source/s_roundPackToF64.c deleted file mode 100755 index fb0ef1d..0000000 --- a/softfloat/SoftFloat-3/source/s_roundPackToF64.c +++ /dev/null @@ -1,66 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -float64_t - softfloat_roundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig ) -{ - int roundingMode; - bool roundNearestEven; - int roundIncrement, roundBits; - bool isTiny; - uint_fast64_t uiZ; - union ui64_f64 uZ; - - roundingMode = softfloat_roundingMode; - roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); - roundIncrement = 0x200; - if ( - ! roundNearestEven - && ( roundingMode != softfloat_round_nearest_maxMag ) - ) { - roundIncrement = - ( roundingMode == softfloat_round_minMag ) - || ( roundingMode - == ( sign ? softfloat_round_max : softfloat_round_min ) ) - ? 0 - : 0x3FF; - } - 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_shift64RightJam( 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; - } - } - if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; - sig = ( sig + roundIncrement )>>10; - sig &= ~ ( ! ( roundBits ^ 0x200 ) & roundNearestEven ); - uiZ = packToF64UI( sign, sig ? exp : 0, sig ); - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/s_roundPackToI32.c b/softfloat/SoftFloat-3/source/s_roundPackToI32.c deleted file mode 100755 index 1c91497..0000000 --- a/softfloat/SoftFloat-3/source/s_roundPackToI32.c +++ /dev/null @@ -1,48 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -int_fast32_t - softfloat_roundPackToI32( - bool sign, uint_fast64_t sig, int_fast8_t roundingMode, bool exact ) -{ - bool roundNearestEven; - int roundIncrement, roundBits; - uint_fast32_t sig32; - union { uint32_t ui; int32_t i; } uZ; - int_fast32_t z; - - roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); - roundIncrement = 0x40; - if ( - ! roundNearestEven - && ( roundingMode != softfloat_round_nearest_maxMag ) - ) { - roundIncrement = - ( roundingMode == softfloat_round_minMag ) - || ( roundingMode - == ( sign ? softfloat_round_max : softfloat_round_min ) ) - ? 0 - : 0x7F; - } - roundBits = sig & 0x7F; - sig += roundIncrement; - if ( sig & UINT64_C( 0xFFFFFF8000000000 ) ) goto invalid; - sig32 = sig>>7; - sig32 &= ~ ( ! ( roundBits ^ 0x40 ) & roundNearestEven ); - uZ.ui = sign ? - sig32 : sig32; - z = uZ.i; - if ( z && ( ( z < 0 ) ^ sign ) ) goto invalid; - if ( exact && roundBits ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - return z; - invalid: - softfloat_raiseFlags( softfloat_flag_invalid ); - return sign ? -0x7FFFFFFF - 1 : 0x7FFFFFFF; - -} - diff --git a/softfloat/SoftFloat-3/source/s_roundPackToI64.c b/softfloat/SoftFloat-3/source/s_roundPackToI64.c deleted file mode 100755 index b2f5d63..0000000 --- a/softfloat/SoftFloat-3/source/s_roundPackToI64.c +++ /dev/null @@ -1,52 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -int_fast64_t - softfloat_roundPackToI64( - bool sign, - uint_fast64_t sig64, - uint_fast64_t sig0, - int_fast8_t roundingMode, - bool exact - ) -{ - bool roundNearestEven, increment; - union { uint64_t ui; int64_t i; } uZ; - int_fast64_t z; - - roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); - increment = ( UINT64_C( 0x8000000000000000 ) <= sig0 ); - if ( - ! roundNearestEven - && ( roundingMode != softfloat_round_nearest_maxMag ) - ) { - increment = - ( roundingMode != softfloat_round_minMag ) - && ( roundingMode - == ( sign ? softfloat_round_min : softfloat_round_max ) ) - && sig0; - } - if ( increment ) { - ++sig64; - if ( ! sig64 ) goto invalid; - sig64 &= - ~ ( ! ( sig0 & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) - & roundNearestEven ); - } - uZ.ui = sign ? - sig64 : sig64; - z = uZ.i; - if ( z && ( ( z < 0 ) ^ sign ) ) goto invalid; - if ( exact && sig0 ) softfloat_exceptionFlags |= softfloat_flag_inexact; - return z; - invalid: - softfloat_raiseFlags( softfloat_flag_invalid ); - return - sign ? - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1 - : INT64_C( 0x7FFFFFFFFFFFFFFF ); - -} - diff --git a/softfloat/SoftFloat-3/source/s_roundPackToUI32.c b/softfloat/SoftFloat-3/source/s_roundPackToUI32.c deleted file mode 100755 index ab44ec7..0000000 --- a/softfloat/SoftFloat-3/source/s_roundPackToUI32.c +++ /dev/null @@ -1,44 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -uint_fast32_t - softfloat_roundPackToUI32( - bool sign, uint_fast64_t sig, int_fast8_t roundingMode, bool exact ) -{ - bool roundNearestEven; - int roundIncrement, roundBits; - uint_fast32_t z; - - roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); - roundIncrement = 0x40; - if ( - ! roundNearestEven - && ( roundingMode != softfloat_round_nearest_maxMag ) - ) { - roundIncrement = - ( roundingMode == softfloat_round_minMag ) - || ( roundingMode - == ( sign ? softfloat_round_max : softfloat_round_min ) ) - ? 0 - : 0x7F; - } - roundBits = sig & 0x7F; - sig += roundIncrement; - if ( sig & UINT64_C( 0xFFFFFF8000000000 ) ) goto invalid; - z = sig>>7; - z &= ~ ( ! ( roundBits ^ 0x40 ) & roundNearestEven ); - if ( sign && z ) goto invalid; - if ( exact && roundBits ) { - softfloat_exceptionFlags |= softfloat_flag_inexact; - } - return z; - invalid: - softfloat_raiseFlags( softfloat_flag_invalid ); - return 0xFFFFFFFF; - -} - diff --git a/softfloat/SoftFloat-3/source/s_roundPackToUI64.c b/softfloat/SoftFloat-3/source/s_roundPackToUI64.c deleted file mode 100755 index d42266f..0000000 --- a/softfloat/SoftFloat-3/source/s_roundPackToUI64.c +++ /dev/null @@ -1,46 +0,0 @@ - -#include -#include -#include "platform.h" -#include "internals.h" -#include "softfloat.h" - -uint_fast64_t - softfloat_roundPackToUI64( - bool sign, - uint_fast64_t sig64, - uint_fast64_t sig0, - int_fast8_t roundingMode, - bool exact - ) -{ - bool roundNearestEven, increment; - - roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); - increment = ( UINT64_C( 0x8000000000000000 ) <= sig0 ); - if ( - ! roundNearestEven - && ( roundingMode != softfloat_round_nearest_maxMag ) - ) { - increment = - ( roundingMode != softfloat_round_minMag ) - && ( roundingMode - == ( sign ? softfloat_round_min : softfloat_round_max ) ) - && sig0; - } - if ( increment ) { - ++sig64; - if ( ! sig64 ) goto invalid; - sig64 &= - ~ ( ! ( sig0 & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) - & roundNearestEven ); - } - if ( sign && sig64 ) goto invalid; - if ( exact && sig0 ) softfloat_exceptionFlags |= softfloat_flag_inexact; - return sig64; - invalid: - softfloat_raiseFlags( softfloat_flag_invalid ); - return UINT64_C( 0xFFFFFFFFFFFFFFFF ); - -} - diff --git a/softfloat/SoftFloat-3/source/s_shift128ExtraRightJam.c b/softfloat/SoftFloat-3/source/s_shift128ExtraRightJam.c deleted file mode 100755 index 6c57974..0000000 --- a/softfloat/SoftFloat-3/source/s_shift128ExtraRightJam.c +++ /dev/null @@ -1,38 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -struct uint128_extra - softfloat_shift128ExtraRightJam( - uint64_t a64, uint64_t a0, uint64_t extra, unsigned int count ) -{ - unsigned int negCount; - struct uint128_extra z; - - negCount = - count; - if ( count < 64 ) { - z.v64 = a64>>count; - z.v0 = a64<<( negCount & 63 ) | a0>>count; - z.extra = a0<<( negCount & 63 ); - } else { - z.v64 = 0; - if ( count == 64 ) { - z.v0 = a64; - z.extra = a0; - } else { - extra |= a0; - if ( count < 128 ) { - z.v0 = a64>>( count & 63 ); - z.extra = a64<<( negCount & 63 ); - } else { - z.v0 = 0; - z.extra = ( count == 128 ) ? a64 : ( a64 != 0 ); - } - } - } - z.extra |= ( extra != 0 ); - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/s_shift128RightJam.c b/softfloat/SoftFloat-3/source/s_shift128RightJam.c deleted file mode 100755 index 5a4e188..0000000 --- a/softfloat/SoftFloat-3/source/s_shift128RightJam.c +++ /dev/null @@ -1,31 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -struct uint128 - softfloat_shift128RightJam( uint64_t a64, uint64_t a0, unsigned int count ) -{ - unsigned int negCount; - struct uint128 z; - - if ( count < 64 ) { - negCount = - count; - z.v64 = a64>>( count & 63 ); - z.v0 = - a64<<( negCount & 63 ) | a0>>count - | ( (uint64_t) ( a0<<( negCount & 63 ) ) != 0 ); - } else { - z.v64 = 0; - z.v0 = - ( count < 128 ) - ? a64>>( count & 63 ) - | ( ( ( a64 & ( ( (uint64_t) 1<<( count & 63 ) ) - 1 ) ) - | a0 ) - != 0 ) - : ( ( a64 | a0 ) != 0 ); - } - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/s_shift32RightJam.c b/softfloat/SoftFloat-3/source/s_shift32RightJam.c deleted file mode 100755 index b697a34..0000000 --- a/softfloat/SoftFloat-3/source/s_shift32RightJam.c +++ /dev/null @@ -1,15 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -uint32_t softfloat_shift32RightJam( uint32_t a, unsigned int count ) -{ - - return - ( count < 32 ) - ? a>>count | ( (uint32_t) ( a<<( ( - count ) & 31 ) ) != 0 ) - : ( a != 0 ); - -} - diff --git a/softfloat/SoftFloat-3/source/s_shift64ExtraRightJam.c b/softfloat/SoftFloat-3/source/s_shift64ExtraRightJam.c deleted file mode 100755 index 167ea54..0000000 --- a/softfloat/SoftFloat-3/source/s_shift64ExtraRightJam.c +++ /dev/null @@ -1,23 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -struct uint64_extra - softfloat_shift64ExtraRightJam( - uint64_t a, uint64_t extra, unsigned int count ) -{ - struct uint64_extra z; - - if ( count < 64 ) { - z.v = a>>count; - z.extra = a<<( ( - count ) & 63 ); - } else { - z.v = 0; - z.extra = ( count == 64 ) ? a : ( a != 0 ); - } - z.extra |= ( extra != 0 ); - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/s_shift64RightJam.c b/softfloat/SoftFloat-3/source/s_shift64RightJam.c deleted file mode 100755 index ebebb61..0000000 --- a/softfloat/SoftFloat-3/source/s_shift64RightJam.c +++ /dev/null @@ -1,15 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -uint64_t softfloat_shift64RightJam( uint64_t a, unsigned int count ) -{ - - return - ( count < 64 ) - ? a>>count | ( (uint64_t) ( a<<( ( - count ) & 63 ) ) != 0 ) - : ( a != 0 ); - -} - diff --git a/softfloat/SoftFloat-3/source/s_shortShift128ExtraRightJam.c b/softfloat/SoftFloat-3/source/s_shortShift128ExtraRightJam.c deleted file mode 100755 index c772740..0000000 --- a/softfloat/SoftFloat-3/source/s_shortShift128ExtraRightJam.c +++ /dev/null @@ -1,20 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -struct uint128_extra - softfloat_shortShift128ExtraRightJam( - uint64_t a64, uint64_t a0, uint64_t extra, unsigned int count ) -{ - unsigned int negCount; - struct uint128_extra z; - - negCount = - count; - z.v64 = a64>>count; - z.v0 = a64<<( negCount & 63 ) | a0>>count; - z.extra = a0<<( negCount & 63 ) | ( extra != 0 ); - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/s_shortShift128Left.c b/softfloat/SoftFloat-3/source/s_shortShift128Left.c deleted file mode 100755 index 9c29988..0000000 --- a/softfloat/SoftFloat-3/source/s_shortShift128Left.c +++ /dev/null @@ -1,16 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -struct uint128 - softfloat_shortShift128Left( uint64_t a64, uint64_t a0, unsigned int count ) -{ - struct uint128 z; - - z.v64 = a64<>( ( - count ) & 63 ); - z.v0 = a0< -#include "platform.h" -#include "primitives.h" - -struct uint128 - softfloat_shortShift128Right( uint64_t a64, uint64_t a0, unsigned int count ) -{ - struct uint128 z; - - z.v64 = a64>>count; - z.v0 = a64<<( ( - count ) & 63 ) | a0>>count; - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/s_shortShift192Left.c b/softfloat/SoftFloat-3/source/s_shortShift192Left.c deleted file mode 100755 index cf1e55d..0000000 --- a/softfloat/SoftFloat-3/source/s_shortShift192Left.c +++ /dev/null @@ -1,20 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -struct uint192 - softfloat_shortShift192Left( - uint64_t a128, uint64_t a64, uint64_t a0, unsigned int count ) -{ - unsigned int negCount; - struct uint192 z; - - negCount = - count; - z.v128 = a128<>( negCount & 63 ); - z.v64 = a64<>( negCount & 63 ); - z.v0 = a0< -#include "platform.h" -#include "primitives.h" - -uint32_t softfloat_shortShift32Right1Jam( uint32_t a ) -{ - - return a>>1 | ( a & 1 ); - -} - diff --git a/softfloat/SoftFloat-3/source/s_shortShift64ExtraRightJam.c b/softfloat/SoftFloat-3/source/s_shortShift64ExtraRightJam.c deleted file mode 100755 index b861c67..0000000 --- a/softfloat/SoftFloat-3/source/s_shortShift64ExtraRightJam.c +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -struct uint64_extra - softfloat_shortShift64ExtraRightJam( - uint64_t a, uint64_t extra, unsigned int count ) -{ - struct uint64_extra z; - - z.v = a>>count; - z.extra = a<<( ( - count ) & 63 ) | ( extra != 0 ); - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/s_shortShift64RightJam.c b/softfloat/SoftFloat-3/source/s_shortShift64RightJam.c deleted file mode 100755 index 0da6c93..0000000 --- a/softfloat/SoftFloat-3/source/s_shortShift64RightJam.c +++ /dev/null @@ -1,12 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -uint64_t softfloat_shortShift64RightJam( uint64_t a, unsigned int count ) -{ - - return a>>count | ( ( a & ( ( (uint64_t) 1< -#include "platform.h" -#include "primitives.h" - -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; - -} - diff --git a/softfloat/SoftFloat-3/source/s_sub192.c b/softfloat/SoftFloat-3/source/s_sub192.c deleted file mode 100755 index 96f21c9..0000000 --- a/softfloat/SoftFloat-3/source/s_sub192.c +++ /dev/null @@ -1,30 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" - -struct uint192 - softfloat_sub192( - uint64_t a128, - uint64_t a64, - uint64_t a0, - uint64_t b128, - uint64_t b64, - uint64_t b0 - ) -{ - struct uint192 z; - unsigned int borrow64, borrow128; - - z.v0 = a0 - b0; - borrow64 = ( a0 < b0 ); - z.v64 = a64 - b64; - borrow128 = ( a64 < b64 ); - z.v128 = a128 - b128; - borrow128 += ( z.v64 < borrow64 ); - z.v64 -= borrow64; - z.v128 -= borrow128; - return z; - -} - diff --git a/softfloat/SoftFloat-3/source/s_subMagsF32.c b/softfloat/SoftFloat-3/source/s_subMagsF32.c deleted file mode 100755 index 0c83b02..0000000 --- a/softfloat/SoftFloat-3/source/s_subMagsF32.c +++ /dev/null @@ -1,81 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -float32_t - softfloat_subMagsF32( uint_fast32_t uiA, uint_fast32_t uiB, bool signZ ) -{ - int_fast16_t expA; - uint_fast32_t sigA; - int_fast16_t expB; - uint_fast32_t sigB; - int_fast16_t expDiff; - uint_fast32_t uiZ; - int_fast16_t expZ; - uint_fast32_t sigZ; - union ui32_f32 uZ; - - expA = expF32UI( uiA ); - sigA = fracF32UI( uiA ); - expB = expF32UI( uiB ); - sigB = fracF32UI( uiB ); - expDiff = expA - expB; - sigA <<= 7; - sigB <<= 7; - if ( 0 < expDiff ) goto expABigger; - if ( expDiff < 0 ) goto expBBigger; - if ( expA == 0xFF ) { - if ( sigA | sigB ) goto propagateNaN; - softfloat_raiseFlags( softfloat_flag_invalid ); - uiZ = defaultNaNF32UI; - goto uiZ; - } - if ( ! expA ) { - expA = 1; - expB = 1; - } - if ( sigB < sigA ) goto aBigger; - if ( sigA < sigB ) goto bBigger; - uiZ = packToF32UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); - goto uiZ; - expBBigger: - if ( expB == 0xFF ) { - if ( sigB ) goto propagateNaN; - uiZ = packToF32UI( signZ ^ 1, 0xFF, 0 ); - goto uiZ; - } - sigA += expA ? 0x40000000 : sigA; - sigA = softfloat_shift32RightJam( sigA, - expDiff ); - sigB |= 0x40000000; - bBigger: - signZ ^= 1; - expZ = expB; - sigZ = sigB - sigA; - goto normRoundPack; - expABigger: - if ( expA == 0xFF ) { - if ( sigA ) goto propagateNaN; - uiZ = uiA; - goto uiZ; - } - sigB += expB ? 0x40000000 : sigB; - sigB = softfloat_shift32RightJam( sigB, expDiff ); - sigA |= 0x40000000; - aBigger: - expZ = expA; - sigZ = sigA - sigB; - normRoundPack: - return softfloat_normRoundPackToF32( signZ, expZ - 1, sigZ ); - propagateNaN: - uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/s_subMagsF64.c b/softfloat/SoftFloat-3/source/s_subMagsF64.c deleted file mode 100755 index 45b81ba..0000000 --- a/softfloat/SoftFloat-3/source/s_subMagsF64.c +++ /dev/null @@ -1,81 +0,0 @@ - -#include -#include -#include "platform.h" -#include "primitives.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_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; - sigA <<= 10; - sigB <<= 10; - if ( 0 < expDiff ) goto expABigger; - if ( expDiff < 0 ) goto expBBigger; - if ( expA == 0x7FF ) { - if ( sigA | sigB ) goto propagateNaN; - softfloat_raiseFlags( softfloat_flag_invalid ); - uiZ = defaultNaNF64UI; - goto uiZ; - } - if ( ! expA ) { - expA = 1; - expB = 1; - } - if ( sigB < sigA ) goto aBigger; - if ( sigA < sigB ) goto bBigger; - uiZ = packToF64UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); - goto uiZ; - expBBigger: - if ( expB == 0x7FF ) { - if ( sigB ) goto propagateNaN; - uiZ = packToF64UI( signZ ^ 1, 0x7FF, 0 ); - goto uiZ; - } - sigA += expA ? UINT64_C( 0x4000000000000000 ) : sigA; - sigA = softfloat_shift64RightJam( sigA, - expDiff ); - sigB |= UINT64_C( 0x4000000000000000 ); - bBigger: - signZ ^= 1; - expZ = expB; - sigZ = sigB - sigA; - goto normRoundPack; - expABigger: - if ( expA == 0x7FF ) { - if ( sigA ) goto propagateNaN; - uiZ = uiA; - goto uiZ; - } - sigB += expB ? UINT64_C( 0x4000000000000000 ) : sigB; - sigB = softfloat_shift64RightJam( sigB, expDiff ); - sigA |= UINT64_C( 0x4000000000000000 ); - aBigger: - expZ = expA; - sigZ = sigA - sigB; - normRoundPack: - return softfloat_normRoundPackToF64( signZ, expZ - 1, sigZ ); - propagateNaN: - uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); - uiZ: - uZ.ui = uiZ; - return uZ.f; - -} - diff --git a/softfloat/SoftFloat-3/source/softfloat.h b/softfloat/SoftFloat-3/source/softfloat.h deleted file mode 100755 index a7ea248..0000000 --- a/softfloat/SoftFloat-3/source/softfloat.h +++ /dev/null @@ -1,225 +0,0 @@ - -#ifndef softfloat_h -#define softfloat_h - -/*** UPDATE COMMENTS. ***/ - -/*============================================================================ - -This C header file is part of the SoftFloat IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -#include "softfloat_types.h" - -/*---------------------------------------------------------------------------- -| Software floating-point underflow tininess-detection mode. -*----------------------------------------------------------------------------*/ -extern int_fast8_t softfloat_detectTininess; -enum { - softfloat_tininess_beforeRounding = 0, - softfloat_tininess_afterRounding = 1 -}; - -/*---------------------------------------------------------------------------- -| Software floating-point rounding mode. -*----------------------------------------------------------------------------*/ -extern int_fast8_t softfloat_roundingMode; -enum { - softfloat_round_nearest_even = 0, - softfloat_round_minMag = 1, - softfloat_round_min = 2, - softfloat_round_max = 3, - softfloat_round_nearest_maxMag = 4 -}; - -/*---------------------------------------------------------------------------- -| Software floating-point exception flags. -*----------------------------------------------------------------------------*/ -extern int_fast8_t softfloat_exceptionFlags; -enum { - softfloat_flag_inexact = 1, - softfloat_flag_underflow = 2, - softfloat_flag_overflow = 4, - softfloat_flag_infinity = 8, - softfloat_flag_invalid = 16 -}; - -/*---------------------------------------------------------------------------- -| Routine to raise any or all of the software floating-point exception flags. -*----------------------------------------------------------------------------*/ -void softfloat_raiseFlags( int_fast8_t ); - -/*---------------------------------------------------------------------------- -| Integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -float32_t ui32_to_f32( uint_fast32_t ); -float64_t ui32_to_f64( uint_fast32_t ); -floatx80_t ui32_to_fx80( uint_fast32_t ); -float128_t ui32_to_f128( uint_fast32_t ); -float32_t ui64_to_f32( uint_fast64_t ); -float64_t ui64_to_f64( uint_fast64_t ); -floatx80_t ui64_to_fx80( uint_fast64_t ); -float128_t ui64_to_f128( uint_fast64_t ); -float32_t i32_to_f32( int_fast32_t ); -float64_t i32_to_f64( int_fast32_t ); -floatx80_t i32_to_fx80( int_fast32_t ); -float128_t i32_to_f128( int_fast32_t ); -float32_t i64_to_f32( int_fast64_t ); -float64_t i64_to_f64( int_fast64_t ); -floatx80_t i64_to_fx80( int_fast64_t ); -float128_t i64_to_f128( int_fast64_t ); - -/*---------------------------------------------------------------------------- -| 32-bit (single-precision) floating-point operations. -*----------------------------------------------------------------------------*/ -uint_fast32_t f32_to_ui32( float32_t, int_fast8_t, bool ); -uint_fast64_t f32_to_ui64( float32_t, int_fast8_t, bool ); -int_fast32_t f32_to_i32( float32_t, int_fast8_t, bool ); -int_fast64_t f32_to_i64( float32_t, int_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 ); -float64_t f32_to_f64( float32_t ); -floatx80_t f32_to_fx80( float32_t ); -float128_t f32_to_f128( float32_t ); -float32_t f32_roundToInt( float32_t, int_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, int_fast8_t, bool ); -uint_fast64_t f64_to_ui64( float64_t, int_fast8_t, bool ); -int_fast32_t f64_to_i32( float64_t, int_fast8_t, bool ); -int_fast64_t f64_to_i64( float64_t, int_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 ); -float32_t f64_to_f32( float64_t ); -floatx80_t f64_to_fx80( float64_t ); -float128_t f64_to_f128( float64_t ); -float64_t f64_roundToInt( float64_t, int_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 ); - -/*---------------------------------------------------------------------------- -| Extended double-precision rounding precision. Valid values are 32, 64, and -| 80. -*----------------------------------------------------------------------------*/ -extern int_fast8_t floatx80_roundingPrecision; - -/*---------------------------------------------------------------------------- -| Extended double-precision floating-point operations. -*----------------------------------------------------------------------------*/ -uint_fast32_t fx80_to_ui32( floatx80_t, int_fast8_t, bool ); -uint_fast64_t fx80_to_ui64( floatx80_t, int_fast8_t, bool ); -int_fast32_t fx80_to_i32( floatx80_t, int_fast8_t, bool ); -int_fast64_t fx80_to_i64( floatx80_t, int_fast8_t, bool ); -uint_fast32_t fx80_to_ui32_r_minMag( floatx80_t, bool ); -uint_fast64_t fx80_to_ui64_r_minMag( floatx80_t, bool ); -int_fast32_t fx80_to_i32_r_minMag( floatx80_t, bool ); -int_fast64_t fx80_to_i64_r_minMag( floatx80_t, bool ); -float32_t fx80_to_f32( floatx80_t ); -float64_t fx80_to_f64( floatx80_t ); -float128_t fx80_to_f128( floatx80_t ); -floatx80_t fx80_roundToInt( floatx80_t, int_fast8_t, bool ); -floatx80_t fx80_add( floatx80_t, floatx80_t ); -floatx80_t fx80_sub( floatx80_t, floatx80_t ); -floatx80_t fx80_mul( floatx80_t, floatx80_t ); -floatx80_t fx80_mulAdd( floatx80_t, floatx80_t, floatx80_t ); -floatx80_t fx80_div( floatx80_t, floatx80_t ); -floatx80_t fx80_rem( floatx80_t, floatx80_t ); -floatx80_t fx80_sqrt( floatx80_t ); -bool fx80_eq( floatx80_t, floatx80_t ); -bool fx80_le( floatx80_t, floatx80_t ); -bool fx80_lt( floatx80_t, floatx80_t ); -bool fx80_eq_signaling( floatx80_t, floatx80_t ); -bool fx80_le_quiet( floatx80_t, floatx80_t ); -bool fx80_lt_quiet( floatx80_t, floatx80_t ); -bool fx80_isSignalingNaN( floatx80_t ); - -/*---------------------------------------------------------------------------- -| 128-bit (quadruple-precision) floating-point operations. -*----------------------------------------------------------------------------*/ -uint_fast32_t f128_to_ui32( float128_t, int_fast8_t, bool ); -uint_fast64_t f128_to_ui64( float128_t, int_fast8_t, bool ); -int_fast32_t f128_to_i32( float128_t, int_fast8_t, bool ); -int_fast64_t f128_to_i64( float128_t, int_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 ); -float32_t f128_to_f32( float128_t ); -float64_t f128_to_f64( float128_t ); -floatx80_t f128_to_fx80( float128_t ); -float128_t f128_roundToInt( float128_t, int_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 - diff --git a/softfloat/SoftFloat-3/source/softfloat_state.c b/softfloat/SoftFloat-3/source/softfloat_state.c deleted file mode 100755 index 8859089..0000000 --- a/softfloat/SoftFloat-3/source/softfloat_state.c +++ /dev/null @@ -1,19 +0,0 @@ - -/*** COMMENTS. ***/ - -#include -#include "platform.h" -#include "internals.h" -#include "specialize.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Floating-point rounding mode, extended double-precision rounding precision, -| and exception flags. -*----------------------------------------------------------------------------*/ -int_fast8_t softfloat_roundingMode = softfloat_round_nearest_even; -int_fast8_t softfloat_detectTininess = init_detectTininess; -int_fast8_t softfloat_exceptionFlags = 0; - -int_fast8_t floatx80_roundingPrecision = 80; - diff --git a/softfloat/SoftFloat-3/source/ui32_to_f32.c b/softfloat/SoftFloat-3/source/ui32_to_f32.c deleted file mode 100755 index ba0fc1a..0000000 --- a/softfloat/SoftFloat-3/source/ui32_to_f32.c +++ /dev/null @@ -1,25 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -float32_t ui32_to_f32( uint_fast32_t a ) -{ - union ui32_f32 uZ; - - if ( ! a ) { - uZ.ui = 0; - return uZ.f; - } - if ( a & 0x80000000 ) { - return - softfloat_roundPackToF32( - 0, 0x9D, softfloat_shortShift32Right1Jam( a ) ); - } else { - return softfloat_normRoundPackToF32( 0, 0x9C, a ); - } - -} - diff --git a/softfloat/SoftFloat-3/source/ui32_to_f64.c b/softfloat/SoftFloat-3/source/ui32_to_f64.c deleted file mode 100755 index d0bd177..0000000 --- a/softfloat/SoftFloat-3/source/ui32_to_f64.c +++ /dev/null @@ -1,26 +0,0 @@ - -#include -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -float64_t ui32_to_f64( uint_fast32_t a ) -{ - uint_fast64_t uiZ; - int shiftCount; - union ui64_f64 uZ; - - if ( ! a ) { - uiZ = 0; - } else { - shiftCount = softfloat_countLeadingZeros32( a ) + 21; - uiZ = - packToF64UI( - 0, 0x432 - shiftCount, (uint_fast64_t) a< -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -float32_t ui64_to_f32( uint_fast64_t a ) -{ - int shiftCount; - union ui32_f32 u; - uint_fast32_t sig; - - shiftCount = softfloat_countLeadingZeros64( a ) - 40; - if ( 0 <= shiftCount ) { - u.ui = - a ? packToF32UI( - 0, 0x95 - shiftCount, (uint_fast32_t) a< -#include "platform.h" -#include "primitives.h" -#include "internals.h" -#include "softfloat.h" - -float64_t ui64_to_f64( uint_fast64_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_shortShift64RightJam( a, 1 ) ); - } else { - return softfloat_normRoundPackToF64( 0, 0x43C, a ); - } - -} - diff --git a/softfloat/f32_add.cc b/softfloat/f32_add.cc new file mode 100755 index 0000000..dc53d68 --- /dev/null +++ b/softfloat/f32_add.cc @@ -0,0 +1,29 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float32_t f32_add( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool signA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signB; + float32_t ( *magsRoutine )( uint_fast32_t, uint_fast32_t, bool ); + + uA.f = a; + uiA = uA.ui; + signA = signF32UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF32UI( uiB ); + magsRoutine = + ( signA == signB ) ? softfloat_addMagsF32 : softfloat_subMagsF32; + return magsRoutine( uiA, uiB, signA ); + +} + diff --git a/softfloat/f32_div.cc b/softfloat/f32_div.cc new file mode 100755 index 0000000..958b140 --- /dev/null +++ b/softfloat/f32_div.cc @@ -0,0 +1,96 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t f32_div( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool signA; + int_fast16_t expA; + uint_fast32_t sigA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signB; + int_fast16_t expB; + uint_fast32_t sigB; + bool signZ; + struct exp16_sig32 normExpSig; + int_fast16_t expZ; + uint_fast32_t sigZ; + uint_fast32_t uiZ; + union ui32_f32 uZ; + + uA.f = a; + uiA = uA.ui; + signA = signF32UI( uiA ); + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF32UI( uiB ); + expB = expF32UI( uiB ); + sigB = fracF32UI( uiB ); + signZ = signA ^ signB; + if ( expA == 0xFF ) { + if ( sigA ) goto propagateNaN; + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN; + goto invalid; + } + goto infinity; + } + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN; + goto zero; + } + if ( ! expB ) { + if ( ! sigB ) { + if ( ! ( expA | sigA ) ) goto invalid; + softfloat_raiseFlags( softfloat_flag_infinity ); + goto infinity; + } + normExpSig = softfloat_normSubnormalF32Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if ( ! expA ) { + if ( ! sigA ) goto zero; + normExpSig = softfloat_normSubnormalF32Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + expZ = expA - expB + 0x7D; + sigA = ( sigA | 0x00800000 )<<7; + sigB = ( sigB | 0x00800000 )<<8; + if ( sigB <= ( sigA + sigA ) ) { + ++expZ; + sigA >>= 1; + } + sigZ = ( (uint_fast64_t) sigA<<32 ) / sigB; + if ( ! ( sigZ & 0x3F ) ) { + sigZ |= ( (uint_fast64_t) sigB * sigZ != (uint_fast64_t) sigA<<32 ); + } + return softfloat_roundPackToF32( signZ, expZ, sigZ ); + propagateNaN: + uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); + goto uiZ; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF32UI; + goto uiZ; + infinity: + uiZ = packToF32UI( signZ, 0xFF, 0 ); + goto uiZ; + zero: + uiZ = packToF32UI( signZ, 0, 0 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/f32_eq.cc b/softfloat/f32_eq.cc new file mode 100755 index 0000000..8f2306b --- /dev/null +++ b/softfloat/f32_eq.cc @@ -0,0 +1,34 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f32_eq( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( + ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) + || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) + ) { + if ( + softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + return ( uiA == uiB ) || ! (uint32_t) ( ( uiA | uiB )<<1 ); + +} + diff --git a/softfloat/f32_eq_signaling.cc b/softfloat/f32_eq_signaling.cc new file mode 100755 index 0000000..bfba48a --- /dev/null +++ b/softfloat/f32_eq_signaling.cc @@ -0,0 +1,29 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f32_eq_signaling( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( + ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) + || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + return ( uiA == uiB ) || ! (uint32_t) ( ( uiA | uiB )<<1 ); + +} + diff --git a/softfloat/f32_isSignalingNaN.cc b/softfloat/f32_isSignalingNaN.cc new file mode 100755 index 0000000..09aaa82 --- /dev/null +++ b/softfloat/f32_isSignalingNaN.cc @@ -0,0 +1,16 @@ + +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f32_isSignalingNaN( float32_t a ) +{ + union ui32_f32 uA; + + uA.f = a; + return softfloat_isSigNaNF32UI( uA.ui ); + +} + diff --git a/softfloat/f32_le.cc b/softfloat/f32_le.cc new file mode 100755 index 0000000..5f47be5 --- /dev/null +++ b/softfloat/f32_le.cc @@ -0,0 +1,34 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f32_le( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( + ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) + || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + signA = signF32UI( uiA ); + signB = signF32UI( uiB ); + return + ( signA != signB ) ? signA || ! (uint32_t) ( ( uiA | uiB )<<1 ) + : ( uiA == uiB ) || ( signA ^ ( uiA < uiB ) ); + +} + diff --git a/softfloat/f32_le_quiet.cc b/softfloat/f32_le_quiet.cc new file mode 100755 index 0000000..2b541da --- /dev/null +++ b/softfloat/f32_le_quiet.cc @@ -0,0 +1,39 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f32_le_quiet( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( + ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) + || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) + ) { + if ( + softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + signA = signF32UI( uiA ); + signB = signF32UI( uiB ); + return + ( signA != signB ) ? signA || ! (uint32_t) ( ( uiA | uiB )<<1 ) + : ( uiA == uiB ) || ( signA ^ ( uiA < uiB ) ); + +} + diff --git a/softfloat/f32_lt.cc b/softfloat/f32_lt.cc new file mode 100755 index 0000000..753b28a --- /dev/null +++ b/softfloat/f32_lt.cc @@ -0,0 +1,34 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f32_lt( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( + ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) + || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + signA = signF32UI( uiA ); + signB = signF32UI( uiB ); + return + ( signA != signB ) ? signA && ( (uint32_t) ( ( uiA | uiB )<<1 ) != 0 ) + : ( uiA != uiB ) && ( signA ^ ( uiA < uiB ) ); + +} + diff --git a/softfloat/f32_lt_quiet.cc b/softfloat/f32_lt_quiet.cc new file mode 100755 index 0000000..ecd90bf --- /dev/null +++ b/softfloat/f32_lt_quiet.cc @@ -0,0 +1,39 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f32_lt_quiet( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( + ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) + || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) + ) { + if ( + softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + signA = signF32UI( uiA ); + signB = signF32UI( uiB ); + return + ( signA != signB ) ? signA && ( (uint32_t) ( ( uiA | uiB )<<1 ) != 0 ) + : ( uiA != uiB ) && ( signA ^ ( uiA < uiB ) ); + +} + diff --git a/softfloat/f32_mul.cc b/softfloat/f32_mul.cc new file mode 100755 index 0000000..d49c1dd --- /dev/null +++ b/softfloat/f32_mul.cc @@ -0,0 +1,89 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t f32_mul( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool signA; + int_fast16_t expA; + uint_fast32_t sigA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signB; + int_fast16_t expB; + uint_fast32_t sigB; + bool signZ; + uint_fast32_t magBits; + struct exp16_sig32 normExpSig; + int_fast16_t expZ; + uint_fast32_t sigZ, uiZ; + union ui32_f32 uZ; + + uA.f = a; + uiA = uA.ui; + signA = signF32UI( uiA ); + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF32UI( uiB ); + expB = expF32UI( uiB ); + sigB = fracF32UI( uiB ); + signZ = signA ^ signB; + if ( expA == 0xFF ) { + if ( sigA || ( ( expB == 0xFF ) && sigB ) ) goto propagateNaN; + magBits = expB | sigB; + goto infArg; + } + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN; + magBits = expA | sigA; + goto infArg; + } + if ( ! expA ) { + if ( ! sigA ) goto zero; + normExpSig = softfloat_normSubnormalF32Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) { + if ( ! sigB ) goto zero; + normExpSig = softfloat_normSubnormalF32Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + expZ = expA + expB - 0x7F; + sigA = ( sigA | 0x00800000 )<<7; + sigB = ( sigB | 0x00800000 )<<8; + sigZ = softfloat_shortShift64RightJam( (uint_fast64_t) sigA * sigB, 32 ); + if ( sigZ < 0x40000000 ) { + --expZ; + sigZ <<= 1; + } + return softfloat_roundPackToF32( signZ, expZ, sigZ ); + propagateNaN: + uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); + goto uiZ; + infArg: + if ( ! magBits ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF32UI; + } else { + uiZ = packToF32UI( signZ, 0xFF, 0 ); + } + goto uiZ; + zero: + uiZ = packToF32UI( signZ, 0, 0 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/f32_mulAdd.cc b/softfloat/f32_mulAdd.cc new file mode 100755 index 0000000..3d4cee9 --- /dev/null +++ b/softfloat/f32_mulAdd.cc @@ -0,0 +1,25 @@ + +#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( 0, uiA, uiB, uiC ); + +} + diff --git a/softfloat/f32_rem.cc b/softfloat/f32_rem.cc new file mode 100755 index 0000000..d29b840 --- /dev/null +++ b/softfloat/f32_rem.cc @@ -0,0 +1,124 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t f32_rem( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool signA; + int_fast16_t expA; + uint_fast32_t sigA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signB; + int_fast16_t expB; + uint_fast32_t sigB; + struct exp16_sig32 normExpSig; + int_fast16_t expDiff; + uint_fast32_t q; + uint_fast64_t sigA64, sigB64, q64; + uint_fast32_t alternateSigA; + uint32_t sigMean; + bool signZ; + uint_fast32_t uiZ; + union ui32_f32 uZ; + + uA.f = a; + uiA = uA.ui; + signA = signF32UI( uiA ); + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF32UI( uiB ); + expB = expF32UI( uiB ); + sigB = fracF32UI( uiB ); + if ( expA == 0xFF ) { + if ( sigA || ( ( expB == 0xFF ) && sigB ) ) goto propagateNaN; + goto invalid; + } + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN; + return a; + } + if ( ! expB ) { + if ( ! sigB ) goto invalid; + normExpSig = softfloat_normSubnormalF32Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if ( ! expA ) { + if ( ! sigA ) return a; + normExpSig = softfloat_normSubnormalF32Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + expDiff = expA - expB; + sigA |= 0x00800000; + sigB |= 0x00800000; + if ( expDiff < 32 ) { + sigA <<= 8; + sigB <<= 8; + if ( expDiff < 0 ) { + if ( expDiff < -1 ) return a; + sigA >>= 1; + } + q = ( sigB <= sigA ); + if ( q ) sigA -= sigB; + if ( 0 < expDiff ) { + q = ( (uint_fast64_t) sigA<<32 ) / sigB; + q >>= 32 - expDiff; + sigB >>= 2; + sigA = ( ( sigA>>1 )<<( expDiff - 1 ) ) - sigB * q; + } else { + sigA >>= 2; + sigB >>= 2; + } + } else { + if ( sigB <= sigA ) sigA -= sigB; + sigA64 = (uint_fast64_t) sigA<<40; + sigB64 = (uint_fast64_t) sigB<<40; + expDiff -= 64; + while ( 0 < expDiff ) { + q64 = softfloat_estimateDiv128To64( sigA64, 0, sigB64 ); + q64 = ( 2 < q64 ) ? q64 - 2 : 0; + sigA64 = - ( ( sigB * q64 )<<38 ); + expDiff -= 62; + } + expDiff += 64; + q64 = softfloat_estimateDiv128To64( sigA64, 0, sigB64 ); + q64 = ( 2 < q64 ) ? q64 - 2 : 0; + q = q64>>( 64 - expDiff ); + sigB <<= 6; + sigA = ( ( sigA64>>33 )<<( expDiff - 1 ) ) - sigB * q; + } + do { + alternateSigA = sigA; + ++q; + sigA -= sigB; + } while ( sigA < 0x80000000 ); + sigMean = sigA + alternateSigA; + if ( ( 0x80000000 <= sigMean ) || ( ! sigMean && ( q & 1 ) ) ) { + sigA = alternateSigA; + } + signZ = ( 0x80000000 <= sigA ); + if ( signZ ) sigA = - sigA; + return softfloat_normRoundPackToF32( signA ^ signZ, expB, sigA ); + propagateNaN: + uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); + goto uiZ; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF32UI; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/f32_roundToInt.cc b/softfloat/f32_roundToInt.cc new file mode 100755 index 0000000..f8f9114 --- /dev/null +++ b/softfloat/f32_roundToInt.cc @@ -0,0 +1,78 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t f32_roundToInt( float32_t a, int_fast8_t roundingMode, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + int_fast16_t expA; + uint_fast32_t uiZ; + bool signA; + uint_fast32_t lastBitMask, roundBitsMask; + union ui32_f32 uZ; + + uA.f = a; + uiA = uA.ui; + expA = expF32UI( uiA ); + if ( 0x96 <= expA ) { + if ( ( expA == 0xFF ) && fracF32UI( uiA ) ) { + uiZ = softfloat_propagateNaNF32UI( uiA, 0 ); + goto uiZ; + } + return a; + } + if ( expA <= 0x7E ) { + if ( ! (uint32_t) ( uiA<<1 ) ) return a; + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + signA = signF32UI( uiA ); + switch ( roundingMode ) { + case softfloat_round_nearest_even: + if ( ( expA == 0x7E ) && fracF32UI( uiA ) ) { + uiZ = packToF32UI( signA, 0x7F, 0 ); + goto uiZ; + } + break; + case softfloat_round_min: + uiZ = signA ? 0xBF800000 : 0; + goto uiZ; + case softfloat_round_max: + uiZ = signA ? 0x80000000 : 0x3F800000; + goto uiZ; + case softfloat_round_nearest_maxMag: + if ( expA == 0x7E ) { + uiZ = packToF32UI( signA, 0x7F, 0 ); + goto uiZ; + } + break; + } + uiZ = packToF32UI( signA, 0, 0 ); + goto uiZ; + } + lastBitMask = (uint_fast32_t) 1<<( 0x96 - expA ); + roundBitsMask = lastBitMask - 1; + uiZ = uiA; + if ( roundingMode == softfloat_round_nearest_maxMag ) { + uiZ += lastBitMask>>1; + } else if ( roundingMode == softfloat_round_nearest_even ) { + uiZ += lastBitMask>>1; + if ( ! ( uiZ & roundBitsMask ) ) uiZ &= ~ lastBitMask; + } else if ( roundingMode != softfloat_round_minMag ) { + if ( signF32UI( uiZ ) ^ ( roundingMode == softfloat_round_max ) ) { + uiZ += roundBitsMask; + } + } + uiZ &= ~ roundBitsMask; + if ( exact && ( uiZ != uiA ) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/f32_sqrt.cc b/softfloat/f32_sqrt.cc new file mode 100755 index 0000000..c9eb907 --- /dev/null +++ b/softfloat/f32_sqrt.cc @@ -0,0 +1,74 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t f32_sqrt( float32_t a ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool signA; + int_fast16_t expA; + uint_fast32_t sigA, uiZ; + struct exp16_sig32 normExpSig; + int_fast16_t expZ; + uint_fast32_t sigZ; + uint_fast64_t term, rem; + union ui32_f32 uZ; + + uA.f = a; + uiA = uA.ui; + signA = signF32UI( uiA ); + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + if ( expA == 0xFF ) { + if ( sigA ) { + uiZ = softfloat_propagateNaNF32UI( 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_normSubnormalF32Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + expZ = ( ( expA - 0x7F )>>1 ) + 0x7E; + sigA = ( sigA | 0x00800000 )<<8; + sigZ = softfloat_estimateSqrt32( expA, sigA ) + 2; + if ( ( sigZ & 0x7F ) <= 5 ) { + if ( sigZ < 2 ) { + sigZ = 0x7FFFFFFF; + goto roundPack; + } + sigA >>= expA & 1; + term = (uint_fast64_t) sigZ * sigZ; + rem = ( (uint_fast64_t) sigA<<32 ) - term; + while ( UINT64_C( 0x8000000000000000 ) <= rem ) { + --sigZ; + rem += ( (uint_fast64_t) sigZ<<1 ) | 1; + } + sigZ |= ( rem != 0 ); + } + sigZ = softfloat_shortShift32Right1Jam( sigZ ); + roundPack: + return softfloat_roundPackToF32( 0, expZ, sigZ ); + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF32UI; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/f32_sub.cc b/softfloat/f32_sub.cc new file mode 100755 index 0000000..c64df8e --- /dev/null +++ b/softfloat/f32_sub.cc @@ -0,0 +1,29 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float32_t f32_sub( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool signA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signB; + float32_t ( *magsRoutine )( uint_fast32_t, uint_fast32_t, bool ); + + uA.f = a; + uiA = uA.ui; + signA = signF32UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF32UI( uiB ); + magsRoutine = + ( signA == signB ) ? softfloat_subMagsF32 : softfloat_addMagsF32; + return magsRoutine( uiA, uiB ^ 0x80000000, signA ); + +} + diff --git a/softfloat/f32_to_f64.cc b/softfloat/f32_to_f64.cc new file mode 100755 index 0000000..9f0ae5c --- /dev/null +++ b/softfloat/f32_to_f64.cc @@ -0,0 +1,47 @@ + +#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 sig; + uint_fast64_t uiZ; + struct exp16_sig32 normExpSig; + union ui64_f64 uZ; + + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + if ( exp == 0xFF ) { + uiZ = + sig ? softfloat_commonNaNToF64UI( + softfloat_f32UIToCommonNaN( uiA ) ) + : packToF64UI( sign, 0x7FF, 0 ); + goto uiZ; + } + if ( ! exp ) { + if ( ! sig ) { + uiZ = packToF64UI( sign, 0, 0 ); + goto uiZ; + } + normExpSig = softfloat_normSubnormalF32Sig( sig ); + exp = normExpSig.exp - 1; + sig = normExpSig.sig; + } + uiZ = packToF64UI( sign, exp + 0x380, (uint_fast64_t) sig<<29 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/f32_to_i32.cc b/softfloat/f32_to_i32.cc new file mode 100755 index 0000000..bbbaee0 --- /dev/null +++ b/softfloat/f32_to_i32.cc @@ -0,0 +1,34 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +int_fast32_t f32_to_i32( float32_t a, int_fast8_t roundingMode, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool sign; + int_fast16_t exp; + uint_fast32_t sig; + uint_fast64_t sig64; + int_fast16_t shiftCount; + + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + if ( ( exp == 0xFF ) && sig ) sign = 0; + if ( exp ) sig |= 0x00800000; + sig64 = (uint_fast64_t) sig<<32; + shiftCount = 0xAF - exp; + if ( 0 < shiftCount ) { + sig64 = softfloat_shift64RightJam( sig64, shiftCount ); + } + return softfloat_roundPackToI32( sign, sig64, roundingMode, exact ); + +} + diff --git a/softfloat/f32_to_i32_r_minMag.cc b/softfloat/f32_to_i32_r_minMag.cc new file mode 100755 index 0000000..63ff1e2 --- /dev/null +++ b/softfloat/f32_to_i32_r_minMag.cc @@ -0,0 +1,45 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast32_t f32_to_i32_r_minMag( float32_t a, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + int_fast16_t exp; + uint_fast32_t sig; + bool sign; + int_fast16_t shiftCount; + int_fast32_t absZ; + + uA.f = a; + uiA = uA.ui; + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + if ( exp < 0x7F ) { + if ( exact && ( exp | sig ) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + sign = signF32UI( uiA ); + shiftCount = 0x9E - exp; + if ( shiftCount <= 0 ) { + if ( uiA != packToF32UI( 1, 0x9E, 0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( ! sign || ( ( exp == 0xFF ) && sig ) ) return 0x7FFFFFFF; + } + return -0x7FFFFFFF - 1; + } + sig = ( sig | 0x00800000 )<<8; + absZ = sig>>shiftCount; + if ( exact && (uint32_t) ( sig<<( ( - shiftCount ) & 31 ) ) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return sign ? - absZ : absZ; + +} + diff --git a/softfloat/f32_to_i64.cc b/softfloat/f32_to_i64.cc new file mode 100755 index 0000000..c0b8981 --- /dev/null +++ b/softfloat/f32_to_i64.cc @@ -0,0 +1,44 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t f32_to_i64( float32_t a, int_fast8_t roundingMode, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool sign; + int_fast16_t exp; + uint_fast32_t sig; + int_fast16_t shiftCount; + uint_fast64_t sig64, extra; + struct uint64_extra sig64Extra; + + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + shiftCount = 0xBE - exp; + if ( shiftCount < 0 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( ! sign || ( ( exp == 0xFF ) && sig ) ) { + return INT64_C( 0x7FFFFFFFFFFFFFFF ); + } + return - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + if ( exp ) sig |= 0x00800000; + sig64 = (uint_fast64_t) sig<<40; + extra = 0; + if ( shiftCount ) { + sig64Extra = softfloat_shift64ExtraRightJam( sig64, 0, shiftCount ); + sig64 = sig64Extra.v; + extra = sig64Extra.extra; + } + return softfloat_roundPackToI64( sign, sig64, extra, roundingMode, exact ); + +} + diff --git a/softfloat/f32_to_i64_r_minMag.cc b/softfloat/f32_to_i64_r_minMag.cc new file mode 100755 index 0000000..33bff93 --- /dev/null +++ b/softfloat/f32_to_i64_r_minMag.cc @@ -0,0 +1,52 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t f32_to_i64_r_minMag( float32_t a, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + int_fast16_t exp; + uint_fast32_t sig; + bool sign; + int_fast16_t shiftCount; + uint_fast64_t sig64; + int_fast64_t absZ; + + uA.f = a; + uiA = uA.ui; + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + if ( exp < 0x7F ) { + if ( exact && ( exp | sig ) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + sign = signF32UI( uiA ); + shiftCount = 0xBE - exp; + if ( shiftCount <= 0 ) { + if ( uiA != packToF32UI( 1, 0xBE, 0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( ! sign || ( ( exp == 0xFF ) && sig ) ) { + return INT64_C( 0x7FFFFFFFFFFFFFFF ); + } + } + return - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + sig |= 0x00800000; + sig64 = (uint_fast64_t) sig<<40; + absZ = sig64>>shiftCount; + shiftCount = 40 - shiftCount; + if ( + exact && ( shiftCount < 0 ) && (uint32_t) ( sig<<( shiftCount & 31 ) ) + ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return sign ? - absZ : absZ; + +} + diff --git a/softfloat/f32_to_ui32.cc b/softfloat/f32_to_ui32.cc new file mode 100755 index 0000000..3501db8 --- /dev/null +++ b/softfloat/f32_to_ui32.cc @@ -0,0 +1,33 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast32_t f32_to_ui32( float32_t a, int_fast8_t roundingMode, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool sign; + int_fast16_t exp; + uint_fast32_t sig; + uint_fast64_t sig64; + int_fast16_t shiftCount; + + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + if ( exp ) sig |= 0x00800000; + sig64 = (uint_fast64_t) sig<<32; + shiftCount = 0xAF - exp; + if ( 0 < shiftCount ) { + sig64 = softfloat_shift64RightJam( sig64, shiftCount ); + } + return softfloat_roundPackToUI32( sign, sig64, roundingMode, exact ); + +} + diff --git a/softfloat/f32_to_ui32_r_minMag.cc b/softfloat/f32_to_ui32_r_minMag.cc new file mode 100755 index 0000000..edd858d --- /dev/null +++ b/softfloat/f32_to_ui32_r_minMag.cc @@ -0,0 +1,41 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast32_t f32_to_ui32_r_minMag( float32_t a, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + int_fast16_t exp; + uint_fast32_t sig; + int_fast16_t shiftCount; + uint_fast32_t z; + + uA.f = a; + uiA = uA.ui; + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + if ( exp < 0x7F ) { + if ( exact && ( exp | sig ) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + if ( signF32UI( uiA ) ) goto invalid; + shiftCount = 0x9E - exp; + if ( shiftCount < 0 ) goto invalid; + sig = ( sig | 0x00800000 )<<8; + z = sig>>shiftCount; + if ( exact && ( sig & ( ( (uint_fast32_t) 1< +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast64_t f32_to_ui64( float32_t a, int_fast8_t roundingMode, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool sign; + int_fast16_t exp; + uint_fast32_t sig; + int_fast16_t shiftCount; + uint_fast64_t sig64, extra; + struct uint64_extra sig64Extra; + + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + shiftCount = 0xBE - exp; + if ( shiftCount < 0 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + } + if ( exp ) sig |= 0x00800000; + sig64 = (uint_fast64_t) sig<<40; + extra = 0; + if ( shiftCount ) { + sig64Extra = softfloat_shift64ExtraRightJam( sig64, 0, shiftCount ); + sig64 = sig64Extra.v; + extra = sig64Extra.extra; + } + return + softfloat_roundPackToUI64( sign, sig64, extra, roundingMode, exact ); + +} + diff --git a/softfloat/f32_to_ui64_r_minMag.cc b/softfloat/f32_to_ui64_r_minMag.cc new file mode 100755 index 0000000..738d6b1 --- /dev/null +++ b/softfloat/f32_to_ui64_r_minMag.cc @@ -0,0 +1,45 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast64_t f32_to_ui64_r_minMag( float32_t a, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + int_fast16_t exp; + uint_fast32_t sig; + int_fast16_t shiftCount; + uint_fast64_t sig64, z; + + uA.f = a; + uiA = uA.ui; + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + if ( exp < 0x7F ) { + if ( exact && ( exp | sig ) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + if ( signF32UI( uiA ) ) goto invalid; + shiftCount = 0xBE - exp; + if ( shiftCount < 0 ) goto invalid; + sig |= 0x00800000; + sig64 = (uint_fast64_t) sig<<40; + z = sig64>>shiftCount; + shiftCount = 40 - shiftCount; + if ( + exact && ( shiftCount < 0 ) && (uint32_t) ( sig<<( shiftCount & 31 ) ) + ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return z; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + +} + diff --git a/softfloat/f64_add.cc b/softfloat/f64_add.cc new file mode 100755 index 0000000..9ec4b5f --- /dev/null +++ b/softfloat/f64_add.cc @@ -0,0 +1,29 @@ + +#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; + float64_t ( *magsRoutine )( uint_fast64_t, uint_fast64_t, bool ); + + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF64UI( uiB ); + magsRoutine = + ( signA == signB ) ? softfloat_addMagsF64 : softfloat_subMagsF64; + return magsRoutine( uiA, uiB, signA ); + +} + diff --git a/softfloat/f64_div.cc b/softfloat/f64_div.cc new file mode 100755 index 0000000..9bc72b3 --- /dev/null +++ b/softfloat/f64_div.cc @@ -0,0 +1,104 @@ + +#include +#include +#include "platform.h" +#include "primitives.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; + uint_fast64_t sigZ; + struct uint128 term, rem; + 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_infinity ); + 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 + 0x3FD; + sigA = ( sigA | UINT64_C( 0x0010000000000000 ) )<<10; + sigB = ( sigB | UINT64_C( 0x0010000000000000 ) )<<11; + if ( sigB <= ( sigA + sigA ) ) { + ++expZ; + sigA >>= 1; + } + sigZ = softfloat_estimateDiv128To64( sigA, 0, sigB ); + if ( ( sigZ & 0x1FF ) <= 2 ) { + term = softfloat_mul64To128( sigB, sigZ ); + rem = softfloat_sub128( sigA, 0, term.v64, term.v0 ); + while ( UINT64_C( 0x8000000000000000 ) <= rem.v64 ) { + --sigZ; + rem = softfloat_add128( rem.v64, rem.v0, 0, sigB ); + } + sigZ |= ( rem.v0 != 0 ); + } + 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/softfloat/f64_eq.cc b/softfloat/f64_eq.cc new file mode 100755 index 0000000..925aabc --- /dev/null +++ b/softfloat/f64_eq.cc @@ -0,0 +1,35 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f64_eq( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( + ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) + || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) + ) { + if ( + softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + return + ( uiA == uiB ) || ! ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ); + +} + diff --git a/softfloat/f64_eq_signaling.cc b/softfloat/f64_eq_signaling.cc new file mode 100755 index 0000000..7a54dc1 --- /dev/null +++ b/softfloat/f64_eq_signaling.cc @@ -0,0 +1,30 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f64_eq_signaling( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( + ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) + || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + return + ( uiA == uiB ) || ! ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ); + +} + diff --git a/softfloat/f64_isSignalingNaN.cc b/softfloat/f64_isSignalingNaN.cc new file mode 100755 index 0000000..d720ac1 --- /dev/null +++ b/softfloat/f64_isSignalingNaN.cc @@ -0,0 +1,16 @@ + +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f64_isSignalingNaN( float64_t a ) +{ + union ui64_f64 uA; + + uA.f = a; + return softfloat_isSigNaNF64UI( uA.ui ); + +} + diff --git a/softfloat/f64_le.cc b/softfloat/f64_le.cc new file mode 100755 index 0000000..e6c5caf --- /dev/null +++ b/softfloat/f64_le.cc @@ -0,0 +1,35 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f64_le( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( + ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) + || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + signA = signF64UI( uiA ); + signB = signF64UI( uiB ); + return + ( signA != signB ) + ? signA || ! ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) + : ( uiA == uiB ) || ( signA ^ ( uiA < uiB ) ); + +} + diff --git a/softfloat/f64_le_quiet.cc b/softfloat/f64_le_quiet.cc new file mode 100755 index 0000000..e9b7ede --- /dev/null +++ b/softfloat/f64_le_quiet.cc @@ -0,0 +1,40 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f64_le_quiet( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( + ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) + || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) + ) { + if ( + softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + signA = signF64UI( uiA ); + signB = signF64UI( uiB ); + return + ( signA != signB ) + ? signA || ! ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) + : ( uiA == uiB ) || ( signA ^ ( uiA < uiB ) ); + +} + diff --git a/softfloat/f64_lt.cc b/softfloat/f64_lt.cc new file mode 100755 index 0000000..1b2f696 --- /dev/null +++ b/softfloat/f64_lt.cc @@ -0,0 +1,35 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f64_lt( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( + ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) + || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + signA = signF64UI( uiA ); + signB = signF64UI( uiB ); + return + ( signA != signB ) + ? signA && ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) + : ( uiA != uiB ) && ( signA ^ ( uiA < uiB ) ); + +} + diff --git a/softfloat/f64_lt_quiet.cc b/softfloat/f64_lt_quiet.cc new file mode 100755 index 0000000..f27e6da --- /dev/null +++ b/softfloat/f64_lt_quiet.cc @@ -0,0 +1,40 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f64_lt_quiet( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( + ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) + || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) + ) { + if ( + softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + signA = signF64UI( uiA ); + signB = signF64UI( uiB ); + return + ( signA != signB ) + ? signA && ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) + : ( uiA != uiB ) && ( signA ^ ( uiA < uiB ) ); + +} + diff --git a/softfloat/f64_mul.cc b/softfloat/f64_mul.cc new file mode 100755 index 0000000..4b5dc4e --- /dev/null +++ b/softfloat/f64_mul.cc @@ -0,0 +1,91 @@ + +#include +#include +#include "platform.h" +#include "primitives.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; + struct uint128 sigZ128; + 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; + sigZ128 = softfloat_mul64To128( sigA, sigB ); + sigZ = sigZ128.v64 | ( sigZ128.v0 != 0 ); + 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/softfloat/f64_mulAdd.cc b/softfloat/f64_mulAdd.cc new file mode 100755 index 0000000..fa1669a --- /dev/null +++ b/softfloat/f64_mulAdd.cc @@ -0,0 +1,25 @@ + +#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( 0, uiA, uiB, uiC ); + +} + diff --git a/softfloat/f64_rem.cc b/softfloat/f64_rem.cc new file mode 100755 index 0000000..08fcd78 --- /dev/null +++ b/softfloat/f64_rem.cc @@ -0,0 +1,113 @@ + +#include +#include +#include "platform.h" +#include "primitives.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; + bool signB; + int_fast16_t expB; + uint_fast64_t sigB; + struct exp16_sig64 normExpSig; + int_fast16_t expDiff; + uint_fast64_t q, alternateSigA; + uint64_t sigMean; + bool signZ; + 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 ); + if ( expA == 0x7FF ) { + if ( sigA || ( ( expB == 0x7FF ) && sigB ) ) goto propagateNaN; + goto invalid; + } + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + 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; + } + expDiff = expA - expB; + sigA = ( sigA | UINT64_C( 0x0010000000000000 ) )<<11; + sigB = ( sigB | UINT64_C( 0x0010000000000000 ) )<<11; + if ( expDiff < 0 ) { + if ( expDiff < -1 ) return a; + sigA >>= 1; + } + q = ( sigB <= sigA ); + if ( q ) sigA -= sigB; + expDiff -= 64; + while ( 0 < expDiff ) { + q = softfloat_estimateDiv128To64( sigA, 0, sigB ); + q = ( 2 < q ) ? q - 2 : 0; + sigA = - ( ( sigB>>2 ) * q ); + expDiff -= 62; + } + expDiff += 64; + if ( 0 < expDiff ) { + q = softfloat_estimateDiv128To64( sigA, 0, sigB ); + q = ( 2 < q ) ? q - 2 : 0; + q >>= 64 - expDiff; + sigB >>= 2; + sigA = ( ( sigA>>1 )<<( expDiff - 1 ) ) - sigB * q; + } else { + sigA >>= 2; + sigB >>= 2; + } + do { + alternateSigA = sigA; + ++q; + sigA -= sigB; + } while ( sigA < UINT64_C( 0x8000000000000000 ) ); + sigMean = sigA + alternateSigA; + if ( + ( UINT64_C( 0x8000000000000000 ) <= sigMean ) + || ( ! sigMean && ( q & 1 ) ) + ) { + sigA = alternateSigA; + } + signZ = ( UINT64_C( 0x8000000000000000 ) <= sigA ); + if ( signZ ) sigA = - sigA; + return softfloat_normRoundPackToF64( signA ^ signZ, expB, sigA ); + 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/softfloat/f64_roundToInt.cc b/softfloat/f64_roundToInt.cc new file mode 100755 index 0000000..ef16dfa --- /dev/null +++ b/softfloat/f64_roundToInt.cc @@ -0,0 +1,80 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f64_roundToInt( float64_t a, int_fast8_t roundingMode, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + int_fast16_t expA; + uint_fast64_t uiZ; + bool signA; + uint_fast64_t lastBitMask, roundBitsMask; + union ui64_f64 uZ; + + uA.f = a; + uiA = uA.ui; + expA = expF64UI( uiA ); + if ( 0x433 <= expA ) { + if ( ( expA == 0x7FF ) && fracF64UI( uiA ) ) { + uiZ = softfloat_propagateNaNF64UI( uiA, 0 ); + goto uiZ; + } + return a; + } + if ( expA <= 0x3FE ) { + if ( ! ( uiA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) ) return a; + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + signA = signF64UI( uiA ); + switch ( roundingMode ) { + case softfloat_round_nearest_even: + if ( ( expA == 0x3FE ) && fracF64UI( uiA ) ) { + uiZ = packToF64UI( signA, 0x3FF, 0 ); + goto uiZ; + } + break; + case softfloat_round_min: + uiZ = signA ? UINT64_C( 0xBFF0000000000000 ) : 0; + goto uiZ; + case softfloat_round_max: + uiZ = + signA ? UINT64_C( 0x8000000000000000 ) + : UINT64_C( 0x3FF0000000000000 ); + goto uiZ; + case softfloat_round_nearest_maxMag: + if ( expA == 0x3FE ) { + uiZ = packToF64UI( signA, 0x3FF, 0 ); + goto uiZ; + } + break; + } + uiZ = packToF64UI( signA, 0, 0 ); + goto uiZ; + } + lastBitMask = (uint_fast64_t) 1<<( 0x433 - expA ); + roundBitsMask = lastBitMask - 1; + uiZ = uiA; + if ( roundingMode == softfloat_round_nearest_maxMag ) { + uiZ += lastBitMask>>1; + } else if ( roundingMode == softfloat_round_nearest_even ) { + uiZ += lastBitMask>>1; + if ( ! ( uiZ & roundBitsMask ) ) uiZ &= ~ lastBitMask; + } else if ( roundingMode != softfloat_round_minMag ) { + if ( signF64UI( uiZ ) ^ ( roundingMode == softfloat_round_max ) ) { + uiZ += roundBitsMask; + } + } + uiZ &= ~ roundBitsMask; + if ( exact && ( uiZ != uiA ) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/f64_sqrt.cc b/softfloat/f64_sqrt.cc new file mode 100755 index 0000000..cd91010 --- /dev/null +++ b/softfloat/f64_sqrt.cc @@ -0,0 +1,74 @@ + +#include +#include +#include "platform.h" +#include "primitives.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; + uint_fast32_t sigZ32; + uint_fast64_t sigZ; + struct uint128 term, rem; + 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; + } + expZ = ( ( expA - 0x3FF )>>1 ) + 0x3FE; + sigA |= UINT64_C( 0x0010000000000000 ); + sigZ32 = softfloat_estimateSqrt32( expA, sigA>>21 ); + sigA <<= 9 - ( expA & 1 ); + sigZ = + softfloat_estimateDiv128To64( sigA, 0, (uint_fast64_t) sigZ32<<32 ) + + ( (uint_fast64_t) sigZ32<<30 ); + if ( ( sigZ & 0x1FF ) <= 5 ) { + term = softfloat_mul64To128( sigZ, sigZ ); + rem = softfloat_sub128( sigA, 0, term.v64, term.v0 ); + while ( UINT64_C( 0x8000000000000000 ) <= rem.v64 ) { + --sigZ; + rem = + softfloat_add128( + rem.v64, rem.v0, sigZ>>63, (uint64_t) ( sigZ<<1 ) ); + } + sigZ |= ( ( rem.v64 | rem.v0 ) != 0 ); + } + return softfloat_roundPackToF64( 0, expZ, sigZ ); + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/f64_sub.cc b/softfloat/f64_sub.cc new file mode 100755 index 0000000..38bd574 --- /dev/null +++ b/softfloat/f64_sub.cc @@ -0,0 +1,29 @@ + +#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; + float64_t ( *magsRoutine )( uint_fast64_t, uint_fast64_t, bool ); + + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF64UI( uiB ); + magsRoutine = + ( signA == signB ) ? softfloat_subMagsF64 : softfloat_addMagsF64; + return magsRoutine( uiA, uiB, signA ); + +} + diff --git a/softfloat/f64_to_f32.cc b/softfloat/f64_to_f32.cc new file mode 100755 index 0000000..395d6c6 --- /dev/null +++ b/softfloat/f64_to_f32.cc @@ -0,0 +1,43 @@ + +#include +#include +#include "platform.h" +#include "primitives.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 sig; + uint_fast32_t uiZ, sig32; + union ui32_f32 uZ; + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp == 0x7FF ) { + uiZ = + sig ? softfloat_commonNaNToF32UI( + softfloat_f64UIToCommonNaN( uiA ) ) + : packToF32UI( sign, 0xFF, 0 ); + goto uiZ; + } + sig32 = softfloat_shortShift64RightJam( sig, 22 ); + if ( ! ( exp | sig32 ) ) { + uiZ = packToF32UI( sign, 0, 0 ); + goto uiZ; + } + return softfloat_roundPackToF32( sign, exp - 0x381, sig32 | 0x40000000 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/f64_to_i32.cc b/softfloat/f64_to_i32.cc new file mode 100755 index 0000000..0778a86 --- /dev/null +++ b/softfloat/f64_to_i32.cc @@ -0,0 +1,30 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +int_fast32_t f64_to_i32( float64_t a, int_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 shiftCount; + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( ( exp == 0x7FF ) && sig ) sign = 0; + if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); + shiftCount = 0x42C - exp; + if ( 0 < shiftCount ) sig = softfloat_shift64RightJam( sig, shiftCount ); + return softfloat_roundPackToI32( sign, sig, roundingMode, exact ); + +} + diff --git a/softfloat/f64_to_i32_r_minMag.cc b/softfloat/f64_to_i32_r_minMag.cc new file mode 100755 index 0000000..39246c2 --- /dev/null +++ b/softfloat/f64_to_i32_r_minMag.cc @@ -0,0 +1,50 @@ + +#include +#include +#include "platform.h" +#include "internals.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; + bool sign; + int_fast16_t shiftCount; + uint_fast32_t absZ; + union { uint32_t ui; int32_t i; } uZ; + int_fast32_t z; + + uA.f = a; + uiA = uA.ui; + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp < 0x3FF ) { + if ( exact && ( exp | sig ) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + sign = signF64UI( uiA ); + if ( 0x41E < exp ) { + if ( ( exp == 0x7FF ) && sig ) sign = 0; + goto invalid; + } + sig |= UINT64_C( 0x0010000000000000 ); + shiftCount = 0x433 - exp; + absZ = sig>>shiftCount; + uZ.ui = sign ? - absZ : absZ; + z = uZ.i; + if ( ( z < 0 ) != sign ) goto invalid; + if ( exact && ( (uint_fast64_t) absZ< +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t f64_to_i64( float64_t a, int_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 shiftCount; + struct uint64_extra sigExtra; + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); + shiftCount = 0x433 - exp; + if ( shiftCount <= 0 ) { + if ( 0x43E < exp ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return + ! sign + || ( ( exp == 0x7FF ) + && ( sig != UINT64_C( 0x0010000000000000 ) ) ) + ? INT64_C( 0x7FFFFFFFFFFFFFFF ) + : - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + sigExtra.v = sig<<( - shiftCount ); + sigExtra.extra = 0; + } else { + sigExtra = softfloat_shift64ExtraRightJam( sig, 0, shiftCount ); + } + return + softfloat_roundPackToI64( + sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); + +} + diff --git a/softfloat/f64_to_i64_r_minMag.cc b/softfloat/f64_to_i64_r_minMag.cc new file mode 100755 index 0000000..525705b --- /dev/null +++ b/softfloat/f64_to_i64_r_minMag.cc @@ -0,0 +1,52 @@ + +#include +#include +#include "platform.h" +#include "internals.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 shiftCount; + int_fast64_t absZ; + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + shiftCount = exp - 0x433; + if ( 0 <= shiftCount ) { + if ( 0x43E <= exp ) { + if ( uiA != packToF64UI( 1, 0x43E, 0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( ! sign || ( ( exp == 0x7FF ) && sig ) ) { + return INT64_C( 0x7FFFFFFFFFFFFFFF ); + } + } + return - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + sig |= UINT64_C( 0x0010000000000000 ); + absZ = sig<>( - shiftCount ); + if ( exact && (uint64_t) ( sig<<( shiftCount & 63 ) ) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + } + return sign ? - absZ : absZ; + +} + diff --git a/softfloat/f64_to_ui32.cc b/softfloat/f64_to_ui32.cc new file mode 100755 index 0000000..b186605 --- /dev/null +++ b/softfloat/f64_to_ui32.cc @@ -0,0 +1,29 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast32_t f64_to_ui32( float64_t a, int_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 shiftCount; + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); + shiftCount = 0x42C - exp; + if ( 0 < shiftCount ) sig = softfloat_shift64RightJam( sig, shiftCount ); + return softfloat_roundPackToUI32( sign, sig, roundingMode, exact ); + +} + diff --git a/softfloat/f64_to_ui32_r_minMag.cc b/softfloat/f64_to_ui32_r_minMag.cc new file mode 100755 index 0000000..9f1dd4d --- /dev/null +++ b/softfloat/f64_to_ui32_r_minMag.cc @@ -0,0 +1,40 @@ + +#include +#include +#include "platform.h" +#include "internals.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 shiftCount; + uint_fast32_t z; + + uA.f = a; + uiA = uA.ui; + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp < 0x3FF ) { + if ( exact && ( exp | sig ) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + if ( signF64UI( uiA ) || ( 0x41E < exp ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return 0xFFFFFFFF; + } + sig |= UINT64_C( 0x0010000000000000 ); + shiftCount = 0x433 - exp; + z = sig>>shiftCount; + if ( exact && ( (uint_fast64_t) z< +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast64_t f64_to_ui64( float64_t a, int_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 shiftCount; + struct uint64_extra sigExtra; + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); + shiftCount = 0x433 - exp; + if ( shiftCount <= 0 ) { + if ( 0x43E < exp ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + } + sigExtra.v = sig<<( - shiftCount ); + sigExtra.extra = 0; + } else { + sigExtra = softfloat_shift64ExtraRightJam( sig, 0, shiftCount ); + } + return + softfloat_roundPackToUI64( + sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); + +} + diff --git a/softfloat/f64_to_ui64_r_minMag.cc b/softfloat/f64_to_ui64_r_minMag.cc new file mode 100755 index 0000000..a66d3ff --- /dev/null +++ b/softfloat/f64_to_ui64_r_minMag.cc @@ -0,0 +1,45 @@ + +#include +#include +#include "platform.h" +#include "internals.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 shiftCount; + uint_fast64_t z; + + uA.f = a; + uiA = uA.ui; + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp < 0x3FF ) { + if ( exact && ( exp | sig ) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + if ( signF64UI( uiA ) ) goto invalid; + shiftCount = exp - 0x433; + if ( 0 <= shiftCount ) { + if ( 0x43E < exp ) goto invalid; + z = ( sig | UINT64_C( 0x0010000000000000 ) )<>( - shiftCount ); + if ( exact && (uint64_t) ( sig<<( shiftCount & 63 ) ) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + } + return z; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + +} + diff --git a/softfloat/i32_to_f32.cc b/softfloat/i32_to_f32.cc new file mode 100755 index 0000000..f51facd --- /dev/null +++ b/softfloat/i32_to_f32.cc @@ -0,0 +1,21 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float32_t i32_to_f32( int_fast32_t a ) +{ + bool sign; + union ui32_f32 uZ; + + sign = ( a < 0 ); + if ( ! ( a & 0x7FFFFFFF ) ) { + uZ.ui = sign ? packToF32UI( 1, 0x9E, 0 ) : 0; + return uZ.f; + } + return softfloat_normRoundPackToF32( sign, 0x9C, sign ? - a : a ); + +} + diff --git a/softfloat/i32_to_f64.cc b/softfloat/i32_to_f64.cc new file mode 100755 index 0000000..d42cbe8 --- /dev/null +++ b/softfloat/i32_to_f64.cc @@ -0,0 +1,31 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +float64_t i32_to_f64( int_fast32_t a ) +{ + uint_fast64_t uiZ; + bool sign; + uint_fast32_t absA; + int shiftCount; + union ui64_f64 uZ; + + if ( ! a ) { + uiZ = 0; + } else { + sign = ( a < 0 ); + absA = sign ? - a : a; + shiftCount = softfloat_countLeadingZeros32( absA ) + 21; + uiZ = + packToF64UI( + sign, 0x432 - shiftCount, (uint_fast64_t) absA< +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +float32_t i64_to_f32( int_fast64_t a ) +{ + bool sign; + uint_fast64_t absA; + int shiftCount; + union ui32_f32 u; + uint_fast32_t sig; + + sign = ( a < 0 ); + absA = sign ? - (uint_fast64_t) a : a; + shiftCount = softfloat_countLeadingZeros64( absA ) - 40; + if ( 0 <= shiftCount ) { + u.ui = + a ? packToF32UI( + sign, 0x95 - shiftCount, (uint_fast32_t) absA< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t i64_to_f64( int_fast64_t a ) +{ + bool sign; + union ui64_f64 uZ; + + sign = ( a < 0 ); + if ( ! ( a & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) ) { + uZ.ui = sign ? packToF64UI( 1, 0x43E, 0 ) : 0; + return uZ.f; + } + return softfloat_normRoundPackToF64( sign, 0x43C, sign ? - a : a ); + +} + diff --git a/softfloat/internals.h b/softfloat/internals.h new file mode 100755 index 0000000..5e6fd76 --- /dev/null +++ b/softfloat/internals.h @@ -0,0 +1,232 @@ + +/*** UPDATE COMMENTS. ***/ + +#include "softfloat_types.h" + +union ui32_f32 { uint32_t ui; float32_t f; }; +union ui64_f64 { uint64_t ui; float64_t f; }; +#ifdef LITTLEENDIAN +union ui128_f128 { uint64_t ui0, ui64; float128_t f; }; +#else +union ui128_f128 { uint64_t ui64, ui0; float128_t f; }; +#endif + +enum { + softfloat_mulAdd_subC = 1, + softfloat_mulAdd_subProd = 2 +}; + +uint_fast32_t + softfloat_roundPackToUI32( bool, uint_fast64_t, int_fast8_t, bool ); +uint_fast64_t + softfloat_roundPackToUI64( + bool, uint_fast64_t, uint_fast64_t, int_fast8_t, bool ); +/*---------------------------------------------------------------------------- +| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 +| and 7, and returns the properly rounded 32-bit integer corresponding to the +| input. If `zSign' is 1, the input is negated before being converted to an +| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input +| is simply rounded to an integer, with the inexact exception raised if the +| input cannot be represented exactly as an integer. However, if the fixed- +| point input is too large, the invalid exception is raised and the largest +| positive or negative integer is returned. +*----------------------------------------------------------------------------*/ +int_fast32_t + softfloat_roundPackToI32( bool, uint_fast64_t, int_fast8_t, bool ); +/*---------------------------------------------------------------------------- +| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and +| `absZ1', with binary point between bits 63 and 64 (between the input words), +| and returns the properly rounded 64-bit integer corresponding to the input. +| If `zSign' is 1, the input is negated before being converted to an integer. +| Ordinarily, the fixed-point input is simply rounded to an integer, with +| the inexact exception raised if the input cannot be represented exactly as +| an integer. However, if the fixed-point input is too large, the invalid +| exception is raised and the largest positive or negative integer is +| returned. +*----------------------------------------------------------------------------*/ +int_fast64_t + softfloat_roundPackToI64( + bool, uint_fast64_t, uint_fast64_t, int_fast8_t, bool ); + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is a NaN; +| otherwise, returns 0. +*----------------------------------------------------------------------------*/ +#define isNaNF32UI( ui ) (0xFF000000<(uint32_t)((uint_fast32_t)(ui)<<1)) +/*---------------------------------------------------------------------------- +| Returns the sign bit of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ +#define signF32UI( a ) ((bool)((uint32_t)(a)>>31)) +/*---------------------------------------------------------------------------- +| Returns the exponent bits of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ +#define expF32UI( a ) ((int_fast16_t)((a)>>23)&0xFF) +/*---------------------------------------------------------------------------- +| Returns the fraction bits of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ +#define fracF32UI( a ) ((a)&0x007FFFFF) +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| single-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ +#define packToF32UI( sign, exp, sig ) (((uint32_t)(sign)<<31)+((uint32_t)(exp)<<23)+(sig)) + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal single-precision floating-point value represented +| by the denormalized significand `aSig'. The normalized exponent and +| significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ +struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; }; +struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t ); + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper single-precision floating- +| point value corresponding to the abstract input. Ordinarily, the abstract +| value is simply rounded and packed into the single-precision format, with +| the inexact exception raised if the abstract input cannot be represented +| exactly. However, if the abstract value is too large, the overflow and +| inexact exceptions are raised and an infinity or maximal finite value is +| returned. If the abstract value is too small, the input value is rounded to +| a subnormal number, and the underflow and inexact exceptions are raised if +| the abstract input cannot be represented exactly as a subnormal single- +| precision floating-point number. +| The input significand `zSig' has its binary point between bits 30 +| and 29, which is 7 bits to the left of the usual location. This shifted +| significand must be normalized or smaller. If `zSig' is not normalized, +| `zExp' must be 0; in that case, the result returned is a subnormal number, +| and it must not require rounding. In the usual case that `zSig' is +| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. +| The handling of underflow and overflow follows the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ +float32_t softfloat_roundPackToF32( bool, int_fast16_t, uint_fast32_t ); +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper single-precision floating- +| point value corresponding to the abstract input. This routine is just like +| `roundAndPackFloat32' except that `zSig' does not have to be normalized. +| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' +| floating-point exponent. +*----------------------------------------------------------------------------*/ +float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t ); + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the single-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ +float32_t softfloat_addMagsF32( uint_fast32_t, uint_fast32_t, bool ); +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the single- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ +float32_t softfloat_subMagsF32( uint_fast32_t, uint_fast32_t, bool ); +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +float32_t + softfloat_mulAddF32( int, uint_fast32_t, uint_fast32_t, uint_fast32_t ); + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is a NaN; +| otherwise, returns 0. +*----------------------------------------------------------------------------*/ +#define isNaNF64UI( ui ) (UINT64_C(0xFFE0000000000000)<(uint64_t)((uint_fast64_t)(ui)<<1)) +/*---------------------------------------------------------------------------- +| Returns the sign bit of the double-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ +#define signF64UI( a ) ((bool)((uint64_t)(a)>>63)) +/*---------------------------------------------------------------------------- +| Returns the exponent bits of the double-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ +#define expF64UI( a ) ((int_fast16_t)((a)>>52)&0x7FF) +/*---------------------------------------------------------------------------- +| Returns the fraction bits of the double-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ +#define fracF64UI( a ) ((a)&UINT64_C(0x000FFFFFFFFFFFFF)) +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| double-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ +#define packToF64UI( sign, exp, sig ) (((uint64_t)(sign)<<63)+((uint64_t)(exp)<<52)+(sig)) + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal double-precision floating-point value represented +| by the denormalized significand `aSig'. The normalized exponent and +| significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ +struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; }; +struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t ); + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper double-precision floating- +| point value corresponding to the abstract input. Ordinarily, the abstract +| value is simply rounded and packed into the double-precision format, with +| the inexact exception raised if the abstract input cannot be represented +| exactly. However, if the abstract value is too large, the overflow and +| inexact exceptions are raised and an infinity or maximal finite value is +| returned. If the abstract value is too small, the input value is rounded +| to a subnormal number, and the underflow and inexact exceptions are raised +| if the abstract input cannot be represented exactly as a subnormal double- +| precision floating-point number. +| The input significand `zSig' has its binary point between bits 62 +| and 61, which is 10 bits to the left of the usual location. This shifted +| significand must be normalized or smaller. If `zSig' is not normalized, +| `zExp' must be 0; in that case, the result returned is a subnormal number, +| and it must not require rounding. In the usual case that `zSig' is +| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. +| The handling of underflow and overflow follows the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ +float64_t softfloat_roundPackToF64( bool, int_fast16_t, uint_fast64_t ); +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper double-precision floating- +| point value corresponding to the abstract input. This routine is just like +| `roundAndPackFloat64' except that `zSig' does not have to be normalized. +| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' +| floating-point exponent. +*----------------------------------------------------------------------------*/ +float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t ); + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the double-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ +float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool ); +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the double- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ +float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool ); +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +float64_t + softfloat_mulAddF64( int, uint_fast64_t, uint_fast64_t, uint_fast64_t ); + diff --git a/softfloat/milieu.h b/softfloat/milieu.h deleted file mode 100644 index ab3d371..0000000 --- a/softfloat/milieu.h +++ /dev/null @@ -1,68 +0,0 @@ - -/*---------------------------------------------------------------------------- -| One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined. -*----------------------------------------------------------------------------*/ -#define BIGENDIAN - -/*---------------------------------------------------------------------------- -| The macro `BITS64' can be defined to indicate that 64-bit integer types are -| supported by the compiler. -*----------------------------------------------------------------------------*/ -#define BITS64 - -/*---------------------------------------------------------------------------- -| Each of the following `typedef's defines the most convenient type that holds -| integers of at least as many bits as specified. For example, `uint8' should -| be the most convenient type that can hold unsigned integers of as many as -| 8 bits. The `flag' type must be able to hold either a 0 or 1. For most -| implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed -| to the same as `int'. -*----------------------------------------------------------------------------*/ -typedef int flag; -typedef int uint8; -typedef int int8; -typedef int uint16; -typedef int int16; -typedef unsigned int uint32; -typedef signed int int32; -#ifdef BITS64 -typedef unsigned long long int uint64; -typedef signed long long int int64; -#endif - -/*---------------------------------------------------------------------------- -| Each of the following `typedef's defines a type that holds integers -| of _exactly_ the number of bits specified. For instance, for most -| implementation of C, `bits16' and `sbits16' should be `typedef'ed to -| `unsigned short int' and `signed short int' (or `short int'), respectively. -*----------------------------------------------------------------------------*/ -typedef unsigned char bits8; -typedef signed char sbits8; -typedef unsigned short int bits16; -typedef signed short int sbits16; -typedef unsigned int bits32; -typedef signed int sbits32; -#ifdef BITS64 -typedef unsigned long long int bits64; -typedef signed long long int sbits64; -#endif - -#ifdef BITS64 -/*---------------------------------------------------------------------------- -| The `LIT64' macro takes as its argument a textual integer literal and -| if necessary ``marks'' the literal as having a 64-bit integer type. -| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be -| appended with the letters `LL' standing for `long long', which is `gcc's -| name for the 64-bit integer type. Some compilers may allow `LIT64' to be -| defined as the identity macro: `#define LIT64( a ) a'. -*----------------------------------------------------------------------------*/ -#define LIT64( a ) a##LL -#endif - -/*---------------------------------------------------------------------------- -| The macro `INLINE' can be used before functions that should be inlined. If -| a compiler does not support explicit inlining, this macro should be defined -| to be `static'. -*----------------------------------------------------------------------------*/ -#define INLINE extern inline - diff --git a/softfloat/primitives.h b/softfloat/primitives.h new file mode 100755 index 0000000..71038ea --- /dev/null +++ b/softfloat/primitives.h @@ -0,0 +1,628 @@ + +/*============================================================================ + +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 3. + +*** UPDATE + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +#include +#include + +/*** CHANGE TO USE `fast' INTEGER TYPES? ***/ +/*** ADD 80-BIT FUNCTIONS? ***/ + +#ifdef LITTLEENDIAN +struct uintx80 { uint64_t v0; uint16_t v64; }; +struct uint128 { uint64_t v0, v64; }; +struct uint192 { uint64_t v0, v64, v128; }; +struct uint256 { uint64_t v0, v64, v128, v192; }; +#else +struct uintx80 { uint16_t v64; uint64_t v0; }; +struct uint128 { uint64_t v64, v0; }; +struct uint192 { uint64_t v128, v64, v0; }; +struct uint256 { uint64_t v256, v128, v64, v0; }; +#endif + +struct uint64_extra { uint64_t v, extra; }; +struct uint128_extra { uint64_t v64; uint64_t v0; uint64_t extra; }; + + +/*** SHIFT COUNTS CANNOT BE ZERO. MUST CHECK BEFORE CALLING! ***/ + + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' +| is equal to the 128-bit value formed by concatenating `b0' and `b1'. +| Otherwise, returns 0. +*----------------------------------------------------------------------------*/ +#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, uint64_t, uint64_t, uint64_t ); +#endif + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less +| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. +| Otherwise, returns 0. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 1 <= 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, uint64_t, uint64_t, uint64_t ); +#endif + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less +| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, +| returns 0. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 1 <= 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, uint64_t, uint64_t, uint64_t ); +#endif + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' must be less than 64. The result is broken into two 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 2 <= INLINE_LEVEL ) +INLINE struct uint128 + softfloat_shortShift128Left( uint64_t a64, uint64_t a0, unsigned int count ) +{ + struct uint128 z; + z.v64 = a64<>( ( - count ) & 63 ); + z.v0 = a0<>( negCount & 63 ); + z.v64 = a64<>( negCount & 63 ); + z.v0 = a0<>count | ( (uint32_t) ( a<<( ( - count ) & 31 ) ) != 0 ) + : ( a != 0 ); +} +#else +uint32_t softfloat_shift32RightJam( uint32_t, unsigned int ); +#endif + +/*---------------------------------------------------------------------------- +| Shift count is less than 32. +*----------------------------------------------------------------------------*/ +#if defined INLINE +INLINE uint32_t softfloat_shortShift32Right1Jam( uint32_t a ) + { return a>>1 | ( a & 1 ); } +#else +uint32_t softfloat_shortShift32Right1Jam( uint32_t ); +#endif + +/*---------------------------------------------------------------------------- +| Shifts `a' right by the number of bits given in `count'. If any nonzero +| bits are shifted off, they are ``jammed'' into the least significant bit of +| the result by setting the least significant bit to 1. The value of `count' +| can be arbitrarily large; in particular, if `count' is greater than 64, the +| result will be either 0 or 1, depending on whether `a' is zero or nonzero. +| The result is stored in the location pointed to by `zPtr'. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 3 <= INLINE_LEVEL ) +INLINE uint64_t softfloat_shift64RightJam( uint64_t a, unsigned int count ) +{ + return + ( count < 64 ) + ? a>>count | ( (uint64_t) ( a<<( ( - count ) & 63 ) ) != 0 ) + : ( a != 0 ); +} +#else +uint64_t softfloat_shift64RightJam( uint64_t, unsigned int ); +#endif + +/*---------------------------------------------------------------------------- +| Shift count is less than 64. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 2 <= INLINE_LEVEL ) +INLINE uint64_t + softfloat_shortShift64RightJam( uint64_t a, unsigned int count ) + { return a>>count | ( ( a & ( ( (uint64_t) 1<>count; + z.extra = a<<( ( - count ) & 63 ); + } else { + z.v = 0; + z.extra = ( count == 64 ) ? a : ( a != 0 ); + } + z.extra |= ( extra != 0 ); + return z; +} +#else +struct uint64_extra + softfloat_shift64ExtraRightJam( uint64_t, uint64_t, unsigned int ); +#endif + +/*---------------------------------------------------------------------------- +| Shift count is less than 64. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 2 <= INLINE_LEVEL ) +INLINE struct uint64_extra + softfloat_shortShift64ExtraRightJam( + uint64_t a, uint64_t extra, unsigned int count ) +{ + struct uint64_extra z; + z.v = a>>count; + z.extra = a<<( ( - count ) & 63 ) | ( extra != 0 ); + return z; +} +#else +struct uint64_extra + softfloat_shortShift64ExtraRightJam( uint64_t, uint64_t, unsigned int ); +#endif + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' can be arbitrarily large; in particular, if `count' is greater +| than 128, the result will be 0. The result is broken into two 64-bit pieces +| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------- +| Shift count is less than 64. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 2 <= INLINE_LEVEL ) +INLINE struct uint128 + softfloat_shortShift128Right( uint64_t a64, uint64_t a0, unsigned int count ) +{ + struct uint128 z; + z.v64 = a64>>count; + z.v0 = a64<<( ( - count ) & 63 ) | a0>>count; + return z; +} +#else +struct uint128 + softfloat_shortShift128Right( uint64_t, uint64_t, unsigned int ); +#endif + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the +| number of bits given in `count'. If any nonzero bits are shifted off, they +| are ``jammed'' into the least significant bit of the result by setting the +| least significant bit to 1. The value of `count' can be arbitrarily large; +| in particular, if `count' is greater than 128, the result will be either +| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or +| nonzero. The result is broken into two 64-bit pieces which are stored at +| the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 4 <= INLINE_LEVEL ) +INLINE struct uint128 + softfloat_shift128RightJam( uint64_t a64, uint64_t a0, unsigned int count ) +{ + unsigned int negCount; + struct uint128 z; + if ( count < 64 ) { + negCount = - count; + z.v64 = a64>>( count & 63 ); + z.v0 = + a64<<( negCount & 63 ) | a0>>count + | ( (uint64_t) ( a0<<( negCount & 63 ) ) != 0 ); + } else { + z.v64 = 0; + z.v0 = + ( count < 128 ) + ? a64>>( count & 63 ) + | ( ( ( a64 & ( ( (uint64_t) 1<<( count & 63 ) ) - 1 ) ) + | a0 ) + != 0 ) + : ( ( a64 | a0 ) != 0 ); + } + return z; +} +#else +struct uint128 + softfloat_shift128RightJam( uint64_t, uint64_t, unsigned int ); +#endif + +/*---------------------------------------------------------------------------- +| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right +| by 64 _plus_ the number of bits given in `count'. The shifted result is +| at most 128 nonzero bits; these are broken into two 64-bit pieces which are +| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted +| off form a third 64-bit result as follows: The _last_ bit shifted off is +| the most-significant bit of the extra result, and the other 63 bits of the +| extra result are all zero if and only if _all_but_the_last_ bits shifted off +| were all zero. This extra result is stored in the location pointed to by +| `z2Ptr'. The value of `count' can be arbitrarily large. +| (This routine makes more sense if `a0', `a1', and `a2' are considered +| to form a fixed-point value with binary point between `a1' and `a2'. This +| fixed-point value is shifted right by the number of bits given in `count', +| and the integer part of the result is returned at the locations pointed to +| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly +| corrupted as described above, and is returned at the location pointed to by +| `z2Ptr'.) +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 5 <= INLINE_LEVEL ) +INLINE struct uint128_extra + softfloat_shift128ExtraRightJam( + uint64_t a64, uint64_t a0, uint64_t extra, unsigned int count ) +{ + unsigned int negCount = - count; + struct uint128_extra z; + if ( count < 64 ) { + z.v64 = a64>>count; + z.v0 = a64<<( negCount & 63 ) | a0>>count; + z.extra = a0<<( negCount & 63 ); + } else { + z.v64 = 0; + if ( count == 64 ) { + z.v0 = a64; + z.extra = a0; + } else { + extra |= a0; + if ( count < 128 ) { + z.v0 = a64>>( count & 63 ); + z.extra = a64<<( negCount & 63 ); + } else { + z.v0 = 0; + z.extra = ( count == 128 ) ? a64 : ( a64 != 0 ); + } + } + } + z.extra |= ( extra != 0 ); + return z; +} +#else +struct uint128_extra + softfloat_shift128ExtraRightJam( uint64_t, uint64_t, uint64_t, unsigned int ); +#endif + +/*---------------------------------------------------------------------------- +| Shift count is less than 64. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 3 <= INLINE_LEVEL ) +INLINE struct uint128_extra + softfloat_shortShift128ExtraRightJam( + uint64_t a64, uint64_t a0, uint64_t extra, unsigned int count ) +{ + unsigned int negCount = - count; + struct uint128_extra z; + z.v64 = a64>>count; + z.v0 = a64<<( negCount & 63 ) | a0>>count; + z.extra = a0<<( negCount & 63 ) | ( extra != 0 ); + return z; +} +#else +struct uint128_extra + softfloat_shortShift128ExtraRightJam( + uint64_t, uint64_t, uint64_t, unsigned int ); +#endif + +extern const uint8_t softfloat_countLeadingZeros8[ 256 ]; + +/*---------------------------------------------------------------------------- +| 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 && ( 2 <= INLINE_LEVEL ) +INLINE int softfloat_countLeadingZeros32( uint32_t a ) +{ + int count = 0; + if ( a < 0x10000 ) { + count = 16; + a <<= 16; + } + if ( a < 0x1000000 ) { + count += 8; + a <<= 8; + } + count += softfloat_countLeadingZeros8[ a>>24 ]; + return count; +} +#else +int softfloat_countLeadingZeros32( uint32_t ); +#endif + +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| `a'. If `a' is zero, 64 is returned. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 4 <= INLINE_LEVEL ) +INLINE int softfloat_countLeadingZeros64( uint64_t a ) +{ + int count = 32; + uint32_t a32 = a; + if ( UINT64_C( 0x100000000 ) <= a ) { + count = 0; + a32 = a>>32; + } + /*------------------------------------------------------------------------ + | 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; +} +#else +int softfloat_countLeadingZeros64( uint64_t ); +#endif + +/*---------------------------------------------------------------------------- +| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit +| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so +| any carry out is lost. The result is broken into two 64-bit pieces which +| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ +#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.v64 += ( z.v0 < a0 ); + return z; +} +#else +struct uint128 softfloat_add128( uint64_t, uint64_t, uint64_t, uint64_t ); +#endif + +/*---------------------------------------------------------------------------- +| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the +| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is +| modulo 2^192, so any carry out is lost. The result is broken into three +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', +| `z1Ptr', and `z2Ptr'. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 3 <= INLINE_LEVEL ) +INLINE struct uint192 + softfloat_add192( + uint64_t a128, + uint64_t a64, + uint64_t a0, + uint64_t b128, + uint64_t b64, + uint64_t b0 + ) +{ + struct uint192 z; + unsigned int carry64, carry128; + z.v0 = a0 + b0; + carry64 = ( z.v0 < a0 ); + z.v64 = a64 + b64; + carry128 = ( z.v64 < a64 ); + z.v128 = a128 + b128; + z.v64 += carry64; + carry128 += ( z.v64 < carry64 ); + z.v128 += carry128; + return z; +} +#else +struct uint192 + softfloat_add192( + uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t ); +#endif + +/*---------------------------------------------------------------------------- +| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the +| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo +| 2^128, so any borrow out (carry out) is lost. The result is broken into two +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and +| `z1Ptr'. +*----------------------------------------------------------------------------*/ +#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, uint64_t, uint64_t, uint64_t ); +#endif + +/*---------------------------------------------------------------------------- +| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' +| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. +| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The +| result is broken into three 64-bit pieces which are stored at the locations +| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 3 <= INLINE_LEVEL ) +INLINE struct uint192 + softfloat_sub192( + uint64_t a128, + uint64_t a64, + uint64_t a0, + uint64_t b128, + uint64_t b64, + uint64_t b0 + ) +{ + struct uint192 z; + unsigned int borrow64, borrow128; + z.v0 = a0 - b0; + borrow64 = ( a0 < b0 ); + z.v64 = a64 - b64; + borrow128 = ( a64 < b64 ); + z.v128 = a128 - b128; + borrow128 += ( z.v64 < borrow64 ); + z.v64 -= borrow64; + z.v128 -= borrow128; + return z; +} +#else +struct uint192 + softfloat_sub192( + uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t ); +#endif + +/*---------------------------------------------------------------------------- +| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken +| into two 64-bit pieces which are stored at the locations pointed to by +| `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 4 <= INLINE_LEVEL ) +INLINE struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ) +{ + uint32_t a32 = a>>32; + uint32_t a0 = a; + uint32_t b32 = b>>32; + uint32_t b0 = b; + struct uint128 z; + uint64_t mid1, mid2, mid; + z.v0 = (uint64_t) a0 * b0; + mid1 = (uint64_t) a32 * b0; + mid2 = (uint64_t) a0 * b32; + z.v64 = (uint64_t) a32 * b32; + mid = mid1 + mid2; + z.v64 += ( (uint64_t) ( mid < mid1 ) )<<32 | mid>>32; + mid <<= 32; + z.v0 += mid; + z.v64 += ( z.v0 < mid ); + return z; +} +#else +struct uint128 softfloat_mul64To128( uint64_t, uint64_t ); +#endif + +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by +| `b' to obtain a 192-bit product. The product is broken into three 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and +| `z2Ptr'. +*----------------------------------------------------------------------------*/ +struct uint192 softfloat_mul128By64To192( uint64_t, uint64_t, uint64_t ); +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the +| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit +| product. The product is broken into four 64-bit pieces which are stored at +| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. +*----------------------------------------------------------------------------*/ +struct uint256 softfloat_mul128To256( uint64_t, uint64_t, uint64_t, uint64_t ); + +/*---------------------------------------------------------------------------- +| Returns an approximation to the 64-bit integer quotient obtained by dividing +| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The +| divisor `b' must be at least 2^63. If q is the exact quotient truncated +| toward zero, the approximation returned lies between q and q + 2 inclusive. +| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit +| unsigned integer is returned. +*----------------------------------------------------------------------------*/ +uint64_t softfloat_estimateDiv128To64( uint64_t, uint64_t, uint64_t ); + +/*---------------------------------------------------------------------------- +| Returns an approximation to the square root of the 32-bit significand given +| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of +| `aExp' (the least significant bit) is 1, the integer returned approximates +| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' +| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either +| case, the approximation returned lies strictly within +/-2 of the exact +| value. +*----------------------------------------------------------------------------*/ +uint32_t softfloat_estimateSqrt32( unsigned int, uint32_t ); + diff --git a/softfloat/s_add128.cc b/softfloat/s_add128.cc new file mode 100755 index 0000000..59c0348 --- /dev/null +++ b/softfloat/s_add128.cc @@ -0,0 +1,17 @@ + +#include +#include "platform.h" +#include "primitives.h" + +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.v64 += ( z.v0 < a0 ); + return z; + +} + diff --git a/softfloat/s_add192.cc b/softfloat/s_add192.cc new file mode 100755 index 0000000..543eb5d --- /dev/null +++ b/softfloat/s_add192.cc @@ -0,0 +1,30 @@ + +#include +#include "platform.h" +#include "primitives.h" + +struct uint192 + softfloat_add192( + uint64_t a128, + uint64_t a64, + uint64_t a0, + uint64_t b128, + uint64_t b64, + uint64_t b0 + ) +{ + struct uint192 z; + unsigned int carry64, carry128; + + z.v0 = a0 + b0; + carry64 = ( z.v0 < a0 ); + z.v64 = a64 + b64; + carry128 = ( z.v64 < a64 ); + z.v128 = a128 + b128; + z.v64 += carry64; + carry128 += ( z.v64 < carry64 ); + z.v128 += carry128; + return z; + +} + diff --git a/softfloat/s_addMagsF32.cc b/softfloat/s_addMagsF32.cc new file mode 100755 index 0000000..f361e2b --- /dev/null +++ b/softfloat/s_addMagsF32.cc @@ -0,0 +1,75 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "specialize.h" + +float32_t + softfloat_addMagsF32( uint_fast32_t uiA, uint_fast32_t uiB, bool signZ ) +{ + int_fast16_t expA; + uint_fast32_t sigA; + int_fast16_t expB; + uint_fast32_t sigB; + int_fast16_t expDiff; + uint_fast32_t uiZ; + int_fast16_t expZ; + uint_fast32_t sigZ; + union ui32_f32 uZ; + + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + expB = expF32UI( uiB ); + sigB = fracF32UI( uiB ); + expDiff = expA - expB; + sigA <<= 6; + sigB <<= 6; + if ( ! expDiff ) { + if ( expA == 0xFF ) { + if ( sigA | sigB ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + if ( ! expA ) { + uiZ = packToF32UI( signZ, 0, ( uiA + uiB ) & 0x7FFFFFFF ); + goto uiZ; + } + expZ = expA; + sigZ = 0x40000000 + sigA + sigB; + } else { + if ( expDiff < 0 ) { + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN; + uiZ = packToF32UI( signZ, 0xFF, 0 ); + goto uiZ; + } + expZ = expB; + sigA += expA ? 0x20000000 : sigA; + sigA = softfloat_shift32RightJam( sigA, - expDiff ); + } else { + if ( expA == 0xFF ) { + if ( sigA ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + expZ = expA; + sigB += expB ? 0x20000000 : sigB; + sigB = softfloat_shift32RightJam( sigB, expDiff ); + } + sigZ = 0x20000000 + sigA + sigB; + if ( sigZ < 0x40000000 ) { + --expZ; + sigZ <<= 1; + } + } + return softfloat_roundPackToF32( signZ, expZ, sigZ ); + propagateNaN: + uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/s_addMagsF64.cc b/softfloat/s_addMagsF64.cc new file mode 100755 index 0000000..a81c3e4 --- /dev/null +++ b/softfloat/s_addMagsF64.cc @@ -0,0 +1,77 @@ + +#include +#include +#include "platform.h" +#include "primitives.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; + sigA <<= 9; + sigB <<= 9; + if ( ! expDiff ) { + if ( expA == 0x7FF ) { + if ( sigA | sigB ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + if ( ! expA ) { + uiZ = + packToF64UI( + signZ, 0, ( uiA + uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ); + goto uiZ; + } + expZ = expA; + sigZ = UINT64_C( 0x4000000000000000 ) + sigA + sigB; + } else { + if ( expDiff < 0 ) { + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + uiZ = packToF64UI( signZ, 0x7FF, 0 ); + goto uiZ; + } + expZ = expB; + sigA += expA ? UINT64_C( 0x2000000000000000 ) : sigA; + sigA = softfloat_shift64RightJam( sigA, - expDiff ); + } else { + if ( expA == 0x7FF ) { + if ( sigA ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + expZ = expA; + sigB += expB ? UINT64_C( 0x2000000000000000 ) : sigB; + sigB = softfloat_shift64RightJam( 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/softfloat/s_countLeadingZeros32.cc b/softfloat/s_countLeadingZeros32.cc new file mode 100755 index 0000000..0bd17e1 --- /dev/null +++ b/softfloat/s_countLeadingZeros32.cc @@ -0,0 +1,22 @@ + +#include +#include "primitives.h" + +int softfloat_countLeadingZeros32( uint32_t a ) +{ + int count; + + count = 0; + if ( a < 0x10000 ) { + count = 16; + a <<= 16; + } + if ( a < 0x1000000 ) { + count += 8; + a <<= 8; + } + count += softfloat_countLeadingZeros8[ a>>24 ]; + return count; + +} + diff --git a/softfloat/s_countLeadingZeros64.cc b/softfloat/s_countLeadingZeros64.cc new file mode 100755 index 0000000..79f4280 --- /dev/null +++ b/softfloat/s_countLeadingZeros64.cc @@ -0,0 +1,32 @@ + +#include +#include "primitives.h" +#include "platform.h" + +int softfloat_countLeadingZeros64( uint64_t a ) +{ + int count; + uint32_t a32; + + count = 32; + a32 = a; + if ( UINT64_C( 0x100000000 ) <= a ) { + count = 0; + a32 = a>>32; + } + /*------------------------------------------------------------------------ + | 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; + +} + diff --git a/softfloat/s_countLeadingZeros8.cc b/softfloat/s_countLeadingZeros8.cc new file mode 100755 index 0000000..4eca7e9 --- /dev/null +++ b/softfloat/s_countLeadingZeros8.cc @@ -0,0 +1,24 @@ + +#include +#include "platform.h" +#include "primitives.h" + +const uint8_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/softfloat/s_eq128.cc b/softfloat/s_eq128.cc new file mode 100755 index 0000000..7261dc4 --- /dev/null +++ b/softfloat/s_eq128.cc @@ -0,0 +1,13 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" + +bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) +{ + + return ( a64 == b64 ) && ( a0 == b0 ); + +} + diff --git a/softfloat/s_estimateDiv128To64.cc b/softfloat/s_estimateDiv128To64.cc new file mode 100755 index 0000000..f8610a2 --- /dev/null +++ b/softfloat/s_estimateDiv128To64.cc @@ -0,0 +1,28 @@ + +#include +#include "platform.h" +#include "primitives.h" + +uint64_t softfloat_estimateDiv128To64( uint64_t a64, uint64_t a0, uint64_t b ) +{ + uint32_t b32; + uint64_t z; + struct uint128 term, rem; + uint64_t rem32; + + if ( b <= a64 ) return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + b32 = b>>32; + z = ( (uint64_t) b32<<32 <= a64 ) ? UINT64_C( 0xFFFFFFFF00000000 ) + : ( a64 / b32 )<<32; + term = softfloat_mul64To128( b, z ); + rem = softfloat_sub128( a64, a0, term.v64, term.v0 ); + while ( UINT64_C( 0x8000000000000000 ) <= rem.v64 ) { + z -= UINT64_C( 0x100000000 ); + rem = softfloat_add128( rem.v64, rem.v0, b32, (uint64_t) ( b<<32 ) ); + } + rem32 = ( rem.v64<<32 ) | ( rem.v0>>32 ); + z |= ( (uint64_t) b32<<32 <= rem32 ) ? 0xFFFFFFFF : rem32 / b32; + return z; + +} + diff --git a/softfloat/s_estimateSqrt32.cc b/softfloat/s_estimateSqrt32.cc new file mode 100755 index 0000000..e22a9dc --- /dev/null +++ b/softfloat/s_estimateSqrt32.cc @@ -0,0 +1,37 @@ + +#include +#include "platform.h" +#include "primitives.h" + +uint32_t softfloat_estimateSqrt32( unsigned int expA, uint32_t a ) +{ + static const uint16_t sqrtOddAdjustments[] = { + 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, + 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 + }; + static const uint16_t sqrtEvenAdjustments[] = { + 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, + 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 + }; + int index; + uint32_t z; + union { uint32_t ui; int32_t i; } u32; + + index = ( a>>27 ) & 15; + if ( expA & 1 ) { + z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; + z = ( ( a / z )<<14 ) + ( z<<15 ); + a >>= 1; + } else { + z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; + z = a / z + z; + z = ( 0x20000 <= z ) ? 0xFFFF8000 : z<<15; + if ( z <= a ) { + u32.ui = a; + return u32.i>>1; + } + } + return (uint32_t) ( ( (uint64_t) a<<31 ) / z ) + ( z>>1 ); + +} + diff --git a/softfloat/s_le128.cc b/softfloat/s_le128.cc new file mode 100755 index 0000000..83b1d7f --- /dev/null +++ b/softfloat/s_le128.cc @@ -0,0 +1,13 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" + +bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) +{ + + return ( a64 < b64 ) || ( ( a64 == b64 ) && ( a0 <= b0 ) ); + +} + diff --git a/softfloat/s_lt128.cc b/softfloat/s_lt128.cc new file mode 100755 index 0000000..33a3df4 --- /dev/null +++ b/softfloat/s_lt128.cc @@ -0,0 +1,13 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" + +bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) +{ + + return ( a64 < b64 ) || ( ( a64 == b64 ) && ( a0 < b0 ) ); + +} + diff --git a/softfloat/s_mul128By64To192.cc b/softfloat/s_mul128By64To192.cc new file mode 100755 index 0000000..dfa8825 --- /dev/null +++ b/softfloat/s_mul128By64To192.cc @@ -0,0 +1,20 @@ + +#include +#include "platform.h" +#include "primitives.h" + +struct uint192 + softfloat_mul128By64To192( uint64_t a64, uint64_t a0, uint64_t b ) +{ + struct uint128 p0, p64; + struct uint192 z; + + p0 = softfloat_mul64To128( a0, b ); + z.v0 = p0.v0; + p64 = softfloat_mul64To128( a64, b ); + z.v64 = p64.v0 + p0.v64; + z.v128 = p64.v64 + ( z.v64 < p64.v0 ); + return z; + +} + diff --git a/softfloat/s_mul128To256.cc b/softfloat/s_mul128To256.cc new file mode 100755 index 0000000..a96cd94 --- /dev/null +++ b/softfloat/s_mul128To256.cc @@ -0,0 +1,28 @@ + +#include +#include "platform.h" +#include "primitives.h" + +struct uint256 + softfloat_mul128To256( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) +{ + struct uint128 p0, p64, p128; + struct uint256 z; + + p0 = softfloat_mul64To128( a0, b0 ); + z.v0 = p0.v0; + p64 = softfloat_mul64To128( a64, b0 ); + z.v64 = p64.v0 + p0.v64; + z.v128 = p64.v64 + ( z.v64 < p64.v0 ); + p128 = softfloat_mul64To128( a64, b64 ); + z.v128 += p128.v0; + z.v192 = p128.v64 + ( z.v128 < p128.v0 ); + p64 = softfloat_mul64To128( a0, b64 ); + z.v64 += p64.v0; + p64.v64 += ( z.v64 < p64.v0 ); + z.v128 += p64.v64; + z.v192 += ( z.v128 < p64.v64 ); + return z; + +} + diff --git a/softfloat/s_mul64To128.cc b/softfloat/s_mul64To128.cc new file mode 100755 index 0000000..c17780b --- /dev/null +++ b/softfloat/s_mul64To128.cc @@ -0,0 +1,28 @@ + +#include +#include "platform.h" +#include "primitives.h" + +struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ) +{ + uint32_t a32, a0, b32, b0; + struct uint128 z; + uint64_t mid1, mid2, mid; + + a32 = a>>32; + a0 = a; + b32 = b>>32; + b0 = b; + z.v0 = (uint64_t) a0 * b0; + mid1 = (uint64_t) a32 * b0; + mid2 = (uint64_t) a0 * b32; + z.v64 = (uint64_t) a32 * b32; + mid = mid1 + mid2; + z.v64 += ( (uint64_t) ( mid < mid1 ) )<<32 | mid>>32; + mid <<= 32; + z.v0 += mid; + z.v64 += ( z.v0 < mid ); + return z; + +} + diff --git a/softfloat/s_mulAddF32.cc b/softfloat/s_mulAddF32.cc new file mode 100755 index 0000000..e55a0ba --- /dev/null +++ b/softfloat/s_mulAddF32.cc @@ -0,0 +1,171 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t + softfloat_mulAddF32( + int op, uint_fast32_t uiA, uint_fast32_t uiB, uint_fast32_t uiC ) +{ + 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 sigZ64, sigC64; + int shiftCount; + 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_shortShift64RightJam( 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_shift64RightJam( sigProd, 32 - expDiff ); + } else { + expZ = expProd; + sigZ64 = + sigProd + + softfloat_shift64RightJam( + (uint_fast64_t) sigC<<32, expDiff ); + sigZ = softfloat_shortShift64RightJam( sigZ64, 32 ); + } + if ( sigZ < 0x40000000 ) { + --expZ; + sigZ <<= 1; + } + } else { +/*** OPTIMIZE BETTER? ***/ + sigC64 = (uint_fast64_t) sigC<<32; + if ( expDiff < 0 ) { + signZ = signC; + expZ = expC; + sigZ64 = sigC64 - softfloat_shift64RightJam( sigProd, - expDiff ); + } else if ( ! expDiff ) { + expZ = expProd; + sigZ64 = sigProd - sigC64; + if ( ! sigZ64 ) goto completeCancellation; + if ( sigZ64 & UINT64_C( 0x8000000000000000 ) ) { + signZ ^= 1; + sigZ64 = - sigZ64; + } + } else { + expZ = expProd; + sigZ64 = sigProd - softfloat_shift64RightJam( sigC64, expDiff ); + } + shiftCount = softfloat_countLeadingZeros64( sigZ64 ) - 1; + expZ -= shiftCount; + shiftCount -= 32; + if ( shiftCount < 0 ) { + sigZ = softfloat_shortShift64RightJam( sigZ64, - shiftCount ); + } else { + sigZ = (uint_fast32_t) sigZ64< +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t + softfloat_mulAddF64( + int op, uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC ) +{ + 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 signProd; + uint_fast64_t magBits, uiZ; + struct exp16_sig64 normExpSig; + int_fast16_t expProd; + struct uint128 sigProd; + bool signZ; + int_fast16_t expZ; + uint_fast64_t sigZ; + int_fast16_t expDiff; + struct uint128 sigC128, sigZ128; + int shiftCount; + 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 ); + signProd = 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; + } + expProd = expA + expB - 0x3FE; + sigA = ( sigA | UINT64_C( 0x0010000000000000 ) )<<10; + sigB = ( sigB | UINT64_C( 0x0010000000000000 ) )<<10; + sigProd = softfloat_mul64To128( sigA, sigB ); + if ( sigProd.v64 < UINT64_C( 0x2000000000000000 ) ) { + --expProd; + sigProd = softfloat_shortShift128Left( sigProd.v64, sigProd.v0, 1 ); + } + signZ = signProd; + if ( ! expC ) { + if ( ! sigC ) { + expZ = expProd - 1; + sigZ = sigProd.v64<<1 | ( sigProd.v0 != 0 ); + goto roundPack; + } + normExpSig = softfloat_normSubnormalF64Sig( sigC ); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = ( sigC | UINT64_C( 0x0010000000000000 ) )<<9; + expDiff = expProd - expC; + if ( signProd == signC ) { + if ( expDiff <= 0 ) { + expZ = expC; + if ( expDiff ) { + sigProd.v64 = + softfloat_shift64RightJam( sigProd.v64, - expDiff ); + } + sigZ = ( sigC + sigProd.v64 ) | ( sigProd.v0 != 0 ); + } else { + expZ = expProd; + sigC128 = softfloat_shift128RightJam( sigC, 0, expDiff ); + sigZ128 = + softfloat_add128( + sigProd.v64, sigProd.v0, sigC128.v64, sigC128.v0 ); + sigZ = sigZ128.v64 | ( sigZ128.v0 != 0 ); + } + if ( sigZ < UINT64_C( 0x4000000000000000 ) ) { + --expZ; + sigZ <<= 1; + } + } else { +/*** OPTIMIZE BETTER? ***/ + if ( expDiff < 0 ) { + signZ = signC; + expZ = expC; + sigProd = + softfloat_shift128RightJam( + sigProd.v64, sigProd.v0, - expDiff ); + sigZ128 = softfloat_sub128( sigC, 0, sigProd.v64, sigProd.v0 ); + } else if ( ! expDiff ) { + expZ = expProd; + sigZ128 = softfloat_sub128( sigProd.v64, sigProd.v0, sigC, 0 ); + if ( ! ( sigZ128.v64 | sigZ128.v0 ) ) goto completeCancellation; + if ( sigZ128.v64 & UINT64_C( 0x8000000000000000 ) ) { + signZ ^= 1; + sigZ128 = softfloat_sub128( 0, 0, sigZ128.v64, sigZ128.v0 ); + } + } else { + expZ = expProd; + sigC128 = softfloat_shift128RightJam( sigC, 0, expDiff ); + sigZ128 = + softfloat_sub128( + sigProd.v64, sigProd.v0, sigC128.v64, sigC128.v0 ); + } + if ( ! sigZ128.v64 ) { + expZ -= 64; + sigZ128.v64 = sigZ128.v0; + sigZ128.v0 = 0; + } + shiftCount = softfloat_countLeadingZeros64( sigZ128.v64 ) - 1; + expZ -= shiftCount; + if ( shiftCount < 0 ) { + sigZ = softfloat_shortShift64RightJam( sigZ128.v64, - shiftCount ); + } else { + sigZ128 = + softfloat_shortShift128Left( + sigZ128.v64, sigZ128.v0, shiftCount ); + sigZ = sigZ128.v64; + } + sigZ |= ( sigZ128.v0 != 0 ); + } + roundPack: + return softfloat_roundPackToF64( signZ, expZ, sigZ ); + propagateNaN_ABC: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + goto propagateNaN_ZC; + infProdArg: + if ( magBits ) { + uiZ = packToF64UI( signProd, 0x7FF, 0 ); + if ( expC != 0x7FF ) goto uiZ; + if ( sigC ) goto propagateNaN_ZC; + if ( signProd == signC ) goto uiZ; + } + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + propagateNaN_ZC: + uiZ = softfloat_propagateNaNF64UI( uiZ, uiC ); + goto uiZ; + zeroProd: + uiZ = uiC; + if ( ! ( expC | sigC ) && ( signProd != signC ) ) { + completeCancellation: + uiZ = + packToF64UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); + } + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/s_normRoundPackToF32.cc b/softfloat/s_normRoundPackToF32.cc new file mode 100755 index 0000000..2e6f4b0 --- /dev/null +++ b/softfloat/s_normRoundPackToF32.cc @@ -0,0 +1,24 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" + +float32_t + softfloat_normRoundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig ) +{ + int shiftCount; + union ui32_f32 uZ; + + shiftCount = softfloat_countLeadingZeros32( sig ) - 1; + exp -= shiftCount; + if ( ( 7 <= shiftCount ) && ( (uint16_t) exp < 0xFD ) ) { + uZ.ui = packToF32UI( sign, sig ? exp : 0, sig<<( shiftCount - 7 ) ); + return uZ.f; + } else { + return softfloat_roundPackToF32( sign, exp, sig< +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" + +float64_t + softfloat_normRoundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig ) +{ + int shiftCount; + union ui64_f64 uZ; + + shiftCount = softfloat_countLeadingZeros64( sig ) - 1; + exp -= shiftCount; + if ( ( 10 <= shiftCount ) && ( (uint16_t) exp < 0x7FD ) ) { + uZ.ui = packToF64UI( sign, sig ? exp : 0, sig<<( shiftCount - 10 ) ); + return uZ.f; + } else { + return softfloat_roundPackToF64( sign, exp, sig< +#include "platform.h" +#include "primitives.h" +#include "internals.h" + +struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t sig ) +{ + int shiftCount; + struct exp16_sig32 z; + + shiftCount = softfloat_countLeadingZeros32( sig ) - 8; + z.exp = 1 - shiftCount; + z.sig = sig< +#include "platform.h" +#include "primitives.h" +#include "internals.h" + +struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t sig ) +{ + int shiftCount; + struct exp16_sig64 z; + + shiftCount = softfloat_countLeadingZeros64( sig ) - 11; + z.exp = 1 - shiftCount; + z.sig = sig< +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +float32_t + softfloat_roundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig ) +{ + int roundingMode; + bool roundNearestEven; + int roundIncrement, roundBits; + bool isTiny; + uint_fast32_t uiZ; + union ui32_f32 uZ; + + roundingMode = softfloat_roundingMode; + roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); + roundIncrement = 0x40; + if ( + ! roundNearestEven + && ( roundingMode != softfloat_round_nearest_maxMag ) + ) { + roundIncrement = + ( roundingMode == softfloat_round_minMag ) + || ( roundingMode + == ( sign ? softfloat_round_max : softfloat_round_min ) ) + ? 0 + : 0x7F; + } + roundBits = sig & 0x7F; + if ( 0xFD <= (uint16_t) exp ) { + if ( exp < 0 ) { + isTiny = + ( softfloat_detectTininess + == softfloat_tininess_beforeRounding ) + || ( exp < -1 ) + || ( sig + roundIncrement < 0x80000000 ); + sig = softfloat_shift32RightJam( 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; + } + } + if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; + sig = ( sig + roundIncrement )>>7; + sig &= ~ ( ! ( roundBits ^ 0x40 ) & roundNearestEven ); + uiZ = packToF32UI( sign, sig ? exp : 0, sig ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/s_roundPackToF64.cc b/softfloat/s_roundPackToF64.cc new file mode 100755 index 0000000..fb0ef1d --- /dev/null +++ b/softfloat/s_roundPackToF64.cc @@ -0,0 +1,66 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +float64_t + softfloat_roundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig ) +{ + int roundingMode; + bool roundNearestEven; + int roundIncrement, roundBits; + bool isTiny; + uint_fast64_t uiZ; + union ui64_f64 uZ; + + roundingMode = softfloat_roundingMode; + roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); + roundIncrement = 0x200; + if ( + ! roundNearestEven + && ( roundingMode != softfloat_round_nearest_maxMag ) + ) { + roundIncrement = + ( roundingMode == softfloat_round_minMag ) + || ( roundingMode + == ( sign ? softfloat_round_max : softfloat_round_min ) ) + ? 0 + : 0x3FF; + } + 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_shift64RightJam( 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; + } + } + if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; + sig = ( sig + roundIncrement )>>10; + sig &= ~ ( ! ( roundBits ^ 0x200 ) & roundNearestEven ); + uiZ = packToF64UI( sign, sig ? exp : 0, sig ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/s_roundPackToI32.cc b/softfloat/s_roundPackToI32.cc new file mode 100755 index 0000000..1c91497 --- /dev/null +++ b/softfloat/s_roundPackToI32.cc @@ -0,0 +1,48 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast32_t + softfloat_roundPackToI32( + bool sign, uint_fast64_t sig, int_fast8_t roundingMode, bool exact ) +{ + bool roundNearestEven; + int roundIncrement, roundBits; + uint_fast32_t sig32; + union { uint32_t ui; int32_t i; } uZ; + int_fast32_t z; + + roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); + roundIncrement = 0x40; + if ( + ! roundNearestEven + && ( roundingMode != softfloat_round_nearest_maxMag ) + ) { + roundIncrement = + ( roundingMode == softfloat_round_minMag ) + || ( roundingMode + == ( sign ? softfloat_round_max : softfloat_round_min ) ) + ? 0 + : 0x7F; + } + roundBits = sig & 0x7F; + sig += roundIncrement; + if ( sig & UINT64_C( 0xFFFFFF8000000000 ) ) goto invalid; + sig32 = sig>>7; + sig32 &= ~ ( ! ( roundBits ^ 0x40 ) & roundNearestEven ); + uZ.ui = sign ? - sig32 : sig32; + z = uZ.i; + if ( z && ( ( z < 0 ) ^ sign ) ) goto invalid; + if ( exact && roundBits ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return z; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return sign ? -0x7FFFFFFF - 1 : 0x7FFFFFFF; + +} + diff --git a/softfloat/s_roundPackToI64.cc b/softfloat/s_roundPackToI64.cc new file mode 100755 index 0000000..b2f5d63 --- /dev/null +++ b/softfloat/s_roundPackToI64.cc @@ -0,0 +1,52 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t + softfloat_roundPackToI64( + bool sign, + uint_fast64_t sig64, + uint_fast64_t sig0, + int_fast8_t roundingMode, + bool exact + ) +{ + bool roundNearestEven, increment; + union { uint64_t ui; int64_t i; } uZ; + int_fast64_t z; + + roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); + increment = ( UINT64_C( 0x8000000000000000 ) <= sig0 ); + if ( + ! roundNearestEven + && ( roundingMode != softfloat_round_nearest_maxMag ) + ) { + increment = + ( roundingMode != softfloat_round_minMag ) + && ( roundingMode + == ( sign ? softfloat_round_min : softfloat_round_max ) ) + && sig0; + } + if ( increment ) { + ++sig64; + if ( ! sig64 ) goto invalid; + sig64 &= + ~ ( ! ( sig0 & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) + & roundNearestEven ); + } + uZ.ui = sign ? - sig64 : sig64; + z = uZ.i; + if ( z && ( ( z < 0 ) ^ sign ) ) goto invalid; + if ( exact && sig0 ) softfloat_exceptionFlags |= softfloat_flag_inexact; + return z; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return + sign ? - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1 + : INT64_C( 0x7FFFFFFFFFFFFFFF ); + +} + diff --git a/softfloat/s_roundPackToUI32.cc b/softfloat/s_roundPackToUI32.cc new file mode 100755 index 0000000..ab44ec7 --- /dev/null +++ b/softfloat/s_roundPackToUI32.cc @@ -0,0 +1,44 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast32_t + softfloat_roundPackToUI32( + bool sign, uint_fast64_t sig, int_fast8_t roundingMode, bool exact ) +{ + bool roundNearestEven; + int roundIncrement, roundBits; + uint_fast32_t z; + + roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); + roundIncrement = 0x40; + if ( + ! roundNearestEven + && ( roundingMode != softfloat_round_nearest_maxMag ) + ) { + roundIncrement = + ( roundingMode == softfloat_round_minMag ) + || ( roundingMode + == ( sign ? softfloat_round_max : softfloat_round_min ) ) + ? 0 + : 0x7F; + } + roundBits = sig & 0x7F; + sig += roundIncrement; + if ( sig & UINT64_C( 0xFFFFFF8000000000 ) ) goto invalid; + z = sig>>7; + z &= ~ ( ! ( roundBits ^ 0x40 ) & roundNearestEven ); + if ( sign && z ) goto invalid; + if ( exact && roundBits ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return z; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return 0xFFFFFFFF; + +} + diff --git a/softfloat/s_roundPackToUI64.cc b/softfloat/s_roundPackToUI64.cc new file mode 100755 index 0000000..d42266f --- /dev/null +++ b/softfloat/s_roundPackToUI64.cc @@ -0,0 +1,46 @@ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast64_t + softfloat_roundPackToUI64( + bool sign, + uint_fast64_t sig64, + uint_fast64_t sig0, + int_fast8_t roundingMode, + bool exact + ) +{ + bool roundNearestEven, increment; + + roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); + increment = ( UINT64_C( 0x8000000000000000 ) <= sig0 ); + if ( + ! roundNearestEven + && ( roundingMode != softfloat_round_nearest_maxMag ) + ) { + increment = + ( roundingMode != softfloat_round_minMag ) + && ( roundingMode + == ( sign ? softfloat_round_min : softfloat_round_max ) ) + && sig0; + } + if ( increment ) { + ++sig64; + if ( ! sig64 ) goto invalid; + sig64 &= + ~ ( ! ( sig0 & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) + & roundNearestEven ); + } + if ( sign && sig64 ) goto invalid; + if ( exact && sig0 ) softfloat_exceptionFlags |= softfloat_flag_inexact; + return sig64; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + +} + diff --git a/softfloat/s_shift128ExtraRightJam.cc b/softfloat/s_shift128ExtraRightJam.cc new file mode 100755 index 0000000..6c57974 --- /dev/null +++ b/softfloat/s_shift128ExtraRightJam.cc @@ -0,0 +1,38 @@ + +#include +#include "platform.h" +#include "primitives.h" + +struct uint128_extra + softfloat_shift128ExtraRightJam( + uint64_t a64, uint64_t a0, uint64_t extra, unsigned int count ) +{ + unsigned int negCount; + struct uint128_extra z; + + negCount = - count; + if ( count < 64 ) { + z.v64 = a64>>count; + z.v0 = a64<<( negCount & 63 ) | a0>>count; + z.extra = a0<<( negCount & 63 ); + } else { + z.v64 = 0; + if ( count == 64 ) { + z.v0 = a64; + z.extra = a0; + } else { + extra |= a0; + if ( count < 128 ) { + z.v0 = a64>>( count & 63 ); + z.extra = a64<<( negCount & 63 ); + } else { + z.v0 = 0; + z.extra = ( count == 128 ) ? a64 : ( a64 != 0 ); + } + } + } + z.extra |= ( extra != 0 ); + return z; + +} + diff --git a/softfloat/s_shift128RightJam.cc b/softfloat/s_shift128RightJam.cc new file mode 100755 index 0000000..5a4e188 --- /dev/null +++ b/softfloat/s_shift128RightJam.cc @@ -0,0 +1,31 @@ + +#include +#include "platform.h" +#include "primitives.h" + +struct uint128 + softfloat_shift128RightJam( uint64_t a64, uint64_t a0, unsigned int count ) +{ + unsigned int negCount; + struct uint128 z; + + if ( count < 64 ) { + negCount = - count; + z.v64 = a64>>( count & 63 ); + z.v0 = + a64<<( negCount & 63 ) | a0>>count + | ( (uint64_t) ( a0<<( negCount & 63 ) ) != 0 ); + } else { + z.v64 = 0; + z.v0 = + ( count < 128 ) + ? a64>>( count & 63 ) + | ( ( ( a64 & ( ( (uint64_t) 1<<( count & 63 ) ) - 1 ) ) + | a0 ) + != 0 ) + : ( ( a64 | a0 ) != 0 ); + } + return z; + +} + diff --git a/softfloat/s_shift32RightJam.cc b/softfloat/s_shift32RightJam.cc new file mode 100755 index 0000000..b697a34 --- /dev/null +++ b/softfloat/s_shift32RightJam.cc @@ -0,0 +1,15 @@ + +#include +#include "platform.h" +#include "primitives.h" + +uint32_t softfloat_shift32RightJam( uint32_t a, unsigned int count ) +{ + + return + ( count < 32 ) + ? a>>count | ( (uint32_t) ( a<<( ( - count ) & 31 ) ) != 0 ) + : ( a != 0 ); + +} + diff --git a/softfloat/s_shift64ExtraRightJam.cc b/softfloat/s_shift64ExtraRightJam.cc new file mode 100755 index 0000000..167ea54 --- /dev/null +++ b/softfloat/s_shift64ExtraRightJam.cc @@ -0,0 +1,23 @@ + +#include +#include "platform.h" +#include "primitives.h" + +struct uint64_extra + softfloat_shift64ExtraRightJam( + uint64_t a, uint64_t extra, unsigned int count ) +{ + struct uint64_extra z; + + if ( count < 64 ) { + z.v = a>>count; + z.extra = a<<( ( - count ) & 63 ); + } else { + z.v = 0; + z.extra = ( count == 64 ) ? a : ( a != 0 ); + } + z.extra |= ( extra != 0 ); + return z; + +} + diff --git a/softfloat/s_shift64RightJam.cc b/softfloat/s_shift64RightJam.cc new file mode 100755 index 0000000..ebebb61 --- /dev/null +++ b/softfloat/s_shift64RightJam.cc @@ -0,0 +1,15 @@ + +#include +#include "platform.h" +#include "primitives.h" + +uint64_t softfloat_shift64RightJam( uint64_t a, unsigned int count ) +{ + + return + ( count < 64 ) + ? a>>count | ( (uint64_t) ( a<<( ( - count ) & 63 ) ) != 0 ) + : ( a != 0 ); + +} + diff --git a/softfloat/s_shortShift128ExtraRightJam.cc b/softfloat/s_shortShift128ExtraRightJam.cc new file mode 100755 index 0000000..c772740 --- /dev/null +++ b/softfloat/s_shortShift128ExtraRightJam.cc @@ -0,0 +1,20 @@ + +#include +#include "platform.h" +#include "primitives.h" + +struct uint128_extra + softfloat_shortShift128ExtraRightJam( + uint64_t a64, uint64_t a0, uint64_t extra, unsigned int count ) +{ + unsigned int negCount; + struct uint128_extra z; + + negCount = - count; + z.v64 = a64>>count; + z.v0 = a64<<( negCount & 63 ) | a0>>count; + z.extra = a0<<( negCount & 63 ) | ( extra != 0 ); + return z; + +} + diff --git a/softfloat/s_shortShift128Left.cc b/softfloat/s_shortShift128Left.cc new file mode 100755 index 0000000..9c29988 --- /dev/null +++ b/softfloat/s_shortShift128Left.cc @@ -0,0 +1,16 @@ + +#include +#include "platform.h" +#include "primitives.h" + +struct uint128 + softfloat_shortShift128Left( uint64_t a64, uint64_t a0, unsigned int count ) +{ + struct uint128 z; + + z.v64 = a64<>( ( - count ) & 63 ); + z.v0 = a0< +#include "platform.h" +#include "primitives.h" + +struct uint128 + softfloat_shortShift128Right( uint64_t a64, uint64_t a0, unsigned int count ) +{ + struct uint128 z; + + z.v64 = a64>>count; + z.v0 = a64<<( ( - count ) & 63 ) | a0>>count; + return z; + +} + diff --git a/softfloat/s_shortShift192Left.cc b/softfloat/s_shortShift192Left.cc new file mode 100755 index 0000000..cf1e55d --- /dev/null +++ b/softfloat/s_shortShift192Left.cc @@ -0,0 +1,20 @@ + +#include +#include "platform.h" +#include "primitives.h" + +struct uint192 + softfloat_shortShift192Left( + uint64_t a128, uint64_t a64, uint64_t a0, unsigned int count ) +{ + unsigned int negCount; + struct uint192 z; + + negCount = - count; + z.v128 = a128<>( negCount & 63 ); + z.v64 = a64<>( negCount & 63 ); + z.v0 = a0< +#include "platform.h" +#include "primitives.h" + +uint32_t softfloat_shortShift32Right1Jam( uint32_t a ) +{ + + return a>>1 | ( a & 1 ); + +} + diff --git a/softfloat/s_shortShift64ExtraRightJam.cc b/softfloat/s_shortShift64ExtraRightJam.cc new file mode 100755 index 0000000..b861c67 --- /dev/null +++ b/softfloat/s_shortShift64ExtraRightJam.cc @@ -0,0 +1,17 @@ + +#include +#include "platform.h" +#include "primitives.h" + +struct uint64_extra + softfloat_shortShift64ExtraRightJam( + uint64_t a, uint64_t extra, unsigned int count ) +{ + struct uint64_extra z; + + z.v = a>>count; + z.extra = a<<( ( - count ) & 63 ) | ( extra != 0 ); + return z; + +} + diff --git a/softfloat/s_shortShift64RightJam.cc b/softfloat/s_shortShift64RightJam.cc new file mode 100755 index 0000000..0da6c93 --- /dev/null +++ b/softfloat/s_shortShift64RightJam.cc @@ -0,0 +1,12 @@ + +#include +#include "platform.h" +#include "primitives.h" + +uint64_t softfloat_shortShift64RightJam( uint64_t a, unsigned int count ) +{ + + return a>>count | ( ( a & ( ( (uint64_t) 1< +#include "platform.h" +#include "primitives.h" + +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; + +} + diff --git a/softfloat/s_sub192.cc b/softfloat/s_sub192.cc new file mode 100755 index 0000000..96f21c9 --- /dev/null +++ b/softfloat/s_sub192.cc @@ -0,0 +1,30 @@ + +#include +#include "platform.h" +#include "primitives.h" + +struct uint192 + softfloat_sub192( + uint64_t a128, + uint64_t a64, + uint64_t a0, + uint64_t b128, + uint64_t b64, + uint64_t b0 + ) +{ + struct uint192 z; + unsigned int borrow64, borrow128; + + z.v0 = a0 - b0; + borrow64 = ( a0 < b0 ); + z.v64 = a64 - b64; + borrow128 = ( a64 < b64 ); + z.v128 = a128 - b128; + borrow128 += ( z.v64 < borrow64 ); + z.v64 -= borrow64; + z.v128 -= borrow128; + return z; + +} + diff --git a/softfloat/s_subMagsF32.cc b/softfloat/s_subMagsF32.cc new file mode 100755 index 0000000..0c83b02 --- /dev/null +++ b/softfloat/s_subMagsF32.cc @@ -0,0 +1,81 @@ + +#include +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t + softfloat_subMagsF32( uint_fast32_t uiA, uint_fast32_t uiB, bool signZ ) +{ + int_fast16_t expA; + uint_fast32_t sigA; + int_fast16_t expB; + uint_fast32_t sigB; + int_fast16_t expDiff; + uint_fast32_t uiZ; + int_fast16_t expZ; + uint_fast32_t sigZ; + union ui32_f32 uZ; + + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + expB = expF32UI( uiB ); + sigB = fracF32UI( uiB ); + expDiff = expA - expB; + sigA <<= 7; + sigB <<= 7; + if ( 0 < expDiff ) goto expABigger; + if ( expDiff < 0 ) goto expBBigger; + if ( expA == 0xFF ) { + if ( sigA | sigB ) goto propagateNaN; + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF32UI; + goto uiZ; + } + if ( ! expA ) { + expA = 1; + expB = 1; + } + if ( sigB < sigA ) goto aBigger; + if ( sigA < sigB ) goto bBigger; + uiZ = packToF32UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); + goto uiZ; + expBBigger: + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN; + uiZ = packToF32UI( signZ ^ 1, 0xFF, 0 ); + goto uiZ; + } + sigA += expA ? 0x40000000 : sigA; + sigA = softfloat_shift32RightJam( sigA, - expDiff ); + sigB |= 0x40000000; + bBigger: + signZ ^= 1; + expZ = expB; + sigZ = sigB - sigA; + goto normRoundPack; + expABigger: + if ( expA == 0xFF ) { + if ( sigA ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + sigB += expB ? 0x40000000 : sigB; + sigB = softfloat_shift32RightJam( sigB, expDiff ); + sigA |= 0x40000000; + aBigger: + expZ = expA; + sigZ = sigA - sigB; + normRoundPack: + return softfloat_normRoundPackToF32( signZ, expZ - 1, sigZ ); + propagateNaN: + uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/s_subMagsF64.cc b/softfloat/s_subMagsF64.cc new file mode 100755 index 0000000..45b81ba --- /dev/null +++ b/softfloat/s_subMagsF64.cc @@ -0,0 +1,81 @@ + +#include +#include +#include "platform.h" +#include "primitives.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_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; + sigA <<= 10; + sigB <<= 10; + if ( 0 < expDiff ) goto expABigger; + if ( expDiff < 0 ) goto expBBigger; + if ( expA == 0x7FF ) { + if ( sigA | sigB ) goto propagateNaN; + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + goto uiZ; + } + if ( ! expA ) { + expA = 1; + expB = 1; + } + if ( sigB < sigA ) goto aBigger; + if ( sigA < sigB ) goto bBigger; + uiZ = packToF64UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); + goto uiZ; + expBBigger: + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + uiZ = packToF64UI( signZ ^ 1, 0x7FF, 0 ); + goto uiZ; + } + sigA += expA ? UINT64_C( 0x4000000000000000 ) : sigA; + sigA = softfloat_shift64RightJam( sigA, - expDiff ); + sigB |= UINT64_C( 0x4000000000000000 ); + bBigger: + signZ ^= 1; + expZ = expB; + sigZ = sigB - sigA; + goto normRoundPack; + expABigger: + if ( expA == 0x7FF ) { + if ( sigA ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + sigB += expB ? UINT64_C( 0x4000000000000000 ) : sigB; + sigB = softfloat_shift64RightJam( sigB, expDiff ); + sigA |= UINT64_C( 0x4000000000000000 ); + aBigger: + expZ = expA; + sigZ = sigA - sigB; + normRoundPack: + return softfloat_normRoundPackToF64( signZ, expZ - 1, sigZ ); + propagateNaN: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/softfloat/softfloat-header b/softfloat/softfloat-header deleted file mode 100644 index eb5303a..0000000 --- a/softfloat/softfloat-header +++ /dev/null @@ -1,259 +0,0 @@ - -/*============================================================================ - -This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| The macro `FLOATX80' must be defined to enable the extended double-precision -| floating-point format `floatx80'. If this macro is not defined, the -| `floatx80' type will not be defined, and none of the functions that either -| input or output the `floatx80' type will be defined. The same applies to -| the `FLOAT128' macro and the quadruple-precision format `float128'. -*----------------------------------------------------------------------------*/ -#define FLOATX80 -#define FLOAT128 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ -typedef unsigned int float32; -typedef unsigned long long float64; -#ifdef FLOATX80 -typedef struct { - unsigned short high; - unsigned long long low; -} floatx80; -#endif -#ifdef FLOAT128 -typedef struct { - unsigned long long high, low; -} float128; -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point underflow tininess-detection mode. -*----------------------------------------------------------------------------*/ -extern int float_detect_tininess; -enum { - float_tininess_after_rounding = 0, - float_tininess_before_rounding = 1 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -extern int float_rounding_mode; -enum { - float_round_nearest_even = 0, - float_round_to_zero = 1, - float_round_up = 2, - float_round_down = 3 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ -extern int float_exception_flags; -enum { - float_flag_inexact = 1, - float_flag_divbyzero = 2, - float_flag_underflow = 4, - float_flag_overflow = 8, - float_flag_invalid = 16 -}; - -/*---------------------------------------------------------------------------- -| Routine to raise any or all of the software IEC/IEEE floating-point -| exception flags. -*----------------------------------------------------------------------------*/ -void float_raise( int ); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -float32 int32_to_float32( int ); -float64 int32_to_float64( int ); -#ifdef FLOATX80 -floatx80 int32_to_floatx80( int ); -#endif -#ifdef FLOAT128 -float128 int32_to_float128( int ); -#endif -float32 int64_to_float32( long long ); -float64 int64_to_float64( long long ); -#ifdef FLOATX80 -floatx80 int64_to_floatx80( long long ); -#endif -#ifdef FLOAT128 -float128 int64_to_float128( long long ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision conversion routines. -*----------------------------------------------------------------------------*/ -int float32_to_int32( float32 ); -int float32_to_int32_round_to_zero( float32 ); -long long float32_to_int64( float32 ); -long long float32_to_int64_round_to_zero( float32 ); -float64 float32_to_float64( float32 ); -#ifdef FLOATX80 -floatx80 float32_to_floatx80( float32 ); -#endif -#ifdef FLOAT128 -float128 float32_to_float128( float32 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision operations. -*----------------------------------------------------------------------------*/ -float32 float32_round_to_int( float32 ); -float32 float32_add( float32, float32 ); -float32 float32_sub( float32, float32 ); -float32 float32_mul( float32, float32 ); -float32 float32_div( float32, float32 ); -float32 float32_rem( float32, float32 ); -float32 float32_sqrt( float32 ); -int float32_eq( float32, float32 ); -int float32_le( float32, float32 ); -int float32_lt( float32, float32 ); -int float32_eq_signaling( float32, float32 ); -int float32_le_quiet( float32, float32 ); -int float32_lt_quiet( float32, float32 ); -int float32_is_signaling_nan( float32 ); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int float64_to_int32( float64 ); -int float64_to_int32_round_to_zero( float64 ); -long long float64_to_int64( float64 ); -long long float64_to_int64_round_to_zero( float64 ); -float32 float64_to_float32( float64 ); -#ifdef FLOATX80 -floatx80 float64_to_floatx80( float64 ); -#endif -#ifdef FLOAT128 -float128 float64_to_float128( float64 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision operations. -*----------------------------------------------------------------------------*/ -float64 float64_round_to_int( float64 ); -float64 float64_add( float64, float64 ); -float64 float64_sub( float64, float64 ); -float64 float64_mul( float64, float64 ); -float64 float64_div( float64, float64 ); -float64 float64_rem( float64, float64 ); -float64 float64_sqrt( float64 ); -int float64_eq( float64, float64 ); -int float64_le( float64, float64 ); -int float64_lt( float64, float64 ); -int float64_eq_signaling( float64, float64 ); -int float64_le_quiet( float64, float64 ); -int float64_lt_quiet( float64, float64 ); -int float64_is_signaling_nan( float64 ); - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int floatx80_to_int32( floatx80 ); -int floatx80_to_int32_round_to_zero( floatx80 ); -long long floatx80_to_int64( floatx80 ); -long long floatx80_to_int64_round_to_zero( floatx80 ); -float32 floatx80_to_float32( floatx80 ); -float64 floatx80_to_float64( floatx80 ); -#ifdef FLOAT128 -float128 floatx80_to_float128( floatx80 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision rounding precision. Valid -| values are 32, 64, and 80. -*----------------------------------------------------------------------------*/ -extern int floatx80_rounding_precision; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_round_to_int( floatx80 ); -floatx80 floatx80_add( floatx80, floatx80 ); -floatx80 floatx80_sub( floatx80, floatx80 ); -floatx80 floatx80_mul( floatx80, floatx80 ); -floatx80 floatx80_div( floatx80, floatx80 ); -floatx80 floatx80_rem( floatx80, floatx80 ); -floatx80 floatx80_sqrt( floatx80 ); -int floatx80_eq( floatx80, floatx80 ); -int floatx80_le( floatx80, floatx80 ); -int floatx80_lt( floatx80, floatx80 ); -int floatx80_eq_signaling( floatx80, floatx80 ); -int floatx80_le_quiet( floatx80, floatx80 ); -int floatx80_lt_quiet( floatx80, floatx80 ); -int floatx80_is_signaling_nan( floatx80 ); - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision conversion routines. -*----------------------------------------------------------------------------*/ -int float128_to_int32( float128 ); -int float128_to_int32_round_to_zero( float128 ); -long long float128_to_int64( float128 ); -long long float128_to_int64_round_to_zero( float128 ); -float32 float128_to_float32( float128 ); -float64 float128_to_float64( float128 ); -#ifdef FLOATX80 -floatx80 float128_to_floatx80( float128 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision operations. -*----------------------------------------------------------------------------*/ -float128 float128_round_to_int( float128 ); -float128 float128_add( float128, float128 ); -float128 float128_sub( float128, float128 ); -float128 float128_mul( float128, float128 ); -float128 float128_div( float128, float128 ); -float128 float128_rem( float128, float128 ); -float128 float128_sqrt( float128 ); -int float128_eq( float128, float128 ); -int float128_le( float128, float128 ); -int float128_lt( float128, float128 ); -int float128_eq_signaling( float128, float128 ); -int float128_le_quiet( float128, float128 ); -int float128_lt_quiet( float128, float128 ); -int float128_is_signaling_nan( float128 ); - -#endif - diff --git a/softfloat/softfloat-macros b/softfloat/softfloat-macros deleted file mode 100644 index d289328..0000000 --- a/softfloat/softfloat-macros +++ /dev/null @@ -1,720 +0,0 @@ - -/*============================================================================ - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 32, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr ) -{ - bits32 z; - - if ( count == 0 ) { - z = a; - } - else if ( count < 32 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - *zPtr = z; - -} - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 64, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr ) -{ - bits64 z; - - if ( count == 0 ) { - z = a; - } - else if ( count < 64 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - *zPtr = z; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 -| _plus_ the number of bits given in `count'. The shifted result is at most -| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The -| bits shifted off form a second 64-bit result as follows: The _last_ bit -| shifted off is the most-significant bit of the extra result, and the other -| 63 bits of the extra result are all zero if and only if _all_but_the_last_ -| bits shifted off were all zero. This extra result is stored in the location -| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. -| (This routine makes more sense if `a0' and `a1' are considered to form -| a fixed-point value with binary point between `a0' and `a1'. This fixed- -| point value is shifted right by the number of bits given in `count', and -| the integer part of the result is returned at the location pointed to by -| `z0Ptr'. The fractional part of the result may be slightly corrupted as -| described above, and is returned at the location pointed to by `z1Ptr'.) -*----------------------------------------------------------------------------*/ - -INLINE void - shift64ExtraRightJamming( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else { - z1 = ( ( a0 | a1 ) != 0 ); - } - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' can be arbitrarily large; in particular, if `count' is greater -| than 128, the result will be 0. The result is broken into two 64-bit pieces -| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - shift128Right( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ); - z0 = a0>>count; - } - else { - z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0; - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. If any nonzero bits are shifted off, they -| are ``jammed'' into the least significant bit of the result by setting the -| least significant bit to 1. The value of `count' can be arbitrarily large; -| in particular, if `count' is greater than 128, the result will be either -| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or -| nonzero. The result is broken into two 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - shift128RightJamming( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ) | ( ( a1<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else if ( count < 128 ) { - z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<>count ); - z0 = a0>>count; - } - else { - if ( count == 64 ) { - z2 = a1; - z1 = a0; - } - else { - a2 |= a1; - if ( count < 128 ) { - z2 = a0<>( count & 63 ); - } - else { - z2 = ( count == 128 ) ? a0 : ( a0 != 0 ); - z1 = 0; - } - } - z0 = 0; - } - z2 |= ( a2 != 0 ); - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' must be less than 64. The result is broken into two 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - shortShift128Left( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - - *z1Ptr = a1<>( ( - count ) & 63 ) ); - -} - -/*---------------------------------------------------------------------------- -| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left -| by the number of bits given in `count'. Any bits shifted off are lost. -| The value of `count' must be less than 64. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - shortShift192Left( - bits64 a0, - bits64 a1, - bits64 a2, - int16 count, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - int8 negCount; - - z2 = a2<>negCount; - z0 |= a1>>negCount; - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit -| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so -| any carry out is lost. The result is broken into two 64-bit pieces which -| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - add128( - bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z1; - - z1 = a1 + b1; - *z1Ptr = z1; - *z0Ptr = a0 + b0 + ( z1 < a1 ); - -} - -/*---------------------------------------------------------------------------- -| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the -| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is -| modulo 2^192, so any carry out is lost. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - add192( - bits64 a0, - bits64 a1, - bits64 a2, - bits64 b0, - bits64 b1, - bits64 b2, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - int8 carry0, carry1; - - z2 = a2 + b2; - carry1 = ( z2 < a2 ); - z1 = a1 + b1; - carry0 = ( z1 < a1 ); - z0 = a0 + b0; - z1 += carry1; - z0 += ( z1 < carry1 ); - z0 += carry0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the -| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo -| 2^128, so any borrow out (carry out) is lost. The result is broken into two -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and -| `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - sub128( - bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - - *z1Ptr = a1 - b1; - *z0Ptr = a0 - b0 - ( a1 < b1 ); - -} - -/*---------------------------------------------------------------------------- -| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' -| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. -| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The -| result is broken into three 64-bit pieces which are stored at the locations -| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - sub192( - bits64 a0, - bits64 a1, - bits64 a2, - bits64 b0, - bits64 b1, - bits64 b2, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - int8 borrow0, borrow1; - - z2 = a2 - b2; - borrow1 = ( a2 < b2 ); - z1 = a1 - b1; - borrow0 = ( a1 < b1 ); - z0 = a0 - b0; - z0 -= ( z1 < borrow1 ); - z1 -= borrow1; - z0 -= borrow0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken -| into two 64-bit pieces which are stored at the locations pointed to by -| `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits32 aHigh, aLow, bHigh, bLow; - bits64 z0, zMiddleA, zMiddleB, z1; - - aLow = a; - aHigh = a>>32; - bLow = b; - bHigh = b>>32; - z1 = ( (bits64) aLow ) * bLow; - zMiddleA = ( (bits64) aLow ) * bHigh; - zMiddleB = ( (bits64) aHigh ) * bLow; - z0 = ( (bits64) aHigh ) * bHigh; - zMiddleA += zMiddleB; - z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 ); - zMiddleA <<= 32; - z1 += zMiddleA; - z0 += ( z1 < zMiddleA ); - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by -| `b' to obtain a 192-bit product. The product is broken into three 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and -| `z2Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - mul128By64To192( - bits64 a0, - bits64 a1, - bits64 b, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2, more1; - - mul64To128( a1, b, &z1, &z2 ); - mul64To128( a0, b, &z0, &more1 ); - add128( z0, more1, 0, z1, &z0, &z1 ); - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the -| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit -| product. The product is broken into four 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - mul128To256( - bits64 a0, - bits64 a1, - bits64 b0, - bits64 b1, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr, - bits64 *z3Ptr - ) -{ - bits64 z0, z1, z2, z3; - bits64 more1, more2; - - mul64To128( a1, b1, &z2, &z3 ); - mul64To128( a1, b0, &z1, &more2 ); - add128( z1, more2, 0, z2, &z1, &z2 ); - mul64To128( a0, b0, &z0, &more1 ); - add128( z0, more1, 0, z1, &z0, &z1 ); - mul64To128( a0, b1, &more1, &more2 ); - add128( more1, more2, 0, z2, &more1, &z2 ); - add128( z0, z1, 0, more1, &z0, &z1 ); - *z3Ptr = z3; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the 64-bit integer quotient obtained by dividing -| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The -| divisor `b' must be at least 2^63. If q is the exact quotient truncated -| toward zero, the approximation returned lies between q and q + 2 inclusive. -| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit -| unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b ) -{ - bits64 b0, b1; - bits64 rem0, rem1, term0, term1; - bits64 z; - - if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF ); - b0 = b>>32; - z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32; - mul64To128( b, z, &term0, &term1 ); - sub128( a0, a1, term0, term1, &rem0, &rem1 ); - while ( ( (sbits64) rem0 ) < 0 ) { - z -= LIT64( 0x100000000 ); - b1 = b<<32; - add128( rem0, rem1, b0, b1, &rem0, &rem1 ); - } - rem0 = ( rem0<<32 ) | ( rem1>>32 ); - z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the square root of the 32-bit significand given -| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of -| `aExp' (the least significant bit) is 1, the integer returned approximates -| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' -| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either -| case, the approximation returned lies strictly within +/-2 of the exact -| value. -*----------------------------------------------------------------------------*/ - -static bits32 estimateSqrt32( int16 aExp, bits32 a ) -{ - static const bits16 sqrtOddAdjustments[] = { - 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, - 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 - }; - static const bits16 sqrtEvenAdjustments[] = { - 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, - 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 - }; - int8 index; - bits32 z; - - index = ( a>>27 ) & 15; - if ( aExp & 1 ) { - z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; - z = ( ( a / z )<<14 ) + ( z<<15 ); - a >>= 1; - } - else { - z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; - z = a / z + z; - z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 ); - if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 ); - } - return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 32 is returned. -*----------------------------------------------------------------------------*/ - -static int8 countLeadingZeros32( bits32 a ) -{ - static const int8 countLeadingZerosHigh[] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 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 - }; - int8 shiftCount; - - shiftCount = 0; - if ( a < 0x10000 ) { - shiftCount += 16; - a <<= 16; - } - if ( a < 0x1000000 ) { - shiftCount += 8; - a <<= 8; - } - shiftCount += countLeadingZerosHigh[ a>>24 ]; - return shiftCount; - -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 64 is returned. -*----------------------------------------------------------------------------*/ - -static int8 countLeadingZeros64( bits64 a ) -{ - int8 shiftCount; - - shiftCount = 0; - if ( a < ( (bits64) 1 )<<32 ) { - shiftCount += 32; - } - else { - a >>= 32; - } - shiftCount += countLeadingZeros32( a ); - return shiftCount; - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' -| is equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 == b0 ) && ( a1 == b1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, -| returns 0. -*----------------------------------------------------------------------------*/ - -INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is -| not equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 != b0 ) || ( a1 != b1 ); - -} - diff --git a/softfloat/softfloat-specialize b/softfloat/softfloat-specialize deleted file mode 100644 index 28bd4fe..0000000 --- a/softfloat/softfloat-specialize +++ /dev/null @@ -1,412 +0,0 @@ - -/*============================================================================ - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Underflow tininess-detection mode, statically initialized to default value. -| (The declaration in `softfloat.h' must match the `int8' type here.) -*----------------------------------------------------------------------------*/ -int8 float_detect_tininess = float_tininess_before_rounding; - -/*---------------------------------------------------------------------------- -| Raises the exceptions specified by `flags'. Floating-point traps can be -| defined here if desired. It is currently not possible for such a trap -| to substitute a result value. If traps are not implemented, this routine -| should be simply `float_exception_flags |= flags;'. -*----------------------------------------------------------------------------*/ - -void float_raise( int8 flags ) -{ - - float_exception_flags |= flags; - -} - -/*---------------------------------------------------------------------------- -| Internal canonical NaN format. -*----------------------------------------------------------------------------*/ -typedef struct { - flag sign; - bits64 high, low; -} commonNaNT; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -#define float32_default_nan 0x7FFFFFFF - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float32_is_nan( float32 a ) -{ - - return ( 0xFF000000 < (bits32) ( a<<1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float32_is_signaling_nan( float32 a ) -{ - - return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float32ToCommonNaN( float32 a ) -{ - commonNaNT z; - - if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a>>31; - z.low = 0; - z.high = ( (bits64) a )<<41; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the single- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float32 commonNaNToFloat32( commonNaNT a ) -{ - - return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); - -} - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float32 propagateFloat32NaN( float32 a, float32 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float32_is_nan( a ); - aIsSignalingNaN = float32_is_signaling_nan( a ); - bIsNaN = float32_is_nan( b ); - bIsSignalingNaN = float32_is_signaling_nan( b ); - a |= 0x00400000; - b |= 0x00400000; - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - return bIsSignalingNaN ? b : aIsSignalingNaN ? a : bIsNaN ? b : a; - -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -#define float64_default_nan LIT64( 0x7FFFFFFFFFFFFFFF ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float64_is_nan( float64 a ) -{ - - return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float64_is_signaling_nan( float64 a ) -{ - - return - ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) - && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float64ToCommonNaN( float64 a ) -{ - commonNaNT z; - - if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a>>63; - z.low = 0; - z.high = a<<12; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float64 commonNaNToFloat64( commonNaNT a ) -{ - - return - ( ( (bits64) a.sign )<<63 ) - | LIT64( 0x7FF8000000000000 ) - | ( a.high>>12 ); - -} - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float64 propagateFloat64NaN( float64 a, float64 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float64_is_nan( a ); - aIsSignalingNaN = float64_is_signaling_nan( a ); - bIsNaN = float64_is_nan( b ); - bIsSignalingNaN = float64_is_signaling_nan( b ); - a |= LIT64( 0x0008000000000000 ); - b |= LIT64( 0x0008000000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - return bIsSignalingNaN ? b : aIsSignalingNaN ? a : bIsNaN ? b : a; - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. The -| `high' and `low' values hold the most- and least-significant bits, -| respectively. -*----------------------------------------------------------------------------*/ -#define floatx80_default_nan_high 0x7FFF -#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag floatx80_is_nan( floatx80 a ) -{ - - return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag floatx80_is_signaling_nan( floatx80 a ) -{ - bits64 aLow; - - aLow = a.low & ~ LIT64( 0x4000000000000000 ); - return - ( ( a.high & 0x7FFF ) == 0x7FFF ) - && (bits64) ( aLow<<1 ) - && ( a.low == aLow ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the -| invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT floatx80ToCommonNaN( floatx80 a ) -{ - commonNaNT z; - - if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>15; - z.low = 0; - z.high = a.low<<1; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the extended -| double-precision floating-point format. -*----------------------------------------------------------------------------*/ - -static floatx80 commonNaNToFloatx80( commonNaNT a ) -{ - floatx80 z; - - z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); - z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two extended double-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = floatx80_is_nan( a ); - aIsSignalingNaN = floatx80_is_signaling_nan( a ); - bIsNaN = floatx80_is_nan( b ); - bIsSignalingNaN = floatx80_is_signaling_nan( b ); - a.low |= LIT64( 0xC000000000000000 ); - b.low |= LIT64( 0xC000000000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - return bIsSignalingNaN ? b : aIsSignalingNaN ? a : bIsNaN ? b : a; - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. The `high' and -| `low' values hold the most- and least-significant bits, respectively. -*----------------------------------------------------------------------------*/ -#define float128_default_nan_high LIT64( 0x7FFFFFFFFFFFFFFF ) -#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float128_is_nan( float128 a ) -{ - - return - ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) - && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float128_is_signaling_nan( float128 a ) -{ - - return - ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) - && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float128ToCommonNaN( float128 a ) -{ - commonNaNT z; - - if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>63; - shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the quadruple- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float128 commonNaNToFloat128( commonNaNT a ) -{ - float128 z; - - shift128Right( a.high, a.low, 16, &z.high, &z.low ); - z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float128 propagateFloat128NaN( float128 a, float128 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float128_is_nan( a ); - aIsSignalingNaN = float128_is_signaling_nan( a ); - bIsNaN = float128_is_nan( b ); - bIsSignalingNaN = float128_is_signaling_nan( b ); - a.high |= LIT64( 0x0000800000000000 ); - b.high |= LIT64( 0x0000800000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - return bIsSignalingNaN ? b : aIsSignalingNaN ? a : bIsNaN ? b : a; - -} - -#endif - diff --git a/softfloat/softfloat.c b/softfloat/softfloat.c deleted file mode 100644 index 0d09b40..0000000 --- a/softfloat/softfloat.c +++ /dev/null @@ -1,5188 +0,0 @@ - -/*============================================================================ - -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -#include "milieu.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Floating-point rounding mode, extended double-precision rounding precision, -| and exception flags. -*----------------------------------------------------------------------------*/ -int8 float_rounding_mode = float_round_nearest_even; -int8 float_exception_flags = 0; -#ifdef FLOATX80 -int8 floatx80_rounding_precision = 80; -#endif - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target if -| desired.) -*----------------------------------------------------------------------------*/ -#include "softfloat-macros" - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize" - -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the largest -| positive or negative integer is returned. -*----------------------------------------------------------------------------*/ - -static int32 roundAndPackInt32( flag zSign, bits64 absZ ) -{ - int8 roundingMode; - flag roundNearestEven; - int8 roundIncrement, roundBits; - int32 z; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - roundIncrement = 0x40; - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - roundIncrement = 0; - } - else { - roundIncrement = 0x7F; - if ( zSign ) { - if ( roundingMode == float_round_up ) roundIncrement = 0; - } - else { - if ( roundingMode == float_round_down ) roundIncrement = 0; - } - } - } - roundBits = absZ & 0x7F; - absZ = ( absZ + roundIncrement )>>7; - absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - z = absZ; - if ( zSign ) z = - z; - if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { - float_raise( float_flag_invalid ); - return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( roundBits ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit integer corresponding to the input. -| If `zSign' is 1, the input is negated before being converted to an integer. -| Ordinarily, the fixed-point input is simply rounded to an integer, with -| the inexact exception raised if the input cannot be represented exactly as -| an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest positive or negative integer is -| returned. -*----------------------------------------------------------------------------*/ - -static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 ) -{ - int8 roundingMode; - flag roundNearestEven, increment; - int64 z; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - increment = ( (sbits64) absZ1 < 0 ); - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - increment = 0; - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && absZ1; - } - else { - increment = ( roundingMode == float_round_up ) && absZ1; - } - } - } - if ( increment ) { - ++absZ0; - if ( absZ0 == 0 ) goto overflow; - absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven ); - } - z = absZ0; - if ( zSign ) z = - z; - if ( z && ( ( z < 0 ) ^ zSign ) ) { - overflow: - float_raise( float_flag_invalid ); - return - zSign ? (sbits64) LIT64( 0x8000000000000000 ) - : LIT64( 0x7FFFFFFFFFFFFFFF ); - } - if ( absZ1 ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE bits32 extractFloat32Frac( float32 a ) -{ - - return a & 0x007FFFFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE int16 extractFloat32Exp( float32 a ) -{ - - return ( a>>23 ) & 0xFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE flag extractFloat32Sign( float32 a ) -{ - - return a>>31; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal single-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros32( aSig ) - 8; - *zSigPtr = aSig<>7; - zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat32' except that `zSig' does not have to be normalized. -| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float32 - normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros32( zSig ) - 1; - return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<>52 ) & 0x7FF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE flag extractFloat64Sign( float64 a ) -{ - - return a>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal double-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( aSig ) - 11; - *zSigPtr = aSig<>10; - zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat64' except that `zSig' does not have to be normalized. -| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float64 - normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( zSig ) - 1; - return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<>15; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal extended double-precision floating-point value -| represented by the denormalized significand `aSig'. The normalized exponent -| and significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloatx80Subnormal( bits64 aSig, int32 *zExpPtr, bits64 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( aSig ); - *zSigPtr = aSig<>48 ) & 0x7FFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the quadruple-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE flag extractFloat128Sign( float128 a ) -{ - - return a.high>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat128Subnormal( - bits64 aSig0, - bits64 aSig1, - int32 *zExpPtr, - bits64 *zSig0Ptr, - bits64 *zSig1Ptr - ) -{ - int8 shiftCount; - - if ( aSig0 == 0 ) { - shiftCount = countLeadingZeros64( aSig1 ) - 15; - if ( shiftCount < 0 ) { - *zSig0Ptr = aSig1>>( - shiftCount ); - *zSig1Ptr = aSig1<<( shiftCount & 63 ); - } - else { - *zSig0Ptr = aSig1<>( - shiftCount ); - if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64( float32 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits32 aSig; - bits64 aSig64, aSigExtra; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = 0xBE - aExp; - if ( shiftCount < 0 ) { - float_raise( float_flag_invalid ); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - return (sbits64) LIT64( 0x8000000000000000 ); - } - if ( aExp ) aSig |= 0x00800000; - aSig64 = aSig; - aSig64 <<= 40; - shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra ); - return roundAndPackInt64( aSign, aSig64, aSigExtra ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64_round_to_zero( float32 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits32 aSig; - bits64 aSig64; - int64 z; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = aExp - 0xBE; - if ( 0 <= shiftCount ) { - if ( a != 0xDF000000 ) { - float_raise( float_flag_invalid ); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - } - return (sbits64) LIT64( 0x8000000000000000 ); - } - else if ( aExp <= 0x7E ) { - if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig64 = aSig | 0x00800000; - aSig64 <<= 40; - z = aSig64>>( - shiftCount ); - if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float32_to_float64( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) ); - return packFloat64( aSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float32_to_floatx80( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) ); - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - aSig |= 0x00800000; - return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float32_to_float128( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a ) ); - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the single-precision floating-point value `a' to an integer, and -| returns the result as a single-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_round_to_int( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 lastBitMask, roundBitsMask; - int8 roundingMode; - float32 z; - - aExp = extractFloat32Exp( a ); - if ( 0x96 <= aExp ) { - if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) { - return propagateFloat32NaN( a, a ); - } - return a; - } - if ( aExp <= 0x7E ) { - if ( (bits32) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat32Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { - return packFloat32( aSign, 0x7F, 0 ); - } - break; - case float_round_down: - return aSign ? 0xBF800000 : 0; - case float_round_up: - return aSign ? 0x80000000 : 0x3F800000; - } - return packFloat32( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x96 - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z += lastBitMask>>1; - if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z += roundBitsMask; - } - } - z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the single-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 6; - bSig <<= 6; - if ( 0 < expDiff ) { - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x20000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x20000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0xFF ) { - if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); - zSig = 0x40000000 + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= 0x20000000; - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (sbits32) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the single- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 7; - bSig <<= 7; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0xFF ) { - if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat32( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign ^ 1, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x40000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - bSig |= 0x40000000; - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x40000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - aSig |= 0x40000000; - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the single-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_add( float32 a, float32 b ) -{ - flag aSign, bSign; - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return addFloat32Sigs( a, b, aSign ); - } - else { - return subFloat32Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sub( float32 a, float32 b ) -{ - flag aSign, bSign; - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return subFloat32Sigs( a, b, aSign ); - } - else { - return addFloat32Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_mul( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits32 aSig, bSig; - bits64 zSig64; - bits32 zSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { - return propagateFloat32NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x7F; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 ); - zSig = zSig64; - if ( 0 <= (sbits32) ( zSig<<1 ) ) { - zSig <<= 1; - --zExp; - } - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the single-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_div( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - float_raise( float_flag_divbyzero ); - return packFloat32( zSign, 0xFF, 0 ); - } - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x7D; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = ( ( (bits64) aSig )<<32 ) / bSig; - if ( ( zSig & 0x3F ) == 0 ) { - zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 ); - } - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the single-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_rem( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, expDiff; - bits32 aSig, bSig; - bits32 q; - bits64 aSig64, bSig64, q64; - bits32 alternateASig; - sbits32 sigMean; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - if ( aExp == 0xFF ) { - if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { - return propagateFloat32NaN( a, b ); - } - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return a; - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - expDiff = aExp - bExp; - aSig |= 0x00800000; - bSig |= 0x00800000; - if ( expDiff < 32 ) { - aSig <<= 8; - bSig <<= 8; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - aSig >>= 1; - } - q = ( bSig <= aSig ); - if ( q ) aSig -= bSig; - if ( 0 < expDiff ) { - q = ( ( (bits64) aSig )<<32 ) / bSig; - q >>= 32 - expDiff; - bSig >>= 2; - aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; - } - else { - aSig >>= 2; - bSig >>= 2; - } - } - else { - if ( bSig <= aSig ) aSig -= bSig; - aSig64 = ( (bits64) aSig )<<40; - bSig64 = ( (bits64) bSig )<<40; - expDiff -= 64; - while ( 0 < expDiff ) { - q64 = estimateDiv128To64( aSig64, 0, bSig64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - aSig64 = - ( ( bSig * q64 )<<38 ); - expDiff -= 62; - } - expDiff += 64; - q64 = estimateDiv128To64( aSig64, 0, bSig64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - q = q64>>( 64 - expDiff ); - bSig <<= 6; - aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while ( 0 <= (sbits32) aSig ); - sigMean = aSig + alternateASig; - if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { - aSig = alternateASig; - } - zSign = ( (sbits32) aSig < 0 ); - if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the single-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sqrt( float32 a ) -{ - flag aSign; - int16 aExp, zExp; - bits32 aSig, zSig; - bits64 rem, term; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, 0 ); - if ( ! aSign ) return a; - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return 0; - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E; - aSig = ( aSig | 0x00800000 )<<8; - zSig = estimateSqrt32( aExp, aSig ) + 2; - if ( ( zSig & 0x7F ) <= 5 ) { - if ( zSig < 2 ) { - zSig = 0x7FFFFFFF; - goto roundAndPack; - } - aSig >>= aExp & 1; - term = ( (bits64) zSig ) * zSig; - rem = ( ( (bits64) aSig )<<32 ) - term; - while ( (sbits64) rem < 0 ) { - --zSig; - rem += ( ( (bits64) zSig )<<1 ) | 1; - } - zSig |= ( rem != 0 ); - } - shift32RightJamming( zSig, 1, &zSig ); - roundAndPack: - return roundAndPackFloat32( 0, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_eq( float32 a, float32 b ) -{ - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_le( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_lt( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_eq_signaling( float32 a, float32 b ) -{ - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_le_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; - int16 aExp, bExp; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_lt_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32( float64 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x42C - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32_round_to_zero( float64 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits64 aSig, savedASig; - int32 z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( 0x41E < aExp ) { - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FF ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x433 - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>( - shiftCount ); - if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the single-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float64_to_float32( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig; - bits32 zSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) ); - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 22, &aSig ); - zSig = aSig; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x381; - } - return roundAndPackFloat32( aSign, aExp, zSig ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float64_to_floatx80( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) ); - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - return - packFloatx80( - aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the quadruple-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float64_to_float128( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig, zSig0, zSig1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a ) ); - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - shift128Right( aSig, 0, 4, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the double-precision floating-point value `a' to an integer, and -| returns the result as a double-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_round_to_int( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - float64 z; - - aExp = extractFloat64Exp( a ); - if ( 0x433 <= aExp ) { - if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) { - return propagateFloat64NaN( a, a ); - } - return a; - } - if ( aExp < 0x3FF ) { - if ( (bits64) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat64Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { - return packFloat64( aSign, 0x3FF, 0 ); - } - break; - case float_round_down: - return aSign ? LIT64( 0xBFF0000000000000 ) : 0; - case float_round_up: - return - aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 ); - } - return packFloat64( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x433 - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z += lastBitMask>>1; - if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z += roundBitsMask; - } - } - z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the double-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 9; - bSig <<= 9; - if ( 0 < expDiff ) { - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0x7FF ) { - if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); - zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= LIT64( 0x2000000000000000 ); - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (sbits64) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 10; - bSig <<= 10; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FF ) { - if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat64( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign ^ 1, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - bSig |= LIT64( 0x4000000000000000 ); - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - aSig |= LIT64( 0x4000000000000000 ); - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the double-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_add( float64 a, float64 b ) -{ - flag aSign, bSign; - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return addFloat64Sigs( a, b, aSign ); - } - else { - return subFloat64Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sub( float64 a, float64 b ) -{ - flag aSign, bSign; - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return subFloat64Sigs( a, b, aSign ); - } - else { - return addFloat64Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_mul( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { - return propagateFloat64NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FF; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - zSig0 |= ( zSig1 != 0 ); - if ( 0 <= (sbits64) ( zSig0<<1 ) ) { - zSig0 <<= 1; - --zExp; - } - return roundAndPackFloat64( zSign, zExp, zSig0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the double-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_div( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - bits64 rem0, rem1; - bits64 term0, term1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - float_raise( float_flag_divbyzero ); - return packFloat64( zSign, 0x7FF, 0 ); - } - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FD; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = estimateDiv128To64( aSig, 0, bSig ); - if ( ( zSig & 0x1FF ) <= 2 ) { - mul64To128( bSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig |= ( rem1 != 0 ); - } - return roundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the double-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_rem( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, expDiff; - bits64 aSig, bSig; - bits64 q, alternateASig; - sbits64 sigMean; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - if ( aExp == 0x7FF ) { - if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { - return propagateFloat64NaN( a, b ); - } - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return a; - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - expDiff = aExp - bExp; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - aSig >>= 1; - } - q = ( bSig <= aSig ); - if ( q ) aSig -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig, 0, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - aSig = - ( ( bSig>>2 ) * q ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig, 0, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - bSig >>= 2; - aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; - } - else { - aSig >>= 2; - bSig >>= 2; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while ( 0 <= (sbits64) aSig ); - sigMean = aSig + alternateASig; - if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { - aSig = alternateASig; - } - zSign = ( (sbits64) aSig < 0 ); - if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the double-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sqrt( float64 a ) -{ - flag aSign; - int16 aExp, zExp; - bits64 aSig, zSig, doubleZSig; - bits64 rem0, rem1, term0, term1; - float64 z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, a ); - if ( ! aSign ) return a; - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return 0; - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE; - aSig |= LIT64( 0x0010000000000000 ); - zSig = estimateSqrt32( aExp, aSig>>21 ); - aSig <<= 9 - ( aExp & 1 ); - zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 ); - if ( ( zSig & 0x1FF ) <= 5 ) { - doubleZSig = zSig<<1; - mul64To128( zSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig; - doubleZSig -= 2; - add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 ); - } - zSig |= ( ( rem0 | rem1 ) != 0 ); - } - return roundAndPackFloat64( 0, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_eq( float64 a, float64 b ) -{ - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_le( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_lt( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. The invalid exception is raised -| if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_eq_signaling( float64 a, float64 b ) -{ - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_le_quiet( float64 a, float64 b ) -{ - flag aSign, bSign; - int16 aExp, bExp; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_lt_quiet( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic---which means in particular that the conversion -| is rounded according to the current rounding mode. If `a' is a NaN, the -| largest positive integer is returned. Otherwise, if the conversion -| overflows, the largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32( floatx80 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; - shiftCount = 0x4037 - aExp; - if ( shiftCount <= 0 ) shiftCount = 1; - shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic, except that the conversion is always rounded -| toward zero. If `a' is a NaN, the largest positive integer is returned. -| Otherwise, if the conversion overflows, the largest integer with the same -| sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32_round_to_zero( floatx80 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig, savedASig; - int32 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - shiftCount = 0x403E - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>( - shiftCount ); - if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the single-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 floatx80_to_float32( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat32( floatx80ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 33, &aSig ); - if ( aExp || aSig ) aExp -= 0x3F81; - return roundAndPackFloat32( aSign, aExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 floatx80_to_float64( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig, zSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat64( floatx80ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shift64RightJamming( aSig, 1, &zSig ); - if ( aExp || aSig ) aExp -= 0x3C01; - return roundAndPackFloat64( aSign, aExp, zSig ); - -} - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the quadruple-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 floatx80_to_float128( floatx80 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig, zSig0, zSig1; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat128( floatx80ToCommonNaN( a ) ); - } - shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp, zSig0, zSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the extended double-precision floating-point value `a' to an integer, -| and returns the result as an extended quadruple-precision floating-point -| value. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_round_to_int( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - floatx80 z; - - aExp = extractFloatx80Exp( a ); - if ( 0x403E <= aExp ) { - if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { - return propagateFloatx80NaN( a, a ); - } - return a; - } - if ( aExp < 0x3FFF ) { - if ( ( aExp == 0 ) - && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { - return a; - } - float_exception_flags |= float_flag_inexact; - aSign = extractFloatx80Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) - ) { - return - packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - break; - case float_round_down: - return - aSign ? - packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) ) - : packFloatx80( 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloatx80( 1, 0, 0 ) - : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - return packFloatx80( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x403E - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.low += lastBitMask>>1; - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z.low += roundBitsMask; - } - } - z.low &= ~ roundBitsMask; - if ( z.low == 0 ) { - ++z.high; - z.low = LIT64( 0x8000000000000000 ); - } - if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the extended double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is -| negated before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - return a; - } - zSig1 = 0; - zSig0 = aSig + bSig; - if ( aExp == 0 ) { - normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); - goto roundAndPack; - } - zExp = aExp; - goto shiftRight1; - } - zSig0 = aSig + bSig; - if ( (sbits64) zSig0 < 0 ) goto roundAndPack; - shiftRight1: - shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= LIT64( 0x8000000000000000 ); - ++zExp; - roundAndPack: - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the extended -| double-precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - zSig1 = 0; - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - bBigger: - sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - aBigger: - sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - return - normalizeRoundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the extended double-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_add( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return addFloatx80Sigs( a, b, aSign ); - } - else { - return subFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sub( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return subFloatx80Sigs( a, b, aSign ); - } - else { - return addFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_mul( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) goto invalid; - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FFE; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - if ( 0 < (sbits64) zSig0 ) { - shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); - --zExp; - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the extended double-precision floating-point -| value `a' by the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_div( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - bits64 rem0, rem1, rem2, term0, term1, term2; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - goto invalid; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FFE; - rem1 = 0; - if ( bSig <= aSig ) { - shift128Right( aSig, 0, 1, &aSig, &rem1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig, rem1, bSig ); - mul64To128( bSig, zSig0, &term0, &term1 ); - sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, bSig ); - if ( (bits64) ( zSig1<<1 ) <= 8 ) { - mul64To128( bSig, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); - } - zSig1 |= ( ( rem1 | rem2 ) != 0 ); - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the extended double-precision floating-point value -| `a' with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_rem( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig; - bits64 q, term0, term1, alternateASig0, alternateASig1; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( (bits64) ( aSig0<<1 ) == 0 ) return a; - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - bSig |= LIT64( 0x8000000000000000 ); - zSign = aSign; - expDiff = aExp - bExp; - aSig1 = 0; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); - expDiff = 0; - } - q = ( bSig <= aSig0 ); - if ( q ) aSig0 -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - mul64To128( bSig, q, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); - while ( le128( term0, term1, aSig0, aSig1 ) ) { - ++q; - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - } - } - else { - term1 = 0; - term0 = bSig; - } - sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); - if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) - || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) - && ( q & 1 ) ) - ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - zSign = ! zSign; - } - return - normalizeRoundAndPackFloatx80( - 80, zSign, bExp + expDiff, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sqrt( floatx80 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; - zSig0 = estimateSqrt32( aExp, aSig0>>32 ); - shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= doubleZSig0; - return - roundAndPackFloatx80( - floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq( floatx80 a, floatx80 b ) -{ - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than or equal to the corresponding value `b', and 0 otherwise. The -| comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is equal -| to the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq_signaling( floatx80 a, floatx80 b ) -{ - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs -| do not cause an exception. Otherwise, the comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause -| an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; - if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); - aSig0 |= ( aSig1 != 0 ); - shiftCount = 0x4028 - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 ); - return roundAndPackInt32( aSign, aSig0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32_round_to_zero( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1, savedASig; - int32 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - aSig0 |= ( aSig1 != 0 ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if ( aExp || aSig0 ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig0 |= LIT64( 0x0001000000000000 ); - shiftCount = 0x402F - aExp; - savedASig = aSig0; - aSig0 >>= shiftCount; - z = aSig0; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig0<>( ( - shiftCount ) & 63 ) ); - if ( (bits64) ( aSig1<>( - shiftCount ); - if ( aSig1 - || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) { - float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the single-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float128_to_float32( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - bits32 zSig; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat32( float128ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - aSig0 |= ( aSig1 != 0 ); - shift64RightJamming( aSig0, 18, &aSig0 ); - zSig = aSig0; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x3F81; - } - return roundAndPackFloat32( aSign, aExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float128_to_float64( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat64( float128ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - aSig0 |= ( aSig1 != 0 ); - if ( aExp || aSig0 ) { - aSig0 |= LIT64( 0x4000000000000000 ); - aExp -= 0x3C01; - } - return roundAndPackFloat64( aSign, aExp, aSig0 ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the extended double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float128_to_floatx80( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloatx80( float128ToCommonNaN( a ) ); - } - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); - return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the quadruple-precision floating-point value `a' to an integer, and -| returns the result as a quadruple-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_round_to_int( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - float128 z; - - aExp = extractFloat128Exp( a ); - if ( 0x402F <= aExp ) { - if ( 0x406F <= aExp ) { - if ( ( aExp == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) - ) { - return propagateFloat128NaN( a, a ); - } - return a; - } - lastBitMask = 1; - lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - if ( lastBitMask ) { - add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low ); - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else { - if ( (sbits64) z.low < 0 ) { - ++z.high; - if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1; - } - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low ); - } - } - z.low &= ~ roundBitsMask; - } - else { - if ( aExp < 0x3FFF ) { - if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat128Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) - && ( extractFloat128Frac0( a ) - | extractFloat128Frac1( a ) ) - ) { - return packFloat128( aSign, 0x3FFF, 0, 0 ); - } - break; - case float_round_down: - return - aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) - : packFloat128( 0, 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloat128( 1, 0, 0, 0 ) - : packFloat128( 0, 0x3FFF, 0, 0 ); - } - return packFloat128( aSign, 0, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x402F - aExp; - roundBitsMask = lastBitMask - 1; - z.low = 0; - z.high = a.high; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.high += lastBitMask>>1; - if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) { - z.high &= ~ lastBitMask; - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - z.high |= ( a.low != 0 ); - z.high += roundBitsMask; - } - } - z.high &= ~ roundBitsMask; - } - if ( ( z.low != a.low ) || ( z.high != a.high ) ) { - float_exception_flags |= float_flag_inexact; - } - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the quadruple-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 addFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - int32 expDiff; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - return a; - } - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); - zSig2 = 0; - zSig0 |= LIT64( 0x0002000000000000 ); - zExp = aExp; - goto shiftRight1; - } - aSig0 |= LIT64( 0x0001000000000000 ); - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - --zExp; - if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; - ++zExp; - shiftRight1: - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - roundAndPack: - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the quadruple- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 subFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; - int32 expDiff; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig0 < aSig0 ) goto aBigger; - if ( aSig0 < bSig0 ) goto bBigger; - if ( bSig1 < aSig1 ) goto aBigger; - if ( aSig1 < bSig1 ) goto bBigger; - return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - bSig0 |= LIT64( 0x4000000000000000 ); - bBigger: - sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); - aSig0 |= LIT64( 0x4000000000000000 ); - aBigger: - sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the quadruple-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_add( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return addFloat128Sigs( a, b, aSign ); - } - else { - return subFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sub( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return subFloat128Sigs( a, b, aSign ); - } - else { - return addFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_mul( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - zExp = aExp + bExp - 0x4000; - aSig0 |= LIT64( 0x0001000000000000 ); - shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); - mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); - add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zSig2 |= ( zSig3 != 0 ); - if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - ++zExp; - } - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the quadruple-precision floating-point value -| `a' by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_div( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - goto invalid; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0, 0, 0 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = aExp - bExp + 0x3FFD; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { - shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); - mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); - sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); - } - zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); - if ( ( zSig1 & 0x3FFF ) <= 4 ) { - mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); - sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the quadruple-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_rem( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2; - bits64 allZero, alternateASig0, alternateASig1, sigMean1; - sbits64 sigMean0; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return a; - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - expDiff = aExp - bExp; - if ( expDiff < -1 ) return a; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), - aSig1, - 15 - ( expDiff < 0 ), - &aSig0, - &aSig1 - ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - q = le128( bSig0, bSig1, aSig0, aSig1 ); - if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero ); - shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero ); - sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 ); - expDiff -= 61; - } - if ( -64 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - q >>= - expDiff; - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - expDiff += 52; - if ( expDiff < 0 ) { - shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - } - else { - shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 ); - } - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 ); - } - else { - shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 ); - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - } - do { - alternateASig0 = aSig0; - alternateASig1 = aSig1; - ++q; - sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - } while ( 0 <= (sbits64) aSig0 ); - add128( - aSig0, aSig1, alternateASig0, alternateASig1, (bits64*)&sigMean0, &sigMean1 ); - if ( ( sigMean0 < 0 ) - || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - } - zSign = ( (sbits64) aSig0 < 0 ); - if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 ); - return - normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the quadruple-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sqrt( float128 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE; - aSig0 |= LIT64( 0x0001000000000000 ); - zSig0 = estimateSqrt32( aExp, aSig0>>17 ); - shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & 0x1FFF ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq( float128 a, float128 b ) -{ - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq_signaling( float128 a, float128 b ) -{ - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif - diff --git a/softfloat/softfloat.cc b/softfloat/softfloat.cc deleted file mode 100644 index c44e828..0000000 --- a/softfloat/softfloat.cc +++ /dev/null @@ -1 +0,0 @@ -#include "softfloat.c" diff --git a/softfloat/softfloat.h b/softfloat/softfloat.h old mode 100644 new mode 100755 index fc3f9dc..a7ea248 --- a/softfloat/softfloat.h +++ b/softfloat/softfloat.h @@ -1,14 +1,225 @@ -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _SOFTFLOAT_H -#define _SOFTFLOAT_H - -#include "softfloat-header" - -#endif - -#ifdef __cplusplus -} -#endif + +#ifndef softfloat_h +#define softfloat_h + +/*** UPDATE COMMENTS. ***/ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +#include "softfloat_types.h" + +/*---------------------------------------------------------------------------- +| Software floating-point underflow tininess-detection mode. +*----------------------------------------------------------------------------*/ +extern int_fast8_t softfloat_detectTininess; +enum { + softfloat_tininess_beforeRounding = 0, + softfloat_tininess_afterRounding = 1 +}; + +/*---------------------------------------------------------------------------- +| Software floating-point rounding mode. +*----------------------------------------------------------------------------*/ +extern int_fast8_t softfloat_roundingMode; +enum { + softfloat_round_nearest_even = 0, + softfloat_round_minMag = 1, + softfloat_round_min = 2, + softfloat_round_max = 3, + softfloat_round_nearest_maxMag = 4 +}; + +/*---------------------------------------------------------------------------- +| Software floating-point exception flags. +*----------------------------------------------------------------------------*/ +extern int_fast8_t softfloat_exceptionFlags; +enum { + softfloat_flag_inexact = 1, + softfloat_flag_underflow = 2, + softfloat_flag_overflow = 4, + softfloat_flag_infinity = 8, + softfloat_flag_invalid = 16 +}; + +/*---------------------------------------------------------------------------- +| Routine to raise any or all of the software floating-point exception flags. +*----------------------------------------------------------------------------*/ +void softfloat_raiseFlags( int_fast8_t ); + +/*---------------------------------------------------------------------------- +| Integer-to-floating-point conversion routines. +*----------------------------------------------------------------------------*/ +float32_t ui32_to_f32( uint_fast32_t ); +float64_t ui32_to_f64( uint_fast32_t ); +floatx80_t ui32_to_fx80( uint_fast32_t ); +float128_t ui32_to_f128( uint_fast32_t ); +float32_t ui64_to_f32( uint_fast64_t ); +float64_t ui64_to_f64( uint_fast64_t ); +floatx80_t ui64_to_fx80( uint_fast64_t ); +float128_t ui64_to_f128( uint_fast64_t ); +float32_t i32_to_f32( int_fast32_t ); +float64_t i32_to_f64( int_fast32_t ); +floatx80_t i32_to_fx80( int_fast32_t ); +float128_t i32_to_f128( int_fast32_t ); +float32_t i64_to_f32( int_fast64_t ); +float64_t i64_to_f64( int_fast64_t ); +floatx80_t i64_to_fx80( int_fast64_t ); +float128_t i64_to_f128( int_fast64_t ); + +/*---------------------------------------------------------------------------- +| 32-bit (single-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +uint_fast32_t f32_to_ui32( float32_t, int_fast8_t, bool ); +uint_fast64_t f32_to_ui64( float32_t, int_fast8_t, bool ); +int_fast32_t f32_to_i32( float32_t, int_fast8_t, bool ); +int_fast64_t f32_to_i64( float32_t, int_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 ); +float64_t f32_to_f64( float32_t ); +floatx80_t f32_to_fx80( float32_t ); +float128_t f32_to_f128( float32_t ); +float32_t f32_roundToInt( float32_t, int_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, int_fast8_t, bool ); +uint_fast64_t f64_to_ui64( float64_t, int_fast8_t, bool ); +int_fast32_t f64_to_i32( float64_t, int_fast8_t, bool ); +int_fast64_t f64_to_i64( float64_t, int_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 ); +float32_t f64_to_f32( float64_t ); +floatx80_t f64_to_fx80( float64_t ); +float128_t f64_to_f128( float64_t ); +float64_t f64_roundToInt( float64_t, int_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 ); + +/*---------------------------------------------------------------------------- +| Extended double-precision rounding precision. Valid values are 32, 64, and +| 80. +*----------------------------------------------------------------------------*/ +extern int_fast8_t floatx80_roundingPrecision; + +/*---------------------------------------------------------------------------- +| Extended double-precision floating-point operations. +*----------------------------------------------------------------------------*/ +uint_fast32_t fx80_to_ui32( floatx80_t, int_fast8_t, bool ); +uint_fast64_t fx80_to_ui64( floatx80_t, int_fast8_t, bool ); +int_fast32_t fx80_to_i32( floatx80_t, int_fast8_t, bool ); +int_fast64_t fx80_to_i64( floatx80_t, int_fast8_t, bool ); +uint_fast32_t fx80_to_ui32_r_minMag( floatx80_t, bool ); +uint_fast64_t fx80_to_ui64_r_minMag( floatx80_t, bool ); +int_fast32_t fx80_to_i32_r_minMag( floatx80_t, bool ); +int_fast64_t fx80_to_i64_r_minMag( floatx80_t, bool ); +float32_t fx80_to_f32( floatx80_t ); +float64_t fx80_to_f64( floatx80_t ); +float128_t fx80_to_f128( floatx80_t ); +floatx80_t fx80_roundToInt( floatx80_t, int_fast8_t, bool ); +floatx80_t fx80_add( floatx80_t, floatx80_t ); +floatx80_t fx80_sub( floatx80_t, floatx80_t ); +floatx80_t fx80_mul( floatx80_t, floatx80_t ); +floatx80_t fx80_mulAdd( floatx80_t, floatx80_t, floatx80_t ); +floatx80_t fx80_div( floatx80_t, floatx80_t ); +floatx80_t fx80_rem( floatx80_t, floatx80_t ); +floatx80_t fx80_sqrt( floatx80_t ); +bool fx80_eq( floatx80_t, floatx80_t ); +bool fx80_le( floatx80_t, floatx80_t ); +bool fx80_lt( floatx80_t, floatx80_t ); +bool fx80_eq_signaling( floatx80_t, floatx80_t ); +bool fx80_le_quiet( floatx80_t, floatx80_t ); +bool fx80_lt_quiet( floatx80_t, floatx80_t ); +bool fx80_isSignalingNaN( floatx80_t ); + +/*---------------------------------------------------------------------------- +| 128-bit (quadruple-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +uint_fast32_t f128_to_ui32( float128_t, int_fast8_t, bool ); +uint_fast64_t f128_to_ui64( float128_t, int_fast8_t, bool ); +int_fast32_t f128_to_i32( float128_t, int_fast8_t, bool ); +int_fast64_t f128_to_i64( float128_t, int_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 ); +float32_t f128_to_f32( float128_t ); +float64_t f128_to_f64( float128_t ); +floatx80_t f128_to_fx80( float128_t ); +float128_t f128_roundToInt( float128_t, int_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 + diff --git a/softfloat/softfloat.mk.in b/softfloat/softfloat.mk.in index 4f86e12..964bc47 100644 --- a/softfloat/softfloat.mk.in +++ b/softfloat/softfloat.mk.in @@ -1,13 +1,112 @@ -softfloat_subproject_deps = +softfloat_subproject_deps = \ + sotfloat_riscv \ softfloat_hdrs = \ - softfloat.h \ - softfloat-macros \ - milieu.h \ - softfloat-specialize \ + internals.h \ + primitives.h \ + softfloat.h \ softfloat_srcs = \ - softfloat.cc \ + f32_add.cc \ + f32_div.cc \ + f32_eq.cc \ + f32_eq_signaling.cc \ + f32_isSignalingNaN.cc \ + f32_le.cc \ + f32_le_quiet.cc \ + f32_lt.cc \ + f32_lt_quiet.cc \ + f32_mulAdd.cc \ + f32_mul.cc \ + f32_rem.cc \ + f32_roundToInt.cc \ + f32_sqrt.cc \ + f32_sub.cc \ + f32_to_f64.cc \ + f32_to_i32.cc \ + f32_to_i32_r_minMag.cc \ + f32_to_i64.cc \ + f32_to_i64_r_minMag.cc \ + f32_to_ui32.cc \ + f32_to_ui32_r_minMag.cc \ + f32_to_ui64.cc \ + f32_to_ui64_r_minMag.cc \ + f64_add.cc \ + f64_div.cc \ + f64_eq.cc \ + f64_eq_signaling.cc \ + f64_isSignalingNaN.cc \ + f64_le.cc \ + f64_le_quiet.cc \ + f64_lt.cc \ + f64_lt_quiet.cc \ + f64_mulAdd.cc \ + f64_mul.cc \ + f64_rem.cc \ + f64_roundToInt.cc \ + f64_sqrt.cc \ + f64_sub.cc \ + f64_to_f32.cc \ + f64_to_i32.cc \ + f64_to_i32_r_minMag.cc \ + f64_to_i64.cc \ + f64_to_i64_r_minMag.cc \ + f64_to_ui32.cc \ + f64_to_ui32_r_minMag.cc \ + f64_to_ui64.cc \ + f64_to_ui64_r_minMag.cc \ + i32_to_f32.cc \ + i32_to_f64.cc \ + i64_to_f32.cc \ + i64_to_f64.cc \ + s_add128.cc \ + s_add192.cc \ + s_addMagsF32.cc \ + s_addMagsF64.cc \ + s_countLeadingZeros32.cc \ + s_countLeadingZeros64.cc \ + s_countLeadingZeros8.cc \ + s_eq128.cc \ + s_estimateDiv128To64.cc \ + s_estimateSqrt32.cc \ + s_le128.cc \ + s_lt128.cc \ + s_mul128By64To192.cc \ + s_mul128To256.cc \ + s_mul64To128.cc \ + s_mulAddF32.cc \ + s_mulAddF64.cc \ + s_normRoundPackToF32.cc \ + s_normRoundPackToF64.cc \ + s_normSubnormalF32Sig.cc \ + s_normSubnormalF64Sig.cc \ + softfloat_state.cc \ + s_roundPackToF32.cc \ + s_roundPackToF64.cc \ + s_roundPackToI32.cc \ + s_roundPackToI64.cc \ + s_roundPackToUI32.cc \ + s_roundPackToUI64.cc \ + s_shift128ExtraRightJam.cc \ + s_shift128RightJam.cc \ + s_shift32RightJam.cc \ + s_shift64ExtraRightJam.cc \ + s_shift64RightJam.cc \ + s_shortShift128ExtraRightJam.cc \ + s_shortShift128Left.cc \ + s_shortShift128Right.cc \ + s_shortShift192Left.cc \ + s_shortShift32Right1Jam.cc \ + s_shortShift64ExtraRightJam.cc \ + s_shortShift64RightJam.cc \ + s_sub128.cc \ + s_sub192.cc \ + s_subMagsF32.cc \ + s_subMagsF64.cc \ + ui32_to_f32.cc \ + ui32_to_f64.cc \ + ui64_to_f32.cc \ + ui64_to_f64.cc \ softfloat_test_srcs = diff --git a/softfloat/softfloat_state.cc b/softfloat/softfloat_state.cc new file mode 100755 index 0000000..8859089 --- /dev/null +++ b/softfloat/softfloat_state.cc @@ -0,0 +1,19 @@ + +/*** COMMENTS. ***/ + +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Floating-point rounding mode, extended double-precision rounding precision, +| and exception flags. +*----------------------------------------------------------------------------*/ +int_fast8_t softfloat_roundingMode = softfloat_round_nearest_even; +int_fast8_t softfloat_detectTininess = init_detectTininess; +int_fast8_t softfloat_exceptionFlags = 0; + +int_fast8_t floatx80_roundingPrecision = 80; + diff --git a/softfloat/ui32_to_f32.cc b/softfloat/ui32_to_f32.cc new file mode 100755 index 0000000..ba0fc1a --- /dev/null +++ b/softfloat/ui32_to_f32.cc @@ -0,0 +1,25 @@ + +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +float32_t ui32_to_f32( uint_fast32_t a ) +{ + union ui32_f32 uZ; + + if ( ! a ) { + uZ.ui = 0; + return uZ.f; + } + if ( a & 0x80000000 ) { + return + softfloat_roundPackToF32( + 0, 0x9D, softfloat_shortShift32Right1Jam( a ) ); + } else { + return softfloat_normRoundPackToF32( 0, 0x9C, a ); + } + +} + diff --git a/softfloat/ui32_to_f64.cc b/softfloat/ui32_to_f64.cc new file mode 100755 index 0000000..d0bd177 --- /dev/null +++ b/softfloat/ui32_to_f64.cc @@ -0,0 +1,26 @@ + +#include +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +float64_t ui32_to_f64( uint_fast32_t a ) +{ + uint_fast64_t uiZ; + int shiftCount; + union ui64_f64 uZ; + + if ( ! a ) { + uiZ = 0; + } else { + shiftCount = softfloat_countLeadingZeros32( a ) + 21; + uiZ = + packToF64UI( + 0, 0x432 - shiftCount, (uint_fast64_t) a< +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +float32_t ui64_to_f32( uint_fast64_t a ) +{ + int shiftCount; + union ui32_f32 u; + uint_fast32_t sig; + + shiftCount = softfloat_countLeadingZeros64( a ) - 40; + if ( 0 <= shiftCount ) { + u.ui = + a ? packToF32UI( + 0, 0x95 - shiftCount, (uint_fast32_t) a< +#include "platform.h" +#include "primitives.h" +#include "internals.h" +#include "softfloat.h" + +float64_t ui64_to_f64( uint_fast64_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_shortShift64RightJam( a, 1 ) ); + } else { + return softfloat_normRoundPackToF64( 0, 0x43C, a ); + } + +} + diff --git a/softfloat_riscv/platform.h b/softfloat_riscv/platform.h new file mode 100755 index 0000000..6c54313 --- /dev/null +++ b/softfloat_riscv/platform.h @@ -0,0 +1,42 @@ + +/*============================================================================ + +*** FIX. + +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define LITTLEENDIAN + +#ifndef UINT64_C +# define UINT64_C(x) (x ## ULL) +# define INT64_C(x) (x ## LL) +#endif diff --git a/softfloat_riscv/s_commonNaNToF32UI.cc b/softfloat_riscv/s_commonNaNToF32UI.cc new file mode 100755 index 0000000..61f2735 --- /dev/null +++ b/softfloat_riscv/s_commonNaNToF32UI.cc @@ -0,0 +1,17 @@ + +#include +#include "platform.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the single- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN a ) +{ + + return (uint_fast32_t) a.sign<<31 | 0x7FFFFFFF; + +} + diff --git a/softfloat_riscv/s_commonNaNToF64UI.cc b/softfloat_riscv/s_commonNaNToF64UI.cc new file mode 100755 index 0000000..da36c04 --- /dev/null +++ b/softfloat_riscv/s_commonNaNToF64UI.cc @@ -0,0 +1,18 @@ + +#include +#include "platform.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the double- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +uint_fast64_t softfloat_commonNaNToF64UI( struct commonNaN a ) +{ + + return + (uint_fast64_t) a.sign<<63 | UINT64_C( 0x7FFFFFFFFFFFFFFF ); + +} + diff --git a/softfloat_riscv/s_f32UIToCommonNaN.cc b/softfloat_riscv/s_f32UIToCommonNaN.cc new file mode 100755 index 0000000..9ee0db9 --- /dev/null +++ b/softfloat_riscv/s_f32UIToCommonNaN.cc @@ -0,0 +1,25 @@ + +#include +#include "platform.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +struct commonNaN softfloat_f32UIToCommonNaN( uint_fast32_t uiA ) +{ + struct commonNaN z; + + if ( softfloat_isSigNaNF32UI( uiA ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + z.sign = uiA>>31; + z.v64 = (uint_fast64_t) 0x7FFFF <<41; + z.v0 = 0; + return z; + +} + diff --git a/softfloat_riscv/s_f64UIToCommonNaN.cc b/softfloat_riscv/s_f64UIToCommonNaN.cc new file mode 100755 index 0000000..84d8ca0 --- /dev/null +++ b/softfloat_riscv/s_f64UIToCommonNaN.cc @@ -0,0 +1,25 @@ + +#include +#include "platform.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +struct commonNaN softfloat_f64UIToCommonNaN( uint_fast64_t uiA ) +{ + struct commonNaN z; + + if ( softfloat_isSigNaNF64UI( uiA ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + z.sign = uiA>>63; + z.v64 = (uint_fast64_t) 0xFFFFFFFFFFFFF <<12; + z.v0 = 0; + return z; + +} + diff --git a/softfloat_riscv/s_isSigNaNF32UI.cc b/softfloat_riscv/s_isSigNaNF32UI.cc new file mode 100755 index 0000000..0a9c33f --- /dev/null +++ b/softfloat_riscv/s_isSigNaNF32UI.cc @@ -0,0 +1,13 @@ + +#include +#include +#include "platform.h" +#include "specialize.h" + +bool softfloat_isSigNaNF32UI( uint_fast32_t ui ) +{ + + return ( ( ui>>22 & 0x1FF ) == 0x1FE ) && ( ui & 0x003FFFFF ); + +} + diff --git a/softfloat_riscv/s_isSigNaNF64UI.cc b/softfloat_riscv/s_isSigNaNF64UI.cc new file mode 100755 index 0000000..d255213 --- /dev/null +++ b/softfloat_riscv/s_isSigNaNF64UI.cc @@ -0,0 +1,15 @@ + +#include +#include +#include "platform.h" +#include "specialize.h" + +bool softfloat_isSigNaNF64UI( uint_fast64_t ui ) +{ + + return + ( ( ui>>51 & 0xFFF ) == 0xFFE ) + && ( ui & UINT64_C( 0x0007FFFFFFFFFFFF ) ); + +} + diff --git a/softfloat_riscv/s_propagateNaNF32UI.cc b/softfloat_riscv/s_propagateNaNF32UI.cc new file mode 100755 index 0000000..07774e8 --- /dev/null +++ b/softfloat_riscv/s_propagateNaNF32UI.cc @@ -0,0 +1,55 @@ + +/*** UPDATE COMMENTS. ***/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Takes two single-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +uint_fast32_t + softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ) +{ + bool isNaNA, isSigNaNA, isNaNB, isSigNaNB; + uint_fast32_t uiMagA, uiMagB; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + isNaNA = isNaNF32UI( uiA ); + isSigNaNA = softfloat_isSigNaNF32UI( uiA ); + isNaNB = isNaNF32UI( uiB ); + isSigNaNB = softfloat_isSigNaNF32UI( uiB ); + /*------------------------------------------------------------------------ + | Make NaNs non-signaling. + *------------------------------------------------------------------------*/ + uiA |= 0x00400000; + uiB |= 0x00400000; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isSigNaNA | isSigNaNB ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + if ( isSigNaNA ) { + if ( isSigNaNB ) goto returnLargerSignificand; + return isNaNB ? uiB : uiA; + } else if ( isNaNA ) { + if ( isSigNaNB || ! isNaNB ) return uiA; + returnLargerSignificand: + uiMagA = uiA<<1; + uiMagB = uiB<<1; + if ( uiMagA < uiMagB ) return uiB; + if ( uiMagB < uiMagA ) return uiA; + return ( uiA < uiB ) ? uiA : uiB; + } else { + return uiB; + } + +} + diff --git a/softfloat_riscv/s_propagateNaNF64UI.cc b/softfloat_riscv/s_propagateNaNF64UI.cc new file mode 100755 index 0000000..0ff6446 --- /dev/null +++ b/softfloat_riscv/s_propagateNaNF64UI.cc @@ -0,0 +1,55 @@ + +/*** UPDATE COMMENTS. ***/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Takes two double-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +uint_fast64_t + softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ) +{ + bool isNaNA, isSigNaNA, isNaNB, isSigNaNB; + uint_fast64_t uiMagA, uiMagB; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + isNaNA = isNaNF64UI( uiA ); + isSigNaNA = softfloat_isSigNaNF64UI( uiA ); + isNaNB = isNaNF64UI( uiB ); + isSigNaNB = softfloat_isSigNaNF64UI( uiB ); + /*------------------------------------------------------------------------ + | Make NaNs non-signaling. + *------------------------------------------------------------------------*/ + uiA |= UINT64_C( 0x0008000000000000 ); + uiB |= UINT64_C( 0x0008000000000000 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isSigNaNA | isSigNaNB ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + if ( isSigNaNA ) { + if ( isSigNaNB ) goto returnLargerSignificand; + return isNaNB ? uiB : uiA; + } else if ( isNaNA ) { + if ( isSigNaNB || ! isNaNB ) return uiA; + returnLargerSignificand: + uiMagA = uiA & UINT64_C( 0x7FFFFFFFFFFFFFFF ); + uiMagB = uiB & UINT64_C( 0x7FFFFFFFFFFFFFFF ); + if ( uiMagA < uiMagB ) return uiB; + if ( uiMagB < uiMagA ) return uiA; + return ( uiA < uiB ) ? uiA : uiB; + } else { + return uiB; + } + +} + diff --git a/softfloat_riscv/softfloat_raiseFlags.cc b/softfloat_riscv/softfloat_raiseFlags.cc new file mode 100755 index 0000000..c0c0dc8 --- /dev/null +++ b/softfloat_riscv/softfloat_raiseFlags.cc @@ -0,0 +1,51 @@ + +/*============================================================================ + +*** FIX. + +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +#include "platform.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Raises the exceptions specified by `flags'. Floating-point traps can be +| defined here if desired. It is currently not possible for such a trap +| to substitute a result value. If traps are not implemented, this routine +| should be simply `float_exception_flags |= flags;'. +*----------------------------------------------------------------------------*/ + +void softfloat_raiseFlags( int_fast8_t flags ) +{ + + softfloat_exceptionFlags |= flags; + +} + diff --git a/softfloat_riscv/softfloat_riscv.ac b/softfloat_riscv/softfloat_riscv.ac new file mode 100644 index 0000000..e69de29 diff --git a/softfloat_riscv/softfloat_riscv.mk.in b/softfloat_riscv/softfloat_riscv.mk.in new file mode 100644 index 0000000..0b996fb --- /dev/null +++ b/softfloat_riscv/softfloat_riscv.mk.in @@ -0,0 +1,21 @@ +softfloat_riscv_subproject_deps = \ + +softfloat_riscv_hdrs = \ + softfloat_types.h \ + platform.h \ + specialize.h \ + +softfloat_riscv_srcs = \ + softfloat_raiseFlags.cc \ + s_commonNaNToF32UI.cc \ + s_commonNaNToF64UI.cc \ + s_f32UIToCommonNaN.cc \ + s_f64UIToCommonNaN.cc \ + s_isSigNaNF32UI.cc \ + s_isSigNaNF64UI.cc \ + s_propagateNaNF32UI.cc \ + s_propagateNaNF64UI.cc \ + +softfloat_riscv_test_srcs = + +softfloat_riscv_install_prog_srcs = diff --git a/softfloat_riscv/softfloat_types.h b/softfloat_riscv/softfloat_types.h new file mode 100755 index 0000000..9fada89 --- /dev/null +++ b/softfloat_riscv/softfloat_types.h @@ -0,0 +1,16 @@ + +#ifndef softfloat_types_h +#define softfloat_types_h + +/*** COMMENTS. ***/ + +#include +#include + +typedef uint32_t float32_t; +typedef uint64_t float64_t; +typedef struct { uint64_t v; uint16_t x; } floatx80_t; +typedef struct { uint64_t v[ 2 ]; } float128_t; + +#endif + diff --git a/softfloat_riscv/specialize.h b/softfloat_riscv/specialize.h new file mode 100755 index 0000000..bf57bc9 --- /dev/null +++ b/softfloat_riscv/specialize.h @@ -0,0 +1,113 @@ + +/*============================================================================ + +*** FIX. + +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +#include +#include + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define init_detectTininess softfloat_tininess_beforeRounding; + +/*---------------------------------------------------------------------------- +| Structure used to transfer NaN representations from one format to another. +*----------------------------------------------------------------------------*/ +struct commonNaN { + bool sign; + uint64_t v64, v0; +}; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated single-precision NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF32UI 0xFFFFFFFF + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is a signaling +| NaN; otherwise, returns 0. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 1 <= INLINE_LEVEL ) +INLINE bool softfloat_isSigNaNF32UI( uint_fast32_t ui ) + { return ( ( ui>>22 & 0x1FF ) == 0x1FE ) && ( ui & 0x003FFFFF ); } +#else +bool softfloat_isSigNaNF32UI( uint_fast32_t ); +#endif + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +struct commonNaN softfloat_f32UIToCommonNaN( uint_fast32_t ); +#if defined INLINE_LEVEL && ( 1 <= INLINE_LEVEL ) +INLINE uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN a ) + { return (uint_fast32_t) a.sign<<31 | 0x7FFFFFFF; } +#else +uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN ); +#endif + +/*---------------------------------------------------------------------------- +| Takes two single-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast32_t softfloat_propagateNaNF32UI( uint_fast32_t, uint_fast32_t ); + +/*---------------------------------------------------------------------------- +| The pattern for a default generated double-precision NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF64UI UINT64_C(0xFFF8000000000000) + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && ( 1 <= INLINE_LEVEL ) +INLINE bool softfloat_isSigNaNF64UI( uint_fast64_t ui ) +{ + return + ( ( ui>>51 & 0xFFF ) == 0xFFE ) + && ( ui & UINT64_C( 0x0007FFFFFFFFFFFF ) ); +} +#else +bool softfloat_isSigNaNF64UI( uint_fast64_t ); +#endif + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +/*** MIGHT BE INLINE'D. ***/ +struct commonNaN softfloat_f64UIToCommonNaN( uint_fast64_t ); +uint_fast64_t softfloat_commonNaNToF64UI( struct commonNaN ); + +/*---------------------------------------------------------------------------- +| Takes two double-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast64_t softfloat_propagateNaNF64UI( uint_fast64_t, uint_fast64_t ); +