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 (c) 1994-1997, by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 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 #include "quad.h" 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #ifdef __sparcv9 32*7c478bd9Sstevel@tonic-gate #define _Q_qtod _Qp_qtod 33*7c478bd9Sstevel@tonic-gate #endif 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate /* 36*7c478bd9Sstevel@tonic-gate * _Q_qtod(x) returns (double)*x. 37*7c478bd9Sstevel@tonic-gate */ 38*7c478bd9Sstevel@tonic-gate double 39*7c478bd9Sstevel@tonic-gate _Q_qtod(const union longdouble *x) 40*7c478bd9Sstevel@tonic-gate { 41*7c478bd9Sstevel@tonic-gate union xdouble u; 42*7c478bd9Sstevel@tonic-gate unsigned int xm, round, sticky, fsr, rm; 43*7c478bd9Sstevel@tonic-gate int subnormal, e; 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate xm = x->l.msw & 0x7fffffff; 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate /* get the rounding mode, fudging directed rounding modes */ 48*7c478bd9Sstevel@tonic-gate /* as though the result were positive */ 49*7c478bd9Sstevel@tonic-gate __quad_getfsrp(&fsr); 50*7c478bd9Sstevel@tonic-gate rm = fsr >> 30; 51*7c478bd9Sstevel@tonic-gate if (x->l.msw & 0x80000000) 52*7c478bd9Sstevel@tonic-gate rm ^= (rm >> 1); 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate /* handle nan, inf, and out-of-range cases */ 55*7c478bd9Sstevel@tonic-gate if (xm >= 0x43ff0000) { 56*7c478bd9Sstevel@tonic-gate if (xm >= 0x7fff0000) { 57*7c478bd9Sstevel@tonic-gate if ((xm & 0xffff) | x->l.frac2 | x->l.frac3 | 58*7c478bd9Sstevel@tonic-gate x->l.frac4) { 59*7c478bd9Sstevel@tonic-gate /* x is nan */ 60*7c478bd9Sstevel@tonic-gate u.l.hi = (x->l.msw & 0x80000000) | 0x7ff80000; 61*7c478bd9Sstevel@tonic-gate u.l.hi |= ((xm & 0x7fff) << 4) | 62*7c478bd9Sstevel@tonic-gate (x->l.frac2 >> 28); 63*7c478bd9Sstevel@tonic-gate u.l.lo = (x->l.frac2 << 4) | 64*7c478bd9Sstevel@tonic-gate (x->l.frac3 >> 28); 65*7c478bd9Sstevel@tonic-gate if (!(xm & 0x8000)) { 66*7c478bd9Sstevel@tonic-gate /* snan, signal invalid */ 67*7c478bd9Sstevel@tonic-gate if (fsr & FSR_NVM) { 68*7c478bd9Sstevel@tonic-gate __quad_fqtod(x, &u.d); 69*7c478bd9Sstevel@tonic-gate } else { 70*7c478bd9Sstevel@tonic-gate fsr = (fsr & ~FSR_CEXC) | 71*7c478bd9Sstevel@tonic-gate FSR_NVA | FSR_NVC; 72*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr); 73*7c478bd9Sstevel@tonic-gate } 74*7c478bd9Sstevel@tonic-gate } 75*7c478bd9Sstevel@tonic-gate return (u.d); 76*7c478bd9Sstevel@tonic-gate } 77*7c478bd9Sstevel@tonic-gate /* x is inf */ 78*7c478bd9Sstevel@tonic-gate u.l.hi = (x->l.msw & 0x80000000) | 0x7ff00000; 79*7c478bd9Sstevel@tonic-gate u.l.lo = 0; 80*7c478bd9Sstevel@tonic-gate return (u.d); 81*7c478bd9Sstevel@tonic-gate } 82*7c478bd9Sstevel@tonic-gate /* x is too big, overflow */ 83*7c478bd9Sstevel@tonic-gate if (rm == FSR_RN || rm == FSR_RP) { 84*7c478bd9Sstevel@tonic-gate u.l.hi = 0x7ff00000; 85*7c478bd9Sstevel@tonic-gate u.l.lo = 0; 86*7c478bd9Sstevel@tonic-gate } else { 87*7c478bd9Sstevel@tonic-gate u.l.hi = 0x7fefffff; 88*7c478bd9Sstevel@tonic-gate u.l.lo = 0xffffffff; 89*7c478bd9Sstevel@tonic-gate } 90*7c478bd9Sstevel@tonic-gate u.l.hi |= (x->l.msw & 0x80000000); 91*7c478bd9Sstevel@tonic-gate if (fsr & (FSR_OFM | FSR_NXM)) { 92*7c478bd9Sstevel@tonic-gate __quad_fqtod(x, &u.d); 93*7c478bd9Sstevel@tonic-gate } else { 94*7c478bd9Sstevel@tonic-gate fsr = (fsr & ~FSR_CEXC) | FSR_OFA | FSR_OFC | 95*7c478bd9Sstevel@tonic-gate FSR_NXA | FSR_NXC; 96*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr); 97*7c478bd9Sstevel@tonic-gate } 98*7c478bd9Sstevel@tonic-gate return (u.d); 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate subnormal = 0; 102*7c478bd9Sstevel@tonic-gate if (xm < 0x3c010000) { 103*7c478bd9Sstevel@tonic-gate if (xm < 0x3bcc0000) { 104*7c478bd9Sstevel@tonic-gate if (QUAD_ISZERO(*x)) { 105*7c478bd9Sstevel@tonic-gate u.l.hi = (x->l.msw & 0x80000000); 106*7c478bd9Sstevel@tonic-gate u.l.lo = 0; 107*7c478bd9Sstevel@tonic-gate return (u.d); 108*7c478bd9Sstevel@tonic-gate } 109*7c478bd9Sstevel@tonic-gate /* x is too small, underflow */ 110*7c478bd9Sstevel@tonic-gate u.l.hi = (x->l.msw & 0x80000000); 111*7c478bd9Sstevel@tonic-gate u.l.lo = ((rm == FSR_RP)? 1 : 0); 112*7c478bd9Sstevel@tonic-gate if (fsr & (FSR_UFM | FSR_NXM)) { 113*7c478bd9Sstevel@tonic-gate __quad_fqtod(x, &u.d); 114*7c478bd9Sstevel@tonic-gate } else { 115*7c478bd9Sstevel@tonic-gate fsr = (fsr & ~FSR_CEXC) | FSR_UFA | FSR_UFC | 116*7c478bd9Sstevel@tonic-gate FSR_NXA | FSR_NXC; 117*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr); 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate return (u.d); 120*7c478bd9Sstevel@tonic-gate } 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* x is in the subnormal range for double */ 123*7c478bd9Sstevel@tonic-gate subnormal = 1; 124*7c478bd9Sstevel@tonic-gate u.l.hi = 0x80000 | ((xm & 0xffff) << 3) | (x->l.frac2 >> 29); 125*7c478bd9Sstevel@tonic-gate u.l.lo = (x->l.frac2 << 3) | (x->l.frac3 >> 29); 126*7c478bd9Sstevel@tonic-gate round = x->l.frac3 & 0x10000000; 127*7c478bd9Sstevel@tonic-gate sticky = (x->l.frac3 & 0xfffffff) | x->l.frac4; 128*7c478bd9Sstevel@tonic-gate e = 0x3c00 - (xm >> 16); 129*7c478bd9Sstevel@tonic-gate if (e >= 32) { 130*7c478bd9Sstevel@tonic-gate sticky |= round | (u.l.lo & 0x7fffffff); 131*7c478bd9Sstevel@tonic-gate round = u.l.lo & 0x80000000; 132*7c478bd9Sstevel@tonic-gate u.l.lo = u.l.hi; 133*7c478bd9Sstevel@tonic-gate u.l.hi = 0; 134*7c478bd9Sstevel@tonic-gate e -= 32; 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate if (e) { 137*7c478bd9Sstevel@tonic-gate sticky |= round | (u.l.lo & ((1 << (e - 1)) - 1)); 138*7c478bd9Sstevel@tonic-gate round = u.l.lo & (1 << (e - 1)); 139*7c478bd9Sstevel@tonic-gate u.l.lo = (u.l.lo >> e) | (u.l.hi << (32 - e)); 140*7c478bd9Sstevel@tonic-gate u.l.hi >>= e; 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate } else { 143*7c478bd9Sstevel@tonic-gate /* x is in the normal range for double */ 144*7c478bd9Sstevel@tonic-gate u.l.hi = ((xm - 0x3c000000) << 4) | (x->l.frac2 >> 28); 145*7c478bd9Sstevel@tonic-gate u.l.lo = (x->l.frac2 << 4) | (x->l.frac3 >> 28); 146*7c478bd9Sstevel@tonic-gate round = x->l.frac3 & 0x8000000; 147*7c478bd9Sstevel@tonic-gate sticky = (x->l.frac3 & 0x7ffffff) | x->l.frac4; 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate /* see if we need to round */ 151*7c478bd9Sstevel@tonic-gate fsr &= ~FSR_CEXC; 152*7c478bd9Sstevel@tonic-gate if (round | sticky) { 153*7c478bd9Sstevel@tonic-gate fsr |= FSR_NXC; 154*7c478bd9Sstevel@tonic-gate if (subnormal) 155*7c478bd9Sstevel@tonic-gate fsr |= FSR_UFC; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate /* round up if necessary */ 158*7c478bd9Sstevel@tonic-gate if (rm == FSR_RP || (rm == FSR_RN && round && (sticky || 159*7c478bd9Sstevel@tonic-gate (u.l.lo & 1)))) { 160*7c478bd9Sstevel@tonic-gate /* round up and check for overflow */ 161*7c478bd9Sstevel@tonic-gate if (++u.l.lo == 0) 162*7c478bd9Sstevel@tonic-gate if (++u.l.hi >= 0x7ff00000) 163*7c478bd9Sstevel@tonic-gate fsr |= FSR_OFC; 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate /* if result is exact and subnormal but underflow trapping is */ 168*7c478bd9Sstevel@tonic-gate /* enabled, signal underflow */ 169*7c478bd9Sstevel@tonic-gate else if (subnormal && (fsr & FSR_UFM)) 170*7c478bd9Sstevel@tonic-gate fsr |= FSR_UFC; 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate /* attach the sign and raise exceptions as need be */ 173*7c478bd9Sstevel@tonic-gate u.l.hi |= (x->l.msw & 0x80000000); 174*7c478bd9Sstevel@tonic-gate if ((fsr & FSR_CEXC) & (fsr >> 23)) { 175*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr); 176*7c478bd9Sstevel@tonic-gate __quad_fqtod(x, &u.d); 177*7c478bd9Sstevel@tonic-gate } else { 178*7c478bd9Sstevel@tonic-gate fsr |= (fsr & 0x1f) << 5; 179*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate return (u.d); 182*7c478bd9Sstevel@tonic-gate } 183