Merge tag 'spi-fix-v4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
[cascardo/linux.git] / arch / sparc / lib / copy_in_user.S
1 /* copy_in_user.S: Copy from userspace to userspace.
2  *
3  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
4  */
5
6 #include <linux/linkage.h>
7 #include <asm/asi.h>
8 #include <asm/export.h>
9
10 #define XCC xcc
11
12 #define EX(x,y,z)               \
13 98:     x,y;                    \
14         .section __ex_table,"a";\
15         .align 4;               \
16         .word 98b, z;           \
17         .text;                  \
18         .align 4;
19
20 #define EX_O4(x,y) EX(x,y,__retl_o4_plus_8)
21 #define EX_O2_4(x,y) EX(x,y,__retl_o2_plus_4)
22 #define EX_O2_1(x,y) EX(x,y,__retl_o2_plus_1)
23
24         .register       %g2,#scratch
25         .register       %g3,#scratch
26
27         .text
28 __retl_o4_plus_8:
29         add     %o4, %o2, %o4
30         retl
31          add    %o4, 8, %o0
32 __retl_o2_plus_4:
33         retl
34          add    %o2, 4, %o0
35 __retl_o2_plus_1:
36         retl
37          add    %o2, 1, %o0
38
39         .align  32
40
41         /* Don't try to get too fancy here, just nice and
42          * simple.  This is predominantly used for well aligned
43          * small copies in the compat layer.  It is also used
44          * to copy register windows around during thread cloning.
45          */
46
47 ENTRY(___copy_in_user)  /* %o0=dst, %o1=src, %o2=len */
48         cmp             %o2, 0
49         be,pn           %XCC, 85f
50          or             %o0, %o1, %o3
51         cmp             %o2, 16
52         bleu,a,pn       %XCC, 80f
53          or             %o3, %o2, %o3
54
55         /* 16 < len <= 64 */
56         andcc           %o3, 0x7, %g0
57         bne,pn          %XCC, 90f
58          nop
59
60         andn            %o2, 0x7, %o4
61         and             %o2, 0x7, %o2
62 1:      subcc           %o4, 0x8, %o4
63         EX_O4(ldxa [%o1] %asi, %o5)
64         EX_O4(stxa %o5, [%o0] %asi)
65         add             %o1, 0x8, %o1
66         bgu,pt          %XCC, 1b
67          add            %o0, 0x8, %o0
68         andcc           %o2, 0x4, %g0
69         be,pt           %XCC, 1f
70          nop
71         sub             %o2, 0x4, %o2
72         EX_O2_4(lduwa [%o1] %asi, %o5)
73         EX_O2_4(stwa %o5, [%o0] %asi)
74         add             %o1, 0x4, %o1
75         add             %o0, 0x4, %o0
76 1:      cmp             %o2, 0
77         be,pt           %XCC, 85f
78          nop
79         ba,pt           %xcc, 90f
80          nop
81
82 80:     /* 0 < len <= 16 */
83         andcc           %o3, 0x3, %g0
84         bne,pn          %XCC, 90f
85          nop
86
87 82:
88         subcc           %o2, 4, %o2
89         EX_O2_4(lduwa [%o1] %asi, %g1)
90         EX_O2_4(stwa %g1, [%o0] %asi)
91         add             %o1, 4, %o1
92         bgu,pt          %XCC, 82b
93          add            %o0, 4, %o0
94
95 85:     retl
96          clr            %o0
97
98         .align  32
99 90:
100         subcc           %o2, 1, %o2
101         EX_O2_1(lduba [%o1] %asi, %g1)
102         EX_O2_1(stba %g1, [%o0] %asi)
103         add             %o1, 1, %o1
104         bgu,pt          %XCC, 90b
105          add            %o0, 1, %o0
106         retl
107          clr            %o0
108 ENDPROC(___copy_in_user)
109 EXPORT_SYMBOL(___copy_in_user)