1/* 2 * Copyright (c) 2008 ARM Ltd 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the company may not be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <picolibc.h> 30 31#include "arm_asm.h" 32 33#ifdef __thumb2__ 34#define magic1(REG) #0x01010101 35#define magic2(REG) #0x80808080 36#else 37#define magic1(REG) REG 38#define magic2(REG) REG , lsl #7 39#endif 40 41 .syntax unified 42#ifdef __thumb__ 43 .thumb 44#endif 45 .text 46 .global strcpy 47 .type strcpy, %function 48strcpy: 49 .fnstart 50 .cfi_sections .debug_frame 51 .cfi_startproc 52 prologue push_ip=HAVE_PAC_LEAF 53 54#if !(defined(__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) || \ 55 (defined (__thumb__) && !defined (__thumb2__))) 56 57#ifdef _ISA_ARM_7 58 pld [r1] 59#endif 60 eor r2, r0, r1 61 mov ip, r0 62 tst r2, #3 63 bne 4f 64 tst r1, #3 65 bne 3f 665: 67#ifndef __thumb2__ 68 str r5, [sp, #-4]! 69 mov r5, #0x01 70 orr r5, r5, r5, lsl #8 71 orr r5, r5, r5, lsl #16 72#endif 73 74 str r4, [sp, #-4]! 75 tst r1, #4 76 ldr r3, [r1], #4 77 beq 2f 78 sub r2, r3, magic1(r5) 79 bics r2, r2, r3 80 tst r2, magic2(r5) 81 itt eq 82 streq r3, [ip], #4 83 ldreq r3, [r1], #4 84 bne 1f 85 /* Inner loop. We now know that r1 is 64-bit aligned, so we 86 can safely fetch up to two words. This allows us to avoid 87 load stalls. */ 88 .p2align 2 892: 90#ifdef _ISA_ARM_7 91 pld [r1, #8] 92#endif 93 ldr r4, [r1], #4 94 sub r2, r3, magic1(r5) 95 bics r2, r2, r3 96 tst r2, magic2(r5) 97 sub r2, r4, magic1(r5) 98 bne 1f 99 str r3, [ip], #4 100 bics r2, r2, r4 101 tst r2, magic2(r5) 102 itt eq 103 ldreq r3, [r1], #4 104 streq r4, [ip], #4 105 beq 2b 106 mov r3, r4 1071: 108#ifdef __ARMEB__ 109 rors r3, r3, #24 110#endif 111 strb r3, [ip], #1 112 tst r3, #0xff 113#ifdef __ARMEL__ 114 ror r3, r3, #8 115#endif 116 bne 1b 117 ldr r4, [sp], #4 118#ifndef __thumb2__ 119 ldr r5, [sp], #4 120#endif 121 bx lr 122 123 /* Strings have the same offset from word alignment, but it's 124 not zero. */ 1253: 126 tst r1, #1 127 beq 1f 128 ldrb r2, [r1], #1 129 strb r2, [ip], #1 130 cmp r2, #0 131 it eq 132 bxeq lr 1331: 134 tst r1, #2 135 beq 5b 136 ldrh r2, [r1], #2 137#ifdef __ARMEB__ 138 tst r2, #0xff00 139 iteet ne 140 strhne r2, [ip], #2 141 lsreq r2, r2, #8 142 strbeq r2, [ip] 143 tstne r2, #0xff 144#else 145 tst r2, #0xff 146 itet ne 147 strhne r2, [ip], #2 148 strbeq r2, [ip] 149 tstne r2, #0xff00 150#endif 151 bne 5b 152 .cfi_remember_state 153 epilogue push_ip=HAVE_PAC_LEAF 154 .cfi_restore_state 155 156 /* src and dst do not have a common word-alignement. Fall back to 157 byte copying. */ 1584: 159 ldrb r2, [r1], #1 160 strb r2, [ip], #1 161 cmp r2, #0 162 bne 4b 163 164#elif !defined (__thumb__) || defined (__thumb2__) 165 mov r3, r0 166 1: 167 ldrb r2, [r1], #1 168 strb r2, [r3], #1 169 cmp r2, #0 170 bne 1b 171#else 172 movs r3, r0 1731: 174 ldrb r2, [r1] 175 adds r1, #1 176 strb r2, [r3] 177 adds r3, #1 178 cmp r2, #0 179 bne 1b 180#endif 181 epilogue push_ip=HAVE_PAC_LEAF 182 .cfi_endproc 183 .cantunwind 184 .fnend 185 .size strcpy, . - strcpy 186 187#if defined(__linux__) && defined(__ELF__) 188.section .note.GNU-stack,"",%progbits 189#endif 190