 8922bc3058
			
		
	
	
	8922bc3058
	
	
	
		
			
			Branch insn can't be scheduled as last insn of Zero Overhead loop Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
		
			
				
	
	
		
			152 lines
		
	
	
	
		
			2.6 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
	
		
			2.6 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify
 | |
|  * it under the terms of the GNU General Public License version 2 as
 | |
|  * published by the Free Software Foundation.
 | |
|  */
 | |
| 
 | |
| #include <linux/linkage.h>
 | |
| 
 | |
| #ifdef __LITTLE_ENDIAN__
 | |
| #define WORD2 r2
 | |
| #define SHIFT r3
 | |
| #else /* BIG ENDIAN */
 | |
| #define WORD2 r3
 | |
| #define SHIFT r2
 | |
| #endif
 | |
| 
 | |
| ENTRY(memcmp)
 | |
| 	or	r12,r0,r1
 | |
| 	asl_s	r12,r12,30
 | |
| 	sub	r3,r2,1
 | |
| 	brls	r2,r12,.Lbytewise
 | |
| 	ld	r4,[r0,0]
 | |
| 	ld	r5,[r1,0]
 | |
| 	lsr.f	lp_count,r3,3
 | |
| #ifdef CONFIG_ISA_ARCV2
 | |
| 	/* In ARCv2 a branch can't be the last instruction in a zero overhead
 | |
| 	 * loop.
 | |
| 	 * So we move the branch to the start of the loop, duplicate it
 | |
| 	 * after the end, and set up r12 so that the branch isn't taken
 | |
| 	 *  initially.
 | |
| 	 */
 | |
| 	mov_s	r12,WORD2
 | |
| 	lpne	.Loop_end
 | |
| 	brne	WORD2,r12,.Lodd
 | |
| 	ld	WORD2,[r0,4]
 | |
| #else
 | |
| 	lpne	.Loop_end
 | |
| 	ld_s	WORD2,[r0,4]
 | |
| #endif
 | |
| 	ld_s	r12,[r1,4]
 | |
| 	brne	r4,r5,.Leven
 | |
| 	ld.a	r4,[r0,8]
 | |
| 	ld.a	r5,[r1,8]
 | |
| #ifdef CONFIG_ISA_ARCV2
 | |
| .Loop_end:
 | |
| 	brne	WORD2,r12,.Lodd
 | |
| #else
 | |
| 	brne	WORD2,r12,.Lodd
 | |
| .Loop_end:
 | |
| #endif
 | |
| 	asl_s	SHIFT,SHIFT,3
 | |
| 	bhs_s	.Last_cmp
 | |
| 	brne	r4,r5,.Leven
 | |
| 	ld	r4,[r0,4]
 | |
| 	ld	r5,[r1,4]
 | |
| #ifdef __LITTLE_ENDIAN__
 | |
| 	nop_s
 | |
| 	; one more load latency cycle
 | |
| .Last_cmp:
 | |
| 	xor	r0,r4,r5
 | |
| 	bset	r0,r0,SHIFT
 | |
| 	sub_s	r1,r0,1
 | |
| 	bic_s	r1,r1,r0
 | |
| 	norm	r1,r1
 | |
| 	b.d	.Leven_cmp
 | |
| 	and	r1,r1,24
 | |
| .Leven:
 | |
| 	xor	r0,r4,r5
 | |
| 	sub_s	r1,r0,1
 | |
| 	bic_s	r1,r1,r0
 | |
| 	norm	r1,r1
 | |
| 	; slow track insn
 | |
| 	and	r1,r1,24
 | |
| .Leven_cmp:
 | |
| 	asl	r2,r4,r1
 | |
| 	asl	r12,r5,r1
 | |
| 	lsr_s	r2,r2,1
 | |
| 	lsr_s	r12,r12,1
 | |
| 	j_s.d	[blink]
 | |
| 	sub	r0,r2,r12
 | |
| 	.balign	4
 | |
| .Lodd:
 | |
| 	xor	r0,WORD2,r12
 | |
| 	sub_s	r1,r0,1
 | |
| 	bic_s	r1,r1,r0
 | |
| 	norm	r1,r1
 | |
| 	; slow track insn
 | |
| 	and	r1,r1,24
 | |
| 	asl_s	r2,r2,r1
 | |
| 	asl_s	r12,r12,r1
 | |
| 	lsr_s	r2,r2,1
 | |
| 	lsr_s	r12,r12,1
 | |
| 	j_s.d	[blink]
 | |
| 	sub	r0,r2,r12
 | |
| #else /* BIG ENDIAN */
 | |
| .Last_cmp:
 | |
| 	neg_s	SHIFT,SHIFT
 | |
| 	lsr	r4,r4,SHIFT
 | |
| 	lsr	r5,r5,SHIFT
 | |
| 	; slow track insn
 | |
| .Leven:
 | |
| 	sub.f	r0,r4,r5
 | |
| 	mov.ne	r0,1
 | |
| 	j_s.d	[blink]
 | |
| 	bset.cs	r0,r0,31
 | |
| .Lodd:
 | |
| 	cmp_s	WORD2,r12
 | |
| 	mov_s	r0,1
 | |
| 	j_s.d	[blink]
 | |
| 	bset.cs	r0,r0,31
 | |
| #endif /* ENDIAN */
 | |
| 	.balign	4
 | |
| .Lbytewise:
 | |
| 	breq	r2,0,.Lnil
 | |
| 	ldb	r4,[r0,0]
 | |
| 	ldb	r5,[r1,0]
 | |
| 	lsr.f	lp_count,r3
 | |
| #ifdef CONFIG_ISA_ARCV2
 | |
| 	mov	r12,r3
 | |
| 	lpne	.Lbyte_end
 | |
| 	brne	r3,r12,.Lbyte_odd
 | |
| #else
 | |
| 	lpne	.Lbyte_end
 | |
| #endif
 | |
| 	ldb_s	r3,[r0,1]
 | |
| 	ldb	r12,[r1,1]
 | |
| 	brne	r4,r5,.Lbyte_even
 | |
| 	ldb.a	r4,[r0,2]
 | |
| 	ldb.a	r5,[r1,2]
 | |
| #ifdef CONFIG_ISA_ARCV2
 | |
| .Lbyte_end:
 | |
| 	brne	r3,r12,.Lbyte_odd
 | |
| #else
 | |
| 	brne	r3,r12,.Lbyte_odd
 | |
| .Lbyte_end:
 | |
| #endif
 | |
| 	bcc	.Lbyte_even
 | |
| 	brne	r4,r5,.Lbyte_even
 | |
| 	ldb_s	r3,[r0,1]
 | |
| 	ldb_s	r12,[r1,1]
 | |
| .Lbyte_odd:
 | |
| 	j_s.d	[blink]
 | |
| 	sub	r0,r3,r12
 | |
| .Lbyte_even:
 | |
| 	j_s.d	[blink]
 | |
| 	sub	r0,r4,r5
 | |
| .Lnil:
 | |
| 	j_s.d	[blink]
 | |
| 	mov	r0,0
 | |
| END(memcmp)
 |