fpeinth.asm

来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 373 行 · 第 1/2 页

ASM
373
字号
;*****************************************************************************
;*
;*                            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:  80x87 interrupt handler.
;*
;*****************************************************************************


.8087
.386p

include struct.inc
include mdef.inc
include stword.inc
include env387.inc
include fstatus.inc

ifndef  __NETWARE__
        xref            __GETDS
endif
        xref            __8087  ; indicate that NDP instructions are present

        modstart        fpeinth

        datasegment

        extrn   __FPE_exception_: proc
        extrn   "C",_STACKLOW   : dword

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.

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                     ; ...
        push    EDX                     ; ...
        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,ES:[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
        _guess                          ; guess precision exception
          test  DL,ST_EF_PR             ; - check for precision exception
          _quif e                       ; - quit if not precision exception
          mov   CL,FPE_INEXACT          ; - indicate precision exception
        _admit                          ; guess stack under/overflow
          test  DL,ST_EF_SF             ; - check for stack under/overflow
          _quif e                       ; - quit if not stack under/overflow
          test  DX,ST_C1                ; - check if underflow
          _if   e                       ; - if underflow
            mov CL,FPE_STACKUNDERFLOW   ; - - indicate stack underflow
          _else                         ; - else
            mov CL,FPE_STACKOVERFLOW    ; - - indicate stack overflow
          _endif                        ; - endif
        _admit                          ; guess invalid operation
          test  DL,ST_EF_IO             ; - check for invalid operation
          _quif e                       ; - quit if not invalid operation
          call  InvalidOp               ; - process invalid operation
        _admit                          ; guess denormal operand
          test  DL,ST_EF_DO             ; - check for denormal operand
          _quif e                       ; - quit if not denormal operand
          mov   CL,FPE_DENORMAL         ; - indicate underflow
        _admit                          ; guess overflow
          test  DL,ST_EF_OF             ; - check for overflow
          _quif e                       ; - quit if not overflow
          call  KOOverFlow              ; - process overflow exception
          mov   CL,FPE_OVERFLOW         ; - set floating point error code
        _admit                          ; guess underflow
          test  DL,ST_EF_UF             ; - check for underflow
          _quif e                       ; - quit if not underflow
          mov   CL,FPE_UNDERFLOW        ; - indicate underflow
        _admit                          ; guess divide by 0
          test  DL,ST_EF_ZD             ; - check for divide by zero
          _quif e                       ; - quit if not divide by zero
          call  GetInf                  ; - process divide by zero
          mov   CL,FPE_ZERODIVIDE       ; - indicate divide by zero
        _endguess                       ; endguess
        _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
                                        ; exception
        and     word ptr ENV_CW[EBP],0FF72h
        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                     ; ...
        pop     EDX                     ; ...
        pop     ECX                     ; ...
        pop     EBX                     ; ...
        pop     EAX                     ; ...

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?