2006-02-09 Joseph S. Myers <joseph@codesourcery.com>
[glibc-ports.git] / sysdeps / alpha / strrchr.S
blob248181f702dafeb392e0e479359af2dd1fd22457
1 /* Copyright (C) 1996, 1997, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
19 /* Return the address of the last occurrence of a given character
20    within a null-terminated string, or null if it is not found.
22    This is generally scheduled for the EV5 (got to look out for my own
23    interests :-), but with EV4 needs in mind.  There are, in fact, fewer
24    stalls on the EV4 than there are on the EV5.
27 #include <sysdep.h>
29         .set noreorder
30         .set noat
32 ENTRY(strrchr)
33 #ifdef PROF
34         ldgp    gp, 0(pv)
35         lda     AT, _mcount
36         jsr     AT, (AT), _mcount
37         .prologue 1
38 #else
39         .prologue 0
40 #endif
42         and     a1, 0xff, a1    # e0    : zero extend our test character
43         mov     zero, t6        # .. e1 : t6 is last match aligned addr
44         sll     a1, 8, t5       # e0    : replicate our test character
45         mov     zero, t7        # .. e1 : t7 is last match byte compare mask
46         or      t5, a1, a1      # e0    :
47         ldq_u   t0, 0(a0)       # .. e1 : load first quadword
48         sll     a1, 16, t5      # e0    :
49         andnot  a0, 7, v0       # .. e1 : align source addr
50         or      t5, a1, a1      # e0    :
51         lda     t4, -1          # .. e1 : build garbage mask
52         sll     a1, 32, t5      # e0    :
53         cmpbge  zero, t0, t1    # .. e1 : bits set iff byte == zero
54         mskqh   t4, a0, t4      # e0    :
55         or      t5, a1, a1      # .. e1 : character replication complete
56         xor     t0, a1, t2      # e0    : make bytes == c zero
57         cmpbge  zero, t4, t4    # .. e1 : bits set iff byte is garbage
58         cmpbge  zero, t2, t3    # e0    : bits set iff byte == c
59         andnot  t1, t4, t1      # .. e1 : clear garbage from null test
60         andnot  t3, t4, t3      # e0    : clear garbage from char test
61         bne     t1, $eos        # .. e1 : did we already hit the terminator?
63         /* Character search main loop */
64 $loop:
65         ldq     t0, 8(v0)       # e0    : load next quadword
66         cmovne  t3, v0, t6      # .. e1 : save previous comparisons match
67         cmovne  t3, t3, t7      # e0    :
68         addq    v0, 8, v0       # .. e1 :
69         xor     t0, a1, t2      # e0    :
70         cmpbge  zero, t0, t1    # .. e1 : bits set iff byte == zero
71         cmpbge  zero, t2, t3    # e0    : bits set iff byte == c
72         beq     t1, $loop       # .. e1 : if we havnt seen a null, loop
74         /* Mask out character matches after terminator */
75 $eos:
76         negq    t1, t4          # e0    : isolate first null byte match
77         and     t1, t4, t4      # e1    :
78         subq    t4, 1, t5       # e0    : build a mask of the bytes upto...
79         or      t4, t5, t4      # e1    : ... and including the null
81         and     t3, t4, t3      # e0    : mask out char matches after null
82         cmovne  t3, t3, t7      # .. e1 : save it, if match found
83         cmovne  t3, v0, t6      # e0    :
85         /* Locate the address of the last matched character */
87         /* Retain the early exit for the ev4 -- the ev5 mispredict penalty
88            is 5 cycles -- the same as just falling through.  */
89         beq     t7, $retnull    # .. e1 :
91         and     t7, 0xf0, t2    # e0    : binary search for the high bit set
92         cmovne  t2, t2, t7      # .. e1 (zdb)
93         cmovne  t2, 4, t2       # e0    :
94         and     t7, 0xcc, t1    # .. e1 :
95         cmovne  t1, t1, t7      # e0    :
96         cmovne  t1, 2, t1       # .. e1 :
97         and     t7, 0xaa, t0    # e0    :
98         cmovne  t0, 1, t0       # .. e1 (zdb)
99         addq    t2, t1, t1      # e0    :
100         addq    t6, t0, v0      # .. e1 : add our aligned base ptr to the mix
101         addq    v0, t1, v0      # e0    :
102         ret                     # .. e1 :
104 $retnull:
105         mov     zero, v0        # e0    :
106         ret                     # .. e1 :
108         END(strrchr)
110 weak_alias (strrchr, rindex)
111 libc_hidden_builtin_def (strrchr)