123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- {
- $Id$
- This file is part of the Free Pascal run time library.
- Copyright (c) 2003 by Florian Klaempfl, member of the
- Free Pascal development team
- Processor dependent part of strings.pp, that can be shared with
- sysutils unit.
- 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.
- **********************************************************************}
- {$define FPC_UNIT_HAS_STRLEN}
- function strlen(p : pchar) : longint;assembler;
- {$i strlen.inc}
- {$define FPC_UNIT_HAS_STRCOPY}
- { Created from glibc: libc/sysdeps/x86_64/strcpy.S Version 1.2 }
- function strcopy(dest,source : pchar) : pchar;assembler;
- asm
- 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. }
- retq
- end;
- {$define FPC_UNIT_HAS_STRCOMP}
- { Created from glibc: libc/sysdeps/x86_64/strcmp.S Version 1.2 }
- function StrComp(Str1, Str2: PChar): StrLenInt;
- asm
- FPC_STRCMP_LOOP:
- movb (%rdi), %al
- cmpb (%rsi), %al
- jne FPC_STRCMP_NEG
- incq %rdi
- incq %rsi
- testb %al, %al
- jnz FPC_STRCMP_LOOP
- xorq %rax, %rax
- ret
- FPC_STRCMP_NEG:
- movl $1, %eax
- movl $-1, %ecx
- cmovbl %ecx, %eax
- ret
- end;
- {
- $Log$
- Revision 1.2 2003-04-30 22:11:06 florian
- + for a lot of x86-64 dependend files mostly dummies added
- Revision 1.1 2003/04/30 16:36:39 florian
- + support for generic pchar routines added
- + some basic rtl stuff for x86-64 added
- }
|