1 /* SPDX-License-Identifier: GPL-2.0-only */ !! 1 /* SPDX-License-Identifier: GPL-2.0 */ >> 2 /* strlen.S: Sparc optimized strlen code >> 3 * Hand optimized from GNU libc's strlen >> 4 * Copyright (C) 1991,1996 Free Software Foundation >> 5 * Copyright (C) 1996,2008 David S. Miller (davem@davemloft.net) >> 6 * Copyright (C) 1996, 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) >> 7 */ 2 8 >> 9 #include <linux/export.h> 3 #include <linux/linkage.h> 10 #include <linux/linkage.h> 4 #include <asm/asm.h> 11 #include <asm/asm.h> 5 #include <asm/alternative-macros.h> << 6 #include <asm/hwcap.h> << 7 << 8 /* int strlen(const char *s) */ << 9 SYM_FUNC_START(strlen) << 10 12 11 ALTERNATIVE("nop", "j strlen_zbb", 0, !! 13 #define LO_MAGIC 0x01010101 >> 14 #define HI_MAGIC 0x80808080 12 15 13 /* !! 16 .text 14 * Returns !! 17 ENTRY(strlen) 15 * a0 - string length !! 18 mov %o0, %o1 16 * !! 19 andcc %o0, 3, %g0 17 * Parameters !! 20 BRANCH32(be, pt, 9f) 18 * a0 - String to measure !! 21 sethi %hi(HI_MAGIC), %o4 19 * !! 22 ldub [%o0], %o5 20 * Clobbers: !! 23 BRANCH_REG_ZERO(pn, %o5, 11f) 21 * t0, t1 !! 24 add %o0, 1, %o0 22 */ !! 25 andcc %o0, 3, %g0 23 mv t1, a0 !! 26 BRANCH32(be, pn, 4f) 24 1: !! 27 or %o4, %lo(HI_MAGIC), %o3 25 lbu t0, 0(t1) !! 28 ldub [%o0], %o5 26 beqz t0, 2f !! 29 BRANCH_REG_ZERO(pn, %o5, 12f) 27 addi t1, t1, 1 !! 30 add %o0, 1, %o0 28 j 1b !! 31 andcc %o0, 3, %g0 >> 32 BRANCH32(be, pt, 5f) >> 33 sethi %hi(LO_MAGIC), %o4 >> 34 ldub [%o0], %o5 >> 35 BRANCH_REG_ZERO(pn, %o5, 13f) >> 36 add %o0, 1, %o0 >> 37 BRANCH32(ba, pt, 8f) >> 38 or %o4, %lo(LO_MAGIC), %o2 >> 39 9: >> 40 or %o4, %lo(HI_MAGIC), %o3 >> 41 4: >> 42 sethi %hi(LO_MAGIC), %o4 >> 43 5: >> 44 or %o4, %lo(LO_MAGIC), %o2 >> 45 8: >> 46 ld [%o0], %o5 29 2: 47 2: 30 sub a0, t1, a0 !! 48 sub %o5, %o2, %o4 31 ret !! 49 andcc %o4, %o3, %g0 32 !! 50 BRANCH32(be, pt, 8b) 33 /* !! 51 add %o0, 4, %o0 34 * Variant of strlen using the ZBB extension i !! 52 35 */ !! 53 /* Check every byte. */ 36 #ifdef CONFIG_RISCV_ISA_ZBB !! 54 srl %o5, 24, %g7 37 strlen_zbb: !! 55 andcc %g7, 0xff, %g0 38 !! 56 BRANCH32(be, pn, 1f) 39 #ifdef CONFIG_CPU_BIG_ENDIAN !! 57 add %o0, -4, %o4 40 # define CZ clz !! 58 srl %o5, 16, %g7 41 # define SHIFT sll !! 59 andcc %g7, 0xff, %g0 42 #else !! 60 BRANCH32(be, pn, 1f) 43 # define CZ ctz !! 61 add %o4, 1, %o4 44 # define SHIFT srl !! 62 srl %o5, 8, %g7 45 #endif !! 63 andcc %g7, 0xff, %g0 46 !! 64 BRANCH32(be, pn, 1f) 47 .option push !! 65 add %o4, 1, %o4 48 .option arch,+zbb !! 66 andcc %o5, 0xff, %g0 49 !! 67 BRANCH32_ANNUL(bne, pt, 2b) 50 /* !! 68 ld [%o0], %o5 51 * Returns !! 69 add %o4, 1, %o4 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 f << 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 load << 76 * preceding the string with the effec << 77 * end of the string's first word. << 78 */ << 79 SHIFT t1, t1, t2 << 80 << 81 /* Convert non-NUL into 0xff and NUL i << 82 orc.b t1, t1 << 83 << 84 /* Convert non-NUL into 0x00 and NUL i << 85 not t1, t1 << 86 << 87 /* << 88 * Search for the first set bit (corre << 89 * original chunk). << 90 */ << 91 CZ t1, t1 << 92 << 93 /* << 94 * The first chunk is special: compare << 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 loo << 101 addi t2, t0, SZREG << 102 li t3, -1 << 103 << 104 /* << 105 * Our critical loop is 4 instructions << 106 * 4 byte or 8 byte chunks. << 107 */ << 108 .p2align 3 << 109 1: 70 1: 110 REG_L t1, SZREG(t0) !! 71 retl 111 addi t0, t0, SZREG !! 72 sub %o4, %o1, %o0 112 orc.b t1, t1 !! 73 11: 113 beq t1, t3, 1b !! 74 retl 114 !! 75 mov 0, %o0 115 not t1, t1 !! 76 12: 116 CZ t1, t1 !! 77 retl 117 srli t1, t1, 3 !! 78 mov 1, %o0 118 !! 79 13: 119 /* Get number of processed bytes. */ !! 80 retl 120 sub t2, t0, t2 !! 81 mov 2, %o0 121 !! 82 ENDPROC(strlen) 122 /* Add number of characters in the fir << 123 add a0, a0, t2 << 124 << 125 /* Add number of characters in the las << 126 add a0, a0, t1 << 127 2: << 128 ret << 129 << 130 .option pop << 131 #endif << 132 SYM_FUNC_END(strlen) << 133 SYM_FUNC_ALIAS(__pi_strlen, strlen) << 134 EXPORT_SYMBOL(strlen) 83 EXPORT_SYMBOL(strlen)
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.