Merge commit 'v2.6.28-rc4' into timers/rtc
[linux-2.6] / arch / sh / lib / memmove.S
1 /* $Id: memmove.S,v 1.2 2001/07/27 11:51:09 gniibe Exp $
2  *
3  * "memmove" implementation of SuperH
4  *
5  * Copyright (C) 1999  Niibe Yutaka
6  *
7  */
8
9 /*
10  * void *memmove(void *dst, const void *src, size_t n);
11  * The memory areas may overlap.
12  */
13
14 #include <linux/linkage.h>
15 ENTRY(memmove)
16         ! if dest > src, call memcpy (it copies in decreasing order)
17         cmp/hi  r5,r4
18         bf      1f
19         mov.l   2f,r0
20         jmp     @r0
21          nop
22         .balign 4
23 2:      .long   memcpy
24 1:
25         sub     r5,r4           ! From here, r4 has the distance to r0
26         tst     r6,r6
27         bt/s    9f              ! if n=0, do nothing
28          mov    r5,r0
29         add     r6,r5
30         mov     #12,r1
31         cmp/gt  r6,r1
32         bt/s    8f              ! if it's too small, copy a byte at once
33          add    #-1,r4
34         add     #1,r4
35         !
36         !                [ ...  ] DST             [ ...  ] SRC
37         !                [ ...  ]                 [ ...  ]
38         !                  :                        :
39         !      r0+r4-->  [ ...  ]       r0    --> [ ...  ]
40         !                  :                        :
41         !                [ ...  ]                 [ ...  ]
42         !                               r5    -->
43         !
44         mov     r4,r1
45         mov     #3,r2
46         and     r2,r1
47         shll2   r1
48         mov     r0,r3           ! Save the value on R0 to R3
49         mova    jmptable,r0
50         add     r1,r0
51         mov.l   @r0,r1
52         jmp     @r1
53          mov    r3,r0           ! and back to R0
54         .balign 4
55 jmptable:
56         .long   case0
57         .long   case1
58         .long   case2
59         .long   case3
60
61         ! copy a byte at once
62 8:      mov.b   @r0+,r1
63         cmp/hs  r5,r0
64         bf/s    8b                      ! while (r0<r5)
65          mov.b  r1,@(r0,r4)
66         add     #1,r4
67 9:
68         add     r4,r0
69         rts
70          sub    r6,r0
71
72 case_none:
73         bra     8b
74          add    #-1,r4
75
76 case0:
77         !
78         !       GHIJ KLMN OPQR -->  GHIJ KLMN OPQR
79         !
80         ! First, align to long word boundary
81         mov     r0,r3
82         and     r2,r3
83         tst     r3,r3
84         bt/s    2f
85          add    #-1,r4
86         mov     #4,r2
87         sub     r3,r2
88 1:      dt      r2
89         mov.b   @r0+,r1
90         bf/s    1b
91          mov.b  r1,@(r0,r4)
92         !
93 2:      ! Second, copy a long word at once
94         add     #-3,r4
95         add     #-3,r5
96 3:      mov.l   @r0+,r1
97         cmp/hs  r5,r0
98         bf/s    3b
99          mov.l  r1,@(r0,r4)
100         add     #3,r5
101         !
102         ! Third, copy a byte at once, if necessary
103         cmp/eq  r5,r0
104         bt/s    9b
105          add    #4,r4
106         bra     8b
107          add    #-1,r4
108
109 case3:
110         !
111         !       GHIJ KLMN OPQR -->  ...G HIJK LMNO PQR.
112         !
113         ! First, align to long word boundary
114         mov     r0,r3
115         and     r2,r3
116         tst     r3,r3
117         bt/s    2f
118          add    #-1,r4
119         mov     #4,r2
120         sub     r3,r2
121 1:      dt      r2
122         mov.b   @r0+,r1
123         bf/s    1b
124          mov.b  r1,@(r0,r4)
125         !
126 2:      ! Second, read a long word and write a long word at once
127         add     #-2,r4
128         mov.l   @(r0,r4),r1
129         add     #-7,r5
130         add     #-4,r4
131         !
132 #ifdef __LITTLE_ENDIAN__
133         shll8   r1
134 3:      mov     r1,r3           ! JIHG
135         shlr8   r3              ! xJIH
136         mov.l   @r0+,r1         ! NMLK
137         mov     r1,r2
138         shll16  r2
139         shll8   r2              ! Kxxx
140         or      r2,r3           ! KJIH
141         cmp/hs  r5,r0
142         bf/s    3b
143          mov.l  r3,@(r0,r4)
144 #else
145         shlr8   r1
146 3:      mov     r1,r3           ! GHIJ
147         shll8   r3              ! HIJx
148         mov.l   @r0+,r1         ! KLMN
149         mov     r1,r2
150         shlr16  r2
151         shlr8   r2              ! xxxK
152         or      r2,r3           ! HIJK
153         cmp/hs  r5,r0
154         bf/s    3b
155          mov.l  r3,@(r0,r4)
156 #endif
157         add     #7,r5
158         !
159         ! Third, copy a byte at once, if necessary
160         cmp/eq  r5,r0
161         bt/s    9b
162          add    #7,r4
163         add     #-3,r0
164         bra     8b
165          add    #-1,r4
166
167 case2:
168         !
169         !       GHIJ KLMN OPQR -->  ..GH IJKL MNOP QR..
170         !
171         ! First, align to word boundary
172         tst     #1,r0
173         bt/s    2f
174          add    #-1,r4
175         mov.b   @r0+,r1
176         mov.b   r1,@(r0,r4)
177         !
178 2:      ! Second, read a word and write a word at once
179         add     #-1,r4
180         add     #-1,r5
181         !
182 3:      mov.w   @r0+,r1
183         cmp/hs  r5,r0
184         bf/s    3b
185          mov.w  r1,@(r0,r4)
186         add     #1,r5
187         !
188         ! Third, copy a byte at once, if necessary
189         cmp/eq  r5,r0
190         bt/s    9b
191          add    #2,r4
192         mov.b   @r0,r1
193         mov.b   r1,@(r0,r4)
194         bra     9b
195          add    #1,r0
196
197 case1:
198         !
199         !       GHIJ KLMN OPQR -->  .GHI JKLM NOPQ R...
200         !
201         ! First, align to long word boundary
202         mov     r0,r3
203         and     r2,r3
204         tst     r3,r3
205         bt/s    2f
206          add    #-1,r4
207         mov     #4,r2
208         sub     r3,r2
209 1:      dt      r2
210         mov.b   @r0+,r1
211         bf/s    1b
212          mov.b  r1,@(r0,r4)
213         !
214 2:      ! Second, read a long word and write a long word at once
215         mov.l   @(r0,r4),r1
216         add     #-7,r5
217         add     #-4,r4
218         !
219 #ifdef __LITTLE_ENDIAN__
220         shll16  r1
221         shll8   r1
222 3:      mov     r1,r3           ! JIHG
223         shlr16  r3
224         shlr8   r3              ! xxxJ
225         mov.l   @r0+,r1         ! NMLK
226         mov     r1,r2
227         shll8   r2              ! MLKx
228         or      r2,r3           ! MLKJ
229         cmp/hs  r5,r0
230         bf/s    3b
231          mov.l  r3,@(r0,r4)
232 #else
233         shlr16  r1
234         shlr8   r1
235 3:      mov     r1,r3           ! GHIJ
236         shll16  r3
237         shll8   r3              ! Jxxx
238         mov.l   @r0+,r1         ! KLMN
239         mov     r1,r2
240         shlr8   r2              ! xKLM
241         or      r2,r3           ! JKLM
242         cmp/hs  r5,r0
243         bf/s    3b              ! while(r0<r5)
244          mov.l  r3,@(r0,r4)
245 #endif
246         add     #7,r5
247         !
248         ! Third, copy a byte at once, if necessary
249         cmp/eq  r5,r0
250         bt/s    9b
251          add    #5,r4
252         add     #-3,r0
253         bra     8b
254          add    #-1,r4