mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
2.4 KiB
149 lines
2.4 KiB
/* SPDX-License-Identifier: GPL-2.0-only */ |
|
/* |
|
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) |
|
*/ |
|
|
|
#include <linux/linkage.h> |
|
|
|
#ifdef __LITTLE_ENDIAN__ |
|
#define WORD2 r2 |
|
#define SHIFT r3 |
|
#else /* BIG ENDIAN */ |
|
#define WORD2 r3 |
|
#define SHIFT r2 |
|
#endif |
|
|
|
ENTRY_CFI(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_CFI(memcmp)
|
|
|