xref: /openbmc/linux/arch/arm64/lib/memchr.S (revision 4b33b5ff)
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
41SYM_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
48L(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)
57L(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
65L(found_word):
66CPU_LE(	rev	tmp, tmp)
67	clz	tmp, tmp
68	sub	tmp, tmp, #64
69	add	result, srcin, tmp, asr #3
70	ret
71L(not_found):
72	mov	result, #0
73	ret
74SYM_FUNC_END(__pi_memchr)
75SYM_FUNC_ALIAS_WEAK(memchr, __pi_memchr)
76EXPORT_SYMBOL_NOKASAN(memchr)
77