xref: /linux/arch/arm64/lib/memchr.S (revision 9e51cafd783b22018fb15bfb06d65f69349223a9)
1caab277bSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
24a899227SCatalin Marinas/*
3*9e51cafdSRobin Murphy * Copyright (C) 2021 Arm Ltd.
44a899227SCatalin Marinas */
54a899227SCatalin Marinas
64a899227SCatalin Marinas#include <linux/linkage.h>
74a899227SCatalin Marinas#include <asm/assembler.h>
84a899227SCatalin Marinas
94a899227SCatalin Marinas/*
104a899227SCatalin Marinas * Find a character in an area of memory.
114a899227SCatalin Marinas *
124a899227SCatalin Marinas * Parameters:
134a899227SCatalin Marinas *	x0 - buf
144a899227SCatalin Marinas *	x1 - c
154a899227SCatalin Marinas *	x2 - n
164a899227SCatalin Marinas * Returns:
174a899227SCatalin Marinas *	x0 - address of first occurrence of 'c' or 0
184a899227SCatalin Marinas */
19*9e51cafdSRobin Murphy
20*9e51cafdSRobin Murphy#define L(label) .L ## label
21*9e51cafdSRobin Murphy
22*9e51cafdSRobin Murphy#define REP8_01 0x0101010101010101
23*9e51cafdSRobin Murphy#define REP8_7f 0x7f7f7f7f7f7f7f7f
24*9e51cafdSRobin Murphy
25*9e51cafdSRobin Murphy#define srcin		x0
26*9e51cafdSRobin Murphy#define chrin		w1
27*9e51cafdSRobin Murphy#define cntin		x2
28*9e51cafdSRobin Murphy
29*9e51cafdSRobin Murphy#define result		x0
30*9e51cafdSRobin Murphy
31*9e51cafdSRobin Murphy#define wordcnt		x3
32*9e51cafdSRobin Murphy#define rep01		x4
33*9e51cafdSRobin Murphy#define repchr		x5
34*9e51cafdSRobin Murphy#define cur_word	x6
35*9e51cafdSRobin Murphy#define cur_byte	w6
36*9e51cafdSRobin Murphy#define tmp		x7
37*9e51cafdSRobin Murphy#define tmp2		x8
38*9e51cafdSRobin Murphy
39*9e51cafdSRobin Murphy	.p2align 4
40*9e51cafdSRobin Murphy	nop
413ac0f452SMark BrownSYM_FUNC_START_WEAK_PI(memchr)
42*9e51cafdSRobin Murphy	and	chrin, chrin, #0xff
43*9e51cafdSRobin Murphy	lsr	wordcnt, cntin, #3
44*9e51cafdSRobin Murphy	cbz	wordcnt, L(byte_loop)
45*9e51cafdSRobin Murphy	mov	rep01, #REP8_01
46*9e51cafdSRobin Murphy	mul	repchr, x1, rep01
47*9e51cafdSRobin Murphy	and	cntin, cntin, #7
48*9e51cafdSRobin MurphyL(word_loop):
49*9e51cafdSRobin Murphy	ldr	cur_word, [srcin], #8
50*9e51cafdSRobin Murphy	sub	wordcnt, wordcnt, #1
51*9e51cafdSRobin Murphy	eor	cur_word, cur_word, repchr
52*9e51cafdSRobin Murphy	sub	tmp, cur_word, rep01
53*9e51cafdSRobin Murphy	orr	tmp2, cur_word, #REP8_7f
54*9e51cafdSRobin Murphy	bics	tmp, tmp, tmp2
55*9e51cafdSRobin Murphy	b.ne	L(found_word)
56*9e51cafdSRobin Murphy	cbnz	wordcnt, L(word_loop)
57*9e51cafdSRobin MurphyL(byte_loop):
58*9e51cafdSRobin Murphy	cbz	cntin, L(not_found)
59*9e51cafdSRobin Murphy	ldrb	cur_byte, [srcin], #1
60*9e51cafdSRobin Murphy	sub	cntin, cntin, #1
61*9e51cafdSRobin Murphy	cmp	cur_byte, chrin
62*9e51cafdSRobin Murphy	b.ne	L(byte_loop)
63*9e51cafdSRobin Murphy	sub	srcin, srcin, #1
644a899227SCatalin Marinas	ret
65*9e51cafdSRobin MurphyL(found_word):
66*9e51cafdSRobin MurphyCPU_LE(	rev	tmp, tmp)
67*9e51cafdSRobin Murphy	clz	tmp, tmp
68*9e51cafdSRobin Murphy	sub	tmp, tmp, #64
69*9e51cafdSRobin Murphy	add	result, srcin, tmp, asr #3
70*9e51cafdSRobin Murphy	ret
71*9e51cafdSRobin MurphyL(not_found):
72*9e51cafdSRobin Murphy	mov	result, #0
734a899227SCatalin Marinas	ret
743ac0f452SMark BrownSYM_FUNC_END_PI(memchr)
75ac0e8c72SMark RutlandEXPORT_SYMBOL_NOKASAN(memchr)
76