| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- /* SPDX-License-Identifier: GPL-2.0-only */
- #include <linux/linkage.h>
- #include <asm/asm.h>
- #include <asm/alternative-macros.h>
- #include <asm/hwcap.h>
- /* int strncmp(const char *cs, const char *ct, size_t count) */
- SYM_FUNC_START(strncmp)
- ALTERNATIVE("nop", "j strncmp_zbb", 0, RISCV_ISA_EXT_ZBB, CONFIG_RISCV_ISA_ZBB)
- /*
- * Returns
- * a0 - comparison result, value like strncmp
- *
- * Parameters
- * a0 - string1
- * a1 - string2
- * a2 - number of characters to compare
- *
- * Clobbers
- * t0, t1, t2
- */
- li t2, 0
- 1:
- beq a2, t2, 2f
- lbu t0, 0(a0)
- lbu t1, 0(a1)
- addi a0, a0, 1
- addi a1, a1, 1
- bne t0, t1, 3f
- addi t2, t2, 1
- bnez t0, 1b
- 2:
- li a0, 0
- ret
- 3:
- /*
- * strncmp only needs to return (< 0, 0, > 0) values
- * not necessarily -1, 0, +1
- */
- sub a0, t0, t1
- ret
- /*
- * Variant of strncmp using the ZBB extension if available
- */
- #ifdef CONFIG_RISCV_ISA_ZBB
- strncmp_zbb:
- .option push
- .option arch,+zbb
- /*
- * Returns
- * a0 - comparison result, like strncmp
- *
- * Parameters
- * a0 - string1
- * a1 - string2
- * a2 - number of characters to compare
- *
- * Clobbers
- * t0, t1, t2, t3, t4, t5, t6
- */
- or t2, a0, a1
- li t5, -1
- and t2, t2, SZREG-1
- add t4, a0, a2
- bnez t2, 3f
- /* Adjust limit for fast-path. */
- andi t6, t4, -SZREG
- /* Main loop for aligned string. */
- .p2align 3
- 1:
- bge a0, t6, 3f
- REG_L t0, 0(a0)
- REG_L t1, 0(a1)
- orc.b t3, t0
- bne t3, t5, 2f
- orc.b t3, t1
- bne t3, t5, 2f
- addi a0, a0, SZREG
- addi a1, a1, SZREG
- beq t0, t1, 1b
- /*
- * Words don't match, and no null byte in the first
- * word. Get bytes in big-endian order and compare.
- */
- #ifndef CONFIG_CPU_BIG_ENDIAN
- rev8 t0, t0
- rev8 t1, t1
- #endif
- /* Synthesize (t0 >= t1) ? 1 : -1 in a branchless sequence. */
- sltu a0, t0, t1
- neg a0, a0
- ori a0, a0, 1
- ret
- 2:
- /*
- * Found a null byte.
- * If words don't match, fall back to simple loop.
- */
- bne t0, t1, 3f
- /* Otherwise, strings are equal. */
- li a0, 0
- ret
- /* Simple loop for misaligned strings. */
- .p2align 3
- 3:
- bge a0, t4, 5f
- lbu t0, 0(a0)
- lbu t1, 0(a1)
- addi a0, a0, 1
- addi a1, a1, 1
- bne t0, t1, 4f
- bnez t0, 3b
- 4:
- sub a0, t0, t1
- ret
- 5:
- li a0, 0
- ret
- .option pop
- #endif
- SYM_FUNC_END(strncmp)
- SYM_FUNC_ALIAS(__pi_strncmp, strncmp)
- EXPORT_SYMBOL(strncmp)
|