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 (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 /*
  26  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  27  * Use is subject to license terms.
  28  */
  29 
  30 #if defined(ELFOBJ)
  31 #pragma weak frexpl = __frexpl
  32 #endif
  33 
  34 #include "libm.h"
  35 
  36 #if defined(__sparc)
  37 
  38 long double
  39 __frexpl(long double x, int *exp) {
  40         union {
  41                 unsigned i[4];
  42                 long double q;
  43         } xx;
  44         unsigned hx;
  45         int e, s;
  46 
  47         xx.q = x;
  48         hx = xx.i[0] & ~0x80000000;
  49 
  50         if (hx >= 0x7fff0000) {      /* x is infinite or NaN */
  51                 *exp = 0;
  52                 return (x);
  53         }
  54 
  55         e = 0;
  56         if (hx < 0x00010000) {       /* x is subnormal or zero */
  57                 if ((hx | xx.i[1] | xx.i[2] | xx.i[3]) == 0) {
  58                         *exp = 0;
  59                         return (x);
  60                 }
  61 
  62                 /* normalize x */
  63                 s = xx.i[0] & 0x80000000;
  64                 while ((hx | (xx.i[1] & 0xffff0000)) == 0) {
  65                         hx = xx.i[1];
  66                         xx.i[1] = xx.i[2];
  67                         xx.i[2] = xx.i[3];
  68                         xx.i[3] = 0;
  69                         e -= 32;
  70                 }
  71                 while (hx < 0x10000) {
  72                         hx = (hx << 1) | (xx.i[1] >> 31);
  73                         xx.i[1] = (xx.i[1] << 1) | (xx.i[2] >> 31);
  74                         xx.i[2] = (xx.i[2] << 1) | (xx.i[3] >> 31);
  75                         xx.i[3] <<= 1;
  76                         e--;
  77                 }
  78                 xx.i[0] = s | hx;
  79         }
  80 
  81         /* now xx.q is normal */
  82         xx.i[0] = (xx.i[0] & ~0x7fff0000) | 0x3ffe0000;
  83         *exp = e + (hx >> 16) - 0x3ffe;
  84         return (xx.q);
  85 }
  86 
  87 #elif defined(__x86)
  88 
  89 long double
  90 __frexpl(long double x, int *exp) {
  91         union {
  92                 unsigned i[3];
  93                 long double e;
  94         } xx;
  95         unsigned hx;
  96         int e;
  97 
  98         xx.e = x;
  99         hx = xx.i[2] & 0x7fff;
 100 
 101         if (hx >= 0x7fff) {  /* x is infinite or NaN */
 102                 *exp = 0;
 103                 return (x);
 104         }
 105 
 106         e = 0;
 107         if (hx < 0x0001) {   /* x is subnormal or zero */
 108                 if ((xx.i[0] | xx.i[1]) == 0) {
 109                         *exp = 0;
 110                         return (x);
 111                 }
 112 
 113                 /* normalize x */
 114                 xx.e *= 18446744073709551616.0L;        /* 2^64 */
 115                 hx = xx.i[2] & 0x7fff;
 116                 e = -64;
 117         }
 118 
 119         /* now xx.e is normal */
 120         xx.i[2] = (xx.i[2] & 0x8000) | 0x3ffe;
 121         *exp = e + hx - 0x3ffe;
 122         return (xx.e);
 123 }
 124 
 125 #else
 126 #error Unknown architecture
 127 #endif