1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain.
4 *
5 * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>.
6 *
7 * Correct handling of y==-inf <drepper@gnu>
8 */
9
10#include <machine/asm.h>
11
12RCSID("$NetBSD: $")
13
14#ifdef __ELF__
15	.section .rodata
16#else
17	.text
18#endif
19
20	.align ALIGNARG(4)
21	ASM_TYPE_DIRECTIVE(zero_nan,@object)
22zero_nan:
23	.double 0.0
24nan:	.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
25minus_zero:
26	.byte 0, 0, 0, 0, 0, 0, 0, 0x80
27	.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
28	ASM_SIZE_DIRECTIVE(zero_nan)
29
30
31#ifdef PIC
32#define MO(op) op##@GOTOFF(%ecx)
33#define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
34#else
35#define MO(op) op
36#define MOX(op,x,f) op(,x,f)
37#endif
38
39	.text
40ENTRY(__ieee754_scalbl)
41	fldt	16(%esp)
42	fxam
43	fnstsw
44	fldt	4(%esp)
45	andl	$0x4700, %eax
46	cmpl	$0x0700, %eax
47	je	1f
48	andl	$0x4500, %eax
49	cmpl	$0x0100, %eax
50	je	2f
51	fxam
52	fnstsw
53	andl	$0x4500, %eax
54	cmpl	$0x0100, %eax
55	je	3f
56	fld	%st(1)
57	frndint
58	fcomp	%st(2)
59	fnstsw
60	sahf
61	jne	4f
62	fscale
63	fstp	%st(1)
64	ret
65
66	/* y is -inf */
671:	fxam
68#ifdef  PIC
69        call    1f
701:      popl    %ecx
71        addl    $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
72#endif
73	fnstsw
74	movl	12(%esp), %edx
75	shrl	$5, %eax
76	fstp	%st
77	fstp	%st
78	andl	$0x8000, %edx
79	andl	$8, %eax
80	jnz	4f
81	shrl	$11, %edx
82	addl	%edx, %eax
83	fldl	MOX(zero_nan, %eax, 1)
84	ret
85
86	/* The result is NaN, but we must not raise an exception.
87	   So use a variable.  */
882:	fstp	%st
89	fstp	%st
90#ifdef  PIC
91        call    1f
921:      popl    %ecx
93        addl    $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
94#endif
95	fldl	MO(nan)
96	ret
97
98	/* The first parameter is a NaN.  Return it.  */
993:	fstp	%st(1)
100	ret
101
102	/* Return NaN and raise the invalid exception.  */
1034:	fstp	%st
104	fstp	%st
105	fldz
106	fdiv	%st
107	ret
108END(__ieee754_scalbl)
109