1405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham/*
2405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * Copyright (c) 2010 MIPS Technologies, Inc.
3405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham *
4405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * All rights reserved.
5405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham *
6405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * Redistribution and use in source and binary forms, with or without
7405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * modification, are permitted provided that the following conditions
8405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * are met:
9405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham *
10405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham *      * Redistributions of source code must retain the above copyright
11405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham *        notice, this list of conditions and the following disclaimer.
12405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham *      * Redistributions in binary form must reproduce the above copyright
13405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham *        notice, this list of conditions and the following disclaimer
14405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham *        in the documentation and/or other materials provided with
15405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham *        the distribution.
16405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham *      * Neither the name of MIPS Technologies Inc. nor the names of its
17405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham *        contributors may be used to endorse or promote products derived
18405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham *        from this software without specific prior written permission.
19405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham *
20405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham */
32405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
33405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#include "mips-string-ops.h"
34405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
35405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#define do_strlen_word(__av) {\
36405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    if (detect_zero(x,x,_01s,_80s)) break;\
37405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    x = __av;\
38405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    cnt += sizeof (unsigned);\
39405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    }
40405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
41405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#define do_strlen_byte(__x) {\
42405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  if ((bx.b.B##__x) == 0) break;\
43405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  ++cnt;\
44405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  }
45405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
46405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#if SMOKE_TEST_MIPS_STRLEN
47405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#define strlen my_strlen
48405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#endif
49405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
50405b8029a6888f386adf3512113a33546141d1c8Raghu Gandhamint
51405b8029a6888f386adf3512113a33546141d1c8Raghu Gandhamstrlen (const void *_a)
52405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham{
53405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  int cnt = 0;
54405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  unsigned x;
55405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
56405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  /* align the string to word boundary so we can do word at a time.  */
57405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  if ((cvt_ptr_to (unsigned, _a) & (sizeof (unsigned) - 1)) != 0)
58405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    {
59405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      if ((cvt_ptr_to (unsigned, _a) & 1) != 0)
60405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	{
61405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  if (get_byte (_a, 0) == 0)
62405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	    return cnt;
63405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  /* set bit 1 so 2-bytes are checked and incremented. */
64405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  inc_ptr_as (char *, _a, 1);
65405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  ++cnt;
66405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	}
67405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      if ((cvt_ptr_to (unsigned, _a) & 2) != 0)
68405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	{
69405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  if (get_byte (_a, 0) == 0)
70405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	    return cnt + 0;
71405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  if (get_byte (_a, 1) == 0)
72405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	    return cnt + 1;
73405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  inc_ptr_as (char *, _a, 2);
74405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  cnt += 2;
75405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	}
76405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    }
77405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
78405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#if __mips64
79405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#error strlen: mips64 check for 4-byte alignment not implemented.
80405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#endif
81405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
82405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  if (1)
83405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    {
84405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      def_and_set_01 (_01s);
85405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      def_and_set_80 (_80s);
86405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
87405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      /* as advantagous as it is to performance, this code cannot pre-load
88405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham         the following word, nor can it prefetch the next line at the start
89405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham         of the loop since the string can be at the end of a page with the
90405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham         following page unmapped. There are tests in the suite to catch
91405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham         any attempt to go beyond the current word. */
92405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      x = get_word (_a, 0);
93405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      while (1)
94405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	{
95405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  /* doing 8 words should cover most strings.  */
96405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  do_strlen_word (get_word (_a, 1));
97405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  do_strlen_word (get_word (_a, 2));
98405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  do_strlen_word (get_word (_a, 3));
99405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  do_strlen_word (get_word (_a, 4));
100405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  do_strlen_word (get_word (_a, 5));
101405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  do_strlen_word (get_word (_a, 6));
102405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  do_strlen_word (get_word (_a, 7));
103405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  do_strlen_word (get_word (_a, 8));
104405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	  inc_ptr_as (unsigned *, _a, 8);
105405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	}
106405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    }
107405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  while (1)
108405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    {
109405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      /* pull apart the last word processed and find the zero.  */
110405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      bitfields_t bx;
111405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      bx.v = x;
112405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#if __mips64
113405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      do_strlen_byte (0);
114405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      do_strlen_byte (1);
115405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      do_strlen_byte (2);
116405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      do_strlen_byte (3);
117405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      do_strlen_byte (4);
118405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      do_strlen_byte (5);
119405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      do_strlen_byte (6);
120405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#else
121405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      do_strlen_byte (0);
122405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      do_strlen_byte (1);
123405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      do_strlen_byte (2);
124405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#endif
125405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      /* last byte is zero */
126405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham      break;
127405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    }
128405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  return cnt;
129405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham}
130405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
131405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#undef do_strlen_byte
132405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#undef do_strlen_word
133405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
134405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#if SMOKE_TEST_MIPS_STRLEN
135405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#include <stdio.h>
136405b8029a6888f386adf3512113a33546141d1c8Raghu Gandhamchar str1[] = "DHRYSTONE PROGRAM, 1'ST STRING";
137405b8029a6888f386adf3512113a33546141d1c8Raghu Gandhamchar str2[] = "DHRYSTONE PROGRAM, 2'ST STRING";
138405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
139405b8029a6888f386adf3512113a33546141d1c8Raghu Gandhamchar str3[] = "another string";
140405b8029a6888f386adf3512113a33546141d1c8Raghu Gandhamchar str4[] = "another";
141405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
142405b8029a6888f386adf3512113a33546141d1c8Raghu Gandhamchar str5[] = "somes tring";
143405b8029a6888f386adf3512113a33546141d1c8Raghu Gandhamchar str6[] = "somes_tring";
144405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
145405b8029a6888f386adf3512113a33546141d1c8Raghu Gandhamchar str7[16], str8[16];
146405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
147405b8029a6888f386adf3512113a33546141d1c8Raghu Gandhamstatic char *
148405b8029a6888f386adf3512113a33546141d1c8Raghu Gandhamchk (unsigned mine, unsigned libs, int *errors)
149405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham{
150405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  static char answer[1024];
151405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  char *result = mine == libs ? "PASS" : "FAIL";
152405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  sprintf (answer, "new_strlen=%d: lib_strlen=%d: %s!", mine, libs, result);
153405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  if (mine != libs)
154405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    (*errors)++;
155405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  return answer;
156405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham}
157405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
158405b8029a6888f386adf3512113a33546141d1c8Raghu Gandhamint
159405b8029a6888f386adf3512113a33546141d1c8Raghu Gandhammain (int argc, char **argv)
160405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham{
161405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  int errors = 0;
162405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  /* set -1 in one position */
163405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  str6[5] = 0xff;
164405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  /* set zero in same position with junk in following 3 */
165405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  str7[0] = str8[0] = 0;
166405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  str7[1] = 0xff;
167405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  str7[2] = 'a';
168405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  str7[3] = 2;
169405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  str8[1] = 's';
170405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  str8[2] = -2;
171405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  str8[3] = 0;
172405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
173405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  fprintf (stderr, "========== mips_strlen%s test...\n",
174405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham	   argv[0] ? argv[0] : "unknown strlen");
175405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#define P(__x,__y) {\
176405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    int a = my_strlen(__x + __y);\
177405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    int b = (strlen)(__x + __y) /* library version */;\
178405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    fprintf(stderr,"%s+%d: %s\n",#__x,__y,chk(a,b,&errors));\
179405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham    }
180405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
181405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str1, 0);
182405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str1, 1);
183405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str1, 2);
184405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str1, 3);
185405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
186405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str2, 0);
187405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str2, 1);
188405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str2, 2);
189405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str2, 3);
190405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
191405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str3, 0);
192405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str3, 1);
193405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str3, 2);
194405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str3, 3);
195405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
196405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str4, 0);
197405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str4, 1);
198405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str4, 2);
199405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str4, 3);
200405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
201405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str5, 0);
202405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str5, 1);
203405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str5, 2);
204405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str5, 3);
205405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
206405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str6, 0);
207405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str6, 1);
208405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str6, 2);
209405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str6, 3);
210405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
211405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str7, 0);
212405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str7, 1);
213405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str7, 2);
214405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str7, 3);
215405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
216405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str8, 0);
217405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str8, 1);
218405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str8, 2);
219405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  P (str8, 3);
220405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham
221405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham  return errors;
222405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham}
223405b8029a6888f386adf3512113a33546141d1c8Raghu Gandham#endif
224