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