home *** CD-ROM | disk | FTP | other *** search
-
- ; *******************************************************
- ; * *
- ; * 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
-