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:
Jens Arnold 2005-01-22 13:18:33 +00:00
parent 0310f16005
commit 78826de045
3 changed files with 103 additions and 1 deletions

View File

@ -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

View File

@ -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
View 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