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