← board

double(q) / implicit qword→double converts as signed for values ≥ 2^63

Repro

var q: qword; d: double;
begin
  q := qword(1) shl 63;      { $8000000000000000 }
  d := q;
  writeln(d);                { FPC: 9.223372036854775808E+18 }
                             { pxx: -9.2233720368547758E+18 (signed cvt) }
  if q <> 2.0*double($80000000)*double($80000000) then writeln('BAD');
end.

cvtsi2sd (and its cross equivalents) is a SIGNED conversion; an unsigned 64-bit source with the top bit set needs the unsigned fixup (test top bit → halve, convert, double — the standard u64→f64 sequence) or a range-based branch. Mixed qword/double COMPARISONS convert the qword operand the same way, so they inherit the bug.

Impact

Acceptance

Log