1/* ANSI C standard library function strncpy. 2 3 Copyright (c) 2001-2008 Tensilica Inc. 4 5 Permission is hereby granted, free of charge, to any person obtaining 6 a copy of this software and associated documentation files (the 7 "Software"), to deal in the Software without restriction, including 8 without limitation the rights to use, copy, modify, merge, publish, 9 distribute, sublicense, and/or sell copies of the Software, and to 10 permit persons to whom the Software is furnished to do so, subject to 11 the following conditions: 12 13 The above copyright notice and this permission notice shall be included 14 in all copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 23 24#include "xtensa-asm.h" 25 26 .text 27.begin schedule 28 .align 4 29 .literal_position 30__strncpy_aux: 31 32.Lsrc1mod2: // src address is odd 33 l8ui a8, a3, 0 // get byte 0 34 addi a3, a3, 1 // advance src pointer 35 s8i a8, a10, 0 // store byte 0 36 addi a4, a4, -1 // decrement n 37 beqz a4, .Lret // if n is zero 38 addi a10, a10, 1 // advance dst pointer 39 beqz a8, .Lfill // if byte 0 is zero 40 bbci.l a3, 1, .Lsrcaligned // if src is now word-aligned 41 42.Lsrc2mod4: // src address is 2 mod 4 43 l8ui a8, a3, 0 // get byte 0 44 addi a4, a4, -1 // decrement n 45 s8i a8, a10, 0 // store byte 0 46 beqz a4, .Lret // if n is zero 47 addi a10, a10, 1 // advance dst pointer 48 beqz a8, .Lfill // if byte 0 is zero 49 l8ui a8, a3, 1 // get byte 0 50 addi a3, a3, 2 // advance src pointer 51 s8i a8, a10, 0 // store byte 0 52 addi a4, a4, -1 // decrement n 53 beqz a4, .Lret // if n is zero 54 addi a10, a10, 1 // advance dst pointer 55 bnez a8, .Lsrcaligned 56 j .Lfill 57 58.Lret: 59#if XTENSA_ESP32_PSRAM_CACHE_FIX 60 memw 61#endif 62 leaf_return 63 64 65 .align 4 66 .global strncpy 67 .type strncpy, @function 68strncpy: 69 leaf_entry sp, 16 70 /* a2 = dst, a3 = src */ 71 72 mov a10, a2 // leave dst in return value register 73 beqz a4, .Lret // if n is zero 74 75 movi a11, MASK0 76 movi a5, MASK1 77 movi a6, MASK2 78 movi a7, MASK3 79 bbsi.l a3, 0, .Lsrc1mod2 80 bbsi.l a3, 1, .Lsrc2mod4 81.Lsrcaligned: 82 83 /* Check if the destination is aligned. */ 84 movi a8, 3 85 bnone a10, a8, .Laligned 86 87 j .Ldstunaligned 88 89 90/* Fill the dst with zeros -- n is at least 1. */ 91 92.Lfill: 93 movi a9, 0 94 bbsi.l a10, 0, .Lfill1mod2 95 bbsi.l a10, 1, .Lfill2mod4 96.Lfillaligned: 97 blti a4, 4, .Lfillcleanup 98 99 /* Loop filling complete words with zero. */ 100#if XCHAL_HAVE_LOOPS 101 102 srai a8, a4, 2 103 loop a8, 1f 104 s32i a9, a10, 0 105 addi a10, a10, 4 106 1071: slli a8, a8, 2 108 sub a4, a4, a8 109 110#else /* !XCHAL_HAVE_LOOPS */ 111 1121: s32i a9, a10, 0 113 addi a10, a10, 4 114 addi a4, a4, -4 115 bgei a4, 4, 1b 116 117#endif /* !XCHAL_HAVE_LOOPS */ 118 119 beqz a4, 2f 120 121.Lfillcleanup: 122 /* Fill leftover (1 to 3) bytes with zero. */ 123 s8i a9, a10, 0 // store byte 0 124 addi a4, a4, -1 // decrement n 125 addi a10, a10, 1 126 bnez a4, .Lfillcleanup 127 1282: 129#if XTENSA_ESP32_PSRAM_CACHE_FIX 130 memw 131#endif 132 leaf_return 133 134.Lfill1mod2: // dst address is odd 135 s8i a9, a10, 0 // store byte 0 136 addi a4, a4, -1 // decrement n 137 beqz a4, 2b // if n is zero 138 addi a10, a10, 1 // advance dst pointer 139 bbci.l a10, 1, .Lfillaligned // if dst is now word-aligned 140 141.Lfill2mod4: // dst address is 2 mod 4 142 s8i a9, a10, 0 // store byte 0 143 addi a4, a4, -1 // decrement n 144 beqz a4, 2b // if n is zero 145 s8i a9, a10, 1 // store byte 1 146 addi a4, a4, -1 // decrement n 147 beqz a4, 2b // if n is zero 148 addi a10, a10, 2 // advance dst pointer 149 j .Lfillaligned 150 151 152/* dst is word-aligned; src is word-aligned; n is at least 1. */ 153 154 .align 4 155#if XCHAL_HAVE_LOOPS 156#if XCHAL_HAVE_DENSITY 157 /* (2 mod 4) alignment for loop instruction */ 158#else 159 /* (1 mod 4) alignment for loop instruction */ 160 .byte 0 161 .byte 0 162#endif 163#endif 164.Laligned: 165#if XCHAL_HAVE_LOOPS 166#if XCHAL_HAVE_DENSITY 167 _movi.n a8, 0 // set up for the maximum loop count 168#else 169 _movi a8, 0 // set up for the maximum loop count 170#endif 171 loop a8, 1f // loop forever (almost anyway) 172 blti a4, 5, .Ldstunaligned // n is near limit; do one at a time 173 l32i a8, a3, 0 // get word from src 174 addi a3, a3, 4 // advance src pointer 175 bnone a8, a11, .Lz0 // if byte 0 is zero 176 bnone a8, a5, .Lz1 // if byte 1 is zero 177 bnone a8, a6, .Lz2 // if byte 2 is zero 178 s32i a8, a10, 0 // store word to dst 179 addi a4, a4, -4 // decrement n 180 addi a10, a10, 4 // advance dst pointer 181 bnone a8, a7, .Lfill // if byte 3 is zero 1821: 183 184#else /* !XCHAL_HAVE_LOOPS */ 185 1861: blti a4, 5, .Ldstunaligned // n is near limit; do one at a time 187 l32i a8, a3, 0 // get word from src 188 addi a3, a3, 4 // advance src pointer 189 bnone a8, a11, .Lz0 // if byte 0 is zero 190 bnone a8, a5, .Lz1 // if byte 1 is zero 191 bnone a8, a6, .Lz2 // if byte 2 is zero 192 s32i a8, a10, 0 // store word to dst 193 addi a4, a4, -4 // decrement n 194 addi a10, a10, 4 // advance dst pointer 195 bany a8, a7, 1b // no zeroes 196#endif /* !XCHAL_HAVE_LOOPS */ 197 198 j .Lfill 199 200.Lz0: /* Byte 0 is zero. */ 201#ifdef __XTENSA_EB__ 202 movi a8, 0 203#endif 204 s8i a8, a10, 0 205 addi a4, a4, -1 // decrement n 206 addi a10, a10, 1 // advance dst pointer 207 j .Lfill 208 209.Lz1: /* Byte 1 is zero. */ 210#ifdef __XTENSA_EB__ 211 extui a8, a8, 16, 16 212#endif 213 s16i a8, a10, 0 214 addi a4, a4, -2 // decrement n 215 addi a10, a10, 2 // advance dst pointer 216 j .Lfill 217 218.Lz2: /* Byte 2 is zero. */ 219#ifdef __XTENSA_EB__ 220 extui a8, a8, 16, 16 221#endif 222 s16i a8, a10, 0 223 movi a8, 0 224 s8i a8, a10, 2 225 addi a4, a4, -3 // decrement n 226 addi a10, a10, 3 // advance dst pointer 227 j .Lfill 228 229 .align 4 230#if XCHAL_HAVE_LOOPS 231#if XCHAL_HAVE_DENSITY 232 /* (2 mod 4) alignment for loop instruction */ 233#else 234 /* (1 mod 4) alignment for loop instruction */ 235 .byte 0 236 .byte 0 237#endif 238#endif 239.Ldstunaligned: 240 241#if XCHAL_HAVE_LOOPS 242#if XCHAL_HAVE_DENSITY 243 _movi.n a8, 0 // set up for the maximum loop count 244#else 245 _movi a8, 0 // set up for the maximum loop count 246#endif 247 loop a8, 2f // loop forever (almost anyway) 248#endif 2491: l8ui a8, a3, 0 250 addi a3, a3, 1 251#if XTENSA_ESP32_PSRAM_CACHE_FIX 252 nop 253 nop 254 nop 255#endif 256 s8i a8, a10, 0 257 addi a4, a4, -1 258 beqz a4, 3f 259 addi a10, a10, 1 260#if XCHAL_HAVE_LOOPS 261 beqz a8, 2f 262#else 263 bnez a8, 1b 264#endif 2652: j .Lfill 266 2673: 268#if XTENSA_ESP32_PSRAM_CACHE_FIX 269 memw 270#endif 271 leaf_return 272.end schedule 273 274 .size strncpy, . - strncpy 275