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