Use free Windows DDK and compile with latest MinGW releases.
[reactos.git] / reactos / include / ntos / 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 */