strlen.S 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * linux/arch/m32r/strlen.S -- strlen code.
  3. *
  4. * Copyright (C) 2001 Hirokazu Takata
  5. *
  6. * size_t strlen(const char *s);
  7. *
  8. */
  9. /* $Id$ */
  10. #include <linux/linkage.h>
  11. #include <asm/assembler.h>
  12. #ifdef CONFIG_ISA_DUAL_ISSUE
  13. .text
  14. ENTRY(strlen)
  15. mv r6, r0 || ldi r2, #0
  16. and3 r0, r0, #3
  17. bnez r0, strlen_byte
  18. ;
  19. strlen_word:
  20. ld r0, @r6+
  21. ;
  22. seth r5, #high(0x01010101)
  23. or3 r5, r5, #low(0x01010101)
  24. sll3 r7, r5, #7
  25. strlen_word_loop:
  26. ld r1, @r6+ || not r4, r0
  27. sub r0, r5 || and r4, r7
  28. and r4, r0
  29. bnez r4, strlen_last_bytes
  30. ld r0, @r6+ || not r4, r1
  31. sub r1, r5 || and r4, r7
  32. and r4, r1 || addi r2, #4
  33. bnez r4, strlen_last_bytes
  34. addi r2, #4 || bra.s strlen_word_loop
  35. ; NOTE: If a null char. exists, return 0.
  36. ; if ((x - 0x01010101) & ~x & 0x80808080)
  37. ; return 0;
  38. ;
  39. strlen_byte:
  40. ldb r1, @r6 || addi r6, #1
  41. beqz r1, strlen_exit
  42. addi r2, #1 || bra.s strlen_byte
  43. ;
  44. strlen_last_bytes:
  45. ldi r0, #4 || addi r6, #-8
  46. ;
  47. strlen_byte_loop:
  48. ldb r1, @r6 || addi r6, #1
  49. addi r0, #-1 || cmpz r1
  50. bc.s strlen_exit || cmpz r0
  51. addi r2, #1 || bnc.s strlen_byte_loop
  52. ;
  53. strlen_exit:
  54. mv r0, r2 || jmp r14
  55. #else /* not CONFIG_ISA_DUAL_ISSUE */
  56. .text
  57. ENTRY(strlen)
  58. mv r6, r0
  59. ldi r2, #0
  60. and3 r0, r0, #3
  61. bnez r0, strlen_byte
  62. ;
  63. strlen_word:
  64. ld r0, @r6+
  65. ;
  66. seth r5, #high(0x01010101)
  67. or3 r5, r5, #low(0x01010101)
  68. sll3 r7, r5, #7
  69. strlen_word_loop:
  70. ld r1, @r6+
  71. not r4, r0 ; NOTE: If a null char. exists, return 0.
  72. sub r0, r5 ; if ((x - 0x01010101) & ~x & 0x80808080)
  73. and r4, r7 ; return 0;
  74. and r4, r0
  75. bnez r4, strlen_last_bytes
  76. addi r2, #4
  77. ;
  78. ld r0, @r6+
  79. not r4, r1 ; NOTE: If a null char. exists, return 0.
  80. sub r1, r5 ; if ((x - 0x01010101) & ~x & 0x80808080)
  81. and r4, r7 ; return 0;
  82. and r4, r1
  83. bnez r4, strlen_last_bytes
  84. addi r2, #4
  85. bra strlen_word_loop
  86. ;
  87. strlen_byte:
  88. ldb r1, @r6
  89. addi r6, #1
  90. beqz r1, strlen_exit
  91. addi r2, #1
  92. bra strlen_byte
  93. ;
  94. strlen_last_bytes:
  95. ldi r0, #4
  96. addi r6, #-8
  97. ;
  98. strlen_byte_loop:
  99. ldb r1, @r6
  100. addi r6, #1
  101. addi r0, #-1
  102. beqz r1, strlen_exit
  103. addi r2, #1
  104. bnez r0, strlen_byte_loop
  105. ;
  106. strlen_exit:
  107. mv r0, r2
  108. jmp r14
  109. #endif /* not CONFIG_ISA_DUAL_ISSUE */
  110. .end