/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright 2011, Richard Lowe. */ /* Functions in this file are duplicated in locallibm.il. Keep them in sync */ #ifndef _LIBM_INLINES_H #define _LIBM_INLINES_H #ifdef __GNUC__ #ifdef __cplusplus extern "C" { #endif #include #include extern __GNU_INLINE float __inline_sqrtf(float a) { float ret; __asm__ __volatile__("sqrtss %1, %0\n\t" : "=x" (ret) : "x" (a)); return (ret); } extern __GNU_INLINE double __inline_sqrt(double a) { double ret; __asm__ __volatile__("sqrtsd %1, %0\n\t" : "=x" (ret) : "x" (a)); return (ret); } extern __GNU_INLINE double __ieee754_sqrt(double a) { return (__inline_sqrt(a)); } /* * 00 - 24 bits * 01 - reserved * 10 - 53 bits * 11 - 64 bits */ extern __GNU_INLINE int __swapRP(int i) { int ret; uint16_t cw; __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw)); ret = (cw >> 8) & 0x3; cw = (cw & 0xfcff) | ((i & 0x3) << 8); __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw)); return (ret); } /* * 00 - Round to nearest, with even preferred * 01 - Round down * 10 - Round up * 11 - Chop */ extern __GNU_INLINE enum fp_direction_type __swap87RD(enum fp_direction_type i) { int ret; uint16_t cw; __asm__ __volatile__("fstcw %0\n\t" : "=m" (cw)); ret = (cw >> 10) & 0x3; cw = (cw & 0xf3ff) | ((i & 0x3) << 10); __asm__ __volatile__("fldcw %0\n\t" : : "m" (cw)); return (ret); } extern __GNU_INLINE int abs(int i) { int ret; __asm__ __volatile__( "movl %1, %0\n\t" "negl %1\n\t" "cmovnsl %1, %0\n\t" : "=r" (ret), "+r" (i) : : "cc"); return (ret); } extern __GNU_INLINE double copysign(double d1, double d2) { double tmpd; __asm__ __volatile__( "movd %3, %1\n\t" "andpd %1, %0\n\t" "andnpd %2, %1\n\t" "orpd %1, %0\n\t" : "+&x" (d1), "=&x" (tmpd) : "x" (d2), "r" (0x7fffffffffffffff)); return (d1); } extern __GNU_INLINE double fabs(double d) { double tmp; __asm__ __volatile__( "movd %2, %1\n\t" "andpd %1, %0" : "+x" (d), "=&x" (tmp) : "r" (0x7fffffffffffffff)); return (d); } extern __GNU_INLINE float fabsf(float d) { __asm__ __volatile__( "andpd %1, %0" : "+x" (d) : "x" (0x7fffffff)); return (d); } extern __GNU_INLINE int finite(double d) { long ret = 0x7fffffffffffffff; uint64_t tmp; __asm__ __volatile__( "movq %2, %1\n\t" "andq %1, %0\n\t" "movq $0x7ff0000000000000, %1\n\t" "subq %1, %0\n\t" "shrq $63, %0\n\t" : "+r" (ret), "=r" (tmp) : "x" (d) : "cc"); return (ret); } extern __GNU_INLINE int signbit(double d) { long ret; __asm__ __volatile__( "movmskpd %1, %0\n\t" "andq $1, %0\n\t" : "=r" (ret) : "x" (d) : "cc"); return (ret); } extern __GNU_INLINE double sqrt(double d) { return (__inline_sqrt(d)); } extern __GNU_INLINE float sqrtf(float f) { return (__inline_sqrtf(f)); } #ifdef __cplusplus } #endif #endif /* __GNUC__ */ #endif /* _LIBM_INLINES_H */