:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / include / napi / i386 / segment.h
1 #ifndef _ASM_SEGMENT_H
2 #define _ASM_SEGMENT_H
3
4 #define KERNEL_CS            (0x8)
5 #define KERNEL_DS            (0x10)
6 #define USER_CS              (0x18 + 0x3)
7 #define USER_DS              (0x20 + 0x3)
8 #define RESERVED_FOR_TSS     (0x28)
9 #define PCR_SELECTOR         (0x30)
10 #define TEB_SELECTOR         (0x38 + 0x3)
11
12 //#define USER_CS            (0x8+0x3)
13 //#define USER_DS            (0x10+0x3)
14 //#define ZERO_DS            0x18
15 //#define KERNEL_CS          0x20
16 //#define KERNEL_DS          0x28
17
18 #ifndef __ASSEMBLY__
19
20 /*
21  * Uh, these should become the main single-value transfer routines..
22  * They automatically use the right size if we just have the right
23  * pointer type..
24  */
25 #define put_user(x,ptr) __put_user((unsigned long)(x),(ptr),sizeof(*(ptr)))
26 #define get_user(ptr) ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr))))
27
28 /*
29  * This is a silly but good way to make sure that
30  * the __put_user function is indeed always optimized,
31  * and that we use the correct sizes..
32  */
33 extern int bad_user_access_length(void);
34
35 /*
36  * dummy pointer type structure.. gcc won't try to do something strange
37  * this way..
38  */
39 struct __segment_dummy { unsigned long a[100]; };
40 #define __sd(x) ((struct __segment_dummy *) (x))
41 #define __const_sd(x) ((const struct __segment_dummy *) (x))
42
43 static inline void __put_user(unsigned long x, void * y, int size)
44 {
45         switch (size) {
46                 case 1:
47                         __asm__ ("movb %b1,%%fs:%0" \
48                                 :"=m" (*__sd(y)) \
49                                 :"iq" ((unsigned char) x), "m" (*__sd(y)));
50                         break;
51                 case 2:
52                         __asm__ ("movw %w1,%%fs:%0" \
53                                 :"=m" (*__sd(y)) \
54                                 :"ir" ((unsigned short) x), "m" (*__sd(y)));
55                         break;
56                 case 4:
57                         __asm__ ("movl %1,%%fs:%0" \
58                                 :"=m" (*__sd(y)) \
59                                 :"ir" (x), "m" (*__sd(y)));
60                         break;
61                 default:
62                         bad_user_access_length();
63         }
64 }
65
66 static inline unsigned long __get_user(const void * y, int size)
67 {
68         unsigned long result;
69
70         switch (size) {
71                 case 1:
72                         __asm__ ("movb %%fs:%1,%b0" \
73                                 :"=q" (result) \
74                                 :"m" (*__const_sd(y)));
75                         return (unsigned char) result;
76                 case 2:
77                         __asm__ ("movw %%fs:%1,%w0" \
78                                 :"=r" (result) \
79                                 :"m" (*__const_sd(y)));
80                         return (unsigned short) result;
81                 case 4:
82                         __asm__ ("movl %%fs:%1,%0" \
83                                 :"=r" (result) \
84                                 :"m" (*__const_sd(y)));
85                         return result;
86                 default:
87                         return bad_user_access_length();
88         }
89 }
90
91 static inline void __generic_memcpy_tofs(void * to, const void * from, unsigned long n)
92 {
93     __asm__ volatile
94         ("      cld \
95                 push %%es \
96                 push %%fs \
97                 cmpl $3,%0 \
98                 pop %%es \
99                 jbe 1f \
100                 movl %%edi,%%ecx \
101                 negl %%ecx \
102                 andl $3,%%ecx \
103                 subl %%ecx,%0 \
104                 rep; movsb \
105                 movl %0,%%ecx \
106                 shrl $2,%%ecx \
107                 rep; movsl \
108                 andl $3,%0 \
109         1:      movl %0,%%ecx \
110                 rep; movsb \
111                 pop %%es" \
112         :"=abd" (n) \
113         :"0" (n),"D" ((long) to),"S" ((long) from) \
114         :"cx","di","si");
115 }
116
117 static inline void __constant_memcpy_tofs(void * to, const void * from, unsigned long n)
118 {
119         switch (n) {
120                 case 0:
121                         return;
122                 case 1:
123                         __put_user(*(const char *) from, (char *) to, 1);
124                         return;
125                 case 2:
126                         __put_user(*(const short *) from, (short *) to, 2);
127                         return;
128                 case 3:
129                         __put_user(*(const short *) from, (short *) to, 2);
130                         __put_user(*(2+(const char *) from), 2+(char *) to, 1);
131                         return;
132                 case 4:
133                         __put_user(*(const int *) from, (int *) to, 4);
134                         return;
135                 case 8:
136                         __put_user(*(const int *) from, (int *) to, 4);
137                         __put_user(*(1+(const int *) from), 1+(int *) to, 4);
138                         return;
139                 case 12:
140                         __put_user(*(const int *) from, (int *) to, 4);
141                         __put_user(*(1+(const int *) from), 1+(int *) to, 4);
142                         __put_user(*(2+(const int *) from), 2+(int *) to, 4);
143                         return;
144                 case 16:
145                         __put_user(*(const int *) from, (int *) to, 4);
146                         __put_user(*(1+(const int *) from), 1+(int *) to, 4);
147                         __put_user(*(2+(const int *) from), 2+(int *) to, 4);
148                         __put_user(*(3+(const int *) from), 3+(int *) to, 4);
149                         return;
150         }
151 #define COMMON(x) \
152 __asm__("cld\n\t" \
153         "push %%es\n\t" \
154         "push %%fs\n\t" \
155         "pop %%es\n\t" \
156         "rep ; movsl\n\t" \
157         x \
158         "pop %%es" \
159         : /* no outputs */ \
160         :"c" (n/4),"D" ((long) to),"S" ((long) from) \
161         :"cx","di","si")
162
163         switch (n % 4) {
164                 case 0:
165                         COMMON("");
166                         return;
167                 case 1:
168                         COMMON("movsb\n\t");
169                         return;
170                 case 2:
171                         COMMON("movsw\n\t");
172                         return;
173                 case 3:
174                         COMMON("movsw\n\tmovsb\n\t");
175                         return;
176         }
177 #undef COMMON
178 }
179
180 static inline void __generic_memcpy_fromfs(void * to, const void * from, unsigned long n)
181 {
182     __asm__ volatile
183         ("      cld \
184                 cmpl $3,%0 \
185                 jbe 1f \
186                 movl %%edi,%%ecx \
187                 negl %%ecx \
188                 andl $3,%%ecx \
189                 subl %%ecx,%0 \
190                 fs; rep; movsb \
191                 movl %0,%%ecx \
192                 shrl $2,%%ecx \
193                 fs; rep; movsl \
194                 andl $3,%0 \
195         1:      movl %0,%%ecx \
196                 fs; rep; movsb"
197         :"=abd" (n)
198         :"0" (n),"D" ((long) to),"S" ((long) from)
199         :"cx","di","si", "memory");
200 }
201
202 static inline void __constant_memcpy_fromfs(void * to, const void * from, unsigned long n)
203 {
204         switch (n) {
205                 case 0:
206                         return;
207                 case 1:
208                         *(char *)to = __get_user((const char *) from, 1);
209                         return;
210                 case 2:
211                         *(short *)to = __get_user((const short *) from, 2);
212                         return;
213                 case 3:
214                         *(short *) to = __get_user((const short *) from, 2);
215                         *((char *) to + 2) = __get_user(2+(const char *) from, 1);
216                         return;
217                 case 4:
218                         *(int *) to = __get_user((const int *) from, 4);
219                         return;
220                 case 8:
221                         *(int *) to = __get_user((const int *) from, 4);
222                         *(1+(int *) to) = __get_user(1+(const int *) from, 4);
223                         return;
224                 case 12:
225                         *(int *) to = __get_user((const int *) from, 4);
226                         *(1+(int *) to) = __get_user(1+(const int *) from, 4);
227                         *(2+(int *) to) = __get_user(2+(const int *) from, 4);
228                         return;
229                 case 16:
230                         *(int *) to = __get_user((const int *) from, 4);
231                         *(1+(int *) to) = __get_user(1+(const int *) from, 4);
232                         *(2+(int *) to) = __get_user(2+(const int *) from, 4);
233                         *(3+(int *) to) = __get_user(3+(const int *) from, 4);
234                         return;
235         }
236 #define COMMON(x) \
237 __asm__("cld\n\t" \
238         "rep ; fs ; movsl\n\t" \
239         x \
240         : /* no outputs */ \
241         :"c" (n/4),"D" ((long) to),"S" ((long) from) \
242         :"cx","di","si","memory")
243
244         switch (n % 4) {
245                 case 0:
246                         COMMON("");
247                         return;
248                 case 1:
249                         COMMON("fs ; movsb");
250                         return;
251                 case 2:
252                         COMMON("fs ; movsw");
253                         return;
254                 case 3:
255                         COMMON("fs ; movsw\n\tfs ; movsb");
256                         return;
257         }
258 #undef COMMON
259 }
260
261 #define memcpy_fromfs(to, from, n) \
262 (__builtin_constant_p(n) ? \
263  __constant_memcpy_fromfs((to),(from),(n)) : \
264  __generic_memcpy_fromfs((to),(from),(n)))
265
266 #define memcpy_tofs(to, from, n) \
267 (__builtin_constant_p(n) ? \
268  __constant_memcpy_tofs((to),(from),(n)) : \
269  __generic_memcpy_tofs((to),(from),(n)))
270
271 /*
272  * These are deprecated..
273  *
274  * Use "put_user()" and "get_user()" with the proper pointer types instead.
275  */
276
277 #define get_fs_byte(addr) __get_user((const unsigned char *)(addr),1)
278 #define get_fs_word(addr) __get_user((const unsigned short *)(addr),2)
279 #define get_fs_long(addr) __get_user((const unsigned int *)(addr),4)
280
281 #define put_fs_byte(x,addr) __put_user((x),(unsigned char *)(addr),1)
282 #define put_fs_word(x,addr) __put_user((x),(unsigned short *)(addr),2)
283 #define put_fs_long(x,addr) __put_user((x),(unsigned int *)(addr),4)
284
285 #ifdef WE_REALLY_WANT_TO_USE_A_BROKEN_INTERFACE
286
287 static inline unsigned short get_user_word(const short *addr)
288 {
289         return __get_user(addr, 2);
290 }
291
292 static inline unsigned char get_user_byte(const char * addr)
293 {
294         return __get_user(addr,1);
295 }
296
297 static inline unsigned long get_user_long(const int *addr)
298 {
299         return __get_user(addr, 4);
300 }
301
302 static inline void put_user_byte(char val,char *addr)
303 {
304         __put_user(val, addr, 1);
305 }
306
307 static inline void put_user_word(short val,short * addr)
308 {
309         __put_user(val, addr, 2);
310 }
311
312 static inline void put_user_long(unsigned long val,int * addr)
313 {
314         __put_user(val, addr, 4);
315 }
316
317 #endif
318
319 /*
320  * Someone who knows GNU asm better than I should double check the following.
321  * It seems to work, but I don't know if I'm doing something subtly wrong.
322  * --- TYT, 11/24/91
323  * [ nothing wrong here, Linus: I just changed the ax to be any reg ]
324  */
325
326 static inline unsigned long get_fs(void)
327 {
328         unsigned long _v;
329         __asm__("mov %%fs,%w0":"=r" (_v):"0" (0));
330         return _v;
331 }
332
333 static inline unsigned long get_ds(void)
334 {
335         unsigned long _v;
336         __asm__("mov %%ds,%w0":"=r" (_v):"0" (0));
337         return _v;
338 }
339
340 static inline void set_fs(unsigned long val)
341 {
342         __asm__ __volatile__("mov %w0,%%fs": /* no output */ :"r" (val));
343 }
344
345 static inline void set_ds(unsigned long val)
346 {
347         __asm__ __volatile__("mov %w0,%%ds": /* no output */ :"r" (val));
348 }
349
350
351 #endif /* __ASSEMBLY__ */
352
353 #endif /* _ASM_SEGMENT_H */