xref: /openbmc/linux/arch/arc/lib/memcmp.S (revision fcc8487d)
1/*
2 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/linkage.h>
10
11#ifdef __LITTLE_ENDIAN__
12#define WORD2 r2
13#define SHIFT r3
14#else /* BIG ENDIAN */
15#define WORD2 r3
16#define SHIFT r2
17#endif
18
19ENTRY_CFI(memcmp)
20	or	r12,r0,r1
21	asl_s	r12,r12,30
22	sub	r3,r2,1
23	brls	r2,r12,.Lbytewise
24	ld	r4,[r0,0]
25	ld	r5,[r1,0]
26	lsr.f	lp_count,r3,3
27#ifdef CONFIG_ISA_ARCV2
28	/* In ARCv2 a branch can't be the last instruction in a zero overhead
29	 * loop.
30	 * So we move the branch to the start of the loop, duplicate it
31	 * after the end, and set up r12 so that the branch isn't taken
32	 *  initially.
33	 */
34	mov_s	r12,WORD2
35	lpne	.Loop_end
36	brne	WORD2,r12,.Lodd
37	ld	WORD2,[r0,4]
38#else
39	lpne	.Loop_end
40	ld_s	WORD2,[r0,4]
41#endif
42	ld_s	r12,[r1,4]
43	brne	r4,r5,.Leven
44	ld.a	r4,[r0,8]
45	ld.a	r5,[r1,8]
46#ifdef CONFIG_ISA_ARCV2
47.Loop_end:
48	brne	WORD2,r12,.Lodd
49#else
50	brne	WORD2,r12,.Lodd
51.Loop_end:
52#endif
53	asl_s	SHIFT,SHIFT,3
54	bhs_s	.Last_cmp
55	brne	r4,r5,.Leven
56	ld	r4,[r0,4]
57	ld	r5,[r1,4]
58#ifdef __LITTLE_ENDIAN__
59	nop_s
60	; one more load latency cycle
61.Last_cmp:
62	xor	r0,r4,r5
63	bset	r0,r0,SHIFT
64	sub_s	r1,r0,1
65	bic_s	r1,r1,r0
66	norm	r1,r1
67	b.d	.Leven_cmp
68	and	r1,r1,24
69.Leven:
70	xor	r0,r4,r5
71	sub_s	r1,r0,1
72	bic_s	r1,r1,r0
73	norm	r1,r1
74	; slow track insn
75	and	r1,r1,24
76.Leven_cmp:
77	asl	r2,r4,r1
78	asl	r12,r5,r1
79	lsr_s	r2,r2,1
80	lsr_s	r12,r12,1
81	j_s.d	[blink]
82	sub	r0,r2,r12
83	.balign	4
84.Lodd:
85	xor	r0,WORD2,r12
86	sub_s	r1,r0,1
87	bic_s	r1,r1,r0
88	norm	r1,r1
89	; slow track insn
90	and	r1,r1,24
91	asl_s	r2,r2,r1
92	asl_s	r12,r12,r1
93	lsr_s	r2,r2,1
94	lsr_s	r12,r12,1
95	j_s.d	[blink]
96	sub	r0,r2,r12
97#else /* BIG ENDIAN */
98.Last_cmp:
99	neg_s	SHIFT,SHIFT
100	lsr	r4,r4,SHIFT
101	lsr	r5,r5,SHIFT
102	; slow track insn
103.Leven:
104	sub.f	r0,r4,r5
105	mov.ne	r0,1
106	j_s.d	[blink]
107	bset.cs	r0,r0,31
108.Lodd:
109	cmp_s	WORD2,r12
110	mov_s	r0,1
111	j_s.d	[blink]
112	bset.cs	r0,r0,31
113#endif /* ENDIAN */
114	.balign	4
115.Lbytewise:
116	breq	r2,0,.Lnil
117	ldb	r4,[r0,0]
118	ldb	r5,[r1,0]
119	lsr.f	lp_count,r3
120#ifdef CONFIG_ISA_ARCV2
121	mov	r12,r3
122	lpne	.Lbyte_end
123	brne	r3,r12,.Lbyte_odd
124#else
125	lpne	.Lbyte_end
126#endif
127	ldb_s	r3,[r0,1]
128	ldb	r12,[r1,1]
129	brne	r4,r5,.Lbyte_even
130	ldb.a	r4,[r0,2]
131	ldb.a	r5,[r1,2]
132#ifdef CONFIG_ISA_ARCV2
133.Lbyte_end:
134	brne	r3,r12,.Lbyte_odd
135#else
136	brne	r3,r12,.Lbyte_odd
137.Lbyte_end:
138#endif
139	bcc	.Lbyte_even
140	brne	r4,r5,.Lbyte_even
141	ldb_s	r3,[r0,1]
142	ldb_s	r12,[r1,1]
143.Lbyte_odd:
144	j_s.d	[blink]
145	sub	r0,r3,r12
146.Lbyte_even:
147	j_s.d	[blink]
148	sub	r0,r4,r5
149.Lnil:
150	j_s.d	[blink]
151	mov	r0,0
152END_CFI(memcmp)
153