Browse Source

* Cleaned out code marked as originated from glibc:
- strlen.inc: removed, was never actually used anywhere.
- StrCopy: removed, its generic version is optimized well enough now.
* StrComp: rewritten, speed somewhat improved.

git-svn-id: trunk@20349 -

sergei 13 years ago
parent
commit
724227c962
3 changed files with 35 additions and 320 deletions
  1. 0 1
      .gitattributes
  2. 35 174
      rtl/x86_64/strings.inc
  3. 0 145
      rtl/x86_64/strlen.inc

+ 0 - 1
.gitattributes

@@ -8461,7 +8461,6 @@ rtl/x86_64/setjump.inc svneol=native#text/plain
 rtl/x86_64/setjumph.inc svneol=native#text/plain
 rtl/x86_64/strings.inc svneol=native#text/plain
 rtl/x86_64/stringss.inc svneol=native#text/plain
-rtl/x86_64/strlen.inc svneol=native#text/plain
 rtl/x86_64/x86_64.inc svneol=native#text/plain
 tests/MPWMake -text
 tests/Makefile svneol=native#text/plain

+ 35 - 174
rtl/x86_64/strings.inc

@@ -17,184 +17,45 @@
 
 {$ASMMODE GAS}
 
-{$ifndef FPC_UNIT_HAS_STRCOPY}
-{$define FPC_UNIT_HAS_STRCOPY}
-{ Created from glibc: libc/sysdeps/x86_64/strcpy.S Version 1.2 }
-function strcopy(dest,source : pchar) : pchar;assembler;
-{$ifdef win64}
-var
-  rdi,rsi : int64;
-{$endif win64}
-asm
-{$ifdef win64}
-        movq %rsi,rsi
-        movq %rdi,rdi
-        movq %rdx, %rsi
-        movq %rcx, %rdi
-{$endif win64}
-        movq %rsi, %rcx                { Source register. }
-        andl $7, %ecx                  { mask alignment bits }
-        movq %rdi, %rdx                { Duplicate destination pointer.  }
-
-        jz .LFPC_STRCOPY_5              { aligned => start loop }
-
-        neg %ecx                       { We need to align to 8 bytes.  }
-        addl $8,%ecx
-
-        { Search the first bytes directly.  }
-.LFPC_STRCOPY_0:
-        movb        (%rsi), %al        { Fetch a byte }
-        testb       %al, %al           { Is it NUL? }
-        movb        %al, (%rdx)        { Store it }
-        jz          .LFPC_STRCOPY_4     { If it was NUL, done! }
-        incq        %rsi
-        incq        %rdx
-        decl        %ecx
-        jnz         .LFPC_STRCOPY_0
-
-.LFPC_STRCOPY_5:
-        movq        $0xfefefefefefefeff,%r8
-
-        { Now the sources is aligned.  Unfortunatly we cannot force
-           to have both source and destination aligned, so ignore the
-           alignment of the destination.  }
-        .p2align 4
-.LFPC_STRCOPY_1:
-        { 1st unroll.  }
-        movq        (%rsi), %rax       { Read double word (8 bytes).  }
-        addq        $8, %rsi           { Adjust pointer for next word.  }
-        movq        %rax, %r9          { Save a copy for NUL finding.  }
-        addq        %r8, %r9           { add the magic value to the word.  We get
-                                         carry bits reported for each byte which
-                                         is *not* 0 }
-        jnc         .LFPC_STRCOPY_3     { highest byte is NUL => return pointer }
-        xorq        %rax, %r9          { (word+magic)^word }
-        orq         %r8, %r9           { set all non-carry bits }
-        incq        %r9                { add 1: if one carry bit was *not* set
-                                         the addition will not result in 0.  }
-
-        jnz         .LFPC_STRCOPY_3                { found NUL => return pointer }
-
-        movq        %rax, (%rdx)        { Write value to destination.  }
-        addq        $8, %rdx        { Adjust pointer.  }
-
-        { 2nd unroll.  }
-        movq        (%rsi), %rax        { Read double word (8 bytes).  }
-        addq        $8, %rsi        { Adjust pointer for next word.  }
-        movq        %rax, %r9        { Save a copy for NUL finding.  }
-        addq        %r8, %r9        { add the magic value to the word.  We get
-                                   carry bits reported for each byte which
-                                   is *not* 0 }
-        jnc         .LFPC_STRCOPY_3                { highest byte is NUL => return pointer }
-        xorq        %rax, %r9        { (word+magic)^word }
-        orq         %r8, %r9        { set all non-carry bits }
-        incq        %r9                { add 1: if one carry bit was *not* set
-                                   the addition will not result in 0.  }
-
-        jnz         .LFPC_STRCOPY_3                { found NUL => return pointer }
-
-        movq        %rax, (%rdx)        { Write value to destination.  }
-        addq        $8, %rdx        { Adjust pointer.  }
-
-        { 3rd unroll.  }
-        movq        (%rsi), %rax        { Read double word (8 bytes).  }
-        addq        $8, %rsi        { Adjust pointer for next word.  }
-        movq        %rax, %r9        { Save a copy for NUL finding.  }
-        addq        %r8, %r9        { add the magic value to the word.  We get
-                                   carry bits reported for each byte which
-                                   is *not* 0 }
-        jnc        .LFPC_STRCOPY_3                { highest byte is NUL => return pointer }
-        xorq        %rax, %r9        { (word+magic)^word }
-        orq        %r8, %r9        { set all non-carry bits }
-        incq        %r9                { add 1: if one carry bit was *not* set
-                                   the addition will not result in 0.  }
-
-        jnz         .LFPC_STRCOPY_3                { found NUL => return pointer }
-
-        movq        %rax, (%rdx)        { Write value to destination.  }
-        addq        $8, %rdx        { Adjust pointer.  }
-
-        { 4th unroll.  }
-        movq        (%rsi), %rax        { Read double word (8 bytes).  }
-        addq        $8, %rsi        { Adjust pointer for next word.  }
-        movq        %rax, %r9        { Save a copy for NUL finding.  }
-        addq        %r8, %r9        { add the magic value to the word.  We get
-                                   carry bits reported for each byte which
-                                   is *not* 0 }
-        jnc         .LFPC_STRCOPY_3                { highest byte is NUL => return pointer }
-        xorq        %rax, %r9        { (word+magic)^word }
-        orq         %r8, %r9        { set all non-carry bits }
-        incq        %r9                { add 1: if one carry bit was *not* set
-                                   the addition will not result in 0.  }
-
-        jnz         .LFPC_STRCOPY_3                { found NUL => return pointer }
-
-        movq        %rax, (%rdx)        { Write value to destination.  }
-        addq        $8, %rdx        { Adjust pointer.  }
-        jmp         .LFPC_STRCOPY_1                { Next iteration.  }
-
-        { Do the last few bytes. %rax contains the value to write.
-           The loop is unrolled twice.  }
-        .p2align 4
-.LFPC_STRCOPY_3:
-        { Note that stpcpy needs to return with the value of the NUL
-           byte.  }
-        movb        %al, (%rdx)        { 1st byte.  }
-        testb       %al, %al        { Is it NUL.  }
-        jz          .LFPC_STRCOPY_4                { yes, finish.  }
-        incq        %rdx                { Increment destination.  }
-        movb        %ah, (%rdx)        { 2nd byte.  }
-        testb       %ah, %ah        { Is it NUL?.  }
-        jz          .LFPC_STRCOPY_4                { yes, finish.  }
-        incq        %rdx                { Increment destination.  }
-        shrq        $16, %rax        { Shift...  }
-        jmp         .LFPC_STRCOPY_3                { and look at next two bytes in %rax.  }
-
-.LFPC_STRCOPY_4:
-        movq        %rdi, %rax        { Source is return value.  }
-{$ifdef win64}
-        movq rsi,%rsi
-        movq rdi,%rdi
-{$endif win64}
-end;
-{$endif FPC_UNIT_HAS_STRCOPY}
-
-
 {$ifndef FPC_UNIT_HAS_STRCOMP}
 {$define FPC_UNIT_HAS_STRCOMP}
-{ Created from glibc: libc/sysdeps/x86_64/strcmp.S Version 1.2 }
-function StrComp(Str1, Str2: PChar): SizeInt;assembler;
-{$ifdef win64}
-var
-  rdi,rsi : int64;
-{$endif win64}
+function StrComp(Str1, Str2: PChar): SizeInt;assembler;nostackframe;
 asm
-{$ifdef win64}
-        movq %rsi,rsi
-        movq %rdi,rdi
-        movq %rdx, %rsi
-        movq %rcx, %rdi
+{$ifndef win64}
+        movq   %rsi,%rdx
+        movq   %rdi,%rcx
 {$endif win64}
-.LFPC_STRCMP_LOOP:
-        movb        (%rdi), %al
-        cmpb        (%rsi), %al
-        jne         .LFPC_STRCMP_NEG
-        incq        %rdi
-        incq        %rsi
-        testb       %al, %al
-        jnz         .LFPC_STRCMP_LOOP
-
-        xorq        %rax, %rax
-        jmp .Lexit
-
-.LFPC_STRCMP_NEG:
-        movq        $1, %rax
-        movq        $-1, %rcx
-        cmovbq      %rcx, %rax
+        subq   %rcx,%rdx
+.balign 16
+.Lloop:                          { unrolled 4 times }
+        movb   (%rcx),%al
+        cmpb   (%rdx,%rcx),%al
+        jne    .Ldiff
+        testb  %al,%al
+        jz    .Leq
+        movb   1(%rcx),%al
+        cmpb   1(%rdx,%rcx),%al
+        jne    .Ldiff
+        testb  %al,%al
+        jz     .Leq
+        movb   2(%rcx),%al
+        cmpb   2(%rdx,%rcx),%al
+        jne    .Ldiff
+        testb  %al,%al
+        jz     .Leq
+        movb   3(%rcx),%al
+        add    $4,%rcx
+        cmpb   -1(%rdx,%rcx),%al
+        jne    .Ldiff
+        testb  %al,%al
+        jnz    .Lloop
+.Leq:
+        xorq   %rax,%rax
+        jmp    .Lexit
+
+.Ldiff:
+        sbbq   %rax,%rax        { -1 if CF was set, 0 otherwise }
+        orb    $1,%al           { 0 becomes 1, -1 remains unchanged }
 .Lexit:
-{$ifdef win64}
-        movq rsi,%rsi
-        movq rdi,%rdi
-{$endif win64}
 end;
 {$endif FPC_UNIT_HAS_STRCOMP}

+ 0 - 145
rtl/x86_64/strlen.inc

@@ -1,145 +0,0 @@
-{
-    This file is part of the Free Pascal run time library.
-    Copyright (c) 1999-2000 by the Free Pascal development team
-
-    Processor specific implementation of strlen
-
-    See the file COPYING.FPC, included in this distribution,
-    for details about the copyright.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
- **********************************************************************}
-{
-  Implemented using the code from  glibc: libc/sysdeps/x86_64/strlen.S Version 1.2
-}
-{$ifdef win64}
-var
-  rdi : qword;
-{$endif win64}
-asm
-        { win64 has different calling conventions }
-{$ifdef win64}
-        movq %rdi,rdi
-        movq %rcx, %rdi                { Duplicate source pointer. }
-{$else win64}
-        movq %rdi, %rcx                { Duplicate source pointer. }
-{$endif win64}
-        andl $7, %ecx                  { mask alignment bits }
-        movq %rdi, %rax                { duplicate destination.  }
-        jz .LFPC_STRLEN_1               { aligned => start loop }
-
-        neg %ecx                       { We need to align to 8 bytes.  }
-        addl $8,%ecx
-        { Search the first bytes directly.  }
-.LFPC_STRLEN_0:
-        cmpb $0x0,(%rax)                { is byte NUL? }
-        je .LFPC_STRLEN_2                { yes => return }
-        incq %rax                       { increment pointer }
-        decl %ecx
-        jnz .LFPC_STRLEN_0
-
-.LFPC_STRLEN_1:
-         movq $0xfefefefefefefeff,%r8  { Save magic.  }
-
-        .p2align 4                     { Align loop.  }
-.LFPC_STRLEN_4:                          { Main Loop is unrolled 4 times.  }
-        { First unroll.  }
-        movq (%rax), %rcx              { get double word (= 8 bytes) in question }
-        addq $8,%rax                   { adjust pointer for next word }
-        movq %r8, %rdx                 { magic value }
-        addq %rcx, %rdx                { add the magic value to the word.  We get
-                                         carry bits reported for each byte which
-                                         is *not* 0 }
-        jnc .LFPC_STRLEN_3               { highest byte is NUL => return pointer }
-        xorq %rcx, %rdx                { (word+magic)^word }
-        orq %r8, %rdx                  { set all non-carry bits }
-        incq %rdx                      { add 1: if one carry bit was *not* set
-                                         the addition will not result in 0.  }
-        jnz .LFPC_STRLEN_3               { found NUL => return pointer }
-
-        { Second unroll.  }
-        movq (%rax), %rcx        { get double word (= 8 bytes) in question }
-        addq $8,%rax                { adjust pointer for next word }
-        movq %r8, %rdx                { magic value }
-        addq %rcx, %rdx                { add the magic value to the word.  We get
-                                   carry bits reported for each byte which
-                                   is *not* 0 }
-        jnc .LFPC_STRLEN_3                        { highest byte is NUL => return pointer }
-        xorq %rcx, %rdx                { (word+magic)^word }
-        orq %r8, %rdx                { set all non-carry bits }
-        incq %rdx                { add 1: if one carry bit was *not* set
-                                   the addition will not result in 0.  }
-        jnz .LFPC_STRLEN_3                        { found NUL => return pointer }
-
-        { Third unroll.  }
-        movq (%rax), %rcx        { get double word (= 8 bytes) in question }
-        addq $8,%rax                { adjust pointer for next word }
-        movq %r8, %rdx                { magic value }
-        addq %rcx, %rdx                { add the magic value to the word.  We get
-                                   carry bits reported for each byte which
-                                   is *not* 0 }
-        jnc .LFPC_STRLEN_3                        { highest byte is NUL => return pointer }
-        xorq %rcx, %rdx                { (word+magic)^word }
-        orq %r8, %rdx                { set all non-carry bits }
-        incq %rdx                { add 1: if one carry bit was *not* set
-                                   the addition will not result in 0.  }
-        jnz .LFPC_STRLEN_3                        { found NUL => return pointer }
-
-        { Fourth unroll.  }
-        movq (%rax), %rcx        { get double word (= 8 bytes) in question }
-        addq $8,%rax                { adjust pointer for next word }
-        movq %r8, %rdx                { magic value }
-        addq %rcx, %rdx                { add the magic value to the word.  We get
-                                   carry bits reported for each byte which
-                                   is *not* 0 }
-        jnc .LFPC_STRLEN_3                        { highest byte is NUL => return pointer }
-        xorq %rcx, %rdx                { (word+magic)^word }
-        orq %r8, %rdx                { set all non-carry bits }
-        incq %rdx                { add 1: if one carry bit was *not* set
-                                   the addition will not result in 0.  }
-        jz .LFPC_STRLEN_4                        { no NUL found => continue loop }
-
-        .p2align 4                { Align, it's a jump target.  }
-.LFPC_STRLEN_3:
-        subq $8,%rax                { correct pointer increment.  }
-
-        testb %cl, %cl                { is first byte NUL? }
-        jz .LFPC_STRLEN_2                        { yes => return }
-        incq %rax                { increment pointer }
-
-        testb %ch, %ch                { is second byte NUL? }
-        jz .LFPC_STRLEN_2                        { yes => return }
-        incq %rax                { increment pointer }
-
-        testl $0x00ff0000, %ecx { is third byte NUL? }
-        jz .LFPC_STRLEN_2                        { yes => return pointer }
-        incq %rax                { increment pointer }
-
-        testl $0xff000000, %ecx { is fourth byte NUL? }
-        jz .LFPC_STRLEN_2                        { yes => return pointer }
-        incq %rax                { increment pointer }
-
-        shrq $32, %rcx                { look at other half.  }
-
-        testb %cl, %cl                { is first byte NUL? }
-        jz .LFPC_STRLEN_2                        { yes => return }
-        incq %rax                { increment pointer }
-
-        testb %ch, %ch                { is second byte NUL? }
-        jz .LFPC_STRLEN_2                        { yes => return }
-        incq %rax                { increment pointer }
-
-        testl $0xff0000, %ecx        { is third byte NUL? }
-        jz .LFPC_STRLEN_2                        { yes => return pointer }
-        incq %rax                { increment pointer }
-.LFPC_STRLEN_2:
-        subq %rdi, %rax                { compute difference to string start }
-{$ifdef win64}
-        movq rdi,%rdi
-{$endif win64}
-end;
-
-