1 /* SPDX-License-Identifier: GPL-2.0-only */ !! 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 2 /* 3 * Copyright (C) 2004, 2007-2010, 2011-2012 Sy !! 3 * strlen.S (c) 1995 David Mosberger (davidm@cs.arizona.edu) >> 4 * >> 5 * Finds length of a 0-terminated string. Optimized for the >> 6 * Alpha architecture: >> 7 * >> 8 * - memory accessed as aligned quadwords only >> 9 * - uses bcmpge to compare 8 bytes in parallel >> 10 * - does binary search to find 0 byte in last >> 11 * quadword (HAKMEM needed 12 instructions to >> 12 * do this instead of the 9 instructions that >> 13 * binary search needs). 4 */ 14 */ >> 15 #include <linux/export.h> >> 16 .set noreorder >> 17 .set noat 5 18 6 #include <linux/linkage.h> !! 19 .align 3 7 20 8 ENTRY_CFI(strlen) !! 21 .globl strlen 9 or r3,r0,7 !! 22 .ent strlen 10 ld r2,[r3,-7] !! 23 11 ld.a r6,[r3,-3] !! 24 strlen: 12 mov r4,0x01010101 !! 25 ldq_u $1, 0($16) # load first quadword ($16 may be misaligned) 13 ; uses long immediate !! 26 lda $2, -1($31) 14 #ifdef __LITTLE_ENDIAN__ !! 27 insqh $2, $16, $2 15 asl_s r1,r0,3 !! 28 andnot $16, 7, $0 16 btst_s r0,2 !! 29 or $2, $1, $1 17 asl r7,r4,r1 !! 30 cmpbge $31, $1, $2 # $2 <- bitmask: bit i == 1 <==> i-th byte == 0 18 ror r5,r4 !! 31 bne $2, found 19 sub r1,r2,r7 !! 32 20 bic_s r1,r1,r2 !! 33 loop: ldq $1, 8($0) 21 mov.eq r7,r4 !! 34 addq $0, 8, $0 # addr += 8 22 sub r12,r6,r7 !! 35 nop # helps dual issue last two insns 23 bic r12,r12,r6 !! 36 cmpbge $31, $1, $2 24 or.eq r12,r12,r1 !! 37 beq $2, loop 25 and r12,r12,r5 !! 38 26 brne r12,0,.Learly_end !! 39 found: blbs $2, done # make aligned case fast 27 #else /* BIG ENDIAN */ !! 40 negq $2, $3 28 ror r5,r4 !! 41 and $2, $3, $2 29 btst_s r0,2 !! 42 30 mov_s r1,31 !! 43 and $2, 0x0f, $1 31 sub3 r7,r1,r0 !! 44 addq $0, 4, $3 32 sub r1,r2,r4 !! 45 cmoveq $1, $3, $0 33 bic_s r1,r1,r2 !! 46 34 bmsk r1,r1,r7 !! 47 and $2, 0x33, $1 35 sub r12,r6,r4 !! 48 addq $0, 2, $3 36 bic r12,r12,r6 !! 49 cmoveq $1, $3, $0 37 bmsk.ne r12,r12,r7 !! 50 38 or.eq r12,r12,r1 !! 51 and $2, 0x55, $1 39 and r12,r12,r5 !! 52 addq $0, 1, $3 40 brne r12,0,.Learly_end !! 53 cmoveq $1, $3, $0 41 #endif /* ENDIAN */ !! 54 42 !! 55 done: subq $0, $16, $0 43 .Loop: !! 56 ret $31, ($26) 44 ld_s r2,[r3,4] !! 57 45 ld.a r6,[r3,8] !! 58 .end strlen 46 ; stall for load result !! 59 EXPORT_SYMBOL(strlen) 47 sub r1,r2,r4 << 48 bic_s r1,r1,r2 << 49 sub r12,r6,r4 << 50 bic r12,r12,r6 << 51 or r12,r12,r1 << 52 and r12,r12,r5 << 53 breq r12,0,.Loop << 54 .Lend: << 55 and.f r1,r1,r5 << 56 sub.ne r3,r3,4 << 57 mov.eq r1,r12 << 58 #ifdef __LITTLE_ENDIAN__ << 59 sub_s r2,r1,1 << 60 bic_s r2,r2,r1 << 61 norm r1,r2 << 62 sub_s r0,r0,3 << 63 lsr_s r1,r1,3 << 64 sub r0,r3,r0 << 65 j_s.d [blink] << 66 sub r0,r0,r1 << 67 #else /* BIG ENDIAN */ << 68 lsr_s r1,r1,7 << 69 mov.eq r2,r6 << 70 bic_s r1,r1,r2 << 71 norm r1,r1 << 72 sub r0,r3,r0 << 73 lsr_s r1,r1,3 << 74 j_s.d [blink] << 75 add r0,r0,r1 << 76 #endif /* ENDIAN */ << 77 .Learly_end: << 78 b.d .Lend << 79 sub_s.ne r1,r1,r1 << 80 END_CFI(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.