summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m32r/lib/strlen.S')
-rw-r--r--arch/m32r/lib/strlen.S120
1 files changed, 120 insertions, 0 deletions
diff --git a/arch/m32r/lib/strlen.S b/arch/m32r/lib/strlen.S
new file mode 100644
index 000000000000..8d23cfbd600c
--- /dev/null
+++ b/arch/m32r/lib/strlen.S
@@ -0,0 +1,120 @@
1/*
2 * linux/arch/m32r/strlen.S -- strlen code.
3 *
4 * Copyright (C) 2001 Hirokazu Takata
5 *
6 * size_t strlen(const char *s);
7 *
8 */
9/* $Id$ */
10
11
12#include <linux/config.h>
13#include <linux/linkage.h>
14#include <asm/assembler.h>
15
16#ifdef CONFIG_ISA_DUAL_ISSUE
17
18 .text
19ENTRY(strlen)
20 mv r6, r0 || ldi r2, #0
21 and3 r0, r0, #3
22 bnez r0, strlen_byte
23;
24strlen_word:
25 ld r0, @r6+
26;
27 seth r5, #high(0x01010101)
28 or3 r5, r5, #low(0x01010101)
29 sll3 r7, r5, #7
30strlen_word_loop:
31 ld r1, @r6+ || not r4, r0
32 sub r0, r5 || and r4, r7
33 and r4, r0
34 bnez r4, strlen_last_bytes
35 ld r0, @r6+ || not r4, r1
36 sub r1, r5 || and r4, r7
37 and r4, r1 || addi r2, #4
38 bnez r4, strlen_last_bytes
39 addi r2, #4 || bra.s strlen_word_loop
40
41 ; NOTE: If a null char. exists, return 0.
42 ; if ((x - 0x01010101) & ~x & 0x80808080)
43 ; return 0;
44;
45strlen_byte:
46 ldb r1, @r6 || addi r6, #1
47 beqz r1, strlen_exit
48 addi r2, #1 || bra.s strlen_byte
49;
50strlen_last_bytes:
51 ldi r0, #4 || addi r6, #-8
52;
53strlen_byte_loop:
54 ldb r1, @r6 || addi r6, #1
55 addi r0, #-1 || cmpz r1
56 bc.s strlen_exit || cmpz r0
57 addi r2, #1 || bnc.s strlen_byte_loop
58;
59strlen_exit:
60 mv r0, r2 || jmp r14
61
62#else /* not CONFIG_ISA_DUAL_ISSUE */
63
64 .text
65ENTRY(strlen)
66 mv r6, r0
67 ldi r2, #0
68 and3 r0, r0, #3
69 bnez r0, strlen_byte
70;
71strlen_word:
72 ld r0, @r6+
73;
74 seth r5, #high(0x01010101)
75 or3 r5, r5, #low(0x01010101)
76 sll3 r7, r5, #7
77strlen_word_loop:
78 ld r1, @r6+
79 not r4, r0 ; NOTE: If a null char. exists, return 0.
80 sub r0, r5 ; if ((x - 0x01010101) & ~x & 0x80808080)
81 and r4, r7 ; return 0;
82 and r4, r0
83 bnez r4, strlen_last_bytes
84 addi r2, #4
85;
86 ld r0, @r6+
87 not r4, r1 ; NOTE: If a null char. exists, return 0.
88 sub r1, r5 ; if ((x - 0x01010101) & ~x & 0x80808080)
89 and r4, r7 ; return 0;
90 and r4, r1
91 bnez r4, strlen_last_bytes
92 addi r2, #4
93 bra strlen_word_loop
94;
95strlen_byte:
96 ldb r1, @r6
97 addi r6, #1
98 beqz r1, strlen_exit
99 addi r2, #1
100 bra strlen_byte
101;
102strlen_last_bytes:
103 ldi r0, #4
104 addi r6, #-8
105;
106strlen_byte_loop:
107 ldb r1, @r6
108 addi r6, #1
109 addi r0, #-1
110 beqz r1, strlen_exit
111 addi r2, #1
112 bnez r0, strlen_byte_loop
113;
114strlen_exit:
115 mv r0, r2
116 jmp r14
117
118#endif /* not CONFIG_ISA_DUAL_ISSUE */
119
120 .end