sync with trunk (r47268)
[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 /* Save the return address */
29 mov ebx, [esp]
30 mov [eax+FIBER_CONTEXT_EIP], ebx
31
32 /* Check if we're to save FPU State */
33 cmp dword ptr [eax+FIBER_CONTEXT_FLAGS], CONTEXT_FULL | CONTEXT_FLOATING_POINT
34 jnz NoFpuStateSave
35
36 /* Save the FPU State (Status and Control)*/
37 fstsw [eax+FIBER_CONTEXT_FLOAT_SAVE_STATUS_WORD]
38 fstcw [eax+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
39
40 /* Check if the CPU supports SIMD MXCSR State Save */
41 cmp byte ptr ds:[PROCESSOR_FEATURE_FXSR], 0
42 jnz NoFpuStateSave
43 stmxcsr [eax+FIBER_CONTEXT_DR6]
44
45 NoFpuStateSave:
46
47 /* Save stack since we're not touching it anymore */
48 mov [eax+FIBER_CONTEXT_ESP], esp
49
50 /* Transfer some data from the TEB */
51 mov ecx, [edx+TEB_FLS_DATA]
52 mov [eax+FIBER_FLS_DATA], ecx
53 mov ecx, [edx+TEB_ACTIVATION_CONTEXT_STACK_POINTER]
54 mov [eax+FIBER_ACTIVATION_CONTEXT_STACK], ecx
55
56 /* Transfer some data related to the Stack */
57 mov ecx, [edx+TEB_EXCEPTION_LIST]
58 mov [eax+FIBER_EXCEPTION_LIST], ecx
59 mov ecx, [edx+TEB_STACK_LIMIT]
60 mov [eax+FIBER_STACK_LIMIT], ecx
61 mov ecx, [edx+TEB_GUARANTEED_STACK_BYTES]
62 mov [eax+FIBER_GUARANTEED_STACK_BYTES], ecx
63
64 /* Switch to the new fiber */
65 mov ecx, [esp+4]
66 mov [edx+TEB_FIBER_DATA], ecx
67
68 /* Switch Fiber Data */
69 mov esi, [ecx+FIBER_EXCEPTION_LIST]
70 mov [edx+TEB_EXCEPTION_LIST], esi
71 mov esi, [ecx+FIBER_STACK_BASE]
72 mov [edx+TEB_STACK_BASE], esi
73 mov esi, [ecx+FIBER_STACK_LIMIT]
74 mov [edx+TEB_STACK_LIMIT], esi
75 mov esi, [ecx+FIBER_DEALLOCATION_STACK]
76 mov [edx+TEB_DEALLOCATION_STACK], esi
77 mov esi, [ecx+FIBER_GUARANTEED_STACK_BYTES]
78 mov [edx+TEB_GUARANTEED_STACK_BYTES], esi
79 mov esi, [ecx+FIBER_ACTIVATION_CONTEXT_STACK]
80 mov [edx+TEB_ACTIVATION_CONTEXT_STACK_POINTER], esi
81
82 /* Restore FPU State */
83 cmp dword ptr [eax+FIBER_CONTEXT_FLAGS], CONTEXT_FULL | CONTEXT_FLOATING_POINT
84 jnz NoFpuStateRestore
85
86 /* Check if the Status Word Changed */
87 mov esi, [eax+FIBER_CONTEXT_FLOAT_SAVE_STATUS_WORD]
88 cmp si, word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_STATUS_WORD]
89 jnz StatusWordChanged
90
91 /* Check if the Control Word Changed */
92 mov esi, [eax+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
93 cmp si, word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
94 jz ControlWordEqual
95
96 StatusWordChanged:
97
98 /* Load the new one */
99 mov word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_TAG_WORD], 0xFFFF
100 fldenv [ecx+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
101
102 ControlWordEqual:
103
104 /* Load the new one */
105 cmp byte ptr ds:[PROCESSOR_FEATURE_FXSR], 0
106 jnz NoFpuStateRestore
107 ldmxcsr [ecx+FIBER_CONTEXT_DR6]
108
109 NoFpuStateRestore:
110
111 /* Restore non-volatile registers */
112 mov esi, [ecx+FIBER_CONTEXT_ESI]
113 mov edi, [ecx+FIBER_CONTEXT_EDI]
114 mov ebx, [ecx+FIBER_CONTEXT_EBX]
115 mov ebp, [ecx+FIBER_CONTEXT_EBP]
116 mov esp, [ecx+FIBER_CONTEXT_ESP]
117
118 /* Restore FLS Data */
119 mov eax, [ecx+FIBER_FLS_DATA]
120 mov [edx+TEB_FLS_DATA], eax
121
122 /* Jump to new fiber */
123 jmp [ecx+FIBER_CONTEXT_EIP]
124
125 /* EOF */