156e0790cSHeiko Stuebner/* SPDX-License-Identifier: GPL-2.0-only */ 256e0790cSHeiko Stuebner 356e0790cSHeiko Stuebner#include <linux/linkage.h> 456e0790cSHeiko Stuebner#include <asm/asm.h> 5b6fcdb19SHeiko Stuebner#include <asm/alternative-macros.h> 628ea374dSAndrew Jones#include <asm/hwcap.h> 756e0790cSHeiko Stuebner 856e0790cSHeiko Stuebner/* int strlen(const char *s) */ 956e0790cSHeiko StuebnerSYM_FUNC_START(strlen) 10b6fcdb19SHeiko Stuebner 11d5a7fab7SSamuel Holland ALTERNATIVE("nop", "j strlen_zbb", 0, RISCV_ISA_EXT_ZBB, CONFIG_RISCV_ISA_ZBB) 12b6fcdb19SHeiko Stuebner 1356e0790cSHeiko Stuebner /* 1456e0790cSHeiko Stuebner * Returns 1556e0790cSHeiko Stuebner * a0 - string length 1656e0790cSHeiko Stuebner * 1756e0790cSHeiko Stuebner * Parameters 1856e0790cSHeiko Stuebner * a0 - String to measure 1956e0790cSHeiko Stuebner * 2056e0790cSHeiko Stuebner * Clobbers: 2156e0790cSHeiko Stuebner * t0, t1 2256e0790cSHeiko Stuebner */ 2356e0790cSHeiko Stuebner mv t1, a0 2456e0790cSHeiko Stuebner1: 2556e0790cSHeiko Stuebner lbu t0, 0(t1) 2656e0790cSHeiko Stuebner beqz t0, 2f 2756e0790cSHeiko Stuebner addi t1, t1, 1 2856e0790cSHeiko Stuebner j 1b 2956e0790cSHeiko Stuebner2: 3056e0790cSHeiko Stuebner sub a0, t1, a0 3156e0790cSHeiko Stuebner ret 32b6fcdb19SHeiko Stuebner 33b6fcdb19SHeiko Stuebner/* 34b6fcdb19SHeiko Stuebner * Variant of strlen using the ZBB extension if available 35b6fcdb19SHeiko Stuebner */ 36b6fcdb19SHeiko Stuebner#ifdef CONFIG_RISCV_ISA_ZBB 37b6fcdb19SHeiko Stuebnerstrlen_zbb: 38b6fcdb19SHeiko Stuebner 39b6fcdb19SHeiko Stuebner#ifdef CONFIG_CPU_BIG_ENDIAN 40b6fcdb19SHeiko Stuebner# define CZ clz 41b6fcdb19SHeiko Stuebner# define SHIFT sll 42b6fcdb19SHeiko Stuebner#else 43b6fcdb19SHeiko Stuebner# define CZ ctz 44b6fcdb19SHeiko Stuebner# define SHIFT srl 45b6fcdb19SHeiko Stuebner#endif 46b6fcdb19SHeiko Stuebner 47b6fcdb19SHeiko Stuebner.option push 48b6fcdb19SHeiko Stuebner.option arch,+zbb 49b6fcdb19SHeiko Stuebner 50b6fcdb19SHeiko Stuebner /* 51b6fcdb19SHeiko Stuebner * Returns 52b6fcdb19SHeiko Stuebner * a0 - string length 53b6fcdb19SHeiko Stuebner * 54b6fcdb19SHeiko Stuebner * Parameters 55b6fcdb19SHeiko Stuebner * a0 - String to measure 56b6fcdb19SHeiko Stuebner * 57b6fcdb19SHeiko Stuebner * Clobbers 58b6fcdb19SHeiko Stuebner * t0, t1, t2, t3 59b6fcdb19SHeiko Stuebner */ 60b6fcdb19SHeiko Stuebner 61b6fcdb19SHeiko Stuebner /* Number of irrelevant bytes in the first word. */ 62b6fcdb19SHeiko Stuebner andi t2, a0, SZREG-1 63b6fcdb19SHeiko Stuebner 64b6fcdb19SHeiko Stuebner /* Align pointer. */ 65b6fcdb19SHeiko Stuebner andi t0, a0, -SZREG 66b6fcdb19SHeiko Stuebner 67b6fcdb19SHeiko Stuebner li t3, SZREG 68b6fcdb19SHeiko Stuebner sub t3, t3, t2 69b6fcdb19SHeiko Stuebner slli t2, t2, 3 70b6fcdb19SHeiko Stuebner 71b6fcdb19SHeiko Stuebner /* Get the first word. */ 72b6fcdb19SHeiko Stuebner REG_L t1, 0(t0) 73b6fcdb19SHeiko Stuebner 74b6fcdb19SHeiko Stuebner /* 75b6fcdb19SHeiko Stuebner * Shift away the partial data we loaded to remove the irrelevant bytes 76b6fcdb19SHeiko Stuebner * preceding the string with the effect of adding NUL bytes at the 77b6fcdb19SHeiko Stuebner * end of the string's first word. 78b6fcdb19SHeiko Stuebner */ 79b6fcdb19SHeiko Stuebner SHIFT t1, t1, t2 80b6fcdb19SHeiko Stuebner 81b6fcdb19SHeiko Stuebner /* Convert non-NUL into 0xff and NUL into 0x00. */ 82b6fcdb19SHeiko Stuebner orc.b t1, t1 83b6fcdb19SHeiko Stuebner 84b6fcdb19SHeiko Stuebner /* Convert non-NUL into 0x00 and NUL into 0xff. */ 85b6fcdb19SHeiko Stuebner not t1, t1 86b6fcdb19SHeiko Stuebner 87b6fcdb19SHeiko Stuebner /* 88b6fcdb19SHeiko Stuebner * Search for the first set bit (corresponding to a NUL byte in the 89b6fcdb19SHeiko Stuebner * original chunk). 90b6fcdb19SHeiko Stuebner */ 91b6fcdb19SHeiko Stuebner CZ t1, t1 92b6fcdb19SHeiko Stuebner 93b6fcdb19SHeiko Stuebner /* 94b6fcdb19SHeiko Stuebner * The first chunk is special: compare against the number 95b6fcdb19SHeiko Stuebner * of valid bytes in this chunk. 96b6fcdb19SHeiko Stuebner */ 97b6fcdb19SHeiko Stuebner srli a0, t1, 3 986934cf8aSHeiko Stuebner bgtu t3, a0, 2f 99b6fcdb19SHeiko Stuebner 100b6fcdb19SHeiko Stuebner /* Prepare for the word comparison loop. */ 101b6fcdb19SHeiko Stuebner addi t2, t0, SZREG 102b6fcdb19SHeiko Stuebner li t3, -1 103b6fcdb19SHeiko Stuebner 104b6fcdb19SHeiko Stuebner /* 105b6fcdb19SHeiko Stuebner * Our critical loop is 4 instructions and processes data in 106b6fcdb19SHeiko Stuebner * 4 byte or 8 byte chunks. 107b6fcdb19SHeiko Stuebner */ 108b6fcdb19SHeiko Stuebner .p2align 3 109b6fcdb19SHeiko Stuebner1: 110b6fcdb19SHeiko Stuebner REG_L t1, SZREG(t0) 111b6fcdb19SHeiko Stuebner addi t0, t0, SZREG 112b6fcdb19SHeiko Stuebner orc.b t1, t1 113b6fcdb19SHeiko Stuebner beq t1, t3, 1b 1146934cf8aSHeiko Stuebner 115b6fcdb19SHeiko Stuebner not t1, t1 116b6fcdb19SHeiko Stuebner CZ t1, t1 1176934cf8aSHeiko Stuebner srli t1, t1, 3 118b6fcdb19SHeiko Stuebner 1196934cf8aSHeiko Stuebner /* Get number of processed bytes. */ 120b6fcdb19SHeiko Stuebner sub t2, t0, t2 121b6fcdb19SHeiko Stuebner 122b6fcdb19SHeiko Stuebner /* Add number of characters in the first word. */ 123b6fcdb19SHeiko Stuebner add a0, a0, t2 124b6fcdb19SHeiko Stuebner 125b6fcdb19SHeiko Stuebner /* Add number of characters in the last word. */ 126b6fcdb19SHeiko Stuebner add a0, a0, t1 1276934cf8aSHeiko Stuebner2: 128b6fcdb19SHeiko Stuebner ret 129b6fcdb19SHeiko Stuebner 130b6fcdb19SHeiko Stuebner.option pop 131b6fcdb19SHeiko Stuebner#endif 13256e0790cSHeiko StuebnerSYM_FUNC_END(strlen) 133*26e7aacbSAlexandre GhitiSYM_FUNC_ALIAS(__pi_strlen, strlen) 134