/* $NetBSD: fpu_explode.c,v 1.6 2005/12/11 12:18:42 christos Exp $ */12/*-3* SPDX-License-Identifier: BSD-3-Clause4*5* Copyright (c) 1992, 19936* The Regents of the University of California. All rights reserved.7*8* This software was developed by the Computer Systems Engineering group9* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and10* contributed to Berkeley.11*12* All advertising materials mentioning features or use of this software13* must display the following acknowledgement:14* This product includes software developed by the University of15* California, Lawrence Berkeley Laboratory.16*17* Redistribution and use in source and binary forms, with or without18* modification, are permitted provided that the following conditions19* are met:20* 1. Redistributions of source code must retain the above copyright21* notice, this list of conditions and the following disclaimer.22* 2. Redistributions in binary form must reproduce the above copyright23* notice, this list of conditions and the following disclaimer in the24* documentation and/or other materials provided with the distribution.25* 3. Neither the name of the University nor the names of its contributors26* may be used to endorse or promote products derived from this software27* without specific prior written permission.28*29* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND30* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE31* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE32* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE33* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL34* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS35* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)36* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT37* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY38* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF39* SUCH DAMAGE.40*/4142/*43* FPU subroutines: `explode' the machine's `packed binary' format numbers44* into our internal format.45*/4647#include <sys/types.h>48#include <sys/systm.h>4950#include <machine/fpu.h>51#include <machine/ieee.h>52#include <machine/pcb.h>5354#include <powerpc/fpu/fpu_arith.h>55#include <powerpc/fpu/fpu_emu.h>56#include <powerpc/fpu/fpu_extern.h>57#include <powerpc/fpu/fpu_instr.h>5859/*60* N.B.: in all of the following, we assume the FP format is61*62* ---------------------------63* | s | exponent | fraction |64* ---------------------------65*66* (which represents -1**s * 1.fraction * 2**exponent), so that the67* sign bit is way at the top (bit 31), the exponent is next, and68* then the remaining bits mark the fraction. A zero exponent means69* zero or denormalized (0.fraction rather than 1.fraction), and the70* maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN.71*72* Since the sign bit is always the topmost bit---this holds even for73* integers---we set that outside all the *tof functions. Each function74* returns the class code for the new number (but note that we use75* FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate).76*/7778/*79* int -> fpn.80*/81int82fpu_itof(struct fpn *fp, u_int i)83{8485if (i == 0)86return (FPC_ZERO);87/*88* The value FP_1 represents 2^FP_LG, so set the exponent89* there and let normalization fix it up. Convert negative90* numbers to sign-and-magnitude. Note that this relies on91* fpu_norm()'s handling of `supernormals'; see fpu_subr.c.92*/93fp->fp_exp = FP_LG;94fp->fp_mant[0] = (int)i < 0 ? -i : i;95fp->fp_mant[1] = 0;96fp->fp_mant[2] = 0;97fp->fp_mant[3] = 0;98fpu_norm(fp);99return (FPC_NUM);100}101102/*103* 64-bit int -> fpn.104*/105int106fpu_xtof(struct fpn *fp, u_int64_t i)107{108109if (i == 0)110return (FPC_ZERO);111/*112* The value FP_1 represents 2^FP_LG, so set the exponent113* there and let normalization fix it up. Convert negative114* numbers to sign-and-magnitude. Note that this relies on115* fpu_norm()'s handling of `supernormals'; see fpu_subr.c.116*/117fp->fp_exp = FP_LG2;118*((int64_t*)fp->fp_mant) = (int64_t)i < 0 ? -i : i;119fp->fp_mant[2] = 0;120fp->fp_mant[3] = 0;121fpu_norm(fp);122return (FPC_NUM);123}124125#define mask(nbits) ((1L << (nbits)) - 1)126127/*128* All external floating formats convert to internal in the same manner,129* as defined here. Note that only normals get an implied 1.0 inserted.130*/131#define FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \132if (exp == 0) { \133if (allfrac == 0) \134return (FPC_ZERO); \135fp->fp_exp = 1 - expbias; \136fp->fp_mant[0] = f0; \137fp->fp_mant[1] = f1; \138fp->fp_mant[2] = f2; \139fp->fp_mant[3] = f3; \140fpu_norm(fp); \141return (FPC_NUM); \142} \143if (exp == (2 * expbias + 1)) { \144if (allfrac == 0) \145return (FPC_INF); \146fp->fp_mant[0] = f0; \147fp->fp_mant[1] = f1; \148fp->fp_mant[2] = f2; \149fp->fp_mant[3] = f3; \150return (FPC_QNAN); \151} \152fp->fp_exp = exp - expbias; \153fp->fp_mant[0] = FP_1 | f0; \154fp->fp_mant[1] = f1; \155fp->fp_mant[2] = f2; \156fp->fp_mant[3] = f3; \157return (FPC_NUM)158159/*160* 32-bit single precision -> fpn.161* We assume a single occupies at most (64-FP_LG) bits in the internal162* format: i.e., needs at most fp_mant[0] and fp_mant[1].163*/164int165fpu_stof(struct fpn *fp, u_int i)166{167int exp;168u_int frac, f0, f1;169#define SNG_SHIFT (SNG_FRACBITS - FP_LG)170171exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS);172frac = i & mask(SNG_FRACBITS);173f0 = frac >> SNG_SHIFT;174f1 = frac << (32 - SNG_SHIFT);175FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0);176}177178/*179* 64-bit double -> fpn.180* We assume this uses at most (96-FP_LG) bits.181*/182int183fpu_dtof(struct fpn *fp, u_int i, u_int j)184{185int exp;186u_int frac, f0, f1, f2;187#define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG)188189exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS);190frac = i & mask(DBL_FRACBITS - 32);191f0 = frac >> DBL_SHIFT;192f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT);193f2 = j << (32 - DBL_SHIFT);194frac |= j;195FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0);196}197198/*199* Explode the contents of a register / regpair / regquad.200* If the input is a signalling NaN, an NV (invalid) exception201* will be set. (Note that nothing but NV can occur until ALU202* operations are performed.)203*/204void205fpu_explode(struct fpemu *fe, struct fpn *fp, int type, int reg)206{207u_int s, *space;208u_int64_t l, *xspace;209210xspace = (u_int64_t *)&fe->fe_fpstate->fpr[reg].fpr;211l = xspace[0];212space = (u_int *)&fe->fe_fpstate->fpr[reg].fpr;213s = space[0];214fp->fp_sign = s >> 31;215fp->fp_sticky = 0;216switch (type) {217case FTYPE_LNG:218s = fpu_xtof(fp, l);219break;220221case FTYPE_INT:222s = fpu_itof(fp, space[1]);223break;224225case FTYPE_SNG:226s = fpu_stof(fp, s);227break;228229case FTYPE_DBL:230s = fpu_dtof(fp, s, space[1]);231break;232233default:234panic("fpu_explode");235panic("fpu_explode: invalid type %d", type);236}237238if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) {239/*240* Input is a signalling NaN. All operations that return241* an input NaN operand put it through a ``NaN conversion'',242* which basically just means ``turn on the quiet bit''.243* We do this here so that all NaNs internally look quiet244* (we can tell signalling ones by their class).245*/246fp->fp_mant[0] |= FP_QUIETBIT;247fe->fe_cx = FPSCR_VXSNAN; /* assert invalid operand */248s = FPC_SNAN;249}250fp->fp_class = s;251DPRINTF(FPE_REG, ("fpu_explode: %%%c%d => ", (type == FTYPE_LNG) ? 'x' :252((type == FTYPE_INT) ? 'i' :253((type == FTYPE_SNG) ? 's' :254((type == FTYPE_DBL) ? 'd' : '?'))),255reg));256DUMPFPN(FPE_REG, fp);257DPRINTF(FPE_REG, ("\n"));258}259260261