[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