18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * arch/alpha/lib/strchr.S 48c2ecf20Sopenharmony_ci * Contributed by Richard Henderson (rth@tamu.edu) 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Return the address of a given character within a null-terminated 78c2ecf20Sopenharmony_ci * string, or null if it is not found. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <asm/export.h> 108c2ecf20Sopenharmony_ci#include <asm/regdef.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci .set noreorder 138c2ecf20Sopenharmony_ci .set noat 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci .align 3 168c2ecf20Sopenharmony_ci .globl strchr 178c2ecf20Sopenharmony_ci .ent strchr 188c2ecf20Sopenharmony_cistrchr: 198c2ecf20Sopenharmony_ci .frame sp, 0, ra 208c2ecf20Sopenharmony_ci .prologue 0 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci zapnot a1, 1, a1 # e0 : zero extend the search character 238c2ecf20Sopenharmony_ci ldq_u t0, 0(a0) # .. e1 : load first quadword 248c2ecf20Sopenharmony_ci sll a1, 8, t5 # e0 : replicate the search character 258c2ecf20Sopenharmony_ci andnot a0, 7, v0 # .. e1 : align our loop pointer 268c2ecf20Sopenharmony_ci or t5, a1, a1 # e0 : 278c2ecf20Sopenharmony_ci lda t4, -1 # .. e1 : build garbage mask 288c2ecf20Sopenharmony_ci sll a1, 16, t5 # e0 : 298c2ecf20Sopenharmony_ci cmpbge zero, t0, t2 # .. e1 : bits set iff byte == zero 308c2ecf20Sopenharmony_ci mskqh t4, a0, t4 # e0 : 318c2ecf20Sopenharmony_ci or t5, a1, a1 # .. e1 : 328c2ecf20Sopenharmony_ci sll a1, 32, t5 # e0 : 338c2ecf20Sopenharmony_ci cmpbge zero, t4, t4 # .. e1 : bits set iff byte is garbage 348c2ecf20Sopenharmony_ci or t5, a1, a1 # e0 : 358c2ecf20Sopenharmony_ci xor t0, a1, t1 # .. e1 : make bytes == c zero 368c2ecf20Sopenharmony_ci cmpbge zero, t1, t3 # e0 : bits set iff byte == c 378c2ecf20Sopenharmony_ci or t2, t3, t0 # e1 : bits set iff char match or zero match 388c2ecf20Sopenharmony_ci andnot t0, t4, t0 # e0 : clear garbage bits 398c2ecf20Sopenharmony_ci bne t0, $found # .. e1 (zdb) 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci$loop: ldq t0, 8(v0) # e0 : 428c2ecf20Sopenharmony_ci addq v0, 8, v0 # .. e1 : 438c2ecf20Sopenharmony_ci nop # e0 : 448c2ecf20Sopenharmony_ci xor t0, a1, t1 # .. e1 (ev5 data stall) 458c2ecf20Sopenharmony_ci cmpbge zero, t0, t2 # e0 : bits set iff byte == 0 468c2ecf20Sopenharmony_ci cmpbge zero, t1, t3 # .. e1 : bits set iff byte == c 478c2ecf20Sopenharmony_ci or t2, t3, t0 # e0 : 488c2ecf20Sopenharmony_ci beq t0, $loop # .. e1 (zdb) 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci$found: negq t0, t1 # e0 : clear all but least set bit 518c2ecf20Sopenharmony_ci and t0, t1, t0 # e1 (stall) 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci and t0, t3, t1 # e0 : bit set iff byte was the char 548c2ecf20Sopenharmony_ci beq t1, $retnull # .. e1 (zdb) 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci and t0, 0xf0, t2 # e0 : binary search for that set bit 578c2ecf20Sopenharmony_ci and t0, 0xcc, t3 # .. e1 : 588c2ecf20Sopenharmony_ci and t0, 0xaa, t4 # e0 : 598c2ecf20Sopenharmony_ci cmovne t2, 4, t2 # .. e1 : 608c2ecf20Sopenharmony_ci cmovne t3, 2, t3 # e0 : 618c2ecf20Sopenharmony_ci cmovne t4, 1, t4 # .. e1 : 628c2ecf20Sopenharmony_ci addq t2, t3, t2 # e0 : 638c2ecf20Sopenharmony_ci addq v0, t4, v0 # .. e1 : 648c2ecf20Sopenharmony_ci addq v0, t2, v0 # e0 : 658c2ecf20Sopenharmony_ci ret # .. e1 : 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci$retnull: 688c2ecf20Sopenharmony_ci mov zero, v0 # e0 : 698c2ecf20Sopenharmony_ci ret # .. e1 : 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci .end strchr 728c2ecf20Sopenharmony_ci EXPORT_SYMBOL(strchr) 73