diff options
Diffstat (limited to 'softfloat/f64_mul.c')
-rw-r--r--[-rwxr-xr-x] | softfloat/f64_mul.c | 241 |
1 files changed, 149 insertions, 92 deletions
diff --git a/softfloat/f64_mul.c b/softfloat/f64_mul.c index cdd8c78..38bdc85 100755..100644 --- a/softfloat/f64_mul.c +++ b/softfloat/f64_mul.c @@ -1,93 +1,150 @@ -// See LICENSE.SoftFloat for license details. -
-#include <stdbool.h>
-#include <stdint.h>
-#include "platform.h"
-#include "primitives.h"
-#include "internals.h"
-#include "specialize.h"
-#include "softfloat.h"
-
-float64_t f64_mul( float64_t a, float64_t b )
-{
- union ui64_f64 uA;
- uint_fast64_t uiA;
- bool signA;
- int_fast16_t expA;
- uint_fast64_t sigA;
- union ui64_f64 uB;
- uint_fast64_t uiB;
- bool signB;
- int_fast16_t expB;
- uint_fast64_t sigB;
- bool signZ;
- uint_fast64_t magBits;
- struct exp16_sig64 normExpSig;
- int_fast16_t expZ;
- struct uint128 sigZ128;
- uint_fast64_t sigZ, uiZ;
- union ui64_f64 uZ;
-
- uA.f = a;
- uiA = uA.ui;
- signA = signF64UI( uiA );
- expA = expF64UI( uiA );
- sigA = fracF64UI( uiA );
- uB.f = b;
- uiB = uB.ui;
- signB = signF64UI( uiB );
- expB = expF64UI( uiB );
- sigB = fracF64UI( uiB );
- signZ = signA ^ signB;
- if ( expA == 0x7FF ) {
- if ( sigA || ( ( expB == 0x7FF ) && sigB ) ) goto propagateNaN;
- magBits = expB | sigB;
- goto infArg;
- }
- if ( expB == 0x7FF ) {
- if ( sigB ) goto propagateNaN;
- magBits = expA | sigA;
- goto infArg;
- }
- if ( ! expA ) {
- if ( ! sigA ) goto zero;
- normExpSig = softfloat_normSubnormalF64Sig( sigA );
- expA = normExpSig.exp;
- sigA = normExpSig.sig;
- }
- if ( ! expB ) {
- if ( ! sigB ) goto zero;
- normExpSig = softfloat_normSubnormalF64Sig( sigB );
- expB = normExpSig.exp;
- sigB = normExpSig.sig;
- }
- expZ = expA + expB - 0x3FF;
- sigA = ( sigA | UINT64_C( 0x0010000000000000 ) )<<10;
- sigB = ( sigB | UINT64_C( 0x0010000000000000 ) )<<11;
- sigZ128 = softfloat_mul64To128( sigA, sigB );
- sigZ = sigZ128.v64 | ( sigZ128.v0 != 0 );
- if ( sigZ < UINT64_C( 0x4000000000000000 ) ) {
- --expZ;
- sigZ <<= 1;
- }
- return softfloat_roundPackToF64( signZ, expZ, sigZ );
- propagateNaN:
- uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
- goto uiZ;
- infArg:
- if ( ! magBits ) {
- softfloat_raiseFlags( softfloat_flag_invalid );
- uiZ = defaultNaNF64UI;
- } else {
- uiZ = packToF64UI( signZ, 0x7FF, 0 );
- }
- goto uiZ;
- zero:
- uiZ = packToF64UI( signZ, 0, 0 );
- uiZ:
- uZ.ui = uiZ;
- return uZ.f;
-
-}
-
+/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include <stdbool.h> +#include <stdint.h> +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f64_mul( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool signA; + int_fast16_t expA; + uint_fast64_t sigA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signB; + int_fast16_t expB; + uint_fast64_t sigB; + bool signZ; + uint_fast64_t magBits; + struct exp16_sig64 normExpSig; + int_fast16_t expZ; +#ifdef SOFTFLOAT_FAST_INT64 + struct uint128 sig128Z; +#else + uint32_t sig128Z[4]; +#endif + uint_fast64_t sigZ, uiZ; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF64UI( uiB ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN; + magBits = expB | sigB; + goto infArg; + } + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + magBits = expA | sigA; + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! sigA ) goto zero; + normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) { + if ( ! sigB ) goto zero; + normExpSig = softfloat_normSubnormalF64Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FF; + sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10; + sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<11; +#ifdef SOFTFLOAT_FAST_INT64 + sig128Z = softfloat_mul64To128( sigA, sigB ); + sigZ = sig128Z.v64 | (sig128Z.v0 != 0); +#else + softfloat_mul64To128M( sigA, sigB, sig128Z ); + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; + if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) sigZ |= 1; +#endif + if ( sigZ < UINT64_C( 0x4000000000000000 ) ) { + --expZ; + sigZ <<= 1; + } + return softfloat_roundPackToF64( signZ, expZ, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if ( ! magBits ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + } else { + uiZ = packToF64UI( signZ, 0x7FF, 0 ); + } + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ = packToF64UI( signZ, 0, 0 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + |