Add CFI statements to ARM's assembly code.
[glibc-ports.git] / sysdeps / arm / memcpy.S
blob673bf43c48c88e30f17eb3b845b42e65609dd270
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, 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
56 /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
58 ENTRY(memcpy)
60                 stmfd   sp!, {r0, r4, lr}
61                 cfi_adjust_cfa_offset (12)
62                 cfi_rel_offset (r4, 4)
63                 cfi_rel_offset (lr, 8)
65                 cfi_remember_state
67                 subs    r2, r2, #4
68                 blt     8f
69                 ands    ip, r0, #3
70         PLD(    pld     [r1, #0]                )
71                 bne     9f
72                 ands    ip, r1, #3
73                 bne     10f
75 1:              subs    r2, r2, #(28)
76                 stmfd   sp!, {r5 - r8}
77                 cfi_adjust_cfa_offset (16)
78                 cfi_rel_offset (r5, 0)
79                 cfi_rel_offset (r6, 4)
80                 cfi_rel_offset (r7, 8)
81                 cfi_rel_offset (r8, 12)
82                 blt     5f
84         CALGN(  ands    ip, r1, #31             )
85         CALGN(  rsb     r3, ip, #32             )
86         CALGN(  sbcnes  r4, r3, r2              )  @ C is always set here
87         CALGN(  bcs     2f                      )
88         CALGN(  adr     r4, 6f                  )
89         CALGN(  subs    r2, r2, r3              )  @ C gets set
90         CALGN(  add     pc, r4, ip              )
92         PLD(    pld     [r1, #0]                )
93 2:      PLD(    subs    r2, r2, #96             )
94         PLD(    pld     [r1, #28]               )
95         PLD(    blt     4f                      )
96         PLD(    pld     [r1, #60]               )
97         PLD(    pld     [r1, #92]               )
99 3:      PLD(    pld     [r1, #124]              )
100 4:              ldmia   r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
101                 subs    r2, r2, #32
102                 stmia   r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
103                 bge     3b
104         PLD(    cmn     r2, #96                 )
105         PLD(    bge     4b                      )
107 5:              ands    ip, r2, #28
108                 rsb     ip, ip, #32
109                 addne   pc, pc, ip              @ C is always clear here
110                 b       7f
111 6:              nop
112                 ldr     r3, [r1], #4
113                 ldr     r4, [r1], #4
114                 ldr     r5, [r1], #4
115                 ldr     r6, [r1], #4
116                 ldr     r7, [r1], #4
117                 ldr     r8, [r1], #4
118                 ldr     lr, [r1], #4
120                 add     pc, pc, ip
121                 nop
122                 nop
123                 str     r3, [r0], #4
124                 str     r4, [r0], #4
125                 str     r5, [r0], #4
126                 str     r6, [r0], #4
127                 str     r7, [r0], #4
128                 str     r8, [r0], #4
129                 str     lr, [r0], #4
131         CALGN(  bcs     2b                      )
133 7:              ldmfd   sp!, {r5 - r8}
134                 cfi_adjust_cfa_offset (-16)
135                 cfi_restore (r5)
136                 cfi_restore (r6)
137                 cfi_restore (r7)
138                 cfi_restore (r8)
140 8:              movs    r2, r2, lsl #31
141                 ldrneb  r3, [r1], #1
142                 ldrcsb  r4, [r1], #1
143                 ldrcsb  ip, [r1]
144                 strneb  r3, [r0], #1
145                 strcsb  r4, [r0], #1
146                 strcsb  ip, [r0]
148 #if defined (__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__)
149                 ldmfd   sp!, {r0, r4, lr}
150                 cfi_adjust_cfa_offset (-12)
151                 cfi_restore (r4)
152                 cfi_restore (lr)
153                 bx      lr
154 #else
155                 ldmfd   sp!, {r0, r4, pc}
156 #endif
158                 cfi_restore_state
160 9:              rsb     ip, ip, #4
161                 cmp     ip, #2
162                 ldrgtb  r3, [r1], #1
163                 ldrgeb  r4, [r1], #1
164                 ldrb    lr, [r1], #1
165                 strgtb  r3, [r0], #1
166                 strgeb  r4, [r0], #1
167                 subs    r2, r2, ip
168                 strb    lr, [r0], #1
169                 blt     8b
170                 ands    ip, r1, #3
171                 beq     1b
173 10:             bic     r1, r1, #3
174                 cmp     ip, #2
175                 ldr     lr, [r1], #4
176                 beq     17f
177                 bgt     18f
180                 .macro  forward_copy_shift pull push
182                 subs    r2, r2, #28
183                 blt     14f
185         CALGN(  ands    ip, r1, #31             )
186         CALGN(  rsb     ip, ip, #32             )
187         CALGN(  sbcnes  r4, ip, r2              )  @ C is always set here
188         CALGN(  subcc   r2, r2, ip              )
189         CALGN(  bcc     15f                     )
191 11:             stmfd   sp!, {r5 - r9}
192                 cfi_adjust_cfa_offset (20)
193                 cfi_rel_offset (r5, 0)
194                 cfi_rel_offset (r6, 4)
195                 cfi_rel_offset (r7, 8)
196                 cfi_rel_offset (r8, 12)
197                 cfi_rel_offset (r9, 16)
199         PLD(    pld     [r1, #0]                )
200         PLD(    subs    r2, r2, #96             )
201         PLD(    pld     [r1, #28]               )
202         PLD(    blt     13f                     )
203         PLD(    pld     [r1, #60]               )
204         PLD(    pld     [r1, #92]               )
206 12:     PLD(    pld     [r1, #124]              )
207 13:             ldmia   r1!, {r4, r5, r6, r7}
208                 mov     r3, lr, pull #\pull
209                 subs    r2, r2, #32
210                 ldmia   r1!, {r8, r9, ip, lr}
211                 orr     r3, r3, r4, push #\push
212                 mov     r4, r4, pull #\pull
213                 orr     r4, r4, r5, push #\push
214                 mov     r5, r5, pull #\pull
215                 orr     r5, r5, r6, push #\push
216                 mov     r6, r6, pull #\pull
217                 orr     r6, r6, r7, push #\push
218                 mov     r7, r7, pull #\pull
219                 orr     r7, r7, r8, push #\push
220                 mov     r8, r8, pull #\pull
221                 orr     r8, r8, r9, push #\push
222                 mov     r9, r9, pull #\pull
223                 orr     r9, r9, ip, push #\push
224                 mov     ip, ip, pull #\pull
225                 orr     ip, ip, lr, push #\push
226                 stmia   r0!, {r3, r4, r5, r6, r7, r8, r9, ip}
227                 bge     12b
228         PLD(    cmn     r2, #96                 )
229         PLD(    bge     13b                     )
231                 ldmfd   sp!, {r5 - r9}
232                 cfi_adjust_cfa_offset (-20)
233                 cfi_restore (r5)
234                 cfi_restore (r6)
235                 cfi_restore (r7)
236                 cfi_restore (r8)
237                 cfi_restore (r9)
239 14:             ands    ip, r2, #28
240                 beq     16f
242 15:             mov     r3, lr, pull #\pull
243                 ldr     lr, [r1], #4
244                 subs    ip, ip, #4
245                 orr     r3, r3, lr, push #\push
246                 str     r3, [r0], #4
247                 bgt     15b
248         CALGN(  cmp     r2, #0                  )
249         CALGN(  bge     11b                     )
251 16:             sub     r1, r1, #(\push / 8)
252                 b       8b
254                 .endm
257                 forward_copy_shift      pull=8  push=24
259 17:             forward_copy_shift      pull=16 push=16
261 18:             forward_copy_shift      pull=24 push=8
263 END(memcpy)
264 libc_hidden_builtin_def (memcpy)