Subversion Repositories Kolibri OS

Rev

Rev 702 | Rev 1075 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
703 serge 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