[PSEH]
[reactos.git] / reactos / lib / pseh / i386 / pseh3_i386.S
1 /*
2 * PROJECT: ReactOS system libraries
3 * LICENSE: GNU GPL - See COPYING in the top level directory
4 * PURPOSE: Support library for PSEH3
5 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
6 */
7
8 #include "pseh3_asmdef.h"
9
10 .intel_syntax noprefix
11
12 .text
13
14 .extern __SEH3$_except_handler
15
16 /*
17 * void
18 * __attribute__((regparm(3)))
19 * __attribute__((returns_twice))
20 * _SEH3$_RegisterFrame[WithNonVolatiles](
21 * PSEH3$_REGISTRATION_FRAME RegistrationFrame<eax>,
22 * PSEH3$_SCOPE_TABLE ScopeTable<edx>,
23 * PVOID AllocaFrame);
24 */
25 .global __SEH3$_RegisterFrameWithNonVolatiles
26 __SEH3$_RegisterFrameWithNonVolatiles:
27
28 /* Save non-volatiles in the registration frame */
29 mov [eax + SEH3_REGISTRATION_FRAME_Ebx], ebx
30 mov [eax + SEH3_REGISTRATION_FRAME_Esi], esi
31 mov [eax + SEH3_REGISTRATION_FRAME_Edi], edi
32
33 .global __SEH3$_RegisterFrameWithStackLayout
34 __SEH3$_RegisterFrameWithStackLayout:
35
36 /* Save the pointer to the alloca frame */
37 mov [eax + SEH3_REGISTRATION_FRAME_AllocaFrame], ecx
38
39 .global __SEH3$_RegisterFrame
40 __SEH3$_RegisterFrame:
41
42 /* Save the address of the static data table */
43 mov [eax + SEH3_REGISTRATION_FRAME_ScopeTable], edx
44
45 /* Set the handler address */
46 mov dword ptr [eax + SEH3_REGISTRATION_FRAME_Handler], offset __SEH3$_except_handler
47
48 /* Set this as the end of the internal chain */
49 mov dword ptr [eax + SEH3_REGISTRATION_FRAME_EndOfChain], eax
50
51 /* Register the frame in the TEB */
52 mov edx, dword ptr fs:[0]
53 mov [eax + SEH3_REGISTRATION_FRAME_Next], edx
54 mov dword ptr fs:[0], eax
55
56 /* Save the stack registers */
57 mov [eax + SEH3_REGISTRATION_FRAME_Esp], esp
58 mov [eax + SEH3_REGISTRATION_FRAME_Ebp], ebp
59
60 /* Set eax to 0 to indicate 1st return */
61 xor eax, eax
62 ret
63
64
65 /*
66 * void
67 * __attribute__((regparm(3)))
68 * __attribute__((returns_twice))
69 * _SEH3$_RegisterTryLevel[WithNonVolatiles](
70 * PSEH3$_REGISTRATION_FRAME RegistrationFrame<edx>,
71 * PSEH3$_SCOPE_TABLE ScopeTable<eax>,
72 * PVOID AllocaFrame);
73 */
74 .global __SEH3$_RegisterTryLevelWithNonVolatiles
75 __SEH3$_RegisterTryLevelWithNonVolatiles:
76
77 /* Save non-volatiles in the registration frame */
78 mov [eax + SEH3_REGISTRATION_FRAME_Ebx], ebx
79 mov [eax + SEH3_REGISTRATION_FRAME_Esi], esi
80 mov [eax + SEH3_REGISTRATION_FRAME_Edi], edi
81
82 .global __SEH3$_RegisterTryLevelWithStackLayout
83 __SEH3$_RegisterTryLevelWithStackLayout:
84
85 /* Save the pointer to the alloca frame */
86 mov [eax + SEH3_REGISTRATION_FRAME_AllocaFrame], ecx
87
88 .global __SEH3$_RegisterTryLevel
89 __SEH3$_RegisterTryLevel:
90
91 /* Save the address of the static data table */
92 mov [eax + SEH3_REGISTRATION_FRAME_ScopeTable], edx
93
94 /* Set the handler address to NULL as identification */
95 and dword ptr [eax + SEH3_REGISTRATION_FRAME_Handler], 0
96
97 /* Get the current registered frame */
98 mov edx, dword ptr fs:[0]
99
100 /* Get the current end of the chain and set this as Next */
101 mov ecx, [edx + SEH3_REGISTRATION_FRAME_EndOfChain]
102 mov [eax + SEH3_REGISTRATION_FRAME_Next], ecx
103
104 /* Set this as the end of the internal chain */
105 mov dword ptr [edx + SEH3_REGISTRATION_FRAME_EndOfChain], eax
106
107 /* Save the stack registers */
108 mov [eax + SEH3_REGISTRATION_FRAME_Esp], esp
109 mov [eax + SEH3_REGISTRATION_FRAME_Ebp], ebp
110
111 /* Set eax to 0 to indicate 1st return */
112 xor eax, eax
113 ret
114
115
116 .global __SEH3$_InvokeEmbeddedFilterFromRegistration
117 __SEH3$_InvokeEmbeddedFilterFromRegistration:
118
119 /* Safe the current non-volatiles */
120 push ebp
121 push ebx
122 push esi
123 push edi
124
125 /* Load the non-volatiles from the registration invocation */
126 mov ebx, [eax + SEH3_REGISTRATION_FRAME_Ebx]
127 mov esi, [eax + SEH3_REGISTRATION_FRAME_Esi]
128 mov edi, [eax + SEH3_REGISTRATION_FRAME_Edi]
129 mov ebp, [eax + SEH3_REGISTRATION_FRAME_Ebp]
130
131 jmp __SEH3$_InvokeEmbeddedFilter2
132
133 /* Get the saved stack pointer */
134 mov edx, [eax + SEH3_REGISTRATION_FRAME_Esp]
135
136 xor eax, eax
137 inc eax
138 call [edx]
139
140 /* Restore the current non-volatiles */
141 pop edi
142 pop esi
143 pop ebx
144 pop ebp
145
146 ret
147
148
149 .global __SEH3$_InvokeEmbeddedFilter
150 __SEH3$_InvokeEmbeddedFilter:
151
152 /* Safe the current non-volatiles */
153 push ebp
154 push ebx
155 push esi
156 push edi
157
158 /* Load ebp from the registration invocation */
159 mov ebp, [eax + SEH3_REGISTRATION_FRAME_Ebp]
160 __SEH3$_InvokeEmbeddedFilter2:
161 /* Calculate the size of the temp stack frame region */
162 mov ecx, [eax + SEH3_REGISTRATION_FRAME_AllocaFrame]
163 sub ecx, [eax + SEH3_REGISTRATION_FRAME_Esp]
164
165 /* Put the return address on the stack */
166 push offset __SEH3$_InvokeEmbeddedFilterReturn
167
168 /* Save the current stack pointer in the AllocaFrame member */
169 mov [eax + SEH3_REGISTRATION_FRAME_AllocaFrame], esp
170
171 /* Allocate enough temp stack space on the stack */
172 sub esp, ecx
173
174 /* Get the scope table */
175 mov edx, [eax + SEH3_REGISTRATION_FRAME_ScopeTable]
176
177 /* Jump into the filter or finally function */
178 jmp [edx + SEH3_SCOPE_TABLE_Filter]
179
180 /* We return to this label with a cleaned up stack */
181 __SEH3$_InvokeEmbeddedFilterReturn:
182
183 /* Restore the current non-volatiles */
184 pop edi
185 pop esi
186 pop ebx
187 pop ebp
188
189 ret
190
191 /*
192 * void
193 * __fastcall
194 * _SEH3$_CallRtlUnwind(
195 * PSEH3$_REGISTRATION_FRAME RegistrationFrame<ecx>)
196 */
197 .global @_SEH3$_CallRtlUnwind@4
198 @_SEH3$_CallRtlUnwind@4:
199
200 push ebp
201 mov ebp, esp
202
203 push edi
204 push esi
205 push ebx
206
207 push 0 /* ReturnValue */
208 push 0 /* ExceptionRecord */
209 push 0 /* TargetIp */
210 push ecx /* TargetFrame */
211 call _RtlUnwind@16
212
213 pop ebx
214 pop esi
215 pop edi
216 pop ebp
217 ret
218