home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 April / Chip_1997-04_cd.bin / prezent / cb / data.z / FDIV.ASM < prev    next >
Assembly Source File  |  1997-01-16  |  4KB  |  164 lines

  1.  
  2. ; *******************************************************
  3. ; *                            *
  4. ; *     Delphi Runtime Library                          *
  5. ; *    Pentium-safe floating-point divide support    *
  6. ; *                            *
  7. ; *    Copyright (c) 1995,96 Borland International    *
  8. ; *                            *
  9. ; *******************************************************
  10.  
  11.     TITLE    FDIV
  12.  
  13.     .386
  14.     .MODEL    FLAT
  15.  
  16.     INCLUDE    SE.ASM
  17.  
  18.     .CODE
  19.  
  20. ; FDIV constants
  21.  
  22. FDIVRiscTable    DB    0,1,0,0,4,0,0,7,0,0,10,0,0,13,0,0
  23.  
  24. FDIVScale1    DD    3F700000H        ;0.9375
  25. FDIVScale2    DD    3F880000H        ;1.0625
  26. FDIV1SHL63    DD    5F000000H        ;1 SHL 63
  27.  
  28. TestDividend    DQ    4150017EC0000000H    ;4195835.0
  29. TestDivisor    DQ    4147FFFF80000000H    ;3145727.0
  30. TestOne        DQ    3FF0000000000000H    ;1.0
  31.  
  32.  
  33.     .DATA
  34.  
  35. ; Externals
  36.  
  37.     EXTRN    TestFDIV:BYTE
  38.  
  39.     .CODE
  40.  
  41. ; Publics
  42.  
  43.     PUBLIC    _FSafeDivide,_FSafeDivideR
  44.  
  45. Dividend    EQU    (TBYTE PTR [ESP])
  46. Divisor        EQU    (TBYTE PTR [ESP+12])
  47.  
  48. ; Flawed FDIV detection
  49.  
  50. FDivideDetect:
  51.  
  52.     MOV    TestFDIV,1        ;Indicate correct FDIV
  53.  
  54.     PUSH    EAX
  55.     SUB    ESP,12
  56.     FSTP    TBYTE PTR [ESP]        ;Save off ST
  57.     FLD    TestDividend        ;Ok if x - (x / y) * y < 1.0
  58.     FDIV    TestDivisor
  59.     FMUL    TestDivisor
  60.     FSUBR    TestDividend
  61.     FCOMP    TestOne
  62.     FSTSW    AX
  63.     SHR    EAX,7
  64.     AND    EAX,002H        ;Zero if FDIV is flawed
  65.     DEC    EAX
  66.     MOV    TestFDIV,AL        ;1 means Ok, -1 means flawed
  67.     FLD    TBYTE PTR [ESP]        ;Restore ST
  68.     ADD    ESP,12
  69.     POP    EAX
  70.     JMP    SHORT _FSafeDivide
  71.  
  72. ; Floating-point divide reverse routine
  73. ; ST(1) = ST(0) / ST(1), pop ST
  74.  
  75. _FSafeDivideR:
  76.  
  77.     FXCH
  78.  
  79. ; Floating-point divide routine
  80. ; ST(1) = ST(1) / ST(0), pop ST
  81.  
  82. _FSafeDivide:
  83.  
  84.     CMP    TestFDIV,0        ;Check FDIV indicator
  85.     JLE    FDivideChecked        ;Jump if flawed or don't know
  86.     FDIV                ;Known to be ok, so just do FDIV
  87.     RET
  88.  
  89. FDivideChecked:
  90.  
  91.     JE    FDivideDetect        ;Do detection if TestFDIV = 0
  92.  
  93. @@1:    PUSH    EAX
  94.     SUB    ESP,24
  95.     FSTP    Divisor            ;Store Divisor and Dividend
  96.     FSTP    Dividend
  97.     FLD    Dividend
  98.     FLD    Divisor
  99. @@2:    MOV    EAX,Divisor.d4        ;Is Divisor a denormal?
  100.     ADD    EAX,EAX
  101.     JNC    @@20            ;Yes, @@20
  102.     XOR    EAX,0E000000H        ;If these three bits are not all
  103.     TEST    EAX,0E000000H        ;ones, FDIV will work
  104.     JZ    @@10            ;Jump if all ones
  105. @@3:    FDIV                ;Do FDIV and exit
  106.     ADD    ESP,24
  107.     POP    EAX
  108.     RET
  109.  
  110. @@10:    SHR    EAX,28            ;If the four bits following the MSB
  111.                     ;of the mantissa have a decimal
  112.                     ;of 1, 4, 7, 10, or 13, FDIV may
  113.     CMP    FDIVRiscTable[EAX],0    ;not work correctly
  114.     JZ    @@3            ;Do FDIV if not 1, 4, 7, 10, or 13
  115.     MOV    EAX,Divisor.d8        ;Get Divisor exponent
  116.     AND    EAX,7FFFH
  117.     JZ    @@3            ;Ok to FDIV if denormal
  118.     CMP    EAX,7FFFH
  119.     JE    @@3            ;Ok to FDIV if NAN or INF
  120.     MOV    EAX,Dividend.d8        ;Get Dividend exponent
  121.     AND    EAX,7FFFH
  122.     CMP    EAX,1            ;Small number?
  123.     JE    @@11            ;Yes, @@11
  124.     FMUL    FDIVScale1        ;Scale by 15/16
  125.     FXCH
  126.     FMUL    FDIVScale1
  127.     FXCH
  128.     JMP    @@3            ;FDIV is now safe
  129.  
  130. @@11:    FMUL    FDIVScale2        ;Scale by 17/16
  131.     FXCH
  132.     FMUL    FDIVScale2
  133.     FXCH
  134.     JMP    @@3            ;FDIV is now safe
  135.  
  136. @@20:    MOV    EAX,Divisor.d0        ;Is entire Divisor zero?
  137.     OR    EAX,Divisor.d4
  138.     JZ    @@3            ;Yes, ok to FDIV
  139.     MOV    EAX,Divisor.d8        ;Get Divisor exponent
  140.     AND    EAX,7FFFH        ;Non-zero exponent is invalid
  141.     JNZ    @@3            ;Ok to FDIV if invalid
  142.     MOV    EAX,Dividend.d8        ;Get Dividend exponent
  143.     AND    EAX,7FFFH        ;Denormal?
  144.     JZ    @@21            ;Yes, @@21
  145.     CMP    EAX,7FFFH        ;NAN or INF?
  146.     JE    @@3            ;Yes, ok to FDIV
  147.     MOV    EAX,Dividend.d4        ;If MSB of mantissa is zero, the
  148.     ADD    EAX,EAX            ;number is invalid
  149.     JNC    @@3            ;Ok to FDIV if invalid
  150.     JMP    SHORT @@22
  151. @@21:    MOV    EAX,Dividend.d4        ;If MSB of mantissa is non-zero, the
  152.     ADD    EAX,EAX            ;number is invalid
  153.     JC    @@3            ;Ok to FDIV if invalid
  154. @@22:    FXCH                ;Scale stored Divisor image by
  155.     FSTP    ST(0)            ;1 SHL 63 and restart
  156.     FLD    ST(0)
  157.     FMUL    FDIV1SHL63
  158.     FSTP    Divisor
  159.     FLD    Dividend
  160.     FXCH
  161.     JMP    @@2
  162.  
  163.     END
  164.