update for HEAD-2003091401
[reactos.git] / lib / ntdll / rtl / i386 / except.s
1 /* $Id$
2  *
3  * COPYRIGHT:         See COPYING in the top level directory
4  * PROJECT:           ReactOS kernel
5  * PURPOSE:           User-mode exception support for IA-32
6  * FILE:              lib/ntdll/rtl/i386/except.s
7  * PROGRAMER:         Casper S. Hornstrup (chorns@users.sourceforge.net)
8  * NOTES:             This file is shared with ntoskrnl/rtl/i386/except.s.
9  *                    Please keep them in sync.
10  */
11
12 #define EXCEPTION_UNWINDING             0x02
13
14 #define EREC_FLAGS                              0x04
15
16 #define ExceptionContinueExecution 0
17 #define ExceptionContinueSearch    1
18 #define ExceptionNestedException   2
19 #define ExceptionCollidedUnwind    3
20
21 .globl _RtlpExecuteHandlerForException
22 .globl _RtlpExecuteHandlerForUnwind
23
24 #define CONTEXT_FLAGS   0x00
25 #define CONTEXT_SEGGS   0x8C
26 #define CONTEXT_SEGFS   0x90
27 #define CONTEXT_SEGES   0x94
28 #define CONTEXT_SEGDS   0x98
29 #define CONTEXT_EDI             0x9C
30 #define CONTEXT_ESI             0xA0
31 #define CONTEXT_EBX             0xA4
32 #define CONTEXT_EDX             0xA8
33 #define CONTEXT_ECX             0xAC
34 #define CONTEXT_EAX             0xB0
35 #define CONTEXT_EBP             0xB4
36 #define CONTEXT_EIP             0xB8
37 #define CONTEXT_SEGCS   0xBC
38 #define CONTEXT_EFLAGS  0xC0
39 #define CONTEXT_ESP             0xC4
40 #define CONTEXT_SEGSS   0xC8
41
42
43 #define RCC_CONTEXT             0x08
44
45 // EAX = value to print
46 _do_debug:
47         pushal
48         pushl   %eax
49         call    _AsmDebug@4
50         popal
51         ret
52
53 #ifndef __NTOSKRNL__
54
55 //
56 // VOID
57 // RtlpCaptureContext(PCONTEXT pContext);
58 //
59 // Parameters:
60 //   [ESP+08h] - PCONTEXT_X86 pContext
61 // Registers:
62 //   None
63 // Returns:
64 //   Nothing
65 // Notes:
66 //   Grabs the current CPU context.
67 .globl _RtlpCaptureContext
68 _RtlpCaptureContext:
69         pushl   %ebp
70     movl        %esp, %ebp
71         movl    RCC_CONTEXT(%ebp), %edx         // EDX = Address of context structure
72
73         cld
74         pushf
75         pop             %eax
76         movl    %eax, CONTEXT_EFLAGS(%edx)
77         xorl    %eax, %eax
78         movl    %eax, CONTEXT_EAX(%edx)
79         movl    %eax, CONTEXT_EBX(%edx)
80         movl    %eax, CONTEXT_ECX(%edx)
81         movl    %eax, CONTEXT_EDX(%edx)
82         movl    %eax, CONTEXT_ESI(%edx)
83         movl    %eax, CONTEXT_EDI(%edx)
84         movl    %cs, %eax
85         movl    %eax, CONTEXT_SEGCS(%edx)
86         movl    %ds, %eax
87         movl    %eax, CONTEXT_SEGDS(%edx)
88         movl    %es, %eax
89         movl    %eax, CONTEXT_SEGES(%edx)
90         movl    %fs, %eax
91         movl    %eax, CONTEXT_SEGFS(%edx)
92         movl    %gs, %eax
93         movl    %eax, CONTEXT_SEGGS(%edx)
94         movl    %ss, %eax
95         movl    %eax, CONTEXT_SEGSS(%edx)
96
97         //
98         // STACK LAYOUT: - (ESP to put in context structure)
99         //               - RETURN ADDRESS OF CALLER OF CALLER
100         //               - EBP OF CALLER OF CALLER
101         //                 ...
102         //               - RETURN ADDRESS OF CALLER
103         //               - EBP OF CALLER
104         //                 ...
105         //
106
107         // Get return address of the caller of the caller of this function
108         movl    %ebp, %ebx
109         //movl  4(%ebx), %eax                   // EAX = return address of caller
110         movl    (%ebx), %ebx                    // EBX = EBP of caller
111
112         movl    4(%ebx), %eax                   // EAX = return address of caller of caller
113         movl    (%ebx), %ebx                    // EBX = EBP of caller of caller
114
115         movl    %eax, CONTEXT_EIP(%edx) // EIP = return address of caller of caller
116         movl    %ebx, CONTEXT_EBP(%edx) // EBP = EBP of caller of caller
117         addl    $8, %ebx
118         movl    %ebx, CONTEXT_ESP(%edx) // ESP = EBP of caller of caller + 8
119
120     movl        %ebp, %esp
121     popl        %ebp
122     ret
123
124 #endif /* !__NTOSKRNL__ */
125
126 #define REH_ERECORD             0x08
127 #define REH_RFRAME              0x0C
128 #define REH_CONTEXT             0x10
129 #define REH_DCONTEXT    0x14
130 #define REH_EROUTINE    0x18
131
132 // Parameters:
133 //   None
134 // Registers:
135 //   [EBP+08h] - PEXCEPTION_RECORD ExceptionRecord
136 //   [EBP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame
137 //   [EBP+10h] - PVOID Context
138 //   [EBP+14h] - PVOID DispatcherContext
139 //   [EBP+18h] - PEXCEPTION_HANDLER ExceptionRoutine
140 //   EDX       - Address of protecting exception handler
141 // Returns:
142 //   EXCEPTION_DISPOSITION
143 // Notes:
144 //   Setup the protecting exception handler and call the exception
145 //   handler in the right context.
146 _RtlpExecuteHandler:
147         pushl    %ebp
148     movl     %esp, %ebp
149     pushl    REH_RFRAME(%ebp)
150
151     pushl    %edx
152     pushl    %fs:0x0
153     movl     %esp, %fs:0x0
154
155     // Prepare to call the exception handler
156     pushl    REH_DCONTEXT(%ebp)
157     pushl    REH_CONTEXT(%ebp)
158     pushl    REH_RFRAME(%ebp)
159     pushl    REH_ERECORD(%ebp)
160
161     // Now call the exception handler
162     movl     REH_EROUTINE(%ebp), %eax
163     call    *%eax
164
165         cmpl    $-1, %fs:0x0
166         jne             .reh_stack_looks_ok
167
168         // This should not happen
169         pushl   0
170         pushl   0
171         pushl   0
172         pushl   0
173         call    _RtlAssert@16
174
175 .reh_loop:
176         jmp     .reh_loop
177
178 .reh_stack_looks_ok:
179     movl     %fs:0x0, %esp
180
181     // Return to the 'front-end' for this function
182     popl     %fs:0x0
183     movl     %ebp, %esp
184     popl     %ebp
185     ret
186
187
188 #define REP_ERECORD     0x04
189 #define REP_RFRAME      0x08
190 #define REP_CONTEXT     0x0C
191 #define REP_DCONTEXT    0x10
192
193 // Parameters:
194 //   [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
195 //   [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
196 //   [ESP+0Ch] - PCONTEXT Context
197 //   [ESP+10h] - PVOID DispatcherContext
198 // Registers:
199 //   None
200 // Returns:
201 //   EXCEPTION_DISPOSITION
202 // Notes:
203 //    This exception handler protects the exception handling
204 //    mechanism by detecting nested exceptions.
205 _RtlpExceptionProtector:
206     movl     $ExceptionContinueSearch, %eax
207     movl     REP_ERECORD(%esp), %ecx
208     testl    $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx)
209     jnz      .rep_end
210
211     // Unwinding is not taking place, so return ExceptionNestedException
212
213     // Set DispatcherContext field to the exception registration for the
214     // exception handler that executed when a nested exception occurred
215     movl     REP_DCONTEXT(%esp), %ecx
216     movl     REP_RFRAME(%esp), %eax
217     movl     %eax, (%ecx)
218     movl     $ExceptionNestedException, %eax
219
220 .rep_end:
221     ret
222
223
224 // Parameters:
225 //   [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
226 //   [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
227 //   [ESP+0Ch] - PCONTEXT Context
228 //   [ESP+10h] - PVOID DispatcherContext
229 //   [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler
230 // Registers:
231 //   None
232 // Returns:
233 //   EXCEPTION_DISPOSITION
234 // Notes:
235 //   Front-end
236 _RtlpExecuteHandlerForException:
237     movl     $_RtlpExceptionProtector, %edx
238     jmp      _RtlpExecuteHandler
239
240
241 #define RUP_ERECORD     0x04
242 #define RUP_RFRAME      0x08
243 #define RUP_CONTEXT     0x0C
244 #define RUP_DCONTEXT    0x10
245
246 // Parameters:
247 //   [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
248 //   [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
249 //   [ESP+0Ch] - PCONTEXT Context
250 //   [ESP+10h] - PVOID DispatcherContext
251 // Registers:
252 //   None
253 // Returns:
254 //   EXCEPTION_DISPOSITION
255 // Notes:
256 //    This exception handler protects the exception handling
257 //    mechanism by detecting collided unwinds.
258 _RtlpUnwindProtector:
259     movl     $ExceptionContinueSearch, %eax
260     movl     %ecx, RUP_ERECORD(%esp)
261     testl    $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx)
262     jz       .rup_end
263
264     // Unwinding is taking place, so return ExceptionCollidedUnwind
265
266     movl     RUP_RFRAME(%esp), %ecx
267     movl     RUP_DCONTEXT(%esp), %edx
268
269     // Set DispatcherContext field to the exception registration for the
270     // exception handler that executed when a collision occurred
271     movl     RUP_RFRAME(%ecx), %eax
272     movl     %eax, (%edx)
273     movl     $ExceptionCollidedUnwind, %eax
274
275 .rup_end:
276     ret
277
278
279 // Parameters:
280 //   [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
281 //   [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
282 //   [ESP+0Ch] - PCONTEXT Context
283 //   [ESP+10h] - PVOID DispatcherContext
284 //   [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler
285 // Registers:
286 //   None
287 // Returns:
288 //   EXCEPTION_DISPOSITION
289 _RtlpExecuteHandlerForUnwind:
290     movl     $_RtlpUnwindProtector, %edx
291     jmp      _RtlpExecuteHandler