Revert "Replace yield_codec() with a call to queue_wait_w_tmo()" and the related...
[Rockbox.git] / firmware / target / sh / strlen-sh.S
blob34837605ac97b5aedd26eaf4c7b8643eb656971e
1 /***************************************************************************
2  *             __________               __   ___.
3  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7  *                     \/            \/     \/    \/            \/
8  * $Id$
9  *
10  * Copyright (C) 2005 by Jens Arnold
11  *
12  * All files in this archive are subject to the GNU General Public License.
13  * See the file COPYING in the source tree root for full license agreement.
14  *
15  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16  * KIND, either express or implied.
17  *
18  ****************************************************************************/
19 #include "config.h"
21     .section    .icode,"ax",@progbits
23     .align      2
24     .global     _strlen
25     .type       _strlen,@function
27 /* Works out the length of a string
28  * This version is optimized for speed
29  *
30  * arguments:
31  *  r4 - start address
32  *
33  * return value:
34  *  r0 - string length
35  *
36  * register usage:
37  *  r0 - current address
38  *  r1 - current value (byte/long)
39  *  r2 - mask for alignment / zero (for cmp/str)
40  *  r4 - start address
41  *
42  */
44 _strlen:
45     mov     r4,r0       /* r0 = start address */
46     tst     #3,r0       /* long aligned? */
47     bt      .start_l    /* yes, jump directly to the longword loop */
49     /* not long aligned: check the first 3 bytes */
50     mov.b   @r0+,r1     /* fetch first byte */
51     tst     r1,r1       /* byte == 0 ? */
52     bt      .hitzero    /* yes, string end found */
53     mov.b   @r0+,r1     /* fetch second byte */
54     mov     #3,r2       /* prepare mask: r2 = 0..00000011b */
55     tst     r1,r1       /* byte == 0 ? */
56     bt      .hitzero    /* yes, string end found */
57     mov.b   @r0+,r1     /* fetch third byte */
58     not     r2,r2       /* prepare mask: r2 = 1..11111100b */
59     tst     r1,r1       /* byte == 0 ? */
60     bt      .hitzero    /* yes, string end found */
62     /* not yet found, fall through into longword loop */
63     and     r2,r0       /* align down to long bound */
65     /* main loop: check longwords */
66 .start_l:
67     mov     #0,r2       /* zero longword for cmp/str */
68 .loop_l:
69     mov.l   @r0+,r1     /* fetch long word */
70     cmp/str r1,r2       /* any zero byte within? */
71     bf      .loop_l     /* no, loop */
72     add     #-4,r0      /* set address back to start of this longword */
74     /* the last longword contains the string end: figure out the byte */
75     mov.b   @r0+,r1     /* fetch first byte */    
76     tst     r1,r1       /* byte == 0 ? */
77     bt      .hitzero    /* yes, string end found */
78     mov.b   @r0+,r1     /* fetch second byte */
79     tst     r1,r1       /* byte == 0 ? */
80     bt      .hitzero    /* yes, string end found */
81     mov.b   @r0+,r1     /* fetch third byte */
82     tst     r1,r1       /* byte == 0 ? */
83     bt      .hitzero    /* yes, string end found */
84     rts                 /* must be the fourth byte */
85     sub     r4,r0       /* len = string_end - string_start */
87 .hitzero:
88     add     #-1,r0      /* undo address increment */
89     rts
90     sub     r4,r0       /* len = string_end - string_start */
92 .end:
93     .size   _strlen,.end-_strlen