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