xref: /openbsd-src/lib/libc/arch/arm/string/memset.S (revision ea6088e7d368d53c49ebfdf4520275cec2f78f5b)
1*ea6088e7Sguenther/*	$OpenBSD: memset.S,v 1.6 2017/11/29 05:13:57 guenther Exp $	*/
2d987040fSdrahn/*	$NetBSD: memset.S,v 1.3 2003/04/05 23:08:52 bjh21 Exp $	*/
3d987040fSdrahn
4d987040fSdrahn/*
5d987040fSdrahn * Copyright (c) 1995 Mark Brinicombe.
6d987040fSdrahn * All rights reserved.
7d987040fSdrahn *
8d987040fSdrahn * Redistribution and use in source and binary forms, with or without
9d987040fSdrahn * modification, are permitted provided that the following conditions
10d987040fSdrahn * are met:
11d987040fSdrahn * 1. Redistributions of source code must retain the above copyright
12d987040fSdrahn *    notice, this list of conditions and the following disclaimer.
13d987040fSdrahn * 2. Redistributions in binary form must reproduce the above copyright
14d987040fSdrahn *    notice, this list of conditions and the following disclaimer in the
15d987040fSdrahn *    documentation and/or other materials provided with the distribution.
16d987040fSdrahn * 3. All advertising materials mentioning features or use of this software
17d987040fSdrahn *    must display the following acknowledgement:
18d987040fSdrahn *	This product includes software developed by Mark Brinicombe.
19d987040fSdrahn * 4. The name of the company nor the name of the author may be used to
20d987040fSdrahn *    endorse or promote products derived from this software without specific
21d987040fSdrahn *    prior written permission.
22d987040fSdrahn *
23d987040fSdrahn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
24d987040fSdrahn * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25d987040fSdrahn * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26d987040fSdrahn * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27d987040fSdrahn * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28d987040fSdrahn * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29d987040fSdrahn * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30d987040fSdrahn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31d987040fSdrahn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32d987040fSdrahn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33d987040fSdrahn * SUCH DAMAGE.
34d987040fSdrahn */
35d987040fSdrahn
3638848718Sguenther#include "DEFS.h"
37d987040fSdrahn
38d987040fSdrahn/*
39d987040fSdrahn * Sets a block of memory to the specified value
40d987040fSdrahn *
41d987040fSdrahn * On entry:
42d987040fSdrahn *   r0 - dest address
43d987040fSdrahn *   r1 - byte to write
44d987040fSdrahn *   r2 - number of bytes to write
45d987040fSdrahn *
46d987040fSdrahn * On exit:
47d987040fSdrahn *   r0 - dest address
48d987040fSdrahn */
49d987040fSdrahn
50c6b709f5Sjsg.syntax unified
51c6b709f5Sjsg
52d987040fSdrahnENTRY(memset)
53d987040fSdrahn	stmfd	sp!, {r0}		/* Remember address for return value */
54d987040fSdrahn	and	r1, r1, #0x000000ff	/* We write bytes */
55d987040fSdrahn
56d987040fSdrahn	cmp	r2, #0x00000004		/* Do we have less than 4 bytes */
57d987040fSdrahn	blt	.Lmemset_lessthanfour
58d987040fSdrahn
59d987040fSdrahn	/* Ok first we will word align the address */
60d987040fSdrahn
61d987040fSdrahn	ands	r3, r0, #0x00000003	/* Get the bottom two bits */
62d987040fSdrahn	beq	.Lmemset_addraligned	/* The address is word aligned */
63d987040fSdrahn
64d987040fSdrahn	rsb	r3, r3, #0x00000004
65d987040fSdrahn	sub	r2, r2, r3
66d987040fSdrahn	cmp	r3, #0x00000002
67d987040fSdrahn	strb	r1, [r0], #0x0001	/* Set 1 byte */
68c6b709f5Sjsg	strbge	r1, [r0], #0x0001	/* Set another byte */
69c6b709f5Sjsg	strbgt	r1, [r0], #0x0001	/* and a third */
70d987040fSdrahn
71d987040fSdrahn	cmp	r2, #0x00000004
72d987040fSdrahn	blt	.Lmemset_lessthanfour
73d987040fSdrahn
74d987040fSdrahn	/* Now we must be word aligned */
75d987040fSdrahn
76d987040fSdrahn.Lmemset_addraligned:
77d987040fSdrahn
78d987040fSdrahn	orr	r3, r1, r1, lsl #8	/* Repeat the byte into a word */
79d987040fSdrahn	orr	r3, r3, r3, lsl #16
80d987040fSdrahn
81d987040fSdrahn	/* We know we have at least 4 bytes ... */
82d987040fSdrahn
83d987040fSdrahn	cmp	r2, #0x00000020		/* If less than 32 then use words */
84d987040fSdrahn	blt	.Lmemset_lessthan32
85d987040fSdrahn
86d987040fSdrahn	/* We have at least 32 so lets use quad words */
87d987040fSdrahn
88d987040fSdrahn	stmfd	sp!, {r4-r6}		/* Store registers */
89d987040fSdrahn	mov	r4, r3			/* Duplicate data */
90d987040fSdrahn	mov	r5, r3
91d987040fSdrahn	mov	r6, r3
92d987040fSdrahn
93d987040fSdrahn.Lmemset_loop16:
94d987040fSdrahn	stmia	r0!, {r3-r6}		/* Store 16 bytes */
95d987040fSdrahn	sub	r2, r2, #0x00000010	/* Adjust count */
96d987040fSdrahn	cmp	r2, #0x00000010		/* Still got at least 16 bytes ? */
97d987040fSdrahn	bgt	.Lmemset_loop16
98d987040fSdrahn
99d987040fSdrahn	ldmfd	sp!, {r4-r6}		/* Restore registers */
100d987040fSdrahn
101d987040fSdrahn	/* Do we need to set some words as well ? */
102d987040fSdrahn
103d987040fSdrahn	cmp	r2, #0x00000004
104d987040fSdrahn	blt	.Lmemset_lessthanfour
105d987040fSdrahn
106d987040fSdrahn	/* Have either less than 16 or less than 32 depending on route taken */
107d987040fSdrahn
108d987040fSdrahn.Lmemset_lessthan32:
109d987040fSdrahn
110d987040fSdrahn	/* We have at least 4 bytes so copy as words */
111d987040fSdrahn
112d987040fSdrahn.Lmemset_loop4:
113d987040fSdrahn	str	r3, [r0], #0x0004
114d987040fSdrahn	sub	r2, r2, #0x0004
115d987040fSdrahn	cmp	r2, #0x00000004
116d987040fSdrahn	bge	.Lmemset_loop4
117d987040fSdrahn
118d987040fSdrahn.Lmemset_lessthanfour:
119d987040fSdrahn	cmp	r2, #0x00000000
120c6b709f5Sjsg	ldmfdeq	sp!, {r0}
121d987040fSdrahn	moveq	pc, lr			/* Zero length so exit */
122d987040fSdrahn
123d987040fSdrahn	cmp	r2, #0x00000002
124d987040fSdrahn	strb	r1, [r0], #0x0001	/* Set 1 byte */
125c6b709f5Sjsg	strbge	r1, [r0], #0x0001	/* Set another byte */
126c6b709f5Sjsg	strbgt	r1, [r0], #0x0001	/* and a third */
127d987040fSdrahn
128d987040fSdrahn	ldmfd	sp!, {r0}
129d987040fSdrahn	mov	pc, lr			/* Exit */
130*ea6088e7SguentherEND_BUILTIN(memset)
131