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$");
71129202Scognet
72275767Sandrew.syntax	unified
73275767Sandrew
74129202Scognet/*
75129202Scognet * memset: Sets a block of memory to the specified value
76129202Scognet *
77129202Scognet * On entry:
78129202Scognet *   r0 - dest address
79129202Scognet *   r1 - byte to write
80129202Scognet *   r2 - number of bytes to write
81129202Scognet *
82129202Scognet * On exit:
83129202Scognet *   r0 - dest address
84129202Scognet */
85129202Scognet#ifdef _BZERO
86129202Scognet/* LINTSTUB: Func: void bzero(void *, size_t) */
87129202ScognetENTRY(bzero)
88129202Scognet	mov	r3, #0x00
89129202Scognet#else
90129202Scognet/* LINTSTUB: Func: void *memset(void *, int, size_t) */
91129202ScognetENTRY(memset)
92129202Scognet	and	r3, r1, #0xff		/* We deal with bytes */
93129202Scognet	mov	r1, r2
94129202Scognet#endif
95129202Scognet	cmp	r1, #0x04		/* Do we have less than 4 bytes */
96129202Scognet	mov	ip, r0
97129202Scognet	blt	.Lmemset_lessthanfour
98129202Scognet
99129202Scognet	/* Ok first we will word align the address */
100129202Scognet	ands	r2, ip, #0x03		/* Get the bottom two bits */
101129202Scognet	bne	.Lmemset_wordunaligned	/* The address is not word aligned */
102129202Scognet
103129202Scognet	/* We are now word aligned */
104129202Scognet.Lmemset_wordaligned:
105129202Scognet#ifndef _BZERO
106129202Scognet	orr	r3, r3, r3, lsl #8	/* Extend value to 16-bits */
107129202Scognet#endif
108172616Scognet#ifdef _ARM_ARCH_5E
109172616Scognet	tst	ip, #0x04		/* Quad-align for armv5e */
110129202Scognet#else
111129202Scognet	cmp	r1, #0x10
112129202Scognet#endif
113129202Scognet#ifndef _BZERO
114129202Scognet	orr	r3, r3, r3, lsl #16	/* Extend value to 32-bits */
115129202Scognet#endif
116172616Scognet#ifdef _ARM_ARCH_5E
117129202Scognet	subne	r1, r1, #0x04		/* Quad-align if necessary */
118129202Scognet	strne	r3, [ip], #0x04
119129202Scognet	cmp	r1, #0x10
120129202Scognet#endif
121129202Scognet	blt	.Lmemset_loop4		/* If less than 16 then use words */
122129202Scognet	mov	r2, r3			/* Duplicate data */
123129202Scognet	cmp	r1, #0x80		/* If < 128 then skip the big loop */
124129202Scognet	blt	.Lmemset_loop32
125129202Scognet
126129202Scognet	/* Do 128 bytes at a time */
127129202Scognet.Lmemset_loop128:
128129202Scognet	subs	r1, r1, #0x80
129172616Scognet#ifdef _ARM_ARCH_5E
130275767Sandrew	strdge	r2, [ip], #0x08
131275767Sandrew	strdge	r2, [ip], #0x08
132275767Sandrew	strdge	r2, [ip], #0x08
133275767Sandrew	strdge	r2, [ip], #0x08
134275767Sandrew	strdge	r2, [ip], #0x08
135275767Sandrew	strdge	r2, [ip], #0x08
136275767Sandrew	strdge	r2, [ip], #0x08
137275767Sandrew	strdge	r2, [ip], #0x08
138275767Sandrew	strdge	r2, [ip], #0x08
139275767Sandrew	strdge	r2, [ip], #0x08
140275767Sandrew	strdge	r2, [ip], #0x08
141275767Sandrew	strdge	r2, [ip], #0x08
142275767Sandrew	strdge	r2, [ip], #0x08
143275767Sandrew	strdge	r2, [ip], #0x08
144275767Sandrew	strdge	r2, [ip], #0x08
145275767Sandrew	strdge	r2, [ip], #0x08
146129202Scognet#else
147275767Sandrew	stmiage	ip!, {r2-r3}
148275767Sandrew	stmiage	ip!, {r2-r3}
149275767Sandrew	stmiage	ip!, {r2-r3}
150275767Sandrew	stmiage	ip!, {r2-r3}
151275767Sandrew	stmiage	ip!, {r2-r3}
152275767Sandrew	stmiage	ip!, {r2-r3}
153275767Sandrew	stmiage	ip!, {r2-r3}
154275767Sandrew	stmiage	ip!, {r2-r3}
155275767Sandrew	stmiage	ip!, {r2-r3}
156275767Sandrew	stmiage	ip!, {r2-r3}
157275767Sandrew	stmiage	ip!, {r2-r3}
158275767Sandrew	stmiage	ip!, {r2-r3}
159275767Sandrew	stmiage	ip!, {r2-r3}
160275767Sandrew	stmiage	ip!, {r2-r3}
161275767Sandrew	stmiage	ip!, {r2-r3}
162275767Sandrew	stmiage	ip!, {r2-r3}
163129202Scognet#endif
164129202Scognet	bgt	.Lmemset_loop128
165137464Scognet	RETeq			/* Zero length so just exit */
166129202Scognet
167129202Scognet	add	r1, r1, #0x80		/* Adjust for extra sub */
168129202Scognet
169129202Scognet	/* Do 32 bytes at a time */
170129202Scognet.Lmemset_loop32:
171129202Scognet	subs	r1, r1, #0x20
172172616Scognet#ifdef _ARM_ARCH_5E
173275767Sandrew	strdge	r2, [ip], #0x08
174275767Sandrew	strdge	r2, [ip], #0x08
175275767Sandrew	strdge	r2, [ip], #0x08
176275767Sandrew	strdge	r2, [ip], #0x08
177129202Scognet#else
178275767Sandrew	stmiage	ip!, {r2-r3}
179275767Sandrew	stmiage	ip!, {r2-r3}
180275767Sandrew	stmiage	ip!, {r2-r3}
181275767Sandrew	stmiage	ip!, {r2-r3}
182129202Scognet#endif
183129202Scognet	bgt	.Lmemset_loop32
184137464Scognet	RETeq			/* Zero length so just exit */
185129202Scognet
186129202Scognet	adds	r1, r1, #0x10		/* Partially adjust for extra sub */
187129202Scognet
188129202Scognet	/* Deal with 16 bytes or more */
189172616Scognet#ifdef _ARM_ARCH_5E
190275767Sandrew	strdge	r2, [ip], #0x08
191275767Sandrew	strdge	r2, [ip], #0x08
192129202Scognet#else
193275767Sandrew	stmiage	ip!, {r2-r3}
194275767Sandrew	stmiage	ip!, {r2-r3}
195129202Scognet#endif
196137464Scognet	RETeq			/* Zero length so just exit */
197129202Scognet
198129202Scognet	addlt	r1, r1, #0x10		/* Possibly adjust for extra sub */
199129202Scognet
200129202Scognet	/* We have at least 4 bytes so copy as words */
201129202Scognet.Lmemset_loop4:
202129202Scognet	subs	r1, r1, #0x04
203129202Scognet	strge	r3, [ip], #0x04
204129202Scognet	bgt	.Lmemset_loop4
205137464Scognet	RETeq			/* Zero length so just exit */
206129202Scognet
207172616Scognet#ifdef _ARM_ARCH_5E
208129202Scognet	/* Compensate for 64-bit alignment check */
209129202Scognet	adds	r1, r1, #0x04
210137464Scognet	RETeq
211129202Scognet	cmp	r1, #2
212129202Scognet#else
213129202Scognet	cmp	r1, #-2
214129202Scognet#endif
215129202Scognet
216129202Scognet	strb	r3, [ip], #0x01		/* Set 1 byte */
217275767Sandrew	strbge	r3, [ip], #0x01		/* Set another byte */
218275767Sandrew	strbgt	r3, [ip]		/* and a third */
219137464Scognet	RET			/* Exit */
220129202Scognet
221129202Scognet.Lmemset_wordunaligned:
222129202Scognet	rsb	r2, r2, #0x004
223129202Scognet	strb	r3, [ip], #0x01		/* Set 1 byte */
224129202Scognet	cmp	r2, #0x02
225275767Sandrew	strbge	r3, [ip], #0x01		/* Set another byte */
226129202Scognet	sub	r1, r1, r2
227275767Sandrew	strbgt	r3, [ip], #0x01		/* and a third */
228129202Scognet	cmp	r1, #0x04		/* More than 4 bytes left? */
229129202Scognet	bge	.Lmemset_wordaligned	/* Yup */
230129202Scognet
231129202Scognet.Lmemset_lessthanfour:
232129202Scognet	cmp	r1, #0x00
233137464Scognet	RETeq			/* Zero length so exit */
234129202Scognet	strb	r3, [ip], #0x01		/* Set 1 byte */
235129202Scognet	cmp	r1, #0x02
236275767Sandrew	strbge	r3, [ip], #0x01		/* Set another byte */
237275767Sandrew	strbgt	r3, [ip]		/* and a third */
238137464Scognet	RET			/* Exit */
239271337Sian#ifdef _BZERO
240271337SianEND(bzero)
241271337Sian#else
242271337SianEND(memset)
243271337Sian#endif
244