1 /*============================================================================
2 This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
3 Arithmetic Package, Release 2b.
4 
5 Written by John R. Hauser.  This work was made possible in part by the
6 International Computer Science Institute, located at Suite 600, 1947 Center
7 Street, Berkeley, California 94704.  Funding was partially provided by the
8 National Science Foundation under grant MIP-9311980.  The original version
9 of this code was written as part of a project to build a fixed-point vector
10 processor in collaboration with the University of California at Berkeley,
11 overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
12 is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
13 arithmetic/SoftFloat.html'.
14 
15 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
16 been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
17 RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
18 AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
19 COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
20 EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
21 INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
22 OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
23 
24 Derivative works are acceptable, even for commercial purposes, so long as
25 (1) the source code for the derivative work includes prominent notice that
26 the work is derivative, and (2) the source code includes prominent notice with
27 these four paragraphs for those parts of this code that are retained.
28 =============================================================================*/
29 
30 #define FLOAT128
31 
32 /*============================================================================
33  * Adapted for Bochs (x86 achitecture simulator) by
34  *            Stanislav Shwartsman [sshwarts at sourceforge net]
35  * ==========================================================================*/
36 
37 #include "softfloat.h"
38 #include "softfloat-specialize.h"
39 
40 /*----------------------------------------------------------------------------
41 | Takes two single-precision floating-point values `a' and `b', one of which
42 | is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
43 | signaling NaN, the invalid exception is raised.
44 *----------------------------------------------------------------------------*/
45 
propagateFloat32NaN(float32 a,float32 b,float_status_t & status)46 float32 propagateFloat32NaN(float32 a, float32 b, float_status_t &status)
47 {
48     int aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
49 
50     aIsNaN = float32_is_nan(a);
51     aIsSignalingNaN = float32_is_signaling_nan(a);
52     bIsNaN = float32_is_nan(b);
53     bIsSignalingNaN = float32_is_signaling_nan(b);
54     a |= 0x00400000;
55     b |= 0x00400000;
56     if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid);
57     if (get_float_nan_handling_mode(status) == float_larger_significand_nan) {
58         if (aIsSignalingNaN) {
59             if (bIsSignalingNaN) goto returnLargerSignificand;
60             return bIsNaN ? b : a;
61         }
62         else if (aIsNaN) {
63             if (bIsSignalingNaN | ! bIsNaN) return a;
64       returnLargerSignificand:
65             if ((Bit32u) (a<<1) < (Bit32u) (b<<1)) return b;
66             if ((Bit32u) (b<<1) < (Bit32u) (a<<1)) return a;
67             return (a < b) ? a : b;
68         }
69         else {
70             return b;
71         }
72     } else {
73         return (aIsSignalingNaN | aIsNaN) ? a : b;
74     }
75 }
76 
77 /*----------------------------------------------------------------------------
78 | Takes two double-precision floating-point values `a' and `b', one of which
79 | is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
80 | signaling NaN, the invalid exception is raised.
81 *----------------------------------------------------------------------------*/
82 
propagateFloat64NaN(float64 a,float64 b,float_status_t & status)83 float64 propagateFloat64NaN(float64 a, float64 b, float_status_t &status)
84 {
85     int aIsNaN = float64_is_nan(a);
86     int aIsSignalingNaN = float64_is_signaling_nan(a);
87     int bIsNaN = float64_is_nan(b);
88     int bIsSignalingNaN = float64_is_signaling_nan(b);
89     a |= BX_CONST64(0x0008000000000000);
90     b |= BX_CONST64(0x0008000000000000);
91     if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid);
92     if (get_float_nan_handling_mode(status) == float_larger_significand_nan) {
93         if (aIsSignalingNaN) {
94             if (bIsSignalingNaN) goto returnLargerSignificand;
95             return bIsNaN ? b : a;
96         }
97         else if (aIsNaN) {
98             if (bIsSignalingNaN | ! bIsNaN) return a;
99       returnLargerSignificand:
100             if ((Bit64u) (a<<1) < (Bit64u) (b<<1)) return b;
101             if ((Bit64u) (b<<1) < (Bit64u) (a<<1)) return a;
102             return (a < b) ? a : b;
103         }
104         else {
105             return b;
106         }
107     } else {
108         return (aIsSignalingNaN | aIsNaN) ? a : b;
109     }
110 }
111 
112 #ifdef FLOATX80
113 
114 /*----------------------------------------------------------------------------
115 | Takes two extended double-precision floating-point values `a' and `b', one
116 | of which is a NaN, and returns the appropriate NaN result.  If either `a' or
117 | `b' is a signaling NaN, the invalid exception is raised.
118 *----------------------------------------------------------------------------*/
119 
propagateFloatx80NaN(floatx80 a,floatx80 b,float_status_t & status)120 floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status_t &status)
121 {
122     int aIsNaN = floatx80_is_nan(a);
123     int aIsSignalingNaN = floatx80_is_signaling_nan(a);
124     int bIsNaN = floatx80_is_nan(b);
125     int bIsSignalingNaN = floatx80_is_signaling_nan(b);
126     a.fraction |= BX_CONST64(0xC000000000000000);
127     b.fraction |= BX_CONST64(0xC000000000000000);
128     if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid);
129     if (aIsSignalingNaN) {
130         if (bIsSignalingNaN) goto returnLargerSignificand;
131         return bIsNaN ? b : a;
132     }
133     else if (aIsNaN) {
134         if (bIsSignalingNaN | ! bIsNaN) return a;
135  returnLargerSignificand:
136         if (a.fraction < b.fraction) return b;
137         if (b.fraction < a.fraction) return a;
138         return (a.exp < b.exp) ? a : b;
139     }
140     else {
141         return b;
142     }
143 }
144 
145 /*----------------------------------------------------------------------------
146 | The pattern for a default generated extended double-precision NaN.
147 *----------------------------------------------------------------------------*/
148 const floatx80 floatx80_default_nan =
149     packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
150 
151 #endif /* FLOATX80 */
152 
153 #ifdef FLOAT128
154 
155 /*----------------------------------------------------------------------------
156 | Takes two quadruple-precision floating-point values `a' and `b', one of
157 | which is a NaN, and returns the appropriate NaN result.  If either `a' or
158 | `b' is a signaling NaN, the invalid exception is raised.
159 *----------------------------------------------------------------------------*/
160 
propagateFloat128NaN(float128 a,float128 b,float_status_t & status)161 float128 propagateFloat128NaN(float128 a, float128 b, float_status_t &status)
162 {
163     int aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
164     aIsNaN = float128_is_nan(a);
165     aIsSignalingNaN = float128_is_signaling_nan(a);
166     bIsNaN = float128_is_nan(b);
167     bIsSignalingNaN = float128_is_signaling_nan(b);
168     a.hi |= BX_CONST64(0x0000800000000000);
169     b.hi |= BX_CONST64(0x0000800000000000);
170     if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid);
171     if (aIsSignalingNaN) {
172         if (bIsSignalingNaN) goto returnLargerSignificand;
173         return bIsNaN ? b : a;
174     }
175     else if (aIsNaN) {
176         if (bIsSignalingNaN | !bIsNaN) return a;
177  returnLargerSignificand:
178         if (lt128(a.hi<<1, a.lo, b.hi<<1, b.lo)) return b;
179         if (lt128(b.hi<<1, b.lo, a.hi<<1, a.lo)) return a;
180         return (a.hi < b.hi) ? a : b;
181     }
182     else {
183         return b;
184     }
185 }
186 
187 /*----------------------------------------------------------------------------
188 | The pattern for a default generated quadruple-precision NaN.
189 *----------------------------------------------------------------------------*/
190 const float128 float128_default_nan =
191     packFloat128(float128_default_nan_hi, float128_default_nan_lo);
192 
193 #endif /* FLOAT128 */
194