1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */ 21da177e4SLinus Torvalds/* 31da177e4SLinus Torvalds * arch/alpha/lib/ev67-strchr.S 41da177e4SLinus Torvalds * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com> 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Return the address of a given character within a null-terminated 71da177e4SLinus Torvalds * string, or null if it is not found. 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * Much of the information about 21264 scheduling/coding comes from: 101da177e4SLinus Torvalds * Compiler Writer's Guide for the Alpha 21264 111da177e4SLinus Torvalds * abbreviated as 'CWG' in other comments here 121da177e4SLinus Torvalds * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html 131da177e4SLinus Torvalds * Scheduling notation: 141da177e4SLinus Torvalds * E - either cluster 151da177e4SLinus Torvalds * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 161da177e4SLinus Torvalds * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 171da177e4SLinus Torvalds * Try not to change the actual algorithm if possible for consistency. 181da177e4SLinus Torvalds */ 19*f3c78e94SMasahiro Yamada#include <linux/export.h> 201da177e4SLinus Torvalds#include <asm/regdef.h> 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds .set noreorder 231da177e4SLinus Torvalds .set noat 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds .align 4 261da177e4SLinus Torvalds .globl strchr 271da177e4SLinus Torvalds .ent strchr 281da177e4SLinus Torvaldsstrchr: 291da177e4SLinus Torvalds .frame sp, 0, ra 301da177e4SLinus Torvalds .prologue 0 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds ldq_u t0, 0(a0) # L : load first quadword Latency=3 331da177e4SLinus Torvalds and a1, 0xff, t3 # E : 00000000000000ch 341da177e4SLinus Torvalds insbl a1, 1, t5 # U : 000000000000ch00 351da177e4SLinus Torvalds insbl a1, 7, a2 # U : ch00000000000000 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds insbl t3, 6, a3 # U : 00ch000000000000 381da177e4SLinus Torvalds or t5, t3, a1 # E : 000000000000chch 391da177e4SLinus Torvalds andnot a0, 7, v0 # E : align our loop pointer 401da177e4SLinus Torvalds lda t4, -1 # E : build garbage mask 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds mskqh t4, a0, t4 # U : only want relevant part of first quad 431da177e4SLinus Torvalds or a2, a3, a2 # E : chch000000000000 441da177e4SLinus Torvalds inswl a1, 2, t5 # E : 00000000chch0000 451da177e4SLinus Torvalds inswl a1, 4, a3 # E : 0000chch00000000 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds or a1, a2, a1 # E : chch00000000chch 481da177e4SLinus Torvalds or a3, t5, t5 # E : 0000chchchch0000 491da177e4SLinus Torvalds cmpbge zero, t0, t2 # E : bits set iff byte == zero 501da177e4SLinus Torvalds cmpbge zero, t4, t4 # E : bits set iff byte is garbage 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds /* This quad is _very_ serialized. Lots of stalling happens */ 531da177e4SLinus Torvalds or t5, a1, a1 # E : chchchchchchchch 541da177e4SLinus Torvalds xor t0, a1, t1 # E : make bytes == c zero 551da177e4SLinus Torvalds cmpbge zero, t1, t3 # E : bits set iff byte == c 561da177e4SLinus Torvalds or t2, t3, t0 # E : bits set iff char match or zero match 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds andnot t0, t4, t0 # E : clear garbage bits 591da177e4SLinus Torvalds cttz t0, a2 # U0 : speculative (in case we get a match) 601da177e4SLinus Torvalds nop # E : 611da177e4SLinus Torvalds bne t0, $found # U : 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds /* 641da177e4SLinus Torvalds * Yuk. This loop is going to stall like crazy waiting for the 651da177e4SLinus Torvalds * data to be loaded. Not much can be done about it unless it's 661da177e4SLinus Torvalds * unrolled multiple times - is that safe to do in kernel space? 671da177e4SLinus Torvalds * Or would exception handling recovery code do the trick here? 681da177e4SLinus Torvalds */ 691da177e4SLinus Torvalds$loop: ldq t0, 8(v0) # L : Latency=3 701da177e4SLinus Torvalds addq v0, 8, v0 # E : 711da177e4SLinus Torvalds xor t0, a1, t1 # E : 721da177e4SLinus Torvalds cmpbge zero, t0, t2 # E : bits set iff byte == 0 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds cmpbge zero, t1, t3 # E : bits set iff byte == c 751da177e4SLinus Torvalds or t2, t3, t0 # E : 761da177e4SLinus Torvalds cttz t3, a2 # U0 : speculative (in case we get a match) 771da177e4SLinus Torvalds beq t0, $loop # U : 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds$found: negq t0, t1 # E : clear all but least set bit 801da177e4SLinus Torvalds and t0, t1, t0 # E : 811da177e4SLinus Torvalds and t0, t3, t1 # E : bit set iff byte was the char 821da177e4SLinus Torvalds addq v0, a2, v0 # E : Add in the bit number from above 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds cmoveq t1, $31, v0 # E : Two mapping slots, latency = 2 851da177e4SLinus Torvalds nop 861da177e4SLinus Torvalds nop 871da177e4SLinus Torvalds ret # L0 : 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds .end strchr 9000fc0e0dSAl Viro EXPORT_SYMBOL(strchr) 91