• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2010 MIPS Technologies, Inc.
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *      * Redistributions of source code must retain the above copyright
11  *        notice, this list of conditions and the following disclaimer.
12  *      * Redistributions in binary form must reproduce the above copyright
13  *        notice, this list of conditions and the following disclaimer
14  *        in the documentation and/or other materials provided with
15  *        the distribution.
16  *      * Neither the name of MIPS Technologies Inc. nor the names of its
17  *        contributors may be used to endorse or promote products derived
18  *        from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include "mips-string-ops.h"
34 
35 #define do_strlen_word(__av) {\
36     if (detect_zero(x,x,_01s,_80s)) break;\
37     x = __av;\
38     cnt += sizeof (unsigned);\
39     }
40 
41 #define do_strlen_byte(__x) {\
42   if ((bx.b.B##__x) == 0) break;\
43   ++cnt;\
44   }
45 
46 #if SMOKE_TEST_MIPS_STRLEN
47 #define strlen my_strlen
48 #endif
49 
50 int
strlen(const void * _a)51 strlen (const void *_a)
52 {
53   int cnt = 0;
54   unsigned x;
55 
56   /* align the string to word boundary so we can do word at a time.  */
57   if ((cvt_ptr_to (unsigned, _a) & (sizeof (unsigned) - 1)) != 0)
58     {
59       if ((cvt_ptr_to (unsigned, _a) & 1) != 0)
60 	{
61 	  if (get_byte (_a, 0) == 0)
62 	    return cnt;
63 	  /* set bit 1 so 2-bytes are checked and incremented. */
64 	  inc_ptr_as (char *, _a, 1);
65 	  ++cnt;
66 	}
67       if ((cvt_ptr_to (unsigned, _a) & 2) != 0)
68 	{
69 	  if (get_byte (_a, 0) == 0)
70 	    return cnt + 0;
71 	  if (get_byte (_a, 1) == 0)
72 	    return cnt + 1;
73 	  inc_ptr_as (char *, _a, 2);
74 	  cnt += 2;
75 	}
76     }
77 
78 #if __mips64
79 #error strlen: mips64 check for 4-byte alignment not implemented.
80 #endif
81 
82   if (1)
83     {
84       def_and_set_01 (_01s);
85       def_and_set_80 (_80s);
86 
87       /* as advantagous as it is to performance, this code cannot pre-load
88          the following word, nor can it prefetch the next line at the start
89          of the loop since the string can be at the end of a page with the
90          following page unmapped. There are tests in the suite to catch
91          any attempt to go beyond the current word. */
92       x = get_word (_a, 0);
93       while (1)
94 	{
95 	  /* doing 8 words should cover most strings.  */
96 	  do_strlen_word (get_word (_a, 1));
97 	  do_strlen_word (get_word (_a, 2));
98 	  do_strlen_word (get_word (_a, 3));
99 	  do_strlen_word (get_word (_a, 4));
100 	  do_strlen_word (get_word (_a, 5));
101 	  do_strlen_word (get_word (_a, 6));
102 	  do_strlen_word (get_word (_a, 7));
103 	  do_strlen_word (get_word (_a, 8));
104 	  inc_ptr_as (unsigned *, _a, 8);
105 	}
106     }
107   while (1)
108     {
109       /* pull apart the last word processed and find the zero.  */
110       bitfields_t bx;
111       bx.v = x;
112 #if __mips64
113       do_strlen_byte (0);
114       do_strlen_byte (1);
115       do_strlen_byte (2);
116       do_strlen_byte (3);
117       do_strlen_byte (4);
118       do_strlen_byte (5);
119       do_strlen_byte (6);
120 #else
121       do_strlen_byte (0);
122       do_strlen_byte (1);
123       do_strlen_byte (2);
124 #endif
125       /* last byte is zero */
126       break;
127     }
128   return cnt;
129 }
130 
131 #undef do_strlen_byte
132 #undef do_strlen_word
133 
134 #if SMOKE_TEST_MIPS_STRLEN
135 #include <stdio.h>
136 char str1[] = "DHRYSTONE PROGRAM, 1'ST STRING";
137 char str2[] = "DHRYSTONE PROGRAM, 2'ST STRING";
138 
139 char str3[] = "another string";
140 char str4[] = "another";
141 
142 char str5[] = "somes tring";
143 char str6[] = "somes_tring";
144 
145 char str7[16], str8[16];
146 
147 static char *
chk(unsigned mine,unsigned libs,int * errors)148 chk (unsigned mine, unsigned libs, int *errors)
149 {
150   static char answer[1024];
151   char *result = mine == libs ? "PASS" : "FAIL";
152   sprintf (answer, "new_strlen=%d: lib_strlen=%d: %s!", mine, libs, result);
153   if (mine != libs)
154     (*errors)++;
155   return answer;
156 }
157 
158 int
main(int argc,char ** argv)159 main (int argc, char **argv)
160 {
161   int errors = 0;
162   /* set -1 in one position */
163   str6[5] = 0xff;
164   /* set zero in same position with junk in following 3 */
165   str7[0] = str8[0] = 0;
166   str7[1] = 0xff;
167   str7[2] = 'a';
168   str7[3] = 2;
169   str8[1] = 's';
170   str8[2] = -2;
171   str8[3] = 0;
172 
173   fprintf (stderr, "========== mips_strlen%s test...\n",
174 	   argv[0] ? argv[0] : "unknown strlen");
175 #define P(__x,__y) {\
176     int a = my_strlen(__x + __y);\
177     int b = (strlen)(__x + __y) /* library version */;\
178     fprintf(stderr,"%s+%d: %s\n",#__x,__y,chk(a,b,&errors));\
179     }
180 
181   P (str1, 0);
182   P (str1, 1);
183   P (str1, 2);
184   P (str1, 3);
185 
186   P (str2, 0);
187   P (str2, 1);
188   P (str2, 2);
189   P (str2, 3);
190 
191   P (str3, 0);
192   P (str3, 1);
193   P (str3, 2);
194   P (str3, 3);
195 
196   P (str4, 0);
197   P (str4, 1);
198   P (str4, 2);
199   P (str4, 3);
200 
201   P (str5, 0);
202   P (str5, 1);
203   P (str5, 2);
204   P (str5, 3);
205 
206   P (str6, 0);
207   P (str6, 1);
208   P (str6, 2);
209   P (str6, 3);
210 
211   P (str7, 0);
212   P (str7, 1);
213   P (str7, 2);
214   P (str7, 3);
215 
216   P (str8, 0);
217   P (str8, 1);
218   P (str8, 2);
219   P (str8, 3);
220 
221   return errors;
222 }
223 #endif
224