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