- Fix inclusion of deleted file.
[reactos.git] / reactos / lib / rtl / i386 / except_asm.s
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NT Library
4 * FILE: lib/rtl/i386/except.S
5 * PURPOSE: User-mode exception support for IA-32
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Casper S. Hornstrup (chorns@users.sourceforge.net)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ndk/asm.h>
13 .intel_syntax noprefix
14
15 #define EXCEPTION_UNWINDING 2
16 #define EXCEPTION_EXIT_UNWIND 4
17 #define EXCEPTION_UNWIND (EXCEPTION_UNWINDING + EXCEPTION_EXIT_UNWIND)
18
19 #define ExceptionContinueExecution 0
20 #define ExceptionContinueSearch 1
21 #define ExceptionNestedException 2
22 #define ExceptionCollidedUnwind 3
23
24 /* FUNCTIONS ****************************************************************/
25
26 .globl _RtlpGetExceptionList@0
27 _RtlpGetExceptionList@0:
28
29 /* Return the exception list */
30 mov eax, [fs:TEB_EXCEPTION_LIST]
31 ret
32
33 .globl _RtlpSetExceptionList@4
34 _RtlpSetExceptionList@4:
35
36 /* Get the new list */
37 mov ecx, [esp+4]
38 mov ecx, [ecx]
39
40 /* Write it */
41 mov [fs:TEB_EXCEPTION_LIST], ecx
42
43 /* Return */
44 ret 4
45
46 .globl _RtlpGetExceptionAddress@0
47 _RtlpGetExceptionAddress@0:
48
49 /* Return the address from the stack */
50 mov eax, [ebp+4]
51
52 /* Return */
53 ret
54
55 .globl _RtlCaptureContext@4
56 _RtlCaptureContext@4:
57
58 /* Preserve EBX and put the context in it */
59 push ebx
60 mov ebx, [esp+8]
61
62 /* Save the basic register context */
63 mov [ebx+CONTEXT_EAX], eax
64 mov [ebx+CONTEXT_ECX], ecx
65 mov [ebx+CONTEXT_EDX], edx
66 mov eax, [esp] /* We pushed EBX, remember? ;) */
67 mov [ebx+CONTEXT_EBX], eax
68 mov [ebx+CONTEXT_ESI], esi
69 mov [ebx+CONTEXT_EDI], edi
70
71 /* Capture the other regs */
72 jmp CaptureRest
73
74 .globl _RtlpCaptureContext@4
75 _RtlpCaptureContext@4:
76
77 /* Preserve EBX and put the context in it */
78 push ebx
79 mov ebx, [esp+8]
80
81 /* Clear the basic register context */
82 mov dword ptr [ebx+CONTEXT_EAX], 0
83 mov dword ptr [ebx+CONTEXT_ECX], 0
84 mov dword ptr [ebx+CONTEXT_EDX], 0
85 mov dword ptr [ebx+CONTEXT_EBX], 0
86 mov dword ptr [ebx+CONTEXT_ESI], 0
87 mov dword ptr [ebx+CONTEXT_EDI], 0
88
89 CaptureRest:
90 /* Capture the segment registers */
91 mov [ebx+CONTEXT_SEGCS], cs
92 mov [ebx+CONTEXT_SEGDS], ds
93 mov [ebx+CONTEXT_SEGES], es
94 mov [ebx+CONTEXT_SEGFS], fs
95 mov [ebx+CONTEXT_SEGGS], gs
96 mov [ebx+CONTEXT_SEGSS], ss
97
98 /* Capture flags */
99 pushfd
100 pop [ebx+CONTEXT_EFLAGS]
101
102 /* The return address should be in [ebp+4] */
103 mov eax, [ebp+4]
104 mov [ebx+CONTEXT_EIP], eax
105
106 /* Get EBP */
107 mov eax, [ebp+0]
108 mov [ebx+CONTEXT_EBP], eax
109
110 /* And get ESP */
111 lea eax, [ebp+8]
112 mov [ebx+CONTEXT_ESP], eax
113
114 /* Return to the caller */
115 pop ebx
116 ret 4
117
118 .globl _RtlpExecuteHandlerForException@20
119 _RtlpExecuteHandlerForException@20:
120
121 /* Copy the routine in EDX */
122 mov edx, offset _RtlpExceptionProtector
123
124 /* Jump to common routine */
125 jmp _RtlpExecuteHandler@20
126
127 .globl _RtlpExecuteHandlerForUnwind@20
128 _RtlpExecuteHandlerForUnwind@20:
129
130 /* Copy the routine in EDX */
131 mov edx, offset _RtlpExceptionProtector
132
133 /* Run the common routine */
134 _RtlpExecuteHandler@20:
135
136 /* Save non-volatile */
137 push ebx
138 push esi
139 push edi
140
141 /* Clear registers */
142 xor eax, eax
143 xor ebx, ebx
144 xor esi, esi
145 xor edi, edi
146
147 /* Call the 2nd-stage executer */
148 push [esp+0x20]
149 push [esp+0x20]
150 push [esp+0x20]
151 push [esp+0x20]
152 push [esp+0x20]
153 call _RtlpExecuteHandler2@20
154
155 /* Restore non-volatile */
156 pop edi
157 pop esi
158 pop ebx
159 ret 0x14
160
161 .globl _RtlpExecuteHandler2@20
162 _RtlpExecuteHandler2@20:
163
164 /* Set up stack frame */
165 push ebp
166 mov ebp, esp
167
168 /* Save the Frame */
169 push [ebp+0xC]
170
171 /* Push handler address */
172 push edx
173
174 /* Push the exception list */
175 push [fs:TEB_EXCEPTION_LIST]
176
177 /* Link us to it */
178 mov [fs:TEB_EXCEPTION_LIST], esp
179
180 /* Call the handler */
181 push [ebp+0x14]
182 push [ebp+0x10]
183 push [ebp+0xC]
184 push [ebp+8]
185 mov ecx, [ebp+0x18]
186 call ecx
187
188 /* Unlink us */
189 mov esp, [fs:TEB_EXCEPTION_LIST]
190
191 /* Restore it */
192 pop [fs:TEB_EXCEPTION_LIST]
193
194 /* Undo stack frame and return */
195 mov esp, ebp
196 pop ebp
197 ret 0x14
198
199 _RtlpExceptionProtector:
200
201 /* Assume we'll continue */
202 mov eax, ExceptionContinueSearch
203
204 /* Put the exception record in ECX and check the Flags */
205 mov ecx, [esp+4]
206 test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_UNWIND
207 jnz return
208
209 /* Save the frame in ECX and Context in EDX */
210 mov ecx, [esp+8]
211 mov edx, [esp+16]
212
213 /* Get the nested frame */
214 mov eax, [ecx+8]
215
216 /* Set it as the dispatcher context */
217 mov [edx], eax
218
219 /* Return nested exception */
220 mov eax, ExceptionNestedException
221
222 return:
223 ret 16
224
225 _RtlpUnwindProtector:
226 /* Assume we'll continue */
227 mov eax, ExceptionContinueSearch
228
229 /* Put the exception record in ECX and check the Flags */
230 mov ecx, [esp+4]
231 test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_UNWIND
232 jnz .return
233
234 /* Save the frame in ECX and Context in EDX */
235 mov ecx, [esp+8]
236 mov edx, [esp+16]
237
238 /* Get the nested frame */
239 mov eax, [ecx+8]
240
241 /* Set it as the dispatcher context */
242 mov [edx], eax
243
244 /* Return collided unwind */
245 mov eax, ExceptionCollidedUnwind
246
247 .return:
248 ret 16
249