1/* ANSI C standard library function strlen. 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 <picolibc.h> 25 26#include "xtensa-asm.h" 27 28 .text 29 .begin schedule 30 .align 4 31 .literal_position 32 .global strlen 33 .type strlen, @function 34strlen: 35 leaf_entry sp, 16 36 /* a2 = s */ 37 38 addi a3, a2, -4 // because we overincrement at the end 39 movi a4, MASK0 40 movi a5, MASK1 41 movi a6, MASK2 42 movi a7, MASK3 43 bbsi.l a2, 0, .L1mod2 44 bbsi.l a2, 1, .L2mod4 45 j .Laligned 46 47.L1mod2: // address is odd 48 l8ui a8, a3, 4 // get byte 0 49 addi a3, a3, 1 // advance string pointer 50 beqz a8, .Lz3 // if byte 0 is zero 51 bbci.l a3, 1, .Laligned // if string pointer is now word-aligned 52 53.L2mod4: // address is 2 mod 4 54 addi a3, a3, 2 // advance ptr for aligned access 55 l32i a8, a3, 0 // get word with first two bytes of string 56 bnone a8, a6, .Lz2 // if byte 2 (of word, not string) is zero 57 bany a8, a7, .Laligned // if byte 3 (of word, not string) is nonzero 58 59 /* Byte 3 is zero. */ 60 addi a3, a3, 3 // point to zero byte 61 sub a2, a3, a2 // subtract to get length 62 leaf_return 63 64 65/* String is word-aligned. */ 66 67 .align 4 68#if XCHAL_HAVE_LOOPS 69#if XCHAL_HAVE_DENSITY 70 /* (2 mod 4) alignment for loop instruction */ 71#else 72 /* (1 mod 4) alignment for loop instruction */ 73 .byte 0 74 .byte 0 75#endif 76#endif 77.Laligned: 78#if XCHAL_HAVE_LOOPS 79#if XCHAL_HAVE_DENSITY 80 _movi.n a8, 0 // set up for the maximum loop count 81#else 82 _movi a8, 0 // set up for the maximum loop count 83#endif 84 loop a8, .Lz3 // loop forever (almost anyway) 85#endif 861: l32i a8, a3, 4 // get next word of string 87 addi a3, a3, 4 // advance string pointer 88 bnone a8, a4, .Lz0 // if byte 0 is zero 89 bnone a8, a5, .Lz1 // if byte 1 is zero 90 bnone a8, a6, .Lz2 // if byte 2 is zero 91#if XCHAL_HAVE_LOOPS 92 bnone a8, a7, .Lz3 // if byte 3 is zero 93#else 94 bany a8, a7, 1b // repeat if byte 3 is non-zero 95#endif 96 97.Lz3: /* Byte 3 is zero. */ 98 addi a3, a3, 3 // point to zero byte 99 /* Fall through.... */ 100 101.Lz0: /* Byte 0 is zero. */ 102 sub a2, a3, a2 // subtract to get length 103 leaf_return 104 105.Lz1: /* Byte 1 is zero. */ 106 addi a3, a3, 1 // point to zero byte 107 sub a2, a3, a2 // subtract to get length 108 leaf_return 109 110.Lz2: /* Byte 2 is zero. */ 111 addi a3, a3, 2 // point to zero byte 112 sub a2, a3, a2 // subtract to get length 113 leaf_return 114 115 .end schedule 116 117 .size strlen, . - strlen 118