fdmth086.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 1,056 行 · 第 1/3 页
ASM
1,056 行
;*****************************************************************************
;*
;* 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*8 math library
;
; __FDM,__FDD
; floating point routines
; 13 June, 1984 @Watcom
;
; All routines have the same calling conventions.
; Op_1 and Op_2 are double prec reals, pointed to by DI and SI resp.
; The binary operations are perfomed as Op_1 (*) Op_2.
;
; In all cases, BP and DI are returned unaltered.
;
;
; have to always point at DGROUP.
; **** This routine does CODE modification ****
; is a power of 2.
; aligning fractions before the add
; No need to push second operand in f8split
; since ss:[si] can already be used to access it
; Moved f8split into each subroutine.
; to get rid of code modification
; we might be running with SS != DGROUP
;
include mdef.inc
include struct.inc
.8087
modstart fdmth086
xref __8087 ; indicate that NDP instructions are present
xref F8OverFlow ; FSTATUS
xref F8UnderFlow ; FSTATUS
xref F8DivZero ; FSTATUS
xref __fdiv_m64r
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
extrn __chipbug : byte
fdadd dw _chkadd
fdsub dw _chksub
fdmul dw _chkmul
fddiv dw _chkdiv
enddata
xdefp __FDA
xdefp __EDA
xdefp __FDS
xdefp __EDS
xdefp __FDM
xdefp __EDM
xdefp __FDD
xdefp __EDD
defp __EDD
push es:6[si]
push es:4[si]
push es:2[si]
push es:[si]
mov si,sp ; point to second operand
docall __FDD
add sp,8
ret
endproc __EDD
defp __EDM
push es:6[si]
push es:4[si]
push es:2[si]
push es:[si]
mov si,sp ; point to second operand
docall __FDM
add sp,8
ret
endproc __EDM
defp __EDS
push es:6[si]
push es:4[si]
push es:2[si]
push es:[si]
mov si,sp ; point to second operand
docall __FDS
add sp,8
ret
endproc __EDS
defp __EDA
push es:6[si]
push es:4[si]
push es:2[si]
push es:[si]
mov si,sp ; point to second operand
docall __FDA
add sp,8
ret
endproc __EDA
;
; __FDS
;
defpe __FDS
go_to fdsub
__FDS87:
fld qword ptr ss:[SI] ; load operand 2
push BP ; save BP
mov BP,SP ; get access to stack
push AX ; push operand 1
push BX ; . . .
push CX ; . . .
push DX ; . . .
fsubr qword ptr -8[BP]; subtract operand 2 from operand 1
_ret87: fstp qword ptr -8[BP]; store result
fwait ; wait
pop DX ; load result into AX:BX:CX:DX
pop CX ; . . .
pop BX ; . . .
pop AX ; . . .
cmp AX,8000h ; is it negative zero? 17-mar-91
_if e ; if it is then
sub AX,AX ; - turn it into positive zero
mov BX,AX ; - ... zero other words as well
mov CX,AX ; - ...
mov DX,AX ; - ...
_endif ; endif
pop BP ; restore BP
ret ; return
__FDSemu:
push BP ; save BP
mov BP,8000h ; indicate that we are doing subtraction
jmp begin
endproc __FDS
;
; __FDA
;
defpe __FDA
go_to fdadd
__FDA87:
fld qword ptr ss:[SI] ; load operand 2
push BP ; save BP
mov BP,SP ; get access to stack
push AX ; push operand 1
push BX ; . . .
push CX ; . . .
push DX ; . . .
fadd qword ptr -8[BP]; add operand 1
jmp _ret87 ; return result from 8087
RetOp_2:
sub bx,bx ; return op2
_shl cx,1 ; get sign bit into position
mov bp,cx ; move it to correct reg
xor bp,ss:6[si] ; see if sign must be reversed
and bp,8000h ; clear out rest of reg
; one of the args was found to be zero
addzero:or BX,BX ; check the first argument
_if ne ; if the first arg is not zero
mov SI,DI ; - return first argument
sub bp,bp ; - don't reverse sign
_endif ; endif
mov ax,ss:6[si] ; get high word
or ax,ax ; see if number is zero
_if ne ; if not then
xor ax,bp ; - reverse sign if required
_endif ; endif
mov BX,ss:4[SI] ; get next sig word
mov CX,ss:2[SI] ; . . .
mov DX,ss:[SI] ; . . .
add SP,8 ; clean up stack
pop DI ; restore DI
pop BP ; return to caller
ret
__FDAemu:
push BP
sub BP,BP ; indicate that we are doing addition
begin: push DI ; save DI
; copy of the f8split routine
push AX ; push operand 1 onto stack
push BX ; . . .
push CX ; . . .
push DX ; . . .
mov DI,SP ; get address of operand 1
_guess ; guess
mov BX,AX ; - get most sig word of op1
mov AX,ss:6[SI] ; - get most sig word of op2
mov DL,AL ; - save mantissa-holding part
mov DH,BL ; - save mantissa-holding part
mov cl,bh ; - save sign
and BX,7FF0h ; - isolate exponent
je addzero ; - quif zero
mov ch,ah ; - save sign
and AX,7FF0h ; - isolate exponent
je addzero ; - quif zero
and cx,8080h ; - only want sign bits
xor dx,1010h ; - set implied one bit of mant.
xor DL,AL ; - . . .
xor DH,BL ; - . . .
_endguess ; endguess
; end of f8split
xor CX,BP ; change sign of op_2 if this is sub
sar CH,1 ; prepare sign byte
add CH,CL ; it is op_2's sign we indicate
mov BP,AX ; save exponent
sub AX,BX ; get shift count
_if l ; - if op_2 < op_1
mov BP,BX ; - - move op_1's exponent into BP
neg AX ; - - negate the shift count
xchg SI,DI ; - - exchange operands
xchg DH,DL ; - - . . .
_shl CH,1 ; - - make op_1's sign count
rcr CL,1
xchg CL,CH ; - - . . .
_endif ; - endif
cmp AX,0400h ; AX has shift count << 4
jae retOp_2 ; if shift count >= 64, return operand 2
shr AX,1 ; move shift count into bottom bits
shr AX,1
shr AX,1
shr AX,1
mov AH,AL ; AH := shift count
mov AL,DH ; AL := high byte of smaller real
mov DH,CH ; DH := sign byte
mov BX,ss:4[DI] ; . . .
mov CX,ss:2[DI] ; . . .
mov DI,ss:[DI] ; . . .
or AH,AH ; test AH (shift count)
_if ne ; if shift count <> 0
xchg DX,DI ; - get DI into byte registers for shift
_loop ; - loop (shift by a byte at a time)
cmp AH,8 ; - - quit if less than a byte to do
_quif l ; - - . . .
sub AH,8 ; - - subtract 8 from shift count
_if e ; - - if exact # of bytes
mov AH,DL ; - - - get high bit for guard bit
_endif ; - - endif
mov DL,DH ; - - shift right 1 byte
mov DH,CL ; - - . . .
mov CL,CH ; - - . . .
mov CH,BL ; - - . . .
mov BL,BH ; - - . . .
mov BH,AL ; - - . . .
mov AL,0 ; - - . . .
_until e ; - until done
_if ne ; - if still more to shift
_loop ; - - loop
shr AL,1 ; - - - shift over fractions
rcr BX,1 ; - - - . . .
rcr CX,1 ; - - - . . .
rcr DX,1 ; - - - . . .
dec AH ; - - - dec shift count
_until e ; - - until shift count = 0
rcr AH,1 ; - - save guard bit
_endif ; - endif
and AH,80h ; - isolate guard bit
xchg DX,DI ; - exchange regs again
_endif ; endif
_shl DH,1 ; get bit 7 of sign word. 1 if signs are
; different, 0 if they are the same
_if nc ; if signs are the same
add DI,ss:[SI] ; - add the mantissas
adc CX,ss:2[SI] ; - . . .
adc BX,ss:4[SI] ; - . . .
adc AL,DL ; - . . .
test AL,20h ; - check for carry
je add_norm ; - if we haven't carried, normalize now
push DX ; - put sign onto stack
mov DX,DI ; - get low word into correct reg
jmp fin_up ; - common finish up routine
_endif ; endif
sub DI,ss:[SI]
sbb CX,ss:2[SI] ; . . .
sbb BX,ss:4[SI] ; . . .
sbb AL,DL ; . . .
cmc ; complement carry
rcr SI,1 ; save complemented carry in SI
and SI,8000h ; isolate the bit
add DX,SI ; and use it to calculate sign of result
_shl SI,1 ; restore the complement of the carry
_if c ; if no borrow, see if result is zero
cmp AL,0 ; - - quif answer is not zero
jne add_norm ; - - . . .
or SI,BX
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?