strlen.S 2.1 KB

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