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