Add CFI statements to ARM's assembly code.
[glibc.git] / sysdeps / arm / memmove.S
blob026d8e2bd1d932ef092e4bbb55151c58a837f5fb
1 /* Copyright (C) 2006, 2008, 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, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
21 #include <sysdep.h>
24  * Data preload for architectures that support it (ARM V5TE and above)
25  */
26 #if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
27      && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__) \
28      && !defined (__ARM_ARCH_4T__) && !defined (__ARM_ARCH_5__) \
29      && !defined (__ARM_ARCH_5T__))
30 #define PLD(code...)    code
31 #else
32 #define PLD(code...)
33 #endif
36  * This can be used to enable code to cacheline align the source pointer.
37  * Experiments on tested architectures (StrongARM and XScale) didn't show
38  * this a worthwhile thing to do.  That might be different in the future.
39  */
40 //#define CALGN(code...)        code
41 #define CALGN(code...)
44  * Endian independent macros for shifting bytes within registers.
45  */
46 #ifndef __ARMEB__
47 #define pull            lsr
48 #define push            lsl
49 #else
50 #define pull            lsl
51 #define push            lsr
52 #endif
54                 .text
57  * Prototype: void *memmove(void *dest, const void *src, size_t n);
58  *
59  * Note:
60  *
61  * If the memory regions don't overlap, we simply branch to memcpy which is
62  * normally a bit faster. Otherwise the copy is done going downwards.
63  */
65 ENTRY(memmove)
67                 subs    ip, r0, r1
68                 cmphi   r2, ip
69 #ifdef NOT_IN_libc
70                 bls     memcpy
71 #else
72                 bls     HIDDEN_JUMPTARGET(memcpy)
73 #endif
75                 stmfd   sp!, {r0, r4, lr}
76                 cfi_adjust_cfa_offset (12)
77                 cfi_rel_offset (r4, 4)
78                 cfi_rel_offset (lr, 8)
80                 cfi_remember_state
82                 add     r1, r1, r2
83                 add     r0, r0, r2
84                 subs    r2, r2, #4
85                 blt     8f
86                 ands    ip, r0, #3
87         PLD(    pld     [r1, #-4]               )
88                 bne     9f
89                 ands    ip, r1, #3
90                 bne     10f
92 1:              subs    r2, r2, #(28)
93                 stmfd   sp!, {r5 - r8}
94                 cfi_adjust_cfa_offset (16)
95                 cfi_rel_offset (r5, 0)
96                 cfi_rel_offset (r6, 4)
97                 cfi_rel_offset (r7, 8)
98                 cfi_rel_offset (r8, 12)
99                 blt     5f
101         CALGN(  ands    ip, r1, #31             )
102         CALGN(  sbcnes  r4, ip, r2              )  @ C is always set here
103         CALGN(  bcs     2f                      )
104         CALGN(  adr     r4, 6f                  )
105         CALGN(  subs    r2, r2, ip              )  @ C is set here
106         CALGN(  add     pc, r4, ip              )
108         PLD(    pld     [r1, #-4]               )
109 2:      PLD(    subs    r2, r2, #96             )
110         PLD(    pld     [r1, #-32]              )
111         PLD(    blt     4f                      )
112         PLD(    pld     [r1, #-64]              )
113         PLD(    pld     [r1, #-96]              )
115 3:      PLD(    pld     [r1, #-128]             )
116 4:              ldmdb   r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
117                 subs    r2, r2, #32
118                 stmdb   r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
119                 bge     3b
120         PLD(    cmn     r2, #96                 )
121         PLD(    bge     4b                      )
123 5:              ands    ip, r2, #28
124                 rsb     ip, ip, #32
125                 addne   pc, pc, ip              @ C is always clear here
126                 b       7f
127 6:              nop
128                 ldr     r3, [r1, #-4]!
129                 ldr     r4, [r1, #-4]!
130                 ldr     r5, [r1, #-4]!
131                 ldr     r6, [r1, #-4]!
132                 ldr     r7, [r1, #-4]!
133                 ldr     r8, [r1, #-4]!
134                 ldr     lr, [r1, #-4]!
136                 add     pc, pc, ip
137                 nop
138                 nop
139                 str     r3, [r0, #-4]!
140                 str     r4, [r0, #-4]!
141                 str     r5, [r0, #-4]!
142                 str     r6, [r0, #-4]!
143                 str     r7, [r0, #-4]!
144                 str     r8, [r0, #-4]!
145                 str     lr, [r0, #-4]!
147         CALGN(  bcs     2b                      )
149 7:              ldmfd   sp!, {r5 - r8}
150                 cfi_adjust_cfa_offset (-16)
151                 cfi_restore (r5)
152                 cfi_restore (r6)
153                 cfi_restore (r7)
154                 cfi_restore (r8)
156 8:              movs    r2, r2, lsl #31
157                 ldrneb  r3, [r1, #-1]!
158                 ldrcsb  r4, [r1, #-1]!
159                 ldrcsb  ip, [r1, #-1]
160                 strneb  r3, [r0, #-1]!
161                 strcsb  r4, [r0, #-1]!
162                 strcsb  ip, [r0, #-1]
164 #if defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)
165                 ldmfd   sp!, {r0, r4, lr}
166                 cfi_adjust_cfa_offset (-12)
167                 cfi_restore (r4)
168                 cfi_restore (lr)
169                 bx      lr
170 #else
171                 ldmfd   sp!, {r0, r4, pc}
172 #endif
174                 cfi_restore_state
176 9:              cmp     ip, #2
177                 ldrgtb  r3, [r1, #-1]!
178                 ldrgeb  r4, [r1, #-1]!
179                 ldrb    lr, [r1, #-1]!
180                 strgtb  r3, [r0, #-1]!
181                 strgeb  r4, [r0, #-1]!
182                 subs    r2, r2, ip
183                 strb    lr, [r0, #-1]!
184                 blt     8b
185                 ands    ip, r1, #3
186                 beq     1b
188 10:             bic     r1, r1, #3
189                 cmp     ip, #2
190                 ldr     r3, [r1, #0]
191                 beq     17f
192                 blt     18f
195                 .macro  backward_copy_shift push pull
197                 subs    r2, r2, #28
198                 blt     14f
200         CALGN(  ands    ip, r1, #31             )
201         CALGN(  rsb     ip, ip, #32             )
202         CALGN(  sbcnes  r4, ip, r2              )  @ C is always set here
203         CALGN(  subcc   r2, r2, ip              )
204         CALGN(  bcc     15f                     )
206 11:             stmfd   sp!, {r5 - r9}
207                 cfi_adjust_cfa_offset (20)
208                 cfi_rel_offset (r5, 0)
209                 cfi_rel_offset (r6, 4)
210                 cfi_rel_offset (r7, 8)
211                 cfi_rel_offset (r8, 12)
212                 cfi_rel_offset (r9, 16)
214         PLD(    pld     [r1, #-4]               )
215         PLD(    subs    r2, r2, #96             )
216         PLD(    pld     [r1, #-32]              )
217         PLD(    blt     13f                     )
218         PLD(    pld     [r1, #-64]              )
219         PLD(    pld     [r1, #-96]              )
221 12:     PLD(    pld     [r1, #-128]             )
222 13:             ldmdb   r1!, {r7, r8, r9, ip}
223                 mov     lr, r3, push #\push
224                 subs    r2, r2, #32
225                 ldmdb   r1!, {r3, r4, r5, r6}
226                 orr     lr, lr, ip, pull #\pull
227                 mov     ip, ip, push #\push
228                 orr     ip, ip, r9, pull #\pull
229                 mov     r9, r9, push #\push
230                 orr     r9, r9, r8, pull #\pull
231                 mov     r8, r8, push #\push
232                 orr     r8, r8, r7, pull #\pull
233                 mov     r7, r7, push #\push
234                 orr     r7, r7, r6, pull #\pull
235                 mov     r6, r6, push #\push
236                 orr     r6, r6, r5, pull #\pull
237                 mov     r5, r5, push #\push
238                 orr     r5, r5, r4, pull #\pull
239                 mov     r4, r4, push #\push
240                 orr     r4, r4, r3, pull #\pull
241                 stmdb   r0!, {r4 - r9, ip, lr}
242                 bge     12b
243         PLD(    cmn     r2, #96                 )
244         PLD(    bge     13b                     )
246                 ldmfd   sp!, {r5 - r9}
247                 cfi_adjust_cfa_offset (-20)
248                 cfi_restore (r5)
249                 cfi_restore (r6)
250                 cfi_restore (r7)
251                 cfi_restore (r8)
252                 cfi_restore (r9)
254 14:             ands    ip, r2, #28
255                 beq     16f
257 15:             mov     lr, r3, push #\push
258                 ldr     r3, [r1, #-4]!
259                 subs    ip, ip, #4
260                 orr     lr, lr, r3, pull #\pull
261                 str     lr, [r0, #-4]!
262                 bgt     15b
263         CALGN(  cmp     r2, #0                  )
264         CALGN(  bge     11b                     )
266 16:             add     r1, r1, #(\pull / 8)
267                 b       8b
269                 .endm
272                 backward_copy_shift     push=8  pull=24
274 17:             backward_copy_shift     push=16 pull=16
276 18:             backward_copy_shift     push=24 pull=8
279 END(memmove)
280 libc_hidden_builtin_def (memmove)