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