1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ 28 /* All Rights Reserved */ 29 30 /* Copyright (c) 1987, 1988 Microsoft Corporation */ 31 /* All Rights Reserved */ 32 33 /* 34 * Copyright (c) 2009, Intel Corporation. 35 * All rights reserved. 36 */ 37 38 #include <sys/asm_linkage.h> 39 #include <sys/asm_misc.h> 40 #include <sys/regset.h> 41 #include <sys/privregs.h> 42 #include <sys/x86_archext.h> 43 44 #if defined(__lint) 45 #include <sys/types.h> 46 #include <sys/fp.h> 47 #else 48 #include "assym.h" 49 #endif 50 51 #if defined(__lint) 52 53 uint_t 54 fpu_initial_probe(void) 55 { return (0); } 56 57 #else /* __lint */ 58 59 /* 60 * Returns zero if x87 "chip" is present(!) 61 */ 62 ENTRY_NP(fpu_initial_probe) 63 CLTS 64 fninit 65 fnstsw %ax 66 movzbl %al, %eax 67 ret 68 SET_SIZE(fpu_initial_probe) 69 70 #endif /* __lint */ 71 72 #if defined(__lint) 73 74 /*ARGSUSED*/ 75 void 76 fxsave_insn(struct fxsave_state *fx) 77 {} 78 79 #else /* __lint */ 80 81 #if defined(__amd64) 82 83 ENTRY_NP(fxsave_insn) 84 FXSAVEQ ((%rdi)) 85 ret 86 SET_SIZE(fxsave_insn) 87 88 #elif defined(__i386) 89 90 ENTRY_NP(fxsave_insn) 91 movl 4(%esp), %eax 92 fxsave (%eax) 93 ret 94 SET_SIZE(fxsave_insn) 95 96 #endif 97 98 #endif /* __lint */ 99 100 #if defined(__i386) 101 102 /* 103 * If (num1/num2 > num1/num3) the FPU has the FDIV bug. 104 */ 105 106 #if defined(__lint) 107 108 int 109 fpu_probe_pentium_fdivbug(void) 110 { return (0); } 111 112 #else /* __lint */ 113 114 ENTRY_NP(fpu_probe_pentium_fdivbug) 115 fldl .num1 116 fldl .num2 117 fdivr %st(1), %st 118 fxch %st(1) 119 fdivl .num3 120 fcompp 121 fstsw %ax 122 sahf 123 jae 0f 124 movl $1, %eax 125 ret 126 127 0: xorl %eax, %eax 128 ret 129 130 .align 4 131 .num1: .4byte 0xbce4217d /* 4.999999 */ 132 .4byte 0x4013ffff 133 .num2: .4byte 0x0 /* 15.0 */ 134 .4byte 0x402e0000 135 .num3: .4byte 0xde7210bf /* 14.999999 */ 136 .4byte 0x402dffff 137 SET_SIZE(fpu_probe_pentium_fdivbug) 138 139 #endif /* __lint */ 140 141 /* 142 * To cope with processors that do not implement fxsave/fxrstor 143 * instructions, patch hot paths in the kernel to use them only 144 * when that feature has been detected. 145 */ 146 147 #if defined(__lint) 148 149 void 150 patch_sse(void) 151 {} 152 153 void 154 patch_sse2(void) 155 {} 156 157 void 158 patch_xsave(void) 159 {} 160 161 #else /* __lint */ 162 163 ENTRY_NP(patch_sse) 164 _HOT_PATCH_PROLOG 165 / 166 / frstor (%ebx); nop -> fxrstor (%ebx) 167 / 168 _HOT_PATCH(_fxrstor_ebx_insn, _patch_fxrstor_ebx, 3) 169 / 170 / lock; xorl $0, (%esp) -> sfence; ret 171 / 172 _HOT_PATCH(_sfence_ret_insn, _patch_sfence_ret, 4) 173 _HOT_PATCH_EPILOG 174 ret 175 _fxrstor_ebx_insn: / see ndptrap_frstor() 176 fxrstor (%ebx) 177 _ldmxcsr_ebx_insn: / see resume_from_zombie() 178 ldmxcsr (%ebx) 179 _sfence_ret_insn: / see membar_producer() 180 .byte 0xf, 0xae, 0xf8 / [sfence instruction] 181 ret 182 SET_SIZE(patch_sse) 183 184 ENTRY_NP(patch_sse2) 185 _HOT_PATCH_PROLOG 186 / 187 / lock; xorl $0, (%esp) -> lfence; ret 188 / 189 _HOT_PATCH(_lfence_ret_insn, _patch_lfence_ret, 4) 190 _HOT_PATCH_EPILOG 191 ret 192 _lfence_ret_insn: / see membar_consumer() 193 .byte 0xf, 0xae, 0xe8 / [lfence instruction] 194 ret 195 SET_SIZE(patch_sse2) 196 197 /* 198 * Patch lazy fp restore instructions in the trap handler 199 * to use xrstor instead of frstor 200 */ 201 ENTRY_NP(patch_xsave) 202 _HOT_PATCH_PROLOG 203 / 204 / frstor (%ebx); nop -> xrstor (%ebx) 205 / 206 _HOT_PATCH(_xrstor_ebx_insn, _patch_xrstor_ebx, 3) 207 _HOT_PATCH_EPILOG 208 ret 209 _xrstor_ebx_insn: / see ndptrap_frstor() 210 #xrstor (%ebx) 211 .byte 0x0f, 0xae, 0x2b 212 SET_SIZE(patch_xsave) 213 214 #endif /* __lint */ 215 #endif /* __i386 */ 216 217 #if defined(__amd64) 218 #if defined(__lint) 219 220 void 221 patch_xsave(void) 222 {} 223 224 #else /* __lint */ 225 226 /* 227 * Patch lazy fp restore instructions in the trap handler 228 * to use xrstor instead of fxrstorq 229 */ 230 ENTRY_NP(patch_xsave) 231 pushq %rbx 232 pushq %rbp 233 pushq %r15 234 / 235 / FXRSTORQ (%rbx); -> xrstor (%rbx) 236 / hot_patch(_xrstor_rbx_insn, _patch_xrstorq_rbx, 4) 237 / 238 leaq _patch_xrstorq_rbx(%rip), %rbx 239 leaq _xrstor_rbx_insn(%rip), %rbp 240 movq $4, %r15 241 1: 242 movq %rbx, %rdi /* patch address */ 243 movzbq (%rbp), %rsi /* instruction byte */ 244 movq $1, %rdx /* count */ 245 call hot_patch_kernel_text 246 addq $1, %rbx 247 addq $1, %rbp 248 subq $1, %r15 249 jnz 1b 250 251 popq %r15 252 popq %rbp 253 popq %rbx 254 ret 255 256 _xrstor_rbx_insn: / see ndptrap_frstor() 257 #rex.W=1 (.byte 0x48) 258 #xrstor (%rbx) 259 .byte 0x48, 0x0f, 0xae, 0x2b 260 SET_SIZE(patch_xsave) 261 262 #endif /* __lint */ 263 #endif /* __amd64 */ 264 265 /* 266 * One of these routines is called from any lwp with floating 267 * point context as part of the prolog of a context switch. 268 */ 269 270 #if defined(__lint) 271 272 /*ARGSUSED*/ 273 void 274 xsave_ctxt(void *arg) 275 {} 276 277 /*ARGSUSED*/ 278 void 279 fpxsave_ctxt(void *arg) 280 {} 281 282 /*ARGSUSED*/ 283 void 284 fpnsave_ctxt(void *arg) 285 {} 286 287 #else /* __lint */ 288 289 #if defined(__amd64) 290 291 ENTRY_NP(fpxsave_ctxt) 292 cmpl $FPU_EN, FPU_CTX_FPU_FLAGS(%rdi) 293 jne 1f 294 295 movl $_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%rdi) 296 FXSAVEQ (FPU_CTX_FPU_REGS(%rdi)) 297 298 /* 299 * On certain AMD processors, the "exception pointers" i.e. the last 300 * instruction pointer, last data pointer, and last opcode 301 * are saved by the fxsave instruction ONLY if the exception summary 302 * bit is set. 303 * 304 * To ensure that we don't leak these values into the next context 305 * on the cpu, we could just issue an fninit here, but that's 306 * rather slow and so we issue an instruction sequence that 307 * clears them more quickly, if a little obscurely. 308 */ 309 btw $7, FXSAVE_STATE_FSW(%rdi) /* Test saved ES bit */ 310 jnc 0f /* jump if ES = 0 */ 311 fnclex /* clear pending x87 exceptions */ 312 0: ffree %st(7) /* clear tag bit to remove possible stack overflow */ 313 fildl .fpzero_const(%rip) 314 /* dummy load changes all exception pointers */ 315 STTS(%rsi) /* trap on next fpu touch */ 316 1: rep; ret /* use 2 byte return instruction when branch target */ 317 /* AMD Software Optimization Guide - Section 6.2 */ 318 SET_SIZE(fpxsave_ctxt) 319 320 ENTRY_NP(xsave_ctxt) 321 cmpl $FPU_EN, FPU_CTX_FPU_FLAGS(%rdi) 322 jne 1f 323 movl $_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%rdi) 324 /* 325 * Setup xsave flags in EDX:EAX 326 */ 327 movl FPU_CTX_FPU_XSAVE_MASK(%rdi), %eax 328 movl FPU_CTX_FPU_XSAVE_MASK+4(%rdi), %edx 329 leaq FPU_CTX_FPU_REGS(%rdi), %rsi 330 #xsave (%rsi) 331 .byte 0x0f, 0xae, 0x26 332 333 /* 334 * (see notes above about "exception pointers") 335 * TODO: does it apply to any machine that uses xsave? 336 */ 337 btw $7, FXSAVE_STATE_FSW(%rdi) /* Test saved ES bit */ 338 jnc 0f /* jump if ES = 0 */ 339 fnclex /* clear pending x87 exceptions */ 340 0: ffree %st(7) /* clear tag bit to remove possible stack overflow */ 341 fildl .fpzero_const(%rip) 342 /* dummy load changes all exception pointers */ 343 STTS(%rsi) /* trap on next fpu touch */ 344 1: ret 345 SET_SIZE(xsave_ctxt) 346 347 #elif defined(__i386) 348 349 ENTRY_NP(fpnsave_ctxt) 350 movl 4(%esp), %eax /* a struct fpu_ctx */ 351 cmpl $FPU_EN, FPU_CTX_FPU_FLAGS(%eax) 352 jne 1f 353 354 movl $_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%eax) 355 fnsave FPU_CTX_FPU_REGS(%eax) 356 /* (fnsave also reinitializes x87 state) */ 357 STTS(%edx) /* trap on next fpu touch */ 358 1: rep; ret /* use 2 byte return instruction when branch target */ 359 /* AMD Software Optimization Guide - Section 6.2 */ 360 SET_SIZE(fpnsave_ctxt) 361 362 ENTRY_NP(fpxsave_ctxt) 363 movl 4(%esp), %eax /* a struct fpu_ctx */ 364 cmpl $FPU_EN, FPU_CTX_FPU_FLAGS(%eax) 365 jne 1f 366 367 movl $_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%eax) 368 fxsave FPU_CTX_FPU_REGS(%eax) 369 /* (see notes above about "exception pointers") */ 370 btw $7, FXSAVE_STATE_FSW(%eax) /* Test saved ES bit */ 371 jnc 0f /* jump if ES = 0 */ 372 fnclex /* clear pending x87 exceptions */ 373 0: ffree %st(7) /* clear tag bit to remove possible stack overflow */ 374 fildl .fpzero_const 375 /* dummy load changes all exception pointers */ 376 STTS(%edx) /* trap on next fpu touch */ 377 1: rep; ret /* use 2 byte return instruction when branch target */ 378 /* AMD Software Optimization Guide - Section 6.2 */ 379 SET_SIZE(fpxsave_ctxt) 380 381 ENTRY_NP(xsave_ctxt) 382 movl 4(%esp), %ecx /* a struct fpu_ctx */ 383 cmpl $FPU_EN, FPU_CTX_FPU_FLAGS(%ecx) 384 jne 1f 385 386 movl $_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%ecx) 387 movl FPU_CTX_FPU_XSAVE_MASK(%ecx), %eax 388 movl FPU_CTX_FPU_XSAVE_MASK+4(%ecx), %edx 389 leal FPU_CTX_FPU_REGS(%ecx), %ecx 390 #xsave (%ecx) 391 .byte 0x0f, 0xae, 0x21 392 393 /* 394 * (see notes above about "exception pointers") 395 * TODO: does it apply to any machine that uses xsave? 396 */ 397 btw $7, FXSAVE_STATE_FSW(%ecx) /* Test saved ES bit */ 398 jnc 0f /* jump if ES = 0 */ 399 fnclex /* clear pending x87 exceptions */ 400 0: ffree %st(7) /* clear tag bit to remove possible stack overflow */ 401 fildl .fpzero_const 402 /* dummy load changes all exception pointers */ 403 STTS(%edx) /* trap on next fpu touch */ 404 1: ret 405 SET_SIZE(xsave_ctxt) 406 407 #endif /* __i386 */ 408 409 .align 8 410 .fpzero_const: 411 .4byte 0x0 412 .4byte 0x0 413 414 #endif /* __lint */ 415 416 417 #if defined(__lint) 418 419 /*ARGSUSED*/ 420 void 421 fpsave(struct fnsave_state *f) 422 {} 423 424 /*ARGSUSED*/ 425 void 426 fpxsave(struct fxsave_state *f) 427 {} 428 429 /*ARGSUSED*/ 430 void 431 xsave(struct xsave_state *f, uint64_t m) 432 {} 433 434 #else /* __lint */ 435 436 #if defined(__amd64) 437 438 ENTRY_NP(fpxsave) 439 CLTS 440 FXSAVEQ ((%rdi)) 441 fninit /* clear exceptions, init x87 tags */ 442 STTS(%rdi) /* set TS bit in %cr0 (disable FPU) */ 443 ret 444 SET_SIZE(fpxsave) 445 446 ENTRY_NP(xsave) 447 CLTS 448 movl %esi, %eax /* bv mask */ 449 movq %rsi, %rdx 450 shrq $32, %rdx 451 #xsave (%rdi) 452 .byte 0x0f, 0xae, 0x27 453 454 fninit /* clear exceptions, init x87 tags */ 455 STTS(%rdi) /* set TS bit in %cr0 (disable FPU) */ 456 ret 457 SET_SIZE(xsave) 458 459 #elif defined(__i386) 460 461 ENTRY_NP(fpsave) 462 CLTS 463 movl 4(%esp), %eax 464 fnsave (%eax) 465 STTS(%eax) /* set TS bit in %cr0 (disable FPU) */ 466 ret 467 SET_SIZE(fpsave) 468 469 ENTRY_NP(fpxsave) 470 CLTS 471 movl 4(%esp), %eax 472 fxsave (%eax) 473 fninit /* clear exceptions, init x87 tags */ 474 STTS(%eax) /* set TS bit in %cr0 (disable FPU) */ 475 ret 476 SET_SIZE(fpxsave) 477 478 ENTRY_NP(xsave) 479 CLTS 480 movl 4(%esp), %ecx 481 movl 8(%esp), %eax 482 movl 12(%esp), %edx 483 #xsave (%ecx) 484 .byte 0x0f, 0xae, 0x21 485 486 fninit /* clear exceptions, init x87 tags */ 487 STTS(%eax) /* set TS bit in %cr0 (disable FPU) */ 488 ret 489 SET_SIZE(xsave) 490 491 #endif /* __i386 */ 492 #endif /* __lint */ 493 494 #if defined(__lint) 495 496 /*ARGSUSED*/ 497 void 498 fprestore(struct fnsave_state *f) 499 {} 500 501 /*ARGSUSED*/ 502 void 503 fpxrestore(struct fxsave_state *f) 504 {} 505 506 /*ARGSUSED*/ 507 void 508 xrestore(struct xsave_state *f, uint64_t m) 509 {} 510 511 #else /* __lint */ 512 513 #if defined(__amd64) 514 515 ENTRY_NP(fpxrestore) 516 CLTS 517 FXRSTORQ ((%rdi)) 518 ret 519 SET_SIZE(fpxrestore) 520 521 ENTRY_NP(xrestore) 522 CLTS 523 movl %esi, %eax /* bv mask */ 524 movq %rsi, %rdx 525 shrq $32, %rdx 526 #xrstor (%rdi) 527 .byte 0x0f, 0xae, 0x2f 528 ret 529 SET_SIZE(xrestore) 530 531 #elif defined(__i386) 532 533 ENTRY_NP(fprestore) 534 CLTS 535 movl 4(%esp), %eax 536 frstor (%eax) 537 ret 538 SET_SIZE(fprestore) 539 540 ENTRY_NP(fpxrestore) 541 CLTS 542 movl 4(%esp), %eax 543 fxrstor (%eax) 544 ret 545 SET_SIZE(fpxrestore) 546 547 ENTRY_NP(xrestore) 548 CLTS 549 movl 4(%esp), %ecx 550 movl 8(%esp), %eax 551 movl 12(%esp), %edx 552 #xrstor (%ecx) 553 .byte 0x0f, 0xae, 0x29 554 ret 555 SET_SIZE(xrestore) 556 557 #endif /* __i386 */ 558 #endif /* __lint */ 559 560 /* 561 * Disable the floating point unit. 562 */ 563 564 #if defined(__lint) 565 566 void 567 fpdisable(void) 568 {} 569 570 #else /* __lint */ 571 572 #if defined(__amd64) 573 574 ENTRY_NP(fpdisable) 575 STTS(%rdi) /* set TS bit in %cr0 (disable FPU) */ 576 ret 577 SET_SIZE(fpdisable) 578 579 #elif defined(__i386) 580 581 ENTRY_NP(fpdisable) 582 STTS(%eax) 583 ret 584 SET_SIZE(fpdisable) 585 586 #endif /* __i386 */ 587 #endif /* __lint */ 588 589 /* 590 * Initialize the fpu hardware. 591 */ 592 593 #if defined(__lint) 594 595 void 596 fpinit(void) 597 {} 598 599 #else /* __lint */ 600 601 #if defined(__amd64) 602 603 ENTRY_NP(fpinit) 604 CLTS 605 cmpl $FP_XSAVE, fp_save_mech 606 je 1f 607 608 /* fxsave */ 609 leaq sse_initial(%rip), %rax 610 FXRSTORQ ((%rax)) /* load clean initial state */ 611 ret 612 613 1: /* xsave */ 614 leaq avx_initial(%rip), %rcx 615 xorl %edx, %edx 616 movl $XFEATURE_AVX, %eax 617 bt $X86FSET_AVX, x86_featureset 618 cmovael %edx, %eax 619 orl $(XFEATURE_LEGACY_FP | XFEATURE_SSE), %eax 620 /* xrstor (%rcx) */ 621 .byte 0x0f, 0xae, 0x29 /* load clean initial state */ 622 ret 623 SET_SIZE(fpinit) 624 625 #elif defined(__i386) 626 627 ENTRY_NP(fpinit) 628 CLTS 629 cmpl $FP_FXSAVE, fp_save_mech 630 je 1f 631 cmpl $FP_XSAVE, fp_save_mech 632 je 2f 633 634 /* fnsave */ 635 fninit 636 movl $x87_initial, %eax 637 frstor (%eax) /* load clean initial state */ 638 ret 639 640 1: /* fxsave */ 641 movl $sse_initial, %eax 642 fxrstor (%eax) /* load clean initial state */ 643 ret 644 645 2: /* xsave */ 646 movl $avx_initial, %ecx 647 xorl %edx, %edx 648 movl $XFEATURE_AVX, %eax 649 bt $X86FSET_AVX, x86_featureset 650 cmovael %edx, %eax 651 orl $(XFEATURE_LEGACY_FP | XFEATURE_SSE), %eax 652 /* xrstor (%ecx) */ 653 .byte 0x0f, 0xae, 0x29 /* load clean initial state */ 654 ret 655 SET_SIZE(fpinit) 656 657 #endif /* __i386 */ 658 #endif /* __lint */ 659 660 /* 661 * Clears FPU exception state. 662 * Returns the FP status word. 663 */ 664 665 #if defined(__lint) 666 667 uint32_t 668 fperr_reset(void) 669 { return (0); } 670 671 uint32_t 672 fpxerr_reset(void) 673 { return (0); } 674 675 #else /* __lint */ 676 677 #if defined(__amd64) 678 679 ENTRY_NP(fperr_reset) 680 CLTS 681 xorl %eax, %eax 682 fnstsw %ax 683 fnclex 684 ret 685 SET_SIZE(fperr_reset) 686 687 ENTRY_NP(fpxerr_reset) 688 pushq %rbp 689 movq %rsp, %rbp 690 subq $0x10, %rsp /* make some temporary space */ 691 CLTS 692 stmxcsr (%rsp) 693 movl (%rsp), %eax 694 andl $_BITNOT(SSE_MXCSR_EFLAGS), (%rsp) 695 ldmxcsr (%rsp) /* clear processor exceptions */ 696 leave 697 ret 698 SET_SIZE(fpxerr_reset) 699 700 #elif defined(__i386) 701 702 ENTRY_NP(fperr_reset) 703 CLTS 704 xorl %eax, %eax 705 fnstsw %ax 706 fnclex 707 ret 708 SET_SIZE(fperr_reset) 709 710 ENTRY_NP(fpxerr_reset) 711 CLTS 712 subl $4, %esp /* make some temporary space */ 713 stmxcsr (%esp) 714 movl (%esp), %eax 715 andl $_BITNOT(SSE_MXCSR_EFLAGS), (%esp) 716 ldmxcsr (%esp) /* clear processor exceptions */ 717 addl $4, %esp 718 ret 719 SET_SIZE(fpxerr_reset) 720 721 #endif /* __i386 */ 722 #endif /* __lint */ 723 724 #if defined(__lint) 725 726 uint32_t 727 fpgetcwsw(void) 728 { 729 return (0); 730 } 731 732 #else /* __lint */ 733 734 #if defined(__amd64) 735 736 ENTRY_NP(fpgetcwsw) 737 pushq %rbp 738 movq %rsp, %rbp 739 subq $0x10, %rsp /* make some temporary space */ 740 CLTS 741 fnstsw (%rsp) /* store the status word */ 742 fnstcw 2(%rsp) /* store the control word */ 743 movl (%rsp), %eax /* put both in %eax */ 744 leave 745 ret 746 SET_SIZE(fpgetcwsw) 747 748 #elif defined(__i386) 749 750 ENTRY_NP(fpgetcwsw) 751 CLTS 752 subl $4, %esp /* make some temporary space */ 753 fnstsw (%esp) /* store the status word */ 754 fnstcw 2(%esp) /* store the control word */ 755 movl (%esp), %eax /* put both in %eax */ 756 addl $4, %esp 757 ret 758 SET_SIZE(fpgetcwsw) 759 760 #endif /* __i386 */ 761 #endif /* __lint */ 762 763 /* 764 * Returns the MXCSR register. 765 */ 766 767 #if defined(__lint) 768 769 uint32_t 770 fpgetmxcsr(void) 771 { 772 return (0); 773 } 774 775 #else /* __lint */ 776 777 #if defined(__amd64) 778 779 ENTRY_NP(fpgetmxcsr) 780 pushq %rbp 781 movq %rsp, %rbp 782 subq $0x10, %rsp /* make some temporary space */ 783 CLTS 784 stmxcsr (%rsp) 785 movl (%rsp), %eax 786 leave 787 ret 788 SET_SIZE(fpgetmxcsr) 789 790 #elif defined(__i386) 791 792 ENTRY_NP(fpgetmxcsr) 793 CLTS 794 subl $4, %esp /* make some temporary space */ 795 stmxcsr (%esp) 796 movl (%esp), %eax 797 addl $4, %esp 798 ret 799 SET_SIZE(fpgetmxcsr) 800 801 #endif /* __i386 */ 802 #endif /* __lint */ 803