/* | |
* 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) |