diff options
Diffstat (limited to 'arch/arm/nwfpe/softfloat-specialize')
-rw-r--r-- | arch/arm/nwfpe/softfloat-specialize | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/arch/arm/nwfpe/softfloat-specialize b/arch/arm/nwfpe/softfloat-specialize new file mode 100644 index 000000000000..acf409144763 --- /dev/null +++ b/arch/arm/nwfpe/softfloat-specialize | |||
@@ -0,0 +1,366 @@ | |||
1 | |||
2 | /* | ||
3 | =============================================================================== | ||
4 | |||
5 | This C source fragment is part of the SoftFloat IEC/IEEE Floating-point | ||
6 | Arithmetic Package, Release 2. | ||
7 | |||
8 | Written by John R. Hauser. This work was made possible in part by the | ||
9 | International Computer Science Institute, located at Suite 600, 1947 Center | ||
10 | Street, Berkeley, California 94704. Funding was partially provided by the | ||
11 | National Science Foundation under grant MIP-9311980. The original version | ||
12 | of this code was written as part of a project to build a fixed-point vector | ||
13 | processor in collaboration with the University of California at Berkeley, | ||
14 | overseen by Profs. Nelson Morgan and John Wawrzynek. More information | ||
15 | is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ | ||
16 | arithmetic/softfloat.html'. | ||
17 | |||
18 | THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort | ||
19 | has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT | ||
20 | TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO | ||
21 | PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY | ||
22 | AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. | ||
23 | |||
24 | Derivative works are acceptable, even for commercial purposes, so long as | ||
25 | (1) they include prominent notice that the work is derivative, and (2) they | ||
26 | include prominent notice akin to these three paragraphs for those parts of | ||
27 | this code that are retained. | ||
28 | |||
29 | =============================================================================== | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | ------------------------------------------------------------------------------- | ||
34 | Underflow tininess-detection mode, statically initialized to default value. | ||
35 | (The declaration in `softfloat.h' must match the `int8' type here.) | ||
36 | ------------------------------------------------------------------------------- | ||
37 | */ | ||
38 | int8 float_detect_tininess = float_tininess_after_rounding; | ||
39 | |||
40 | /* | ||
41 | ------------------------------------------------------------------------------- | ||
42 | Raises the exceptions specified by `flags'. Floating-point traps can be | ||
43 | defined here if desired. It is currently not possible for such a trap to | ||
44 | substitute a result value. If traps are not implemented, this routine | ||
45 | should be simply `float_exception_flags |= flags;'. | ||
46 | |||
47 | ScottB: November 4, 1998 | ||
48 | Moved this function out of softfloat-specialize into fpmodule.c. | ||
49 | This effectively isolates all the changes required for integrating with the | ||
50 | Linux kernel into fpmodule.c. Porting to NetBSD should only require modifying | ||
51 | fpmodule.c to integrate with the NetBSD kernel (I hope!). | ||
52 | ------------------------------------------------------------------------------- | ||
53 | void float_raise( int8 flags ) | ||
54 | { | ||
55 | float_exception_flags |= flags; | ||
56 | } | ||
57 | */ | ||
58 | |||
59 | /* | ||
60 | ------------------------------------------------------------------------------- | ||
61 | Internal canonical NaN format. | ||
62 | ------------------------------------------------------------------------------- | ||
63 | */ | ||
64 | typedef struct { | ||
65 | flag sign; | ||
66 | bits64 high, low; | ||
67 | } commonNaNT; | ||
68 | |||
69 | /* | ||
70 | ------------------------------------------------------------------------------- | ||
71 | The pattern for a default generated single-precision NaN. | ||
72 | ------------------------------------------------------------------------------- | ||
73 | */ | ||
74 | #define float32_default_nan 0xFFFFFFFF | ||
75 | |||
76 | /* | ||
77 | ------------------------------------------------------------------------------- | ||
78 | Returns 1 if the single-precision floating-point value `a' is a NaN; | ||
79 | otherwise returns 0. | ||
80 | ------------------------------------------------------------------------------- | ||
81 | */ | ||
82 | flag float32_is_nan( float32 a ) | ||
83 | { | ||
84 | |||
85 | return ( 0xFF000000 < (bits32) ( a<<1 ) ); | ||
86 | |||
87 | } | ||
88 | |||
89 | /* | ||
90 | ------------------------------------------------------------------------------- | ||
91 | Returns 1 if the single-precision floating-point value `a' is a signaling | ||
92 | NaN; otherwise returns 0. | ||
93 | ------------------------------------------------------------------------------- | ||
94 | */ | ||
95 | flag float32_is_signaling_nan( float32 a ) | ||
96 | { | ||
97 | |||
98 | return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); | ||
99 | |||
100 | } | ||
101 | |||
102 | /* | ||
103 | ------------------------------------------------------------------------------- | ||
104 | Returns the result of converting the single-precision floating-point NaN | ||
105 | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid | ||
106 | exception is raised. | ||
107 | ------------------------------------------------------------------------------- | ||
108 | */ | ||
109 | static commonNaNT float32ToCommonNaN( float32 a ) | ||
110 | { | ||
111 | commonNaNT z; | ||
112 | |||
113 | if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); | ||
114 | z.sign = a>>31; | ||
115 | z.low = 0; | ||
116 | z.high = ( (bits64) a )<<41; | ||
117 | return z; | ||
118 | |||
119 | } | ||
120 | |||
121 | /* | ||
122 | ------------------------------------------------------------------------------- | ||
123 | Returns the result of converting the canonical NaN `a' to the single- | ||
124 | precision floating-point format. | ||
125 | ------------------------------------------------------------------------------- | ||
126 | */ | ||
127 | static float32 commonNaNToFloat32( commonNaNT a ) | ||
128 | { | ||
129 | |||
130 | return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); | ||
131 | |||
132 | } | ||
133 | |||
134 | /* | ||
135 | ------------------------------------------------------------------------------- | ||
136 | Takes two single-precision floating-point values `a' and `b', one of which | ||
137 | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a | ||
138 | signaling NaN, the invalid exception is raised. | ||
139 | ------------------------------------------------------------------------------- | ||
140 | */ | ||
141 | static float32 propagateFloat32NaN( float32 a, float32 b ) | ||
142 | { | ||
143 | flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; | ||
144 | |||
145 | aIsNaN = float32_is_nan( a ); | ||
146 | aIsSignalingNaN = float32_is_signaling_nan( a ); | ||
147 | bIsNaN = float32_is_nan( b ); | ||
148 | bIsSignalingNaN = float32_is_signaling_nan( b ); | ||
149 | a |= 0x00400000; | ||
150 | b |= 0x00400000; | ||
151 | if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); | ||
152 | if ( aIsNaN ) { | ||
153 | return ( aIsSignalingNaN & bIsNaN ) ? b : a; | ||
154 | } | ||
155 | else { | ||
156 | return b; | ||
157 | } | ||
158 | |||
159 | } | ||
160 | |||
161 | /* | ||
162 | ------------------------------------------------------------------------------- | ||
163 | The pattern for a default generated double-precision NaN. | ||
164 | ------------------------------------------------------------------------------- | ||
165 | */ | ||
166 | #define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) | ||
167 | |||
168 | /* | ||
169 | ------------------------------------------------------------------------------- | ||
170 | Returns 1 if the double-precision floating-point value `a' is a NaN; | ||
171 | otherwise returns 0. | ||
172 | ------------------------------------------------------------------------------- | ||
173 | */ | ||
174 | flag float64_is_nan( float64 a ) | ||
175 | { | ||
176 | |||
177 | return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); | ||
178 | |||
179 | } | ||
180 | |||
181 | /* | ||
182 | ------------------------------------------------------------------------------- | ||
183 | Returns 1 if the double-precision floating-point value `a' is a signaling | ||
184 | NaN; otherwise returns 0. | ||
185 | ------------------------------------------------------------------------------- | ||
186 | */ | ||
187 | flag float64_is_signaling_nan( float64 a ) | ||
188 | { | ||
189 | |||
190 | return | ||
191 | ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) | ||
192 | && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); | ||
193 | |||
194 | } | ||
195 | |||
196 | /* | ||
197 | ------------------------------------------------------------------------------- | ||
198 | Returns the result of converting the double-precision floating-point NaN | ||
199 | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid | ||
200 | exception is raised. | ||
201 | ------------------------------------------------------------------------------- | ||
202 | */ | ||
203 | static commonNaNT float64ToCommonNaN( float64 a ) | ||
204 | { | ||
205 | commonNaNT z; | ||
206 | |||
207 | if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); | ||
208 | z.sign = a>>63; | ||
209 | z.low = 0; | ||
210 | z.high = a<<12; | ||
211 | return z; | ||
212 | |||
213 | } | ||
214 | |||
215 | /* | ||
216 | ------------------------------------------------------------------------------- | ||
217 | Returns the result of converting the canonical NaN `a' to the double- | ||
218 | precision floating-point format. | ||
219 | ------------------------------------------------------------------------------- | ||
220 | */ | ||
221 | static float64 commonNaNToFloat64( commonNaNT a ) | ||
222 | { | ||
223 | |||
224 | return | ||
225 | ( ( (bits64) a.sign )<<63 ) | ||
226 | | LIT64( 0x7FF8000000000000 ) | ||
227 | | ( a.high>>12 ); | ||
228 | |||
229 | } | ||
230 | |||
231 | /* | ||
232 | ------------------------------------------------------------------------------- | ||
233 | Takes two double-precision floating-point values `a' and `b', one of which | ||
234 | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a | ||
235 | signaling NaN, the invalid exception is raised. | ||
236 | ------------------------------------------------------------------------------- | ||
237 | */ | ||
238 | static float64 propagateFloat64NaN( float64 a, float64 b ) | ||
239 | { | ||
240 | flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; | ||
241 | |||
242 | aIsNaN = float64_is_nan( a ); | ||
243 | aIsSignalingNaN = float64_is_signaling_nan( a ); | ||
244 | bIsNaN = float64_is_nan( b ); | ||
245 | bIsSignalingNaN = float64_is_signaling_nan( b ); | ||
246 | a |= LIT64( 0x0008000000000000 ); | ||
247 | b |= LIT64( 0x0008000000000000 ); | ||
248 | if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); | ||
249 | if ( aIsNaN ) { | ||
250 | return ( aIsSignalingNaN & bIsNaN ) ? b : a; | ||
251 | } | ||
252 | else { | ||
253 | return b; | ||
254 | } | ||
255 | |||
256 | } | ||
257 | |||
258 | #ifdef FLOATX80 | ||
259 | |||
260 | /* | ||
261 | ------------------------------------------------------------------------------- | ||
262 | The pattern for a default generated extended double-precision NaN. The | ||
263 | `high' and `low' values hold the most- and least-significant bits, | ||
264 | respectively. | ||
265 | ------------------------------------------------------------------------------- | ||
266 | */ | ||
267 | #define floatx80_default_nan_high 0xFFFF | ||
268 | #define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) | ||
269 | |||
270 | /* | ||
271 | ------------------------------------------------------------------------------- | ||
272 | Returns 1 if the extended double-precision floating-point value `a' is a | ||
273 | NaN; otherwise returns 0. | ||
274 | ------------------------------------------------------------------------------- | ||
275 | */ | ||
276 | flag floatx80_is_nan( floatx80 a ) | ||
277 | { | ||
278 | |||
279 | return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); | ||
280 | |||
281 | } | ||
282 | |||
283 | /* | ||
284 | ------------------------------------------------------------------------------- | ||
285 | Returns 1 if the extended double-precision floating-point value `a' is a | ||
286 | signaling NaN; otherwise returns 0. | ||
287 | ------------------------------------------------------------------------------- | ||
288 | */ | ||
289 | flag floatx80_is_signaling_nan( floatx80 a ) | ||
290 | { | ||
291 | //register int lr; | ||
292 | bits64 aLow; | ||
293 | |||
294 | //__asm__("mov %0, lr" : : "g" (lr)); | ||
295 | //fp_printk("floatx80_is_signalling_nan() called from 0x%08x\n",lr); | ||
296 | aLow = a.low & ~ LIT64( 0x4000000000000000 ); | ||
297 | return | ||
298 | ( ( a.high & 0x7FFF ) == 0x7FFF ) | ||
299 | && (bits64) ( aLow<<1 ) | ||
300 | && ( a.low == aLow ); | ||
301 | |||
302 | } | ||
303 | |||
304 | /* | ||
305 | ------------------------------------------------------------------------------- | ||
306 | Returns the result of converting the extended double-precision floating- | ||
307 | point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the | ||
308 | invalid exception is raised. | ||
309 | ------------------------------------------------------------------------------- | ||
310 | */ | ||
311 | static commonNaNT floatx80ToCommonNaN( floatx80 a ) | ||
312 | { | ||
313 | commonNaNT z; | ||
314 | |||
315 | if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); | ||
316 | z.sign = a.high>>15; | ||
317 | z.low = 0; | ||
318 | z.high = a.low<<1; | ||
319 | return z; | ||
320 | |||
321 | } | ||
322 | |||
323 | /* | ||
324 | ------------------------------------------------------------------------------- | ||
325 | Returns the result of converting the canonical NaN `a' to the extended | ||
326 | double-precision floating-point format. | ||
327 | ------------------------------------------------------------------------------- | ||
328 | */ | ||
329 | static floatx80 commonNaNToFloatx80( commonNaNT a ) | ||
330 | { | ||
331 | floatx80 z; | ||
332 | |||
333 | z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); | ||
334 | z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; | ||
335 | return z; | ||
336 | |||
337 | } | ||
338 | |||
339 | /* | ||
340 | ------------------------------------------------------------------------------- | ||
341 | Takes two extended double-precision floating-point values `a' and `b', one | ||
342 | of which is a NaN, and returns the appropriate NaN result. If either `a' or | ||
343 | `b' is a signaling NaN, the invalid exception is raised. | ||
344 | ------------------------------------------------------------------------------- | ||
345 | */ | ||
346 | static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) | ||
347 | { | ||
348 | flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; | ||
349 | |||
350 | aIsNaN = floatx80_is_nan( a ); | ||
351 | aIsSignalingNaN = floatx80_is_signaling_nan( a ); | ||
352 | bIsNaN = floatx80_is_nan( b ); | ||
353 | bIsSignalingNaN = floatx80_is_signaling_nan( b ); | ||
354 | a.low |= LIT64( 0xC000000000000000 ); | ||
355 | b.low |= LIT64( 0xC000000000000000 ); | ||
356 | if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); | ||
357 | if ( aIsNaN ) { | ||
358 | return ( aIsSignalingNaN & bIsNaN ) ? b : a; | ||
359 | } | ||
360 | else { | ||
361 | return b; | ||
362 | } | ||
363 | |||
364 | } | ||
365 | |||
366 | #endif | ||