Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * arch/alpha/lib/strrchr.S
0004  * Contributed by Richard Henderson (rth@tamu.edu)
0005  *
0006  * Return the address of the last occurrence of a given character
0007  * within a null-terminated string, or null if it is not found.
0008  */
0009 #include <asm/export.h>
0010 #include <asm/regdef.h>
0011 
0012     .set noreorder
0013     .set noat
0014 
0015     .align 3
0016     .ent strrchr
0017     .globl strrchr
0018 strrchr:
0019     .frame sp, 0, ra
0020     .prologue 0
0021 
0022     zapnot  a1, 1, a1   # e0    : zero extend our test character
0023     mov zero, t6    # .. e1 : t6 is last match aligned addr
0024     sll a1, 8, t5   # e0    : replicate our test character
0025     mov zero, t8    # .. e1 : t8 is last match byte compare mask
0026     or  t5, a1, a1  # e0    :
0027     ldq_u   t0, 0(a0)   # .. e1 : load first quadword
0028     sll a1, 16, t5  # e0    :
0029     andnot  a0, 7, v0   # .. e1 : align source addr
0030     or  t5, a1, a1  # e0    :
0031     lda t4, -1      # .. e1 : build garbage mask
0032     sll a1, 32, t5  # e0    :
0033     cmpbge  zero, t0, t1    # .. e1 : bits set iff byte == zero
0034     mskqh   t4, a0, t4  # e0    :
0035     or  t5, a1, a1  # .. e1 : character replication complete
0036     xor t0, a1, t2  # e0    : make bytes == c zero
0037     cmpbge  zero, t4, t4    # .. e1 : bits set iff byte is garbage
0038     cmpbge  zero, t2, t3    # e0    : bits set iff byte == c
0039     andnot  t1, t4, t1  # .. e1 : clear garbage from null test
0040     andnot  t3, t4, t3  # e0    : clear garbage from char test
0041     bne t1, $eos    # .. e1 : did we already hit the terminator?
0042 
0043     /* Character search main loop */
0044 $loop:
0045     ldq t0, 8(v0)   # e0    : load next quadword
0046     cmovne  t3, v0, t6  # .. e1 : save previous comparisons match
0047     cmovne  t3, t3, t8  # e0    :
0048     addq    v0, 8, v0   # .. e1 :
0049     xor t0, a1, t2  # e0    :
0050     cmpbge  zero, t0, t1    # .. e1 : bits set iff byte == zero
0051     cmpbge  zero, t2, t3    # e0    : bits set iff byte == c
0052     beq t1, $loop   # .. e1 : if we havnt seen a null, loop
0053 
0054     /* Mask out character matches after terminator */
0055 $eos:
0056     negq    t1, t4      # e0    : isolate first null byte match
0057     and t1, t4, t4  # e1    :
0058     subq    t4, 1, t5   # e0    : build a mask of the bytes up to...
0059     or  t4, t5, t4  # e1    : ... and including the null
0060 
0061     and t3, t4, t3  # e0    : mask out char matches after null
0062     cmovne  t3, t3, t8  # .. e1 : save it, if match found
0063     cmovne  t3, v0, t6  # e0    :
0064 
0065     /* Locate the address of the last matched character */
0066 
0067     /* Retain the early exit for the ev4 -- the ev5 mispredict penalty
0068        is 5 cycles -- the same as just falling through.  */
0069     beq t8, $retnull    # .. e1 :
0070 
0071     and t8, 0xf0, t2    # e0    : binary search for the high bit set
0072     cmovne  t2, t2, t8  # .. e1 (zdb)
0073     cmovne  t2, 4, t2   # e0    :
0074     and t8, 0xcc, t1    # .. e1 :
0075     cmovne  t1, t1, t8  # e0    :
0076     cmovne  t1, 2, t1   # .. e1 :
0077     and t8, 0xaa, t0    # e0    :
0078     cmovne  t0, 1, t0   # .. e1 (zdb)
0079     addq    t2, t1, t1  # e0    :
0080     addq    t6, t0, v0  # .. e1 : add our aligned base ptr to the mix
0081     addq    v0, t1, v0  # e0    :
0082     ret         # .. e1 :
0083 
0084 $retnull:
0085     mov zero, v0    # e0    :
0086     ret         # .. e1 :
0087 
0088     .end strrchr
0089     EXPORT_SYMBOL(strrchr)