fpu_explode.c revision 302408
1111314Snyan/* $NetBSD: fpu_explode.c,v 1.6 2005/12/11 12:18:42 christos Exp $ */ 2111314Snyan 3111314Snyan/* 4111314Snyan * Copyright (c) 1992, 1993 5111314Snyan * The Regents of the University of California. All rights reserved. 6111314Snyan * 7111314Snyan * This software was developed by the Computer Systems Engineering group 8111314Snyan * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9111314Snyan * contributed to Berkeley. 10111314Snyan * 11111314Snyan * All advertising materials mentioning features or use of this software 12125234Snyan * must display the following acknowledgement: 13127520Snyan * This product includes software developed by the University of 14111314Snyan * California, Lawrence Berkeley Laboratory. 15111314Snyan * 16111314Snyan * Redistribution and use in source and binary forms, with or without 17111314Snyan * modification, are permitted provided that the following conditions 18111314Snyan * are met: 19111314Snyan * 1. Redistributions of source code must retain the above copyright 20122755Snyan * notice, this list of conditions and the following disclaimer. 21122755Snyan * 2. Redistributions in binary form must reproduce the above copyright 22122755Snyan * notice, this list of conditions and the following disclaimer in the 23122755Snyan * documentation and/or other materials provided with the distribution. 24111314Snyan * 3. Neither the name of the University nor the names of its contributors 25111314Snyan * may be used to endorse or promote products derived from this software 26111314Snyan * without specific prior written permission. 27122056Snyan * 28124795Snyan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29142783Snyan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30142783Snyan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31142783Snyan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32142783Snyan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33142783Snyan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34145743Snyan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35145743Snyan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36151634Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37145743Snyan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38145743Snyan * SUCH DAMAGE. 39111314Snyan * 40111314Snyan * @(#)fpu_explode.c 8.1 (Berkeley) 6/11/93 41111314Snyan */ 42111314Snyan 43111314Snyan/* 44111314Snyan * FPU subroutines: `explode' the machine's `packed binary' format numbers 45111314Snyan * into our internal format. 46111314Snyan */ 47111314Snyan 48111314Snyan#include <sys/cdefs.h> 49111314Snyan__FBSDID("$FreeBSD: stable/11/sys/powerpc/fpu/fpu_explode.c 295271 2016-02-04 17:43:56Z jhb $"); 50111314Snyan 51111314Snyan#include <sys/types.h> 52111314Snyan#include <sys/systm.h> 53111314Snyan 54111314Snyan#include <machine/fpu.h> 55124795Snyan#include <machine/ieee.h> 56124795Snyan#include <machine/pcb.h> 57124795Snyan 58124795Snyan#include <powerpc/fpu/fpu_arith.h> 59111314Snyan#include <powerpc/fpu/fpu_emu.h> 60111314Snyan#include <powerpc/fpu/fpu_extern.h> 61111314Snyan#include <powerpc/fpu/fpu_instr.h> 62111314Snyan 63111314Snyan/* 64111314Snyan * N.B.: in all of the following, we assume the FP format is 65111314Snyan * 66111314Snyan * --------------------------- 67111314Snyan * | s | exponent | fraction | 68111314Snyan * --------------------------- 69124795Snyan * 70124795Snyan * (which represents -1**s * 1.fraction * 2**exponent), so that the 71124795Snyan * sign bit is way at the top (bit 31), the exponent is next, and 72127520Snyan * then the remaining bits mark the fraction. A zero exponent means 73111314Snyan * zero or denormalized (0.fraction rather than 1.fraction), and the 74111314Snyan * maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN. 75111314Snyan * 76125234Snyan * Since the sign bit is always the topmost bit---this holds even for 77137526Snyan * integers---we set that outside all the *tof functions. Each function 78137526Snyan * returns the class code for the new number (but note that we use 79137526Snyan * FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate). 80137526Snyan */ 81137526Snyan 82124795Snyan/* 83127520Snyan * int -> fpn. 84124795Snyan */ 85111314Snyanint 86111314Snyanfpu_itof(struct fpn *fp, u_int i) 87111314Snyan{ 88111314Snyan 89111314Snyan if (i == 0) 90111314Snyan return (FPC_ZERO); 91111314Snyan /* 92111314Snyan * The value FP_1 represents 2^FP_LG, so set the exponent 93111314Snyan * there and let normalization fix it up. Convert negative 94125234Snyan * numbers to sign-and-magnitude. Note that this relies on 95111314Snyan * fpu_norm()'s handling of `supernormals'; see fpu_subr.c. 96111314Snyan */ 97111314Snyan fp->fp_exp = FP_LG; 98111314Snyan fp->fp_mant[0] = (int)i < 0 ? -i : i; 99111314Snyan fp->fp_mant[1] = 0; 100111314Snyan fp->fp_mant[2] = 0; 101111314Snyan fp->fp_mant[3] = 0; 102111314Snyan fpu_norm(fp); 103111314Snyan return (FPC_NUM); 104111314Snyan} 105111314Snyan 106111314Snyan/* 107111314Snyan * 64-bit int -> fpn. 108111314Snyan */ 109111314Snyanint 110111314Snyanfpu_xtof(struct fpn *fp, u_int64_t i) 111111314Snyan{ 112111314Snyan 113111314Snyan if (i == 0) 114125234Snyan return (FPC_ZERO); 115111314Snyan /* 116111314Snyan * The value FP_1 represents 2^FP_LG, so set the exponent 117111314Snyan * there and let normalization fix it up. Convert negative 118111314Snyan * numbers to sign-and-magnitude. Note that this relies on 119111314Snyan * fpu_norm()'s handling of `supernormals'; see fpu_subr.c. 120111314Snyan */ 121111314Snyan fp->fp_exp = FP_LG2; 122111314Snyan *((int64_t*)fp->fp_mant) = (int64_t)i < 0 ? -i : i; 123111314Snyan fp->fp_mant[2] = 0; 124111314Snyan fp->fp_mant[3] = 0; 125111314Snyan fpu_norm(fp); 126111314Snyan return (FPC_NUM); 127111314Snyan} 128111314Snyan 129111314Snyan#define mask(nbits) ((1L << (nbits)) - 1) 130111314Snyan 131111314Snyan/* 132111314Snyan * All external floating formats convert to internal in the same manner, 133111314Snyan * as defined here. Note that only normals get an implied 1.0 inserted. 134111314Snyan */ 135111314Snyan#define FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \ 136111314Snyan if (exp == 0) { \ 137111314Snyan if (allfrac == 0) \ 138111314Snyan return (FPC_ZERO); \ 139111314Snyan fp->fp_exp = 1 - expbias; \ 140111314Snyan fp->fp_mant[0] = f0; \ 141111314Snyan fp->fp_mant[1] = f1; \ 142111314Snyan fp->fp_mant[2] = f2; \ 143124795Snyan fp->fp_mant[3] = f3; \ 144111314Snyan fpu_norm(fp); \ 145111314Snyan return (FPC_NUM); \ 146111314Snyan } \ 147111314Snyan if (exp == (2 * expbias + 1)) { \ 148124795Snyan if (allfrac == 0) \ 149124795Snyan return (FPC_INF); \ 150111314Snyan fp->fp_mant[0] = f0; \ 151111314Snyan fp->fp_mant[1] = f1; \ 152111314Snyan fp->fp_mant[2] = f2; \ 153111314Snyan fp->fp_mant[3] = f3; \ 154111314Snyan return (FPC_QNAN); \ 155111314Snyan } \ 156111314Snyan fp->fp_exp = exp - expbias; \ 157111314Snyan fp->fp_mant[0] = FP_1 | f0; \ 158111314Snyan fp->fp_mant[1] = f1; \ 159111314Snyan fp->fp_mant[2] = f2; \ 160111314Snyan fp->fp_mant[3] = f3; \ 161111314Snyan return (FPC_NUM) 162111314Snyan 163111314Snyan/* 164111314Snyan * 32-bit single precision -> fpn. 165124795Snyan * We assume a single occupies at most (64-FP_LG) bits in the internal 166111314Snyan * format: i.e., needs at most fp_mant[0] and fp_mant[1]. 167111314Snyan */ 168111314Snyanint 169111314Snyanfpu_stof(struct fpn *fp, u_int i) 170111314Snyan{ 171111314Snyan int exp; 172111314Snyan u_int frac, f0, f1; 173111314Snyan#define SNG_SHIFT (SNG_FRACBITS - FP_LG) 174111314Snyan 175111314Snyan exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS); 176111314Snyan frac = i & mask(SNG_FRACBITS); 177111314Snyan f0 = frac >> SNG_SHIFT; 178111314Snyan f1 = frac << (32 - SNG_SHIFT); 179111314Snyan FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0); 180111314Snyan} 181111314Snyan 182124795Snyan/* 183111314Snyan * 64-bit double -> fpn. 184111314Snyan * We assume this uses at most (96-FP_LG) bits. 185111314Snyan */ 186151051Sglebiusint 187151051Sglebiusfpu_dtof(struct fpn *fp, u_int i, u_int j) 188151051Sglebius{ 189151051Sglebius int exp; 190111314Snyan u_int frac, f0, f1, f2; 191124408Snyan#define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG) 192124408Snyan 193111314Snyan exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS); 194111314Snyan frac = i & mask(DBL_FRACBITS - 32); 195111314Snyan f0 = frac >> DBL_SHIFT; 196111314Snyan f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT); 197111314Snyan f2 = j << (32 - DBL_SHIFT); 198111314Snyan frac |= j; 199111314Snyan FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0); 200111314Snyan} 201111314Snyan 202111314Snyan/* 203123984Sbde * Explode the contents of a register / regpair / regquad. 204123984Sbde * If the input is a signalling NaN, an NV (invalid) exception 205123984Sbde * will be set. (Note that nothing but NV can occur until ALU 206123984Sbde * operations are performed.) 207111314Snyan */ 208111314Snyanvoid 209123984Sbdefpu_explode(struct fpemu *fe, struct fpn *fp, int type, int reg) 210123984Sbde{ 211111314Snyan u_int s, *space; 212111314Snyan u_int64_t l, *xspace; 213111314Snyan 214111314Snyan xspace = (u_int64_t *)&fe->fe_fpstate->fpr[reg].fpr; 215111314Snyan l = xspace[0]; 216111314Snyan space = (u_int *)&fe->fe_fpstate->fpr[reg].fpr; 217111314Snyan s = space[0]; 218111314Snyan fp->fp_sign = s >> 31; 219111314Snyan fp->fp_sticky = 0; 220124795Snyan switch (type) { 221111314Snyan 222111314Snyan case FTYPE_LNG: 223111314Snyan s = fpu_xtof(fp, l); 224111314Snyan break; 225111314Snyan 226111314Snyan case FTYPE_INT: 227111314Snyan s = fpu_itof(fp, space[1]); 228111314Snyan break; 229111314Snyan 230111314Snyan case FTYPE_SNG: 231111314Snyan s = fpu_stof(fp, s); 232111314Snyan break; 233111314Snyan 234111314Snyan case FTYPE_DBL: 235111314Snyan s = fpu_dtof(fp, s, space[1]); 236111314Snyan break; 237111314Snyan 238111314Snyan default: 239111314Snyan panic("fpu_explode"); 240111314Snyan panic("fpu_explode: invalid type %d", type); 241111314Snyan } 242111314Snyan 243111314Snyan if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) { 244111314Snyan /* 245111314Snyan * Input is a signalling NaN. All operations that return 246111314Snyan * an input NaN operand put it through a ``NaN conversion'', 247111314Snyan * which basically just means ``turn on the quiet bit''. 248111314Snyan * We do this here so that all NaNs internally look quiet 249111314Snyan * (we can tell signalling ones by their class). 250111314Snyan */ 251111314Snyan fp->fp_mant[0] |= FP_QUIETBIT; 252111314Snyan fe->fe_cx = FPSCR_VXSNAN; /* assert invalid operand */ 253111314Snyan s = FPC_SNAN; 254111314Snyan } 255111314Snyan fp->fp_class = s; 256111314Snyan DPRINTF(FPE_REG, ("fpu_explode: %%%c%d => ", (type == FTYPE_LNG) ? 'x' : 257111314Snyan ((type == FTYPE_INT) ? 'i' : 258111314Snyan ((type == FTYPE_SNG) ? 's' : 259111314Snyan ((type == FTYPE_DBL) ? 'd' : '?'))), 260111314Snyan reg)); 261111314Snyan DUMPFPN(FPE_REG, fp); 262111314Snyan DPRINTF(FPE_REG, ("\n")); 263111314Snyan} 264111314Snyan