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