strcmp.S 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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 strcmp(const char *cs, const char *ct) */
  7. SYM_FUNC_START(strcmp)
  8. ALTERNATIVE("nop", "j strcmp_zbb", 0, RISCV_ISA_EXT_ZBB, CONFIG_RISCV_ISA_ZBB)
  9. /*
  10. * Returns
  11. * a0 - comparison result, value like strcmp
  12. *
  13. * Parameters
  14. * a0 - string1
  15. * a1 - string2
  16. *
  17. * Clobbers
  18. * t0, t1
  19. */
  20. 1:
  21. lbu t0, 0(a0)
  22. lbu t1, 0(a1)
  23. addi a0, a0, 1
  24. addi a1, a1, 1
  25. bne t0, t1, 2f
  26. bnez t0, 1b
  27. li a0, 0
  28. ret
  29. 2:
  30. /*
  31. * strcmp only needs to return (< 0, 0, > 0) values
  32. * not necessarily -1, 0, +1
  33. */
  34. sub a0, t0, t1
  35. ret
  36. /*
  37. * Variant of strcmp using the ZBB extension if available.
  38. * The code was published as part of the bitmanip manual
  39. * in Appendix A.
  40. */
  41. #ifdef CONFIG_RISCV_ISA_ZBB
  42. strcmp_zbb:
  43. .option push
  44. .option arch,+zbb
  45. /*
  46. * Returns
  47. * a0 - comparison result, value like strcmp
  48. *
  49. * Parameters
  50. * a0 - string1
  51. * a1 - string2
  52. *
  53. * Clobbers
  54. * t0, t1, t2, t3, t4
  55. */
  56. or t2, a0, a1
  57. li t4, -1
  58. and t2, t2, SZREG-1
  59. bnez t2, 3f
  60. /* Main loop for aligned string. */
  61. .p2align 3
  62. 1:
  63. REG_L t0, 0(a0)
  64. REG_L t1, 0(a1)
  65. orc.b t3, t0
  66. bne t3, t4, 2f
  67. addi a0, a0, SZREG
  68. addi a1, a1, SZREG
  69. beq t0, t1, 1b
  70. /*
  71. * Words don't match, and no null byte in the first
  72. * word. Get bytes in big-endian order and compare.
  73. */
  74. #ifndef CONFIG_CPU_BIG_ENDIAN
  75. rev8 t0, t0
  76. rev8 t1, t1
  77. #endif
  78. /* Synthesize (t0 >= t1) ? 1 : -1 in a branchless sequence. */
  79. sltu a0, t0, t1
  80. neg a0, a0
  81. ori a0, a0, 1
  82. ret
  83. 2:
  84. /*
  85. * Found a null byte.
  86. * If words don't match, fall back to simple loop.
  87. */
  88. bne t0, t1, 3f
  89. /* Otherwise, strings are equal. */
  90. li a0, 0
  91. ret
  92. /* Simple loop for misaligned strings. */
  93. .p2align 3
  94. 3:
  95. lbu t0, 0(a0)
  96. lbu t1, 0(a1)
  97. addi a0, a0, 1
  98. addi a1, a1, 1
  99. bne t0, t1, 4f
  100. bnez t0, 3b
  101. 4:
  102. sub a0, t0, t1
  103. ret
  104. .option pop
  105. #endif
  106. SYM_FUNC_END(strcmp)
  107. SYM_FUNC_ALIAS(__pi_strcmp, strcmp)
  108. EXPORT_SYMBOL(strcmp)