mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-30 16:13:54 +08:00
8922bc3058
Branch insn can't be scheduled as last insn of Zero Overhead loop Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
153 lines
2.6 KiB
ArmAsm
153 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)
|