diff options
Diffstat (limited to 'newlib/libc/machine/riscv/strcmp.S')
-rw-r--r-- | newlib/libc/machine/riscv/strcmp.S | 207 |
1 files changed, 127 insertions, 80 deletions
diff --git a/newlib/libc/machine/riscv/strcmp.S b/newlib/libc/machine/riscv/strcmp.S index 12c39db..0b1dfc4 100644 --- a/newlib/libc/machine/riscv/strcmp.S +++ b/newlib/libc/machine/riscv/strcmp.S @@ -16,15 +16,15 @@ .type strcmp, @function strcmp: #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) -1: +.Lcompare: lbu a2, 0(a0) lbu a3, 0(a1) - add a0, a0, 1 - add a1, a1, 1 - bne a2, a3, 2f - bnez a2, 1b + addi a0, a0, 1 + addi a1, a1, 1 + bne a2, a3, .Lreturn_diff + bnez a2, .Lcompare -2: +.Lreturn_diff: sub a0, a2, a3 ret @@ -48,12 +48,16 @@ strcmp: REG_L a2, \i*SZREG(a0) REG_L a3, \i*SZREG(a1) - and t0, a2, a5 - or t1, a2, a5 - add t0, t0, a5 - or t0, t0, t1 + #if __riscv_zbb + orc.b a4, a2 + #else + and a4, a2, a5 + or t1, a2, a5 + add a4, a4, a5 + or a4, a4, t1 + #endif - bne t0, t2, .Lnull\i + bne a4, t2, .Lnull\i .if \i+1-\n bne a2, a3, .Lmismatch .else @@ -95,73 +99,109 @@ strcmp: .Lmismatch: # words don't match, but a2 has no null byte. + #if __riscv_zbb + xor a4, a2, a3 # find differing bits + + # Check system endianness + # If little-endian, use Count Trailing Zeros (ctz) + # If big-endian, use Count Leading Zeros (clz) + # This helps identify the position of the first differing byte between a2 and a3. + + # For example, in little-endian, least significant byte comes first. + # So trailing zeros help find which byte position differs. + + # In big-endian, most significant byte comes first, so leading zeros are used. + # The position will then be used to extract the differing byte. + + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + ctz a5, a4 + #else + clz a5, a4 + #endif + + andi a5, a5, -8 # find position of bit offset to the start of the byte where the first difference occurs + + + # Shift a2 and a3 right by a5 bits to bring the target byte to the LSB, and isolate the byte of interest + srl a2, a2, a5 + and a2, a2, 0xff + + srl a3, a3, a5 + and a3, a3, 0xff + + + sub a0, a2, a3 # Calculate and return the difference in the isolated bytes + ret + + #else + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #if __riscv_xlen == 64 + sll a4, a2, 48 + sll a5, a3, 48 + bne a4, a5, .Lmismatch_upper + sll a4, a2, 32 + sll a5, a3, 32 + bne a4, a5, .Lmismatch_upper + #endif + sll a4, a2, 16 + sll a5, a3, 16 + bne a4, a5, .Lmismatch_upper + + srl a4, a2, 8*SZREG-16 + srl a5, a3, 8*SZREG-16 + sub a0, a4, a5 + and a1, a0, 0xff + bnez a1, .Lfinal_upper_diff + ret -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - -#if __riscv_xlen == 64 - sll a4, a2, 48 - sll a5, a3, 48 - bne a4, a5, .Lmismatch_upper - sll a4, a2, 32 - sll a5, a3, 32 - bne a4, a5, .Lmismatch_upper -#endif - sll a4, a2, 16 - sll a5, a3, 16 - bne a4, a5, .Lmismatch_upper - - srl a4, a2, 8*SZREG-16 - srl a5, a3, 8*SZREG-16 - sub a0, a4, a5 - and a1, a0, 0xff - bnez a1, 1f - ret - -.Lmismatch_upper: - srl a4, a4, 8*SZREG-16 - srl a5, a5, 8*SZREG-16 - sub a0, a4, a5 - and a1, a0, 0xff - bnez a1, 1f - ret - -1:and a4, a4, 0xff - and a5, a5, 0xff - sub a0, a4, a5 - ret - -#else - -#if __riscv_xlen == 64 - srl a4, a2, 48 - srl a5, a3, 48 - bne a4, a5, .Lmismatch_lower - srl a4, a2, 32 - srl a5, a3, 32 - bne a4, a5, .Lmismatch_lower -#endif - srl a4, a2, 16 - srl a5, a3, 16 - bne a4, a5, .Lmismatch_lower - - srl a4, a2, 8 - srl a5, a3, 8 - bne a4, a5, 1f - and a4, a2, 0xff - and a5, a3, 0xff -1:sub a0, a4, a5 - ret - -.Lmismatch_lower: - srl a2, a4, 8 - srl a3, a5, 8 - bne a2, a3, 1f - and a2, a4, 0xff - and a3, a5, 0xff -1:sub a0, a2, a3 - ret - -#endif + .Lmismatch_upper: + srl a4, a4, 8*SZREG-16 + srl a5, a5, 8*SZREG-16 + sub a0, a4, a5 + and a1, a0, 0xff + bnez a1, .Lfinal_upper_diff + ret + + .Lfinal_upper_diff: + and a4, a4, 0xff + and a5, a5, 0xff + sub a0, a4, a5 + ret + #else + #if __riscv_xlen == 64 + srl a4, a2, 48 + srl a5, a3, 48 + bne a4, a5, .Lmismatch_lower + srl a4, a2, 32 + srl a5, a3, 32 + bne a4, a5, .Lmismatch_lower + #endif + srl a4, a2, 16 + srl a5, a3, 16 + bne a4, a5, .Lmismatch_lower + + srl a4, a2, 8 + srl a5, a3, 8 + bne a4, a5, .Lbyte_diff + and a4, a2, 0xff + and a5, a3, 0xff + + .Lbyte_diff: + sub a0, a4, a5 + ret + + .Lmismatch_lower: + srl a2, a4, 8 + srl a3, a5, 8 + bne a2, a3, .Lfinal_lower_diff + and a2, a4, 0xff + and a3, a5, 0xff + + .Lfinal_lower_diff: + sub a0, a2, a3 + ret + #endif + #endif .Lmisaligned: # misaligned @@ -169,10 +209,10 @@ strcmp: lbu a3, 0(a1) add a0, a0, 1 add a1, a1, 1 - bne a2, a3, 1f + bne a2, a3, .Lmisaligned_diff bnez a2, .Lmisaligned -1: +.Lmisaligned_diff: sub a0, a2, a3 ret @@ -188,9 +228,16 @@ strcmp: foundnull 1 3 foundnull 2 3 #endif +#ifdef __riscv_cmodel_large + # Put the data within the funciton for large code model to prevent + # the data put too far. +.align 3 +mask: +.dword 0x7f7f7f7f7f7f7f7f +#endif .size strcmp, .-strcmp -#if SZREG == 8 +#if SZREG == 8 && !defined(__riscv_cmodel_large) .section .srodata.cst8,"aM",@progbits,8 .align 3 mask: |