[fpc-devel] Broken frac function in FPC3.1.1 / Windows x86_64

J. Gareth Moreton gareth at moreton-family.com
Sat Apr 28 19:09:27 CEST 2018


 If I may add a possible solution, would code akin to the following fix the
problems? (Pray that the mail list formatting doesn't mess it all up!)

 ----

 {$WARN 7121 off : Check size of memory operand "$1: memory-operand-size is
$2 bits, but expected [$3 bits]"}
 {$ASMMODE Intel}

 const
   MAX_DOUBLE_WITH_FRAC: Double = 4503599627370496;
   SIGN_MASK: QWord  = $7FFFFFFFFFFFFFFF;

 function SafeFrac(X: ValReal): ValReal; assembler; nostackframe;
 asm
   MOVSD     XMM5, [RIP+SIGN_MASK]
   MOVSD     XMM4, XMM0
   ANDPD     XMM4, XMM5 { Remove sign bit }
   COMISD    XMM4, [RIP+MAX_DOUBLE_WITH_FRAC] { If less than, then ZF =
0, PF = 0 and CF = 1}
   JNC       @IsZero    { If carry flag is clear, the absolute
value is too
                          large to contain a
fractional component (and
                          potentially too large to
fit into RAX) }
   CVTTSD2SI RAX,  XMM0
   CVTSI2SD  XMM4, RAX
   SUBPD     XMM0, XMM4
   RET
 @IsZero:
   XORPD     XMM0, XMM0
 end;

 ----

 The first MOVSD could be removed and simply be merged with ANDPD to save
on a register, but I wrote it this way to take advantage of instruction
prefetching and offer a slight speed boost.

 There is one minor functional change though... when testing this function,
I discovered that if you try to pass infinity or minus infinity, the result
is zero, whereas currently with Frac, it triggers SIGFPE.

 Gareth aka. Kit
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20180428/80b0ee9d/attachment.html>


More information about the fpc-devel mailing list