xref: /illumos-gate/usr/src/lib/libm/i386/src/rndintl.S (revision 5d9d9091f564c198a760790b0bfa72c44e17912b)
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 "rndintl.s"
30
31#include "libm.h"
32
33	ENTRY(aintl)
34	movl	%esp,%eax
35	subl	$8,%esp
36	fstcw	-8(%eax)
37	fldt	4(%eax)
38	movw	-8(%eax),%cx
39	orw	$0x0c00,%cx
40	movw	%cx,-4(%eax)
41	fldcw	-4(%eax)		/ set RD = to_zero
42	frndint
43	fstcw	-4(%eax)
44	movw	-4(%eax),%dx
45	andw	$0xf3ff,%dx
46	movw	-8(%eax),%cx
47	andw	$0x0c00,%cx
48	orw	%dx,%cx
49	movw	%cx,-8(%eax)
50	fldcw	-8(%eax)		/ restore RD
51	addl	$8,%esp
52	ret
53	.align	4
54	SET_SIZE(aintl)
55
56	ENTRY(irintl)
57	movl	%esp,%ecx
58	subl	$8,%esp
59	fldt	4(%ecx)			/ load x
60	fistpl	-8(%ecx)		/ [x]
61	fwait
62	movl	-8(%ecx),%eax
63	addl	$8,%esp
64	ret
65	.align	4
66	SET_SIZE(irintl)
67
68	.data
69	.align	4
70half:	.float	0.5
71
72	ENTRY(anintl)
73.Lanintl:
74	movl	%esp,%ecx
75	subl	$8,%esp
76	fstcw	-8(%ecx)
77	fldt	4(%ecx)
78	movw	-8(%ecx),%dx
79	andw	$0xf3ff,%dx
80	movw	%dx,-4(%ecx)
81	fldcw	-4(%ecx)		/ set RD = to_nearest
82	fld	%st(0)
83	frndint				/ [x],x
84	fstcw	-4(%ecx)
85	movw	-4(%ecx),%dx
86	andw	$0xf3ff,%dx
87	movw	-8(%ecx),%ax
88	andw	$0x0c00,%ax
89	orw	%dx,%ax
90	movw	%ax,-8(%ecx)
91	fldcw	-8(%ecx)		/ restore RD
92	fucom				/ check if x is already an integer
93	fstsw	%ax
94	sahf
95	jp	.L0
96	je	.L0
97	fxch				/ x,[x]
98	fsub	%st(1),%st		/ x-[x],[x]
99	fabs				/ |x-[x]|,[x]
100	PIC_SETUP(1)
101	fcoms	PIC_L(half)
102	PIC_WRAPUP
103	fnstsw	%ax
104	sahf
105	jae	.halfway		/ if |x-[x]| = 0.5 goto halfway,
106					/ most cases will not take branch.
107.L0:
108	addl	$8,%esp
109	fstp	%st(0)
110	ret
111.halfway:
112	/ x = n+0.5, recompute anint(x) as x+sign(x)*0.5
113	fldt	4(%ecx)			/ x, 0.5, [x]
114	movw	12(%ecx),%ax		/ sign+exp part of x
115	andw	$0x8000,%ax		/ look at sign bit
116	jnz	.x_neg
117	faddp
118	addl	$8,%esp
119	fstp	%st(1)
120	ret
121.x_neg:
122	/ here, x is negative, so return x-0.5
123	fsubp	%st,%st(1)		/ x-0.5,[x]
124	addl	$8,%esp
125	fstp	%st(1)
126	ret
127	.align	4
128	SET_SIZE(anintl)
129
130	ENTRY(nintl)
131	pushl	%ebp
132	movl	%esp,%ebp
133	subl	$8,%esp
134	pushl	16(%ebp)
135	pushl	12(%ebp)
136	pushl	8(%ebp)
137	call	.Lanintl		/// LOCAL
138	fistpl	-8(%ebp)
139	fwait
140	movl	-8(%ebp),%eax
141	leave
142	ret
143	.align	4
144	SET_SIZE(nintl)
145