strlen.S 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /* Optimized strlen for Xtensa.
  2. Copyright (C) 2001, 2007 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, write to the Free
  14. Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
  15. Boston, MA 02110-1301, USA. */
  16. #include "../../sysdeps/linux/xtensa/sysdep.h"
  17. #include <bits/xtensa-config.h>
  18. #ifdef __XTENSA_EB__
  19. #define MASK0 0xff000000
  20. #define MASK1 0x00ff0000
  21. #define MASK2 0x0000ff00
  22. #define MASK3 0x000000ff
  23. #else
  24. #define MASK0 0x000000ff
  25. #define MASK1 0x0000ff00
  26. #define MASK2 0x00ff0000
  27. #define MASK3 0xff000000
  28. #endif
  29. .text
  30. ENTRY (strlen)
  31. /* a2 = s */
  32. addi a3, a2, -4 // because we overincrement at the end
  33. movi a4, MASK0
  34. movi a5, MASK1
  35. movi a6, MASK2
  36. movi a7, MASK3
  37. bbsi.l a2, 0, .L1mod2
  38. bbsi.l a2, 1, .L2mod4
  39. j .Laligned
  40. .L1mod2: // address is odd
  41. l8ui a8, a3, 4 // get byte 0
  42. addi a3, a3, 1 // advance string pointer
  43. beqz a8, .Lz3 // if byte 0 is zero
  44. bbci.l a3, 1, .Laligned // if string pointer is now word-aligned
  45. .L2mod4: // address is 2 mod 4
  46. addi a3, a3, 2 // advance ptr for aligned access
  47. l32i a8, a3, 0 // get word with first two bytes of string
  48. bnone a8, a6, .Lz2 // if byte 2 (of word, not string) is zero
  49. bany a8, a7, .Laligned // if byte 3 (of word, not string) is nonzero
  50. /* Byte 3 is zero. */
  51. addi a3, a3, 3 // point to zero byte
  52. sub a2, a3, a2 // subtract to get length
  53. retw
  54. /* String is word-aligned. */
  55. .align 4
  56. /* (2 mod 4) alignment for loop instruction */
  57. .Laligned:
  58. #if XCHAL_HAVE_LOOPS
  59. _movi.n a8, 0 // set up for the maximum loop count
  60. loop a8, .Lz3 // loop forever (almost anyway)
  61. #endif
  62. 1: l32i a8, a3, 4 // get next word of string
  63. addi a3, a3, 4 // advance string pointer
  64. bnone a8, a4, .Lz0 // if byte 0 is zero
  65. bnone a8, a5, .Lz1 // if byte 1 is zero
  66. bnone a8, a6, .Lz2 // if byte 2 is zero
  67. #if XCHAL_HAVE_LOOPS
  68. bnone a8, a7, .Lz3 // if byte 3 is zero
  69. #else
  70. bany a8, a7, 1b // repeat if byte 3 is non-zero
  71. #endif
  72. .Lz3: /* Byte 3 is zero. */
  73. addi a3, a3, 3 // point to zero byte
  74. /* Fall through.... */
  75. .Lz0: /* Byte 0 is zero. */
  76. sub a2, a3, a2 // subtract to get length
  77. retw
  78. .Lz1: /* Byte 1 is zero. */
  79. addi a3, a3, 1 // point to zero byte
  80. sub a2, a3, a2 // subtract to get length
  81. retw
  82. .Lz2: /* Byte 2 is zero. */
  83. addi a3, a3, 2 // point to zero byte
  84. sub a2, a3, a2 // subtract to get length
  85. retw
  86. libc_hidden_def (strlen)