Subversion Repositories Kolibri OS

Rev

Rev 703 | 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. ifndef  __NETWARE__
  44.         xref            __GETDS
  45. endif
  46.         xref            __8087  ; indicate that NDP instructions are present
  47.  
  48.         modstart        fpeinth
  49.  
  50.         datasegment
  51.  
  52.         extrn   __FPE_exception_: proc
  53.         extrn   "C",_STACKLOW   : dword
  54.  
  55. TInf    db 00h,00h,00h,00h,00h,00h,00h,80h,0ffh,7fh
  56. F8Inf   db 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0efh,7fh
  57. F4Inf   db 0ffh,0ffh,7fh,7fh
  58.         db      512 dup(0)
  59. FPEStk  label byte
  60. SaveSS  dw      0
  61. SaveESP dd      0
  62.         enddata
  63.  
  64.  
  65. ; Interrupt handler for 80x87 exceptions.
  66.  
  67. xdefp   __FPEHandler_
  68. defp    __FPEHandler_
  69. public "C",__FPEHandlerStart_
  70. __FPEHandlerStart_ label byte
  71.         push    EAX                     ; save reg
  72.         mov     AL,20h                  ; issue EOI to 8259 controller
  73.         out     20h,AL                  ; ...
  74.         out     0a0h,AL                 ; issue EOI to slave 8259
  75.         xor     AX,AX                   ; clear busy signal
  76.         out     0f0h,AL                 ; ...
  77.         pop     EAX                     ; restore regs
  78. public  __FPE2Handler_
  79. __FPE2Handler_ label byte
  80.         push    EAX                     ; save regs
  81.         push    EBX                     ; ...
  82.         push    ECX                     ; ...
  83.         push    EDX                     ; ...
  84.         push    ESI                     ; ...
  85.         push    EDI                     ; ...
  86.         push    EBP                     ; ...
  87.         push    DS                      ; ...
  88.         push    ES                      ; ...
  89.         sub     ESP,ENV_SIZE            ; make room for environment information
  90.         mov     EBP,ESP                 ; point to buffer for 80x87 environment
  91.         fnstenv [EBP]                   ; get 80x87 environment
  92.         fwait                           ; wait for 80x87
  93.         fdisi                           ; disable interrupts
  94.         sti                             ; enable CPU interrupts
  95. ifndef  __NETWARE__
  96.      ;   call    __GETDS                 ; load DS
  97. endif
  98. ifdef __NETWARE__
  99.       ;  push    SS                      ; load DS
  100.       ;  pop     DS                      ; ...
  101. endif
  102.         mov     EDX,ENV_CW[EBP]         ; get control word
  103.         not     EDX                     ; flip the mask bits
  104.         mov     DH,0FFh                 ; turn on top byte
  105.         and     EDX,ENV_SW[EBP]         ; get status word
  106.       ;  mov     ES,ENV_IP+4[EBP]        ; get intruction address
  107.         mov     EDI,ENV_IP[EBP]         ; ...
  108. opcode: mov     BX,[EDI]                ; get opcode
  109.         inc     EDI                     ; point to next opcode
  110.         cmp     BL,0d8h                 ; check if its the opcode
  111.         jb      opcode                  ; ...
  112.         cmp     BL,0dfh                 ; ...
  113.         ja      opcode                  ; ...
  114.       ;  mov     ES,ENV_OP+4[EBP]        ; get pointer to operand
  115.         mov     EDI,ENV_OP[EBP]         ; ...
  116.         xchg    BL,BH                   ; get opcode in right position
  117.         mov     CL,FPE_OK               ; assume exception to be ignored
  118.         _guess                          ; guess precision exception
  119.           test  DL,ST_EF_PR             ; - check for precision exception
  120.           _quif e                       ; - quit if not precision exception
  121.           mov   CL,FPE_INEXACT          ; - indicate precision exception
  122.         _admit                          ; guess stack under/overflow
  123.           test  DL,ST_EF_SF             ; - check for stack under/overflow
  124.           _quif e                       ; - quit if not stack under/overflow
  125.           test  DX,ST_C1                ; - check if underflow
  126.           _if   e                       ; - if underflow
  127.             mov CL,FPE_STACKUNDERFLOW   ; - - indicate stack underflow
  128.           _else                         ; - else
  129.             mov CL,FPE_STACKOVERFLOW    ; - - indicate stack overflow
  130.           _endif                        ; - endif
  131.         _admit                          ; guess invalid operation
  132.           test  DL,ST_EF_IO             ; - check for invalid operation
  133.           _quif e                       ; - quit if not invalid operation
  134.           call  InvalidOp               ; - process invalid operation
  135.         _admit                          ; guess denormal operand
  136.           test  DL,ST_EF_DO             ; - check for denormal operand
  137.           _quif e                       ; - quit if not denormal operand
  138.           mov   CL,FPE_DENORMAL         ; - indicate underflow
  139.         _admit                          ; guess overflow
  140.           test  DL,ST_EF_OF             ; - check for overflow
  141.           _quif e                       ; - quit if not overflow
  142.           call  KOOverFlow              ; - process overflow exception
  143.           mov   CL,FPE_OVERFLOW         ; - set floating point error code
  144.         _admit                          ; guess underflow
  145.           test  DL,ST_EF_UF             ; - check for underflow
  146.           _quif e                       ; - quit if not underflow
  147.           mov   CL,FPE_UNDERFLOW        ; - indicate underflow
  148.         _admit                          ; guess divide by 0
  149.           test  DL,ST_EF_ZD             ; - check for divide by zero
  150.           _quif e                       ; - quit if not divide by zero
  151.           call  GetInf                  ; - process divide by zero
  152.           mov   CL,FPE_ZERODIVIDE       ; - indicate divide by zero
  153.         _endguess                       ; endguess
  154.         _guess                          ; guess exception to be handled
  155.           cmp   CL,FPE_OK               ; - check if exception allowed
  156.           _quif e                       ; - quit if exception not allowed
  157. ;         cmp   SaveSS,0                ; - check if already in handler
  158. ;         _quif ne                      ; - quit if already in handler
  159.           push  _STACKLOW               ; - save old stack low
  160.           mov   SaveSS,SS               ; - save current stack pointer
  161.           mov   SaveESP,ESP             ; - ...
  162.           push  DS                      ; - get new stack pointer
  163.           pop   SS                      ; - ...
  164.           lea   ESP,FPEStk              ; - ...
  165.           lea   EAX,FPEStk-512          ; - set stack low variable
  166.           mov   _STACKLOW,EAX           ; - set stack low variable
  167.           movzx EAX,CL                  ; - set floating point status
  168.           call  __FPE_exception_        ; - call user's handler
  169.           mov   SS,SaveSS               ; - restore stack pointer
  170.           mov   ESP,SaveESP             ; - ...
  171.           pop   _STACKLOW               ; - restore old stacklow
  172.           mov   SaveSS,0                ; - indicate handler can be re-entered
  173.         _endguess                       ; endguess
  174.         fclex                           ; clear exceptions that may have
  175.                                         ; occurred as a result of handling the
  176.                                         ; exception
  177.         and     word ptr ENV_CW[EBP],0FF72h
  178.         fldcw   word ptr ENV_CW[EBP]    ; enable interrupts
  179.         fwait                           ; ...
  180.         add     ESP,ENV_SIZE            ; clean up stack
  181.         pop     ES                      ; restore registers
  182.         pop     DS                      ; ...
  183.         pop     EBP                     ; ...
  184.         pop     EDI                     ; ...
  185.         pop     ESI                     ; ...
  186.         pop     EDX                     ; ...
  187.         pop     ECX                     ; ...
  188.         pop     EBX                     ; ...
  189.         pop     EAX                     ; ...
  190.         iretd                           ; return from interrupt handler
  191. public  "C",__FPEHandlerEnd_
  192. __FPEHandlerEnd_ label byte
  193. endproc __FPEHandler_
  194.  
  195.  
  196. ; Process invalid operation.
  197.  
  198. InvalidOp proc near
  199.         mov   CL,FPE_INVALID            ; assume invalid operation
  200.         _guess                          ; guess it's square root
  201.           cmp   BX,0D9FAh               ; - ...
  202.           _quif ne                      ; - quit if it's not that instruction
  203.           mov   CL,FPE_SQRTNEG          ; - indicate sqrt(negative number)
  204.           ret                           ; - return
  205.         _endguess                       ; endguess
  206.         _guess                          ; guess it's square root
  207.           cmp   BX,0D9F1h               ; - ...
  208.           _quif ne                      ; - quit if it's not that instruction
  209.           mov   CL,FPE_LOGERR           ; - indicate sqrt(negative number)
  210.           ret                           ; - return
  211.         _endguess                       ; endguess
  212.         _guess                          ; guess: 'fprem' instruction
  213.           cmp   BX,0D9F8h               ; - check for 'fprem'   10-may-90
  214.           _if   ne                      ; - if not 'fprem'
  215.             cmp   BX,0D9F5h             ; - - check for 'fprem1'
  216.           _endif                        ; - endif
  217.           _quif ne                      ; - quit if not 'fprem' or 'fprem1'
  218.           mov   CL,FPE_MODERR           ; - indicate mod(negative number)
  219.         _admit                          ; guess: integer overflow
  220.           mov   DX,BX                   ; - save op code
  221.           and   DX,0310h                ; - check for fist/fistp instruction
  222.           cmp   DX,0310h                ; - ...
  223.           _quif ne                      ; - quit if its not that instruction
  224.           mov   CL,FPE_IOVERFLOW        ; - indicate integer overflow
  225.         _admit                          ; guess it's floating point underflow
  226. ;;        mov   DX,BX                   ; - save op code
  227.           and   DX,0110h                ; - check if fst or fstp instruction
  228.           cmp   DX,0110h                ; - ...
  229.           _quif ne                      ; - quit if it's not that instruction
  230. ; Destination is short or long real and source register is an unnormal
  231. ; with exponent in range.
  232.           fstp  st(0)                   ; - pop old result
  233.           fldz                          ; - load zero
  234.           mov   DL,BL                   ; - save op code
  235.           and   DL,0C0h                 ; - check the MOD bits of instruction
  236.           cmp   DL,0C0h                 ; - ...
  237.           _if   ne                      ; - if result to be placed in memory
  238.             call  Store                 ; - - store result in memory
  239.           _endif                        ; - endif
  240.           test  BL,08h                  ; - check if result to be popped
  241.           _if   ne                      ; - if result to be popped
  242.             fstp  st(0)                 ; - - pop the result
  243.           _endif                        ; - endif
  244.           mov   CL,FPE_UNDERFLOW        ; - indicate underflow
  245.         _admit                          ; guess it's divide
  246.           mov   DX,BX                   ; - save op code
  247.           and   DX,0130h                ; - check for fdiv/fidiv instruction
  248.           cmp   DX,0030h                ; - ...
  249.           _quif ne                      ; - quit if it's not that instruction
  250.           mov   DX,ENV_TW[EBP]          ; - get tag word
  251.           mov   CL,AH                   ; - get stack pointer
  252.           and   CL,38h                  ; - ...
  253.           shr   CL,2                    ; - ...
  254.           ror   DX,CL                   ; - make stack top low order bits
  255.           and   DL,05h                  ; - check if top two elements are 0
  256.           cmp   DL,05h                  ; - ...
  257.           _quif ne                      ; - quif if they are not 0
  258.           mov   CL,FPE_ZERODIVIDE       ; - indicate divide by zero
  259.         _endguess                       ; endguess
  260.         ret
  261. endproc InvalidOp
  262.  
  263.  
  264. ; Process overflow exception (note that only floating point overflows
  265. ; are handled - integer overflows are invalid operations).
  266.  
  267. KOOverFlow proc near
  268.         _guess                  ; guess: fscale instruction     10-may-90
  269.           cmp   BX,0D9FDh       ; - quit if not 'fscale' instruction
  270.           _quif ne              ; - ...
  271.         _admit                  ; guess: fst/fstp instruction
  272.           mov   DX,BX           ; - save op code
  273.           and   DX,0110h        ; - check if fst or fstp instruction
  274.           cmp   DX,0110h        ; - ...
  275.           _quif ne              ; - quit if not an fst/fstp instr.
  276.           call  GetInf          ; - load infinity
  277.           mov   DL,BL           ; - save op code
  278.           and   DL,0C0h         ; - check the MOD bits of instruction
  279.           cmp   DL,0C0h         ; - ...
  280.           _if   ne              ; - if result to be placed in memory
  281.             call Store          ; - - store infinity
  282.           _endif                ; - endif
  283.           test  BL,08h          ; - check if result to be popped
  284.           _if   ne              ; - if result to be popped
  285.             fstp  st(0)         ; - - pop result
  286.           _endif                ; - endif
  287.         _admit                  ; admit arithmetic operation
  288.           mov   DL,BL           ; - save op code
  289.           and   DL,0C0h         ; - check if both operands on stack
  290.           cmp   DL,0C0h         ; - ...
  291.           _quif ne              ; - quif both operands not on stack
  292. ;
  293. ; This code handles overflow on the following intructions:
  294. ;    fxxx   ST,ST(i)
  295. ;    fxxx   ST(i),ST    where xxx is one of mul,div,sub or add
  296. ;    fxxxp  ST(i),ST
  297. ;
  298.           lea   ESI,TInf        ; - load internal infinity
  299.           call  Load            ; - ...
  300.         _admit                  ; admit
  301. ;
  302. ; This admit block is to handle overflow on the following intructions:
  303. ;    fxxx   short real
  304. ;    fxxx   long real   where xxx is one of mul,div,sub or add
  305. ;
  306.           call  GetInf          ; - load infinity
  307.         _endguess               ; endguess
  308.         ret                     ; return
  309. endproc KOOverFlow
  310.  
  311.  
  312. ; Replace the top element of the stack with the appropriate signed
  313. ; infinity.
  314.  
  315. GetInf  proc    near
  316.         ftst                    ; get sign of result
  317.         fstsw   word ptr ENV_OP[EBP]
  318.         fstp    st(0)           ; pop argument off stack (does fwait)
  319.         test    BH,04h          ; check if single or double
  320.         _if     ne              ; if double
  321.           fld   qword ptr F8Inf ; - load double precision infinity
  322.         _else                   ; else
  323.           fld   dword ptr F4Inf ; - load single precision infinity
  324.         _endif                  ; endif
  325.         test    word ptr ENV_OP[EBP],ST_C0
  326.         _if     ne              ; if argument is negative
  327.           fchs                  ; - return negative infinity
  328.         _endif                  ; endif
  329.         ret                     ; return
  330. endproc GetInf
  331.  
  332.  
  333. ; Replace an element on the stack with internal zero or infinity.
  334.  
  335. Load    proc    near
  336.         test    BH,04h          ; check if result is top element
  337.         _if     e               ; if result is not top element
  338.           mov   DL,0            ; - indicate we are at the top
  339.         _else                   ; else
  340.           mov   DL,BL           ; - get st(i)
  341.           and   DL,07h          ; - . . .
  342.         _endif                  ; endif
  343.         push    EDX             ; save st(i)
  344.         _loop                   ; loop
  345.           dec   DL              ; - decrement counter
  346.           _quif l               ; - quit if we are at st(i)
  347.           fincstp               ; - increment stack pointer
  348.         _endloop                ; endloop
  349.         fstp    st(0)           ; free the stack element
  350.         fld     tbyte ptr [ESI] ; load internal zero
  351.         pop     EDX             ; get st(i)
  352.         _loop                   ; loop
  353.           dec   DL              ; - decrement counter
  354.           _quif l               ; - quit if we are at st(i)
  355.           fdecstp               ; - decrement stack pointer
  356.         _endloop                ; endloop
  357.         ret                     ; return
  358. endproc Load
  359.  
  360.  
  361. ; Store the top element of the stack at ES:EDI.
  362.  
  363. Store   proc    near
  364.         test    BH,04h
  365.         _if     ne                      ; if double
  366.           fst   qword ptr ES:[EDI]      ; - store as double precision result
  367.         _else                           ; else
  368.           fst   dword ptr ES:[EDI]      ; - store as single precision result
  369.         _endif                          ; endif
  370.         ret                             ; return
  371. endproc Store
  372.  
  373.         endmod
  374.         end
  375.