* Applied a counterpart of r22318 to 64-bit mod/div routines.

git-svn-id: trunk@23643 -
This commit is contained in:
sergei 2013-02-21 19:37:31 +00:00
parent b2d67c38f3
commit 5d5d226487

View File

@ -115,35 +115,6 @@
{$endif FPC_INCLUDE_SOFTWARE_SHIFT_INT64} {$endif FPC_INCLUDE_SOFTWARE_SHIFT_INT64}
function count_leading_zeros(q : qword) : longint;
var
r,i : longint;
begin
r:=0;
for i:=0 to 31 do
begin
if (tqwordrec(q).high and (dword($80000000) shr i))<>0 then
begin
count_leading_zeros:=r;
exit;
end;
inc(r);
end;
for i:=0 to 31 do
begin
if (tqwordrec(q).low and (dword($80000000) shr i))<>0 then
begin
count_leading_zeros:=r;
exit;
end;
inc(r);
end;
count_leading_zeros:=r;
end;
{$ifndef FPC_SYSTEM_HAS_DIV_QWORD} {$ifndef FPC_SYSTEM_HAS_DIV_QWORD}
function fpc_div_qword(n,z : qword) : qword;[public,alias: 'FPC_DIV_QWORD']; compilerproc; function fpc_div_qword(n,z : qword) : qword;[public,alias: 'FPC_DIV_QWORD']; compilerproc;
@ -154,24 +125,26 @@
fpc_div_qword:=0; fpc_div_qword:=0;
if n=0 then if n=0 then
HandleErrorAddrFrameInd(200,get_pc_addr,get_frame); HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
lzz:=count_leading_zeros(z); if z=0 then
lzn:=count_leading_zeros(n);
{ if the denominator contains less zeros }
{ then the numerator }
{ the d is greater than the n }
if lzn<lzz then
exit; exit;
shift:=lzn-lzz; lzz:=BsrQWord(z);
lzn:=BsrQWord(n);
{ if the denominator contains less zeros }
{ than the numerator }
{ then d is greater than the n }
if lzn>lzz then
exit;
shift:=lzz-lzn;
n:=n shl shift; n:=n shl shift;
repeat for shift:=shift downto 0 do
if z>=n then begin
begin if z>=n then
z:=z-n; begin
fpc_div_qword:=fpc_div_qword+(qword(1) shl shift); z:=z-n;
end; fpc_div_qword:=fpc_div_qword+(qword(1) shl shift);
dec(shift); end;
n:=n shr 1; n:=n shr 1;
until shift<0; end;
end; end;
{$endif FPC_SYSTEM_HAS_DIV_QWORD} {$endif FPC_SYSTEM_HAS_DIV_QWORD}
@ -186,24 +159,26 @@
fpc_mod_qword:=0; fpc_mod_qword:=0;
if n=0 then if n=0 then
HandleErrorAddrFrameInd(200,get_pc_addr,get_frame); HandleErrorAddrFrameInd(200,get_pc_addr,get_frame);
lzz:=count_leading_zeros(z); if z=0 then
lzn:=count_leading_zeros(n); exit;
lzz:=BsrQword(z);
lzn:=BsrQword(n);
{ if the denominator contains less zeros } { if the denominator contains less zeros }
{ then the numerator } { then the numerator }
{ the d is greater than the n } { the d is greater than the n }
if lzn<lzz then if lzn>lzz then
begin begin
fpc_mod_qword:=z; fpc_mod_qword:=z;
exit; exit;
end; end;
shift:=lzn-lzz; shift:=lzz-lzn;
n:=n shl shift; n:=n shl shift;
repeat for shift:=shift downto 0 do
if z>=n then begin
z:=z-n; if z>=n then
dec(shift); z:=z-n;
n:=n shr 1; n:=n shr 1;
until shift<0; end;
fpc_mod_qword:=z; fpc_mod_qword:=z;
end; end;
{$endif FPC_SYSTEM_HAS_MOD_QWORD} {$endif FPC_SYSTEM_HAS_MOD_QWORD}