Subversion Repositories Kolibri OS

Rev

Rev 702 | Rev 1075 | Go to most recent revision | 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.         fnstenv [EBP]                   ; get 80x87 environment
  75.         fwait                           ; wait for 80x87
  76.         mov     EDX,ENV_CW[EBP]         ; get control word
  77.         not     EDX                     ; flip the mask bits
  78.         mov     DH,0FFh                 ; turn on top byte
  79.         and     EDX,ENV_SW[EBP]         ; get status word
  80.         mov     EDI,ENV_IP[EBP]         ; ...
  81. opcode:
  82.         mov     BX,[EDI]                ; get opcode
  83.         inc     EDI                     ; point to next opcode
  84.         cmp     BL,0d8h                 ; check if its the opcode
  85.         jb      opcode                  ; ...
  86.         cmp     BL,0dfh                 ; ...
  87.         ja      opcode                  ; ...
  88.         mov     EDI,ENV_OP[EBP]         ; ...
  89.         xchg    BL,BH                   ; get opcode in right position
  90.         mov     CL,FPE_OK               ; assume exception to be ignored
  91.         _guess                          ; guess precision exception
  92.           test  DL,ST_EF_PR             ; - check for precision exception
  93.           _quif e                       ; - quit if not precision exception
  94.           mov   CL,FPE_INEXACT          ; - indicate precision exception
  95.         _admit                          ; guess stack under/overflow
  96.           test  DL,ST_EF_SF             ; - check for stack under/overflow
  97.           _quif e                       ; - quit if not stack under/overflow
  98.           test  DX,ST_C1                ; - check if underflow
  99.           _if   e                       ; - if underflow
  100.             mov CL,FPE_STACKUNDERFLOW   ; - - indicate stack underflow
  101.           _else                         ; - else
  102.             mov CL,FPE_STACKOVERFLOW    ; - - indicate stack overflow
  103.           _endif                        ; - endif
  104.         _admit                          ; guess invalid operation
  105.           test  DL,ST_EF_IO             ; - check for invalid operation
  106.           _quif e                       ; - quit if not invalid operation
  107.           call  InvalidOp               ; - process invalid operation
  108.         _admit                          ; guess denormal operand
  109.           test  DL,ST_EF_DO             ; - check for denormal operand
  110.           _quif e                       ; - quit if not denormal operand
  111.           mov   CL,FPE_DENORMAL         ; - indicate underflow
  112.         _admit                          ; guess overflow
  113.           test  DL,ST_EF_OF             ; - check for overflow
  114.           _quif e                       ; - quit if not overflow
  115.           call  KOOverFlow              ; - process overflow exception
  116.           mov   CL,FPE_OVERFLOW         ; - set floating point error code
  117.         _admit                          ; guess underflow
  118.           test  DL,ST_EF_UF             ; - check for underflow
  119.           _quif e                       ; - quit if not underflow
  120.           mov   CL,FPE_UNDERFLOW        ; - indicate underflow
  121.         _admit                          ; guess divide by 0
  122.           test  DL,ST_EF_ZD             ; - check for divide by zero
  123.           _quif e                       ; - quit if not divide by zero
  124.           call  GetInf                  ; - process divide by zero
  125.           mov   CL,FPE_ZERODIVIDE       ; - indicate divide by zero
  126.         _endguess                       ; endguess
  127.         _guess                          ; guess exception to be handled
  128.           cmp   CL,FPE_OK               ; - check if exception allowed
  129.           _quif e                       ; - quit if exception not allowed
  130.           movzx EAX,CL                  ; - set floating point status
  131.           call  __FPE_exception_        ; - call user's handler
  132.         _endguess                       ; endguess
  133.         fclex                           ; clear exceptions that may have
  134.                                         ; occurred as a result of handling the
  135.                                         ; exception
  136.         and     word ptr ENV_CW[EBP],0FF72h
  137.         fldcw   word ptr ENV_CW[EBP]    ; enable interrupts
  138.         fwait                           ; ...
  139.         add     ESP,ENV_SIZE            ; clean up stack
  140.         pop     EBP                     ; ...
  141.         pop     EDI                     ; ...
  142.         pop     ESI                     ; ...
  143.         pop     EDX                     ; ...
  144.         pop     ECX                     ; ...
  145.         pop     EBX                     ; ...
  146.         pop     EAX                     ; ...
  147.         ret                             ; return from interrupt handler
  148.  
  149. endproc __FPEHandler_
  150.  
  151. ; Process invalid operation.
  152.  
  153. InvalidOp proc near
  154.         mov   CL,FPE_INVALID            ; assume invalid operation
  155.         _guess                          ; guess it's square root
  156.           cmp   BX,0D9FAh               ; - ...
  157.           _quif ne                      ; - quit if it's not that instruction
  158.           mov   CL,FPE_SQRTNEG          ; - indicate sqrt(negative number)
  159.           ret                           ; - return
  160.         _endguess                       ; endguess
  161.         _guess                          ; guess it's square root
  162.           cmp   BX,0D9F1h               ; - ...
  163.           _quif ne                      ; - quit if it's not that instruction
  164.           mov   CL,FPE_LOGERR           ; - indicate sqrt(negative number)
  165.           ret                           ; - return
  166.         _endguess                       ; endguess
  167.         _guess                          ; guess: 'fprem' instruction
  168.           cmp   BX,0D9F8h               ; - check for 'fprem'   10-may-90
  169.           _if   ne                      ; - if not 'fprem'
  170.             cmp   BX,0D9F5h             ; - - check for 'fprem1'
  171.           _endif                        ; - endif
  172.           _quif ne                      ; - quit if not 'fprem' or 'fprem1'
  173.           mov   CL,FPE_MODERR           ; - indicate mod(negative number)
  174.         _admit                          ; guess: integer overflow
  175.           mov   DX,BX                   ; - save op code
  176.           and   DX,0310h                ; - check for fist/fistp instruction
  177.           cmp   DX,0310h                ; - ...
  178.           _quif ne                      ; - quit if its not that instruction
  179.           mov   CL,FPE_IOVERFLOW        ; - indicate integer overflow
  180.         _admit                          ; guess it's floating point underflow
  181. ;;        mov   DX,BX                   ; - save op code
  182.           and   DX,0110h                ; - check if fst or fstp instruction
  183.           cmp   DX,0110h                ; - ...
  184.           _quif ne                      ; - quit if it's not that instruction
  185. ; Destination is short or long real and source register is an unnormal
  186. ; with exponent in range.
  187.           fstp  st(0)                   ; - pop old result
  188.           fldz                          ; - load zero
  189.           mov   DL,BL                   ; - save op code
  190.           and   DL,0C0h                 ; - check the MOD bits of instruction
  191.           cmp   DL,0C0h                 ; - ...
  192.           _if   ne                      ; - if result to be placed in memory
  193.             call  Store                 ; - - store result in memory
  194.           _endif                        ; - endif
  195.           test  BL,08h                  ; - check if result to be popped
  196.           _if   ne                      ; - if result to be popped
  197.             fstp  st(0)                 ; - - pop the result
  198.           _endif                        ; - endif
  199.           mov   CL,FPE_UNDERFLOW        ; - indicate underflow
  200.         _admit                          ; guess it's divide
  201.           mov   DX,BX                   ; - save op code
  202.           and   DX,0130h                ; - check for fdiv/fidiv instruction
  203.           cmp   DX,0030h                ; - ...
  204.           _quif ne                      ; - quit if it's not that instruction
  205.           mov   DX,ENV_TW[EBP]          ; - get tag word
  206.           mov   CL,AH                   ; - get stack pointer
  207.           and   CL,38h                  ; - ...
  208.           shr   CL,2                    ; - ...
  209.           ror   DX,CL                   ; - make stack top low order bits
  210.           and   DL,05h                  ; - check if top two elements are 0
  211.           cmp   DL,05h                  ; - ...
  212.           _quif ne                      ; - quif if they are not 0
  213.           mov   CL,FPE_ZERODIVIDE       ; - indicate divide by zero
  214.         _endguess                       ; endguess
  215.         ret
  216. endproc InvalidOp
  217.  
  218.  
  219. ; Process overflow exception (note that only floating point overflows
  220. ; are handled - integer overflows are invalid operations).
  221.  
  222. KOOverFlow proc near
  223.         _guess                  ; guess: fscale instruction     10-may-90
  224.           cmp   BX,0D9FDh       ; - quit if not 'fscale' instruction
  225.           _quif ne              ; - ...
  226.         _admit                  ; guess: fst/fstp instruction
  227.           mov   DX,BX           ; - save op code
  228.           and   DX,0110h        ; - check if fst or fstp instruction
  229.           cmp   DX,0110h        ; - ...
  230.           _quif ne              ; - quit if not an fst/fstp instr.
  231.           call  GetInf          ; - load infinity
  232.           mov   DL,BL           ; - save op code
  233.           and   DL,0C0h         ; - check the MOD bits of instruction
  234.           cmp   DL,0C0h         ; - ...
  235.           _if   ne              ; - if result to be placed in memory
  236.             call Store          ; - - store infinity
  237.           _endif                ; - endif
  238.           test  BL,08h          ; - check if result to be popped
  239.           _if   ne              ; - if result to be popped
  240.             fstp  st(0)         ; - - pop result
  241.           _endif                ; - endif
  242.         _admit                  ; admit arithmetic operation
  243.           mov   DL,BL           ; - save op code
  244.           and   DL,0C0h         ; - check if both operands on stack
  245.           cmp   DL,0C0h         ; - ...
  246.           _quif ne              ; - quif both operands not on stack
  247. ;
  248. ; This code handles overflow on the following intructions:
  249. ;    fxxx   ST,ST(i)
  250. ;    fxxx   ST(i),ST    where xxx is one of mul,div,sub or add
  251. ;    fxxxp  ST(i),ST
  252. ;
  253.           lea   ESI,TInf        ; - load internal infinity
  254.           call  Load            ; - ...
  255.         _admit                  ; admit
  256. ;
  257. ; This admit block is to handle overflow on the following intructions:
  258. ;    fxxx   short real
  259. ;    fxxx   long real   where xxx is one of mul,div,sub or add
  260. ;
  261.           call  GetInf          ; - load infinity
  262.         _endguess               ; endguess
  263.         ret                     ; return
  264. endproc KOOverFlow
  265.  
  266.  
  267. ; Replace the top element of the stack with the appropriate signed
  268. ; infinity.
  269.  
  270. GetInf  proc    near
  271.         ftst                    ; get sign of result
  272.         fstsw   word ptr ENV_OP[EBP]
  273.         fstp    st(0)           ; pop argument off stack (does fwait)
  274.         test    BH,04h          ; check if single or double
  275.         _if     ne              ; if double
  276.           fld   qword ptr F8Inf ; - load double precision infinity
  277.         _else                   ; else
  278.           fld   dword ptr F4Inf ; - load single precision infinity
  279.         _endif                  ; endif
  280.         test    word ptr ENV_OP[EBP],ST_C0
  281.         _if     ne              ; if argument is negative
  282.           fchs                  ; - return negative infinity
  283.         _endif                  ; endif
  284.         ret                     ; return
  285. endproc GetInf
  286.  
  287.  
  288. ; Replace an element on the stack with internal zero or infinity.
  289.  
  290. Load    proc    near
  291.         test    BH,04h          ; check if result is top element
  292.         _if     e               ; if result is not top element
  293.           mov   DL,0            ; - indicate we are at the top
  294.         _else                   ; else
  295.           mov   DL,BL           ; - get st(i)
  296.           and   DL,07h          ; - . . .
  297.         _endif                  ; endif
  298.         push    EDX             ; save st(i)
  299.         _loop                   ; loop
  300.           dec   DL              ; - decrement counter
  301.           _quif l               ; - quit if we are at st(i)
  302.           fincstp               ; - increment stack pointer
  303.         _endloop                ; endloop
  304.         fstp    st(0)           ; free the stack element
  305.         fld     tbyte ptr [ESI] ; load internal zero
  306.         pop     EDX             ; get st(i)
  307.         _loop                   ; loop
  308.           dec   DL              ; - decrement counter
  309.           _quif l               ; - quit if we are at st(i)
  310.           fdecstp               ; - decrement stack pointer
  311.         _endloop                ; endloop
  312.         ret                     ; return
  313. endproc Load
  314.  
  315.  
  316. ; Store the top element of the stack at ES:EDI.
  317.  
  318. Store   proc    near
  319.         test    BH,04h
  320.         _if     ne                      ; if double
  321.           fst   qword ptr [EDI]         ; - store as double precision result
  322.         _else                           ; else
  323.           fst   dword ptr [EDI]         ; - store as single precision result
  324.         _endif                          ; endif
  325.         ret                             ; return
  326. endproc Store
  327.  
  328.         endmod
  329.         end
  330.