|
| 1 | +/*============================================================================ |
| 2 | +
|
| 3 | +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic |
| 4 | +Package, Release 3d, by John R. Hauser. |
| 5 | +
|
| 6 | +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of |
| 7 | +California. All rights reserved. |
| 8 | +
|
| 9 | +Redistribution and use in source and binary forms, with or without |
| 10 | +modification, are permitted provided that the following conditions are met: |
| 11 | +
|
| 12 | + 1. Redistributions of source code must retain the above copyright notice, |
| 13 | + this list of conditions, and the following disclaimer. |
| 14 | +
|
| 15 | + 2. Redistributions in binary form must reproduce the above copyright notice, |
| 16 | + this list of conditions, and the following disclaimer in the documentation |
| 17 | + and/or other materials provided with the distribution. |
| 18 | +
|
| 19 | + 3. Neither the name of the University nor the names of its contributors may |
| 20 | + be used to endorse or promote products derived from this software without |
| 21 | + specific prior written permission. |
| 22 | +
|
| 23 | +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY |
| 24 | +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 25 | +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE |
| 26 | +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY |
| 27 | +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 28 | +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 29 | +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 30 | +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 31 | +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 32 | +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 33 | +
|
| 34 | +=============================================================================*/ |
| 35 | + |
| 36 | +#include <stdbool.h> |
| 37 | +#include <stdint.h> |
| 38 | +#include "platform.h" |
| 39 | +#include "internals.h" |
| 40 | +#include "softfloat.h" |
| 41 | + |
| 42 | +float8_t |
| 43 | + softfloat_roundPackToF8( bool sign, int_fast8_t exp, uint_fast16_t sig ) |
| 44 | +{ |
| 45 | + uint_fast8_t roundingMode; |
| 46 | + bool roundNearEven; |
| 47 | + uint_fast8_t roundIncrement, roundBits; |
| 48 | + bool isTiny; |
| 49 | + uint_fast8_t uiZ; |
| 50 | + union ui8_f8 uZ; |
| 51 | + |
| 52 | + /*------------------------------------------------------------------------ |
| 53 | + *------------------------------------------------------------------------*/ |
| 54 | + roundingMode = softfloat_roundingMode; |
| 55 | + roundNearEven = (roundingMode == softfloat_round_near_even); |
| 56 | + roundIncrement = 0x8; // How much to add to round, in this case 0x4 since we only need to round if gaurd bit it set |
| 57 | + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { |
| 58 | + roundIncrement = |
| 59 | + (roundingMode |
| 60 | + == (sign ? softfloat_round_min : softfloat_round_max)) |
| 61 | + ? 0xF // Always round up |
| 62 | + : 0; // Always round down |
| 63 | + } |
| 64 | + roundBits = sig & 0xF; |
| 65 | + /*------------------------------------------------------------------------ |
| 66 | + *------------------------------------------------------------------------*/ |
| 67 | + if ( exp < 0 ) { |
| 68 | + isTiny = |
| 69 | + (softfloat_detectTininess == softfloat_tininess_beforeRounding) |
| 70 | + || (exp < -1)// If exp == -2 rounding doesn't matter, will be tiny regardless |
| 71 | + || (sig + roundIncrement < 0x200); // make rounding won't increment exp |
| 72 | + sig = softfloat_shiftRightJam32( sig, -exp ); // shift right and update sticky bit |
| 73 | + exp = 0; // Set exponent to 0 for subnormal |
| 74 | + roundBits = sig & 0xF; // GRS |
| 75 | + if ( isTiny && roundBits ) { |
| 76 | + softfloat_raiseFlags( softfloat_flag_underflow ); |
| 77 | + } |
| 78 | + /*---------------------------------------------------------------- |
| 79 | + *----------------------------------------------------------------*/ |
| 80 | + } else if ( (0x7 < exp) // Already too large |
| 81 | + || ((0x200 <= sig + roundIncrement) && exp == 0x7)) { // At max exp but round up |
| 82 | + softfloat_raiseFlags( |
| 83 | + softfloat_flag_overflow | softfloat_flag_inexact ); |
| 84 | + uiZ = signInfF8UI(sign) - ! roundIncrement; // TODO: confused |
| 85 | + goto uiZ; |
| 86 | + } |
| 87 | + /*------------------------------------------------------------------------ |
| 88 | + *------------------------------------------------------------------------*/ |
| 89 | + sig = (sig + roundIncrement)>>4; // Round and delete GSR bits |
| 90 | + if ( roundBits ) { |
| 91 | + softfloat_exceptionFlags |= softfloat_flag_inexact; |
| 92 | +#ifdef SOFTFLOAT_ROUND_ODD |
| 93 | + if ( roundingMode == softfloat_round_odd ) { |
| 94 | + sig |= 1; |
| 95 | + goto packReturn; |
| 96 | + } |
| 97 | +#endif |
| 98 | + } |
| 99 | + sig &= ~(uint_fast16_t) (! (roundBits ^ 8) & roundNearEven); |
| 100 | + if ( ! sig ) { |
| 101 | + exp = 0; |
| 102 | + sign = 0; // Encode as zero |
| 103 | + } |
| 104 | + /*------------------------------------------------------------------------ |
| 105 | + *------------------------------------------------------------------------*/ |
| 106 | + packReturn: |
| 107 | + uiZ = packToF8UI( sign, exp, (uint_fast8_t) sig); |
| 108 | + uiZ: |
| 109 | + uZ.ui = uiZ; |
| 110 | + return uZ.f; |
| 111 | +} |
0 commit comments