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