9f9ecf5ad90e06f387e0a1287c2092595004e3e8
2 /*============================================================================
4 This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5 Package, Release 3a, by John R. Hauser.
7 Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are met:
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
24 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 =============================================================================*/
40 #include "internals.h"
41 #include "specialize.h"
42 #include "softfloat.h"
44 #ifdef SOFTFLOAT_FAST_INT64
48 uint_fast64_t uiA
, uint_fast64_t uiB
, uint_fast64_t uiC
, uint_fast8_t op
)
60 uint_fast64_t magBits
, uiZ
;
61 struct exp16_sig64 normExpSig
;
63 struct uint128 sig128Z
;
66 struct uint128 sig128C
;
67 int_fast8_t shiftCount
;
70 /*------------------------------------------------------------------------
71 *------------------------------------------------------------------------*/
72 signA
= signF64UI( uiA
);
73 expA
= expF64UI( uiA
);
74 sigA
= fracF64UI( uiA
);
75 signB
= signF64UI( uiB
);
76 expB
= expF64UI( uiB
);
77 sigB
= fracF64UI( uiB
);
78 signC
= signF64UI( uiC
) ^ (op
== softfloat_mulAdd_subC
);
79 expC
= expF64UI( uiC
);
80 sigC
= fracF64UI( uiC
);
81 signZ
= signA
^ signB
^ (op
== softfloat_mulAdd_subProd
);
82 /*------------------------------------------------------------------------
83 *------------------------------------------------------------------------*/
84 if ( expA
== 0x7FF ) {
85 if ( sigA
|| ((expB
== 0x7FF) && sigB
) ) goto propagateNaN_ABC
;
86 magBits
= expB
| sigB
;
89 if ( expB
== 0x7FF ) {
90 if ( sigB
) goto propagateNaN_ABC
;
91 magBits
= expA
| sigA
;
94 if ( expC
== 0x7FF ) {
102 /*------------------------------------------------------------------------
103 *------------------------------------------------------------------------*/
105 if ( ! sigA
) goto zeroProd
;
106 normExpSig
= softfloat_normSubnormalF64Sig( sigA
);
107 expA
= normExpSig
.exp
;
108 sigA
= normExpSig
.sig
;
111 if ( ! sigB
) goto zeroProd
;
112 normExpSig
= softfloat_normSubnormalF64Sig( sigB
);
113 expB
= normExpSig
.exp
;
114 sigB
= normExpSig
.sig
;
116 /*------------------------------------------------------------------------
117 *------------------------------------------------------------------------*/
118 expZ
= expA
+ expB
- 0x3FE;
119 sigA
= (sigA
| UINT64_C( 0x0010000000000000 ))<<10;
120 sigB
= (sigB
| UINT64_C( 0x0010000000000000 ))<<10;
121 sig128Z
= softfloat_mul64To128( sigA
, sigB
);
122 if ( sig128Z
.v64
< UINT64_C( 0x2000000000000000 ) ) {
126 sig128Z
.v64
, sig128Z
.v0
, sig128Z
.v64
, sig128Z
.v0
);
131 sigZ
= sig128Z
.v64
<<1 | (sig128Z
.v0
!= 0);
134 normExpSig
= softfloat_normSubnormalF64Sig( sigC
);
135 expC
= normExpSig
.exp
;
136 sigC
= normExpSig
.sig
;
138 sigC
= (sigC
| UINT64_C( 0x0010000000000000 ))<<9;
139 /*------------------------------------------------------------------------
140 *------------------------------------------------------------------------*/
141 expDiff
= expZ
- expC
;
144 if ( (signZ
== signC
) || (expDiff
< -1) ) {
145 sig128Z
.v64
= softfloat_shiftRightJam64( sig128Z
.v64
, -expDiff
);
148 softfloat_shortShiftRightJam128( sig128Z
.v64
, sig128Z
.v0
, 1 );
150 } else if ( expDiff
) {
151 sig128C
= softfloat_shiftRightJam128( sigC
, 0, expDiff
);
153 /*------------------------------------------------------------------------
154 *------------------------------------------------------------------------*/
155 if ( signZ
== signC
) {
156 /*--------------------------------------------------------------------
157 *--------------------------------------------------------------------*/
158 if ( expDiff
<= 0 ) {
159 sigZ
= (sigC
+ sig128Z
.v64
) | (sig128Z
.v0
!= 0);
163 sig128Z
.v64
, sig128Z
.v0
, sig128C
.v64
, sig128C
.v0
);
164 sigZ
= sig128Z
.v64
| (sig128Z
.v0
!= 0);
166 if ( sigZ
< UINT64_C( 0x4000000000000000 ) ) {
171 /*--------------------------------------------------------------------
172 *--------------------------------------------------------------------*/
175 sig128Z
= softfloat_sub128( sigC
, 0, sig128Z
.v64
, sig128Z
.v0
);
176 } else if ( ! expDiff
) {
177 sig128Z
.v64
= sig128Z
.v64
- sigC
;
178 if ( ! (sig128Z
.v64
| sig128Z
.v0
) ) goto completeCancellation
;
179 if ( sig128Z
.v64
& UINT64_C( 0x8000000000000000 ) ) {
181 sig128Z
= softfloat_sub128( 0, 0, sig128Z
.v64
, sig128Z
.v0
);
186 sig128Z
.v64
, sig128Z
.v0
, sig128C
.v64
, sig128C
.v0
);
188 /*--------------------------------------------------------------------
189 *--------------------------------------------------------------------*/
190 if ( ! sig128Z
.v64
) {
192 sig128Z
.v64
= sig128Z
.v0
;
195 shiftCount
= softfloat_countLeadingZeros64( sig128Z
.v64
) - 1;
197 if ( shiftCount
< 0 ) {
198 sigZ
= softfloat_shortShiftRightJam64( sig128Z
.v64
, -shiftCount
);
201 softfloat_shortShiftLeft128(
202 sig128Z
.v64
, sig128Z
.v0
, shiftCount
);
205 sigZ
|= (sig128Z
.v0
!= 0);
208 return softfloat_roundPackToF64( signZ
, expZ
, sigZ
);
209 /*------------------------------------------------------------------------
210 *------------------------------------------------------------------------*/
212 uiZ
= softfloat_propagateNaNF64UI( uiA
, uiB
);
213 goto propagateNaN_ZC
;
214 /*------------------------------------------------------------------------
215 *------------------------------------------------------------------------*/
218 uiZ
= packToF64UI( signZ
, 0x7FF, 0 );
219 if ( expC
!= 0x7FF ) goto uiZ
;
220 if ( sigC
) goto propagateNaN_ZC
;
221 if ( signZ
== signC
) goto uiZ
;
224 softfloat_raiseFlags( softfloat_flag_invalid
);
225 uiZ
= defaultNaNF64UI
;
227 uiZ
= softfloat_propagateNaNF64UI( uiZ
, uiC
);
229 /*------------------------------------------------------------------------
230 *------------------------------------------------------------------------*/
233 if ( ! (expC
| sigC
) && (signZ
!= signC
) ) {
234 completeCancellation
:
236 packToF64UI( softfloat_roundingMode
== softfloat_round_min
, 0, 0 );
248 uint_fast64_t uiA
, uint_fast64_t uiB
, uint_fast64_t uiC
, uint_fast8_t op
)
260 uint64_t magBits
, uiZ
;
261 struct exp16_sig64 normExpSig
;
265 int_fast16_t shiftCount
, expDiff
;
269 /*------------------------------------------------------------------------
270 *------------------------------------------------------------------------*/
271 signA
= signF64UI( uiA
);
272 expA
= expF64UI( uiA
);
273 sigA
= fracF64UI( uiA
);
274 signB
= signF64UI( uiB
);
275 expB
= expF64UI( uiB
);
276 sigB
= fracF64UI( uiB
);
277 signC
= signF64UI( uiC
) ^ (op
== softfloat_mulAdd_subC
);
278 expC
= expF64UI( uiC
);
279 sigC
= fracF64UI( uiC
);
280 signZ
= signA
^ signB
^ (op
== softfloat_mulAdd_subProd
);
281 /*------------------------------------------------------------------------
282 *------------------------------------------------------------------------*/
283 if ( expA
== 0x7FF ) {
284 if ( sigA
|| ((expB
== 0x7FF) && sigB
) ) goto propagateNaN_ABC
;
285 magBits
= expB
| sigB
;
288 if ( expB
== 0x7FF ) {
289 if ( sigB
) goto propagateNaN_ABC
;
290 magBits
= expA
| sigA
;
293 if ( expC
== 0x7FF ) {
296 goto propagateNaN_ZC
;
301 /*------------------------------------------------------------------------
302 *------------------------------------------------------------------------*/
304 if ( ! sigA
) goto zeroProd
;
305 normExpSig
= softfloat_normSubnormalF64Sig( sigA
);
306 expA
= normExpSig
.exp
;
307 sigA
= normExpSig
.sig
;
310 if ( ! sigB
) goto zeroProd
;
311 normExpSig
= softfloat_normSubnormalF64Sig( sigB
);
312 expB
= normExpSig
.exp
;
313 sigB
= normExpSig
.sig
;
315 /*------------------------------------------------------------------------
316 *------------------------------------------------------------------------*/
317 expZ
= expA
+ expB
- 0x3FE;
318 sigA
= (sigA
| UINT64_C( 0x0010000000000000 ))<<10;
319 sigB
= (sigB
| UINT64_C( 0x0010000000000000 ))<<11;
320 softfloat_mul64To128M( sigA
, sigB
, sig128Z
);
322 (uint64_t) sig128Z
[indexWord( 4, 3 )]<<32 | sig128Z
[indexWord( 4, 2 )];
324 if ( ! (sigZ
& UINT64_C( 0x4000000000000000 )) ) {
330 if ( shiftCount
) sigZ
<<= 1;
333 normExpSig
= softfloat_normSubnormalF64Sig( sigC
);
334 expC
= normExpSig
.exp
;
335 sigC
= normExpSig
.sig
;
337 sigC
= (sigC
| UINT64_C( 0x0010000000000000 ))<<10;
338 /*------------------------------------------------------------------------
339 *------------------------------------------------------------------------*/
340 expDiff
= expZ
- expC
;
343 if ( (signZ
== signC
) || (expDiff
< -1) ) {
344 shiftCount
-= expDiff
;
346 sigZ
= softfloat_shiftRightJam64( sigZ
, shiftCount
);
349 if ( ! shiftCount
) {
350 softfloat_shortShiftRight128M( sig128Z
, 1, sig128Z
);
354 if ( shiftCount
) softfloat_add128M( sig128Z
, sig128Z
, sig128Z
);
357 (uint64_t) sig128Z
[indexWord( 4, 3 )]<<32
358 | sig128Z
[indexWord( 4, 2 )];
360 sig128C
[indexWord( 4, 3 )] = sigC
>>32;
361 sig128C
[indexWord( 4, 2 )] = sigC
;
362 sig128C
[indexWord( 4, 1 )] = 0;
363 sig128C
[indexWord( 4, 0 )] = 0;
364 softfloat_shiftRightJam128M( sig128C
, expDiff
, sig128C
);
367 /*------------------------------------------------------------------------
368 *------------------------------------------------------------------------*/
369 if ( signZ
== signC
) {
370 /*--------------------------------------------------------------------
371 *--------------------------------------------------------------------*/
372 if ( expDiff
<= 0 ) {
375 softfloat_add128M( sig128Z
, sig128C
, sig128Z
);
377 (uint64_t) sig128Z
[indexWord( 4, 3 )]<<32
378 | sig128Z
[indexWord( 4, 2 )];
380 if ( sigZ
& UINT64_C( 0x8000000000000000 ) ) {
382 sigZ
= softfloat_shortShiftRightJam64( sigZ
, 1 );
385 /*--------------------------------------------------------------------
386 *--------------------------------------------------------------------*/
389 if ( expDiff
< -1 ) {
392 sig128Z
[indexWord( 4, 1 )] || sig128Z
[indexWord( 4, 0 )]
394 sigZ
= (sigZ
- 1) | 1;
396 if ( ! (sigZ
& UINT64_C( 0x4000000000000000 )) ) {
402 sig128C
[indexWord( 4, 3 )] = sigC
>>32;
403 sig128C
[indexWord( 4, 2 )] = sigC
;
404 sig128C
[indexWord( 4, 1 )] = 0;
405 sig128C
[indexWord( 4, 0 )] = 0;
406 softfloat_sub128M( sig128C
, sig128Z
, sig128Z
);
408 } else if ( ! expDiff
) {
411 ! sigZ
&& ! sig128Z
[indexWord( 4, 1 )]
412 && ! sig128Z
[indexWord( 4, 0 )]
414 goto completeCancellation
;
416 sig128Z
[indexWord( 4, 3 )] = sigZ
>>32;
417 sig128Z
[indexWord( 4, 2 )] = sigZ
;
418 if ( sigZ
& UINT64_C( 0x8000000000000000 ) ) {
420 softfloat_negX128M( sig128Z
);
423 softfloat_sub128M( sig128Z
, sig128C
, sig128Z
);
426 (uint64_t) sig128Z
[indexWord( 4, 3 )]<<32
427 | sig128Z
[indexWord( 4, 2 )];
428 if ( ! (sigZ
& UINT64_C( 0x4000000000000000 )) ) {
435 /*--------------------------------------------------------------------
436 *--------------------------------------------------------------------*/
439 (uint64_t) sig128Z
[indexWord( 4, 3 )]<<32
440 | sig128Z
[indexWord( 4, 2 )];
444 (uint64_t) sig128Z
[indexWord( 4, 1 )]<<32
445 | sig128Z
[indexWord( 4, 0 )];
447 shiftCount
+= softfloat_countLeadingZeros64( sigZ
) - 1;
450 softfloat_shiftLeft128M( sig128Z
, shiftCount
, sig128Z
);
452 (uint64_t) sig128Z
[indexWord( 4, 3 )]<<32
453 | sig128Z
[indexWord( 4, 2 )];
457 if ( sig128Z
[indexWord( 4, 1 )] || sig128Z
[indexWord( 4, 0 )] ) sigZ
|= 1;
459 return softfloat_roundPackToF64( signZ
, expZ
- 1, sigZ
);
460 /*------------------------------------------------------------------------
461 *------------------------------------------------------------------------*/
463 uiZ
= softfloat_propagateNaNF64UI( uiA
, uiB
);
464 goto propagateNaN_ZC
;
465 /*------------------------------------------------------------------------
466 *------------------------------------------------------------------------*/
469 uiZ
= packToF64UI( signZ
, 0x7FF, 0 );
470 if ( expC
!= 0x7FF ) goto uiZ
;
471 if ( sigC
) goto propagateNaN_ZC
;
472 if ( signZ
== signC
) goto uiZ
;
475 softfloat_raiseFlags( softfloat_flag_invalid
);
476 uiZ
= defaultNaNF64UI
;
478 uiZ
= softfloat_propagateNaNF64UI( uiZ
, uiC
);
480 /*------------------------------------------------------------------------
481 *------------------------------------------------------------------------*/
484 if ( ! (expC
| sigC
) && (signZ
!= signC
) ) {
485 completeCancellation
:
487 packToF64UI( softfloat_roundingMode
== softfloat_round_min
, 0, 0 );