xref: /linux/arch/arm64/lib/memchr.S (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1caab277bSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
24a899227SCatalin Marinas/*
39e51cafdSRobin 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 */
199e51cafdSRobin Murphy
209e51cafdSRobin Murphy#define L(label) .L ## label
219e51cafdSRobin Murphy
229e51cafdSRobin Murphy#define REP8_01 0x0101010101010101
239e51cafdSRobin Murphy#define REP8_7f 0x7f7f7f7f7f7f7f7f
249e51cafdSRobin Murphy
259e51cafdSRobin Murphy#define srcin		x0
269e51cafdSRobin Murphy#define chrin		w1
279e51cafdSRobin Murphy#define cntin		x2
289e51cafdSRobin Murphy
299e51cafdSRobin Murphy#define result		x0
309e51cafdSRobin Murphy
319e51cafdSRobin Murphy#define wordcnt		x3
329e51cafdSRobin Murphy#define rep01		x4
339e51cafdSRobin Murphy#define repchr		x5
349e51cafdSRobin Murphy#define cur_word	x6
359e51cafdSRobin Murphy#define cur_byte	w6
369e51cafdSRobin Murphy#define tmp		x7
379e51cafdSRobin Murphy#define tmp2		x8
389e51cafdSRobin Murphy
399e51cafdSRobin Murphy	.p2align 4
409e51cafdSRobin Murphy	nop
41*0f61f6beSMark RutlandSYM_FUNC_START(__pi_memchr)
429e51cafdSRobin Murphy	and	chrin, chrin, #0xff
439e51cafdSRobin Murphy	lsr	wordcnt, cntin, #3
449e51cafdSRobin Murphy	cbz	wordcnt, L(byte_loop)
459e51cafdSRobin Murphy	mov	rep01, #REP8_01
469e51cafdSRobin Murphy	mul	repchr, x1, rep01
479e51cafdSRobin Murphy	and	cntin, cntin, #7
489e51cafdSRobin MurphyL(word_loop):
499e51cafdSRobin Murphy	ldr	cur_word, [srcin], #8
509e51cafdSRobin Murphy	sub	wordcnt, wordcnt, #1
519e51cafdSRobin Murphy	eor	cur_word, cur_word, repchr
529e51cafdSRobin Murphy	sub	tmp, cur_word, rep01
539e51cafdSRobin Murphy	orr	tmp2, cur_word, #REP8_7f
549e51cafdSRobin Murphy	bics	tmp, tmp, tmp2
559e51cafdSRobin Murphy	b.ne	L(found_word)
569e51cafdSRobin Murphy	cbnz	wordcnt, L(word_loop)
579e51cafdSRobin MurphyL(byte_loop):
589e51cafdSRobin Murphy	cbz	cntin, L(not_found)
599e51cafdSRobin Murphy	ldrb	cur_byte, [srcin], #1
609e51cafdSRobin Murphy	sub	cntin, cntin, #1
619e51cafdSRobin Murphy	cmp	cur_byte, chrin
629e51cafdSRobin Murphy	b.ne	L(byte_loop)
639e51cafdSRobin Murphy	sub	srcin, srcin, #1
644a899227SCatalin Marinas	ret
659e51cafdSRobin MurphyL(found_word):
669e51cafdSRobin MurphyCPU_LE(	rev	tmp, tmp)
679e51cafdSRobin Murphy	clz	tmp, tmp
689e51cafdSRobin Murphy	sub	tmp, tmp, #64
699e51cafdSRobin Murphy	add	result, srcin, tmp, asr #3
709e51cafdSRobin Murphy	ret
719e51cafdSRobin MurphyL(not_found):
729e51cafdSRobin Murphy	mov	result, #0
734a899227SCatalin Marinas	ret
74*0f61f6beSMark RutlandSYM_FUNC_END(__pi_memchr)
75*0f61f6beSMark RutlandSYM_FUNC_ALIAS_WEAK(memchr, __pi_memchr)
76ac0e8c72SMark RutlandEXPORT_SYMBOL_NOKASAN(memchr)
77