11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* IEEE754 floating point arithmetic 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * single precision 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MIPS floating point support 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1994-2000 Algorithmics Ltd. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ######################################################################## 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can distribute it and/or modify it 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * under the terms of the GNU General Public License (Version 2) as 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope it will be useful, but WITHOUT 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for more details. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License along 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with this program; if not, write to the Free Software Foundation, Inc., 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ######################################################################## 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "ieee754sp.h" 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y) 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds COMPXSP; 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds COMPYSP; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EXPLODEXSP; 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EXPLODEYSP; 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CLEARCX; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FLUSHXSP; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FLUSHYSP; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (CLPAIR(xc, yc)) { 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SETCX(IEEE754_INVALID_OPERATION); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ieee754sp_nanxcpt(ieee754sp_indef(), "mul", x, y); 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return y; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return x; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Infinity handling */ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SETCX(IEEE754_INVALID_OPERATION); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ieee754sp_inf(xs ^ ys); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ieee754sp_zero(xs ^ ys); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SPDNORMX; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SPDNORMY; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SPDNORMX; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* rm = xm * ym, re = xe+ye basically */ 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds assert(xm & SP_HIDDEN_BIT); 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds assert(ym & SP_HIDDEN_BIT); 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int re = xe + ye; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rs = xs ^ ys; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned rm; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* shunt to top of word */ 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds xm <<= 32 - (SP_MBITS + 1); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ym <<= 32 - (SP_MBITS + 1); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* multiply 32bits xm,ym to give high 32bits rm with stickness 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short lxm = xm & 0xffff; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short hxm = xm >> 16; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short lym = ym & 0xffff; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short hym = ym >> 16; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned lrm; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned hrm; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lrm = lxm * lym; /* 16 * 16 => 32 */ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hrm = hxm * hym; /* 16 * 16 => 32 */ 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned t = lxm * hym; /* 16 * 16 => 32 */ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned at = lrm + (t << 16); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hrm += at < lrm; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lrm = at; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hrm = hrm + (t >> 16); 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned t = hxm * lym; /* 16 * 16 => 32 */ 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned at = lrm + (t << 16); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hrm += at < lrm; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lrm = at; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hrm = hrm + (t >> 16); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rm = hrm | (lrm != 0); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sticky shift down to normal rounding precision 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((int) rm < 0) { 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rm = (rm >> (32 - (SP_MBITS + 1 + 3))) | 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((rm << (SP_MBITS + 1 + 3)) != 0); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds re++; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) | 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((rm << (SP_MBITS + 1 + 3 + 1)) != 0); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds assert(rm & (SP_HIDDEN_BIT << 3)); 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SPNORMRET2(rs, re, rm, "mul", x, y); 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 171