Contributor: DJ MURDOCH { I have been working with Cleve Moler (from MathWorks) and Tim Coe about a sw workaround for the Pentium FDIV bug. Here is a BP version of the algorithm: The FDIV_FIX unit defines a single function: function fdiv(x: extended; y: extended): extended; which will use about 25% more cycles than a single fdiv call, but always return exact results for all double precision numbers, including the special cases of Nan, Inf and denormal. It also handles all extended precision numbers, giving a maximum error of a single bit in the last position (1ulp). This error can only be introduced if the FDIV operations fails. During the unit startup code, I test the FDIV instruction, and if if fails, initialize a 16-byte table of critical nibble values. If FDIV passes, the table is left empty, and no fixups will be done on divisions. =============== FDIV_FIX.PAS =========================== } {$N+,E-,G+} Unit FDIV_FIX; Interface function fdiv(x, y : Extended): Extended; const fdiv_risc_table : array [0..15] of byte = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); fdiv_scale : single = 0.9375; one_shl_63_l : Longint = $5f000000; var one_shl_63 : single absolute one_shl_63_l; Implementation function fdiv(x, y : Extended): Extended; Assembler; asm fld [x] @restart: mov bx,word ptr [y+6] fld [y] add bx,bx jnc @denormal {$IFOPT G+} shr bx,4 {$ELSE} mov cl,4 shr bx,cl {$ENDIF} cmp bl,255 jne @ok {$IFOPT G+} shr bx,8 {$ELSE} mov bl,bh and bx,255 {$ENDIF} cmp byte ptr fdiv_risc_table[bx],bh jz @ok fld [fdiv_scale] fmul st(2),st fmulp st(1),st jmp @ok @denormal: or bx,word ptr [y] or bx,word ptr [y+2] or bx,word ptr [y+4] jz @zero fld [one_shl_63] fmul st(2),st fmulp st(1),st fstp [y] jmp @restart @zero: @ok: fdivp st(1),st end; const a_bug : single = 4195835.0; b_bug : single = 3145727.0; Procedure fdiv_init; var r : double; i : Integer; begin r := a_bug / b_bug; if a_bug - r * b_bug > 1.0 then begin i := 1; repeat fdiv_risc_table[i] := i; Inc(i,3); until i >= 16; end; end; begin fdiv_init; end.