aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc/machine/riscv/strcmp.S
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/machine/riscv/strcmp.S')
-rw-r--r--newlib/libc/machine/riscv/strcmp.S207
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: