1bbbf1280Sopenharmony_ci/* 2bbbf1280Sopenharmony_ci * strcpy 3bbbf1280Sopenharmony_ci * 4bbbf1280Sopenharmony_ci * Copyright (c) 2008-2020, Arm Limited. 5bbbf1280Sopenharmony_ci * SPDX-License-Identifier: MIT 6bbbf1280Sopenharmony_ci */ 7bbbf1280Sopenharmony_ci 8bbbf1280Sopenharmony_ci/* For GLIBC: 9bbbf1280Sopenharmony_ci#include <string.h> 10bbbf1280Sopenharmony_ci#include <memcopy.h> 11bbbf1280Sopenharmony_ci 12bbbf1280Sopenharmony_ci#undef strcmp 13bbbf1280Sopenharmony_ci*/ 14bbbf1280Sopenharmony_ci 15bbbf1280Sopenharmony_ci#ifdef __thumb2__ 16bbbf1280Sopenharmony_ci#define magic1(REG) "#0x01010101" 17bbbf1280Sopenharmony_ci#define magic2(REG) "#0x80808080" 18bbbf1280Sopenharmony_ci#else 19bbbf1280Sopenharmony_ci#define magic1(REG) #REG 20bbbf1280Sopenharmony_ci#define magic2(REG) #REG ", lsl #7" 21bbbf1280Sopenharmony_ci#endif 22bbbf1280Sopenharmony_ci 23bbbf1280Sopenharmony_cichar* __attribute__((naked)) 24bbbf1280Sopenharmony_ci__strcpy_arm (char* dst, const char* src) 25bbbf1280Sopenharmony_ci{ 26bbbf1280Sopenharmony_ci __asm__ ( 27bbbf1280Sopenharmony_ci "pld [r1, #0]\n\t" 28bbbf1280Sopenharmony_ci "eor r2, r0, r1\n\t" 29bbbf1280Sopenharmony_ci "mov ip, r0\n\t" 30bbbf1280Sopenharmony_ci "tst r2, #3\n\t" 31bbbf1280Sopenharmony_ci "bne 4f\n\t" 32bbbf1280Sopenharmony_ci "tst r1, #3\n\t" 33bbbf1280Sopenharmony_ci "bne 3f\n" 34bbbf1280Sopenharmony_ci "5:\n\t" 35bbbf1280Sopenharmony_ci# ifndef __thumb2__ 36bbbf1280Sopenharmony_ci "str r5, [sp, #-4]!\n\t" 37bbbf1280Sopenharmony_ci "mov r5, #0x01\n\t" 38bbbf1280Sopenharmony_ci "orr r5, r5, r5, lsl #8\n\t" 39bbbf1280Sopenharmony_ci "orr r5, r5, r5, lsl #16\n\t" 40bbbf1280Sopenharmony_ci# endif 41bbbf1280Sopenharmony_ci 42bbbf1280Sopenharmony_ci "str r4, [sp, #-4]!\n\t" 43bbbf1280Sopenharmony_ci "tst r1, #4\n\t" 44bbbf1280Sopenharmony_ci "ldr r3, [r1], #4\n\t" 45bbbf1280Sopenharmony_ci "beq 2f\n\t" 46bbbf1280Sopenharmony_ci "sub r2, r3, "magic1(r5)"\n\t" 47bbbf1280Sopenharmony_ci "bics r2, r2, r3\n\t" 48bbbf1280Sopenharmony_ci "tst r2, "magic2(r5)"\n\t" 49bbbf1280Sopenharmony_ci "itt eq\n\t" 50bbbf1280Sopenharmony_ci "streq r3, [ip], #4\n\t" 51bbbf1280Sopenharmony_ci "ldreq r3, [r1], #4\n" 52bbbf1280Sopenharmony_ci "bne 1f\n\t" 53bbbf1280Sopenharmony_ci /* Inner loop. We now know that r1 is 64-bit aligned, so we 54bbbf1280Sopenharmony_ci can safely fetch up to two words. This allows us to avoid 55bbbf1280Sopenharmony_ci load stalls. */ 56bbbf1280Sopenharmony_ci ".p2align 2\n" 57bbbf1280Sopenharmony_ci "2:\n\t" 58bbbf1280Sopenharmony_ci "pld [r1, #8]\n\t" 59bbbf1280Sopenharmony_ci "ldr r4, [r1], #4\n\t" 60bbbf1280Sopenharmony_ci "sub r2, r3, "magic1(r5)"\n\t" 61bbbf1280Sopenharmony_ci "bics r2, r2, r3\n\t" 62bbbf1280Sopenharmony_ci "tst r2, "magic2(r5)"\n\t" 63bbbf1280Sopenharmony_ci "sub r2, r4, "magic1(r5)"\n\t" 64bbbf1280Sopenharmony_ci "bne 1f\n\t" 65bbbf1280Sopenharmony_ci "str r3, [ip], #4\n\t" 66bbbf1280Sopenharmony_ci "bics r2, r2, r4\n\t" 67bbbf1280Sopenharmony_ci "tst r2, "magic2(r5)"\n\t" 68bbbf1280Sopenharmony_ci "itt eq\n\t" 69bbbf1280Sopenharmony_ci "ldreq r3, [r1], #4\n\t" 70bbbf1280Sopenharmony_ci "streq r4, [ip], #4\n\t" 71bbbf1280Sopenharmony_ci "beq 2b\n\t" 72bbbf1280Sopenharmony_ci "mov r3, r4\n" 73bbbf1280Sopenharmony_ci "1:\n\t" 74bbbf1280Sopenharmony_ci# ifdef __ARMEB__ 75bbbf1280Sopenharmony_ci "rors r3, r3, #24\n\t" 76bbbf1280Sopenharmony_ci# endif 77bbbf1280Sopenharmony_ci "strb r3, [ip], #1\n\t" 78bbbf1280Sopenharmony_ci "tst r3, #0xff\n\t" 79bbbf1280Sopenharmony_ci# ifdef __ARMEL__ 80bbbf1280Sopenharmony_ci "ror r3, r3, #8\n\t" 81bbbf1280Sopenharmony_ci# endif 82bbbf1280Sopenharmony_ci "bne 1b\n\t" 83bbbf1280Sopenharmony_ci "ldr r4, [sp], #4\n\t" 84bbbf1280Sopenharmony_ci# ifndef __thumb2__ 85bbbf1280Sopenharmony_ci "ldr r5, [sp], #4\n\t" 86bbbf1280Sopenharmony_ci# endif 87bbbf1280Sopenharmony_ci "BX LR\n" 88bbbf1280Sopenharmony_ci 89bbbf1280Sopenharmony_ci /* Strings have the same offset from word alignment, but it's 90bbbf1280Sopenharmony_ci not zero. */ 91bbbf1280Sopenharmony_ci "3:\n\t" 92bbbf1280Sopenharmony_ci "tst r1, #1\n\t" 93bbbf1280Sopenharmony_ci "beq 1f\n\t" 94bbbf1280Sopenharmony_ci "ldrb r2, [r1], #1\n\t" 95bbbf1280Sopenharmony_ci "strb r2, [ip], #1\n\t" 96bbbf1280Sopenharmony_ci "cmp r2, #0\n\t" 97bbbf1280Sopenharmony_ci "it eq\n" 98bbbf1280Sopenharmony_ci "BXEQ LR\n" 99bbbf1280Sopenharmony_ci "1:\n\t" 100bbbf1280Sopenharmony_ci "tst r1, #2\n\t" 101bbbf1280Sopenharmony_ci "beq 5b\n\t" 102bbbf1280Sopenharmony_ci "ldrh r2, [r1], #2\n\t" 103bbbf1280Sopenharmony_ci# ifdef __ARMEB__ 104bbbf1280Sopenharmony_ci "tst r2, #0xff00\n\t" 105bbbf1280Sopenharmony_ci "iteet ne\n\t" 106bbbf1280Sopenharmony_ci "strneh r2, [ip], #2\n\t" 107bbbf1280Sopenharmony_ci "lsreq r2, r2, #8\n\t" 108bbbf1280Sopenharmony_ci "streqb r2, [ip]\n\t" 109bbbf1280Sopenharmony_ci "tstne r2, #0xff\n\t" 110bbbf1280Sopenharmony_ci# else 111bbbf1280Sopenharmony_ci "tst r2, #0xff\n\t" 112bbbf1280Sopenharmony_ci "itet ne\n\t" 113bbbf1280Sopenharmony_ci "strneh r2, [ip], #2\n\t" 114bbbf1280Sopenharmony_ci "streqb r2, [ip]\n\t" 115bbbf1280Sopenharmony_ci "tstne r2, #0xff00\n\t" 116bbbf1280Sopenharmony_ci# endif 117bbbf1280Sopenharmony_ci "bne 5b\n\t" 118bbbf1280Sopenharmony_ci "BX LR\n" 119bbbf1280Sopenharmony_ci 120bbbf1280Sopenharmony_ci /* src and dst do not have a common word-alignement. Fall back to 121bbbf1280Sopenharmony_ci byte copying. */ 122bbbf1280Sopenharmony_ci "4:\n\t" 123bbbf1280Sopenharmony_ci "ldrb r2, [r1], #1\n\t" 124bbbf1280Sopenharmony_ci "strb r2, [ip], #1\n\t" 125bbbf1280Sopenharmony_ci "cmp r2, #0\n\t" 126bbbf1280Sopenharmony_ci "bne 4b\n\t" 127bbbf1280Sopenharmony_ci "BX LR"); 128bbbf1280Sopenharmony_ci} 129bbbf1280Sopenharmony_ci/* For GLIBC: libc_hidden_builtin_def (strcpy) */ 130