1bbbf1280Sopenharmony_ci/*
2bbbf1280Sopenharmony_ci * memset - fill memory with a constant
3bbbf1280Sopenharmony_ci *
4bbbf1280Sopenharmony_ci * Copyright (c) 2010-2021, Arm Limited.
5bbbf1280Sopenharmony_ci * SPDX-License-Identifier: MIT
6bbbf1280Sopenharmony_ci */
7bbbf1280Sopenharmony_ci
8bbbf1280Sopenharmony_ci/*
9bbbf1280Sopenharmony_ci   Written by Dave Gilbert <david.gilbert@linaro.org>
10bbbf1280Sopenharmony_ci
11bbbf1280Sopenharmony_ci   This memset routine is optimised on a Cortex-A9 and should work on
12bbbf1280Sopenharmony_ci   all ARMv7 processors.
13bbbf1280Sopenharmony_ci
14bbbf1280Sopenharmony_ci */
15bbbf1280Sopenharmony_ci
16bbbf1280Sopenharmony_ci	.syntax unified
17bbbf1280Sopenharmony_ci	.arch armv7-a
18bbbf1280Sopenharmony_ci
19bbbf1280Sopenharmony_ci@ 2011-08-30 david.gilbert@linaro.org
20bbbf1280Sopenharmony_ci@    Extracted from local git 2f11b436
21bbbf1280Sopenharmony_ci
22bbbf1280Sopenharmony_ci@ this lets us check a flag in a 00/ff byte easily in either endianness
23bbbf1280Sopenharmony_ci#ifdef __ARMEB__
24bbbf1280Sopenharmony_ci#define CHARTSTMASK(c) 1<<(31-(c*8))
25bbbf1280Sopenharmony_ci#else
26bbbf1280Sopenharmony_ci#define CHARTSTMASK(c) 1<<(c*8)
27bbbf1280Sopenharmony_ci#endif
28bbbf1280Sopenharmony_ci	.thumb
29bbbf1280Sopenharmony_ci
30bbbf1280Sopenharmony_ci@ ---------------------------------------------------------------------------
31bbbf1280Sopenharmony_ci	.thumb_func
32bbbf1280Sopenharmony_ci	.align 2
33bbbf1280Sopenharmony_ci	.p2align 4,,15
34bbbf1280Sopenharmony_ci	.global __memset_arm
35bbbf1280Sopenharmony_ci	.type __memset_arm,%function
36bbbf1280Sopenharmony_ci__memset_arm:
37bbbf1280Sopenharmony_ci	@ r0 = address
38bbbf1280Sopenharmony_ci	@ r1 = character
39bbbf1280Sopenharmony_ci	@ r2 = count
40bbbf1280Sopenharmony_ci	@ returns original address in r0
41bbbf1280Sopenharmony_ci
42bbbf1280Sopenharmony_ci	mov	r3, r0		@ Leave r0 alone
43bbbf1280Sopenharmony_ci	cbz	r2, 10f		@ Exit if 0 length
44bbbf1280Sopenharmony_ci
45bbbf1280Sopenharmony_ci	tst	r0, #7
46bbbf1280Sopenharmony_ci	beq	2f		@ Already aligned
47bbbf1280Sopenharmony_ci
48bbbf1280Sopenharmony_ci	@ Ok, so we're misaligned here
49bbbf1280Sopenharmony_ci1:
50bbbf1280Sopenharmony_ci	strb	r1, [r3], #1
51bbbf1280Sopenharmony_ci	subs	r2,r2,#1
52bbbf1280Sopenharmony_ci	tst	r3, #7
53bbbf1280Sopenharmony_ci	cbz	r2, 10f		@ Exit if we hit the end
54bbbf1280Sopenharmony_ci	bne	1b		@ go round again if still misaligned
55bbbf1280Sopenharmony_ci
56bbbf1280Sopenharmony_ci2:
57bbbf1280Sopenharmony_ci	@ OK, so we're aligned
58bbbf1280Sopenharmony_ci	push	{r4,r5,r6,r7}
59bbbf1280Sopenharmony_ci	bics	r4, r2, #15	@ if less than 16 bytes then need to finish it off
60bbbf1280Sopenharmony_ci	beq	5f
61bbbf1280Sopenharmony_ci
62bbbf1280Sopenharmony_ci3:
63bbbf1280Sopenharmony_ci	@ POSIX says that ch is cast to an unsigned char.  A uxtb is one
64bbbf1280Sopenharmony_ci	@ byte and takes two cycles, where an AND is four bytes but one
65bbbf1280Sopenharmony_ci	@ cycle.
66bbbf1280Sopenharmony_ci	and	r1, #0xFF
67bbbf1280Sopenharmony_ci	orr	r1, r1, r1, lsl#8	@ Same character into all bytes
68bbbf1280Sopenharmony_ci	orr	r1, r1, r1, lsl#16
69bbbf1280Sopenharmony_ci	mov	r5,r1
70bbbf1280Sopenharmony_ci	mov	r6,r1
71bbbf1280Sopenharmony_ci	mov	r7,r1
72bbbf1280Sopenharmony_ci
73bbbf1280Sopenharmony_ci4:
74bbbf1280Sopenharmony_ci	subs	r4,r4,#16
75bbbf1280Sopenharmony_ci	stmia	r3!,{r1,r5,r6,r7}
76bbbf1280Sopenharmony_ci	bne	4b
77bbbf1280Sopenharmony_ci	and	r2,r2,#15
78bbbf1280Sopenharmony_ci
79bbbf1280Sopenharmony_ci	@ At this point we're still aligned and we have upto align-1 bytes left to right
80bbbf1280Sopenharmony_ci	@ we can avoid some of the byte-at-a time now by testing for some big chunks
81bbbf1280Sopenharmony_ci	tst	r2,#8
82bbbf1280Sopenharmony_ci	itt	ne
83bbbf1280Sopenharmony_ci	subne	r2,r2,#8
84bbbf1280Sopenharmony_ci	stmiane	r3!,{r1,r5}
85bbbf1280Sopenharmony_ci
86bbbf1280Sopenharmony_ci5:
87bbbf1280Sopenharmony_ci	pop	{r4,r5,r6,r7}
88bbbf1280Sopenharmony_ci	cbz	r2, 10f
89bbbf1280Sopenharmony_ci
90bbbf1280Sopenharmony_ci	@ Got to do any last < alignment bytes
91bbbf1280Sopenharmony_ci6:
92bbbf1280Sopenharmony_ci	subs	r2,r2,#1
93bbbf1280Sopenharmony_ci	strb	r1,[r3],#1
94bbbf1280Sopenharmony_ci	bne	6b
95bbbf1280Sopenharmony_ci
96bbbf1280Sopenharmony_ci10:
97bbbf1280Sopenharmony_ci	bx	lr		@ goodbye
98bbbf1280Sopenharmony_ci	.size	__memset_arm, . - __memset_arm
99