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