1 /* Copyright (c) 2009 Xilinx, Inc. All rights reserved. 2 3 Redistribution and use in source and binary forms, with or without 4 modification, are permitted provided that the following conditions are 5 met: 6 7 1. Redistributions source code must retain the above copyright notice, 8 this list of conditions and the following disclaimer. 9 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 14 3. Neither the name of Xilinx nor the names of its contributors may be 15 used to endorse or promote products derived from this software without 16 specific prior written permission. 17 18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS 19 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 21 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 24 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 31 FUNCTION 32 <<strlen>>---character string length 33 34 INDEX 35 strlen 36 37 ANSI_SYNOPSIS 38 #include <string.h> 39 size_t strlen(const char *<[str]>); 40 41 TRAD_SYNOPSIS 42 #include <string.h> 43 size_t strlen(<[str]>) 44 char *<[src]>; 45 46 DESCRIPTION 47 The <<strlen>> function works out the length of the string 48 starting at <<*<[str]>>> by counting chararacters until it 49 reaches a <<NULL>> character. 50 51 RETURNS 52 <<strlen>> returns the character count. 53 54 PORTABILITY 55 <<strlen>> is ANSI C. 56 57 <<strlen>> requires no supporting OS subroutines. 58 59 QUICKREF 60 strlen ansi pure 61 */ 62 63 #include <_ansi.h> 64 #include <string.h> 65 #include <limits.h> 66 67 #define LBLOCKSIZE (sizeof (long)) 68 #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) 69 70 #if LONG_MAX == 2147483647L 71 #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) 72 #else 73 #if LONG_MAX == 9223372036854775807L 74 /* Nonzero if X (a long int) contains a NULL byte. */ 75 #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) 76 #else 77 #error long int is not a 32bit or 64bit type. 78 #endif 79 #endif 80 81 #ifndef DETECTNULL 82 #error long int is not a 32bit or 64bit byte 83 #endif 84 85 size_t 86 _DEFUN (strlen, (str), 87 _CONST char *str) 88 { 89 90 #ifndef HAVE_HW_PCMP 91 92 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) 93 _CONST char *start = str; 94 95 while (*str) 96 str++; 97 98 return str - start; 99 #else 100 _CONST char *start = str; 101 unsigned long *aligned_addr; 102 103 if (!UNALIGNED (str)) 104 { 105 /* If the string is word-aligned, we can check for the presence of 106 a null in each word-sized block. */ 107 aligned_addr = (unsigned long*)str; 108 while (!DETECTNULL (*aligned_addr)) 109 aligned_addr++; 110 111 /* Once a null is detected, we check each byte in that block for a 112 precise position of the null. */ 113 str = (char*)aligned_addr; 114 } 115 116 while (*str) 117 str++; 118 return str - start; 119 #endif /* not PREFER_SIZE_OVER_SPEED */ 120 121 #else 122 123 #include "mb_endian.h" 124 125 asm volatile (" \n\ 126 or r9, r0, r0 /* Index register */ \n\ 127 check_alignment: \n\ 128 andi r3, r5, 3 \n\ 129 bnei r3, align_arg \n\ 130 len_loop: \n" 131 LOAD4BYTES("r3", "r5", "r9") 132 " \n\ 133 pcmpbf r4, r3, r0 \n\ 134 bnei r4, end_len \n\ 135 brid len_loop \n\ 136 addik r9, r9, 4 \n\ 137 end_len: \n\ 138 lbu r3, r5, r9 \n\ 139 beqi r3, done_len \n\ 140 brid end_len \n\ 141 addik r9, r9, 1 \n\ 142 done_len: \n\ 143 rtsd r15, 8 \n\ 144 or r3, r0, r9 /* Return len */ \n\ 145 align_arg: \n\ 146 rsubik r10, r3, 4 \n\ 147 align_loop: \n\ 148 lbu r3, r5, r9 \n\ 149 beqid r3, done_len \n\ 150 addik r10, r10, -1 \n\ 151 bneid r10, align_loop \n\ 152 addik r9, r9, 1 \n\ 153 bri len_loop"); 154 155 #endif /* ! HAVE_HW_PCMP */ 156 } 157