blob: 9fb7e6a85001160760dc79de5cd3b5b091cb75e6 [file] [log] [blame]
Raghu Gandham405b8022012-07-25 18:16:42 -07001/*
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
50int
51strlen (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>
136char str1[] = "DHRYSTONE PROGRAM, 1'ST STRING";
137char str2[] = "DHRYSTONE PROGRAM, 2'ST STRING";
138
139char str3[] = "another string";
140char str4[] = "another";
141
142char str5[] = "somes tring";
143char str6[] = "somes_tring";
144
145char str7[16], str8[16];
146
147static char *
148chk (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
158int
159main (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