/* SPDX-License-Identifier: GPL-2.0-only */12#include <linux/linkage.h>3#include <asm/asm.h>4#include <asm/alternative-macros.h>5#include <asm/hwcap.h>67/* int strlen(const char *s) */8SYM_FUNC_START(strlen)910__ALTERNATIVE_CFG("nop", "j strlen_zbb", 0, RISCV_ISA_EXT_ZBB,11IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB))1213/*14* Returns15* a0 - string length16*17* Parameters18* a0 - String to measure19*20* Clobbers:21* t0, t122*/23mv t1, a0241:25lbu t0, 0(t1)26beqz t0, 2f27addi t1, t1, 128j 1b292:30sub a0, t1, a031ret3233/*34* Variant of strlen using the ZBB extension if available35*/36#if defined(CONFIG_RISCV_ISA_ZBB) && defined(CONFIG_TOOLCHAIN_HAS_ZBB)37strlen_zbb:3839#ifdef CONFIG_CPU_BIG_ENDIAN40# define CZ clz41# define SHIFT sll42#else43# define CZ ctz44# define SHIFT srl45#endif4647.option push48.option arch,+zbb4950/*51* Returns52* a0 - string length53*54* Parameters55* a0 - String to measure56*57* Clobbers58* t0, t1, t2, t359*/6061/* Number of irrelevant bytes in the first word. */62andi t2, a0, SZREG-16364/* Align pointer. */65andi t0, a0, -SZREG6667li t3, SZREG68sub t3, t3, t269slli t2, t2, 37071/* Get the first word. */72REG_L t1, 0(t0)7374/*75* Shift away the partial data we loaded to remove the irrelevant bytes76* preceding the string with the effect of adding NUL bytes at the77* end of the string's first word.78*/79SHIFT t1, t1, t28081/* Convert non-NUL into 0xff and NUL into 0x00. */82orc.b t1, t18384/* Convert non-NUL into 0x00 and NUL into 0xff. */85not t1, t18687/*88* Search for the first set bit (corresponding to a NUL byte in the89* original chunk).90*/91CZ t1, t19293/*94* The first chunk is special: compare against the number95* of valid bytes in this chunk.96*/97srli a0, t1, 398bgtu t3, a0, 2f99100/* Prepare for the word comparison loop. */101addi t2, t0, SZREG102li t3, -1103104/*105* Our critical loop is 4 instructions and processes data in106* 4 byte or 8 byte chunks.107*/108.p2align 31091:110REG_L t1, SZREG(t0)111addi t0, t0, SZREG112orc.b t1, t1113beq t1, t3, 1b114115not t1, t1116CZ t1, t1117srli t1, t1, 3118119/* Get number of processed bytes. */120sub t2, t0, t2121122/* Add number of characters in the first word. */123add a0, a0, t2124125/* Add number of characters in the last word. */126add a0, a0, t11272:128ret129130.option pop131#endif132SYM_FUNC_END(strlen)133SYM_FUNC_ALIAS(__pi_strlen, strlen)134EXPORT_SYMBOL(strlen)135136137