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 #pragma weak modfl = __modfl 31 32 #include "libm.h" 33 34 #if defined(__sparc) 35 36 long double 37 __modfl(long double x, long double *iptr) { 38 union { 39 unsigned i[4]; 40 long double q; 41 } xx, yy; 42 unsigned hx, s; 43 44 xx.q = x; 45 hx = xx.i[0] & ~0x80000000; 46 47 if (hx >= 0x406f0000) { /* x is NaN, infinite, or integral */ 48 *iptr = x; 49 if (hx < 0x7fff0000 || (hx == 0x7fff0000 && 50 (xx.i[1] | xx.i[2] | xx.i[3]) == 0)) { 51 xx.i[0] &= 0x80000000; 52 xx.i[1] = xx.i[2] = xx.i[3] = 0; 53 } 54 return (xx.q); 55 } 56 57 if (hx < 0x3fff0000) { /* |x| < 1 */ 58 xx.i[0] &= 0x80000000; 59 xx.i[1] = xx.i[2] = xx.i[3] = 0; 60 *iptr = xx.q; 61 return (x); 62 } 63 64 /* split x at the binary point */ 65 s = xx.i[0] & 0x80000000; 66 if (hx < 0x40100000) { 67 yy.i[0] = xx.i[0] & ~((1 << (0x400f - (hx >> 16))) - 1); 68 yy.i[1] = yy.i[2] = yy.i[3] = 0; 69 } else if (hx < 0x40300000) { 70 yy.i[0] = xx.i[0]; 71 yy.i[1] = xx.i[1] & ~((1 << (0x402f - (hx >> 16))) - 1); 72 yy.i[2] = yy.i[3] = 0; 73 } else if (hx < 0x40500000) { 74 yy.i[0] = xx.i[0]; 75 yy.i[1] = xx.i[1]; 76 yy.i[2] = xx.i[2] & ~((1 << (0x404f - (hx >> 16))) - 1); 77 yy.i[3] = 0; 78 } else { 79 yy.i[0] = xx.i[0]; 80 yy.i[1] = xx.i[1]; 81 yy.i[2] = xx.i[2]; 82 yy.i[3] = xx.i[3] & ~((1 << (0x406f - (hx >> 16))) - 1); 83 } 84 *iptr = yy.q; 85 86 /* 87 * we could implement the following more efficiently than by using 88 * software emulation of fsubq, but we'll do it this way for now 89 * (and hope hardware support becomes commonplace) 90 */ 91 xx.q -= yy.q; 92 xx.i[0] = (xx.i[0] & ~0x80000000) | s; /* keep sign of x */ 93 return (xx.q); 94 } 95 96 #elif defined(__x86) 97 98 long double 99 __modfl(long double x, long double *iptr) { 100 union { 101 unsigned i[3]; 102 long double e; 103 } xx, yy; 104 unsigned hx, s; 105 106 /* 107 * It might be faster to use one of the x86 fpops instead of 108 * the following. 109 */ 110 xx.e = x; 111 hx = xx.i[2] & 0x7fff; 112 113 if (hx >= 0x403e) { /* x is NaN, infinite, or integral */ 114 *iptr = x; 115 if (hx < 0x7fff || (hx == 0x7fff && 116 ((xx.i[1] << 1) | xx.i[0]) == 0)) { 117 xx.i[2] &= 0x8000; 118 xx.i[1] = xx.i[0] = 0; 119 } 120 return (xx.e); 121 } 122 123 if (hx < 0x3fff) { /* |x| < 1 */ 124 xx.i[2] &= 0x8000; 125 xx.i[1] = xx.i[0] = 0; 126 *iptr = xx.e; 127 return (x); 128 } 129 130 /* split x at the binary point */ 131 s = xx.i[2] & 0x8000; 132 yy.i[2] = xx.i[2]; 133 if (hx < 0x401f) { 134 yy.i[1] = xx.i[1] & ~((1 << (0x401e - hx)) - 1); 135 yy.i[0] = 0; 136 } else { 137 yy.i[1] = xx.i[1]; 138 yy.i[0] = xx.i[0] & ~((1 << (0x403e - hx)) - 1); 139 } 140 *iptr = yy.e; 141 xx.e -= yy.e; 142 xx.i[2] = (xx.i[2] & ~0x8000) | s; /* keep sign of x */ 143 return (xx.e); 144 } 145 146 #else 147 #error Unknown architecture 148 #endif 149