125c28e8Piotr Jasiukajtis/*
225c28e8Piotr Jasiukajtis * CDDL HEADER START
325c28e8Piotr Jasiukajtis *
425c28e8Piotr Jasiukajtis * The contents of this file are subject to the terms of the
525c28e8Piotr Jasiukajtis * Common Development and Distribution License (the "License").
625c28e8Piotr Jasiukajtis * You may not use this file except in compliance with the License.
725c28e8Piotr Jasiukajtis *
825c28e8Piotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
925c28e8Piotr Jasiukajtis * or http://www.opensolaris.org/os/licensing.
1025c28e8Piotr Jasiukajtis * See the License for the specific language governing permissions
1125c28e8Piotr Jasiukajtis * and limitations under the License.
1225c28e8Piotr Jasiukajtis *
1325c28e8Piotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each
1425c28e8Piotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1525c28e8Piotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the
1625c28e8Piotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying
1725c28e8Piotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner]
1825c28e8Piotr Jasiukajtis *
1925c28e8Piotr Jasiukajtis * CDDL HEADER END
2025c28e8Piotr Jasiukajtis */
2125c28e8Piotr Jasiukajtis
2225c28e8Piotr Jasiukajtis/*
2325c28e8Piotr Jasiukajtis * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
2425c28e8Piotr Jasiukajtis * Use is subject to license terms.
2525c28e8Piotr Jasiukajtis */
2625c28e8Piotr Jasiukajtis
2725c28e8Piotr Jasiukajtis/*
2825c28e8Piotr Jasiukajtis * Copyright 2011, Richard Lowe.
2925c28e8Piotr Jasiukajtis */
3025c28e8Piotr Jasiukajtis
3125c28e8Piotr Jasiukajtis/* Functions in this file are duplicated in locallibm.il.  Keep them in sync */
3225c28e8Piotr Jasiukajtis
3325c28e8Piotr Jasiukajtis#ifndef _LIBM_INLINES_H
3425c28e8Piotr Jasiukajtis#define	_LIBM_INLINES_H
3525c28e8Piotr Jasiukajtis
3625c28e8Piotr Jasiukajtis#ifdef __GNUC__
3725c28e8Piotr Jasiukajtis
3825c28e8Piotr Jasiukajtis#include <sys/types.h>
3925c28e8Piotr Jasiukajtis#include <sys/ieeefp.h>
4025c28e8Piotr Jasiukajtis
4125c28e8Piotr Jasiukajtis#ifdef __cplusplus
4225c28e8Piotr Jasiukajtisextern "C" {
4325c28e8Piotr Jasiukajtis#endif
4425c28e8Piotr Jasiukajtis
457f11fd0Richard Loweextern __GNU_INLINE double
4625c28e8Piotr Jasiukajtis__inline_sqrt(double d)
4725c28e8Piotr Jasiukajtis{
4825c28e8Piotr Jasiukajtis	double ret;
4925c28e8Piotr Jasiukajtis
5025c28e8Piotr Jasiukajtis	__asm__ __volatile__("fsqrtd %1,%0\n\t" : "=e" (ret) : "e" (d));
5125c28e8Piotr Jasiukajtis	return (ret);
5225c28e8Piotr Jasiukajtis}
5325c28e8Piotr Jasiukajtis
547f11fd0Richard Loweextern __GNU_INLINE float
5525c28e8Piotr Jasiukajtis__inline_sqrtf(float f)
5625c28e8Piotr Jasiukajtis{
5725c28e8Piotr Jasiukajtis	float ret;
5825c28e8Piotr Jasiukajtis
5925c28e8Piotr Jasiukajtis	__asm__ __volatile__("fsqrts %1,%0\n\t" : "=f" (ret) : "f" (f));
6025c28e8Piotr Jasiukajtis	return (ret);
6125c28e8Piotr Jasiukajtis}
6225c28e8Piotr Jasiukajtis
637f11fd0Richard Loweextern __GNU_INLINE enum fp_class_type
6425c28e8Piotr Jasiukajtisfp_classf(float f)
6525c28e8Piotr Jasiukajtis{
6625c28e8Piotr Jasiukajtis	enum fp_class_type ret;
6725c28e8Piotr Jasiukajtis	uint32_t tmp;
6825c28e8Piotr Jasiukajtis
6925c28e8Piotr Jasiukajtis	/* XXX: Separate input and output */
7025c28e8Piotr Jasiukajtis	__asm__ __volatile__(
7125c28e8Piotr Jasiukajtis	    "sethi  %%hi(0x80000000),%1\n\t"
7225c28e8Piotr Jasiukajtis	    "andncc %2,%1,%0\n\t"
7325c28e8Piotr Jasiukajtis	    "bne    1f\n\t"
7425c28e8Piotr Jasiukajtis	    "nop\n\t"
7525c28e8Piotr Jasiukajtis	    "mov    0,%0\n\t"
7625c28e8Piotr Jasiukajtis	    "ba	2f\n\t"		/* x is 0 */
7725c28e8Piotr Jasiukajtis	    "nop\n\t"
7825c28e8Piotr Jasiukajtis	    "1:\n\t"
7925c28e8Piotr Jasiukajtis	    "sethi  %%hi(0x7f800000),%1\n\t"
8025c28e8Piotr Jasiukajtis	    "andcc  %0,%1,%%g0\n\t"
8125c28e8Piotr Jasiukajtis	    "bne    1f\n\t"
8225c28e8Piotr Jasiukajtis	    "nop\n\t"
8325c28e8Piotr Jasiukajtis	    "mov    1,%0\n\t"
8425c28e8Piotr Jasiukajtis	    "ba	    2f\n\t"	/* x is subnormal */
8525c28e8Piotr Jasiukajtis	    "nop\n\t"
8625c28e8Piotr Jasiukajtis	    "1:\n\t"
8725c28e8Piotr Jasiukajtis	    "cmp    %0,%1\n\t"
8825c28e8Piotr Jasiukajtis	    "bge    1f\n\t"
8925c28e8Piotr Jasiukajtis	    "nop\n\t"
9025c28e8Piotr Jasiukajtis	    "mov    2,%0\n\t"
9125c28e8Piotr Jasiukajtis	    "ba	    2f\n\t"	/* x is normal */
9225c28e8Piotr Jasiukajtis	    "nop\n\t"
9325c28e8Piotr Jasiukajtis	    "1:\n\t"
9425c28e8Piotr Jasiukajtis	    "bg	    1f\n\t"
9525c28e8Piotr Jasiukajtis	    "nop\n\t"
9625c28e8Piotr Jasiukajtis	    "mov    3,%0\n\t"
9725c28e8Piotr Jasiukajtis	    "ba	    2f\n\t"	/* x is __infinity */
9825c28e8Piotr Jasiukajtis	    "nop\n\t"
9925c28e8Piotr Jasiukajtis	    "1:\n\t"
10025c28e8Piotr Jasiukajtis	    "sethi  %%hi(0x00400000),%1\n\t"
10125c28e8Piotr Jasiukajtis	    "andcc  %0,%1,%%g0\n\t"
10225c28e8Piotr Jasiukajtis	    "mov    4,%0\n\t"	/* x is quiet NaN */
10325c28e8Piotr Jasiukajtis	    "bne    2f\n\t"
10425c28e8Piotr Jasiukajtis	    "nop\n\t"
10525c28e8Piotr Jasiukajtis	    "mov    5,%0\n\t"	/* x is signaling NaN */
10625c28e8Piotr Jasiukajtis	    "2:\n\t"
10725c28e8Piotr Jasiukajtis	    : "=r" (ret), "=&r" (tmp)
10825c28e8Piotr Jasiukajtis	    : "r" (f)
10925c28e8Piotr Jasiukajtis	    : "cc");
11025c28e8Piotr Jasiukajtis	return (ret);
11125c28e8Piotr Jasiukajtis}
11225c28e8Piotr Jasiukajtis
11325c28e8Piotr Jasiukajtis#define	_HI_WORD(x)	((uint32_t *)&x)[0]
11425c28e8Piotr Jasiukajtis#define	_LO_WORD(x)	((uint32_t *)&x)[1]
11525c28e8Piotr Jasiukajtis
1167f11fd0Richard Loweextern __GNU_INLINE enum fp_class_type
11725c28e8Piotr Jasiukajtisfp_class(double d)
11825c28e8Piotr Jasiukajtis{
11925c28e8Piotr Jasiukajtis	enum fp_class_type ret;
12025c28e8Piotr Jasiukajtis	uint32_t tmp;
12125c28e8Piotr Jasiukajtis
12225c28e8Piotr Jasiukajtis	__asm__ __volatile__(
12325c28e8Piotr Jasiukajtis	    "sethi %%hi(0x80000000),%1\n\t"	/* %1 gets 80000000 */
12425c28e8Piotr Jasiukajtis	    "andn  %2,%1,%0\n\t"		/* %2-%0 gets abs(x) */
12525c28e8Piotr Jasiukajtis	    "orcc  %0,%3,%%g0\n\t"		/* set cc as x is zero/nonzero */
12625c28e8Piotr Jasiukajtis	    "bne   1f\n\t"			/* branch if x is nonzero */
12725c28e8Piotr Jasiukajtis	    "nop\n\t"
12825c28e8Piotr Jasiukajtis	    "mov   0,%0\n\t"
12925c28e8Piotr Jasiukajtis	    "ba	   2f\n\t"			/* x is 0 */
13025c28e8Piotr Jasiukajtis	    "nop\n\t"
13125c28e8Piotr Jasiukajtis	    "1:\n\t"
13225c28e8Piotr Jasiukajtis	    "sethi %%hi(0x7ff00000),%1\n\t"	/* %1 gets 7ff00000 */
13325c28e8Piotr Jasiukajtis	    "andcc %0,%1,%%g0\n\t"		/* cc set by __exp field of x */
13425c28e8Piotr Jasiukajtis	    "bne   1f\n\t"			/* branch if normal or max __exp */
13525c28e8Piotr Jasiukajtis	    "nop\n\t"
13625c28e8Piotr Jasiukajtis	    "mov   1,%0\n\t"
13725c28e8Piotr Jasiukajtis	    "ba	   2f\n\t"			/* x is subnormal */
13825c28e8Piotr Jasiukajtis	    "nop\n\t"
13925c28e8Piotr Jasiukajtis	    "1:\n\t"
14025c28e8Piotr Jasiukajtis	    "cmp   %0,%1\n\t"
14125c28e8Piotr Jasiukajtis	    "bge   1f\n\t"			/* branch if x is max __exp */
14225c28e8Piotr Jasiukajtis	    "nop\n\t"
14325c28e8Piotr Jasiukajtis	    "mov   2,%0\n\t"
14425c28e8Piotr Jasiukajtis	    "ba	   2f\n\t"			/* x is normal */
14525c28e8Piotr Jasiukajtis	    "nop\n\t"
14625c28e8Piotr Jasiukajtis	    "1:\n\t"
14725c28e8Piotr Jasiukajtis	    "andn  %0,%1,%0\n\t"		/* o0 gets msw __significand field */
14825c28e8Piotr Jasiukajtis	    "orcc  %0,%3,%%g0\n\t"		/* set cc by OR __significand */
14925c28e8Piotr Jasiukajtis	    "bne   1f\n\t"			/* Branch if __nan */
15025c28e8Piotr Jasiukajtis	    "nop\n\t"
15125c28e8Piotr Jasiukajtis	    "mov   3,%0\n\t"
15225c28e8Piotr Jasiukajtis	    "ba	   2f\n\t"			/* x is __infinity */
15325c28e8Piotr Jasiukajtis	    "nop\n\t"
15425c28e8Piotr Jasiukajtis	    "1:\n\t"
15525c28e8Piotr Jasiukajtis	    "sethi %%hi(0x00080000),%1\n\t"
15625c28e8Piotr Jasiukajtis	    "andcc %0,%1,%%g0\n\t"		/* set cc by quiet/sig bit */
15725c28e8Piotr Jasiukajtis	    "be	   1f\n\t"			/* Branch if signaling */
15825c28e8Piotr Jasiukajtis	    "nop\n\t"
15925c28e8Piotr Jasiukajtis	    "mov   4,%0\n\t"			/* x is quiet NaN */
16025c28e8Piotr Jasiukajtis	    "ba	   2f\n\t"
16125c28e8Piotr Jasiukajtis	    "nop\n\t"
16225c28e8Piotr Jasiukajtis	    "1:\n\t"
16325c28e8Piotr Jasiukajtis	    "mov   5,%0\n\t"			/* x is signaling NaN */
16425c28e8Piotr Jasiukajtis	    "2:\n\t"
16525c28e8Piotr Jasiukajtis	    : "=&r" (ret), "=&r" (tmp)
16625c28e8Piotr Jasiukajtis	    : "r" (_HI_WORD(d)), "r" (_LO_WORD(d))
16725c28e8Piotr Jasiukajtis	    : "cc");
16825c28e8Piotr Jasiukajtis
16925c28e8Piotr Jasiukajtis	return (ret);
17025c28e8Piotr Jasiukajtis}
17125c28e8Piotr Jasiukajtis
1727f11fd0Richard Loweextern __GNU_INLINE int
17325c28e8Piotr Jasiukajtis__swapEX(int i)
17425c28e8Piotr Jasiukajtis{
17525c28e8Piotr Jasiukajtis	int ret;
17625c28e8Piotr Jasiukajtis	uint32_t fsr;
17725c28e8Piotr Jasiukajtis	uint32_t tmp1, tmp2;
17825c28e8Piotr Jasiukajtis
17925c28e8Piotr Jasiukajtis	__asm__ __volatile__(
18025c28e8Piotr Jasiukajtis	    "and  %4,0x1f,%2\n\t" /* tmp1 = %2 = %o1 */
18125c28e8Piotr Jasiukajtis	    "sll  %2,5,%2\n\t"	/* shift input to aexc bit location */
18225c28e8Piotr Jasiukajtis	    ".volatile\n\t"
18325c28e8Piotr Jasiukajtis	    "st   %%fsr,%1\n\t"
18425c28e8Piotr Jasiukajtis	    "ld   %1,%0\n\t"	/* %0 = fsr */
18525c28e8Piotr Jasiukajtis	    "andn %0,0x3e0,%3\n\t" /* tmp2 = %3 = %o2 */
18625c28e8Piotr Jasiukajtis	    "or   %2,%3,%2\n\t"	/* %2 = new fsr */
18725c28e8Piotr Jasiukajtis	    "st	  %2,%1\n\t"
18825c28e8Piotr Jasiukajtis	    "ld	  %1,%%fsr\n\t"
18925c28e8Piotr Jasiukajtis	    "srl  %0,5,%0\n\t"
19025c28e8Piotr Jasiukajtis	    "and  %0,0x1f,%0\n\t" /* %0 = ret = %o0 */
19125c28e8Piotr Jasiukajtis	    ".nonvolatile\n\t"
19225c28e8Piotr Jasiukajtis	    : "=r" (ret), "=m" (fsr), "=r" (tmp1), "=r" (tmp2)
19325c28e8Piotr Jasiukajtis	    : "r" (i)
19425c28e8Piotr Jasiukajtis	    : "cc");
19525c28e8Piotr Jasiukajtis
19625c28e8Piotr Jasiukajtis	return (ret);
19725c28e8Piotr Jasiukajtis}
19825c28e8Piotr Jasiukajtis
19925c28e8Piotr Jasiukajtis/*
20025c28e8Piotr Jasiukajtis * On the SPARC, __swapRP is a no-op; always return 0 for backward
20125c28e8Piotr Jasiukajtis * compatibility
20225c28e8Piotr Jasiukajtis */
20325c28e8Piotr Jasiukajtis/* ARGSUSED */
2047f11fd0Richard Loweextern __GNU_INLINE enum fp_precision_type
20525c28e8Piotr Jasiukajtis__swapRP(enum fp_precision_type i)
20625c28e8Piotr Jasiukajtis{
20725c28e8Piotr Jasiukajtis	return (0);
20825c28e8Piotr Jasiukajtis}
20925c28e8Piotr Jasiukajtis
2107f11fd0Richard Loweextern __GNU_INLINE enum fp_direction_type
21125c28e8Piotr Jasiukajtis__swapRD(enum fp_direction_type d)
21225c28e8Piotr Jasiukajtis{
21325c28e8Piotr Jasiukajtis	enum fp_direction_type ret;
21425c28e8Piotr Jasiukajtis	uint32_t fsr;
21525c28e8Piotr Jasiukajtis	uint32_t tmp1, tmp2, tmp3;
21625c28e8Piotr Jasiukajtis
21725c28e8Piotr Jasiukajtis	__asm__ __volatile__(
21825c28e8Piotr Jasiukajtis	    "and  %5,0x3,%0\n\t"
21925c28e8Piotr Jasiukajtis	    "sll  %0,30,%2\n\t"		/* shift input to RD bit location */
22025c28e8Piotr Jasiukajtis	    ".volatile\n\t"
22125c28e8Piotr Jasiukajtis	    "st   %%fsr,%1\n\t"
22225c28e8Piotr Jasiukajtis	    "ld	  %1,%0\n\t"		/* %0 = fsr */
22325c28e8Piotr Jasiukajtis	    "set  0xc0000000,%4\n\t"	/* mask of rounding direction bits */
22425c28e8Piotr Jasiukajtis	    "andn %0,%4,%3\n\t"
22525c28e8Piotr Jasiukajtis	    "or   %2,%3,%2\n\t"		/* %2 = new fsr */
22625c28e8Piotr Jasiukajtis	    "st	  %2,%1\n\t"
22725c28e8Piotr Jasiukajtis	    "ld	  %1,%%fsr\n\t"
22825c28e8Piotr Jasiukajtis	    "srl  %0,30,%0\n\t"
22925c28e8Piotr Jasiukajtis	    "and  %0,0x3,%0\n\t"
23025c28e8Piotr Jasiukajtis	    ".nonvolatile\n\t"
23125c28e8Piotr Jasiukajtis	    : "=r" (ret), "=m" (fsr), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)
23225c28e8Piotr Jasiukajtis	    : "r" (d)
23325c28e8Piotr Jasiukajtis	    : "cc");
23425c28e8Piotr Jasiukajtis
23525c28e8Piotr Jasiukajtis	return (ret);
23625c28e8Piotr Jasiukajtis}
23725c28e8Piotr Jasiukajtis
2387f11fd0Richard Loweextern __GNU_INLINE int
23925c28e8Piotr Jasiukajtis__swapTE(int i)
24025c28e8Piotr Jasiukajtis{
24125c28e8Piotr Jasiukajtis	int ret;
24225c28e8Piotr Jasiukajtis	uint32_t fsr, tmp1, tmp2;
24325c28e8Piotr Jasiukajtis
24425c28e8Piotr Jasiukajtis	__asm__ __volatile__(
24525c28e8Piotr Jasiukajtis	    "and  %4,0x1f,%0\n\t"
24625c28e8Piotr Jasiukajtis	    "sll  %0,23,%2\n\t"		/* shift input to TEM bit location */
24725c28e8Piotr Jasiukajtis	    ".volatile\n\t"
24825c28e8Piotr Jasiukajtis	    "st   %%fsr,%1\n\t"
24925c28e8Piotr Jasiukajtis	    "ld	  %1,%0\n\t"		/* %0 = fsr */
25025c28e8Piotr Jasiukajtis	    "set  0x0f800000,%3\n\t"	/* mask of TEM (Trap Enable Mode bits) */
25125c28e8Piotr Jasiukajtis	    "andn %0,%3,%3\n\t"
25225c28e8Piotr Jasiukajtis	    "or   %2,%3,%2\n\t"		/* %2 = new fsr */
25325c28e8Piotr Jasiukajtis	    "st	  %2,%1\n\t"
25425c28e8Piotr Jasiukajtis	    "ld	  %1,%%fsr\n\t"
25525c28e8Piotr Jasiukajtis	    "srl  %0,23,%0\n\t"
25625c28e8Piotr Jasiukajtis	    "and  %0,0x1f,%0\n\t"
25725c28e8Piotr Jasiukajtis	    ".nonvolatile\n\t"
25825c28e8Piotr Jasiukajtis	    : "=r" (ret), "=m" (fsr), "=r" (tmp1), "=r" (tmp2)
25925c28e8Piotr Jasiukajtis	    : "r" (i)
26025c28e8Piotr Jasiukajtis	    : "cc");
26125c28e8Piotr Jasiukajtis
26225c28e8Piotr Jasiukajtis	return (ret);
26325c28e8Piotr Jasiukajtis}
26425c28e8Piotr Jasiukajtis
2657f11fd0Richard Loweextern __GNU_INLINE double
26625c28e8Piotr Jasiukajtissqrt(double d)
26725c28e8Piotr Jasiukajtis{
26825c28e8Piotr Jasiukajtis	return (__inline_sqrt(d));
26925c28e8Piotr Jasiukajtis}
27025c28e8Piotr Jasiukajtis
2717f11fd0Richard Loweextern __GNU_INLINE float
27225c28e8Piotr Jasiukajtissqrtf(float f)
27325c28e8Piotr Jasiukajtis{
27425c28e8Piotr Jasiukajtis	return (__inline_sqrtf(f));
27525c28e8Piotr Jasiukajtis}
27625c28e8Piotr Jasiukajtis
2777f11fd0Richard Loweextern __GNU_INLINE double
27825c28e8Piotr Jasiukajtisfabs(double d)
27925c28e8Piotr Jasiukajtis{
28025c28e8Piotr Jasiukajtis	double ret;
28125c28e8Piotr Jasiukajtis
28225c28e8Piotr Jasiukajtis	__asm__ __volatile__("fabsd %1,%0\n\t" : "=e" (ret) : "e" (d));
28325c28e8Piotr Jasiukajtis	return (ret);
28425c28e8Piotr Jasiukajtis}
28525c28e8Piotr Jasiukajtis
2867f11fd0Richard Loweextern __GNU_INLINE float
28725c28e8Piotr Jasiukajtisfabsf(float f)
28825c28e8Piotr Jasiukajtis{
28925c28e8Piotr Jasiukajtis	float ret;
29025c28e8Piotr Jasiukajtis
29125c28e8Piotr Jasiukajtis	__asm__ __volatile__("fabss %1,%0\n\t" : "=f" (ret) : "f" (f));
29225c28e8Piotr Jasiukajtis	return (ret);
29325c28e8Piotr Jasiukajtis}
29425c28e8Piotr Jasiukajtis
29525c28e8Piotr Jasiukajtis#ifdef __cplusplus
29625c28e8Piotr Jasiukajtis}
29725c28e8Piotr Jasiukajtis#endif
29825c28e8Piotr Jasiukajtis
29925c28e8Piotr Jasiukajtis#endif	/* __GNUC */
30025c28e8Piotr Jasiukajtis
30125c28e8Piotr Jasiukajtis#endif /* _LIBM_INLINES_H */