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