strchr.S 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Copyright (C) 2013, 2022 Synopsys, Inc. (www.synopsys.com)
  3. * Copyright (C) 2007 ARC International (UK) LTD
  4. *
  5. * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
  6. */
  7. #include <sysdep.h>
  8. #include <features.h>
  9. #include <asm.h>
  10. /* ARC700 has a relatively long pipeline and branch prediction, so we want
  11. to avoid branches that are hard to predict. On the other hand, the
  12. presence of the norm instruction makes it easier to operate on whole
  13. words branch-free. */
  14. ENTRY(strchr)
  15. extb_s r1,r1
  16. asl r5,r1,8
  17. bmsk r2,r0,1
  18. or r5,r5,r1
  19. mov_s r3,0x01010101
  20. breq.d r2,r0,.Laligned
  21. asl r4,r5,16
  22. SUBR_S r0,r0,r2
  23. asl r7,r2,3
  24. ld_s r2,[r0]
  25. #ifdef __LITTLE_ENDIAN__
  26. asl r7,r3,r7
  27. #else
  28. lsr r7,r3,r7
  29. #endif
  30. or r5,r5,r4
  31. ror r4,r3
  32. sub r12,r2,r7
  33. bic_s r12,r12,r2
  34. and r12,r12,r4
  35. brne.d r12,0,.Lfound0_ua
  36. xor r6,r2,r5
  37. ld.a r2,[r0,4]
  38. sub r12,r6,r7
  39. bic r12,r12,r6
  40. #ifdef __LITTLE_ENDIAN__
  41. and r7,r12,r4
  42. breq r7,0,.Loop ; For speed, we want this branch to be unaligned.
  43. b .Lfound_char ; Likewise this one.
  44. #else
  45. and r12,r12,r4
  46. breq r12,0,.Loop ; For speed, we want this branch to be unaligned.
  47. lsr_s r12,r12,7
  48. bic r2,r7,r6
  49. b.d .Lfound_char_b
  50. and_s r2,r2,r12
  51. #endif
  52. ; /* We require this code address to be unaligned for speed... */
  53. .Laligned:
  54. ld_s r2,[r0]
  55. or r5,r5,r4
  56. ror r4,r3
  57. ; /* ... so that this code address is aligned, for itself and ... */
  58. .Loop:
  59. sub r12,r2,r3
  60. bic_s r12,r12,r2
  61. and r12,r12,r4
  62. brne.d r12,0,.Lfound0
  63. xor r6,r2,r5
  64. ld.a r2,[r0,4]
  65. sub r12,r6,r3
  66. bic r12,r12,r6
  67. and r7,r12,r4
  68. breq r7,0,.Loop /* ... so that this branch is unaligned. */
  69. ; Found searched-for character. r0 has already advanced to next word.
  70. #ifdef __LITTLE_ENDIAN__
  71. /* We only need the information about the first matching byte
  72. (i.e. the least significant matching byte) to be exact,
  73. hence there is no problem with carry effects. */
  74. .Lfound_char:
  75. sub r3,r7,1
  76. bic r3,r3,r7
  77. norm r2,r3
  78. SUBR_S r0,r0,1
  79. ASRR_S r2,r2,3
  80. j.d [blink]
  81. SUBR_S r0,r0,r2
  82. .balign 4
  83. .Lfound0_ua:
  84. mov r3,r7
  85. .Lfound0:
  86. sub r3,r6,r3
  87. bic r3,r3,r6
  88. and r2,r3,r4
  89. or_s r12,r12,r2
  90. SUBR_S r3,r12,1
  91. bic_s r3,r3,r12
  92. norm r3,r3
  93. ADDR_S r0,r0,3
  94. ASRR_S r12,r3,3
  95. asl.f 0,r2,r3
  96. SUBR_S r0,r0,r12
  97. j_s.d [blink]
  98. mov.pl r0,0
  99. #else /* BIG ENDIAN */
  100. .Lfound_char:
  101. lsr r7,r7,7
  102. bic r2,r7,r6
  103. .Lfound_char_b:
  104. norm r2,r2
  105. SUBR_S r0,r0,4
  106. asr_s r2,r2,3
  107. j.d [blink]
  108. ADDR_S r0,r0,r2
  109. .Lfound0_ua:
  110. mov_s r3,r7
  111. .Lfound0:
  112. asl_s r2,r2,7
  113. or r7,r6,r4
  114. bic_s r12,r12,r2
  115. sub r2,r7,r3
  116. or r2,r2,r6
  117. bic r12,r2,r12
  118. bic.f r3,r4,r12
  119. norm r3,r3
  120. add.pl r3,r3,1
  121. asr_s r12,r3,3
  122. asl.f 0,r2,r3
  123. ADDR_S r0,r0,r12
  124. j_s.d [blink]
  125. mov.mi r0,0
  126. #endif /* ENDIAN */
  127. END(strchr)
  128. libc_hidden_def(strchr)
  129. #ifdef __UCLIBC_SUSV3_LEGACY__
  130. strong_alias(strchr,index)
  131. #endif