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