mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-08 22:47:54 +02:00
* 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 -
This commit is contained in:
parent
2499b5514f
commit
724227c962
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
@ -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
|
||||
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
|
||||
|
||||
xorq %rax, %rax
|
||||
jmp .Lexit
|
||||
|
||||
.LFPC_STRCMP_NEG:
|
||||
movq $1, %rax
|
||||
movq $-1, %rcx
|
||||
cmovbq %rcx, %rax
|
||||
.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}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user