ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / sparc / lib / memcpy.S
1 /* memcpy.S: Sparc optimized memcpy, bcopy and memmove code
2  * Hand optimized from GNU libc's memcpy, bcopy and memmove
3  * Copyright (C) 1991,1996 Free Software Foundation
4  * Copyright (C) 1995 Linus Torvalds (Linus.Torvalds@helsinki.fi)
5  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
6  * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
7  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
8  */
9
10 #ifdef __KERNEL__
11
12 #define FUNC(x)                                                                                         \
13         .globl  x;              \
14         .type   x,@function;    \
15         .align  4;                                                                                      \
16 x:
17
18 #undef FASTER_REVERSE
19 #undef FASTER_NONALIGNED
20 #define FASTER_ALIGNED
21
22 /* In kernel these functions don't return a value.
23  * One should use macros in asm/string.h for that purpose.
24  * We return 0, so that bugs are more apparent.
25  */
26 #define SETUP_RETL
27 #define RETL_INSN       clr     %o0
28
29 #else
30
31 /* libc */
32
33 #include "DEFS.h"
34
35 #define FASTER_REVERSE
36 #define FASTER_NONALIGNED
37 #define FASTER_ALIGNED
38
39 #define SETUP_RETL      mov     %o0, %g6
40 #define RETL_INSN       mov     %g6, %o0
41
42 #endif
43
44 /* Both these macros have to start with exactly the same insn */
45 #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7)                                 \
46         ldd     [%src + offset + 0x00], %t0;                                                            \
47         ldd     [%src + offset + 0x08], %t2;                                                            \
48         ldd     [%src + offset + 0x10], %t4;                                                            \
49         ldd     [%src + offset + 0x18], %t6;                                                            \
50         st      %t0, [%dst + offset + 0x00];                                                            \
51         st      %t1, [%dst + offset + 0x04];                                                            \
52         st      %t2, [%dst + offset + 0x08];                                                            \
53         st      %t3, [%dst + offset + 0x0c];                                                            \
54         st      %t4, [%dst + offset + 0x10];                                                            \
55         st      %t5, [%dst + offset + 0x14];                                                            \
56         st      %t6, [%dst + offset + 0x18];                                                            \
57         st      %t7, [%dst + offset + 0x1c];
58
59 #define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7)                            \
60         ldd     [%src + offset + 0x00], %t0;                                                            \
61         ldd     [%src + offset + 0x08], %t2;                                                            \
62         ldd     [%src + offset + 0x10], %t4;                                                            \
63         ldd     [%src + offset + 0x18], %t6;                                                            \
64         std     %t0, [%dst + offset + 0x00];                                                            \
65         std     %t2, [%dst + offset + 0x08];                                                            \
66         std     %t4, [%dst + offset + 0x10];                                                            \
67         std     %t6, [%dst + offset + 0x18];
68
69 #define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3)                                                \
70         ldd     [%src - offset - 0x10], %t0;                                                            \
71         ldd     [%src - offset - 0x08], %t2;                                                            \
72         st      %t0, [%dst - offset - 0x10];                                                            \
73         st      %t1, [%dst - offset - 0x0c];                                                            \
74         st      %t2, [%dst - offset - 0x08];                                                            \
75         st      %t3, [%dst - offset - 0x04];
76
77 #define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1, t2, t3)                                           \
78         ldd     [%src - offset - 0x10], %t0;                                                            \
79         ldd     [%src - offset - 0x08], %t2;                                                            \
80         std     %t0, [%dst - offset - 0x10];                                                            \
81         std     %t2, [%dst - offset - 0x08];
82
83 #define MOVE_SHORTCHUNK(src, dst, offset, t0, t1)                                                       \
84         ldub    [%src - offset - 0x02], %t0;                                                            \
85         ldub    [%src - offset - 0x01], %t1;                                                            \
86         stb     %t0, [%dst - offset - 0x02];                                                            \
87         stb     %t1, [%dst - offset - 0x01];
88
89 /* Both these macros have to start with exactly the same insn */
90 #define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7)                                \
91         ldd     [%src - offset - 0x20], %t0;                                                            \
92         ldd     [%src - offset - 0x18], %t2;                                                            \
93         ldd     [%src - offset - 0x10], %t4;                                                            \
94         ldd     [%src - offset - 0x08], %t6;                                                            \
95         st      %t0, [%dst - offset - 0x20];                                                            \
96         st      %t1, [%dst - offset - 0x1c];                                                            \
97         st      %t2, [%dst - offset - 0x18];                                                            \
98         st      %t3, [%dst - offset - 0x14];                                                            \
99         st      %t4, [%dst - offset - 0x10];                                                            \
100         st      %t5, [%dst - offset - 0x0c];                                                            \
101         st      %t6, [%dst - offset - 0x08];                                                            \
102         st      %t7, [%dst - offset - 0x04];
103
104 #define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7)                           \
105         ldd     [%src - offset - 0x20], %t0;                                                            \
106         ldd     [%src - offset - 0x18], %t2;                                                            \
107         ldd     [%src - offset - 0x10], %t4;                                                            \
108         ldd     [%src - offset - 0x08], %t6;                                                            \
109         std     %t0, [%dst - offset - 0x20];                                                            \
110         std     %t2, [%dst - offset - 0x18];                                                            \
111         std     %t4, [%dst - offset - 0x10];                                                            \
112         std     %t6, [%dst - offset - 0x08];
113
114 #define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3)                                               \
115         ldd     [%src + offset + 0x00], %t0;                                                            \
116         ldd     [%src + offset + 0x08], %t2;                                                            \
117         st      %t0, [%dst + offset + 0x00];                                                            \
118         st      %t1, [%dst + offset + 0x04];                                                            \
119         st      %t2, [%dst + offset + 0x08];                                                            \
120         st      %t3, [%dst + offset + 0x0c];
121
122 #define RMOVE_SHORTCHUNK(src, dst, offset, t0, t1)                                                      \
123         ldub    [%src + offset + 0x00], %t0;                                                            \
124         ldub    [%src + offset + 0x01], %t1;                                                            \
125         stb     %t0, [%dst + offset + 0x00];                                                            \
126         stb     %t1, [%dst + offset + 0x01];
127
128 #define SMOVE_CHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2)            \
129         ldd     [%src + offset + 0x00], %t0;                                                            \
130         ldd     [%src + offset + 0x08], %t2;                                                            \
131         srl     %t0, shir, %t5;                                                                         \
132         srl     %t1, shir, %t6;                                                                         \
133         sll     %t0, shil, %t0;                                                                         \
134         or      %t5, %prev, %t5;                                                                        \
135         sll     %t1, shil, %prev;                                                                       \
136         or      %t6, %t0, %t0;                                                                          \
137         srl     %t2, shir, %t1;                                                                         \
138         srl     %t3, shir, %t6;                                                                         \
139         sll     %t2, shil, %t2;                                                                         \
140         or      %t1, %prev, %t1;                                                                        \
141         std     %t4, [%dst + offset + offset2 - 0x04];                                                  \
142         std     %t0, [%dst + offset + offset2 + 0x04];                                                  \
143         sll     %t3, shil, %prev;                                                                       \
144         or      %t6, %t2, %t4;
145
146 #define SMOVE_ALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2)       \
147         ldd     [%src + offset + 0x00], %t0;                                                            \
148         ldd     [%src + offset + 0x08], %t2;                                                            \
149         srl     %t0, shir, %t4;                                                                         \
150         srl     %t1, shir, %t5;                                                                         \
151         sll     %t0, shil, %t6;                                                                         \
152         or      %t4, %prev, %t0;                                                                        \
153         sll     %t1, shil, %prev;                                                                       \
154         or      %t5, %t6, %t1;                                                                          \
155         srl     %t2, shir, %t4;                                                                         \
156         srl     %t3, shir, %t5;                                                                         \
157         sll     %t2, shil, %t6;                                                                         \
158         or      %t4, %prev, %t2;                                                                        \
159         sll     %t3, shil, %prev;                                                                       \
160         or      %t5, %t6, %t3;                                                                          \
161         std     %t0, [%dst + offset + offset2 + 0x00];                                                  \
162         std     %t2, [%dst + offset + offset2 + 0x08];
163
164         .text
165         .align  4
166
167 #ifdef FASTER_REVERSE
168
169 70:     /* rdword_align */
170
171         andcc           %o1, 1, %g0
172         be              4f
173          andcc          %o1, 2, %g0
174
175         ldub            [%o1 - 1], %g2
176         sub             %o1, 1, %o1
177         stb             %g2, [%o0 - 1]
178         sub             %o2, 1, %o2
179         be              3f
180          sub            %o0, 1, %o0
181 4:
182         lduh            [%o1 - 2], %g2
183         sub             %o1, 2, %o1
184         sth             %g2, [%o0 - 2]
185         sub             %o2, 2, %o2
186         b               3f
187          sub            %o0, 2, %o0
188
189 #endif /* FASTER_REVERSE */
190
191 0:
192         retl
193          nop            ! Only bcopy returns here and it retuns void...
194
195 FUNC(bcopy)
196         mov             %o0, %o3
197         mov             %o1, %o0
198         mov             %o3, %o1
199         tst             %o2
200         bcs             0b
201          /* Do the cmp in the delay slot */
202 #ifdef __KERNEL__
203 FUNC(amemmove)
204 FUNC(__memmove)
205 #endif
206 FUNC(memmove)
207         cmp             %o0, %o1
208         SETUP_RETL
209         bleu            9f
210          sub            %o0, %o1, %o4
211
212         add             %o1, %o2, %o3
213         cmp             %o3, %o0
214         bleu            0f
215          andcc          %o4, 3, %o5
216
217 #ifndef FASTER_REVERSE
218
219         add             %o1, %o2, %o1
220         add             %o0, %o2, %o0
221         sub             %o1, 1, %o1
222         sub             %o0, 1, %o0
223         
224 1:      /* reverse_bytes */
225
226         ldub            [%o1], %o4
227         subcc           %o2, 1, %o2
228         stb             %o4, [%o0]
229         sub             %o1, 1, %o1
230         bne             1b
231          sub            %o0, 1, %o0
232
233         retl
234          RETL_INSN
235
236 #else /* FASTER_REVERSE */
237
238         add             %o1, %o2, %o1
239         add             %o0, %o2, %o0
240         bne             77f
241          cmp            %o2, 15
242         bleu            91f
243          andcc          %o1, 3, %g0
244         bne             70b
245 3:
246          andcc          %o1, 4, %g0
247
248         be              2f
249          mov            %o2, %g1
250
251         ld              [%o1 - 4], %o4
252         sub             %g1, 4, %g1
253         st              %o4, [%o0 - 4]
254         sub             %o1, 4, %o1
255         sub             %o0, 4, %o0
256 2:
257         andcc           %g1, 0xffffff80, %g7
258         be              3f
259          andcc          %o0, 4, %g0
260
261         be              74f + 4
262 5:
263         RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
264         RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
265         RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
266         RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
267         subcc           %g7, 128, %g7
268         sub             %o1, 128, %o1
269         bne             5b
270          sub            %o0, 128, %o0
271 3:
272         andcc           %g1, 0x70, %g7
273         be              72f
274          andcc          %g1, 8, %g0
275
276         sethi           %hi(72f), %o5
277         srl             %g7, 1, %o4
278         add             %g7, %o4, %o4
279         sub             %o1, %g7, %o1
280         sub             %o5, %o4, %o5
281         jmpl            %o5 + %lo(72f), %g0
282          sub            %o0, %g7, %o0
283
284 71:     /* rmemcpy_table */
285         RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
286         RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
287         RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
288         RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
289         RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
290         RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
291         RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
292
293 72:     /* rmemcpy_table_end */
294
295         be              73f
296          andcc          %g1, 4, %g0
297
298         ldd             [%o1 - 0x08], %g2
299         sub             %o0, 8, %o0
300         sub             %o1, 8, %o1
301         st              %g2, [%o0]
302         st              %g3, [%o0 + 0x04]
303
304 73:     /* rmemcpy_last7 */
305
306         be              1f
307          andcc          %g1, 2, %g0
308
309         ld              [%o1 - 4], %g2
310         sub             %o1, 4, %o1
311         st              %g2, [%o0 - 4]
312         sub             %o0, 4, %o0
313 1:
314         be              1f
315          andcc          %g1, 1, %g0
316
317         lduh            [%o1 - 2], %g2
318         sub             %o1, 2, %o1
319         sth             %g2, [%o0 - 2]
320         sub             %o0, 2, %o0
321 1:
322         be              1f
323          nop
324
325         ldub            [%o1 - 1], %g2
326         stb             %g2, [%o0 - 1]
327 1:
328         retl
329          RETL_INSN
330
331 74:     /* rldd_std */
332         RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
333         RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
334         RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
335         RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
336         subcc           %g7, 128, %g7
337         sub             %o1, 128, %o1
338         bne             74b
339          sub            %o0, 128, %o0
340
341         andcc           %g1, 0x70, %g7
342         be              72b
343          andcc          %g1, 8, %g0
344
345         sethi           %hi(72b), %o5
346         srl             %g7, 1, %o4
347         add             %g7, %o4, %o4
348         sub             %o1, %g7, %o1
349         sub             %o5, %o4, %o5
350         jmpl            %o5 + %lo(72b), %g0
351          sub            %o0, %g7, %o0
352
353 75:     /* rshort_end */
354
355         and             %o2, 0xe, %o3
356 2:
357         sethi           %hi(76f), %o5
358         sll             %o3, 3, %o4
359         sub             %o0, %o3, %o0
360         sub             %o5, %o4, %o5
361         sub             %o1, %o3, %o1
362         jmpl            %o5 + %lo(76f), %g0
363          andcc          %o2, 1, %g0
364
365         RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
366         RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
367         RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
368         RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
369         RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
370         RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
371         RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
372
373 76:     /* rshort_table_end */
374
375         be              1f
376          nop
377         ldub            [%o1 - 1], %g2
378         stb             %g2, [%o0 - 1]
379 1:
380         retl
381          RETL_INSN
382
383 91:     /* rshort_aligned_end */
384
385         bne             75b
386          andcc          %o2, 8, %g0
387
388         be              1f
389          andcc          %o2, 4, %g0
390
391         ld              [%o1 - 0x08], %g2
392         ld              [%o1 - 0x04], %g3
393         sub             %o1, 8, %o1
394         st              %g2, [%o0 - 0x08]
395         st              %g3, [%o0 - 0x04]
396         sub             %o0, 8, %o0
397 1:
398         b               73b
399          mov            %o2, %g1
400
401 77:     /* rnon_aligned */
402         cmp             %o2, 15
403         bleu            75b
404          andcc          %o0, 3, %g0
405         be              64f
406          andcc          %o0, 1, %g0
407         be              63f
408          andcc          %o0, 2, %g0
409         ldub            [%o1 - 1], %g5
410         sub             %o1, 1, %o1
411         stb             %g5, [%o0 - 1]
412         sub             %o0, 1, %o0
413         be              64f
414          sub            %o2, 1, %o2
415 63:
416         ldub            [%o1 - 1], %g5
417         sub             %o1, 2, %o1
418         stb             %g5, [%o0 - 1]
419         sub             %o0, 2, %o0
420         ldub            [%o1], %g5
421         sub             %o2, 2, %o2
422         stb             %g5, [%o0]
423 64:     
424         and             %o1, 3, %g2
425         and             %o1, -4, %o1
426         and             %o2, 0xc, %g3
427         add             %o1, 4, %o1
428         cmp             %g3, 4
429         sll             %g2, 3, %g4
430         mov             32, %g2
431         be              4f
432          sub            %g2, %g4, %g7
433
434         blu             3f
435          cmp            %g3, 8
436
437         be              2f
438          srl            %o2, 2, %g3
439
440         ld              [%o1 - 4], %o3
441         add             %o0, -8, %o0
442         ld              [%o1 - 8], %o4
443         add             %o1, -16, %o1
444         b               7f
445          add            %g3, 1, %g3
446 2:
447         ld              [%o1 - 4], %o4
448         add             %o0, -4, %o0
449         ld              [%o1 - 8], %g1
450         add             %o1, -12, %o1
451         b               8f
452          add            %g3, 2, %g3
453 3:
454         ld              [%o1 - 4], %o5
455         add             %o0, -12, %o0
456         ld              [%o1 - 8], %o3
457         add             %o1, -20, %o1
458         b               6f
459          srl            %o2, 2, %g3
460 4:
461         ld              [%o1 - 4], %g1
462         srl             %o2, 2, %g3
463         ld              [%o1 - 8], %o5
464         add             %o1, -24, %o1
465         add             %o0, -16, %o0
466         add             %g3, -1, %g3
467
468         ld              [%o1 + 12], %o3
469 5:
470         sll             %o5, %g4, %g2
471         srl             %g1, %g7, %g5
472         or              %g2, %g5, %g2
473         st              %g2, [%o0 + 12]
474 6:
475         ld              [%o1 + 8], %o4
476         sll             %o3, %g4, %g2
477         srl             %o5, %g7, %g5
478         or              %g2, %g5, %g2
479         st              %g2, [%o0 + 8]
480 7:
481         ld              [%o1 + 4], %g1
482         sll             %o4, %g4, %g2
483         srl             %o3, %g7, %g5
484         or              %g2, %g5, %g2
485         st              %g2, [%o0 + 4]
486 8:
487         ld              [%o1], %o5
488         sll             %g1, %g4, %g2
489         srl             %o4, %g7, %g5
490         addcc           %g3, -4, %g3
491         or              %g2, %g5, %g2
492         add             %o1, -16, %o1
493         st              %g2, [%o0]
494         add             %o0, -16, %o0
495         bne,a           5b      
496          ld             [%o1 + 12], %o3
497         sll             %o5, %g4, %g2
498         srl             %g1, %g7, %g5
499         srl             %g4, 3, %g3
500         or              %g2, %g5, %g2
501         add             %o1, %g3, %o1
502         andcc           %o2, 2, %g0
503         st              %g2, [%o0 + 12]
504         be              1f
505          andcc          %o2, 1, %g0
506         
507         ldub            [%o1 + 15], %g5
508         add             %o1, -2, %o1
509         stb             %g5, [%o0 + 11]
510         add             %o0, -2, %o0
511         ldub            [%o1 + 16], %g5
512         stb             %g5, [%o0 + 12]
513 1:
514         be              1f
515          nop
516         ldub            [%o1 + 15], %g5
517         stb             %g5, [%o0 + 11]
518 1:
519         retl
520          RETL_INSN
521
522 #endif /* FASTER_REVERSE */
523
524 /* NOTE: This code is executed just for the cases,
525          where %src (=%o1) & 3 is != 0.
526          We need to align it to 4. So, for (%src & 3)
527          1 we need to do ldub,lduh
528          2 lduh
529          3 just ldub
530          so even if it looks weird, the branches
531          are correct here. -jj
532  */
533 78:     /* dword_align */
534
535         andcc           %o1, 1, %g0
536         be              4f
537          andcc          %o1, 2, %g0
538
539         ldub            [%o1], %g2
540         add             %o1, 1, %o1
541         stb             %g2, [%o0]
542         sub             %o2, 1, %o2
543         bne             3f
544          add            %o0, 1, %o0
545 4:
546         lduh            [%o1], %g2
547         add             %o1, 2, %o1
548         sth             %g2, [%o0]
549         sub             %o2, 2, %o2
550         b               3f
551          add            %o0, 2, %o0
552
553 #ifdef __KERNEL__
554 FUNC(__memcpy)
555 #endif
556 FUNC(memcpy)    /* %o0=dst %o1=src %o2=len */
557
558         sub             %o0, %o1, %o4
559         SETUP_RETL
560 9:
561         andcc           %o4, 3, %o5
562 0:
563         bne             86f
564          cmp            %o2, 15
565
566         bleu            90f
567          andcc          %o1, 3, %g0
568
569         bne             78b
570 3:
571          andcc          %o1, 4, %g0
572
573         be              2f
574          mov            %o2, %g1
575
576         ld              [%o1], %o4
577         sub             %g1, 4, %g1
578         st              %o4, [%o0]
579         add             %o1, 4, %o1
580         add             %o0, 4, %o0
581 2:
582         andcc           %g1, 0xffffff80, %g7
583         be              3f
584          andcc          %o0, 4, %g0
585
586         be              82f + 4
587 5:
588         MOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
589         MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
590         MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
591         MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
592         subcc           %g7, 128, %g7
593         add             %o1, 128, %o1
594         bne             5b
595          add            %o0, 128, %o0
596 3:
597         andcc           %g1, 0x70, %g7
598         be              80f
599          andcc          %g1, 8, %g0
600
601         sethi           %hi(80f), %o5
602         srl             %g7, 1, %o4
603         add             %g7, %o4, %o4
604         add             %o1, %g7, %o1
605         sub             %o5, %o4, %o5
606         jmpl            %o5 + %lo(80f), %g0
607          add            %o0, %g7, %o0
608
609 79:     /* memcpy_table */
610
611         MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
612         MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
613         MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
614         MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
615         MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
616         MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
617         MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
618
619 80:     /* memcpy_table_end */
620         be              81f
621          andcc          %g1, 4, %g0
622
623         ldd             [%o1], %g2
624         add             %o0, 8, %o0
625         st              %g2, [%o0 - 0x08]
626         add             %o1, 8, %o1
627         st              %g3, [%o0 - 0x04]
628
629 81:     /* memcpy_last7 */
630
631         be              1f
632          andcc          %g1, 2, %g0
633
634         ld              [%o1], %g2
635         add             %o1, 4, %o1
636         st              %g2, [%o0]
637         add             %o0, 4, %o0
638 1:
639         be              1f
640          andcc          %g1, 1, %g0
641
642         lduh            [%o1], %g2
643         add             %o1, 2, %o1
644         sth             %g2, [%o0]
645         add             %o0, 2, %o0
646 1:
647         be              1f
648          nop
649
650         ldub            [%o1], %g2
651         stb             %g2, [%o0]
652 1:
653         retl
654          RETL_INSN
655
656 82:     /* ldd_std */
657         MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
658         MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
659         MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
660         MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
661         subcc           %g7, 128, %g7
662         add             %o1, 128, %o1
663         bne             82b
664          add            %o0, 128, %o0
665
666 #ifndef FASTER_ALIGNED
667
668         andcc           %g1, 0x70, %g7
669         be              80b
670          andcc          %g1, 8, %g0
671
672         sethi           %hi(80b), %o5
673         srl             %g7, 1, %o4
674         add             %g7, %o4, %o4
675         add             %o1, %g7, %o1
676         sub             %o5, %o4, %o5
677         jmpl            %o5 + %lo(80b), %g0
678          add            %o0, %g7, %o0
679
680 #else /* FASTER_ALIGNED */
681
682         andcc           %g1, 0x70, %g7
683         be              84f
684          andcc          %g1, 8, %g0
685
686         sethi           %hi(84f), %o5
687         add             %o1, %g7, %o1
688         sub             %o5, %g7, %o5
689         jmpl            %o5 + %lo(84f), %g0
690          add            %o0, %g7, %o0
691
692 83:     /* amemcpy_table */
693
694         MOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
695         MOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
696         MOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
697         MOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
698         MOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
699         MOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
700         MOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
701
702 84:     /* amemcpy_table_end */
703         be              85f
704          andcc          %g1, 4, %g0
705
706         ldd             [%o1], %g2
707         add             %o0, 8, %o0
708         std             %g2, [%o0 - 0x08]
709         add             %o1, 8, %o1
710 85:     /* amemcpy_last7 */
711         be              1f
712          andcc          %g1, 2, %g0
713
714         ld              [%o1], %g2
715         add             %o1, 4, %o1
716         st              %g2, [%o0]
717         add             %o0, 4, %o0
718 1:
719         be              1f
720          andcc          %g1, 1, %g0
721
722         lduh            [%o1], %g2
723         add             %o1, 2, %o1
724         sth             %g2, [%o0]
725         add             %o0, 2, %o0
726 1:
727         be              1f
728          nop
729
730         ldub            [%o1], %g2
731         stb             %g2, [%o0]
732 1:
733         retl
734          RETL_INSN
735
736 #endif /* FASTER_ALIGNED */
737
738 86:     /* non_aligned */
739         cmp             %o2, 6
740         bleu            88f
741
742 #ifdef FASTER_NONALIGNED
743
744          cmp            %o2, 256
745         bcc             87f
746
747 #endif /* FASTER_NONALIGNED */
748
749          andcc          %o0, 3, %g0
750         be              61f
751          andcc          %o0, 1, %g0
752         be              60f
753          andcc          %o0, 2, %g0
754
755         ldub            [%o1], %g5
756         add             %o1, 1, %o1
757         stb             %g5, [%o0]
758         sub             %o2, 1, %o2
759         bne             61f
760          add            %o0, 1, %o0
761 60:
762         ldub            [%o1], %g3
763         add             %o1, 2, %o1
764         stb             %g3, [%o0]
765         sub             %o2, 2, %o2
766         ldub            [%o1 - 1], %g3
767         add             %o0, 2, %o0
768         stb             %g3, [%o0 - 1]
769 61:
770         and             %o1, 3, %g2
771         and             %o2, 0xc, %g3
772         and             %o1, -4, %o1
773         cmp             %g3, 4
774         sll             %g2, 3, %g4
775         mov             32, %g2
776         be              4f
777          sub            %g2, %g4, %g7
778         
779         blu             3f
780          cmp            %g3, 0x8
781
782         be              2f
783          srl            %o2, 2, %g3
784
785         ld              [%o1], %o3
786         add             %o0, -8, %o0
787         ld              [%o1 + 4], %o4
788         b               8f
789          add            %g3, 1, %g3
790 2:
791         ld              [%o1], %o4
792         add             %o0, -12, %o0
793         ld              [%o1 + 4], %o5
794         add             %g3, 2, %g3
795         b               9f
796          add            %o1, -4, %o1
797 3:
798         ld              [%o1], %g1
799         add             %o0, -4, %o0
800         ld              [%o1 + 4], %o3
801         srl             %o2, 2, %g3
802         b               7f
803          add            %o1, 4, %o1
804 4:
805         ld              [%o1], %o5
806         cmp             %o2, 7
807         ld              [%o1 + 4], %g1
808         srl             %o2, 2, %g3
809         bleu            10f
810          add            %o1, 8, %o1
811
812         ld              [%o1], %o3
813         add             %g3, -1, %g3
814 5:
815         sll             %o5, %g4, %g2
816         srl             %g1, %g7, %g5
817         or              %g2, %g5, %g2
818         st              %g2, [%o0]
819 7:
820         ld              [%o1 + 4], %o4
821         sll             %g1, %g4, %g2
822         srl             %o3, %g7, %g5
823         or              %g2, %g5, %g2
824         st              %g2, [%o0 + 4]
825 8:
826         ld              [%o1 + 8], %o5
827         sll             %o3, %g4, %g2
828         srl             %o4, %g7, %g5
829         or              %g2, %g5, %g2
830         st              %g2, [%o0 + 8]
831 9:
832         ld              [%o1 + 12], %g1
833         sll             %o4, %g4, %g2
834         srl             %o5, %g7, %g5
835         addcc           %g3, -4, %g3
836         or              %g2, %g5, %g2
837         add             %o1, 16, %o1
838         st              %g2, [%o0 + 12]
839         add             %o0, 16, %o0
840         bne,a           5b
841          ld             [%o1], %o3
842 10:
843         sll             %o5, %g4, %g2
844         srl             %g1, %g7, %g5
845         srl             %g7, 3, %g3
846         or              %g2, %g5, %g2
847         sub             %o1, %g3, %o1
848         andcc           %o2, 2, %g0
849         st              %g2, [%o0]
850         be              1f
851          andcc          %o2, 1, %g0
852
853         ldub            [%o1], %g2
854         add             %o1, 2, %o1
855         stb             %g2, [%o0 + 4]
856         add             %o0, 2, %o0
857         ldub            [%o1 - 1], %g2
858         stb             %g2, [%o0 + 3]
859 1:
860         be              1f
861          nop
862         ldub            [%o1], %g2
863         stb             %g2, [%o0 + 4]
864 1:
865         retl
866          RETL_INSN
867
868 #ifdef FASTER_NONALIGNED
869
870 87:     /* faster_nonaligned */
871
872         andcc           %o1, 3, %g0
873         be              3f
874          andcc          %o1, 1, %g0
875
876         be              4f
877          andcc          %o1, 2, %g0
878
879         ldub            [%o1], %g2
880         add             %o1, 1, %o1
881         stb             %g2, [%o0]
882         sub             %o2, 1, %o2
883         bne             3f
884          add            %o0, 1, %o0
885 4:
886         lduh            [%o1], %g2
887         add             %o1, 2, %o1
888         srl             %g2, 8, %g3
889         sub             %o2, 2, %o2
890         stb             %g3, [%o0]
891         add             %o0, 2, %o0
892         stb             %g2, [%o0 - 1]
893 3:
894          andcc          %o1, 4, %g0
895
896         bne             2f
897          cmp            %o5, 1
898
899         ld              [%o1], %o4
900         srl             %o4, 24, %g2
901         stb             %g2, [%o0]
902         srl             %o4, 16, %g3
903         stb             %g3, [%o0 + 1]
904         srl             %o4, 8, %g2
905         stb             %g2, [%o0 + 2]
906         sub             %o2, 4, %o2
907         stb             %o4, [%o0 + 3]
908         add             %o1, 4, %o1
909         add             %o0, 4, %o0
910 2:
911         be              33f
912          cmp            %o5, 2
913         be              32f
914          sub            %o2, 4, %o2
915 31:
916         ld              [%o1], %g2
917         add             %o1, 4, %o1
918         srl             %g2, 24, %g3
919         and             %o0, 7, %g5
920         stb             %g3, [%o0]
921         cmp             %g5, 7
922         sll             %g2, 8, %g1
923         add             %o0, 4, %o0
924         be              41f
925          and            %o2, 0xffffffc0, %o3
926         ld              [%o0 - 7], %o4
927 4:
928         SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
929         SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
930         SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
931         SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
932         subcc           %o3, 64, %o3
933         add             %o1, 64, %o1
934         bne             4b
935          add            %o0, 64, %o0
936
937         andcc           %o2, 0x30, %o3
938         be,a            1f
939          srl            %g1, 16, %g2
940 4:
941         SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
942         subcc           %o3, 16, %o3
943         add             %o1, 16, %o1
944         bne             4b
945          add            %o0, 16, %o0
946
947         srl             %g1, 16, %g2
948 1:
949         st              %o4, [%o0 - 7]
950         sth             %g2, [%o0 - 3]
951         srl             %g1, 8, %g4
952         b               88f
953          stb            %g4, [%o0 - 1]
954 32:
955         ld              [%o1], %g2
956         add             %o1, 4, %o1
957         srl             %g2, 16, %g3
958         and             %o0, 7, %g5
959         sth             %g3, [%o0]
960         cmp             %g5, 6
961         sll             %g2, 16, %g1
962         add             %o0, 4, %o0
963         be              42f
964          and            %o2, 0xffffffc0, %o3
965         ld              [%o0 - 6], %o4
966 4:
967         SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
968         SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
969         SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
970         SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
971         subcc           %o3, 64, %o3
972         add             %o1, 64, %o1
973         bne             4b
974          add            %o0, 64, %o0
975
976         andcc           %o2, 0x30, %o3
977         be,a            1f
978          srl            %g1, 16, %g2
979 4:
980         SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
981         subcc           %o3, 16, %o3
982         add             %o1, 16, %o1
983         bne             4b
984          add            %o0, 16, %o0
985
986         srl             %g1, 16, %g2
987 1:
988         st              %o4, [%o0 - 6]
989         b               88f
990          sth            %g2, [%o0 - 2]
991 33:
992         ld              [%o1], %g2
993         sub             %o2, 4, %o2
994         srl             %g2, 24, %g3
995         and             %o0, 7, %g5
996         stb             %g3, [%o0]
997         cmp             %g5, 5
998         srl             %g2, 8, %g4
999         sll             %g2, 24, %g1
1000         sth             %g4, [%o0 + 1]
1001         add             %o1, 4, %o1
1002         be              43f
1003          and            %o2, 0xffffffc0, %o3
1004
1005         ld              [%o0 - 1], %o4
1006         add             %o0, 4, %o0
1007 4:
1008         SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1009         SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1010         SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1011         SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1012         subcc           %o3, 64, %o3
1013         add             %o1, 64, %o1
1014         bne             4b
1015          add            %o0, 64, %o0
1016
1017         andcc           %o2, 0x30, %o3
1018         be,a            1f
1019          srl            %g1, 24, %g2
1020 4:
1021         SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1022         subcc           %o3, 16, %o3
1023         add             %o1, 16, %o1
1024         bne             4b
1025          add            %o0, 16, %o0
1026
1027         srl             %g1, 24, %g2
1028 1:
1029         st              %o4, [%o0 - 5]
1030         b               88f
1031          stb            %g2, [%o0 - 1]
1032 41:
1033         SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1034         SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1035         SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1036         SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1037         subcc           %o3, 64, %o3
1038         add             %o1, 64, %o1
1039         bne             41b
1040          add            %o0, 64, %o0
1041          
1042         andcc           %o2, 0x30, %o3
1043         be,a            1f
1044          srl            %g1, 16, %g2
1045 4:
1046         SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1047         subcc           %o3, 16, %o3
1048         add             %o1, 16, %o1
1049         bne             4b
1050          add            %o0, 16, %o0
1051
1052         srl             %g1, 16, %g2
1053 1:
1054         sth             %g2, [%o0 - 3]
1055         srl             %g1, 8, %g4
1056         b               88f
1057          stb            %g4, [%o0 - 1]
1058 43:
1059         SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1060         SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1061         SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1062         SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1063         subcc           %o3, 64, %o3
1064         add             %o1, 64, %o1
1065         bne             43b
1066          add            %o0, 64, %o0
1067
1068         andcc           %o2, 0x30, %o3
1069         be,a            1f
1070          srl            %g1, 24, %g2
1071 4:
1072         SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1073         subcc           %o3, 16, %o3
1074         add             %o1, 16, %o1
1075         bne             4b
1076          add            %o0, 16, %o0
1077
1078         srl             %g1, 24, %g2
1079 1:
1080         stb             %g2, [%o0 + 3]
1081         b               88f
1082          add            %o0, 4, %o0
1083 42:
1084         SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1085         SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1086         SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1087         SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1088         subcc           %o3, 64, %o3
1089         add             %o1, 64, %o1
1090         bne             42b
1091          add            %o0, 64, %o0
1092          
1093         andcc           %o2, 0x30, %o3
1094         be,a            1f
1095          srl            %g1, 16, %g2
1096 4:
1097         SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1098         subcc           %o3, 16, %o3
1099         add             %o1, 16, %o1
1100         bne             4b
1101          add            %o0, 16, %o0
1102
1103         srl             %g1, 16, %g2
1104 1:
1105         sth             %g2, [%o0 - 2]
1106
1107         /* Fall through */
1108          
1109 #endif /* FASTER_NONALIGNED */
1110
1111 88:     /* short_end */
1112
1113         and             %o2, 0xe, %o3
1114 20:
1115         sethi           %hi(89f), %o5
1116         sll             %o3, 3, %o4
1117         add             %o0, %o3, %o0
1118         sub             %o5, %o4, %o5
1119         add             %o1, %o3, %o1
1120         jmpl            %o5 + %lo(89f), %g0
1121          andcc          %o2, 1, %g0
1122
1123         MOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
1124         MOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
1125         MOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
1126         MOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
1127         MOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
1128         MOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
1129         MOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
1130
1131 89:     /* short_table_end */
1132
1133         be              1f
1134          nop
1135
1136         ldub            [%o1], %g2
1137         stb             %g2, [%o0]
1138 1:
1139         retl
1140          RETL_INSN
1141
1142 90:     /* short_aligned_end */
1143         bne             88b
1144          andcc          %o2, 8, %g0
1145
1146         be              1f
1147          andcc          %o2, 4, %g0
1148
1149         ld              [%o1 + 0x00], %g2
1150         ld              [%o1 + 0x04], %g3
1151         add             %o1, 8, %o1
1152         st              %g2, [%o0 + 0x00]
1153         st              %g3, [%o0 + 0x04]
1154         add             %o0, 8, %o0
1155 1:
1156         b               81b
1157          mov            %o2, %g1