Allow 'long' labels with single-argument %xd too. The label need to be at least 3...
[kugel-rb.git] / firmware / target / sh / strlen-sh.S
blobe7169e25db7397b1589192ebbfb15dda1afd7039
1 /***************************************************************************
2  *             __________               __   ___.
3  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7  *                     \/            \/     \/    \/            \/
8  * $Id$
9  *
10  * Copyright (C) 2005 by Jens Arnold
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18  * KIND, either express or implied.
19  *
20  ****************************************************************************/
21 #include "config.h"
23     .section    .icode,"ax",@progbits
25     .align      2
26     .global     _strlen
27     .type       _strlen,@function
29 /* Works out the length of a string
30  * This version is optimized for speed
31  *
32  * arguments:
33  *  r4 - start address
34  *
35  * return value:
36  *  r0 - string length
37  *
38  * register usage:
39  *  r0 - current address
40  *  r1 - current value (byte/long)
41  *  r2 - mask for alignment / zero (for cmp/str)
42  *  r4 - start address
43  *
44  */
46 _strlen:
47     mov     r4,r0       /* r0 = start address */
48     tst     #3,r0       /* long aligned? */
49     bt      .start_l    /* yes, jump directly to the longword loop */
51     /* not long aligned: check the first 3 bytes */
52     mov.b   @r0+,r1     /* fetch first byte */
53     tst     r1,r1       /* byte == 0 ? */
54     bt      .hitzero    /* yes, string end found */
55     mov.b   @r0+,r1     /* fetch second byte */
56     mov     #3,r2       /* prepare mask: r2 = 0..00000011b */
57     tst     r1,r1       /* byte == 0 ? */
58     bt      .hitzero    /* yes, string end found */
59     mov.b   @r0+,r1     /* fetch third byte */
60     not     r2,r2       /* prepare mask: r2 = 1..11111100b */
61     tst     r1,r1       /* byte == 0 ? */
62     bt      .hitzero    /* yes, string end found */
64     /* not yet found, fall through into longword loop */
65     and     r2,r0       /* align down to long bound */
67     /* main loop: check longwords */
68 .start_l:
69     mov     #0,r2       /* zero longword for cmp/str */
70 .loop_l:
71     mov.l   @r0+,r1     /* fetch long word */
72     cmp/str r1,r2       /* any zero byte within? */
73     bf      .loop_l     /* no, loop */
74     add     #-4,r0      /* set address back to start of this longword */
76     /* the last longword contains the string end: figure out the byte */
77     mov.b   @r0+,r1     /* fetch first byte */    
78     tst     r1,r1       /* byte == 0 ? */
79     bt      .hitzero    /* yes, string end found */
80     mov.b   @r0+,r1     /* fetch second byte */
81     tst     r1,r1       /* byte == 0 ? */
82     bt      .hitzero    /* yes, string end found */
83     mov.b   @r0+,r1     /* fetch third byte */
84     tst     r1,r1       /* byte == 0 ? */
85     bt      .hitzero    /* yes, string end found */
86     rts                 /* must be the fourth byte */
87     sub     r4,r0       /* len = string_end - string_start */
89 .hitzero:
90     add     #-1,r0      /* undo address increment */
91     rts
92     sub     r4,r0       /* len = string_end - string_start */
94 .end:
95     .size   _strlen,.end-_strlen