update from main archive 961105
[glibc.git] / sysdeps / alpha / strrchr.S
blob02f37f50be4fe2a7856eb8a7a9fc33fbf69ea535
1 /* Copyright (C) 1996 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
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 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB.  If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA.  */
20 /* Return the address of the last occurrance of a given character
21    within a null-terminated string, or null if it is not found.
23    This is generally scheduled for the EV5 (got to look out for my own
24    interests :-), but with EV4 needs in mind.  There are, in fact, fewer
25    stalls on the EV4 than there are on the EV5.
28 #include <sysdep.h>
30         .set noreorder
31         .set noat
33 ENTRY(strrchr)
34 #ifdef PROF
35         ldgp    gp, 0(pv)
36         lda     AT, _mcount
37         jsr     AT, (AT), _mcount
38         .prologue 1
39 #else
40         .prologue 0
41 #endif
43         zapnot  a1, 1, a1       # e0    : zero extend our test character
44         mov     zero, t6        # .. e1 : t6 is last match aligned addr
45         sll     a1, 8, t5       # e0    : replicate our test character
46         mov     zero, t7        # .. e1 : t7 is last match byte compare mask
47         or      t5, a1, a1      # e0    :
48         ldq_u   t0, 0(a0)       # .. e1 : load first quadword
49         sll     a1, 16, t5      # e0    :
50         andnot  a0, 7, v0       # .. e1 : align source addr
51         or      t5, a1, a1      # e0    :
52         lda     t4, -1          # .. e1 : build garbage mask
53         sll     a1, 32, t5      # e0    :
54         cmpbge  zero, t0, t1    # .. e1 : bits set iff byte == zero
55         mskqh   t4, a0, t4      # e0    :
56         or      t5, a1, a1      # .. e1 : character replication complete
57         xor     t0, a1, t2      # e0    : make bytes == c zero
58         cmpbge  zero, t4, t4    # .. e1 : bits set iff byte is garbage
59         cmpbge  zero, t2, t3    # e0    : bits set iff byte == c
60         andnot  t1, t4, t1      # .. e1 : clear garbage from null test
61         andnot  t3, t4, t3      # e0    : clear garbage from char test
62         bne     t1, $eos        # .. e1 : did we already hit the terminator?
64         /* Character search main loop */
65 $loop:
66         ldq     t0, 8(v0)       # e0    : load next quadword
67         cmovne  t3, v0, t6      # .. e1 : save previous comparisons match
68         cmovne  t3, t3, t7      # e0    :
69         addq    v0, 8, v0       # .. e1 :
70         xor     t0, a1, t2      # e0    :
71         cmpbge  zero, t0, t1    # .. e1 : bits set iff byte == zero
72         cmpbge  zero, t2, t3    # e0    : bits set iff byte == c
73         beq     t1, $loop       # .. e1 : if we havnt seen a null, loop
75         /* Mask out character matches after terminator */
76 $eos:
77         negq    t1, t4          # e0    : isolate first null byte match
78         and     t1, t4, t4      # e1    :
79         subq    t4, 1, t5       # e0    : build a mask of the bytes upto...
80         or      t4, t5, t4      # e1    : ... and including the null
82         and     t3, t4, t3      # e0    : mask out char matches after null
83         cmovne  t3, t3, t7      # .. e1 : save it, if match found
84         cmovne  t3, v0, t6      # e0    :
86         /* Locate the address of the last matched character */
88         /* Retain the early exit for the ev4 -- the ev5 mispredict penalty
89            is 5 cycles -- the same as just falling through.  */
90         beq     t7, $retnull    # .. e1 :
92         and     t7, 0xf0, t2    # e0    : binary search for the high bit set
93         cmovne  t2, t2, t7      # .. e1 (zdb)
94         cmovne  t2, 4, t2       # e0    :
95         and     t7, 0xcc, t1    # .. e1 :
96         cmovne  t1, t1, t7      # e0    :
97         cmovne  t1, 2, t1       # .. e1 :
98         and     t7, 0xaa, t0    # e0    :
99         cmovne  t0, 1, t0       # .. e1 (zdb)
100         addq    t2, t1, t1      # e0    :
101         addq    t6, t0, v0      # .. e1 : add our aligned base ptr to the mix
102         addq    v0, t1, v0      # e0    :
103         ret                     # .. e1 :
105 $retnull:
106         mov     zero, v0        # e0    :
107         ret                     # .. e1 :
109         END(strrchr)
111 weak_alias (strrchr, rindex)