1176491Smarcel/* $NetBSD: fpu_explode.c,v 1.6 2005/12/11 12:18:42 christos Exp $ */ 2176491Smarcel 3176491Smarcel/* 4176491Smarcel * Copyright (c) 1992, 1993 5176491Smarcel * The Regents of the University of California. All rights reserved. 6176491Smarcel * 7176491Smarcel * This software was developed by the Computer Systems Engineering group 8176491Smarcel * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9176491Smarcel * contributed to Berkeley. 10176491Smarcel * 11176491Smarcel * All advertising materials mentioning features or use of this software 12176491Smarcel * must display the following acknowledgement: 13176491Smarcel * This product includes software developed by the University of 14176491Smarcel * California, Lawrence Berkeley Laboratory. 15176491Smarcel * 16176491Smarcel * Redistribution and use in source and binary forms, with or without 17176491Smarcel * modification, are permitted provided that the following conditions 18176491Smarcel * are met: 19176491Smarcel * 1. Redistributions of source code must retain the above copyright 20176491Smarcel * notice, this list of conditions and the following disclaimer. 21176491Smarcel * 2. Redistributions in binary form must reproduce the above copyright 22176491Smarcel * notice, this list of conditions and the following disclaimer in the 23176491Smarcel * documentation and/or other materials provided with the distribution. 24176491Smarcel * 3. Neither the name of the University nor the names of its contributors 25176491Smarcel * may be used to endorse or promote products derived from this software 26176491Smarcel * without specific prior written permission. 27176491Smarcel * 28176491Smarcel * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29176491Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30176491Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31176491Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32176491Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33176491Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34176491Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35176491Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36176491Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37176491Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38176491Smarcel * SUCH DAMAGE. 39176491Smarcel * 40176491Smarcel * @(#)fpu_explode.c 8.1 (Berkeley) 6/11/93 41176491Smarcel */ 42176491Smarcel 43176491Smarcel/* 44176491Smarcel * FPU subroutines: `explode' the machine's `packed binary' format numbers 45176491Smarcel * into our internal format. 46176491Smarcel */ 47176491Smarcel 48176491Smarcel#include <sys/cdefs.h> 49176491Smarcel__FBSDID("$FreeBSD: releng/11.0/sys/powerpc/fpu/fpu_explode.c 295271 2016-02-04 17:43:56Z jhb $"); 50176491Smarcel 51178030Sgrehan#include <sys/types.h> 52176491Smarcel#include <sys/systm.h> 53176491Smarcel 54176491Smarcel#include <machine/fpu.h> 55176491Smarcel#include <machine/ieee.h> 56295271Sjhb#include <machine/pcb.h> 57176491Smarcel 58176491Smarcel#include <powerpc/fpu/fpu_arith.h> 59176491Smarcel#include <powerpc/fpu/fpu_emu.h> 60176491Smarcel#include <powerpc/fpu/fpu_extern.h> 61176491Smarcel#include <powerpc/fpu/fpu_instr.h> 62176491Smarcel 63176491Smarcel/* 64176491Smarcel * N.B.: in all of the following, we assume the FP format is 65176491Smarcel * 66176491Smarcel * --------------------------- 67176491Smarcel * | s | exponent | fraction | 68176491Smarcel * --------------------------- 69176491Smarcel * 70176491Smarcel * (which represents -1**s * 1.fraction * 2**exponent), so that the 71176491Smarcel * sign bit is way at the top (bit 31), the exponent is next, and 72176491Smarcel * then the remaining bits mark the fraction. A zero exponent means 73176491Smarcel * zero or denormalized (0.fraction rather than 1.fraction), and the 74176491Smarcel * maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN. 75176491Smarcel * 76176491Smarcel * Since the sign bit is always the topmost bit---this holds even for 77176491Smarcel * integers---we set that outside all the *tof functions. Each function 78176491Smarcel * returns the class code for the new number (but note that we use 79176491Smarcel * FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate). 80176491Smarcel */ 81176491Smarcel 82176491Smarcel/* 83176491Smarcel * int -> fpn. 84176491Smarcel */ 85176491Smarcelint 86176491Smarcelfpu_itof(struct fpn *fp, u_int i) 87176491Smarcel{ 88176491Smarcel 89176491Smarcel if (i == 0) 90176491Smarcel return (FPC_ZERO); 91176491Smarcel /* 92176491Smarcel * The value FP_1 represents 2^FP_LG, so set the exponent 93176491Smarcel * there and let normalization fix it up. Convert negative 94176491Smarcel * numbers to sign-and-magnitude. Note that this relies on 95176491Smarcel * fpu_norm()'s handling of `supernormals'; see fpu_subr.c. 96176491Smarcel */ 97176491Smarcel fp->fp_exp = FP_LG; 98176491Smarcel fp->fp_mant[0] = (int)i < 0 ? -i : i; 99176491Smarcel fp->fp_mant[1] = 0; 100176491Smarcel fp->fp_mant[2] = 0; 101176491Smarcel fp->fp_mant[3] = 0; 102176491Smarcel fpu_norm(fp); 103176491Smarcel return (FPC_NUM); 104176491Smarcel} 105176491Smarcel 106176491Smarcel/* 107176491Smarcel * 64-bit int -> fpn. 108176491Smarcel */ 109176491Smarcelint 110176491Smarcelfpu_xtof(struct fpn *fp, u_int64_t i) 111176491Smarcel{ 112176491Smarcel 113176491Smarcel if (i == 0) 114176491Smarcel return (FPC_ZERO); 115176491Smarcel /* 116176491Smarcel * The value FP_1 represents 2^FP_LG, so set the exponent 117176491Smarcel * there and let normalization fix it up. Convert negative 118176491Smarcel * numbers to sign-and-magnitude. Note that this relies on 119176491Smarcel * fpu_norm()'s handling of `supernormals'; see fpu_subr.c. 120176491Smarcel */ 121176491Smarcel fp->fp_exp = FP_LG2; 122176491Smarcel *((int64_t*)fp->fp_mant) = (int64_t)i < 0 ? -i : i; 123176491Smarcel fp->fp_mant[2] = 0; 124176491Smarcel fp->fp_mant[3] = 0; 125176491Smarcel fpu_norm(fp); 126176491Smarcel return (FPC_NUM); 127176491Smarcel} 128176491Smarcel 129176491Smarcel#define mask(nbits) ((1L << (nbits)) - 1) 130176491Smarcel 131176491Smarcel/* 132176491Smarcel * All external floating formats convert to internal in the same manner, 133176491Smarcel * as defined here. Note that only normals get an implied 1.0 inserted. 134176491Smarcel */ 135176491Smarcel#define FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \ 136176491Smarcel if (exp == 0) { \ 137176491Smarcel if (allfrac == 0) \ 138176491Smarcel return (FPC_ZERO); \ 139176491Smarcel fp->fp_exp = 1 - expbias; \ 140176491Smarcel fp->fp_mant[0] = f0; \ 141176491Smarcel fp->fp_mant[1] = f1; \ 142176491Smarcel fp->fp_mant[2] = f2; \ 143176491Smarcel fp->fp_mant[3] = f3; \ 144176491Smarcel fpu_norm(fp); \ 145176491Smarcel return (FPC_NUM); \ 146176491Smarcel } \ 147176491Smarcel if (exp == (2 * expbias + 1)) { \ 148176491Smarcel if (allfrac == 0) \ 149176491Smarcel return (FPC_INF); \ 150176491Smarcel fp->fp_mant[0] = f0; \ 151176491Smarcel fp->fp_mant[1] = f1; \ 152176491Smarcel fp->fp_mant[2] = f2; \ 153176491Smarcel fp->fp_mant[3] = f3; \ 154176491Smarcel return (FPC_QNAN); \ 155176491Smarcel } \ 156176491Smarcel fp->fp_exp = exp - expbias; \ 157176491Smarcel fp->fp_mant[0] = FP_1 | f0; \ 158176491Smarcel fp->fp_mant[1] = f1; \ 159176491Smarcel fp->fp_mant[2] = f2; \ 160176491Smarcel fp->fp_mant[3] = f3; \ 161176491Smarcel return (FPC_NUM) 162176491Smarcel 163176491Smarcel/* 164176491Smarcel * 32-bit single precision -> fpn. 165176491Smarcel * We assume a single occupies at most (64-FP_LG) bits in the internal 166176491Smarcel * format: i.e., needs at most fp_mant[0] and fp_mant[1]. 167176491Smarcel */ 168176491Smarcelint 169176491Smarcelfpu_stof(struct fpn *fp, u_int i) 170176491Smarcel{ 171176491Smarcel int exp; 172176491Smarcel u_int frac, f0, f1; 173176491Smarcel#define SNG_SHIFT (SNG_FRACBITS - FP_LG) 174176491Smarcel 175176491Smarcel exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS); 176176491Smarcel frac = i & mask(SNG_FRACBITS); 177176491Smarcel f0 = frac >> SNG_SHIFT; 178176491Smarcel f1 = frac << (32 - SNG_SHIFT); 179176491Smarcel FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0); 180176491Smarcel} 181176491Smarcel 182176491Smarcel/* 183176491Smarcel * 64-bit double -> fpn. 184176491Smarcel * We assume this uses at most (96-FP_LG) bits. 185176491Smarcel */ 186176491Smarcelint 187176491Smarcelfpu_dtof(struct fpn *fp, u_int i, u_int j) 188176491Smarcel{ 189176491Smarcel int exp; 190176491Smarcel u_int frac, f0, f1, f2; 191176491Smarcel#define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG) 192176491Smarcel 193176491Smarcel exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS); 194176491Smarcel frac = i & mask(DBL_FRACBITS - 32); 195176491Smarcel f0 = frac >> DBL_SHIFT; 196176491Smarcel f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT); 197176491Smarcel f2 = j << (32 - DBL_SHIFT); 198176491Smarcel frac |= j; 199176491Smarcel FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0); 200176491Smarcel} 201176491Smarcel 202176491Smarcel/* 203176491Smarcel * Explode the contents of a register / regpair / regquad. 204176491Smarcel * If the input is a signalling NaN, an NV (invalid) exception 205176491Smarcel * will be set. (Note that nothing but NV can occur until ALU 206176491Smarcel * operations are performed.) 207176491Smarcel */ 208176491Smarcelvoid 209176491Smarcelfpu_explode(struct fpemu *fe, struct fpn *fp, int type, int reg) 210176491Smarcel{ 211176491Smarcel u_int s, *space; 212176491Smarcel u_int64_t l, *xspace; 213176491Smarcel 214295271Sjhb xspace = (u_int64_t *)&fe->fe_fpstate->fpr[reg].fpr; 215176491Smarcel l = xspace[0]; 216295271Sjhb space = (u_int *)&fe->fe_fpstate->fpr[reg].fpr; 217176491Smarcel s = space[0]; 218176491Smarcel fp->fp_sign = s >> 31; 219176491Smarcel fp->fp_sticky = 0; 220176491Smarcel switch (type) { 221176491Smarcel 222176491Smarcel case FTYPE_LNG: 223176491Smarcel s = fpu_xtof(fp, l); 224176491Smarcel break; 225176491Smarcel 226176491Smarcel case FTYPE_INT: 227176491Smarcel s = fpu_itof(fp, space[1]); 228176491Smarcel break; 229176491Smarcel 230176491Smarcel case FTYPE_SNG: 231176491Smarcel s = fpu_stof(fp, s); 232176491Smarcel break; 233176491Smarcel 234176491Smarcel case FTYPE_DBL: 235176491Smarcel s = fpu_dtof(fp, s, space[1]); 236176491Smarcel break; 237176491Smarcel 238258250Snwhitehorn default: 239176491Smarcel panic("fpu_explode"); 240176491Smarcel panic("fpu_explode: invalid type %d", type); 241176491Smarcel } 242176491Smarcel 243176491Smarcel if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) { 244176491Smarcel /* 245176491Smarcel * Input is a signalling NaN. All operations that return 246176491Smarcel * an input NaN operand put it through a ``NaN conversion'', 247176491Smarcel * which basically just means ``turn on the quiet bit''. 248176491Smarcel * We do this here so that all NaNs internally look quiet 249176491Smarcel * (we can tell signalling ones by their class). 250176491Smarcel */ 251176491Smarcel fp->fp_mant[0] |= FP_QUIETBIT; 252176491Smarcel fe->fe_cx = FPSCR_VXSNAN; /* assert invalid operand */ 253176491Smarcel s = FPC_SNAN; 254176491Smarcel } 255176491Smarcel fp->fp_class = s; 256176491Smarcel DPRINTF(FPE_REG, ("fpu_explode: %%%c%d => ", (type == FTYPE_LNG) ? 'x' : 257176491Smarcel ((type == FTYPE_INT) ? 'i' : 258176491Smarcel ((type == FTYPE_SNG) ? 's' : 259176491Smarcel ((type == FTYPE_DBL) ? 'd' : '?'))), 260176491Smarcel reg)); 261176491Smarcel DUMPFPN(FPE_REG, fp); 262176491Smarcel DPRINTF(FPE_REG, ("\n")); 263176491Smarcel} 264