1 /* Copyright (C) 2006-2022 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <https://www.gnu.org/licenses/>. */
19 /* Thumb requires excessive IT insns here. */
22 #include <arm-features.h>
25 * Data preload for architectures that support it (ARM V5TE and above)
27 #if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
28 && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__) \
29 && !defined (__ARM_ARCH_4T__) && !defined (__ARM_ARCH_5__) \
30 && !defined (__ARM_ARCH_5T__))
31 #define PLD(code...) code
37 * This can be used to enable code to cacheline align the source pointer.
38 * Experiments on tested architectures (StrongARM and XScale) didn't show
39 * this a worthwhile thing to do. That might be different in the future.
41 //#define CALGN(code...) code
42 #define CALGN(code...)
45 * Endian independent macros for shifting bytes within registers.
58 /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
63 cfi_adjust_cfa_offset (12)
64 cfi_rel_offset (r4, 4)
65 cfi_rel_offset (lr, 8)
79 cfi_adjust_cfa_offset (16)
80 cfi_rel_offset (r5, 0)
81 cfi_rel_offset (r6, 4)
82 cfi_rel_offset (r7, 8)
83 cfi_rel_offset (r8, 12)
86 CALGN( ands ip, r1, #31 )
87 CALGN( rsb r3, ip, #32 )
88 CALGN( sbcsne r4, r3, r2 ) @ C is always set here
91 CALGN( subs r2, r2, r3 ) @ C gets set
93 CALGN( add pc, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2))
95 CALGN( add r4, r4, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2))
100 2: PLD( cmp r2, #96 )
106 3: PLD( pld [r1, #124] )
107 4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
109 stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
114 #ifndef ARM_ALWAYS_BX
115 /* C is always clear here. */
116 addne pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
121 cfi_adjust_cfa_offset (4)
122 cfi_rel_offset (r10, 0)
123 0: add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
124 /* If alignment is not perfect, then there will be some
125 padding (nop) instructions between this BX and label 6.
126 The computation above assumed that two instructions
127 later is exactly the right spot. */
128 add r10, #(6f - (0b + PC_OFS))
131 .p2align ARM_BX_ALIGN_LOG2
133 .p2align ARM_BX_ALIGN_LOG2
135 .p2align ARM_BX_ALIGN_LOG2
137 .p2align ARM_BX_ALIGN_LOG2
139 .p2align ARM_BX_ALIGN_LOG2
141 .p2align ARM_BX_ALIGN_LOG2
143 .p2align ARM_BX_ALIGN_LOG2
145 .p2align ARM_BX_ALIGN_LOG2
148 #ifndef ARM_ALWAYS_BX
149 add pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
152 0: add r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
153 /* If alignment is not perfect, then there will be some
154 padding (nop) instructions between this BX and label 66.
155 The computation above assumed that two instructions
156 later is exactly the right spot. */
157 add r10, #(66f - (0b + PC_OFS))
160 .p2align ARM_BX_ALIGN_LOG2
162 .p2align ARM_BX_ALIGN_LOG2
164 .p2align ARM_BX_ALIGN_LOG2
166 .p2align ARM_BX_ALIGN_LOG2
168 .p2align ARM_BX_ALIGN_LOG2
170 .p2align ARM_BX_ALIGN_LOG2
172 .p2align ARM_BX_ALIGN_LOG2
174 .p2align ARM_BX_ALIGN_LOG2
179 cfi_adjust_cfa_offset (-4)
186 cfi_adjust_cfa_offset (-16)
192 8: movs r2, r2, lsl #31
200 #if ((defined (__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__)) \
201 || defined (ARM_ALWAYS_BX))
203 cfi_adjust_cfa_offset (-12)
233 .macro forward_copy_shift pull push
238 CALGN( ands ip, r1, #31 )
239 CALGN( rsb ip, ip, #32 )
240 CALGN( sbcsne r4, ip, r2 ) @ C is always set here
241 CALGN( subcc r2, r2, ip )
244 11: push {r5 - r8, r10}
245 cfi_adjust_cfa_offset (20)
246 cfi_rel_offset (r5, 0)
247 cfi_rel_offset (r6, 4)
248 cfi_rel_offset (r7, 8)
249 cfi_rel_offset (r8, 12)
250 cfi_rel_offset (r10, 16)
259 12: PLD( pld [r1, #124] )
260 13: ldmia r1!, {r4, r5, r6, r7}
261 mov r3, lr, PULL #\pull
263 ldmia r1!, {r8, r10, ip, lr}
264 orr r3, r3, r4, PUSH #\push
265 mov r4, r4, PULL #\pull
266 orr r4, r4, r5, PUSH #\push
267 mov r5, r5, PULL #\pull
268 orr r5, r5, r6, PUSH #\push
269 mov r6, r6, PULL #\pull
270 orr r6, r6, r7, PUSH #\push
271 mov r7, r7, PULL #\pull
272 orr r7, r7, r8, PUSH #\push
273 mov r8, r8, PULL #\pull
274 orr r8, r8, r10, PUSH #\push
275 mov r10, r10, PULL #\pull
276 orr r10, r10, ip, PUSH #\push
277 mov ip, ip, PULL #\pull
278 orr ip, ip, lr, PUSH #\push
279 stmia r0!, {r3, r4, r5, r6, r7, r8, r10, ip}
283 cfi_adjust_cfa_offset (-20)
293 15: mov r3, lr, PULL #\pull
296 orr r3, r3, lr, PUSH #\push
302 16: sub r1, r1, #(\push / 8)
308 forward_copy_shift pull=8 push=24
310 17: forward_copy_shift pull=16 push=16
312 18: forward_copy_shift pull=24 push=8
315 libc_hidden_builtin_def (memcpy)