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