1 /* Copyright (c) 2017 SiFive Inc. All rights reserved.
3 This copyrighted material is made available to anyone wishing to use,
4 modify, copy, or redistribute it subject to the terms and conditions
5 of the FreeBSD License. This program is distributed in the hope that
6 it will be useful, but WITHOUT ANY WARRANTY expressed or implied,
7 including the implied warranties of MERCHANTABILITY or FITNESS FOR
8 A PARTICULAR PURPOSE. A copy of this license is available at
9 http://www.opensource.org/licenses.
15 size_t strlen(const char *str
)
17 const char *start
= str
;
19 #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
22 return str
- start
- 1;
24 if (__builtin_expect ((uintptr_t)str
& (sizeof (long) - 1), 0)) do
29 return str
- start
- 1;
30 } while ((uintptr_t)str
& (sizeof (long) - 1));
32 unsigned long *ls
= (unsigned long *)str
;
33 while (!__libc_detect_null (*ls
++))
35 asm volatile ("" : "+r"(ls
)); /* prevent "optimization" */
37 str
= (const char *)ls
;
38 size_t ret
= str
- start
, sl
= sizeof (long);
40 char c0
= str
[0 - sl
], c1
= str
[1 - sl
], c2
= str
[2 - sl
], c3
= str
[3 - sl
];
41 if (c0
== 0) return ret
+ 0 - sl
;
42 if (c1
== 0) return ret
+ 1 - sl
;
43 if (c2
== 0) return ret
+ 2 - sl
;
44 if (sl
== 4 || c3
== 0) return ret
+ 3 - sl
;
46 c0
= str
[4 - sl
], c1
= str
[5 - sl
], c2
= str
[6 - sl
], c3
= str
[7 - sl
];
47 if (c0
== 0) return ret
+ 4 - sl
;
48 if (c1
== 0) return ret
+ 5 - sl
;
49 if (c2
== 0) return ret
+ 6 - sl
;
52 #endif /* not PREFER_SIZE_OVER_SPEED */