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