Assembler optimized strlen() for SH1, both smaller & faster. Moved strlen() into IRAM.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5629 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
0310f16005
commit
78826de045
|
@ -21,7 +21,11 @@ common/strcat.c
|
|||
common/strchr.c
|
||||
common/strcmp.c
|
||||
common/strcpy.c
|
||||
#if CONFIG_CPU == SH7034
|
||||
common/strlen_a.S
|
||||
#else
|
||||
common/strlen.c
|
||||
#endif
|
||||
common/strncmp.c
|
||||
common/strncpy.c
|
||||
common/strrchr.c
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
FUNCTION
|
||||
<<strlen>>---character string length
|
||||
|
||||
|
@ -53,6 +53,10 @@ QUICKREF
|
|||
#error long int is not a 32bit or 64bit byte
|
||||
#endif
|
||||
|
||||
size_t
|
||||
_DEFUN (strlen, (str),
|
||||
_CONST char *str) __attribute__ ((section (".icode")));
|
||||
|
||||
size_t
|
||||
_DEFUN (strlen, (str),
|
||||
_CONST char *str)
|
||||
|
|
94
firmware/common/strlen_a.S
Executable file
94
firmware/common/strlen_a.S
Executable file
|
@ -0,0 +1,94 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 by Jens Arnold
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "config.h"
|
||||
|
||||
.section .icode,"ax",@progbits
|
||||
|
||||
.align 2
|
||||
.global _strlen
|
||||
.type _strlen,@function
|
||||
|
||||
/* Works out the length of a string
|
||||
* This version is optimized for speed
|
||||
*
|
||||
* arguments:
|
||||
* r4 - start address
|
||||
*
|
||||
* return value:
|
||||
* r0 - string length
|
||||
*
|
||||
* register usage:
|
||||
* r0 - current address
|
||||
* r1 - current value (byte/long)
|
||||
* r2 - mask for alignment / zero (for cmp/str)
|
||||
* r4 - start address
|
||||
*
|
||||
*/
|
||||
|
||||
_strlen:
|
||||
mov r4,r0 /* r0 = start address */
|
||||
tst #3,r0 /* long aligned? */
|
||||
bt .start_l /* yes, jump directly to the longword loop */
|
||||
|
||||
/* not long aligned: check the first 3 bytes */
|
||||
mov.b @r0+,r1 /* fetch first byte */
|
||||
tst r1,r1 /* byte == 0 ? */
|
||||
bt .hitzero /* yes, string end found */
|
||||
mov.b @r0+,r1 /* fetch second byte */
|
||||
mov #3,r2 /* prepare mask: r2 = 0..00000011b */
|
||||
tst r1,r1 /* byte == 0 ? */
|
||||
bt .hitzero /* yes, string end found */
|
||||
mov.b @r0+,r1 /* fetch third byte */
|
||||
not r2,r2 /* prepare mask: r2 = 1..11111100b */
|
||||
tst r1,r1 /* byte == 0 ? */
|
||||
bt .hitzero /* yes, string end found */
|
||||
|
||||
/* not yet found, fall through into longword loop */
|
||||
and r2,r0 /* align down to long bound */
|
||||
|
||||
/* main loop: check longwords */
|
||||
.start_l:
|
||||
mov #0,r2 /* zero longword for cmp/str */
|
||||
.loop_l:
|
||||
mov.l @r0+,r1 /* fetch long word */
|
||||
cmp/str r1,r2 /* any zero byte within? */
|
||||
bf .loop_l /* no, loop */
|
||||
add #-4,r0 /* set address back to start of this longword */
|
||||
|
||||
/* the last longword contains the string end: figure out the byte */
|
||||
mov.b @r0+,r1 /* fetch first byte */
|
||||
tst r1,r1 /* byte == 0 ? */
|
||||
bt .hitzero /* yes, string end found */
|
||||
mov.b @r0+,r1 /* fetch second byte */
|
||||
tst r1,r1 /* byte == 0 ? */
|
||||
bt .hitzero /* yes, string end found */
|
||||
mov.b @r0+,r1 /* fetch third byte */
|
||||
tst r1,r1 /* byte == 0 ? */
|
||||
bt .hitzero /* yes, string end found */
|
||||
rts /* must be the fourth byte */
|
||||
sub r4,r0 /* len = string_end - string_start */
|
||||
|
||||
.hitzero:
|
||||
add #-1,r0 /* undo address increment */
|
||||
rts
|
||||
sub r4,r0 /* len = string_end - string_start */
|
||||
|
||||
.end:
|
||||
.size _strlen,.end-_strlen
|
||||
|
Loading…
Reference in New Issue
Block a user