Sync with trunk (r47116), hopefully without breaking anything.
[reactos.git] / dll / win32 / kernel32 / thread / i386 / fiber.S
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/thread/i386/fiber.S
5 * PURPOSE: Fiber context switch code for the x86 architecture
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * KJK::Hyperion <noog@libero.it>
8 */
9
10 #include <ndk/asm.h>
11
12 .globl _SwitchToFiber@4
13 .intel_syntax noprefix
14
15 _SwitchToFiber@4:
16 /* Get the TEB */
17 mov edx, fs:[TEB_SELF]
18
19 /* Get the Fiber */
20 mov eax, [edx+TEB_FIBER_DATA]
21
22 /* Save the non-volatile registers */
23 mov [eax+FIBER_CONTEXT_EBX], ebx
24 mov [eax+FIBER_CONTEXT_ESI], esi
25 mov [eax+FIBER_CONTEXT_EDI], edi
26 mov [eax+FIBER_CONTEXT_EBP], ebp
27
28 /* Check if we're to save FPU State */
29 cmp dword ptr [eax+FIBER_CONTEXT_FLAGS], CONTEXT_FULL | CONTEXT_FLOATING_POINT
30 jnz NoFpuStateSave
31
32 /* Save the FPU State (Status and Control)*/
33 fstsw [eax+FIBER_CONTEXT_FLOAT_SAVE_STATUS_WORD]
34 fstcw [eax+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
35
36 /* Check if the CPU supports SIMD MXCSR State Save */
37 cmp byte ptr ds:[PROCESSOR_FEATURE_FXSR], 0
38 jnz NoFpuStateSave
39 stmxcsr [eax+FIBER_CONTEXT_DR6]
40
41 NoFpuStateSave:
42
43 /* Save stack since we're not touching it anymore */
44 mov [eax+FIBER_CONTEXT_ESP], esp
45
46 /* Transfer some data from the TEB */
47 mov ecx, [edx+TEB_FLS_DATA]
48 mov [eax+FIBER_FLS_DATA], ecx
49 mov ecx, [edx+TEB_ACTIVATION_CONTEXT_STACK_POINTER]
50 mov [eax+FIBER_ACTIVATION_CONTEXT_STACK], ecx
51
52 /* Transfer some data related to the Stack */
53 mov ecx, [edx+TEB_EXCEPTION_LIST]
54 mov [eax+FIBER_EXCEPTION_LIST], ecx
55 mov ecx, [edx+TEB_STACK_LIMIT]
56 mov [eax+FIBER_STACK_LIMIT], ecx
57 mov ecx, [edx+TEB_GUARANTEED_STACK_BYTES]
58 mov [eax+FIBER_GUARANTEED_STACK_BYTES], ecx
59
60 /* Switch to the new fiber */
61 mov ecx, [esp+4]
62 mov [edx+TEB_FIBER_DATA], ecx
63
64 /* Switch Fiber Data */
65 mov esi, [ecx+FIBER_EXCEPTION_LIST]
66 mov [edx+TEB_EXCEPTION_LIST], esi
67 mov esi, [ecx+FIBER_STACK_BASE]
68 mov [edx+TEB_STACK_BASE], esi
69 mov esi, [ecx+FIBER_STACK_LIMIT]
70 mov [edx+TEB_STACK_LIMIT], esi
71 mov esi, [ecx+FIBER_DEALLOCATION_STACK]
72 mov [edx+TEB_DEALLOCATION_STACK], esi
73 mov esi, [ecx+FIBER_GUARANTEED_STACK_BYTES]
74 mov [edx+TEB_GUARANTEED_STACK_BYTES], esi
75 mov esi, [ecx+FIBER_ACTIVATION_CONTEXT_STACK]
76 mov [edx+TEB_ACTIVATION_CONTEXT_STACK_POINTER], esi
77
78 /* Restore FPU State */
79 cmp dword ptr [eax+FIBER_CONTEXT_FLAGS], CONTEXT_FULL | CONTEXT_FLOATING_POINT
80 jnz NoFpuStateRestore
81
82 /* Check if the Status Word Changed */
83 mov esi, [eax+FIBER_CONTEXT_FLOAT_SAVE_STATUS_WORD]
84 cmp si, word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_STATUS_WORD]
85 jnz StatusWordChanged
86
87 /* Check if the Control Word Changed */
88 mov esi, [eax+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
89 cmp si, word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
90 jz ControlWordEqual
91
92 StatusWordChanged:
93
94 /* Load the new one */
95 mov word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_TAG_WORD], 0xFFFF
96 fldenv [ecx+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
97
98 ControlWordEqual:
99
100 /* Load the new one */
101 cmp byte ptr ds:[PROCESSOR_FEATURE_FXSR], 0
102 jnz NoFpuStateRestore
103 ldmxcsr [ecx+FIBER_CONTEXT_DR6]
104
105 NoFpuStateRestore:
106
107 /* Restore non-volatile registers */
108 mov esi, [ecx+FIBER_CONTEXT_ESI]
109 mov edi, [ecx+FIBER_CONTEXT_EDI]
110 mov ebx, [ecx+FIBER_CONTEXT_EBX]
111 mov ebp, [ecx+FIBER_CONTEXT_EBP]
112 mov esp, [ecx+FIBER_CONTEXT_ESP]
113
114 /* Restore FLS Data */
115 mov eax, [ecx+FIBER_FLS_DATA]
116 mov [edx+TEB_FLS_DATA], eax
117
118 /* Return */
119 ret 4
120
121 /* EOF */