~vorlon/ubuntu/natty/eglibc/multiarch

« back to all changes in this revision

Viewing changes to sysdeps/powerpc/powerpc64/power7/memchr.S

  • Committer: Steve Langasek
  • Date: 2011-02-18 21:18:44 UTC
  • mfrom: (103.1.7 eglibc)
  • Revision ID: steve.langasek@linaro.org-20110218211844-lodmi8b1qhyq3f3x
Tags: 2.13~pre1-0ubuntu1+multiarch.1
merge from natty

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Optimized memchr implementation for PowerPC64/POWER7 using cmpb insn.
 
2
   Copyright (C) 2010 Free Software Foundation, Inc.
 
3
   Contributed by Luis Machado <luisgpm@br.ibm.com>.
 
4
   This file is part of the GNU C Library.
 
5
 
 
6
   The GNU C Library is free software; you can redistribute it and/or
 
7
   modify it under the terms of the GNU Lesser General Public
 
8
   License as published by the Free Software Foundation; either
 
9
   version 2.1 of the License, or (at your option) any later version.
 
10
 
 
11
   The GNU C Library is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
   Lesser General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU Lesser General Public
 
17
   License along with the GNU C Library; if not, write to the Free
 
18
   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA
 
19
   02110-1301 USA.  */
 
20
 
 
21
#include <sysdep.h>
 
22
#include <bp-sym.h>
 
23
#include <bp-asm.h>
 
24
 
 
25
/* int [r3] memchr (char *s [r3], int byte [r4], int size [r5])  */
 
26
        .machine  power7
 
27
ENTRY (BP_SYM (__memchr))
 
28
        CALL_MCOUNT 2
 
29
        dcbt    0,r3
 
30
        clrrdi  r8,r3,3
 
31
        rlwimi  r4,r4,8,16,23
 
32
        rlwimi  r4,r4,16,0,15
 
33
        insrdi  r4,r4,32,0
 
34
        add     r7,r3,r5      /* Calculate the last acceptable address.  */
 
35
        cmpldi  r5,32
 
36
        ble     L(small_range)
 
37
 
 
38
        cmpld   cr7,r3,r7     /* Is the address equal or less than r3?  If
 
39
                                 it's equal or less, it means size is either 0
 
40
                                 or a negative number.  */
 
41
        ble     cr7,L(proceed)
 
42
 
 
43
        li      r7,-1         /* Make r11 the biggest if r4 <= 0.  */
 
44
L(proceed):
 
45
        rlwinm  r6,r3,3,26,28 /* Calculate padding.  */
 
46
        ld      r12,0(r8)     /* Load doubleword from memory.  */
 
47
        cmpb    r10,r12,r4    /* Check for BYTE's in DWORD1.  */
 
48
        sld     r10,r10,r6
 
49
        srd     r10,r10,r6
 
50
        cmpldi  cr7,r10,0     /* If r10 == 0, no BYTE's's have been found.  */
 
51
        bne     cr7,L(done)
 
52
 
 
53
        /* Are we done already?  */
 
54
        addi    r9,r8,8
 
55
        cmpld   cr6,r9,r7
 
56
        bge     cr6,L(null)
 
57
 
 
58
        mtcrf   0x01,r8
 
59
        /* Are we now aligned to a quadword boundary?  If so, skip to
 
60
           the main loop.  Otherwise, go through the alignment code.  */
 
61
 
 
62
        bt      28,L(loop_setup)
 
63
 
 
64
        /* Handle DWORD2 of pair.  */
 
65
        ldu     r12,8(r8)
 
66
        cmpb    r10,r12,r4
 
67
        cmpldi  cr7,r10,0
 
68
        bne     cr7,L(done)
 
69
 
 
70
        /* Are we done already?  */
 
71
        addi    r9,r8,8
 
72
        cmpld   cr6,r9,r7
 
73
        bge     cr6,L(null)
 
74
 
 
75
L(loop_setup):
 
76
        sub     r5,r7,r9
 
77
        srdi    r6,r5,4       /* Number of loop iterations.  */
 
78
        mtctr   r6            /* Setup the counter.  */
 
79
        b       L(loop)
 
80
        /* Main loop to look for BYTE backwards in the string.  Since
 
81
           it's a small loop (< 8 instructions), align it to 32-bytes.  */
 
82
        .p2align  5
 
83
L(loop):
 
84
        /* Load two doublewords, compare and merge in a
 
85
           single register for speed.  This is an attempt
 
86
           to speed up the byte-checking process for bigger strings.  */
 
87
 
 
88
        ld      r12,8(r8)
 
89
        ldu     r11,16(r8)
 
90
        cmpb    r10,r12,r4
 
91
        cmpb    r9,r11,r4
 
92
        or      r5,r9,r10     /* Merge everything in one doubleword.  */
 
93
        cmpldi  cr7,r5,0
 
94
        bne     cr7,L(found)
 
95
        bdnz    L(loop)
 
96
        /* We're here because the counter reached 0, and that means we
 
97
           didn't have any matches for BYTE in the whole range.  Just return
 
98
           the original range.  */
 
99
        addi    r9,r8,8
 
100
        cmpld   cr6,r9,r7
 
101
        blt     cr6,L(loop_small)
 
102
        b       L(null)
 
103
 
 
104
        /* OK, one (or both) of the doublewords contains BYTE.  Check
 
105
           the first doubleword and decrement the address in case the first
 
106
           doubleword really contains BYTE.  */
 
107
        .align  4
 
108
L(found):
 
109
        cmpldi  cr6,r10,0
 
110
        addi    r8,r8,-8
 
111
        bne     cr6,L(done)
 
112
 
 
113
        /* BYTE must be in the second doubleword.  Adjust the address
 
114
           again and move the result of cmpb to r10 so we can calculate the
 
115
           pointer.  */
 
116
 
 
117
        mr      r10,r9
 
118
        addi    r8,r8,8
 
119
 
 
120
        /* r10 has the output of the cmpb instruction, that is, it contains
 
121
           0xff in the same position as BYTE in the original
 
122
           doubleword from the string.  Use that to calculate the pointer.
 
123
           We need to make sure BYTE is *before* the end of the
 
124
           range.  */
 
125
L(done):
 
126
        cntlzd  r0,r10        /* Count leading zeroes before the match.  */
 
127
        srdi    r0,r0,3       /* Convert leading zeroes to bytes.  */
 
128
        add     r3,r8,r0
 
129
        cmpld   r3,r7
 
130
        bge     L(null)
 
131
        blr
 
132
 
 
133
        .align  4
 
134
L(null):
 
135
        li      r3,0
 
136
        blr
 
137
 
 
138
/* Deals with size <= 32.  */
 
139
        .align  4
 
140
L(small_range):
 
141
        cmpldi  r5,0
 
142
        beq     L(null)
 
143
 
 
144
        rlwinm  r6,r3,3,26,28 /* Calculate padding.  */
 
145
        ld      r12,0(r8)     /* Load word from memory.  */
 
146
        cmpb    r10,r12,r4    /* Check for BYTE in DWORD1.  */
 
147
        sld     r10,r10,r6
 
148
        srd     r10,r10,r6
 
149
        cmpldi  cr7,r10,0
 
150
        bne     cr7,L(done)
 
151
 
 
152
        /* Are we done already?  */
 
153
        addi    r9,r8,8
 
154
        cmpld   r9,r7
 
155
        bge     L(null)
 
156
        b       L(loop_small)
 
157
 
 
158
        .p2align  5
 
159
L(loop_small):
 
160
        ldu     r12,8(r8)
 
161
        cmpb    r10,r12,r4
 
162
        addi    r9,r8,8
 
163
        cmpldi  cr6,r10,0
 
164
        bne     cr6,L(done)
 
165
        cmpld   r9,r7
 
166
        bge     L(null)
 
167
        b       L(loop_small)
 
168
 
 
169
END (BP_SYM (__memchr))
 
170
weak_alias (BP_SYM (__memchr), BP_SYM(memchr))
 
171
libc_hidden_builtin_def (memchr)