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