1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1987, 2000, 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" /* SunOS-4.1 */ 28 29 /* Unpack procedures for Sparc FPU simulator. */ 30 31 #include <sys/fpu/fpu_simulator.h> 32 #include <sys/fpu/globals.h> 33 34 static void 35 unpackint32( 36 unpacked *pu, /* unpacked result */ 37 int32_t x) /* packed int32_t */ 38 { 39 uint_t ux; 40 41 pu->sticky = pu->rounded = 0; 42 if (x == 0) { 43 pu->sign = 0; 44 pu->fpclass = fp_zero; 45 } else { 46 (*pu).sign = x < 0; 47 (*pu).fpclass = fp_normal; 48 (*pu).exponent = INTEGER_BIAS; 49 if (x < 0) ux = -x; else ux = x; 50 (*pu).significand[0] = ux>>15; 51 (*pu).significand[1] = (ux&0x7fff)<<17; 52 (*pu).significand[2] = 0; 53 (*pu).significand[3] = 0; 54 fpu_normalize(pu); 55 } 56 } 57 58 59 /* 60 * Workaround for bug 4287443--- we have to convince the compiler 61 * that unpackint64 isn't a leaf routine. 62 */ 63 static void 64 subroutine(void) 65 { 66 } 67 68 static void 69 unpackint64( 70 unpacked *pu, /* unpacked result */ 71 int64_t x) /* packed int64_t */ 72 { 73 union { 74 uint64_t ll; 75 uint32_t i[2]; 76 } ux; 77 78 subroutine(); 79 80 pu->sticky = pu->rounded = 0; 81 if (x == 0) { 82 pu->sign = 0; 83 pu->fpclass = fp_zero; 84 } else { 85 (*pu).sign = x < 0; 86 (*pu).fpclass = fp_normal; 87 (*pu).exponent = LONGLONG_BIAS; 88 if (x < 0) ux.ll = -x; else ux.ll = x; 89 (*pu).significand[0] = ux.i[0]>>15; 90 (*pu).significand[1] = (((ux.i[0]&0x7fff)<<17) | (ux.i[1]>>15)); 91 (*pu).significand[2] = (ux.i[1]&0x7fff)<<17; 92 (*pu).significand[3] = 0; 93 fpu_normalize(pu); 94 } 95 } 96 97 void 98 unpacksingle( 99 fp_simd_type *pfpsd, /* simulator data */ 100 unpacked *pu, /* unpacked result */ 101 single_type x) /* packed single */ 102 { 103 uint_t U; 104 105 pu->sticky = pu->rounded = 0; 106 U = x.significand; 107 (*pu).sign = x.sign; 108 pu->significand[1] = 0; 109 pu->significand[2] = 0; 110 pu->significand[3] = 0; 111 if (x.exponent == 0) { /* zero or sub */ 112 if (x.significand == 0) { /* zero */ 113 pu->fpclass = fp_zero; 114 return; 115 } else { /* subnormal */ 116 pu->fpclass = fp_normal; 117 pu->exponent = -SINGLE_BIAS-6; 118 pu->significand[0] = U; 119 fpu_normalize(pu); 120 return; 121 } 122 } else if (x.exponent == 0xff) { /* inf or nan */ 123 if (x.significand == 0) { /* inf */ 124 pu->fpclass = fp_infinity; 125 return; 126 } else { /* nan */ 127 if ((U & 0x400000) != 0) { /* quiet */ 128 pu->fpclass = fp_quiet; 129 } else { /* signaling */ 130 pu->fpclass = fp_signaling; 131 fpu_set_exception(pfpsd, fp_invalid); 132 } 133 pu->significand[0] = 0x18000 | (U >> 7); 134 (*pu).significand[1] = ((U&0x7f)<<25); 135 return; 136 } 137 } 138 (*pu).exponent = x.exponent - SINGLE_BIAS; 139 (*pu).fpclass = fp_normal; 140 (*pu).significand[0] = 0x10000|(U>>7); 141 (*pu).significand[1] = ((U&0x7f)<<25); 142 } 143 144 void 145 unpackdouble( 146 fp_simd_type *pfpsd, /* simulator data */ 147 unpacked *pu, /* unpacked result */ 148 double_type x, /* packed double, sign/exponent/upper 20 bits */ 149 uint_t y) /* and the lower 32 bits of the significand */ 150 { 151 uint_t U; 152 153 pu->sticky = pu->rounded = 0; 154 U = x.significand; 155 (*pu).sign = x.sign; 156 pu->significand[1] = y; 157 pu->significand[2] = 0; 158 pu->significand[3] = 0; 159 if (x.exponent == 0) { /* zero or sub */ 160 if ((x.significand == 0) && (y == 0)) { /* zero */ 161 pu->fpclass = fp_zero; 162 return; 163 } else { /* subnormal */ 164 pu->fpclass = fp_normal; 165 pu->exponent = -DOUBLE_BIAS-3; 166 pu->significand[0] = U; 167 fpu_normalize(pu); 168 return; 169 } 170 } else if (x.exponent == 0x7ff) { /* inf or nan */ 171 if ((U|y) == 0) { /* inf */ 172 pu->fpclass = fp_infinity; 173 return; 174 } else { /* nan */ 175 if ((U & 0x80000) != 0) { /* quiet */ 176 pu->fpclass = fp_quiet; 177 } else { /* signaling */ 178 pu->fpclass = fp_signaling; 179 fpu_set_exception(pfpsd, fp_invalid); 180 } 181 pu->significand[0] = 0x18000 | (U >> 4); 182 (*pu).significand[1] = ((U&0xf)<<28)|(y>>4); 183 (*pu).significand[2] = ((y&0xf)<<28); 184 return; 185 } 186 } 187 (*pu).exponent = x.exponent - DOUBLE_BIAS; 188 (*pu).fpclass = fp_normal; 189 (*pu).significand[0] = 0x10000|(U>>4); 190 (*pu).significand[1] = ((U&0xf)<<28)|(y>>4); 191 (*pu).significand[2] = ((y&0xf)<<28); 192 } 193 194 static void 195 unpackextended( 196 fp_simd_type *pfpsd, /* simulator data */ 197 unpacked *pu, /* unpacked result */ 198 extended_type x, /* packed extended, sign/exponent/16 bits */ 199 uint32_t y, /* 2nd word of extended significand */ 200 uint32_t z, /* 3rd word of extended significand */ 201 uint32_t w) /* 4th word of extended significand */ 202 { 203 uint_t U; 204 205 pu->sticky = pu->rounded = 0; 206 U = x.significand; 207 (*pu).sign = x.sign; 208 (*pu).fpclass = fp_normal; 209 (*pu).exponent = x.exponent - EXTENDED_BIAS; 210 (*pu).significand[0] = (x.exponent == 0) ? U : 0x10000|U; 211 (*pu).significand[1] = y; 212 (*pu).significand[2] = z; 213 (*pu).significand[3] = w; 214 if (x.exponent < 0x7fff) { /* zero, normal, or subnormal */ 215 if ((z|y|w|pu->significand[0]) == 0) { /* zero */ 216 pu->fpclass = fp_zero; 217 return; 218 } else { /* normal or subnormal */ 219 if (x.exponent == 0) { 220 fpu_normalize(pu); 221 pu->exponent += 1; 222 } 223 return; 224 } 225 } else { /* inf or nan */ 226 if ((U|z|y|w) == 0) { /* inf */ 227 pu->fpclass = fp_infinity; 228 return; 229 } else { /* nan */ 230 if ((U & 0x00008000) != 0) { /* quiet */ 231 pu->fpclass = fp_quiet; 232 } else { /* signaling */ 233 pu->fpclass = fp_signaling; 234 fpu_set_exception(pfpsd, fp_invalid); 235 } 236 pu->significand[0] |= 0x8000; /* make quiet */ 237 return; 238 } 239 } 240 } 241 242 void 243 _fp_unpack( 244 fp_simd_type *pfpsd, /* simulator data */ 245 unpacked *pu, /* unpacked result */ 246 uint_t n, /* register where data starts */ 247 enum fp_op_type dtype) /* type of datum */ 248 { 249 freg_type f; 250 union { 251 uint32_t y[4]; 252 uint64_t ll[2]; 253 freg_type f; 254 } fp; 255 256 switch (dtype) { 257 case fp_op_int32: 258 pfpsd->fp_current_read_freg(&f, n, pfpsd); 259 unpackint32(pu, f.int32_reg); 260 break; 261 case fp_op_int64: 262 263 if ((n & 0x1) == 1) /* fix register encoding */ 264 n = (n & 0x1e) | 0x20; 265 pfpsd->fp_current_read_dreg(&fp.ll[0], DOUBLE(n), pfpsd); 266 unpackint64(pu, fp.f.int64_reg); 267 break; 268 case fp_op_single: 269 pfpsd->fp_current_read_freg(&f, n, pfpsd); 270 unpacksingle(pfpsd, pu, f.single_reg); 271 break; 272 case fp_op_double: 273 if ((n & 0x1) == 1) /* fix register encoding */ 274 n = (n & 0x1e) | 0x20; 275 pfpsd->fp_current_read_dreg(&fp.ll[0], DOUBLE(n), pfpsd); 276 unpackdouble(pfpsd, pu, fp.f.double_reg, fp.y[1]); 277 break; 278 case fp_op_extended: 279 if ((n & 0x1) == 1) /* fix register encoding */ 280 n = (n & 0x1e) | 0x20; 281 pfpsd->fp_current_read_dreg(&fp.ll[0], QUAD_E(n), pfpsd); 282 pfpsd->fp_current_read_dreg(&fp.ll[1], QUAD_F(n), pfpsd); 283 unpackextended(pfpsd, pu, fp.f.extended_reg, fp.y[1], 284 fp.y[2], fp.y[3]); 285 break; 286 } 287 } 288 289 void 290 _fp_unpack_word( 291 fp_simd_type *pfpsd, /* simulator data */ 292 uint32_t *pu, /* unpacked result */ 293 uint_t n) /* register where data starts */ 294 { 295 pfpsd->fp_current_read_freg(pu, n, pfpsd); 296 } 297 298 void 299 _fp_unpack_extword( 300 fp_simd_type *pfpsd, /* simulator data */ 301 uint64_t *pu, /* unpacked result */ 302 uint_t n) /* register where data starts */ 303 { 304 if ((n & 0x1) == 1) /* fix register encoding */ 305 n = (n & 0x1e) | 0x20; 306 pfpsd->fp_current_read_dreg(pu, DOUBLE(n), pfpsd); 307 } 308