2 /*============================================================================
4 This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5 Package, Release 3d, by John R. Hauser.
7 Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8 California. All rights reserved.
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"
65 uint_fast64_t magBits
;
67 struct exp32_sig128 normExpSig
;
71 int_fast32_t shiftDist
, expDiff
;
74 static uint64_t zero256
[4] = INIT_UINTM4( 0, 0, 0, 0 );
75 uint_fast64_t sigZExtra
, sig256Z0
;
78 /*------------------------------------------------------------------------
79 *------------------------------------------------------------------------*/
80 signA
= signF128UI64( uiA64
);
81 expA
= expF128UI64( uiA64
);
82 sigA
.v64
= fracF128UI64( uiA64
);
84 signB
= signF128UI64( uiB64
);
85 expB
= expF128UI64( uiB64
);
86 sigB
.v64
= fracF128UI64( uiB64
);
88 signC
= signF128UI64( uiC64
) ^ (op
== softfloat_mulAdd_subC
);
89 expC
= expF128UI64( uiC64
);
90 sigC
.v64
= fracF128UI64( uiC64
);
92 signZ
= signA
^ signB
^ (op
== softfloat_mulAdd_subProd
);
93 /*------------------------------------------------------------------------
94 *------------------------------------------------------------------------*/
95 if ( expA
== 0x7FFF ) {
97 (sigA
.v64
| sigA
.v0
) || ((expB
== 0x7FFF) && (sigB
.v64
| sigB
.v0
))
99 goto propagateNaN_ABC
;
101 magBits
= expB
| sigB
.v64
| sigB
.v0
;
104 if ( expB
== 0x7FFF ) {
105 if ( sigB
.v64
| sigB
.v0
) goto propagateNaN_ABC
;
106 magBits
= expA
| sigA
.v64
| sigA
.v0
;
109 if ( expC
== 0x7FFF ) {
110 if ( sigC
.v64
| sigC
.v0
) {
113 goto propagateNaN_ZC
;
119 /*------------------------------------------------------------------------
120 *------------------------------------------------------------------------*/
122 if ( ! (sigA
.v64
| sigA
.v0
) ) goto zeroProd
;
123 normExpSig
= softfloat_normSubnormalF128Sig( sigA
.v64
, sigA
.v0
);
124 expA
= normExpSig
.exp
;
125 sigA
= normExpSig
.sig
;
128 if ( ! (sigB
.v64
| sigB
.v0
) ) goto zeroProd
;
129 normExpSig
= softfloat_normSubnormalF128Sig( sigB
.v64
, sigB
.v0
);
130 expB
= normExpSig
.exp
;
131 sigB
= normExpSig
.sig
;
133 /*------------------------------------------------------------------------
134 *------------------------------------------------------------------------*/
135 expZ
= expA
+ expB
- 0x3FFE;
136 sigA
.v64
|= UINT64_C( 0x0001000000000000 );
137 sigB
.v64
|= UINT64_C( 0x0001000000000000 );
138 sigA
= softfloat_shortShiftLeft128( sigA
.v64
, sigA
.v0
, 8 );
139 sigB
= softfloat_shortShiftLeft128( sigB
.v64
, sigB
.v0
, 15 );
140 softfloat_mul128To256M( sigA
.v64
, sigA
.v0
, sigB
.v64
, sigB
.v0
, sig256Z
);
141 sigZ
.v64
= sig256Z
[indexWord( 4, 3 )];
142 sigZ
.v0
= sig256Z
[indexWord( 4, 2 )];
144 if ( ! (sigZ
.v64
& UINT64_C( 0x0100000000000000 )) ) {
149 if ( ! (sigC
.v64
| sigC
.v0
) ) {
153 normExpSig
= softfloat_normSubnormalF128Sig( sigC
.v64
, sigC
.v0
);
154 expC
= normExpSig
.exp
;
155 sigC
= normExpSig
.sig
;
157 sigC
.v64
|= UINT64_C( 0x0001000000000000 );
158 sigC
= softfloat_shortShiftLeft128( sigC
.v64
, sigC
.v0
, 8 );
159 /*------------------------------------------------------------------------
160 *------------------------------------------------------------------------*/
161 expDiff
= expZ
- expC
;
164 if ( (signZ
== signC
) || (expDiff
< -1) ) {
165 shiftDist
-= expDiff
;
168 softfloat_shiftRightJam128( sigZ
.v64
, sigZ
.v0
, shiftDist
);
173 softfloat_shortShiftRight128(
174 sig256Z
[indexWord( 4, 1 )], sig256Z
[indexWord( 4, 0 )],
177 sig256Z
[indexWord( 4, 1 )] = (sigZ
.v0
<<63) | x128
.v64
;
178 sig256Z
[indexWord( 4, 0 )] = x128
.v0
;
179 sigZ
= softfloat_shortShiftRight128( sigZ
.v64
, sigZ
.v0
, 1 );
180 sig256Z
[indexWord( 4, 3 )] = sigZ
.v64
;
181 sig256Z
[indexWord( 4, 2 )] = sigZ
.v0
;
185 if ( shiftDist
) softfloat_add256M( sig256Z
, sig256Z
, sig256Z
);
187 sigZ
.v64
= sig256Z
[indexWord( 4, 3 )];
188 sigZ
.v0
= sig256Z
[indexWord( 4, 2 )];
190 sig256C
[indexWord( 4, 3 )] = sigC
.v64
;
191 sig256C
[indexWord( 4, 2 )] = sigC
.v0
;
192 sig256C
[indexWord( 4, 1 )] = 0;
193 sig256C
[indexWord( 4, 0 )] = 0;
194 softfloat_shiftRightJam256M( sig256C
, expDiff
, sig256C
);
197 /*------------------------------------------------------------------------
198 *------------------------------------------------------------------------*/
200 if ( signZ
== signC
) {
201 /*--------------------------------------------------------------------
202 *--------------------------------------------------------------------*/
203 if ( expDiff
<= 0 ) {
204 sigZ
= softfloat_add128( sigC
.v64
, sigC
.v0
, sigZ
.v64
, sigZ
.v0
);
206 softfloat_add256M( sig256Z
, sig256C
, sig256Z
);
207 sigZ
.v64
= sig256Z
[indexWord( 4, 3 )];
208 sigZ
.v0
= sig256Z
[indexWord( 4, 2 )];
210 if ( sigZ
.v64
& UINT64_C( 0x0200000000000000 ) ) {
215 /*--------------------------------------------------------------------
216 *--------------------------------------------------------------------*/
219 if ( expDiff
< -1 ) {
221 softfloat_sub128( sigC
.v64
, sigC
.v0
, sigZ
.v64
, sigZ
.v0
);
223 sig256Z
[indexWord( 4, 1 )] | sig256Z
[indexWord( 4, 0 )];
225 sigZ
= softfloat_sub128( sigZ
.v64
, sigZ
.v0
, 0, 1 );
227 if ( ! (sigZ
.v64
& UINT64_C( 0x0100000000000000 )) ) {
231 goto shiftRightRoundPack
;
233 sig256C
[indexWord( 4, 3 )] = sigC
.v64
;
234 sig256C
[indexWord( 4, 2 )] = sigC
.v0
;
235 sig256C
[indexWord( 4, 1 )] = 0;
236 sig256C
[indexWord( 4, 0 )] = 0;
237 softfloat_sub256M( sig256C
, sig256Z
, sig256Z
);
239 } else if ( ! expDiff
) {
240 sigZ
= softfloat_sub128( sigZ
.v64
, sigZ
.v0
, sigC
.v64
, sigC
.v0
);
242 ! (sigZ
.v64
| sigZ
.v0
) && ! sig256Z
[indexWord( 4, 1 )]
243 && ! sig256Z
[indexWord( 4, 0 )]
245 goto completeCancellation
;
247 sig256Z
[indexWord( 4, 3 )] = sigZ
.v64
;
248 sig256Z
[indexWord( 4, 2 )] = sigZ
.v0
;
249 if ( sigZ
.v64
& UINT64_C( 0x8000000000000000 ) ) {
251 softfloat_sub256M( zero256
, sig256Z
, sig256Z
);
254 softfloat_sub256M( sig256Z
, sig256C
, sig256Z
);
256 sigZ
.v64
= sig256Z
[indexWord( 4, 3 )];
257 sigZ
.v0
= sig256Z
[indexWord( 4, 2 )];
258 if ( ! (sigZ
.v64
& UINT64_C( 0x0100000000000000 )) ) {
265 /*--------------------------------------------------------------------
266 *--------------------------------------------------------------------*/
267 sigZ
.v64
= sig256Z
[indexWord( 4, 3 )];
268 sigZ
.v0
= sig256Z
[indexWord( 4, 2 )];
269 sigZExtra
= sig256Z
[indexWord( 4, 1 )];
270 sig256Z0
= sig256Z
[indexWord( 4, 0 )];
272 if ( sig256Z0
) sigZExtra
|= 1;
277 sigZExtra
= sig256Z0
;
290 shiftDist
= softfloat_countLeadingZeros64( sigZ
.v64
);
291 expZ
+= 7 - shiftDist
;
292 shiftDist
= 15 - shiftDist
;
293 if ( 0 < shiftDist
) goto shiftRightRoundPack
;
295 shiftDist
= -shiftDist
;
296 sigZ
= softfloat_shortShiftLeft128( sigZ
.v64
, sigZ
.v0
, shiftDist
);
297 x128
= softfloat_shortShiftLeft128( 0, sigZExtra
, shiftDist
);
304 sigZExtra
= sig256Z
[indexWord( 4, 1 )] | sig256Z
[indexWord( 4, 0 )];
306 sigZExtra
= (uint64_t) (sigZ
.v0
<<(64 - shiftDist
)) | (sigZExtra
!= 0);
307 sigZ
= softfloat_shortShiftRight128( sigZ
.v64
, sigZ
.v0
, shiftDist
);
310 softfloat_roundPackToF128(
311 signZ
, expZ
- 1, sigZ
.v64
, sigZ
.v0
, sigZExtra
);
312 /*------------------------------------------------------------------------
313 *------------------------------------------------------------------------*/
315 uiZ
= softfloat_propagateNaNF128UI( uiA64
, uiA0
, uiB64
, uiB0
);
316 goto propagateNaN_ZC
;
317 /*------------------------------------------------------------------------
318 *------------------------------------------------------------------------*/
321 uiZ
.v64
= packToF128UI64( signZ
, 0x7FFF, 0 );
323 if ( expC
!= 0x7FFF ) goto uiZ
;
324 if ( sigC
.v64
| sigC
.v0
) goto propagateNaN_ZC
;
325 if ( signZ
== signC
) goto uiZ
;
327 softfloat_raiseFlags( softfloat_flag_invalid
);
328 uiZ
.v64
= defaultNaNF128UI64
;
329 uiZ
.v0
= defaultNaNF128UI0
;
331 uiZ
= softfloat_propagateNaNF128UI( uiZ
.v64
, uiZ
.v0
, uiC64
, uiC0
);
333 /*------------------------------------------------------------------------
334 *------------------------------------------------------------------------*/
338 if ( ! (expC
| sigC
.v64
| sigC
.v0
) && (signZ
!= signC
) ) {
339 completeCancellation
:
342 (softfloat_roundingMode
== softfloat_round_min
), 0, 0 );