div386.asm

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

ASM
308
字号
;*****************************************************************************
;*
;*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
;*               DESCRIBE IT HERE!
;*
;*****************************************************************************


;
include mdef.inc
include struct.inc

.8087
        modstart        div386

        xref            __8087  ; indicate that NDP instructions are present

        datasegment
        extrn   __real87 : byte         ; 8087.asm
        extrn   __chipbug: byte
        enddata

        xref    F8DivZero       ; Fstatus
        xref    F8OverFlow      ; Fstatus
        xref    F8UnderFlow     ; Fstatus
        xref    __fdiv_m64

        xdefp   __FDD

;  double __FDD( double , double )
sign    equ     -12
den     equ     sign-8
quot    equ     den-12
lo      equ     0
hi      equ     4

        defpe   __FDD
        or      EBX,EBX                 ; if low word of divisor is 0
        _if     e                       ; then
          _shl  ECX,1                   ; - shift sign of divisor into carry
          _if   e                       ; - if divisor is zero
            jmp   F8DivZero             ; - - handle divide by zero
          _endif                        ; - endif
          rcr   ECX,1                   ; - restore sign of divisor
        _endif                          ; endif
        or      EAX,EAX                 ; check dividend for zero
        _if     e                       ; if so then
          _shl  EDX,1                   ; - save sign of dividend
          _if   e                       ; - if dividend is 0
            ret                         ; - - return
          _endif                        ; - endif
          rcr   EDX,1                   ; - restore sign of dividend
        _endif                          ; endif

        cmp     byte ptr __real87,0     ; if no 80x87 is present
        je      short __FDDemu          ; then emulate

__FDD87:
        push    EDX                     ; push operand 1
        push    EAX                     ; . . .
        fld     qword ptr [ESP]         ; load operand 1
        push    ECX                     ; push operand 2
        push    EBX                     ; . . .
        test    byte ptr __chipbug,1    ; have we got a bad divider?
        _if     ne                      ; then
          call  __fdiv_m64              ; - call support rtn for divide
        _else                           ; else
          fdiv  qword ptr [ESP]         ; - divide operand 1 by operand 2
          add   ESP,8                   ; - clean up stack
        _endif                          ; endif
        fstp    qword ptr [ESP]         ; store result
        fwait                           ; wait
        pop     EAX                     ; load result into DX:AX
        pop     EDX                     ; . . .
        cmp     EDX,80000000H           ; is it a negative zero?
        _if     e                       ; if it is then
          sub   EDX,EDX                 ; - make it positive 0.0
          mov   EAX,EDX                 ; - ...
        _endif                          ; endif
        ret                             ; return

__FDDemu:
        push    EBP                     ; save EBP
        mov     EBP,ESP                 ; get access to stack
        push    EDI                     ; save EDI
        push    ESI                     ; and ESI

        mov     EDI,EDX                 ; get high part of op1
        mov     ESI,ECX                 ; get high part of op2
        sar     EDI,20          ; shift exponent to bottom, duplicating sign
        sar     ECX,20          ; shift exponent to bottom, duplicating sign
        and     EDI,0800007FFh          ; isolate signs and exponent
        and     ECX,0800007FFh          ; ...
        rol     EDI,16                  ; rotate signs to bottom
        rol     ECX,16                  ; ...
        add     DI,CX                   ; calc sign of result
        rol     EDI,16                  ; rotate signs to top
        rol     ECX,16                  ; ...
        and     EDX,000FFFFFh           ; isolate fraction
        and     ESI,000FFFFFh           ; isolate fraction
        or      DI,DI                   ; if op1 is not a denormal
        _if     ne                      ; then
          or    EDX,00100000h           ; - turn on implied 1 bit
        _else                           ; else (denormal)
          _loop                         ; - loop (normalize it)
            _shl  EAX,1                 ; - - shift fraction left
            _rcl  EDX,1                 ; - - . . .
            dec   DI                    ; - - decrement exponent
            test  EDX,00100000h         ; - - until implied 1 bit is on
          _until  ne                    ; - until implied 1 bit is on
        _endif                          ; endif
        or      CX,CX                   ; if op2 is not a denormal
        _if     ne                      ; then
          or    ESI,00100000h           ; - turn on implied 1 bit
        _else                           ; else (denormal)
          _loop                         ; - loop (normalize it)
            _shl  EBX,1                 ; - - shift fraction left
            _rcl  ESI,1                 ; - - . . .
            dec   CX                    ; - - decrement exponent
            test  ESI,00100000h         ; - - until implied 1 bit is on
          _until  ne                    ; - until implied 1 bit is on
        _endif                          ; endif

        sub     DI,CX                   ; calculate exponent of result
        add     DI,03ffh                ; add in removed bias
        _guess                          ; guess: overflow
          _quif s                       ; - quit if exponent is negative
          cmp   DI,07FFh                ; - quit if not overflow
          _quif b                       ; - . . .
          mov   EAX,ECX                 ; - put sign into EAX

⌨️ 快捷键说明

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