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