[PATCH] m32r: fix and update for gcc-4.0
[linux-2.6.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/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