memset.S revision 270882
1129202Scognet/*	$NetBSD: memset.S,v 1.4 2003/10/14 07:51:45 scw Exp $	*/
2129202Scognet
3129202Scognet/*
4129202Scognet * Copyright 2003 Wasabi Systems, Inc.
5129202Scognet * All rights reserved.
6129202Scognet *
7129202Scognet * Written by Steve C. Woodford for Wasabi Systems, Inc.
8129202Scognet *
9129202Scognet * Redistribution and use in source and binary forms, with or without
10129202Scognet * modification, are permitted provided that the following conditions
11129202Scognet * are met:
12129202Scognet * 1. Redistributions of source code must retain the above copyright
13129202Scognet *    notice, this list of conditions and the following disclaimer.
14129202Scognet * 2. Redistributions in binary form must reproduce the above copyright
15129202Scognet *    notice, this list of conditions and the following disclaimer in the
16129202Scognet *    documentation and/or other materials provided with the distribution.
17129202Scognet * 3. All advertising materials mentioning features or use of this software
18129202Scognet *    must display the following acknowledgement:
19129202Scognet *      This product includes software developed for the NetBSD Project by
20129202Scognet *      Wasabi Systems, Inc.
21129202Scognet * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22129202Scognet *    or promote products derived from this software without specific prior
23129202Scognet *    written permission.
24129202Scognet *
25129202Scognet * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26129202Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27129202Scognet * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28129202Scognet * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29129202Scognet * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30129202Scognet * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31129202Scognet * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32129202Scognet * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33129202Scognet * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34129202Scognet * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35129202Scognet * POSSIBILITY OF SUCH DAMAGE.
36129202Scognet */
37129202Scognet/*
38129202Scognet * Copyright (c) 1995 Mark Brinicombe.
39129202Scognet * All rights reserved.
40129202Scognet *
41129202Scognet * Redistribution and use in source and binary forms, with or without
42129202Scognet * modification, are permitted provided that the following conditions
43129202Scognet * are met:
44129202Scognet * 1. Redistributions of source code must retain the above copyright
45129202Scognet *    notice, this list of conditions and the following disclaimer.
46129202Scognet * 2. Redistributions in binary form must reproduce the above copyright
47129202Scognet *    notice, this list of conditions and the following disclaimer in the
48129202Scognet *    documentation and/or other materials provided with the distribution.
49129202Scognet * 3. All advertising materials mentioning features or use of this software
50129202Scognet *    must display the following acknowledgement:
51129202Scognet *	This product includes software developed by Mark Brinicombe.
52129202Scognet * 4. The name of the company nor the name of the author may be used to
53129202Scognet *    endorse or promote products derived from this software without specific
54129202Scognet *    prior written permission.
55129202Scognet *
56129202Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
57129202Scognet * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
58129202Scognet * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
59129202Scognet * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
60129202Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
61129202Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
62129202Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63129202Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64129202Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65129202Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66129202Scognet * SUCH DAMAGE.
67129202Scognet */
68129202Scognet
69129202Scognet#include <machine/asm.h>
70129202Scognet__FBSDID("$FreeBSD: head/lib/libc/arm/string/memset.S 270882 2014-08-31 17:21:51Z ian $");
71129202Scognet
72129202Scognet/*
73129202Scognet * memset: Sets a block of memory to the specified value
74129202Scognet *
75129202Scognet * On entry:
76129202Scognet *   r0 - dest address
77129202Scognet *   r1 - byte to write
78129202Scognet *   r2 - number of bytes to write
79129202Scognet *
80129202Scognet * On exit:
81129202Scognet *   r0 - dest address
82129202Scognet */
83129202Scognet#ifdef _BZERO
84129202Scognet/* LINTSTUB: Func: void bzero(void *, size_t) */
85129202ScognetENTRY(bzero)
86129202Scognet	mov	r3, #0x00
87129202Scognet#else
88129202Scognet/* LINTSTUB: Func: void *memset(void *, int, size_t) */
89129202ScognetENTRY(memset)
90129202Scognet	and	r3, r1, #0xff		/* We deal with bytes */
91129202Scognet	mov	r1, r2
92129202Scognet#endif
93129202Scognet	cmp	r1, #0x04		/* Do we have less than 4 bytes */
94129202Scognet	mov	ip, r0
95129202Scognet	blt	.Lmemset_lessthanfour
96129202Scognet
97129202Scognet	/* Ok first we will word align the address */
98129202Scognet	ands	r2, ip, #0x03		/* Get the bottom two bits */
99129202Scognet	bne	.Lmemset_wordunaligned	/* The address is not word aligned */
100129202Scognet
101129202Scognet	/* We are now word aligned */
102129202Scognet.Lmemset_wordaligned:
103129202Scognet#ifndef _BZERO
104129202Scognet	orr	r3, r3, r3, lsl #8	/* Extend value to 16-bits */
105129202Scognet#endif
106172616Scognet#ifdef _ARM_ARCH_5E
107172616Scognet	tst	ip, #0x04		/* Quad-align for armv5e */
108129202Scognet#else
109129202Scognet	cmp	r1, #0x10
110129202Scognet#endif
111129202Scognet#ifndef _BZERO
112129202Scognet	orr	r3, r3, r3, lsl #16	/* Extend value to 32-bits */
113129202Scognet#endif
114172616Scognet#ifdef _ARM_ARCH_5E
115129202Scognet	subne	r1, r1, #0x04		/* Quad-align if necessary */
116129202Scognet	strne	r3, [ip], #0x04
117129202Scognet	cmp	r1, #0x10
118129202Scognet#endif
119129202Scognet	blt	.Lmemset_loop4		/* If less than 16 then use words */
120129202Scognet	mov	r2, r3			/* Duplicate data */
121129202Scognet	cmp	r1, #0x80		/* If < 128 then skip the big loop */
122129202Scognet	blt	.Lmemset_loop32
123129202Scognet
124129202Scognet	/* Do 128 bytes at a time */
125129202Scognet.Lmemset_loop128:
126129202Scognet	subs	r1, r1, #0x80
127172616Scognet#ifdef _ARM_ARCH_5E
128129202Scognet	strged	r2, [ip], #0x08
129129202Scognet	strged	r2, [ip], #0x08
130129202Scognet	strged	r2, [ip], #0x08
131129202Scognet	strged	r2, [ip], #0x08
132129202Scognet	strged	r2, [ip], #0x08
133129202Scognet	strged	r2, [ip], #0x08
134129202Scognet	strged	r2, [ip], #0x08
135129202Scognet	strged	r2, [ip], #0x08
136129202Scognet	strged	r2, [ip], #0x08
137129202Scognet	strged	r2, [ip], #0x08
138129202Scognet	strged	r2, [ip], #0x08
139129202Scognet	strged	r2, [ip], #0x08
140129202Scognet	strged	r2, [ip], #0x08
141129202Scognet	strged	r2, [ip], #0x08
142129202Scognet	strged	r2, [ip], #0x08
143129202Scognet	strged	r2, [ip], #0x08
144129202Scognet#else
145129202Scognet	stmgeia	ip!, {r2-r3}
146129202Scognet	stmgeia	ip!, {r2-r3}
147129202Scognet	stmgeia	ip!, {r2-r3}
148129202Scognet	stmgeia	ip!, {r2-r3}
149129202Scognet	stmgeia	ip!, {r2-r3}
150129202Scognet	stmgeia	ip!, {r2-r3}
151129202Scognet	stmgeia	ip!, {r2-r3}
152129202Scognet	stmgeia	ip!, {r2-r3}
153129202Scognet	stmgeia	ip!, {r2-r3}
154129202Scognet	stmgeia	ip!, {r2-r3}
155129202Scognet	stmgeia	ip!, {r2-r3}
156129202Scognet	stmgeia	ip!, {r2-r3}
157129202Scognet	stmgeia	ip!, {r2-r3}
158129202Scognet	stmgeia	ip!, {r2-r3}
159129202Scognet	stmgeia	ip!, {r2-r3}
160129202Scognet	stmgeia	ip!, {r2-r3}
161129202Scognet#endif
162129202Scognet	bgt	.Lmemset_loop128
163137464Scognet	RETeq			/* Zero length so just exit */
164129202Scognet
165129202Scognet	add	r1, r1, #0x80		/* Adjust for extra sub */
166129202Scognet
167129202Scognet	/* Do 32 bytes at a time */
168129202Scognet.Lmemset_loop32:
169129202Scognet	subs	r1, r1, #0x20
170172616Scognet#ifdef _ARM_ARCH_5E
171129202Scognet	strged	r2, [ip], #0x08
172129202Scognet	strged	r2, [ip], #0x08
173129202Scognet	strged	r2, [ip], #0x08
174129202Scognet	strged	r2, [ip], #0x08
175129202Scognet#else
176129202Scognet	stmgeia	ip!, {r2-r3}
177129202Scognet	stmgeia	ip!, {r2-r3}
178129202Scognet	stmgeia	ip!, {r2-r3}
179129202Scognet	stmgeia	ip!, {r2-r3}
180129202Scognet#endif
181129202Scognet	bgt	.Lmemset_loop32
182137464Scognet	RETeq			/* Zero length so just exit */
183129202Scognet
184129202Scognet	adds	r1, r1, #0x10		/* Partially adjust for extra sub */
185129202Scognet
186129202Scognet	/* Deal with 16 bytes or more */
187172616Scognet#ifdef _ARM_ARCH_5E
188129202Scognet	strged	r2, [ip], #0x08
189129202Scognet	strged	r2, [ip], #0x08
190129202Scognet#else
191129202Scognet	stmgeia	ip!, {r2-r3}
192129202Scognet	stmgeia	ip!, {r2-r3}
193129202Scognet#endif
194137464Scognet	RETeq			/* Zero length so just exit */
195129202Scognet
196129202Scognet	addlt	r1, r1, #0x10		/* Possibly adjust for extra sub */
197129202Scognet
198129202Scognet	/* We have at least 4 bytes so copy as words */
199129202Scognet.Lmemset_loop4:
200129202Scognet	subs	r1, r1, #0x04
201129202Scognet	strge	r3, [ip], #0x04
202129202Scognet	bgt	.Lmemset_loop4
203137464Scognet	RETeq			/* Zero length so just exit */
204129202Scognet
205172616Scognet#ifdef _ARM_ARCH_5E
206129202Scognet	/* Compensate for 64-bit alignment check */
207129202Scognet	adds	r1, r1, #0x04
208137464Scognet	RETeq
209129202Scognet	cmp	r1, #2
210129202Scognet#else
211129202Scognet	cmp	r1, #-2
212129202Scognet#endif
213129202Scognet
214129202Scognet	strb	r3, [ip], #0x01		/* Set 1 byte */
215129202Scognet	strgeb	r3, [ip], #0x01		/* Set another byte */
216129202Scognet	strgtb	r3, [ip]		/* and a third */
217137464Scognet	RET			/* Exit */
218129202Scognet
219129202Scognet.Lmemset_wordunaligned:
220129202Scognet	rsb	r2, r2, #0x004
221129202Scognet	strb	r3, [ip], #0x01		/* Set 1 byte */
222129202Scognet	cmp	r2, #0x02
223129202Scognet	strgeb	r3, [ip], #0x01		/* Set another byte */
224129202Scognet	sub	r1, r1, r2
225129202Scognet	strgtb	r3, [ip], #0x01		/* and a third */
226129202Scognet	cmp	r1, #0x04		/* More than 4 bytes left? */
227129202Scognet	bge	.Lmemset_wordaligned	/* Yup */
228129202Scognet
229129202Scognet.Lmemset_lessthanfour:
230129202Scognet	cmp	r1, #0x00
231137464Scognet	RETeq			/* Zero length so exit */
232129202Scognet	strb	r3, [ip], #0x01		/* Set 1 byte */
233129202Scognet	cmp	r1, #0x02
234129202Scognet	strgeb	r3, [ip], #0x01		/* Set another byte */
235129202Scognet	strgtb	r3, [ip]		/* and a third */
236137464Scognet	RET			/* Exit */
237270882Sian#ifdef _BZERO
238270882SianEND(bzero)
239270882Sian#else
240270882SianEND(memset)
241270882Sian#endif
242