xref: /illumos-gate/usr/src/lib/libm/i386/src/hypot.s (revision ddc0e0b5)
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 "hypot.s"
30
31#include "libm.h"
32LIBM_ANSI_PRAGMA_WEAK(hypot,function)
33#include "libm_protos.h"
34
35	.data
36	.align	4
37inf:
38	.long	0x7f800000
39
40	ENTRY(hypot)
41	movl	8(%esp),%eax		/ eax <-- hi_32(x)
42	andl	$0x7fffffff,%eax	/ eax <-- hi_32(|x|)
43	jz	.x_maybe_0		/ if x = +/-0, return |y|
44	subl	$0x7ff00000,%eax	/ eax <-- hi_32(|x|) - hi_32(INF)
45	jz	.x_maybe_inf
46.check_y:
47	movl	16(%esp),%eax		/ eax <-- hi_32(y)
48	andl	$0x7fffffff,%eax	/ eax <-- hi_32(|y|)
49	jz	.y_maybe_0		/ if y = +/-0, return |x|
50	subl	$0x7ff00000,%eax	/ eax <-- hi_32(|y|) - hi_32(INF)
51	jz	.y_maybe_inf
52.do_hypot:
53	fldl	12(%esp)		/ ,y
54	fmul	%st(0),%st		/ ,y*y
55	fldl	4(%esp)			/ x,y*y
56	fmul	%st(0),%st		/ x*x,y*y
57	faddp	%st,%st(1)		/ x*x+y*y
58	fsqrt				/ sqrt(x*x+y*y)
59	subl	$8,%esp
60	fstpl	(%esp)			/ round to double
61	fldl	(%esp)			/ sqrt(x*x+y*y) rounded to double
62	PIC_SETUP(1)
63	flds	PIC_L(inf)		/ inf , sqrt(x*x+y*y)
64	PIC_WRAPUP
65	addl	$8,%esp
66	fucomp
67	fstsw	%ax			/ store status in %ax
68	sahf				/ 80387 flags in %ah to 80386 flags
69	jz	.maybe_ovflw
70	ret
71
72.maybe_ovflw:
73	jnp	.ovflw
74	ret
75
76.ovflw:
77	/	overflow occurred
78	fstp	%st(0)			/ stack empty
79	pushl	%ebp
80	movl	%esp,%ebp
81	PIC_SETUP(2)
82	pushl	$4
83	pushl	20(%ebp)		/ high y
84	pushl	16(%ebp)		/ low y
85	pushl	12(%ebp)		/ high x
86	pushl	8(%ebp)			/ low x
87	call	PIC_F(_SVID_libm_err)
88	addl	$20,%esp
89	PIC_WRAPUP
90	leave
91	ret
92
93.x_maybe_0:
94	movl	4(%esp),%ecx		/ ecx <-- lo_32(x)
95	orl	%ecx,%eax		/ is x = +/-0?
96	jnz	.check_y		/ branch if x is denormal
97	/  x = +/-0, so return |y|
98	fldl	12(%esp)
99	fabs
100	ret
101
102.x_maybe_inf:
103	movl	4(%esp),%ecx		/ ecx <-- lo_32(x)
104	orl	%ecx,%eax		/ is x = +/-INF?
105	jnz	.check_y		/ branch if x is NaN
106	/ push&pop y in case y is a SNaN
107	fldl	12(%esp)
108	fstp	%st(0)
109	/ x = +/-INF, so return |x|
110	fldl	4(%esp)
111	fabs
112	ret
113
114.y_maybe_0:
115	movl	12(%esp),%ecx		/ ecx <-- lo_32(y)
116	orl	%ecx,%eax		/ is y = +/-0?
117	jnz	.do_hypot		/ branch if y is denormal
118	/  y = +/-0, so return |x|
119	fldl	4(%esp)
120	fabs
121	ret
122
123.y_maybe_inf:
124	movl	12(%esp),%ecx		/ ecx <-- lo_32(y)
125	orl	%ecx,%eax		/ is y = +/-INF?
126	jnz	.do_hypot		/ branch if y is NaN
127	/ push&pop x in case x is a SNaN
128	fldl	4(%esp)
129	fstp	%st(0)
130	/  y = +/-INF, so return |y|
131	fldl	12(%esp)
132	fabs
133	ret
134	.align	4
135	SET_SIZE(hypot)
136