VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / arch / sparc64 / lib / U3copy_in_user.S
1 /* U3copy_in_user.S: UltraSparc-III optimized memcpy.
2  *
3  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
4  */
5
6 #include <asm/visasm.h>
7 #include <asm/asi.h>
8 #include <asm/dcu.h>
9 #include <asm/spitfire.h>
10
11 #define XCC xcc
12
13 #define EXNV(x,y,a,b)   \
14 98:     x,y;                            \
15         .section .fixup;                \
16         .align 4;                       \
17 99:     retl;                           \
18          a, b, %o0;                     \
19         .section __ex_table;            \
20         .align 4;                       \
21         .word 98b, 99b;                 \
22         .text;                          \
23         .align 4;
24 #define EXNV1(x,y,a,b)                  \
25 98:     x,y;                            \
26         .section .fixup;                \
27         .align 4;                       \
28 99:     a, b, %o0;                      \
29         retl;                           \
30          add %o0, 1, %o0;               \
31         .section __ex_table;            \
32         .align 4;                       \
33         .word 98b, 99b;                 \
34         .text;                          \
35         .align 4;
36 #define EXNV4(x,y,a,b)                  \
37 98:     x,y;                            \
38         .section .fixup;                \
39         .align 4;                       \
40 99:     a, b, %o0;                      \
41         retl;                           \
42          add %o0, 4, %o0;               \
43         .section __ex_table;            \
44         .align 4;                       \
45         .word 98b, 99b;                 \
46         .text;                          \
47         .align 4;
48 #define EXNV8(x,y,a,b)                  \
49 98:     x,y;                            \
50         .section .fixup;                \
51         .align 4;                       \
52 99:     a, b, %o0;                      \
53         retl;                           \
54          add %o0, 8, %o0;               \
55         .section __ex_table;            \
56         .align 4;                       \
57         .word 98b, 99b;                 \
58         .text;                          \
59         .align 4;
60
61         .register       %g2,#scratch
62         .register       %g3,#scratch
63
64         .text
65         .align  32
66
67         /* Don't try to get too fancy here, just nice and
68          * simple.  This is predominantly used for well aligned
69          * small copies in the compat layer.  It is also used
70          * to copy register windows around during thread cloning.
71          */
72
73         .globl  U3copy_in_user
74 U3copy_in_user: /* %o0=dst, %o1=src, %o2=len */
75         /* Writing to %asi is _expensive_ so we hardcode it.
76          * Reading %asi to check for KERNEL_DS is comparatively
77          * cheap.
78          */
79         rd              %asi, %g1
80         cmp             %g1, ASI_AIUS
81         bne,pn          %icc, U3memcpy_user_stub
82          nop
83
84         cmp             %o2, 0
85         be,pn           %XCC, out
86          or             %o0, %o1, %o3
87         cmp             %o2, 16
88         bleu,a,pn       %XCC, small_copy
89          or             %o3, %o2, %o3
90
91 medium_copy: /* 16 < len <= 64 */
92         andcc           %o3, 0x7, %g0
93         bne,pn          %XCC, small_copy_unaligned
94          sub            %o0, %o1, %o3
95
96 medium_copy_aligned:
97         andn            %o2, 0x7, %o4
98         and             %o2, 0x7, %o2
99 1:      subcc           %o4, 0x8, %o4
100         EXNV8(ldxa [%o1] %asi, %o5, add %o4, %o2)
101         EXNV8(stxa %o5, [%o1 + %o3] ASI_AIUS, add %o4, %o2)
102         bgu,pt          %XCC, 1b
103          add            %o1, 0x8, %o1
104         andcc           %o2, 0x4, %g0
105         be,pt           %XCC, 1f
106          nop
107         sub             %o2, 0x4, %o2
108         EXNV4(lduwa [%o1] %asi, %o5, add %o4, %o2)
109         EXNV4(stwa %o5, [%o1 + %o3] ASI_AIUS, add %o4, %o2)
110         add             %o1, 0x4, %o1
111 1:      cmp             %o2, 0
112         be,pt           %XCC, out
113          nop
114         ba,pt           %xcc, small_copy_unaligned
115          nop
116
117 small_copy: /* 0 < len <= 16 */
118         andcc           %o3, 0x3, %g0
119         bne,pn          %XCC, small_copy_unaligned
120          sub            %o0, %o1, %o3
121
122 small_copy_aligned:
123         subcc           %o2, 4, %o2
124         EXNV4(lduwa [%o1] %asi, %g1, add %o2, %g0)
125         EXNV4(stwa %g1, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
126         bgu,pt          %XCC, small_copy_aligned
127          add            %o1, 4, %o1
128
129 out:    retl
130          clr            %o0
131
132         .align  32
133 small_copy_unaligned:
134         subcc           %o2, 1, %o2
135         EXNV1(lduba [%o1] %asi, %g1, add %o2, %g0)
136         EXNV1(stba %g1, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
137         bgu,pt          %XCC, small_copy_unaligned
138          add            %o1, 1, %o1
139         retl
140          clr            %o0