Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
[pandora-kernel.git] / arch / m32r / lib / strlen.S
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/linkage.h>
13 #include <asm/assembler.h>
14
15 #ifdef CONFIG_ISA_DUAL_ISSUE
16
17         .text
18 ENTRY(strlen)
19         mv      r6, r0              ||  ldi     r2, #0
20         and3    r0, r0, #3
21         bnez    r0, strlen_byte
22 ;
23 strlen_word:
24         ld      r0, @r6+
25 ;
26         seth    r5, #high(0x01010101)
27         or3     r5, r5, #low(0x01010101)
28         sll3    r7, r5, #7
29 strlen_word_loop:
30         ld      r1, @r6+            ||  not     r4, r0
31         sub     r0, r5              ||  and     r4, r7
32         and     r4, r0
33         bnez    r4, strlen_last_bytes
34         ld      r0, @r6+            ||  not     r4, r1
35         sub     r1, r5              ||  and     r4, r7
36         and     r4, r1              ||  addi    r2, #4
37         bnez    r4, strlen_last_bytes
38         addi    r2, #4              ||  bra.s   strlen_word_loop
39
40         ; NOTE: If a null char. exists, return 0.
41         ; if ((x - 0x01010101) & ~x & 0x80808080)
42         ;     return 0;
43 ;
44 strlen_byte:
45         ldb     r1, @r6             ||  addi    r6, #1
46         beqz    r1, strlen_exit
47         addi    r2, #1              ||  bra.s   strlen_byte
48 ;
49 strlen_last_bytes:
50         ldi     r0, #4              ||  addi    r6, #-8
51 ;
52 strlen_byte_loop:
53         ldb     r1, @r6             ||  addi    r6, #1
54         addi    r0, #-1             ||  cmpz    r1
55         bc.s    strlen_exit         ||  cmpz    r0
56         addi    r2, #1              ||  bnc.s   strlen_byte_loop
57 ;
58 strlen_exit:
59         mv      r0, r2              ||  jmp     r14
60
61 #else /* not CONFIG_ISA_DUAL_ISSUE */
62
63         .text
64 ENTRY(strlen)
65         mv      r6, r0
66         ldi     r2, #0
67         and3    r0, r0, #3
68         bnez    r0, strlen_byte
69 ;
70 strlen_word:
71         ld      r0, @r6+
72 ;
73         seth    r5, #high(0x01010101)
74         or3     r5, r5, #low(0x01010101)
75         sll3    r7, r5, #7
76 strlen_word_loop:
77         ld      r1, @r6+
78         not     r4, r0          ; NOTE: If a null char. exists, return 0.
79         sub     r0, r5          ; if ((x - 0x01010101) & ~x & 0x80808080)
80         and     r4, r7          ;     return 0;
81         and     r4, r0
82         bnez    r4, strlen_last_bytes
83         addi    r2, #4
84 ;
85         ld      r0, @r6+
86         not     r4, r1          ; NOTE: If a null char. exists, return 0.
87         sub     r1, r5          ; if ((x - 0x01010101) & ~x & 0x80808080)
88         and     r4, r7          ;     return 0;
89         and     r4, r1
90         bnez    r4, strlen_last_bytes
91         addi    r2, #4
92         bra     strlen_word_loop
93 ;
94 strlen_byte:
95         ldb     r1, @r6
96         addi    r6, #1
97         beqz    r1, strlen_exit
98         addi    r2, #1
99         bra     strlen_byte
100 ;
101 strlen_last_bytes:
102         ldi     r0, #4
103         addi    r6, #-8
104 ;
105 strlen_byte_loop:
106         ldb     r1, @r6
107         addi    r6, #1
108         addi    r0, #-1
109         beqz    r1, strlen_exit
110         addi    r2, #1
111         bnez    r0, strlen_byte_loop
112 ;
113 strlen_exit:
114         mv      r0, r2
115         jmp     r14
116
117 #endif /* not CONFIG_ISA_DUAL_ISSUE */
118
119         .end