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