VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/math/fesetenv.asm@ 96282

Last change on this file since 96282 was 96213, checked in by vboxsync, 2 years ago

IPRT/nocrt: Implemented feraiseexcept and adjusted relevan code for X86_FSW_XCPT_MASK containg a bit more than X86_MXCSR_XCPT_FLAGS. bugref:10261

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.8 KB
Line 
1; $Id: fesetenv.asm 96213 2022-08-15 09:36:00Z vboxsync $
2;; @file
3; IPRT - No-CRT fesetenv - AMD64 & X86.
4;
5
6;
7; Copyright (C) 2022 Oracle Corporation
8;
9; This file is part of VirtualBox Open Source Edition (OSE), as
10; available from http://www.virtualbox.org. This file is free software;
11; you can redistribute it and/or modify it under the terms of the GNU
12; General Public License (GPL) as published by the Free Software
13; Foundation, in version 2 as it comes in the "COPYING" file of the
14; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16;
17; The contents of this file may alternatively be used under the terms
18; of the Common Development and Distribution License Version 1.0
19; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20; VirtualBox OSE distribution, in which case the provisions of the
21; CDDL are applicable instead of those of the GPL.
22;
23; You may elect to license modified versions of this file under the
24; terms and conditions of either the GPL or the CDDL or both.
25;
26
27
28%define RT_ASM_WITH_SEH64
29%include "iprt/asmdefs.mac"
30%include "iprt/x86.mac"
31
32%define RT_NOCRT_FE_DFL_ENV 1
33%define RT_NOCRT_FE_NOMASK_ENV 2
34%define RT_NOCRT_FE_PC53_ENV 3
35%define RT_NOCRT_FE_PC64_ENV 4
36%define RT_NOCRT_FE_LAST_ENV 4
37
38
39BEGINCODE
40
41;;
42; Sets the FPU+SSE environment.
43;
44; @returns eax = 0 on success, -1 on failure.
45; @param pEnv 32-bit: [xBP+8] msc64: rcx gcc64: rdi - Saved environment to restore.
46;
47RT_NOCRT_BEGINPROC fesetenv
48 push xBP
49 SEH64_PUSH_xBP
50 mov xBP, xSP
51 SEH64_SET_FRAME_xBP 0
52 sub xBP, 20h
53 SEH64_ALLOCATE_STACK 20h
54 SEH64_END_PROLOGUE
55
56 ;
57 ; Load the parameter into rcx.
58 ;
59%ifdef ASM_CALL64_GCC
60 mov rcx, rdi
61%elifdef RT_ARCH_X86
62 mov ecx, [xBP + xCB*2]
63%endif
64
65 ;
66 ; For the x87 state we only set FSW.XCPT, FCW.XCPT, FCW.RC and FCW.PC.
67 ; So we save the current environment, merge those fields and load it.
68 ;
69 fnstenv [xBP - 20h]
70
71 ; Check for special "pointer" values:
72 cmp xCX, RT_NOCRT_FE_LAST_ENV
73 ja .x87_regular
74
75 or eax, -1
76 test xCX, xCX
77 jnz .x87_special
78%ifdef RT_STRICT
79 int3
80%endif
81 jmp .return
82
83 ;
84 ; Special x87 state. Clear all pending exceptions.
85 ;
86 ; We have 4 special environments with only some differences in FCW differs, so set
87 ; up FCW in AX, starting with a NOMASK environment as it has the fewest bits set.
88 ;
89.x87_special:
90 and word [xBP - 20h + X86FSTENV32P.FSW], ~X86_FSW_XCPT_ES_MASK
91 mov ax, [xBP - 20h + X86FSTENV32P.FCW]
92 and ax, ~(X86_FCW_MASK_ALL | X86_FCW_PC_MASK | X86_FCW_RC_MASK | X86_FCW_IC_MASK)
93%ifdef RT_OS_WINDOWS
94 or ax, X86_FCW_DM | X86_FCW_PC_53 | X86_FCW_RC_NEAREST | X86_FCW_IC_PROJECTIVE
95%else
96 or ax, X86_FCW_DM | X86_FCW_PC_64 | X86_FCW_RC_NEAREST | X86_FCW_IC_PROJECTIVE
97%endif
98 cmp xCX, RT_NOCRT_FE_NOMASK_ENV
99 je .x87_special_done
100 or ax, X86_FCW_MASK_ALL
101
102%ifdef RT_OS_WINDOWS
103 cmp xCX, RT_NOCRT_FE_PC64_ENV
104 jne .x87_special_done
105 or ax, X86_FCW_PC_64 ; X86_FCW_PC_64 is a super set of X86_FCW_PC_53, so no need to clear bits
106%else
107 cmp xCX, RT_NOCRT_FE_PC53_ENV
108 jne .x87_special_done
109 and ax, X86_FCW_PC_64 & ~X86_FCW_PC_53 ; X86_FCW_PC_64 is a super set of X86_FCW_PC_53, so clear the bit that differs.
110%endif
111
112.x87_special_done:
113 mov [xBP - 20h + X86FSTENV32P.FCW], ax
114 jmp .x87_common
115
116 ;
117 ; Merge input and current.
118 ;
119.x87_regular:
120 ; FCW:
121 mov ax, [xCX + X86FSTENV32P.FCW]
122 mov dx, [xBP - 20h + X86FSTENV32P.FCW]
123 and ax, X86_FCW_MASK_ALL | X86_FCW_RC_MASK | X86_FCW_PC_MASK
124 and dx, ~(X86_FCW_MASK_ALL | X86_FCW_RC_MASK | X86_FCW_PC_MASK)
125 or dx, ax
126 mov [xBP - 20h + X86FSTENV32P.FCW], dx
127 ; FSW
128 mov ax, [xCX + X86FSTENV32P.FSW]
129 mov dx, [xBP - 20h + X86FSTENV32P.FSW]
130 and ax, X86_FSW_XCPT_MASK
131 and dx, ~(X86_FSW_XCPT_MASK)
132 or dx, ax
133 mov [xBP - 20h + X86FSTENV32P.FSW], dx
134
135.x87_common:
136 ; Clear the exception info.
137 xor eax, eax
138 mov [xBP - 20h + X86FSTENV32P.FPUIP], eax
139 mov [xBP - 20h + X86FSTENV32P.FPUCS], eax ; covers FOP too.
140 mov [xBP - 20h + X86FSTENV32P.FPUDP], eax
141 mov [xBP - 20h + X86FSTENV32P.FPUDS], eax
142
143 ; Load the merged and cleaned up environment.
144 fldenv [xBP - 20h]
145
146
147 ;
148 ; Now for SSE, if supported, where we'll restore everything as is.
149 ;
150%ifdef RT_ARCH_X86
151 ; SSE supported (ecx preserved)?
152 extern NAME(rtNoCrtHasSse)
153 call NAME(rtNoCrtHasSse)
154 test al, al
155 jz .return_okay
156%endif
157
158 cmp xCX, RT_NOCRT_FE_LAST_ENV
159 jb .sse_special_env
160 ldmxcsr [xCX + 28]
161 jmp .return_okay
162
163.sse_special_env:
164 stmxcsr [xBP - 10h]
165 mov eax, [xBP - 10h]
166 and eax, ~(X86_MXCSR_XCPT_FLAGS | X86_MXCSR_XCPT_MASK | X86_MXCSR_RC_MASK | X86_MXCSR_DAZ | X86_MXCSR_FZ)
167 or eax, X86_MXCSR_RC_NEAREST | X86_MXCSR_DM
168 cmp xCX, RT_NOCRT_FE_NOMASK_ENV ; Only the NOMASK one differs here.
169 je .sse_special_load_eax
170 or eax, X86_MXCSR_RC_NEAREST | X86_MXCSR_XCPT_MASK ; default environment masks all exceptions
171.sse_special_load_eax:
172 mov [xBP - 10h], eax
173 ldmxcsr [xBP - 10h]
174
175 ;
176 ; Return success.
177 ;
178.return_okay:
179 xor eax, eax
180.return:
181 leave
182 ret
183ENDPROC RT_NOCRT(fesetenv)
184
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette