214a264170ff696d7046b449d16028216cffa07d
[reactos.git] / reactos / lib / 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/i386/segment.h>
11 #include <ndk/asm.h>
12
13 #define CONTEXT_FULL 0x10007
14 #define CONTEXT_FLOATING_POINT 0xF
15
16 .globl _SwitchToFiber@4
17 .intel_syntax noprefix
18
19 _SwitchToFiber@4:
20 /* Get the TEB */
21 mov edx, fs:[TEB_SELECTOR]
22
23 /* Get the Fiber */
24 mov eax, [edx+TEB_FIBER_DATA]
25
26 /* Save the non-volatile registers */
27 mov [eax+FIBER_CONTEXT_EBX], ebx
28 mov [eax+FIBER_CONTEXT_ESI], esi
29 mov [eax+FIBER_CONTEXT_EDI], edi
30 mov [eax+FIBER_CONTEXT_EBP], ebp
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 [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 [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 /* Return */
123 ret 4
124
125 /* EOF */