From 97152cc41ba175cdaef34c457df85d6fc613dae3 Mon Sep 17 00:00:00 2001 From: sergei <gorelkin@nanoreflex.ru> Date: Mon, 29 Apr 2013 01:12:45 +0000 Subject: [PATCH] * Fixed overflow handling in i386 assembler implementations of fpc_div_qword and fpc_mod_qword. Resolves #23963. git-svn-id: trunk@24362 - --- .gitattributes | 1 + rtl/i386/int64p.inc | 33 ++++++++++++++++++++------------- tests/webtbs/tw23963.pp | 14 ++++++++++++++ 3 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 tests/webtbs/tw23963.pp diff --git a/.gitattributes b/.gitattributes index 7792c9bd4e..4c554b346c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13383,6 +13383,7 @@ tests/webtbs/tw2382.pp svneol=native#text/plain tests/webtbs/tw2388.pp svneol=native#text/plain tests/webtbs/tw23912.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/tw24007.pp svneol=native#text/plain tests/webtbs/tw2409.pp svneol=native#text/plain diff --git a/rtl/i386/int64p.inc b/rtl/i386/int64p.inc index 7627f74288..37c3c7e278 100644 --- a/rtl/i386/int64p.inc +++ b/rtl/i386/int64p.inc @@ -18,10 +18,10 @@ {$define FPC_SYSTEM_HAS_DIV_QWORD} function fpc_div_qword(n,z : qword) : qword;assembler;[public,alias: 'FPC_DIV_QWORD']; compilerproc; var - shift,lzz,lzn : longint; - saveebx,saveedi : longint; + saveebx,saveedi,saveesi : longint; asm movl %ebx,saveebx + movl %esi,saveesi movl %edi,saveedi { the following piece of code is taken from the } { AMD Athlon Processor x86 Code Optimization manual } @@ -68,18 +68,23 @@ roll $1,%edi divl %ebx movl z,%ebx - movl %eax,%ecx + movl %eax,%esi // save quotient to esi imull %eax,%edi mull n addl %edi,%edx + setcb %cl // cl:edx:eax = 65 bits quotient*divisor + + movl z+4,%edi // edi:ebx = dividend subl %eax,%ebx - movl %ecx,%eax - movl z+4,%ecx - sbbl %edx,%ecx - sbbl $0,%eax + movb $0,%al + sbbl %edx,%edi + sbbb %cl,%al + sbbl $0,%esi xorl %edx,%edx + movl %esi,%eax .Lexit: movl saveebx,%ebx + movl saveesi,%esi movl saveedi,%edi end; @@ -87,7 +92,6 @@ {$define FPC_SYSTEM_HAS_MOD_QWORD} function fpc_mod_qword(n,z : qword) : qword;assembler;[public,alias: 'FPC_MOD_QWORD']; compilerproc; var - shift,lzz,lzn : longint; saveebx,saveedi : longint; asm movl %ebx,saveebx @@ -139,19 +143,22 @@ roll $1,%edi divl %ebx movl z,%ebx - movl %eax,%ecx imull %eax,%edi mull n addl %edi,%edx - subl %eax,%ebx - movl z+4,%ecx + setcb %cl // cl:edx:eax = 65 bits quotient*divisor + 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 - sbbl %edx,%ecx sbbl %edx,%edx andl %edx,%eax andl n+4,%edx addl %ebx,%eax - adcl %ecx,%edx + adcl %edi,%edx .Lexit: movl saveebx,%ebx movl saveedi,%edi diff --git a/tests/webtbs/tw23963.pp b/tests/webtbs/tw23963.pp new file mode 100644 index 0000000000..f5de32cc68 --- /dev/null +++ b/tests/webtbs/tw23963.pp @@ -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.