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