1129198Scognet/*	$NetBSD: bcopy_page.S,v 1.7 2003/10/13 21:03:13 scw Exp $	*/
2129198Scognet
3139735Simp/*-
4129198Scognet * Copyright (c) 1995 Scott Stevens
5129198Scognet * All rights reserved.
6129198Scognet *
7129198Scognet * Redistribution and use in source and binary forms, with or without
8129198Scognet * modification, are permitted provided that the following conditions
9129198Scognet * are met:
10129198Scognet * 1. Redistributions of source code must retain the above copyright
11129198Scognet *    notice, this list of conditions and the following disclaimer.
12129198Scognet * 2. Redistributions in binary form must reproduce the above copyright
13129198Scognet *    notice, this list of conditions and the following disclaimer in the
14129198Scognet *    documentation and/or other materials provided with the distribution.
15129198Scognet * 3. All advertising materials mentioning features or use of this software
16129198Scognet *    must display the following acknowledgement:
17129198Scognet *	This product includes software developed by Scott Stevens.
18129198Scognet * 4. The name of the author may not be used to endorse or promote products
19129198Scognet *    derived from this software without specific prior written permission.
20129198Scognet *
21129198Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22129198Scognet * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23129198Scognet * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24129198Scognet * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25129198Scognet * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26129198Scognet * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27129198Scognet * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28129198Scognet * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29129198Scognet * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30129198Scognet * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31129198Scognet *
32129198Scognet * RiscBSD kernel project
33129198Scognet *
34129198Scognet * bcopy_page.S
35129198Scognet *
36129198Scognet * page optimised bcopy and bzero routines
37129198Scognet *
38129198Scognet * Created      : 08/04/95
39129198Scognet */
40129198Scognet
41129198Scognet#include <machine/asm.h>
42150996Scognet
43129198Scognet__FBSDID("$FreeBSD$");
44150996Scognet
45150996Scognet#include "assym.s"
46150996Scognet
47172614Scognet#ifndef _ARM_ARCH_5E
48129198Scognet
49129198Scognet/* #define BIG_LOOPS */
50129198Scognet
51129198Scognet/*
52129198Scognet * bcopy_page(src, dest)
53129198Scognet *
54129198Scognet * Optimised copy page routine.
55129198Scognet *
56129198Scognet * On entry:
57129198Scognet *   r0 - src address
58129198Scognet *   r1 - dest address
59129198Scognet *
60129198Scognet * Requires:
61129198Scognet *   number of bytes per page (PAGE_SIZE) is a multiple of 512 (BIG_LOOPS), 128
62129198Scognet *   otherwise.
63129198Scognet */
64129198Scognet
65129198Scognet#define	CHUNK_SIZE	32
66129198Scognet
67129198Scognet#define	PREFETCH_FIRST_CHUNK	/* nothing */
68129198Scognet#define	PREFETCH_NEXT_CHUNK	/* nothing */
69129198Scognet
70129198Scognet#ifndef COPY_CHUNK
71129198Scognet#define	COPY_CHUNK \
72129198Scognet	PREFETCH_NEXT_CHUNK ; \
73129198Scognet	ldmia	r0!, {r3-r8,ip,lr} ; \
74129198Scognet	stmia	r1!, {r3-r8,ip,lr}
75129198Scognet#endif /* ! COPY_CHUNK */
76129198Scognet
77129198Scognet#ifndef SAVE_REGS
78288662Srwatson#define	SAVE_REGS	stmfd	sp!, {r4-r8, lr}; _SAVE({r4-r8, lr})
79129198Scognet#define	RESTORE_REGS	ldmfd	sp!, {r4-r8, pc}
80129198Scognet#endif
81129198Scognet
82129198ScognetENTRY(bcopy_page)
83129198Scognet	PREFETCH_FIRST_CHUNK
84129198Scognet	SAVE_REGS
85129198Scognet#ifdef BIG_LOOPS
86129198Scognet	mov	r2, #(PAGE_SIZE >> 9)
87129198Scognet#else
88129198Scognet	mov	r2, #(PAGE_SIZE >> 7)
89129198Scognet#endif
90129198Scognet
91129198Scognet1:
92129198Scognet	COPY_CHUNK
93129198Scognet	COPY_CHUNK
94129198Scognet	COPY_CHUNK
95129198Scognet	COPY_CHUNK
96129198Scognet
97129198Scognet#ifdef BIG_LOOPS
98129198Scognet	/* There is little point making the loop any larger; unless we are
99129198Scognet	   running with the cache off, the load/store overheads will
100129198Scognet	   completely dominate this loop.  */
101129198Scognet	COPY_CHUNK
102129198Scognet	COPY_CHUNK
103129198Scognet	COPY_CHUNK
104129198Scognet	COPY_CHUNK
105129198Scognet
106129198Scognet	COPY_CHUNK
107129198Scognet	COPY_CHUNK
108129198Scognet	COPY_CHUNK
109129198Scognet	COPY_CHUNK
110129198Scognet
111129198Scognet	COPY_CHUNK
112129198Scognet	COPY_CHUNK
113129198Scognet	COPY_CHUNK
114129198Scognet	COPY_CHUNK
115129198Scognet#endif
116129198Scognet	subs	r2, r2, #1
117129198Scognet	bne	1b
118129198Scognet
119129198Scognet	RESTORE_REGS		/* ...and return. */
120248361SandrewEND(bcopy_page)
121129198Scognet
122129198Scognet/*
123129198Scognet * bzero_page(dest)
124129198Scognet *
125129198Scognet * Optimised zero page routine.
126129198Scognet *
127129198Scognet * On entry:
128129198Scognet *   r0 - dest address
129129198Scognet *
130129198Scognet * Requires:
131129198Scognet *   number of bytes per page (PAGE_SIZE) is a multiple of 512 (BIG_LOOPS), 128
132129198Scognet *   otherwise
133129198Scognet */
134129198Scognet
135129198ScognetENTRY(bzero_page)
136129198Scognet	stmfd	sp!, {r4-r8, lr}
137288662Srwatson	_SAVE({r4-r8, lr})
138129198Scognet#ifdef BIG_LOOPS
139129198Scognet	mov	r2, #(PAGE_SIZE >> 9)
140129198Scognet#else
141129198Scognet	mov	r2, #(PAGE_SIZE >> 7)
142129198Scognet#endif
143129198Scognet	mov	r3, #0
144129198Scognet	mov	r4, #0
145129198Scognet	mov	r5, #0
146129198Scognet	mov	r6, #0
147129198Scognet	mov	r7, #0
148129198Scognet	mov	r8, #0
149129198Scognet	mov	ip, #0
150129198Scognet	mov	lr, #0
151129198Scognet
152129198Scognet1:
153129198Scognet	stmia	r0!, {r3-r8,ip,lr}
154129198Scognet	stmia	r0!, {r3-r8,ip,lr}
155129198Scognet	stmia	r0!, {r3-r8,ip,lr}
156129198Scognet	stmia	r0!, {r3-r8,ip,lr}
157129198Scognet
158129198Scognet#ifdef BIG_LOOPS
159129198Scognet	/* There is little point making the loop any larger; unless we are
160129198Scognet	   running with the cache off, the load/store overheads will
161129198Scognet	   completely dominate this loop.  */
162129198Scognet	stmia	r0!, {r3-r8,ip,lr}
163129198Scognet	stmia	r0!, {r3-r8,ip,lr}
164129198Scognet	stmia	r0!, {r3-r8,ip,lr}
165129198Scognet	stmia	r0!, {r3-r8,ip,lr}
166129198Scognet
167129198Scognet	stmia	r0!, {r3-r8,ip,lr}
168129198Scognet	stmia	r0!, {r3-r8,ip,lr}
169129198Scognet	stmia	r0!, {r3-r8,ip,lr}
170129198Scognet	stmia	r0!, {r3-r8,ip,lr}
171129198Scognet
172129198Scognet	stmia	r0!, {r3-r8,ip,lr}
173129198Scognet	stmia	r0!, {r3-r8,ip,lr}
174129198Scognet	stmia	r0!, {r3-r8,ip,lr}
175129198Scognet	stmia	r0!, {r3-r8,ip,lr}
176129198Scognet
177129198Scognet#endif
178129198Scognet
179129198Scognet	subs	r2, r2, #1
180129198Scognet	bne	1b
181129198Scognet
182129198Scognet	ldmfd	sp!, {r4-r8, pc}
183248361SandrewEND(bzero_page)
184129198Scognet
185172614Scognet#else	/* _ARM_ARCH_5E */
186129198Scognet
187129198Scognet/*
188172614Scognet * armv5e version of bcopy_page
189129198Scognet */
190129198ScognetENTRY(bcopy_page)
191129198Scognet	pld	[r0]
192129198Scognet	stmfd	sp!, {r4, r5}
193288662Srwatson	_SAVE({r4, r5})
194129198Scognet	mov	ip, #32
195129198Scognet	ldr	r2, [r0], #0x04		/* 0x00 */
196129198Scognet	ldr	r3, [r0], #0x04		/* 0x04 */
197129198Scognet1:	pld	[r0, #0x18]		/* Prefetch 0x20 */
198129198Scognet	ldr	r4, [r0], #0x04		/* 0x08 */
199129198Scognet	ldr	r5, [r0], #0x04		/* 0x0c */
200129198Scognet	strd	r2, [r1], #0x08
201129198Scognet	ldr	r2, [r0], #0x04		/* 0x10 */
202129198Scognet	ldr	r3, [r0], #0x04		/* 0x14 */
203129198Scognet	strd	r4, [r1], #0x08
204129198Scognet	ldr	r4, [r0], #0x04		/* 0x18 */
205129198Scognet	ldr	r5, [r0], #0x04		/* 0x1c */
206129198Scognet	strd	r2, [r1], #0x08
207129198Scognet	ldr	r2, [r0], #0x04		/* 0x20 */
208129198Scognet	ldr	r3, [r0], #0x04		/* 0x24 */
209129198Scognet	pld	[r0, #0x18]		/* Prefetch 0x40 */
210129198Scognet	strd	r4, [r1], #0x08
211129198Scognet	ldr	r4, [r0], #0x04		/* 0x28 */
212129198Scognet	ldr	r5, [r0], #0x04		/* 0x2c */
213129198Scognet	strd	r2, [r1], #0x08
214129198Scognet	ldr	r2, [r0], #0x04		/* 0x30 */
215129198Scognet	ldr	r3, [r0], #0x04		/* 0x34 */
216129198Scognet	strd	r4, [r1], #0x08
217129198Scognet	ldr	r4, [r0], #0x04		/* 0x38 */
218129198Scognet	ldr	r5, [r0], #0x04		/* 0x3c */
219129198Scognet	strd	r2, [r1], #0x08
220129198Scognet	ldr	r2, [r0], #0x04		/* 0x40 */
221129198Scognet	ldr	r3, [r0], #0x04		/* 0x44 */
222129198Scognet	pld	[r0, #0x18]		/* Prefetch 0x60 */
223129198Scognet	strd	r4, [r1], #0x08
224129198Scognet	ldr	r4, [r0], #0x04		/* 0x48 */
225129198Scognet	ldr	r5, [r0], #0x04		/* 0x4c */
226129198Scognet	strd	r2, [r1], #0x08
227129198Scognet	ldr	r2, [r0], #0x04		/* 0x50 */
228129198Scognet	ldr	r3, [r0], #0x04		/* 0x54 */
229129198Scognet	strd	r4, [r1], #0x08
230129198Scognet	ldr	r4, [r0], #0x04		/* 0x58 */
231129198Scognet	ldr	r5, [r0], #0x04		/* 0x5c */
232129198Scognet	strd	r2, [r1], #0x08
233129198Scognet	ldr	r2, [r0], #0x04		/* 0x60 */
234129198Scognet	ldr	r3, [r0], #0x04		/* 0x64 */
235129198Scognet	pld	[r0, #0x18]		/* Prefetch 0x80 */
236129198Scognet	strd	r4, [r1], #0x08
237129198Scognet	ldr	r4, [r0], #0x04		/* 0x68 */
238129198Scognet	ldr	r5, [r0], #0x04		/* 0x6c */
239129198Scognet	strd	r2, [r1], #0x08
240129198Scognet	ldr	r2, [r0], #0x04		/* 0x70 */
241129198Scognet	ldr	r3, [r0], #0x04		/* 0x74 */
242129198Scognet	strd	r4, [r1], #0x08
243129198Scognet	ldr	r4, [r0], #0x04		/* 0x78 */
244129198Scognet	ldr	r5, [r0], #0x04		/* 0x7c */
245129198Scognet	strd	r2, [r1], #0x08
246129198Scognet	subs	ip, ip, #0x01
247129198Scognet	ldrgt	r2, [r0], #0x04		/* 0x80 */
248129198Scognet	ldrgt	r3, [r0], #0x04		/* 0x84 */
249129198Scognet	strd	r4, [r1], #0x08
250129198Scognet	bgt	1b
251129198Scognet	ldmfd	sp!, {r4, r5}
252137463Scognet	RET
253248361SandrewEND(bcopy_page)
254129198Scognet
255129198Scognet/*
256172614Scognet * armv5e version of bzero_page
257129198Scognet */
258129198ScognetENTRY(bzero_page)
259129198Scognet	mov	r1, #PAGE_SIZE
260129198Scognet	mov	r2, #0
261129198Scognet	mov	r3, #0
262129198Scognet1:	strd	r2, [r0], #8		/* 32 */
263129198Scognet	strd	r2, [r0], #8
264129198Scognet	strd	r2, [r0], #8
265129198Scognet	strd	r2, [r0], #8
266129198Scognet	strd	r2, [r0], #8		/* 64 */
267129198Scognet	strd	r2, [r0], #8
268129198Scognet	strd	r2, [r0], #8
269129198Scognet	strd	r2, [r0], #8
270129198Scognet	strd	r2, [r0], #8		/* 96 */
271129198Scognet	strd	r2, [r0], #8
272129198Scognet	strd	r2, [r0], #8
273129198Scognet	strd	r2, [r0], #8
274129198Scognet	strd	r2, [r0], #8		/* 128 */
275129198Scognet	strd	r2, [r0], #8
276129198Scognet	strd	r2, [r0], #8
277129198Scognet	strd	r2, [r0], #8
278129198Scognet	subs	r1, r1, #128
279129198Scognet	bne	1b
280137463Scognet	RET
281248361SandrewEND(bzero_page)
282172614Scognet#endif	/* _ARM_ARCH_5E */
283