1/* Optimized strcmp implementation for PowerPC64. 2 Copyright (C) 2003-2021 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] strncmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5]) */ 24 25#ifndef STRNCMP 26# define STRNCMP strncmp 27#endif 28 29ENTRY_TOCLESS (STRNCMP, 4) 30 CALL_MCOUNT 3 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 rN r5 /* max string length */ 37#define rWORD1 r6 /* current word in s1 */ 38#define rWORD2 r7 /* current word in s2 */ 39#define rFEFE r8 /* constant 0xfefefefefefefeff (-0x0101010101010101) */ 40#define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */ 41#define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */ 42#define rBITDIF r11 /* bits that differ in s1 & s2 words */ 43#define rTMP r12 44 45 dcbt 0,rSTR1 46 or rTMP, rSTR2, rSTR1 47 lis r7F7F, 0x7f7f 48 dcbt 0,rSTR2 49 clrldi. rTMP, rTMP, 61 50 cmpldi cr1, rN, 0 51 lis rFEFE, -0x101 52 bne L(unaligned) 53/* We are doubleword aligned so set up for two loops. first a double word 54 loop, then fall into the byte loop if any residual. */ 55 srdi. rTMP, rN, 3 56 clrldi rN, rN, 61 57 addi rFEFE, rFEFE, -0x101 58 addi r7F7F, r7F7F, 0x7f7f 59 cmpldi cr1, rN, 0 60 beq L(unaligned) 61 62 mtctr rTMP /* Power4 wants mtctr 1st in dispatch group. */ 63 ld rWORD1, 0(rSTR1) 64 ld rWORD2, 0(rSTR2) 65 sldi rTMP, rFEFE, 32 66 insrdi r7F7F, r7F7F, 32, 0 67 add rFEFE, rFEFE, rTMP 68 b L(g1) 69 70L(g0): 71 ldu rWORD1, 8(rSTR1) 72 bne- cr1, L(different) 73 ldu rWORD2, 8(rSTR2) 74L(g1): add rTMP, rFEFE, rWORD1 75 nor rNEG, r7F7F, rWORD1 76 bdz L(tail) 77 and. rTMP, rTMP, rNEG 78 cmpd cr1, rWORD1, rWORD2 79 beq+ L(g0) 80 81/* OK. We've hit the end of the string. We need to be careful that 82 we don't compare two strings as different because of gunk beyond 83 the end of the strings... */ 84 85#ifdef __LITTLE_ENDIAN__ 86L(endstring): 87 addi rTMP2, rTMP, -1 88 beq cr1, L(equal) 89 andc rTMP2, rTMP2, rTMP 90 rldimi rTMP2, rTMP2, 1, 0 91 and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ 92 and rWORD1, rWORD1, rTMP2 93 cmpd cr1, rWORD1, rWORD2 94 beq cr1, L(equal) 95 xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ 96 neg rNEG, rBITDIF 97 and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ 98 cntlzd rNEG, rNEG /* bitcount of the bit. */ 99 andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ 100 sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ 101 sld rWORD2, rWORD2, rNEG 102 xor. rBITDIF, rWORD1, rWORD2 103 sub rRTN, rWORD1, rWORD2 104 blt- L(highbit) 105 sradi rRTN, rRTN, 63 /* must return an int. */ 106 ori rRTN, rRTN, 1 107 blr 108L(equal): 109 li rRTN, 0 110 blr 111 112L(different): 113 ld rWORD1, -8(rSTR1) 114 xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ 115 neg rNEG, rBITDIF 116 and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ 117 cntlzd rNEG, rNEG /* bitcount of the bit. */ 118 andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ 119 sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ 120 sld rWORD2, rWORD2, rNEG 121 xor. rBITDIF, rWORD1, rWORD2 122 sub rRTN, rWORD1, rWORD2 123 blt- L(highbit) 124 sradi rRTN, rRTN, 63 125 ori rRTN, rRTN, 1 126 blr 127L(highbit): 128 sradi rRTN, rWORD2, 63 129 ori rRTN, rRTN, 1 130 blr 131 132#else 133L(endstring): 134 and rTMP, r7F7F, rWORD1 135 beq cr1, L(equal) 136 add rTMP, rTMP, r7F7F 137 xor. rBITDIF, rWORD1, rWORD2 138 andc rNEG, rNEG, rTMP 139 blt- L(highbit) 140 cntlzd rBITDIF, rBITDIF 141 cntlzd rNEG, rNEG 142 addi rNEG, rNEG, 7 143 cmpd cr1, rNEG, rBITDIF 144 sub rRTN, rWORD1, rWORD2 145 blt- cr1, L(equal) 146 sradi rRTN, rRTN, 63 /* must return an int. */ 147 ori rRTN, rRTN, 1 148 blr 149L(equal): 150 li rRTN, 0 151 blr 152 153L(different): 154 ld rWORD1, -8(rSTR1) 155 xor. rBITDIF, rWORD1, rWORD2 156 sub rRTN, rWORD1, rWORD2 157 blt- L(highbit) 158 sradi rRTN, rRTN, 63 159 ori rRTN, rRTN, 1 160 blr 161L(highbit): 162 sradi rRTN, rWORD2, 63 163 ori rRTN, rRTN, 1 164 blr 165#endif 166 167/* Oh well. In this case, we just do a byte-by-byte comparison. */ 168 .align 4 169L(tail): 170 and. rTMP, rTMP, rNEG 171 cmpd cr1, rWORD1, rWORD2 172 bne- L(endstring) 173 addi rSTR1, rSTR1, 8 174 bne- cr1, L(different) 175 addi rSTR2, rSTR2, 8 176 cmpldi cr1, rN, 0 177L(unaligned): 178 mtctr rN /* Power4 wants mtctr 1st in dispatch group */ 179 bgt cr1, L(uz) 180L(ux): 181 li rRTN, 0 182 blr 183 .align 4 184L(uz): 185 lbz rWORD1, 0(rSTR1) 186 lbz rWORD2, 0(rSTR2) 187 nop 188 b L(u1) 189L(u0): 190 lbzu rWORD2, 1(rSTR2) 191L(u1): 192 bdz L(u3) 193 cmpdi cr1, rWORD1, 0 194 cmpd rWORD1, rWORD2 195 beq- cr1, L(u3) 196 lbzu rWORD1, 1(rSTR1) 197 bne- L(u2) 198 lbzu rWORD2, 1(rSTR2) 199 bdz L(u3) 200 cmpdi cr1, rWORD1, 0 201 cmpd rWORD1, rWORD2 202 bne- L(u3) 203 lbzu rWORD1, 1(rSTR1) 204 bne+ cr1, L(u0) 205 206L(u2): lbzu rWORD1, -1(rSTR1) 207L(u3): sub rRTN, rWORD1, rWORD2 208 blr 209END (STRNCMP) 210libc_hidden_builtin_def (strncmp) 211