fldm086.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 439 行 · 第 1/2 页
ASM
439 行
ifdef _BUILDING_MATHLIB
include mdef.inc
include struct.inc
include xception.inc
modstart fldm086, word
endif
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
;<>
;<> long double math library
;<>
;<> inputs: AX - pointer to long double (op1)
;<> DX - pointer to long double (op2)
;<> BX - pointer to long double (result)
;<>
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
xdefp __FLDM ; 10-byte real multiply
xdefp ___LDM ; 10-byte real multiply
;=====================================================================
defp __FLDM
ifdef _BUILDING_MATHLIB
push DS ; save DS
push SS ; fpc code assumes parms are relative to SS
pop DS ; ...
endif
push SI ; save SI
push DI ; save DI
push CX ; save CX
push BX ; save pointer to result
mov SI,AX ; point to op1
mov DI,DX ; point to op2
lcall ___LDM ; do the multiply
pop DI ; restore pointer to result
mov [DI],DX ; store result
mov 2[DI],CX ; ...
mov 4[DI],BX ; ...
mov 6[DI],AX ; ...
mov 8[DI],SI ; ...
pop CX ; restore CX
pop DI ; restore DI
pop SI ; restore SI
ifdef _BUILDING_MATHLIB
pop DS ; restore DS
endif
ret ; return
endproc __FLDM
defp __FLDMC
ifdef _BUILDING_MATHLIB
push DS ; save DS
push SS ; fpc code assumes parms are relative to SS
pop DS ; ...
endif
push SI ; save SI
push DI ; save DI
push CX ; save CX
push BX ; save pointer to result
mov SI,AX ; point to op1
mov DI,DX ; point to op2
push CS:8[DI] ; push constant op2 onto stack
push CS:6[DI] ; ...
push CS:4[DI] ; ...
push CS:2[DI] ; ...
push CS:[DI] ; ...
mov DI,SP ; point to op2
lcall ___LDM ; do the multiply
add SP,10 ; remove constant from stack
pop DI ; restore pointer to result
mov [DI],DX ; store result
mov 2[DI],CX ; ...
mov 4[DI],BX ; ...
mov 6[DI],AX ; ...
mov 8[DI],SI ; ...
pop CX ; restore CX
pop DI ; restore DI
pop SI ; restore SI
ifdef _BUILDING_MATHLIB
pop DS ; restore DS
endif
ret ; return
endproc __FLDMC
defp mul_oflow ; overflow
mov SI,CX ; get sign
or SI,7FFFh ; set exponent for infinity
mov AX,8000h ; set fraction
sub BX,BX ; ...
mov CX,BX ; ...
mov DX,BX ; ...
ifdef _BUILDING_MATHLIB
pop DS ; restore DS
endif
ret ; return
endproc mul_oflow
;
; input:
; DI - pointer to operand
; AX - sign+exponent of op1
; DX - sign+exponent of op2
;
defp mul_by_pow2
mov CX,AX ; calc. sign of result
xor CX,DX ; ...
and CX,8000h ; ...
and AX,7FFFh ; isolate exponent
and DX,7FFFh ; ...
_guess ; guess: overflow
cmp AX,7FFFh ; - see if op1 was infinity 06-nov-92
je mul_oflow ; - answer is infinity
cmp DX,7FFFh ; - see if op2 was infinity
je mul_oflow ; - answer is infinity
add AX,DX ; - determine exponent of result
sub AX,3FFFh ; - remove extra bias
_quif c ; - quit if exponent is negative
cmp AX,7FFFh ; - check for overflow
jae mul_oflow ; - . . .
_endguess ; endguess
cmp AX,-64 ; if exponent is too small
_if l ; then underflow
sub AX,AX ; - set result to 0
mov BX,AX ; - ...
mov CX,AX ; - ...
mov DX,AX ; - ...
mov SI,AX ; - ...
ifdef _BUILDING_MATHLIB
pop DS ; - restore DS
endif
ret ; - return
_endif ; endif
push CX ; save sign
mov SI,AX ; get exponent
mov AX,6[DI] ; load mantissa
mov BX,4[DI] ; ...
mov CX,2[DI] ; ...
mov DX,[DI] ; ...
pop DI ; restore sign
or SI,SI ; if denormal number
_if s ; then
_loop ; - loop
shr AX,1 ; - - shift number right
rcr BX,1 ; - - ...
rcr CX,1 ; - - ...
rcr DX,1 ; - - ...
inc SI ; - - increment exponent
_until e ; - until done
_endif ; endif
or SI,DI ; get sign
ifdef _BUILDING_MATHLIB
pop DS ; restore DS
endif
ret ; return
endproc mul_by_pow2
; input:
; SI - pointer to op1
; DI - pointer to op2
; output:
; SI - exponent+sign of result
; AX:BX:CX:DX - mantissa
defp ___LDM
ifdef _BUILDING_MATHLIB
push DS ; save DS
push SS ; fpc code assumes parms are relative to SS
pop DS ; ...
endif
mov AX,8[SI] ; get exponent+sign of op1
mov DX,8[DI] ; get exponent+sign of op2
_guess ; guess: op1 is 0
sub BX,BX ; - counter for number of zeros
mov CX,[SI] ; - quit if op1 is not 0
or CX,CX ; - ...
_quif ne ; - ...
inc BX ; - op1 has at least 1 zero
or CX,2[SI] ; - check the higher order words
_quif ne ; - ...
inc BX ; - op1 has at least 2 zeros
or CX,4[SI] ; - ...
_quif ne ; - ...
inc BX ; - op1 has at least 3 zeros
or CX,6[SI] ; - ...
; if CX = 8000h, then op1 is a power of 2, just return op2 with
; appropriate sign and exponent
cmp CX,8000h ; - if op1 is a power of 2
jne l1
pow2_hop: jmp mul_by_pow2 ; - then do special calc.
l1: or CX,CX ; - test high order word
_quif ne ; - quit if op1 is not 0
_shl AX,1 ; - place sign in carry
_if e ; - if operand one is 0
mov BX,AX ; - - set result to 0
mov DX,AX ; - - ...
mov SI,AX ; - - ...
ifdef _BUILDING_MATHLIB
pop DS ; - - restore DS
endif
ret ; - - return
_endif ; - endif
rcr AX,1 ; - put back the sign
_endguess ; endguess
_guess ; guess: op2 is 0
mov CX,[DI] ; - quit if op2 is not 0
or CX,CX ; - ...
_quif ne ; - ...
dec BX ; - decrement counter
or CX,2[DI] ; - check the higher order words
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?