mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-11 12:10:43 +01:00
* Fixed overflow handling in i386 assembler implementations of fpc_div_qword and fpc_mod_qword.
Resolves #23963. git-svn-id: trunk@24362 -
This commit is contained in:
parent
1fea5a82c1
commit
97152cc41b
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -13383,6 +13383,7 @@ tests/webtbs/tw2382.pp svneol=native#text/plain
|
|||||||
tests/webtbs/tw2388.pp svneol=native#text/plain
|
tests/webtbs/tw2388.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw23912.pp svneol=native#text/plain
|
tests/webtbs/tw23912.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw23962.pp svneol=native#text/plain
|
tests/webtbs/tw23962.pp svneol=native#text/plain
|
||||||
|
tests/webtbs/tw23963.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw2397.pp svneol=native#text/plain
|
tests/webtbs/tw2397.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw24007.pp svneol=native#text/plain
|
tests/webtbs/tw24007.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw2409.pp svneol=native#text/plain
|
tests/webtbs/tw2409.pp svneol=native#text/plain
|
||||||
|
|||||||
@ -18,10 +18,10 @@
|
|||||||
{$define FPC_SYSTEM_HAS_DIV_QWORD}
|
{$define FPC_SYSTEM_HAS_DIV_QWORD}
|
||||||
function fpc_div_qword(n,z : qword) : qword;assembler;[public,alias: 'FPC_DIV_QWORD']; compilerproc;
|
function fpc_div_qword(n,z : qword) : qword;assembler;[public,alias: 'FPC_DIV_QWORD']; compilerproc;
|
||||||
var
|
var
|
||||||
shift,lzz,lzn : longint;
|
saveebx,saveedi,saveesi : longint;
|
||||||
saveebx,saveedi : longint;
|
|
||||||
asm
|
asm
|
||||||
movl %ebx,saveebx
|
movl %ebx,saveebx
|
||||||
|
movl %esi,saveesi
|
||||||
movl %edi,saveedi
|
movl %edi,saveedi
|
||||||
{ the following piece of code is taken from the }
|
{ the following piece of code is taken from the }
|
||||||
{ AMD Athlon Processor x86 Code Optimization manual }
|
{ AMD Athlon Processor x86 Code Optimization manual }
|
||||||
@ -68,18 +68,23 @@
|
|||||||
roll $1,%edi
|
roll $1,%edi
|
||||||
divl %ebx
|
divl %ebx
|
||||||
movl z,%ebx
|
movl z,%ebx
|
||||||
movl %eax,%ecx
|
movl %eax,%esi // save quotient to esi
|
||||||
imull %eax,%edi
|
imull %eax,%edi
|
||||||
mull n
|
mull n
|
||||||
addl %edi,%edx
|
addl %edi,%edx
|
||||||
|
setcb %cl // cl:edx:eax = 65 bits quotient*divisor
|
||||||
|
|
||||||
|
movl z+4,%edi // edi:ebx = dividend
|
||||||
subl %eax,%ebx
|
subl %eax,%ebx
|
||||||
movl %ecx,%eax
|
movb $0,%al
|
||||||
movl z+4,%ecx
|
sbbl %edx,%edi
|
||||||
sbbl %edx,%ecx
|
sbbb %cl,%al
|
||||||
sbbl $0,%eax
|
sbbl $0,%esi
|
||||||
xorl %edx,%edx
|
xorl %edx,%edx
|
||||||
|
movl %esi,%eax
|
||||||
.Lexit:
|
.Lexit:
|
||||||
movl saveebx,%ebx
|
movl saveebx,%ebx
|
||||||
|
movl saveesi,%esi
|
||||||
movl saveedi,%edi
|
movl saveedi,%edi
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -87,7 +92,6 @@
|
|||||||
{$define FPC_SYSTEM_HAS_MOD_QWORD}
|
{$define FPC_SYSTEM_HAS_MOD_QWORD}
|
||||||
function fpc_mod_qword(n,z : qword) : qword;assembler;[public,alias: 'FPC_MOD_QWORD']; compilerproc;
|
function fpc_mod_qword(n,z : qword) : qword;assembler;[public,alias: 'FPC_MOD_QWORD']; compilerproc;
|
||||||
var
|
var
|
||||||
shift,lzz,lzn : longint;
|
|
||||||
saveebx,saveedi : longint;
|
saveebx,saveedi : longint;
|
||||||
asm
|
asm
|
||||||
movl %ebx,saveebx
|
movl %ebx,saveebx
|
||||||
@ -139,19 +143,22 @@
|
|||||||
roll $1,%edi
|
roll $1,%edi
|
||||||
divl %ebx
|
divl %ebx
|
||||||
movl z,%ebx
|
movl z,%ebx
|
||||||
movl %eax,%ecx
|
|
||||||
imull %eax,%edi
|
imull %eax,%edi
|
||||||
mull n
|
mull n
|
||||||
addl %edi,%edx
|
addl %edi,%edx
|
||||||
subl %eax,%ebx
|
setcb %cl // cl:edx:eax = 65 bits quotient*divisor
|
||||||
movl z+4,%ecx
|
movl z+4,%edi
|
||||||
|
subl %eax,%ebx // subtract (quotient*divisor) from dividend
|
||||||
|
movb $0,%al
|
||||||
|
sbbl %edx,%edi
|
||||||
|
sbbb %cl,%al // if carry is set now, the quotient was off by 1,
|
||||||
|
// and we need to add divisor to result
|
||||||
movl n,%eax
|
movl n,%eax
|
||||||
sbbl %edx,%ecx
|
|
||||||
sbbl %edx,%edx
|
sbbl %edx,%edx
|
||||||
andl %edx,%eax
|
andl %edx,%eax
|
||||||
andl n+4,%edx
|
andl n+4,%edx
|
||||||
addl %ebx,%eax
|
addl %ebx,%eax
|
||||||
adcl %ecx,%edx
|
adcl %edi,%edx
|
||||||
.Lexit:
|
.Lexit:
|
||||||
movl saveebx,%ebx
|
movl saveebx,%ebx
|
||||||
movl saveedi,%edi
|
movl saveedi,%edi
|
||||||
|
|||||||
14
tests/webtbs/tw23963.pp
Normal file
14
tests/webtbs/tw23963.pp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{$mode objfpc}
|
||||||
|
|
||||||
|
var
|
||||||
|
Dividend, Divisor, Quotient : QWord;
|
||||||
|
begin
|
||||||
|
Dividend := QWord( $ffffffffffffffff );
|
||||||
|
Divisor := QWord( $100000003 );
|
||||||
|
Quotient := dividend div divisor;
|
||||||
|
if quotient <> $FFFFFFFD then
|
||||||
|
Halt(1);
|
||||||
|
Quotient := dividend mod divisor;
|
||||||
|
if quotient <> 8 then
|
||||||
|
Halt(2);
|
||||||
|
end.
|
||||||
Loading…
Reference in New Issue
Block a user