ARCv2: Adhere to Zero Delay loop restriction
Branch insn can't be scheduled as last insn of Zero Overhead loop Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
This commit is contained in:
parent
1f7e3dc0ba
commit
8922bc3058
@ -22,11 +22,10 @@
|
|||||||
static inline void __delay(unsigned long loops)
|
static inline void __delay(unsigned long loops)
|
||||||
{
|
{
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
"1: sub.f %0, %0, 1 \n"
|
" lp 1f \n"
|
||||||
" jpnz 1b \n"
|
" nop \n"
|
||||||
: "+r"(loops)
|
"1: \n"
|
||||||
:
|
: "+l"(loops));
|
||||||
: "cc");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void __bad_udelay(void);
|
extern void __bad_udelay(void);
|
||||||
|
@ -659,31 +659,30 @@ static inline unsigned long __arc_clear_user(void __user *to, unsigned long n)
|
|||||||
static inline long
|
static inline long
|
||||||
__arc_strncpy_from_user(char *dst, const char __user *src, long count)
|
__arc_strncpy_from_user(char *dst, const char __user *src, long count)
|
||||||
{
|
{
|
||||||
long res = count;
|
long res = 0;
|
||||||
char val;
|
char val;
|
||||||
unsigned int hw_count;
|
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" lp 2f \n"
|
" lp 3f \n"
|
||||||
"1: ldb.ab %3, [%2, 1] \n"
|
"1: ldb.ab %3, [%2, 1] \n"
|
||||||
" breq.d %3, 0, 2f \n"
|
" breq.d %3, 0, 3f \n"
|
||||||
" stb.ab %3, [%1, 1] \n"
|
" stb.ab %3, [%1, 1] \n"
|
||||||
"2: sub %0, %6, %4 \n"
|
" add %0, %0, 1 # Num of NON NULL bytes copied \n"
|
||||||
"3: ;nop \n"
|
"3: \n"
|
||||||
" .section .fixup, \"ax\" \n"
|
" .section .fixup, \"ax\" \n"
|
||||||
" .align 4 \n"
|
" .align 4 \n"
|
||||||
"4: mov %0, %5 \n"
|
"4: mov %0, %4 # sets @res as -EFAULT \n"
|
||||||
" j 3b \n"
|
" j 3b \n"
|
||||||
" .previous \n"
|
" .previous \n"
|
||||||
" .section __ex_table, \"a\" \n"
|
" .section __ex_table, \"a\" \n"
|
||||||
" .align 4 \n"
|
" .align 4 \n"
|
||||||
" .word 1b, 4b \n"
|
" .word 1b, 4b \n"
|
||||||
" .previous \n"
|
" .previous \n"
|
||||||
: "=r"(res), "+r"(dst), "+r"(src), "=&r"(val), "=l"(hw_count)
|
: "+r"(res), "+r"(dst), "+r"(src), "=r"(val)
|
||||||
: "g"(-EFAULT), "ir"(count), "4"(count) /* this "4" seeds lp_count */
|
: "g"(-EFAULT), "l"(count)
|
||||||
: "memory");
|
: "memory");
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -24,14 +24,32 @@ ENTRY(memcmp)
|
|||||||
ld r4,[r0,0]
|
ld r4,[r0,0]
|
||||||
ld r5,[r1,0]
|
ld r5,[r1,0]
|
||||||
lsr.f lp_count,r3,3
|
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
|
lpne .Loop_end
|
||||||
ld_s WORD2,[r0,4]
|
ld_s WORD2,[r0,4]
|
||||||
|
#endif
|
||||||
ld_s r12,[r1,4]
|
ld_s r12,[r1,4]
|
||||||
brne r4,r5,.Leven
|
brne r4,r5,.Leven
|
||||||
ld.a r4,[r0,8]
|
ld.a r4,[r0,8]
|
||||||
ld.a r5,[r1,8]
|
ld.a r5,[r1,8]
|
||||||
|
#ifdef CONFIG_ISA_ARCV2
|
||||||
|
.Loop_end:
|
||||||
|
brne WORD2,r12,.Lodd
|
||||||
|
#else
|
||||||
brne WORD2,r12,.Lodd
|
brne WORD2,r12,.Lodd
|
||||||
.Loop_end:
|
.Loop_end:
|
||||||
|
#endif
|
||||||
asl_s SHIFT,SHIFT,3
|
asl_s SHIFT,SHIFT,3
|
||||||
bhs_s .Last_cmp
|
bhs_s .Last_cmp
|
||||||
brne r4,r5,.Leven
|
brne r4,r5,.Leven
|
||||||
@ -89,7 +107,6 @@ ENTRY(memcmp)
|
|||||||
bset.cs r0,r0,31
|
bset.cs r0,r0,31
|
||||||
.Lodd:
|
.Lodd:
|
||||||
cmp_s WORD2,r12
|
cmp_s WORD2,r12
|
||||||
|
|
||||||
mov_s r0,1
|
mov_s r0,1
|
||||||
j_s.d [blink]
|
j_s.d [blink]
|
||||||
bset.cs r0,r0,31
|
bset.cs r0,r0,31
|
||||||
@ -100,14 +117,25 @@ ENTRY(memcmp)
|
|||||||
ldb r4,[r0,0]
|
ldb r4,[r0,0]
|
||||||
ldb r5,[r1,0]
|
ldb r5,[r1,0]
|
||||||
lsr.f lp_count,r3
|
lsr.f lp_count,r3
|
||||||
|
#ifdef CONFIG_ISA_ARCV2
|
||||||
|
mov r12,r3
|
||||||
lpne .Lbyte_end
|
lpne .Lbyte_end
|
||||||
|
brne r3,r12,.Lbyte_odd
|
||||||
|
#else
|
||||||
|
lpne .Lbyte_end
|
||||||
|
#endif
|
||||||
ldb_s r3,[r0,1]
|
ldb_s r3,[r0,1]
|
||||||
ldb r12,[r1,1]
|
ldb r12,[r1,1]
|
||||||
brne r4,r5,.Lbyte_even
|
brne r4,r5,.Lbyte_even
|
||||||
ldb.a r4,[r0,2]
|
ldb.a r4,[r0,2]
|
||||||
ldb.a r5,[r1,2]
|
ldb.a r5,[r1,2]
|
||||||
|
#ifdef CONFIG_ISA_ARCV2
|
||||||
|
.Lbyte_end:
|
||||||
|
brne r3,r12,.Lbyte_odd
|
||||||
|
#else
|
||||||
brne r3,r12,.Lbyte_odd
|
brne r3,r12,.Lbyte_odd
|
||||||
.Lbyte_end:
|
.Lbyte_end:
|
||||||
|
#endif
|
||||||
bcc .Lbyte_even
|
bcc .Lbyte_even
|
||||||
brne r4,r5,.Lbyte_even
|
brne r4,r5,.Lbyte_even
|
||||||
ldb_s r3,[r0,1]
|
ldb_s r3,[r0,1]
|
||||||
|
Loading…
Reference in New Issue
Block a user