aboutsummaryrefslogtreecommitdiff
path: root/source/s_subMagsF32.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/s_subMagsF32.c')
-rw-r--r--source/s_subMagsF32.c128
1 files changed, 78 insertions, 50 deletions
diff --git a/source/s_subMagsF32.c b/source/s_subMagsF32.c
index ba5ac9a..012d4da 100644
--- a/source/s_subMagsF32.c
+++ b/source/s_subMagsF32.c
@@ -2,10 +2,10 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
-Package, Release 3a, by John R. Hauser.
+Package, Release 3b, by John R. Hauser.
-Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
-All rights reserved.
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 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:
@@ -41,8 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "specialize.h"
#include "softfloat.h"
-float32_t
- softfloat_subMagsF32( uint_fast32_t uiA, uint_fast32_t uiB, bool signZ )
+float32_t softfloat_subMagsF32( uint_fast32_t uiA, uint_fast32_t uiB )
{
int_fast16_t expA;
uint_fast32_t sigA;
@@ -50,61 +49,90 @@ float32_t
uint_fast32_t sigB;
int_fast16_t expDiff;
uint_fast32_t uiZ;
+ int_fast32_t sigDiff;
+ bool signZ;
+ int_fast8_t shiftDist;
int_fast16_t expZ;
- uint_fast32_t sigZ;
+ uint_fast32_t sigX, sigY;
union ui32_f32 uZ;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
expA = expF32UI( uiA );
sigA = fracF32UI( uiA );
expB = expF32UI( uiB );
sigB = fracF32UI( uiB );
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
expDiff = expA - expB;
- sigA <<= 7;
- sigB <<= 7;
- if ( 0 < expDiff ) goto expABigger;
- if ( expDiff < 0 ) goto expBBigger;
- if ( expA == 0xFF ) {
- if ( sigA | sigB ) goto propagateNaN;
- softfloat_raiseFlags( softfloat_flag_invalid );
- uiZ = defaultNaNF32UI;
+ if ( ! expDiff ) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if ( expA == 0xFF ) {
+ if ( sigA | sigB ) goto propagateNaN;
+ softfloat_raiseFlags( softfloat_flag_invalid );
+ uiZ = defaultNaNF32UI;
+ goto uiZ;
+ }
+ sigDiff = sigA - sigB;
+ if ( ! sigDiff ) {
+ uiZ =
+ packToF32UI(
+ (softfloat_roundingMode == softfloat_round_min), 0, 0 );
+ goto uiZ;
+ }
+ if ( expA ) --expA;
+ signZ = signF32UI( uiA );
+ if ( sigDiff < 0 ) {
+ signZ = ! signZ;
+ sigDiff = -sigDiff;
+ }
+ shiftDist = softfloat_countLeadingZeros32( sigDiff ) - 8;
+ expZ = expA - shiftDist;
+ if ( expZ < 0 ) {
+ shiftDist = expA;
+ expZ = 0;
+ }
+ uiZ = packToF32UI( signZ, expZ, sigDiff<<shiftDist );
goto uiZ;
+ } else {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ signZ = signF32UI( uiA );
+ sigA <<= 7;
+ sigB <<= 7;
+ if ( expDiff < 0 ) {
+ /*----------------------------------------------------------------
+ *----------------------------------------------------------------*/
+ signZ = ! signZ;
+ if ( expB == 0xFF ) {
+ if ( sigB ) goto propagateNaN;
+ uiZ = packToF32UI( signZ, 0xFF, 0 );
+ goto uiZ;
+ }
+ expZ = expB - 1;
+ sigX = sigB | 0x40000000;
+ sigY = sigA + (expA ? 0x40000000 : sigA);
+ expDiff = -expDiff;
+ } else {
+ /*----------------------------------------------------------------
+ *----------------------------------------------------------------*/
+ if ( expA == 0xFF ) {
+ if ( sigA ) goto propagateNaN;
+ uiZ = uiA;
+ goto uiZ;
+ }
+ expZ = expA - 1;
+ sigX = sigA | 0x40000000;
+ sigY = sigB + (expB ? 0x40000000 : sigB);
+ }
+ return
+ softfloat_normRoundPackToF32(
+ signZ, expZ, sigX - softfloat_shiftRightJam32( sigY, expDiff )
+ );
}
- if ( ! expA ) {
- expA = 1;
- expB = 1;
- }
- if ( sigB < sigA ) goto aBigger;
- if ( sigA < sigB ) goto bBigger;
- uiZ = packToF32UI( softfloat_roundingMode == softfloat_round_min, 0, 0 );
- goto uiZ;
- expBBigger:
- if ( expB == 0xFF ) {
- if ( sigB ) goto propagateNaN;
- uiZ = packToF32UI( signZ ^ 1, 0xFF, 0 );
- goto uiZ;
- }
- sigA += expA ? 0x40000000 : sigA;
- sigA = softfloat_shiftRightJam32( sigA, -expDiff );
- sigB |= 0x40000000;
- bBigger:
- signZ ^= 1;
- expZ = expB;
- sigZ = sigB - sigA;
- goto normRoundPack;
- expABigger:
- if ( expA == 0xFF ) {
- if ( sigA ) goto propagateNaN;
- uiZ = uiA;
- goto uiZ;
- }
- sigB += expB ? 0x40000000 : sigB;
- sigB = softfloat_shiftRightJam32( sigB, expDiff );
- sigA |= 0x40000000;
- aBigger:
- expZ = expA;
- sigZ = sigA - sigB;
- normRoundPack:
- return softfloat_normRoundPackToF32( signZ, expZ - 1, sigZ );
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
propagateNaN:
uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
uiZ: