Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
s_mulAddF64.c File Reference
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
Include dependency graph for s_mulAddF64.c:

Go to the source code of this file.

Functions

float64_t softfloat_mulAddF64 (uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC, uint_fast8_t op)
 

Function Documentation

◆ softfloat_mulAddF64()

float64_t softfloat_mulAddF64 ( uint_fast64_t uiA,
uint_fast64_t uiB,
uint_fast64_t uiC,
uint_fast8_t op )

Definition at line 247 of file s_mulAddF64.c.

249{
250 bool signA;
251 int_fast16_t expA;
252 uint64_t sigA;
253 bool signB;
254 int_fast16_t expB;
255 uint64_t sigB;
256 bool signC;
257 int_fast16_t expC;
258 uint64_t sigC;
259 bool signZ;
260 uint64_t magBits, uiZ;
261 struct exp16_sig64 normExpSig;
262 int_fast16_t expZ;
263 uint32_t sig128Z[4];
264 uint64_t sigZ;
265 int_fast16_t shiftDist, expDiff;
266 uint32_t sig128C[4];
267 union ui64_f64 uZ;
268
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;
286 goto infProdArg;
287 }
288 if ( expB == 0x7FF ) {
289 if ( sigB ) goto propagateNaN_ABC;
290 magBits = expA | sigA;
291 goto infProdArg;
292 }
293 if ( expC == 0x7FF ) {
294 if ( sigC ) {
295 uiZ = 0;
296 goto propagateNaN_ZC;
297 }
298 uiZ = uiC;
299 goto uiZ;
300 }
301 /*------------------------------------------------------------------------
302 *------------------------------------------------------------------------*/
303 if ( ! expA ) {
304 if ( ! sigA ) goto zeroProd;
305 normExpSig = softfloat_normSubnormalF64Sig( sigA );
306 expA = normExpSig.exp;
307 sigA = normExpSig.sig;
308 }
309 if ( ! expB ) {
310 if ( ! sigB ) goto zeroProd;
311 normExpSig = softfloat_normSubnormalF64Sig( sigB );
312 expB = normExpSig.exp;
313 sigB = normExpSig.sig;
314 }
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 );
321 sigZ =
322 (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )];
323 shiftDist = 0;
324 if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) {
325 --expZ;
326 shiftDist = -1;
327 }
328 if ( ! expC ) {
329 if ( ! sigC ) {
330 if ( shiftDist ) sigZ <<= 1;
331 goto sigZ;
332 }
333 normExpSig = softfloat_normSubnormalF64Sig( sigC );
334 expC = normExpSig.exp;
335 sigC = normExpSig.sig;
336 }
337 sigC = (sigC | UINT64_C( 0x0010000000000000 ))<<10;
338 /*------------------------------------------------------------------------
339 *------------------------------------------------------------------------*/
340 expDiff = expZ - expC;
341 if ( expDiff < 0 ) {
342 expZ = expC;
343 if ( (signZ == signC) || (expDiff < -1) ) {
344 shiftDist -= expDiff;
345 if ( shiftDist) {
346 sigZ = softfloat_shiftRightJam64( sigZ, shiftDist );
347 }
348 } else {
349 if ( ! shiftDist ) {
350 softfloat_shortShiftRight128M( sig128Z, 1, sig128Z );
351 }
352 }
353 } else {
354 if ( shiftDist ) softfloat_add128M( sig128Z, sig128Z, sig128Z );
355 if ( ! expDiff ) {
356 sigZ =
357 (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
358 | sig128Z[indexWord( 4, 2 )];
359 } else {
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 );
365 }
366 }
367 /*------------------------------------------------------------------------
368 *------------------------------------------------------------------------*/
369 if ( signZ == signC ) {
370 /*--------------------------------------------------------------------
371 *--------------------------------------------------------------------*/
372 if ( expDiff <= 0 ) {
373 sigZ += sigC;
374 } else {
375 softfloat_add128M( sig128Z, sig128C, sig128Z );
376 sigZ =
377 (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
378 | sig128Z[indexWord( 4, 2 )];
379 }
380 if ( sigZ & UINT64_C( 0x8000000000000000 ) ) {
381 ++expZ;
382 sigZ = softfloat_shortShiftRightJam64( sigZ, 1 );
383 }
384 } else {
385 /*--------------------------------------------------------------------
386 *--------------------------------------------------------------------*/
387 if ( expDiff < 0 ) {
388 signZ = signC;
389 if ( expDiff < -1 ) {
390 sigZ = sigC - sigZ;
391 if (
392 sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )]
393 ) {
394 sigZ = (sigZ - 1) | 1;
395 }
396 if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) {
397 --expZ;
398 sigZ <<= 1;
399 }
400 goto roundPack;
401 } else {
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 );
407 }
408 } else if ( ! expDiff ) {
409 sigZ -= sigC;
410 if (
411 ! sigZ && ! sig128Z[indexWord( 4, 1 )]
412 && ! sig128Z[indexWord( 4, 0 )]
413 ) {
414 goto completeCancellation;
415 }
416 sig128Z[indexWord( 4, 3 )] = sigZ>>32;
417 sig128Z[indexWord( 4, 2 )] = sigZ;
418 if ( sigZ & UINT64_C( 0x8000000000000000 ) ) {
419 signZ = ! signZ;
420 softfloat_negX128M( sig128Z );
421 }
422 } else {
423 softfloat_sub128M( sig128Z, sig128C, sig128Z );
424 if ( 1 < expDiff ) {
425 sigZ =
426 (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
427 | sig128Z[indexWord( 4, 2 )];
428 if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) {
429 --expZ;
430 sigZ <<= 1;
431 }
432 goto sigZ;
433 }
434 }
435 /*--------------------------------------------------------------------
436 *--------------------------------------------------------------------*/
437 shiftDist = 0;
438 sigZ =
439 (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
440 | sig128Z[indexWord( 4, 2 )];
441 if ( ! sigZ ) {
442 shiftDist = 64;
443 sigZ =
444 (uint64_t) sig128Z[indexWord( 4, 1 )]<<32
445 | sig128Z[indexWord( 4, 0 )];
446 }
447 shiftDist += softfloat_countLeadingZeros64( sigZ ) - 1;
448 if ( shiftDist ) {
449 expZ -= shiftDist;
450 softfloat_shiftLeft128M( sig128Z, shiftDist, sig128Z );
451 sigZ =
452 (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
453 | sig128Z[indexWord( 4, 2 )];
454 }
455 }
456 sigZ:
457 if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) sigZ |= 1;
458 roundPack:
459 return softfloat_roundPackToF64( signZ, expZ - 1, sigZ );
460 /*------------------------------------------------------------------------
461 *------------------------------------------------------------------------*/
462 propagateNaN_ABC:
463 uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
464 goto propagateNaN_ZC;
465 /*------------------------------------------------------------------------
466 *------------------------------------------------------------------------*/
467 infProdArg:
468 if ( magBits ) {
469 uiZ = packToF64UI( signZ, 0x7FF, 0 );
470 if ( expC != 0x7FF ) goto uiZ;
471 if ( sigC ) goto propagateNaN_ZC;
472 if ( signZ == signC ) goto uiZ;
473 }
475 uiZ = defaultNaNF64UI;
476 propagateNaN_ZC:
477 uiZ = softfloat_propagateNaNF64UI( uiZ, uiC );
478 goto uiZ;
479 /*------------------------------------------------------------------------
480 *------------------------------------------------------------------------*/
481 zeroProd:
482 uiZ = uiC;
483 if ( ! (expC | sigC) && (signZ != signC) ) {
484 completeCancellation:
485 uiZ =
488 }
489 uiZ:
490 uZ.ui = uiZ;
491 return uZ.f;
492
493}
uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB)
void softfloat_raiseFlags(uint_fast8_t flags)
#define defaultNaNF64UI
Definition specialize.h:158
float64_t softfloat_roundPackToF64(bool, int_fast16_t, uint_fast64_t)
struct exp16_sig64 softfloat_normSubnormalF64Sig(uint_fast64_t)
#define signF64UI(a)
Definition internals.h:125
#define packToF64UI(sign, exp, sig)
Definition internals.h:128
@ softfloat_mulAdd_subProd
Definition internals.h:56
@ softfloat_mulAdd_subC
Definition internals.h:55
#define expF64UI(a)
Definition internals.h:126
#define fracF64UI(a)
Definition internals.h:127
#define indexWord(total, n)
#define softfloat_add128M(aPtr, bPtr, zPtr)
Definition primitives.h:923
uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint_fast8_t dist)
#define softfloat_sub128M(aPtr, bPtr, zPtr)
void softfloat_mul64To128M(uint64_t a, uint64_t b, uint32_t *zPtr)
#define softfloat_shiftRightJam128M(aPtr, dist, zPtr)
Definition primitives.h:881
#define softfloat_negX128M(zPtr)
#define softfloat_shiftLeft128M(aPtr, dist, zPtr)
Definition primitives.h:747
uint64_t softfloat_shiftRightJam64(uint64_t a, uint_fast32_t dist)
#define softfloat_shortShiftRight128M(aPtr, dist, zPtr)
Definition primitives.h:782
THREAD_LOCAL uint_fast8_t softfloat_roundingMode
@ softfloat_flag_invalid
Definition softfloat.h:89
@ softfloat_round_min
Definition softfloat.h:74
#define softfloat_countLeadingZeros64
unsigned int uint32_t
Definition stdint.h:126
#define UINT64_C(val)
Definition stdint.h:284
int16_t int_fast16_t
Definition stdint.h:151
unsigned __int64 uint64_t
Definition stdint.h:136