1 // SPDX-License-Identifier: BSD-3-Clause 2 3 /*============================================================================ 4 5 This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 6 Package, Release 3a, by John R. Hauser. 7 8 Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of 9 California. All rights reserved. 10 11 Redistribution and use in source and binary forms, with or without 12 modification, are permitted provided that the following conditions are met: 13 14 1. Redistributions of source code must retain the above copyright notice, 15 this list of conditions, and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright notice, 18 this list of conditions, and the following disclaimer in the documentation 19 and/or other materials provided with the distribution. 20 21 3. Neither the name of the University nor the names of its contributors may 22 be used to endorse or promote products derived from this software without 23 specific prior written permission. 24 25 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 26 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 27 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 28 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 29 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 30 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 32 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 36 =============================================================================*/ 37 38 #include <stdbool.h> 39 #include <stdint.h> 40 #include "platform.h" 41 #include "internals.h" 42 #include "specialize.h" 43 #include "softfloat.h" 44 45 void softfloat_mulAddF128M(const uint32_t * aWPtr,const uint32_t * bWPtr,const uint32_t * cWPtr,uint32_t * zWPtr,uint_fast8_t op)46 softfloat_mulAddF128M( 47 const uint32_t *aWPtr, 48 const uint32_t *bWPtr, 49 const uint32_t *cWPtr, 50 uint32_t *zWPtr, 51 uint_fast8_t op 52 ) 53 { 54 uint32_t uiA96; 55 int32_t expA; 56 uint32_t uiB96; 57 int32_t expB; 58 uint32_t uiC96; 59 bool signC; 60 int32_t expC; 61 bool signProd, prodIsInfinite; 62 uint32_t *ptr, uiZ96, sigA[4]; 63 uint_fast8_t shiftCount; 64 uint32_t sigX[5]; 65 int32_t expProd; 66 uint32_t sigProd[8], wordSig; 67 bool doSub; 68 uint_fast8_t 69 (*addCarryMRoutinePtr)( 70 uint_fast8_t, 71 const uint32_t *, 72 const uint32_t *, 73 uint_fast8_t, 74 uint32_t * 75 ); 76 int32_t expDiff; 77 bool signZ; 78 int32_t expZ; 79 uint32_t *extSigPtr; 80 uint_fast8_t carry; 81 void (*roundPackRoutinePtr)( bool, int32_t, uint32_t *, uint32_t * ); 82 83 /*------------------------------------------------------------------------ 84 *------------------------------------------------------------------------*/ 85 uiA96 = aWPtr[indexWordHi( 4 )]; 86 expA = expF128UI96( uiA96 ); 87 uiB96 = bWPtr[indexWordHi( 4 )]; 88 expB = expF128UI96( uiB96 ); 89 uiC96 = cWPtr[indexWordHi( 4 )]; 90 signC = signF128UI96( uiC96 ) ^ (op == softfloat_mulAdd_subC); 91 expC = expF128UI96( uiC96 ); 92 signProd = 93 signF128UI96( uiA96 ) ^ signF128UI96( uiB96 ) 94 ^ (op == softfloat_mulAdd_subProd); 95 /*------------------------------------------------------------------------ 96 *------------------------------------------------------------------------*/ 97 prodIsInfinite = false; 98 if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { 99 if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) { 100 goto propagateNaN_ZC; 101 } 102 ptr = (uint32_t *) aWPtr; 103 if ( ! (uint32_t) (uiA96<<1) ) goto possibleInvalidProd; 104 if ( ! (uint32_t) (uiB96<<1) ) { 105 ptr = (uint32_t *) bWPtr; 106 possibleInvalidProd: 107 if ( 108 ! (ptr[indexWord( 4, 2 )] | ptr[indexWord( 4, 1 )] 109 | ptr[indexWord( 4, 0 )]) 110 ) { 111 goto invalid; 112 } 113 } 114 prodIsInfinite = true; 115 } 116 if ( expC == 0x7FFF ) { 117 if ( 118 fracF128UI96( uiC96 ) 119 || (cWPtr[indexWord( 4, 2 )] | cWPtr[indexWord( 4, 1 )] 120 | cWPtr[indexWord( 4, 0 )]) 121 ) { 122 zWPtr[indexWordHi( 4 )] = 0; 123 goto propagateNaN_ZC; 124 } 125 if ( prodIsInfinite && (signProd != signC) ) goto invalid; 126 goto copyC; 127 } 128 if ( prodIsInfinite ) { 129 uiZ96 = packToF128UI96( signProd, 0x7FFF, 0 ); 130 goto uiZ; 131 } 132 /*------------------------------------------------------------------------ 133 *------------------------------------------------------------------------*/ 134 if ( expA ) { 135 sigA[indexWordHi( 4 )] = fracF128UI96( uiA96 ) | 0x00010000; 136 sigA[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; 137 sigA[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; 138 sigA[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; 139 } else { 140 expA = softfloat_shiftNormSigF128M( aWPtr, 0, sigA ); 141 if ( expA == -128 ) goto zeroProd; 142 } 143 if ( expB ) { 144 sigX[indexWordHi( 4 )] = fracF128UI96( uiB96 ) | 0x00010000; 145 sigX[indexWord( 4, 2 )] = bWPtr[indexWord( 4, 2 )]; 146 sigX[indexWord( 4, 1 )] = bWPtr[indexWord( 4, 1 )]; 147 sigX[indexWord( 4, 0 )] = bWPtr[indexWord( 4, 0 )]; 148 } else { 149 expB = softfloat_shiftNormSigF128M( bWPtr, 0, sigX ); 150 if ( expB == -128 ) goto zeroProd; 151 } 152 /*------------------------------------------------------------------------ 153 *------------------------------------------------------------------------*/ 154 expProd = expA + expB - 0x3FF0; 155 softfloat_mul128MTo256M( sigA, sigX, sigProd ); 156 /*------------------------------------------------------------------------ 157 *------------------------------------------------------------------------*/ 158 wordSig = fracF128UI96( uiC96 ); 159 if ( expC ) { 160 --expC; 161 wordSig |= 0x00010000; 162 } 163 sigX[indexWordHi( 5 )] = wordSig; 164 sigX[indexWord( 5, 3 )] = cWPtr[indexWord( 4, 2 )]; 165 sigX[indexWord( 5, 2 )] = cWPtr[indexWord( 4, 1 )]; 166 sigX[indexWord( 5, 1 )] = cWPtr[indexWord( 4, 0 )]; 167 /*------------------------------------------------------------------------ 168 *------------------------------------------------------------------------*/ 169 doSub = (signProd != signC); 170 addCarryMRoutinePtr = 171 doSub ? softfloat_addComplCarryM : softfloat_addCarryM; 172 expDiff = expProd - expC; 173 if ( expDiff <= 0 ) { 174 /*-------------------------------------------------------------------- 175 *--------------------------------------------------------------------*/ 176 signZ = signC; 177 expZ = expC; 178 if ( 179 sigProd[indexWord( 8, 2 )] 180 || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )]) 181 ) { 182 sigProd[indexWord( 8, 3 )] |= 1; 183 } 184 extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )]; 185 if ( expDiff ) { 186 softfloat_shiftRightJam160M( extSigPtr, -expDiff, extSigPtr ); 187 } 188 carry = 0; 189 if ( doSub ) { 190 wordSig = extSigPtr[indexWordLo( 5 )]; 191 extSigPtr[indexWordLo( 5 )] = -wordSig; 192 carry = ! wordSig; 193 } 194 (*addCarryMRoutinePtr)( 195 4, 196 &sigX[indexMultiwordHi( 5, 4 )], 197 extSigPtr + indexMultiwordHi( 5, 4 ), 198 carry, 199 extSigPtr + indexMultiwordHi( 5, 4 ) 200 ); 201 wordSig = extSigPtr[indexWordHi( 5 )]; 202 if ( ! expZ ) { 203 if ( wordSig & 0x80000000 ) { 204 signZ = ! signZ; 205 softfloat_negX160M( extSigPtr ); 206 wordSig = extSigPtr[indexWordHi( 5 )]; 207 } 208 goto checkCancellation; 209 } 210 if ( wordSig < 0x00010000 ) { 211 --expZ; 212 softfloat_add160M( extSigPtr, extSigPtr, extSigPtr ); 213 goto roundPack; 214 } 215 goto extSigReady_noCancellation; 216 } else { 217 /*-------------------------------------------------------------------- 218 *--------------------------------------------------------------------*/ 219 signZ = signProd; 220 expZ = expProd; 221 sigX[indexWordLo( 5 )] = 0; 222 expDiff -= 128; 223 if ( 0 <= expDiff ) { 224 /*---------------------------------------------------------------- 225 *----------------------------------------------------------------*/ 226 if ( expDiff ) softfloat_shiftRightJam160M( sigX, expDiff, sigX ); 227 wordSig = sigX[indexWordLo( 5 )]; 228 carry = 0; 229 if ( doSub ) { 230 carry = ! wordSig; 231 wordSig = -wordSig; 232 } 233 carry = 234 (*addCarryMRoutinePtr)( 235 4, 236 &sigProd[indexMultiwordLo( 8, 4 )], 237 &sigX[indexMultiwordHi( 5, 4 )], 238 carry, 239 &sigProd[indexMultiwordLo( 8, 4 )] 240 ); 241 sigProd[indexWord( 8, 2 )] |= wordSig; 242 ptr = &sigProd[indexWord( 8, 4 )]; 243 } else { 244 /*---------------------------------------------------------------- 245 *----------------------------------------------------------------*/ 246 shiftCount = expDiff & 31; 247 if ( shiftCount ) { 248 softfloat_shortShiftRight160M( sigX, shiftCount, sigX ); 249 } 250 expDiff >>= 5; 251 extSigPtr = 252 &sigProd[indexMultiwordLo( 8, 5 )] - wordIncr 253 + expDiff * -wordIncr; 254 carry = 255 (*addCarryMRoutinePtr)( 5, extSigPtr, sigX, doSub, extSigPtr ); 256 if ( expDiff == -4 ) { 257 /*------------------------------------------------------------ 258 *------------------------------------------------------------*/ 259 wordSig = sigProd[indexWordHi( 8 )]; 260 if ( wordSig & 0x80000000 ) { 261 signZ = ! signZ; 262 softfloat_negX256M( sigProd ); 263 wordSig = sigProd[indexWordHi( 8 )]; 264 } 265 /*------------------------------------------------------------ 266 *------------------------------------------------------------*/ 267 if ( wordSig ) goto expProdBigger_noWordShift; 268 wordSig = sigProd[indexWord( 8, 6 )]; 269 if ( 0x00040000 <= wordSig ) goto expProdBigger_noWordShift; 270 expZ -= 32; 271 extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )] - wordIncr; 272 for (;;) { 273 if ( wordSig ) break; 274 wordSig = extSigPtr[indexWord( 5, 3 )]; 275 if ( 0x00040000 <= wordSig ) break; 276 expZ -= 32; 277 extSigPtr -= wordIncr; 278 if ( extSigPtr == &sigProd[indexMultiwordLo( 8, 5 )] ) { 279 goto checkCancellation; 280 } 281 } 282 /*------------------------------------------------------------ 283 *------------------------------------------------------------*/ 284 ptr = extSigPtr + indexWordLo( 5 ); 285 do { 286 ptr -= wordIncr; 287 if ( *ptr ) { 288 extSigPtr[indexWordLo( 5 )] |= 1; 289 break; 290 } 291 } while ( ptr != &sigProd[indexWordLo( 8 )] ); 292 wordSig = extSigPtr[indexWordHi( 5 )]; 293 goto extSigReady; 294 } 295 ptr = extSigPtr + indexWordHi( 5 ) + wordIncr; 296 } 297 /*-------------------------------------------------------------------- 298 *--------------------------------------------------------------------*/ 299 if ( carry != doSub ) { 300 if ( doSub ) { 301 do { 302 wordSig = *ptr; 303 *ptr = wordSig - 1; 304 ptr += wordIncr; 305 } while ( ! wordSig ); 306 } else { 307 do { 308 wordSig = *ptr + 1; 309 *ptr = wordSig; 310 ptr += wordIncr; 311 } while ( ! wordSig ); 312 } 313 } 314 /*-------------------------------------------------------------------- 315 *--------------------------------------------------------------------*/ 316 expProdBigger_noWordShift: 317 if ( 318 sigProd[indexWord( 8, 2 )] 319 || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )]) 320 ) { 321 sigProd[indexWord( 8, 3 )] |= 1; 322 } 323 extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )]; 324 wordSig = extSigPtr[indexWordHi( 5 )]; 325 } 326 extSigReady: 327 roundPackRoutinePtr = softfloat_normRoundPackMToF128M; 328 if ( wordSig < 0x00010000 ) goto doRoundPack; 329 extSigReady_noCancellation: 330 if ( 0x00020000 <= wordSig ) { 331 ++expZ; 332 softfloat_shortShiftRightJam160M( extSigPtr, 1, extSigPtr ); 333 } 334 roundPack: 335 roundPackRoutinePtr = softfloat_roundPackMToF128M; 336 doRoundPack: 337 (*roundPackRoutinePtr)( signZ, expZ, extSigPtr, zWPtr ); 338 return; 339 /*------------------------------------------------------------------------ 340 *------------------------------------------------------------------------*/ 341 invalid: 342 softfloat_invalidF128M( zWPtr ); 343 propagateNaN_ZC: 344 softfloat_propagateNaNF128M( zWPtr, cWPtr, zWPtr ); 345 return; 346 /*------------------------------------------------------------------------ 347 *------------------------------------------------------------------------*/ 348 zeroProd: 349 if ( 350 ! (uint32_t) (uiC96<<1) && (signProd != signC) 351 && ! cWPtr[indexWord( 4, 2 )] 352 && ! (cWPtr[indexWord( 4, 1 )] | cWPtr[indexWord( 4, 0 )]) 353 ) { 354 goto completeCancellation; 355 } 356 copyC: 357 zWPtr[indexWordHi( 4 )] = uiC96; 358 zWPtr[indexWord( 4, 2 )] = cWPtr[indexWord( 4, 2 )]; 359 zWPtr[indexWord( 4, 1 )] = cWPtr[indexWord( 4, 1 )]; 360 zWPtr[indexWord( 4, 0 )] = cWPtr[indexWord( 4, 0 )]; 361 return; 362 /*------------------------------------------------------------------------ 363 *------------------------------------------------------------------------*/ 364 checkCancellation: 365 if ( 366 wordSig 367 || (extSigPtr[indexWord( 5, 3 )] | extSigPtr[indexWord( 5, 2 )]) 368 || (extSigPtr[indexWord( 5, 1 )] | extSigPtr[indexWord( 5, 0 )]) 369 ) { 370 goto extSigReady; 371 } 372 completeCancellation: 373 uiZ96 = 374 packToF128UI96( 375 (softfloat_roundingMode == softfloat_round_min), 0, 0 ); 376 uiZ: 377 zWPtr[indexWordHi( 4 )] = uiZ96; 378 zWPtr[indexWord( 4, 2 )] = 0; 379 zWPtr[indexWord( 4, 1 )] = 0; 380 zWPtr[indexWord( 4, 0 )] = 0; 381 382 } 383 384