Blame sysdeps/i386/fpu/s_asinhl.S

Packit 6c4009
/* ix87 specific implementation of arcsinh.
Packit 6c4009
   Copyright (C) 1996-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <libm-alias-ldouble.h>
Packit 6c4009
#include <machine/asm.h>
Packit 6c4009
Packit 6c4009
	.section .rodata
Packit 6c4009
Packit 6c4009
	.align ALIGNARG(4)
Packit 6c4009
	.type huge,@object
Packit 6c4009
huge:	.tfloat 1e+4930
Packit 6c4009
	ASM_SIZE_DIRECTIVE(huge)
Packit 6c4009
	.align ALIGNARG(4)
Packit 6c4009
	/* Please note that we use double value for 1.0.  This number
Packit 6c4009
	   has an exact representation and so we don't get accuracy
Packit 6c4009
	   problems.  The advantage is that the code is simpler.  */
Packit 6c4009
	.type one,@object
Packit 6c4009
one:	.double 1.0
Packit 6c4009
	ASM_SIZE_DIRECTIVE(one)
Packit 6c4009
	/* It is not important that this constant is precise.  It is only
Packit 6c4009
	   a value which is known to be on the safe side for using the
Packit 6c4009
	   fyl2xp1 instruction.  */
Packit 6c4009
	.type limit,@object
Packit 6c4009
limit:	.double 0.29
Packit 6c4009
	ASM_SIZE_DIRECTIVE(limit)
Packit 6c4009
Packit 6c4009
#ifdef PIC
Packit 6c4009
#define MO(op) op##@GOTOFF(%edx)
Packit 6c4009
#else
Packit 6c4009
#define MO(op) op
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
	.text
Packit 6c4009
ENTRY(__asinhl)
Packit 6c4009
	movl	12(%esp), %ecx
Packit 6c4009
	movl	$0x7fff, %eax
Packit 6c4009
	andl	%ecx, %eax
Packit 6c4009
	andl	$0x8000, %ecx
Packit 6c4009
	movl	%eax, %edx
Packit 6c4009
	orl	$0xffff8000, %edx
Packit 6c4009
	incl	%edx
Packit 6c4009
	jz	7f			// x in ±Inf or NaN
Packit 6c4009
	xorl	%ecx, 12(%esp)
Packit 6c4009
	fldt	4(%esp)			// |x|
Packit 6c4009
	cmpl	$0x3fde, %eax
Packit 6c4009
	jb	2f			// |x| < 2^-34
Packit 6c4009
	fldln2				// log(2) : |x|
Packit 6c4009
	cmpl	$0x4020, %eax
Packit 6c4009
	fxch				// |x| : log(2)
Packit 6c4009
	ja	3f			// |x| > 2^34
Packit 6c4009
#ifdef	PIC
Packit 6c4009
	LOAD_PIC_REG (dx)
Packit 6c4009
#endif
Packit 6c4009
	cmpl	$0x4000, %eax
Packit 6c4009
	ja	5f			// |x| > 2
Packit 6c4009
Packit 6c4009
	// 2^-34 <= |x| <= 2 => y = sign(x)*log1p(|x|+|x|^2/(1+sqrt(1+|x|^2)))
Packit 6c4009
	fld	%st			// |x| : |x| : log(2)
Packit 6c4009
	fmul	%st(1)			// |x|^2 : |x| : log(2)
Packit 6c4009
	fld	%st			// |x|^2 : |x|^2 : |x| : log(2)
Packit 6c4009
	faddl	MO(one)			// 1+|x|^2 : |x|^2 : |x| : log(2)
Packit 6c4009
	fsqrt				// sqrt(1+|x|^2) : |x|^2 : |x| : log(2)
Packit 6c4009
	faddl	MO(one)			// 1+sqrt(1+|x|^2) : |x|^2 : |x| : log(2)
Packit 6c4009
	fdivrp				// |x|^2/(1+sqrt(1+|x|^2)) : |x| : log(2)
Packit 6c4009
	faddp				// |x|+|x|^2/(1+sqrt(1+|x|^2)) : log(2)
Packit 6c4009
	fcoml	MO(limit)
Packit 6c4009
	fnstsw
Packit 6c4009
	sahf
Packit 6c4009
	ja	6f
Packit 6c4009
	fyl2xp1
Packit 6c4009
	jecxz	4f
Packit 6c4009
	fchs
Packit 6c4009
4:	ret
Packit 6c4009
Packit 6c4009
7:	fldt	4(%esp)
Packit 6c4009
	fadd	%st
Packit 6c4009
	ret
Packit 6c4009
Packit 6c4009
6:	faddl	MO(one)
Packit 6c4009
	fyl2x
Packit 6c4009
	jecxz	4f
Packit 6c4009
	fchs
Packit 6c4009
4:	ret
Packit 6c4009
Packit 6c4009
	// |x| < 2^-34 => y = x (inexact iff |x| != 0.0)
Packit 6c4009
	.align ALIGNARG(4)
Packit 6c4009
2:
Packit 6c4009
#ifdef	PIC
Packit 6c4009
	LOAD_PIC_REG (dx)
Packit 6c4009
#endif
Packit 6c4009
	jecxz	4f
Packit 6c4009
	fchs				// x
Packit 6c4009
4:	fld	%st			// x : x
Packit 6c4009
	fldt	MO(huge)		// huge : x : x
Packit 6c4009
	faddp				// huge+x : x
Packit 6c4009
	fstp	%st(0)			// x
Packit 6c4009
	cmpl	$0x0001, %eax
Packit 6c4009
	jae	8f
Packit 6c4009
	fld	%st(0)
Packit 6c4009
	fmul	%st(0)
Packit 6c4009
	fstp	%st(0)
Packit 6c4009
8:	ret
Packit 6c4009
Packit 6c4009
	// |x| > 2^34 => y = sign(x) * (log(|x|) + log(2))
Packit 6c4009
	.align ALIGNARG(4)
Packit 6c4009
3:	fyl2x				// log(|x|)
Packit 6c4009
	fldln2				// log(2) : log(|x|)
Packit 6c4009
	faddp				// log(|x|)+log(2)
Packit 6c4009
	jecxz	4f
Packit 6c4009
	fchs
Packit 6c4009
4:	ret
Packit 6c4009
Packit 6c4009
	// |x| > 2 => y = sign(x) * log(2*|x| + 1/(|x|+sqrt(x*x+1)))
Packit 6c4009
	.align ALIGNARG(4)
Packit 6c4009
5:	fld	%st			// |x| : |x| : log(2)
Packit 6c4009
	fadd	%st, %st(1)		// |x| : 2*|x| : log(2)
Packit 6c4009
	fld	%st			// |x| : |x| : 2*|x| : log(2)
Packit 6c4009
	fmul	%st(1)			// |x|^2 : |x| : 2*|x| : log(2)
Packit 6c4009
	faddl	MO(one)			// 1+|x|^2 : |x| : 2*|x| : log(2)
Packit 6c4009
	fsqrt				// sqrt(1+|x|^2) : |x| : 2*|x| : log(2)
Packit 6c4009
	faddp				// |x|+sqrt(1+|x|^2) : 2*|x| : log(2)
Packit 6c4009
	fdivrl	MO(one)			// 1/(|x|+sqrt(1+|x|^2)) : 2*|x| : log(2)
Packit 6c4009
	faddp				// 2*|x|+1/(|x|+sqrt(1+|x|^2)) : log(2)
Packit 6c4009
	fyl2x				// log(2*|x|+1/(|x|+sqrt(1+|x|^2)))
Packit 6c4009
	jecxz	4f
Packit 6c4009
	fchs
Packit 6c4009
4:	ret
Packit 6c4009
END(__asinhl)
Packit 6c4009
libm_alias_ldouble (__asinh, asinh)