📄 flda386.asm
字号:
;*****************************************************************************
;*
;* 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 - add and subtract
;*
;* __FLDA add real*10 to real*10
;* __FLDAC add real*10 to real*10 (opnd 2 on stack)
;* __FLDS subtract real*10 from real*10
;* ___LDA long double add routine
;*
;*****************************************************************************
ifdef _BUILDING_MATHLIB
include mdef.inc
include struct.inc
include xception.inc
modstart flda386, dword
endif
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
;<>
;<> long double math library
;<>
;<> inputs: EAX - pointer to long double (op1)
;<> EDX - pointer to long double (op2)
;<> EBX - pointer to long double (result)
;<>
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
xdefp __FLDA ; add real*10 to real*10
xdefp __FLDAC ; add real*10 to real*10 (opnd 2 on stack)
xdefp __FLDS ; subtract real*10 from real*10
xdefp ___LDA ; long double add routine
defp __FLDS
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 ___LDS ; do the subtract
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
endproc __FLDS
defp __FLDA
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 ___LDA ; do the add
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
endproc __FLDA
defp __FLDAC
push ESI ; save ESI
push ECX ; save ECX
push EBX ; save EBX
mov SI,16+8[ESP] ; load op2 from stack
mov ECX,16+4[ESP] ; ...
mov EBX,16+0[ESP] ; ...
shl ESI,16 ; shift to the top
mov SI,8[EAX] ; load op1
mov EDX,4[EAX] ; ...
mov EAX,[EAX] ; ...
call ___LDA ; do the add
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 12 ; return and clean up stack
endproc __FLDAC
defp ___LDS
push EDI ; save EDI
mov EDI,80000000h ; indicate subtract
jmp __add ; do the add
;
; op1 is a NaN or infinity
;
addnan1:_guess ; guess:
dec SI ; - adjust low exponent
add ESI,10000h ; - increment high word
_quif c ; - quit if NaN
_quif o ; - ...
; op2 is not a NaN or infinity
pop EDI ; - restore EDI
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 ; - ...
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
_if e ; - if signs are same
or EDI,EDI ; - - if 'subtract'
jne short addnan3 ; - - then return -NaN
_else ; - else
or EDI,EDI ; - - if 'add'
_if e ; - - then
addnan3: sar EDX,1 ; - - - answer is -NaN
mov SI,0FFFFh ; - - - ...
_endif ; - - endif
_endif ; - endif
_admit ; 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
_if e ; - if op1 == op2
or EDI,EDI ; - - check for 'add'
_endif ; - endif
_quif e ; - quit if 'add'
mov EDX,ECX ; - load op2
mov EAX,EBX ; - ...
shr ESI,16 ; - ...
_endguess ; endguess
pop EDI ; restore EDI
ret ; return
;
; op1 is not a NaN or infinity, but op2 is
;
addnan2:mov EDX,ECX ; return op2
mov EAX,EBX ; ...
sub ESI,10000h ; readjust high exponent
_guess ; guess: op2 is infinity
or EAX,EAX ; - quit if op2 not infinity
_quif ne ; - ...
cmp EDX,80000000h ; - ...
_quif ne ; - ...
xor ESI,EDI ; - flip sign if 'subtract'
_endguess ; endguess
shr ESI,16 ; shift exponent to bottom
pop EDI ; restore EDI
ret ; return
endproc ___LDS
defp ___LDA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -