1/*
2 * strlen - calculate the length of a string
3 *
4 * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 * See https://llvm.org/LICENSE.txt for license information.
6 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 */
8
9#if __ARM_ARCH >= 6 && __ARM_ARCH_ISA_THUMB == 2
10
11/*
12 Assumes:
13 ARMv6T2, AArch32
14
15 */
16
17#include "../asmdefs.h"
18
19#ifdef __ARMEB__
20#define S2LO lsl
21#define S2HI lsr
22#else
23#define S2LO lsr
24#define S2HI lsl
25#endif
26
27 /* This code requires Thumb. */
28 .thumb
29 .syntax unified
30
31/* Parameters and result. */
32#define srcin r0
33#define result r0
34
35/* Internal variables. */
36#define src r1
37#define data1a r2
38#define data1b r3
39#define const_m1 r12
40#define const_0 r4
41#define tmp1 r4 /* Overlaps const_0 */
42#define tmp2 r5
43
44ENTRY (__strlen_armv6t2)
45 pld [srcin, #0]
46 strd r4, r5, [sp, #-8]!
47 bic src, srcin, #7
48 mvn const_m1, #0
49 ands tmp1, srcin, #7 /* (8 - bytes) to alignment. */
50 pld [src, #32]
51 bne.w L(misaligned8)
52 mov const_0, #0
53 mov result, #-8
54L(loop_aligned):
55 /* Bytes 0-7. */
56 ldrd data1a, data1b, [src]
57 pld [src, #64]
58 add result, result, #8
59L(start_realigned):
60 uadd8 data1a, data1a, const_m1 /* Saturating GE<0:3> set. */
61 sel data1a, const_0, const_m1 /* Select based on GE<0:3>. */
62 uadd8 data1b, data1b, const_m1
63 sel data1b, data1a, const_m1 /* Only used if d1a == 0. */
64 cbnz data1b, L(null_found)
65
66 /* Bytes 8-15. */
67 ldrd data1a, data1b, [src, #8]
68 uadd8 data1a, data1a, const_m1 /* Saturating GE<0:3> set. */
69 add result, result, #8
70 sel data1a, const_0, const_m1 /* Select based on GE<0:3>. */
71 uadd8 data1b, data1b, const_m1
72 sel data1b, data1a, const_m1 /* Only used if d1a == 0. */
73 cbnz data1b, L(null_found)
74
75 /* Bytes 16-23. */
76 ldrd data1a, data1b, [src, #16]
77 uadd8 data1a, data1a, const_m1 /* Saturating GE<0:3> set. */
78 add result, result, #8
79 sel data1a, const_0, const_m1 /* Select based on GE<0:3>. */
80 uadd8 data1b, data1b, const_m1
81 sel data1b, data1a, const_m1 /* Only used if d1a == 0. */
82 cbnz data1b, L(null_found)
83
84 /* Bytes 24-31. */
85 ldrd data1a, data1b, [src, #24]
86 add src, src, #32
87 uadd8 data1a, data1a, const_m1 /* Saturating GE<0:3> set. */
88 add result, result, #8
89 sel data1a, const_0, const_m1 /* Select based on GE<0:3>. */
90 uadd8 data1b, data1b, const_m1
91 sel data1b, data1a, const_m1 /* Only used if d1a == 0. */
92 cmp data1b, #0
93 beq L(loop_aligned)
94
95L(null_found):
96 cmp data1a, #0
97 itt eq
98 addeq result, result, #4
99 moveq data1a, data1b
100#ifndef __ARMEB__
101 rev data1a, data1a
102#endif
103 clz data1a, data1a
104 ldrd r4, r5, [sp], #8
105 add result, result, data1a, lsr #3 /* Bits -> Bytes. */
106 bx lr
107
108L(misaligned8):
109 ldrd data1a, data1b, [src]
110 and tmp2, tmp1, #3
111 rsb result, tmp1, #0
112 lsl tmp2, tmp2, #3 /* Bytes -> bits. */
113 tst tmp1, #4
114 pld [src, #64]
115 S2HI tmp2, const_m1, tmp2
116 orn data1a, data1a, tmp2
117 itt ne
118 ornne data1b, data1b, tmp2
119 movne data1a, const_m1
120 mov const_0, #0
121 b L(start_realigned)
122
123END (__strlen_armv6t2)
124
125#endif /* __ARM_ARCH >= 6 && __ARM_ARCH_ISA_THUMB == 2 */
126

source code of libc/AOR_v20.02/string/arm/strlen-armv6t2.S