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