155113Storek /* 255113Storek * Copyright (c) 1992 The Regents of the University of California. 355113Storek * All rights reserved. 455113Storek * 555113Storek * This software was developed by the Computer Systems Engineering group 655113Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 755113Storek * contributed to Berkeley. 855113Storek * 955500Sbostic * All advertising materials mentioning features or use of this software 1055500Sbostic * must display the following acknowledgement: 1155500Sbostic * This product includes software developed by the University of 1255500Sbostic * California, Lawrence Berkeley Laboratories. 1355500Sbostic * 1455113Storek * %sccs.include.redist.c% 1555113Storek * 16*56537Sbostic * @(#)fpu_explode.c 7.3 (Berkeley) 10/11/92 1755113Storek * 1855113Storek * from: $Header: fpu_explode.c,v 1.2 92/06/17 05:41:32 torek Exp $ 1955113Storek */ 2055113Storek 2155113Storek /* 2255113Storek * FPU subroutines: `explode' the machine's `packed binary' format numbers 2355113Storek * into our internal format. 2455113Storek */ 2555113Storek 26*56537Sbostic #include <sys/types.h> 2755113Storek 28*56537Sbostic #include <machine/ieee.h> 29*56537Sbostic #include <machine/instr.h> 30*56537Sbostic #include <machine/reg.h> 3155113Storek 32*56537Sbostic #include <sparc/fpu/fpu_arith.h> 33*56537Sbostic #include <sparc/fpu/fpu_emu.h> 3455113Storek 3555113Storek /* 3655113Storek * N.B.: in all of the following, we assume the FP format is 3755113Storek * 3855113Storek * --------------------------- 3955113Storek * | s | exponent | fraction | 4055113Storek * --------------------------- 4155113Storek * 4255113Storek * (which represents -1**s * 1.fraction * 2**exponent), so that the 4355113Storek * sign bit is way at the top (bit 31), the exponent is next, and 4455113Storek * then the remaining bits mark the fraction. A zero exponent means 4555113Storek * zero or denormalized (0.fraction rather than 1.fraction), and the 4655113Storek * maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN. 4755113Storek * 4855113Storek * Since the sign bit is always the topmost bit---this holds even for 4955113Storek * integers---we set that outside all the *tof functions. Each function 5055113Storek * returns the class code for the new number (but note that we use 5155113Storek * FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate). 5255113Storek */ 5355113Storek 5455113Storek /* 5555113Storek * int -> fpn. 5655113Storek */ 5755113Storek int 5855113Storek fpu_itof(fp, i) 5955113Storek register struct fpn *fp; 6055113Storek register u_int i; 6155113Storek { 6255113Storek 6355113Storek if (i == 0) 6455113Storek return (FPC_ZERO); 6555113Storek /* 6655113Storek * The value FP_1 represents 2^FP_LG, so set the exponent 6755113Storek * there and let normalization fix it up. Convert negative 6855113Storek * numbers to sign-and-magnitude. Note that this relies on 6955113Storek * fpu_norm()'s handling of `supernormals'; see fpu_subr.c. 7055113Storek */ 7155113Storek fp->fp_exp = FP_LG; 7255113Storek fp->fp_mant[0] = (int)i < 0 ? -i : i; 7355113Storek fp->fp_mant[1] = 0; 7455113Storek fp->fp_mant[2] = 0; 7555113Storek fp->fp_mant[3] = 0; 7655113Storek fpu_norm(fp); 7755113Storek return (FPC_NUM); 7855113Storek } 7955113Storek 8055113Storek #define mask(nbits) ((1 << (nbits)) - 1) 8155113Storek 8255113Storek /* 8355113Storek * All external floating formats convert to internal in the same manner, 8455113Storek * as defined here. Note that only normals get an implied 1.0 inserted. 8555113Storek */ 8655113Storek #define FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \ 8755113Storek if (exp == 0) { \ 8855113Storek if (allfrac == 0) \ 8955113Storek return (FPC_ZERO); \ 9055113Storek fp->fp_exp = 1 - expbias; \ 9155113Storek fp->fp_mant[0] = f0; \ 9255113Storek fp->fp_mant[1] = f1; \ 9355113Storek fp->fp_mant[2] = f2; \ 9455113Storek fp->fp_mant[3] = f3; \ 9555113Storek fpu_norm(fp); \ 9655113Storek return (FPC_NUM); \ 9755113Storek } \ 9855113Storek if (exp == (2 * expbias + 1)) { \ 9955113Storek if (allfrac == 0) \ 10055113Storek return (FPC_INF); \ 10155113Storek fp->fp_mant[0] = f0; \ 10255113Storek fp->fp_mant[1] = f1; \ 10355113Storek fp->fp_mant[2] = f2; \ 10455113Storek fp->fp_mant[3] = f3; \ 10555113Storek return (FPC_QNAN); \ 10655113Storek } \ 10755113Storek fp->fp_exp = exp - expbias; \ 10855113Storek fp->fp_mant[0] = FP_1 | f0; \ 10955113Storek fp->fp_mant[1] = f1; \ 11055113Storek fp->fp_mant[2] = f2; \ 11155113Storek fp->fp_mant[3] = f3; \ 11255113Storek return (FPC_NUM) 11355113Storek 11455113Storek /* 11555113Storek * 32-bit single precision -> fpn. 11655113Storek * We assume a single occupies at most (64-FP_LG) bits in the internal 11755113Storek * format: i.e., needs at most fp_mant[0] and fp_mant[1]. 11855113Storek */ 11955113Storek int 12055113Storek fpu_stof(fp, i) 12155113Storek register struct fpn *fp; 12255113Storek register u_int i; 12355113Storek { 12455113Storek register int exp; 12555113Storek register u_int frac, f0, f1; 12655113Storek #define SNG_SHIFT (SNG_FRACBITS - FP_LG) 12755113Storek 12855113Storek exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS); 12955113Storek frac = i & mask(SNG_FRACBITS); 13055113Storek f0 = frac >> SNG_SHIFT; 13155113Storek f1 = frac << (32 - SNG_SHIFT); 13255113Storek FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0); 13355113Storek } 13455113Storek 13555113Storek /* 13655113Storek * 64-bit double -> fpn. 13755113Storek * We assume this uses at most (96-FP_LG) bits. 13855113Storek */ 13955113Storek int 14055113Storek fpu_dtof(fp, i, j) 14155113Storek register struct fpn *fp; 14255113Storek register u_int i, j; 14355113Storek { 14455113Storek register int exp; 14555113Storek register u_int frac, f0, f1, f2; 14655113Storek #define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG) 14755113Storek 14855113Storek exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS); 14955113Storek frac = i & mask(DBL_FRACBITS - 32); 15055113Storek f0 = frac >> DBL_SHIFT; 15155113Storek f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT); 15255113Storek f2 = j << (32 - DBL_SHIFT); 15355113Storek frac |= j; 15455113Storek FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0); 15555113Storek } 15655113Storek 15755113Storek /* 15855113Storek * 128-bit extended -> fpn. 15955113Storek */ 16055113Storek int 16155113Storek fpu_xtof(fp, i, j, k, l) 16255113Storek register struct fpn *fp; 16355113Storek register u_int i, j, k, l; 16455113Storek { 16555113Storek register int exp; 16655113Storek register u_int frac, f0, f1, f2, f3; 16755113Storek #define EXT_SHIFT (-(EXT_FRACBITS - 3 * 32 - FP_LG)) /* left shift! */ 16855113Storek 16955113Storek /* 17055113Storek * Note that ext and fpn `line up', hence no shifting needed. 17155113Storek */ 17255113Storek exp = (i >> (32 - 1 - EXT_EXPBITS)) & mask(EXT_EXPBITS); 17355113Storek frac = i & mask(EXT_FRACBITS - 3 * 32); 17455113Storek f0 = (frac << EXT_SHIFT) | (j >> (32 - EXT_SHIFT)); 17555113Storek f1 = (j << EXT_SHIFT) | (k >> (32 - EXT_SHIFT)); 17655113Storek f2 = (k << EXT_SHIFT) | (l >> (32 - EXT_SHIFT)); 17755113Storek f3 = l << EXT_SHIFT; 17855113Storek frac |= j | k | l; 17955113Storek FP_TOF(exp, EXT_EXP_BIAS, frac, f0, f1, f2, f3); 18055113Storek } 18155113Storek 18255113Storek /* 18355113Storek * Explode the contents of a register / regpair / regquad. 18455113Storek * If the input is a signalling NaN, an NV (invalid) exception 18555113Storek * will be set. (Note that nothing but NV can occur until ALU 18655113Storek * operations are performed.) 18755113Storek */ 18855113Storek void 18955113Storek fpu_explode(fe, fp, type, reg) 19055113Storek register struct fpemu *fe; 19155113Storek register struct fpn *fp; 19255113Storek int type, reg; 19355113Storek { 19455113Storek register u_int s, *space; 19555113Storek 19655113Storek space = &fe->fe_fpstate->fs_regs[reg]; 19755113Storek s = space[0]; 19855113Storek fp->fp_sign = s >> 31; 19955113Storek fp->fp_sticky = 0; 20055113Storek switch (type) { 20155113Storek 20255113Storek case FTYPE_INT: 20355113Storek s = fpu_itof(fp, s); 20455113Storek break; 20555113Storek 20655113Storek case FTYPE_SNG: 20755113Storek s = fpu_stof(fp, s); 20855113Storek break; 20955113Storek 21055113Storek case FTYPE_DBL: 21155113Storek s = fpu_dtof(fp, s, space[1]); 21255113Storek break; 21355113Storek 21455113Storek case FTYPE_EXT: 21555113Storek s = fpu_xtof(fp, s, space[1], space[2], space[3]); 21655113Storek break; 21755113Storek 21855113Storek default: 21955113Storek panic("fpu_explode"); 22055113Storek } 22155113Storek if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) { 22255113Storek /* 22355113Storek * Input is a signalling NaN. All operations that return 22455113Storek * an input NaN operand put it through a ``NaN conversion'', 22555113Storek * which basically just means ``turn on the quiet bit''. 22655113Storek * We do this here so that all NaNs internally look quiet 22755113Storek * (we can tell signalling ones by their class). 22855113Storek */ 22955113Storek fp->fp_mant[0] |= FP_QUIETBIT; 23055113Storek fe->fe_cx = FSR_NV; /* assert invalid operand */ 23155113Storek s = FPC_SNAN; 23255113Storek } 23355113Storek fp->fp_class = s; 23455113Storek } 235