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