1 /* Copyright (C) 2006-2016 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))
100 PLD( sfi_pld r1, #0 )
101 2: PLD( subs r2, r2, #96 )
102 PLD( sfi_pld r1, #28 )
104 PLD( sfi_pld r1, #60 )
105 PLD( sfi_pld r1, #92 )
107 3: PLD( sfi_pld r1, #124 )
109 ldmia \B!, {r3, r4, r5, r6, r7, r8, ip, lr}
112 stmia \B!, {r3, r4, r5, r6, r7, r8, ip, lr}
119 #ifndef ARM_ALWAYS_BX
120 /* C is always clear here. */
121 addne pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
126 cfi_adjust_cfa_offset (4)
127 cfi_rel_offset (r10, 0)
128 0: add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
129 /* If alignment is not perfect, then there will be some
130 padding (nop) instructions between this BX and label 6.
131 The computation above assumed that two instructions
132 later is exactly the right spot. */
133 add r10, #(6f - (0b + PC_OFS))
136 .p2align ARM_BX_ALIGN_LOG2
138 .p2align ARM_BX_ALIGN_LOG2
141 .p2align ARM_BX_ALIGN_LOG2
144 .p2align ARM_BX_ALIGN_LOG2
147 .p2align ARM_BX_ALIGN_LOG2
150 .p2align ARM_BX_ALIGN_LOG2
153 .p2align ARM_BX_ALIGN_LOG2
156 .p2align ARM_BX_ALIGN_LOG2
160 #ifndef ARM_ALWAYS_BX
161 add pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
164 0: add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
165 /* If alignment is not perfect, then there will be some
166 padding (nop) instructions between this BX and label 66.
167 The computation above assumed that two instructions
168 later is exactly the right spot. */
169 add r10, #(66f - (0b + PC_OFS))
172 .p2align ARM_BX_ALIGN_LOG2
174 .p2align ARM_BX_ALIGN_LOG2
177 .p2align ARM_BX_ALIGN_LOG2
180 .p2align ARM_BX_ALIGN_LOG2
183 .p2align ARM_BX_ALIGN_LOG2
186 .p2align ARM_BX_ALIGN_LOG2
189 .p2align ARM_BX_ALIGN_LOG2
192 .p2align ARM_BX_ALIGN_LOG2
198 cfi_adjust_cfa_offset (-4)
205 cfi_adjust_cfa_offset (-16)
211 8: movs r2, r2, lsl #31
225 #if ((defined (__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__)) \
226 || defined (ARM_ALWAYS_BX))
228 cfi_adjust_cfa_offset (-12)
265 .macro forward_copy_shift pull push
270 CALGN( ands ip, r1, #31 )
271 CALGN( rsb ip, ip, #32 )
272 CALGN( sbcsne r4, ip, r2 ) @ C is always set here
273 CALGN( subcc r2, r2, ip )
276 11: push {r5 - r8, r10}
277 cfi_adjust_cfa_offset (20)
278 cfi_rel_offset (r5, 0)
279 cfi_rel_offset (r6, 4)
280 cfi_rel_offset (r7, 8)
281 cfi_rel_offset (r8, 12)
282 cfi_rel_offset (r10, 16)
284 PLD( sfi_pld r1, #0 )
285 PLD( subs r2, r2, #96 )
286 PLD( sfi_pld r1, #28 )
288 PLD( sfi_pld r1, #60 )
289 PLD( sfi_pld r1, #92 )
291 12: PLD( sfi_pld r1, #124 )
293 ldmia \B!, {r4, r5, r6, r7}
294 mov r3, lr, PULL #\pull
297 ldmia \B!, {r8, r10, ip, lr}
298 orr r3, r3, r4, PUSH #\push
299 mov r4, r4, PULL #\pull
300 orr r4, r4, r5, PUSH #\push
301 mov r5, r5, PULL #\pull
302 orr r5, r5, r6, PUSH #\push
303 mov r6, r6, PULL #\pull
304 orr r6, r6, r7, PUSH #\push
305 mov r7, r7, PULL #\pull
306 orr r7, r7, r8, PUSH #\push
307 mov r8, r8, PULL #\pull
308 orr r8, r8, r10, PUSH #\push
309 mov r10, r10, PULL #\pull
310 orr r10, r10, ip, PUSH #\push
311 mov ip, ip, PULL #\pull
312 orr ip, ip, lr, PUSH #\push
314 stmia \B!, {r3, r4, r5, r6, r7, r8, r10, ip}
320 cfi_adjust_cfa_offset (-20)
330 15: mov r3, lr, PULL #\pull
334 orr r3, r3, lr, PUSH #\push
341 16: sub r1, r1, #(\push / 8)
347 forward_copy_shift pull=8 push=24
349 17: forward_copy_shift pull=16 push=16
351 18: forward_copy_shift pull=24 push=8
354 libc_hidden_builtin_def (memcpy)