1 /* Copyright (C) 2006-2017 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 /* Thumb requires excessive IT insns here. */
23 #include <arm-features.h>
26 * Data preload for architectures that support it (ARM V5TE and above)
28 #if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
29 && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__) \
30 && !defined (__ARM_ARCH_4T__) && !defined (__ARM_ARCH_5__) \
31 && !defined (__ARM_ARCH_5T__))
32 #define PLD(code...) code
38 * This can be used to enable code to cacheline align the source pointer.
39 * Experiments on tested architectures (StrongARM and XScale) didn't show
40 * this a worthwhile thing to do. That might be different in the future.
42 //#define CALGN(code...) code
43 #define CALGN(code...)
46 * Endian independent macros for shifting bytes within registers.
59 /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
64 cfi_adjust_cfa_offset (12)
65 cfi_rel_offset (r4, 4)
66 cfi_rel_offset (lr, 8)
80 cfi_adjust_cfa_offset (16)
81 cfi_rel_offset (r5, 0)
82 cfi_rel_offset (r6, 4)
83 cfi_rel_offset (r7, 8)
84 cfi_rel_offset (r8, 12)
87 CALGN( ands ip, r1, #31 )
88 CALGN( rsb r3, ip, #32 )
89 CALGN( sbcsne r4, r3, r2 ) @ C is always set here
92 CALGN( subs r2, r2, r3 ) @ C gets set
94 CALGN( add pc, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2))
96 CALGN( add r4, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2))
101 2: PLD( subs r2, r2, #96 )
107 3: PLD( pld [r1, #124] )
108 4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
110 stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
117 #ifndef ARM_ALWAYS_BX
118 /* C is always clear here. */
119 addne pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
124 cfi_adjust_cfa_offset (4)
125 cfi_rel_offset (r10, 0)
126 0: add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
127 /* If alignment is not perfect, then there will be some
128 padding (nop) instructions between this BX and label 6.
129 The computation above assumed that two instructions
130 later is exactly the right spot. */
131 add r10, #(6f - (0b + PC_OFS))
134 .p2align ARM_BX_ALIGN_LOG2
136 .p2align ARM_BX_ALIGN_LOG2
138 .p2align ARM_BX_ALIGN_LOG2
140 .p2align ARM_BX_ALIGN_LOG2
142 .p2align ARM_BX_ALIGN_LOG2
144 .p2align ARM_BX_ALIGN_LOG2
146 .p2align ARM_BX_ALIGN_LOG2
148 .p2align ARM_BX_ALIGN_LOG2
151 #ifndef ARM_ALWAYS_BX
152 add pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
155 0: add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
156 /* If alignment is not perfect, then there will be some
157 padding (nop) instructions between this BX and label 66.
158 The computation above assumed that two instructions
159 later is exactly the right spot. */
160 add r10, #(66f - (0b + PC_OFS))
163 .p2align ARM_BX_ALIGN_LOG2
165 .p2align ARM_BX_ALIGN_LOG2
167 .p2align ARM_BX_ALIGN_LOG2
169 .p2align ARM_BX_ALIGN_LOG2
171 .p2align ARM_BX_ALIGN_LOG2
173 .p2align ARM_BX_ALIGN_LOG2
175 .p2align ARM_BX_ALIGN_LOG2
177 .p2align ARM_BX_ALIGN_LOG2
182 cfi_adjust_cfa_offset (-4)
189 cfi_adjust_cfa_offset (-16)
195 8: movs r2, r2, lsl #31
203 #if ((defined (__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__)) \
204 || defined (ARM_ALWAYS_BX))
206 cfi_adjust_cfa_offset (-12)
236 .macro forward_copy_shift pull push
241 CALGN( ands ip, r1, #31 )
242 CALGN( rsb ip, ip, #32 )
243 CALGN( sbcsne r4, ip, r2 ) @ C is always set here
244 CALGN( subcc r2, r2, ip )
247 11: push {r5 - r8, r10}
248 cfi_adjust_cfa_offset (20)
249 cfi_rel_offset (r5, 0)
250 cfi_rel_offset (r6, 4)
251 cfi_rel_offset (r7, 8)
252 cfi_rel_offset (r8, 12)
253 cfi_rel_offset (r10, 16)
256 PLD( subs r2, r2, #96 )
262 12: PLD( pld [r1, #124] )
263 13: ldmia r1!, {r4, r5, r6, r7}
264 mov r3, lr, PULL #\pull
266 ldmia r1!, {r8, r10, ip, lr}
267 orr r3, r3, r4, PUSH #\push
268 mov r4, r4, PULL #\pull
269 orr r4, r4, r5, PUSH #\push
270 mov r5, r5, PULL #\pull
271 orr r5, r5, r6, PUSH #\push
272 mov r6, r6, PULL #\pull
273 orr r6, r6, r7, PUSH #\push
274 mov r7, r7, PULL #\pull
275 orr r7, r7, r8, PUSH #\push
276 mov r8, r8, PULL #\pull
277 orr r8, r8, r10, PUSH #\push
278 mov r10, r10, PULL #\pull
279 orr r10, r10, ip, PUSH #\push
280 mov ip, ip, PULL #\pull
281 orr ip, ip, lr, PUSH #\push
282 stmia r0!, {r3, r4, r5, r6, r7, r8, r10, ip}
288 cfi_adjust_cfa_offset (-20)
298 15: mov r3, lr, PULL #\pull
301 orr r3, r3, lr, PUSH #\push
307 16: sub r1, r1, #(\push / 8)
313 forward_copy_shift pull=8 push=24
315 17: forward_copy_shift pull=16 push=16
317 18: forward_copy_shift pull=24 push=8
320 libc_hidden_builtin_def (memcpy)