xref: /titanic_44/usr/src/uts/intel/ia32/ml/float.s (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5ae115bc7Smrj * Common Development and Distribution License (the "License").
6ae115bc7Smrj * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21ae115bc7Smrj
227c478bd9Sstevel@tonic-gate/*
23*7af88ac7SKuriakose Kuruvilla * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate/*      Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
277c478bd9Sstevel@tonic-gate/*      Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T   */
287c478bd9Sstevel@tonic-gate/*        All Rights Reserved   */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate/*      Copyright (c) 1987, 1988 Microsoft Corporation  */
317c478bd9Sstevel@tonic-gate/*        All Rights Reserved   */
327c478bd9Sstevel@tonic-gate
33*7af88ac7SKuriakose Kuruvilla/*
34*7af88ac7SKuriakose Kuruvilla * Copyright (c) 2009, Intel Corporation.
35*7af88ac7SKuriakose Kuruvilla * All rights reserved.
36*7af88ac7SKuriakose Kuruvilla */
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
39ae115bc7Smrj#include <sys/asm_misc.h>
407c478bd9Sstevel@tonic-gate#include <sys/regset.h>
417c478bd9Sstevel@tonic-gate#include <sys/privregs.h>
427c478bd9Sstevel@tonic-gate#include <sys/x86_archext.h>
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate#if defined(__lint)
457c478bd9Sstevel@tonic-gate#include <sys/types.h>
467c478bd9Sstevel@tonic-gate#include <sys/fp.h>
477c478bd9Sstevel@tonic-gate#else
487c478bd9Sstevel@tonic-gate#include "assym.h"
497c478bd9Sstevel@tonic-gate#endif
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate#if defined(__lint)
527c478bd9Sstevel@tonic-gate
53ae115bc7Smrjuint_t
54ae115bc7Smrjfpu_initial_probe(void)
55ae115bc7Smrj{ return (0); }
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate#else	/* __lint */
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate	/*
60ae115bc7Smrj	 * Returns zero if x87 "chip" is present(!)
617c478bd9Sstevel@tonic-gate	 */
62ae115bc7Smrj	ENTRY_NP(fpu_initial_probe)
63ae115bc7Smrj	CLTS
64ae115bc7Smrj	fninit
65ae115bc7Smrj	fnstsw	%ax
66ae115bc7Smrj	movzbl	%al, %eax
67ae115bc7Smrj	ret
68ae115bc7Smrj	SET_SIZE(fpu_initial_probe)
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate#endif	/* __lint */
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate#if defined(__lint)
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate/*ARGSUSED*/
757c478bd9Sstevel@tonic-gatevoid
76ae115bc7Smrjfxsave_insn(struct fxsave_state *fx)
777c478bd9Sstevel@tonic-gate{}
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate#else	/* __lint */
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate#if defined(__amd64)
827c478bd9Sstevel@tonic-gate
83ae115bc7Smrj	ENTRY_NP(fxsave_insn)
84f0f4f396Ska153516	FXSAVEQ	((%rdi))
857c478bd9Sstevel@tonic-gate	ret
86ae115bc7Smrj	SET_SIZE(fxsave_insn)
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate#elif defined(__i386)
897c478bd9Sstevel@tonic-gate
90ae115bc7Smrj	ENTRY_NP(fxsave_insn)
91ae115bc7Smrj	movl	4(%esp), %eax
92ae115bc7Smrj	fxsave	(%eax)
93ae115bc7Smrj	ret
94ae115bc7Smrj	SET_SIZE(fxsave_insn)
95ae115bc7Smrj
96ae115bc7Smrj#endif
97ae115bc7Smrj
98ae115bc7Smrj#endif	/* __lint */
99ae115bc7Smrj
100ae115bc7Smrj#if defined(__i386)
101ae115bc7Smrj
102ae115bc7Smrj/*
103ae115bc7Smrj * If (num1/num2 > num1/num3) the FPU has the FDIV bug.
104ae115bc7Smrj */
105ae115bc7Smrj
106ae115bc7Smrj#if defined(__lint)
107ae115bc7Smrj
108ae115bc7Smrjint
109ae115bc7Smrjfpu_probe_pentium_fdivbug(void)
110ae115bc7Smrj{ return (0); }
111ae115bc7Smrj
112ae115bc7Smrj#else	/* __lint */
113ae115bc7Smrj
114ae115bc7Smrj	ENTRY_NP(fpu_probe_pentium_fdivbug)
115ae115bc7Smrj	fldl	.num1
116ae115bc7Smrj	fldl	.num2
1177c478bd9Sstevel@tonic-gate	fdivr	%st(1), %st
1187c478bd9Sstevel@tonic-gate	fxch	%st(1)
119ae115bc7Smrj	fdivl	.num3
1207c478bd9Sstevel@tonic-gate	fcompp
1217c478bd9Sstevel@tonic-gate	fstsw	%ax
1227c478bd9Sstevel@tonic-gate	sahf
123ae115bc7Smrj	jae	0f
124ae115bc7Smrj	movl	$1, %eax
1257c478bd9Sstevel@tonic-gate	ret
1267c478bd9Sstevel@tonic-gate
127ae115bc7Smrj0:	xorl	%eax, %eax
128ae115bc7Smrj	ret
129ae115bc7Smrj
130ae115bc7Smrj	.align	4
131ae115bc7Smrj.num1:	.4byte	0xbce4217d	/* 4.999999 */
132ae115bc7Smrj	.4byte	0x4013ffff
133ae115bc7Smrj.num2:	.4byte	0x0		/* 15.0 */
134ae115bc7Smrj	.4byte	0x402e0000
135ae115bc7Smrj.num3:	.4byte	0xde7210bf	/* 14.999999 */
136ae115bc7Smrj	.4byte	0x402dffff
137ae115bc7Smrj	SET_SIZE(fpu_probe_pentium_fdivbug)
138ae115bc7Smrj
139ae115bc7Smrj#endif	/* __lint */
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate/*
1427c478bd9Sstevel@tonic-gate * To cope with processors that do not implement fxsave/fxrstor
1437c478bd9Sstevel@tonic-gate * instructions, patch hot paths in the kernel to use them only
1447c478bd9Sstevel@tonic-gate * when that feature has been detected.
1457c478bd9Sstevel@tonic-gate */
146ae115bc7Smrj
147ae115bc7Smrj#if defined(__lint)
148ae115bc7Smrj
149ae115bc7Smrjvoid
150ae115bc7Smrjpatch_sse(void)
151ae115bc7Smrj{}
152ae115bc7Smrj
153ae115bc7Smrjvoid
154ae115bc7Smrjpatch_sse2(void)
155ae115bc7Smrj{}
156ae115bc7Smrj
157*7af88ac7SKuriakose Kuruvillavoid
158*7af88ac7SKuriakose Kuruvillapatch_xsave(void)
159*7af88ac7SKuriakose Kuruvilla{}
160*7af88ac7SKuriakose Kuruvilla
161ae115bc7Smrj#else	/* __lint */
162ae115bc7Smrj
1637c478bd9Sstevel@tonic-gate	ENTRY_NP(patch_sse)
164ae115bc7Smrj	_HOT_PATCH_PROLOG
1657c478bd9Sstevel@tonic-gate	/
166ae115bc7Smrj	/	frstor (%ebx); nop	-> fxrstor (%ebx)
1677c478bd9Sstevel@tonic-gate	/
168ae115bc7Smrj	_HOT_PATCH(_fxrstor_ebx_insn, _patch_fxrstor_ebx, 3)
1697c478bd9Sstevel@tonic-gate	/
1707c478bd9Sstevel@tonic-gate	/	lock; xorl $0, (%esp)	-> sfence; ret
1717c478bd9Sstevel@tonic-gate	/
172ae115bc7Smrj	_HOT_PATCH(_sfence_ret_insn, _patch_sfence_ret, 4)
173ae115bc7Smrj	_HOT_PATCH_EPILOG
1747c478bd9Sstevel@tonic-gate	ret
175ae115bc7Smrj_fxrstor_ebx_insn:			/ see ndptrap_frstor()
176ae115bc7Smrj	fxrstor	(%ebx)
1777c478bd9Sstevel@tonic-gate_ldmxcsr_ebx_insn:			/ see resume_from_zombie()
1787c478bd9Sstevel@tonic-gate	ldmxcsr	(%ebx)
1797c478bd9Sstevel@tonic-gate_sfence_ret_insn:			/ see membar_producer()
1807c478bd9Sstevel@tonic-gate	.byte	0xf, 0xae, 0xf8		/ [sfence instruction]
1817c478bd9Sstevel@tonic-gate	ret
1827c478bd9Sstevel@tonic-gate	SET_SIZE(patch_sse)
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate	ENTRY_NP(patch_sse2)
185ae115bc7Smrj	_HOT_PATCH_PROLOG
1867c478bd9Sstevel@tonic-gate	/
1877c478bd9Sstevel@tonic-gate	/	lock; xorl $0, (%esp)	-> lfence; ret
1887c478bd9Sstevel@tonic-gate	/
189ae115bc7Smrj	_HOT_PATCH(_lfence_ret_insn, _patch_lfence_ret, 4)
190ae115bc7Smrj	_HOT_PATCH_EPILOG
1917c478bd9Sstevel@tonic-gate	ret
1927c478bd9Sstevel@tonic-gate_lfence_ret_insn:			/ see membar_consumer()
1937c478bd9Sstevel@tonic-gate	.byte	0xf, 0xae, 0xe8		/ [lfence instruction]
1947c478bd9Sstevel@tonic-gate	ret
1957c478bd9Sstevel@tonic-gate	SET_SIZE(patch_sse2)
1967c478bd9Sstevel@tonic-gate
197*7af88ac7SKuriakose Kuruvilla	/*
198*7af88ac7SKuriakose Kuruvilla	 * Patch lazy fp restore instructions in the trap handler
199*7af88ac7SKuriakose Kuruvilla	 * to use xrstor instead of frstor
200*7af88ac7SKuriakose Kuruvilla	 */
201*7af88ac7SKuriakose Kuruvilla	ENTRY_NP(patch_xsave)
202*7af88ac7SKuriakose Kuruvilla	_HOT_PATCH_PROLOG
203*7af88ac7SKuriakose Kuruvilla	/
204*7af88ac7SKuriakose Kuruvilla	/	frstor (%ebx); nop	-> xrstor (%ebx)
205*7af88ac7SKuriakose Kuruvilla	/
206*7af88ac7SKuriakose Kuruvilla	_HOT_PATCH(_xrstor_ebx_insn, _patch_xrstor_ebx, 3)
207*7af88ac7SKuriakose Kuruvilla	_HOT_PATCH_EPILOG
208*7af88ac7SKuriakose Kuruvilla	ret
209*7af88ac7SKuriakose Kuruvilla_xrstor_ebx_insn:			/ see ndptrap_frstor()
210*7af88ac7SKuriakose Kuruvilla	#xrstor (%ebx)
211*7af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x2b
212*7af88ac7SKuriakose Kuruvilla	SET_SIZE(patch_xsave)
213*7af88ac7SKuriakose Kuruvilla
2147c478bd9Sstevel@tonic-gate#endif	/* __lint */
215ae115bc7Smrj#endif	/* __i386 */
2167c478bd9Sstevel@tonic-gate
217*7af88ac7SKuriakose Kuruvilla#if defined(__amd64)
218*7af88ac7SKuriakose Kuruvilla#if defined(__lint)
219*7af88ac7SKuriakose Kuruvilla
220*7af88ac7SKuriakose Kuruvillavoid
221*7af88ac7SKuriakose Kuruvillapatch_xsave(void)
222*7af88ac7SKuriakose Kuruvilla{}
223*7af88ac7SKuriakose Kuruvilla
224*7af88ac7SKuriakose Kuruvilla#else	/* __lint */
225*7af88ac7SKuriakose Kuruvilla
226*7af88ac7SKuriakose Kuruvilla	/*
227*7af88ac7SKuriakose Kuruvilla	 * Patch lazy fp restore instructions in the trap handler
228*7af88ac7SKuriakose Kuruvilla	 * to use xrstor instead of fxrstorq
229*7af88ac7SKuriakose Kuruvilla	 */
230*7af88ac7SKuriakose Kuruvilla	ENTRY_NP(patch_xsave)
231*7af88ac7SKuriakose Kuruvilla	pushq	%rbx
232*7af88ac7SKuriakose Kuruvilla	pushq	%rbp
233*7af88ac7SKuriakose Kuruvilla	pushq	%r15
234*7af88ac7SKuriakose Kuruvilla	/
235*7af88ac7SKuriakose Kuruvilla	/	FXRSTORQ (%rbx);	-> xrstor (%rbx)
236*7af88ac7SKuriakose Kuruvilla	/ hot_patch(_xrstor_rbx_insn, _patch_xrstorq_rbx, 4)
237*7af88ac7SKuriakose Kuruvilla	/
238*7af88ac7SKuriakose Kuruvilla	leaq	_patch_xrstorq_rbx(%rip), %rbx
239*7af88ac7SKuriakose Kuruvilla	leaq	_xrstor_rbx_insn(%rip), %rbp
240*7af88ac7SKuriakose Kuruvilla	movq	$4, %r15
241*7af88ac7SKuriakose Kuruvilla1:
242*7af88ac7SKuriakose Kuruvilla	movq	%rbx, %rdi			/* patch address */
243*7af88ac7SKuriakose Kuruvilla	movzbq	(%rbp), %rsi			/* instruction byte */
244*7af88ac7SKuriakose Kuruvilla	movq	$1, %rdx			/* count */
245*7af88ac7SKuriakose Kuruvilla	call	hot_patch_kernel_text
246*7af88ac7SKuriakose Kuruvilla	addq	$1, %rbx
247*7af88ac7SKuriakose Kuruvilla	addq	$1, %rbp
248*7af88ac7SKuriakose Kuruvilla	subq	$1, %r15
249*7af88ac7SKuriakose Kuruvilla	jnz	1b
250*7af88ac7SKuriakose Kuruvilla
251*7af88ac7SKuriakose Kuruvilla	popq	%r15
252*7af88ac7SKuriakose Kuruvilla	popq	%rbp
253*7af88ac7SKuriakose Kuruvilla	popq	%rbx
254*7af88ac7SKuriakose Kuruvilla	ret
255*7af88ac7SKuriakose Kuruvilla
256*7af88ac7SKuriakose Kuruvilla_xrstor_rbx_insn:			/ see ndptrap_frstor()
257*7af88ac7SKuriakose Kuruvilla	#rex.W=1 (.byte 0x48)
258*7af88ac7SKuriakose Kuruvilla	#xrstor (%rbx)
259*7af88ac7SKuriakose Kuruvilla	.byte	0x48, 0x0f, 0xae, 0x2b
260*7af88ac7SKuriakose Kuruvilla	SET_SIZE(patch_xsave)
261*7af88ac7SKuriakose Kuruvilla
262*7af88ac7SKuriakose Kuruvilla#endif	/* __lint */
263*7af88ac7SKuriakose Kuruvilla#endif	/* __amd64 */
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate/*
2667c478bd9Sstevel@tonic-gate * One of these routines is called from any lwp with floating
267ae115bc7Smrj * point context as part of the prolog of a context switch.
2687c478bd9Sstevel@tonic-gate */
2697c478bd9Sstevel@tonic-gate
2707c478bd9Sstevel@tonic-gate#if defined(__lint)
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate/*ARGSUSED*/
2737c478bd9Sstevel@tonic-gatevoid
274*7af88ac7SKuriakose Kuruvillaxsave_ctxt(void *arg)
275*7af88ac7SKuriakose Kuruvilla{}
276*7af88ac7SKuriakose Kuruvilla
277*7af88ac7SKuriakose Kuruvilla/*ARGSUSED*/
278*7af88ac7SKuriakose Kuruvillavoid
279ae115bc7Smrjfpxsave_ctxt(void *arg)
2807c478bd9Sstevel@tonic-gate{}
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate/*ARGSUSED*/
2837c478bd9Sstevel@tonic-gatevoid
284ae115bc7Smrjfpnsave_ctxt(void *arg)
2857c478bd9Sstevel@tonic-gate{}
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate#else	/* __lint */
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate#if defined(__amd64)
2907c478bd9Sstevel@tonic-gate
291ae115bc7Smrj	ENTRY_NP(fpxsave_ctxt)
292ae115bc7Smrj	cmpl	$FPU_EN, FPU_CTX_FPU_FLAGS(%rdi)
2937c478bd9Sstevel@tonic-gate	jne	1f
294ae115bc7Smrj
295ae115bc7Smrj	movl	$_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%rdi)
296f0f4f396Ska153516	FXSAVEQ	(FPU_CTX_FPU_REGS(%rdi))
297f0f4f396Ska153516
298ae115bc7Smrj	/*
299ae115bc7Smrj	 * On certain AMD processors, the "exception pointers" i.e. the last
300ae115bc7Smrj	 * instruction pointer, last data pointer, and last opcode
301ae115bc7Smrj	 * are saved by the fxsave instruction ONLY if the exception summary
302ae115bc7Smrj	 * bit is set.
303ae115bc7Smrj	 *
304ae115bc7Smrj	 * To ensure that we don't leak these values into the next context
305ae115bc7Smrj	 * on the cpu, we could just issue an fninit here, but that's
306ae115bc7Smrj	 * rather slow and so we issue an instruction sequence that
307ae115bc7Smrj	 * clears them more quickly, if a little obscurely.
308ae115bc7Smrj	 */
309ae115bc7Smrj	btw	$7, FXSAVE_STATE_FSW(%rdi)	/* Test saved ES bit */
310ae115bc7Smrj	jnc	0f				/* jump if ES = 0 */
3117c478bd9Sstevel@tonic-gate	fnclex		/* clear pending x87 exceptions */
312ae115bc7Smrj0:	ffree	%st(7)	/* clear tag bit to remove possible stack overflow */
313ae115bc7Smrj	fildl	.fpzero_const(%rip)
314ae115bc7Smrj			/* dummy load changes all exception pointers */
315ae115bc7Smrj	STTS(%rsi)	/* trap on next fpu touch */
31685641879Skalai1:	rep;	ret	/* use 2 byte return instruction when branch target */
31785641879Skalai			/* AMD Software Optimization Guide - Section 6.2 */
318ae115bc7Smrj	SET_SIZE(fpxsave_ctxt)
3197c478bd9Sstevel@tonic-gate
320*7af88ac7SKuriakose Kuruvilla	ENTRY_NP(xsave_ctxt)
321*7af88ac7SKuriakose Kuruvilla	cmpl	$FPU_EN, FPU_CTX_FPU_FLAGS(%rdi)
322*7af88ac7SKuriakose Kuruvilla	jne	1f
323*7af88ac7SKuriakose Kuruvilla	movl	$_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%rdi)
324*7af88ac7SKuriakose Kuruvilla	/*
325*7af88ac7SKuriakose Kuruvilla	 * Setup xsave flags in EDX:EAX
326*7af88ac7SKuriakose Kuruvilla	 */
327*7af88ac7SKuriakose Kuruvilla	movl	FPU_CTX_FPU_XSAVE_MASK(%rdi), %eax
328*7af88ac7SKuriakose Kuruvilla	movl	FPU_CTX_FPU_XSAVE_MASK+4(%rdi), %edx
329*7af88ac7SKuriakose Kuruvilla	leaq	FPU_CTX_FPU_REGS(%rdi), %rsi
330*7af88ac7SKuriakose Kuruvilla	#xsave	(%rsi)
331*7af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x26
332*7af88ac7SKuriakose Kuruvilla
333*7af88ac7SKuriakose Kuruvilla	/*
334*7af88ac7SKuriakose Kuruvilla	 * (see notes above about "exception pointers")
335*7af88ac7SKuriakose Kuruvilla	 * TODO: does it apply to any machine that uses xsave?
336*7af88ac7SKuriakose Kuruvilla	 */
337*7af88ac7SKuriakose Kuruvilla	btw	$7, FXSAVE_STATE_FSW(%rdi)	/* Test saved ES bit */
338*7af88ac7SKuriakose Kuruvilla	jnc	0f				/* jump if ES = 0 */
339*7af88ac7SKuriakose Kuruvilla	fnclex		/* clear pending x87 exceptions */
340*7af88ac7SKuriakose Kuruvilla0:	ffree	%st(7)	/* clear tag bit to remove possible stack overflow */
341*7af88ac7SKuriakose Kuruvilla	fildl	.fpzero_const(%rip)
342*7af88ac7SKuriakose Kuruvilla			/* dummy load changes all exception pointers */
343*7af88ac7SKuriakose Kuruvilla	STTS(%rsi)	/* trap on next fpu touch */
344*7af88ac7SKuriakose Kuruvilla1:	ret
345*7af88ac7SKuriakose Kuruvilla	SET_SIZE(xsave_ctxt)
346*7af88ac7SKuriakose Kuruvilla
3477c478bd9Sstevel@tonic-gate#elif defined(__i386)
3487c478bd9Sstevel@tonic-gate
349ae115bc7Smrj	ENTRY_NP(fpnsave_ctxt)
350ae115bc7Smrj	movl	4(%esp), %eax		/* a struct fpu_ctx */
351ae115bc7Smrj	cmpl	$FPU_EN, FPU_CTX_FPU_FLAGS(%eax)
3527c478bd9Sstevel@tonic-gate	jne	1f
3537c478bd9Sstevel@tonic-gate
354ae115bc7Smrj	movl	$_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%eax)
355ae115bc7Smrj	fnsave	FPU_CTX_FPU_REGS(%eax)
356ae115bc7Smrj			/* (fnsave also reinitializes x87 state) */
357ae115bc7Smrj	STTS(%edx)	/* trap on next fpu touch */
35885641879Skalai1:	rep;	ret	/* use 2 byte return instruction when branch target */
35985641879Skalai			/* AMD Software Optimization Guide - Section 6.2 */
360ae115bc7Smrj	SET_SIZE(fpnsave_ctxt)
361ae115bc7Smrj
362ae115bc7Smrj	ENTRY_NP(fpxsave_ctxt)
363ae115bc7Smrj	movl	4(%esp), %eax		/* a struct fpu_ctx */
364ae115bc7Smrj	cmpl	$FPU_EN, FPU_CTX_FPU_FLAGS(%eax)
365ae115bc7Smrj	jne	1f
366ae115bc7Smrj
367ae115bc7Smrj	movl	$_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%eax)
368ae115bc7Smrj	fxsave	FPU_CTX_FPU_REGS(%eax)
369ae115bc7Smrj			/* (see notes above about "exception pointers") */
370ae115bc7Smrj	btw	$7, FXSAVE_STATE_FSW(%eax)	/* Test saved ES bit */
371ae115bc7Smrj	jnc	0f				/* jump if ES = 0 */
372ae115bc7Smrj	fnclex		/* clear pending x87 exceptions */
373ae115bc7Smrj0:	ffree	%st(7)	/* clear tag bit to remove possible stack overflow */
374ae115bc7Smrj	fildl	.fpzero_const
375ae115bc7Smrj			/* dummy load changes all exception pointers */
376ae115bc7Smrj	STTS(%edx)	/* trap on next fpu touch */
377ae115bc7Smrj1:	rep;	ret	/* use 2 byte return instruction when branch target */
378ae115bc7Smrj			/* AMD Software Optimization Guide - Section 6.2 */
379ae115bc7Smrj	SET_SIZE(fpxsave_ctxt)
3807c478bd9Sstevel@tonic-gate
381*7af88ac7SKuriakose Kuruvilla	ENTRY_NP(xsave_ctxt)
382*7af88ac7SKuriakose Kuruvilla	movl	4(%esp), %ecx		/* a struct fpu_ctx */
383*7af88ac7SKuriakose Kuruvilla	cmpl	$FPU_EN, FPU_CTX_FPU_FLAGS(%ecx)
384*7af88ac7SKuriakose Kuruvilla	jne	1f
385*7af88ac7SKuriakose Kuruvilla
386*7af88ac7SKuriakose Kuruvilla	movl	$_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%ecx)
387*7af88ac7SKuriakose Kuruvilla	movl	FPU_CTX_FPU_XSAVE_MASK(%ecx), %eax
388*7af88ac7SKuriakose Kuruvilla	movl	FPU_CTX_FPU_XSAVE_MASK+4(%ecx), %edx
389*7af88ac7SKuriakose Kuruvilla	leal	FPU_CTX_FPU_REGS(%ecx), %ecx
390*7af88ac7SKuriakose Kuruvilla	#xsave	(%ecx)
391*7af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x21
392*7af88ac7SKuriakose Kuruvilla
393*7af88ac7SKuriakose Kuruvilla	/*
394*7af88ac7SKuriakose Kuruvilla	 * (see notes above about "exception pointers")
395*7af88ac7SKuriakose Kuruvilla	 * TODO: does it apply to any machine that uses xsave?
396*7af88ac7SKuriakose Kuruvilla	 */
397*7af88ac7SKuriakose Kuruvilla	btw	$7, FXSAVE_STATE_FSW(%ecx)	/* Test saved ES bit */
398*7af88ac7SKuriakose Kuruvilla	jnc	0f				/* jump if ES = 0 */
399*7af88ac7SKuriakose Kuruvilla	fnclex		/* clear pending x87 exceptions */
400*7af88ac7SKuriakose Kuruvilla0:	ffree	%st(7)	/* clear tag bit to remove possible stack overflow */
401*7af88ac7SKuriakose Kuruvilla	fildl	.fpzero_const
402*7af88ac7SKuriakose Kuruvilla			/* dummy load changes all exception pointers */
403*7af88ac7SKuriakose Kuruvilla	STTS(%edx)	/* trap on next fpu touch */
404*7af88ac7SKuriakose Kuruvilla1:	ret
405*7af88ac7SKuriakose Kuruvilla	SET_SIZE(xsave_ctxt)
406*7af88ac7SKuriakose Kuruvilla
4077c478bd9Sstevel@tonic-gate#endif	/* __i386 */
408ae115bc7Smrj
409ae115bc7Smrj	.align	8
410ae115bc7Smrj.fpzero_const:
411ae115bc7Smrj	.4byte	0x0
412ae115bc7Smrj	.4byte	0x0
413ae115bc7Smrj
4147c478bd9Sstevel@tonic-gate#endif	/* __lint */
4157c478bd9Sstevel@tonic-gate
416ae115bc7Smrj
4177c478bd9Sstevel@tonic-gate#if defined(__lint)
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4207c478bd9Sstevel@tonic-gatevoid
4217c478bd9Sstevel@tonic-gatefpsave(struct fnsave_state *f)
4227c478bd9Sstevel@tonic-gate{}
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4257c478bd9Sstevel@tonic-gatevoid
4267c478bd9Sstevel@tonic-gatefpxsave(struct fxsave_state *f)
4277c478bd9Sstevel@tonic-gate{}
4287c478bd9Sstevel@tonic-gate
429*7af88ac7SKuriakose Kuruvilla/*ARGSUSED*/
430*7af88ac7SKuriakose Kuruvillavoid
431*7af88ac7SKuriakose Kuruvillaxsave(struct xsave_state *f, uint64_t m)
432*7af88ac7SKuriakose Kuruvilla{}
433*7af88ac7SKuriakose Kuruvilla
4347c478bd9Sstevel@tonic-gate#else	/* __lint */
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate#if defined(__amd64)
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate	ENTRY_NP(fpxsave)
439ae115bc7Smrj	CLTS
440f0f4f396Ska153516	FXSAVEQ	((%rdi))
441ae115bc7Smrj	fninit				/* clear exceptions, init x87 tags */
442ae115bc7Smrj	STTS(%rdi)			/* set TS bit in %cr0 (disable FPU) */
4437c478bd9Sstevel@tonic-gate	ret
4447c478bd9Sstevel@tonic-gate	SET_SIZE(fpxsave)
4457c478bd9Sstevel@tonic-gate
446*7af88ac7SKuriakose Kuruvilla	ENTRY_NP(xsave)
447*7af88ac7SKuriakose Kuruvilla	CLTS
448*7af88ac7SKuriakose Kuruvilla	movl	%esi, %eax		/* bv mask */
449*7af88ac7SKuriakose Kuruvilla	movq	%rsi, %rdx
450*7af88ac7SKuriakose Kuruvilla	shrq	$32, %rdx
451*7af88ac7SKuriakose Kuruvilla	#xsave	(%rdi)
452*7af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x27
453*7af88ac7SKuriakose Kuruvilla
454*7af88ac7SKuriakose Kuruvilla	fninit				/* clear exceptions, init x87 tags */
455*7af88ac7SKuriakose Kuruvilla	STTS(%rdi)			/* set TS bit in %cr0 (disable FPU) */
456*7af88ac7SKuriakose Kuruvilla	ret
457*7af88ac7SKuriakose Kuruvilla	SET_SIZE(xsave)
458*7af88ac7SKuriakose Kuruvilla
4597c478bd9Sstevel@tonic-gate#elif defined(__i386)
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate	ENTRY_NP(fpsave)
462ae115bc7Smrj	CLTS
463ae115bc7Smrj	movl	4(%esp), %eax
4647c478bd9Sstevel@tonic-gate	fnsave	(%eax)
465ae115bc7Smrj	STTS(%eax)			/* set TS bit in %cr0 (disable FPU) */
4667c478bd9Sstevel@tonic-gate	ret
4677c478bd9Sstevel@tonic-gate	SET_SIZE(fpsave)
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate	ENTRY_NP(fpxsave)
470ae115bc7Smrj	CLTS
471ae115bc7Smrj	movl	4(%esp), %eax
4727c478bd9Sstevel@tonic-gate	fxsave	(%eax)
473ae115bc7Smrj	fninit				/* clear exceptions, init x87 tags */
474ae115bc7Smrj	STTS(%eax)			/* set TS bit in %cr0 (disable FPU) */
4757c478bd9Sstevel@tonic-gate	ret
4767c478bd9Sstevel@tonic-gate	SET_SIZE(fpxsave)
4777c478bd9Sstevel@tonic-gate
478*7af88ac7SKuriakose Kuruvilla	ENTRY_NP(xsave)
479*7af88ac7SKuriakose Kuruvilla	CLTS
480*7af88ac7SKuriakose Kuruvilla	movl	4(%esp), %ecx
481*7af88ac7SKuriakose Kuruvilla	movl	8(%esp), %eax
482*7af88ac7SKuriakose Kuruvilla	movl	12(%esp), %edx
483*7af88ac7SKuriakose Kuruvilla	#xsave	(%ecx)
484*7af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x21
485*7af88ac7SKuriakose Kuruvilla
486*7af88ac7SKuriakose Kuruvilla	fninit				/* clear exceptions, init x87 tags */
487*7af88ac7SKuriakose Kuruvilla	STTS(%eax)			/* set TS bit in %cr0 (disable FPU) */
488*7af88ac7SKuriakose Kuruvilla	ret
489*7af88ac7SKuriakose Kuruvilla	SET_SIZE(xsave)
490*7af88ac7SKuriakose Kuruvilla
4917c478bd9Sstevel@tonic-gate#endif	/* __i386 */
4927c478bd9Sstevel@tonic-gate#endif	/* __lint */
4937c478bd9Sstevel@tonic-gate
4947c478bd9Sstevel@tonic-gate#if defined(__lint)
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4977c478bd9Sstevel@tonic-gatevoid
4987c478bd9Sstevel@tonic-gatefprestore(struct fnsave_state *f)
4997c478bd9Sstevel@tonic-gate{}
5007c478bd9Sstevel@tonic-gate
5017c478bd9Sstevel@tonic-gate/*ARGSUSED*/
5027c478bd9Sstevel@tonic-gatevoid
5037c478bd9Sstevel@tonic-gatefpxrestore(struct fxsave_state *f)
5047c478bd9Sstevel@tonic-gate{}
5057c478bd9Sstevel@tonic-gate
506*7af88ac7SKuriakose Kuruvilla/*ARGSUSED*/
507*7af88ac7SKuriakose Kuruvillavoid
508*7af88ac7SKuriakose Kuruvillaxrestore(struct xsave_state *f, uint64_t m)
509*7af88ac7SKuriakose Kuruvilla{}
510*7af88ac7SKuriakose Kuruvilla
5117c478bd9Sstevel@tonic-gate#else	/* __lint */
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate#if defined(__amd64)
5147c478bd9Sstevel@tonic-gate
5157c478bd9Sstevel@tonic-gate	ENTRY_NP(fpxrestore)
516ae115bc7Smrj	CLTS
517f0f4f396Ska153516	FXRSTORQ	((%rdi))
5187c478bd9Sstevel@tonic-gate	ret
5197c478bd9Sstevel@tonic-gate	SET_SIZE(fpxrestore)
5207c478bd9Sstevel@tonic-gate
521*7af88ac7SKuriakose Kuruvilla	ENTRY_NP(xrestore)
522*7af88ac7SKuriakose Kuruvilla	CLTS
523*7af88ac7SKuriakose Kuruvilla	movl	%esi, %eax		/* bv mask */
524*7af88ac7SKuriakose Kuruvilla	movq	%rsi, %rdx
525*7af88ac7SKuriakose Kuruvilla	shrq	$32, %rdx
526*7af88ac7SKuriakose Kuruvilla	#xrstor	(%rdi)
527*7af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x2f
528*7af88ac7SKuriakose Kuruvilla	ret
529*7af88ac7SKuriakose Kuruvilla	SET_SIZE(xrestore)
530*7af88ac7SKuriakose Kuruvilla
5317c478bd9Sstevel@tonic-gate#elif defined(__i386)
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate	ENTRY_NP(fprestore)
534ae115bc7Smrj	CLTS
535ae115bc7Smrj	movl	4(%esp), %eax
5367c478bd9Sstevel@tonic-gate	frstor	(%eax)
5377c478bd9Sstevel@tonic-gate	ret
5387c478bd9Sstevel@tonic-gate	SET_SIZE(fprestore)
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate	ENTRY_NP(fpxrestore)
541ae115bc7Smrj	CLTS
542ae115bc7Smrj	movl	4(%esp), %eax
5437c478bd9Sstevel@tonic-gate	fxrstor	(%eax)
5447c478bd9Sstevel@tonic-gate	ret
5457c478bd9Sstevel@tonic-gate	SET_SIZE(fpxrestore)
5467c478bd9Sstevel@tonic-gate
547*7af88ac7SKuriakose Kuruvilla	ENTRY_NP(xrestore)
548*7af88ac7SKuriakose Kuruvilla	CLTS
549*7af88ac7SKuriakose Kuruvilla	movl	4(%esp), %ecx
550*7af88ac7SKuriakose Kuruvilla	movl	8(%esp), %eax
551*7af88ac7SKuriakose Kuruvilla	movl	12(%esp), %edx
552*7af88ac7SKuriakose Kuruvilla	#xrstor	(%ecx)
553*7af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x29
554*7af88ac7SKuriakose Kuruvilla	ret
555*7af88ac7SKuriakose Kuruvilla	SET_SIZE(xrestore)
556*7af88ac7SKuriakose Kuruvilla
5577c478bd9Sstevel@tonic-gate#endif	/* __i386 */
5587c478bd9Sstevel@tonic-gate#endif	/* __lint */
5597c478bd9Sstevel@tonic-gate
5607c478bd9Sstevel@tonic-gate/*
5617c478bd9Sstevel@tonic-gate * Disable the floating point unit.
5627c478bd9Sstevel@tonic-gate */
5637c478bd9Sstevel@tonic-gate
5647c478bd9Sstevel@tonic-gate#if defined(__lint)
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gatevoid
5677c478bd9Sstevel@tonic-gatefpdisable(void)
5687c478bd9Sstevel@tonic-gate{}
5697c478bd9Sstevel@tonic-gate
5707c478bd9Sstevel@tonic-gate#else	/* __lint */
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate#if defined(__amd64)
5737c478bd9Sstevel@tonic-gate
5747c478bd9Sstevel@tonic-gate	ENTRY_NP(fpdisable)
575ae115bc7Smrj	STTS(%rdi)			/* set TS bit in %cr0 (disable FPU) */
5767c478bd9Sstevel@tonic-gate	ret
5777c478bd9Sstevel@tonic-gate	SET_SIZE(fpdisable)
5787c478bd9Sstevel@tonic-gate
5797c478bd9Sstevel@tonic-gate#elif defined(__i386)
5807c478bd9Sstevel@tonic-gate
5817c478bd9Sstevel@tonic-gate	ENTRY_NP(fpdisable)
582ae115bc7Smrj	STTS(%eax)
5837c478bd9Sstevel@tonic-gate	ret
5847c478bd9Sstevel@tonic-gate	SET_SIZE(fpdisable)
5857c478bd9Sstevel@tonic-gate
5867c478bd9Sstevel@tonic-gate#endif	/* __i386 */
5877c478bd9Sstevel@tonic-gate#endif	/* __lint */
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate/*
5907c478bd9Sstevel@tonic-gate * Initialize the fpu hardware.
5917c478bd9Sstevel@tonic-gate */
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate#if defined(__lint)
5947c478bd9Sstevel@tonic-gate
5957c478bd9Sstevel@tonic-gatevoid
5967c478bd9Sstevel@tonic-gatefpinit(void)
5977c478bd9Sstevel@tonic-gate{}
5987c478bd9Sstevel@tonic-gate
5997c478bd9Sstevel@tonic-gate#else	/* __lint */
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate#if defined(__amd64)
6027c478bd9Sstevel@tonic-gate
6037c478bd9Sstevel@tonic-gate	ENTRY_NP(fpinit)
604ae115bc7Smrj	CLTS
605*7af88ac7SKuriakose Kuruvilla	cmpl	$FP_XSAVE, fp_save_mech
606*7af88ac7SKuriakose Kuruvilla	je	1f
607*7af88ac7SKuriakose Kuruvilla
608*7af88ac7SKuriakose Kuruvilla	/* fxsave */
6097c478bd9Sstevel@tonic-gate	leaq	sse_initial(%rip), %rax
610f0f4f396Ska153516	FXRSTORQ	((%rax))		/* load clean initial state */
6117c478bd9Sstevel@tonic-gate	ret
612*7af88ac7SKuriakose Kuruvilla
613*7af88ac7SKuriakose Kuruvilla1:	/* xsave */
614*7af88ac7SKuriakose Kuruvilla	leaq	avx_initial(%rip), %rcx
615*7af88ac7SKuriakose Kuruvilla	xorl	%edx, %edx
616*7af88ac7SKuriakose Kuruvilla	movl	$XFEATURE_AVX, %eax
617*7af88ac7SKuriakose Kuruvilla	bt	$X86FSET_AVX, x86_featureset
618*7af88ac7SKuriakose Kuruvilla	cmovael	%edx, %eax
619*7af88ac7SKuriakose Kuruvilla	orl	$(XFEATURE_LEGACY_FP | XFEATURE_SSE), %eax
620*7af88ac7SKuriakose Kuruvilla	/* xrstor (%rcx) */
621*7af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x29		/* load clean initial state */
622*7af88ac7SKuriakose Kuruvilla	ret
6237c478bd9Sstevel@tonic-gate	SET_SIZE(fpinit)
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate#elif defined(__i386)
6267c478bd9Sstevel@tonic-gate
6277c478bd9Sstevel@tonic-gate	ENTRY_NP(fpinit)
628ae115bc7Smrj	CLTS
629*7af88ac7SKuriakose Kuruvilla	cmpl	$FP_FXSAVE, fp_save_mech
6307c478bd9Sstevel@tonic-gate	je	1f
631*7af88ac7SKuriakose Kuruvilla	cmpl	$FP_XSAVE, fp_save_mech
632*7af88ac7SKuriakose Kuruvilla	je	2f
6337c478bd9Sstevel@tonic-gate
634*7af88ac7SKuriakose Kuruvilla	/* fnsave */
635ae115bc7Smrj	fninit
6367c478bd9Sstevel@tonic-gate	movl	$x87_initial, %eax
637ae115bc7Smrj	frstor	(%eax)			/* load clean initial state */
6387c478bd9Sstevel@tonic-gate	ret
639*7af88ac7SKuriakose Kuruvilla
640*7af88ac7SKuriakose Kuruvilla1:	/* fxsave */
6417c478bd9Sstevel@tonic-gate	movl	$sse_initial, %eax
642ae115bc7Smrj	fxrstor	(%eax)			/* load clean initial state */
6437c478bd9Sstevel@tonic-gate	ret
644*7af88ac7SKuriakose Kuruvilla
645*7af88ac7SKuriakose Kuruvilla2:	/* xsave */
646*7af88ac7SKuriakose Kuruvilla	movl	$avx_initial, %ecx
647*7af88ac7SKuriakose Kuruvilla	xorl	%edx, %edx
648*7af88ac7SKuriakose Kuruvilla	movl	$XFEATURE_AVX, %eax
649*7af88ac7SKuriakose Kuruvilla	bt	$X86FSET_AVX, x86_featureset
650*7af88ac7SKuriakose Kuruvilla	cmovael	%edx, %eax
651*7af88ac7SKuriakose Kuruvilla	orl	$(XFEATURE_LEGACY_FP | XFEATURE_SSE), %eax
652*7af88ac7SKuriakose Kuruvilla	/* xrstor (%ecx) */
653*7af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x29	/* load clean initial state */
654*7af88ac7SKuriakose Kuruvilla	ret
6557c478bd9Sstevel@tonic-gate	SET_SIZE(fpinit)
6567c478bd9Sstevel@tonic-gate
6577c478bd9Sstevel@tonic-gate#endif	/* __i386 */
6587c478bd9Sstevel@tonic-gate#endif	/* __lint */
6597c478bd9Sstevel@tonic-gate
6607c478bd9Sstevel@tonic-gate/*
6617c478bd9Sstevel@tonic-gate * Clears FPU exception state.
6627c478bd9Sstevel@tonic-gate * Returns the FP status word.
6637c478bd9Sstevel@tonic-gate */
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate#if defined(__lint)
6667c478bd9Sstevel@tonic-gate
6677c478bd9Sstevel@tonic-gateuint32_t
6687c478bd9Sstevel@tonic-gatefperr_reset(void)
669ae115bc7Smrj{ return (0); }
6707c478bd9Sstevel@tonic-gate
6717c478bd9Sstevel@tonic-gateuint32_t
6727c478bd9Sstevel@tonic-gatefpxerr_reset(void)
673ae115bc7Smrj{ return (0); }
6747c478bd9Sstevel@tonic-gate
6757c478bd9Sstevel@tonic-gate#else	/* __lint */
6767c478bd9Sstevel@tonic-gate
6777c478bd9Sstevel@tonic-gate#if defined(__amd64)
6787c478bd9Sstevel@tonic-gate
6797c478bd9Sstevel@tonic-gate	ENTRY_NP(fperr_reset)
680ae115bc7Smrj	CLTS
6817c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
682ae115bc7Smrj	fnstsw	%ax
683ae115bc7Smrj	fnclex
6847c478bd9Sstevel@tonic-gate	ret
6857c478bd9Sstevel@tonic-gate	SET_SIZE(fperr_reset)
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate	ENTRY_NP(fpxerr_reset)
6887c478bd9Sstevel@tonic-gate	pushq	%rbp
6897c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
6907c478bd9Sstevel@tonic-gate	subq	$0x10, %rsp		/* make some temporary space */
691ae115bc7Smrj	CLTS
692ae115bc7Smrj	stmxcsr	(%rsp)
6937c478bd9Sstevel@tonic-gate	movl	(%rsp), %eax
6947c478bd9Sstevel@tonic-gate	andl	$_BITNOT(SSE_MXCSR_EFLAGS), (%rsp)
6957c478bd9Sstevel@tonic-gate	ldmxcsr	(%rsp)			/* clear processor exceptions */
6967c478bd9Sstevel@tonic-gate	leave
6977c478bd9Sstevel@tonic-gate	ret
6987c478bd9Sstevel@tonic-gate	SET_SIZE(fpxerr_reset)
6997c478bd9Sstevel@tonic-gate
7007c478bd9Sstevel@tonic-gate#elif defined(__i386)
7017c478bd9Sstevel@tonic-gate
7027c478bd9Sstevel@tonic-gate	ENTRY_NP(fperr_reset)
703ae115bc7Smrj	CLTS
7047c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
705ae115bc7Smrj	fnstsw	%ax
706ae115bc7Smrj	fnclex
7077c478bd9Sstevel@tonic-gate	ret
7087c478bd9Sstevel@tonic-gate	SET_SIZE(fperr_reset)
7097c478bd9Sstevel@tonic-gate
7107c478bd9Sstevel@tonic-gate	ENTRY_NP(fpxerr_reset)
711ae115bc7Smrj	CLTS
712ae115bc7Smrj	subl	$4, %esp		/* make some temporary space */
713ae115bc7Smrj	stmxcsr	(%esp)
7147c478bd9Sstevel@tonic-gate	movl	(%esp), %eax
7157c478bd9Sstevel@tonic-gate	andl	$_BITNOT(SSE_MXCSR_EFLAGS), (%esp)
716ae115bc7Smrj	ldmxcsr	(%esp)			/* clear processor exceptions */
7177c478bd9Sstevel@tonic-gate	addl	$4, %esp
7187c478bd9Sstevel@tonic-gate	ret
7197c478bd9Sstevel@tonic-gate	SET_SIZE(fpxerr_reset)
7207c478bd9Sstevel@tonic-gate
7217c478bd9Sstevel@tonic-gate#endif	/* __i386 */
7227c478bd9Sstevel@tonic-gate#endif	/* __lint */
7237c478bd9Sstevel@tonic-gate
7247c478bd9Sstevel@tonic-gate#if defined(__lint)
7257c478bd9Sstevel@tonic-gate
7267c478bd9Sstevel@tonic-gateuint32_t
7277c478bd9Sstevel@tonic-gatefpgetcwsw(void)
7287c478bd9Sstevel@tonic-gate{
7297c478bd9Sstevel@tonic-gate	return (0);
7307c478bd9Sstevel@tonic-gate}
7317c478bd9Sstevel@tonic-gate
7327c478bd9Sstevel@tonic-gate#else   /* __lint */
7337c478bd9Sstevel@tonic-gate
7347c478bd9Sstevel@tonic-gate#if defined(__amd64)
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate	ENTRY_NP(fpgetcwsw)
7377c478bd9Sstevel@tonic-gate	pushq	%rbp
7387c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
7397c478bd9Sstevel@tonic-gate	subq	$0x10, %rsp		/* make some temporary space	*/
740ae115bc7Smrj	CLTS
7417c478bd9Sstevel@tonic-gate	fnstsw	(%rsp)			/* store the status word	*/
7427c478bd9Sstevel@tonic-gate	fnstcw	2(%rsp)			/* store the control word	*/
7437c478bd9Sstevel@tonic-gate	movl	(%rsp), %eax		/* put both in %eax		*/
7447c478bd9Sstevel@tonic-gate	leave
7457c478bd9Sstevel@tonic-gate	ret
7467c478bd9Sstevel@tonic-gate	SET_SIZE(fpgetcwsw)
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate#elif defined(__i386)
7497c478bd9Sstevel@tonic-gate
7507c478bd9Sstevel@tonic-gate	ENTRY_NP(fpgetcwsw)
751ae115bc7Smrj	CLTS
7527c478bd9Sstevel@tonic-gate	subl	$4, %esp		/* make some temporary space	*/
7537c478bd9Sstevel@tonic-gate	fnstsw	(%esp)			/* store the status word	*/
7547c478bd9Sstevel@tonic-gate	fnstcw	2(%esp)			/* store the control word	*/
7557c478bd9Sstevel@tonic-gate	movl	(%esp), %eax		/* put both in %eax		*/
7567c478bd9Sstevel@tonic-gate	addl	$4, %esp
7577c478bd9Sstevel@tonic-gate	ret
7587c478bd9Sstevel@tonic-gate	SET_SIZE(fpgetcwsw)
7597c478bd9Sstevel@tonic-gate
7607c478bd9Sstevel@tonic-gate#endif	/* __i386 */
7617c478bd9Sstevel@tonic-gate#endif  /* __lint */
7627c478bd9Sstevel@tonic-gate
7637c478bd9Sstevel@tonic-gate/*
7647c478bd9Sstevel@tonic-gate * Returns the MXCSR register.
7657c478bd9Sstevel@tonic-gate */
7667c478bd9Sstevel@tonic-gate
7677c478bd9Sstevel@tonic-gate#if defined(__lint)
7687c478bd9Sstevel@tonic-gate
7697c478bd9Sstevel@tonic-gateuint32_t
7707c478bd9Sstevel@tonic-gatefpgetmxcsr(void)
7717c478bd9Sstevel@tonic-gate{
7727c478bd9Sstevel@tonic-gate	return (0);
7737c478bd9Sstevel@tonic-gate}
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate#else   /* __lint */
7767c478bd9Sstevel@tonic-gate
7777c478bd9Sstevel@tonic-gate#if defined(__amd64)
7787c478bd9Sstevel@tonic-gate
7797c478bd9Sstevel@tonic-gate	ENTRY_NP(fpgetmxcsr)
7807c478bd9Sstevel@tonic-gate	pushq	%rbp
7817c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
7827c478bd9Sstevel@tonic-gate	subq	$0x10, %rsp		/* make some temporary space */
783ae115bc7Smrj	CLTS
784ae115bc7Smrj	stmxcsr	(%rsp)
7857c478bd9Sstevel@tonic-gate	movl	(%rsp), %eax
7867c478bd9Sstevel@tonic-gate	leave
7877c478bd9Sstevel@tonic-gate	ret
7887c478bd9Sstevel@tonic-gate	SET_SIZE(fpgetmxcsr)
7897c478bd9Sstevel@tonic-gate
7907c478bd9Sstevel@tonic-gate#elif defined(__i386)
7917c478bd9Sstevel@tonic-gate
7927c478bd9Sstevel@tonic-gate	ENTRY_NP(fpgetmxcsr)
793ae115bc7Smrj	CLTS
7947c478bd9Sstevel@tonic-gate	subl	$4, %esp		/* make some temporary space */
795ae115bc7Smrj	stmxcsr	(%esp)
7967c478bd9Sstevel@tonic-gate	movl	(%esp), %eax
7977c478bd9Sstevel@tonic-gate	addl	$4, %esp
7987c478bd9Sstevel@tonic-gate	ret
7997c478bd9Sstevel@tonic-gate	SET_SIZE(fpgetmxcsr)
8007c478bd9Sstevel@tonic-gate
8017c478bd9Sstevel@tonic-gate#endif	/* __i386 */
8027c478bd9Sstevel@tonic-gate#endif  /* __lint */
803