- beginning of vertex matrix blending using extensions (currently
[wine] / dlls / ntdll / signal_i386.c
1 /*
2  * i386 signal handling routines
3  *
4  * Copyright 1999 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #ifdef __i386__
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <errno.h>
27 #include <signal.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33
34 #ifdef HAVE_SYS_PARAM_H
35 # include <sys/param.h>
36 #endif
37 #ifdef HAVE_SYSCALL_H
38 # include <syscall.h>
39 #else
40 # ifdef HAVE_SYS_SYSCALL_H
41 #  include <sys/syscall.h>
42 # endif
43 #endif
44
45 #ifdef HAVE_SYS_VM86_H
46 # include <sys/vm86.h>
47 #endif
48
49 #ifdef HAVE_SYS_SIGNAL_H
50 # include <sys/signal.h>
51 #endif
52
53 #include "windef.h"
54 #include "winternl.h"
55 #include "wine/library.h"
56
57 #include "selectors.h"
58
59 /***********************************************************************
60  * signal context platform-specific definitions
61  */
62
63 #ifdef linux
64 typedef struct
65 {
66     unsigned short sc_gs, __gsh;
67     unsigned short sc_fs, __fsh;
68     unsigned short sc_es, __esh;
69     unsigned short sc_ds, __dsh;
70     unsigned long sc_edi;
71     unsigned long sc_esi;
72     unsigned long sc_ebp;
73     unsigned long sc_esp;
74     unsigned long sc_ebx;
75     unsigned long sc_edx;
76     unsigned long sc_ecx;
77     unsigned long sc_eax;
78     unsigned long sc_trapno;
79     unsigned long sc_err;
80     unsigned long sc_eip;
81     unsigned short sc_cs, __csh;
82     unsigned long sc_eflags;
83     unsigned long esp_at_signal;
84     unsigned short sc_ss, __ssh;
85     unsigned long i387;
86     unsigned long oldmask;
87     unsigned long cr2;
88 } SIGCONTEXT;
89
90 #define HANDLER_DEF(name) void name( int __signal, SIGCONTEXT __context )
91 #define HANDLER_CONTEXT (&__context)
92
93 /* this is the sigaction structure from the Linux 2.1.20 kernel.  */
94 struct kernel_sigaction
95 {
96     void (*ksa_handler)();
97     unsigned long ksa_mask;
98     unsigned long ksa_flags;
99     void *ksa_restorer;
100 };
101
102 /* Similar to the sigaction function in libc, except it leaves alone the
103    restorer field, which is used to specify the signal stack address */
104 static inline int wine_sigaction( int sig, struct kernel_sigaction *new,
105                                   struct kernel_sigaction *old )
106 {
107     __asm__ __volatile__( "pushl %%ebx\n\t"
108                           "movl %2,%%ebx\n\t"
109                           "int $0x80\n\t"
110                           "popl %%ebx"
111                           : "=a" (sig)
112                           : "0" (SYS_sigaction), "r" (sig), "c" (new), "d" (old) );
113     if (sig>=0) return 0;
114     errno = -sig;
115     return -1;
116 }
117
118 #ifdef HAVE_SIGALTSTACK
119 /* direct syscall for sigaltstack to work around glibc 2.0 brain-damage */
120 static inline int wine_sigaltstack( const struct sigaltstack *new,
121                                     struct sigaltstack *old )
122 {
123     int ret;
124     __asm__ __volatile__( "pushl %%ebx\n\t"
125                           "movl %2,%%ebx\n\t"
126                           "int $0x80\n\t"
127                           "popl %%ebx"
128                           : "=a" (ret)
129                           : "0" (SYS_sigaltstack), "r" (new), "c" (old) );
130     if (ret >= 0) return 0;
131     errno = -ret;
132     return -1;
133 }
134 #endif
135
136 #define VM86_EAX 0 /* the %eax value while vm86_enter is executing */
137
138 int vm86_enter( void **vm86_ptr );
139 void vm86_return(void);
140 void vm86_return_end(void);
141 __ASM_GLOBAL_FUNC(vm86_enter,
142                   "pushl %ebp\n\t"
143                   "movl %esp, %ebp\n\t"
144                   "movl $166,%eax\n\t"  /*SYS_vm86*/
145                   "movl 8(%ebp),%ecx\n\t" /* vm86_ptr */
146                   "movl (%ecx),%ecx\n\t"
147                   "pushl %ebx\n\t"
148                   "movl $1,%ebx\n\t"    /*VM86_ENTER*/
149                   "pushl %ecx\n\t"      /* put vm86plus_struct ptr somewhere we can find it */
150                   "pushl %fs\n\t"
151                   "int $0x80\n"
152                   ".globl " __ASM_NAME("vm86_return") "\n\t"
153                   __ASM_FUNC("vm86_return") "\n"
154                   __ASM_NAME("vm86_return") ":\n\t"
155                   "popl %fs\n\t"
156                   "popl %ecx\n\t"
157                   "popl %ebx\n\t"
158                   "popl %ebp\n\t"
159                   "testl %eax,%eax\n\t"
160                   "jl 0f\n\t"
161                   "cmpb $0,%al\n\t" /* VM86_SIGNAL */
162                   "je " __ASM_NAME("vm86_enter") "\n\t"
163                   "0:\n\t"
164                   "movl 4(%esp),%ecx\n\t"  /* vm86_ptr */
165                   "movl $0,(%ecx)\n\t"
166                   ".globl " __ASM_NAME("vm86_return_end") "\n\t"
167                   __ASM_FUNC("vm86_return_end") "\n"
168                   __ASM_NAME("vm86_return_end") ":\n\t"
169                   "ret" );
170
171 #ifdef HAVE_SYS_VM86_H
172 # define __HAVE_VM86
173 #endif
174
175 #endif  /* linux */
176
177 #ifdef BSDI
178
179 #define EAX_sig(context)     ((context)->tf_eax)
180 #define EBX_sig(context)     ((context)->tf_ebx)
181 #define ECX_sig(context)     ((context)->tf_ecx)
182 #define EDX_sig(context)     ((context)->tf_edx)
183 #define ESI_sig(context)     ((context)->tf_esi)
184 #define EDI_sig(context)     ((context)->tf_edi)
185 #define EBP_sig(context)     ((context)->tf_ebp)
186
187 #define CS_sig(context)      ((context)->tf_cs)
188 #define DS_sig(context)      ((context)->tf_ds)
189 #define ES_sig(context)      ((context)->tf_es)
190 #define SS_sig(context)      ((context)->tf_ss)
191
192 #include <machine/frame.h>
193 typedef struct trapframe SIGCONTEXT;
194
195 #define HANDLER_DEF(name) void name( int __signal, int code, SIGCONTEXT *__context )
196 #define HANDLER_CONTEXT __context
197
198 #define EFL_sig(context)     ((context)->tf_eflags)
199
200 #define EIP_sig(context)     (*((unsigned long*)&(context)->tf_eip))
201 #define ESP_sig(context)     (*((unsigned long*)&(context)->tf_esp))
202
203 #endif /* bsdi */
204
205 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
206
207 typedef struct sigcontext SIGCONTEXT;
208
209 #define HANDLER_DEF(name) void name( int __signal, int code, SIGCONTEXT *__context )
210 #define HANDLER_CONTEXT __context
211
212 #endif  /* FreeBSD */
213
214 #if defined(__svr4__) || defined(_SCO_DS) || defined(__sun)
215
216 #ifdef _SCO_DS
217 #include <sys/regset.h>
218 #endif
219 /* Solaris kludge */
220 #undef ERR
221 #include <sys/ucontext.h>
222 #undef ERR
223 typedef struct ucontext SIGCONTEXT;
224
225 #define HANDLER_DEF(name) void name( int __signal, void *__siginfo, SIGCONTEXT *__context )
226 #define HANDLER_CONTEXT __context
227
228 #endif  /* svr4 || SCO_DS */
229
230 #ifdef __EMX__
231
232 typedef struct
233 {
234     unsigned long ContextFlags;
235     FLOATING_SAVE_AREA sc_float;
236     unsigned long sc_gs;
237     unsigned long sc_fs;
238     unsigned long sc_es;
239     unsigned long sc_ds;
240     unsigned long sc_edi;
241     unsigned long sc_esi;
242     unsigned long sc_eax;
243     unsigned long sc_ebx;
244     unsigned long sc_ecx;
245     unsigned long sc_edx;
246     unsigned long sc_ebp;
247     unsigned long sc_eip;
248     unsigned long sc_cs;
249     unsigned long sc_eflags;
250     unsigned long sc_esp;
251     unsigned long sc_ss;
252 } SIGCONTEXT;
253
254 #endif  /* __EMX__ */
255
256 #ifdef __CYGWIN__
257
258 /* FIXME: This section is just here so it can compile, it's most likely
259  * completely wrong. */
260
261 typedef struct
262 {
263     unsigned short sc_gs, __gsh;
264     unsigned short sc_fs, __fsh;
265     unsigned short sc_es, __esh;
266     unsigned short sc_ds, __dsh;
267     unsigned long sc_edi;
268     unsigned long sc_esi;
269     unsigned long sc_ebp;
270     unsigned long sc_esp;
271     unsigned long sc_ebx;
272     unsigned long sc_edx;
273     unsigned long sc_ecx;
274     unsigned long sc_eax;
275     unsigned long sc_trapno;
276     unsigned long sc_err;
277     unsigned long sc_eip;
278     unsigned short sc_cs, __csh;
279     unsigned long sc_eflags;
280     unsigned long esp_at_signal;
281     unsigned short sc_ss, __ssh;
282     unsigned long i387;
283     unsigned long oldmask;
284     unsigned long cr2;
285 } SIGCONTEXT;
286
287 #define HANDLER_DEF(name) void name( int __signal, SIGCONTEXT __context )
288 #define HANDLER_CONTEXT (&__context)
289
290 #endif /* __CYGWIN__ */
291
292 #if defined(linux) || defined(__NetBSD__) || defined(__FreeBSD__) ||\
293     defined(__OpenBSD__) || defined(__EMX__) || defined(__CYGWIN__)
294
295 #define EAX_sig(context)     ((context)->sc_eax)
296 #define EBX_sig(context)     ((context)->sc_ebx)
297 #define ECX_sig(context)     ((context)->sc_ecx)
298 #define EDX_sig(context)     ((context)->sc_edx)
299 #define ESI_sig(context)     ((context)->sc_esi)
300 #define EDI_sig(context)     ((context)->sc_edi)
301 #define EBP_sig(context)     ((context)->sc_ebp)
302
303 #define CS_sig(context)      ((context)->sc_cs)
304 #define DS_sig(context)      ((context)->sc_ds)
305 #define ES_sig(context)      ((context)->sc_es)
306 #define SS_sig(context)      ((context)->sc_ss)
307
308 /* FS and GS are now in the sigcontext struct of FreeBSD, but not
309  * saved by the exception handling. duh.
310  * Actually they are in -current (have been for a while), and that
311  * patch now finally has been MFC'd to -stable too (Nov 15 1999).
312  * If you're running a system from the -stable branch older than that,
313  * like a 3.3-RELEASE, grab the patch from the ports tree:
314  * ftp://ftp.freebsd.org/pub/FreeBSD/FreeBSD-current/ports/emulators/wine/files/patch-3.3-sys-fsgs
315  * (If its not yet there when you look, go here:
316  * http://www.jelal.kn-bremen.de/freebsd/ports/emulators/wine/files/ )
317  */
318 #ifdef __FreeBSD__
319 #define FS_sig(context)      ((context)->sc_fs)
320 #define GS_sig(context)      ((context)->sc_gs)
321 #endif
322
323 #ifdef linux
324 #define FS_sig(context)      ((context)->sc_fs)
325 #define GS_sig(context)      ((context)->sc_gs)
326 #define CR2_sig(context)     ((context)->cr2)
327 #define TRAP_sig(context)    ((context)->sc_trapno)
328 #define ERROR_sig(context)   ((context)->sc_err)
329 #define FPU_sig(context)     ((FLOATING_SAVE_AREA*)((context)->i387))
330 #endif
331
332 #ifndef __FreeBSD__
333 #define EFL_sig(context)     ((context)->sc_eflags)
334 #else
335 #define EFL_sig(context)     ((context)->sc_efl)
336 /* FreeBSD, see i386/i386/traps.c::trap_pfault va->err kludge  */
337 #define CR2_sig(context)     ((context)->sc_err)
338 #define TRAP_sig(context)    ((context)->sc_trapno)
339 #endif
340
341 #define EIP_sig(context)     (*((unsigned long*)&(context)->sc_eip))
342 #define ESP_sig(context)     (*((unsigned long*)&(context)->sc_esp))
343
344 #endif  /* linux || __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
345
346 #if defined(__svr4__) || defined(_SCO_DS) || defined(__sun)
347
348 #ifdef _SCO_DS
349 #define gregs regs
350 #endif
351
352 #define EAX_sig(context)     ((context)->uc_mcontext.gregs[EAX])
353 #define EBX_sig(context)     ((context)->uc_mcontext.gregs[EBX])
354 #define ECX_sig(context)     ((context)->uc_mcontext.gregs[ECX])
355 #define EDX_sig(context)     ((context)->uc_mcontext.gregs[EDX])
356 #define ESI_sig(context)     ((context)->uc_mcontext.gregs[ESI])
357 #define EDI_sig(context)     ((context)->uc_mcontext.gregs[EDI])
358 #define EBP_sig(context)     ((context)->uc_mcontext.gregs[EBP])
359
360 #define CS_sig(context)      ((context)->uc_mcontext.gregs[CS])
361 #define DS_sig(context)      ((context)->uc_mcontext.gregs[DS])
362 #define ES_sig(context)      ((context)->uc_mcontext.gregs[ES])
363 #define SS_sig(context)      ((context)->uc_mcontext.gregs[SS])
364
365 #define FS_sig(context)      ((context)->uc_mcontext.gregs[FS])
366 #define GS_sig(context)      ((context)->uc_mcontext.gregs[GS])
367
368 #define EFL_sig(context)     ((context)->uc_mcontext.gregs[EFL])
369
370 #define EIP_sig(context)     ((context)->uc_mcontext.gregs[EIP])
371 #ifdef R_ESP
372 #define ESP_sig(context)     ((context)->uc_mcontext.gregs[R_ESP])
373 #else
374 #define ESP_sig(context)     ((context)->uc_mcontext.gregs[ESP])
375 #endif
376 #ifdef TRAPNO
377 #define TRAP_sig(context)     ((context)->uc_mcontext.gregs[TRAPNO])
378 #endif
379
380 #endif  /* svr4 || SCO_DS */
381
382
383 /* exception code definitions (already defined by FreeBSD/NetBSD) */
384 #if !defined(__FreeBSD__) && !defined(__NetBSD__) /* FIXME: other BSDs? */
385 #define T_DIVIDE        0   /* Division by zero exception */
386 #define T_TRCTRAP       1   /* Single-step exception */
387 #define T_NMI           2   /* NMI interrupt */
388 #define T_BPTFLT        3   /* Breakpoint exception */
389 #define T_OFLOW         4   /* Overflow exception */
390 #define T_BOUND         5   /* Bound range exception */
391 #define T_PRIVINFLT     6   /* Invalid opcode exception */
392 #define T_DNA           7   /* Device not available exception */
393 #define T_DOUBLEFLT     8   /* Double fault exception */
394 #define T_FPOPFLT       9   /* Coprocessor segment overrun */
395 #define T_TSSFLT        10  /* Invalid TSS exception */
396 #define T_SEGNPFLT      11  /* Segment not present exception */
397 #define T_STKFLT        12  /* Stack fault */
398 #define T_PROTFLT       13  /* General protection fault */
399 #define T_PAGEFLT       14  /* Page fault */
400 #define T_RESERVED      15  /* Unknown exception */
401 #define T_ARITHTRAP     16  /* Floating point exception */
402 #define T_ALIGNFLT      17  /* Alignment check exception */
403 #define T_MCHK          18  /* Machine check exception */
404 #define T_CACHEFLT      19  /* Cache flush exception */
405 #endif
406 #if defined(__NetBSD__)
407 #define T_MCHK          19  /* Machine check exception */
408 #endif
409
410 #define T_UNKNOWN     (-1)  /* Unknown fault (TRAP_sig not defined) */
411
412 #include "wine/exception.h"
413 #include "stackframe.h"
414 #include "global.h"
415 #include "miscemu.h"
416 #include "syslevel.h"
417 #include "wine/debug.h"
418
419 WINE_DEFAULT_DEBUG_CHANNEL(seh);
420
421 typedef int (*wine_signal_handler)(unsigned int sig);
422
423 static wine_signal_handler handlers[256];
424
425 static sigset_t all_sigs;
426
427 extern void WINAPI EXC_RtlRaiseException( PEXCEPTION_RECORD, PCONTEXT );
428
429 /***********************************************************************
430  *           dispatch_signal
431  */
432 inline static int dispatch_signal(unsigned int sig)
433 {
434     if (handlers[sig] == NULL) return 0;
435     return handlers[sig](sig);
436 }
437
438
439 /***********************************************************************
440  *           get_trap_code
441  *
442  * Get the trap code for a signal.
443  */
444 static inline int get_trap_code( const SIGCONTEXT *sigcontext )
445 {
446 #ifdef TRAP_sig
447     return TRAP_sig(sigcontext);
448 #else
449     return T_UNKNOWN;  /* unknown trap code */
450 #endif
451 }
452
453 /***********************************************************************
454  *           get_error_code
455  *
456  * Get the error code for a signal.
457  */
458 static inline int get_error_code( const SIGCONTEXT *sigcontext )
459 {
460 #ifdef ERROR_sig
461     return ERROR_sig(sigcontext);
462 #else
463     return 0;
464 #endif
465 }
466
467 /***********************************************************************
468  *           get_cr2_value
469  *
470  * Get the CR2 value for a signal.
471  */
472 static inline void *get_cr2_value( const SIGCONTEXT *sigcontext )
473 {
474 #ifdef CR2_sig
475     return (void *)CR2_sig(sigcontext);
476 #else
477     return NULL;
478 #endif
479 }
480
481
482 #ifdef __HAVE_VM86
483 /***********************************************************************
484  *           save_vm86_context
485  *
486  * Set the register values from a vm86 structure.
487  */
488 static void save_vm86_context( CONTEXT *context, const struct vm86plus_struct *vm86 )
489 {
490     context->Eax    = vm86->regs.eax;
491     context->Ebx    = vm86->regs.ebx;
492     context->Ecx    = vm86->regs.ecx;
493     context->Edx    = vm86->regs.edx;
494     context->Esi    = vm86->regs.esi;
495     context->Edi    = vm86->regs.edi;
496     context->Esp    = vm86->regs.esp;
497     context->Ebp    = vm86->regs.ebp;
498     context->Eip    = vm86->regs.eip;
499     context->SegCs  = vm86->regs.cs;
500     context->SegDs  = vm86->regs.ds;
501     context->SegEs  = vm86->regs.es;
502     context->SegFs  = vm86->regs.fs;
503     context->SegGs  = vm86->regs.gs;
504     context->SegSs  = vm86->regs.ss;
505     context->EFlags = vm86->regs.eflags;
506 }
507
508
509 /***********************************************************************
510  *           restore_vm86_context
511  *
512  * Build a vm86 structure from the register values.
513  */
514 static void restore_vm86_context( const CONTEXT *context, struct vm86plus_struct *vm86 )
515 {
516     vm86->regs.eax    = context->Eax;
517     vm86->regs.ebx    = context->Ebx;
518     vm86->regs.ecx    = context->Ecx;
519     vm86->regs.edx    = context->Edx;
520     vm86->regs.esi    = context->Esi;
521     vm86->regs.edi    = context->Edi;
522     vm86->regs.esp    = context->Esp;
523     vm86->regs.ebp    = context->Ebp;
524     vm86->regs.eip    = context->Eip;
525     vm86->regs.cs     = context->SegCs;
526     vm86->regs.ds     = context->SegDs;
527     vm86->regs.es     = context->SegEs;
528     vm86->regs.fs     = context->SegFs;
529     vm86->regs.gs     = context->SegGs;
530     vm86->regs.ss     = context->SegSs;
531     vm86->regs.eflags = context->EFlags;
532 }
533 #endif /* __HAVE_VM86 */
534
535
536 /***********************************************************************
537  *           save_context
538  *
539  * Set the register values from a sigcontext.
540  */
541 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
542 {
543     WORD fs;
544     /* get %fs at time of the fault */
545 #ifdef FS_sig
546     fs = FS_sig(sigcontext);
547 #else
548     fs = wine_get_fs();
549 #endif
550     context->SegFs = fs;
551
552     /* now restore a proper %fs for the fault handler */
553     if (!IS_SELECTOR_SYSTEM(CS_sig(sigcontext)) ||
554         !IS_SELECTOR_SYSTEM(SS_sig(sigcontext)))  /* 16-bit mode */
555     {
556         /*
557          * Win16 or DOS protected mode. Note that during switch 
558          * from 16-bit mode to linear mode, CS may be set to system 
559          * segment before FS is restored. Fortunately, in this case 
560          * SS is still non-system segment. This is why both CS and SS
561          * are checked.
562          */
563         fs = SYSLEVEL_Win16CurrentTeb;
564     }
565 #ifdef __HAVE_VM86
566     else if ((void *)EIP_sig(sigcontext) == vm86_return)  /* vm86 mode */
567     {
568         /* fetch the saved %fs on the stack */
569         fs = *(unsigned int *)ESP_sig(sigcontext);
570         if (EAX_sig(sigcontext) == VM86_EAX) {
571             struct vm86plus_struct *vm86;
572             wine_set_fs(fs);
573             /* retrieve pointer to vm86plus struct that was stored in vm86_enter
574              * (but we could also get if from teb->vm86_ptr) */
575             vm86 = *(struct vm86plus_struct **)(ESP_sig(sigcontext) + sizeof(int));
576             /* get context from vm86 struct */
577             save_vm86_context( context, vm86 );
578             return;
579         }
580     }
581 #endif  /* __HAVE_VM86 */
582
583     wine_set_fs(fs);
584
585     context->Eax    = EAX_sig(sigcontext);
586     context->Ebx    = EBX_sig(sigcontext);
587     context->Ecx    = ECX_sig(sigcontext);
588     context->Edx    = EDX_sig(sigcontext);
589     context->Esi    = ESI_sig(sigcontext);
590     context->Edi    = EDI_sig(sigcontext);
591     context->Ebp    = EBP_sig(sigcontext);
592     context->EFlags = EFL_sig(sigcontext);
593     context->Eip    = EIP_sig(sigcontext);
594     context->Esp    = ESP_sig(sigcontext);
595     context->SegCs  = LOWORD(CS_sig(sigcontext));
596     context->SegDs  = LOWORD(DS_sig(sigcontext));
597     context->SegEs  = LOWORD(ES_sig(sigcontext));
598     context->SegSs  = LOWORD(SS_sig(sigcontext));
599 #ifdef GS_sig
600     context->SegGs  = LOWORD(GS_sig(sigcontext));
601 #else
602     context->SegGs  = wine_get_gs();
603 #endif
604 }
605
606
607 /***********************************************************************
608  *           restore_context
609  *
610  * Build a sigcontext from the register values.
611  */
612 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
613 {
614 #ifdef __HAVE_VM86
615     /* check if exception occurred in vm86 mode */
616     if ((void *)EIP_sig(sigcontext) == vm86_return &&
617         IS_SELECTOR_SYSTEM(CS_sig(sigcontext)) &&
618         EAX_sig(sigcontext) == VM86_EAX)
619     {
620         /* retrieve pointer to vm86plus struct that was stored in vm86_enter
621          * (but we could also get it from teb->vm86_ptr) */
622         struct vm86plus_struct *vm86 = *(struct vm86plus_struct **)(ESP_sig(sigcontext) + sizeof(int));
623         restore_vm86_context( context, vm86 );
624         return;
625     }
626 #endif /* __HAVE_VM86 */
627
628     EAX_sig(sigcontext) = context->Eax;
629     EBX_sig(sigcontext) = context->Ebx;
630     ECX_sig(sigcontext) = context->Ecx;
631     EDX_sig(sigcontext) = context->Edx;
632     ESI_sig(sigcontext) = context->Esi;
633     EDI_sig(sigcontext) = context->Edi;
634     EBP_sig(sigcontext) = context->Ebp;
635     EFL_sig(sigcontext) = context->EFlags;
636     EIP_sig(sigcontext) = context->Eip;
637     ESP_sig(sigcontext) = context->Esp;
638     CS_sig(sigcontext)  = context->SegCs;
639     DS_sig(sigcontext)  = context->SegDs;
640     ES_sig(sigcontext)  = context->SegEs;
641     SS_sig(sigcontext)  = context->SegSs;
642 #ifdef FS_sig
643     FS_sig(sigcontext)  = context->SegFs;
644 #else
645     wine_set_fs( context->SegFs );
646 #endif
647 #ifdef GS_sig
648     GS_sig(sigcontext)  = context->SegGs;
649 #else
650     wine_set_gs( context->SegGs );
651 #endif
652 }
653
654
655 /***********************************************************************
656  *           save_fpu
657  *
658  * Set the FPU context from a sigcontext.
659  */
660 inline static void save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
661 {
662 #ifdef FPU_sig
663     if (FPU_sig(sigcontext))
664     {
665         context->FloatSave = *FPU_sig(sigcontext);
666         return;
667     }
668 #endif  /* FPU_sig */
669 #ifdef __GNUC__
670     __asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) );
671 #endif  /* __GNUC__ */
672 }
673
674
675 /***********************************************************************
676  *           restore_fpu
677  *
678  * Restore the FPU context to a sigcontext.
679  */
680 inline static void restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
681 {
682     /* reset the current interrupt status */
683     context->FloatSave.StatusWord &= context->FloatSave.ControlWord | 0xffffff80;
684 #ifdef FPU_sig
685     if (FPU_sig(sigcontext))
686     {
687         *FPU_sig(sigcontext) = context->FloatSave;
688         return;
689     }
690 #endif  /* FPU_sig */
691 #ifdef __GNUC__
692     /* avoid nested exceptions */
693     __asm__ __volatile__( "frstor %0; fwait" : : "m" (context->FloatSave) );
694 #endif  /* __GNUC__ */
695 }
696
697
698 /**********************************************************************
699  *              get_fpu_code
700  *
701  * Get the FPU exception code from the FPU status.
702  */
703 static inline DWORD get_fpu_code( const CONTEXT *context )
704 {
705     DWORD status = context->FloatSave.StatusWord;
706
707     if (status & 0x01)  /* IE */
708     {
709         if (status & 0x40)  /* SF */
710             return EXCEPTION_FLT_STACK_CHECK;
711         else
712             return EXCEPTION_FLT_INVALID_OPERATION;
713     }
714     if (status & 0x02) return EXCEPTION_FLT_DENORMAL_OPERAND;  /* DE flag */
715     if (status & 0x04) return EXCEPTION_FLT_DIVIDE_BY_ZERO;    /* ZE flag */
716     if (status & 0x08) return EXCEPTION_FLT_OVERFLOW;          /* OE flag */
717     if (status & 0x10) return EXCEPTION_FLT_UNDERFLOW;         /* UE flag */
718     if (status & 0x20) return EXCEPTION_FLT_INEXACT_RESULT;    /* PE flag */
719     return EXCEPTION_FLT_INVALID_OPERATION;  /* generic error */
720 }
721
722
723 /***********************************************************************
724  *           SIGNAL_Unblock
725  *
726  * Unblock signals. Called from EXC_RtlRaiseException.
727  */
728 void SIGNAL_Unblock( void )
729 {
730     sigprocmask( SIG_UNBLOCK, &all_sigs, NULL );
731 }
732
733
734 /**********************************************************************
735  *              do_segv
736  *
737  * Implementation of SIGSEGV handler.
738  */
739 static void do_segv( CONTEXT *context, int trap_code, void *cr2, int err_code )
740 {
741     EXCEPTION_RECORD rec;
742     DWORD page_fault_code = EXCEPTION_ACCESS_VIOLATION;
743
744 #ifdef CR2_sig
745     /* we want the page-fault case to be fast */
746     if (trap_code == T_PAGEFLT)
747         if (!(page_fault_code = VIRTUAL_HandleFault( cr2 ))) return;
748 #endif
749
750     rec.ExceptionRecord  = NULL;
751     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
752     rec.ExceptionAddress = (LPVOID)context->Eip;
753     rec.NumberParameters = 0;
754
755     switch(trap_code)
756     {
757     case T_OFLOW:   /* Overflow exception */
758         rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
759         break;
760     case T_BOUND:   /* Bound range exception */
761         rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
762         break;
763     case T_PRIVINFLT:   /* Invalid opcode exception */
764         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
765         break;
766     case T_STKFLT:  /* Stack fault */
767         rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
768         break;
769     case T_SEGNPFLT:  /* Segment not present exception */
770     case T_PROTFLT:   /* General protection fault */
771     case T_UNKNOWN:   /* Unknown fault code */
772         if (INSTR_EmulateInstruction( context )) return;
773         rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
774         break;
775     case T_PAGEFLT:  /* Page fault */
776 #ifdef CR2_sig
777         rec.NumberParameters = 2;
778         rec.ExceptionInformation[0] = (err_code & 2) != 0;
779         rec.ExceptionInformation[1] = (DWORD)cr2;
780 #endif /* CR2_sig */
781         rec.ExceptionCode = page_fault_code;
782         break;
783     case T_ALIGNFLT:  /* Alignment check exception */
784         /* FIXME: pass through exception handler first? */
785         if (context->EFlags & 0x00040000)
786         {
787             /* Disable AC flag, return */
788             context->EFlags &= ~0x00040000;
789             return;
790         }
791         rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
792         break;
793     default:
794         ERR( "Got unexpected trap %d\n", trap_code );
795         /* fall through */
796     case T_NMI:       /* NMI interrupt */
797     case T_DNA:       /* Device not available exception */
798     case T_DOUBLEFLT: /* Double fault exception */
799     case T_TSSFLT:    /* Invalid TSS exception */
800     case T_RESERVED:  /* Unknown exception */
801     case T_MCHK:      /* Machine check exception */
802 #ifdef T_CACHEFLT
803     case T_CACHEFLT:  /* Cache flush exception */
804 #endif
805         rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
806         break;
807     }
808     EXC_RtlRaiseException( &rec, context );
809 }
810
811
812 /**********************************************************************
813  *              do_trap
814  *
815  * Implementation of SIGTRAP handler.
816  */
817 static void do_trap( CONTEXT *context, int trap_code )
818 {
819     EXCEPTION_RECORD rec;
820
821     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
822     rec.ExceptionRecord  = NULL;
823     rec.ExceptionAddress = (LPVOID)context->Eip;
824     rec.NumberParameters = 0;
825
826     switch(trap_code)
827     {
828     case T_TRCTRAP:  /* Single-step exception */
829         if (context->EFlags & 0x100)
830         {
831             rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
832             context->EFlags &= ~0x100;  /* clear single-step flag */
833         }
834         else
835         {
836             /* likely we get this because of a kill(SIGTRAP) on ourself,
837              * so send a bp exception instead of a single step exception
838              */
839             TRACE("Spurious single step trap => breakpoint simulation\n");
840             rec.ExceptionCode = EXCEPTION_BREAKPOINT;
841         }
842         break;
843     case T_BPTFLT:   /* Breakpoint exception */
844         rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1;  /* back up over the int3 instruction */
845         /* fall through */
846     default:
847         rec.ExceptionCode = EXCEPTION_BREAKPOINT;
848         break;
849     }
850     EXC_RtlRaiseException( &rec, context );
851 }
852
853
854 /**********************************************************************
855  *              do_fpe
856  *
857  * Implementation of SIGFPE handler
858  */
859 static void do_fpe( CONTEXT *context, int trap_code )
860 {
861     EXCEPTION_RECORD rec;
862
863     switch(trap_code)
864     {
865     case T_DIVIDE:   /* Division by zero exception */
866         rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
867         break;
868     case T_FPOPFLT:   /* Coprocessor segment overrun */
869         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
870         break;
871     case T_ARITHTRAP:  /* Floating point exception */
872     case T_UNKNOWN:    /* Unknown fault code */
873         rec.ExceptionCode = get_fpu_code( context );
874         break;
875     default:
876         ERR( "Got unexpected trap %d\n", trap_code );
877         rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
878         break;
879     }
880     rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
881     rec.ExceptionRecord  = NULL;
882     rec.ExceptionAddress = (LPVOID)context->Eip;
883     rec.NumberParameters = 0;
884     EXC_RtlRaiseException( &rec, context );
885 }
886
887
888 #ifdef __HAVE_VM86
889 /**********************************************************************
890  *              set_vm86_pend
891  *
892  * Handler for SIGUSR2, which we use to set the vm86 pending flag.
893  */
894 static void set_vm86_pend( CONTEXT *context )
895 {
896     EXCEPTION_RECORD rec;
897     TEB *teb = NtCurrentTeb();
898     struct vm86plus_struct *vm86 = (struct vm86plus_struct*)(teb->vm86_ptr);
899
900     rec.ExceptionCode           = EXCEPTION_VM86_STI;
901     rec.ExceptionFlags          = EXCEPTION_CONTINUABLE;
902     rec.ExceptionRecord         = NULL;
903     rec.NumberParameters        = 1;
904     rec.ExceptionInformation[0] = 0;
905
906     /* __wine_enter_vm86() merges the vm86_pending flag in safely */
907     teb->vm86_pending |= VIP_MASK;
908     /* see if we were in VM86 mode */
909     if (context->EFlags & 0x00020000)
910     {
911         /* seems so, also set flag in signal context */
912         if (context->EFlags & VIP_MASK) return;
913         context->EFlags |= VIP_MASK;
914         vm86->regs.eflags |= VIP_MASK; /* no exception recursion */
915         if (context->EFlags & VIF_MASK) {
916             /* VIF is set, throw exception */
917             teb->vm86_pending = 0;
918             teb->vm86_ptr = NULL;
919             rec.ExceptionAddress = (LPVOID)context->Eip;
920             EXC_RtlRaiseException( &rec, context );
921             teb->vm86_ptr = vm86;
922         }
923     }
924     else if (vm86)
925     {
926         /* not in VM86, but possibly setting up for it */
927         if (vm86->regs.eflags & VIP_MASK) return;
928         vm86->regs.eflags |= VIP_MASK;
929         if (((char*)context->Eip >= (char*)vm86_return) &&
930             ((char*)context->Eip <= (char*)vm86_return_end) &&
931             (VM86_TYPE(context->Eax) != VM86_SIGNAL)) {
932             /* exiting from VM86, can't throw */
933             return;
934         }
935         if (vm86->regs.eflags & VIF_MASK) {
936             /* VIF is set, throw exception */
937             CONTEXT vcontext;
938             teb->vm86_pending = 0;
939             teb->vm86_ptr = NULL;
940             save_vm86_context( &vcontext, vm86 );
941             rec.ExceptionAddress = (LPVOID)vcontext.Eip;
942             EXC_RtlRaiseException( &rec, &vcontext );
943             teb->vm86_ptr = vm86;
944             restore_vm86_context( &vcontext, vm86 );
945         }
946     }
947 }
948
949
950 /**********************************************************************
951  *              usr2_handler
952  *
953  * Handler for SIGUSR2.
954  * We use it to signal that the running __wine_enter_vm86() should
955  * immediately set VIP_MASK, causing pending events to be handled
956  * as early as possible.
957  */
958 static HANDLER_DEF(usr2_handler)
959 {
960     CONTEXT context;
961
962     save_context( &context, HANDLER_CONTEXT );
963     set_vm86_pend( &context );
964     restore_context( &context, HANDLER_CONTEXT );
965 }
966
967
968 /**********************************************************************
969  *              alrm_handler
970  *
971  * Handler for SIGALRM.
972  * Increases the alarm counter and sets the vm86 pending flag.
973  */
974 static HANDLER_DEF(alrm_handler)
975 {
976     CONTEXT context;
977
978     save_context( &context, HANDLER_CONTEXT );
979     NtCurrentTeb()->alarms++;
980     set_vm86_pend( &context );
981     restore_context( &context, HANDLER_CONTEXT );
982 }
983 #endif /* __HAVE_VM86 */
984
985
986 /**********************************************************************
987  *              segv_handler
988  *
989  * Handler for SIGSEGV and related errors.
990  */
991 static HANDLER_DEF(segv_handler)
992 {
993     CONTEXT context;
994     save_context( &context, HANDLER_CONTEXT );
995     do_segv( &context, get_trap_code(HANDLER_CONTEXT),
996              get_cr2_value(HANDLER_CONTEXT), get_error_code(HANDLER_CONTEXT) );
997     restore_context( &context, HANDLER_CONTEXT );
998 }
999
1000
1001 /**********************************************************************
1002  *              trap_handler
1003  *
1004  * Handler for SIGTRAP.
1005  */
1006 static HANDLER_DEF(trap_handler)
1007 {
1008     CONTEXT context;
1009     save_context( &context, HANDLER_CONTEXT );
1010     do_trap( &context, get_trap_code(HANDLER_CONTEXT) );
1011     restore_context( &context, HANDLER_CONTEXT );
1012 }
1013
1014
1015 /**********************************************************************
1016  *              fpe_handler
1017  *
1018  * Handler for SIGFPE.
1019  */
1020 static HANDLER_DEF(fpe_handler)
1021 {
1022     CONTEXT context;
1023     save_fpu( &context, HANDLER_CONTEXT );
1024     save_context( &context, HANDLER_CONTEXT );
1025     do_fpe( &context, get_trap_code(HANDLER_CONTEXT) );
1026     restore_context( &context, HANDLER_CONTEXT );
1027     restore_fpu( &context, HANDLER_CONTEXT );
1028 }
1029
1030
1031 /**********************************************************************
1032  *              int_handler
1033  *
1034  * Handler for SIGINT.
1035  */
1036 static HANDLER_DEF(int_handler)
1037 {
1038     if (!dispatch_signal(SIGINT))
1039     {
1040         EXCEPTION_RECORD rec;
1041         CONTEXT context;
1042
1043         save_context( &context, HANDLER_CONTEXT );
1044         rec.ExceptionCode    = CONTROL_C_EXIT;
1045         rec.ExceptionFlags   = EXCEPTION_CONTINUABLE;
1046         rec.ExceptionRecord  = NULL;
1047         rec.ExceptionAddress = (LPVOID)context.Eip;
1048         rec.NumberParameters = 0;
1049         EXC_RtlRaiseException( &rec, &context );
1050         restore_context( &context, HANDLER_CONTEXT );
1051     }
1052 }
1053
1054 /**********************************************************************
1055  *              abrt_handler
1056  *
1057  * Handler for SIGABRT.
1058  */
1059 static HANDLER_DEF(abrt_handler)
1060 {
1061     EXCEPTION_RECORD rec;
1062     CONTEXT context;
1063
1064     save_context( &context, HANDLER_CONTEXT );
1065     rec.ExceptionCode    = EXCEPTION_WINE_ASSERTION;
1066     rec.ExceptionFlags   = EH_NONCONTINUABLE;
1067     rec.ExceptionRecord  = NULL;
1068     rec.ExceptionAddress = (LPVOID)context.Eip;
1069     rec.NumberParameters = 0;
1070     EXC_RtlRaiseException( &rec, &context ); /* Should never return.. */
1071     restore_context( &context, HANDLER_CONTEXT );
1072 }
1073
1074
1075 /***********************************************************************
1076  *           set_handler
1077  *
1078  * Set a signal handler
1079  */
1080 static int set_handler( int sig, int have_sigaltstack, void (*func)() )
1081 {
1082     struct sigaction sig_act;
1083
1084 #ifdef linux
1085     if (!have_sigaltstack && NtCurrentTeb()->signal_stack)
1086     {
1087         struct kernel_sigaction sig_act;
1088         sig_act.ksa_handler = func;
1089         sig_act.ksa_flags   = SA_RESTART;
1090         sig_act.ksa_mask    = (1 << (SIGINT-1)) |
1091                               (1 << (SIGUSR2-1)) |
1092                               (1 << (SIGALRM-1));
1093         /* point to the top of the stack */
1094         sig_act.ksa_restorer = (char *)NtCurrentTeb()->signal_stack + SIGNAL_STACK_SIZE;
1095         return wine_sigaction( sig, &sig_act, NULL );
1096     }
1097 #endif  /* linux */
1098     sig_act.sa_handler = func;
1099     sigemptyset( &sig_act.sa_mask );
1100     sigaddset( &sig_act.sa_mask, SIGINT );
1101     sigaddset( &sig_act.sa_mask, SIGUSR2 );
1102     sigaddset( &sig_act.sa_mask, SIGALRM );
1103
1104 #ifdef linux
1105     sig_act.sa_flags = SA_RESTART;
1106 #elif defined (__svr4__) || defined(_SCO_DS)
1107     sig_act.sa_flags = SA_SIGINFO | SA_RESTART;
1108 #else
1109     sig_act.sa_flags = 0;
1110 #endif
1111
1112 #ifdef SA_ONSTACK
1113     if (have_sigaltstack) sig_act.sa_flags |= SA_ONSTACK;
1114 #endif
1115     return sigaction( sig, &sig_act, NULL );
1116 }
1117
1118
1119 /***********************************************************************
1120  *           __wine_set_signal_handler   (NTDLL.@)
1121  */
1122 int __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
1123 {
1124     if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
1125     if (handlers[sig] != NULL) return -2;
1126     handlers[sig] = wsh;
1127     return 0;
1128 }
1129
1130
1131 /**********************************************************************
1132  *              SIGNAL_Init
1133  */
1134 BOOL SIGNAL_Init(void)
1135 {
1136     int have_sigaltstack = 0;
1137
1138 #ifdef HAVE_SIGALTSTACK
1139     struct sigaltstack ss;
1140     if ((ss.ss_sp = NtCurrentTeb()->signal_stack))
1141     {
1142         ss.ss_size  = SIGNAL_STACK_SIZE;
1143         ss.ss_flags = 0;
1144         if (!sigaltstack(&ss, NULL)) have_sigaltstack = 1;
1145 #ifdef linux
1146         /* sigaltstack may fail because the kernel is too old, or
1147            because glibc is brain-dead. In the latter case a
1148            direct system call should succeed. */
1149         else if (!wine_sigaltstack(&ss, NULL)) have_sigaltstack = 1;
1150 #endif  /* linux */
1151     }
1152 #endif  /* HAVE_SIGALTSTACK */
1153
1154     sigfillset( &all_sigs );
1155
1156     if (set_handler( SIGINT,  have_sigaltstack, (void (*)())int_handler ) == -1) goto error;
1157     if (set_handler( SIGFPE,  have_sigaltstack, (void (*)())fpe_handler ) == -1) goto error;
1158     if (set_handler( SIGSEGV, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
1159     if (set_handler( SIGILL,  have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
1160     if (set_handler( SIGABRT, have_sigaltstack, (void (*)())abrt_handler ) == -1) goto error;
1161 #ifdef SIGBUS
1162     if (set_handler( SIGBUS,  have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
1163 #endif
1164 #ifdef SIGTRAP
1165     if (set_handler( SIGTRAP, have_sigaltstack, (void (*)())trap_handler ) == -1) goto error;
1166 #endif
1167
1168 #ifdef __HAVE_VM86
1169     if (set_handler( SIGALRM, have_sigaltstack, (void (*)())alrm_handler ) == -1) goto error;
1170     if (set_handler( SIGUSR2, have_sigaltstack, (void (*)())usr2_handler ) == -1) goto error;
1171 #endif
1172
1173     return TRUE;
1174
1175  error:
1176     perror("sigaction");
1177     return FALSE;
1178 }
1179
1180
1181 /**********************************************************************
1182  *              SIGNAL_Reset
1183  */
1184 void SIGNAL_Reset(void)
1185 {
1186     sigset_t block_set;
1187
1188     /* block the async signals */
1189     sigemptyset( &block_set );
1190     sigaddset( &block_set, SIGALRM );
1191     sigaddset( &block_set, SIGIO );
1192     sigaddset( &block_set, SIGHUP );
1193     sigaddset( &block_set, SIGUSR2 );
1194     sigprocmask( SIG_BLOCK, &block_set, NULL );
1195
1196     /* restore default handlers */
1197     signal( SIGINT, SIG_DFL );
1198     signal( SIGFPE, SIG_DFL );
1199     signal( SIGSEGV, SIG_DFL );
1200     signal( SIGILL, SIG_DFL );
1201 #ifdef SIGBUS
1202     signal( SIGBUS, SIG_DFL );
1203 #endif
1204 #ifdef SIGTRAP
1205     signal( SIGTRAP, SIG_DFL );
1206 #endif
1207 }
1208
1209
1210 #ifdef __HAVE_VM86
1211 /**********************************************************************
1212  *              __wine_enter_vm86   (NTDLL.@)
1213  *
1214  * Enter vm86 mode with the specified register context.
1215  */
1216 void __wine_enter_vm86( CONTEXT *context )
1217 {
1218     EXCEPTION_RECORD rec;
1219     TEB *teb = NtCurrentTeb();
1220     int res;
1221     struct vm86plus_struct vm86;
1222
1223     memset( &vm86, 0, sizeof(vm86) );
1224     for (;;)
1225     {
1226         restore_vm86_context( context, &vm86 );
1227         /* Linux doesn't preserve pending flag (VIP_MASK) on return,
1228          * so save it on entry, just in case */
1229         teb->vm86_pending |= (context->EFlags & VIP_MASK);
1230         /* Work around race conditions with signal handler
1231          * (avoiding sigprocmask for performance reasons) */
1232         teb->vm86_ptr = &vm86;
1233         vm86.regs.eflags |= teb->vm86_pending;
1234         /* Check for VIF|VIP here, since vm86_enter doesn't */
1235         if ((vm86.regs.eflags & (VIF_MASK|VIP_MASK)) == (VIF_MASK|VIP_MASK)) {
1236             teb->vm86_ptr = NULL;
1237             teb->vm86_pending = 0;
1238             context->EFlags |= VIP_MASK;
1239             rec.ExceptionCode = EXCEPTION_VM86_STI;
1240             rec.ExceptionInformation[0] = 0;
1241             goto cancel_vm86;
1242         }
1243
1244         do
1245         {
1246             res = vm86_enter( &teb->vm86_ptr ); /* uses and clears teb->vm86_ptr */
1247             if (res < 0)
1248             {
1249                 errno = -res;
1250                 return;
1251             }
1252         } while (VM86_TYPE(res) == VM86_SIGNAL);
1253
1254         save_vm86_context( context, &vm86 );
1255         context->EFlags |= teb->vm86_pending;
1256
1257         switch(VM86_TYPE(res))
1258         {
1259         case VM86_UNKNOWN: /* unhandled GP fault - IO-instruction or similar */
1260             do_segv( context, T_PROTFLT, 0, 0 );
1261             continue;
1262         case VM86_TRAP: /* return due to DOS-debugger request */
1263             do_trap( context, VM86_ARG(res) );
1264             continue;
1265         case VM86_INTx: /* int3/int x instruction (ARG = x) */
1266             rec.ExceptionCode = EXCEPTION_VM86_INTx;
1267             break;
1268         case VM86_STI: /* sti/popf/iret instruction enabled virtual interrupts */
1269             teb->vm86_pending = 0;
1270             rec.ExceptionCode = EXCEPTION_VM86_STI;
1271             break;
1272         case VM86_PICRETURN: /* return due to pending PIC request */
1273             rec.ExceptionCode = EXCEPTION_VM86_PICRETURN;
1274             break;
1275         default:
1276             ERR( "unhandled result from vm86 mode %x\n", res );
1277             continue;
1278         }
1279         rec.ExceptionInformation[0] = VM86_ARG(res);
1280 cancel_vm86:
1281         rec.ExceptionFlags          = EXCEPTION_CONTINUABLE;
1282         rec.ExceptionRecord         = NULL;
1283         rec.ExceptionAddress        = (LPVOID)context->Eip;
1284         rec.NumberParameters        = 1;
1285         EXC_RtlRaiseException( &rec, context );
1286     }
1287 }
1288
1289 #else /* __HAVE_VM86 */
1290 /**********************************************************************
1291  *              __wine_enter_vm86   (NTDLL.@)
1292  */
1293 void __wine_enter_vm86( CONTEXT *context )
1294 {
1295     MESSAGE("vm86 mode not supported on this platform\n");
1296 }
1297 #endif /* __HAVE_VM86 */
1298
1299 /**********************************************************************
1300  *              DbgBreakPoint   (NTDLL.@)
1301  */
1302 __ASM_GLOBAL_FUNC( DbgBreakPoint, "int $3; ret");
1303
1304 /**********************************************************************
1305  *              DbgUserBreakPoint   (NTDLL.@)
1306  */
1307 __ASM_GLOBAL_FUNC( DbgUserBreakPoint, "int $3; ret");
1308
1309 #endif  /* __i386__ */