push 22b3e00525a9a3743634eb8f21ffe1bf98bf885e
[wine/hacks.git] / dlls / ntdll / signal_powerpc.c
blob8b4438a7654265b2ae6594b7bcc79da6dc409c6a
1 /*
2 * PowerPC signal handling routines
4 * Copyright 2002 Marcus Meissner, SuSE Linux AG
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #ifdef __powerpc__
23 #include "config.h"
24 #include "wine/port.h"
26 #include <assert.h>
27 #include <signal.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
35 #ifdef HAVE_SYS_PARAM_H
36 # include <sys/param.h>
37 #endif
38 #ifdef HAVE_SYSCALL_H
39 # include <syscall.h>
40 #else
41 # ifdef HAVE_SYS_SYSCALL_H
42 # include <sys/syscall.h>
43 # endif
44 #endif
46 #ifdef HAVE_SYS_VM86_H
47 # include <sys/vm86.h>
48 #endif
50 #ifdef HAVE_SYS_SIGNAL_H
51 # include <sys/signal.h>
52 #endif
54 #include "ntstatus.h"
55 #define WIN32_NO_STATUS
56 #include "windef.h"
57 #include "winternl.h"
58 #include "wine/library.h"
59 #include "wine/exception.h"
60 #include "ntdll_misc.h"
61 #include "wine/debug.h"
63 WINE_DEFAULT_DEBUG_CHANNEL(seh);
65 static pthread_key_t teb_key;
67 /***********************************************************************
68 * signal context platform-specific definitions
70 #ifdef linux
72 typedef struct ucontext SIGCONTEXT;
74 # define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context )
75 # define HANDLER_CONTEXT (__context)
77 /* All Registers access - only for local access */
78 # define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
81 /* Gpr Registers access */
82 # define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
84 # define IAR_sig(context) REG_sig(nip, context) /* Program counter */
85 # define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
86 # define CTR_sig(context) REG_sig(ctr, context) /* Count register */
88 # define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
89 # define LR_sig(context) REG_sig(link, context) /* Link register */
90 # define CR_sig(context) REG_sig(ccr, context) /* Condition register */
92 /* Float Registers access */
93 # define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
95 # define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
97 /* Exception Registers access */
98 # define DAR_sig(context) REG_sig(dar, context)
99 # define DSISR_sig(context) REG_sig(dsisr, context)
100 # define TRAP_sig(context) REG_sig(trap, context)
102 #endif /* linux */
104 #ifdef __APPLE__
106 # include <sys/ucontext.h>
108 # include <sys/types.h>
109 typedef siginfo_t siginfo;
111 typedef struct ucontext SIGCONTEXT;
114 # define HANDLER_DEF(name) void name( int __signal, siginfo *__siginfo, SIGCONTEXT *__context )
115 # define HANDLER_CONTEXT (__context)
117 /* All Registers access - only for local access */
118 # define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
119 # define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
120 # define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
121 # define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
123 /* Gpr Registers access */
124 # define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
126 # define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
127 # define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
128 # define CTR_sig(context) REG_sig(ctr, context)
130 # define XER_sig(context) REG_sig(xer, context) /* Link register */
131 # define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
132 # define CR_sig(context) REG_sig(cr, context) /* Condition register */
134 /* Float Registers access */
135 # define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
137 # define FPSCR_sig(context) FLOATREG_sig(fpscr, context)
139 /* Exception Registers access */
140 # define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
141 # define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
142 # define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
144 /* Signal defs : Those are undefined on darwin
145 SIGBUS
146 #undef BUS_ADRERR
147 #undef BUS_OBJERR
148 SIGILL
149 #undef ILL_ILLOPN
150 #undef ILL_ILLTRP
151 #undef ILL_ILLADR
152 #undef ILL_COPROC
153 #undef ILL_PRVREG
154 #undef ILL_BADSTK
155 SIGTRAP
156 #undef TRAP_BRKPT
157 #undef TRAP_TRACE
158 SIGFPE
161 #endif /* __APPLE__ */
165 typedef int (*wine_signal_handler)(unsigned int sig);
167 static wine_signal_handler handlers[256];
169 /***********************************************************************
170 * dispatch_signal
172 static inline int dispatch_signal(unsigned int sig)
174 if (handlers[sig] == NULL) return 0;
175 return handlers[sig](sig);
178 /***********************************************************************
179 * save_context
181 * Set the register values from a sigcontext.
183 static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
186 #define C(x) context->Gpr##x = GPR_sig(x,sigcontext)
187 /* Save Gpr registers */
188 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
189 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
190 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
191 C(31);
192 #undef C
194 context->Iar = IAR_sig(sigcontext); /* Program Counter */
195 context->Msr = MSR_sig(sigcontext); /* Machine State Register (Supervisor) */
196 context->Ctr = CTR_sig(sigcontext);
198 context->Xer = XER_sig(sigcontext);
199 context->Lr = LR_sig(sigcontext);
200 context->Cr = CR_sig(sigcontext);
202 /* Saving Exception regs */
203 context->Dar = DAR_sig(sigcontext);
204 context->Dsisr = DSISR_sig(sigcontext);
205 context->Trap = TRAP_sig(sigcontext);
209 /***********************************************************************
210 * restore_context
212 * Build a sigcontext from the register values.
214 static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
217 #define C(x) GPR_sig(x,sigcontext) = context->Gpr##x
218 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
219 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
220 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
221 C(31);
222 #undef C
224 IAR_sig(sigcontext) = context->Iar; /* Program Counter */
225 MSR_sig(sigcontext) = context->Msr; /* Machine State Register (Supervisor) */
226 CTR_sig(sigcontext) = context->Ctr;
228 XER_sig(sigcontext) = context->Xer;
229 LR_sig(sigcontext) = context->Lr;
230 CR_sig(sigcontext) = context->Cr;
232 /* Setting Exception regs */
233 DAR_sig(sigcontext) = context->Dar;
234 DSISR_sig(sigcontext) = context->Dsisr;
235 TRAP_sig(sigcontext) = context->Trap;
239 /***********************************************************************
240 * save_fpu
242 * Set the FPU context from a sigcontext.
244 static inline void save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
246 #define C(x) context->Fpr##x = FLOAT_sig(x,sigcontext)
247 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
248 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
249 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
250 C(31);
251 #undef C
252 context->Fpscr = FPSCR_sig(sigcontext);
256 /***********************************************************************
257 * restore_fpu
259 * Restore the FPU context to a sigcontext.
261 static inline void restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
263 #define C(x) FLOAT_sig(x,sigcontext) = context->Fpr##x
264 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10);
265 C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20);
266 C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30);
267 C(31);
268 #undef C
269 FPSCR_sig(sigcontext) = context->Fpscr;
273 /***********************************************************************
274 * RtlCaptureContext (NTDLL.@)
276 void WINAPI RtlCaptureContext( CONTEXT *context )
278 FIXME("not implemented\n");
279 memset( context, 0, sizeof(*context) );
283 /***********************************************************************
284 * set_cpu_context
286 * Set the new CPU context.
288 void set_cpu_context( const CONTEXT *context )
290 FIXME("not implemented\n");
294 /***********************************************************************
295 * copy_context
297 * Copy a register context according to the flags.
299 void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
301 if (flags & CONTEXT_CONTROL)
303 to->Msr = from->Msr;
304 to->Ctr = from->Ctr;
305 to->Iar = from->Iar;
306 to->Lr = from->Lr;
307 to->Dar = from->Dar;
308 to->Dsisr = from->Dsisr;
309 to->Trap = from->Trap;
311 if (flags & CONTEXT_INTEGER)
313 to->Gpr0 = from->Gpr0;
314 to->Gpr1 = from->Gpr1;
315 to->Gpr2 = from->Gpr2;
316 to->Gpr3 = from->Gpr3;
317 to->Gpr4 = from->Gpr4;
318 to->Gpr5 = from->Gpr5;
319 to->Gpr6 = from->Gpr6;
320 to->Gpr7 = from->Gpr7;
321 to->Gpr8 = from->Gpr8;
322 to->Gpr9 = from->Gpr9;
323 to->Gpr10 = from->Gpr10;
324 to->Gpr11 = from->Gpr11;
325 to->Gpr12 = from->Gpr12;
326 to->Gpr13 = from->Gpr13;
327 to->Gpr14 = from->Gpr14;
328 to->Gpr15 = from->Gpr15;
329 to->Gpr16 = from->Gpr16;
330 to->Gpr17 = from->Gpr17;
331 to->Gpr18 = from->Gpr18;
332 to->Gpr19 = from->Gpr19;
333 to->Gpr20 = from->Gpr20;
334 to->Gpr21 = from->Gpr21;
335 to->Gpr22 = from->Gpr22;
336 to->Gpr23 = from->Gpr23;
337 to->Gpr24 = from->Gpr24;
338 to->Gpr25 = from->Gpr25;
339 to->Gpr26 = from->Gpr26;
340 to->Gpr27 = from->Gpr27;
341 to->Gpr28 = from->Gpr28;
342 to->Gpr29 = from->Gpr29;
343 to->Gpr30 = from->Gpr30;
344 to->Gpr31 = from->Gpr31;
345 to->Xer = from->Xer;
346 to->Cr = from->Cr;
348 if (flags & CONTEXT_FLOATING_POINT)
350 to->Fpr0 = from->Fpr0;
351 to->Fpr1 = from->Fpr1;
352 to->Fpr2 = from->Fpr2;
353 to->Fpr3 = from->Fpr3;
354 to->Fpr4 = from->Fpr4;
355 to->Fpr5 = from->Fpr5;
356 to->Fpr6 = from->Fpr6;
357 to->Fpr7 = from->Fpr7;
358 to->Fpr8 = from->Fpr8;
359 to->Fpr9 = from->Fpr9;
360 to->Fpr10 = from->Fpr10;
361 to->Fpr11 = from->Fpr11;
362 to->Fpr12 = from->Fpr12;
363 to->Fpr13 = from->Fpr13;
364 to->Fpr14 = from->Fpr14;
365 to->Fpr15 = from->Fpr15;
366 to->Fpr16 = from->Fpr16;
367 to->Fpr17 = from->Fpr17;
368 to->Fpr18 = from->Fpr18;
369 to->Fpr19 = from->Fpr19;
370 to->Fpr20 = from->Fpr20;
371 to->Fpr21 = from->Fpr21;
372 to->Fpr22 = from->Fpr22;
373 to->Fpr23 = from->Fpr23;
374 to->Fpr24 = from->Fpr24;
375 to->Fpr25 = from->Fpr25;
376 to->Fpr26 = from->Fpr26;
377 to->Fpr27 = from->Fpr27;
378 to->Fpr28 = from->Fpr28;
379 to->Fpr29 = from->Fpr29;
380 to->Fpr30 = from->Fpr30;
381 to->Fpr31 = from->Fpr31;
382 to->Fpscr = from->Fpscr;
387 /***********************************************************************
388 * context_to_server
390 * Convert a register context to the server format.
392 NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
394 DWORD flags = from->ContextFlags; /* no CPU id? */
396 memset( to, 0, sizeof(*to) );
397 to->cpu = CPU_POWERPC;
399 if (flags & CONTEXT_CONTROL)
401 to->flags |= SERVER_CTX_CONTROL;
402 to->ctl.powerpc_regs.iar = from->Iar;
403 to->ctl.powerpc_regs.msr = from->Msr;
404 to->ctl.powerpc_regs.ctr = from->Ctr;
405 to->ctl.powerpc_regs.lr = from->Lr;
406 to->ctl.powerpc_regs.dar = from->Dar;
407 to->ctl.powerpc_regs.dsisr = from->Dsisr;
408 to->ctl.powerpc_regs.trap = from->Trap;
410 if (flags & CONTEXT_INTEGER)
412 to->flags |= SERVER_CTX_INTEGER;
413 to->integer.powerpc_regs.gpr[0] = from->Gpr0;
414 to->integer.powerpc_regs.gpr[1] = from->Gpr1;
415 to->integer.powerpc_regs.gpr[2] = from->Gpr2;
416 to->integer.powerpc_regs.gpr[3] = from->Gpr3;
417 to->integer.powerpc_regs.gpr[4] = from->Gpr4;
418 to->integer.powerpc_regs.gpr[5] = from->Gpr5;
419 to->integer.powerpc_regs.gpr[6] = from->Gpr6;
420 to->integer.powerpc_regs.gpr[7] = from->Gpr7;
421 to->integer.powerpc_regs.gpr[8] = from->Gpr8;
422 to->integer.powerpc_regs.gpr[9] = from->Gpr9;
423 to->integer.powerpc_regs.gpr[10] = from->Gpr10;
424 to->integer.powerpc_regs.gpr[11] = from->Gpr11;
425 to->integer.powerpc_regs.gpr[12] = from->Gpr12;
426 to->integer.powerpc_regs.gpr[13] = from->Gpr13;
427 to->integer.powerpc_regs.gpr[14] = from->Gpr14;
428 to->integer.powerpc_regs.gpr[15] = from->Gpr15;
429 to->integer.powerpc_regs.gpr[16] = from->Gpr16;
430 to->integer.powerpc_regs.gpr[17] = from->Gpr17;
431 to->integer.powerpc_regs.gpr[18] = from->Gpr18;
432 to->integer.powerpc_regs.gpr[19] = from->Gpr19;
433 to->integer.powerpc_regs.gpr[20] = from->Gpr20;
434 to->integer.powerpc_regs.gpr[21] = from->Gpr21;
435 to->integer.powerpc_regs.gpr[22] = from->Gpr22;
436 to->integer.powerpc_regs.gpr[23] = from->Gpr23;
437 to->integer.powerpc_regs.gpr[24] = from->Gpr24;
438 to->integer.powerpc_regs.gpr[25] = from->Gpr25;
439 to->integer.powerpc_regs.gpr[26] = from->Gpr26;
440 to->integer.powerpc_regs.gpr[27] = from->Gpr27;
441 to->integer.powerpc_regs.gpr[28] = from->Gpr28;
442 to->integer.powerpc_regs.gpr[29] = from->Gpr29;
443 to->integer.powerpc_regs.gpr[30] = from->Gpr30;
444 to->integer.powerpc_regs.gpr[31] = from->Gpr31;
445 to->integer.powerpc_regs.xer = from->Xer;
446 to->integer.powerpc_regs.cr = from->Cr;
448 if (flags & CONTEXT_FLOATING_POINT)
450 to->flags |= SERVER_CTX_FLOATING_POINT;
451 to->fp.powerpc_regs.fpr[0] = from->Fpr0;
452 to->fp.powerpc_regs.fpr[1] = from->Fpr1;
453 to->fp.powerpc_regs.fpr[2] = from->Fpr2;
454 to->fp.powerpc_regs.fpr[3] = from->Fpr3;
455 to->fp.powerpc_regs.fpr[4] = from->Fpr4;
456 to->fp.powerpc_regs.fpr[5] = from->Fpr5;
457 to->fp.powerpc_regs.fpr[6] = from->Fpr6;
458 to->fp.powerpc_regs.fpr[7] = from->Fpr7;
459 to->fp.powerpc_regs.fpr[8] = from->Fpr8;
460 to->fp.powerpc_regs.fpr[9] = from->Fpr9;
461 to->fp.powerpc_regs.fpr[10] = from->Fpr10;
462 to->fp.powerpc_regs.fpr[11] = from->Fpr11;
463 to->fp.powerpc_regs.fpr[12] = from->Fpr12;
464 to->fp.powerpc_regs.fpr[13] = from->Fpr13;
465 to->fp.powerpc_regs.fpr[14] = from->Fpr14;
466 to->fp.powerpc_regs.fpr[15] = from->Fpr15;
467 to->fp.powerpc_regs.fpr[16] = from->Fpr16;
468 to->fp.powerpc_regs.fpr[17] = from->Fpr17;
469 to->fp.powerpc_regs.fpr[18] = from->Fpr18;
470 to->fp.powerpc_regs.fpr[19] = from->Fpr19;
471 to->fp.powerpc_regs.fpr[20] = from->Fpr20;
472 to->fp.powerpc_regs.fpr[21] = from->Fpr21;
473 to->fp.powerpc_regs.fpr[22] = from->Fpr22;
474 to->fp.powerpc_regs.fpr[23] = from->Fpr23;
475 to->fp.powerpc_regs.fpr[24] = from->Fpr24;
476 to->fp.powerpc_regs.fpr[25] = from->Fpr25;
477 to->fp.powerpc_regs.fpr[26] = from->Fpr26;
478 to->fp.powerpc_regs.fpr[27] = from->Fpr27;
479 to->fp.powerpc_regs.fpr[28] = from->Fpr28;
480 to->fp.powerpc_regs.fpr[29] = from->Fpr29;
481 to->fp.powerpc_regs.fpr[30] = from->Fpr30;
482 to->fp.powerpc_regs.fpr[31] = from->Fpr31;
483 to->fp.powerpc_regs.fpscr = from->Fpscr;
485 return STATUS_SUCCESS;
489 /***********************************************************************
490 * context_from_server
492 * Convert a register context from the server format.
494 NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
496 if (from->cpu != CPU_POWERPC) return STATUS_INVALID_PARAMETER;
498 to->ContextFlags = 0; /* no CPU id? */
499 if (from->flags & SERVER_CTX_CONTROL)
501 to->ContextFlags |= CONTEXT_CONTROL;
502 to->Msr = from->ctl.powerpc_regs.msr;
503 to->Ctr = from->ctl.powerpc_regs.ctr;
504 to->Iar = from->ctl.powerpc_regs.iar;
505 to->Lr = from->ctl.powerpc_regs.lr;
506 to->Dar = from->ctl.powerpc_regs.dar;
507 to->Dsisr = from->ctl.powerpc_regs.dsisr;
508 to->Trap = from->ctl.powerpc_regs.trap;
510 if (from->flags & SERVER_CTX_INTEGER)
512 to->ContextFlags |= CONTEXT_INTEGER;
513 to->Gpr0 = from->integer.powerpc_regs.gpr[0];
514 to->Gpr1 = from->integer.powerpc_regs.gpr[1];
515 to->Gpr2 = from->integer.powerpc_regs.gpr[2];
516 to->Gpr3 = from->integer.powerpc_regs.gpr[3];
517 to->Gpr4 = from->integer.powerpc_regs.gpr[4];
518 to->Gpr5 = from->integer.powerpc_regs.gpr[5];
519 to->Gpr6 = from->integer.powerpc_regs.gpr[6];
520 to->Gpr7 = from->integer.powerpc_regs.gpr[7];
521 to->Gpr8 = from->integer.powerpc_regs.gpr[8];
522 to->Gpr9 = from->integer.powerpc_regs.gpr[9];
523 to->Gpr10 = from->integer.powerpc_regs.gpr[10];
524 to->Gpr11 = from->integer.powerpc_regs.gpr[11];
525 to->Gpr12 = from->integer.powerpc_regs.gpr[12];
526 to->Gpr13 = from->integer.powerpc_regs.gpr[13];
527 to->Gpr14 = from->integer.powerpc_regs.gpr[14];
528 to->Gpr15 = from->integer.powerpc_regs.gpr[15];
529 to->Gpr16 = from->integer.powerpc_regs.gpr[16];
530 to->Gpr17 = from->integer.powerpc_regs.gpr[17];
531 to->Gpr18 = from->integer.powerpc_regs.gpr[18];
532 to->Gpr19 = from->integer.powerpc_regs.gpr[19];
533 to->Gpr20 = from->integer.powerpc_regs.gpr[20];
534 to->Gpr21 = from->integer.powerpc_regs.gpr[21];
535 to->Gpr22 = from->integer.powerpc_regs.gpr[22];
536 to->Gpr23 = from->integer.powerpc_regs.gpr[23];
537 to->Gpr24 = from->integer.powerpc_regs.gpr[24];
538 to->Gpr25 = from->integer.powerpc_regs.gpr[25];
539 to->Gpr26 = from->integer.powerpc_regs.gpr[26];
540 to->Gpr27 = from->integer.powerpc_regs.gpr[27];
541 to->Gpr28 = from->integer.powerpc_regs.gpr[28];
542 to->Gpr29 = from->integer.powerpc_regs.gpr[29];
543 to->Gpr30 = from->integer.powerpc_regs.gpr[30];
544 to->Gpr31 = from->integer.powerpc_regs.gpr[31];
545 to->Xer = from->integer.powerpc_regs.xer;
546 to->Cr = from->integer.powerpc_regs.cr;
548 if (from->flags & SERVER_CTX_FLOATING_POINT)
550 to->ContextFlags |= CONTEXT_FLOATING_POINT;
551 to->Fpr0 = from->fp.powerpc_regs.fpr[0];
552 to->Fpr1 = from->fp.powerpc_regs.fpr[1];
553 to->Fpr2 = from->fp.powerpc_regs.fpr[2];
554 to->Fpr3 = from->fp.powerpc_regs.fpr[3];
555 to->Fpr4 = from->fp.powerpc_regs.fpr[4];
556 to->Fpr5 = from->fp.powerpc_regs.fpr[5];
557 to->Fpr6 = from->fp.powerpc_regs.fpr[6];
558 to->Fpr7 = from->fp.powerpc_regs.fpr[7];
559 to->Fpr8 = from->fp.powerpc_regs.fpr[8];
560 to->Fpr9 = from->fp.powerpc_regs.fpr[9];
561 to->Fpr10 = from->fp.powerpc_regs.fpr[10];
562 to->Fpr11 = from->fp.powerpc_regs.fpr[11];
563 to->Fpr12 = from->fp.powerpc_regs.fpr[12];
564 to->Fpr13 = from->fp.powerpc_regs.fpr[13];
565 to->Fpr14 = from->fp.powerpc_regs.fpr[14];
566 to->Fpr15 = from->fp.powerpc_regs.fpr[15];
567 to->Fpr16 = from->fp.powerpc_regs.fpr[16];
568 to->Fpr17 = from->fp.powerpc_regs.fpr[17];
569 to->Fpr18 = from->fp.powerpc_regs.fpr[18];
570 to->Fpr19 = from->fp.powerpc_regs.fpr[19];
571 to->Fpr20 = from->fp.powerpc_regs.fpr[20];
572 to->Fpr21 = from->fp.powerpc_regs.fpr[21];
573 to->Fpr22 = from->fp.powerpc_regs.fpr[22];
574 to->Fpr23 = from->fp.powerpc_regs.fpr[23];
575 to->Fpr24 = from->fp.powerpc_regs.fpr[24];
576 to->Fpr25 = from->fp.powerpc_regs.fpr[25];
577 to->Fpr26 = from->fp.powerpc_regs.fpr[26];
578 to->Fpr27 = from->fp.powerpc_regs.fpr[27];
579 to->Fpr28 = from->fp.powerpc_regs.fpr[28];
580 to->Fpr29 = from->fp.powerpc_regs.fpr[29];
581 to->Fpr30 = from->fp.powerpc_regs.fpr[30];
582 to->Fpr31 = from->fp.powerpc_regs.fpr[31];
583 to->Fpscr = from->fp.powerpc_regs.fpscr;
585 return STATUS_SUCCESS;
589 /**********************************************************************
590 * get_fpu_code
592 * Get the FPU exception code from the FPU status.
594 static inline DWORD get_fpu_code( const CONTEXT *context )
596 DWORD status = context->Fpscr;
598 if (status & 0x01) /* IE */
600 if (status & 0x40) /* SF */
601 return EXCEPTION_FLT_STACK_CHECK;
602 else
603 return EXCEPTION_FLT_INVALID_OPERATION;
605 if (status & 0x02) return EXCEPTION_FLT_DENORMAL_OPERAND; /* DE flag */
606 if (status & 0x04) return EXCEPTION_FLT_DIVIDE_BY_ZERO; /* ZE flag */
607 if (status & 0x08) return EXCEPTION_FLT_OVERFLOW; /* OE flag */
608 if (status & 0x10) return EXCEPTION_FLT_UNDERFLOW; /* UE flag */
609 if (status & 0x20) return EXCEPTION_FLT_INEXACT_RESULT; /* PE flag */
610 return EXCEPTION_FLT_INVALID_OPERATION; /* generic error */
614 /**********************************************************************
615 * call_stack_handlers
617 * Call the stack handlers chain.
619 static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
621 EXCEPTION_POINTERS ptrs;
623 FIXME( "not implemented on PowerPC\n" );
625 /* hack: call unhandled exception filter directly */
626 ptrs.ExceptionRecord = rec;
627 ptrs.ContextRecord = context;
628 unhandled_exception_filter( &ptrs );
629 return STATUS_UNHANDLED_EXCEPTION;
633 /*******************************************************************
634 * raise_exception
636 * Implementation of NtRaiseException.
638 static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
640 NTSTATUS status;
642 if (first_chance)
644 DWORD c;
646 TRACE( "code=%x flags=%x addr=%p ip=%x tid=%04x\n",
647 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
648 context->Iar, GetCurrentThreadId() );
649 for (c = 0; c < rec->NumberParameters; c++)
650 TRACE( " info[%d]=%08lx\n", c, rec->ExceptionInformation[c] );
651 if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
653 if (rec->ExceptionInformation[1] >> 16)
654 MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
655 rec->ExceptionAddress,
656 (char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
657 else
658 MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
659 rec->ExceptionAddress,
660 (char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
662 else
664 /* FIXME: dump context */
667 status = send_debug_event( rec, TRUE, context );
668 if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
669 return STATUS_SUCCESS;
671 if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
672 return STATUS_SUCCESS;
674 if ((status = call_stack_handlers( rec, context )) != STATUS_UNHANDLED_EXCEPTION)
675 return status;
678 /* last chance exception */
680 status = send_debug_event( rec, FALSE, context );
681 if (status != DBG_CONTINUE)
683 if (rec->ExceptionFlags & EH_STACK_INVALID)
684 ERR("Exception frame is not in stack limits => unable to dispatch exception.\n");
685 else if (rec->ExceptionCode == STATUS_NONCONTINUABLE_EXCEPTION)
686 ERR("Process attempted to continue execution after noncontinuable exception.\n");
687 else
688 ERR("Unhandled exception code %x flags %x addr %p\n",
689 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
690 NtTerminateProcess( NtCurrentProcess(), 1 );
692 return STATUS_SUCCESS;
696 /**********************************************************************
697 * do_segv
699 * Implementation of SIGSEGV handler.
701 static void do_segv( CONTEXT *context, int trap, int err, int code, void * addr )
703 EXCEPTION_RECORD rec;
704 NTSTATUS status;
706 rec.ExceptionRecord = NULL;
707 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
708 rec.ExceptionAddress = addr;
709 rec.NumberParameters = 0;
711 switch (trap) {
712 case SIGSEGV:
713 switch ( code & 0xffff ) {
714 case SEGV_MAPERR:
715 case SEGV_ACCERR:
716 rec.NumberParameters = 2;
717 rec.ExceptionInformation[0] = 0; /* FIXME ? */
718 rec.ExceptionInformation[1] = (ULONG_PTR)addr;
719 if (!(rec.ExceptionCode = virtual_handle_fault(addr, rec.ExceptionInformation[0])))
720 return;
721 break;
722 default:FIXME("Unhandled SIGSEGV/%x\n",code);
723 break;
725 break;
726 case SIGBUS:
727 switch ( code & 0xffff ) {
728 case BUS_ADRALN:
729 rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
730 break;
731 #ifdef BUS_ADRERR
732 case BUS_ADRERR:
733 #endif
734 #ifdef BUS_OBJERR
735 case BUS_OBJERR:
736 /* FIXME: correct for all cases ? */
737 rec.NumberParameters = 2;
738 rec.ExceptionInformation[0] = 0; /* FIXME ? */
739 rec.ExceptionInformation[1] = (ULONG_PTR)addr;
740 if (!(rec.ExceptionCode = virtual_handle_fault(addr, rec.ExceptionInformation[0])))
741 return;
742 break;
743 #endif
744 default:FIXME("Unhandled SIGBUS/%x\n",code);
745 break;
747 break;
748 case SIGILL:
749 switch ( code & 0xffff ) {
750 case ILL_ILLOPC: /* illegal opcode */
751 #ifdef ILL_ILLOPN
752 case ILL_ILLOPN: /* illegal operand */
753 #endif
754 #ifdef ILL_ILLADR
755 case ILL_ILLADR: /* illegal addressing mode */
756 #endif
757 #ifdef ILL_ILLTRP
758 case ILL_ILLTRP: /* illegal trap */
759 #endif
760 #ifdef ILL_COPROC
761 case ILL_COPROC: /* coprocessor error */
762 #endif
763 rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
764 break;
765 case ILL_PRVOPC: /* privileged opcode */
766 #ifdef ILL_PRVREG
767 case ILL_PRVREG: /* privileged register */
768 #endif
769 rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
770 break;
771 #ifdef ILL_BADSTK
772 case ILL_BADSTK: /* internal stack error */
773 rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
774 break;
775 #endif
776 default:FIXME("Unhandled SIGILL/%x\n", code);
777 break;
779 break;
781 status = raise_exception( &rec, context, TRUE );
782 if (status) raise_status( status, &rec );
785 /**********************************************************************
786 * do_trap
788 * Implementation of SIGTRAP handler.
790 static void do_trap( CONTEXT *context, int code, void * addr )
792 EXCEPTION_RECORD rec;
793 NTSTATUS status;
795 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
796 rec.ExceptionRecord = NULL;
797 rec.ExceptionAddress = addr;
798 rec.NumberParameters = 0;
800 /* FIXME: check if we might need to modify PC */
801 switch (code & 0xffff) {
802 #ifdef TRAP_BRKPT
803 case TRAP_BRKPT:
804 rec.ExceptionCode = EXCEPTION_BREAKPOINT;
805 break;
806 #endif
807 #ifdef TRAP_TRACE
808 case TRAP_TRACE:
809 rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
810 break;
811 #endif
812 default:FIXME("Unhandled SIGTRAP/%x\n", code);
813 break;
815 status = raise_exception( &rec, context, TRUE );
816 if (status) raise_status( status, &rec );
819 /**********************************************************************
820 * do_trap
822 * Implementation of SIGFPE handler.
824 static void do_fpe( CONTEXT *context, int code, void * addr )
826 EXCEPTION_RECORD rec;
827 NTSTATUS status;
829 switch ( code & 0xffff ) {
830 #ifdef FPE_FLTSUB
831 case FPE_FLTSUB:
832 rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
833 break;
834 #endif
835 #ifdef FPE_INTDIV
836 case FPE_INTDIV:
837 rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
838 break;
839 #endif
840 #ifdef FPE_INTOVF
841 case FPE_INTOVF:
842 rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
843 break;
844 #endif
845 #ifdef FPE_FLTDIV
846 case FPE_FLTDIV:
847 rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
848 break;
849 #endif
850 #ifdef FPE_FLTOVF
851 case FPE_FLTOVF:
852 rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
853 break;
854 #endif
855 #ifdef FPE_FLTUND
856 case FPE_FLTUND:
857 rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
858 break;
859 #endif
860 #ifdef FPE_FLTRES
861 case FPE_FLTRES:
862 rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
863 break;
864 #endif
865 #ifdef FPE_FLTINV
866 case FPE_FLTINV:
867 #endif
868 default:
869 rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
870 break;
872 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
873 rec.ExceptionRecord = NULL;
874 rec.ExceptionAddress = addr;
875 rec.NumberParameters = 0;
876 status = raise_exception( &rec, context, TRUE );
877 if (status) raise_status( status, &rec );
880 /**********************************************************************
881 * segv_handler
883 * Handler for SIGSEGV and related errors.
885 static HANDLER_DEF(segv_handler)
887 CONTEXT context;
888 save_context( &context, HANDLER_CONTEXT );
889 do_segv( &context, __siginfo->si_signo, __siginfo->si_errno, __siginfo->si_code, __siginfo->si_addr );
890 restore_context( &context, HANDLER_CONTEXT );
893 /**********************************************************************
894 * trap_handler
896 * Handler for SIGTRAP.
898 static HANDLER_DEF(trap_handler)
900 CONTEXT context;
901 save_context( &context, HANDLER_CONTEXT );
902 do_trap( &context, __siginfo->si_code, __siginfo->si_addr );
903 restore_context( &context, HANDLER_CONTEXT );
906 /**********************************************************************
907 * fpe_handler
909 * Handler for SIGFPE.
911 static HANDLER_DEF(fpe_handler)
913 CONTEXT context;
914 save_fpu( &context, HANDLER_CONTEXT );
915 save_context( &context, HANDLER_CONTEXT );
916 do_fpe( &context, __siginfo->si_code, __siginfo->si_addr );
917 restore_context( &context, HANDLER_CONTEXT );
918 restore_fpu( &context, HANDLER_CONTEXT );
921 /**********************************************************************
922 * int_handler
924 * Handler for SIGINT.
926 static HANDLER_DEF(int_handler)
928 if (!dispatch_signal(SIGINT))
930 EXCEPTION_RECORD rec;
931 CONTEXT context;
932 NTSTATUS status;
934 save_context( &context, HANDLER_CONTEXT );
935 rec.ExceptionCode = CONTROL_C_EXIT;
936 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
937 rec.ExceptionRecord = NULL;
938 rec.ExceptionAddress = (LPVOID)context.Iar;
939 rec.NumberParameters = 0;
940 status = raise_exception( &rec, &context, TRUE );
941 if (status) raise_status( status, &rec );
942 restore_context( &context, HANDLER_CONTEXT );
947 /**********************************************************************
948 * abrt_handler
950 * Handler for SIGABRT.
952 static HANDLER_DEF(abrt_handler)
954 EXCEPTION_RECORD rec;
955 CONTEXT context;
956 NTSTATUS status;
958 save_context( &context, HANDLER_CONTEXT );
959 rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
960 rec.ExceptionFlags = EH_NONCONTINUABLE;
961 rec.ExceptionRecord = NULL;
962 rec.ExceptionAddress = (LPVOID)context.Iar;
963 rec.NumberParameters = 0;
964 status = raise_exception( &rec, &context, TRUE );
965 if (status) raise_status( status, &rec );
966 restore_context( &context, HANDLER_CONTEXT );
970 /**********************************************************************
971 * quit_handler
973 * Handler for SIGQUIT.
975 static HANDLER_DEF(quit_handler)
977 abort_thread(0);
981 /**********************************************************************
982 * usr1_handler
984 * Handler for SIGUSR1, used to signal a thread that it got suspended.
986 static HANDLER_DEF(usr1_handler)
988 CONTEXT context;
990 save_context( &context, HANDLER_CONTEXT );
991 wait_suspend( &context );
992 restore_context( &context, HANDLER_CONTEXT );
996 /**********************************************************************
997 * get_signal_stack_total_size
999 * Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
1000 * Must be a power of two.
1002 size_t get_signal_stack_total_size(void)
1004 assert( sizeof(TEB) <= getpagesize() );
1005 return getpagesize(); /* this is just for the TEB, we don't need a signal stack */
1009 /***********************************************************************
1010 * set_handler
1012 * Set a signal handler
1014 static int set_handler( int sig, void (*func)() )
1016 struct sigaction sig_act;
1018 sig_act.sa_sigaction = func;
1019 sig_act.sa_mask = server_block_set;
1020 sig_act.sa_flags = SA_RESTART | SA_SIGINFO;
1021 return sigaction( sig, &sig_act, NULL );
1025 /***********************************************************************
1026 * __wine_set_signal_handler (NTDLL.@)
1028 int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
1030 if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
1031 if (handlers[sig] != NULL) return -2;
1032 handlers[sig] = wsh;
1033 return 0;
1037 /**********************************************************************
1038 * signal_init_thread
1040 void signal_init_thread( TEB *teb )
1042 static int init_done;
1044 if (!init_done)
1046 pthread_key_create( &teb_key, NULL );
1047 init_done = 1;
1049 pthread_setspecific( teb_key, teb );
1053 /**********************************************************************
1054 * signal_init_process
1056 void signal_init_process(void)
1058 if (set_handler( SIGINT, (void (*)())int_handler ) == -1) goto error;
1059 if (set_handler( SIGFPE, (void (*)())fpe_handler ) == -1) goto error;
1060 if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error;
1061 if (set_handler( SIGILL, (void (*)())segv_handler ) == -1) goto error;
1062 if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
1063 if (set_handler( SIGQUIT, (void (*)())quit_handler ) == -1) goto error;
1064 if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
1065 #ifdef SIGBUS
1066 if (set_handler( SIGBUS, (void (*)())segv_handler ) == -1) goto error;
1067 #endif
1068 #ifdef SIGTRAP
1069 if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
1070 #endif
1071 return;
1073 error:
1074 perror("sigaction");
1075 exit(1);
1079 /**********************************************************************
1080 * __wine_enter_vm86 (NTDLL.@)
1082 void __wine_enter_vm86( CONTEXT *context )
1084 MESSAGE("vm86 mode not supported on this platform\n");
1087 /***********************************************************************
1088 * RtlUnwind (NTDLL.@)
1090 void WINAPI RtlUnwind( PVOID pEndFrame, PVOID targetIp, PEXCEPTION_RECORD pRecord, PVOID retval )
1092 FIXME( "Not implemented on PowerPC\n" );
1095 /*******************************************************************
1096 * NtRaiseException (NTDLL.@)
1098 NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
1100 NTSTATUS status = raise_exception( rec, context, first_chance );
1101 if (status == STATUS_SUCCESS) NtSetContextThread( GetCurrentThread(), context );
1102 return status;
1105 /***********************************************************************
1106 * RtlRaiseException (NTDLL.@)
1108 void WINAPI RtlRaiseException( EXCEPTION_RECORD *rec )
1110 CONTEXT context;
1111 NTSTATUS status;
1113 RtlCaptureContext( &context );
1114 rec->ExceptionAddress = (void *)context.Iar;
1115 status = raise_exception( rec, &context, TRUE );
1116 if (status) raise_status( status, rec );
1119 /**********************************************************************
1120 * DbgBreakPoint (NTDLL.@)
1122 void WINAPI DbgBreakPoint(void)
1124 kill(getpid(), SIGTRAP);
1127 /**********************************************************************
1128 * DbgUserBreakPoint (NTDLL.@)
1130 void WINAPI DbgUserBreakPoint(void)
1132 kill(getpid(), SIGTRAP);
1135 /**********************************************************************
1136 * NtCurrentTeb (NTDLL.@)
1138 TEB * WINAPI NtCurrentTeb(void)
1140 return pthread_getspecific( teb_key );
1143 #endif /* __powerpc__ */