Subversion Repositories Kolibri OS

Rev

Rev 1075 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;*****************************************************************************
  2. ;*
  3. ;*                            Open Watcom Project
  4. ;*
  5. ;*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
  6. ;*
  7. ;*  ========================================================================
  8. ;*
  9. ;*    This file contains Original Code and/or Modifications of Original
  10. ;*    Code as defined in and that are subject to the Sybase Open Watcom
  11. ;*    Public License version 1.0 (the 'License'). You may not use this file
  12. ;*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
  13. ;*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
  14. ;*    provided with the Original Code and Modifications, and is also
  15. ;*    available at www.sybase.com/developer/opensource.
  16. ;*
  17. ;*    The Original Code and all software distributed under the License are
  18. ;*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  19. ;*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
  20. ;*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
  21. ;*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
  22. ;*    NON-INFRINGEMENT. Please see the License for the specific language
  23. ;*    governing rights and limitations under the License.
  24. ;*
  25. ;*  ========================================================================
  26. ;*
  27. ;* Description:  80x87 interrupt handler.
  28. ;*
  29. ;*****************************************************************************
  30.  
  31.  
  32. ;;; //e:\watcom\src\bld\watcom\h;E:\WATCOM\H;E:\WATCOM\H\NT
  33.  
  34. .8087
  35. .386p
  36.  
  37. include struct.inc
  38. include mdef.inc
  39. include stword.inc
  40. include env387.inc
  41. include fstatus.inc
  42.  
  43.         xref            __8087  ; indicate that NDP instructions are present
  44.  
  45.         modstart        fpeinth
  46.  
  47.         datasegment
  48.  
  49.         extrn   __FPE_exception_: proc
  50.         extrn   "C",_STACKLOW   : dword
  51.  
  52. TInf    db 00h,00h,00h,00h,00h,00h,00h,80h,0ffh,7fh
  53. F8Inf   db 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0efh,7fh
  54. F4Inf   db 0ffh,0ffh,7fh,7fh
  55.         enddata
  56.  
  57. ; User handler for 80x87 exceptions.
  58.  
  59. xdefp   __FPEHandler_
  60. defp    __FPEHandler_
  61.  
  62. public  __FPE2Handler_
  63. __FPE2Handler_ label byte
  64.  
  65.         push    EAX                     ; save regs
  66.         push    EBX                     ; ...
  67.         push    ECX                     ; ...
  68.         push    EDX                     ; ...
  69.         push    ESI                     ; ...
  70.         push    EDI                     ; ...
  71.         push    EBP                     ; ...
  72.         sub     ESP,ENV_SIZE            ; make room for environment information
  73.         mov     EBP,ESP                 ; point to buffer for 80x87 environment
  74.   ; Now EXC_NUM is located in [EBP+ENV_SIZE+32]
  75.   ; but it isn't necessary to testing EXC_NUM,
  76.   ; because only #MF is unmasked now
  77.         fnstenv [EBP]                   ; get 80x87 environment
  78.         fwait                           ; wait for 80x87
  79.         mov     EDX,ENV_CW[EBP]         ; get control word
  80.         not     EDX                     ; flip the mask bits
  81.         mov     DH,0FFh                 ; turn on top byte
  82.         and     EDX,ENV_SW[EBP]         ; get status word
  83.         mov     EDI,ENV_IP[EBP]         ; ...
  84. opcode:
  85.         mov     BX,[EDI]                ; get opcode
  86.         inc     EDI                     ; point to next opcode
  87.         cmp     BL,0d8h                 ; check if its the opcode
  88.         jb      opcode                  ; ...
  89.         cmp     BL,0dfh                 ; ...
  90.         ja      opcode                  ; ...
  91.         mov     EDI,ENV_OP[EBP]         ; ...
  92.         xchg    BL,BH                   ; get opcode in right position
  93.         mov     CL,FPE_OK               ; assume exception to be ignored
  94.         _guess                          ; guess precision exception
  95.           test  DL,ST_EF_PR             ; - check for precision exception
  96.           _quif e                       ; - quit if not precision exception
  97.           mov   CL,FPE_INEXACT          ; - indicate precision exception
  98.         _admit                          ; guess stack under/overflow
  99.           test  DL,ST_EF_SF             ; - check for stack under/overflow
  100.           _quif e                       ; - quit if not stack under/overflow
  101.           test  DX,ST_C1                ; - check if underflow
  102.           _if   e                       ; - if underflow
  103.             mov CL,FPE_STACKUNDERFLOW   ; - - indicate stack underflow
  104.           _else                         ; - else
  105.             mov CL,FPE_STACKOVERFLOW    ; - - indicate stack overflow
  106.           _endif                        ; - endif
  107.         _admit                          ; guess invalid operation
  108.           test  DL,ST_EF_IO             ; - check for invalid operation
  109.           _quif e                       ; - quit if not invalid operation
  110.           call  InvalidOp               ; - process invalid operation
  111.         _admit                          ; guess denormal operand
  112.           test  DL,ST_EF_DO             ; - check for denormal operand
  113.           _quif e                       ; - quit if not denormal operand
  114.           mov   CL,FPE_DENORMAL         ; - indicate underflow
  115.         _admit                          ; guess overflow
  116.           test  DL,ST_EF_OF             ; - check for overflow
  117.           _quif e                       ; - quit if not overflow
  118.           call  KOOverFlow              ; - process overflow exception
  119.           mov   CL,FPE_OVERFLOW         ; - set floating point error code
  120.         _admit                          ; guess underflow
  121.           test  DL,ST_EF_UF             ; - check for underflow
  122.           _quif e                       ; - quit if not underflow
  123.           mov   CL,FPE_UNDERFLOW        ; - indicate underflow
  124.         _admit                          ; guess divide by 0
  125.           test  DL,ST_EF_ZD             ; - check for divide by zero
  126.           _quif e                       ; - quit if not divide by zero
  127.           call  GetInf                  ; - process divide by zero
  128.           mov   CL,FPE_ZERODIVIDE       ; - indicate divide by zero
  129.         _endguess                       ; endguess
  130.    ; More correctly to rise this mask bit - is on end of __FPE_exception_
  131.    ; but it may not returned at all...
  132.         push    ECX
  133.         mov     EAX, 68
  134.         mov     EBX, 25                 ;
  135.         mov     ECX, 16                 ; #MF
  136.         mov     EDX, 1                  ; rise activity
  137.         int     40h                     ; change state of signal activity
  138.         pop     ECX
  139.         _guess                          ; guess exception to be handled
  140.           cmp   CL,FPE_OK               ; - check if exception allowed
  141.           _quif e                       ; - quit if exception not allowed
  142.           movzx EAX,CL                  ; - set floating point status
  143.           call  __FPE_exception_        ; - call user's handler
  144.         _endguess                       ; endguess
  145.         fclex                           ; clear exceptions that may have
  146.                                         ; occurred as a result of handling the
  147.                                         ; exception
  148.         and     word ptr ENV_CW[EBP],0FF72h
  149.         fldcw   word ptr ENV_CW[EBP]    ; enable interrupts
  150.         fwait                           ; ...
  151.         add     ESP,ENV_SIZE            ; clean up stack
  152.         pop     EBP                     ; ...
  153.         pop     EDI                     ; ...
  154.         pop     ESI                     ; ...
  155.         pop     EDX                     ; ...
  156.         pop     ECX                     ; ...
  157.         pop     EBX                     ; ...
  158.         pop     EAX                     ; ...
  159.         ret     4                       ; return from interrupt handler
  160.                                         ; with removing EXC_NUM
  161.  
  162. endproc __FPEHandler_
  163.  
  164. ; Process invalid operation.
  165.  
  166. InvalidOp proc near
  167.         mov   CL,FPE_INVALID            ; assume invalid operation
  168.         _guess                          ; guess it's square root
  169.           cmp   BX,0D9FAh               ; - ...
  170.           _quif ne                      ; - quit if it's not that instruction
  171.           mov   CL,FPE_SQRTNEG          ; - indicate sqrt(negative number)
  172.           ret                           ; - return
  173.         _endguess                       ; endguess
  174.         _guess                          ; guess it's square root
  175.           cmp   BX,0D9F1h               ; - ...
  176.           _quif ne                      ; - quit if it's not that instruction
  177.           mov   CL,FPE_LOGERR           ; - indicate sqrt(negative number)
  178.           ret                           ; - return
  179.         _endguess                       ; endguess
  180.         _guess                          ; guess: 'fprem' instruction
  181.           cmp   BX,0D9F8h               ; - check for 'fprem'   10-may-90
  182.           _if   ne                      ; - if not 'fprem'
  183.             cmp   BX,0D9F5h             ; - - check for 'fprem1'
  184.           _endif                        ; - endif
  185.           _quif ne                      ; - quit if not 'fprem' or 'fprem1'
  186.           mov   CL,FPE_MODERR           ; - indicate mod(negative number)
  187.         _admit                          ; guess: integer overflow
  188.           mov   DX,BX                   ; - save op code
  189.           and   DX,0310h                ; - check for fist/fistp instruction
  190.           cmp   DX,0310h                ; - ...
  191.           _quif ne                      ; - quit if its not that instruction
  192.           mov   CL,FPE_IOVERFLOW        ; - indicate integer overflow
  193.         _admit                          ; guess it's floating point underflow
  194. ;;        mov   DX,BX                   ; - save op code
  195.           and   DX,0110h                ; - check if fst or fstp instruction
  196.           cmp   DX,0110h                ; - ...
  197.           _quif ne                      ; - quit if it's not that instruction
  198. ; Destination is short or long real and source register is an unnormal
  199. ; with exponent in range.
  200.           fstp  st(0)                   ; - pop old result
  201.           fldz                          ; - load zero
  202.           mov   DL,BL                   ; - save op code
  203.           and   DL,0C0h                 ; - check the MOD bits of instruction
  204.           cmp   DL,0C0h                 ; - ...
  205.           _if   ne                      ; - if result to be placed in memory
  206.             call  Store                 ; - - store result in memory
  207.           _endif                        ; - endif
  208.           test  BL,08h                  ; - check if result to be popped
  209.           _if   ne                      ; - if result to be popped
  210.             fstp  st(0)                 ; - - pop the result
  211.           _endif                        ; - endif
  212.           mov   CL,FPE_UNDERFLOW        ; - indicate underflow
  213.         _admit                          ; guess it's divide
  214.           mov   DX,BX                   ; - save op code
  215.           and   DX,0130h                ; - check for fdiv/fidiv instruction
  216.           cmp   DX,0030h                ; - ...
  217.           _quif ne                      ; - quit if it's not that instruction
  218.           mov   DX,ENV_TW[EBP]          ; - get tag word
  219.           mov   CL,AH                   ; - get stack pointer
  220.           and   CL,38h                  ; - ...
  221.           shr   CL,2                    ; - ...
  222.           ror   DX,CL                   ; - make stack top low order bits
  223.           and   DL,05h                  ; - check if top two elements are 0
  224.           cmp   DL,05h                  ; - ...
  225.           _quif ne                      ; - quif if they are not 0
  226.           mov   CL,FPE_ZERODIVIDE       ; - indicate divide by zero
  227.         _endguess                       ; endguess
  228.         ret
  229. endproc InvalidOp
  230.  
  231.  
  232. ; Process overflow exception (note that only floating point overflows
  233. ; are handled - integer overflows are invalid operations).
  234.  
  235. KOOverFlow proc near
  236.         _guess                  ; guess: fscale instruction     10-may-90
  237.           cmp   BX,0D9FDh       ; - quit if not 'fscale' instruction
  238.           _quif ne              ; - ...
  239.         _admit                  ; guess: fst/fstp instruction
  240.           mov   DX,BX           ; - save op code
  241.           and   DX,0110h        ; - check if fst or fstp instruction
  242.           cmp   DX,0110h        ; - ...
  243.           _quif ne              ; - quit if not an fst/fstp instr.
  244.           call  GetInf          ; - load infinity
  245.           mov   DL,BL           ; - save op code
  246.           and   DL,0C0h         ; - check the MOD bits of instruction
  247.           cmp   DL,0C0h         ; - ...
  248.           _if   ne              ; - if result to be placed in memory
  249.             call Store          ; - - store infinity
  250.           _endif                ; - endif
  251.           test  BL,08h          ; - check if result to be popped
  252.           _if   ne              ; - if result to be popped
  253.             fstp  st(0)         ; - - pop result
  254.           _endif                ; - endif
  255.         _admit                  ; admit arithmetic operation
  256.           mov   DL,BL           ; - save op code
  257.           and   DL,0C0h         ; - check if both operands on stack
  258.           cmp   DL,0C0h         ; - ...
  259.           _quif ne              ; - quif both operands not on stack
  260. ;
  261. ; This code handles overflow on the following intructions:
  262. ;    fxxx   ST,ST(i)
  263. ;    fxxx   ST(i),ST    where xxx is one of mul,div,sub or add
  264. ;    fxxxp  ST(i),ST
  265. ;
  266.           lea   ESI,TInf        ; - load internal infinity
  267.           call  Load            ; - ...
  268.         _admit                  ; admit
  269. ;
  270. ; This admit block is to handle overflow on the following intructions:
  271. ;    fxxx   short real
  272. ;    fxxx   long real   where xxx is one of mul,div,sub or add
  273. ;
  274.           call  GetInf          ; - load infinity
  275.         _endguess               ; endguess
  276.         ret                     ; return
  277. endproc KOOverFlow
  278.  
  279.  
  280. ; Replace the top element of the stack with the appropriate signed
  281. ; infinity.
  282.  
  283. GetInf  proc    near
  284.         ftst                    ; get sign of result
  285.         fstsw   word ptr ENV_OP[EBP]
  286.         fstp    st(0)           ; pop argument off stack (does fwait)
  287.         test    BH,04h          ; check if single or double
  288.         _if     ne              ; if double
  289.           fld   qword ptr F8Inf ; - load double precision infinity
  290.         _else                   ; else
  291.           fld   dword ptr F4Inf ; - load single precision infinity
  292.         _endif                  ; endif
  293.         test    word ptr ENV_OP[EBP],ST_C0
  294.         _if     ne              ; if argument is negative
  295.           fchs                  ; - return negative infinity
  296.         _endif                  ; endif
  297.         ret                     ; return
  298. endproc GetInf
  299.  
  300.  
  301. ; Replace an element on the stack with internal zero or infinity.
  302.  
  303. Load    proc    near
  304.         test    BH,04h          ; check if result is top element
  305.         _if     e               ; if result is not top element
  306.           mov   DL,0            ; - indicate we are at the top
  307.         _else                   ; else
  308.           mov   DL,BL           ; - get st(i)
  309.           and   DL,07h          ; - . . .
  310.         _endif                  ; endif
  311.         push    EDX             ; save st(i)
  312.         _loop                   ; loop
  313.           dec   DL              ; - decrement counter
  314.           _quif l               ; - quit if we are at st(i)
  315.           fincstp               ; - increment stack pointer
  316.         _endloop                ; endloop
  317.         fstp    st(0)           ; free the stack element
  318.         fld     tbyte ptr [ESI] ; load internal zero
  319.         pop     EDX             ; get st(i)
  320.         _loop                   ; loop
  321.           dec   DL              ; - decrement counter
  322.           _quif l               ; - quit if we are at st(i)
  323.           fdecstp               ; - decrement stack pointer
  324.         _endloop                ; endloop
  325.         ret                     ; return
  326. endproc Load
  327.  
  328.  
  329. ; Store the top element of the stack at ES:EDI.
  330.  
  331. Store   proc    near
  332.         test    BH,04h
  333.         _if     ne                      ; if double
  334.           fst   qword ptr [EDI]         ; - store as double precision result
  335.         _else                           ; else
  336.           fst   dword ptr [EDI]         ; - store as single precision result
  337.         _endif                          ; endif
  338.         ret                             ; return
  339. endproc Store
  340.  
  341.         endmod
  342.         end
  343.