Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / arch / m32r / lib / strlen.S
blob41c77e387593804a731351c6edbe3ad8156e1ceb
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  *  linux/arch/m32r/strlen.S --  strlen code.
4  *
5  *  Copyright (C) 2001  Hirokazu Takata
6  *
7  *  size_t strlen(const char *s);
8  *
9  */
11 #include <linux/linkage.h>
12 #include <asm/assembler.h>
14 #ifdef CONFIG_ISA_DUAL_ISSUE
16         .text
17 ENTRY(strlen)
18         mv      r6, r0              ||  ldi     r2, #0
19         and3    r0, r0, #3
20         bnez    r0, strlen_byte
22 strlen_word:
23         ld      r0, @r6+
25         seth    r5, #high(0x01010101)
26         or3     r5, r5, #low(0x01010101)
27         sll3    r7, r5, #7
28 strlen_word_loop:
29         ld      r1, @r6+            ||  not     r4, r0
30         sub     r0, r5              ||  and     r4, r7
31         and     r4, r0
32         bnez    r4, strlen_last_bytes
33         ld      r0, @r6+            ||  not     r4, r1
34         sub     r1, r5              ||  and     r4, r7
35         and     r4, r1              ||  addi    r2, #4
36         bnez    r4, strlen_last_bytes
37         addi    r2, #4              ||  bra.s   strlen_word_loop
39         ; NOTE: If a null char. exists, return 0.
40         ; if ((x - 0x01010101) & ~x & 0x80808080)
41         ;     return 0;
43 strlen_byte:
44         ldb     r1, @r6             ||  addi    r6, #1
45         beqz    r1, strlen_exit
46         addi    r2, #1              ||  bra.s   strlen_byte
48 strlen_last_bytes:
49         ldi     r0, #4              ||  addi    r6, #-8
51 strlen_byte_loop:
52         ldb     r1, @r6             ||  addi    r6, #1
53         addi    r0, #-1             ||  cmpz    r1
54         bc.s    strlen_exit         ||  cmpz    r0
55         addi    r2, #1              ||  bnc.s   strlen_byte_loop
57 strlen_exit:
58         mv      r0, r2              ||  jmp     r14
60 #else /* not CONFIG_ISA_DUAL_ISSUE */
62         .text
63 ENTRY(strlen)
64         mv      r6, r0
65         ldi     r2, #0
66         and3    r0, r0, #3
67         bnez    r0, strlen_byte
69 strlen_word:
70         ld      r0, @r6+
72         seth    r5, #high(0x01010101)
73         or3     r5, r5, #low(0x01010101)
74         sll3    r7, r5, #7
75 strlen_word_loop:
76         ld      r1, @r6+
77         not     r4, r0          ; NOTE: If a null char. exists, return 0.
78         sub     r0, r5          ; if ((x - 0x01010101) & ~x & 0x80808080)
79         and     r4, r7          ;     return 0;
80         and     r4, r0
81         bnez    r4, strlen_last_bytes
82         addi    r2, #4
84         ld      r0, @r6+
85         not     r4, r1          ; NOTE: If a null char. exists, return 0.
86         sub     r1, r5          ; if ((x - 0x01010101) & ~x & 0x80808080)
87         and     r4, r7          ;     return 0;
88         and     r4, r1
89         bnez    r4, strlen_last_bytes
90         addi    r2, #4
91         bra     strlen_word_loop
93 strlen_byte:
94         ldb     r1, @r6
95         addi    r6, #1
96         beqz    r1, strlen_exit
97         addi    r2, #1
98         bra     strlen_byte
100 strlen_last_bytes:
101         ldi     r0, #4
102         addi    r6, #-8
104 strlen_byte_loop:
105         ldb     r1, @r6
106         addi    r6, #1
107         addi    r0, #-1
108         beqz    r1, strlen_exit
109         addi    r2, #1
110         bnez    r0, strlen_byte_loop
112 strlen_exit:
113         mv      r0, r2
114         jmp     r14
116 #endif /* not CONFIG_ISA_DUAL_ISSUE */
118         .end