fdmth386.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 485 行 · 第 1/2 页
ASM
485 行
;*****************************************************************************
;*
;* 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: REAL*8 math library.
;*
;*****************************************************************************
;
; inputs: EDX,EAX - operand 1 (high word, low word resp. ) (op1)
; ECX,EBX - operand 2 (op2)
;
; operations are performed as op1 (*) op2 where (*) is the selected
; operation
;
; output: EDX,EAX - result (high word, low word resp. )
;
;
include mdef.inc
include struct.inc
.8087
modstart fdmth386
xref __8087 ; indicate that NDP instructions are present
datasegment
extrn __real87 : byte ; 8087.asm
enddata
xref F8DivZero ; Fstatus
xref F8OverFlow ; Fstatus
xref F8UnderFlow ; Fstatus
xdefp __FDA ; add real*8 to real*8
xdefp __FDS ; subtract real*8 from real*8
xdefp __FDM ; 8-byte real multiply
defpe __FDS
xor ECX,80000000h ; flip the sign of op2 and add
defpe __FDA
or EBX,EBX ; if low word of op2 is 0
_if e ; then
_shl ECX,1 ; - place sign in carry
je ret_op1 ; - if op2 is 0 then return operand 1
rcr ECX,1 ; - put sign back
_endif ; endif
or EAX,EAX ; if op1 is 0
_if e ; then
_shl EDX,1 ; - place sign in carry
_if e ; - if op1 really is 0
mov EDX,ECX ; - - return operand 2
mov EAX,EBX ; - - . . .
ret_op1: ret ; - - return
_endif ; - endif
rcr EDX,1 ; - put sign back
_endif ; endif
cmp byte ptr __real87,0; if 8087 not to be used
je short __FDAemu ; then emulate
__FDA87:
push EDX ; push operand 1
push EAX ; . . .
fld qword ptr [ESP] ; load operand 1
push ECX ; push operand 2
push EBX ; . . .
fadd qword ptr [ESP] ; add operand 2 to operand 1
_ret87:
fstp qword ptr 8[ESP]; store result
add ESP,8 ; clean up stack
fwait ; wait
pop EAX ; load result into EDX:EAX
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
__FDAemu:
push EBP ; save EBP
push EDI ; save EDI
push ESI ; save EDI
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 ; ...
mov EBP,ECX ; assume op1 < op2
rol EDI,16 ; rotate signs to bottom
rol ECX,16 ; ...
add CX,DI ; 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
_endif ; endif
or CX,CX ; if op2 is not a denormal
_if ne ; then
or ESI,00100000h ; - turn on implied 1 bit
_endif ; endif
_shl EAX,1 ; shift left 1 to make room for guard bit
_rcl EDX,1 ; ...
_shl EBX,1 ; ...
_rcl ESI,1 ; ...
sub CX,DI ; calculate difference in exponents
_if ne ; if different
_if b ; - if op1 < op2
mov EBP,EDI ; - - get larger exponent for result
neg CX ; - - negate the shift count
xchg EAX,EBX ; - - flip operands
xchg EDX,ESI ; - - . . .
_endif ; - endif
cmp CX,53+1 ; - if shift count too big
_if a ; - then, return operand 1
mov EDX,ESI ; - - get value in correct registers
mov EAX,EBX ; - - . . .
_shl EBP,1 ; - - get sign
rcr EDX,1 ; - - rebuild operand 1
rcr EAX,1 ; - - ...
and EDX,800FFFFFh ; - - ...
ror EBP,13 ; - - rotate exponent into position
and EBP,7FF00000h ; - - ...
or EDX,EBP ; - - put in exponent
pop ESI ; - - restore ESI
pop EDI ; - - restore EDI
pop EBP ; - - restore EBP
ret ; - - return
_endif ; - endif
_endif ; endif
or ECX,ECX ; get bit 0 of sign word - value is 0 if
; both operands have same sign, 1 if not
_if s ; if signs are different
neg ESI ; - negate the fraction of op2
neg EBX ; - . . .
sbb ESI,0 ; - . . .
xor EBP,80000000h ; - flip sign
_endif ; endif
sub EDI,EDI ; get a zero for sticky bits
cmp CL,0 ; if shifting required
_if ne ; then
push EBX ; - save EBX
sub EBX,EBX ; - for zero fill
cmp CL,32 ; - if shift count >= 32
_if ae ; - then
or EAX,EAX ; - - check low order word for 1 bits
setne BL ; - - BL=1 if EAX non zero
mov EDI,EBX ; - - save sticky bits
sub EBX,EBX ; - - for zero fill
mov EAX,EDX ; - - shift right 32
sub EDX,EDX ; - - zero high word
;;; sub CL,32 ; - - adjust shift count
_endif ; - endif
shrd EBX,EAX,CL ; - get the extra sticky bits
or EDI,EBX ; - save them
sub EBX,EBX ; - for zero fill
shrd EAX,EDX,CL ; - align the fractions
shrd EDX,EBX,CL ; - ...
pop EBX ; - restore EBX
_endif ; endif
add EAX,EBX ; add the fractions
adc EDX,ESI ; . . .
_if s ; if answer is negative
cmp CL,53 ; - if shift count >= 53
_if ae ; - then
test EDI,7FFFFFFFh ; - - check the sticky bits
setne BL ; - - make single sticky bit
shr EBX,1 ; - - carry set if sticky=1
adc EAX,0 ; - - round up fraction if required
adc EDX,0 ; - - . . .
_endif ; - endif
neg EDX ; - negate the fraction
neg EAX ; - . . .
sbb EDX,0 ; - . . .
xor EBP,80000000h ; - flip the sign
_endif ; endif
mov EBX,EAX ; get result
or EBX,EDX ; if not zero
_if ne ; then
or BP,BP ; - if exponent is 0
je short denormal ; - denormal when exponent hits 0
_loop ; - loop (normalize)
test EDX,7FE00000h ; - - stop when bit slides into exponent field
_quif ne ; - - ...
dec BP ; - - decrement exponent
je short denormal; - - denormal when exponent hits 0
_shl EAX,1 ; - - shift fraction left one bit
_rcl EDX,1 ; - - ...
_endloop ; - endloop
test EDX,00400000h ; - if we got a carry
_if ne ; - then
shr EDX,1 ; - - shift fraction right 1
rcr EAX,1 ; - - ...
adc EDI,0 ; - - keep sticky bit
inc BP ; - - increment exponent
cmp BP,07FFh ; - - quit if overflow
je add_oflow ; - - . . .
_endif ; - endif
; normalize the fraction
shr EDX,1 ; - get guard bit
rcr EAX,1 ; - ...
_if c ; - if guard bit is on
or EDI,EDI ; - - check the sticky bits
setne BL ; - - make single sticky bit
or EBX,EAX ; - - or sticky bit with bottom bit
shr EBX,1 ; - - carry set if sticky=1 or bottom=1
adc EAX,0 ; - - round up fraction if required
adc EDX,0 ; - - . . .
test EDX,00200000h ; - - if we got a carry (02-nov-90)
_if ne ; - - then
shr EDX,1 ; - - - shift fraction right 1
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?