1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Adapted for use as log2 by Ulrich Drepper <drepper@cygnus.com>.
4 * Public domain.
5 *
6 * Changed to use fyl2xp1 for values near 1, <drepper@cygnus.com>.
7 * Adapted for x86-64 by Andreas Jaeger <aj@suse.de>.
8 */
9
10#include <machine/asm.h>
11
12#ifdef __ELF__
13	.section .rodata
14#else
15	.text
16#endif
17	.align ALIGNARG(4)
18	ASM_TYPE_DIRECTIVE(one,@object)
19one:	.double 1.0
20	ASM_SIZE_DIRECTIVE(one)
21	/* It is not important that this constant is precise.  It is only
22	   a value which is known to be on the safe side for using the
23	   fyl2xp1 instruction.  */
24	ASM_TYPE_DIRECTIVE(limit,@object)
25limit:	.double 0.29
26	ASM_SIZE_DIRECTIVE(limit)
27
28
29#ifdef PIC
30#define MO(op) op##(%rip)
31#else
32#define MO(op) op
33#endif
34
35	.text
36ENTRY(__ieee754_log2l)
37	fldl	MO(one)
38	fldt	8(%rsp)		// x : 1
39	fxam
40	fnstsw
41	fld	%st		// x : x : 1
42	testb	$1, %ah
43	jnz	3f		// in case x is NaN or �Inf
444:	fsub	%st(2), %st	// x-1 : x : 1
45	fld	%st		// x-1 : x-1 : x : 1
46	fabs			// |x-1| : x-1 : x : 1
47	fcompl	MO(limit)	// x-1 : x : 1
48	fnstsw			// x-1 : x : 1
49	andb	$0x45, %ah
50	jz	2f
51	fstp	%st(1)		// x-1 : 1
52	fyl2xp1			// log(x)
53	ret
54
552:	fstp	%st(0)		// x : 1
56	fyl2x			// log(x)
57	ret
58
593:	testb	$4, %ah
60	jnz	4b		// in case x is �Inf
61	fstp	%st(1)
62	fstp	%st(1)
63	ret
64END (__ieee754_log2l)
65