1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
23 */
24/*
25 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
26 * Use is subject to license terms.
27 */
28
29	.file	"nexttowardl.s"
30
31#include "libm.h"
32LIBM_ANSI_PRAGMA_WEAK(nexttowardl,function)
33
34	.section .rodata
35	.align	4
36.LFmaxl:	.long	0xffffffff,0xffffffff,0x00007ffe
37.LFminl:	.long	0x1,0x0,0x0
38
39
40	ENTRY(nexttowardl)
41	pushl	%ebp
42	movl	%esp,%ebp
43	fldt	20(%ebp)	/ y
44	subl	$12,%esp
45	fldt	8(%ebp)		/ load x
46	fucom			/ x : y
47	fstsw	%ax
48	sahf
49	jp	.LNaN
50	je	.Lequal
51	fstp	%st(1)		/ x
52	ja	.Lbigger
53	/ x < y
54	ftst
55	movl	$1,-12(%ebp)	/// -12(%ebp) contains Fminl
56	movl	$0,-8(%ebp)
57	movl	$0,%ecx			/// final needs this
58	movl	%ecx,-4(%ebp)
59	fnstsw	%ax
60	sahf
61	je	.Lfinal
62	ja	.Laddulp
63	jb	.Lsubulp
64.Lbigger:
65	/ x > y
66	ftst
67	movl	$1,-12(%ebp)	/// -12(%ebp) contains -Fminl
68	movl	$0,-8(%ebp)
69	movl	$0x00008000,%ecx	/// final needs this
70	movl	%ecx,-4(%ebp)
71	fnstsw	%ax
72	sahf
73	je	.Lfinal
74	jb	.Laddulp
75.Lsubulp:
76	movl	12(%ebp),%edx	/ high word of significand of x
77	movl	16(%ebp),%ecx	/ x's exponent
78	andl	$0x0000ffff,%ecx
79	movl	%edx,%eax
80	not	%eax
81	andl	$0x80000000,%eax	/ look at explicit leading bit
82	orl	%ecx,%eax
83	andl	$0x80007fff,%eax
84	jnz	.Lnot_pseudonormal	/ zero value implies pseudonormal
85	addl	$1,%ecx		/ if pseudonormal, turn into equivalent normal
86.Lnot_pseudonormal:
87	movl	8(%ebp),%eax	/ low x
88	subl	$1,%eax		/ low x - ulp
89	movl	%eax,-12(%ebp)
90	cmpl	$0xffffffff,%eax	/ this means low x was 0
91	jz	.Lborrow
92	movl	%edx,-8(%ebp)
93	movl	%ecx,-4(%ebp)
94	jmp	.Lfinal
95.Lborrow:
96	cmpl	$0x80000000,%edx	/ look at high x
97	je	.Lsecond_borrow
98	subl	$1,%edx
99	movl	%edx,-8(%ebp)
100	movl	%ecx,-4(%ebp)
101	jmp	.Lfinal
102.Lsecond_borrow:
103	movl	%ecx,%eax
104	andl	$0x7fff,%eax	/ look at exp x without sign bit
105	cmpl	$1,%eax
106	jbe	.Lsubnormal_result	/ exp > 1 ==> result will be normal
107	movl	$0xffffffff,-8(%ebp)
108	subl	$1,%ecx
109	movl	%ecx,-4(%ebp)
110	jmp	.Lfinal
111.Lsubnormal_result:
112	movl	$0x7fffffff,-8(%ebp)
113	movl	%ecx,%eax
114	andl	$0x8000,%eax	/ look at sign bit
115	jz	.Lpositive
116	movl	$0x8000,%ecx
117	movl	%ecx,-4(%ebp)
118	jmp	.Lfinal
119.Lpositive:
120	movl	$0,%ecx
121	movl	%ecx,-4(%ebp)
122	jmp	.Lfinal
123.Laddulp:
124	movl	12(%ebp),%edx	/ high x
125	movl	16(%ebp),%ecx	/ x's exponent
126	andl	$0x0000ffff,%ecx
127	movl	%edx,%eax
128	not	%eax
129	andl	$0x80000000,%eax	/ look at explicit leading bit
130	orl	%ecx,%eax
131	andl	$0x80007fff,%eax
132	jnz	.Lnot_pseudonormal_2	/ zero value implies pseudonormal
133	addl	$1,%ecx
134.Lnot_pseudonormal_2:
135	movl	8(%ebp),%eax	/ low x
136	addl	$1,%eax		/ low x + ulp
137	movl	%eax,-12(%ebp)
138	jz	.Lcarry		/ jump if the content of %eax is 0
139	movl	%edx,-8(%ebp)
140	movl	%ecx,-4(%ebp)
141	jmp .Lfinal
142.Lcarry:
143	movl	%edx,%eax
144	andl	$0x7fffffff,%eax
145	cmpl	$0x7fffffff,%eax	/ look at high x
146	je	.Lsecond_carry
147	addl	$1,%edx
148	movl	%edx,-8(%ebp)
149	movl	%ecx,-4(%ebp)
150	jmp	.Lfinal
151.Lsecond_carry:
152	movl	$0x80000000,-8(%ebp)
153	addl	$1,%ecx
154	movl	%ecx,-4(%ebp)
155.Lfinal:
156	fstp	%st(0)
157	fldt	-12(%ebp)
158	andl	$0x00007fff,%ecx
159	jz	.Lunderflow
160	cmpw	$0x7fff,%cx
161	je	.Loverflow
162	jmp	.Lreturn
163.Loverflow:
164	PIC_SETUP(1)
165	fldt	PIC_L(.LFmaxl)
166	PIC_WRAPUP
167	fmulp	%st,%st(0)	/ create overflow signal
168	jmp	.Lreturn
169.Lunderflow:
170	PIC_SETUP(2)
171	fldt	PIC_L(.LFminl)
172	PIC_WRAPUP
173	fmulp	%st,%st(0)	/ create underflow signal
174	jmp	.Lreturn
175.Lequal:
176	fstp	%st(0)		/ C99 says to return y when x == y
177	jmp	.Lreturn
178.LNaN:
179	faddp	%st,%st(1)	/ x+y,x
180.Lreturn:
181	fwait
182	leave
183	ret
184	.align	4
185	SET_SIZE(nexttowardl)
186