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