mirror of
https://git.planet-casio.com/Vhex-Kernel-Core/fxlibc.git
synced 2024-12-29 13:03:38 +01:00
string: split strnlen, optimize strlen in assembler (DONE)
This change provides an optimized hand-written strlen function for SuperH targets. The original plan was to declare the C-based naive version weak and just let the linker figure out the proper one to use, but unfortunately static libraries don't work like that; ld intentionally stops at the first version even if it's weak. Instead, some #ifdef's are used in the C-based strlen to not compile it when unneeded. The optimized strlen uses 4-byte accesses and cmp/str.
This commit is contained in:
parent
a48c163e55
commit
6021c536f7
5 changed files with 55 additions and 34 deletions
|
@ -137,7 +137,8 @@ set(SOURCES
|
||||||
src/libc/string/memset.c
|
src/libc/string/memset.c
|
||||||
src/libc/string/strcmp.c
|
src/libc/string/strcmp.c
|
||||||
src/libc/string/strdup.c
|
src/libc/string/strdup.c
|
||||||
src/libc/string/strlen.c)
|
src/libc/string/strlen.c
|
||||||
|
src/libc/string/strnlen.c)
|
||||||
|
|
||||||
if(vhex-generic IN_LIST TARGET_FOLDERS)
|
if(vhex-generic IN_LIST TARGET_FOLDERS)
|
||||||
# TODO
|
# TODO
|
||||||
|
@ -169,6 +170,7 @@ if(sh-generic IN_LIST TARGET_FOLDERS)
|
||||||
src/libc/setjmp/target/sh-generic/setjmp.S
|
src/libc/setjmp/target/sh-generic/setjmp.S
|
||||||
src/libc/setjmp/target/sh-generic/longjmp.S
|
src/libc/setjmp/target/sh-generic/longjmp.S
|
||||||
src/libc/string/target/sh-generic/memchr.S
|
src/libc/string/target/sh-generic/memchr.S
|
||||||
|
src/libc/string/target/sh-generic/strlen.S
|
||||||
src/target/sh-generic/cpucap.c)
|
src/target/sh-generic/cpucap.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
2
STATUS
2
STATUS
|
@ -130,7 +130,7 @@ DONE: Function/symbol/macro is defined, builds, links, and is tested
|
||||||
! 7.21.5.8 strtok: TODO
|
! 7.21.5.8 strtok: TODO
|
||||||
7.21.6.1 memset: DONE
|
7.21.6.1 memset: DONE
|
||||||
! 7.21.6.2 strerror: TODO
|
! 7.21.6.2 strerror: TODO
|
||||||
! 7.21.6.3 strlen: TODO
|
7.21.6.3 strlen: DONE
|
||||||
Extensions:
|
Extensions:
|
||||||
- strnlen: TODO
|
- strnlen: TODO
|
||||||
- strchrnul: TODO
|
- strchrnul: TODO
|
||||||
|
|
|
@ -1,37 +1,12 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/*
|
#ifndef __SUPPORT_ARCH_SH
|
||||||
** The strlen() function calculates the length of the string pointed to by s,
|
|
||||||
** excluding the termi‐nating null byte ('\0').
|
|
||||||
**
|
|
||||||
** TODO: use quad-word access !
|
|
||||||
*/
|
|
||||||
size_t strlen(char const *str)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (str == NULL)
|
size_t strlen(char const *s)
|
||||||
return (0);
|
{
|
||||||
i = -1;
|
size_t i = 0;
|
||||||
while (str[++i] != '\0') ;
|
while(s[i]) i++;
|
||||||
return (i);
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
#endif /*__SUPPORT_ARCH_SH*/
|
||||||
** The strnlen() function returns the number of bytes in the string pointed to
|
|
||||||
** by s, excluding the terminating null byte ('\0'), but at most maxlen.
|
|
||||||
** In doing this, strnlen() looks only at the first maxlen characters in the
|
|
||||||
** string pointed to by s and never beyond s+maxlen.
|
|
||||||
**
|
|
||||||
** TODO: use quad-word access !
|
|
||||||
*/
|
|
||||||
size_t strnlen(char const *str, size_t maxlen)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (str == NULL)
|
|
||||||
return (0);
|
|
||||||
i = -1;
|
|
||||||
while (str[++i] != '\0' && (size_t)i < maxlen) ;
|
|
||||||
return (i);
|
|
||||||
}
|
|
||||||
|
|
8
src/libc/string/strnlen.c
Normal file
8
src/libc/string/strnlen.c
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
size_t strnlen(char const *s, size_t n)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while(s[i] && i < n) i++;
|
||||||
|
return i;
|
||||||
|
}
|
36
src/libc/string/target/sh-generic/strlen.S
Normal file
36
src/libc/string/target/sh-generic/strlen.S
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
.global _strlen
|
||||||
|
.type _strlen, @function
|
||||||
|
|
||||||
|
_strlen:
|
||||||
|
mov r4, r0
|
||||||
|
mov #0, r2
|
||||||
|
|
||||||
|
/* Check 3 bytes to make sure we don't skip any when aligning */
|
||||||
|
mov.b @r0+, r1
|
||||||
|
tst r1, r1
|
||||||
|
bt .end
|
||||||
|
mov.b @r0+, r1
|
||||||
|
tst r1, r1
|
||||||
|
bt .end
|
||||||
|
mov.b @r0+, r1
|
||||||
|
tst r1, r1
|
||||||
|
bt .end
|
||||||
|
|
||||||
|
/* Align to a 4-byte boundary */
|
||||||
|
or #3, r0
|
||||||
|
xor #3, r0
|
||||||
|
|
||||||
|
/* Read bytes by groups of 4 */
|
||||||
|
1: mov.l @r0+, r1
|
||||||
|
cmp/str r1, r2
|
||||||
|
bf 1b
|
||||||
|
|
||||||
|
/* Go back to find out which of the last 4 bytes is the NUL */
|
||||||
|
add #-4, r0
|
||||||
|
2: mov.b @r0+, r1
|
||||||
|
tst r1, r1
|
||||||
|
bf 2b
|
||||||
|
|
||||||
|
.end: add #-1, r0
|
||||||
|
rts
|
||||||
|
sub r4, r0
|
Loading…
Reference in a new issue