1/* SPDX-License-Identifier: GPL-2.0-only */ 2 3#include <linux/linkage.h> 4#include <asm/asm.h> 5#include <asm/alternative-macros.h> 6#include <asm/hwcap.h> 7 8/* int strlen(const char *s) */ 9SYM_FUNC_START(strlen) 10 11 __ALTERNATIVE_CFG("nop", "j strlen_zbb", 0, RISCV_ISA_EXT_ZBB, 12 IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB)) 13 14 /* 15 * Returns 16 * a0 - string length 17 * 18 * Parameters 19 * a0 - String to measure 20 * 21 * Clobbers: 22 * t0, t1 23 */ 24 addi t1, a0, -1 251: 26 addi t1, t1, 1 27 lbu t0, 0(t1) 28 bnez t0, 1b 29 sub a0, t1, a0 30 ret 31 32/* 33 * Variant of strlen using the ZBB extension if available 34 */ 35#if defined(CONFIG_RISCV_ISA_ZBB) && defined(CONFIG_TOOLCHAIN_HAS_ZBB) 36strlen_zbb: 37 38#ifdef CONFIG_CPU_BIG_ENDIAN 39# define CZ clz 40# define SHIFT sll 41#else 42# define CZ ctz 43# define SHIFT srl 44#endif 45 46.option push 47.option arch,+zbb 48 49 /* 50 * Returns 51 * a0 - string length 52 * 53 * Parameters 54 * a0 - String to measure 55 * 56 * Clobbers 57 * t0, t1, t2, t3 58 */ 59 60 /* Number of irrelevant bytes in the first word. */ 61 andi t2, a0, SZREG-1 62 63 /* Align pointer. */ 64 andi t0, a0, -SZREG 65 66 li t3, SZREG 67 sub t3, t3, t2 68 slli t2, t2, 3 69 70 /* Get the first word. */ 71 REG_L t1, 0(t0) 72 73 /* 74 * Shift away the partial data we loaded to remove the irrelevant bytes 75 * preceding the string with the effect of adding NUL bytes at the 76 * end of the string's first word. 77 */ 78 SHIFT t1, t1, t2 79 80 /* Convert non-NUL into 0xff and NUL into 0x00. */ 81 orc.b t1, t1 82 83 /* Convert non-NUL into 0x00 and NUL into 0xff. */ 84 not t1, t1 85 86 /* 87 * Search for the first set bit (corresponding to a NUL byte in the 88 * original chunk). 89 */ 90 CZ t1, t1 91 92 /* 93 * The first chunk is special: compare against the number 94 * of valid bytes in this chunk. 95 */ 96 srli a0, t1, 3 97 bgtu t3, a0, 2f 98 99 /* Prepare for the word comparison loop. */ 100 addi t2, t0, SZREG 101 li t3, -1 102 103 /* 104 * Our critical loop is 4 instructions and processes data in 105 * 4 byte or 8 byte chunks. 106 */ 107 .p2align 3 1081: 109 REG_L t1, SZREG(t0) 110 addi t0, t0, SZREG 111 orc.b t1, t1 112 beq t1, t3, 1b 113 114 not t1, t1 115 CZ t1, t1 116 srli t1, t1, 3 117 118 /* Get number of processed bytes. */ 119 sub t2, t0, t2 120 121 /* Add number of characters in the first word. */ 122 add a0, a0, t2 123 124 /* Add number of characters in the last word. */ 125 add a0, a0, t1 1262: 127 ret 128 129.option pop 130#endif 131SYM_FUNC_END(strlen) 132SYM_FUNC_ALIAS(__pi_strlen, strlen) 133EXPORT_SYMBOL(strlen) 134