strncmp.S 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. #include <linux/linkage.h>
  3. #include <asm/asm.h>
  4. #include <asm/alternative-macros.h>
  5. #include <asm/hwcap.h>
  6. /* int strncmp(const char *cs, const char *ct, size_t count) */
  7. SYM_FUNC_START(strncmp)
  8. ALTERNATIVE("nop", "j strncmp_zbb", 0, RISCV_ISA_EXT_ZBB, CONFIG_RISCV_ISA_ZBB)
  9. /*
  10. * Returns
  11. * a0 - comparison result, value like strncmp
  12. *
  13. * Parameters
  14. * a0 - string1
  15. * a1 - string2
  16. * a2 - number of characters to compare
  17. *
  18. * Clobbers
  19. * t0, t1, t2
  20. */
  21. li t2, 0
  22. 1:
  23. beq a2, t2, 2f
  24. lbu t0, 0(a0)
  25. lbu t1, 0(a1)
  26. addi a0, a0, 1
  27. addi a1, a1, 1
  28. bne t0, t1, 3f
  29. addi t2, t2, 1
  30. bnez t0, 1b
  31. 2:
  32. li a0, 0
  33. ret
  34. 3:
  35. /*
  36. * strncmp only needs to return (< 0, 0, > 0) values
  37. * not necessarily -1, 0, +1
  38. */
  39. sub a0, t0, t1
  40. ret
  41. /*
  42. * Variant of strncmp using the ZBB extension if available
  43. */
  44. #ifdef CONFIG_RISCV_ISA_ZBB
  45. strncmp_zbb:
  46. .option push
  47. .option arch,+zbb
  48. /*
  49. * Returns
  50. * a0 - comparison result, like strncmp
  51. *
  52. * Parameters
  53. * a0 - string1
  54. * a1 - string2
  55. * a2 - number of characters to compare
  56. *
  57. * Clobbers
  58. * t0, t1, t2, t3, t4, t5, t6
  59. */
  60. or t2, a0, a1
  61. li t5, -1
  62. and t2, t2, SZREG-1
  63. add t4, a0, a2
  64. bnez t2, 3f
  65. /* Adjust limit for fast-path. */
  66. andi t6, t4, -SZREG
  67. /* Main loop for aligned string. */
  68. .p2align 3
  69. 1:
  70. bge a0, t6, 3f
  71. REG_L t0, 0(a0)
  72. REG_L t1, 0(a1)
  73. orc.b t3, t0
  74. bne t3, t5, 2f
  75. orc.b t3, t1
  76. bne t3, t5, 2f
  77. addi a0, a0, SZREG
  78. addi a1, a1, SZREG
  79. beq t0, t1, 1b
  80. /*
  81. * Words don't match, and no null byte in the first
  82. * word. Get bytes in big-endian order and compare.
  83. */
  84. #ifndef CONFIG_CPU_BIG_ENDIAN
  85. rev8 t0, t0
  86. rev8 t1, t1
  87. #endif
  88. /* Synthesize (t0 >= t1) ? 1 : -1 in a branchless sequence. */
  89. sltu a0, t0, t1
  90. neg a0, a0
  91. ori a0, a0, 1
  92. ret
  93. 2:
  94. /*
  95. * Found a null byte.
  96. * If words don't match, fall back to simple loop.
  97. */
  98. bne t0, t1, 3f
  99. /* Otherwise, strings are equal. */
  100. li a0, 0
  101. ret
  102. /* Simple loop for misaligned strings. */
  103. .p2align 3
  104. 3:
  105. bge a0, t4, 5f
  106. lbu t0, 0(a0)
  107. lbu t1, 0(a1)
  108. addi a0, a0, 1
  109. addi a1, a1, 1
  110. bne t0, t1, 4f
  111. bnez t0, 3b
  112. 4:
  113. sub a0, t0, t1
  114. ret
  115. 5:
  116. li a0, 0
  117. ret
  118. .option pop
  119. #endif
  120. SYM_FUNC_END(strncmp)
  121. SYM_FUNC_ALIAS(__pi_strncmp, strncmp)
  122. EXPORT_SYMBOL(strncmp)