1*1da177e4SLinus Torvalds/* 2*1da177e4SLinus Torvalds * arch/alpha/lib/ev67-strchr.S 3*1da177e4SLinus Torvalds * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com> 4*1da177e4SLinus Torvalds * 5*1da177e4SLinus Torvalds * Return the address of a given character within a null-terminated 6*1da177e4SLinus Torvalds * string, or null if it is not found. 7*1da177e4SLinus Torvalds * 8*1da177e4SLinus Torvalds * Much of the information about 21264 scheduling/coding comes from: 9*1da177e4SLinus Torvalds * Compiler Writer's Guide for the Alpha 21264 10*1da177e4SLinus Torvalds * abbreviated as 'CWG' in other comments here 11*1da177e4SLinus Torvalds * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html 12*1da177e4SLinus Torvalds * Scheduling notation: 13*1da177e4SLinus Torvalds * E - either cluster 14*1da177e4SLinus Torvalds * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 15*1da177e4SLinus Torvalds * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 16*1da177e4SLinus Torvalds * Try not to change the actual algorithm if possible for consistency. 17*1da177e4SLinus Torvalds */ 18*1da177e4SLinus Torvalds 19*1da177e4SLinus Torvalds#include <asm/regdef.h> 20*1da177e4SLinus Torvalds 21*1da177e4SLinus Torvalds .set noreorder 22*1da177e4SLinus Torvalds .set noat 23*1da177e4SLinus Torvalds 24*1da177e4SLinus Torvalds .align 4 25*1da177e4SLinus Torvalds .globl strchr 26*1da177e4SLinus Torvalds .ent strchr 27*1da177e4SLinus Torvaldsstrchr: 28*1da177e4SLinus Torvalds .frame sp, 0, ra 29*1da177e4SLinus Torvalds .prologue 0 30*1da177e4SLinus Torvalds 31*1da177e4SLinus Torvalds ldq_u t0, 0(a0) # L : load first quadword Latency=3 32*1da177e4SLinus Torvalds and a1, 0xff, t3 # E : 00000000000000ch 33*1da177e4SLinus Torvalds insbl a1, 1, t5 # U : 000000000000ch00 34*1da177e4SLinus Torvalds insbl a1, 7, a2 # U : ch00000000000000 35*1da177e4SLinus Torvalds 36*1da177e4SLinus Torvalds insbl t3, 6, a3 # U : 00ch000000000000 37*1da177e4SLinus Torvalds or t5, t3, a1 # E : 000000000000chch 38*1da177e4SLinus Torvalds andnot a0, 7, v0 # E : align our loop pointer 39*1da177e4SLinus Torvalds lda t4, -1 # E : build garbage mask 40*1da177e4SLinus Torvalds 41*1da177e4SLinus Torvalds mskqh t4, a0, t4 # U : only want relevant part of first quad 42*1da177e4SLinus Torvalds or a2, a3, a2 # E : chch000000000000 43*1da177e4SLinus Torvalds inswl a1, 2, t5 # E : 00000000chch0000 44*1da177e4SLinus Torvalds inswl a1, 4, a3 # E : 0000chch00000000 45*1da177e4SLinus Torvalds 46*1da177e4SLinus Torvalds or a1, a2, a1 # E : chch00000000chch 47*1da177e4SLinus Torvalds or a3, t5, t5 # E : 0000chchchch0000 48*1da177e4SLinus Torvalds cmpbge zero, t0, t2 # E : bits set iff byte == zero 49*1da177e4SLinus Torvalds cmpbge zero, t4, t4 # E : bits set iff byte is garbage 50*1da177e4SLinus Torvalds 51*1da177e4SLinus Torvalds /* This quad is _very_ serialized. Lots of stalling happens */ 52*1da177e4SLinus Torvalds or t5, a1, a1 # E : chchchchchchchch 53*1da177e4SLinus Torvalds xor t0, a1, t1 # E : make bytes == c zero 54*1da177e4SLinus Torvalds cmpbge zero, t1, t3 # E : bits set iff byte == c 55*1da177e4SLinus Torvalds or t2, t3, t0 # E : bits set iff char match or zero match 56*1da177e4SLinus Torvalds 57*1da177e4SLinus Torvalds andnot t0, t4, t0 # E : clear garbage bits 58*1da177e4SLinus Torvalds cttz t0, a2 # U0 : speculative (in case we get a match) 59*1da177e4SLinus Torvalds nop # E : 60*1da177e4SLinus Torvalds bne t0, $found # U : 61*1da177e4SLinus Torvalds 62*1da177e4SLinus Torvalds /* 63*1da177e4SLinus Torvalds * Yuk. This loop is going to stall like crazy waiting for the 64*1da177e4SLinus Torvalds * data to be loaded. Not much can be done about it unless it's 65*1da177e4SLinus Torvalds * unrolled multiple times - is that safe to do in kernel space? 66*1da177e4SLinus Torvalds * Or would exception handling recovery code do the trick here? 67*1da177e4SLinus Torvalds */ 68*1da177e4SLinus Torvalds$loop: ldq t0, 8(v0) # L : Latency=3 69*1da177e4SLinus Torvalds addq v0, 8, v0 # E : 70*1da177e4SLinus Torvalds xor t0, a1, t1 # E : 71*1da177e4SLinus Torvalds cmpbge zero, t0, t2 # E : bits set iff byte == 0 72*1da177e4SLinus Torvalds 73*1da177e4SLinus Torvalds cmpbge zero, t1, t3 # E : bits set iff byte == c 74*1da177e4SLinus Torvalds or t2, t3, t0 # E : 75*1da177e4SLinus Torvalds cttz t3, a2 # U0 : speculative (in case we get a match) 76*1da177e4SLinus Torvalds beq t0, $loop # U : 77*1da177e4SLinus Torvalds 78*1da177e4SLinus Torvalds$found: negq t0, t1 # E : clear all but least set bit 79*1da177e4SLinus Torvalds and t0, t1, t0 # E : 80*1da177e4SLinus Torvalds and t0, t3, t1 # E : bit set iff byte was the char 81*1da177e4SLinus Torvalds addq v0, a2, v0 # E : Add in the bit number from above 82*1da177e4SLinus Torvalds 83*1da177e4SLinus Torvalds cmoveq t1, $31, v0 # E : Two mapping slots, latency = 2 84*1da177e4SLinus Torvalds nop 85*1da177e4SLinus Torvalds nop 86*1da177e4SLinus Torvalds ret # L0 : 87*1da177e4SLinus Torvalds 88*1da177e4SLinus Torvalds .end strchr 89