1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1988,1995-1996,2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* Pack procedures for Sparc FPU simulator. */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #include <sys/fpu/fpu_simulator.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/fpu/globals.h> 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate /* 35*7c478bd9Sstevel@tonic-gate * Returns 1 if overflow should go to infinity, 0 if to max finite. 36*7c478bd9Sstevel@tonic-gate */ 37*7c478bd9Sstevel@tonic-gate static int 38*7c478bd9Sstevel@tonic-gate overflow_to_infinity( 39*7c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd, /* Pointer to simulator data */ 40*7c478bd9Sstevel@tonic-gate int sign) /* negative or positive */ 41*7c478bd9Sstevel@tonic-gate { 42*7c478bd9Sstevel@tonic-gate int inf; 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate switch (pfpsd->fp_direction) { 45*7c478bd9Sstevel@tonic-gate case fp_nearest: 46*7c478bd9Sstevel@tonic-gate inf = 1; 47*7c478bd9Sstevel@tonic-gate break; 48*7c478bd9Sstevel@tonic-gate case fp_tozero: 49*7c478bd9Sstevel@tonic-gate inf = 0; 50*7c478bd9Sstevel@tonic-gate break; 51*7c478bd9Sstevel@tonic-gate case fp_positive: 52*7c478bd9Sstevel@tonic-gate inf = !sign; 53*7c478bd9Sstevel@tonic-gate break; 54*7c478bd9Sstevel@tonic-gate case fp_negative: 55*7c478bd9Sstevel@tonic-gate inf = sign; 56*7c478bd9Sstevel@tonic-gate break; 57*7c478bd9Sstevel@tonic-gate } 58*7c478bd9Sstevel@tonic-gate return (inf); 59*7c478bd9Sstevel@tonic-gate } 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate /* 62*7c478bd9Sstevel@tonic-gate * Round according to current rounding mode. 63*7c478bd9Sstevel@tonic-gate */ 64*7c478bd9Sstevel@tonic-gate static void 65*7c478bd9Sstevel@tonic-gate round( 66*7c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd, /* Pointer to simulator data */ 67*7c478bd9Sstevel@tonic-gate unpacked *pu) /* unpacked result */ 68*7c478bd9Sstevel@tonic-gate { 69*7c478bd9Sstevel@tonic-gate int increment; /* boolean to indicate round up */ 70*7c478bd9Sstevel@tonic-gate int sr; 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate sr = pu->sticky|pu->rounded; 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate if (sr == 0) 75*7c478bd9Sstevel@tonic-gate return; 76*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_inexact); 77*7c478bd9Sstevel@tonic-gate switch (pfpsd->fp_direction) { 78*7c478bd9Sstevel@tonic-gate case fp_nearest: 79*7c478bd9Sstevel@tonic-gate increment = pu->rounded; 80*7c478bd9Sstevel@tonic-gate break; 81*7c478bd9Sstevel@tonic-gate case fp_tozero: 82*7c478bd9Sstevel@tonic-gate increment = 0; 83*7c478bd9Sstevel@tonic-gate break; 84*7c478bd9Sstevel@tonic-gate case fp_positive: 85*7c478bd9Sstevel@tonic-gate increment = (pu->sign == 0) & (sr != 0); 86*7c478bd9Sstevel@tonic-gate break; 87*7c478bd9Sstevel@tonic-gate case fp_negative: 88*7c478bd9Sstevel@tonic-gate increment = (pu->sign != 0) & (sr != 0); 89*7c478bd9Sstevel@tonic-gate break; 90*7c478bd9Sstevel@tonic-gate } 91*7c478bd9Sstevel@tonic-gate if (increment) { 92*7c478bd9Sstevel@tonic-gate pu->significand[3]++; 93*7c478bd9Sstevel@tonic-gate if (pu->significand[3] == 0) { 94*7c478bd9Sstevel@tonic-gate pu->significand[2]++; 95*7c478bd9Sstevel@tonic-gate if (pu->significand[2] == 0) { 96*7c478bd9Sstevel@tonic-gate pu->significand[1]++; 97*7c478bd9Sstevel@tonic-gate if (pu->significand[1] == 0) { 98*7c478bd9Sstevel@tonic-gate pu->significand[0]++; /* rounding carried out */ 99*7c478bd9Sstevel@tonic-gate if (pu->significand[0] == 0x20000) { 100*7c478bd9Sstevel@tonic-gate pu->exponent++; 101*7c478bd9Sstevel@tonic-gate pu->significand[0] = 0x10000; 102*7c478bd9Sstevel@tonic-gate } 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate } 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate if ((pfpsd->fp_direction == fp_nearest) && 108*7c478bd9Sstevel@tonic-gate (pu->sticky == 0) && increment != 0) { /* ambiguous case */ 109*7c478bd9Sstevel@tonic-gate pu->significand[3] &= 0xfffffffe; /* force round to even */ 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate static void 114*7c478bd9Sstevel@tonic-gate packint32( 115*7c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd, /* Pointer to simulator data */ 116*7c478bd9Sstevel@tonic-gate unpacked *pu, /* unpacked result */ 117*7c478bd9Sstevel@tonic-gate int32_t *px) /* packed int32_t */ 118*7c478bd9Sstevel@tonic-gate { 119*7c478bd9Sstevel@tonic-gate switch (pu->fpclass) { 120*7c478bd9Sstevel@tonic-gate case fp_zero: 121*7c478bd9Sstevel@tonic-gate *px = 0; 122*7c478bd9Sstevel@tonic-gate break; 123*7c478bd9Sstevel@tonic-gate case fp_normal: 124*7c478bd9Sstevel@tonic-gate if (pu->exponent >= 32) 125*7c478bd9Sstevel@tonic-gate goto overflow; 126*7c478bd9Sstevel@tonic-gate fpu_rightshift(pu, 112 - pu->exponent); 127*7c478bd9Sstevel@tonic-gate round(pfpsd, pu); 128*7c478bd9Sstevel@tonic-gate if (pu->significand[3] >= 0x80000000) 129*7c478bd9Sstevel@tonic-gate if ((pu->sign == 0)||(pu->significand[3] > 0x80000000)) 130*7c478bd9Sstevel@tonic-gate goto overflow; 131*7c478bd9Sstevel@tonic-gate *px = pu->significand[3]; 132*7c478bd9Sstevel@tonic-gate if (pu->sign) 133*7c478bd9Sstevel@tonic-gate *px = -*px; 134*7c478bd9Sstevel@tonic-gate break; 135*7c478bd9Sstevel@tonic-gate case fp_infinity: 136*7c478bd9Sstevel@tonic-gate case fp_quiet: 137*7c478bd9Sstevel@tonic-gate case fp_signaling: 138*7c478bd9Sstevel@tonic-gate overflow: 139*7c478bd9Sstevel@tonic-gate if (pu->sign) 140*7c478bd9Sstevel@tonic-gate *px = 0x80000000; 141*7c478bd9Sstevel@tonic-gate else 142*7c478bd9Sstevel@tonic-gate *px = 0x7fffffff; 143*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_exceptions &= ~(1 << (int)fp_inexact); 144*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_invalid); 145*7c478bd9Sstevel@tonic-gate break; 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate static void 150*7c478bd9Sstevel@tonic-gate packint64( 151*7c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd, /* Pointer to simulator data */ 152*7c478bd9Sstevel@tonic-gate unpacked *pu, /* unpacked result */ 153*7c478bd9Sstevel@tonic-gate int64_t *px) /* packed int64_t */ 154*7c478bd9Sstevel@tonic-gate { 155*7c478bd9Sstevel@tonic-gate union { 156*7c478bd9Sstevel@tonic-gate uint64_t ll; 157*7c478bd9Sstevel@tonic-gate uint32_t i[2]; 158*7c478bd9Sstevel@tonic-gate } x; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate switch (pu->fpclass) { 161*7c478bd9Sstevel@tonic-gate case fp_zero: 162*7c478bd9Sstevel@tonic-gate *px = 0; 163*7c478bd9Sstevel@tonic-gate break; 164*7c478bd9Sstevel@tonic-gate case fp_normal: 165*7c478bd9Sstevel@tonic-gate if (pu->exponent >= 64) 166*7c478bd9Sstevel@tonic-gate goto overflow; 167*7c478bd9Sstevel@tonic-gate fpu_rightshift(pu, 112 - pu->exponent); 168*7c478bd9Sstevel@tonic-gate round(pfpsd, pu); 169*7c478bd9Sstevel@tonic-gate if (pu->significand[2] >= 0x80000000) 170*7c478bd9Sstevel@tonic-gate if ((pu->sign == 0) || 171*7c478bd9Sstevel@tonic-gate (pu->significand[2] > 0x80000000) || 172*7c478bd9Sstevel@tonic-gate (((pu->significand[2] == 0x80000000) && 173*7c478bd9Sstevel@tonic-gate (pu->significand[3] > 0)))) 174*7c478bd9Sstevel@tonic-gate goto overflow; 175*7c478bd9Sstevel@tonic-gate x.i[0] = pu->significand[2]; 176*7c478bd9Sstevel@tonic-gate x.i[1] = pu->significand[3]; 177*7c478bd9Sstevel@tonic-gate *px = x.ll; 178*7c478bd9Sstevel@tonic-gate if (pu->sign) 179*7c478bd9Sstevel@tonic-gate *px = -*px; 180*7c478bd9Sstevel@tonic-gate break; 181*7c478bd9Sstevel@tonic-gate case fp_infinity: 182*7c478bd9Sstevel@tonic-gate case fp_quiet: 183*7c478bd9Sstevel@tonic-gate case fp_signaling: 184*7c478bd9Sstevel@tonic-gate overflow: 185*7c478bd9Sstevel@tonic-gate if (pu->sign) 186*7c478bd9Sstevel@tonic-gate *px = (int64_t)0x8000000000000000; 187*7c478bd9Sstevel@tonic-gate else 188*7c478bd9Sstevel@tonic-gate *px = (int64_t)0x7fffffffffffffff; 189*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_exceptions &= ~(1 << (int)fp_inexact); 190*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_invalid); 191*7c478bd9Sstevel@tonic-gate break; 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate static void 196*7c478bd9Sstevel@tonic-gate packsingle( 197*7c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd, /* Pointer to simulator data */ 198*7c478bd9Sstevel@tonic-gate unpacked *pu, /* unpacked result */ 199*7c478bd9Sstevel@tonic-gate single_type *px) /* packed single */ 200*7c478bd9Sstevel@tonic-gate { 201*7c478bd9Sstevel@tonic-gate px->sign = pu->sign; 202*7c478bd9Sstevel@tonic-gate switch (pu->fpclass) { 203*7c478bd9Sstevel@tonic-gate case fp_zero: 204*7c478bd9Sstevel@tonic-gate px->exponent = 0; 205*7c478bd9Sstevel@tonic-gate px->significand = 0; 206*7c478bd9Sstevel@tonic-gate break; 207*7c478bd9Sstevel@tonic-gate case fp_infinity: 208*7c478bd9Sstevel@tonic-gate infinity: 209*7c478bd9Sstevel@tonic-gate px->exponent = 0xff; 210*7c478bd9Sstevel@tonic-gate px->significand = 0; 211*7c478bd9Sstevel@tonic-gate break; 212*7c478bd9Sstevel@tonic-gate case fp_quiet: 213*7c478bd9Sstevel@tonic-gate case fp_signaling: 214*7c478bd9Sstevel@tonic-gate fpu_rightshift(pu, 113-24); 215*7c478bd9Sstevel@tonic-gate px->exponent = 0xff; 216*7c478bd9Sstevel@tonic-gate px->significand = 0x400000|(0x3fffff&pu->significand[3]); 217*7c478bd9Sstevel@tonic-gate break; 218*7c478bd9Sstevel@tonic-gate case fp_normal: 219*7c478bd9Sstevel@tonic-gate fpu_rightshift(pu, 113-24); 220*7c478bd9Sstevel@tonic-gate pu->exponent += SINGLE_BIAS; 221*7c478bd9Sstevel@tonic-gate if (pu->exponent <= 0) { 222*7c478bd9Sstevel@tonic-gate px->exponent = 0; 223*7c478bd9Sstevel@tonic-gate fpu_rightshift(pu, 1 - pu->exponent); 224*7c478bd9Sstevel@tonic-gate round(pfpsd, pu); 225*7c478bd9Sstevel@tonic-gate if (pu->significand[3] == 0x800000) { 226*7c478bd9Sstevel@tonic-gate /* 227*7c478bd9Sstevel@tonic-gate * rounded 228*7c478bd9Sstevel@tonic-gate * back up to 229*7c478bd9Sstevel@tonic-gate * normal 230*7c478bd9Sstevel@tonic-gate */ 231*7c478bd9Sstevel@tonic-gate px->exponent = 1; 232*7c478bd9Sstevel@tonic-gate px->significand = 0; 233*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_inexact); 234*7c478bd9Sstevel@tonic-gate } else 235*7c478bd9Sstevel@tonic-gate px->significand = 0x7fffff & pu->significand[3]; 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate if (pfpsd->fp_current_exceptions & (1 << fp_inexact)) 238*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_underflow); 239*7c478bd9Sstevel@tonic-gate if (pfpsd->fp_fsrtem & (1<<fp_underflow)) { 240*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_underflow); 241*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_exceptions &= 242*7c478bd9Sstevel@tonic-gate ~(1 << (int)fp_inexact); 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate return; 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate round(pfpsd, pu); 247*7c478bd9Sstevel@tonic-gate if (pu->significand[3] == 0x1000000) { /* rounding overflow */ 248*7c478bd9Sstevel@tonic-gate pu->significand[3] = 0x800000; 249*7c478bd9Sstevel@tonic-gate pu->exponent += 1; 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate if (pu->exponent >= 0xff) { 252*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_overflow); 253*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_inexact); 254*7c478bd9Sstevel@tonic-gate if (pfpsd->fp_fsrtem & (1<<fp_overflow)) { 255*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_exceptions &= 256*7c478bd9Sstevel@tonic-gate ~(1 << (int)fp_inexact); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate if (overflow_to_infinity(pfpsd, pu->sign)) 259*7c478bd9Sstevel@tonic-gate goto infinity; 260*7c478bd9Sstevel@tonic-gate px->exponent = 0xfe; 261*7c478bd9Sstevel@tonic-gate px->significand = 0x7fffff; 262*7c478bd9Sstevel@tonic-gate return; 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate px->exponent = pu->exponent; 265*7c478bd9Sstevel@tonic-gate px->significand = 0x7fffff & pu->significand[3]; 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate static void 270*7c478bd9Sstevel@tonic-gate packdouble( 271*7c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd, /* Pointer to simulator data */ 272*7c478bd9Sstevel@tonic-gate unpacked *pu, /* unpacked result */ 273*7c478bd9Sstevel@tonic-gate double_type *px, /* packed double, sign/exponent/upper 20 bits */ 274*7c478bd9Sstevel@tonic-gate uint_t *py) /* and the lower 32 bits of the significand */ 275*7c478bd9Sstevel@tonic-gate { 276*7c478bd9Sstevel@tonic-gate px->sign = pu->sign; 277*7c478bd9Sstevel@tonic-gate switch (pu->fpclass) { 278*7c478bd9Sstevel@tonic-gate case fp_zero: 279*7c478bd9Sstevel@tonic-gate px->exponent = 0; 280*7c478bd9Sstevel@tonic-gate px->significand = 0; 281*7c478bd9Sstevel@tonic-gate *py = 0; 282*7c478bd9Sstevel@tonic-gate break; 283*7c478bd9Sstevel@tonic-gate case fp_infinity: 284*7c478bd9Sstevel@tonic-gate infinity: 285*7c478bd9Sstevel@tonic-gate px->exponent = 0x7ff; 286*7c478bd9Sstevel@tonic-gate px->significand = 0; 287*7c478bd9Sstevel@tonic-gate *py = 0; 288*7c478bd9Sstevel@tonic-gate break; 289*7c478bd9Sstevel@tonic-gate case fp_quiet: 290*7c478bd9Sstevel@tonic-gate case fp_signaling: 291*7c478bd9Sstevel@tonic-gate fpu_rightshift(pu, 113-53); 292*7c478bd9Sstevel@tonic-gate px->exponent = 0x7ff; 293*7c478bd9Sstevel@tonic-gate px->significand = 0x80000 | (0x7ffff & pu->significand[2]); 294*7c478bd9Sstevel@tonic-gate *py = pu->significand[3]; 295*7c478bd9Sstevel@tonic-gate break; 296*7c478bd9Sstevel@tonic-gate case fp_normal: 297*7c478bd9Sstevel@tonic-gate fpu_rightshift(pu, 113-53); 298*7c478bd9Sstevel@tonic-gate pu->exponent += DOUBLE_BIAS; 299*7c478bd9Sstevel@tonic-gate if (pu->exponent <= 0) { /* underflow */ 300*7c478bd9Sstevel@tonic-gate px->exponent = 0; 301*7c478bd9Sstevel@tonic-gate fpu_rightshift(pu, 1 - pu->exponent); 302*7c478bd9Sstevel@tonic-gate round(pfpsd, pu); 303*7c478bd9Sstevel@tonic-gate if (pu->significand[2] == 0x100000) { 304*7c478bd9Sstevel@tonic-gate /* 305*7c478bd9Sstevel@tonic-gate * rounded 306*7c478bd9Sstevel@tonic-gate * back up to 307*7c478bd9Sstevel@tonic-gate * normal 308*7c478bd9Sstevel@tonic-gate */ 309*7c478bd9Sstevel@tonic-gate px->exponent = 1; 310*7c478bd9Sstevel@tonic-gate px->significand = 0; 311*7c478bd9Sstevel@tonic-gate *py = 0; 312*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_inexact); 313*7c478bd9Sstevel@tonic-gate } else { 314*7c478bd9Sstevel@tonic-gate px->exponent = 0; 315*7c478bd9Sstevel@tonic-gate px->significand = 0xfffff & pu->significand[2]; 316*7c478bd9Sstevel@tonic-gate *py = pu->significand[3]; 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate if (pfpsd->fp_current_exceptions & (1 << fp_inexact)) 319*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_underflow); 320*7c478bd9Sstevel@tonic-gate if (pfpsd->fp_fsrtem & (1<<fp_underflow)) { 321*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_underflow); 322*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_exceptions &= 323*7c478bd9Sstevel@tonic-gate ~(1 << (int)fp_inexact); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate return; 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate round(pfpsd, pu); 328*7c478bd9Sstevel@tonic-gate if (pu->significand[2] == 0x200000) { /* rounding overflow */ 329*7c478bd9Sstevel@tonic-gate pu->significand[2] = 0x100000; 330*7c478bd9Sstevel@tonic-gate pu->exponent += 1; 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate if (pu->exponent >= 0x7ff) { /* overflow */ 333*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_overflow); 334*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_inexact); 335*7c478bd9Sstevel@tonic-gate if (pfpsd->fp_fsrtem & (1<<fp_overflow)) { 336*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_exceptions &= 337*7c478bd9Sstevel@tonic-gate ~(1 << (int)fp_inexact); 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate if (overflow_to_infinity(pfpsd, pu->sign)) 340*7c478bd9Sstevel@tonic-gate goto infinity; 341*7c478bd9Sstevel@tonic-gate px->exponent = 0x7fe; 342*7c478bd9Sstevel@tonic-gate px->significand = 0xfffff; 343*7c478bd9Sstevel@tonic-gate *py = 0xffffffffU; 344*7c478bd9Sstevel@tonic-gate return; 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate px->exponent = pu->exponent; 347*7c478bd9Sstevel@tonic-gate px->significand = 0xfffff & pu->significand[2]; 348*7c478bd9Sstevel@tonic-gate *py = pu->significand[3]; 349*7c478bd9Sstevel@tonic-gate break; 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate static void 354*7c478bd9Sstevel@tonic-gate packextended( 355*7c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd, /* Pointer to simulator data */ 356*7c478bd9Sstevel@tonic-gate unpacked *pu, /* unpacked result */ 357*7c478bd9Sstevel@tonic-gate extended_type *px, /* packed extended, sign/exponent/16 bits */ 358*7c478bd9Sstevel@tonic-gate uint_t *py, /* 2nd word of extended significand */ 359*7c478bd9Sstevel@tonic-gate uint_t *pz, /* 3rd word of extended significand */ 360*7c478bd9Sstevel@tonic-gate uint_t *pw) /* 4th word of extended significand */ 361*7c478bd9Sstevel@tonic-gate { 362*7c478bd9Sstevel@tonic-gate px->sign = pu->sign; 363*7c478bd9Sstevel@tonic-gate switch (pu->fpclass) { 364*7c478bd9Sstevel@tonic-gate case fp_zero: 365*7c478bd9Sstevel@tonic-gate px->exponent = 0; 366*7c478bd9Sstevel@tonic-gate px->significand = 0; 367*7c478bd9Sstevel@tonic-gate *pz = 0; 368*7c478bd9Sstevel@tonic-gate *py = 0; 369*7c478bd9Sstevel@tonic-gate *pw = 0; 370*7c478bd9Sstevel@tonic-gate break; 371*7c478bd9Sstevel@tonic-gate case fp_infinity: 372*7c478bd9Sstevel@tonic-gate infinity: 373*7c478bd9Sstevel@tonic-gate px->exponent = 0x7fff; 374*7c478bd9Sstevel@tonic-gate px->significand = 0; 375*7c478bd9Sstevel@tonic-gate *pz = 0; 376*7c478bd9Sstevel@tonic-gate *py = 0; 377*7c478bd9Sstevel@tonic-gate *pw = 0; 378*7c478bd9Sstevel@tonic-gate break; 379*7c478bd9Sstevel@tonic-gate case fp_quiet: 380*7c478bd9Sstevel@tonic-gate case fp_signaling: 381*7c478bd9Sstevel@tonic-gate px->exponent = 0x7fff; 382*7c478bd9Sstevel@tonic-gate px->significand = 0x8000 | pu->significand[0]; 383*7c478bd9Sstevel@tonic-gate /* 384*7c478bd9Sstevel@tonic-gate * Insure quiet 385*7c478bd9Sstevel@tonic-gate * nan. 386*7c478bd9Sstevel@tonic-gate */ 387*7c478bd9Sstevel@tonic-gate *py = pu->significand[1]; 388*7c478bd9Sstevel@tonic-gate *pz = pu->significand[2]; 389*7c478bd9Sstevel@tonic-gate *pw = pu->significand[3]; 390*7c478bd9Sstevel@tonic-gate break; 391*7c478bd9Sstevel@tonic-gate case fp_normal: 392*7c478bd9Sstevel@tonic-gate pu->exponent += EXTENDED_BIAS; 393*7c478bd9Sstevel@tonic-gate if (pu->exponent <= 0) { /* underflow */ 394*7c478bd9Sstevel@tonic-gate fpu_rightshift(pu, 1-pu->exponent); 395*7c478bd9Sstevel@tonic-gate round(pfpsd, pu); 396*7c478bd9Sstevel@tonic-gate if (pu->significand[0] < 0x00010000) { 397*7c478bd9Sstevel@tonic-gate /* 398*7c478bd9Sstevel@tonic-gate * not rounded 399*7c478bd9Sstevel@tonic-gate * back up 400*7c478bd9Sstevel@tonic-gate * to normal 401*7c478bd9Sstevel@tonic-gate */ 402*7c478bd9Sstevel@tonic-gate px->exponent = 0; 403*7c478bd9Sstevel@tonic-gate } else { 404*7c478bd9Sstevel@tonic-gate px->exponent = 1; 405*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_inexact); 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate if (pfpsd->fp_current_exceptions & (1 << fp_inexact)) 408*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_underflow); 409*7c478bd9Sstevel@tonic-gate if (pfpsd->fp_fsrtem & (1<<fp_underflow)) { 410*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_underflow); 411*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_exceptions &= 412*7c478bd9Sstevel@tonic-gate ~(1 << (int)fp_inexact); 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate px->significand = pu->significand[0]; 415*7c478bd9Sstevel@tonic-gate *py = pu->significand[1]; 416*7c478bd9Sstevel@tonic-gate *pz = pu->significand[2]; 417*7c478bd9Sstevel@tonic-gate *pw = pu->significand[3]; 418*7c478bd9Sstevel@tonic-gate return; 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate round(pfpsd, pu); /* rounding overflow handled in round() */ 421*7c478bd9Sstevel@tonic-gate if (pu->exponent >= 0x7fff) { /* overflow */ 422*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_overflow); 423*7c478bd9Sstevel@tonic-gate fpu_set_exception(pfpsd, fp_inexact); 424*7c478bd9Sstevel@tonic-gate if (pfpsd->fp_fsrtem & (1<<fp_overflow)) { 425*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_exceptions &= 426*7c478bd9Sstevel@tonic-gate ~(1 << (int)fp_inexact); 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate if (overflow_to_infinity(pfpsd, pu->sign)) 429*7c478bd9Sstevel@tonic-gate goto infinity; 430*7c478bd9Sstevel@tonic-gate px->exponent = 0x7ffe; /* overflow to max norm */ 431*7c478bd9Sstevel@tonic-gate px->significand = 0xffff; 432*7c478bd9Sstevel@tonic-gate *py = 0xffffffffU; 433*7c478bd9Sstevel@tonic-gate *pz = 0xffffffffU; 434*7c478bd9Sstevel@tonic-gate *pw = 0xffffffffU; 435*7c478bd9Sstevel@tonic-gate return; 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate px->exponent = pu->exponent; 438*7c478bd9Sstevel@tonic-gate px->significand = pu->significand[0]; 439*7c478bd9Sstevel@tonic-gate *py = pu->significand[1]; 440*7c478bd9Sstevel@tonic-gate *pz = pu->significand[2]; 441*7c478bd9Sstevel@tonic-gate *pw = pu->significand[3]; 442*7c478bd9Sstevel@tonic-gate break; 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate void 447*7c478bd9Sstevel@tonic-gate _fp_pack( 448*7c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd, /* Pointer to simulator data */ 449*7c478bd9Sstevel@tonic-gate unpacked *pu, /* unpacked operand */ 450*7c478bd9Sstevel@tonic-gate uint_t n, /* register where datum starts */ 451*7c478bd9Sstevel@tonic-gate enum fp_op_type type) /* type of datum */ 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate { 454*7c478bd9Sstevel@tonic-gate switch (type) { 455*7c478bd9Sstevel@tonic-gate case fp_op_int32: 456*7c478bd9Sstevel@tonic-gate { 457*7c478bd9Sstevel@tonic-gate int32_t x; 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate packint32(pfpsd, pu, &x); 460*7c478bd9Sstevel@tonic-gate if (!(pfpsd->fp_current_exceptions & pfpsd->fp_fsrtem)) 461*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_write_freg(&x, n, pfpsd); 462*7c478bd9Sstevel@tonic-gate break; 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate case fp_op_int64: 465*7c478bd9Sstevel@tonic-gate { 466*7c478bd9Sstevel@tonic-gate int64_t x; 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate packint64(pfpsd, pu, &x); 469*7c478bd9Sstevel@tonic-gate if ((n & 0x1) == 1) /* fix register encoding */ 470*7c478bd9Sstevel@tonic-gate n = (n & 0x1e) | 0x20; 471*7c478bd9Sstevel@tonic-gate if (!(pfpsd->fp_current_exceptions & pfpsd->fp_fsrtem)) 472*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_write_dreg(&x, DOUBLE(n), pfpsd); 473*7c478bd9Sstevel@tonic-gate break; 474*7c478bd9Sstevel@tonic-gate } 475*7c478bd9Sstevel@tonic-gate case fp_op_single: 476*7c478bd9Sstevel@tonic-gate { 477*7c478bd9Sstevel@tonic-gate single_type x; 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate packsingle(pfpsd, pu, &x); 480*7c478bd9Sstevel@tonic-gate if (!(pfpsd->fp_current_exceptions & pfpsd->fp_fsrtem)) 481*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_write_freg(&x, n, pfpsd); 482*7c478bd9Sstevel@tonic-gate break; 483*7c478bd9Sstevel@tonic-gate } 484*7c478bd9Sstevel@tonic-gate case fp_op_double: 485*7c478bd9Sstevel@tonic-gate { 486*7c478bd9Sstevel@tonic-gate union { 487*7c478bd9Sstevel@tonic-gate double_type x[2]; 488*7c478bd9Sstevel@tonic-gate uint32_t y[2]; 489*7c478bd9Sstevel@tonic-gate uint64_t ll; 490*7c478bd9Sstevel@tonic-gate } db; 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate packdouble(pfpsd, pu, &db.x[0], &db.y[1]); 493*7c478bd9Sstevel@tonic-gate if (!(pfpsd->fp_current_exceptions & 494*7c478bd9Sstevel@tonic-gate pfpsd->fp_fsrtem)) { 495*7c478bd9Sstevel@tonic-gate if ((n & 0x1) == 1) /* fix register encoding */ 496*7c478bd9Sstevel@tonic-gate n = (n & 0x1e) | 0x20; 497*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_write_dreg(&db.ll, DOUBLE(n), 498*7c478bd9Sstevel@tonic-gate pfpsd); 499*7c478bd9Sstevel@tonic-gate } 500*7c478bd9Sstevel@tonic-gate break; 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate case fp_op_extended: 503*7c478bd9Sstevel@tonic-gate { 504*7c478bd9Sstevel@tonic-gate union { 505*7c478bd9Sstevel@tonic-gate extended_type x; 506*7c478bd9Sstevel@tonic-gate uint32_t y[4]; 507*7c478bd9Sstevel@tonic-gate uint64_t ll[2]; 508*7c478bd9Sstevel@tonic-gate } ex; 509*7c478bd9Sstevel@tonic-gate unpacked U; 510*7c478bd9Sstevel@tonic-gate int k; 511*7c478bd9Sstevel@tonic-gate switch (pfpsd->fp_precision) { 512*7c478bd9Sstevel@tonic-gate /* 513*7c478bd9Sstevel@tonic-gate * Implement extended 514*7c478bd9Sstevel@tonic-gate * rounding precision 515*7c478bd9Sstevel@tonic-gate * mode. 516*7c478bd9Sstevel@tonic-gate */ 517*7c478bd9Sstevel@tonic-gate case fp_single: 518*7c478bd9Sstevel@tonic-gate { 519*7c478bd9Sstevel@tonic-gate single_type tx; 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate packsingle(pfpsd, pu, &tx); 522*7c478bd9Sstevel@tonic-gate pu = &U; 523*7c478bd9Sstevel@tonic-gate unpacksingle(pfpsd, pu, tx); 524*7c478bd9Sstevel@tonic-gate break; 525*7c478bd9Sstevel@tonic-gate } 526*7c478bd9Sstevel@tonic-gate case fp_double: 527*7c478bd9Sstevel@tonic-gate { 528*7c478bd9Sstevel@tonic-gate double_type tx; 529*7c478bd9Sstevel@tonic-gate uint_t ty; 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate packdouble(pfpsd, pu, &tx, &ty); 532*7c478bd9Sstevel@tonic-gate pu = &U; 533*7c478bd9Sstevel@tonic-gate unpackdouble(pfpsd, pu, tx, ty); 534*7c478bd9Sstevel@tonic-gate break; 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate case fp_precision_3: /* rounded to 64 bits */ 537*7c478bd9Sstevel@tonic-gate { 538*7c478bd9Sstevel@tonic-gate k = pu->exponent + EXTENDED_BIAS; 539*7c478bd9Sstevel@tonic-gate if (k >= 0) k = 113-64; 540*7c478bd9Sstevel@tonic-gate else k = 113-64-k; 541*7c478bd9Sstevel@tonic-gate fpu_rightshift(pu, 113-64); 542*7c478bd9Sstevel@tonic-gate round(pfpsd, pu); 543*7c478bd9Sstevel@tonic-gate pu->sticky = pu->rounded = 0; 544*7c478bd9Sstevel@tonic-gate pu->exponent += k; 545*7c478bd9Sstevel@tonic-gate fpu_normalize(pu); 546*7c478bd9Sstevel@tonic-gate break; 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate packextended(pfpsd, pu, &ex.x, &ex.y[1], 550*7c478bd9Sstevel@tonic-gate &ex.y[2], &ex.y[3]); 551*7c478bd9Sstevel@tonic-gate if (!(pfpsd->fp_current_exceptions & 552*7c478bd9Sstevel@tonic-gate pfpsd->fp_fsrtem)) { 553*7c478bd9Sstevel@tonic-gate if ((n & 0x1) == 1) /* fix register encoding */ 554*7c478bd9Sstevel@tonic-gate n = (n & 0x1e) | 0x20; 555*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_write_dreg(&ex.ll[0], 556*7c478bd9Sstevel@tonic-gate QUAD_E(n), pfpsd); 557*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_write_dreg(&ex.ll[1], 558*7c478bd9Sstevel@tonic-gate QUAD_F(n), pfpsd); 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate break; 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate } 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate void 567*7c478bd9Sstevel@tonic-gate _fp_pack_word( 568*7c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd, /* Pointer to simulator data */ 569*7c478bd9Sstevel@tonic-gate uint32_t *pu, /* unpacked operand */ 570*7c478bd9Sstevel@tonic-gate uint_t n) /* register where datum starts */ 571*7c478bd9Sstevel@tonic-gate { 572*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_write_freg(pu, n, pfpsd); 573*7c478bd9Sstevel@tonic-gate } 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate void 576*7c478bd9Sstevel@tonic-gate _fp_pack_extword( 577*7c478bd9Sstevel@tonic-gate fp_simd_type *pfpsd, /* Pointer to simulator data */ 578*7c478bd9Sstevel@tonic-gate uint64_t *pu, /* unpacked operand */ 579*7c478bd9Sstevel@tonic-gate uint_t n) /* register where datum starts */ 580*7c478bd9Sstevel@tonic-gate { 581*7c478bd9Sstevel@tonic-gate if ((n & 1) == 1) /* fix register encoding */ 582*7c478bd9Sstevel@tonic-gate n = (n & 0x1e) | 0x20; 583*7c478bd9Sstevel@tonic-gate pfpsd->fp_current_write_dreg(pu, DOUBLE(n), pfpsd); 584*7c478bd9Sstevel@tonic-gate } 585