SIGFPE handling

git-svn-id: svn://kolibrios.org@703 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2008-01-26 21:57:46 +00:00
parent 616f769298
commit 97918755c2
9 changed files with 1802 additions and 1612 deletions

View File

@ -4,10 +4,10 @@ projectIdent
VpeMain
1
WRect
-32
330
10304
9950
0
370
10240
9870
2
MProject
3
@ -42,8 +42,8 @@ WRect
WFileName
10
clib_r.tgt
0
0
10
42
11
VComponent
12
@ -59,5 +59,5 @@ WFileName
7
crt.tgt
0
0
11
17
8

View File

@ -180,165 +180,12 @@ void _WCI86FAR __default_sigfpe_handler( int fpe_sig )
}
#endif
#if defined( __OS2__ )
void __chk8087( void )
/********************/
{
char devinfo;
#if defined( __386__ )
DosDevConfig( &devinfo, DEVINFO_COPROCESSOR );
if( devinfo == 0 ) {
_RWD_real87 = 0;
} else {
_RWD_real87 = __x87id();
}
_RWD_8087 = _RWD_real87;
#else
if( _RWD_8087 == 0 ) {
DosDevConfig( &devinfo, 3, 0 );
if( devinfo == 0 ) {
_RWD_real87 = 0;
} else {
_RWD_real87 = __x87id();
}
_RWD_8087 = _RWD_real87;
}
if( _RWD_real87 ) {
__GrabFP87();
}
if( _RWD_8087 ) {
_RWD_FPE_handler = __default_sigfpe_handler;
}
#endif
_fpreset();
}
#elif defined( __QNX__ )
void __chk8087( void )
/********************/
{
extern char __87;
extern char __r87;
_RWD_real87 = __r87;
_RWD_8087 = __87;
_fpreset();
}
#elif defined( __LINUX__ )
void __chk8087( void )
/********************/
{
// TODO: We really need to call Linux and determine if the machine
// has a real FPU or not, so we can properly work with an FPU
// emulator.
_RWD_real87 = __x87id();
_RWD_8087 = _RWD_real87;
_fpreset();
}
#elif defined( __NETWARE__ )
extern short __87present( void );
#pragma aux __87present = \
"smsw ax ", \
"test ax, 4 ", \
"jne no_emu ", \
"xor ax, ax ", \
"no_emu: ", \
"mov ax, 1 " \
value [ ax ];
extern void __chk8087( void )
/*****************************/
{
if( _RWD_8087 == 0 ) {
if( __87present() ) {
_RWD_8087 = 3; /* 387 */
_RWD_real87 = 3;
}
__init_80x87();
}
}
#elif defined( __NT__ )
void __chk8087( void )
/********************/
{
_RWD_real87 = __x87id();
_RWD_8087 = _RWD_real87;
__init_8087();
}
#elif defined( __DOS__ )
void __chk8087( void )
/********************/
{
if( _RWD_8087 != 0 ) { /* if we already know we have an 80x87 */
#if !defined( __386__ )
if( __dos87real )
__GrabFP87();
#endif
_RWD_FPE_handler = __default_sigfpe_handler;
return; /* this prevents real87 from being set */
} /* when we have an emulator */
_RWD_real87 = __x87id(); /* if a coprocessor is present then we */
_RWD_8087 = _RWD_real87; /* initialize even when NO87 is defined */
#if !defined( __386__ )
__dos87real = _RWD_real87;
#endif
__init_8087(); /* this handles the fpi87 and NO87 case */
if( _RWD_no87 != 0 ) { /* if NO87 environment var is defined */
_RWD_8087 = 0; /* then we want to pretend that the */
_RWD_real87 = 0; /* coprocessor doesn't exist */
}
if( _RWD_real87 ) {
__GrabFP87();
}
if( _RWD_8087 ) {
_RWD_FPE_handler = __default_sigfpe_handler;
}
}
#elif defined( __WINDOWS__ )
void __chk8087( void )
/********************/
{
if( _RWD_8087 != 0 ) /* if we already know we have an 80x87 */
return; /* this prevents real87 from being set */
/* when we have an emulator */
if( GetWinFlags() & WF_80x87 ) { /* if a coprocessor is present then we */
#if defined( __386__ )
extern void pascal _FloatingPoint( void );
_FloatingPoint();
#endif
_RWD_real87 = __x87id(); /* initialize even when NO87 is defined */
_RWD_8087 = _RWD_real87; /* this handles the fpi87 and NO87 case */
__init_8087();
} else {
#if defined( __386__ )
// check to see if emulator is loaded
union REGS regs;
regs.w.ax = 0xfa00;
int86( 0x2f, &regs, &regs );
if( regs.w.ax == 0x0666 ) { /* check for emulator present */
_RWD_real87 = __x87id(); /* initialize even when NO87 is defined */
_RWD_8087 = _RWD_real87; /* this handles the fpi87 and NO87 case */
__init_8087();
}
#endif
}
if( _RWD_no87 != 0 ) { /* if NO87 environment var is defined */
_RWD_8087 = 0; /* then we want to pretend that the */
_RWD_real87 = 0; /* coprocessor doesn't exist */
}
}
#endif

View File

@ -0,0 +1,102 @@
;*****************************************************************************
;*
;* Open Watcom Project
;*
;* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
;*
;* ========================================================================
;*
;* This file contains Original Code and/or Modifications of Original
;* Code as defined in and that are subject to the Sybase Open Watcom
;* Public License version 1.0 (the 'License'). You may not use this file
;* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
;* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
;* provided with the Original Code and Modifications, and is also
;* available at www.sybase.com/developer/opensource.
;*
;* The Original Code and all software distributed under the License are
;* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
;* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
;* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
;* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
;* NON-INFRINGEMENT. Please see the License for the specific language
;* governing rights and limitations under the License.
;*
;* ========================================================================
;*
;* Description: Connect/disconnect 80x87 interrupt handler.
;*
;*****************************************************************************
.8087
.386p
include struct.inc
include mdef.inc
xref __FPE2Handler_
modstart fpe387
datasegment
Save87 dd 0
enddata
xdefp "C",__Init_FPE_handler
defp __Init_FPE_handler
_guess ; guess initialization required
cmp dword ptr Save87,0 ; - quit if already initialized
_quif ne ; - ...
_admit ; admit: already initialized
ret ; - return
_endguess ; endguess
push EAX ; save registers
push EBX ; ...
push ECX ; ...
mov EAX, 68
mov EBX, 15
lea ECX, __FPE2Handler_
int 40h ; set new #FPE handler
mov Save87, EAX ; save old handler
pop ECX ; ...
pop EBX ; ...
pop EAX ; ...
ret ; return
endproc __Init_FPE_handler
xdefp "C",__Fini_FPE_handler
defp __Fini_FPE_handler
cmp dword ptr Save87,0 ; if not initialized
_if e ; - then
ret ; - return
_endif ; endif
push EAX ; save registers
push EBX ; ...
push EDX ; ...
sub ESP,4 ; allocate space for control word
fstcw word ptr [ESP] ; get control word
fwait ; ...
mov byte ptr [ESP],7Fh ; disable exception interrupts
fldcw word ptr [ESP] ; ...
fwait ; ...
add ESP,4 ; remove temporary
mov EAX, 68
mov EBX, 15
mov ECX, dword ptr Save87
int 40h ; set new #FPE handler
pop EDX ; ...
pop EBX ; ...
pop EAX ; ...
ret
endproc __Fini_FPE_handler
endmod
end

View File

@ -40,9 +40,6 @@ include stword.inc
include env387.inc
include fstatus.inc
ifndef __NETWARE__
xref __GETDS
endif
xref __8087 ; indicate that NDP instructions are present
modstart fpeinth
@ -55,28 +52,16 @@ endif
TInf db 00h,00h,00h,00h,00h,00h,00h,80h,0ffh,7fh
F8Inf db 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0efh,7fh
F4Inf db 0ffh,0ffh,7fh,7fh
db 512 dup(0)
FPEStk label byte
SaveSS dw 0
SaveESP dd 0
enddata
; Interrupt handler for 80x87 exceptions.
; User handler for 80x87 exceptions.
xdefp __FPEHandler_
defp __FPEHandler_
public "C",__FPEHandlerStart_
__FPEHandlerStart_ label byte
push EAX ; save reg
mov AL,20h ; issue EOI to 8259 controller
out 20h,AL ; ...
out 0a0h,AL ; issue EOI to slave 8259
xor AX,AX ; clear busy signal
out 0f0h,AL ; ...
pop EAX ; restore regs
public __FPE2Handler_
__FPE2Handler_ label byte
push EAX ; save regs
push EBX ; ...
push ECX ; ...
@ -84,34 +69,22 @@ __FPE2Handler_ label byte
push ESI ; ...
push EDI ; ...
push EBP ; ...
push DS ; ...
push ES ; ...
sub ESP,ENV_SIZE ; make room for environment information
mov EBP,ESP ; point to buffer for 80x87 environment
fnstenv [EBP] ; get 80x87 environment
fwait ; wait for 80x87
fdisi ; disable interrupts
sti ; enable CPU interrupts
ifndef __NETWARE__
; call __GETDS ; load DS
endif
ifdef __NETWARE__
; push SS ; load DS
; pop DS ; ...
endif
mov EDX,ENV_CW[EBP] ; get control word
not EDX ; flip the mask bits
mov DH,0FFh ; turn on top byte
and EDX,ENV_SW[EBP] ; get status word
; mov ES,ENV_IP+4[EBP] ; get intruction address
mov EDI,ENV_IP[EBP] ; ...
opcode: mov BX,[EDI] ; get opcode
opcode:
mov BX,[EDI] ; get opcode
inc EDI ; point to next opcode
cmp BL,0d8h ; check if its the opcode
jb opcode ; ...
cmp BL,0dfh ; ...
ja opcode ; ...
; mov ES,ENV_OP+4[EBP] ; get pointer to operand
mov EDI,ENV_OP[EBP] ; ...
xchg BL,BH ; get opcode in right position
mov CL,FPE_OK ; assume exception to be ignored
@ -154,22 +127,8 @@ opcode: mov BX,[EDI] ; get opcode
_guess ; guess exception to be handled
cmp CL,FPE_OK ; - check if exception allowed
_quif e ; - quit if exception not allowed
; cmp SaveSS,0 ; - check if already in handler
; _quif ne ; - quit if already in handler
push _STACKLOW ; - save old stack low
mov SaveSS,SS ; - save current stack pointer
mov SaveESP,ESP ; - ...
push DS ; - get new stack pointer
pop SS ; - ...
lea ESP,FPEStk ; - ...
lea EAX,FPEStk-512 ; - set stack low variable
mov _STACKLOW,EAX ; - set stack low variable
movzx EAX,CL ; - set floating point status
call __FPE_exception_ ; - call user's handler
mov SS,SaveSS ; - restore stack pointer
mov ESP,SaveESP ; - ...
pop _STACKLOW ; - restore old stacklow
mov SaveSS,0 ; - indicate handler can be re-entered
_endguess ; endguess
fclex ; clear exceptions that may have
; occurred as a result of handling the
@ -178,8 +137,6 @@ opcode: mov BX,[EDI] ; get opcode
fldcw word ptr ENV_CW[EBP] ; enable interrupts
fwait ; ...
add ESP,ENV_SIZE ; clean up stack
pop ES ; restore registers
pop DS ; ...
pop EBP ; ...
pop EDI ; ...
pop ESI ; ...
@ -187,11 +144,9 @@ opcode: mov BX,[EDI] ; get opcode
pop ECX ; ...
pop EBX ; ...
pop EAX ; ...
iretd ; return from interrupt handler
public "C",__FPEHandlerEnd_
__FPEHandlerEnd_ label byte
endproc __FPEHandler_
ret ; return from interrupt handler
endproc __FPEHandler_
; Process invalid operation.
@ -363,9 +318,9 @@ endproc Load
Store proc near
test BH,04h
_if ne ; if double
fst qword ptr ES:[EDI] ; - store as double precision result
fst qword ptr [EDI] ; - store as double precision result
_else ; else
fst dword ptr ES:[EDI] ; - store as single precision result
fst dword ptr [EDI] ; - store as single precision result
_endif ; endif
ret ; return
endproc Store

View File

@ -0,0 +1,43 @@
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: typedef for external signal routines and
* prototypes for other signal internal function
*
****************************************************************************/
#include "extfunc.h"
typedef void (*__sigfpe_func)( int, int );
#ifdef _M_IX86
#pragma aux (__outside_CLIB) __sig_func;
#pragma aux (__outside_CLIB) __sigfpe_func;
#endif
_WCRTLINK extern void __sigfpe_handler( int );
extern void __sigabort( void );
extern void __restore_FPE_handler( void );
extern void __grab_FPE_handler( void );

View File

@ -0,0 +1,33 @@
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#define __SIGNALTABLE SignalTable

View File

@ -36,24 +36,11 @@
extern void __Init_FPE_handler();
extern void __Fini_FPE_handler();
#ifdef __DOS_386__
extern int __FPEHandlerStart_;
extern int __FPEHandlerEnd_;
extern int __DPMI_hosted(void);
#endif
void __GrabFP87( void )
{
#ifndef __WINDOWS__
if( _RWD_FPE_handler_exit != __Fini_FPE_handler ) {
#ifdef __DOS_386__
if( !_IsPharLap() && ( __DPMI_hosted() == 1 )) {
DPMILockLinearRegion((long)&__FPEHandlerStart_,
((long)&__FPEHandlerEnd_ - (long)&__FPEHandlerStart_));
}
#endif
__Init_FPE_handler();
_RWD_FPE_handler_exit = __Fini_FPE_handler;
}
#endif
}

View File

@ -0,0 +1,187 @@
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: signal handling ( for DOS, Windows 3.x and ? Netware )
*
****************************************************************************/
#include "variety.h"
#include <stdio.h>
#include <signal.h>
//#include <dos.h>
#include <errno.h>
#include <float.h>
#include "rtdata.h"
#include "sigtab.h"
#include "sigfunc.h"
#include "seterrno.h"
#ifndef __WINDOWS_386__
#ifndef __NETWARE__
//extern void __grab_int23( void );
//extern void __restore_int23( void );
//extern void __grab_int_ctrl_break( void );
//extern void __restore_int_ctrl_break( void );
#endif
#endif
#define __SIGLAST SIGIOVFL
static __sig_func SignalTable[] = {
SIG_IGN, /* unused */
SIG_DFL, /* SIGABRT */
SIG_DFL, /* SIGFPE */
SIG_DFL, /* SIGILL */
SIG_DFL, /* SIGINT */
SIG_DFL, /* SIGSEGV */
SIG_DFL, /* SIGTERM */
SIG_DFL, /* SIGBREAK */
SIG_IGN, /* SIGUSR1 */
SIG_IGN, /* SIGUSR2 */
SIG_IGN, /* SIGUSR3 */
SIG_DFL, /* SIGIDIVZ */
SIG_DFL /* SIGIOVFL */
};
static FPEhandler *__old_FPE_handler = NULL;
void __sigabort( void )
{
raise( SIGABRT );
}
//extern void _fpmath( void );
//#pragma aux _fpmath "__fpmath";
_WCRTLINK void __sigfpe_handler( int fpe_type )
{
__sig_func func;
func = SignalTable[ SIGFPE ];
if( func != SIG_IGN && func != SIG_DFL && func != SIG_ERR ) {
SignalTable[ SIGFPE ] = SIG_DFL; /* 09-nov-87 FWC */
(*(__sigfpe_func)func)( SIGFPE, fpe_type ); /* so we can pass 2'nd parm */
}
}
_WCRTLINK __sig_func signal( int sig, __sig_func func )
{
__sig_func prev_func;
if(( sig < 1 ) || ( sig > __SIGLAST )) {
__set_errno( EINVAL );
return( SIG_ERR );
}
_RWD_abort = __sigabort; /* change the abort rtn address */
if( sig == SIGINT ) {
if( func == SIG_DFL ) {
// __restore_int23();
} else if( func != SIG_ERR ) {
// __grab_int23();
}
} else if( sig == SIGBREAK ) {
if( func == SIG_DFL ) {
// __restore_int_ctrl_break();
} else if( func != SIG_ERR ) {
// __grab_int_ctrl_break();
}
} else if( sig == SIGFPE ) {
if( func == SIG_DFL ) {
__restore_FPE_handler();
} else if( func != SIG_ERR ) {
__grab_FPE_handler();
}
}
prev_func = _RWD_sigtab[ sig ];
_RWD_sigtab[ sig ] = func;
return( prev_func );
}
_WCRTLINK int raise( int sig )
{
__sig_func func;
func = _RWD_sigtab[ sig ];
switch( sig ) {
case SIGFPE:
__sigfpe_handler( FPE_EXPLICITGEN );
break;
case SIGABRT:
if( func == SIG_DFL ) {
__terminate();
}
case SIGINT:
if( func != SIG_IGN && func != SIG_DFL && func != SIG_ERR ) {
_RWD_sigtab[ sig ] = SIG_DFL; /* 09-nov-87 FWC */
// __restore_int23();
(*func)( sig );
}
break;
case SIGBREAK:
if( func != SIG_IGN && func != SIG_DFL && func != SIG_ERR ) {
_RWD_sigtab[ sig ] = SIG_DFL; /* 09-nov-87 FWC */
// __restore_int_ctrl_break();
(*func)( sig );
}
break;
case SIGILL:
case SIGSEGV:
case SIGTERM:
case SIGUSR1:
case SIGUSR2:
case SIGUSR3:
case SIGIDIVZ:
case SIGIOVFL:
if( func != SIG_IGN && func != SIG_DFL && func != SIG_ERR ) {
_RWD_sigtab[ sig ] = SIG_DFL; /* 09-nov-87 FWC */
(*func)( sig );
}
break;
default:
return( -1 );
}
return( 0 );
}
void __restore_FPE_handler( void )
{
if( __old_FPE_handler == NULL ) {
return;
}
__FPE_handler = __old_FPE_handler;
__old_FPE_handler = NULL;
}
void __grab_FPE_handler( void )
{
if( __old_FPE_handler == NULL ) {
__old_FPE_handler = __FPE_handler;
__FPE_handler = __sigfpe_handler;
}
}

File diff suppressed because it is too large Load Diff