xref: /onnv-gate/usr/src/uts/intel/ia32/ml/float.s (revision 3446:5903aece022d)
10Sstevel@tonic-gate/*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*3446Smrj * Common Development and Distribution License (the "License").
6*3446Smrj * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*3446Smrj
220Sstevel@tonic-gate/*
23*3446Smrj * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate/*      Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
280Sstevel@tonic-gate/*      Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T   */
290Sstevel@tonic-gate/*        All Rights Reserved   */
300Sstevel@tonic-gate
310Sstevel@tonic-gate/*      Copyright (c) 1987, 1988 Microsoft Corporation  */
320Sstevel@tonic-gate/*        All Rights Reserved   */
330Sstevel@tonic-gate
340Sstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
350Sstevel@tonic-gate
360Sstevel@tonic-gate#include <sys/asm_linkage.h>
37*3446Smrj#include <sys/asm_misc.h>
380Sstevel@tonic-gate#include <sys/regset.h>
390Sstevel@tonic-gate#include <sys/privregs.h>
400Sstevel@tonic-gate#include <sys/x86_archext.h>
410Sstevel@tonic-gate
420Sstevel@tonic-gate#if defined(__lint)
430Sstevel@tonic-gate#include <sys/types.h>
440Sstevel@tonic-gate#include <sys/fp.h>
450Sstevel@tonic-gate#else
460Sstevel@tonic-gate#include "assym.h"
470Sstevel@tonic-gate#endif
480Sstevel@tonic-gate
490Sstevel@tonic-gate#if defined(__lint)
50*3446Smrj
51*3446Smrjuint_t
52*3446Smrjfpu_initial_probe(void)
53*3446Smrj{ return (0); }
540Sstevel@tonic-gate
550Sstevel@tonic-gate#else	/* __lint */
560Sstevel@tonic-gate
570Sstevel@tonic-gate	/*
58*3446Smrj	 * Returns zero if x87 "chip" is present(!)
590Sstevel@tonic-gate	 */
60*3446Smrj	ENTRY_NP(fpu_initial_probe)
61*3446Smrj	CLTS
62*3446Smrj	fninit
63*3446Smrj	fnstsw	%ax
64*3446Smrj	movzbl	%al, %eax
65*3446Smrj	ret
66*3446Smrj	SET_SIZE(fpu_initial_probe)
670Sstevel@tonic-gate
680Sstevel@tonic-gate#endif	/* __lint */
690Sstevel@tonic-gate
70*3446Smrj#if defined(__lint)
710Sstevel@tonic-gate
720Sstevel@tonic-gate/*ARGSUSED*/
730Sstevel@tonic-gatevoid
74*3446Smrjfxsave_insn(struct fxsave_state *fx)
750Sstevel@tonic-gate{}
760Sstevel@tonic-gate
770Sstevel@tonic-gate#else	/* __lint */
780Sstevel@tonic-gate
790Sstevel@tonic-gate#if defined(__amd64)
800Sstevel@tonic-gate
81*3446Smrj	ENTRY_NP(fxsave_insn)
82*3446Smrj	fxsave	(%rdi)
830Sstevel@tonic-gate	ret
84*3446Smrj	SET_SIZE(fxsave_insn)
850Sstevel@tonic-gate
860Sstevel@tonic-gate#elif defined(__i386)
870Sstevel@tonic-gate
88*3446Smrj	ENTRY_NP(fxsave_insn)
89*3446Smrj	movl	4(%esp), %eax
90*3446Smrj	fxsave	(%eax)
91*3446Smrj	ret
92*3446Smrj	SET_SIZE(fxsave_insn)
93*3446Smrj
94*3446Smrj#endif
95*3446Smrj
96*3446Smrj#endif	/* __lint */
97*3446Smrj
98*3446Smrj#if defined(__i386)
99*3446Smrj
100*3446Smrj/*
101*3446Smrj * If (num1/num2 > num1/num3) the FPU has the FDIV bug.
102*3446Smrj */
103*3446Smrj
104*3446Smrj#if defined(__lint)
105*3446Smrj
106*3446Smrjint
107*3446Smrjfpu_probe_pentium_fdivbug(void)
108*3446Smrj{ return (0); }
109*3446Smrj
110*3446Smrj#else	/* __lint */
111*3446Smrj
112*3446Smrj	ENTRY_NP(fpu_probe_pentium_fdivbug)
113*3446Smrj	fldl	.num1
114*3446Smrj	fldl	.num2
1150Sstevel@tonic-gate	fdivr	%st(1), %st
1160Sstevel@tonic-gate	fxch	%st(1)
117*3446Smrj	fdivl	.num3
1180Sstevel@tonic-gate	fcompp
1190Sstevel@tonic-gate	fstsw	%ax
1200Sstevel@tonic-gate	sahf
121*3446Smrj	jae	0f
122*3446Smrj	movl	$1, %eax
123*3446Smrj	ret
124*3446Smrj
125*3446Smrj0:	xorl	%eax, %eax
126*3446Smrj	ret
127*3446Smrj
128*3446Smrj	.align	4
129*3446Smrj.num1:	.4byte	0xbce4217d	/* 4.999999 */
130*3446Smrj	.4byte	0x4013ffff
131*3446Smrj.num2:	.4byte	0x0		/* 15.0 */
132*3446Smrj	.4byte	0x402e0000
133*3446Smrj.num3:	.4byte	0xde7210bf	/* 14.999999 */
134*3446Smrj	.4byte	0x402dffff
135*3446Smrj	SET_SIZE(fpu_probe_pentium_fdivbug)
136*3446Smrj
137*3446Smrj#endif	/* __lint */
1380Sstevel@tonic-gate
139*3446Smrj/*
140*3446Smrj * To cope with processors that do not implement fxsave/fxrstor
141*3446Smrj * instructions, patch hot paths in the kernel to use them only
142*3446Smrj * when that feature has been detected.
143*3446Smrj */
144*3446Smrj
145*3446Smrj#if defined(__lint)
146*3446Smrj
147*3446Smrjvoid
148*3446Smrjpatch_sse(void)
149*3446Smrj{}
1500Sstevel@tonic-gate
151*3446Smrjvoid
152*3446Smrjpatch_sse2(void)
153*3446Smrj{}
154*3446Smrj
155*3446Smrj#else	/* __lint */
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate	ENTRY_NP(patch_sse)
158*3446Smrj	_HOT_PATCH_PROLOG
1590Sstevel@tonic-gate	/
160*3446Smrj	/	frstor (%ebx); nop	-> fxrstor (%ebx)
1610Sstevel@tonic-gate	/
162*3446Smrj	_HOT_PATCH(_fxrstor_ebx_insn, _patch_fxrstor_ebx, 3)
1630Sstevel@tonic-gate	/
1640Sstevel@tonic-gate	/	lock; xorl $0, (%esp)	-> sfence; ret
1650Sstevel@tonic-gate	/
166*3446Smrj	_HOT_PATCH(_sfence_ret_insn, _patch_sfence_ret, 4)
167*3446Smrj	_HOT_PATCH_EPILOG
1680Sstevel@tonic-gate	ret
169*3446Smrj_fxrstor_ebx_insn:			/ see ndptrap_frstor()
170*3446Smrj	fxrstor	(%ebx)
1710Sstevel@tonic-gate_ldmxcsr_ebx_insn:			/ see resume_from_zombie()
1720Sstevel@tonic-gate	ldmxcsr	(%ebx)
1730Sstevel@tonic-gate_sfence_ret_insn:			/ see membar_producer()
1740Sstevel@tonic-gate	.byte	0xf, 0xae, 0xf8		/ [sfence instruction]
1750Sstevel@tonic-gate	ret
1760Sstevel@tonic-gate	SET_SIZE(patch_sse)
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate	ENTRY_NP(patch_sse2)
179*3446Smrj	_HOT_PATCH_PROLOG
1800Sstevel@tonic-gate	/
1810Sstevel@tonic-gate	/	lock; xorl $0, (%esp)	-> lfence; ret
1820Sstevel@tonic-gate	/
183*3446Smrj	_HOT_PATCH(_lfence_ret_insn, _patch_lfence_ret, 4)
184*3446Smrj	_HOT_PATCH_EPILOG
1850Sstevel@tonic-gate	ret
1860Sstevel@tonic-gate_lfence_ret_insn:			/ see membar_consumer()
1870Sstevel@tonic-gate	.byte	0xf, 0xae, 0xe8		/ [lfence instruction]
1880Sstevel@tonic-gate	ret
1890Sstevel@tonic-gate	SET_SIZE(patch_sse2)
1900Sstevel@tonic-gate
191*3446Smrj#endif	/* __lint */
1920Sstevel@tonic-gate#endif	/* __i386 */
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate
1950Sstevel@tonic-gate/*
1960Sstevel@tonic-gate * One of these routines is called from any lwp with floating
197*3446Smrj * point context as part of the prolog of a context switch.
1980Sstevel@tonic-gate */
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate#if defined(__lint)
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate/*ARGSUSED*/
2030Sstevel@tonic-gatevoid
204*3446Smrjfpxsave_ctxt(void *arg)
2050Sstevel@tonic-gate{}
2060Sstevel@tonic-gate
2070Sstevel@tonic-gate/*ARGSUSED*/
2080Sstevel@tonic-gatevoid
209*3446Smrjfpnsave_ctxt(void *arg)
2100Sstevel@tonic-gate{}
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate#else	/* __lint */
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate#if defined(__amd64)
2150Sstevel@tonic-gate
216*3446Smrj	ENTRY_NP(fpxsave_ctxt)
217*3446Smrj	cmpl	$FPU_EN, FPU_CTX_FPU_FLAGS(%rdi)
2180Sstevel@tonic-gate	jne	1f
219*3446Smrj
220*3446Smrj	movl	$_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%rdi)
221*3446Smrj	fxsave	FPU_CTX_FPU_REGS(%rdi)
222*3446Smrj	/*
223*3446Smrj	 * On certain AMD processors, the "exception pointers" i.e. the last
224*3446Smrj	 * instruction pointer, last data pointer, and last opcode
225*3446Smrj	 * are saved by the fxsave instruction ONLY if the exception summary
226*3446Smrj	 * bit is set.
227*3446Smrj	 *
228*3446Smrj	 * To ensure that we don't leak these values into the next context
229*3446Smrj	 * on the cpu, we could just issue an fninit here, but that's
230*3446Smrj	 * rather slow and so we issue an instruction sequence that
231*3446Smrj	 * clears them more quickly, if a little obscurely.
232*3446Smrj	 */
233*3446Smrj	btw	$7, FXSAVE_STATE_FSW(%rdi)	/* Test saved ES bit */
234*3446Smrj	jnc	0f				/* jump if ES = 0 */
235*3446Smrj	fnclex		/* clear pending x87 exceptions */
236*3446Smrj0:	ffree	%st(7)	/* clear tag bit to remove possible stack overflow */
237*3446Smrj	fildl	.fpzero_const(%rip)
238*3446Smrj			/* dummy load changes all exception pointers */
239*3446Smrj	STTS(%rsi)	/* trap on next fpu touch */
240545Skalai1:	rep;	ret	/* use 2 byte return instruction when branch target */
241545Skalai			/* AMD Software Optimization Guide - Section 6.2 */
242*3446Smrj	SET_SIZE(fpxsave_ctxt)
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate#elif defined(__i386)
2450Sstevel@tonic-gate
246*3446Smrj	ENTRY_NP(fpnsave_ctxt)
247*3446Smrj	movl	4(%esp), %eax		/* a struct fpu_ctx */
248*3446Smrj	cmpl	$FPU_EN, FPU_CTX_FPU_FLAGS(%eax)
2490Sstevel@tonic-gate	jne	1f
250*3446Smrj
251*3446Smrj	movl	$_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%eax)
252*3446Smrj	fnsave	FPU_CTX_FPU_REGS(%eax)
253*3446Smrj			/* (fnsave also reinitializes x87 state) */
254*3446Smrj	STTS(%edx)	/* trap on next fpu touch */
255545Skalai1:	rep;	ret	/* use 2 byte return instruction when branch target */
256545Skalai			/* AMD Software Optimization Guide - Section 6.2 */
257*3446Smrj	SET_SIZE(fpnsave_ctxt)
258*3446Smrj
259*3446Smrj	ENTRY_NP(fpxsave_ctxt)
260*3446Smrj	movl	4(%esp), %eax		/* a struct fpu_ctx */
261*3446Smrj	cmpl	$FPU_EN, FPU_CTX_FPU_FLAGS(%eax)
262*3446Smrj	jne	1f
2630Sstevel@tonic-gate
264*3446Smrj	movl	$_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%eax)
265*3446Smrj	fxsave	FPU_CTX_FPU_REGS(%eax)
266*3446Smrj			/* (see notes above about "exception pointers") */
267*3446Smrj	btw	$7, FXSAVE_STATE_FSW(%eax)	/* Test saved ES bit */
268*3446Smrj	jnc	0f				/* jump if ES = 0 */
269*3446Smrj	fnclex		/* clear pending x87 exceptions */
270*3446Smrj0:	ffree	%st(7)	/* clear tag bit to remove possible stack overflow */
271*3446Smrj	fildl	.fpzero_const
272*3446Smrj			/* dummy load changes all exception pointers */
273*3446Smrj	STTS(%edx)	/* trap on next fpu touch */
274545Skalai1:	rep;	ret	/* use 2 byte return instruction when branch target */
275545Skalai			/* AMD Software Optimization Guide - Section 6.2 */
276*3446Smrj	SET_SIZE(fpxsave_ctxt)
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate#endif	/* __i386 */
279*3446Smrj
280*3446Smrj	.align	8
281*3446Smrj.fpzero_const:
282*3446Smrj	.4byte	0x0
283*3446Smrj	.4byte	0x0
284*3446Smrj
2850Sstevel@tonic-gate#endif	/* __lint */
2860Sstevel@tonic-gate
287*3446Smrj
2880Sstevel@tonic-gate#if defined(__lint)
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate/*ARGSUSED*/
2910Sstevel@tonic-gatevoid
2920Sstevel@tonic-gatefpsave(struct fnsave_state *f)
2930Sstevel@tonic-gate{}
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate/*ARGSUSED*/
2960Sstevel@tonic-gatevoid
2970Sstevel@tonic-gatefpxsave(struct fxsave_state *f)
2980Sstevel@tonic-gate{}
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate#else	/* __lint */
3010Sstevel@tonic-gate
3020Sstevel@tonic-gate#if defined(__amd64)
3030Sstevel@tonic-gate
3040Sstevel@tonic-gate	ENTRY_NP(fpxsave)
305*3446Smrj	CLTS
3060Sstevel@tonic-gate	fxsave	(%rdi)
307*3446Smrj	fninit				/* clear exceptions, init x87 tags */
308*3446Smrj	STTS(%rdi)			/* set TS bit in %cr0 (disable FPU) */
3090Sstevel@tonic-gate	ret
3100Sstevel@tonic-gate	SET_SIZE(fpxsave)
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate#elif defined(__i386)
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate	ENTRY_NP(fpsave)
315*3446Smrj	CLTS
316*3446Smrj	movl	4(%esp), %eax
3170Sstevel@tonic-gate	fnsave	(%eax)
318*3446Smrj	STTS(%eax)			/* set TS bit in %cr0 (disable FPU) */
3190Sstevel@tonic-gate	ret
3200Sstevel@tonic-gate	SET_SIZE(fpsave)
3210Sstevel@tonic-gate
3220Sstevel@tonic-gate	ENTRY_NP(fpxsave)
323*3446Smrj	CLTS
324*3446Smrj	movl	4(%esp), %eax
3250Sstevel@tonic-gate	fxsave	(%eax)
326*3446Smrj	fninit				/* clear exceptions, init x87 tags */
327*3446Smrj	STTS(%eax)			/* set TS bit in %cr0 (disable FPU) */
3280Sstevel@tonic-gate	ret
3290Sstevel@tonic-gate	SET_SIZE(fpxsave)
3300Sstevel@tonic-gate
3310Sstevel@tonic-gate#endif	/* __i386 */
3320Sstevel@tonic-gate#endif	/* __lint */
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate#if defined(__lint)
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate/*ARGSUSED*/
3370Sstevel@tonic-gatevoid
3380Sstevel@tonic-gatefprestore(struct fnsave_state *f)
3390Sstevel@tonic-gate{}
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate/*ARGSUSED*/
3420Sstevel@tonic-gatevoid
3430Sstevel@tonic-gatefpxrestore(struct fxsave_state *f)
3440Sstevel@tonic-gate{}
3450Sstevel@tonic-gate
3460Sstevel@tonic-gate#else	/* __lint */
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate#if defined(__amd64)
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate	ENTRY_NP(fpxrestore)
351*3446Smrj	CLTS
3520Sstevel@tonic-gate	fxrstor	(%rdi)
3530Sstevel@tonic-gate	ret
3540Sstevel@tonic-gate	SET_SIZE(fpxrestore)
3550Sstevel@tonic-gate
3560Sstevel@tonic-gate#elif defined(__i386)
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate	ENTRY_NP(fprestore)
359*3446Smrj	CLTS
360*3446Smrj	movl	4(%esp), %eax
3610Sstevel@tonic-gate	frstor	(%eax)
3620Sstevel@tonic-gate	ret
3630Sstevel@tonic-gate	SET_SIZE(fprestore)
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate	ENTRY_NP(fpxrestore)
366*3446Smrj	CLTS
367*3446Smrj	movl	4(%esp), %eax
3680Sstevel@tonic-gate	fxrstor	(%eax)
3690Sstevel@tonic-gate	ret
3700Sstevel@tonic-gate	SET_SIZE(fpxrestore)
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate#endif	/* __i386 */
3730Sstevel@tonic-gate#endif	/* __lint */
3740Sstevel@tonic-gate
3750Sstevel@tonic-gate/*
3760Sstevel@tonic-gate * Disable the floating point unit.
3770Sstevel@tonic-gate */
3780Sstevel@tonic-gate
3790Sstevel@tonic-gate#if defined(__lint)
3800Sstevel@tonic-gate
3810Sstevel@tonic-gatevoid
3820Sstevel@tonic-gatefpdisable(void)
3830Sstevel@tonic-gate{}
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate#else	/* __lint */
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate#if defined(__amd64)
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate	ENTRY_NP(fpdisable)
390*3446Smrj	STTS(%rdi)			/* set TS bit in %cr0 (disable FPU) */
3910Sstevel@tonic-gate	ret
3920Sstevel@tonic-gate	SET_SIZE(fpdisable)
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate#elif defined(__i386)
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate	ENTRY_NP(fpdisable)
397*3446Smrj	STTS(%eax)
3980Sstevel@tonic-gate	ret
3990Sstevel@tonic-gate	SET_SIZE(fpdisable)
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate#endif	/* __i386 */
4020Sstevel@tonic-gate#endif	/* __lint */
4030Sstevel@tonic-gate
4040Sstevel@tonic-gate/*
4050Sstevel@tonic-gate * Initialize the fpu hardware.
4060Sstevel@tonic-gate */
4070Sstevel@tonic-gate
4080Sstevel@tonic-gate#if defined(__lint)
4090Sstevel@tonic-gate
4100Sstevel@tonic-gatevoid
4110Sstevel@tonic-gatefpinit(void)
4120Sstevel@tonic-gate{}
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate#else	/* __lint */
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate#if defined(__amd64)
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate	ENTRY_NP(fpinit)
419*3446Smrj	CLTS
4200Sstevel@tonic-gate	leaq	sse_initial(%rip), %rax
4210Sstevel@tonic-gate	fxrstor	(%rax)			/* load clean initial state */
4220Sstevel@tonic-gate	ret
4230Sstevel@tonic-gate	SET_SIZE(fpinit)
4240Sstevel@tonic-gate
4250Sstevel@tonic-gate#elif defined(__i386)
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate	ENTRY_NP(fpinit)
428*3446Smrj	CLTS
4290Sstevel@tonic-gate	cmpl	$__FP_SSE, fp_kind
4300Sstevel@tonic-gate	je	1f
4310Sstevel@tonic-gate
432*3446Smrj	fninit
4330Sstevel@tonic-gate	movl	$x87_initial, %eax
434*3446Smrj	frstor	(%eax)			/* load clean initial state */
4350Sstevel@tonic-gate	ret
4360Sstevel@tonic-gate1:
4370Sstevel@tonic-gate	movl	$sse_initial, %eax
438*3446Smrj	fxrstor	(%eax)			/* load clean initial state */
4390Sstevel@tonic-gate	ret
4400Sstevel@tonic-gate	SET_SIZE(fpinit)
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate#endif	/* __i386 */
4430Sstevel@tonic-gate#endif	/* __lint */
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate/*
4460Sstevel@tonic-gate * Clears FPU exception state.
4470Sstevel@tonic-gate * Returns the FP status word.
4480Sstevel@tonic-gate */
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate#if defined(__lint)
4510Sstevel@tonic-gate
4520Sstevel@tonic-gateuint32_t
4530Sstevel@tonic-gatefperr_reset(void)
454*3446Smrj{ return (0); }
4550Sstevel@tonic-gate
4560Sstevel@tonic-gateuint32_t
4570Sstevel@tonic-gatefpxerr_reset(void)
458*3446Smrj{ return (0); }
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate#else	/* __lint */
4610Sstevel@tonic-gate
4620Sstevel@tonic-gate#if defined(__amd64)
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate	ENTRY_NP(fperr_reset)
465*3446Smrj	CLTS
4660Sstevel@tonic-gate	xorl	%eax, %eax
467*3446Smrj	fnstsw	%ax
468*3446Smrj	fnclex
4690Sstevel@tonic-gate	ret
4700Sstevel@tonic-gate	SET_SIZE(fperr_reset)
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate	ENTRY_NP(fpxerr_reset)
4730Sstevel@tonic-gate	pushq	%rbp
4740Sstevel@tonic-gate	movq	%rsp, %rbp
4750Sstevel@tonic-gate	subq	$0x10, %rsp		/* make some temporary space */
476*3446Smrj	CLTS
477*3446Smrj	stmxcsr	(%rsp)
4780Sstevel@tonic-gate	movl	(%rsp), %eax
4790Sstevel@tonic-gate	andl	$_BITNOT(SSE_MXCSR_EFLAGS), (%rsp)
4800Sstevel@tonic-gate	ldmxcsr	(%rsp)			/* clear processor exceptions */
4810Sstevel@tonic-gate	leave
4820Sstevel@tonic-gate	ret
4830Sstevel@tonic-gate	SET_SIZE(fpxerr_reset)
4840Sstevel@tonic-gate
4850Sstevel@tonic-gate#elif defined(__i386)
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate	ENTRY_NP(fperr_reset)
488*3446Smrj	CLTS
4890Sstevel@tonic-gate	xorl	%eax, %eax
490*3446Smrj	fnstsw	%ax
491*3446Smrj	fnclex
4920Sstevel@tonic-gate	ret
4930Sstevel@tonic-gate	SET_SIZE(fperr_reset)
4940Sstevel@tonic-gate
4950Sstevel@tonic-gate	ENTRY_NP(fpxerr_reset)
496*3446Smrj	CLTS
497*3446Smrj	subl	$4, %esp		/* make some temporary space */
498*3446Smrj	stmxcsr	(%esp)
4990Sstevel@tonic-gate	movl	(%esp), %eax
5000Sstevel@tonic-gate	andl	$_BITNOT(SSE_MXCSR_EFLAGS), (%esp)
501*3446Smrj	ldmxcsr	(%esp)			/* clear processor exceptions */
5020Sstevel@tonic-gate	addl	$4, %esp
5030Sstevel@tonic-gate	ret
5040Sstevel@tonic-gate	SET_SIZE(fpxerr_reset)
5050Sstevel@tonic-gate
5060Sstevel@tonic-gate#endif	/* __i386 */
5070Sstevel@tonic-gate#endif	/* __lint */
5080Sstevel@tonic-gate
5090Sstevel@tonic-gate#if defined(__lint)
5100Sstevel@tonic-gate
5110Sstevel@tonic-gateuint32_t
5120Sstevel@tonic-gatefpgetcwsw(void)
5130Sstevel@tonic-gate{
5140Sstevel@tonic-gate	return (0);
5150Sstevel@tonic-gate}
5160Sstevel@tonic-gate
5170Sstevel@tonic-gate#else   /* __lint */
5180Sstevel@tonic-gate
5190Sstevel@tonic-gate#if defined(__amd64)
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate	ENTRY_NP(fpgetcwsw)
5220Sstevel@tonic-gate	pushq	%rbp
5230Sstevel@tonic-gate	movq	%rsp, %rbp
5240Sstevel@tonic-gate	subq	$0x10, %rsp		/* make some temporary space	*/
525*3446Smrj	CLTS
5260Sstevel@tonic-gate	fnstsw	(%rsp)			/* store the status word	*/
5270Sstevel@tonic-gate	fnstcw	2(%rsp)			/* store the control word	*/
5280Sstevel@tonic-gate	movl	(%rsp), %eax		/* put both in %eax		*/
5290Sstevel@tonic-gate	leave
5300Sstevel@tonic-gate	ret
5310Sstevel@tonic-gate	SET_SIZE(fpgetcwsw)
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate#elif defined(__i386)
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate	ENTRY_NP(fpgetcwsw)
536*3446Smrj	CLTS
5370Sstevel@tonic-gate	subl	$4, %esp		/* make some temporary space	*/
5380Sstevel@tonic-gate	fnstsw	(%esp)			/* store the status word	*/
5390Sstevel@tonic-gate	fnstcw	2(%esp)			/* store the control word	*/
5400Sstevel@tonic-gate	movl	(%esp), %eax		/* put both in %eax		*/
5410Sstevel@tonic-gate	addl	$4, %esp
5420Sstevel@tonic-gate	ret
5430Sstevel@tonic-gate	SET_SIZE(fpgetcwsw)
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate#endif	/* __i386 */
5460Sstevel@tonic-gate#endif  /* __lint */
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate/*
5490Sstevel@tonic-gate * Returns the MXCSR register.
5500Sstevel@tonic-gate */
5510Sstevel@tonic-gate
5520Sstevel@tonic-gate#if defined(__lint)
5530Sstevel@tonic-gate
5540Sstevel@tonic-gateuint32_t
5550Sstevel@tonic-gatefpgetmxcsr(void)
5560Sstevel@tonic-gate{
5570Sstevel@tonic-gate	return (0);
5580Sstevel@tonic-gate}
5590Sstevel@tonic-gate
5600Sstevel@tonic-gate#else   /* __lint */
5610Sstevel@tonic-gate
5620Sstevel@tonic-gate#if defined(__amd64)
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate	ENTRY_NP(fpgetmxcsr)
5650Sstevel@tonic-gate	pushq	%rbp
5660Sstevel@tonic-gate	movq	%rsp, %rbp
567*3446Smrj	subq	$0x10, %rsp		/* make some temporary space */
568*3446Smrj	CLTS
569*3446Smrj	stmxcsr	(%rsp)
5700Sstevel@tonic-gate	movl	(%rsp), %eax
5710Sstevel@tonic-gate	leave
5720Sstevel@tonic-gate	ret
5730Sstevel@tonic-gate	SET_SIZE(fpgetmxcsr)
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate#elif defined(__i386)
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate	ENTRY_NP(fpgetmxcsr)
578*3446Smrj	CLTS
579*3446Smrj	subl	$4, %esp		/* make some temporary space */
580*3446Smrj	stmxcsr	(%esp)
5810Sstevel@tonic-gate	movl	(%esp), %eax
5820Sstevel@tonic-gate	addl	$4, %esp
5830Sstevel@tonic-gate	ret
5840Sstevel@tonic-gate	SET_SIZE(fpgetmxcsr)
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate#endif	/* __i386 */
5870Sstevel@tonic-gate#endif  /* __lint */
588