Update copyright notices with scripts/update-copyrights
[glibc.git] / ports / sysdeps / alpha / strrchr.S
blobe85f0cf4640bd9e2cbd9200db2e51863dd9ed018
1 /* Copyright (C) 1996-2014 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, see
16    <http://www.gnu.org/licenses/>.  */
18 /* Return the address of the last occurrence of a given character
19    within a null-terminated string, or null if it is not found.
21    This is generally scheduled for the EV5 (got to look out for my own
22    interests :-), but with EV4 needs in mind.  There are, in fact, fewer
23    stalls on the EV4 than there are on the EV5.
26 #include <sysdep.h>
28         .set noreorder
29         .set noat
31 ENTRY(strrchr)
32 #ifdef PROF
33         ldgp    gp, 0(pv)
34         lda     AT, _mcount
35         jsr     AT, (AT), _mcount
36         .prologue 1
37 #else
38         .prologue 0
39 #endif
41         and     a1, 0xff, a1    # e0    : zero extend our test character
42         mov     zero, t6        # .. e1 : t6 is last match aligned addr
43         sll     a1, 8, t5       # e0    : replicate our test character
44         mov     zero, t7        # .. e1 : t7 is last match byte compare mask
45         or      t5, a1, a1      # e0    :
46         ldq_u   t0, 0(a0)       # .. e1 : load first quadword
47         sll     a1, 16, t5      # e0    :
48         andnot  a0, 7, v0       # .. e1 : align source addr
49         or      t5, a1, a1      # e0    :
50         lda     t4, -1          # .. e1 : build garbage mask
51         sll     a1, 32, t5      # e0    :
52         cmpbge  zero, t0, t1    # .. e1 : bits set iff byte == zero
53         mskqh   t4, a0, t4      # e0    :
54         or      t5, a1, a1      # .. e1 : character replication complete
55         xor     t0, a1, t2      # e0    : make bytes == c zero
56         cmpbge  zero, t4, t4    # .. e1 : bits set iff byte is garbage
57         cmpbge  zero, t2, t3    # e0    : bits set iff byte == c
58         andnot  t1, t4, t1      # .. e1 : clear garbage from null test
59         andnot  t3, t4, t3      # e0    : clear garbage from char test
60         bne     t1, $eos        # .. e1 : did we already hit the terminator?
62         /* Character search main loop */
63 $loop:
64         ldq     t0, 8(v0)       # e0    : load next quadword
65         cmovne  t3, v0, t6      # .. e1 : save previous comparisons match
66         cmovne  t3, t3, t7      # e0    :
67         addq    v0, 8, v0       # .. e1 :
68         xor     t0, a1, t2      # e0    :
69         cmpbge  zero, t0, t1    # .. e1 : bits set iff byte == zero
70         cmpbge  zero, t2, t3    # e0    : bits set iff byte == c
71         beq     t1, $loop       # .. e1 : if we havnt seen a null, loop
73         /* Mask out character matches after terminator */
74 $eos:
75         negq    t1, t4          # e0    : isolate first null byte match
76         and     t1, t4, t4      # e1    :
77         subq    t4, 1, t5       # e0    : build a mask of the bytes upto...
78         or      t4, t5, t4      # e1    : ... and including the null
80         and     t3, t4, t3      # e0    : mask out char matches after null
81         cmovne  t3, t3, t7      # .. e1 : save it, if match found
82         cmovne  t3, v0, t6      # e0    :
84         /* Locate the address of the last matched character */
86         /* Retain the early exit for the ev4 -- the ev5 mispredict penalty
87            is 5 cycles -- the same as just falling through.  */
88         beq     t7, $retnull    # .. e1 :
90         and     t7, 0xf0, t2    # e0    : binary search for the high bit set
91         cmovne  t2, t2, t7      # .. e1 (zdb)
92         cmovne  t2, 4, t2       # e0    :
93         and     t7, 0xcc, t1    # .. e1 :
94         cmovne  t1, t1, t7      # e0    :
95         cmovne  t1, 2, t1       # .. e1 :
96         and     t7, 0xaa, t0    # e0    :
97         cmovne  t0, 1, t0       # .. e1 (zdb)
98         addq    t2, t1, t1      # e0    :
99         addq    t6, t0, v0      # .. e1 : add our aligned base ptr to the mix
100         addq    v0, t1, v0      # e0    :
101         ret                     # .. e1 :
103 $retnull:
104         mov     zero, v0        # e0    :
105         ret                     # .. e1 :
107         END(strrchr)
109 weak_alias (strrchr, rindex)
110 libc_hidden_builtin_def (strrchr)