/* SPDX-License-Identifier: GPL-2.0 */ | |
/* | |
* Taken from Linux arch/riscv/lib/strcmp.S | |
*/ | |
#include <linux/linkage.h> | |
#include <asm/asm.h> | |
ENTRY(__strcmp) | |
WEAK(strcmp) | |
.option push | |
.option arch,+zbb | |
/* | |
* Returns | |
* a0 - comparison result, value like strcmp | |
* | |
* Parameters | |
* a0 - string1 | |
* a1 - string2 | |
* | |
* Clobbers | |
* t0, t1, t2, t3, t4 | |
*/ | |
or t2, a0, a1 | |
li t4, -1 | |
and t2, t2, SZREG-1 | |
bnez t2, 3f | |
/* Main loop for aligned string. */ | |
.p2align 3 | |
1: | |
REG_L t0, 0(a0) | |
REG_L t1, 0(a1) | |
orc.b t3, t0 | |
bne t3, t4, 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. | |
*/ | |
#if __BYTE_ORDER__ == __ORDER_LITTLE_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: | |
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 | |
.option pop | |
END(__strcmp) |