rockbox/firmware/target/sh/strlen-sh.S
Daniel Stenberg 2acc0ac542 Updated our source code header to explicitly mention that we are GPL v2 or
later. We still need to hunt down snippets used that are not. 1324 modified
files...
http://www.rockbox.org/mail/archive/rockbox-dev-archive-2008-06/0060.shtml


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17847 a1c6a512-1295-4272-9138-f99709370657
2008-06-28 18:10:04 +00:00

96 lines
3.3 KiB
ArmAsm

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2005 by Jens Arnold
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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