strchr.S 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. ! Copyright (C) 2013 Imagination Technologies Ltd.
  2. ! Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
  3. #include <features.h>
  4. .text
  5. .global _strchr
  6. .type _strchr, function
  7. ! D1Ar1 src
  8. ! D0Ar2 c
  9. _strchr:
  10. AND D0Ar2,D0Ar2,#0xff ! Drop all but 8 bits of c
  11. MOV D1Ar5, D1Ar1 ! Copy src to D1Ar5
  12. AND D1Ar5, D1Ar5, #7 ! Check 64 bit alignment
  13. CMP D1Ar5, #0
  14. BZ $Laligned64bit ! Jump to 64 bit aligned strchr
  15. $Lalign64bit:
  16. GETB D0Re0, [D1Ar1++] ! Get the next character
  17. ADD D1Ar5, D1Ar5, #1 ! Increment alignment counter
  18. CMP D0Re0, D0Ar2 ! Is the char c
  19. BZ $Lcharatprevious ! If so exit returning position
  20. CMP D0Re0, #0 ! End of string?
  21. BZ $Lnotfound ! If so exit
  22. CMP D1Ar5, #8 ! Are we aligned 64bit yet?
  23. BNZ $Lalign64bit ! If not keep aligning
  24. $Laligned64bit: ! src is 64bit aligned
  25. MOV D0Ar4, D0Ar2 ! put c into D0Ar4
  26. LSL D0Ar4, D0Ar4, #8 ! Shift it up
  27. ADD D0Ar4, D0Ar4, D0Ar2 ! another c
  28. LSL D0Ar4, D0Ar4, #8 ! shift
  29. ADD D0Ar4, D0Ar4, D0Ar2 ! another c
  30. LSL D0Ar4, D0Ar4, #8 ! shift
  31. ADD D0Ar4, D0Ar4, D0Ar2 ! 4 copies of c
  32. $Lcheck8bytes:
  33. GETL D0Re0, D1Re0, [D1Ar1++] ! grab 16 bytes
  34. MOV A0.3, D0Re0 ! save for later use
  35. ! first word
  36. ! check for \0
  37. MOV D0Ar2, D0Re0 ! D0Ar2 is a scratch now
  38. ADDT D0Re0, D0Re0, #HI(0xfefefeff) ! Do 4 1-byte compares
  39. ADD D0Re0, D0Re0, #LO(0xfefefeff)
  40. XOR D0Ar2, D0Ar2, #-1
  41. AND D0Re0, D0Re0, D0Ar2
  42. ANDMT D0Re0, D0Re0, #HI(0x80808080)
  43. ANDMB D0Re0, D0Re0, #LO(0x80808080)
  44. CMP D0Re0, #0
  45. BNZ $Lnullinword1 ! found \0 (or c if c==\0)
  46. ! Check for c
  47. MOV D0Re0, A0.3 ! restore the first word
  48. XOR D0Re0, D0Re0, D0Ar4
  49. MOV D0Ar2, D0Re0 ! DO 4 1-byte compares
  50. ADDT D0Re0, D0Re0, #HI(0xfefefeff)
  51. ADD D0Re0, D0Re0, #LO(0xfefefeff)
  52. XOR D0Ar2, D0Ar2, #-1
  53. AND D0Re0, D0Re0, D0Ar2
  54. ANDMT D0Re0, D0Re0, #HI(0x80808080)
  55. ANDMB D0Re0, D0Re0, #LO(0x80808080)
  56. CMP D0Re0, #0
  57. BNZ $Lcharinword1 ! found c
  58. ! second word
  59. ! check for \0
  60. MOV A0.3, D1Re0 ! save for later use
  61. MOV D1Ar3, D1Re0
  62. ADDT D1Re0, D1Re0, #HI(0xfefefeff) ! Do 4 1-byte compares
  63. ADD D1Re0, D1Re0, #LO(0xfefefeff)
  64. XOR D1Ar3, D1Ar3, #-1
  65. AND D1Re0, D1Re0, D1Ar3
  66. ANDMT D1Re0, D1Re0, #HI(0x80808080)
  67. ANDMB D1Re0, D1Re0, #LO(0x80808080)
  68. CMP D1Re0, #0
  69. BNZ $Lnullinword2 ! Found \0 (or c if c==\0)
  70. MOV D0.4, A0.3 ! restore the second word
  71. XOR D1Re0, D0.4, D0Ar4 ! test c
  72. MOV D1Ar3, D1Re0
  73. ADDT D1Re0, D1Re0, #HI(0xfefefeff) ! Do 4 1-byte compares
  74. ADD D1Re0, D1Re0, #LO(0xfefefeff)
  75. XOR D1Ar3, D1Ar3, #-1
  76. AND D1Re0, D1Re0, D1Ar3
  77. ANDMT D1Re0, D1Re0, #HI(0x80808080)
  78. ANDMB D1Re0, D1Re0, #LO(0x80808080)
  79. CMP D1Re0, #0
  80. BNZ $Lcharinword2 ! found c
  81. B $Lcheck8bytes ! Keep checking
  82. $Lnullinword1: ! found \0 somewhere, check for c too
  83. SUB D1Ar1, D1Ar1, #4
  84. $Lnullinword2:
  85. SUB D1Ar1, D1Ar1, #4
  86. AND D0Ar2, D0Ar4, #0xff ! restore c
  87. MOV D0Re0, A0.3 ! restore the word
  88. MOV D0.4, D0Re0 ! for shifting later
  89. AND D0Re0, D0Re0, #0xff ! take first byte of word
  90. CMP D0Re0, D0Ar2
  91. BZ $Lcharatcurrent ! found c
  92. CMP D0Re0, #0!
  93. BZ $Lnotfound ! found \0
  94. ADD D1Ar1, D1Ar1, #1
  95. LSR D0.4, D0.4, #8
  96. MOV D0Re0, D0.4
  97. AND D0Re0, D0Re0, #0xff ! take second byte of word
  98. CMP D0Re0, D0Ar2
  99. BZ $Lcharatcurrent ! found c
  100. CMP D0Re0, #0
  101. BZ $Lnotfound ! found \0
  102. ADD D1Ar1, D1Ar1, #1
  103. LSR D0.4, D0.4, #8
  104. MOV D0Re0, D0.4
  105. AND D0Re0, D0Re0, #0xff ! take third byte of word
  106. CMP D0Re0, D0Ar2
  107. BZ $Lcharatcurrent ! found c
  108. CMP D0Re0, #0
  109. BZ $Lnotfound ! found \0
  110. ADD D1Ar1, D1Ar1, #1 ! move to 4th byte
  111. CMP D0Ar2, #0 ! If c was \0
  112. BZ $Lcharatcurrent ! c has been found!
  113. $Lnotfound:
  114. MOV D0Re0, #0 ! End of string c not found
  115. B $Lend
  116. $Lcharinword1: ! found c in first word
  117. MOV D1Re0, D0Re0
  118. SUB D1Ar1, D1Ar1, #4
  119. $Lcharinword2: ! found c in second word
  120. SUB D1Ar1, D1Ar1, #4
  121. AND D0Re0, D1Re0, #0xff ! First byte
  122. CMP D0Re0, #0 ! Test c (zero indicates c due
  123. ! to the 4 1-byte compare code)
  124. BNE $Lcharatcurrent
  125. ADD D1Ar1, D1Ar1, #1
  126. LSR D1Re0, D1Re0, #8
  127. AND D0Re0, D1Re0, #0xff ! Second byte
  128. CMP D0Re0, #0 ! Test c (indicated by zero)
  129. BNE $Lcharatcurrent
  130. ADD D1Ar1, D1Ar1, #1
  131. LSR D1Re0, D1Re0, #8
  132. AND D0Re0, D1Re0, #0xff ! Third byte
  133. CMP D0Re0, #0 ! Test c (indicated by zero)
  134. BNE $Lcharatcurrent
  135. ADD D1Ar1, D1Ar1, #1 ! Must be the fourth byte
  136. B $Lcharatcurrent
  137. $Lcharatprevious:
  138. SUB D1Ar1, D1Ar1, #1 ! Fix-up pointer
  139. $Lcharatcurrent:
  140. MOV D0Re0, D1Ar1 ! Return the string pointer
  141. $Lend:
  142. MOV PC, D1RtP
  143. .size _strchr,.-_strchr
  144. libc_hidden_def(strchr)
  145. #ifdef __UCLIBC_SUSV3_LEGACY__
  146. strong_alias(strchr,index)
  147. #endif