5 #include "primitives.h"
7 #include "specialize.h"
12 int op
, uint_fast64_t uiA
, uint_fast64_t uiB
, uint_fast64_t uiC
)
24 uint_fast64_t magBits
, uiZ
;
25 struct exp16_sig64 normExpSig
;
27 struct uint128 sigProd
;
32 struct uint128 sigC128
, sigZ128
;
36 signA
= signF64UI( uiA
);
37 expA
= expF64UI( uiA
);
38 sigA
= fracF64UI( uiA
);
39 signB
= signF64UI( uiB
);
40 expB
= expF64UI( uiB
);
41 sigB
= fracF64UI( uiB
);
42 signC
= signF64UI( uiC
) ^ ( op
== softfloat_mulAdd_subC
);
43 expC
= expF64UI( uiC
);
44 sigC
= fracF64UI( uiC
);
45 signProd
= signA
^ signB
^ ( op
== softfloat_mulAdd_subProd
);
46 if ( expA
== 0x7FF ) {
47 if ( sigA
|| ( ( expB
== 0x7FF ) && sigB
) ) goto propagateNaN_ABC
;
48 magBits
= expB
| sigB
;
51 if ( expB
== 0x7FF ) {
52 if ( sigB
) goto propagateNaN_ABC
;
53 magBits
= expA
| sigA
;
56 if ( expC
== 0x7FF ) {
65 if ( ! sigA
) goto zeroProd
;
66 normExpSig
= softfloat_normSubnormalF64Sig( sigA
);
67 expA
= normExpSig
.exp
;
68 sigA
= normExpSig
.sig
;
71 if ( ! sigB
) goto zeroProd
;
72 normExpSig
= softfloat_normSubnormalF64Sig( sigB
);
73 expB
= normExpSig
.exp
;
74 sigB
= normExpSig
.sig
;
76 expProd
= expA
+ expB
- 0x3FE;
77 sigA
= ( sigA
| UINT64_C( 0x0010000000000000 ) )<<10;
78 sigB
= ( sigB
| UINT64_C( 0x0010000000000000 ) )<<10;
79 sigProd
= softfloat_mul64To128( sigA
, sigB
);
80 if ( sigProd
.v64
< UINT64_C( 0x2000000000000000 ) ) {
82 sigProd
= softfloat_shortShift128Left( sigProd
.v64
, sigProd
.v0
, 1 );
88 sigZ
= sigProd
.v64
<<1 | ( sigProd
.v0
!= 0 );
91 normExpSig
= softfloat_normSubnormalF64Sig( sigC
);
92 expC
= normExpSig
.exp
;
93 sigC
= normExpSig
.sig
;
95 sigC
= ( sigC
| UINT64_C( 0x0010000000000000 ) )<<9;
96 expDiff
= expProd
- expC
;
97 if ( signProd
== signC
) {
102 softfloat_shift64RightJam( sigProd
.v64
, - expDiff
);
104 sigZ
= ( sigC
+ sigProd
.v64
) | ( sigProd
.v0
!= 0 );
107 sigC128
= softfloat_shift128RightJam( sigC
, 0, expDiff
);
110 sigProd
.v64
, sigProd
.v0
, sigC128
.v64
, sigC128
.v0
);
111 sigZ
= sigZ128
.v64
| ( sigZ128
.v0
!= 0 );
113 if ( sigZ
< UINT64_C( 0x4000000000000000 ) ) {
118 /*** OPTIMIZE BETTER? ***/
123 softfloat_shift128RightJam(
124 sigProd
.v64
, sigProd
.v0
, - expDiff
);
125 sigZ128
= softfloat_sub128( sigC
, 0, sigProd
.v64
, sigProd
.v0
);
126 } else if ( ! expDiff
) {
128 sigZ128
= softfloat_sub128( sigProd
.v64
, sigProd
.v0
, sigC
, 0 );
129 if ( ! ( sigZ128
.v64
| sigZ128
.v0
) ) goto completeCancellation
;
130 if ( sigZ128
.v64
& UINT64_C( 0x8000000000000000 ) ) {
132 sigZ128
= softfloat_sub128( 0, 0, sigZ128
.v64
, sigZ128
.v0
);
136 sigC128
= softfloat_shift128RightJam( sigC
, 0, expDiff
);
139 sigProd
.v64
, sigProd
.v0
, sigC128
.v64
, sigC128
.v0
);
141 if ( ! sigZ128
.v64
) {
143 sigZ128
.v64
= sigZ128
.v0
;
146 shiftCount
= softfloat_countLeadingZeros64( sigZ128
.v64
) - 1;
148 if ( shiftCount
< 0 ) {
149 sigZ
= softfloat_shortShift64RightJam( sigZ128
.v64
, - shiftCount
);
152 softfloat_shortShift128Left(
153 sigZ128
.v64
, sigZ128
.v0
, shiftCount
);
156 sigZ
|= ( sigZ128
.v0
!= 0 );
159 return softfloat_roundPackToF64( signZ
, expZ
, sigZ
);
161 uiZ
= softfloat_propagateNaNF64UI( uiA
, uiB
);
162 goto propagateNaN_ZC
;
165 uiZ
= packToF64UI( signProd
, 0x7FF, 0 );
166 if ( expC
!= 0x7FF ) goto uiZ
;
167 if ( sigC
) goto propagateNaN_ZC
;
168 if ( signProd
== signC
) goto uiZ
;
171 softfloat_raiseFlags( softfloat_flag_invalid
);
172 uiZ
= defaultNaNF64UI
;
174 uiZ
= softfloat_propagateNaNF64UI( uiZ
, uiC
);
178 if ( ! ( expC
| sigC
) && ( signProd
!= signC
) ) {
179 completeCancellation
:
181 packToF64UI( softfloat_roundingMode
== softfloat_round_min
, 0, 0 );