xref: /titanic_52/usr/src/uts/intel/ia32/ml/float.s (revision 4d40e39c66a331aefef24083480939f0e78a9045)
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/*
237af88ac7SKuriakose Kuruvilla * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
24*4d40e39cSAndy Fiddaman * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate/*      Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
287c478bd9Sstevel@tonic-gate/*      Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T   */
297c478bd9Sstevel@tonic-gate/*        All Rights Reserved   */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate/*      Copyright (c) 1987, 1988 Microsoft Corporation  */
327c478bd9Sstevel@tonic-gate/*        All Rights Reserved   */
337c478bd9Sstevel@tonic-gate
347af88ac7SKuriakose Kuruvilla/*
357af88ac7SKuriakose Kuruvilla * Copyright (c) 2009, Intel Corporation.
367af88ac7SKuriakose Kuruvilla * All rights reserved.
377af88ac7SKuriakose Kuruvilla */
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
40ae115bc7Smrj#include <sys/asm_misc.h>
417c478bd9Sstevel@tonic-gate#include <sys/regset.h>
427c478bd9Sstevel@tonic-gate#include <sys/privregs.h>
437c478bd9Sstevel@tonic-gate#include <sys/x86_archext.h>
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate#if defined(__lint)
467c478bd9Sstevel@tonic-gate#include <sys/types.h>
477c478bd9Sstevel@tonic-gate#include <sys/fp.h>
487c478bd9Sstevel@tonic-gate#else
497c478bd9Sstevel@tonic-gate#include "assym.h"
507c478bd9Sstevel@tonic-gate#endif
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate#if defined(__lint)
537c478bd9Sstevel@tonic-gate
54ae115bc7Smrjuint_t
55ae115bc7Smrjfpu_initial_probe(void)
56ae115bc7Smrj{ return (0); }
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate#else	/* __lint */
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate	/*
61ae115bc7Smrj	 * Returns zero if x87 "chip" is present(!)
627c478bd9Sstevel@tonic-gate	 */
63ae115bc7Smrj	ENTRY_NP(fpu_initial_probe)
64ae115bc7Smrj	CLTS
65ae115bc7Smrj	fninit
66ae115bc7Smrj	fnstsw	%ax
67ae115bc7Smrj	movzbl	%al, %eax
68ae115bc7Smrj	ret
69ae115bc7Smrj	SET_SIZE(fpu_initial_probe)
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate#endif	/* __lint */
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate#if defined(__lint)
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate/*ARGSUSED*/
767c478bd9Sstevel@tonic-gatevoid
77ae115bc7Smrjfxsave_insn(struct fxsave_state *fx)
787c478bd9Sstevel@tonic-gate{}
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate#else	/* __lint */
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate#if defined(__amd64)
837c478bd9Sstevel@tonic-gate
84ae115bc7Smrj	ENTRY_NP(fxsave_insn)
85f0f4f396Ska153516	FXSAVEQ	((%rdi))
867c478bd9Sstevel@tonic-gate	ret
87ae115bc7Smrj	SET_SIZE(fxsave_insn)
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate#elif defined(__i386)
907c478bd9Sstevel@tonic-gate
91ae115bc7Smrj	ENTRY_NP(fxsave_insn)
92ae115bc7Smrj	movl	4(%esp), %eax
93ae115bc7Smrj	fxsave	(%eax)
94ae115bc7Smrj	ret
95ae115bc7Smrj	SET_SIZE(fxsave_insn)
96ae115bc7Smrj
97ae115bc7Smrj#endif
98ae115bc7Smrj
99ae115bc7Smrj#endif	/* __lint */
100ae115bc7Smrj
101ae115bc7Smrj#if defined(__i386)
102ae115bc7Smrj
103ae115bc7Smrj/*
104ae115bc7Smrj * If (num1/num2 > num1/num3) the FPU has the FDIV bug.
105ae115bc7Smrj */
106ae115bc7Smrj
107ae115bc7Smrj#if defined(__lint)
108ae115bc7Smrj
109ae115bc7Smrjint
110ae115bc7Smrjfpu_probe_pentium_fdivbug(void)
111ae115bc7Smrj{ return (0); }
112ae115bc7Smrj
113ae115bc7Smrj#else	/* __lint */
114ae115bc7Smrj
115ae115bc7Smrj	ENTRY_NP(fpu_probe_pentium_fdivbug)
116ae115bc7Smrj	fldl	.num1
117ae115bc7Smrj	fldl	.num2
1187c478bd9Sstevel@tonic-gate	fdivr	%st(1), %st
1197c478bd9Sstevel@tonic-gate	fxch	%st(1)
120ae115bc7Smrj	fdivl	.num3
1217c478bd9Sstevel@tonic-gate	fcompp
1227c478bd9Sstevel@tonic-gate	fstsw	%ax
1237c478bd9Sstevel@tonic-gate	sahf
124ae115bc7Smrj	jae	0f
125ae115bc7Smrj	movl	$1, %eax
1267c478bd9Sstevel@tonic-gate	ret
1277c478bd9Sstevel@tonic-gate
128ae115bc7Smrj0:	xorl	%eax, %eax
129ae115bc7Smrj	ret
130ae115bc7Smrj
131ae115bc7Smrj	.align	4
132ae115bc7Smrj.num1:	.4byte	0xbce4217d	/* 4.999999 */
133ae115bc7Smrj	.4byte	0x4013ffff
134ae115bc7Smrj.num2:	.4byte	0x0		/* 15.0 */
135ae115bc7Smrj	.4byte	0x402e0000
136ae115bc7Smrj.num3:	.4byte	0xde7210bf	/* 14.999999 */
137ae115bc7Smrj	.4byte	0x402dffff
138ae115bc7Smrj	SET_SIZE(fpu_probe_pentium_fdivbug)
139ae115bc7Smrj
140ae115bc7Smrj#endif	/* __lint */
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate/*
1437c478bd9Sstevel@tonic-gate * To cope with processors that do not implement fxsave/fxrstor
1447c478bd9Sstevel@tonic-gate * instructions, patch hot paths in the kernel to use them only
1457c478bd9Sstevel@tonic-gate * when that feature has been detected.
1467c478bd9Sstevel@tonic-gate */
147ae115bc7Smrj
148ae115bc7Smrj#if defined(__lint)
149ae115bc7Smrj
150ae115bc7Smrjvoid
151ae115bc7Smrjpatch_sse(void)
152ae115bc7Smrj{}
153ae115bc7Smrj
154ae115bc7Smrjvoid
155ae115bc7Smrjpatch_sse2(void)
156ae115bc7Smrj{}
157ae115bc7Smrj
1587af88ac7SKuriakose Kuruvillavoid
1597af88ac7SKuriakose Kuruvillapatch_xsave(void)
1607af88ac7SKuriakose Kuruvilla{}
1617af88ac7SKuriakose Kuruvilla
162ae115bc7Smrj#else	/* __lint */
163ae115bc7Smrj
1647c478bd9Sstevel@tonic-gate	ENTRY_NP(patch_sse)
165ae115bc7Smrj	_HOT_PATCH_PROLOG
1667c478bd9Sstevel@tonic-gate	/
167ae115bc7Smrj	/	frstor (%ebx); nop	-> fxrstor (%ebx)
1687c478bd9Sstevel@tonic-gate	/
169ae115bc7Smrj	_HOT_PATCH(_fxrstor_ebx_insn, _patch_fxrstor_ebx, 3)
1707c478bd9Sstevel@tonic-gate	/
1717c478bd9Sstevel@tonic-gate	/	lock; xorl $0, (%esp)	-> sfence; ret
1727c478bd9Sstevel@tonic-gate	/
173ae115bc7Smrj	_HOT_PATCH(_sfence_ret_insn, _patch_sfence_ret, 4)
174ae115bc7Smrj	_HOT_PATCH_EPILOG
1757c478bd9Sstevel@tonic-gate	ret
176ae115bc7Smrj_fxrstor_ebx_insn:			/ see ndptrap_frstor()
177ae115bc7Smrj	fxrstor	(%ebx)
1787c478bd9Sstevel@tonic-gate_ldmxcsr_ebx_insn:			/ see resume_from_zombie()
1797c478bd9Sstevel@tonic-gate	ldmxcsr	(%ebx)
1807c478bd9Sstevel@tonic-gate_sfence_ret_insn:			/ see membar_producer()
1817c478bd9Sstevel@tonic-gate	.byte	0xf, 0xae, 0xf8		/ [sfence instruction]
1827c478bd9Sstevel@tonic-gate	ret
1837c478bd9Sstevel@tonic-gate	SET_SIZE(patch_sse)
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate	ENTRY_NP(patch_sse2)
186ae115bc7Smrj	_HOT_PATCH_PROLOG
1877c478bd9Sstevel@tonic-gate	/
1887c478bd9Sstevel@tonic-gate	/	lock; xorl $0, (%esp)	-> lfence; ret
1897c478bd9Sstevel@tonic-gate	/
190ae115bc7Smrj	_HOT_PATCH(_lfence_ret_insn, _patch_lfence_ret, 4)
191ae115bc7Smrj	_HOT_PATCH_EPILOG
1927c478bd9Sstevel@tonic-gate	ret
1937c478bd9Sstevel@tonic-gate_lfence_ret_insn:			/ see membar_consumer()
1947c478bd9Sstevel@tonic-gate	.byte	0xf, 0xae, 0xe8		/ [lfence instruction]
1957c478bd9Sstevel@tonic-gate	ret
1967c478bd9Sstevel@tonic-gate	SET_SIZE(patch_sse2)
1977c478bd9Sstevel@tonic-gate
1987af88ac7SKuriakose Kuruvilla	/*
1997af88ac7SKuriakose Kuruvilla	 * Patch lazy fp restore instructions in the trap handler
2007af88ac7SKuriakose Kuruvilla	 * to use xrstor instead of frstor
2017af88ac7SKuriakose Kuruvilla	 */
2027af88ac7SKuriakose Kuruvilla	ENTRY_NP(patch_xsave)
2037af88ac7SKuriakose Kuruvilla	_HOT_PATCH_PROLOG
2047af88ac7SKuriakose Kuruvilla	/
2057af88ac7SKuriakose Kuruvilla	/	frstor (%ebx); nop	-> xrstor (%ebx)
2067af88ac7SKuriakose Kuruvilla	/
2077af88ac7SKuriakose Kuruvilla	_HOT_PATCH(_xrstor_ebx_insn, _patch_xrstor_ebx, 3)
2087af88ac7SKuriakose Kuruvilla	_HOT_PATCH_EPILOG
2097af88ac7SKuriakose Kuruvilla	ret
2107af88ac7SKuriakose Kuruvilla_xrstor_ebx_insn:			/ see ndptrap_frstor()
2117af88ac7SKuriakose Kuruvilla	#xrstor (%ebx)
2127af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x2b
2137af88ac7SKuriakose Kuruvilla	SET_SIZE(patch_xsave)
2147af88ac7SKuriakose Kuruvilla
2157c478bd9Sstevel@tonic-gate#endif	/* __lint */
216ae115bc7Smrj#endif	/* __i386 */
2177c478bd9Sstevel@tonic-gate
2187af88ac7SKuriakose Kuruvilla#if defined(__amd64)
2197af88ac7SKuriakose Kuruvilla#if defined(__lint)
2207af88ac7SKuriakose Kuruvilla
2217af88ac7SKuriakose Kuruvillavoid
2227af88ac7SKuriakose Kuruvillapatch_xsave(void)
2237af88ac7SKuriakose Kuruvilla{}
2247af88ac7SKuriakose Kuruvilla
2257af88ac7SKuriakose Kuruvilla#else	/* __lint */
2267af88ac7SKuriakose Kuruvilla
2277af88ac7SKuriakose Kuruvilla	/*
2287af88ac7SKuriakose Kuruvilla	 * Patch lazy fp restore instructions in the trap handler
2297af88ac7SKuriakose Kuruvilla	 * to use xrstor instead of fxrstorq
2307af88ac7SKuriakose Kuruvilla	 */
2317af88ac7SKuriakose Kuruvilla	ENTRY_NP(patch_xsave)
2327af88ac7SKuriakose Kuruvilla	pushq	%rbx
2337af88ac7SKuriakose Kuruvilla	pushq	%rbp
2347af88ac7SKuriakose Kuruvilla	pushq	%r15
2357af88ac7SKuriakose Kuruvilla	/
2367af88ac7SKuriakose Kuruvilla	/	FXRSTORQ (%rbx);	-> xrstor (%rbx)
2377af88ac7SKuriakose Kuruvilla	/ hot_patch(_xrstor_rbx_insn, _patch_xrstorq_rbx, 4)
2387af88ac7SKuriakose Kuruvilla	/
2397af88ac7SKuriakose Kuruvilla	leaq	_patch_xrstorq_rbx(%rip), %rbx
2407af88ac7SKuriakose Kuruvilla	leaq	_xrstor_rbx_insn(%rip), %rbp
2417af88ac7SKuriakose Kuruvilla	movq	$4, %r15
2427af88ac7SKuriakose Kuruvilla1:
2437af88ac7SKuriakose Kuruvilla	movq	%rbx, %rdi			/* patch address */
2447af88ac7SKuriakose Kuruvilla	movzbq	(%rbp), %rsi			/* instruction byte */
2457af88ac7SKuriakose Kuruvilla	movq	$1, %rdx			/* count */
2467af88ac7SKuriakose Kuruvilla	call	hot_patch_kernel_text
2477af88ac7SKuriakose Kuruvilla	addq	$1, %rbx
2487af88ac7SKuriakose Kuruvilla	addq	$1, %rbp
2497af88ac7SKuriakose Kuruvilla	subq	$1, %r15
2507af88ac7SKuriakose Kuruvilla	jnz	1b
2517af88ac7SKuriakose Kuruvilla
2527af88ac7SKuriakose Kuruvilla	popq	%r15
2537af88ac7SKuriakose Kuruvilla	popq	%rbp
2547af88ac7SKuriakose Kuruvilla	popq	%rbx
2557af88ac7SKuriakose Kuruvilla	ret
2567af88ac7SKuriakose Kuruvilla
2577af88ac7SKuriakose Kuruvilla_xrstor_rbx_insn:			/ see ndptrap_frstor()
2587af88ac7SKuriakose Kuruvilla	#rex.W=1 (.byte 0x48)
2597af88ac7SKuriakose Kuruvilla	#xrstor (%rbx)
2607af88ac7SKuriakose Kuruvilla	.byte	0x48, 0x0f, 0xae, 0x2b
2617af88ac7SKuriakose Kuruvilla	SET_SIZE(patch_xsave)
2627af88ac7SKuriakose Kuruvilla
2637af88ac7SKuriakose Kuruvilla#endif	/* __lint */
2647af88ac7SKuriakose Kuruvilla#endif	/* __amd64 */
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate/*
2677c478bd9Sstevel@tonic-gate * One of these routines is called from any lwp with floating
268ae115bc7Smrj * point context as part of the prolog of a context switch.
2697c478bd9Sstevel@tonic-gate */
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate#if defined(__lint)
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate/*ARGSUSED*/
2747c478bd9Sstevel@tonic-gatevoid
2757af88ac7SKuriakose Kuruvillaxsave_ctxt(void *arg)
2767af88ac7SKuriakose Kuruvilla{}
2777af88ac7SKuriakose Kuruvilla
2787af88ac7SKuriakose Kuruvilla/*ARGSUSED*/
2797af88ac7SKuriakose Kuruvillavoid
280ae115bc7Smrjfpxsave_ctxt(void *arg)
2817c478bd9Sstevel@tonic-gate{}
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate/*ARGSUSED*/
2847c478bd9Sstevel@tonic-gatevoid
285ae115bc7Smrjfpnsave_ctxt(void *arg)
2867c478bd9Sstevel@tonic-gate{}
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate#else	/* __lint */
2897c478bd9Sstevel@tonic-gate
2907c478bd9Sstevel@tonic-gate#if defined(__amd64)
2917c478bd9Sstevel@tonic-gate
292ae115bc7Smrj	ENTRY_NP(fpxsave_ctxt)
293ae115bc7Smrj	cmpl	$FPU_EN, FPU_CTX_FPU_FLAGS(%rdi)
2947c478bd9Sstevel@tonic-gate	jne	1f
295ae115bc7Smrj
296ae115bc7Smrj	movl	$_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%rdi)
297f0f4f396Ska153516	FXSAVEQ	(FPU_CTX_FPU_REGS(%rdi))
298f0f4f396Ska153516
299ae115bc7Smrj	/*
300ae115bc7Smrj	 * On certain AMD processors, the "exception pointers" i.e. the last
301ae115bc7Smrj	 * instruction pointer, last data pointer, and last opcode
302ae115bc7Smrj	 * are saved by the fxsave instruction ONLY if the exception summary
303ae115bc7Smrj	 * bit is set.
304ae115bc7Smrj	 *
305ae115bc7Smrj	 * To ensure that we don't leak these values into the next context
306ae115bc7Smrj	 * on the cpu, we could just issue an fninit here, but that's
307ae115bc7Smrj	 * rather slow and so we issue an instruction sequence that
308ae115bc7Smrj	 * clears them more quickly, if a little obscurely.
309ae115bc7Smrj	 */
310ae115bc7Smrj	btw	$7, FXSAVE_STATE_FSW(%rdi)	/* Test saved ES bit */
311ae115bc7Smrj	jnc	0f				/* jump if ES = 0 */
3127c478bd9Sstevel@tonic-gate	fnclex		/* clear pending x87 exceptions */
313ae115bc7Smrj0:	ffree	%st(7)	/* clear tag bit to remove possible stack overflow */
314ae115bc7Smrj	fildl	.fpzero_const(%rip)
315ae115bc7Smrj			/* dummy load changes all exception pointers */
316ae115bc7Smrj	STTS(%rsi)	/* trap on next fpu touch */
31785641879Skalai1:	rep;	ret	/* use 2 byte return instruction when branch target */
31885641879Skalai			/* AMD Software Optimization Guide - Section 6.2 */
319ae115bc7Smrj	SET_SIZE(fpxsave_ctxt)
3207c478bd9Sstevel@tonic-gate
3217af88ac7SKuriakose Kuruvilla	ENTRY_NP(xsave_ctxt)
3227af88ac7SKuriakose Kuruvilla	cmpl	$FPU_EN, FPU_CTX_FPU_FLAGS(%rdi)
3237af88ac7SKuriakose Kuruvilla	jne	1f
3247af88ac7SKuriakose Kuruvilla	movl	$_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%rdi)
3257af88ac7SKuriakose Kuruvilla	/*
3267af88ac7SKuriakose Kuruvilla	 * Setup xsave flags in EDX:EAX
3277af88ac7SKuriakose Kuruvilla	 */
3287af88ac7SKuriakose Kuruvilla	movl	FPU_CTX_FPU_XSAVE_MASK(%rdi), %eax
3297af88ac7SKuriakose Kuruvilla	movl	FPU_CTX_FPU_XSAVE_MASK+4(%rdi), %edx
3307af88ac7SKuriakose Kuruvilla	leaq	FPU_CTX_FPU_REGS(%rdi), %rsi
3317af88ac7SKuriakose Kuruvilla	#xsave	(%rsi)
3327af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x26
3337af88ac7SKuriakose Kuruvilla
3347af88ac7SKuriakose Kuruvilla	/*
3357af88ac7SKuriakose Kuruvilla	 * (see notes above about "exception pointers")
3367af88ac7SKuriakose Kuruvilla	 * TODO: does it apply to any machine that uses xsave?
3377af88ac7SKuriakose Kuruvilla	 */
3387af88ac7SKuriakose Kuruvilla	btw	$7, FXSAVE_STATE_FSW(%rdi)	/* Test saved ES bit */
3397af88ac7SKuriakose Kuruvilla	jnc	0f				/* jump if ES = 0 */
3407af88ac7SKuriakose Kuruvilla	fnclex		/* clear pending x87 exceptions */
3417af88ac7SKuriakose Kuruvilla0:	ffree	%st(7)	/* clear tag bit to remove possible stack overflow */
3427af88ac7SKuriakose Kuruvilla	fildl	.fpzero_const(%rip)
3437af88ac7SKuriakose Kuruvilla			/* dummy load changes all exception pointers */
3447af88ac7SKuriakose Kuruvilla	STTS(%rsi)	/* trap on next fpu touch */
3457af88ac7SKuriakose Kuruvilla1:	ret
3467af88ac7SKuriakose Kuruvilla	SET_SIZE(xsave_ctxt)
3477af88ac7SKuriakose Kuruvilla
3487c478bd9Sstevel@tonic-gate#elif defined(__i386)
3497c478bd9Sstevel@tonic-gate
350ae115bc7Smrj	ENTRY_NP(fpnsave_ctxt)
351ae115bc7Smrj	movl	4(%esp), %eax		/* a struct fpu_ctx */
352ae115bc7Smrj	cmpl	$FPU_EN, FPU_CTX_FPU_FLAGS(%eax)
3537c478bd9Sstevel@tonic-gate	jne	1f
3547c478bd9Sstevel@tonic-gate
355ae115bc7Smrj	movl	$_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%eax)
356ae115bc7Smrj	fnsave	FPU_CTX_FPU_REGS(%eax)
357ae115bc7Smrj			/* (fnsave also reinitializes x87 state) */
358ae115bc7Smrj	STTS(%edx)	/* trap on next fpu touch */
35985641879Skalai1:	rep;	ret	/* use 2 byte return instruction when branch target */
36085641879Skalai			/* AMD Software Optimization Guide - Section 6.2 */
361ae115bc7Smrj	SET_SIZE(fpnsave_ctxt)
362ae115bc7Smrj
363ae115bc7Smrj	ENTRY_NP(fpxsave_ctxt)
364ae115bc7Smrj	movl	4(%esp), %eax		/* a struct fpu_ctx */
365ae115bc7Smrj	cmpl	$FPU_EN, FPU_CTX_FPU_FLAGS(%eax)
366ae115bc7Smrj	jne	1f
367ae115bc7Smrj
368ae115bc7Smrj	movl	$_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%eax)
369ae115bc7Smrj	fxsave	FPU_CTX_FPU_REGS(%eax)
370ae115bc7Smrj			/* (see notes above about "exception pointers") */
371ae115bc7Smrj	btw	$7, FXSAVE_STATE_FSW(%eax)	/* Test saved ES bit */
372ae115bc7Smrj	jnc	0f				/* jump if ES = 0 */
373ae115bc7Smrj	fnclex		/* clear pending x87 exceptions */
374ae115bc7Smrj0:	ffree	%st(7)	/* clear tag bit to remove possible stack overflow */
375ae115bc7Smrj	fildl	.fpzero_const
376ae115bc7Smrj			/* dummy load changes all exception pointers */
377ae115bc7Smrj	STTS(%edx)	/* trap on next fpu touch */
378ae115bc7Smrj1:	rep;	ret	/* use 2 byte return instruction when branch target */
379ae115bc7Smrj			/* AMD Software Optimization Guide - Section 6.2 */
380ae115bc7Smrj	SET_SIZE(fpxsave_ctxt)
3817c478bd9Sstevel@tonic-gate
3827af88ac7SKuriakose Kuruvilla	ENTRY_NP(xsave_ctxt)
3837af88ac7SKuriakose Kuruvilla	movl	4(%esp), %ecx		/* a struct fpu_ctx */
3847af88ac7SKuriakose Kuruvilla	cmpl	$FPU_EN, FPU_CTX_FPU_FLAGS(%ecx)
3857af88ac7SKuriakose Kuruvilla	jne	1f
3867af88ac7SKuriakose Kuruvilla
3877af88ac7SKuriakose Kuruvilla	movl	$_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%ecx)
3887af88ac7SKuriakose Kuruvilla	movl	FPU_CTX_FPU_XSAVE_MASK(%ecx), %eax
3897af88ac7SKuriakose Kuruvilla	movl	FPU_CTX_FPU_XSAVE_MASK+4(%ecx), %edx
3907af88ac7SKuriakose Kuruvilla	leal	FPU_CTX_FPU_REGS(%ecx), %ecx
3917af88ac7SKuriakose Kuruvilla	#xsave	(%ecx)
3927af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x21
3937af88ac7SKuriakose Kuruvilla
3947af88ac7SKuriakose Kuruvilla	/*
3957af88ac7SKuriakose Kuruvilla	 * (see notes above about "exception pointers")
3967af88ac7SKuriakose Kuruvilla	 * TODO: does it apply to any machine that uses xsave?
3977af88ac7SKuriakose Kuruvilla	 */
3987af88ac7SKuriakose Kuruvilla	btw	$7, FXSAVE_STATE_FSW(%ecx)	/* Test saved ES bit */
3997af88ac7SKuriakose Kuruvilla	jnc	0f				/* jump if ES = 0 */
4007af88ac7SKuriakose Kuruvilla	fnclex		/* clear pending x87 exceptions */
4017af88ac7SKuriakose Kuruvilla0:	ffree	%st(7)	/* clear tag bit to remove possible stack overflow */
4027af88ac7SKuriakose Kuruvilla	fildl	.fpzero_const
4037af88ac7SKuriakose Kuruvilla			/* dummy load changes all exception pointers */
4047af88ac7SKuriakose Kuruvilla	STTS(%edx)	/* trap on next fpu touch */
4057af88ac7SKuriakose Kuruvilla1:	ret
4067af88ac7SKuriakose Kuruvilla	SET_SIZE(xsave_ctxt)
4077af88ac7SKuriakose Kuruvilla
4087c478bd9Sstevel@tonic-gate#endif	/* __i386 */
409ae115bc7Smrj
410ae115bc7Smrj	.align	8
411ae115bc7Smrj.fpzero_const:
412ae115bc7Smrj	.4byte	0x0
413ae115bc7Smrj	.4byte	0x0
414ae115bc7Smrj
4157c478bd9Sstevel@tonic-gate#endif	/* __lint */
4167c478bd9Sstevel@tonic-gate
417ae115bc7Smrj
4187c478bd9Sstevel@tonic-gate#if defined(__lint)
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4217c478bd9Sstevel@tonic-gatevoid
4227c478bd9Sstevel@tonic-gatefpsave(struct fnsave_state *f)
4237c478bd9Sstevel@tonic-gate{}
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4267c478bd9Sstevel@tonic-gatevoid
4277c478bd9Sstevel@tonic-gatefpxsave(struct fxsave_state *f)
4287c478bd9Sstevel@tonic-gate{}
4297c478bd9Sstevel@tonic-gate
4307af88ac7SKuriakose Kuruvilla/*ARGSUSED*/
4317af88ac7SKuriakose Kuruvillavoid
4327af88ac7SKuriakose Kuruvillaxsave(struct xsave_state *f, uint64_t m)
4337af88ac7SKuriakose Kuruvilla{}
4347af88ac7SKuriakose Kuruvilla
4357c478bd9Sstevel@tonic-gate#else	/* __lint */
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate#if defined(__amd64)
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate	ENTRY_NP(fpxsave)
440ae115bc7Smrj	CLTS
441f0f4f396Ska153516	FXSAVEQ	((%rdi))
442ae115bc7Smrj	fninit				/* clear exceptions, init x87 tags */
443ae115bc7Smrj	STTS(%rdi)			/* set TS bit in %cr0 (disable FPU) */
4447c478bd9Sstevel@tonic-gate	ret
4457c478bd9Sstevel@tonic-gate	SET_SIZE(fpxsave)
4467c478bd9Sstevel@tonic-gate
4477af88ac7SKuriakose Kuruvilla	ENTRY_NP(xsave)
4487af88ac7SKuriakose Kuruvilla	CLTS
4497af88ac7SKuriakose Kuruvilla	movl	%esi, %eax		/* bv mask */
4507af88ac7SKuriakose Kuruvilla	movq	%rsi, %rdx
4517af88ac7SKuriakose Kuruvilla	shrq	$32, %rdx
4527af88ac7SKuriakose Kuruvilla	#xsave	(%rdi)
4537af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x27
4547af88ac7SKuriakose Kuruvilla
4557af88ac7SKuriakose Kuruvilla	fninit				/* clear exceptions, init x87 tags */
4567af88ac7SKuriakose Kuruvilla	STTS(%rdi)			/* set TS bit in %cr0 (disable FPU) */
4577af88ac7SKuriakose Kuruvilla	ret
4587af88ac7SKuriakose Kuruvilla	SET_SIZE(xsave)
4597af88ac7SKuriakose Kuruvilla
4607c478bd9Sstevel@tonic-gate#elif defined(__i386)
4617c478bd9Sstevel@tonic-gate
4627c478bd9Sstevel@tonic-gate	ENTRY_NP(fpsave)
463ae115bc7Smrj	CLTS
464ae115bc7Smrj	movl	4(%esp), %eax
4657c478bd9Sstevel@tonic-gate	fnsave	(%eax)
466ae115bc7Smrj	STTS(%eax)			/* set TS bit in %cr0 (disable FPU) */
4677c478bd9Sstevel@tonic-gate	ret
4687c478bd9Sstevel@tonic-gate	SET_SIZE(fpsave)
4697c478bd9Sstevel@tonic-gate
4707c478bd9Sstevel@tonic-gate	ENTRY_NP(fpxsave)
471ae115bc7Smrj	CLTS
472ae115bc7Smrj	movl	4(%esp), %eax
4737c478bd9Sstevel@tonic-gate	fxsave	(%eax)
474ae115bc7Smrj	fninit				/* clear exceptions, init x87 tags */
475ae115bc7Smrj	STTS(%eax)			/* set TS bit in %cr0 (disable FPU) */
4767c478bd9Sstevel@tonic-gate	ret
4777c478bd9Sstevel@tonic-gate	SET_SIZE(fpxsave)
4787c478bd9Sstevel@tonic-gate
4797af88ac7SKuriakose Kuruvilla	ENTRY_NP(xsave)
4807af88ac7SKuriakose Kuruvilla	CLTS
4817af88ac7SKuriakose Kuruvilla	movl	4(%esp), %ecx
4827af88ac7SKuriakose Kuruvilla	movl	8(%esp), %eax
4837af88ac7SKuriakose Kuruvilla	movl	12(%esp), %edx
4847af88ac7SKuriakose Kuruvilla	#xsave	(%ecx)
4857af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x21
4867af88ac7SKuriakose Kuruvilla
4877af88ac7SKuriakose Kuruvilla	fninit				/* clear exceptions, init x87 tags */
4887af88ac7SKuriakose Kuruvilla	STTS(%eax)			/* set TS bit in %cr0 (disable FPU) */
4897af88ac7SKuriakose Kuruvilla	ret
4907af88ac7SKuriakose Kuruvilla	SET_SIZE(xsave)
4917af88ac7SKuriakose Kuruvilla
4927c478bd9Sstevel@tonic-gate#endif	/* __i386 */
4937c478bd9Sstevel@tonic-gate#endif	/* __lint */
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate#if defined(__lint)
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate/*ARGSUSED*/
4987c478bd9Sstevel@tonic-gatevoid
4997c478bd9Sstevel@tonic-gatefprestore(struct fnsave_state *f)
5007c478bd9Sstevel@tonic-gate{}
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate/*ARGSUSED*/
5037c478bd9Sstevel@tonic-gatevoid
5047c478bd9Sstevel@tonic-gatefpxrestore(struct fxsave_state *f)
5057c478bd9Sstevel@tonic-gate{}
5067c478bd9Sstevel@tonic-gate
5077af88ac7SKuriakose Kuruvilla/*ARGSUSED*/
5087af88ac7SKuriakose Kuruvillavoid
5097af88ac7SKuriakose Kuruvillaxrestore(struct xsave_state *f, uint64_t m)
5107af88ac7SKuriakose Kuruvilla{}
5117af88ac7SKuriakose Kuruvilla
5127c478bd9Sstevel@tonic-gate#else	/* __lint */
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate#if defined(__amd64)
5157c478bd9Sstevel@tonic-gate
5167c478bd9Sstevel@tonic-gate	ENTRY_NP(fpxrestore)
517ae115bc7Smrj	CLTS
518f0f4f396Ska153516	FXRSTORQ	((%rdi))
5197c478bd9Sstevel@tonic-gate	ret
5207c478bd9Sstevel@tonic-gate	SET_SIZE(fpxrestore)
5217c478bd9Sstevel@tonic-gate
5227af88ac7SKuriakose Kuruvilla	ENTRY_NP(xrestore)
5237af88ac7SKuriakose Kuruvilla	CLTS
5247af88ac7SKuriakose Kuruvilla	movl	%esi, %eax		/* bv mask */
5257af88ac7SKuriakose Kuruvilla	movq	%rsi, %rdx
5267af88ac7SKuriakose Kuruvilla	shrq	$32, %rdx
5277af88ac7SKuriakose Kuruvilla	#xrstor	(%rdi)
5287af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x2f
5297af88ac7SKuriakose Kuruvilla	ret
5307af88ac7SKuriakose Kuruvilla	SET_SIZE(xrestore)
5317af88ac7SKuriakose Kuruvilla
5327c478bd9Sstevel@tonic-gate#elif defined(__i386)
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate	ENTRY_NP(fprestore)
535ae115bc7Smrj	CLTS
536ae115bc7Smrj	movl	4(%esp), %eax
5377c478bd9Sstevel@tonic-gate	frstor	(%eax)
5387c478bd9Sstevel@tonic-gate	ret
5397c478bd9Sstevel@tonic-gate	SET_SIZE(fprestore)
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate	ENTRY_NP(fpxrestore)
542ae115bc7Smrj	CLTS
543ae115bc7Smrj	movl	4(%esp), %eax
5447c478bd9Sstevel@tonic-gate	fxrstor	(%eax)
5457c478bd9Sstevel@tonic-gate	ret
5467c478bd9Sstevel@tonic-gate	SET_SIZE(fpxrestore)
5477c478bd9Sstevel@tonic-gate
5487af88ac7SKuriakose Kuruvilla	ENTRY_NP(xrestore)
5497af88ac7SKuriakose Kuruvilla	CLTS
5507af88ac7SKuriakose Kuruvilla	movl	4(%esp), %ecx
5517af88ac7SKuriakose Kuruvilla	movl	8(%esp), %eax
5527af88ac7SKuriakose Kuruvilla	movl	12(%esp), %edx
5537af88ac7SKuriakose Kuruvilla	#xrstor	(%ecx)
5547af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x29
5557af88ac7SKuriakose Kuruvilla	ret
5567af88ac7SKuriakose Kuruvilla	SET_SIZE(xrestore)
5577af88ac7SKuriakose Kuruvilla
5587c478bd9Sstevel@tonic-gate#endif	/* __i386 */
5597c478bd9Sstevel@tonic-gate#endif	/* __lint */
5607c478bd9Sstevel@tonic-gate
5617c478bd9Sstevel@tonic-gate/*
5627c478bd9Sstevel@tonic-gate * Disable the floating point unit.
5637c478bd9Sstevel@tonic-gate */
5647c478bd9Sstevel@tonic-gate
5657c478bd9Sstevel@tonic-gate#if defined(__lint)
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gatevoid
5687c478bd9Sstevel@tonic-gatefpdisable(void)
5697c478bd9Sstevel@tonic-gate{}
5707c478bd9Sstevel@tonic-gate
5717c478bd9Sstevel@tonic-gate#else	/* __lint */
5727c478bd9Sstevel@tonic-gate
5737c478bd9Sstevel@tonic-gate#if defined(__amd64)
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate	ENTRY_NP(fpdisable)
576ae115bc7Smrj	STTS(%rdi)			/* set TS bit in %cr0 (disable FPU) */
5777c478bd9Sstevel@tonic-gate	ret
5787c478bd9Sstevel@tonic-gate	SET_SIZE(fpdisable)
5797c478bd9Sstevel@tonic-gate
5807c478bd9Sstevel@tonic-gate#elif defined(__i386)
5817c478bd9Sstevel@tonic-gate
5827c478bd9Sstevel@tonic-gate	ENTRY_NP(fpdisable)
583ae115bc7Smrj	STTS(%eax)
5847c478bd9Sstevel@tonic-gate	ret
5857c478bd9Sstevel@tonic-gate	SET_SIZE(fpdisable)
5867c478bd9Sstevel@tonic-gate
5877c478bd9Sstevel@tonic-gate#endif	/* __i386 */
5887c478bd9Sstevel@tonic-gate#endif	/* __lint */
5897c478bd9Sstevel@tonic-gate
5907c478bd9Sstevel@tonic-gate/*
5917c478bd9Sstevel@tonic-gate * Initialize the fpu hardware.
5927c478bd9Sstevel@tonic-gate */
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate#if defined(__lint)
5957c478bd9Sstevel@tonic-gate
5967c478bd9Sstevel@tonic-gatevoid
5977c478bd9Sstevel@tonic-gatefpinit(void)
5987c478bd9Sstevel@tonic-gate{}
5997c478bd9Sstevel@tonic-gate
6007c478bd9Sstevel@tonic-gate#else	/* __lint */
6017c478bd9Sstevel@tonic-gate
6027c478bd9Sstevel@tonic-gate#if defined(__amd64)
6037c478bd9Sstevel@tonic-gate
6047c478bd9Sstevel@tonic-gate	ENTRY_NP(fpinit)
605ae115bc7Smrj	CLTS
6067af88ac7SKuriakose Kuruvilla	cmpl	$FP_XSAVE, fp_save_mech
6077af88ac7SKuriakose Kuruvilla	je	1f
6087af88ac7SKuriakose Kuruvilla
6097af88ac7SKuriakose Kuruvilla	/* fxsave */
6107c478bd9Sstevel@tonic-gate	leaq	sse_initial(%rip), %rax
611f0f4f396Ska153516	FXRSTORQ	((%rax))		/* load clean initial state */
6127c478bd9Sstevel@tonic-gate	ret
6137af88ac7SKuriakose Kuruvilla
6147af88ac7SKuriakose Kuruvilla1:	/* xsave */
6157af88ac7SKuriakose Kuruvilla	leaq	avx_initial(%rip), %rcx
6167af88ac7SKuriakose Kuruvilla	xorl	%edx, %edx
6177af88ac7SKuriakose Kuruvilla	movl	$XFEATURE_AVX, %eax
618*4d40e39cSAndy Fiddaman	btl	$X86FSET_AVX, x86_featureset
6197af88ac7SKuriakose Kuruvilla	cmovael	%edx, %eax
6207af88ac7SKuriakose Kuruvilla	orl	$(XFEATURE_LEGACY_FP | XFEATURE_SSE), %eax
6217af88ac7SKuriakose Kuruvilla	/* xrstor (%rcx) */
6227af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x29		/* load clean initial state */
6237af88ac7SKuriakose Kuruvilla	ret
6247c478bd9Sstevel@tonic-gate	SET_SIZE(fpinit)
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate#elif defined(__i386)
6277c478bd9Sstevel@tonic-gate
6287c478bd9Sstevel@tonic-gate	ENTRY_NP(fpinit)
629ae115bc7Smrj	CLTS
6307af88ac7SKuriakose Kuruvilla	cmpl	$FP_FXSAVE, fp_save_mech
6317c478bd9Sstevel@tonic-gate	je	1f
6327af88ac7SKuriakose Kuruvilla	cmpl	$FP_XSAVE, fp_save_mech
6337af88ac7SKuriakose Kuruvilla	je	2f
6347c478bd9Sstevel@tonic-gate
6357af88ac7SKuriakose Kuruvilla	/* fnsave */
636ae115bc7Smrj	fninit
6377c478bd9Sstevel@tonic-gate	movl	$x87_initial, %eax
638ae115bc7Smrj	frstor	(%eax)			/* load clean initial state */
6397c478bd9Sstevel@tonic-gate	ret
6407af88ac7SKuriakose Kuruvilla
6417af88ac7SKuriakose Kuruvilla1:	/* fxsave */
6427c478bd9Sstevel@tonic-gate	movl	$sse_initial, %eax
643ae115bc7Smrj	fxrstor	(%eax)			/* load clean initial state */
6447c478bd9Sstevel@tonic-gate	ret
6457af88ac7SKuriakose Kuruvilla
6467af88ac7SKuriakose Kuruvilla2:	/* xsave */
6477af88ac7SKuriakose Kuruvilla	movl	$avx_initial, %ecx
6487af88ac7SKuriakose Kuruvilla	xorl	%edx, %edx
6497af88ac7SKuriakose Kuruvilla	movl	$XFEATURE_AVX, %eax
6507af88ac7SKuriakose Kuruvilla	bt	$X86FSET_AVX, x86_featureset
6517af88ac7SKuriakose Kuruvilla	cmovael	%edx, %eax
6527af88ac7SKuriakose Kuruvilla	orl	$(XFEATURE_LEGACY_FP | XFEATURE_SSE), %eax
6537af88ac7SKuriakose Kuruvilla	/* xrstor (%ecx) */
6547af88ac7SKuriakose Kuruvilla	.byte	0x0f, 0xae, 0x29	/* load clean initial state */
6557af88ac7SKuriakose Kuruvilla	ret
6567c478bd9Sstevel@tonic-gate	SET_SIZE(fpinit)
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate#endif	/* __i386 */
6597c478bd9Sstevel@tonic-gate#endif	/* __lint */
6607c478bd9Sstevel@tonic-gate
6617c478bd9Sstevel@tonic-gate/*
6627c478bd9Sstevel@tonic-gate * Clears FPU exception state.
6637c478bd9Sstevel@tonic-gate * Returns the FP status word.
6647c478bd9Sstevel@tonic-gate */
6657c478bd9Sstevel@tonic-gate
6667c478bd9Sstevel@tonic-gate#if defined(__lint)
6677c478bd9Sstevel@tonic-gate
6687c478bd9Sstevel@tonic-gateuint32_t
6697c478bd9Sstevel@tonic-gatefperr_reset(void)
670ae115bc7Smrj{ return (0); }
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gateuint32_t
6737c478bd9Sstevel@tonic-gatefpxerr_reset(void)
674ae115bc7Smrj{ return (0); }
6757c478bd9Sstevel@tonic-gate
6767c478bd9Sstevel@tonic-gate#else	/* __lint */
6777c478bd9Sstevel@tonic-gate
6787c478bd9Sstevel@tonic-gate#if defined(__amd64)
6797c478bd9Sstevel@tonic-gate
6807c478bd9Sstevel@tonic-gate	ENTRY_NP(fperr_reset)
681ae115bc7Smrj	CLTS
6827c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
683ae115bc7Smrj	fnstsw	%ax
684ae115bc7Smrj	fnclex
6857c478bd9Sstevel@tonic-gate	ret
6867c478bd9Sstevel@tonic-gate	SET_SIZE(fperr_reset)
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate	ENTRY_NP(fpxerr_reset)
6897c478bd9Sstevel@tonic-gate	pushq	%rbp
6907c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
6917c478bd9Sstevel@tonic-gate	subq	$0x10, %rsp		/* make some temporary space */
692ae115bc7Smrj	CLTS
693ae115bc7Smrj	stmxcsr	(%rsp)
6947c478bd9Sstevel@tonic-gate	movl	(%rsp), %eax
6957c478bd9Sstevel@tonic-gate	andl	$_BITNOT(SSE_MXCSR_EFLAGS), (%rsp)
6967c478bd9Sstevel@tonic-gate	ldmxcsr	(%rsp)			/* clear processor exceptions */
6977c478bd9Sstevel@tonic-gate	leave
6987c478bd9Sstevel@tonic-gate	ret
6997c478bd9Sstevel@tonic-gate	SET_SIZE(fpxerr_reset)
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate#elif defined(__i386)
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate	ENTRY_NP(fperr_reset)
704ae115bc7Smrj	CLTS
7057c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
706ae115bc7Smrj	fnstsw	%ax
707ae115bc7Smrj	fnclex
7087c478bd9Sstevel@tonic-gate	ret
7097c478bd9Sstevel@tonic-gate	SET_SIZE(fperr_reset)
7107c478bd9Sstevel@tonic-gate
7117c478bd9Sstevel@tonic-gate	ENTRY_NP(fpxerr_reset)
712ae115bc7Smrj	CLTS
713ae115bc7Smrj	subl	$4, %esp		/* make some temporary space */
714ae115bc7Smrj	stmxcsr	(%esp)
7157c478bd9Sstevel@tonic-gate	movl	(%esp), %eax
7167c478bd9Sstevel@tonic-gate	andl	$_BITNOT(SSE_MXCSR_EFLAGS), (%esp)
717ae115bc7Smrj	ldmxcsr	(%esp)			/* clear processor exceptions */
7187c478bd9Sstevel@tonic-gate	addl	$4, %esp
7197c478bd9Sstevel@tonic-gate	ret
7207c478bd9Sstevel@tonic-gate	SET_SIZE(fpxerr_reset)
7217c478bd9Sstevel@tonic-gate
7227c478bd9Sstevel@tonic-gate#endif	/* __i386 */
7237c478bd9Sstevel@tonic-gate#endif	/* __lint */
7247c478bd9Sstevel@tonic-gate
7257c478bd9Sstevel@tonic-gate#if defined(__lint)
7267c478bd9Sstevel@tonic-gate
7277c478bd9Sstevel@tonic-gateuint32_t
7287c478bd9Sstevel@tonic-gatefpgetcwsw(void)
7297c478bd9Sstevel@tonic-gate{
7307c478bd9Sstevel@tonic-gate	return (0);
7317c478bd9Sstevel@tonic-gate}
7327c478bd9Sstevel@tonic-gate
7337c478bd9Sstevel@tonic-gate#else   /* __lint */
7347c478bd9Sstevel@tonic-gate
7357c478bd9Sstevel@tonic-gate#if defined(__amd64)
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gate	ENTRY_NP(fpgetcwsw)
7387c478bd9Sstevel@tonic-gate	pushq	%rbp
7397c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
7407c478bd9Sstevel@tonic-gate	subq	$0x10, %rsp		/* make some temporary space	*/
741ae115bc7Smrj	CLTS
7427c478bd9Sstevel@tonic-gate	fnstsw	(%rsp)			/* store the status word	*/
7437c478bd9Sstevel@tonic-gate	fnstcw	2(%rsp)			/* store the control word	*/
7447c478bd9Sstevel@tonic-gate	movl	(%rsp), %eax		/* put both in %eax		*/
7457c478bd9Sstevel@tonic-gate	leave
7467c478bd9Sstevel@tonic-gate	ret
7477c478bd9Sstevel@tonic-gate	SET_SIZE(fpgetcwsw)
7487c478bd9Sstevel@tonic-gate
7497c478bd9Sstevel@tonic-gate#elif defined(__i386)
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate	ENTRY_NP(fpgetcwsw)
752ae115bc7Smrj	CLTS
7537c478bd9Sstevel@tonic-gate	subl	$4, %esp		/* make some temporary space	*/
7547c478bd9Sstevel@tonic-gate	fnstsw	(%esp)			/* store the status word	*/
7557c478bd9Sstevel@tonic-gate	fnstcw	2(%esp)			/* store the control word	*/
7567c478bd9Sstevel@tonic-gate	movl	(%esp), %eax		/* put both in %eax		*/
7577c478bd9Sstevel@tonic-gate	addl	$4, %esp
7587c478bd9Sstevel@tonic-gate	ret
7597c478bd9Sstevel@tonic-gate	SET_SIZE(fpgetcwsw)
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate#endif	/* __i386 */
7627c478bd9Sstevel@tonic-gate#endif  /* __lint */
7637c478bd9Sstevel@tonic-gate
7647c478bd9Sstevel@tonic-gate/*
7657c478bd9Sstevel@tonic-gate * Returns the MXCSR register.
7667c478bd9Sstevel@tonic-gate */
7677c478bd9Sstevel@tonic-gate
7687c478bd9Sstevel@tonic-gate#if defined(__lint)
7697c478bd9Sstevel@tonic-gate
7707c478bd9Sstevel@tonic-gateuint32_t
7717c478bd9Sstevel@tonic-gatefpgetmxcsr(void)
7727c478bd9Sstevel@tonic-gate{
7737c478bd9Sstevel@tonic-gate	return (0);
7747c478bd9Sstevel@tonic-gate}
7757c478bd9Sstevel@tonic-gate
7767c478bd9Sstevel@tonic-gate#else   /* __lint */
7777c478bd9Sstevel@tonic-gate
7787c478bd9Sstevel@tonic-gate#if defined(__amd64)
7797c478bd9Sstevel@tonic-gate
7807c478bd9Sstevel@tonic-gate	ENTRY_NP(fpgetmxcsr)
7817c478bd9Sstevel@tonic-gate	pushq	%rbp
7827c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
7837c478bd9Sstevel@tonic-gate	subq	$0x10, %rsp		/* make some temporary space */
784ae115bc7Smrj	CLTS
785ae115bc7Smrj	stmxcsr	(%rsp)
7867c478bd9Sstevel@tonic-gate	movl	(%rsp), %eax
7877c478bd9Sstevel@tonic-gate	leave
7887c478bd9Sstevel@tonic-gate	ret
7897c478bd9Sstevel@tonic-gate	SET_SIZE(fpgetmxcsr)
7907c478bd9Sstevel@tonic-gate
7917c478bd9Sstevel@tonic-gate#elif defined(__i386)
7927c478bd9Sstevel@tonic-gate
7937c478bd9Sstevel@tonic-gate	ENTRY_NP(fpgetmxcsr)
794ae115bc7Smrj	CLTS
7957c478bd9Sstevel@tonic-gate	subl	$4, %esp		/* make some temporary space */
796ae115bc7Smrj	stmxcsr	(%esp)
7977c478bd9Sstevel@tonic-gate	movl	(%esp), %eax
7987c478bd9Sstevel@tonic-gate	addl	$4, %esp
7997c478bd9Sstevel@tonic-gate	ret
8007c478bd9Sstevel@tonic-gate	SET_SIZE(fpgetmxcsr)
8017c478bd9Sstevel@tonic-gate
8027c478bd9Sstevel@tonic-gate#endif	/* __i386 */
8037c478bd9Sstevel@tonic-gate#endif  /* __lint */
804