1*55113Storek /* 2*55113Storek * Copyright (c) 1992 The Regents of the University of California. 3*55113Storek * All rights reserved. 4*55113Storek * 5*55113Storek * This software was developed by the Computer Systems Engineering group 6*55113Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7*55113Storek * contributed to Berkeley. 8*55113Storek * 9*55113Storek * %sccs.include.redist.c% 10*55113Storek * 11*55113Storek * @(#)fpu_explode.c 7.1 (Berkeley) 07/13/92 12*55113Storek * 13*55113Storek * from: $Header: fpu_explode.c,v 1.2 92/06/17 05:41:32 torek Exp $ 14*55113Storek */ 15*55113Storek 16*55113Storek /* 17*55113Storek * FPU subroutines: `explode' the machine's `packed binary' format numbers 18*55113Storek * into our internal format. 19*55113Storek */ 20*55113Storek 21*55113Storek #include "sys/types.h" 22*55113Storek 23*55113Storek #include "machine/ieee.h" 24*55113Storek #include "machine/instr.h" 25*55113Storek #include "machine/reg.h" 26*55113Storek 27*55113Storek #include "fpu_arith.h" 28*55113Storek #include "fpu_emu.h" 29*55113Storek 30*55113Storek /* 31*55113Storek * N.B.: in all of the following, we assume the FP format is 32*55113Storek * 33*55113Storek * --------------------------- 34*55113Storek * | s | exponent | fraction | 35*55113Storek * --------------------------- 36*55113Storek * 37*55113Storek * (which represents -1**s * 1.fraction * 2**exponent), so that the 38*55113Storek * sign bit is way at the top (bit 31), the exponent is next, and 39*55113Storek * then the remaining bits mark the fraction. A zero exponent means 40*55113Storek * zero or denormalized (0.fraction rather than 1.fraction), and the 41*55113Storek * maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN. 42*55113Storek * 43*55113Storek * Since the sign bit is always the topmost bit---this holds even for 44*55113Storek * integers---we set that outside all the *tof functions. Each function 45*55113Storek * returns the class code for the new number (but note that we use 46*55113Storek * FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate). 47*55113Storek */ 48*55113Storek 49*55113Storek /* 50*55113Storek * int -> fpn. 51*55113Storek */ 52*55113Storek int 53*55113Storek fpu_itof(fp, i) 54*55113Storek register struct fpn *fp; 55*55113Storek register u_int i; 56*55113Storek { 57*55113Storek 58*55113Storek if (i == 0) 59*55113Storek return (FPC_ZERO); 60*55113Storek /* 61*55113Storek * The value FP_1 represents 2^FP_LG, so set the exponent 62*55113Storek * there and let normalization fix it up. Convert negative 63*55113Storek * numbers to sign-and-magnitude. Note that this relies on 64*55113Storek * fpu_norm()'s handling of `supernormals'; see fpu_subr.c. 65*55113Storek */ 66*55113Storek fp->fp_exp = FP_LG; 67*55113Storek fp->fp_mant[0] = (int)i < 0 ? -i : i; 68*55113Storek fp->fp_mant[1] = 0; 69*55113Storek fp->fp_mant[2] = 0; 70*55113Storek fp->fp_mant[3] = 0; 71*55113Storek fpu_norm(fp); 72*55113Storek return (FPC_NUM); 73*55113Storek } 74*55113Storek 75*55113Storek #define mask(nbits) ((1 << (nbits)) - 1) 76*55113Storek 77*55113Storek /* 78*55113Storek * All external floating formats convert to internal in the same manner, 79*55113Storek * as defined here. Note that only normals get an implied 1.0 inserted. 80*55113Storek */ 81*55113Storek #define FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \ 82*55113Storek if (exp == 0) { \ 83*55113Storek if (allfrac == 0) \ 84*55113Storek return (FPC_ZERO); \ 85*55113Storek fp->fp_exp = 1 - expbias; \ 86*55113Storek fp->fp_mant[0] = f0; \ 87*55113Storek fp->fp_mant[1] = f1; \ 88*55113Storek fp->fp_mant[2] = f2; \ 89*55113Storek fp->fp_mant[3] = f3; \ 90*55113Storek fpu_norm(fp); \ 91*55113Storek return (FPC_NUM); \ 92*55113Storek } \ 93*55113Storek if (exp == (2 * expbias + 1)) { \ 94*55113Storek if (allfrac == 0) \ 95*55113Storek return (FPC_INF); \ 96*55113Storek fp->fp_mant[0] = f0; \ 97*55113Storek fp->fp_mant[1] = f1; \ 98*55113Storek fp->fp_mant[2] = f2; \ 99*55113Storek fp->fp_mant[3] = f3; \ 100*55113Storek return (FPC_QNAN); \ 101*55113Storek } \ 102*55113Storek fp->fp_exp = exp - expbias; \ 103*55113Storek fp->fp_mant[0] = FP_1 | f0; \ 104*55113Storek fp->fp_mant[1] = f1; \ 105*55113Storek fp->fp_mant[2] = f2; \ 106*55113Storek fp->fp_mant[3] = f3; \ 107*55113Storek return (FPC_NUM) 108*55113Storek 109*55113Storek /* 110*55113Storek * 32-bit single precision -> fpn. 111*55113Storek * We assume a single occupies at most (64-FP_LG) bits in the internal 112*55113Storek * format: i.e., needs at most fp_mant[0] and fp_mant[1]. 113*55113Storek */ 114*55113Storek int 115*55113Storek fpu_stof(fp, i) 116*55113Storek register struct fpn *fp; 117*55113Storek register u_int i; 118*55113Storek { 119*55113Storek register int exp; 120*55113Storek register u_int frac, f0, f1; 121*55113Storek #define SNG_SHIFT (SNG_FRACBITS - FP_LG) 122*55113Storek 123*55113Storek exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS); 124*55113Storek frac = i & mask(SNG_FRACBITS); 125*55113Storek f0 = frac >> SNG_SHIFT; 126*55113Storek f1 = frac << (32 - SNG_SHIFT); 127*55113Storek FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0); 128*55113Storek } 129*55113Storek 130*55113Storek /* 131*55113Storek * 64-bit double -> fpn. 132*55113Storek * We assume this uses at most (96-FP_LG) bits. 133*55113Storek */ 134*55113Storek int 135*55113Storek fpu_dtof(fp, i, j) 136*55113Storek register struct fpn *fp; 137*55113Storek register u_int i, j; 138*55113Storek { 139*55113Storek register int exp; 140*55113Storek register u_int frac, f0, f1, f2; 141*55113Storek #define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG) 142*55113Storek 143*55113Storek exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS); 144*55113Storek frac = i & mask(DBL_FRACBITS - 32); 145*55113Storek f0 = frac >> DBL_SHIFT; 146*55113Storek f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT); 147*55113Storek f2 = j << (32 - DBL_SHIFT); 148*55113Storek frac |= j; 149*55113Storek FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0); 150*55113Storek } 151*55113Storek 152*55113Storek /* 153*55113Storek * 128-bit extended -> fpn. 154*55113Storek */ 155*55113Storek int 156*55113Storek fpu_xtof(fp, i, j, k, l) 157*55113Storek register struct fpn *fp; 158*55113Storek register u_int i, j, k, l; 159*55113Storek { 160*55113Storek register int exp; 161*55113Storek register u_int frac, f0, f1, f2, f3; 162*55113Storek #define EXT_SHIFT (-(EXT_FRACBITS - 3 * 32 - FP_LG)) /* left shift! */ 163*55113Storek 164*55113Storek /* 165*55113Storek * Note that ext and fpn `line up', hence no shifting needed. 166*55113Storek */ 167*55113Storek exp = (i >> (32 - 1 - EXT_EXPBITS)) & mask(EXT_EXPBITS); 168*55113Storek frac = i & mask(EXT_FRACBITS - 3 * 32); 169*55113Storek f0 = (frac << EXT_SHIFT) | (j >> (32 - EXT_SHIFT)); 170*55113Storek f1 = (j << EXT_SHIFT) | (k >> (32 - EXT_SHIFT)); 171*55113Storek f2 = (k << EXT_SHIFT) | (l >> (32 - EXT_SHIFT)); 172*55113Storek f3 = l << EXT_SHIFT; 173*55113Storek frac |= j | k | l; 174*55113Storek FP_TOF(exp, EXT_EXP_BIAS, frac, f0, f1, f2, f3); 175*55113Storek } 176*55113Storek 177*55113Storek /* 178*55113Storek * Explode the contents of a register / regpair / regquad. 179*55113Storek * If the input is a signalling NaN, an NV (invalid) exception 180*55113Storek * will be set. (Note that nothing but NV can occur until ALU 181*55113Storek * operations are performed.) 182*55113Storek */ 183*55113Storek void 184*55113Storek fpu_explode(fe, fp, type, reg) 185*55113Storek register struct fpemu *fe; 186*55113Storek register struct fpn *fp; 187*55113Storek int type, reg; 188*55113Storek { 189*55113Storek register u_int s, *space; 190*55113Storek 191*55113Storek space = &fe->fe_fpstate->fs_regs[reg]; 192*55113Storek s = space[0]; 193*55113Storek fp->fp_sign = s >> 31; 194*55113Storek fp->fp_sticky = 0; 195*55113Storek switch (type) { 196*55113Storek 197*55113Storek case FTYPE_INT: 198*55113Storek s = fpu_itof(fp, s); 199*55113Storek break; 200*55113Storek 201*55113Storek case FTYPE_SNG: 202*55113Storek s = fpu_stof(fp, s); 203*55113Storek break; 204*55113Storek 205*55113Storek case FTYPE_DBL: 206*55113Storek s = fpu_dtof(fp, s, space[1]); 207*55113Storek break; 208*55113Storek 209*55113Storek case FTYPE_EXT: 210*55113Storek s = fpu_xtof(fp, s, space[1], space[2], space[3]); 211*55113Storek break; 212*55113Storek 213*55113Storek default: 214*55113Storek panic("fpu_explode"); 215*55113Storek } 216*55113Storek if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) { 217*55113Storek /* 218*55113Storek * Input is a signalling NaN. All operations that return 219*55113Storek * an input NaN operand put it through a ``NaN conversion'', 220*55113Storek * which basically just means ``turn on the quiet bit''. 221*55113Storek * We do this here so that all NaNs internally look quiet 222*55113Storek * (we can tell signalling ones by their class). 223*55113Storek */ 224*55113Storek fp->fp_mant[0] |= FP_QUIETBIT; 225*55113Storek fe->fe_cx = FSR_NV; /* assert invalid operand */ 226*55113Storek s = FPC_SNAN; 227*55113Storek } 228*55113Storek fp->fp_class = s; 229*55113Storek } 230