xref: /reactos/sdk/lib/pseh/i386/pseh3_i386.S (revision c2c66aff)
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<ecx>);
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    /* Safe the return address */
34    mov ebx, [esp]
35    mov [eax + SEH3_REGISTRATION_FRAME_ReturnAddress], ebx
36    mov ebx, [eax + SEH3_REGISTRATION_FRAME_Ebx]
37
38.global __SEH3$_RegisterFrameWithStackLayout
39__SEH3$_RegisterFrameWithStackLayout:
40
41    /* Save the pointer to the alloca frame */
42    mov [eax + SEH3_REGISTRATION_FRAME_AllocaFrame], ecx
43
44.global __SEH3$_RegisterFrame
45__SEH3$_RegisterFrame:
46
47    /* Save the address of the static data table */
48    mov [eax + SEH3_REGISTRATION_FRAME_ScopeTable], edx
49
50    /* Set the handler address */
51    mov dword ptr [eax + SEH3_REGISTRATION_FRAME_Handler], offset __SEH3$_except_handler
52
53    /* Set this as the end of the internal chain */
54    mov dword ptr [eax + SEH3_REGISTRATION_FRAME_EndOfChain], eax
55
56    /* Register the frame in the TEB */
57    mov edx, dword ptr fs:[0]
58    mov [eax + SEH3_REGISTRATION_FRAME_Next], edx
59    mov dword ptr fs:[0], eax
60
61    /* Save the stack registers */
62    mov [eax + SEH3_REGISTRATION_FRAME_Esp], esp
63    mov [eax + SEH3_REGISTRATION_FRAME_Ebp], ebp
64
65    /* Set eax to 0 to indicate 1st return */
66    xor eax, eax
67    ret
68
69
70/*
71 *  void
72 *  __attribute__((regparm(3)))
73 *  __attribute__((returns_twice))
74 *  _SEH3$_RegisterTryLevel[WithNonVolatiles](
75 *       PSEH3$_REGISTRATION_FRAME RegistrationFrame<eax>,
76 *       PSEH3$_SCOPE_TABLE ScopeTable<edx>,
77 *       PVOID AllocaFrame<ecx>);
78 */
79.global __SEH3$_RegisterTryLevelWithNonVolatiles
80__SEH3$_RegisterTryLevelWithNonVolatiles:
81
82    /* Save non-volatiles in the registration frame */
83    mov [eax + SEH3_REGISTRATION_FRAME_Ebx], ebx
84    mov [eax + SEH3_REGISTRATION_FRAME_Esi], esi
85    mov [eax + SEH3_REGISTRATION_FRAME_Edi], edi
86
87    /* Safe the return address */
88    mov ebx, [esp]
89    mov [eax + SEH3_REGISTRATION_FRAME_ReturnAddress], ebx
90    mov ebx, [eax + SEH3_REGISTRATION_FRAME_Ebx]
91
92.global __SEH3$_RegisterTryLevelWithStackLayout
93__SEH3$_RegisterTryLevelWithStackLayout:
94
95    /* Save the pointer to the alloca frame */
96    mov [eax + SEH3_REGISTRATION_FRAME_AllocaFrame], ecx
97
98.global __SEH3$_RegisterTryLevel
99__SEH3$_RegisterTryLevel:
100
101    /* Save the address of the static data table */
102    mov [eax + SEH3_REGISTRATION_FRAME_ScopeTable], edx
103
104    /* Set the handler address to NULL as identification */
105    and dword ptr [eax + SEH3_REGISTRATION_FRAME_Handler], 0
106
107    /* Get the current registered frame */
108    mov edx, dword ptr fs:[0]
109
110    /* Get the current end of the chain and set this as Next */
111    mov ecx, [edx + SEH3_REGISTRATION_FRAME_EndOfChain]
112    mov [eax + SEH3_REGISTRATION_FRAME_Next], ecx
113
114    /* Set this as the end of the internal chain */
115    mov dword ptr [edx + SEH3_REGISTRATION_FRAME_EndOfChain], eax
116
117    /* Save the stack registers */
118    mov [eax + SEH3_REGISTRATION_FRAME_Esp], esp
119    mov [eax + SEH3_REGISTRATION_FRAME_Ebp], ebp
120
121    /* Set eax to 0 to indicate 1st return */
122    xor eax, eax
123    ret
124
125
126.global __SEH3$_InvokeEmbeddedFilterFromRegistration
127__SEH3$_InvokeEmbeddedFilterFromRegistration:
128
129    /* Safe the current non-volatiles */
130    push ebp
131    push ebx
132    push esi
133    push edi
134
135    /* Save the registration frame pointer */
136    push eax
137
138    /* Load the non-volatiles from the registration invocation */
139    mov ebx, [eax + SEH3_REGISTRATION_FRAME_Ebx]
140    mov esi, [eax + SEH3_REGISTRATION_FRAME_Esi]
141    mov edi, [eax + SEH3_REGISTRATION_FRAME_Edi]
142    mov ebp, [eax + SEH3_REGISTRATION_FRAME_Ebp]
143
144    /* Calculate the size of the temp stack frame region */
145    mov ecx, [eax + SEH3_REGISTRATION_FRAME_AllocaFrame]
146    sub ecx, [eax + SEH3_REGISTRATION_FRAME_Esp]
147
148    /* Put the return address on the stack */
149    push offset __SEH3$_InvokeEmbeddedFilterReturnClang
150
151    /* Save the current stack pointer in the AllocaFrame member */
152    mov [eax + SEH3_REGISTRATION_FRAME_AllocaFrame], esp
153
154    /* Allocate enough temp stack space on the stack */
155    sub esp, ecx
156
157    /* Get the return address that was saved when registering the frame */
158    mov edx, [eax + SEH3_REGISTRATION_FRAME_ReturnAddress]
159
160    /* Jump into the filter or finally function */
161    xor eax, eax
162    inc eax
163    jmp edx
164
165    /* We return to this label with a cleaned up stack */
166__SEH3$_InvokeEmbeddedFilterReturnClang:
167
168    /* Restore the registration frame pointer */
169    pop ecx
170
171    /* Save the non-volatiles back in the registration frame */
172    mov [ecx + SEH3_REGISTRATION_FRAME_Ebx], ebx
173    mov [ecx + SEH3_REGISTRATION_FRAME_Esi], esi
174    mov [ecx + SEH3_REGISTRATION_FRAME_Edi], edi
175    mov [ecx + SEH3_REGISTRATION_FRAME_Ebp], ebp
176
177    /* Restore the current non-volatiles */
178    pop edi
179    pop esi
180    pop ebx
181    pop ebp
182
183    ret
184
185
186.global __SEH3$_InvokeEmbeddedFilter
187__SEH3$_InvokeEmbeddedFilter:
188
189    /* Safe the current non-volatiles */
190    push ebp
191    push ebx
192    push esi
193    push edi
194
195    /* Load ebp from the registration invocation */
196    mov ebp, [eax + SEH3_REGISTRATION_FRAME_Ebp]
197
198    /* Calculate the size of the temp stack frame region */
199    mov ecx, [eax + SEH3_REGISTRATION_FRAME_AllocaFrame]
200    sub ecx, [eax + SEH3_REGISTRATION_FRAME_Esp]
201
202    /* Put the return address on the stack */
203    push offset __SEH3$_InvokeEmbeddedFilterReturn
204
205    /* Save the current stack pointer in the AllocaFrame member */
206    mov [eax + SEH3_REGISTRATION_FRAME_AllocaFrame], esp
207
208    /* Allocate enough temp stack space on the stack */
209    sub esp, ecx
210
211    /* Get the scope table */
212    mov edx, [eax + SEH3_REGISTRATION_FRAME_ScopeTable]
213
214    /* Jump into the filter or finally function */
215    jmp [edx + SEH3_SCOPE_TABLE_Filter]
216
217    /* We return to this label with a cleaned up stack */
218__SEH3$_InvokeEmbeddedFilterReturn:
219
220    /* Restore the current non-volatiles */
221    pop edi
222    pop esi
223    pop ebx
224    pop ebp
225
226    ret
227
228/*
229 * void
230 * __fastcall
231 * _SEH3$_CallRtlUnwind(
232 *     PSEH3$_REGISTRATION_FRAME RegistrationFrame<ecx>)
233 */
234.global @_SEH3$_CallRtlUnwind@4
235@_SEH3$_CallRtlUnwind@4:
236
237    push ebp
238    mov ebp, esp
239
240    push edi
241    push esi
242    push ebx
243
244    push 0   /* ReturnValue */
245    push 0   /* ExceptionRecord */
246    push 0   /* TargetIp */
247    push ecx /* TargetFrame */
248    call _RtlUnwind@16
249
250    pop ebx
251    pop esi
252    pop edi
253    pop ebp
254    ret
255
256