home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1997 April
/
Chip_1997-04_cd.bin
/
prezent
/
cb
/
data.z
/
FDIV.ASM
< prev
next >
Wrap
Assembly Source File
|
1997-01-16
|
4KB
|
164 lines
; *******************************************************
; * *
; * Delphi Runtime Library *
; * Pentium-safe floating-point divide support *
; * *
; * Copyright (c) 1995,96 Borland International *
; * *
; *******************************************************
TITLE FDIV
.386
.MODEL FLAT
INCLUDE SE.ASM
.CODE
; FDIV constants
FDIVRiscTable DB 0,1,0,0,4,0,0,7,0,0,10,0,0,13,0,0
FDIVScale1 DD 3F700000H ;0.9375
FDIVScale2 DD 3F880000H ;1.0625
FDIV1SHL63 DD 5F000000H ;1 SHL 63
TestDividend DQ 4150017EC0000000H ;4195835.0
TestDivisor DQ 4147FFFF80000000H ;3145727.0
TestOne DQ 3FF0000000000000H ;1.0
.DATA
; Externals
EXTRN TestFDIV:BYTE
.CODE
; Publics
PUBLIC _FSafeDivide,_FSafeDivideR
Dividend EQU (TBYTE PTR [ESP])
Divisor EQU (TBYTE PTR [ESP+12])
; Flawed FDIV detection
FDivideDetect:
MOV TestFDIV,1 ;Indicate correct FDIV
PUSH EAX
SUB ESP,12
FSTP TBYTE PTR [ESP] ;Save off ST
FLD TestDividend ;Ok if x - (x / y) * y < 1.0
FDIV TestDivisor
FMUL TestDivisor
FSUBR TestDividend
FCOMP TestOne
FSTSW AX
SHR EAX,7
AND EAX,002H ;Zero if FDIV is flawed
DEC EAX
MOV TestFDIV,AL ;1 means Ok, -1 means flawed
FLD TBYTE PTR [ESP] ;Restore ST
ADD ESP,12
POP EAX
JMP SHORT _FSafeDivide
; Floating-point divide reverse routine
; ST(1) = ST(0) / ST(1), pop ST
_FSafeDivideR:
FXCH
; Floating-point divide routine
; ST(1) = ST(1) / ST(0), pop ST
_FSafeDivide:
CMP TestFDIV,0 ;Check FDIV indicator
JLE FDivideChecked ;Jump if flawed or don't know
FDIV ;Known to be ok, so just do FDIV
RET
FDivideChecked:
JE FDivideDetect ;Do detection if TestFDIV = 0
@@1: PUSH EAX
SUB ESP,24
FSTP Divisor ;Store Divisor and Dividend
FSTP Dividend
FLD Dividend
FLD Divisor
@@2: MOV EAX,Divisor.d4 ;Is Divisor a denormal?
ADD EAX,EAX
JNC @@20 ;Yes, @@20
XOR EAX,0E000000H ;If these three bits are not all
TEST EAX,0E000000H ;ones, FDIV will work
JZ @@10 ;Jump if all ones
@@3: FDIV ;Do FDIV and exit
ADD ESP,24
POP EAX
RET
@@10: SHR EAX,28 ;If the four bits following the MSB
;of the mantissa have a decimal
;of 1, 4, 7, 10, or 13, FDIV may
CMP FDIVRiscTable[EAX],0 ;not work correctly
JZ @@3 ;Do FDIV if not 1, 4, 7, 10, or 13
MOV EAX,Divisor.d8 ;Get Divisor exponent
AND EAX,7FFFH
JZ @@3 ;Ok to FDIV if denormal
CMP EAX,7FFFH
JE @@3 ;Ok to FDIV if NAN or INF
MOV EAX,Dividend.d8 ;Get Dividend exponent
AND EAX,7FFFH
CMP EAX,1 ;Small number?
JE @@11 ;Yes, @@11
FMUL FDIVScale1 ;Scale by 15/16
FXCH
FMUL FDIVScale1
FXCH
JMP @@3 ;FDIV is now safe
@@11: FMUL FDIVScale2 ;Scale by 17/16
FXCH
FMUL FDIVScale2
FXCH
JMP @@3 ;FDIV is now safe
@@20: MOV EAX,Divisor.d0 ;Is entire Divisor zero?
OR EAX,Divisor.d4
JZ @@3 ;Yes, ok to FDIV
MOV EAX,Divisor.d8 ;Get Divisor exponent
AND EAX,7FFFH ;Non-zero exponent is invalid
JNZ @@3 ;Ok to FDIV if invalid
MOV EAX,Dividend.d8 ;Get Dividend exponent
AND EAX,7FFFH ;Denormal?
JZ @@21 ;Yes, @@21
CMP EAX,7FFFH ;NAN or INF?
JE @@3 ;Yes, ok to FDIV
MOV EAX,Dividend.d4 ;If MSB of mantissa is zero, the
ADD EAX,EAX ;number is invalid
JNC @@3 ;Ok to FDIV if invalid
JMP SHORT @@22
@@21: MOV EAX,Dividend.d4 ;If MSB of mantissa is non-zero, the
ADD EAX,EAX ;number is invalid
JC @@3 ;Ok to FDIV if invalid
@@22: FXCH ;Scale stored Divisor image by
FSTP ST(0) ;1 SHL 63 and restart
FLD ST(0)
FMUL FDIV1SHL63
FSTP Divisor
FLD Dividend
FXCH
JMP @@2
END