ev67-strchr.S 2.8 KB

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