aboutsummaryrefslogtreecommitdiff
path: root/lib/libc/amd64/string
diff options
context:
space:
mode:
authorRobert Clausecker <fuz@FreeBSD.org>2023-08-25 16:22:22 +0000
committerRobert Clausecker <fuz@FreeBSD.org>2023-08-25 19:21:54 +0000
commit3d8ef251aa9dceabd57f7821a0e6749d35317db3 (patch)
treed669fa04db73715db528a1ec843aee1dddca1ab6 /lib/libc/amd64/string
parent247e8662d2c080c27937ec4d62e80b2358e8c74f (diff)
Diffstat (limited to 'lib/libc/amd64/string')
-rw-r--r--lib/libc/amd64/string/strchrnul.S17
1 files changed, 10 insertions, 7 deletions
diff --git a/lib/libc/amd64/string/strchrnul.S b/lib/libc/amd64/string/strchrnul.S
index 9aa9591b07ca..0e70b02311d7 100644
--- a/lib/libc/amd64/string/strchrnul.S
+++ b/lib/libc/amd64/string/strchrnul.S
@@ -52,22 +52,25 @@ ARCHENTRY(__strchrnul, scalar)
movabs $0x0101010101010101, %r8
mov (%rdi), %rax # load first word
imul %r8, %rsi # replicate char 8 times
- movabs $0x8080808080808080, %r9
/*
* Unaligned input: align to 8 bytes. Then proceed the same
- * way as with aligned input, but ignore matches before the
- * beginning of the string. This is achieved by shifting r9
- * into r10 to have 0x00 bytes before the string begins.
+ * way as with aligned input, but prevent matches before the
+ * beginning of the string. This is achieved by oring 0x01
+ * into each byte of the buffer before the string
*/
shl $3, %ecx
- mov %r9, %r10
+ mov %r8, %r10
add $8, %rdi
- shl %cl, %r10 # 0x80 where the string is
+ shl %cl, %r10 # 0x01 where the string is
+ xor %r8, %r10 # 0x01 where it is not
neg %r8 # negate 01..01 so we can use lea
+ movabs $0x8080808080808080, %r9
mov %rsi, %rcx
xor %rax, %rcx # str ^ c
+ or %r10, %rax # str without NUL bytes before it
+ or %r10, %rcx # (str ^ c) without matches before it
lea (%rax, %r8, 1), %rdx # str - 0x01..01
lea (%rcx, %r8, 1), %r11 # (str ^ c) - 0x01..01
not %rax # ~str
@@ -75,7 +78,7 @@ ARCHENTRY(__strchrnul, scalar)
and %rdx, %rax # (str - 0x01..01) & ~str
and %r11, %rcx # ((str ^ c - 0x01..01) & ~(str ^ c)
or %rcx, %rax # matches for both
- and %r10, %rax # not including junk bytes or bytes before the string
+ and %r9, %rax # not including junk bytes
jnz 1f
/* main loop unrolled twice */