GNU Linux-libre 4.9.328-gnu1
[releases.git] / arch / mn10300 / lib / memmove.S
1 /* MN10300 Optimised simple memory to memory copy, with support for overlapping
2  * regions
3  *
4  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public Licence
9  * as published by the Free Software Foundation; either version
10  * 2 of the Licence, or (at your option) any later version.
11  */
12 #include <asm/cache.h>
13
14         .section .text
15         .balign L1_CACHE_BYTES
16
17 ###############################################################################
18 #
19 # void *memmove(void *dst, const void *src, size_t n)
20 #
21 ###############################################################################
22         .globl  memmove
23         .type   memmove,@function
24 memmove:
25         # fall back to memcpy if dst < src to work bottom up
26         cmp     d1,d0
27         bcs     memmove_memcpy
28
29         # work top down
30         movm    [d2,d3],(sp)
31         mov     d0,(12,sp)
32         mov     d1,(16,sp)
33         mov     (20,sp),d2                      # count
34         add     d0,d2,a0                        # dst end
35         add     d1,d2,a1                        # src end
36         mov     d0,e3                           # the return value
37
38         cmp     +0,d2
39         beq     memmove_done                    # return if zero-length copy
40
41         # see if the three parameters are all four-byte aligned
42         or      d0,d1,d3
43         or      d2,d3
44         and     +3,d3
45         bne     memmove_1                       # jump if not
46
47         # we want to transfer as much as we can in chunks of 32 bytes
48         add     -4,a1
49         cmp     +31,d2
50         bls     memmove_4_remainder             # 4-byte aligned remainder
51
52         add     -32,d2
53         mov     +32,d3
54
55 memmove_4_loop:
56         mov     (a1),d0
57         sub_sub +4,a1,+4,a0
58         mov     d0,(a0)
59         mov     (a1),d1
60         sub_sub +4,a1,+4,a0
61         mov     d1,(a0)
62
63         mov     (a1),d0
64         sub_sub +4,a1,+4,a0
65         mov     d0,(a0)
66         mov     (a1),d1
67         sub_sub +4,a1,+4,a0
68         mov     d1,(a0)
69
70         mov     (a1),d0
71         sub_sub +4,a1,+4,a0
72         mov     d0,(a0)
73         mov     (a1),d1
74         sub_sub +4,a1,+4,a0
75         mov     d1,(a0)
76
77         mov     (a1),d0
78         sub_sub +4,a1,+4,a0
79         mov     d0,(a0)
80         mov     (a1),d1
81         sub_sub +4,a1,+4,a0
82         mov     d1,(a0)
83
84         sub     d3,d2
85         bcc     memmove_4_loop
86
87         add     d3,d2
88         beq     memmove_4_no_remainder
89
90 memmove_4_remainder:
91         # cut 4-7 words down to 0-3
92         cmp     +16,d2
93         bcs     memmove_4_three_or_fewer_words
94         mov     (a1),d0
95         sub_sub +4,a1,+4,a0
96         mov     d0,(a0)
97         mov     (a1),d1
98         sub_sub +4,a1,+4,a0
99         mov     d1,(a0)
100         mov     (a1),e0
101         sub_sub +4,a1,+4,a0
102         mov     e0,(a0)
103         mov     (a1),e1
104         sub_sub +4,a1,+4,a0
105         mov     e1,(a0)
106         add     -16,d2
107         beq     memmove_4_no_remainder
108
109         # copy the remaining 1, 2 or 3 words
110 memmove_4_three_or_fewer_words:
111         cmp     +8,d2
112         bcs     memmove_4_one_word
113         beq     memmove_4_two_words
114         mov     (a1),d0
115         sub_sub +4,a1,+4,a0
116         mov     d0,(a0)
117 memmove_4_two_words:
118         mov     (a1),d0
119         sub_sub +4,a1,+4,a0
120         mov     d0,(a0)
121 memmove_4_one_word:
122         mov     (a1),d0
123         sub_sub +4,a1,+4,a0
124         mov     d0,(a0)
125
126 memmove_4_no_remainder:
127         # check we copied the correct amount
128         # TODO: REMOVE CHECK
129         sub     e3,a0,d2
130         beq     memmove_done
131         break
132         break
133         break
134
135 memmove_done:
136         mov     e3,a0
137         ret     [d2,d3],8
138
139         # handle misaligned copying
140 memmove_1:
141         add     -1,a1
142         add     -1,d2
143         mov     +1,d3
144         setlb                                   # setlb requires the next insns
145                                                 # to occupy exactly 4 bytes
146
147         sub     d3,d2
148         movbu   (a1),d0
149         sub_sub d3,a1,d3,a0
150         movbu   d0,(a0)
151         lcc
152
153         mov     e3,a0
154         ret     [d2,d3],8
155
156 memmove_memcpy:
157         jmp     memcpy
158
159 memmove_end:
160         .size   memmove, memmove_end-memmove