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, 2015 The Regents of the University of 8 California. 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 "softfloat.h" 42 43 void 44 softfloat_roundPackMToExtF80M( 45 bool sign, 46 int32_t exp, 47 uint32_t *extSigPtr, 48 uint_fast8_t roundingPrecision, 49 struct extFloat80M *zSPtr 50 ) 51 { 52 uint_fast8_t roundingMode; 53 bool roundNearEven; 54 uint64_t sig, roundIncrement, roundMask, roundBits; 55 bool isTiny; 56 uint32_t sigExtra; 57 bool doIncrement; 58 59 /*------------------------------------------------------------------------ 60 *------------------------------------------------------------------------*/ 61 roundingMode = softfloat_roundingMode; 62 roundNearEven = (roundingMode == softfloat_round_near_even); 63 sig = 64 (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32 65 | extSigPtr[indexWord( 3, 1 )]; 66 if ( roundingPrecision == 80 ) goto precision80; 67 if ( roundingPrecision == 64 ) { 68 roundIncrement = UINT64_C( 0x0000000000000400 ); 69 roundMask = UINT64_C( 0x00000000000007FF ); 70 } else if ( roundingPrecision == 32 ) { 71 roundIncrement = UINT64_C( 0x0000008000000000 ); 72 roundMask = UINT64_C( 0x000000FFFFFFFFFF ); 73 } else { 74 goto precision80; 75 } 76 /*------------------------------------------------------------------------ 77 *------------------------------------------------------------------------*/ 78 if ( extSigPtr[indexWordLo( 3 )] ) sig |= 1; 79 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { 80 roundIncrement = 81 (roundingMode 82 == (sign ? softfloat_round_min : softfloat_round_max)) 83 ? roundMask 84 : 0; 85 } 86 roundBits = sig & roundMask; 87 /*------------------------------------------------------------------------ 88 *------------------------------------------------------------------------*/ 89 if ( 0x7FFD <= (uint32_t) (exp - 1) ) { 90 if ( exp <= 0 ) { 91 isTiny = 92 (softfloat_detectTininess 93 == softfloat_tininess_beforeRounding) 94 || (exp < 0) 95 || (sig <= (uint64_t) (sig + roundIncrement)); 96 sig = softfloat_shiftRightJam64( sig, 1 - exp ); 97 roundBits = sig & roundMask; 98 if ( roundBits ) { 99 if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow ); 100 softfloat_exceptionFlags |= softfloat_flag_inexact; 101 } 102 sig += roundIncrement; 103 exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0); 104 roundIncrement = roundMask + 1; 105 if ( roundNearEven && (roundBits<<1 == roundIncrement) ) { 106 roundMask |= roundIncrement; 107 } 108 sig &= ~roundMask; 109 goto packReturn; 110 } 111 if ( 112 (0x7FFE < exp) 113 || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig)) 114 ) { 115 goto overflow; 116 } 117 } 118 /*------------------------------------------------------------------------ 119 *------------------------------------------------------------------------*/ 120 if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; 121 sig += roundIncrement; 122 if ( sig < roundIncrement ) { 123 ++exp; 124 sig = UINT64_C( 0x8000000000000000 ); 125 } 126 roundIncrement = roundMask + 1; 127 if ( roundNearEven && (roundBits<<1 == roundIncrement) ) { 128 roundMask |= roundIncrement; 129 } 130 sig &= ~roundMask; 131 goto packReturn; 132 /*------------------------------------------------------------------------ 133 *------------------------------------------------------------------------*/ 134 precision80: 135 sigExtra = extSigPtr[indexWordLo( 3 )]; 136 doIncrement = (0x80000000 <= sigExtra); 137 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { 138 doIncrement = 139 (roundingMode 140 == (sign ? softfloat_round_min : softfloat_round_max)) 141 && sigExtra; 142 } 143 /*------------------------------------------------------------------------ 144 *------------------------------------------------------------------------*/ 145 if ( 0x7FFD <= (uint32_t) (exp - 1) ) { 146 /*-------------------------------------------------------------------- 147 *--------------------------------------------------------------------*/ 148 if ( exp <= 0 ) { 149 isTiny = 150 (softfloat_detectTininess 151 == softfloat_tininess_beforeRounding) 152 || (exp < 0) 153 || ! doIncrement 154 || (sig < UINT64_C( 0xFFFFFFFFFFFFFFFF )); 155 softfloat_shiftRightJam96M( extSigPtr, 1 - exp, extSigPtr ); 156 sigExtra = extSigPtr[indexWordLo( 3 )]; 157 if ( sigExtra ) { 158 if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow ); 159 softfloat_exceptionFlags |= softfloat_flag_inexact; 160 } 161 doIncrement = (0x80000000 <= sigExtra); 162 if ( 163 ! roundNearEven 164 && (roundingMode != softfloat_round_near_maxMag) 165 ) { 166 doIncrement = 167 (roundingMode 168 == (sign ? softfloat_round_min : softfloat_round_max)) 169 && sigExtra; 170 } 171 exp = 0; 172 sig = 173 (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32 174 | extSigPtr[indexWord( 3, 1 )]; 175 if ( doIncrement ) { 176 ++sig; 177 sig &= ~(uint64_t) (! (sigExtra & 0x7FFFFFFF) & roundNearEven); 178 exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0); 179 } 180 goto packReturn; 181 } 182 /*-------------------------------------------------------------------- 183 *--------------------------------------------------------------------*/ 184 if ( 185 (0x7FFE < exp) 186 || ((exp == 0x7FFE) && (sig == UINT64_C( 0xFFFFFFFFFFFFFFFF )) 187 && doIncrement) 188 ) { 189 roundMask = 0; 190 overflow: 191 softfloat_raiseFlags( 192 softfloat_flag_overflow | softfloat_flag_inexact ); 193 if ( 194 roundNearEven 195 || (roundingMode == softfloat_round_near_maxMag) 196 || (roundingMode 197 == (sign ? softfloat_round_min : softfloat_round_max)) 198 ) { 199 exp = 0x7FFF; 200 sig = UINT64_C( 0x8000000000000000 ); 201 } else { 202 exp = 0x7FFE; 203 sig = ~roundMask; 204 } 205 goto packReturn; 206 } 207 } 208 /*------------------------------------------------------------------------ 209 *------------------------------------------------------------------------*/ 210 if ( sigExtra ) softfloat_exceptionFlags |= softfloat_flag_inexact; 211 if ( doIncrement ) { 212 ++sig; 213 if ( ! sig ) { 214 ++exp; 215 sig = UINT64_C( 0x8000000000000000 ); 216 } else { 217 sig &= ~(uint64_t) (! (sigExtra & 0x7FFFFFFF) & roundNearEven); 218 } 219 } 220 /*------------------------------------------------------------------------ 221 *------------------------------------------------------------------------*/ 222 packReturn: 223 zSPtr->signExp = packToExtF80UI64( sign, exp ); 224 zSPtr->signif = sig; 225 226 } 227 228