Browse Source

* fixed overflow checking in qword multiplication

florian 21 years ago
parent
commit
9205c6e800
1 changed files with 64 additions and 10 deletions
  1. 64 10
      rtl/i386/int64p.inc

+ 64 - 10
rtl/i386/int64p.inc

@@ -168,17 +168,19 @@
       the longbool for checkoverflow avoids a misaligned stack
       the longbool for checkoverflow avoids a misaligned stack
     }
     }
     function fpc_mul_qword(f1,f2 : qword;checkoverflow : longbool) : qword;[public,alias: 'FPC_MUL_QWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
     function fpc_mul_qword(f1,f2 : qword;checkoverflow : longbool) : qword;[public,alias: 'FPC_MUL_QWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
-
       var
       var
-         _f1 : qword;
-         r : qword;
+        r : qword;
+        overflowed : boolean;
       begin
       begin
-        _f1:=f1;
+        overflowed:=false;
         { 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 }
         asm
         asm
            movl f1+4,%edx
            movl f1+4,%edx
            movl f2+4,%ecx
            movl f2+4,%ecx
+           cmpl $0,checkoverflow
+           jnz .Loverflowchecked
+
            orl %ecx,%edx
            orl %ecx,%edx
            movl f2,%edx
            movl f2,%edx
            movl f1,%eax
            movl f1,%eax
@@ -194,18 +196,70 @@
         .Lqwordmulready:
         .Lqwordmulready:
            movl %eax,r
            movl %eax,r
            movl %edx,r+4
            movl %edx,r+4
-        end [ 'eax','edx','ecx' ];
+           jmp .Lend
+
+        .Loverflowchecked:
+           { if both upper dwords are <>0 then it overflows always }
+           or %ecx,%ecx
+           jz .Loverok1
+           or %edx,%edx
+           jnz .Loverflowed
+        .Loverok1:
+           { overflow checked code }
+           orl %ecx,%edx
+           movl f2,%edi
+           movl f1,%esi
+           jnz .Lqwordmultwomul2
+           movl %edi,%eax
+           mull %esi
+           movl %eax,%esi
+           movl %edx,%edi
+           jmp .Lqwordmulready2
+
+        .Lqwordmultwomul2:
+           movl f1+4,%eax
+           mull %edi
+           movl %eax,%edi
+           jc  .Loverflowed
+
+           movl %esi,%eax
+           mull %ecx
+           movl %eax,%ecx
+           jc  .Loverflowed
+
+           addl %edi,%ecx
+           jc  .Loverflowed
+
+           movl f2,%eax
+           mull %esi
+           movl %eax,%esi
+           movl %edx,%edi
+
+           addl %ecx,%edi
+           jc  .Loverflowed
+
+        .Lqwordmulready2:
+           movl %esi,r
+           movl %edi,r+4
+           jmp .Lend
+
+        .Loverflowed:
+           movb $1,overflowed
+
+        .Lend:
+        end [ 'eax','edx','ecx','edi','esi' ];
         fpc_mul_qword:=r;
         fpc_mul_qword:=r;
-        { if one of the operands is greater than the result an
-          overflow occurs                                      }
-        if checkoverflow and (_f1<>0) and (f2<>0) and
-           ((_f1>fpc_mul_qword) or (f2>fpc_mul_qword)) then
+
+        if overflowed then
           HandleErrorFrame(215,get_frame);
           HandleErrorFrame(215,get_frame);
       end;
       end;
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.4  2004-07-25 11:50:39  florian
+  Revision 1.5  2004-09-26 08:52:51  florian
+    * fixed overflow checking in qword multiplication
+
+  Revision 1.4  2004/07/25 11:50:39  florian
     * assembler version of mod_qword_word reactivated
     * assembler version of mod_qword_word reactivated
 
 
   Revision 1.3  2004/05/10 20:58:20  florian
   Revision 1.3  2004/05/10 20:58:20  florian