fpu_explode.c revision 92986
11573Srgrimes/* 21573Srgrimes * Copyright (c) 1992, 1993 31573Srgrimes * The Regents of the University of California. All rights reserved. 41573Srgrimes * 51573Srgrimes * This software was developed by the Computer Systems Engineering group 61573Srgrimes * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 71573Srgrimes * contributed to Berkeley. 81573Srgrimes * 91573Srgrimes * All advertising materials mentioning features or use of this software 101573Srgrimes * must display the following acknowledgement: 111573Srgrimes * This product includes software developed by the University of 121573Srgrimes * California, Lawrence Berkeley Laboratory. 131573Srgrimes * 141573Srgrimes * Redistribution and use in source and binary forms, with or without 151573Srgrimes * modification, are permitted provided that the following conditions 161573Srgrimes * are met: 171573Srgrimes * 1. Redistributions of source code must retain the above copyright 181573Srgrimes * notice, this list of conditions and the following disclaimer. 191573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 201573Srgrimes * notice, this list of conditions and the following disclaimer in the 211573Srgrimes * documentation and/or other materials provided with the distribution. 221573Srgrimes * 3. All advertising materials mentioning features or use of this software 231573Srgrimes * must display the following acknowledgement: 241573Srgrimes * This product includes software developed by the University of 251573Srgrimes * California, Berkeley and its contributors. 261573Srgrimes * 4. Neither the name of the University nor the names of its contributors 271573Srgrimes * may be used to endorse or promote products derived from this software 281573Srgrimes * without specific prior written permission. 291573Srgrimes * 301573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 311573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 321573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 331573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 341573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 351573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 361573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 371573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 381573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 391573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 401573Srgrimes * SUCH DAMAGE. 411573Srgrimes * 421573Srgrimes * @(#)fpu_explode.c 8.1 (Berkeley) 6/11/93 431573Srgrimes * $NetBSD: fpu_explode.c,v 1.5 2000/08/03 18:32:08 eeh Exp $ 441573Srgrimes */ 451573Srgrimes 461573Srgrimes#include <sys/cdefs.h> 471573Srgrimes__FBSDID("$FreeBSD: head/lib/libc/sparc64/fpu/fpu_explode.c 92986 2002-03-22 21:53:29Z obrien $"); 481573Srgrimes 491573Srgrimes/* 501573Srgrimes * FPU subroutines: `explode' the machine's `packed binary' format numbers 511573Srgrimes * into our internal format. 521573Srgrimes */ 531573Srgrimes 541573Srgrimes#include <sys/param.h> 551573Srgrimes 561573Srgrimes#include <machine/frame.h> 571573Srgrimes#include <machine/fp.h> 581573Srgrimes#include <machine/fsr.h> 591573Srgrimes#include <machine/ieee.h> 601573Srgrimes#include <machine/instr.h> 611573Srgrimes 6213545Sjulian#include "fpu_arith.h" 6313545Sjulian#include "fpu_emu.h" 6413545Sjulian#include "fpu_extern.h" 6513545Sjulian 661573Srgrimes/* 671573Srgrimes * N.B.: in all of the following, we assume the FP format is 681573Srgrimes * 691573Srgrimes * --------------------------- 701573Srgrimes * | s | exponent | fraction | 711573Srgrimes * --------------------------- 721573Srgrimes * 731573Srgrimes * (which represents -1**s * 1.fraction * 2**exponent), so that the 741573Srgrimes * sign bit is way at the top (bit 31), the exponent is next, and 751573Srgrimes * then the remaining bits mark the fraction. A zero exponent means 761573Srgrimes * zero or denormalized (0.fraction rather than 1.fraction), and the 771573Srgrimes * maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN. 781573Srgrimes * 791573Srgrimes * Since the sign bit is always the topmost bit---this holds even for 801573Srgrimes * integers---we set that outside all the *tof functions. Each function 811573Srgrimes * returns the class code for the new number (but note that we use 821573Srgrimes * FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate). 831573Srgrimes */ 841573Srgrimes 851573Srgrimes/* 861573Srgrimes * int -> fpn. 871573Srgrimes */ 881573Srgrimesint 891573Srgrimes__fpu_itof(fp, i) 901573Srgrimes struct fpn *fp; 911573Srgrimes u_int i; 921573Srgrimes{ 931573Srgrimes 941573Srgrimes if (i == 0) 951573Srgrimes return (FPC_ZERO); 961573Srgrimes /* 971573Srgrimes * The value FP_1 represents 2^FP_LG, so set the exponent 981573Srgrimes * there and let normalization fix it up. Convert negative 991573Srgrimes * numbers to sign-and-magnitude. Note that this relies on 1001573Srgrimes * fpu_norm()'s handling of `supernormals'; see fpu_subr.c. 1011573Srgrimes */ 1021573Srgrimes fp->fp_exp = FP_LG; 1031573Srgrimes fp->fp_mant[0] = (int)i < 0 ? -i : i; 1041573Srgrimes fp->fp_mant[1] = 0; 1051573Srgrimes fp->fp_mant[2] = 0; 1061573Srgrimes fp->fp_mant[3] = 0; 1071573Srgrimes __fpu_norm(fp); 1081573Srgrimes return (FPC_NUM); 1091573Srgrimes} 1101573Srgrimes 1111573Srgrimes/* 1121573Srgrimes * 64-bit int -> fpn. 1131573Srgrimes */ 1141573Srgrimesint 1151573Srgrimes__fpu_xtof(fp, i) 1161573Srgrimes struct fpn *fp; 1171573Srgrimes u_int64_t i; 1181573Srgrimes{ 1191573Srgrimes 1201573Srgrimes if (i == 0) 1211573Srgrimes return (FPC_ZERO); 1221573Srgrimes /* 1231573Srgrimes * The value FP_1 represents 2^FP_LG, so set the exponent 1241573Srgrimes * there and let normalization fix it up. Convert negative 1251573Srgrimes * numbers to sign-and-magnitude. Note that this relies on 1261573Srgrimes * fpu_norm()'s handling of `supernormals'; see fpu_subr.c. 1271573Srgrimes */ 1281573Srgrimes fp->fp_exp = FP_LG2; 1291573Srgrimes *((int64_t*)fp->fp_mant) = (int64_t)i < 0 ? -i : i; 1301573Srgrimes fp->fp_mant[2] = 0; 1311573Srgrimes fp->fp_mant[3] = 0; 1321573Srgrimes __fpu_norm(fp); 1331573Srgrimes return (FPC_NUM); 1341573Srgrimes} 1351573Srgrimes 1361573Srgrimes#define mask(nbits) ((1L << (nbits)) - 1) 1371573Srgrimes 1381573Srgrimes/* 1391573Srgrimes * All external floating formats convert to internal in the same manner, 1401573Srgrimes * as defined here. Note that only normals get an implied 1.0 inserted. 1411573Srgrimes */ 1421573Srgrimes#define FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \ 1431573Srgrimes if (exp == 0) { \ 1441573Srgrimes if (allfrac == 0) \ 1451573Srgrimes return (FPC_ZERO); \ 1461573Srgrimes fp->fp_exp = 1 - expbias; \ 1471573Srgrimes fp->fp_mant[0] = f0; \ 1481573Srgrimes fp->fp_mant[1] = f1; \ 1491573Srgrimes fp->fp_mant[2] = f2; \ 1501573Srgrimes fp->fp_mant[3] = f3; \ 1511573Srgrimes __fpu_norm(fp); \ 1521573Srgrimes return (FPC_NUM); \ 1531573Srgrimes } \ 1541573Srgrimes if (exp == (2 * expbias + 1)) { \ 1551573Srgrimes if (allfrac == 0) \ 1561573Srgrimes return (FPC_INF); \ 1571573Srgrimes fp->fp_mant[0] = f0; \ 1581573Srgrimes fp->fp_mant[1] = f1; \ 1591573Srgrimes fp->fp_mant[2] = f2; \ 1601573Srgrimes fp->fp_mant[3] = f3; \ 1611573Srgrimes return (FPC_QNAN); \ 1621573Srgrimes } \ 1631573Srgrimes fp->fp_exp = exp - expbias; \ 1641573Srgrimes fp->fp_mant[0] = FP_1 | f0; \ 1651573Srgrimes fp->fp_mant[1] = f1; \ 1661573Srgrimes fp->fp_mant[2] = f2; \ 1671573Srgrimes fp->fp_mant[3] = f3; \ 1681573Srgrimes return (FPC_NUM) 1691573Srgrimes 1701573Srgrimes/* 1711573Srgrimes * 32-bit single precision -> fpn. 1721573Srgrimes * We assume a single occupies at most (64-FP_LG) bits in the internal 1731573Srgrimes * format: i.e., needs at most fp_mant[0] and fp_mant[1]. 1741573Srgrimes */ 1751573Srgrimesint 1761573Srgrimes__fpu_stof(fp, i) 1771573Srgrimes struct fpn *fp; 1781573Srgrimes u_int i; 1791573Srgrimes{ 1801573Srgrimes int exp; 1811573Srgrimes u_int frac, f0, f1; 1821573Srgrimes#define SNG_SHIFT (SNG_FRACBITS - FP_LG) 1831573Srgrimes 1841573Srgrimes exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS); 1851573Srgrimes frac = i & mask(SNG_FRACBITS); 1861573Srgrimes f0 = frac >> SNG_SHIFT; 1871573Srgrimes f1 = frac << (32 - SNG_SHIFT); 1881573Srgrimes FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0); 1891573Srgrimes} 1901573Srgrimes 1911573Srgrimes/* 1921573Srgrimes * 64-bit double -> fpn. 1931573Srgrimes * We assume this uses at most (96-FP_LG) bits. 1941573Srgrimes */ 1951573Srgrimesint 1961573Srgrimes__fpu_dtof(fp, i, j) 1971573Srgrimes struct fpn *fp; 1981573Srgrimes u_int i, j; 1991573Srgrimes{ 2001573Srgrimes int exp; 2011573Srgrimes u_int frac, f0, f1, f2; 2021573Srgrimes#define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG) 2031573Srgrimes 2041573Srgrimes exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS); 2051573Srgrimes frac = i & mask(DBL_FRACBITS - 32); 2061573Srgrimes f0 = frac >> DBL_SHIFT; 2071573Srgrimes f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT); 2081573Srgrimes f2 = j << (32 - DBL_SHIFT); 2091573Srgrimes frac |= j; 2101573Srgrimes FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0); 2111573Srgrimes} 2121573Srgrimes 2131573Srgrimes/* 2141573Srgrimes * 128-bit extended -> fpn. 2151573Srgrimes */ 2161573Srgrimesint 2171573Srgrimes__fpu_qtof(fp, i, j, k, l) 2181573Srgrimes struct fpn *fp; 2191573Srgrimes u_int i, j, k, l; 2201573Srgrimes{ 2211573Srgrimes int exp; 2221573Srgrimes u_int frac, f0, f1, f2, f3; 2231573Srgrimes#define EXT_SHIFT (-(EXT_FRACBITS - 3 * 32 - FP_LG)) /* left shift! */ 2241573Srgrimes 2251573Srgrimes /* 2261573Srgrimes * Note that ext and fpn `line up', hence no shifting needed. 2271573Srgrimes */ 2281573Srgrimes exp = (i >> (32 - 1 - EXT_EXPBITS)) & mask(EXT_EXPBITS); 2291573Srgrimes frac = i & mask(EXT_FRACBITS - 3 * 32); 2301573Srgrimes f0 = (frac << EXT_SHIFT) | (j >> (32 - EXT_SHIFT)); 2311573Srgrimes f1 = (j << EXT_SHIFT) | (k >> (32 - EXT_SHIFT)); 2321573Srgrimes f2 = (k << EXT_SHIFT) | (l >> (32 - EXT_SHIFT)); 2331573Srgrimes f3 = l << EXT_SHIFT; 2341573Srgrimes frac |= j | k | l; 2351573Srgrimes FP_TOF(exp, EXT_EXP_BIAS, frac, f0, f1, f2, f3); 2361573Srgrimes} 2371573Srgrimes 2381573Srgrimes/* 2391573Srgrimes * Explode the contents of a / regpair / regquad. 2401573Srgrimes * If the input is a signalling NaN, an NV (invalid) exception 2411573Srgrimes * will be set. (Note that nothing but NV can occur until ALU 2421573Srgrimes * operations are performed.) 2431573Srgrimes */ 2441573Srgrimesvoid 2451573Srgrimes__fpu_explode(fe, fp, type, reg) 2461573Srgrimes struct fpemu *fe; 2471573Srgrimes struct fpn *fp; 2481573Srgrimes int type, reg; 2491573Srgrimes{ 2501573Srgrimes u_int s; 2511573Srgrimes u_int64_t l; 2521573Srgrimes 2531573Srgrimes l = __fpu_getreg64(reg & ~1); 2541573Srgrimes s = __fpu_getreg(reg); 2551573Srgrimes fp->fp_sign = s >> 31; 2561573Srgrimes fp->fp_sticky = 0; 2571573Srgrimes switch (type) { 2581573Srgrimes case FTYPE_LNG: 2591573Srgrimes s = __fpu_xtof(fp, l); 2601573Srgrimes break; 2611573Srgrimes 2621573Srgrimes case FTYPE_INT: 2631573Srgrimes s = __fpu_itof(fp, s); 2641573Srgrimes break; 2651573Srgrimes 2661573Srgrimes case FTYPE_SNG: 2671573Srgrimes s = __fpu_stof(fp, s); 2681573Srgrimes break; 2691573Srgrimes 2701573Srgrimes case FTYPE_DBL: 2711573Srgrimes s = __fpu_dtof(fp, s, __fpu_getreg(reg + 1)); 2721573Srgrimes break; 2731573Srgrimes 2741573Srgrimes case FTYPE_EXT: 2751573Srgrimes s = __fpu_qtof(fp, s, __fpu_getreg(reg + 1), 2761573Srgrimes __fpu_getreg(reg + 2), 2771573Srgrimes __fpu_getreg(reg + 3)); 2781573Srgrimes break; 2791573Srgrimes 2801573Srgrimes default: 2811573Srgrimes __fpu_panic("fpu_explode"); 2821573Srgrimes } 2831573Srgrimes 2841573Srgrimes if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) { 2851573Srgrimes /* 2861573Srgrimes * Input is a signalling NaN. All operations that return 2871573Srgrimes * an input NaN operand put it through a ``NaN conversion'', 2881573Srgrimes * which basically just means ``turn on the quiet bit''. 2891573Srgrimes * We do this here so that all NaNs internally look quiet 2901573Srgrimes * (we can tell signalling ones by their class). 2911573Srgrimes */ 2921573Srgrimes fp->fp_mant[0] |= FP_QUIETBIT; 2931573Srgrimes fe->fe_cx = FSR_NV; /* assert invalid operand */ 2941573Srgrimes s = FPC_SNAN; 2951573Srgrimes } 2961573Srgrimes fp->fp_class = s; 2971573Srgrimes DPRINTF(FPE_REG, ("fpu_explode: %%%c%d => ", (type == FTYPE_LNG) ? 'x' : 2981573Srgrimes ((type == FTYPE_INT) ? 'i' : 2991573Srgrimes ((type == FTYPE_SNG) ? 's' : 3001573Srgrimes ((type == FTYPE_DBL) ? 'd' : 3011573Srgrimes ((type == FTYPE_EXT) ? 'q' : '?')))), 3021573Srgrimes reg)); 3031573Srgrimes DUMPFPN(FPE_REG, fp); 3041573Srgrimes DPRINTF(FPE_REG, ("\n")); 3051573Srgrimes} 3061573Srgrimes