1/* Optimized strcmp implementation for PowerPC64. 2 Copyright (C) 1997-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19#include <sysdep.h> 20 21/* See strlen.s for comments on how the end-of-string testing works. */ 22 23/* int [r3] strcmp (const char *s1 [r3], const char *s2 [r4]) */ 24 25#ifndef STRCMP 26# define STRCMP strcmp 27#endif 28 29ENTRY_TOCLESS (STRCMP, 4) 30 CALL_MCOUNT 2 31 32#define rTMP2 r0 33#define rRTN r3 34#define rSTR1 r3 /* first string arg */ 35#define rSTR2 r4 /* second string arg */ 36#define rWORD1 r5 /* current word in s1 */ 37#define rWORD2 r6 /* current word in s2 */ 38#define rFEFE r7 /* constant 0xfefefefefefefeff (-0x0101010101010101) */ 39#define r7F7F r8 /* constant 0x7f7f7f7f7f7f7f7f */ 40#define rNEG r9 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */ 41#define rBITDIF r10 /* bits that differ in s1 & s2 words */ 42#define rTMP r11 43 44 dcbt 0,rSTR1 45 or rTMP, rSTR2, rSTR1 46 dcbt 0,rSTR2 47 clrldi. rTMP, rTMP, 61 48 lis rFEFE, -0x101 49 bne L(unaligned) 50 51 ld rWORD1, 0(rSTR1) 52 ld rWORD2, 0(rSTR2) 53 lis r7F7F, 0x7f7f 54 addi rFEFE, rFEFE, -0x101 55 addi r7F7F, r7F7F, 0x7f7f 56 sldi rTMP, rFEFE, 32 57 insrdi r7F7F, r7F7F, 32, 0 58 add rFEFE, rFEFE, rTMP 59 b L(g1) 60 61L(g0): ldu rWORD1, 8(rSTR1) 62 bne cr1, L(different) 63 ldu rWORD2, 8(rSTR2) 64L(g1): add rTMP, rFEFE, rWORD1 65 nor rNEG, r7F7F, rWORD1 66 and. rTMP, rTMP, rNEG 67 cmpd cr1, rWORD1, rWORD2 68 beq+ L(g0) 69 70/* OK. We've hit the end of the string. We need to be careful that 71 we don't compare two strings as different because of gunk beyond 72 the end of the strings... */ 73#ifdef __LITTLE_ENDIAN__ 74L(endstring): 75 addi rTMP2, rTMP, -1 76 beq cr1, L(equal) 77 andc rTMP2, rTMP2, rTMP 78 rldimi rTMP2, rTMP2, 1, 0 79 and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ 80 and rWORD1, rWORD1, rTMP2 81 cmpd cr1, rWORD1, rWORD2 82 beq cr1, L(equal) 83 xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ 84 neg rNEG, rBITDIF 85 and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ 86 cntlzd rNEG, rNEG /* bitcount of the bit. */ 87 andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ 88 sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ 89 sld rWORD2, rWORD2, rNEG 90 xor. rBITDIF, rWORD1, rWORD2 91 sub rRTN, rWORD1, rWORD2 92 blt- L(highbit) 93 sradi rRTN, rRTN, 63 /* must return an int. */ 94 ori rRTN, rRTN, 1 95 blr 96L(equal): 97 li rRTN, 0 98 blr 99 100L(different): 101 ld rWORD1, -8(rSTR1) 102 xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ 103 neg rNEG, rBITDIF 104 and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ 105 cntlzd rNEG, rNEG /* bitcount of the bit. */ 106 andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ 107 sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ 108 sld rWORD2, rWORD2, rNEG 109 xor. rBITDIF, rWORD1, rWORD2 110 sub rRTN, rWORD1, rWORD2 111 blt- L(highbit) 112 sradi rRTN, rRTN, 63 113 ori rRTN, rRTN, 1 114 blr 115L(highbit): 116 sradi rRTN, rWORD2, 63 117 ori rRTN, rRTN, 1 118 blr 119 120#else 121L(endstring): 122 and rTMP, r7F7F, rWORD1 123 beq cr1, L(equal) 124 add rTMP, rTMP, r7F7F 125 xor. rBITDIF, rWORD1, rWORD2 126 andc rNEG, rNEG, rTMP 127 blt- L(highbit) 128 cntlzd rBITDIF, rBITDIF 129 cntlzd rNEG, rNEG 130 addi rNEG, rNEG, 7 131 cmpd cr1, rNEG, rBITDIF 132 sub rRTN, rWORD1, rWORD2 133 blt- cr1, L(equal) 134 sradi rRTN, rRTN, 63 /* must return an int. */ 135 ori rRTN, rRTN, 1 136 blr 137L(equal): 138 li rRTN, 0 139 blr 140 141L(different): 142 ld rWORD1, -8(rSTR1) 143 xor. rBITDIF, rWORD1, rWORD2 144 sub rRTN, rWORD1, rWORD2 145 blt- L(highbit) 146 sradi rRTN, rRTN, 63 147 ori rRTN, rRTN, 1 148 blr 149L(highbit): 150 sradi rRTN, rWORD2, 63 151 ori rRTN, rRTN, 1 152 blr 153#endif 154 155/* Oh well. In this case, we just do a byte-by-byte comparison. */ 156 .align 4 157L(unaligned): 158 lbz rWORD1, 0(rSTR1) 159 lbz rWORD2, 0(rSTR2) 160 b L(u1) 161 162L(u0): lbzu rWORD1, 1(rSTR1) 163 bne- L(u4) 164 lbzu rWORD2, 1(rSTR2) 165L(u1): cmpwi cr1, rWORD1, 0 166 beq- cr1, L(u3) 167 cmpd rWORD1, rWORD2 168 bne- L(u3) 169 lbzu rWORD1, 1(rSTR1) 170 lbzu rWORD2, 1(rSTR2) 171 cmpdi cr1, rWORD1, 0 172 cmpd rWORD1, rWORD2 173 bne+ cr1, L(u0) 174L(u3): sub rRTN, rWORD1, rWORD2 175 blr 176L(u4): lbz rWORD1, -1(rSTR1) 177 sub rRTN, rWORD1, rWORD2 178 blr 179END (STRCMP) 180libc_hidden_builtin_def (strcmp) 181