diff options
Diffstat (limited to 'arch/m32r/lib/strlen.S')
-rw-r--r-- | arch/m32r/lib/strlen.S | 120 |
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 | ||
19 | ENTRY(strlen) | ||
20 | mv r6, r0 || ldi r2, #0 | ||
21 | and3 r0, r0, #3 | ||
22 | bnez r0, strlen_byte | ||
23 | ; | ||
24 | strlen_word: | ||
25 | ld r0, @r6+ | ||
26 | ; | ||
27 | seth r5, #high(0x01010101) | ||
28 | or3 r5, r5, #low(0x01010101) | ||
29 | sll3 r7, r5, #7 | ||
30 | strlen_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 | ; | ||
45 | strlen_byte: | ||
46 | ldb r1, @r6 || addi r6, #1 | ||
47 | beqz r1, strlen_exit | ||
48 | addi r2, #1 || bra.s strlen_byte | ||
49 | ; | ||
50 | strlen_last_bytes: | ||
51 | ldi r0, #4 || addi r6, #-8 | ||
52 | ; | ||
53 | strlen_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 | ; | ||
59 | strlen_exit: | ||
60 | mv r0, r2 || jmp r14 | ||
61 | |||
62 | #else /* not CONFIG_ISA_DUAL_ISSUE */ | ||
63 | |||
64 | .text | ||
65 | ENTRY(strlen) | ||
66 | mv r6, r0 | ||
67 | ldi r2, #0 | ||
68 | and3 r0, r0, #3 | ||
69 | bnez r0, strlen_byte | ||
70 | ; | ||
71 | strlen_word: | ||
72 | ld r0, @r6+ | ||
73 | ; | ||
74 | seth r5, #high(0x01010101) | ||
75 | or3 r5, r5, #low(0x01010101) | ||
76 | sll3 r7, r5, #7 | ||
77 | strlen_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 | ; | ||
95 | strlen_byte: | ||
96 | ldb r1, @r6 | ||
97 | addi r6, #1 | ||
98 | beqz r1, strlen_exit | ||
99 | addi r2, #1 | ||
100 | bra strlen_byte | ||
101 | ; | ||
102 | strlen_last_bytes: | ||
103 | ldi r0, #4 | ||
104 | addi r6, #-8 | ||
105 | ; | ||
106 | strlen_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 | ; | ||
114 | strlen_exit: | ||
115 | mv r0, r2 | ||
116 | jmp r14 | ||
117 | |||
118 | #endif /* not CONFIG_ISA_DUAL_ISSUE */ | ||
119 | |||
120 | .end | ||