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