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