1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * strlen() for PPC32 4 * 5 * Copyright (C) 2018 Christophe Leroy CS Syst 6 * 7 * Inspired from glibc implementation 8 */ 9 #include <linux/export.h> 10 #include <asm/ppc_asm.h> 11 #include <asm/cache.h> 12 13 .text 14 15 /* 16 * Algorithm: 17 * 18 * 1) Given a word 'x', we can test to see if 19 * by subtracting 0x01010101, and seeing if 20 * byte changed from 0 to 1. This works bec 21 * 0 byte must have had no incoming carry ( 22 * significant), so it is 0x00 - 0x01 == 0x 23 * byte values, either they have the high b 24 * 1 is subtracted you get a value in the r 25 * have their high bit set. The expression 26 * (x - 0x01010101) & ~x & 0x80808080), whi 27 * there were no 0x00 bytes in the word. Y 28 * match, but possibly false 0x80 matches i 29 * byte to a true match due to carries. Fo 30 * of no consequence since the least signif 31 * we're interested in, but big-endian need 32 * byte matches. 33 * 2) Given a word 'x', we can test to see _wh 34 * calculating ~(((x & ~0x80808080) - 0x808 35 * This produces 0x80 in each byte that was 36 * the other bytes. The '| ~0x80808080' cle 37 * byte, and the '| x' part ensures that by 38 * produce 0x00. The addition will carry in 39 * iff that byte had one of its low 7 bits 40 * which was the most significant bit set a 41 * many to add to the index. 42 * This is from the book 'The PowerPC Compi 43 * by Steve Hoxey, Faraydon Karim, Bill Hay 44 */ 45 46 _GLOBAL(strlen) 47 andi. r0, r3, 3 48 lis r7, 0x0101 49 addi r10, r3, -4 50 addic r7, r7, 0x0101 /* r7 = 0x0101 51 rotlwi r6, r7, 31 /* r6 = 0x8080 52 bne- 3f 53 .balign IFETCH_ALIGN_BYTES 54 1: lwzu r9, 4(r10) 55 2: subf r8, r7, r9 56 and. r8, r8, r6 57 beq+ 1b 58 andc. r8, r8, r9 59 beq+ 1b 60 andc r8, r9, r6 61 orc r9, r9, r6 62 subfe r8, r6, r8 63 nor r8, r8, r9 64 cntlzw r8, r8 65 subf r3, r3, r10 66 srwi r8, r8, 3 67 add r3, r3, r8 68 blr 69 70 /* Missaligned string: make sure bytes 71 3: xor r10, r10, r0 72 orc r8, r8, r8 73 lwzu r9, 4(r10) 74 slwi r0, r0, 3 75 srw r8, r8, r0 76 orc r9, r9, r8 77 b 2b 78 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.