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 */
8
9#include <machine/asm.h>
10
11#ifdef __ELF__
12	.section .rodata
13#else
14	.text
15#endif
16	.align ALIGNARG(4)
17	ASM_TYPE_DIRECTIVE(one,@object)
18one:	.double 1.0
19	ASM_SIZE_DIRECTIVE(one)
20	/* It is not important that this constant is precise.  It is only
21	   a value which is known to be on the safe side for using the
22	   fyl2xp1 instruction.  */
23	ASM_TYPE_DIRECTIVE(limit,@object)
24limit:	.double 0.29
25	ASM_SIZE_DIRECTIVE(limit)
26
27
28#ifdef PIC
29#define MO(op) op##@GOTOFF(%edx)
30#else
31#define MO(op) op
32#endif
33
34	.text
35ENTRY(__ieee754_log2f)
36#ifdef PIC
37	call	1f
381:	popl	%edx
39	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %edx
40#endif
41	fldl	MO(one)
42	flds	4(%esp)		// x : 1
43	fxam
44	fnstsw
45	fld	%st		// x : x : 1
46	sahf
47	jc	3f		// in case x is NaN or �Inf
484:	fsub	%st(2), %st	// x-1 : x : 1
49	fld	%st		// x-1 : x-1 : x : 1
50	fabs			// |x-1| : x-1 : x : 1
51	fcompl	MO(limit)	// x-1 : x : 1
52	fnstsw			// x-1 : x : 1
53	andb	$0x45, %ah
54	jz	2f
55	fstp	%st(1)		// x-1 : 1
56	fyl2xp1			// log(x)
57	ret
58
592:	fstp	%st(0)		// x : 1
60	fyl2x			// log(x)
61	ret
62
633:	jp	4b		// in case x is �Inf
64	fstp	%st(1)
65	fstp	%st(1)
66	ret
67END (__ieee754_log2f)
68