summaryrefslogtreecommitdiff
path: root/arch/arc/lib/strlen.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arc/lib/strlen.S')
-rw-r--r--arch/arc/lib/strlen.S80
1 files changed, 80 insertions, 0 deletions
diff --git a/arch/arc/lib/strlen.S b/arch/arc/lib/strlen.S
new file mode 100644
index 0000000..666e22c
--- /dev/null
+++ b/arch/arc/lib/strlen.S
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2004, 2007-2010, 2011-2014 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+.global strlen
+.align 4
+strlen:
+ or %r3, %r0, 7
+ ld %r2, [%r3, -7]
+ ld.a %r6, [%r3, -3]
+ mov %r4, 0x01010101
+ /* uses long immediate */
+#ifdef __LITTLE_ENDIAN__
+ asl_s %r1, %r0, 3
+ btst_s %r0, 2
+ asl %r7, %r4, %r1
+ ror %r5, %r4
+ sub %r1, %r2, %r7
+ bic_s %r1, %r1, %r2
+ mov.eq %r7, %r4
+ sub %r12, %r6, %r7
+ bic %r12, %r12, %r6
+ or.eq %r12, %r12, %r1
+ and %r12, %r12, %r5
+ brne %r12, 0, .Learly_end
+#else /* __BIG_ENDIAN__ */
+ ror %r5, %r4
+ btst_s %r0, 2
+ mov_s %r1, 31
+ sub3 %r7, %r1, %r0
+ sub %r1, %r2, %r4
+ bic_s %r1, %r1, %r2
+ bmsk %r1, %r1, %r7
+ sub %r12, %r6, %r4
+ bic %r12, %r12, %r6
+ bmsk.ne %r12, %r12, %r7
+ or.eq %r12, %r12, %r1
+ and %r12, %r12, %r5
+ brne %r12, 0, .Learly_end
+#endif /* _ENDIAN__ */
+
+.Loop:
+ ld_s %r2, [%r3, 4]
+ ld.a %r6, [%r3, 8]
+ /* stall for load result */
+ sub %r1, %r2, %r4
+ bic_s %r1, %r1, %r2
+ sub %r12, %r6, %r4
+ bic %r12, %r12, %r6
+ or %r12, %r12, %r1
+ and %r12, %r12, %r5
+ breq %r12, 0, .Loop
+.Lend:
+ and.f %r1, %r1, %r5
+ sub.ne %r3, %r3, 4
+ mov.eq %r1, %r12
+#ifdef __LITTLE_ENDIAN__
+ sub_s %r2, %r1, 1
+ bic_s %r2, %r2, %r1
+ norm %r1, %r2
+ sub_s %r0, %r0, 3
+ lsr_s %r1, %r1, 3
+ sub %r0, %r3, %r0
+ j_s.d [%blink]
+ sub %r0, %r0, %r1
+#else /* __BIG_ENDIAN__ */
+ lsr_s %r1, %r1, 7
+ mov.eq %r2, %r6
+ bic_s %r1, %r1, %r2
+ norm %r1, %r1
+ sub %r0, %r3, %r0
+ lsr_s %r1, %r1, 3
+ j_s.d [%blink]
+ add %r0, %r0, %r1
+#endif /* _ENDIAN */
+.Learly_end:
+ b.d .Lend
+ sub_s.ne %r1, %r1, %r1