/*1* arch/alpha/lib/ev67-strchr.S2* 21264 version contributed by Rick Gorton <[email protected]>3*4* Return the address of a given character within a null-terminated5* string, or null if it is not found.6*7* Much of the information about 21264 scheduling/coding comes from:8* Compiler Writer's Guide for the Alpha 212649* abbreviated as 'CWG' in other comments here10* ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html11* Scheduling notation:12* E - either cluster13* U - upper subcluster; U0 - subcluster U0; U1 - subcluster U114* L - lower subcluster; L0 - subcluster L0; L1 - subcluster L115* Try not to change the actual algorithm if possible for consistency.16*/1718#include <asm/regdef.h>1920.set noreorder21.set noat2223.align 424.globl strchr25.ent strchr26strchr:27.frame sp, 0, ra28.prologue 02930ldq_u t0, 0(a0) # L : load first quadword Latency=331and a1, 0xff, t3 # E : 00000000000000ch32insbl a1, 1, t5 # U : 000000000000ch0033insbl a1, 7, a2 # U : ch000000000000003435insbl t3, 6, a3 # U : 00ch00000000000036or t5, t3, a1 # E : 000000000000chch37andnot a0, 7, v0 # E : align our loop pointer38lda t4, -1 # E : build garbage mask3940mskqh t4, a0, t4 # U : only want relevant part of first quad41or a2, a3, a2 # E : chch00000000000042inswl a1, 2, t5 # E : 00000000chch000043inswl a1, 4, a3 # E : 0000chch000000004445or a1, a2, a1 # E : chch00000000chch46or a3, t5, t5 # E : 0000chchchch000047cmpbge zero, t0, t2 # E : bits set iff byte == zero48cmpbge zero, t4, t4 # E : bits set iff byte is garbage4950/* This quad is _very_ serialized. Lots of stalling happens */51or t5, a1, a1 # E : chchchchchchchch52xor t0, a1, t1 # E : make bytes == c zero53cmpbge zero, t1, t3 # E : bits set iff byte == c54or t2, t3, t0 # E : bits set iff char match or zero match5556andnot t0, t4, t0 # E : clear garbage bits57cttz t0, a2 # U0 : speculative (in case we get a match)58nop # E :59bne t0, $found # U :6061/*62* Yuk. This loop is going to stall like crazy waiting for the63* data to be loaded. Not much can be done about it unless it's64* unrolled multiple times - is that safe to do in kernel space?65* Or would exception handling recovery code do the trick here?66*/67$loop: ldq t0, 8(v0) # L : Latency=368addq v0, 8, v0 # E :69xor t0, a1, t1 # E :70cmpbge zero, t0, t2 # E : bits set iff byte == 07172cmpbge zero, t1, t3 # E : bits set iff byte == c73or t2, t3, t0 # E :74cttz t3, a2 # U0 : speculative (in case we get a match)75beq t0, $loop # U :7677$found: negq t0, t1 # E : clear all but least set bit78and t0, t1, t0 # E :79and t0, t3, t1 # E : bit set iff byte was the char80addq v0, a2, v0 # E : Add in the bit number from above8182cmoveq t1, $31, v0 # E : Two mapping slots, latency = 283nop84nop85ret # L0 :8687.end strchr888990