aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2013-10-07 08:40:08 -0400
committerVineet Gupta <vgupta@synopsys.com>2015-06-22 04:36:56 -0400
commit8922bc3058abbe5deaf887147e26531750ce7513 (patch)
tree647f15f01077a23afd047e3d01b125a93e2ac9b1
parent1f7e3dc0baaa41217dc06d3370e1efd1aecbc1f0 (diff)
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>
-rw-r--r--arch/arc/include/asm/delay.h9
-rw-r--r--arch/arc/include/asm/uaccess.h17
-rw-r--r--arch/arc/lib/memcmp.S30
3 files changed, 41 insertions, 15 deletions
diff --git a/arch/arc/include/asm/delay.h b/arch/arc/include/asm/delay.h
index 43de30256981..08e7e2a16ac1 100644
--- a/arch/arc/include/asm/delay.h
+++ b/arch/arc/include/asm/delay.h
@@ -22,11 +22,10 @@
22static inline void __delay(unsigned long loops) 22static inline void __delay(unsigned long loops)
23{ 23{
24 __asm__ __volatile__( 24 __asm__ __volatile__(
25 "1: sub.f %0, %0, 1 \n" 25 " lp 1f \n"
26 " jpnz 1b \n" 26 " nop \n"
27 : "+r"(loops) 27 "1: \n"
28 : 28 : "+l"(loops));
29 : "cc");
30} 29}
31 30
32extern void __bad_udelay(void); 31extern void __bad_udelay(void);
diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h
index 30c9baffa96f..d1da6032b715 100644
--- a/arch/arc/include/asm/uaccess.h
+++ b/arch/arc/include/asm/uaccess.h
@@ -659,31 +659,30 @@ static inline unsigned long __arc_clear_user(void __user *to, unsigned long n)
659static inline long 659static inline long
660__arc_strncpy_from_user(char *dst, const char __user *src, long count) 660__arc_strncpy_from_user(char *dst, const char __user *src, long count)
661{ 661{
662 long res = count; 662 long res = 0;
663 char val; 663 char val;
664 unsigned int hw_count;
665 664
666 if (count == 0) 665 if (count == 0)
667 return 0; 666 return 0;
668 667
669 __asm__ __volatile__( 668 __asm__ __volatile__(
670 " lp 2f \n" 669 " lp 3f \n"
671 "1: ldb.ab %3, [%2, 1] \n" 670 "1: ldb.ab %3, [%2, 1] \n"
672 " breq.d %3, 0, 2f \n" 671 " breq.d %3, 0, 3f \n"
673 " stb.ab %3, [%1, 1] \n" 672 " stb.ab %3, [%1, 1] \n"
674 "2: sub %0, %6, %4 \n" 673 " add %0, %0, 1 # Num of NON NULL bytes copied \n"
675 "3: ;nop \n" 674 "3: \n"
676 " .section .fixup, \"ax\" \n" 675 " .section .fixup, \"ax\" \n"
677 " .align 4 \n" 676 " .align 4 \n"
678 "4: mov %0, %5 \n" 677 "4: mov %0, %4 # sets @res as -EFAULT \n"
679 " j 3b \n" 678 " j 3b \n"
680 " .previous \n" 679 " .previous \n"
681 " .section __ex_table, \"a\" \n" 680 " .section __ex_table, \"a\" \n"
682 " .align 4 \n" 681 " .align 4 \n"
683 " .word 1b, 4b \n" 682 " .word 1b, 4b \n"
684 " .previous \n" 683 " .previous \n"
685 : "=r"(res), "+r"(dst), "+r"(src), "=&r"(val), "=l"(hw_count) 684 : "+r"(res), "+r"(dst), "+r"(src), "=r"(val)
686 : "g"(-EFAULT), "ir"(count), "4"(count) /* this "4" seeds lp_count */ 685 : "g"(-EFAULT), "l"(count)
687 : "memory"); 686 : "memory");
688 687
689 return res; 688 return res;
diff --git a/arch/arc/lib/memcmp.S b/arch/arc/lib/memcmp.S
index 978bf8314dfb..a4015e7d9ab7 100644
--- a/arch/arc/lib/memcmp.S
+++ b/arch/arc/lib/memcmp.S
@@ -24,14 +24,32 @@ ENTRY(memcmp)
24 ld r4,[r0,0] 24 ld r4,[r0,0]
25 ld r5,[r1,0] 25 ld r5,[r1,0]
26 lsr.f lp_count,r3,3 26 lsr.f lp_count,r3,3
27#ifdef CONFIG_ISA_ARCV2
28 /* In ARCv2 a branch can't be the last instruction in a zero overhead
29 * loop.
30 * So we move the branch to the start of the loop, duplicate it
31 * after the end, and set up r12 so that the branch isn't taken
32 * initially.
33 */
34 mov_s r12,WORD2
35 lpne .Loop_end
36 brne WORD2,r12,.Lodd
37 ld WORD2,[r0,4]
38#else
27 lpne .Loop_end 39 lpne .Loop_end
28 ld_s WORD2,[r0,4] 40 ld_s WORD2,[r0,4]
41#endif
29 ld_s r12,[r1,4] 42 ld_s r12,[r1,4]
30 brne r4,r5,.Leven 43 brne r4,r5,.Leven
31 ld.a r4,[r0,8] 44 ld.a r4,[r0,8]
32 ld.a r5,[r1,8] 45 ld.a r5,[r1,8]
46#ifdef CONFIG_ISA_ARCV2
47.Loop_end:
48 brne WORD2,r12,.Lodd
49#else
33 brne WORD2,r12,.Lodd 50 brne WORD2,r12,.Lodd
34.Loop_end: 51.Loop_end:
52#endif
35 asl_s SHIFT,SHIFT,3 53 asl_s SHIFT,SHIFT,3
36 bhs_s .Last_cmp 54 bhs_s .Last_cmp
37 brne r4,r5,.Leven 55 brne r4,r5,.Leven
@@ -89,7 +107,6 @@ ENTRY(memcmp)
89 bset.cs r0,r0,31 107 bset.cs r0,r0,31
90.Lodd: 108.Lodd:
91 cmp_s WORD2,r12 109 cmp_s WORD2,r12
92
93 mov_s r0,1 110 mov_s r0,1
94 j_s.d [blink] 111 j_s.d [blink]
95 bset.cs r0,r0,31 112 bset.cs r0,r0,31
@@ -100,14 +117,25 @@ ENTRY(memcmp)
100 ldb r4,[r0,0] 117 ldb r4,[r0,0]
101 ldb r5,[r1,0] 118 ldb r5,[r1,0]
102 lsr.f lp_count,r3 119 lsr.f lp_count,r3
120#ifdef CONFIG_ISA_ARCV2
121 mov r12,r3
103 lpne .Lbyte_end 122 lpne .Lbyte_end
123 brne r3,r12,.Lbyte_odd
124#else
125 lpne .Lbyte_end
126#endif
104 ldb_s r3,[r0,1] 127 ldb_s r3,[r0,1]
105 ldb r12,[r1,1] 128 ldb r12,[r1,1]
106 brne r4,r5,.Lbyte_even 129 brne r4,r5,.Lbyte_even
107 ldb.a r4,[r0,2] 130 ldb.a r4,[r0,2]
108 ldb.a r5,[r1,2] 131 ldb.a r5,[r1,2]
132#ifdef CONFIG_ISA_ARCV2
133.Lbyte_end:
134 brne r3,r12,.Lbyte_odd
135#else
109 brne r3,r12,.Lbyte_odd 136 brne r3,r12,.Lbyte_odd
110.Lbyte_end: 137.Lbyte_end:
138#endif
111 bcc .Lbyte_even 139 bcc .Lbyte_even
112 brne r4,r5,.Lbyte_even 140 brne r4,r5,.Lbyte_even
113 ldb_s r3,[r0,1] 141 ldb_s r3,[r0,1]