1/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6#include <asm_macros.S>
7
8	.global	memset
9
10/* -----------------------------------------------------------------------
11 * void *memset(void *dst, int val, size_t count)
12 *
13 * Copy the value of 'val' (converted to an unsigned char) into
14 * each of the first 'count' characters of the object pointed to by 'dst'.
15 *
16 * Returns the value of 'dst'.
17 * -----------------------------------------------------------------------
18 */
19func memset
20	cbz	x2, exit		/* exit if 'count' = 0 */
21	mov	x3, x0			/* keep x0 */
22	tst	x0, #7
23	b.eq	aligned			/* 8-bytes aligned */
24
25	/* Unaligned 'dst' */
26unaligned:
27	strb	w1, [x3], #1
28	subs	x2, x2, #1
29	b.eq	exit			/* exit if 0 */
30	tst	x3, #7
31	b.ne	unaligned		/* continue while unaligned */
32
33	/* 8-bytes aligned */
34aligned:cbz	x1, x1_zero
35	bfi	w1, w1, #8, #8		/* propagate 'val' */
36	bfi	w1, w1, #16, #16
37	bfi	x1, x1, #32, #32
38
39x1_zero:ands	x4, x2, #~0x3f
40	b.eq	less_64
41
42write_64:
43	.rept	4
44	stp	x1, x1, [x3], #16	/* write 64 bytes in a loop */
45	.endr
46	subs	x4, x4, #64
47	b.ne	write_64
48less_64:tbz	w2, #5, less_32		/* < 32 bytes */
49	stp	x1, x1, [x3], #16	/* write 32 bytes */
50	stp	x1, x1, [x3], #16
51less_32:tbz	w2, #4, less_16		/* < 16 bytes */
52	stp	x1, x1, [x3], #16	/* write 16 bytes */
53less_16:tbz	w2, #3, less_8		/* < 8 bytes */
54	str	x1, [x3], #8		/* write 8 bytes */
55less_8:	tbz	w2, #2, less_4		/* < 4 bytes */
56	str	w1, [x3], #4		/* write 4 bytes */
57less_4:	tbz	w2, #1, less_2		/* < 2 bytes */
58	strh	w1, [x3], #2		/* write 2 bytes */
59less_2:	tbz	w2, #0, exit
60	strb	w1, [x3]		/* write 1 byte */
61exit:	ret
62
63endfunc	memset
64