1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
/* Optimized strcmp implementation for Power7 using 'cmpb' instruction
Copyright (C) 2014-2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* The optimization is achieved here through cmpb instruction.
8byte aligned strings are processed with double word comparision
and unaligned strings are handled effectively with loop unrolling
technique */
#include <sysdep.h>
/* int [r3] strcmp (const char *s1 [r3], const char *s2 [r4]) */
.machine power7
EALIGN (strcmp, 4, 0)
CALL_MCOUNT 2
or r9, r3, r4
rldicl. r10, r9, 0, 61 /* are s1 and s2 8 byte aligned..? */
bne cr0, L(process_unaligned_bytes)
li r5, 0
.align 4
/* process input parameters on double word aligned boundary */
L(unrollDword):
ld r8,0(r3)
ld r10,0(r4)
cmpb r7,r8,r5
cmpdi cr7,r7,0
mr r9,r7
bne cr7,L(null_found)
cmpld cr7,r8,r10
bne cr7,L(different)
ld r8,8(r3)
ld r10,8(r4)
cmpb r7,r8,r5
cmpdi cr7,r7,0
mr r9,r7
bne cr7,L(null_found)
cmpld cr7,r8,r10
bne cr7,L(different)
ld r8,16(r3)
ld r10,16(r4)
cmpb r7,r8,r5
cmpdi cr7,r7,0
mr r9,r7
bne cr7,L(null_found)
cmpld cr7,r8,r10
bne cr7,L(different)
ld r8,24(r3)
ld r10,24(r4)
cmpb r7,r8,r5
cmpdi cr7,r7,0
mr r9,r7
bne cr7,L(null_found)
cmpld cr7,r8,r10
bne cr7,L(different)
addi r3, r3, 32
addi r4, r4, 32
beq cr7, L(unrollDword)
.align 4
L(null_found):
#ifdef __LITTLE_ENDIAN__
neg r7,r9
and r9,r9,r7
li r7,-1
cntlzd r9,r9
subfic r9,r9,71
sld r9,r7,r9
#else
cntlzd r9,r9
li r7,-1
addi r9,r9,8
srd r9,r7,r9
#endif
or r8,r8,r9
or r10,r10,r9
L(different):
cmpb r9,r8,r10
#ifdef __LITTLE_ENDIAN__
addi r7,r9,1
andc r9,r7,r9
cntlzd r9,r9
subfic r9,r9,63
#else
not r9,r9
cntlzd r9,r9
subfic r9,r9,56
#endif
srd r3,r8,r9
srd r10,r10,r9
rldicl r10,r10,0,56
rldicl r3,r3,0,56
subf r3,r10,r3
blr
.align 4
L(process_unaligned_bytes):
lbz r9, 0(r3) /* load byte from s1 */
lbz r10, 0(r4) /* load byte from s2 */
cmpdi cr7, r9, 0 /* compare *s1 with NULL */
beq cr7, L(diffOfNULL) /* if *s1 is NULL , return *s1 - *s2 */
cmplw cr7, r9, r10 /* compare *s1 and *s2 */
bne cr7, L(ComputeDiff) /* branch to compute difference and return */
lbz r9, 1(r3) /* load next byte from s1 */
lbz r10, 1(r4) /* load next byte from s2 */
cmpdi cr7, r9, 0 /* compare *s1 with NULL */
beq cr7, L(diffOfNULL) /* if *s1 is NULL , return *s1 - *s2 */
cmplw cr7, r9, r10 /* compare *s1 and *s2 */
bne cr7, L(ComputeDiff) /* branch to compute difference and return */
lbz r9, 2(r3) /* unroll 3rd byte here */
lbz r10, 2(r4)
cmpdi cr7, r9, 0
beq cr7, L(diffOfNULL)
cmplw cr7, r9, r10
bne 7, L(ComputeDiff)
lbz r9, 3(r3) /* unroll 4th byte now */
lbz r10, 3(r4)
addi r3, r3, 4 /* increment s1 by unroll factor */
cmpdi cr7, r9, 0
cmplw cr6, 9, r10
beq cr7, L(diffOfNULL)
addi r4, r4, 4 /* increment s2 by unroll factor */
beq cr6, L(process_unaligned_bytes) /* unroll byte processing */
.align 4
L(ComputeDiff):
extsw r9, r9
subf r10, r10, r9 /* compute s1 - s2 */
extsw r3, r10
blr /* return */
.align 4
L(diffOfNULL):
li r9, 0
subf r10, r10, r9 /* compute s1 - s2 */
extsw r3, r10 /* sign extend result */
blr /* return */
END (strcmp)
libc_hidden_builtin_def (strcmp)
|