1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2021 Arm Ltd.
4  */
5 
6 #include <linux/linkage.h>
7 #include <asm/assembler.h>
8 
9 /*
10  * Find a character in an area of memory.
11  *
12  * Parameters:
13  *	x0 - buf
14  *	x1 - c
15  *	x2 - n
16  * Returns:
17  *	x0 - address of first occurrence of 'c' or 0
18  */
19 
20 #define L(label) .L ## label
21 
22 #define REP8_01 0x0101010101010101
23 #define REP8_7f 0x7f7f7f7f7f7f7f7f
24 
25 #define srcin		x0
26 #define chrin		w1
27 #define cntin		x2
28 
29 #define result		x0
30 
31 #define wordcnt		x3
32 #define rep01		x4
33 #define repchr		x5
34 #define cur_word	x6
35 #define cur_byte	w6
36 #define tmp		x7
37 #define tmp2		x8
38 
39 	.p2align 4
40 	nop
41 SYM_FUNC_START(__pi_memchr)
42 	and	chrin, chrin, #0xff
43 	lsr	wordcnt, cntin, #3
44 	cbz	wordcnt, L(byte_loop)
45 	mov	rep01, #REP8_01
46 	mul	repchr, x1, rep01
47 	and	cntin, cntin, #7
48 L(word_loop):
49 	ldr	cur_word, [srcin], #8
50 	sub	wordcnt, wordcnt, #1
51 	eor	cur_word, cur_word, repchr
52 	sub	tmp, cur_word, rep01
53 	orr	tmp2, cur_word, #REP8_7f
54 	bics	tmp, tmp, tmp2
55 	b.ne	L(found_word)
56 	cbnz	wordcnt, L(word_loop)
57 L(byte_loop):
58 	cbz	cntin, L(not_found)
59 	ldrb	cur_byte, [srcin], #1
60 	sub	cntin, cntin, #1
61 	cmp	cur_byte, chrin
62 	b.ne	L(byte_loop)
63 	sub	srcin, srcin, #1
64 	ret
65 L(found_word):
66 CPU_LE(	rev	tmp, tmp)
67 	clz	tmp, tmp
68 	sub	tmp, tmp, #64
69 	add	result, srcin, tmp, asr #3
70 	ret
71 L(not_found):
72 	mov	result, #0
73 	ret
74 SYM_FUNC_END(__pi_memchr)
75 SYM_FUNC_ALIAS_WEAK(memchr, __pi_memchr)
76 EXPORT_SYMBOL_NOKASAN(memchr)
77