fldd386.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 392 行 · 第 1/2 页
ASM
392 行
;*****************************************************************************
;*
;* 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: long double math library - divide __FLDD, ___LDD
;*
;*****************************************************************************
ifdef _BUILDING_MATHLIB
include mdef.inc
include struct.inc
include xception.inc
xref F8DivZero
xref F8InvalidOp
modstart fldd386, dword
endif
xdefp __FLDD
xdefp ___LDD
; void __FLDD( long double *op1 , long double *op2, long double *result )
; EAX - pointer to op1
; EDX - pointer to op2
; EBX - pointer for result
;
sign equ -8
den equ sign-8
quot equ den-12
lo equ 0
hi equ 4
defp __FLDD
push ESI ; save ESI
push ECX ; save ECX
push EBX ; save EBX
mov SI,8[EDX] ; load op2
mov ECX,4[EDX] ; ...
mov EBX,[EDX] ; ...
shl ESI,16 ; shift to the top
mov SI,8[EAX] ; load op1
mov EDX,4[EAX] ; ...
mov EAX,[EAX] ; ...
call ___LDD ; do the divide
pop EBX ; restore pointer to result
mov [EBX],EAX ; store result
mov 4[EBX],EDX ; ...
mov 8[EBX],SI ; ...
pop ECX ; restore ECX
pop ESI ; restore ESI
ret ; return
;
; op1 is a NaN or infinity
;
divnan1:_guess ; guess:
dec SI ; - adjust low exponent
add ESI,10000h ; - increment high exponent
_quif c ; - quit if NaN
_quif o ; - ...
; op2 is not a NaN or infinity
_if s ; - if op2 is negative
or EAX,EAX ; - - check low word of op1
_if e ; - - if could be infinity
cmp EDX,80000000h;- - - check high word
_endif ; - - endif
_if e ; - - if op1 is infinity
xor SI,8000h ; - - - flip the sign of op1
_endif ; - - endif
_endif ; - endif
ret ; - return op1
_endguess ; endguess
sub ESI,10000h ; readjust high exponent
;
; both operands are NaNs and/or infinity
;
_guess ; guess: both are infinities
or EAX,EAX ; - quit if not infinity
_quif ne ; - ...
or EBX,EBX ; - ...
_quif ne ; - ...
cmp EDX,80000000h ; - ...
_quif ne ; - ...
cmp ECX,EDX ; - ...
_quif ne ; - ...
sar EDX,1 ; - return -NaN
mov SI,0FFFFh ; - ...
ret ; - return
_endguess ; endguess
_guess ; guess: fabs(op1) < fabs(op2)
cmp EDX,ECX ; - compare high words
_if e ; - if high words equal
cmp EAX,EBX ; - - compare low words
; _if e ; - - if low words equal
; mov EAX,ESI ; - - - get signs and exponents
; shr EAX,16 ; - - - shift op2 sign+exponent to bottom
; cmp SI,AX ; - - - compare sign+exponents
; mov EAX,EBX ; - - - restore EAX
; _endif ; - - endif
_endif ; - endif
_quif a ; - quit if op1 > op2
mov EDX,ECX ; - load op2
mov EAX,EBX ; - ...
shr ESI,16 ; - ...
_endguess ; endguess
ret ; return
;
; op1 is not a NaN or infinity, but op2 is
;
divnan2:sub ESI,10000h ; readjust high exponent
_guess ; guess: op2 is +/- inf
or EBX,EBX ; - quit if op2 is not inf
_quif ne ; - ...
cmp ECX,80000000h ; - ...
_quif ne ; - ...
mov EAX,ESI ; - get signs
shl EAX,16 ; - get sign of op1 to top
xor ESI,EAX ; - get xor of signs
and ESI,ECX ; - just keep the sign bit
sub ECX,ECX ; - return +/- 0
_endguess ; endguess
mov EDX,ECX ; return op2
mov EAX,EBX ; ...
shr ESI,16 ; get exponent of op2
ret ; return
endproc __FLDD
defp ___LDD
add SI,1 ; add 1 to exponent
jc divnan1 ; quit if NaN
jo divnan1 ; ...
add ESI,0FFFFh ; readjust low exponent and inc high word
jc short divnan2 ; quit if NaN
jo short divnan2 ; ...
sub ESI,10000h ; readjust high exponent
_guess ; guess: divide by 0
or ECX,ECX ; - quit if op2 is not 0
_quif ne ; - ...
or EBX,EBX ; - quit if op2 is not 0
_quif ne ; - ...
test ESI,7FFF0000h ; - quit if op2's exponent is not 0
_quif ne ; - ...
_guess ; - guess: 0/0 (invalid operation)
or EAX,EAX ; - - quit if op1 is not 0
_quif ne ; - - ...
or EDX,EDX ; - - quit if op1 is not 0
_quif ne ; - - ...
mov EAX,ESI ; - - get exponent
_shl AX,1 ; - - place sign in carry
_quif ne ; - - quit if op1 not 0
call F8InvalidOp ; - - indicate invalid operation
mov EDX,0C0000000h ; - - return NaN
sub EAX,EAX ; - - ...
mov SI,0FFFFh ; - - ...
_admit ; - admit: zero divide
call F8DivZero ; - - invoke zero divide exception
mov EDX,80000000h ; - - return signed infinity
sub EAX,EAX ; - - ...
or SI,7FFFh ; - - ...
_endguess ; - endguess
ret ; - return
_endguess ; endguess
_guess ; guess: op1 is 0
or EAX,EAX ; - quit if op1 is not 0
_quif ne ; - ...
or EDX,EDX ; - quit if op1 is not 0
_quif ne ; - ...
_shl SI,1 ; - place sign in carry
_if e ; - if operand one is 0
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?