Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-2.6] / arch / mn10300 / lib / memcpy.S
1 /* MN10300 Optimised simple memory to memory copy
2  *
3  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public Licence
8  * as published by the Free Software Foundation; either version
9  * 2 of the Licence, or (at your option) any later version.
10  */
11 #include <asm/cache.h>
12
13         .section .text
14         .balign L1_CACHE_BYTES
15
16 ###############################################################################
17 #
18 # void *memcpy(void *dst, const void *src, size_t n)
19 #
20 ###############################################################################
21         .globl  memcpy
22         .type   memcpy,@function
23 memcpy:
24         movm    [d2,d3],(sp)
25         mov     d0,(12,sp)
26         mov     d1,(16,sp)
27         mov     (20,sp),d2                      # count
28         mov     d0,a0                           # dst
29         mov     d1,a1                           # src
30         mov     d0,e3                           # the return value
31
32         cmp     +0,d2
33         beq     memcpy_done                     # return if zero-length copy
34
35         # see if the three parameters are all four-byte aligned
36         or      d0,d1,d3
37         or      d2,d3
38         and     +3,d3
39         bne     memcpy_1                        # jump if not
40
41         # we want to transfer as much as we can in chunks of 32 bytes
42         cmp     +31,d2
43         bls     memcpy_4_remainder              # 4-byte aligned remainder
44
45         movm    [exreg1],(sp)
46         add     -32,d2
47         mov     +32,d3
48
49 memcpy_4_loop:
50         mov     (a1+),d0
51         mov     (a1+),d1
52         mov     (a1+),e0
53         mov     (a1+),e1
54         mov     (a1+),e4
55         mov     (a1+),e5
56         mov     (a1+),e6
57         mov     (a1+),e7
58         mov     d0,(a0+)
59         mov     d1,(a0+)
60         mov     e0,(a0+)
61         mov     e1,(a0+)
62         mov     e4,(a0+)
63         mov     e5,(a0+)
64         mov     e6,(a0+)
65         mov     e7,(a0+)
66
67         sub     d3,d2
68         bcc     memcpy_4_loop
69
70         movm    (sp),[exreg1]
71         add     d3,d2
72         beq     memcpy_4_no_remainder
73
74 memcpy_4_remainder:
75         # cut 4-7 words down to 0-3
76         cmp     +16,d2
77         bcs     memcpy_4_three_or_fewer_words
78         mov     (a1+),d0
79         mov     (a1+),d1
80         mov     (a1+),e0
81         mov     (a1+),e1
82         mov     d0,(a0+)
83         mov     d1,(a0+)
84         mov     e0,(a0+)
85         mov     e1,(a0+)
86         add     -16,d2
87         beq     memcpy_4_no_remainder
88
89         # copy the remaining 1, 2 or 3 words
90 memcpy_4_three_or_fewer_words:
91         cmp     +8,d2
92         bcs     memcpy_4_one_word
93         beq     memcpy_4_two_words
94         mov     (a1+),d0
95         mov     d0,(a0+)
96 memcpy_4_two_words:
97         mov     (a1+),d0
98         mov     d0,(a0+)
99 memcpy_4_one_word:
100         mov     (a1+),d0
101         mov     d0,(a0+)
102
103 memcpy_4_no_remainder:
104         # check we copied the correct amount
105         # TODO: REMOVE CHECK
106         sub     e3,a0,d2
107         mov     (20,sp),d1
108         cmp     d2,d1
109         beq     memcpy_done
110         break
111         break
112         break
113
114 memcpy_done:
115         mov     e3,a0
116         ret     [d2,d3],8
117
118         # handle misaligned copying
119 memcpy_1:
120         add     -1,d2
121         mov     +1,d3
122         setlb                                   # setlb requires the next insns
123                                                 # to occupy exactly 4 bytes
124
125         sub     d3,d2
126         movbu   (a1),d0
127         movbu   d0,(a0)
128         add_add d3,a1,d3,a0
129         lcc
130
131         mov     e3,a0
132         ret     [d2,d3],8
133
134 memcpy_end:
135         .size   memcpy, memcpy_end-memcpy