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