summaryrefslogtreecommitdiffstats
path: root/src/libs/softfloat-3e/source/s_subMagsF16.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/softfloat-3e/source/s_subMagsF16.c')
-rw-r--r--src/libs/softfloat-3e/source/s_subMagsF16.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/src/libs/softfloat-3e/source/s_subMagsF16.c b/src/libs/softfloat-3e/source/s_subMagsF16.c
new file mode 100644
index 00000000..3a21efec
--- /dev/null
+++ b/src/libs/softfloat-3e/source/s_subMagsF16.c
@@ -0,0 +1,187 @@
+
+/*============================================================================
+
+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, 2015, 2016, 2017 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"
+
+float16_t softfloat_subMagsF16( uint_fast16_t uiA, uint_fast16_t uiB SOFTFLOAT_STATE_DECL_COMMA )
+{
+ int_fast8_t expA;
+ uint_fast16_t sigA;
+ int_fast8_t expB;
+ uint_fast16_t sigB;
+ int_fast8_t expDiff;
+ uint_fast16_t uiZ;
+ int_fast16_t sigDiff;
+ bool signZ;
+ int_fast8_t shiftDist, expZ;
+ uint_fast16_t sigZ, sigX, sigY;
+ uint_fast32_t sig32Z;
+ int_fast8_t roundingMode;
+ union ui16_f16 uZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expA = expF16UI( uiA );
+ sigA = fracF16UI( uiA );
+ expB = expF16UI( uiB );
+ sigB = fracF16UI( uiB );
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expDiff = expA - expB;
+ if ( ! expDiff ) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if ( expA == 0x1F ) {
+ if ( sigA | sigB ) goto propagateNaN;
+ softfloat_raiseFlags( softfloat_flag_invalid SOFTFLOAT_STATE_ARG_COMMA );
+ uiZ = defaultNaNF16UI;
+ goto uiZ;
+ }
+ sigDiff = sigA - sigB;
+ if ( ! sigDiff ) {
+ uiZ =
+ packToF16UI(
+ (softfloat_roundingMode == softfloat_round_min), 0, 0 );
+ goto uiZ;
+ }
+ if ( expA ) --expA;
+ signZ = signF16UI( uiA );
+ if ( sigDiff < 0 ) {
+ signZ = ! signZ;
+ sigDiff = -sigDiff;
+ }
+ shiftDist = softfloat_countLeadingZeros16( sigDiff ) - 5;
+ expZ = expA - shiftDist;
+ if ( expZ < 0 ) {
+ shiftDist = expA;
+ expZ = 0;
+ }
+ sigZ = sigDiff<<shiftDist;
+ goto pack;
+ } else {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ signZ = signF16UI( uiA );
+ if ( expDiff < 0 ) {
+ /*----------------------------------------------------------------
+ *----------------------------------------------------------------*/
+ signZ = ! signZ;
+ if ( expB == 0x1F ) {
+ if ( sigB ) goto propagateNaN;
+ uiZ = packToF16UI( signZ, 0x1F, 0 );
+ goto uiZ;
+ }
+ if ( expDiff <= -13 ) {
+ uiZ = packToF16UI( signZ, expB, sigB );
+ if ( expA | sigA ) goto subEpsilon;
+ goto uiZ;
+ }
+ expZ = expA + 19;
+ sigX = sigB | 0x0400;
+ sigY = sigA + (expA ? 0x0400 : sigA);
+ expDiff = -expDiff;
+ } else {
+ /*----------------------------------------------------------------
+ *----------------------------------------------------------------*/
+ uiZ = uiA;
+ if ( expA == 0x1F ) {
+ if ( sigA ) goto propagateNaN;
+ goto uiZ;
+ }
+ if ( 13 <= expDiff ) {
+ if ( expB | sigB ) goto subEpsilon;
+ goto uiZ;
+ }
+ expZ = expB + 19;
+ sigX = sigA | 0x0400;
+ sigY = sigB + (expB ? 0x0400 : sigB);
+ }
+ sig32Z = ((uint_fast32_t) sigX<<expDiff) - sigY;
+ shiftDist = softfloat_countLeadingZeros32( sig32Z ) - 1;
+ sig32Z <<= shiftDist;
+ expZ -= shiftDist;
+ sigZ = sig32Z>>16;
+ if ( sig32Z & 0xFFFF ) {
+ sigZ |= 1;
+ } else {
+ if ( ! (sigZ & 0xF) && ((unsigned int) expZ < 0x1E) ) {
+ sigZ >>= 4;
+ goto pack;
+ }
+ }
+ return softfloat_roundPackToF16( signZ, expZ, sigZ SOFTFLOAT_STATE_ARG_COMMA );
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ uiZ = softfloat_propagateNaNF16UI( uiA, uiB SOFTFLOAT_STATE_ARG_COMMA );
+ goto uiZ;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ subEpsilon:
+ roundingMode = softfloat_roundingMode;
+ if ( roundingMode != softfloat_round_near_even ) {
+ if (
+ (roundingMode == softfloat_round_minMag)
+ || (roundingMode
+ == (signF16UI( uiZ ) ? softfloat_round_max
+ : softfloat_round_min))
+ ) {
+ --uiZ;
+ }
+#ifdef SOFTFLOAT_ROUND_ODD
+ else if ( roundingMode == softfloat_round_odd ) {
+ uiZ = (uiZ - 1) | 1;
+ }
+#endif
+ }
+ softfloat_exceptionFlags |= softfloat_flag_inexact;
+ goto uiZ;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ pack:
+ uiZ = packToF16UI( signZ, expZ, sigZ );
+ uiZ:
+ uZ.ui = uiZ;
+ return uZ.f;
+
+}
+