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