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
72275256Sandrew.syntax	unified
73275256Sandrew
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
117283831Sandrew	itt	ne
118129202Scognet	subne	r1, r1, #0x04		/* Quad-align if necessary */
119129202Scognet	strne	r3, [ip], #0x04
120129202Scognet	cmp	r1, #0x10
121129202Scognet#endif
122129202Scognet	blt	.Lmemset_loop4		/* If less than 16 then use words */
123129202Scognet	mov	r2, r3			/* Duplicate data */
124129202Scognet	cmp	r1, #0x80		/* If < 128 then skip the big loop */
125129202Scognet	blt	.Lmemset_loop32
126129202Scognet
127129202Scognet	/* Do 128 bytes at a time */
128129202Scognet.Lmemset_loop128:
129129202Scognet	subs	r1, r1, #0x80
130172616Scognet#ifdef _ARM_ARCH_5E
131283831Sandrew	itttt	ge
132275256Sandrew	strdge	r2, [ip], #0x08
133275256Sandrew	strdge	r2, [ip], #0x08
134275256Sandrew	strdge	r2, [ip], #0x08
135275256Sandrew	strdge	r2, [ip], #0x08
136283831Sandrew	itttt	ge
137275256Sandrew	strdge	r2, [ip], #0x08
138275256Sandrew	strdge	r2, [ip], #0x08
139275256Sandrew	strdge	r2, [ip], #0x08
140275256Sandrew	strdge	r2, [ip], #0x08
141283831Sandrew	itttt	ge
142275256Sandrew	strdge	r2, [ip], #0x08
143275256Sandrew	strdge	r2, [ip], #0x08
144275256Sandrew	strdge	r2, [ip], #0x08
145275256Sandrew	strdge	r2, [ip], #0x08
146283831Sandrew	itttt	ge
147275256Sandrew	strdge	r2, [ip], #0x08
148275256Sandrew	strdge	r2, [ip], #0x08
149275256Sandrew	strdge	r2, [ip], #0x08
150275256Sandrew	strdge	r2, [ip], #0x08
151129202Scognet#else
152275256Sandrew	stmiage	ip!, {r2-r3}
153275256Sandrew	stmiage	ip!, {r2-r3}
154275256Sandrew	stmiage	ip!, {r2-r3}
155275256Sandrew	stmiage	ip!, {r2-r3}
156275256Sandrew	stmiage	ip!, {r2-r3}
157275256Sandrew	stmiage	ip!, {r2-r3}
158275256Sandrew	stmiage	ip!, {r2-r3}
159275256Sandrew	stmiage	ip!, {r2-r3}
160275256Sandrew	stmiage	ip!, {r2-r3}
161275256Sandrew	stmiage	ip!, {r2-r3}
162275256Sandrew	stmiage	ip!, {r2-r3}
163275256Sandrew	stmiage	ip!, {r2-r3}
164275256Sandrew	stmiage	ip!, {r2-r3}
165275256Sandrew	stmiage	ip!, {r2-r3}
166275256Sandrew	stmiage	ip!, {r2-r3}
167275256Sandrew	stmiage	ip!, {r2-r3}
168129202Scognet#endif
169129202Scognet	bgt	.Lmemset_loop128
170283831Sandrew	it	eq
171137464Scognet	RETeq			/* Zero length so just exit */
172129202Scognet
173129202Scognet	add	r1, r1, #0x80		/* Adjust for extra sub */
174129202Scognet
175129202Scognet	/* Do 32 bytes at a time */
176129202Scognet.Lmemset_loop32:
177129202Scognet	subs	r1, r1, #0x20
178283831Sandrew	itttt	ge
179172616Scognet#ifdef _ARM_ARCH_5E
180275256Sandrew	strdge	r2, [ip], #0x08
181275256Sandrew	strdge	r2, [ip], #0x08
182275256Sandrew	strdge	r2, [ip], #0x08
183275256Sandrew	strdge	r2, [ip], #0x08
184129202Scognet#else
185275256Sandrew	stmiage	ip!, {r2-r3}
186275256Sandrew	stmiage	ip!, {r2-r3}
187275256Sandrew	stmiage	ip!, {r2-r3}
188275256Sandrew	stmiage	ip!, {r2-r3}
189129202Scognet#endif
190129202Scognet	bgt	.Lmemset_loop32
191283831Sandrew	it	eq
192137464Scognet	RETeq			/* Zero length so just exit */
193129202Scognet
194129202Scognet	adds	r1, r1, #0x10		/* Partially adjust for extra sub */
195129202Scognet
196129202Scognet	/* Deal with 16 bytes or more */
197283831Sandrew	itt	ge
198172616Scognet#ifdef _ARM_ARCH_5E
199275256Sandrew	strdge	r2, [ip], #0x08
200275256Sandrew	strdge	r2, [ip], #0x08
201129202Scognet#else
202275256Sandrew	stmiage	ip!, {r2-r3}
203275256Sandrew	stmiage	ip!, {r2-r3}
204129202Scognet#endif
205283831Sandrew	it	eq
206137464Scognet	RETeq			/* Zero length so just exit */
207129202Scognet
208283831Sandrew	it	lt
209129202Scognet	addlt	r1, r1, #0x10		/* Possibly adjust for extra sub */
210129202Scognet
211129202Scognet	/* We have at least 4 bytes so copy as words */
212129202Scognet.Lmemset_loop4:
213129202Scognet	subs	r1, r1, #0x04
214283831Sandrew	it	ge
215129202Scognet	strge	r3, [ip], #0x04
216129202Scognet	bgt	.Lmemset_loop4
217283831Sandrew	it	eq
218137464Scognet	RETeq			/* Zero length so just exit */
219129202Scognet
220172616Scognet#ifdef _ARM_ARCH_5E
221129202Scognet	/* Compensate for 64-bit alignment check */
222129202Scognet	adds	r1, r1, #0x04
223283831Sandrew	it	eq
224137464Scognet	RETeq
225129202Scognet	cmp	r1, #2
226129202Scognet#else
227129202Scognet	cmp	r1, #-2
228129202Scognet#endif
229129202Scognet
230129202Scognet	strb	r3, [ip], #0x01		/* Set 1 byte */
231283831Sandrew	it	ge
232275256Sandrew	strbge	r3, [ip], #0x01		/* Set another byte */
233283831Sandrew	it	gt
234275256Sandrew	strbgt	r3, [ip]		/* and a third */
235137464Scognet	RET			/* Exit */
236129202Scognet
237129202Scognet.Lmemset_wordunaligned:
238129202Scognet	rsb	r2, r2, #0x004
239129202Scognet	strb	r3, [ip], #0x01		/* Set 1 byte */
240129202Scognet	cmp	r2, #0x02
241283831Sandrew	it	ge
242275256Sandrew	strbge	r3, [ip], #0x01		/* Set another byte */
243129202Scognet	sub	r1, r1, r2
244283831Sandrew	it	gt
245275256Sandrew	strbgt	r3, [ip], #0x01		/* and a third */
246129202Scognet	cmp	r1, #0x04		/* More than 4 bytes left? */
247283831Sandrew	it	ge
248129202Scognet	bge	.Lmemset_wordaligned	/* Yup */
249129202Scognet
250129202Scognet.Lmemset_lessthanfour:
251129202Scognet	cmp	r1, #0x00
252283831Sandrew	it	eq
253137464Scognet	RETeq			/* Zero length so exit */
254129202Scognet	strb	r3, [ip], #0x01		/* Set 1 byte */
255129202Scognet	cmp	r1, #0x02
256283831Sandrew	it	ge
257275256Sandrew	strbge	r3, [ip], #0x01		/* Set another byte */
258283831Sandrew	it	gt
259275256Sandrew	strbgt	r3, [ip]		/* and a third */
260137464Scognet	RET			/* Exit */
261270882Sian#ifdef _BZERO
262270882SianEND(bzero)
263270882Sian#else
264270882SianEND(memset)
265270882Sian#endif
266288373Skib
267288373Skib	.section .note.GNU-stack,"",%progbits
268