1 2 /*============================================================================ 3 4 This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 5 Package, Release 3a, by John R. Hauser. 6 7 Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. 8 All rights reserved. 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions are met: 12 13 1. Redistributions of source code must retain the above copyright notice, 14 this list of conditions, and the following disclaimer. 15 16 2. Redistributions in binary form must reproduce the above copyright notice, 17 this list of conditions, and the following disclaimer in the documentation 18 and/or other materials provided with the distribution. 19 20 3. Neither the name of the University nor the names of its contributors may 21 be used to endorse or promote products derived from this software without 22 specific prior written permission. 23 24 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 25 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 27 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 35 =============================================================================*/ 36 37 #include <stdbool.h> 38 #include <stdint.h> 39 #include "platform.h" 40 #include "internals.h" 41 #include "specialize.h" 42 #include "softfloat.h" 43 44 #ifdef SOFTFLOAT_FAST_INT64 45 46 void 47 f128M_roundToInt( 48 const float128_t *aPtr, 49 uint_fast8_t roundingMode, 50 bool exact, 51 float128_t *zPtr 52 ) 53 { 54 55 *zPtr = f128_roundToInt( *aPtr, roundingMode, exact ); 56 57 } 58 59 #else 60 61 void 62 f128M_roundToInt( 63 const float128_t *aPtr, 64 uint_fast8_t roundingMode, 65 bool exact, 66 float128_t *zPtr 67 ) 68 { 69 const uint32_t *aWPtr; 70 uint32_t *zWPtr; 71 uint32_t ui96; 72 int32_t exp; 73 uint32_t sigExtra; 74 bool sign; 75 uint_fast8_t bitPos; 76 bool roundNear; 77 unsigned int index, lastIndex; 78 bool extra; 79 uint32_t wordA, bit, wordZ; 80 uint_fast8_t carry; 81 uint32_t extrasMask; 82 83 /*------------------------------------------------------------------------ 84 *------------------------------------------------------------------------*/ 85 aWPtr = (const uint32_t *) aPtr; 86 zWPtr = (uint32_t *) zPtr; 87 /*------------------------------------------------------------------------ 88 *------------------------------------------------------------------------*/ 89 ui96 = aWPtr[indexWordHi( 4 )]; 90 exp = expF128UI96( ui96 ); 91 /*------------------------------------------------------------------------ 92 *------------------------------------------------------------------------*/ 93 if ( exp < 0x3FFF ) { 94 zWPtr[indexWord( 4, 2 )] = 0; 95 zWPtr[indexWord( 4, 1 )] = 0; 96 zWPtr[indexWord( 4, 0 )] = 0; 97 sigExtra = aWPtr[indexWord( 4, 2 )]; 98 if ( ! sigExtra ) { 99 sigExtra = aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]; 100 } 101 if ( ! sigExtra && ! (ui96 & 0x7FFFFFFF) ) goto ui96; 102 if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; 103 sign = signF128UI96( ui96 ); 104 switch ( roundingMode ) { 105 case softfloat_round_near_even: 106 if ( ! fracF128UI96( ui96 ) && ! sigExtra ) break; 107 case softfloat_round_near_maxMag: 108 if ( exp == 0x3FFE ) goto mag1; 109 break; 110 case softfloat_round_min: 111 if ( sign ) goto mag1; 112 break; 113 case softfloat_round_max: 114 if ( ! sign ) goto mag1; 115 break; 116 } 117 ui96 = packToF128UI96( sign, 0, 0 ); 118 goto ui96; 119 mag1: 120 ui96 = packToF128UI96( sign, 0x3FFF, 0 ); 121 goto ui96; 122 } 123 /*------------------------------------------------------------------------ 124 *------------------------------------------------------------------------*/ 125 if ( 0x406F <= exp ) { 126 if ( 127 (exp == 0x7FFF) 128 && (fracF128UI96( ui96 ) 129 || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] 130 | aWPtr[indexWord( 4, 0 )])) 131 ) { 132 softfloat_propagateNaNF128M( aWPtr, 0, zWPtr ); 133 return; 134 } 135 zWPtr[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; 136 zWPtr[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; 137 zWPtr[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; 138 goto ui96; 139 } 140 /*------------------------------------------------------------------------ 141 *------------------------------------------------------------------------*/ 142 bitPos = 0x406F - exp; 143 roundNear = 144 (roundingMode == softfloat_round_near_maxMag) 145 || (roundingMode == softfloat_round_near_even); 146 bitPos -= roundNear; 147 index = indexWordLo( 4 ); 148 lastIndex = indexWordHi( 4 ); 149 extra = 0; 150 for (;;) { 151 wordA = aWPtr[index]; 152 if ( bitPos < 32 ) break; 153 if ( wordA ) extra = 1; 154 zWPtr[index] = 0; 155 index += wordIncr; 156 bitPos -= 32; 157 } 158 bit = (uint32_t) 1<<bitPos; 159 if ( roundNear ) { 160 wordZ = wordA + bit; 161 carry = (wordZ < wordA); 162 bit <<= 1; 163 extrasMask = bit - 1; 164 if ( 165 (roundingMode == softfloat_round_near_even) 166 && ! extra && ! (wordZ & extrasMask) 167 ) { 168 if ( ! bit ) { 169 zWPtr[index] = wordZ; 170 index += wordIncr; 171 wordZ = aWPtr[index] + carry; 172 carry &= ! wordZ; 173 zWPtr[index] = wordZ & ~1; 174 goto propagateCarry; 175 } 176 wordZ &= ~bit; 177 } 178 } else { 179 extrasMask = bit - 1; 180 wordZ = wordA; 181 carry = 0; 182 if ( 183 (roundingMode != softfloat_round_minMag) 184 && (signF128UI96( ui96 ) ^ (roundingMode == softfloat_round_max)) 185 ) { 186 if ( extra || (wordA & extrasMask) ) { 187 wordZ += bit; 188 carry = (wordZ < wordA); 189 } 190 } 191 } 192 wordZ &= ~extrasMask; 193 zWPtr[index] = wordZ; 194 propagateCarry: 195 while ( index != lastIndex ) { 196 index += wordIncr; 197 wordZ = aWPtr[index] + carry; 198 zWPtr[index] = wordZ; 199 carry &= ! wordZ; 200 } 201 /*------------------------------------------------------------------------ 202 *------------------------------------------------------------------------*/ 203 if ( exact && (softfloat_compare128M( aWPtr, zWPtr ) != 0) ) { 204 softfloat_exceptionFlags |= softfloat_flag_inexact; 205 } 206 return; 207 /*------------------------------------------------------------------------ 208 *------------------------------------------------------------------------*/ 209 ui96: 210 zWPtr[indexWordHi( 4 )] = ui96; 211 212 } 213 214 #endif 215 216