Here is a revision of the last patch I submitted for dlls/ntdll/signal_powerpc.c (not commited). Last patch broke linux ppc support, so I add more #ifdef *_sig to check if we can use specific register like Float or exception registers, which are not defined for the linux target.
ChangeLog: - Save more registers (exception, float...) if they are defined - Add Mac OS X Signal support
Thanks ;)
Pierre
Index: dlls/ntdll/signal_powerpc.c =================================================================== RCS file: /home/wine/wine/dlls/ntdll/signal_powerpc.c,v retrieving revision 1.13 diff -u -r1.13 signal_powerpc.c --- dlls/ntdll/signal_powerpc.c 4 May 2003 02:25:07 -0000 1.13 +++ dlls/ntdll/signal_powerpc.c 7 May 2003 18:26:09 -0000 @@ -65,11 +65,102 @@ /*********************************************************************** * signal context platform-specific definitions */ +#ifdef linux +# warning Please define registers for your platform linux ppc some are missing typedef struct ucontext SIGCONTEXT; -#define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context ) -#define HANDLER_CONTEXT (__context) +# define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context ) +# define HANDLER_CONTEXT (__context) + +/* All Registers access - only for local access */ +# define REG_sig(reg_name, context) (context)->uc_mcontext.regs->reg_name + + +/* Gpr Registers access */ +# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context) + +# define IAR_sig(context) REG_sig(nip, context) /* Programm counter */ +# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */ +# define CTR_sig(context) REG_sig(ctr, context) /* Count register */ + +# define XER_sig(context) #error XER_sig not defined on your platform /* Link register */ +# define LR_sig(context) #error LR_sig not defined on your platform /* User's integer exception register */ +# define CR_sig(context) #error CR_sig not defined on your platform /* Condition register */ + +/* Float Registers access */ +# define FLOAT_sig(reg_num, context) #error FLOAT_sig not defined on your platform /* Float registers */ + +# define FPSCR_sig(reg_num, context) #error FPSCR_sig not defined on your platform /* Float registers */ + +/* Exception Registers access */ +# define DAR_sig(context) #error DAR_sig not defined on your platform +# define DSISR_sig(context) #error DSISR_sig not defined on your platform +# define TRAP_sig(context) #error TRAP_sig not defined on your platform + +#endif /* linux */ + +#ifdef __darwin__ + +# include <sys/ucontext.h> + +# include <sys/types.h> +# include <signal.h> +typedef siginfo_t siginfo; + +typedef struct ucontext SIGCONTEXT; + + +# define HANDLER_DEF(name) void name( int __signal, siginfo *__siginfo, SIGCONTEXT *__context ) +# define HANDLER_CONTEXT (__context) + +/* All Registers access - only for local access */ +# define REG_sig(reg_name, context) (context)->uc_mcontext->ss.reg_name +# define FLOATREG_sig(reg_name, context) (context)->uc_mcontext->fs.reg_name +# define EXCEPREG_sig(reg_name, context) (context)->uc_mcontext->es.reg_name +# define VECREG_sig(reg_name, context) (context)->uc_mcontext->vs.reg_name + +/* Gpr Registers access */ +# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context) + +# define IAR_sig(context) REG_sig(srr0, context) /* Programm counter */ +# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */ +# define CTR_sig(context) REG_sig(ctr, context) + +# define XER_sig(context) REG_sig(xer, context) /* Link register */ +# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */ +# define CR_sig(context) REG_sig(cr, context) /* Condition register */ + +/* Float Registers access */ +# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context) + +# define FPSCR_sig(context) (double)( FLOATREG_sig(fpscr, context) ) + +/* Exception Registers access */ +# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */ +# define DSISR_sig(context) EXCEPREG_sig(dsisr, context) +# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */ + +/* Signal defs : Those are undefined on darwin +SIGBUS +#undef BUS_ADRERR +#undef BUS_OBJERR +SIGILL +#undef ILL_ILLOPN +#undef ILL_ILLTRP +#undef ILL_ILLADR +#undef ILL_COPROC +#undef ILL_PRVREG +#undef ILL_BADSTK +SIGTRAP +#undef TRAP_BRKPT +#undef TRAP_TRACE +SIGFPE +*/ + +#endif /* __darwin__ */ + + typedef int (*wine_signal_handler)(unsigned int sig); @@ -93,30 +184,27 @@ */ static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext ) { -#define CX(x,y) context->x = sigcontext->uc_mcontext.regs->y -#define C(x) CX(Gpr##x,gpr[x]) + +#define C(x) context->Gpr##x = GPR_sig(x,sigcontext) + /* Save Gpr registers */ C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20); C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30); C(31); +#undef C - CX(Iar,nip); - CX(Msr,msr); - CX(Ctr,ctr); -#undef CX - /* FIXME: fp regs? */ - - /* FIXME: missing pt_regs ... - unsigned long link; - unsigned long xer; - unsigned long ccr; - unsigned long mq; - - unsigned long trap; - unsigned long dar; - unsigned long dsisr; - - */ + context->Iar = IAR_sig(sigcontext); /* Program Counter */ + context->Msr = MSR_sig(sigcontext); /* Machine State Register (Supervisor) */ + context->Ctr = CTR_sig(sigcontext); + + context->Xer = XER_sig(sigcontext); + context->Lr = LR_sig(sigcontext); + context->Cr = CR_sig(sigcontext); + + /* Saving Exception regs */ + context->Dar = DAR_sig(sigcontext); + context->Dsisr = DSISR_sig(sigcontext); + context->Trap = TRAP_sig(sigcontext); } @@ -127,16 +215,26 @@ */ static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext ) { -#define CX(x,y) sigcontext->uc_mcontext.regs->y = context->x + +#define C(x) GPR_sig(x,sigcontext) = context->Gpr##x C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20); C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30); C(31); +#undef C - CX(Iar,nip); - CX(Msr,msr); - CX(Ctr,ctr); -#undef CX + IAR_sig(sigcontext) = context->Iar; /* Program Counter */ + MSR_sig(sigcontext) = context->Msr; /* Machine State Register (Supervisor) */ + CTR_sig(sigcontext) = context->Ctr; + + XER_sig(sigcontext) = context->Xer; + LR_sig(sigcontext) = context->Lr; + CR_sig(sigcontext) = context->Cr; + + /* Setting Exception regs */ + DAR_sig(sigcontext) = context->Dar; + DSISR_sig(sigcontext) = context->Dsisr; + TRAP_sig(sigcontext) = context->Trap; } @@ -147,7 +245,13 @@ */ inline static void save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext ) { - /* FIXME? */ +#define C(x) context->Fpr##x = FLOAT_sig(x,sigcontext) + C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); + C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20); + C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30); + C(31); +#undef C + context->Fpscr = FPSCR_sig(sigcontext); } @@ -158,7 +262,13 @@ */ inline static void restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext ) { - /* FIXME? */ +#define C(x) FLOAT_sig(x,sigcontext) = context->Fpr##x + C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); + C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20); + C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30); + C(31); +#undef C + FPSCR_sig(sigcontext) = context->Fpscr; } @@ -169,7 +279,7 @@ */ static inline DWORD get_fpu_code( const CONTEXT *context ) { - DWORD status = 0 /* FIXME */; + DWORD status = context->Fpscr; if (status & 0x01) /* IE */ { @@ -186,164 +296,227 @@ return EXCEPTION_FLT_INVALID_OPERATION; /* generic error */ } - /********************************************************************** - * segv_handler + * do_segv * - * Handler for SIGSEGV and related errors. + * Implementation of SIGSEGV handler. */ -static HANDLER_DEF(segv_handler) +static void do_segv( CONTEXT *context, int trap, int err, int code, void * addr ) { - CONTEXT context; EXCEPTION_RECORD rec; DWORD page_fault_code = EXCEPTION_ACCESS_VIOLATION; - save_context( &context, HANDLER_CONTEXT ); - rec.ExceptionRecord = NULL; rec.ExceptionFlags = EXCEPTION_CONTINUABLE; - rec.ExceptionAddress = (LPVOID)HANDLER_CONTEXT->uc_mcontext.regs->nip; + rec.ExceptionAddress = addr; rec.NumberParameters = 0; - switch (__siginfo->si_signo) { + + switch (trap) { case SIGSEGV: - switch ( __siginfo->si_code & 0xffff ) { + switch ( code & 0xffff ) { case SEGV_MAPERR: case SEGV_ACCERR: rec.NumberParameters = 2; rec.ExceptionInformation[0] = 0; /* FIXME ? */ - rec.ExceptionInformation[1] = (DWORD)__siginfo->si_addr; - if (!(page_fault_code=VIRTUAL_HandleFault(__siginfo->si_addr))) + rec.ExceptionInformation[1] = (DWORD)addr; + if (!(page_fault_code=VIRTUAL_HandleFault(addr))) return; rec.ExceptionCode = page_fault_code; break; - default:FIXME("Unhandled SIGSEGV/%x\n",__siginfo->si_code); + default:FIXME("Unhandled SIGSEGV/%x\n",code); break; } break; case SIGBUS: - switch ( __siginfo->si_code & 0xffff ) { + switch ( code & 0xffff ) { case BUS_ADRALN: rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; break; +#ifdef BUS_ADRERR case BUS_ADRERR: +#endif +#ifdef BUS_OBJERR case BUS_OBJERR: /* FIXME: correct for all cases ? */ rec.NumberParameters = 2; rec.ExceptionInformation[0] = 0; /* FIXME ? */ - rec.ExceptionInformation[1] = (DWORD)__siginfo->si_addr; - if (!(page_fault_code=VIRTUAL_HandleFault(__siginfo->si_addr))) + rec.ExceptionInformation[1] = (DWORD)addr; + if (!(page_fault_code=VIRTUAL_HandleFault(addr))) return; rec.ExceptionCode = page_fault_code; break; - default:FIXME("Unhandled SIGBUS/%x\n",__siginfo->si_code); +#endif + default:FIXME("Unhandled SIGBUS/%x\n",code); break; } break; case SIGILL: - switch ( __siginfo->si_code & 0xffff ) { + switch ( code & 0xffff ) { case ILL_ILLOPC: /* illegal opcode */ +#ifdef ILL_ILLOPN case ILL_ILLOPN: /* illegal operand */ +#endif +#ifdef ILL_ILLADR case ILL_ILLADR: /* illegal addressing mode */ +#endif +#ifdef ILL_ILLTRP case ILL_ILLTRP: /* illegal trap */ +#endif +#ifdef ILL_COPROC case ILL_COPROC: /* coprocessor error */ +#endif rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; break; case ILL_PRVOPC: /* privileged opcode */ +#ifdef ILL_PRVREG case ILL_PRVREG: /* privileged register */ +#endif rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION; break; +#ifdef ILL_BADSTK case ILL_BADSTK: /* internal stack error */ rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW; break; - default:FIXME("Unhandled SIGILL/%x\n",__siginfo->si_code); +#endif + default:FIXME("Unhandled SIGILL/%x\n", code); break; } break; } - EXC_RtlRaiseException( &rec, &context ); - restore_context( &context, HANDLER_CONTEXT ); + EXC_RtlRaiseException( &rec, context ); } /********************************************************************** - * trap_handler + * do_trap * - * Handler for SIGTRAP. + * Implementation of SIGTRAP handler. */ -static HANDLER_DEF(trap_handler) +static void do_trap( CONTEXT *context, int code, void * addr ) { - CONTEXT context; EXCEPTION_RECORD rec; - save_context( &context, HANDLER_CONTEXT ); - rec.ExceptionFlags = EXCEPTION_CONTINUABLE; rec.ExceptionRecord = NULL; - rec.ExceptionAddress = (LPVOID)__context->uc_mcontext.regs->nip; + rec.ExceptionAddress = addr; rec.NumberParameters = 0; /* FIXME: check if we might need to modify PC */ - switch (__siginfo->si_code & 0xffff) { + switch (code & 0xffff) { +#ifdef TRAP_BRKPT case TRAP_BRKPT: rec.ExceptionCode = EXCEPTION_BREAKPOINT; break; +#endif +#ifdef TRAP_TRACE case TRAP_TRACE: rec.ExceptionCode = EXCEPTION_SINGLE_STEP; break; +#endif + default:FIXME("Unhandled SIGTRAP/%x\n", code); + break; } - EXC_RtlRaiseException( &rec, &context ); - restore_context( &context, HANDLER_CONTEXT ); + EXC_RtlRaiseException( &rec, context ); } - /********************************************************************** - * fpe_handler + * do_trap * - * Handler for SIGFPE. + * Implementation of SIGFPE handler. */ -static HANDLER_DEF(fpe_handler) +static void do_fpe( CONTEXT *context, int code, void * addr ) { - CONTEXT context; EXCEPTION_RECORD rec; - /*save_fpu( &context, HANDLER_CONTEXT );*/ - save_context( &context, HANDLER_CONTEXT ); - - switch ( __siginfo->si_code & 0xffff ) { + switch ( code & 0xffff ) { +#ifdef FPE_FLTSUB case FPE_FLTSUB: rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; break; +#endif +#ifdef FPE_INTDIV case FPE_INTDIV: rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO; break; +#endif +#ifdef FPE_INTOVF case FPE_INTOVF: rec.ExceptionCode = EXCEPTION_INT_OVERFLOW; break; +#endif +#ifdef FPE_FLTDIV case FPE_FLTDIV: rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO; break; +#endif +#ifdef FPE_FLTOVF case FPE_FLTOVF: rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW; break; +#endif +#ifdef FPE_FLTUND case FPE_FLTUND: rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW; break; +#endif +#ifdef FPE_FLTRES case FPE_FLTRES: rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT; break; +#endif +#ifdef FPE_FLTINV case FPE_FLTINV: +#endif default: rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; break; } rec.ExceptionFlags = EXCEPTION_CONTINUABLE; rec.ExceptionRecord = NULL; - rec.ExceptionAddress = (LPVOID)__context->uc_mcontext.regs->nip; + rec.ExceptionAddress = addr; rec.NumberParameters = 0; - EXC_RtlRaiseException( &rec, &context ); + EXC_RtlRaiseException( &rec, context ); +} + +/********************************************************************** + * segv_handler + * + * Handler for SIGSEGV and related errors. + */ +static HANDLER_DEF(segv_handler) +{ + CONTEXT context; + save_context( &context, HANDLER_CONTEXT ); + do_segv( &context, __siginfo->si_signo, __siginfo->si_errno, __siginfo->si_code, __siginfo->si_addr ); restore_context( &context, HANDLER_CONTEXT ); - /*restore_fpu( &context, HANDLER_CONTEXT );*/ } +/********************************************************************** + * trap_handler + * + * Handler for SIGTRAP. + */ +static HANDLER_DEF(trap_handler) +{ + CONTEXT context; + save_context( &context, HANDLER_CONTEXT ); + do_trap( &context, __siginfo->si_code, __siginfo->si_addr ); + restore_context( &context, HANDLER_CONTEXT ); +} + +/********************************************************************** + * fpe_handler + * + * Handler for SIGFPE. + */ +static HANDLER_DEF(fpe_handler) +{ + CONTEXT context; + save_fpu( &context, HANDLER_CONTEXT ); + save_context( &context, HANDLER_CONTEXT ); + do_fpe( &context, __siginfo->si_code, __siginfo->si_addr ); + restore_context( &context, HANDLER_CONTEXT ); + restore_fpu( &context, HANDLER_CONTEXT ); +} /********************************************************************** * int_handler Index: dlls/ntdll/signal_powerpc.c =================================================================== RCS file: /home/wine/wine/dlls/ntdll/signal_powerpc.c,v retrieving revision 1.13 diff -u -r1.13 signal_powerpc.c --- dlls/ntdll/signal_powerpc.c 4 May 2003 02:25:07 -0000 1.13 +++ dlls/ntdll/signal_powerpc.c 11 May 2003 11:18:50 -0000 @@ -65,11 +65,104 @@ /*********************************************************************** * signal context platform-specific definitions */ +#ifdef linux +# warning Please define registers for your platform 'linux' some are missing typedef struct ucontext SIGCONTEXT; -#define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context ) -#define HANDLER_CONTEXT (__context) +# define HANDLER_DEF(name) void name( int __signal, struct siginfo *__siginfo, SIGCONTEXT *__context ) +# define HANDLER_CONTEXT (__context) + +/* All Registers access - only for local access */ +# define REG_sig(reg_name, context) (context)->uc_mcontext.regs->reg_name + + +/* Gpr Registers access */ +# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context) + +# define IAR_sig(context) REG_sig(nip, context) /* Programm counter */ +# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */ +# define CTR_sig(context) REG_sig(ctr, context) /* Count register */ + +/* Following registers should be defined, someone using linux should define them */ + +# undef XER_sig(context) /* Link register */ +# undef LR_sig(context) /* User's integer exception register */ +# undef CR_sig(context) /* Condition register */ + +/* Float Registers access */ +# undef FLOAT_sig(reg_num, context) /* Float registers */ + +# undef FPSCR_sig(reg_num, context) /* Float registers */ + +/* Exception Registers access */ +# undef DAR_sig(context) +# undef DSISR_sig(context) +# undef TRAP_sig(context) + +#endif /* linux */ + +#ifdef __darwin__ + +# include <sys/ucontext.h> + +# include <sys/types.h> +# include <signal.h> +typedef siginfo_t siginfo; + +typedef struct ucontext SIGCONTEXT; + + +# define HANDLER_DEF(name) void name( int __signal, siginfo *__siginfo, SIGCONTEXT *__context ) +# define HANDLER_CONTEXT (__context) + +/* All Registers access - only for local access */ +# define REG_sig(reg_name, context) (context)->uc_mcontext->ss.reg_name +# define FLOATREG_sig(reg_name, context) (context)->uc_mcontext->fs.reg_name +# define EXCEPREG_sig(reg_name, context) (context)->uc_mcontext->es.reg_name +# define VECREG_sig(reg_name, context) (context)->uc_mcontext->vs.reg_name + +/* Gpr Registers access */ +# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context) + +# define IAR_sig(context) REG_sig(srr0, context) /* Programm counter */ +# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */ +# define CTR_sig(context) REG_sig(ctr, context) + +# define XER_sig(context) REG_sig(xer, context) /* Link register */ +# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */ +# define CR_sig(context) REG_sig(cr, context) /* Condition register */ + +/* Float Registers access */ +# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context) + +# define FPSCR_sig(context) (double)( FLOATREG_sig(fpscr, context) ) + +/* Exception Registers access */ +# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */ +# define DSISR_sig(context) EXCEPREG_sig(dsisr, context) +# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */ + +/* Signal defs : Those are undefined on darwin +SIGBUS +#undef BUS_ADRERR +#undef BUS_OBJERR +SIGILL +#undef ILL_ILLOPN +#undef ILL_ILLTRP +#undef ILL_ILLADR +#undef ILL_COPROC +#undef ILL_PRVREG +#undef ILL_BADSTK +SIGTRAP +#undef TRAP_BRKPT +#undef TRAP_TRACE +SIGFPE +*/ + +#endif /* __darwin__ */ + + typedef int (*wine_signal_handler)(unsigned int sig); @@ -93,30 +186,39 @@ */ static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext ) { -#define CX(x,y) context->x = sigcontext->uc_mcontext.regs->y -#define C(x) CX(Gpr##x,gpr[x]) + +#define C(x) context->Gpr##x = GPR_sig(x,sigcontext) + /* Save Gpr registers */ C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20); C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30); C(31); +#undef C - CX(Iar,nip); - CX(Msr,msr); - CX(Ctr,ctr); -#undef CX - /* FIXME: fp regs? */ - - /* FIXME: missing pt_regs ... - unsigned long link; - unsigned long xer; - unsigned long ccr; - unsigned long mq; - - unsigned long trap; - unsigned long dar; - unsigned long dsisr; - - */ + context->Iar = IAR_sig(sigcontext); /* Program Counter */ + context->Msr = MSR_sig(sigcontext); /* Machine State Register (Supervisor) */ + context->Ctr = CTR_sig(sigcontext); + +#ifdef XER_sig + context->Xer = XER_sig(sigcontext); +#endif +#ifdef LR_sig + context->Lr = LR_sig(sigcontext); +#endif +#ifdef CR_sig + context->Cr = CR_sig(sigcontext); +#endif + + /* Saving Exception regs */ +#ifdef DAR_sig + context->Dar = DAR_sig(sigcontext); +#endif +#ifdef DSISR_sig + context->Dsisr = DSISR_sig(sigcontext); +#endif +#ifdef TRAP_sig + context->Trap = TRAP_sig(sigcontext); +#endif } @@ -127,16 +229,38 @@ */ static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext ) { -#define CX(x,y) sigcontext->uc_mcontext.regs->y = context->x + +#define C(x) GPR_sig(x,sigcontext) = context->Gpr##x C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20); C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30); C(31); +#undef C - CX(Iar,nip); - CX(Msr,msr); - CX(Ctr,ctr); -#undef CX + IAR_sig(sigcontext) = context->Iar; /* Program Counter */ + MSR_sig(sigcontext) = context->Msr; /* Machine State Register (Supervisor) */ + CTR_sig(sigcontext) = context->Ctr; + +#ifdef XER_sig + XER_sig(sigcontext) = context->Xer; +#endif +#ifdef LR_sig + LR_sig(sigcontext) = context->Lr; +#endif +#ifdef CR_sig + CR_sig(sigcontext) = context->Cr; +#endif + + /* Setting Exception regs */ +#ifdef DAR_sig + DAR_sig(sigcontext) = context->Dar; +#endif +#ifdef DSISR_sig + DSISR_sig(sigcontext) = context->Dsisr; +#endif +#ifdef TRAP_sig + TRAP_sig(sigcontext) = context->Trap; +#endif } @@ -147,7 +271,18 @@ */ inline static void save_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext ) { - /* FIXME? */ +#ifdef FLOAT_sig +# define C(x) context->Fpr##x = FLOAT_sig(x,sigcontext) + C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); + C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20); + C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30); + C(31); +# undef C +#endif /* FLOAT_sig */ + +#ifdef FPSCR_sig + context->Fpscr = FPSCR_sig(sigcontext); +#endif } @@ -158,7 +293,19 @@ */ inline static void restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext ) { - /* FIXME? */ +#ifdef FLOAT_sig +# define C(x) FLOAT_sig(x,sigcontext) = context->Fpr##x + + C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); + C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19); C(20); + C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28); C(29); C(30); + C(31); +# undef C +#endif /* FLOAT_sig */ + +#ifdef FPSCR_sig + FPSCR_sig(sigcontext) = context->Fpscr; +#endif } @@ -169,7 +316,7 @@ */ static inline DWORD get_fpu_code( const CONTEXT *context ) { - DWORD status = 0 /* FIXME */; + DWORD status = context->Fpscr; if (status & 0x01) /* IE */ { @@ -186,164 +333,227 @@ return EXCEPTION_FLT_INVALID_OPERATION; /* generic error */ } - /********************************************************************** - * segv_handler + * do_segv * - * Handler for SIGSEGV and related errors. + * Implementation of SIGSEGV handler. */ -static HANDLER_DEF(segv_handler) +static void do_segv( CONTEXT *context, int trap, int err, int code, void * addr ) { - CONTEXT context; EXCEPTION_RECORD rec; DWORD page_fault_code = EXCEPTION_ACCESS_VIOLATION; - save_context( &context, HANDLER_CONTEXT ); - rec.ExceptionRecord = NULL; rec.ExceptionFlags = EXCEPTION_CONTINUABLE; - rec.ExceptionAddress = (LPVOID)HANDLER_CONTEXT->uc_mcontext.regs->nip; + rec.ExceptionAddress = addr; rec.NumberParameters = 0; - switch (__siginfo->si_signo) { + + switch (trap) { case SIGSEGV: - switch ( __siginfo->si_code & 0xffff ) { + switch ( code & 0xffff ) { case SEGV_MAPERR: case SEGV_ACCERR: rec.NumberParameters = 2; rec.ExceptionInformation[0] = 0; /* FIXME ? */ - rec.ExceptionInformation[1] = (DWORD)__siginfo->si_addr; - if (!(page_fault_code=VIRTUAL_HandleFault(__siginfo->si_addr))) + rec.ExceptionInformation[1] = (DWORD)addr; + if (!(page_fault_code=VIRTUAL_HandleFault(addr))) return; rec.ExceptionCode = page_fault_code; break; - default:FIXME("Unhandled SIGSEGV/%x\n",__siginfo->si_code); + default:FIXME("Unhandled SIGSEGV/%x\n",code); break; } break; case SIGBUS: - switch ( __siginfo->si_code & 0xffff ) { + switch ( code & 0xffff ) { case BUS_ADRALN: rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; break; +#ifdef BUS_ADRERR case BUS_ADRERR: +#endif +#ifdef BUS_OBJERR case BUS_OBJERR: /* FIXME: correct for all cases ? */ rec.NumberParameters = 2; rec.ExceptionInformation[0] = 0; /* FIXME ? */ - rec.ExceptionInformation[1] = (DWORD)__siginfo->si_addr; - if (!(page_fault_code=VIRTUAL_HandleFault(__siginfo->si_addr))) + rec.ExceptionInformation[1] = (DWORD)addr; + if (!(page_fault_code=VIRTUAL_HandleFault(addr))) return; rec.ExceptionCode = page_fault_code; break; - default:FIXME("Unhandled SIGBUS/%x\n",__siginfo->si_code); +#endif + default:FIXME("Unhandled SIGBUS/%x\n",code); break; } break; case SIGILL: - switch ( __siginfo->si_code & 0xffff ) { + switch ( code & 0xffff ) { case ILL_ILLOPC: /* illegal opcode */ +#ifdef ILL_ILLOPN case ILL_ILLOPN: /* illegal operand */ +#endif +#ifdef ILL_ILLADR case ILL_ILLADR: /* illegal addressing mode */ +#endif +#ifdef ILL_ILLTRP case ILL_ILLTRP: /* illegal trap */ +#endif +#ifdef ILL_COPROC case ILL_COPROC: /* coprocessor error */ +#endif rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; break; case ILL_PRVOPC: /* privileged opcode */ +#ifdef ILL_PRVREG case ILL_PRVREG: /* privileged register */ +#endif rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION; break; +#ifdef ILL_BADSTK case ILL_BADSTK: /* internal stack error */ rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW; break; - default:FIXME("Unhandled SIGILL/%x\n",__siginfo->si_code); +#endif + default:FIXME("Unhandled SIGILL/%x\n", code); break; } break; } - EXC_RtlRaiseException( &rec, &context ); - restore_context( &context, HANDLER_CONTEXT ); + EXC_RtlRaiseException( &rec, context ); } /********************************************************************** - * trap_handler + * do_trap * - * Handler for SIGTRAP. + * Implementation of SIGTRAP handler. */ -static HANDLER_DEF(trap_handler) +static void do_trap( CONTEXT *context, int code, void * addr ) { - CONTEXT context; EXCEPTION_RECORD rec; - save_context( &context, HANDLER_CONTEXT ); - rec.ExceptionFlags = EXCEPTION_CONTINUABLE; rec.ExceptionRecord = NULL; - rec.ExceptionAddress = (LPVOID)__context->uc_mcontext.regs->nip; + rec.ExceptionAddress = addr; rec.NumberParameters = 0; /* FIXME: check if we might need to modify PC */ - switch (__siginfo->si_code & 0xffff) { + switch (code & 0xffff) { +#ifdef TRAP_BRKPT case TRAP_BRKPT: rec.ExceptionCode = EXCEPTION_BREAKPOINT; break; +#endif +#ifdef TRAP_TRACE case TRAP_TRACE: rec.ExceptionCode = EXCEPTION_SINGLE_STEP; break; +#endif + default:FIXME("Unhandled SIGTRAP/%x\n", code); + break; } - EXC_RtlRaiseException( &rec, &context ); - restore_context( &context, HANDLER_CONTEXT ); + EXC_RtlRaiseException( &rec, context ); } - /********************************************************************** - * fpe_handler + * do_trap * - * Handler for SIGFPE. + * Implementation of SIGFPE handler. */ -static HANDLER_DEF(fpe_handler) +static void do_fpe( CONTEXT *context, int code, void * addr ) { - CONTEXT context; EXCEPTION_RECORD rec; - /*save_fpu( &context, HANDLER_CONTEXT );*/ - save_context( &context, HANDLER_CONTEXT ); - - switch ( __siginfo->si_code & 0xffff ) { + switch ( code & 0xffff ) { +#ifdef FPE_FLTSUB case FPE_FLTSUB: rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; break; +#endif +#ifdef FPE_INTDIV case FPE_INTDIV: rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO; break; +#endif +#ifdef FPE_INTOVF case FPE_INTOVF: rec.ExceptionCode = EXCEPTION_INT_OVERFLOW; break; +#endif +#ifdef FPE_FLTDIV case FPE_FLTDIV: rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO; break; +#endif +#ifdef FPE_FLTOVF case FPE_FLTOVF: rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW; break; +#endif +#ifdef FPE_FLTUND case FPE_FLTUND: rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW; break; +#endif +#ifdef FPE_FLTRES case FPE_FLTRES: rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT; break; +#endif +#ifdef FPE_FLTINV case FPE_FLTINV: +#endif default: rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; break; } rec.ExceptionFlags = EXCEPTION_CONTINUABLE; rec.ExceptionRecord = NULL; - rec.ExceptionAddress = (LPVOID)__context->uc_mcontext.regs->nip; + rec.ExceptionAddress = addr; rec.NumberParameters = 0; - EXC_RtlRaiseException( &rec, &context ); + EXC_RtlRaiseException( &rec, context ); +} + +/********************************************************************** + * segv_handler + * + * Handler for SIGSEGV and related errors. + */ +static HANDLER_DEF(segv_handler) +{ + CONTEXT context; + save_context( &context, HANDLER_CONTEXT ); + do_segv( &context, __siginfo->si_signo, __siginfo->si_errno, __siginfo->si_code, __siginfo->si_addr ); restore_context( &context, HANDLER_CONTEXT ); - /*restore_fpu( &context, HANDLER_CONTEXT );*/ } +/********************************************************************** + * trap_handler + * + * Handler for SIGTRAP. + */ +static HANDLER_DEF(trap_handler) +{ + CONTEXT context; + save_context( &context, HANDLER_CONTEXT ); + do_trap( &context, __siginfo->si_code, __siginfo->si_addr ); + restore_context( &context, HANDLER_CONTEXT ); +} + +/********************************************************************** + * fpe_handler + * + * Handler for SIGFPE. + */ +static HANDLER_DEF(fpe_handler) +{ + CONTEXT context; + save_fpu( &context, HANDLER_CONTEXT ); + save_context( &context, HANDLER_CONTEXT ); + do_fpe( &context, __siginfo->si_code, __siginfo->si_addr ); + restore_context( &context, HANDLER_CONTEXT ); + restore_fpu( &context, HANDLER_CONTEXT ); +} /********************************************************************** * int_handler