aboutsummaryrefslogtreecommitdiff
path: root/lib/libc/aarch64/string/strspn.S
blob: 0ef42c2b737e90964b551f3a379c9e359aa3147c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*-
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright (c) 2024 Getz Mikalsen <getz@FreeBSD.org>
*/

#include <machine/asm.h>

	.weak	strspn
	.set	strspn, __strspn
	.text

ENTRY(__strspn)

	/* check for special cases */
	ldrb	w4, [x1]		// first character in set
	cbz	w4, .Lzero		// empty set always returns 0

	mov	x15, #1			// preload register with 1 for stores

	// set is only one character
	ldrb	w5, [x1, #1]		// second character in the set
	cbz	w5, .Lsingle

	stp	x29, x30, [sp, #-16]!
	mov	x29, sp
	sub	sp, sp, #256		// allocate 256 bytes on the stack

	/* no special case matches -- prepare lookup table */
	mov	w3, #28
0:	add	x9, sp, x3, lsl #3
	stp	xzr, xzr, [x9]
	stp	xzr, xzr, [x9, #16]
	subs	w3, w3, #4
	b.cs	0b

	strb	w15, [sp, x4]		// register first character in set
	add	x1, x1, #2

	/* process remaining chars in set */
	.p2align 4


0:	ldrb	w4, [x1]		// next char in set
	strb	w15, [sp, x5]		// register previous char
	cbz	w4, 1f			// NUL encountered?

	ldrb	w5, [x1, #1]
	add	x1, x1, #2
	strb	w15, [sp, x4]
	cbnz	w5, 0b

1:	mov	x5, x0			// stash a copy of src

	/* find mismatch */
	.p2align 4
0:	ldrb	w8, [x0]
	ldrb	w9, [sp, x8]
	cbz	w9, 2f

	ldrb	w8, [x0, #1]
	ldrb	w9, [sp, x8]
	cbz	w9, 3f

	ldrb	w8, [x0, #2]
	ldrb	w9, [sp, x8]
	cbz	w9, 4f

	ldrb	w8, [x0, #3]
	add	x0, x0, #4
	ldrb	w9, [sp, x8]
	cbnz	w9, 0b

	sub	x0, x0, #3
4:	sub	x5, x5, #1
3:	add	x0, x0, #1
2:	sub	x0, x0, x5
	mov	sp, x29
	ldp	x29, x30, [sp], #16
	ret

.Lzero:
	mov	x0, #0
	ret

.Lsingle:
	ldrb	w8, [x0, x5]
	cmp	w4, w8
	b.ne	1f

	add	x5, x5, #1
	ldrb	w8, [x0, x5]
	cmp	w4, w8
	b.ne	1f

	add	x5, x5, #1
	ldrb	w8, [x0, x5]
	cmp	w4, w8
	b.ne	1f

	add	x5, x5, #1
	ldrb	w8, [x0, x5]
	add	x5, x5, #1
	cmp	w4, w8
	b.eq	.Lsingle

	sub	x5, x5, #1
1:	mov	x0, x5
	ret

END(__strspn)