1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Taken from Linux arch/riscv/lib/strlen.S 4 */ 5 6#include <linux/linkage.h> 7#include <asm/asm.h> 8 9#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 10# define CZ ctz 11# define SHIFT srl 12#else 13# define CZ clz 14# define SHIFT sll 15#endif 16 17ENTRY(__strlen) 18WEAK(strlen) 19.option push 20.option arch,+zbb 21 /* 22 * Returns 23 * a0 - string length 24 * 25 * Parameters 26 * a0 - String to measure 27 * 28 * Clobbers 29 * t0, t1, t2, t3 30 */ 31 32 /* Number of irrelevant bytes in the first word. */ 33 andi t2, a0, SZREG-1 34 35 /* Align pointer. */ 36 andi t0, a0, -SZREG 37 38 li t3, SZREG 39 sub t3, t3, t2 40 slli t2, t2, 3 41 42 /* Get the first word. */ 43 REG_L t1, 0(t0) 44 45 /* 46 * Shift away the partial data we loaded to remove the irrelevant bytes 47 * preceding the string with the effect of adding NUL bytes at the 48 * end of the string's first word. 49 */ 50 SHIFT t1, t1, t2 51 52 /* Convert non-NUL into 0xff and NUL into 0x00. */ 53 orc.b t1, t1 54 55 /* Convert non-NUL into 0x00 and NUL into 0xff. */ 56 not t1, t1 57 58 /* 59 * Search for the first set bit (corresponding to a NUL byte in the 60 * original chunk). 61 */ 62 CZ t1, t1 63 64 /* 65 * The first chunk is special: compare against the number 66 * of valid bytes in this chunk. 67 */ 68 srli a0, t1, 3 69 bgtu t3, a0, 2f 70 71 /* Prepare for the word comparison loop. */ 72 addi t2, t0, SZREG 73 li t3, -1 74 75 /* 76 * Our critical loop is 4 instructions and processes data in 77 * 4 byte or 8 byte chunks. 78 */ 79 .p2align 3 801: 81 REG_L t1, SZREG(t0) 82 addi t0, t0, SZREG 83 orc.b t1, t1 84 beq t1, t3, 1b 85 86 not t1, t1 87 CZ t1, t1 88 srli t1, t1, 3 89 90 /* Get number of processed bytes. */ 91 sub t2, t0, t2 92 93 /* Add number of characters in the first word. */ 94 add a0, a0, t2 95 96 /* Add number of characters in the last word. */ 97 add a0, a0, t1 982: 99 ret 100.option pop 101END(__strlen) 102