Cygwin: Add new APIs tc[gs]etwinsize()
[newlib-cygwin.git] / newlib / libc / machine / xtensa / strlen.S
blob6560a3185d307762c3d2c937dde4d601366e6773
1 /* ANSI C standard library function strlen.
3    Copyright (c) 2001-2008 Tensilica Inc.
5    Permission is hereby granted, free of charge, to any person obtaining
6    a copy of this software and associated documentation files (the
7    "Software"), to deal in the Software without restriction, including
8    without limitation the rights to use, copy, modify, merge, publish,
9    distribute, sublicense, and/or sell copies of the Software, and to
10    permit persons to whom the Software is furnished to do so, subject to
11    the following conditions:
13    The above copyright notice and this permission notice shall be included
14    in all copies or substantial portions of the Software.
16    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
24 #include "xtensa-asm.h"
26         .text
27         .begin schedule
28         .align  4
29         .literal_position
30         .global strlen
31         .type   strlen, @function
32 strlen:
33         leaf_entry sp, 16
34         /* a2 = s */
36         addi    a3, a2, -4      // because we overincrement at the end
37         movi    a4, MASK0
38         movi    a5, MASK1
39         movi    a6, MASK2
40         movi    a7, MASK3
41         bbsi.l  a2, 0, .L1mod2
42         bbsi.l  a2, 1, .L2mod4
43         j       .Laligned
45 .L1mod2: // address is odd
46         l8ui    a8, a3, 4       // get byte 0
47         addi    a3, a3, 1       // advance string pointer
48         beqz    a8, .Lz3        // if byte 0 is zero
49         bbci.l  a3, 1, .Laligned // if string pointer is now word-aligned
51 .L2mod4: // address is 2 mod 4
52         addi    a3, a3, 2       // advance ptr for aligned access
53         l32i    a8, a3, 0       // get word with first two bytes of string
54         bnone   a8, a6, .Lz2    // if byte 2 (of word, not string) is zero
55         bany    a8, a7, .Laligned // if byte 3 (of word, not string) is nonzero
57         /* Byte 3 is zero.  */
58         addi    a3, a3, 3       // point to zero byte
59         sub     a2, a3, a2      // subtract to get length
60         leaf_return
63 /* String is word-aligned.  */
65         .align  4
66 #if XCHAL_HAVE_LOOPS
67 #if XCHAL_HAVE_DENSITY
68         /* (2 mod 4) alignment for loop instruction */
69 #else
70         /* (1 mod 4) alignment for loop instruction */
71         .byte   0
72         .byte   0
73 #endif
74 #endif
75 .Laligned:
76 #if XCHAL_HAVE_LOOPS
77 #if XCHAL_HAVE_DENSITY
78         _movi.n a8, 0           // set up for the maximum loop count
79 #else
80         _movi   a8, 0           // set up for the maximum loop count
81 #endif
82         loop    a8, .Lz3        // loop forever (almost anyway)
83 #endif
84 1:      l32i    a8, a3, 4       // get next word of string
85         addi    a3, a3, 4       // advance string pointer
86         bnone   a8, a4, .Lz0    // if byte 0 is zero
87         bnone   a8, a5, .Lz1    // if byte 1 is zero
88         bnone   a8, a6, .Lz2    // if byte 2 is zero
89 #if XCHAL_HAVE_LOOPS
90         bnone   a8, a7, .Lz3    // if byte 3 is zero
91 #else
92         bany    a8, a7, 1b      // repeat if byte 3 is non-zero
93 #endif
95 .Lz3:   /* Byte 3 is zero.  */
96         addi    a3, a3, 3       // point to zero byte
97         /* Fall through....  */
99 .Lz0:   /* Byte 0 is zero.  */
100         sub     a2, a3, a2      // subtract to get length
101         leaf_return
103 .Lz1:   /* Byte 1 is zero.  */
104         addi    a3, a3, 1       // point to zero byte
105         sub     a2, a3, a2      // subtract to get length
106         leaf_return
108 .Lz2:   /* Byte 2 is zero.  */
109         addi    a3, a3, 2       // point to zero byte
110         sub     a2, a3, a2      // subtract to get length
111         leaf_return
113         .end schedule
115         .size   strlen, . - strlen