Commit 158142c2c2df728cfa3b5320c65534921a764f26
1 parent
4f716dc6
soft float support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1332 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
1774 additions
and
3 deletions
Too many changes to show.
To preserve performance only 6 of 8 files are displayed.
Makefile.target
... | ... | @@ -229,7 +229,7 @@ ifeq ($(TARGET_ARCH), i386) |
229 | 229 | OBJS+= vm86.o |
230 | 230 | endif |
231 | 231 | ifeq ($(TARGET_ARCH), arm) |
232 | -OBJS+=nwfpe/softfloat.o nwfpe/fpa11.o nwfpe/fpa11_cpdo.o \ | |
232 | +OBJS+=nwfpe/fpa11.o nwfpe/fpa11_cpdo.o \ | |
233 | 233 | nwfpe/fpa11_cpdt.o nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o \ |
234 | 234 | nwfpe/double_cpdo.o nwfpe/extended_cpdo.o |
235 | 235 | endif |
... | ... | @@ -237,8 +237,14 @@ SRCS:= $(OBJS:.o=.c) |
237 | 237 | OBJS+= libqemu.a |
238 | 238 | |
239 | 239 | # cpu emulator library |
240 | -LIBOBJS=exec.o kqemu.o translate-all.o cpu-exec.o\ | |
240 | +LIBOBJS=exec.o kqemu.o translate-op.o translate-all.o cpu-exec.o\ | |
241 | 241 | translate.o op.o |
242 | +ifdef CONFIG_SOFTFLOAT | |
243 | +LIBOBJS+=fpu/softfloat.o | |
244 | +else | |
245 | +LIBOBJS+=fpu/softfloat-native.o | |
246 | +endif | |
247 | +DEFINES+=-I$(SRC_PATH)/fpu | |
242 | 248 | |
243 | 249 | ifeq ($(TARGET_ARCH), i386) |
244 | 250 | LIBOBJS+=helper.o helper2.o |
... | ... | @@ -399,7 +405,9 @@ libqemu.a: $(LIBOBJS) |
399 | 405 | |
400 | 406 | translate.o: translate.c gen-op.h opc.h cpu.h |
401 | 407 | |
402 | -translate-all.o: translate-all.c op.h opc.h cpu.h | |
408 | +translate-all.o: translate-all.c opc.h cpu.h | |
409 | + | |
410 | +translate-op.o: translate-all.c op.h opc.h cpu.h | |
403 | 411 | |
404 | 412 | op.h: op.o $(DYNGEN) |
405 | 413 | $(DYNGEN) -o $@ $< | ... | ... |
configure
... | ... | @@ -593,6 +593,7 @@ fi |
593 | 593 | #echo "Creating $config_mak, $config_h and $target_dir/Makefile" |
594 | 594 | |
595 | 595 | mkdir -p $target_dir |
596 | +mkdir -p $target_dir/fpu | |
596 | 597 | if test "$target" = "arm-user" -o "$target" = "armeb-user" ; then |
597 | 598 | mkdir -p $target_dir/nwfpe |
598 | 599 | fi |
... | ... | @@ -658,6 +659,10 @@ if test "$target_user_only" = "yes" ; then |
658 | 659 | echo "#define CONFIG_USER_ONLY 1" >> $config_h |
659 | 660 | fi |
660 | 661 | |
662 | +if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" ; then | |
663 | + echo "CONFIG_SOFTFLOAT=yes" >> $config_mak | |
664 | + echo "#define CONFIG_SOFTFLOAT 1" >> $config_h | |
665 | +fi | |
661 | 666 | # sdl defines |
662 | 667 | |
663 | 668 | if test "$target_user_only" = "no"; then | ... | ... |
fpu/softfloat-macros.h
0 → 100644
1 | + | |
2 | +/*============================================================================ | |
3 | + | |
4 | +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point | |
5 | +Arithmetic Package, Release 2b. | |
6 | + | |
7 | +Written by John R. Hauser. This work was made possible in part by the | |
8 | +International Computer Science Institute, located at Suite 600, 1947 Center | |
9 | +Street, Berkeley, California 94704. Funding was partially provided by the | |
10 | +National Science Foundation under grant MIP-9311980. The original version | |
11 | +of this code was written as part of a project to build a fixed-point vector | |
12 | +processor in collaboration with the University of California at Berkeley, | |
13 | +overseen by Profs. Nelson Morgan and John Wawrzynek. More information | |
14 | +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ | |
15 | +arithmetic/SoftFloat.html'. | |
16 | + | |
17 | +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has | |
18 | +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES | |
19 | +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS | |
20 | +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, | |
21 | +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE | |
22 | +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE | |
23 | +INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR | |
24 | +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. | |
25 | + | |
26 | +Derivative works are acceptable, even for commercial purposes, so long as | |
27 | +(1) the source code for the derivative work includes prominent notice that | |
28 | +the work is derivative, and (2) the source code includes prominent notice with | |
29 | +these four paragraphs for those parts of this code that are retained. | |
30 | + | |
31 | +=============================================================================*/ | |
32 | + | |
33 | +/*---------------------------------------------------------------------------- | |
34 | +| Shifts `a' right by the number of bits given in `count'. If any nonzero | |
35 | +| bits are shifted off, they are ``jammed'' into the least significant bit of | |
36 | +| the result by setting the least significant bit to 1. The value of `count' | |
37 | +| can be arbitrarily large; in particular, if `count' is greater than 32, the | |
38 | +| result will be either 0 or 1, depending on whether `a' is zero or nonzero. | |
39 | +| The result is stored in the location pointed to by `zPtr'. | |
40 | +*----------------------------------------------------------------------------*/ | |
41 | + | |
42 | +INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr ) | |
43 | +{ | |
44 | + bits32 z; | |
45 | + | |
46 | + if ( count == 0 ) { | |
47 | + z = a; | |
48 | + } | |
49 | + else if ( count < 32 ) { | |
50 | + z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 ); | |
51 | + } | |
52 | + else { | |
53 | + z = ( a != 0 ); | |
54 | + } | |
55 | + *zPtr = z; | |
56 | + | |
57 | +} | |
58 | + | |
59 | +/*---------------------------------------------------------------------------- | |
60 | +| Shifts `a' right by the number of bits given in `count'. If any nonzero | |
61 | +| bits are shifted off, they are ``jammed'' into the least significant bit of | |
62 | +| the result by setting the least significant bit to 1. The value of `count' | |
63 | +| can be arbitrarily large; in particular, if `count' is greater than 64, the | |
64 | +| result will be either 0 or 1, depending on whether `a' is zero or nonzero. | |
65 | +| The result is stored in the location pointed to by `zPtr'. | |
66 | +*----------------------------------------------------------------------------*/ | |
67 | + | |
68 | +INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr ) | |
69 | +{ | |
70 | + bits64 z; | |
71 | + | |
72 | + if ( count == 0 ) { | |
73 | + z = a; | |
74 | + } | |
75 | + else if ( count < 64 ) { | |
76 | + z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 ); | |
77 | + } | |
78 | + else { | |
79 | + z = ( a != 0 ); | |
80 | + } | |
81 | + *zPtr = z; | |
82 | + | |
83 | +} | |
84 | + | |
85 | +/*---------------------------------------------------------------------------- | |
86 | +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 | |
87 | +| _plus_ the number of bits given in `count'. The shifted result is at most | |
88 | +| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The | |
89 | +| bits shifted off form a second 64-bit result as follows: The _last_ bit | |
90 | +| shifted off is the most-significant bit of the extra result, and the other | |
91 | +| 63 bits of the extra result are all zero if and only if _all_but_the_last_ | |
92 | +| bits shifted off were all zero. This extra result is stored in the location | |
93 | +| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. | |
94 | +| (This routine makes more sense if `a0' and `a1' are considered to form | |
95 | +| a fixed-point value with binary point between `a0' and `a1'. This fixed- | |
96 | +| point value is shifted right by the number of bits given in `count', and | |
97 | +| the integer part of the result is returned at the location pointed to by | |
98 | +| `z0Ptr'. The fractional part of the result may be slightly corrupted as | |
99 | +| described above, and is returned at the location pointed to by `z1Ptr'.) | |
100 | +*----------------------------------------------------------------------------*/ | |
101 | + | |
102 | +INLINE void | |
103 | + shift64ExtraRightJamming( | |
104 | + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) | |
105 | +{ | |
106 | + bits64 z0, z1; | |
107 | + int8 negCount = ( - count ) & 63; | |
108 | + | |
109 | + if ( count == 0 ) { | |
110 | + z1 = a1; | |
111 | + z0 = a0; | |
112 | + } | |
113 | + else if ( count < 64 ) { | |
114 | + z1 = ( a0<<negCount ) | ( a1 != 0 ); | |
115 | + z0 = a0>>count; | |
116 | + } | |
117 | + else { | |
118 | + if ( count == 64 ) { | |
119 | + z1 = a0 | ( a1 != 0 ); | |
120 | + } | |
121 | + else { | |
122 | + z1 = ( ( a0 | a1 ) != 0 ); | |
123 | + } | |
124 | + z0 = 0; | |
125 | + } | |
126 | + *z1Ptr = z1; | |
127 | + *z0Ptr = z0; | |
128 | + | |
129 | +} | |
130 | + | |
131 | +/*---------------------------------------------------------------------------- | |
132 | +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the | |
133 | +| number of bits given in `count'. Any bits shifted off are lost. The value | |
134 | +| of `count' can be arbitrarily large; in particular, if `count' is greater | |
135 | +| than 128, the result will be 0. The result is broken into two 64-bit pieces | |
136 | +| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. | |
137 | +*----------------------------------------------------------------------------*/ | |
138 | + | |
139 | +INLINE void | |
140 | + shift128Right( | |
141 | + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) | |
142 | +{ | |
143 | + bits64 z0, z1; | |
144 | + int8 negCount = ( - count ) & 63; | |
145 | + | |
146 | + if ( count == 0 ) { | |
147 | + z1 = a1; | |
148 | + z0 = a0; | |
149 | + } | |
150 | + else if ( count < 64 ) { | |
151 | + z1 = ( a0<<negCount ) | ( a1>>count ); | |
152 | + z0 = a0>>count; | |
153 | + } | |
154 | + else { | |
155 | + z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0; | |
156 | + z0 = 0; | |
157 | + } | |
158 | + *z1Ptr = z1; | |
159 | + *z0Ptr = z0; | |
160 | + | |
161 | +} | |
162 | + | |
163 | +/*---------------------------------------------------------------------------- | |
164 | +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the | |
165 | +| number of bits given in `count'. If any nonzero bits are shifted off, they | |
166 | +| are ``jammed'' into the least significant bit of the result by setting the | |
167 | +| least significant bit to 1. The value of `count' can be arbitrarily large; | |
168 | +| in particular, if `count' is greater than 128, the result will be either | |
169 | +| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or | |
170 | +| nonzero. The result is broken into two 64-bit pieces which are stored at | |
171 | +| the locations pointed to by `z0Ptr' and `z1Ptr'. | |
172 | +*----------------------------------------------------------------------------*/ | |
173 | + | |
174 | +INLINE void | |
175 | + shift128RightJamming( | |
176 | + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) | |
177 | +{ | |
178 | + bits64 z0, z1; | |
179 | + int8 negCount = ( - count ) & 63; | |
180 | + | |
181 | + if ( count == 0 ) { | |
182 | + z1 = a1; | |
183 | + z0 = a0; | |
184 | + } | |
185 | + else if ( count < 64 ) { | |
186 | + z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 ); | |
187 | + z0 = a0>>count; | |
188 | + } | |
189 | + else { | |
190 | + if ( count == 64 ) { | |
191 | + z1 = a0 | ( a1 != 0 ); | |
192 | + } | |
193 | + else if ( count < 128 ) { | |
194 | + z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 ); | |
195 | + } | |
196 | + else { | |
197 | + z1 = ( ( a0 | a1 ) != 0 ); | |
198 | + } | |
199 | + z0 = 0; | |
200 | + } | |
201 | + *z1Ptr = z1; | |
202 | + *z0Ptr = z0; | |
203 | + | |
204 | +} | |
205 | + | |
206 | +/*---------------------------------------------------------------------------- | |
207 | +| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right | |
208 | +| by 64 _plus_ the number of bits given in `count'. The shifted result is | |
209 | +| at most 128 nonzero bits; these are broken into two 64-bit pieces which are | |
210 | +| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted | |
211 | +| off form a third 64-bit result as follows: The _last_ bit shifted off is | |
212 | +| the most-significant bit of the extra result, and the other 63 bits of the | |
213 | +| extra result are all zero if and only if _all_but_the_last_ bits shifted off | |
214 | +| were all zero. This extra result is stored in the location pointed to by | |
215 | +| `z2Ptr'. The value of `count' can be arbitrarily large. | |
216 | +| (This routine makes more sense if `a0', `a1', and `a2' are considered | |
217 | +| to form a fixed-point value with binary point between `a1' and `a2'. This | |
218 | +| fixed-point value is shifted right by the number of bits given in `count', | |
219 | +| and the integer part of the result is returned at the locations pointed to | |
220 | +| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly | |
221 | +| corrupted as described above, and is returned at the location pointed to by | |
222 | +| `z2Ptr'.) | |
223 | +*----------------------------------------------------------------------------*/ | |
224 | + | |
225 | +INLINE void | |
226 | + shift128ExtraRightJamming( | |
227 | + bits64 a0, | |
228 | + bits64 a1, | |
229 | + bits64 a2, | |
230 | + int16 count, | |
231 | + bits64 *z0Ptr, | |
232 | + bits64 *z1Ptr, | |
233 | + bits64 *z2Ptr | |
234 | + ) | |
235 | +{ | |
236 | + bits64 z0, z1, z2; | |
237 | + int8 negCount = ( - count ) & 63; | |
238 | + | |
239 | + if ( count == 0 ) { | |
240 | + z2 = a2; | |
241 | + z1 = a1; | |
242 | + z0 = a0; | |
243 | + } | |
244 | + else { | |
245 | + if ( count < 64 ) { | |
246 | + z2 = a1<<negCount; | |
247 | + z1 = ( a0<<negCount ) | ( a1>>count ); | |
248 | + z0 = a0>>count; | |
249 | + } | |
250 | + else { | |
251 | + if ( count == 64 ) { | |
252 | + z2 = a1; | |
253 | + z1 = a0; | |
254 | + } | |
255 | + else { | |
256 | + a2 |= a1; | |
257 | + if ( count < 128 ) { | |
258 | + z2 = a0<<negCount; | |
259 | + z1 = a0>>( count & 63 ); | |
260 | + } | |
261 | + else { | |
262 | + z2 = ( count == 128 ) ? a0 : ( a0 != 0 ); | |
263 | + z1 = 0; | |
264 | + } | |
265 | + } | |
266 | + z0 = 0; | |
267 | + } | |
268 | + z2 |= ( a2 != 0 ); | |
269 | + } | |
270 | + *z2Ptr = z2; | |
271 | + *z1Ptr = z1; | |
272 | + *z0Ptr = z0; | |
273 | + | |
274 | +} | |
275 | + | |
276 | +/*---------------------------------------------------------------------------- | |
277 | +| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the | |
278 | +| number of bits given in `count'. Any bits shifted off are lost. The value | |
279 | +| of `count' must be less than 64. The result is broken into two 64-bit | |
280 | +| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. | |
281 | +*----------------------------------------------------------------------------*/ | |
282 | + | |
283 | +INLINE void | |
284 | + shortShift128Left( | |
285 | + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) | |
286 | +{ | |
287 | + | |
288 | + *z1Ptr = a1<<count; | |
289 | + *z0Ptr = | |
290 | + ( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 63 ) ); | |
291 | + | |
292 | +} | |
293 | + | |
294 | +/*---------------------------------------------------------------------------- | |
295 | +| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left | |
296 | +| by the number of bits given in `count'. Any bits shifted off are lost. | |
297 | +| The value of `count' must be less than 64. The result is broken into three | |
298 | +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', | |
299 | +| `z1Ptr', and `z2Ptr'. | |
300 | +*----------------------------------------------------------------------------*/ | |
301 | + | |
302 | +INLINE void | |
303 | + shortShift192Left( | |
304 | + bits64 a0, | |
305 | + bits64 a1, | |
306 | + bits64 a2, | |
307 | + int16 count, | |
308 | + bits64 *z0Ptr, | |
309 | + bits64 *z1Ptr, | |
310 | + bits64 *z2Ptr | |
311 | + ) | |
312 | +{ | |
313 | + bits64 z0, z1, z2; | |
314 | + int8 negCount; | |
315 | + | |
316 | + z2 = a2<<count; | |
317 | + z1 = a1<<count; | |
318 | + z0 = a0<<count; | |
319 | + if ( 0 < count ) { | |
320 | + negCount = ( ( - count ) & 63 ); | |
321 | + z1 |= a2>>negCount; | |
322 | + z0 |= a1>>negCount; | |
323 | + } | |
324 | + *z2Ptr = z2; | |
325 | + *z1Ptr = z1; | |
326 | + *z0Ptr = z0; | |
327 | + | |
328 | +} | |
329 | + | |
330 | +/*---------------------------------------------------------------------------- | |
331 | +| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit | |
332 | +| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so | |
333 | +| any carry out is lost. The result is broken into two 64-bit pieces which | |
334 | +| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. | |
335 | +*----------------------------------------------------------------------------*/ | |
336 | + | |
337 | +INLINE void | |
338 | + add128( | |
339 | + bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) | |
340 | +{ | |
341 | + bits64 z1; | |
342 | + | |
343 | + z1 = a1 + b1; | |
344 | + *z1Ptr = z1; | |
345 | + *z0Ptr = a0 + b0 + ( z1 < a1 ); | |
346 | + | |
347 | +} | |
348 | + | |
349 | +/*---------------------------------------------------------------------------- | |
350 | +| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the | |
351 | +| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is | |
352 | +| modulo 2^192, so any carry out is lost. The result is broken into three | |
353 | +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', | |
354 | +| `z1Ptr', and `z2Ptr'. | |
355 | +*----------------------------------------------------------------------------*/ | |
356 | + | |
357 | +INLINE void | |
358 | + add192( | |
359 | + bits64 a0, | |
360 | + bits64 a1, | |
361 | + bits64 a2, | |
362 | + bits64 b0, | |
363 | + bits64 b1, | |
364 | + bits64 b2, | |
365 | + bits64 *z0Ptr, | |
366 | + bits64 *z1Ptr, | |
367 | + bits64 *z2Ptr | |
368 | + ) | |
369 | +{ | |
370 | + bits64 z0, z1, z2; | |
371 | + int8 carry0, carry1; | |
372 | + | |
373 | + z2 = a2 + b2; | |
374 | + carry1 = ( z2 < a2 ); | |
375 | + z1 = a1 + b1; | |
376 | + carry0 = ( z1 < a1 ); | |
377 | + z0 = a0 + b0; | |
378 | + z1 += carry1; | |
379 | + z0 += ( z1 < carry1 ); | |
380 | + z0 += carry0; | |
381 | + *z2Ptr = z2; | |
382 | + *z1Ptr = z1; | |
383 | + *z0Ptr = z0; | |
384 | + | |
385 | +} | |
386 | + | |
387 | +/*---------------------------------------------------------------------------- | |
388 | +| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the | |
389 | +| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo | |
390 | +| 2^128, so any borrow out (carry out) is lost. The result is broken into two | |
391 | +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and | |
392 | +| `z1Ptr'. | |
393 | +*----------------------------------------------------------------------------*/ | |
394 | + | |
395 | +INLINE void | |
396 | + sub128( | |
397 | + bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) | |
398 | +{ | |
399 | + | |
400 | + *z1Ptr = a1 - b1; | |
401 | + *z0Ptr = a0 - b0 - ( a1 < b1 ); | |
402 | + | |
403 | +} | |
404 | + | |
405 | +/*---------------------------------------------------------------------------- | |
406 | +| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' | |
407 | +| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. | |
408 | +| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The | |
409 | +| result is broken into three 64-bit pieces which are stored at the locations | |
410 | +| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. | |
411 | +*----------------------------------------------------------------------------*/ | |
412 | + | |
413 | +INLINE void | |
414 | + sub192( | |
415 | + bits64 a0, | |
416 | + bits64 a1, | |
417 | + bits64 a2, | |
418 | + bits64 b0, | |
419 | + bits64 b1, | |
420 | + bits64 b2, | |
421 | + bits64 *z0Ptr, | |
422 | + bits64 *z1Ptr, | |
423 | + bits64 *z2Ptr | |
424 | + ) | |
425 | +{ | |
426 | + bits64 z0, z1, z2; | |
427 | + int8 borrow0, borrow1; | |
428 | + | |
429 | + z2 = a2 - b2; | |
430 | + borrow1 = ( a2 < b2 ); | |
431 | + z1 = a1 - b1; | |
432 | + borrow0 = ( a1 < b1 ); | |
433 | + z0 = a0 - b0; | |
434 | + z0 -= ( z1 < borrow1 ); | |
435 | + z1 -= borrow1; | |
436 | + z0 -= borrow0; | |
437 | + *z2Ptr = z2; | |
438 | + *z1Ptr = z1; | |
439 | + *z0Ptr = z0; | |
440 | + | |
441 | +} | |
442 | + | |
443 | +/*---------------------------------------------------------------------------- | |
444 | +| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken | |
445 | +| into two 64-bit pieces which are stored at the locations pointed to by | |
446 | +| `z0Ptr' and `z1Ptr'. | |
447 | +*----------------------------------------------------------------------------*/ | |
448 | + | |
449 | +INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr ) | |
450 | +{ | |
451 | + bits32 aHigh, aLow, bHigh, bLow; | |
452 | + bits64 z0, zMiddleA, zMiddleB, z1; | |
453 | + | |
454 | + aLow = a; | |
455 | + aHigh = a>>32; | |
456 | + bLow = b; | |
457 | + bHigh = b>>32; | |
458 | + z1 = ( (bits64) aLow ) * bLow; | |
459 | + zMiddleA = ( (bits64) aLow ) * bHigh; | |
460 | + zMiddleB = ( (bits64) aHigh ) * bLow; | |
461 | + z0 = ( (bits64) aHigh ) * bHigh; | |
462 | + zMiddleA += zMiddleB; | |
463 | + z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 ); | |
464 | + zMiddleA <<= 32; | |
465 | + z1 += zMiddleA; | |
466 | + z0 += ( z1 < zMiddleA ); | |
467 | + *z1Ptr = z1; | |
468 | + *z0Ptr = z0; | |
469 | + | |
470 | +} | |
471 | + | |
472 | +/*---------------------------------------------------------------------------- | |
473 | +| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by | |
474 | +| `b' to obtain a 192-bit product. The product is broken into three 64-bit | |
475 | +| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and | |
476 | +| `z2Ptr'. | |
477 | +*----------------------------------------------------------------------------*/ | |
478 | + | |
479 | +INLINE void | |
480 | + mul128By64To192( | |
481 | + bits64 a0, | |
482 | + bits64 a1, | |
483 | + bits64 b, | |
484 | + bits64 *z0Ptr, | |
485 | + bits64 *z1Ptr, | |
486 | + bits64 *z2Ptr | |
487 | + ) | |
488 | +{ | |
489 | + bits64 z0, z1, z2, more1; | |
490 | + | |
491 | + mul64To128( a1, b, &z1, &z2 ); | |
492 | + mul64To128( a0, b, &z0, &more1 ); | |
493 | + add128( z0, more1, 0, z1, &z0, &z1 ); | |
494 | + *z2Ptr = z2; | |
495 | + *z1Ptr = z1; | |
496 | + *z0Ptr = z0; | |
497 | + | |
498 | +} | |
499 | + | |
500 | +/*---------------------------------------------------------------------------- | |
501 | +| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the | |
502 | +| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit | |
503 | +| product. The product is broken into four 64-bit pieces which are stored at | |
504 | +| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. | |
505 | +*----------------------------------------------------------------------------*/ | |
506 | + | |
507 | +INLINE void | |
508 | + mul128To256( | |
509 | + bits64 a0, | |
510 | + bits64 a1, | |
511 | + bits64 b0, | |
512 | + bits64 b1, | |
513 | + bits64 *z0Ptr, | |
514 | + bits64 *z1Ptr, | |
515 | + bits64 *z2Ptr, | |
516 | + bits64 *z3Ptr | |
517 | + ) | |
518 | +{ | |
519 | + bits64 z0, z1, z2, z3; | |
520 | + bits64 more1, more2; | |
521 | + | |
522 | + mul64To128( a1, b1, &z2, &z3 ); | |
523 | + mul64To128( a1, b0, &z1, &more2 ); | |
524 | + add128( z1, more2, 0, z2, &z1, &z2 ); | |
525 | + mul64To128( a0, b0, &z0, &more1 ); | |
526 | + add128( z0, more1, 0, z1, &z0, &z1 ); | |
527 | + mul64To128( a0, b1, &more1, &more2 ); | |
528 | + add128( more1, more2, 0, z2, &more1, &z2 ); | |
529 | + add128( z0, z1, 0, more1, &z0, &z1 ); | |
530 | + *z3Ptr = z3; | |
531 | + *z2Ptr = z2; | |
532 | + *z1Ptr = z1; | |
533 | + *z0Ptr = z0; | |
534 | + | |
535 | +} | |
536 | + | |
537 | +/*---------------------------------------------------------------------------- | |
538 | +| Returns an approximation to the 64-bit integer quotient obtained by dividing | |
539 | +| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The | |
540 | +| divisor `b' must be at least 2^63. If q is the exact quotient truncated | |
541 | +| toward zero, the approximation returned lies between q and q + 2 inclusive. | |
542 | +| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit | |
543 | +| unsigned integer is returned. | |
544 | +*----------------------------------------------------------------------------*/ | |
545 | + | |
546 | +static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b ) | |
547 | +{ | |
548 | + bits64 b0, b1; | |
549 | + bits64 rem0, rem1, term0, term1; | |
550 | + bits64 z; | |
551 | + | |
552 | + if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF ); | |
553 | + b0 = b>>32; | |
554 | + z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32; | |
555 | + mul64To128( b, z, &term0, &term1 ); | |
556 | + sub128( a0, a1, term0, term1, &rem0, &rem1 ); | |
557 | + while ( ( (sbits64) rem0 ) < 0 ) { | |
558 | + z -= LIT64( 0x100000000 ); | |
559 | + b1 = b<<32; | |
560 | + add128( rem0, rem1, b0, b1, &rem0, &rem1 ); | |
561 | + } | |
562 | + rem0 = ( rem0<<32 ) | ( rem1>>32 ); | |
563 | + z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0; | |
564 | + return z; | |
565 | + | |
566 | +} | |
567 | + | |
568 | +/*---------------------------------------------------------------------------- | |
569 | +| Returns an approximation to the square root of the 32-bit significand given | |
570 | +| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of | |
571 | +| `aExp' (the least significant bit) is 1, the integer returned approximates | |
572 | +| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' | |
573 | +| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either | |
574 | +| case, the approximation returned lies strictly within +/-2 of the exact | |
575 | +| value. | |
576 | +*----------------------------------------------------------------------------*/ | |
577 | + | |
578 | +static bits32 estimateSqrt32( int16 aExp, bits32 a ) | |
579 | +{ | |
580 | + static const bits16 sqrtOddAdjustments[] = { | |
581 | + 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, | |
582 | + 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 | |
583 | + }; | |
584 | + static const bits16 sqrtEvenAdjustments[] = { | |
585 | + 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, | |
586 | + 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 | |
587 | + }; | |
588 | + int8 index; | |
589 | + bits32 z; | |
590 | + | |
591 | + index = ( a>>27 ) & 15; | |
592 | + if ( aExp & 1 ) { | |
593 | + z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; | |
594 | + z = ( ( a / z )<<14 ) + ( z<<15 ); | |
595 | + a >>= 1; | |
596 | + } | |
597 | + else { | |
598 | + z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; | |
599 | + z = a / z + z; | |
600 | + z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 ); | |
601 | + if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 ); | |
602 | + } | |
603 | + return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 ); | |
604 | + | |
605 | +} | |
606 | + | |
607 | +/*---------------------------------------------------------------------------- | |
608 | +| Returns the number of leading 0 bits before the most-significant 1 bit of | |
609 | +| `a'. If `a' is zero, 32 is returned. | |
610 | +*----------------------------------------------------------------------------*/ | |
611 | + | |
612 | +static int8 countLeadingZeros32( bits32 a ) | |
613 | +{ | |
614 | + static const int8 countLeadingZerosHigh[] = { | |
615 | + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, | |
616 | + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, | |
617 | + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
618 | + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
619 | + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
620 | + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
621 | + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
622 | + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
623 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
624 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
625 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
626 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
627 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
628 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
629 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
630 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
631 | + }; | |
632 | + int8 shiftCount; | |
633 | + | |
634 | + shiftCount = 0; | |
635 | + if ( a < 0x10000 ) { | |
636 | + shiftCount += 16; | |
637 | + a <<= 16; | |
638 | + } | |
639 | + if ( a < 0x1000000 ) { | |
640 | + shiftCount += 8; | |
641 | + a <<= 8; | |
642 | + } | |
643 | + shiftCount += countLeadingZerosHigh[ a>>24 ]; | |
644 | + return shiftCount; | |
645 | + | |
646 | +} | |
647 | + | |
648 | +/*---------------------------------------------------------------------------- | |
649 | +| Returns the number of leading 0 bits before the most-significant 1 bit of | |
650 | +| `a'. If `a' is zero, 64 is returned. | |
651 | +*----------------------------------------------------------------------------*/ | |
652 | + | |
653 | +static int8 countLeadingZeros64( bits64 a ) | |
654 | +{ | |
655 | + int8 shiftCount; | |
656 | + | |
657 | + shiftCount = 0; | |
658 | + if ( a < ( (bits64) 1 )<<32 ) { | |
659 | + shiftCount += 32; | |
660 | + } | |
661 | + else { | |
662 | + a >>= 32; | |
663 | + } | |
664 | + shiftCount += countLeadingZeros32( a ); | |
665 | + return shiftCount; | |
666 | + | |
667 | +} | |
668 | + | |
669 | +/*---------------------------------------------------------------------------- | |
670 | +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' | |
671 | +| is equal to the 128-bit value formed by concatenating `b0' and `b1'. | |
672 | +| Otherwise, returns 0. | |
673 | +*----------------------------------------------------------------------------*/ | |
674 | + | |
675 | +INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) | |
676 | +{ | |
677 | + | |
678 | + return ( a0 == b0 ) && ( a1 == b1 ); | |
679 | + | |
680 | +} | |
681 | + | |
682 | +/*---------------------------------------------------------------------------- | |
683 | +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less | |
684 | +| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. | |
685 | +| Otherwise, returns 0. | |
686 | +*----------------------------------------------------------------------------*/ | |
687 | + | |
688 | +INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) | |
689 | +{ | |
690 | + | |
691 | + return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) ); | |
692 | + | |
693 | +} | |
694 | + | |
695 | +/*---------------------------------------------------------------------------- | |
696 | +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less | |
697 | +| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, | |
698 | +| returns 0. | |
699 | +*----------------------------------------------------------------------------*/ | |
700 | + | |
701 | +INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) | |
702 | +{ | |
703 | + | |
704 | + return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) ); | |
705 | + | |
706 | +} | |
707 | + | |
708 | +/*---------------------------------------------------------------------------- | |
709 | +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is | |
710 | +| not equal to the 128-bit value formed by concatenating `b0' and `b1'. | |
711 | +| Otherwise, returns 0. | |
712 | +*----------------------------------------------------------------------------*/ | |
713 | + | |
714 | +INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) | |
715 | +{ | |
716 | + | |
717 | + return ( a0 != b0 ) || ( a1 != b1 ); | |
718 | + | |
719 | +} | |
720 | + | ... | ... |
fpu/softfloat-native.c
0 → 100644
1 | +/* Native implementation of soft float functions. Only a single status | |
2 | + context is supported */ | |
3 | +#include "softfloat.h" | |
4 | +#include <math.h> | |
5 | + | |
6 | +void set_float_rounding_mode(int val STATUS_PARAM) | |
7 | +{ | |
8 | + STATUS(float_rounding_mode) = val; | |
9 | +#if defined(_BSD) && !defined(__APPLE__) | |
10 | + fpsetround(val); | |
11 | +#elif defined(__arm__) | |
12 | + /* nothing to do */ | |
13 | +#else | |
14 | + fesetround(val); | |
15 | +#endif | |
16 | +} | |
17 | + | |
18 | +#ifdef FLOATX80 | |
19 | +void set_floatx80_rounding_precision(int val STATUS_PARAM) | |
20 | +{ | |
21 | + STATUS(floatx80_rounding_precision) = val; | |
22 | +} | |
23 | +#endif | |
24 | + | |
25 | +#if defined(_BSD) | |
26 | +#define lrint(d) ((int32_t)rint(d)) | |
27 | +#define llrint(d) ((int64_t)rint(d)) | |
28 | +#endif | |
29 | + | |
30 | +#if defined(__powerpc__) | |
31 | + | |
32 | +/* correct (but slow) PowerPC rint() (glibc version is incorrect) */ | |
33 | +double qemu_rint(double x) | |
34 | +{ | |
35 | + double y = 4503599627370496.0; | |
36 | + if (fabs(x) >= y) | |
37 | + return x; | |
38 | + if (x < 0) | |
39 | + y = -y; | |
40 | + y = (x + y) - y; | |
41 | + if (y == 0.0) | |
42 | + y = copysign(y, x); | |
43 | + return y; | |
44 | +} | |
45 | + | |
46 | +#define rint qemu_rint | |
47 | +#endif | |
48 | + | |
49 | +/*---------------------------------------------------------------------------- | |
50 | +| Software IEC/IEEE integer-to-floating-point conversion routines. | |
51 | +*----------------------------------------------------------------------------*/ | |
52 | +float32 int32_to_float32(int v STATUS_PARAM) | |
53 | +{ | |
54 | + return (float32)v; | |
55 | +} | |
56 | + | |
57 | +float64 int32_to_float64(int v STATUS_PARAM) | |
58 | +{ | |
59 | + return (float64)v; | |
60 | +} | |
61 | + | |
62 | +#ifdef FLOATX80 | |
63 | +floatx80 int32_to_floatx80(int v STATUS_PARAM) | |
64 | +{ | |
65 | + return (floatx80)v; | |
66 | +} | |
67 | +#endif | |
68 | +float32 int64_to_float32( int64_t v STATUS_PARAM) | |
69 | +{ | |
70 | + return (float32)v; | |
71 | +} | |
72 | +float64 int64_to_float64( int64_t v STATUS_PARAM) | |
73 | +{ | |
74 | + return (float64)v; | |
75 | +} | |
76 | +#ifdef FLOATX80 | |
77 | +floatx80 int64_to_floatx80( int64_t v STATUS_PARAM) | |
78 | +{ | |
79 | + return (floatx80)v; | |
80 | +} | |
81 | +#endif | |
82 | + | |
83 | +/*---------------------------------------------------------------------------- | |
84 | +| Software IEC/IEEE single-precision conversion routines. | |
85 | +*----------------------------------------------------------------------------*/ | |
86 | +int float32_to_int32( float32 a STATUS_PARAM) | |
87 | +{ | |
88 | + return lrintf(a); | |
89 | +} | |
90 | +int float32_to_int32_round_to_zero( float32 a STATUS_PARAM) | |
91 | +{ | |
92 | + return (int)a; | |
93 | +} | |
94 | +int64_t float32_to_int64( float32 a STATUS_PARAM) | |
95 | +{ | |
96 | + return llrintf(a); | |
97 | +} | |
98 | + | |
99 | +int64_t float32_to_int64_round_to_zero( float32 a STATUS_PARAM) | |
100 | +{ | |
101 | + return (int64_t)a; | |
102 | +} | |
103 | + | |
104 | +float64 float32_to_float64( float32 a STATUS_PARAM) | |
105 | +{ | |
106 | + return a; | |
107 | +} | |
108 | +#ifdef FLOATX80 | |
109 | +floatx80 float32_to_floatx80( float32 a STATUS_PARAM) | |
110 | +{ | |
111 | + return a; | |
112 | +} | |
113 | +#endif | |
114 | + | |
115 | +/*---------------------------------------------------------------------------- | |
116 | +| Software IEC/IEEE single-precision operations. | |
117 | +*----------------------------------------------------------------------------*/ | |
118 | +float32 float32_round_to_int( float32 a STATUS_PARAM) | |
119 | +{ | |
120 | + return rintf(a); | |
121 | +} | |
122 | + | |
123 | +float32 float32_sqrt( float32 a STATUS_PARAM) | |
124 | +{ | |
125 | + return sqrtf(a); | |
126 | +} | |
127 | +char float32_is_signaling_nan( float32 a1) | |
128 | +{ | |
129 | + float32u u; | |
130 | + uint32_t a; | |
131 | + u.f = a1; | |
132 | + a = u.i; | |
133 | + return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); | |
134 | +} | |
135 | + | |
136 | +/*---------------------------------------------------------------------------- | |
137 | +| Software IEC/IEEE double-precision conversion routines. | |
138 | +*----------------------------------------------------------------------------*/ | |
139 | +int float64_to_int32( float64 a STATUS_PARAM) | |
140 | +{ | |
141 | + return lrint(a); | |
142 | +} | |
143 | +int float64_to_int32_round_to_zero( float64 a STATUS_PARAM) | |
144 | +{ | |
145 | + return (int)a; | |
146 | +} | |
147 | +int64_t float64_to_int64( float64 a STATUS_PARAM) | |
148 | +{ | |
149 | + return llrint(a); | |
150 | +} | |
151 | +int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM) | |
152 | +{ | |
153 | + return (int64_t)a; | |
154 | +} | |
155 | +float32 float64_to_float32( float64 a STATUS_PARAM) | |
156 | +{ | |
157 | + return a; | |
158 | +} | |
159 | +#ifdef FLOATX80 | |
160 | +floatx80 float64_to_floatx80( float64 a STATUS_PARAM) | |
161 | +{ | |
162 | + return a; | |
163 | +} | |
164 | +#endif | |
165 | +#ifdef FLOAT128 | |
166 | +float128 float64_to_float128( float64 a STATUS_PARAM) | |
167 | +{ | |
168 | + return a; | |
169 | +} | |
170 | +#endif | |
171 | + | |
172 | +/*---------------------------------------------------------------------------- | |
173 | +| Software IEC/IEEE double-precision operations. | |
174 | +*----------------------------------------------------------------------------*/ | |
175 | +float64 float64_round_to_int( float64 a STATUS_PARAM ) | |
176 | +{ | |
177 | +#if defined(__arm__) | |
178 | + switch(STATUS(float_rounding_mode)) { | |
179 | + default: | |
180 | + case float_round_nearest_even: | |
181 | + asm("rndd %0, %1" : "=f" (a) : "f"(a)); | |
182 | + break; | |
183 | + case float_round_down: | |
184 | + asm("rnddm %0, %1" : "=f" (a) : "f"(a)); | |
185 | + break; | |
186 | + case float_round_up: | |
187 | + asm("rnddp %0, %1" : "=f" (a) : "f"(a)); | |
188 | + break; | |
189 | + case float_round_to_zero: | |
190 | + asm("rnddz %0, %1" : "=f" (a) : "f"(a)); | |
191 | + break; | |
192 | + } | |
193 | +#else | |
194 | + return rint(a); | |
195 | +#endif | |
196 | +} | |
197 | + | |
198 | +float64 float64_sqrt( float64 a STATUS_PARAM) | |
199 | +{ | |
200 | + return sqrt(a); | |
201 | +} | |
202 | +char float64_is_signaling_nan( float64 a1) | |
203 | +{ | |
204 | + float64u u; | |
205 | + uint64_t a; | |
206 | + u.f = a1; | |
207 | + a = u.i; | |
208 | + return | |
209 | + ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) | |
210 | + && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); | |
211 | + | |
212 | +} | |
213 | + | |
214 | +#ifdef FLOATX80 | |
215 | + | |
216 | +/*---------------------------------------------------------------------------- | |
217 | +| Software IEC/IEEE extended double-precision conversion routines. | |
218 | +*----------------------------------------------------------------------------*/ | |
219 | +int floatx80_to_int32( floatx80 a STATUS_PARAM) | |
220 | +{ | |
221 | + return lrintl(a); | |
222 | +} | |
223 | +int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM) | |
224 | +{ | |
225 | + return (int)a; | |
226 | +} | |
227 | +int64_t floatx80_to_int64( floatx80 a STATUS_PARAM) | |
228 | +{ | |
229 | + return llrintl(a); | |
230 | +} | |
231 | +int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM) | |
232 | +{ | |
233 | + return (int64_t)a; | |
234 | +} | |
235 | +float32 floatx80_to_float32( floatx80 a STATUS_PARAM) | |
236 | +{ | |
237 | + return a; | |
238 | +} | |
239 | +float64 floatx80_to_float64( floatx80 a STATUS_PARAM) | |
240 | +{ | |
241 | + return a; | |
242 | +} | |
243 | + | |
244 | +/*---------------------------------------------------------------------------- | |
245 | +| Software IEC/IEEE extended double-precision operations. | |
246 | +*----------------------------------------------------------------------------*/ | |
247 | +floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM) | |
248 | +{ | |
249 | + return rintl(a); | |
250 | +} | |
251 | +floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM) | |
252 | +{ | |
253 | + return sqrtl(a); | |
254 | +} | |
255 | +char floatx80_is_signaling_nan( floatx80 a1) | |
256 | +{ | |
257 | + floatx80u u; | |
258 | + u.f = a1; | |
259 | + return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 ); | |
260 | +} | |
261 | + | |
262 | +#endif | ... | ... |
fpu/softfloat-native.h
0 → 100644
1 | +/* Native implementation of soft float functions */ | |
2 | +#include <math.h> | |
3 | +#if defined(_BSD) && !defined(__APPLE__) | |
4 | +#include <ieeefp.h> | |
5 | +#else | |
6 | +#include <fenv.h> | |
7 | +#endif | |
8 | + | |
9 | +typedef float float32; | |
10 | +typedef double float64; | |
11 | +#ifdef FLOATX80 | |
12 | +typedef long double floatx80; | |
13 | +#endif | |
14 | + | |
15 | +typedef union { | |
16 | + float32 f; | |
17 | + uint32_t i; | |
18 | +} float32u; | |
19 | +typedef union { | |
20 | + float64 f; | |
21 | + uint64_t i; | |
22 | +} float64u; | |
23 | +#ifdef FLOATX80 | |
24 | +typedef union { | |
25 | + floatx80 f; | |
26 | + struct { | |
27 | + uint64_t low; | |
28 | + uint16_t high; | |
29 | + } i; | |
30 | +} floatx80u; | |
31 | +#endif | |
32 | + | |
33 | +/*---------------------------------------------------------------------------- | |
34 | +| Software IEC/IEEE floating-point rounding mode. | |
35 | +*----------------------------------------------------------------------------*/ | |
36 | +#if defined(_BSD) && !defined(__APPLE__) | |
37 | +enum { | |
38 | + float_round_nearest_even = FP_RN, | |
39 | + float_round_down = FE_RM, | |
40 | + float_round_up = FE_RP, | |
41 | + float_round_to_zero = FE_RZ | |
42 | +}; | |
43 | +#elif defined(__arm__) | |
44 | +enum { | |
45 | + float_round_nearest_even = 0, | |
46 | + float_round_down = 1, | |
47 | + float_round_up = 2, | |
48 | + float_round_to_zero = 3 | |
49 | +}; | |
50 | +#else | |
51 | +enum { | |
52 | + float_round_nearest_even = FE_TONEAREST, | |
53 | + float_round_down = FE_DOWNWARD, | |
54 | + float_round_up = FE_UPWARD, | |
55 | + float_round_to_zero = FE_TOWARDZERO | |
56 | +}; | |
57 | +#endif | |
58 | + | |
59 | +typedef struct float_status { | |
60 | + signed char float_rounding_mode; | |
61 | +#ifdef FLOATX80 | |
62 | + signed char floatx80_rounding_precision; | |
63 | +#endif | |
64 | +} float_status; | |
65 | + | |
66 | +void set_float_rounding_mode(int val STATUS_PARAM); | |
67 | +#ifdef FLOATX80 | |
68 | +void set_floatx80_rounding_precision(int val STATUS_PARAM); | |
69 | +#endif | |
70 | + | |
71 | +/*---------------------------------------------------------------------------- | |
72 | +| Software IEC/IEEE integer-to-floating-point conversion routines. | |
73 | +*----------------------------------------------------------------------------*/ | |
74 | +float32 int32_to_float32( int STATUS_PARAM); | |
75 | +float64 int32_to_float64( int STATUS_PARAM); | |
76 | +#ifdef FLOATX80 | |
77 | +floatx80 int32_to_floatx80( int STATUS_PARAM); | |
78 | +#endif | |
79 | +#ifdef FLOAT128 | |
80 | +float128 int32_to_float128( int STATUS_PARAM); | |
81 | +#endif | |
82 | +float32 int64_to_float32( int64_t STATUS_PARAM); | |
83 | +float64 int64_to_float64( int64_t STATUS_PARAM); | |
84 | +#ifdef FLOATX80 | |
85 | +floatx80 int64_to_floatx80( int64_t STATUS_PARAM); | |
86 | +#endif | |
87 | +#ifdef FLOAT128 | |
88 | +float128 int64_to_float128( int64_t STATUS_PARAM); | |
89 | +#endif | |
90 | + | |
91 | +/*---------------------------------------------------------------------------- | |
92 | +| Software IEC/IEEE single-precision conversion routines. | |
93 | +*----------------------------------------------------------------------------*/ | |
94 | +int float32_to_int32( float32 STATUS_PARAM); | |
95 | +int float32_to_int32_round_to_zero( float32 STATUS_PARAM); | |
96 | +int64_t float32_to_int64( float32 STATUS_PARAM); | |
97 | +int64_t float32_to_int64_round_to_zero( float32 STATUS_PARAM); | |
98 | +float64 float32_to_float64( float32 STATUS_PARAM); | |
99 | +#ifdef FLOATX80 | |
100 | +floatx80 float32_to_floatx80( float32 STATUS_PARAM); | |
101 | +#endif | |
102 | +#ifdef FLOAT128 | |
103 | +float128 float32_to_float128( float32 STATUS_PARAM); | |
104 | +#endif | |
105 | + | |
106 | +/*---------------------------------------------------------------------------- | |
107 | +| Software IEC/IEEE single-precision operations. | |
108 | +*----------------------------------------------------------------------------*/ | |
109 | +float32 float32_round_to_int( float32 STATUS_PARAM); | |
110 | +INLINE float32 float32_add( float32 a, float32 b STATUS_PARAM) | |
111 | +{ | |
112 | + return a + b; | |
113 | +} | |
114 | +INLINE float32 float32_sub( float32 a, float32 b STATUS_PARAM) | |
115 | +{ | |
116 | + return a - b; | |
117 | +} | |
118 | +INLINE float32 float32_mul( float32 a, float32 b STATUS_PARAM) | |
119 | +{ | |
120 | + return a * b; | |
121 | +} | |
122 | +INLINE float32 float32_div( float32 a, float32 b STATUS_PARAM) | |
123 | +{ | |
124 | + return a / b; | |
125 | +} | |
126 | +float32 float32_rem( float32, float32 STATUS_PARAM); | |
127 | +float32 float32_sqrt( float32 STATUS_PARAM); | |
128 | +INLINE char float32_eq( float32 a, float32 b STATUS_PARAM) | |
129 | +{ | |
130 | + /* XXX: incorrect because it can raise an exception */ | |
131 | + return a == b; | |
132 | +} | |
133 | +INLINE char float32_le( float32 a, float32 b STATUS_PARAM) | |
134 | +{ | |
135 | + return a <= b; | |
136 | +} | |
137 | +INLINE char float32_lt( float32 a, float32 b STATUS_PARAM) | |
138 | +{ | |
139 | + return a < b; | |
140 | +} | |
141 | +INLINE char float32_eq_signaling( float32 a, float32 b STATUS_PARAM) | |
142 | +{ | |
143 | + return a == b; | |
144 | +} | |
145 | +INLINE char float32_le_quiet( float32 a, float32 b STATUS_PARAM) | |
146 | +{ | |
147 | + return islessequal(a, b); | |
148 | +} | |
149 | +INLINE char float32_lt_quiet( float32 a, float32 b STATUS_PARAM) | |
150 | +{ | |
151 | + return isless(a, b); | |
152 | +} | |
153 | +char float32_is_signaling_nan( float32 ); | |
154 | + | |
155 | +INLINE float32 float32_abs(float32 a) | |
156 | +{ | |
157 | + return fabsf(a); | |
158 | +} | |
159 | + | |
160 | +INLINE float32 float32_chs(float32 a) | |
161 | +{ | |
162 | + return -a; | |
163 | +} | |
164 | + | |
165 | +/*---------------------------------------------------------------------------- | |
166 | +| Software IEC/IEEE double-precision conversion routines. | |
167 | +*----------------------------------------------------------------------------*/ | |
168 | +int float64_to_int32( float64 STATUS_PARAM ); | |
169 | +int float64_to_int32_round_to_zero( float64 STATUS_PARAM ); | |
170 | +int64_t float64_to_int64( float64 STATUS_PARAM ); | |
171 | +int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM ); | |
172 | +float32 float64_to_float32( float64 STATUS_PARAM ); | |
173 | +#ifdef FLOATX80 | |
174 | +floatx80 float64_to_floatx80( float64 STATUS_PARAM ); | |
175 | +#endif | |
176 | +#ifdef FLOAT128 | |
177 | +float128 float64_to_float128( float64 STATUS_PARAM ); | |
178 | +#endif | |
179 | + | |
180 | +/*---------------------------------------------------------------------------- | |
181 | +| Software IEC/IEEE double-precision operations. | |
182 | +*----------------------------------------------------------------------------*/ | |
183 | +float64 float64_round_to_int( float64 STATUS_PARAM ); | |
184 | +INLINE float64 float64_add( float64 a, float64 b STATUS_PARAM) | |
185 | +{ | |
186 | + return a + b; | |
187 | +} | |
188 | +INLINE float64 float64_sub( float64 a, float64 b STATUS_PARAM) | |
189 | +{ | |
190 | + return a - b; | |
191 | +} | |
192 | +INLINE float64 float64_mul( float64 a, float64 b STATUS_PARAM) | |
193 | +{ | |
194 | + return a * b; | |
195 | +} | |
196 | +INLINE float64 float64_div( float64 a, float64 b STATUS_PARAM) | |
197 | +{ | |
198 | + return a / b; | |
199 | +} | |
200 | +float64 float64_rem( float64, float64 STATUS_PARAM ); | |
201 | +float64 float64_sqrt( float64 STATUS_PARAM ); | |
202 | +INLINE char float64_eq( float64 a, float64 b STATUS_PARAM) | |
203 | +{ | |
204 | + return a == b; | |
205 | +} | |
206 | +INLINE char float64_le( float64 a, float64 b STATUS_PARAM) | |
207 | +{ | |
208 | + return a <= b; | |
209 | +} | |
210 | +INLINE char float64_lt( float64 a, float64 b STATUS_PARAM) | |
211 | +{ | |
212 | + return a < b; | |
213 | +} | |
214 | +INLINE char float64_eq_signaling( float64 a, float64 b STATUS_PARAM) | |
215 | +{ | |
216 | + return a == b; | |
217 | +} | |
218 | +INLINE char float64_le_quiet( float64 a, float64 b STATUS_PARAM) | |
219 | +{ | |
220 | + return islessequal(a, b); | |
221 | +} | |
222 | +INLINE char float64_lt_quiet( float64 a, float64 b STATUS_PARAM) | |
223 | +{ | |
224 | + return isless(a, b); | |
225 | + | |
226 | +} | |
227 | +char float64_is_signaling_nan( float64 ); | |
228 | + | |
229 | +INLINE float64 float64_abs(float64 a) | |
230 | +{ | |
231 | + return fabs(a); | |
232 | +} | |
233 | + | |
234 | +INLINE float64 float64_chs(float64 a) | |
235 | +{ | |
236 | + return -a; | |
237 | +} | |
238 | + | |
239 | +#ifdef FLOATX80 | |
240 | + | |
241 | +/*---------------------------------------------------------------------------- | |
242 | +| Software IEC/IEEE extended double-precision conversion routines. | |
243 | +*----------------------------------------------------------------------------*/ | |
244 | +int floatx80_to_int32( floatx80 STATUS_PARAM ); | |
245 | +int floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM ); | |
246 | +int64_t floatx80_to_int64( floatx80 STATUS_PARAM); | |
247 | +int64_t floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM); | |
248 | +float32 floatx80_to_float32( floatx80 STATUS_PARAM ); | |
249 | +float64 floatx80_to_float64( floatx80 STATUS_PARAM ); | |
250 | +#ifdef FLOAT128 | |
251 | +float128 floatx80_to_float128( floatx80 STATUS_PARAM ); | |
252 | +#endif | |
253 | + | |
254 | +/*---------------------------------------------------------------------------- | |
255 | +| Software IEC/IEEE extended double-precision operations. | |
256 | +*----------------------------------------------------------------------------*/ | |
257 | +floatx80 floatx80_round_to_int( floatx80 STATUS_PARAM ); | |
258 | +INLINE floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM) | |
259 | +{ | |
260 | + return a + b; | |
261 | +} | |
262 | +INLINE floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM) | |
263 | +{ | |
264 | + return a - b; | |
265 | +} | |
266 | +INLINE floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM) | |
267 | +{ | |
268 | + return a * b; | |
269 | +} | |
270 | +INLINE floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM) | |
271 | +{ | |
272 | + return a / b; | |
273 | +} | |
274 | +floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM ); | |
275 | +floatx80 floatx80_sqrt( floatx80 STATUS_PARAM ); | |
276 | +INLINE char floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM) | |
277 | +{ | |
278 | + return a == b; | |
279 | +} | |
280 | +INLINE char floatx80_le( floatx80 a, floatx80 b STATUS_PARAM) | |
281 | +{ | |
282 | + return a <= b; | |
283 | +} | |
284 | +INLINE char floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM) | |
285 | +{ | |
286 | + return a < b; | |
287 | +} | |
288 | +INLINE char floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM) | |
289 | +{ | |
290 | + return a == b; | |
291 | +} | |
292 | +INLINE char floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM) | |
293 | +{ | |
294 | + return islessequal(a, b); | |
295 | +} | |
296 | +INLINE char floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM) | |
297 | +{ | |
298 | + return isless(a, b); | |
299 | + | |
300 | +} | |
301 | +char floatx80_is_signaling_nan( floatx80 ); | |
302 | + | |
303 | +INLINE floatx80 floatx80_abs(floatx80 a) | |
304 | +{ | |
305 | + return fabsl(a); | |
306 | +} | |
307 | + | |
308 | +INLINE floatx80 floatx80_chs(floatx80 a) | |
309 | +{ | |
310 | + return -a; | |
311 | +} | |
312 | +#endif | ... | ... |
fpu/softfloat-specialize.h
0 → 100644
1 | + | |
2 | +/*============================================================================ | |
3 | + | |
4 | +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point | |
5 | +Arithmetic Package, Release 2b. | |
6 | + | |
7 | +Written by John R. Hauser. This work was made possible in part by the | |
8 | +International Computer Science Institute, located at Suite 600, 1947 Center | |
9 | +Street, Berkeley, California 94704. Funding was partially provided by the | |
10 | +National Science Foundation under grant MIP-9311980. The original version | |
11 | +of this code was written as part of a project to build a fixed-point vector | |
12 | +processor in collaboration with the University of California at Berkeley, | |
13 | +overseen by Profs. Nelson Morgan and John Wawrzynek. More information | |
14 | +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ | |
15 | +arithmetic/SoftFloat.html'. | |
16 | + | |
17 | +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has | |
18 | +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES | |
19 | +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS | |
20 | +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, | |
21 | +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE | |
22 | +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE | |
23 | +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR | |
24 | +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. | |
25 | + | |
26 | +Derivative works are acceptable, even for commercial purposes, so long as | |
27 | +(1) the source code for the derivative work includes prominent notice that | |
28 | +the work is derivative, and (2) the source code includes prominent notice with | |
29 | +these four paragraphs for those parts of this code that are retained. | |
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 | +int8 float_detect_tininess = float_tininess_after_rounding; | |
38 | + | |
39 | +/*---------------------------------------------------------------------------- | |
40 | +| Raises the exceptions specified by `flags'. Floating-point traps can be | |
41 | +| defined here if desired. It is currently not possible for such a trap | |
42 | +| to substitute a result value. If traps are not implemented, this routine | |
43 | +| should be simply `float_exception_flags |= flags;'. | |
44 | +*----------------------------------------------------------------------------*/ | |
45 | + | |
46 | +void float_raise( int8 flags STATUS_PARAM ) | |
47 | +{ | |
48 | + | |
49 | + STATUS(float_exception_flags) |= flags; | |
50 | + | |
51 | +} | |
52 | + | |
53 | +/*---------------------------------------------------------------------------- | |
54 | +| Internal canonical NaN format. | |
55 | +*----------------------------------------------------------------------------*/ | |
56 | +typedef struct { | |
57 | + flag sign; | |
58 | + bits64 high, low; | |
59 | +} commonNaNT; | |
60 | + | |
61 | +/*---------------------------------------------------------------------------- | |
62 | +| The pattern for a default generated single-precision NaN. | |
63 | +*----------------------------------------------------------------------------*/ | |
64 | +#define float32_default_nan 0xFFC00000 | |
65 | + | |
66 | +/*---------------------------------------------------------------------------- | |
67 | +| Returns 1 if the single-precision floating-point value `a' is a NaN; | |
68 | +| otherwise returns 0. | |
69 | +*----------------------------------------------------------------------------*/ | |
70 | + | |
71 | +flag float32_is_nan( float32 a ) | |
72 | +{ | |
73 | + | |
74 | + return ( 0xFF000000 < (bits32) ( a<<1 ) ); | |
75 | + | |
76 | +} | |
77 | + | |
78 | +/*---------------------------------------------------------------------------- | |
79 | +| Returns 1 if the single-precision floating-point value `a' is a signaling | |
80 | +| NaN; otherwise returns 0. | |
81 | +*----------------------------------------------------------------------------*/ | |
82 | + | |
83 | +flag float32_is_signaling_nan( float32 a ) | |
84 | +{ | |
85 | + | |
86 | + return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); | |
87 | + | |
88 | +} | |
89 | + | |
90 | +/*---------------------------------------------------------------------------- | |
91 | +| Returns the result of converting the single-precision floating-point NaN | |
92 | +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid | |
93 | +| exception is raised. | |
94 | +*----------------------------------------------------------------------------*/ | |
95 | + | |
96 | +static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM ) | |
97 | +{ | |
98 | + commonNaNT z; | |
99 | + | |
100 | + if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR ); | |
101 | + z.sign = a>>31; | |
102 | + z.low = 0; | |
103 | + z.high = ( (bits64) a )<<41; | |
104 | + return z; | |
105 | + | |
106 | +} | |
107 | + | |
108 | +/*---------------------------------------------------------------------------- | |
109 | +| Returns the result of converting the canonical NaN `a' to the single- | |
110 | +| precision floating-point format. | |
111 | +*----------------------------------------------------------------------------*/ | |
112 | + | |
113 | +static float32 commonNaNToFloat32( commonNaNT a ) | |
114 | +{ | |
115 | + | |
116 | + return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); | |
117 | + | |
118 | +} | |
119 | + | |
120 | +/*---------------------------------------------------------------------------- | |
121 | +| Takes two single-precision floating-point values `a' and `b', one of which | |
122 | +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a | |
123 | +| signaling NaN, the invalid exception is raised. | |
124 | +*----------------------------------------------------------------------------*/ | |
125 | + | |
126 | +static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) | |
127 | +{ | |
128 | + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; | |
129 | + | |
130 | + aIsNaN = float32_is_nan( a ); | |
131 | + aIsSignalingNaN = float32_is_signaling_nan( a ); | |
132 | + bIsNaN = float32_is_nan( b ); | |
133 | + bIsSignalingNaN = float32_is_signaling_nan( b ); | |
134 | + a |= 0x00400000; | |
135 | + b |= 0x00400000; | |
136 | + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); | |
137 | + if ( aIsSignalingNaN ) { | |
138 | + if ( bIsSignalingNaN ) goto returnLargerSignificand; | |
139 | + return bIsNaN ? b : a; | |
140 | + } | |
141 | + else if ( aIsNaN ) { | |
142 | + if ( bIsSignalingNaN | ! bIsNaN ) return a; | |
143 | + returnLargerSignificand: | |
144 | + if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b; | |
145 | + if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a; | |
146 | + return ( a < b ) ? a : b; | |
147 | + } | |
148 | + else { | |
149 | + return b; | |
150 | + } | |
151 | + | |
152 | +} | |
153 | + | |
154 | +/*---------------------------------------------------------------------------- | |
155 | +| The pattern for a default generated double-precision NaN. | |
156 | +*----------------------------------------------------------------------------*/ | |
157 | +#define float64_default_nan LIT64( 0xFFF8000000000000 ) | |
158 | + | |
159 | +/*---------------------------------------------------------------------------- | |
160 | +| Returns 1 if the double-precision floating-point value `a' is a NaN; | |
161 | +| otherwise returns 0. | |
162 | +*----------------------------------------------------------------------------*/ | |
163 | + | |
164 | +flag float64_is_nan( float64 a ) | |
165 | +{ | |
166 | + | |
167 | + return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); | |
168 | + | |
169 | +} | |
170 | + | |
171 | +/*---------------------------------------------------------------------------- | |
172 | +| Returns 1 if the double-precision floating-point value `a' is a signaling | |
173 | +| NaN; otherwise returns 0. | |
174 | +*----------------------------------------------------------------------------*/ | |
175 | + | |
176 | +flag float64_is_signaling_nan( float64 a ) | |
177 | +{ | |
178 | + | |
179 | + return | |
180 | + ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) | |
181 | + && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); | |
182 | + | |
183 | +} | |
184 | + | |
185 | +/*---------------------------------------------------------------------------- | |
186 | +| Returns the result of converting the double-precision floating-point NaN | |
187 | +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid | |
188 | +| exception is raised. | |
189 | +*----------------------------------------------------------------------------*/ | |
190 | + | |
191 | +static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM) | |
192 | +{ | |
193 | + commonNaNT z; | |
194 | + | |
195 | + if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR); | |
196 | + z.sign = a>>63; | |
197 | + z.low = 0; | |
198 | + z.high = a<<12; | |
199 | + return z; | |
200 | + | |
201 | +} | |
202 | + | |
203 | +/*---------------------------------------------------------------------------- | |
204 | +| Returns the result of converting the canonical NaN `a' to the double- | |
205 | +| precision floating-point format. | |
206 | +*----------------------------------------------------------------------------*/ | |
207 | + | |
208 | +static float64 commonNaNToFloat64( commonNaNT a ) | |
209 | +{ | |
210 | + | |
211 | + return | |
212 | + ( ( (bits64) a.sign )<<63 ) | |
213 | + | LIT64( 0x7FF8000000000000 ) | |
214 | + | ( a.high>>12 ); | |
215 | + | |
216 | +} | |
217 | + | |
218 | +/*---------------------------------------------------------------------------- | |
219 | +| Takes two double-precision floating-point values `a' and `b', one of which | |
220 | +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a | |
221 | +| signaling NaN, the invalid exception is raised. | |
222 | +*----------------------------------------------------------------------------*/ | |
223 | + | |
224 | +static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) | |
225 | +{ | |
226 | + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; | |
227 | + | |
228 | + aIsNaN = float64_is_nan( a ); | |
229 | + aIsSignalingNaN = float64_is_signaling_nan( a ); | |
230 | + bIsNaN = float64_is_nan( b ); | |
231 | + bIsSignalingNaN = float64_is_signaling_nan( b ); | |
232 | + a |= LIT64( 0x0008000000000000 ); | |
233 | + b |= LIT64( 0x0008000000000000 ); | |
234 | + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); | |
235 | + if ( aIsSignalingNaN ) { | |
236 | + if ( bIsSignalingNaN ) goto returnLargerSignificand; | |
237 | + return bIsNaN ? b : a; | |
238 | + } | |
239 | + else if ( aIsNaN ) { | |
240 | + if ( bIsSignalingNaN | ! bIsNaN ) return a; | |
241 | + returnLargerSignificand: | |
242 | + if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b; | |
243 | + if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a; | |
244 | + return ( a < b ) ? a : b; | |
245 | + } | |
246 | + else { | |
247 | + return b; | |
248 | + } | |
249 | + | |
250 | +} | |
251 | + | |
252 | +#ifdef FLOATX80 | |
253 | + | |
254 | +/*---------------------------------------------------------------------------- | |
255 | +| The pattern for a default generated extended double-precision NaN. The | |
256 | +| `high' and `low' values hold the most- and least-significant bits, | |
257 | +| respectively. | |
258 | +*----------------------------------------------------------------------------*/ | |
259 | +#define floatx80_default_nan_high 0xFFFF | |
260 | +#define floatx80_default_nan_low LIT64( 0xC000000000000000 ) | |
261 | + | |
262 | +/*---------------------------------------------------------------------------- | |
263 | +| Returns 1 if the extended double-precision floating-point value `a' is a | |
264 | +| NaN; otherwise returns 0. | |
265 | +*----------------------------------------------------------------------------*/ | |
266 | + | |
267 | +flag floatx80_is_nan( floatx80 a ) | |
268 | +{ | |
269 | + | |
270 | + return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); | |
271 | + | |
272 | +} | |
273 | + | |
274 | +/*---------------------------------------------------------------------------- | |
275 | +| Returns 1 if the extended double-precision floating-point value `a' is a | |
276 | +| signaling NaN; otherwise returns 0. | |
277 | +*----------------------------------------------------------------------------*/ | |
278 | + | |
279 | +flag floatx80_is_signaling_nan( floatx80 a ) | |
280 | +{ | |
281 | + bits64 aLow; | |
282 | + | |
283 | + aLow = a.low & ~ LIT64( 0x4000000000000000 ); | |
284 | + return | |
285 | + ( ( a.high & 0x7FFF ) == 0x7FFF ) | |
286 | + && (bits64) ( aLow<<1 ) | |
287 | + && ( a.low == aLow ); | |
288 | + | |
289 | +} | |
290 | + | |
291 | +/*---------------------------------------------------------------------------- | |
292 | +| Returns the result of converting the extended double-precision floating- | |
293 | +| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the | |
294 | +| invalid exception is raised. | |
295 | +*----------------------------------------------------------------------------*/ | |
296 | + | |
297 | +static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM) | |
298 | +{ | |
299 | + commonNaNT z; | |
300 | + | |
301 | + if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR); | |
302 | + z.sign = a.high>>15; | |
303 | + z.low = 0; | |
304 | + z.high = a.low<<1; | |
305 | + return z; | |
306 | + | |
307 | +} | |
308 | + | |
309 | +/*---------------------------------------------------------------------------- | |
310 | +| Returns the result of converting the canonical NaN `a' to the extended | |
311 | +| double-precision floating-point format. | |
312 | +*----------------------------------------------------------------------------*/ | |
313 | + | |
314 | +static floatx80 commonNaNToFloatx80( commonNaNT a ) | |
315 | +{ | |
316 | + floatx80 z; | |
317 | + | |
318 | + z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); | |
319 | + z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; | |
320 | + return z; | |
321 | + | |
322 | +} | |
323 | + | |
324 | +/*---------------------------------------------------------------------------- | |
325 | +| Takes two extended double-precision floating-point values `a' and `b', one | |
326 | +| of which is a NaN, and returns the appropriate NaN result. If either `a' or | |
327 | +| `b' is a signaling NaN, the invalid exception is raised. | |
328 | +*----------------------------------------------------------------------------*/ | |
329 | + | |
330 | +static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM) | |
331 | +{ | |
332 | + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; | |
333 | + | |
334 | + aIsNaN = floatx80_is_nan( a ); | |
335 | + aIsSignalingNaN = floatx80_is_signaling_nan( a ); | |
336 | + bIsNaN = floatx80_is_nan( b ); | |
337 | + bIsSignalingNaN = floatx80_is_signaling_nan( b ); | |
338 | + a.low |= LIT64( 0xC000000000000000 ); | |
339 | + b.low |= LIT64( 0xC000000000000000 ); | |
340 | + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); | |
341 | + if ( aIsSignalingNaN ) { | |
342 | + if ( bIsSignalingNaN ) goto returnLargerSignificand; | |
343 | + return bIsNaN ? b : a; | |
344 | + } | |
345 | + else if ( aIsNaN ) { | |
346 | + if ( bIsSignalingNaN | ! bIsNaN ) return a; | |
347 | + returnLargerSignificand: | |
348 | + if ( a.low < b.low ) return b; | |
349 | + if ( b.low < a.low ) return a; | |
350 | + return ( a.high < b.high ) ? a : b; | |
351 | + } | |
352 | + else { | |
353 | + return b; | |
354 | + } | |
355 | + | |
356 | +} | |
357 | + | |
358 | +#endif | |
359 | + | |
360 | +#ifdef FLOAT128 | |
361 | + | |
362 | +/*---------------------------------------------------------------------------- | |
363 | +| The pattern for a default generated quadruple-precision NaN. The `high' and | |
364 | +| `low' values hold the most- and least-significant bits, respectively. | |
365 | +*----------------------------------------------------------------------------*/ | |
366 | +#define float128_default_nan_high LIT64( 0xFFFF800000000000 ) | |
367 | +#define float128_default_nan_low LIT64( 0x0000000000000000 ) | |
368 | + | |
369 | +/*---------------------------------------------------------------------------- | |
370 | +| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; | |
371 | +| otherwise returns 0. | |
372 | +*----------------------------------------------------------------------------*/ | |
373 | + | |
374 | +flag float128_is_nan( float128 a ) | |
375 | +{ | |
376 | + | |
377 | + return | |
378 | + ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) | |
379 | + && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); | |
380 | + | |
381 | +} | |
382 | + | |
383 | +/*---------------------------------------------------------------------------- | |
384 | +| Returns 1 if the quadruple-precision floating-point value `a' is a | |
385 | +| signaling NaN; otherwise returns 0. | |
386 | +*----------------------------------------------------------------------------*/ | |
387 | + | |
388 | +flag float128_is_signaling_nan( float128 a ) | |
389 | +{ | |
390 | + | |
391 | + return | |
392 | + ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) | |
393 | + && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); | |
394 | + | |
395 | +} | |
396 | + | |
397 | +/*---------------------------------------------------------------------------- | |
398 | +| Returns the result of converting the quadruple-precision floating-point NaN | |
399 | +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid | |
400 | +| exception is raised. | |
401 | +*----------------------------------------------------------------------------*/ | |
402 | + | |
403 | +static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM) | |
404 | +{ | |
405 | + commonNaNT z; | |
406 | + | |
407 | + if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR); | |
408 | + z.sign = a.high>>63; | |
409 | + shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); | |
410 | + return z; | |
411 | + | |
412 | +} | |
413 | + | |
414 | +/*---------------------------------------------------------------------------- | |
415 | +| Returns the result of converting the canonical NaN `a' to the quadruple- | |
416 | +| precision floating-point format. | |
417 | +*----------------------------------------------------------------------------*/ | |
418 | + | |
419 | +static float128 commonNaNToFloat128( commonNaNT a ) | |
420 | +{ | |
421 | + float128 z; | |
422 | + | |
423 | + shift128Right( a.high, a.low, 16, &z.high, &z.low ); | |
424 | + z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); | |
425 | + return z; | |
426 | + | |
427 | +} | |
428 | + | |
429 | +/*---------------------------------------------------------------------------- | |
430 | +| Takes two quadruple-precision floating-point values `a' and `b', one of | |
431 | +| which is a NaN, and returns the appropriate NaN result. If either `a' or | |
432 | +| `b' is a signaling NaN, the invalid exception is raised. | |
433 | +*----------------------------------------------------------------------------*/ | |
434 | + | |
435 | +static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM) | |
436 | +{ | |
437 | + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; | |
438 | + | |
439 | + aIsNaN = float128_is_nan( a ); | |
440 | + aIsSignalingNaN = float128_is_signaling_nan( a ); | |
441 | + bIsNaN = float128_is_nan( b ); | |
442 | + bIsSignalingNaN = float128_is_signaling_nan( b ); | |
443 | + a.high |= LIT64( 0x0000800000000000 ); | |
444 | + b.high |= LIT64( 0x0000800000000000 ); | |
445 | + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); | |
446 | + if ( aIsSignalingNaN ) { | |
447 | + if ( bIsSignalingNaN ) goto returnLargerSignificand; | |
448 | + return bIsNaN ? b : a; | |
449 | + } | |
450 | + else if ( aIsNaN ) { | |
451 | + if ( bIsSignalingNaN | ! bIsNaN ) return a; | |
452 | + returnLargerSignificand: | |
453 | + if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b; | |
454 | + if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a; | |
455 | + return ( a.high < b.high ) ? a : b; | |
456 | + } | |
457 | + else { | |
458 | + return b; | |
459 | + } | |
460 | + | |
461 | +} | |
462 | + | |
463 | +#endif | |
464 | + | ... | ... |