The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/powerpc/fpu/fpu_explode.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: fpu_explode.c,v 1.6 2005/12/11 12:18:42 christos Exp $ */
    2 
    3 /*-
    4  * SPDX-License-Identifier: BSD-3-Clause
    5  *
    6  * Copyright (c) 1992, 1993
    7  *      The Regents of the University of California.  All rights reserved.
    8  *
    9  * This software was developed by the Computer Systems Engineering group
   10  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
   11  * contributed to Berkeley.
   12  *
   13  * All advertising materials mentioning features or use of this software
   14  * must display the following acknowledgement:
   15  *      This product includes software developed by the University of
   16  *      California, Lawrence Berkeley Laboratory.
   17  *
   18  * Redistribution and use in source and binary forms, with or without
   19  * modification, are permitted provided that the following conditions
   20  * are met:
   21  * 1. Redistributions of source code must retain the above copyright
   22  *    notice, this list of conditions and the following disclaimer.
   23  * 2. Redistributions in binary form must reproduce the above copyright
   24  *    notice, this list of conditions and the following disclaimer in the
   25  *    documentation and/or other materials provided with the distribution.
   26  * 3. Neither the name of the University nor the names of its contributors
   27  *    may be used to endorse or promote products derived from this software
   28  *    without specific prior written permission.
   29  *
   30  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   40  * SUCH DAMAGE.
   41  *
   42  *      @(#)fpu_explode.c       8.1 (Berkeley) 6/11/93
   43  */
   44 
   45 /*
   46  * FPU subroutines: `explode' the machine's `packed binary' format numbers
   47  * into our internal format.
   48  */
   49 
   50 #include <sys/cdefs.h>
   51 __FBSDID("$FreeBSD$");
   52 
   53 #include <sys/types.h>
   54 #include <sys/systm.h>
   55 
   56 #include <machine/fpu.h>
   57 #include <machine/ieee.h>
   58 #include <machine/pcb.h>
   59 
   60 #include <powerpc/fpu/fpu_arith.h>
   61 #include <powerpc/fpu/fpu_emu.h>
   62 #include <powerpc/fpu/fpu_extern.h>
   63 #include <powerpc/fpu/fpu_instr.h>
   64 
   65 /*
   66  * N.B.: in all of the following, we assume the FP format is
   67  *
   68  *      ---------------------------
   69  *      | s | exponent | fraction |
   70  *      ---------------------------
   71  *
   72  * (which represents -1**s * 1.fraction * 2**exponent), so that the
   73  * sign bit is way at the top (bit 31), the exponent is next, and
   74  * then the remaining bits mark the fraction.  A zero exponent means
   75  * zero or denormalized (0.fraction rather than 1.fraction), and the
   76  * maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN.
   77  *
   78  * Since the sign bit is always the topmost bit---this holds even for
   79  * integers---we set that outside all the *tof functions.  Each function
   80  * returns the class code for the new number (but note that we use
   81  * FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate).
   82  */
   83 
   84 /*
   85  * int -> fpn.
   86  */
   87 int
   88 fpu_itof(struct fpn *fp, u_int i)
   89 {
   90 
   91         if (i == 0)
   92                 return (FPC_ZERO);
   93         /*
   94          * The value FP_1 represents 2^FP_LG, so set the exponent
   95          * there and let normalization fix it up.  Convert negative
   96          * numbers to sign-and-magnitude.  Note that this relies on
   97          * fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
   98          */
   99         fp->fp_exp = FP_LG;
  100         fp->fp_mant[0] = (int)i < 0 ? -i : i;
  101         fp->fp_mant[1] = 0;
  102         fp->fp_mant[2] = 0;
  103         fp->fp_mant[3] = 0;
  104         fpu_norm(fp);
  105         return (FPC_NUM);
  106 }
  107 
  108 /*
  109  * 64-bit int -> fpn.
  110  */
  111 int
  112 fpu_xtof(struct fpn *fp, u_int64_t i)
  113 {
  114 
  115         if (i == 0)
  116                 return (FPC_ZERO);
  117         /*
  118          * The value FP_1 represents 2^FP_LG, so set the exponent
  119          * there and let normalization fix it up.  Convert negative
  120          * numbers to sign-and-magnitude.  Note that this relies on
  121          * fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
  122          */
  123         fp->fp_exp = FP_LG2;
  124         *((int64_t*)fp->fp_mant) = (int64_t)i < 0 ? -i : i;
  125         fp->fp_mant[2] = 0;
  126         fp->fp_mant[3] = 0;
  127         fpu_norm(fp);
  128         return (FPC_NUM);
  129 }
  130 
  131 #define mask(nbits) ((1L << (nbits)) - 1)
  132 
  133 /*
  134  * All external floating formats convert to internal in the same manner,
  135  * as defined here.  Note that only normals get an implied 1.0 inserted.
  136  */
  137 #define FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \
  138         if (exp == 0) { \
  139                 if (allfrac == 0) \
  140                         return (FPC_ZERO); \
  141                 fp->fp_exp = 1 - expbias; \
  142                 fp->fp_mant[0] = f0; \
  143                 fp->fp_mant[1] = f1; \
  144                 fp->fp_mant[2] = f2; \
  145                 fp->fp_mant[3] = f3; \
  146                 fpu_norm(fp); \
  147                 return (FPC_NUM); \
  148         } \
  149         if (exp == (2 * expbias + 1)) { \
  150                 if (allfrac == 0) \
  151                         return (FPC_INF); \
  152                 fp->fp_mant[0] = f0; \
  153                 fp->fp_mant[1] = f1; \
  154                 fp->fp_mant[2] = f2; \
  155                 fp->fp_mant[3] = f3; \
  156                 return (FPC_QNAN); \
  157         } \
  158         fp->fp_exp = exp - expbias; \
  159         fp->fp_mant[0] = FP_1 | f0; \
  160         fp->fp_mant[1] = f1; \
  161         fp->fp_mant[2] = f2; \
  162         fp->fp_mant[3] = f3; \
  163         return (FPC_NUM)
  164 
  165 /*
  166  * 32-bit single precision -> fpn.
  167  * We assume a single occupies at most (64-FP_LG) bits in the internal
  168  * format: i.e., needs at most fp_mant[0] and fp_mant[1].
  169  */
  170 int
  171 fpu_stof(struct fpn *fp, u_int i)
  172 {
  173         int exp;
  174         u_int frac, f0, f1;
  175 #define SNG_SHIFT (SNG_FRACBITS - FP_LG)
  176 
  177         exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS);
  178         frac = i & mask(SNG_FRACBITS);
  179         f0 = frac >> SNG_SHIFT;
  180         f1 = frac << (32 - SNG_SHIFT);
  181         FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0);
  182 }
  183 
  184 /*
  185  * 64-bit double -> fpn.
  186  * We assume this uses at most (96-FP_LG) bits.
  187  */
  188 int
  189 fpu_dtof(struct fpn *fp, u_int i, u_int j)
  190 {
  191         int exp;
  192         u_int frac, f0, f1, f2;
  193 #define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG)
  194 
  195         exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS);
  196         frac = i & mask(DBL_FRACBITS - 32);
  197         f0 = frac >> DBL_SHIFT;
  198         f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT);
  199         f2 = j << (32 - DBL_SHIFT);
  200         frac |= j;
  201         FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0);
  202 }
  203 
  204 /*
  205  * Explode the contents of a register / regpair / regquad.
  206  * If the input is a signalling NaN, an NV (invalid) exception
  207  * will be set.  (Note that nothing but NV can occur until ALU
  208  * operations are performed.)
  209  */
  210 void
  211 fpu_explode(struct fpemu *fe, struct fpn *fp, int type, int reg)
  212 {
  213         u_int s, *space;
  214         u_int64_t l, *xspace;
  215 
  216         xspace = (u_int64_t *)&fe->fe_fpstate->fpr[reg].fpr;
  217         l = xspace[0];
  218         space = (u_int *)&fe->fe_fpstate->fpr[reg].fpr;
  219         s = space[0];
  220         fp->fp_sign = s >> 31;
  221         fp->fp_sticky = 0;
  222         switch (type) {
  223         case FTYPE_LNG:
  224                 s = fpu_xtof(fp, l);
  225                 break;
  226 
  227         case FTYPE_INT:
  228                 s = fpu_itof(fp, space[1]);
  229                 break;
  230 
  231         case FTYPE_SNG:
  232                 s = fpu_stof(fp, s);
  233                 break;
  234 
  235         case FTYPE_DBL:
  236                 s = fpu_dtof(fp, s, space[1]);
  237                 break;
  238 
  239         default:
  240                 panic("fpu_explode");
  241                 panic("fpu_explode: invalid type %d", type);
  242         }
  243 
  244         if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) {
  245                 /*
  246                  * Input is a signalling NaN.  All operations that return
  247                  * an input NaN operand put it through a ``NaN conversion'',
  248                  * which basically just means ``turn on the quiet bit''.
  249                  * We do this here so that all NaNs internally look quiet
  250                  * (we can tell signalling ones by their class).
  251                  */
  252                 fp->fp_mant[0] |= FP_QUIETBIT;
  253                 fe->fe_cx = FPSCR_VXSNAN;       /* assert invalid operand */
  254                 s = FPC_SNAN;
  255         }
  256         fp->fp_class = s;
  257         DPRINTF(FPE_REG, ("fpu_explode: %%%c%d => ", (type == FTYPE_LNG) ? 'x' :
  258                 ((type == FTYPE_INT) ? 'i' : 
  259                         ((type == FTYPE_SNG) ? 's' :
  260                                 ((type == FTYPE_DBL) ? 'd' : '?'))),
  261                 reg));
  262         DUMPFPN(FPE_REG, fp);
  263         DPRINTF(FPE_REG, ("\n"));
  264 }

Cache object: cb0b32f436135b962e9dfefde56128cd


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.