ev67-strchr.S 2.8 KB

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