fsmth086.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 652 行 · 第 1/2 页
ASM
652 行
;*****************************************************************************
;*
;* 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!
;*
;*****************************************************************************
;
; real*4 math library
;
; 04-apr-86 G. Coschi special over/underflow check in mul,div
; have to always point at DGROUP.
; we might be running with SS != DGROUP
;
; inputs: DX,AX - operand 1 (high word, low word resp. ) (op1)
; CX,BX - operand 2 (op2)
;
; operations are performed as op1 (*) op2 where (*) is the selected
; operation
;
; output: DX,AX - result (high word, low word resp. )
;
; __FSA, __FSS - written 28-apr-84
; - modified by A.Kasapi 15-may-84
; - to: Calculate sign of result
; - Guard bit in addition for extra accuracy
; Add documentation
; __FSM - written 16-may-84
; - by Athos Kasapi
; __FSD - written may-84 by "
;
;
;
include mdef.inc
include struct.inc
.8087
modstart fsmth086
xref __8087 ; indicate that NDP instructions are present
xref F4DivZero ; Fstatus
xref F4OverFlow ; Fstatus
xref F4UnderFlow ; Fstatus
xref __fdiv_m32
go_to macro frtn
if _MODEL and _DS_PEGGED
jmp frtn
else
if _MODEL and (_BIG_DATA or _HUGE_DATA)
push ax
push bp
push ds
mov ax,DGROUP ; get access to DGROUP
mov bp,sp
mov ds,ax ; . . .
mov ax,frtn
xchg ax,4[bp]
pop ds
pop bp
retn
else
jmp frtn
endif
endif
endm
datasegment
extrn __real87 : byte ; cstart
extern __chipbug : byte
fsadd dw _chkadd
fsmul dw _chkmul
fsdiv dw _chkdiv
enddata
xdefp __FSA ; add real*4 to real*4
xdefp __FSS ; subtract real*4 from real*4
xdefp __FSM ; 4-byte real multiply
xdefp __FSD ; 4-byte real divide
defpe __FSS
jcxz ret_op1 ; if op2 is 0 then return operand 1
xor CH,80h ; flip the sign of op2 and add
defpe __FSA
jcxz ret_op1 ; if op2 is 0 then return operand 1
or DX,DX ; if op1 is 0
_if e ; then
mov DX,CX ; - return operand 2
mov AX,BX ; - . . .
ret_op1: ret ; - return
_endif ; endif
go_to fsadd
__FSA87:
push BP ; save BP
mov BP,SP ; get access to stack
push DX ; push operand 1
push AX ; . . .
fld dword ptr -4[BP]; load operand 1
push CX ; push operand 2
push BX ; . . .
fadd dword ptr -8[BP]; add operand 2 to operand 1
_ret87:
fstp dword ptr -4[BP]; store result
add sp,4 ; clean up stack
fwait ; wait
pop AX ; load result into DX:AX
pop DX ; . . .
cmp DX,8000h ; check for negative zero
_if e ; if it is then
sub AX,AX ; - make it positive
mov DX,AX ; - ...
_endif ; endif
pop BP ; restore BP
ret ; return
__FSAemu:
push DI ; save DI
xchg AX,BX ; flip registers around
xchg AX,DX ; . . .
;
; now have:
; AX:BX
; +- CX:DX
;<> Scheme for calculating sign of result:
;<> The sign word is built and kept in DL
;<> Bits 0 and 1 hold the sum of the sign bits
;<> shifted out of op_1 and op_2
;<> Bit 2 holds the sign of the larger operand. It is assumed to be
;<> op_1 until op_2 is found larger
mov DI,DX ; put low order word of op2 in DI
sub DX,DX ; clear DX
_shl AX,1 ; get exponent of op1 into AH
_rcl DL,1 ;
mov DH,DL ;
_shl DL,1 ;
_shl DL,1 ;
add DL,DH ;
stc ; put implied 1 bit into top bit of
rcr AL,1 ; ... fraction
_shl CX,1 ; get exponent of op2 into CH
adc DL,0 ;
stc ; put implied 1 bit into top bit
rcr CL,1 ; ... of fraction
mov DH,AH ; assume op1 > op2
sub AH,CH ; calculate difference in exponents
_if ne ; if different
_if b ; - if op1 < op2
mov DH,CH ; - - get larger exponent for result
neg AH ; - - negate the shift count
xchg AL,CL ; - - flip operands
xchg BX,DI ; - - . . .
xor DL,4
;<> op_2 is larger, so its sign now occupies bit 2 of sign word. This
;<> information is only correct if the signs of op-1 and op-2 are different.
;<> Since we look past bit 1 for sign only if the signs are different, bit2
;<> will supply the correct information when it is needed. We get the sign of
;<> op_2 by flipping the sign of op_1, already in bit 2
_endif ; - endif
mov CH,AH ; - get shift count
mov AH,0 ; - zero guard byte
_loop ; - loop (align fractions)
shr CL,1 ; - - shift over fraction
rcr DI,1 ; - - . . .
dec CH ; - - decrement shift count
_until e ; - until fractions aligned
rcr AH,1 ; - only need last bit in guard byte
;<> bit 7 of the guard byte holds an extra significant bit from mantissa
;<> of the operand we shifted left to allign with the greater operand
;<> it is added or subtracted from with operands by shifting the bit into
;<> the carry bit just before the operation
_endif ; endif
shr DL,1 ; get bit 0 of sign word - value is 0 if
; both operands have same sign, 1 if not
_if nc ; if signs are the same
add BX,DI ; - add the fractions
adc AL,CL ; - . . .
_if c ; - if carry
rcr AL,1 ; - - shift fraction right 1 bit
rcr BX,1 ; - - . . .
rcr AH,1 ; - - save extra sig bit in guard bit
inc DH ; - - increment exponent
_if z ; - - if we overflowed
ror dl,1 ; - - - set sign of infinity
rcr ah,1 ; - - - . . .
jmp add_oflow ; - - - handle overflow
_endif ; - - endif
_endif ; - endif
_else ; else (signs are different)
shr DL,1 ; - skip junk bit
rol AH,1 ; - get guard bit
ror AH,1 ; - and put it back
sbb BX,DI ; - subtract the fractions
sbb AL,CL ; - . . .
_guess ; - guess
_quif nc ; - - quit if no borrow
inc DL ; - - sign := sign of op_2
not AL ; - - negate the fraction (considering
; - - the guard bit an extension of the
not BX ; - - fraction)
neg AH ; - - . . .
sbb BX,-1 ; - - . . .
sbb AL,-1 ; - - . . .
_admit ; - admit
cmp AL,0 ; - - quit if answer is not 0
_quif ne ; - - . . .
or BX,BX ; - - . . .
_quif ne ; - - . . .
sub AX,AX ; - - set result to 0
sub DX,DX ; - - . . .
pop DI ; - - restore DI
ret ; - - return (answer is 0)
_endguess ; - endguess
_endif ; endif
; normalize the fraction
_shl AH,1 ; get guard bit
adc BX,0 ; round up fraction if required
adc AL,0 ; . . .
_guess underflow ; guess
_quif nc ; - quit if round up didn't overflow frac
inc DH ; - adjust exponent
_admit ; admit
_loop ; - loop (shift until high bit appears)
_rcl BX,1 ; - - shift fraction left
_rcl AL,1 ; - - . . .
_quif c,underflow ; - - quit if carry has appeared
dec DH ; - - decrement exponent
_until e ; - until underflow
jmp add_uflow ; - handle underflow
_endguess ; endguess
mov AH,DH ; get exponent
ror DL,1 ; get sign bit
rcr AX,1 ; shift it into result
rcr BX,1 ; . . .
mov DX,AX ; get result in DX:AX
mov AX,BX ; . . .
pop DI ; restore DI
ret ; return
add_uflow: ; handle underflow
pop DI ; restore DI
jmp F4UnderFlow ; goto underflow routine
add_oflow: ; handle overflow
pop DI ; restore DI
jmp F4OverFlow ; handle overflow
endproc __FSA
endproc __FSS
;=====================================================================
defpe __FSM
;<> multiplies X by Y and places result in C.
;<> X2 and X1 represent the high and low words of X. Similarly for Y and C
;<> Special care is taken to use only six registers, so the code is a bit
;<> obscure
_guess ; guess: answer not 0
or DX,DX ; - see if first arg is zero
_quif e ; - quit if op1 is 0
or CX,CX ; - quit if op2 is 0
_quif e ; - . . .
go_to fsmul ; - invoke support rtn
_endguess ; endguess
sub AX,AX ; set answer to 0
sub DX,DX ; . . .
ret ; return
__FSM87:
push BP ; save BP
mov BP,SP ; get access to stack
push DX ; push operand 1
push AX ; . . .
fld dword ptr -4[BP]; load operand 1
push CX ; push operand 2
push BX ; . . .
fmul dword ptr -8[BP]; mulitply operand 1 by operand 2
jmp _ret87 ; goto common epilogue
__FSMemu:
push SI ; save SI
push DI ; save DI
xchg AX,BX ; flip registers around
xchg AX,DX ; . . .
;
; now have:
; AX:BX
; * CX:DX
;
mov DI,BX ; move arguments to better registers
mov BX,AX ; . . .
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?