From 5cd8d2b93fad2011fdf8f49a263d77697af35b32 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 11 Jul 2018 01:16:28 -0700 Subject: Upgrade to SoftFloat 3e --- softfloat/f64_div.c | 112 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 89 insertions(+), 23 deletions(-) mode change 100755 => 100644 softfloat/f64_div.c (limited to 'softfloat/f64_div.c') diff --git a/softfloat/f64_div.c b/softfloat/f64_div.c old mode 100755 new mode 100644 index c8eede9..7f5eddd --- a/softfloat/f64_div.c +++ b/softfloat/f64_div.c @@ -1,10 +1,42 @@ -// See LICENSE.SoftFloat for license details. +/*============================================================================ + +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 #include #include "platform.h" -#include "primitives.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" @@ -24,22 +56,28 @@ float64_t f64_div( float64_t a, float64_t b ) bool signZ; struct exp16_sig64 normExpSig; int_fast16_t expZ; + uint32_t recip32, sig32Z, doubleTerm; + uint_fast64_t rem; + uint32_t q; uint_fast64_t sigZ; - struct uint128 term, rem; uint_fast64_t uiZ; union ui64_f64 uZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; signA = signF64UI( uiA ); - expA = expF64UI( uiA ); - sigA = fracF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); uB.f = b; uiB = uB.ui; signB = signF64UI( uiB ); - expB = expF64UI( uiB ); - sigB = fracF64UI( uiB ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ if ( expA == 0x7FF ) { if ( sigA ) goto propagateNaN; if ( expB == 0x7FF ) { @@ -52,10 +90,12 @@ float64_t f64_div( float64_t a, float64_t b ) if ( sigB ) goto propagateNaN; goto zero; } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ if ( ! expB ) { if ( ! sigB ) { - if ( ! ( expA | sigA ) ) goto invalid; - softfloat_raiseFlags( softfloat_flag_infinity ); + if ( ! (expA | sigA) ) goto invalid; + softfloat_raiseFlags( softfloat_flag_infinite ); goto infinity; } normExpSig = softfloat_normSubnormalF64Sig( sigB ); @@ -68,34 +108,60 @@ float64_t f64_div( float64_t a, float64_t b ) expA = normExpSig.exp; sigA = normExpSig.sig; } - expZ = expA - expB + 0x3FD; - sigA = ( sigA | UINT64_C( 0x0010000000000000 ) )<<10; - sigB = ( sigB | UINT64_C( 0x0010000000000000 ) )<<11; - if ( sigB <= ( sigA + sigA ) ) { - ++expZ; - sigA >>= 1; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x3FE; + sigA |= UINT64_C( 0x0010000000000000 ); + sigB |= UINT64_C( 0x0010000000000000 ); + if ( sigA < sigB ) { + --expZ; + sigA <<= 11; + } else { + sigA <<= 10; } - sigZ = softfloat_estimateDiv128To64( sigA, 0, sigB ); - if ( ( sigZ & 0x1FF ) <= 2 ) { - term = softfloat_mul64To128( sigB, sigZ ); - rem = softfloat_sub128( sigA, 0, term.v64, term.v0 ); - while ( UINT64_C( 0x8000000000000000 ) <= rem.v64 ) { - --sigZ; - rem = softfloat_add128( rem.v64, rem.v0, 0, sigB ); + sigB <<= 11; + recip32 = softfloat_approxRecip32_1( sigB>>32 ) - 2; + sig32Z = ((uint32_t) (sigA>>32) * (uint_fast64_t) recip32)>>32; + doubleTerm = sig32Z<<1; + rem = + ((sigA - (uint_fast64_t) doubleTerm * (uint32_t) (sigB>>32))<<28) + - (uint_fast64_t) doubleTerm * ((uint32_t) sigB>>4); + q = (((uint32_t) (rem>>32) * (uint_fast64_t) recip32)>>32) + 4; + sigZ = ((uint_fast64_t) sig32Z<<32) + ((uint_fast64_t) q<<4); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (sigZ & 0x1FF) < 4<<4 ) { + q &= ~7; + sigZ &= ~(uint_fast64_t) 0x7F; + doubleTerm = q<<1; + rem = + ((rem - (uint_fast64_t) doubleTerm * (uint32_t) (sigB>>32))<<28) + - (uint_fast64_t) doubleTerm * ((uint32_t) sigB>>4); + if ( rem & UINT64_C( 0x8000000000000000 ) ) { + sigZ -= 1<<7; + } else { + if ( rem ) sigZ |= 1; } - sigZ |= ( rem.v0 != 0 ); } return softfloat_roundPackToF64( signZ, expZ, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF64UI; goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ infinity: uiZ = packToF64UI( signZ, 0x7FF, 0 ); goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ zero: uiZ = packToF64UI( signZ, 0, 0 ); uiZ: -- cgit v1.1