1*9d5a6349SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 21da177e4SLinus Torvalds /* IEEE754 floating point arithmetic 31da177e4SLinus Torvalds * single precision 41da177e4SLinus Torvalds */ 51da177e4SLinus Torvalds /* 61da177e4SLinus Torvalds * MIPS floating point support 71da177e4SLinus Torvalds * Copyright (C) 1994-2000 Algorithmics Ltd. 81da177e4SLinus Torvalds */ 91da177e4SLinus Torvalds 101da177e4SLinus Torvalds #include "ieee754sp.h" 111da177e4SLinus Torvalds ieee754sp_tlong(union ieee754sp x)122209bcb1SRalf Baechles64 ieee754sp_tlong(union ieee754sp x) 131da177e4SLinus Torvalds { 143f7cac41SRalf Baechle u32 residue; 153f7cac41SRalf Baechle int round; 163f7cac41SRalf Baechle int sticky; 173f7cac41SRalf Baechle int odd; 183f7cac41SRalf Baechle 191da177e4SLinus Torvalds COMPXDP; /* <-- need 64-bit mantissa tmp */ 201da177e4SLinus Torvalds 219e8bad1fSRalf Baechle ieee754_clearcx(); 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds EXPLODEXSP; 241da177e4SLinus Torvalds FLUSHXSP; 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds switch (xc) { 271da177e4SLinus Torvalds case IEEE754_CLASS_SNAN: 281da177e4SLinus Torvalds case IEEE754_CLASS_QNAN: 299e8bad1fSRalf Baechle ieee754_setcx(IEEE754_INVALID_OPERATION); 3090efba36SRalf Baechle return ieee754di_indef(); 313f7cac41SRalf Baechle 3290d53a91SMaciej W. Rozycki case IEEE754_CLASS_INF: 3390d53a91SMaciej W. Rozycki ieee754_setcx(IEEE754_INVALID_OPERATION); 3490d53a91SMaciej W. Rozycki return ieee754di_overflow(xs); 3590d53a91SMaciej W. Rozycki 361da177e4SLinus Torvalds case IEEE754_CLASS_ZERO: 371da177e4SLinus Torvalds return 0; 383f7cac41SRalf Baechle 391da177e4SLinus Torvalds case IEEE754_CLASS_DNORM: 401da177e4SLinus Torvalds case IEEE754_CLASS_NORM: 411da177e4SLinus Torvalds break; 421da177e4SLinus Torvalds } 431da177e4SLinus Torvalds if (xe >= 63) { 441da177e4SLinus Torvalds /* look for valid corner case */ 451da177e4SLinus Torvalds if (xe == 63 && xs && xm == SP_HIDDEN_BIT) 461da177e4SLinus Torvalds return -0x8000000000000000LL; 471da177e4SLinus Torvalds /* Set invalid. We will only use overflow for floating 481da177e4SLinus Torvalds point overflow */ 499e8bad1fSRalf Baechle ieee754_setcx(IEEE754_INVALID_OPERATION); 5090d53a91SMaciej W. Rozycki return ieee754di_overflow(xs); 511da177e4SLinus Torvalds } 521da177e4SLinus Torvalds /* oh gawd */ 53ad8fb553SRalf Baechle if (xe > SP_FBITS) { 54ad8fb553SRalf Baechle xm <<= xe - SP_FBITS; 55ad8fb553SRalf Baechle } else if (xe < SP_FBITS) { 561da177e4SLinus Torvalds if (xe < -1) { 571da177e4SLinus Torvalds residue = xm; 581da177e4SLinus Torvalds round = 0; 591da177e4SLinus Torvalds sticky = residue != 0; 601da177e4SLinus Torvalds xm = 0; 61abb86dc5SAndrea Gelmini } else { 62ad8fb553SRalf Baechle residue = xm << (32 - SP_FBITS + xe); 631da177e4SLinus Torvalds round = (residue >> 31) != 0; 641da177e4SLinus Torvalds sticky = (residue << 1) != 0; 65ad8fb553SRalf Baechle xm >>= SP_FBITS - xe; 661da177e4SLinus Torvalds } 671da177e4SLinus Torvalds odd = (xm & 0x1) != 0x0; 681da177e4SLinus Torvalds switch (ieee754_csr.rm) { 6956a64733SRalf Baechle case FPU_CSR_RN: 701da177e4SLinus Torvalds if (round && (sticky || odd)) 711da177e4SLinus Torvalds xm++; 721da177e4SLinus Torvalds break; 7356a64733SRalf Baechle case FPU_CSR_RZ: 741da177e4SLinus Torvalds break; 7556a64733SRalf Baechle case FPU_CSR_RU: /* toward +Infinity */ 761da177e4SLinus Torvalds if ((round || sticky) && !xs) 771da177e4SLinus Torvalds xm++; 781da177e4SLinus Torvalds break; 7956a64733SRalf Baechle case FPU_CSR_RD: /* toward -Infinity */ 801da177e4SLinus Torvalds if ((round || sticky) && xs) 811da177e4SLinus Torvalds xm++; 821da177e4SLinus Torvalds break; 831da177e4SLinus Torvalds } 841da177e4SLinus Torvalds if ((xm >> 63) != 0) { 851da177e4SLinus Torvalds /* This can happen after rounding */ 869e8bad1fSRalf Baechle ieee754_setcx(IEEE754_INVALID_OPERATION); 8790d53a91SMaciej W. Rozycki return ieee754di_overflow(xs); 881da177e4SLinus Torvalds } 891da177e4SLinus Torvalds if (round || sticky) 909e8bad1fSRalf Baechle ieee754_setcx(IEEE754_INEXACT); 911da177e4SLinus Torvalds } 921da177e4SLinus Torvalds if (xs) 931da177e4SLinus Torvalds return -xm; 941da177e4SLinus Torvalds else 951da177e4SLinus Torvalds return xm; 961da177e4SLinus Torvalds } 97