xref: /linux/arch/arc/lib/memcmp.S (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
25210d1e6SVineet Gupta/*
35210d1e6SVineet Gupta * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
45210d1e6SVineet Gupta */
55210d1e6SVineet Gupta
6ec7ac6afSVineet Gupta#include <linux/linkage.h>
75210d1e6SVineet Gupta
85210d1e6SVineet Gupta#ifdef __LITTLE_ENDIAN__
95210d1e6SVineet Gupta#define WORD2 r2
105210d1e6SVineet Gupta#define SHIFT r3
115210d1e6SVineet Gupta#else /* BIG ENDIAN */
125210d1e6SVineet Gupta#define WORD2 r3
135210d1e6SVineet Gupta#define SHIFT r2
145210d1e6SVineet Gupta#endif
155210d1e6SVineet Gupta
1686effd0dSVineet GuptaENTRY_CFI(memcmp)
175210d1e6SVineet Gupta	or	r12,r0,r1
185210d1e6SVineet Gupta	asl_s	r12,r12,30
195210d1e6SVineet Gupta	sub	r3,r2,1
205210d1e6SVineet Gupta	brls	r2,r12,.Lbytewise
215210d1e6SVineet Gupta	ld	r4,[r0,0]
225210d1e6SVineet Gupta	ld	r5,[r1,0]
235210d1e6SVineet Gupta	lsr.f	lp_count,r3,3
248922bc30SVineet Gupta#ifdef CONFIG_ISA_ARCV2
258922bc30SVineet Gupta	/* In ARCv2 a branch can't be the last instruction in a zero overhead
268922bc30SVineet Gupta	 * loop.
278922bc30SVineet Gupta	 * So we move the branch to the start of the loop, duplicate it
288922bc30SVineet Gupta	 * after the end, and set up r12 so that the branch isn't taken
298922bc30SVineet Gupta	 *  initially.
308922bc30SVineet Gupta	 */
318922bc30SVineet Gupta	mov_s	r12,WORD2
328922bc30SVineet Gupta	lpne	.Loop_end
338922bc30SVineet Gupta	brne	WORD2,r12,.Lodd
348922bc30SVineet Gupta	ld	WORD2,[r0,4]
358922bc30SVineet Gupta#else
365210d1e6SVineet Gupta	lpne	.Loop_end
375210d1e6SVineet Gupta	ld_s	WORD2,[r0,4]
388922bc30SVineet Gupta#endif
395210d1e6SVineet Gupta	ld_s	r12,[r1,4]
405210d1e6SVineet Gupta	brne	r4,r5,.Leven
415210d1e6SVineet Gupta	ld.a	r4,[r0,8]
425210d1e6SVineet Gupta	ld.a	r5,[r1,8]
438922bc30SVineet Gupta#ifdef CONFIG_ISA_ARCV2
448922bc30SVineet Gupta.Loop_end:
458922bc30SVineet Gupta	brne	WORD2,r12,.Lodd
468922bc30SVineet Gupta#else
475210d1e6SVineet Gupta	brne	WORD2,r12,.Lodd
485210d1e6SVineet Gupta.Loop_end:
498922bc30SVineet Gupta#endif
505210d1e6SVineet Gupta	asl_s	SHIFT,SHIFT,3
515210d1e6SVineet Gupta	bhs_s	.Last_cmp
525210d1e6SVineet Gupta	brne	r4,r5,.Leven
535210d1e6SVineet Gupta	ld	r4,[r0,4]
545210d1e6SVineet Gupta	ld	r5,[r1,4]
555210d1e6SVineet Gupta#ifdef __LITTLE_ENDIAN__
565210d1e6SVineet Gupta	nop_s
575210d1e6SVineet Gupta	; one more load latency cycle
585210d1e6SVineet Gupta.Last_cmp:
595210d1e6SVineet Gupta	xor	r0,r4,r5
605210d1e6SVineet Gupta	bset	r0,r0,SHIFT
615210d1e6SVineet Gupta	sub_s	r1,r0,1
625210d1e6SVineet Gupta	bic_s	r1,r1,r0
635210d1e6SVineet Gupta	norm	r1,r1
645210d1e6SVineet Gupta	b.d	.Leven_cmp
655210d1e6SVineet Gupta	and	r1,r1,24
665210d1e6SVineet Gupta.Leven:
675210d1e6SVineet Gupta	xor	r0,r4,r5
685210d1e6SVineet Gupta	sub_s	r1,r0,1
695210d1e6SVineet Gupta	bic_s	r1,r1,r0
705210d1e6SVineet Gupta	norm	r1,r1
715210d1e6SVineet Gupta	; slow track insn
725210d1e6SVineet Gupta	and	r1,r1,24
735210d1e6SVineet Gupta.Leven_cmp:
745210d1e6SVineet Gupta	asl	r2,r4,r1
755210d1e6SVineet Gupta	asl	r12,r5,r1
765210d1e6SVineet Gupta	lsr_s	r2,r2,1
775210d1e6SVineet Gupta	lsr_s	r12,r12,1
785210d1e6SVineet Gupta	j_s.d	[blink]
795210d1e6SVineet Gupta	sub	r0,r2,r12
805210d1e6SVineet Gupta	.balign	4
815210d1e6SVineet Gupta.Lodd:
825210d1e6SVineet Gupta	xor	r0,WORD2,r12
835210d1e6SVineet Gupta	sub_s	r1,r0,1
845210d1e6SVineet Gupta	bic_s	r1,r1,r0
855210d1e6SVineet Gupta	norm	r1,r1
865210d1e6SVineet Gupta	; slow track insn
875210d1e6SVineet Gupta	and	r1,r1,24
885210d1e6SVineet Gupta	asl_s	r2,r2,r1
895210d1e6SVineet Gupta	asl_s	r12,r12,r1
905210d1e6SVineet Gupta	lsr_s	r2,r2,1
915210d1e6SVineet Gupta	lsr_s	r12,r12,1
925210d1e6SVineet Gupta	j_s.d	[blink]
935210d1e6SVineet Gupta	sub	r0,r2,r12
945210d1e6SVineet Gupta#else /* BIG ENDIAN */
955210d1e6SVineet Gupta.Last_cmp:
965210d1e6SVineet Gupta	neg_s	SHIFT,SHIFT
975210d1e6SVineet Gupta	lsr	r4,r4,SHIFT
985210d1e6SVineet Gupta	lsr	r5,r5,SHIFT
995210d1e6SVineet Gupta	; slow track insn
1005210d1e6SVineet Gupta.Leven:
1015210d1e6SVineet Gupta	sub.f	r0,r4,r5
1025210d1e6SVineet Gupta	mov.ne	r0,1
1035210d1e6SVineet Gupta	j_s.d	[blink]
1045210d1e6SVineet Gupta	bset.cs	r0,r0,31
1055210d1e6SVineet Gupta.Lodd:
1065210d1e6SVineet Gupta	cmp_s	WORD2,r12
1075210d1e6SVineet Gupta	mov_s	r0,1
1085210d1e6SVineet Gupta	j_s.d	[blink]
1095210d1e6SVineet Gupta	bset.cs	r0,r0,31
1105210d1e6SVineet Gupta#endif /* ENDIAN */
1115210d1e6SVineet Gupta	.balign	4
1125210d1e6SVineet Gupta.Lbytewise:
1135210d1e6SVineet Gupta	breq	r2,0,.Lnil
1145210d1e6SVineet Gupta	ldb	r4,[r0,0]
1155210d1e6SVineet Gupta	ldb	r5,[r1,0]
1165210d1e6SVineet Gupta	lsr.f	lp_count,r3
1178922bc30SVineet Gupta#ifdef CONFIG_ISA_ARCV2
1188922bc30SVineet Gupta	mov	r12,r3
1195210d1e6SVineet Gupta	lpne	.Lbyte_end
1208922bc30SVineet Gupta	brne	r3,r12,.Lbyte_odd
1218922bc30SVineet Gupta#else
1228922bc30SVineet Gupta	lpne	.Lbyte_end
1238922bc30SVineet Gupta#endif
1245210d1e6SVineet Gupta	ldb_s	r3,[r0,1]
1255210d1e6SVineet Gupta	ldb	r12,[r1,1]
1265210d1e6SVineet Gupta	brne	r4,r5,.Lbyte_even
1275210d1e6SVineet Gupta	ldb.a	r4,[r0,2]
1285210d1e6SVineet Gupta	ldb.a	r5,[r1,2]
1298922bc30SVineet Gupta#ifdef CONFIG_ISA_ARCV2
1308922bc30SVineet Gupta.Lbyte_end:
1318922bc30SVineet Gupta	brne	r3,r12,.Lbyte_odd
1328922bc30SVineet Gupta#else
1335210d1e6SVineet Gupta	brne	r3,r12,.Lbyte_odd
1345210d1e6SVineet Gupta.Lbyte_end:
1358922bc30SVineet Gupta#endif
1365210d1e6SVineet Gupta	bcc	.Lbyte_even
1375210d1e6SVineet Gupta	brne	r4,r5,.Lbyte_even
1385210d1e6SVineet Gupta	ldb_s	r3,[r0,1]
1395210d1e6SVineet Gupta	ldb_s	r12,[r1,1]
1405210d1e6SVineet Gupta.Lbyte_odd:
1415210d1e6SVineet Gupta	j_s.d	[blink]
1425210d1e6SVineet Gupta	sub	r0,r3,r12
1435210d1e6SVineet Gupta.Lbyte_even:
1445210d1e6SVineet Gupta	j_s.d	[blink]
1455210d1e6SVineet Gupta	sub	r0,r4,r5
1465210d1e6SVineet Gupta.Lnil:
1475210d1e6SVineet Gupta	j_s.d	[blink]
1485210d1e6SVineet Gupta	mov	r0,0
14986effd0dSVineet GuptaEND_CFI(memcmp)
150