Przeglądaj źródła

* improved Compare(D)Word as well

git-svn-id: trunk@17651 -
florian 14 lat temu
rodzic
commit
cd8913b88e
1 zmienionych plików z 72 dodań i 38 usunięć
  1. 72 38
      rtl/i386/i386.inc

+ 72 - 38
rtl/i386/i386.inc

@@ -481,30 +481,44 @@ end;
 {$endif FPC_SYSTEM_HAS_COMPAREBYTE}
 
 
-
 {$ifndef FPC_SYSTEM_HAS_COMPAREWORD}
 {$define FPC_SYSTEM_HAS_COMPAREWORD}
-function CompareWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler;
-var
-  saveesi,saveedi,saveebx : longint;
+function CompareWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler; nostackframe;
 asm
-        movl    %edi,saveedi
-        movl    %esi,saveesi
-        movl    %ebx,saveebx
+        cmpl    $32,%ecx          { empirical average value, on a Athlon XP the
+                                    break even is at 14, on a Core 2 Duo > 100 }
+        jg      .LCmpWordFull
+        testl   %ecx,%ecx
+        je      .LCmpWordZero
+
+        pushl   %ebx
+.LCmpWordLoop:
+        movw    (%eax),%bx
+        cmpw    (%edx),%bx
+        leal    2(%eax),%eax
+        leal    2(%edx),%edx
+        jne     .LCmpWordExitFast
+        decl    %ecx
+        jne     .LCmpWordLoop
+.LCmpWordExitFast:
+        movzwl  -2(%edx),%ecx     { Compare last position }
+        movzwl  %bx,%eax
+        subl    %ecx,%eax
+        popl    %ebx
+        ret
+
+.LCmpWordZero:
+        movl    $0,%eax
+        ret
+
+.LCmpWordFull:
+        pushl   %esi
+        pushl   %edi
+        pushl   %ebx
         cld
-{$ifdef REGCALL}
         movl    %eax,%edi
         movl    %edx,%esi
         movl    %ecx,%eax
-{$else}
-        movl    buf2,%esi       { Load params}
-        movl    buf1,%edi
-        movl    len,%eax
-{$endif}
-        testl   %eax,%eax       {We address -2(%esi), so we have to deal with len=0}
-        je      .LCmpwordExit
-        cmpl    $5,%eax         {<5 (3 bytes align + 4 bytes cmpsl = 4 words}
-        jl      .LCmpword2      { not worth aligning and go through all trouble}
         movl    (%edi),%ebx     // Compare alignment bytes.
         cmpl    (%esi),%ebx
         jne     .LCmpword2      // Aligning will go wrong already. Max 2 words will be scanned Branch NOW
@@ -543,35 +557,55 @@ asm
         movzwl  -2(%edi),%eax    // Compare failing (or equal) position
         subl    %ecx,%eax        // calculate end result.
 .LCmpwordExit:
-        movl    saveedi,%edi
-        movl    saveesi,%esi
-        movl    saveebx,%ebx
+        popl    %ebx
+        popl    %edi
+        popl    %esi
 end;
 {$endif FPC_SYSTEM_HAS_COMPAREWORD}
 
 
 {$ifndef FPC_SYSTEM_HAS_COMPAREDWORD}
 {$define FPC_SYSTEM_HAS_COMPAREDWORD}
-function CompareDWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler;
-var
-  saveesi,saveedi,saveebx : longint;
+function CompareDWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler; nostackframe;
 asm
-        movl    %edi,saveedi
-        movl    %esi,saveesi
+        cmpl    $32,%ecx          { empirical average value, on a Athlon XP the
+                                    break even is at 12, on a Core 2 Duo > 100 }
+        jg      .LCmpDWordFull
+        testl   %ecx,%ecx
+        je      .LCmpDWordZero
+
+        pushl   %ebx
+.LCmpDWordLoop:
+        movl    (%eax),%ebx
+        cmpl    (%edx),%ebx
+        leal    4(%eax),%eax
+        leal    4(%edx),%edx
+        jne     .LCmpDWordExitFast
+        decl    %ecx
+        jne     .LCmpDWordLoop
+.LCmpDWordExitFast:
+        xorl    %eax,%eax
+        movl    -4(%edx),%edx       // Compare failing (or equal) position
+        subl    %edx,%ebx           // calculate end result.
+        setb    %dl
+        seta    %cl
+        addb    %cl,%al
+        subb    %dl,%al
+        movsbl  %al,%eax
+
+        popl    %ebx
+        ret
+
+.LCmpDWordZero:
+        movl    $0,%eax
+        ret
+
+.LCmpDWordFull:
+        pushl   %esi
+        pushl   %edi
         cld
-{$ifdef REGCALL}
         movl    %eax,%edi
         movl    %edx,%esi
-        movl    %ecx,%eax
-{$else}
-        movl    buf2,%esi       { Load params}
-        movl    buf1,%edi
-        movl    len,%eax
-        movl    %eax,%ecx
-{$endif}
-        testl   %eax,%eax
-        je      .LCmpDwordExit
-        movl    %eax,%ecx
         xorl    %eax,%eax
         rep                     { Compare entire DWords}
         cmpsl
@@ -583,8 +617,8 @@ asm
         subb    %dl,%al
         movsbl  %al,%eax
 .LCmpDwordExit:
-        movl    saveedi,%edi
-        movl    saveesi,%esi
+        popl    %edi
+        popl    %esi
 end;
 {$endif FPC_SYSTEM_HAS_COMPAREDWORD}