xref: /minix3/common/lib/libc/arch/mips/string/bcopy.S (revision f14fb602092e015ff630df58e17c2a9cd57d29b3)
1*f14fb602SLionel Sambuc/*	$NetBSD: bcopy.S,v 1.4 2011/08/27 13:23:52 bouyer Exp $	*/
2b6cbf720SGianluca Guida
3b6cbf720SGianluca Guida/*
4b6cbf720SGianluca Guida * Mach Operating System
5b6cbf720SGianluca Guida * Copyright (c) 1993 Carnegie Mellon University
6b6cbf720SGianluca Guida * All Rights Reserved.
7b6cbf720SGianluca Guida *
8b6cbf720SGianluca Guida * Permission to use, copy, modify and distribute this software and its
9b6cbf720SGianluca Guida * documentation is hereby granted, provided that both the copyright
10b6cbf720SGianluca Guida * notice and this permission notice appear in all copies of the
11b6cbf720SGianluca Guida * software, derivative works or modified versions, and any portions
12b6cbf720SGianluca Guida * thereof, and that both notices appear in supporting documentation.
13b6cbf720SGianluca Guida *
14b6cbf720SGianluca Guida * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15b6cbf720SGianluca Guida * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16b6cbf720SGianluca Guida * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17b6cbf720SGianluca Guida *
18b6cbf720SGianluca Guida * Carnegie Mellon requests users of this software to return to
19b6cbf720SGianluca Guida *
20b6cbf720SGianluca Guida *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
21b6cbf720SGianluca Guida *  School of Computer Science
22b6cbf720SGianluca Guida *  Carnegie Mellon University
23b6cbf720SGianluca Guida *  Pittsburgh PA 15213-3890
24b6cbf720SGianluca Guida *
25b6cbf720SGianluca Guida * any improvements or extensions that they make and grant Carnegie Mellon
26b6cbf720SGianluca Guida * the rights to redistribute these changes.
27b6cbf720SGianluca Guida */
28b6cbf720SGianluca Guida
29b6cbf720SGianluca Guida/*
30b6cbf720SGianluca Guida *	File:	mips_bcopy.s
31b6cbf720SGianluca Guida *	Author:	Chris Maeda
32b6cbf720SGianluca Guida *	Date:	June 1993
33b6cbf720SGianluca Guida *
34b6cbf720SGianluca Guida *	Fast copy routine.  Derived from aligned_block_copy.
35b6cbf720SGianluca Guida */
36b6cbf720SGianluca Guida
37b6cbf720SGianluca Guida
38b6cbf720SGianluca Guida#include <mips/asm.h>
39b6cbf720SGianluca Guida#ifndef _LOCORE
40b6cbf720SGianluca Guida#define _LOCORE		/* XXX not really, just assembly-code source */
41b6cbf720SGianluca Guida#endif
42b6cbf720SGianluca Guida#include <machine/endian.h>
43b6cbf720SGianluca Guida
44b6cbf720SGianluca Guida
45b6cbf720SGianluca Guida#if defined(LIBC_SCCS) && !defined(lint)
46b6cbf720SGianluca Guida#if 0
47b6cbf720SGianluca Guida	RCSID("from: @(#)mips_bcopy.s	2.2 CMU 18/06/93")
48b6cbf720SGianluca Guida#else
49*f14fb602SLionel Sambuc	RCSID("$NetBSD: bcopy.S,v 1.4 2011/08/27 13:23:52 bouyer Exp $")
50b6cbf720SGianluca Guida#endif
51b6cbf720SGianluca Guida#endif /* LIBC_SCCS and not lint */
52b6cbf720SGianluca Guida
53b6cbf720SGianluca Guida/*
54b6cbf720SGianluca Guida *	bcopy(caddr_t src, caddr_t dst, unsigned int len)
55b6cbf720SGianluca Guida *
56b6cbf720SGianluca Guida *	a0 	src address
57b6cbf720SGianluca Guida *	a1	dst address
58b6cbf720SGianluca Guida *	a2	length
59b6cbf720SGianluca Guida */
60b6cbf720SGianluca Guida
61b6cbf720SGianluca Guida#if defined(MEMCOPY) || defined(MEMMOVE)
62b6cbf720SGianluca Guida#ifdef MEMCOPY
63b6cbf720SGianluca Guida#define	FUNCTION	memcpy
64b6cbf720SGianluca Guida#else
65b6cbf720SGianluca Guida#define FUNCTION	memmove
66b6cbf720SGianluca Guida#endif
67b6cbf720SGianluca Guida#define	SRCREG		a1
68b6cbf720SGianluca Guida#define	DSTREG		a0
69b6cbf720SGianluca Guida#else
70b6cbf720SGianluca Guida#define	FUNCTION	bcopy
71b6cbf720SGianluca Guida#define	SRCREG		a0
72b6cbf720SGianluca Guida#define	DSTREG		a1
73b6cbf720SGianluca Guida#endif
74b6cbf720SGianluca Guida
75b6cbf720SGianluca Guida#define	SIZEREG		a2
76b6cbf720SGianluca Guida
77b6cbf720SGianluca GuidaLEAF(FUNCTION)
78b6cbf720SGianluca Guida	.set	noat
79b6cbf720SGianluca Guida	.set	noreorder
80b6cbf720SGianluca Guida
81b6cbf720SGianluca Guida#if defined(MEMCOPY) || defined(MEMMOVE)
82b6cbf720SGianluca Guida	/* set up return value, while we still can */
83b6cbf720SGianluca Guida	move	v0,DSTREG
84b6cbf720SGianluca Guida#endif
85b6cbf720SGianluca Guida	/*
86b6cbf720SGianluca Guida	 *	Make sure we can copy forwards.
87b6cbf720SGianluca Guida	 */
88b6cbf720SGianluca Guida	sltu	t0,SRCREG,DSTREG	# t0 == SRCREG < DSTREG
89b6cbf720SGianluca Guida	bne	t0,zero,6f		# copy backwards
90b6cbf720SGianluca Guida
91b6cbf720SGianluca Guida	/*
92b6cbf720SGianluca Guida	 * 	There are four alignment cases (with frequency)
93b6cbf720SGianluca Guida	 *	(Based on measurements taken with a DECstation 5000/200
94b6cbf720SGianluca Guida	 *	 inside a Mach kernel.)
95b6cbf720SGianluca Guida	 *
96b6cbf720SGianluca Guida	 * 	aligned   -> aligned		(mostly)
97b6cbf720SGianluca Guida	 * 	unaligned -> aligned		(sometimes)
98b6cbf720SGianluca Guida	 * 	aligned,unaligned -> unaligned	(almost never)
99b6cbf720SGianluca Guida	 *
100b6cbf720SGianluca Guida	 *	Note that we could add another case that checks if
101b6cbf720SGianluca Guida	 *	the destination and source are unaligned but the
102b6cbf720SGianluca Guida	 *	copy is alignable.  eg if src and dest are both
103b6cbf720SGianluca Guida	 *	on a halfword boundary.
104b6cbf720SGianluca Guida	 */
105b6cbf720SGianluca Guida	andi		t1,DSTREG,(SZREG-1)	# get last bits of dest
106b6cbf720SGianluca Guida	bne		t1,zero,3f		# dest unaligned
107b6cbf720SGianluca Guida	andi		t0,SRCREG,(SZREG-1)	# get last bits of src
108b6cbf720SGianluca Guida	bne		t0,zero,5f
109b6cbf720SGianluca Guida
110b6cbf720SGianluca Guida	/*
111b6cbf720SGianluca Guida	 *	Forward aligned->aligned copy, 8 words at a time.
112b6cbf720SGianluca Guida	 */
113b6cbf720SGianluca Guida98:
114b6cbf720SGianluca Guida	li		AT,-(SZREG*8)
115b6cbf720SGianluca Guida	and		t0,SIZEREG,AT		# count truncated to multiples
116b6cbf720SGianluca Guida	PTR_ADDU	a3,SRCREG,t0		# run fast loop up to this addr
117b6cbf720SGianluca Guida	sltu		AT,SRCREG,a3		# any work to do?
118b6cbf720SGianluca Guida	beq		AT,zero,2f
119b6cbf720SGianluca Guida	PTR_SUBU	SIZEREG,t0
120b6cbf720SGianluca Guida
121b6cbf720SGianluca Guida	/*
122b6cbf720SGianluca Guida	 *	loop body
123b6cbf720SGianluca Guida	 */
124b6cbf720SGianluca Guida1:	# cp
125b6cbf720SGianluca Guida	REG_L		t3,(0*SZREG)(SRCREG)
126b6cbf720SGianluca Guida	REG_L		v1,(1*SZREG)(SRCREG)
127b6cbf720SGianluca Guida	REG_L		t0,(2*SZREG)(SRCREG)
128b6cbf720SGianluca Guida	REG_L		t1,(3*SZREG)(SRCREG)
129b6cbf720SGianluca Guida	PTR_ADDU	SRCREG,SZREG*8
130b6cbf720SGianluca Guida	REG_S		t3,(0*SZREG)(DSTREG)
131b6cbf720SGianluca Guida	REG_S		v1,(1*SZREG)(DSTREG)
132b6cbf720SGianluca Guida	REG_S		t0,(2*SZREG)(DSTREG)
133b6cbf720SGianluca Guida	REG_S		t1,(3*SZREG)(DSTREG)
134b6cbf720SGianluca Guida	REG_L		t1,(-1*SZREG)(SRCREG)
135b6cbf720SGianluca Guida	REG_L		t0,(-2*SZREG)(SRCREG)
136b6cbf720SGianluca Guida	REG_L		v1,(-3*SZREG)(SRCREG)
137b6cbf720SGianluca Guida	REG_L		t3,(-4*SZREG)(SRCREG)
138b6cbf720SGianluca Guida	PTR_ADDU	DSTREG,SZREG*8
139b6cbf720SGianluca Guida	REG_S		t1,(-1*SZREG)(DSTREG)
140b6cbf720SGianluca Guida	REG_S		t0,(-2*SZREG)(DSTREG)
141b6cbf720SGianluca Guida	REG_S		v1,(-3*SZREG)(DSTREG)
142b6cbf720SGianluca Guida	bne		SRCREG,a3,1b
143b6cbf720SGianluca Guida	REG_S		t3,(-4*SZREG)(DSTREG)
144b6cbf720SGianluca Guida
145b6cbf720SGianluca Guida	/*
146b6cbf720SGianluca Guida	 *	Copy a word at a time, no loop unrolling.
147b6cbf720SGianluca Guida	 */
148b6cbf720SGianluca Guida2:	# wordcopy
149b6cbf720SGianluca Guida	andi		t2,SIZEREG,(SZREG-1)	# get byte count / SZREG
150b6cbf720SGianluca Guida	PTR_SUBU	t2,SIZEREG,t2		# t2 = words to copy * SZREG
151b6cbf720SGianluca Guida	beq		t2,zero,3f
152b6cbf720SGianluca Guida	PTR_ADDU	t0,SRCREG,t2		# stop at t0
153b6cbf720SGianluca Guida	PTR_SUBU	SIZEREG,SIZEREG,t2
154b6cbf720SGianluca Guida1:
155b6cbf720SGianluca Guida	REG_L		t3,0(SRCREG)
156b6cbf720SGianluca Guida	PTR_ADDU	SRCREG,SZREG
157b6cbf720SGianluca Guida	REG_S		t3,0(DSTREG)
158b6cbf720SGianluca Guida	bne		SRCREG,t0,1b
159b6cbf720SGianluca Guida	PTR_ADDU	DSTREG,SZREG
160b6cbf720SGianluca Guida
161b6cbf720SGianluca Guida3:	# bytecopy
162b6cbf720SGianluca Guida	beq		SIZEREG,zero,4f		# nothing left to do?
163b6cbf720SGianluca Guida	nop
164b6cbf720SGianluca Guida1:
165b6cbf720SGianluca Guida	lb		t3,0(SRCREG)
166b6cbf720SGianluca Guida	PTR_ADDU	SRCREG,1
167b6cbf720SGianluca Guida	sb		t3,0(DSTREG)
168b6cbf720SGianluca Guida	PTR_SUBU	SIZEREG,1
169b6cbf720SGianluca Guida	bgtz		SIZEREG,1b
170b6cbf720SGianluca Guida	PTR_ADDU	DSTREG,1
171b6cbf720SGianluca Guida
172b6cbf720SGianluca Guida4:	# copydone
173*f14fb602SLionel Sambuc	.set at		#-mfix-loongson2f-btb
174b6cbf720SGianluca Guida	j	ra
175b6cbf720SGianluca Guida	nop
176*f14fb602SLionel Sambuc	.set noat
177b6cbf720SGianluca Guida
178b6cbf720SGianluca Guida	/*
179b6cbf720SGianluca Guida	 *	Copy from unaligned source to aligned dest.
180b6cbf720SGianluca Guida	 */
181b6cbf720SGianluca Guida5:	# destaligned
182b6cbf720SGianluca Guida	andi		t0,SIZEREG,(SZREG-1)	# t0 = bytecount mod SZREG
183b6cbf720SGianluca Guida	PTR_SUBU	a3,SIZEREG,t0		# number of words to transfer
184b6cbf720SGianluca Guida	beq		a3,zero,3b
185b6cbf720SGianluca Guida	nop
186b6cbf720SGianluca Guida	move		SIZEREG,t0		# this many to do after we are done
187b6cbf720SGianluca Guida	PTR_ADDU	a3,SRCREG,a3		# stop point
188b6cbf720SGianluca Guida
189b6cbf720SGianluca Guida1:
190b6cbf720SGianluca Guida	REG_LHI		t3,0(SRCREG)
191b6cbf720SGianluca Guida	REG_LLO		t3,SZREG-1(SRCREG)
192b6cbf720SGianluca Guida	PTR_ADDI	SRCREG,SZREG
193b6cbf720SGianluca Guida	REG_S		t3,0(DSTREG)
194b6cbf720SGianluca Guida	bne		SRCREG,a3,1b
195b6cbf720SGianluca Guida	PTR_ADDI	DSTREG,SZREG
196b6cbf720SGianluca Guida
197b6cbf720SGianluca Guida	b		3b
198b6cbf720SGianluca Guida	nop
199b6cbf720SGianluca Guida
200b6cbf720SGianluca Guida6:	# backcopy -- based on above
201b6cbf720SGianluca Guida	PTR_ADDU	SRCREG,SIZEREG
202b6cbf720SGianluca Guida	PTR_ADDU	DSTREG,SIZEREG
203b6cbf720SGianluca Guida	andi		t1,DSTREG,SZREG-1	# get last 3 bits of dest
204b6cbf720SGianluca Guida	bne		t1,zero,3f
205b6cbf720SGianluca Guida	andi		t0,SRCREG,SZREG-1	# get last 3 bits of src
206b6cbf720SGianluca Guida	bne		t0,zero,5f
207b6cbf720SGianluca Guida
208b6cbf720SGianluca Guida	/*
209b6cbf720SGianluca Guida	 *	Forward aligned->aligned copy, 8*4 bytes at a time.
210b6cbf720SGianluca Guida	 */
211b6cbf720SGianluca Guida	li		AT,(-8*SZREG)
212b6cbf720SGianluca Guida	and		t0,SIZEREG,AT		# count truncated to multiple of 32
213b6cbf720SGianluca Guida	beq		t0,zero,2f		# any work to do?
214b6cbf720SGianluca Guida	PTR_SUBU	SIZEREG,t0
215b6cbf720SGianluca Guida	PTR_SUBU	a3,SRCREG,t0
216b6cbf720SGianluca Guida
217b6cbf720SGianluca Guida	/*
218b6cbf720SGianluca Guida	 *	loop body
219b6cbf720SGianluca Guida	 */
220b6cbf720SGianluca Guida1:	# cp
221b6cbf720SGianluca Guida	REG_L		t3,(-4*SZREG)(SRCREG)
222b6cbf720SGianluca Guida	REG_L		v1,(-3*SZREG)(SRCREG)
223b6cbf720SGianluca Guida	REG_L		t0,(-2*SZREG)(SRCREG)
224b6cbf720SGianluca Guida	REG_L		t1,(-1*SZREG)(SRCREG)
225b6cbf720SGianluca Guida	PTR_SUBU	SRCREG,8*SZREG
226b6cbf720SGianluca Guida	REG_S		t3,(-4*SZREG)(DSTREG)
227b6cbf720SGianluca Guida	REG_S		v1,(-3*SZREG)(DSTREG)
228b6cbf720SGianluca Guida	REG_S		t0,(-2*SZREG)(DSTREG)
229b6cbf720SGianluca Guida	REG_S		t1,(-1*SZREG)(DSTREG)
230b6cbf720SGianluca Guida	REG_L		t1,(3*SZREG)(SRCREG)
231b6cbf720SGianluca Guida	REG_L		t0,(2*SZREG)(SRCREG)
232b6cbf720SGianluca Guida	REG_L		v1,(1*SZREG)(SRCREG)
233b6cbf720SGianluca Guida	REG_L		t3,(0*SZREG)(SRCREG)
234b6cbf720SGianluca Guida	PTR_SUBU	DSTREG,8*SZREG
235b6cbf720SGianluca Guida	REG_S		t1,(3*SZREG)(DSTREG)
236b6cbf720SGianluca Guida	REG_S		t0,(2*SZREG)(DSTREG)
237b6cbf720SGianluca Guida	REG_S		v1,(1*SZREG)(DSTREG)
238b6cbf720SGianluca Guida	bne		SRCREG,a3,1b
239b6cbf720SGianluca Guida	REG_S		t3,(0*SZREG)(DSTREG)
240b6cbf720SGianluca Guida
241b6cbf720SGianluca Guida	/*
242b6cbf720SGianluca Guida	 *	Copy a word at a time, no loop unrolling.
243b6cbf720SGianluca Guida	 */
244b6cbf720SGianluca Guida2:	# wordcopy
245b6cbf720SGianluca Guida	andi		t2,SIZEREG,SZREG-1	# get byte count / 4
246b6cbf720SGianluca Guida	PTR_SUBU	t2,SIZEREG,t2		# t2 = number of words to copy
247b6cbf720SGianluca Guida	beq		t2,zero,3f
248b6cbf720SGianluca Guida	PTR_SUBU	t0,SRCREG,t2		# stop at t0
249b6cbf720SGianluca Guida	PTR_SUBU	SIZEREG,SIZEREG,t2
250b6cbf720SGianluca Guida1:
251b6cbf720SGianluca Guida	REG_L		t3,-SZREG(SRCREG)
252b6cbf720SGianluca Guida	PTR_SUBU	SRCREG,SZREG
253b6cbf720SGianluca Guida	REG_S		t3,-SZREG(DSTREG)
254b6cbf720SGianluca Guida	bne		SRCREG,t0,1b
255b6cbf720SGianluca Guida	PTR_SUBU	DSTREG,SZREG
256b6cbf720SGianluca Guida
257b6cbf720SGianluca Guida3:	# bytecopy
258b6cbf720SGianluca Guida	beq		SIZEREG,zero,4f		# nothing left to do?
259b6cbf720SGianluca Guida	nop
260b6cbf720SGianluca Guida1:
261b6cbf720SGianluca Guida	lb		t3,-1(SRCREG)
262b6cbf720SGianluca Guida	PTR_SUBU	SRCREG,1
263b6cbf720SGianluca Guida	sb		t3,-1(DSTREG)
264b6cbf720SGianluca Guida	PTR_SUBU	SIZEREG,1
265b6cbf720SGianluca Guida	bgtz		SIZEREG,1b
266b6cbf720SGianluca Guida	PTR_SUBU	DSTREG,1
267b6cbf720SGianluca Guida
268b6cbf720SGianluca Guida4:	# copydone
269*f14fb602SLionel Sambuc	.set at		#-mfix-loongson2f-btb
270b6cbf720SGianluca Guida	j	ra
271b6cbf720SGianluca Guida	nop
272*f14fb602SLionel Sambuc	.set noat
273b6cbf720SGianluca Guida
274b6cbf720SGianluca Guida	/*
275b6cbf720SGianluca Guida	 *	Copy from unaligned source to aligned dest.
276b6cbf720SGianluca Guida	 */
277b6cbf720SGianluca Guida5:	# destaligned
278b6cbf720SGianluca Guida	andi		t0,SIZEREG,SZREG-1	# t0 = bytecount mod 4
279b6cbf720SGianluca Guida	PTR_SUBU	a3,SIZEREG,t0		# number of words to transfer
280b6cbf720SGianluca Guida	beq		a3,zero,3b
281b6cbf720SGianluca Guida	nop
282b6cbf720SGianluca Guida	move		SIZEREG,t0		# this many to do after we are done
283b6cbf720SGianluca Guida	PTR_SUBU	a3,SRCREG,a3		# stop point
284b6cbf720SGianluca Guida
285b6cbf720SGianluca Guida1:
286b6cbf720SGianluca Guida	REG_LHI		t3,-SZREG(SRCREG)
287b6cbf720SGianluca Guida	REG_LLO		t3,-1(SRCREG)
288b6cbf720SGianluca Guida	PTR_SUBU	SRCREG,SZREG
289b6cbf720SGianluca Guida	REG_S		t3,-SZREG(DSTREG)
290b6cbf720SGianluca Guida	bne		SRCREG,a3,1b
291b6cbf720SGianluca Guida	PTR_SUBU	DSTREG,SZREG
292b6cbf720SGianluca Guida
293b6cbf720SGianluca Guida	b		3b
294b6cbf720SGianluca Guida	nop
295b6cbf720SGianluca Guida
296b6cbf720SGianluca Guida	.set	reorder
297b6cbf720SGianluca Guida	.set	at
298b6cbf720SGianluca Guida	END(FUNCTION)
299