Move all files into ports/ subdirectory in preparation for merge with glibc
[glibc.git] / ports / sysdeps / arm / memcpy.S
blob08f7f76ecf192c5e394ec57d9ee0db68aa57cbc0
1 /* Copyright (C) 2006, 2009 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
4    Contributed by MontaVista Software, Inc. (written by Nicolas Pitre)
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library.  If not, see
18    <http://www.gnu.org/licenses/>.  */
20 #include <sysdep.h>
23  * Data preload for architectures that support it (ARM V5TE and above)
24  */
25 #if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
26      && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__) \
27      && !defined (__ARM_ARCH_4T__) && !defined (__ARM_ARCH_5__) \
28      && !defined (__ARM_ARCH_5T__))
29 #define PLD(code...)    code
30 #else
31 #define PLD(code...)
32 #endif
35  * This can be used to enable code to cacheline align the source pointer.
36  * Experiments on tested architectures (StrongARM and XScale) didn't show
37  * this a worthwhile thing to do.  That might be different in the future.
38  */
39 //#define CALGN(code...)        code
40 #define CALGN(code...)
43  * Endian independent macros for shifting bytes within registers.
44  */
45 #ifndef __ARMEB__
46 #define pull            lsr
47 #define push            lsl
48 #else
49 #define pull            lsl
50 #define push            lsr
51 #endif
53                 .text
55 /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
57 ENTRY(memcpy)
59                 stmfd   sp!, {r0, r4, lr}
60                 cfi_adjust_cfa_offset (12)
61                 cfi_rel_offset (r4, 4)
62                 cfi_rel_offset (lr, 8)
64                 cfi_remember_state
66                 subs    r2, r2, #4
67                 blt     8f
68                 ands    ip, r0, #3
69         PLD(    pld     [r1, #0]                )
70                 bne     9f
71                 ands    ip, r1, #3
72                 bne     10f
74 1:              subs    r2, r2, #(28)
75                 stmfd   sp!, {r5 - r8}
76                 cfi_adjust_cfa_offset (16)
77                 cfi_rel_offset (r5, 0)
78                 cfi_rel_offset (r6, 4)
79                 cfi_rel_offset (r7, 8)
80                 cfi_rel_offset (r8, 12)
81                 blt     5f
83         CALGN(  ands    ip, r1, #31             )
84         CALGN(  rsb     r3, ip, #32             )
85         CALGN(  sbcnes  r4, r3, r2              )  @ C is always set here
86         CALGN(  bcs     2f                      )
87         CALGN(  adr     r4, 6f                  )
88         CALGN(  subs    r2, r2, r3              )  @ C gets set
89         CALGN(  add     pc, r4, ip              )
91         PLD(    pld     [r1, #0]                )
92 2:      PLD(    subs    r2, r2, #96             )
93         PLD(    pld     [r1, #28]               )
94         PLD(    blt     4f                      )
95         PLD(    pld     [r1, #60]               )
96         PLD(    pld     [r1, #92]               )
98 3:      PLD(    pld     [r1, #124]              )
99 4:              ldmia   r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
100                 subs    r2, r2, #32
101                 stmia   r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
102                 bge     3b
103         PLD(    cmn     r2, #96                 )
104         PLD(    bge     4b                      )
106 5:              ands    ip, r2, #28
107                 rsb     ip, ip, #32
108                 addne   pc, pc, ip              @ C is always clear here
109                 b       7f
110 6:              nop
111                 ldr     r3, [r1], #4
112                 ldr     r4, [r1], #4
113                 ldr     r5, [r1], #4
114                 ldr     r6, [r1], #4
115                 ldr     r7, [r1], #4
116                 ldr     r8, [r1], #4
117                 ldr     lr, [r1], #4
119                 add     pc, pc, ip
120                 nop
121                 nop
122                 str     r3, [r0], #4
123                 str     r4, [r0], #4
124                 str     r5, [r0], #4
125                 str     r6, [r0], #4
126                 str     r7, [r0], #4
127                 str     r8, [r0], #4
128                 str     lr, [r0], #4
130         CALGN(  bcs     2b                      )
132 7:              ldmfd   sp!, {r5 - r8}
133                 cfi_adjust_cfa_offset (-16)
134                 cfi_restore (r5)
135                 cfi_restore (r6)
136                 cfi_restore (r7)
137                 cfi_restore (r8)
139 8:              movs    r2, r2, lsl #31
140                 ldrneb  r3, [r1], #1
141                 ldrcsb  r4, [r1], #1
142                 ldrcsb  ip, [r1]
143                 strneb  r3, [r0], #1
144                 strcsb  r4, [r0], #1
145                 strcsb  ip, [r0]
147 #if defined (__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__)
148                 ldmfd   sp!, {r0, r4, lr}
149                 cfi_adjust_cfa_offset (-12)
150                 cfi_restore (r4)
151                 cfi_restore (lr)
152                 bx      lr
153 #else
154                 ldmfd   sp!, {r0, r4, pc}
155 #endif
157                 cfi_restore_state
159 9:              rsb     ip, ip, #4
160                 cmp     ip, #2
161                 ldrgtb  r3, [r1], #1
162                 ldrgeb  r4, [r1], #1
163                 ldrb    lr, [r1], #1
164                 strgtb  r3, [r0], #1
165                 strgeb  r4, [r0], #1
166                 subs    r2, r2, ip
167                 strb    lr, [r0], #1
168                 blt     8b
169                 ands    ip, r1, #3
170                 beq     1b
172 10:             bic     r1, r1, #3
173                 cmp     ip, #2
174                 ldr     lr, [r1], #4
175                 beq     17f
176                 bgt     18f
179                 .macro  forward_copy_shift pull push
181                 subs    r2, r2, #28
182                 blt     14f
184         CALGN(  ands    ip, r1, #31             )
185         CALGN(  rsb     ip, ip, #32             )
186         CALGN(  sbcnes  r4, ip, r2              )  @ C is always set here
187         CALGN(  subcc   r2, r2, ip              )
188         CALGN(  bcc     15f                     )
190 11:             stmfd   sp!, {r5 - r9}
191                 cfi_adjust_cfa_offset (20)
192                 cfi_rel_offset (r5, 0)
193                 cfi_rel_offset (r6, 4)
194                 cfi_rel_offset (r7, 8)
195                 cfi_rel_offset (r8, 12)
196                 cfi_rel_offset (r9, 16)
198         PLD(    pld     [r1, #0]                )
199         PLD(    subs    r2, r2, #96             )
200         PLD(    pld     [r1, #28]               )
201         PLD(    blt     13f                     )
202         PLD(    pld     [r1, #60]               )
203         PLD(    pld     [r1, #92]               )
205 12:     PLD(    pld     [r1, #124]              )
206 13:             ldmia   r1!, {r4, r5, r6, r7}
207                 mov     r3, lr, pull #\pull
208                 subs    r2, r2, #32
209                 ldmia   r1!, {r8, r9, ip, lr}
210                 orr     r3, r3, r4, push #\push
211                 mov     r4, r4, pull #\pull
212                 orr     r4, r4, r5, push #\push
213                 mov     r5, r5, pull #\pull
214                 orr     r5, r5, r6, push #\push
215                 mov     r6, r6, pull #\pull
216                 orr     r6, r6, r7, push #\push
217                 mov     r7, r7, pull #\pull
218                 orr     r7, r7, r8, push #\push
219                 mov     r8, r8, pull #\pull
220                 orr     r8, r8, r9, push #\push
221                 mov     r9, r9, pull #\pull
222                 orr     r9, r9, ip, push #\push
223                 mov     ip, ip, pull #\pull
224                 orr     ip, ip, lr, push #\push
225                 stmia   r0!, {r3, r4, r5, r6, r7, r8, r9, ip}
226                 bge     12b
227         PLD(    cmn     r2, #96                 )
228         PLD(    bge     13b                     )
230                 ldmfd   sp!, {r5 - r9}
231                 cfi_adjust_cfa_offset (-20)
232                 cfi_restore (r5)
233                 cfi_restore (r6)
234                 cfi_restore (r7)
235                 cfi_restore (r8)
236                 cfi_restore (r9)
238 14:             ands    ip, r2, #28
239                 beq     16f
241 15:             mov     r3, lr, pull #\pull
242                 ldr     lr, [r1], #4
243                 subs    ip, ip, #4
244                 orr     r3, r3, lr, push #\push
245                 str     r3, [r0], #4
246                 bgt     15b
247         CALGN(  cmp     r2, #0                  )
248         CALGN(  bge     11b                     )
250 16:             sub     r1, r1, #(\push / 8)
251                 b       8b
253                 .endm
256                 forward_copy_shift      pull=8  push=24
258 17:             forward_copy_shift      pull=16 push=16
260 18:             forward_copy_shift      pull=24 push=8
262 END(memcpy)
263 libc_hidden_builtin_def (memcpy)