xref: /illumos-gate/usr/src/lib/crt/i386/fsr.S (revision 012e6ce759c490003aed29439cc47d3d73a99ad3)
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, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#include <sys/asm_linkage.h>
28
29	.file	"fsr.s"
30	.ident	""
31
32	.section	.data
33	.align 4
34
35/*
36 * The following table maps trap enable bits in __fsr_init_value
37 * (after shifting right one bit):
38 *
39 * bit 0 - inexact trap
40 * bit 1 - division trap
41 * bit 2 - underflow trap
42 * bit 3 - overflow trap
43 * bit 4 - invalid trap
44 *
45 * to exception masks in the floating point control word
46 *
47 * bit 0 - invalid mask
48 * bit 2 - zero divide mask
49 * bit 3 - overflow mask
50 * bit 4 - underflow mask
51 * bit 5 - inexact mask
52 */
53	.local	trap_table
54	.type	trap_table,@object
55trap_table:
56	.byte	0b11111111
57	.byte	0b11011111
58	.byte	0b11111011
59	.byte	0b11011011
60	.byte	0b11101111
61	.byte	0b11001111
62	.byte	0b11101011
63	.byte	0b11001011
64	.byte	0b11110111
65	.byte	0b11010111
66	.byte	0b11110011
67	.byte	0b11010011
68	.byte	0b11100111
69	.byte	0b11000111
70	.byte	0b11100011
71	.byte	0b11000011
72	.byte	0b11111110
73	.byte	0b11011110
74	.byte	0b11111010
75	.byte	0b11011010
76	.byte	0b11101110
77	.byte	0b11001110
78	.byte	0b11101010
79	.byte	0b11001010
80	.byte	0b11110110
81	.byte	0b11010110
82	.byte	0b11110010
83	.byte	0b11010010
84	.byte	0b11100110
85	.byte	0b11000110
86	.byte	0b11100010
87	.byte	0b11000010
88
89	.size	trap_table,32
90
91ENTRY_NP(__fsr)
92	pushl	%ebp
93	movl	%esp,%ebp
94	pushl	%edx
95	pushl	%ecx
96	pushl	%ebx
97	subl	$4,%esp
98
99	/* Setup PIC */
100	call	9f
1019:	popl	%ebx
102	addl	$_GLOBAL_OFFSET_TABLE_ + [. - 9b], %ebx
103
104	movl	8(%ebp), %ecx		/* the value set by CG is passed in */
105	shrl	$1,%ecx			/* get rid of fns bit */
106	cmpl	$0,%ecx			/* if remaining bits are zero */
107	je	3f			/*   there's nothing to do */
108
109	fstcw	0(%esp)			/* store the control word */
110
111	movl	%ecx,%edx
112	andl	$0x1f,%edx		/* get the trap enable bits */
113	movl	trap_table@GOT(%ebx), %eax
114	addl	%eax,%edx
115	movb	(%edx),%al
116	andb	%al,0(%esp)	/* unmask the corresponding exceptions */
117
118	testl	$0x200,%ecx		/* test denormal trap enable */
119	jz	1f			/* skip if zero */
120
121	andb	$0xfd,0(%esp)	/* unmask denormal exception */
122
1231:
124	movl	%ecx,%edx
125	andl	$0x60,%edx		/* get the rounding direction */
126	jz	1f			/* skip if zero */
127
128	movl	%edx,%eax		/* exchange negative<->tozero */
129	andl	$0x20,%eax		/*   leaving nearest and positive */
130	shll	$1,%eax			/*   as is */
131	xorl	%eax,%edx
132	shll	$5,%edx
133	andw	$0xf3ff,0(%esp)		/* update rounding direction */
134	orw	%dx,0(%esp)
135
1361:
137	andl	$0x180,%ecx		/* get the rounding precision */
138	jz	1f			/* skip if zero */
139
140	xorl	$0x180,%ecx		/* reverse bits */
141	shll	$1,%ecx
142	andw	$0xfcff,0(%esp)		/* update rounding precision */
143	orw	%cx,0(%esp)
144
1451:
146	fldcw	0(%esp)			/* load the modified control word */
147
1483:
149	addl	$4,%esp
150	popl	%ebx
151	popl	%ecx
152	popl	%edx
153	popl	%ebp
154	ret
155SET_SIZE(__fsr)
156