sync to trunk revision 36500
[reactos.git] / reactos / include / psdk / intrin_x86.h
1 /*
2 Compatibility <intrin_x86.h> header for GCC -- GCC equivalents of intrinsic
3 Microsoft Visual C++ functions. Originally developed for the ReactOS
4 (<http://www.reactos.org/>) and TinyKrnl (<http://www.tinykrnl.org/>)
5 projects.
6
7 Copyright (c) 2006 KJK::Hyperion <hackbunny@reactos.com>
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the "Software"),
11 to deal in the Software without restriction, including without limitation
12 the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 and/or sell copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following conditions:
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26 */
27
28 #ifndef KJK_INTRIN_X86_H_
29 #define KJK_INTRIN_X86_H_
30
31 /*
32 FIXME: review all "memory" clobbers, add/remove to match Visual C++
33 behavior: some "obvious" memory barriers are not present in the Visual C++
34 implementation - e.g. __stosX; on the other hand, some memory barriers that
35 *are* present could have been missed
36 */
37
38 /*
39 NOTE: this is a *compatibility* header. Some functions may look wrong at
40 first, but they're only "as wrong" as they would be on Visual C++. Our
41 priority is compatibility
42
43 NOTE: unlike most people who write inline asm for GCC, I didn't pull the
44 constraints and the uses of __volatile__ out of my... hat. Do not touch
45 them. I hate cargo cult programming
46
47 NOTE: be very careful with declaring "memory" clobbers. Some "obvious"
48 barriers aren't there in Visual C++ (e.g. __stosX)
49
50 NOTE: review all intrinsics with a return value, add/remove __volatile__
51 where necessary. If an intrinsic whose value is ignored generates a no-op
52 under Visual C++, __volatile__ must be omitted; if it always generates code
53 (for example, if it has side effects), __volatile__ must be specified. GCC
54 will only optimize out non-volatile asm blocks with outputs, so input-only
55 blocks are safe. Oddities such as the non-volatile 'rdmsr' are intentional
56 and follow Visual C++ behavior
57
58 NOTE: on GCC 4.1.0, please use the __sync_* built-ins for barriers and
59 atomic operations. Test the version like this:
60
61 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
62 ...
63
64 Pay attention to the type of barrier. Make it match with what Visual C++
65 would use in the same case
66 */
67
68 /*** Stack frame juggling ***/
69 #define _ReturnAddress() (__builtin_return_address(0))
70 #define _AddressOfReturnAddress() (&(((void **)(__builtin_frame_address(0)))[1]))
71 /* TODO: __getcallerseflags but how??? */
72
73
74 /*** Atomic operations ***/
75
76 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
77 #define _ReadWriteBarrier() __sync_synchronize()
78 #else
79 static void __inline__ __attribute__((always_inline)) _MemoryBarrier(void)
80 {
81 __asm__ __volatile__("" : : : "memory");
82 }
83 #define _ReadWriteBarrier() _MemoryBarrier()
84 #endif
85
86 /* BUGBUG: GCC only supports full barriers */
87 #define _ReadBarrier _ReadWriteBarrier
88 #define _WriteBarrier _ReadWriteBarrier
89
90 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
91
92 static __inline__ __attribute__((always_inline)) char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)
93 {
94 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
95 }
96
97 static __inline__ __attribute__((always_inline)) short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)
98 {
99 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
100 }
101
102 static __inline__ __attribute__((always_inline)) long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)
103 {
104 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
105 }
106
107 static __inline__ __attribute__((always_inline)) void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)
108 {
109 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
110 }
111
112 static __inline__ __attribute__((always_inline)) long _InterlockedExchange(volatile long * const Target, const long Value)
113 {
114 /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */
115 __sync_synchronize();
116 return __sync_lock_test_and_set(Target, Value);
117 }
118
119 #if defined(_M_AMD64)
120 static __inline__ __attribute__((always_inline)) long long _InterlockedExchange64(volatile long long * const Target, const long long Value)
121 {
122 /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */
123 __sync_synchronize();
124 return __sync_lock_test_and_set(Target, Value);
125 }
126 #endif
127
128 static __inline__ __attribute__((always_inline)) void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)
129 {
130 /* NOTE: ditto */
131 __sync_synchronize();
132 return __sync_lock_test_and_set(Target, Value);
133 }
134
135 static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd16(volatile short * const Addend, const short Value)
136 {
137 return __sync_fetch_and_add(Addend, Value);
138 }
139
140 static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)
141 {
142 return __sync_fetch_and_add(Addend, Value);
143 }
144
145 #if defined(_M_AMD64)
146 static __inline__ __attribute__((always_inline)) long long _InterlockedExchangeAdd64(volatile long long * const Addend, const long long Value)
147 {
148 return __sync_fetch_and_add(Addend, Value);
149 }
150 #endif
151
152 static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask)
153 {
154 return __sync_fetch_and_and(value, mask);
155 }
156
157 static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask)
158 {
159 return __sync_fetch_and_and(value, mask);
160 }
161
162 static __inline__ __attribute__((always_inline)) long _InterlockedAnd(volatile long * const value, const long mask)
163 {
164 return __sync_fetch_and_and(value, mask);
165 }
166
167 #if defined(_M_AMD64)
168 static __inline__ __attribute__((always_inline)) long _InterlockedAnd64(volatile long long * const value, const long long mask)
169 {
170 return __sync_fetch_and_and(value, mask);
171 }
172 #endif
173
174 static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask)
175 {
176 return __sync_fetch_and_or(value, mask);
177 }
178
179 static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask)
180 {
181 return __sync_fetch_and_or(value, mask);
182 }
183
184 static __inline__ __attribute__((always_inline)) long _InterlockedOr(volatile long * const value, const long mask)
185 {
186 return __sync_fetch_and_or(value, mask);
187 }
188
189 #if defined(_M_AMD64)
190 static __inline__ __attribute__((always_inline)) long _InterlockedOr64(volatile long long * const value, const long long mask)
191 {
192 return __sync_fetch_and_or(value, mask);
193 }
194 #endif
195
196 static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask)
197 {
198 return __sync_fetch_and_xor(value, mask);
199 }
200
201 static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask)
202 {
203 return __sync_fetch_and_xor(value, mask);
204 }
205
206 static __inline__ __attribute__((always_inline)) long _InterlockedXor(volatile long * const value, const long mask)
207 {
208 return __sync_fetch_and_xor(value, mask);
209 }
210
211 #else
212
213 static __inline__ __attribute__((always_inline)) char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)
214 {
215 char retval = Comperand;
216 __asm__("lock; cmpxchgb %b[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory");
217 return retval;
218 }
219
220 static __inline__ __attribute__((always_inline)) short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)
221 {
222 short retval = Comperand;
223 __asm__("lock; cmpxchgw %w[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory");
224 return retval;
225 }
226
227 static __inline__ __attribute__((always_inline)) long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)
228 {
229 long retval = Comperand;
230 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory");
231 return retval;
232 }
233
234 static __inline__ __attribute__((always_inline)) void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)
235 {
236 void * retval = (void *)Comperand;
237 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "=a" (retval) : "[retval]" (retval), [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory");
238 return retval;
239 }
240
241 static __inline__ __attribute__((always_inline)) long _InterlockedExchange(volatile long * const Target, const long Value)
242 {
243 long retval = Value;
244 __asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory");
245 return retval;
246 }
247
248 static __inline__ __attribute__((always_inline)) void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)
249 {
250 void * retval = Value;
251 __asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory");
252 return retval;
253 }
254
255 static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd16(volatile short * const Addend, const short Value)
256 {
257 long retval = Value;
258 __asm__("lock; xaddw %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory");
259 return retval;
260 }
261
262 static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)
263 {
264 long retval = Value;
265 __asm__("lock; xaddl %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory");
266 return retval;
267 }
268
269 static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask)
270 {
271 char x;
272 char y;
273
274 y = *value;
275
276 do
277 {
278 x = y;
279 y = _InterlockedCompareExchange8(value, x & mask, x);
280 }
281 while(y != x);
282
283 return y;
284 }
285
286 static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask)
287 {
288 short x;
289 short y;
290
291 y = *value;
292
293 do
294 {
295 x = y;
296 y = _InterlockedCompareExchange16(value, x & mask, x);
297 }
298 while(y != x);
299
300 return y;
301 }
302
303 static __inline__ __attribute__((always_inline)) long _InterlockedAnd(volatile long * const value, const long mask)
304 {
305 long x;
306 long y;
307
308 y = *value;
309
310 do
311 {
312 x = y;
313 y = _InterlockedCompareExchange(value, x & mask, x);
314 }
315 while(y != x);
316
317 return y;
318 }
319
320 static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask)
321 {
322 char x;
323 char y;
324
325 y = *value;
326
327 do
328 {
329 x = y;
330 y = _InterlockedCompareExchange8(value, x | mask, x);
331 }
332 while(y != x);
333
334 return y;
335 }
336
337 static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask)
338 {
339 short x;
340 short y;
341
342 y = *value;
343
344 do
345 {
346 x = y;
347 y = _InterlockedCompareExchange16(value, x | mask, x);
348 }
349 while(y != x);
350
351 return y;
352 }
353
354 static __inline__ __attribute__((always_inline)) long _InterlockedOr(volatile long * const value, const long mask)
355 {
356 long x;
357 long y;
358
359 y = *value;
360
361 do
362 {
363 x = y;
364 y = _InterlockedCompareExchange(value, x | mask, x);
365 }
366 while(y != x);
367
368 return y;
369 }
370
371 static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask)
372 {
373 char x;
374 char y;
375
376 y = *value;
377
378 do
379 {
380 x = y;
381 y = _InterlockedCompareExchange8(value, x ^ mask, x);
382 }
383 while(y != x);
384
385 return y;
386 }
387
388 static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask)
389 {
390 short x;
391 short y;
392
393 y = *value;
394
395 do
396 {
397 x = y;
398 y = _InterlockedCompareExchange16(value, x ^ mask, x);
399 }
400 while(y != x);
401
402 return y;
403 }
404
405 static __inline__ __attribute__((always_inline)) long _InterlockedXor(volatile long * const value, const long mask)
406 {
407 long x;
408 long y;
409
410 y = *value;
411
412 do
413 {
414 x = y;
415 y = _InterlockedCompareExchange(value, x ^ mask, x);
416 }
417 while(y != x);
418
419 return y;
420 }
421
422 #endif
423
424 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 && defined(__x86_64__)
425
426 static __inline__ __attribute__((always_inline)) long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)
427 {
428 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
429 }
430
431 #else
432
433 static __inline__ __attribute__((always_inline)) long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)
434 {
435 long long retval = Comperand;
436
437 __asm__
438 (
439 "lock; cmpxchg8b %[Destination]" :
440 [retval] "+A" (retval) :
441 [Destination] "m" (*Destination),
442 "b" ((unsigned long)((Exchange >> 0) & 0xFFFFFFFF)),
443 "c" ((unsigned long)((Exchange >> 32) & 0xFFFFFFFF)) :
444 "memory"
445 );
446
447 return retval;
448 }
449
450 #endif
451
452 static __inline__ __attribute__((always_inline)) long _InterlockedAddLargeStatistic(volatile long long * const Addend, const long Value)
453 {
454 __asm__
455 (
456 "lock; add %[Value], %[Lo32];"
457 "jae LABEL%=;"
458 "lock; adc $0, %[Hi32];"
459 "LABEL%=:;" :
460 [Lo32] "=m" (*((volatile long *)(Addend) + 0)), [Hi32] "=m" (*((volatile long *)(Addend) + 1)) :
461 [Value] "ir" (Value)
462 );
463
464 return Value;
465 }
466
467 static __inline__ __attribute__((always_inline)) long _InterlockedDecrement(volatile long * const lpAddend)
468 {
469 return _InterlockedExchangeAdd(lpAddend, -1) - 1;
470 }
471
472 static __inline__ __attribute__((always_inline)) long _InterlockedIncrement(volatile long * const lpAddend)
473 {
474 return _InterlockedExchangeAdd(lpAddend, 1) + 1;
475 }
476
477 static __inline__ __attribute__((always_inline)) long _InterlockedDecrement16(volatile short * const lpAddend)
478 {
479 return _InterlockedExchangeAdd16(lpAddend, -1) - 1;
480 }
481
482 static __inline__ __attribute__((always_inline)) long _InterlockedIncrement16(volatile short * const lpAddend)
483 {
484 return _InterlockedExchangeAdd16(lpAddend, 1) + 1;
485 }
486
487 #if defined(_M_AMD64)
488 static __inline__ __attribute__((always_inline)) long long _InterlockedDecrement64(volatile long long * const lpAddend)
489 {
490 return _InterlockedExchangeAdd64(lpAddend, -1) - 1;
491 }
492
493 static __inline__ __attribute__((always_inline)) long long _InterlockedIncrement64(volatile long long * const lpAddend)
494 {
495 return _InterlockedExchangeAdd64(lpAddend, 1) + 1;
496 }
497 #endif
498
499 static __inline__ __attribute__((always_inline)) unsigned char _interlockedbittestandreset(volatile long * a, const long b)
500 {
501 unsigned char retval;
502 __asm__("lock; btrl %[b], %[a]; setb %b[retval]" : [retval] "=r" (retval), [a] "=m" (*a) : [b] "Ir" (b) : "memory");
503 return retval;
504 }
505
506 #if defined(_M_AMD64)
507 static __inline__ __attribute__((always_inline)) unsigned char _interlockedbittestandreset64(volatile long long * a, const long long b)
508 {
509 unsigned char retval;
510 __asm__("lock; btrq %[b], %[a]; setb %b[retval]" : [retval] "=r" (retval), [a] "=m" (*a) : [b] "Ir" (b) : "memory");
511 return retval;
512 }
513 #endif
514
515 static __inline__ __attribute__((always_inline)) unsigned char _interlockedbittestandset(volatile long * a, const long b)
516 {
517 unsigned char retval;
518 __asm__("lock; btsl %[b], %[a]; setc %b[retval]" : [retval] "=r" (retval), [a] "=m" (*a) : [b] "Ir" (b) : "memory");
519 return retval;
520 }
521
522 #if defined(_M_AMD64)
523 static __inline__ __attribute__((always_inline)) unsigned char _interlockedbittestandset64(volatile long long * a, const long long b)
524 {
525 unsigned char retval;
526 __asm__("lock; btsq %[b], %[a]; setc %b[retval]" : [retval] "=r" (retval), [a] "=m" (*a) : [b] "Ir" (b) : "memory");
527 return retval;
528 }
529 #endif
530
531 /*** String operations ***/
532 /* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */
533 static __inline__ __attribute__((always_inline)) void __stosb(unsigned char * Dest, const unsigned char Data, size_t Count)
534 {
535 __asm__ __volatile__
536 (
537 "rep; stosb" :
538 [Dest] "=D" (Dest), [Count] "=c" (Count) :
539 "[Dest]" (Dest), "a" (Data), "[Count]" (Count)
540 );
541 }
542
543 static __inline__ __attribute__((always_inline)) void __stosw(unsigned short * Dest, const unsigned short Data, size_t Count)
544 {
545 __asm__ __volatile__
546 (
547 "rep; stosw" :
548 [Dest] "=D" (Dest), [Count] "=c" (Count) :
549 "[Dest]" (Dest), "a" (Data), "[Count]" (Count)
550 );
551 }
552
553 static __inline__ __attribute__((always_inline)) void __stosd(unsigned long * Dest, const unsigned long Data, size_t Count)
554 {
555 __asm__ __volatile__
556 (
557 "rep; stosl" :
558 [Dest] "=D" (Dest), [Count] "=c" (Count) :
559 "[Dest]" (Dest), "a" (Data), "[Count]" (Count)
560 );
561 }
562
563 static __inline__ __attribute__((always_inline)) void __movsb(unsigned char * Destination, const unsigned char * Source, size_t Count)
564 {
565 __asm__ __volatile__
566 (
567 "rep; movsb" :
568 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
569 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
570 );
571 }
572
573 static __inline__ __attribute__((always_inline)) void __movsw(unsigned short * Destination, const unsigned short * Source, size_t Count)
574 {
575 __asm__ __volatile__
576 (
577 "rep; movsw" :
578 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
579 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
580 );
581 }
582
583 static __inline__ __attribute__((always_inline)) void __movsd(unsigned long * Destination, const unsigned long * Source, size_t Count)
584 {
585 __asm__ __volatile__
586 (
587 "rep; movsd" :
588 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
589 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
590 );
591 }
592
593 #if defined(_M_AMD64)
594 /*** GS segment addressing ***/
595
596 static __inline__ __attribute__((always_inline)) void __writegsbyte(const unsigned long Offset, const unsigned char Data)
597 {
598 __asm__ __volatile__("movb %b[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
599 }
600
601 static __inline__ __attribute__((always_inline)) void __writegsword(const unsigned long Offset, const unsigned short Data)
602 {
603 __asm__ __volatile__("movw %w[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
604 }
605
606 static __inline__ __attribute__((always_inline)) void __writegsdword(const unsigned long Offset, const unsigned long Data)
607 {
608 __asm__ __volatile__("movl %k[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
609 }
610
611 static __inline__ __attribute__((always_inline)) void __writegsqword(const unsigned long Offset, const unsigned __int64 Data)
612 {
613 __asm__ __volatile__("movq %q[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
614 }
615
616 static __inline__ __attribute__((always_inline)) unsigned char __readgsbyte(const unsigned long Offset)
617 {
618 unsigned char value;
619 __asm__ __volatile__("movb %%gs:%a[Offset], %b[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
620 return value;
621 }
622
623 static __inline__ __attribute__((always_inline)) unsigned short __readgsword(const unsigned long Offset)
624 {
625 unsigned short value;
626 __asm__ __volatile__("movw %%gs:%a[Offset], %w[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
627 return value;
628 }
629
630 static __inline__ __attribute__((always_inline)) unsigned long __readgsdword(const unsigned long Offset)
631 {
632 unsigned long value;
633 __asm__ __volatile__("movl %%gs:%a[Offset], %k[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
634 return value;
635 }
636
637 static __inline__ __attribute__((always_inline)) unsigned __int64 __readgsqword(const unsigned long Offset)
638 {
639 unsigned __int64 value;
640 __asm__ __volatile__("movq %%gs:%a[Offset], %q[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
641 return value;
642 }
643
644 static __inline__ __attribute__((always_inline)) void __incgsbyte(const unsigned long Offset)
645 {
646 __asm__ __volatile__("incb %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
647 }
648
649 static __inline__ __attribute__((always_inline)) void __incgsword(const unsigned long Offset)
650 {
651 __asm__ __volatile__("incw %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
652 }
653
654 static __inline__ __attribute__((always_inline)) void __incgsdword(const unsigned long Offset)
655 {
656 __asm__ __volatile__("incl %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
657 }
658
659 static __inline__ __attribute__((always_inline)) void __addgsbyte(const unsigned long Offset, const unsigned char Data)
660 {
661 __asm__ __volatile__("addb %b[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
662 }
663
664 static __inline__ __attribute__((always_inline)) void __addgsword(const unsigned long Offset, const unsigned short Data)
665 {
666 __asm__ __volatile__("addw %w[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
667 }
668
669 static __inline__ __attribute__((always_inline)) void __addgsdword(const unsigned long Offset, const unsigned int Data)
670 {
671 __asm__ __volatile__("addl %k[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
672 }
673
674 static __inline__ __attribute__((always_inline)) void __addgsqword(const unsigned long Offset, const unsigned __int64 Data)
675 {
676 __asm__ __volatile__("addq %k[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
677 }
678
679 #else
680 /*** FS segment addressing ***/
681 static __inline__ __attribute__((always_inline)) void __writefsbyte(const unsigned long Offset, const unsigned char Data)
682 {
683 __asm__ __volatile__("movb %b[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
684 }
685
686 static __inline__ __attribute__((always_inline)) void __writefsword(const unsigned long Offset, const unsigned short Data)
687 {
688 __asm__ __volatile__("movw %w[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
689 }
690
691 static __inline__ __attribute__((always_inline)) void __writefsdword(const unsigned long Offset, const unsigned long Data)
692 {
693 __asm__ __volatile__("movl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
694 }
695
696 static __inline__ __attribute__((always_inline)) unsigned char __readfsbyte(const unsigned long Offset)
697 {
698 unsigned char value;
699 __asm__ __volatile__("movb %%fs:%a[Offset], %b[value]" : [value] "=q" (value) : [Offset] "irm" (Offset) : "memory");
700 return value;
701 }
702
703 static __inline__ __attribute__((always_inline)) unsigned short __readfsword(const unsigned long Offset)
704 {
705 unsigned short value;
706 __asm__ __volatile__("movw %%fs:%a[Offset], %w[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
707 return value;
708 }
709
710 static __inline__ __attribute__((always_inline)) unsigned long __readfsdword(const unsigned long Offset)
711 {
712 unsigned long value;
713 __asm__ __volatile__("movl %%fs:%a[Offset], %k[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
714 return value;
715 }
716
717 static __inline__ __attribute__((always_inline)) void __incfsbyte(const unsigned long Offset)
718 {
719 __asm__ __volatile__("incb %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
720 }
721
722 static __inline__ __attribute__((always_inline)) void __incfsword(const unsigned long Offset)
723 {
724 __asm__ __volatile__("incw %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
725 }
726
727 static __inline__ __attribute__((always_inline)) void __incfsdword(const unsigned long Offset)
728 {
729 __asm__ __volatile__("incl %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
730 }
731
732 /* NOTE: the bizarre implementation of __addfsxxx mimics the broken Visual C++ behavior */
733 static __inline__ __attribute__((always_inline)) void __addfsbyte(const unsigned long Offset, const unsigned char Data)
734 {
735 if(!__builtin_constant_p(Offset))
736 __asm__ __volatile__("addb %k[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset) : "memory");
737 else
738 __asm__ __volatile__("addb %b[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
739 }
740
741 static __inline__ __attribute__((always_inline)) void __addfsword(const unsigned long Offset, const unsigned short Data)
742 {
743 if(!__builtin_constant_p(Offset))
744 __asm__ __volatile__("addw %k[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset) : "memory");
745 else
746 __asm__ __volatile__("addw %w[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
747 }
748
749 static __inline__ __attribute__((always_inline)) void __addfsdword(const unsigned long Offset, const unsigned int Data)
750 {
751 if(!__builtin_constant_p(Offset))
752 __asm__ __volatile__("addl %k[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset) : "memory");
753 else
754 __asm__ __volatile__("addl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
755 }
756 #endif
757
758
759 /*** Bit manipulation ***/
760 static __inline__ __attribute__((always_inline)) unsigned char _BitScanForward(unsigned long * const Index, const unsigned long Mask)
761 {
762 __asm__("bsfl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
763 return Mask ? 1 : 0;
764 }
765
766 static __inline__ __attribute__((always_inline)) unsigned char _BitScanReverse(unsigned long * const Index, const unsigned long Mask)
767 {
768 __asm__("bsrl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
769 return Mask ? 1 : 0;
770 }
771
772 /* NOTE: again, the bizarre implementation follows Visual C++ */
773 static __inline__ __attribute__((always_inline)) unsigned char _bittest(const long * const a, const long b)
774 {
775 unsigned char retval;
776
777 if(__builtin_constant_p(b))
778 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));
779 else
780 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));
781
782 return retval;
783 }
784
785 static __inline__ __attribute__((always_inline)) unsigned char _bittestandcomplement(long * const a, const long b)
786 {
787 unsigned char retval;
788
789 if(__builtin_constant_p(b))
790 __asm__("btc %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));
791 else
792 __asm__("btc %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));
793
794 return retval;
795 }
796
797 static __inline__ __attribute__((always_inline)) unsigned char _bittestandreset(long * const a, const long b)
798 {
799 unsigned char retval;
800
801 if(__builtin_constant_p(b))
802 __asm__("btr %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));
803 else
804 __asm__("btr %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));
805
806 return retval;
807 }
808
809 static __inline__ __attribute__((always_inline)) unsigned char _bittestandset(long * const a, const long b)
810 {
811 unsigned char retval;
812
813 if(__builtin_constant_p(b))
814 __asm__("bts %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));
815 else
816 __asm__("bts %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));
817
818 return retval;
819 }
820
821 static __inline__ __attribute__((always_inline)) unsigned char _rotl8(const unsigned char value, const unsigned char shift)
822 {
823 unsigned char retval;
824 __asm__("rolb %b[shift], %b[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
825 return retval;
826 }
827
828 static __inline__ __attribute__((always_inline)) unsigned short _rotl16(const unsigned short value, const unsigned char shift)
829 {
830 unsigned short retval;
831 __asm__("rolw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
832 return retval;
833 }
834
835 #ifndef __MSVCRT__
836 static __inline__ __attribute__((always_inline)) unsigned int _rotl(const unsigned int value, const int shift)
837 {
838 unsigned long retval;
839 __asm__("roll %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
840 return retval;
841 }
842
843 static __inline__ __attribute__((always_inline)) unsigned long _rotr(const unsigned int value, const unsigned char shift)
844 {
845 unsigned long retval;
846 __asm__("rorl %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
847 return retval;
848 }
849 #endif
850
851 static __inline__ __attribute__((always_inline)) unsigned char _rotr8(const unsigned char value, const unsigned char shift)
852 {
853 unsigned char retval;
854 __asm__("rorb %b[shift], %b[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
855 return retval;
856 }
857
858 static __inline__ __attribute__((always_inline)) unsigned short _rotr16(const unsigned short value, const unsigned char shift)
859 {
860 unsigned short retval;
861 __asm__("rorw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
862 return retval;
863 }
864
865 /*
866 NOTE: in __ll_lshift, __ll_rshift and __ull_rshift we use the "A"
867 constraint (edx:eax) for the Mask argument, because it's the only way GCC
868 can pass 64-bit operands around - passing the two 32 bit parts separately
869 just confuses it. Also we declare Bit as an int and then truncate it to
870 match Visual C++ behavior
871 */
872 static __inline__ __attribute__((always_inline)) unsigned long long __ll_lshift(const unsigned long long Mask, const int Bit)
873 {
874 unsigned long long retval = Mask;
875
876 __asm__
877 (
878 "shldl %b[Bit], %%eax, %%edx; sall %b[Bit], %%eax" :
879 "+A" (retval) :
880 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
881 );
882
883 return retval;
884 }
885
886 static __inline__ __attribute__((always_inline)) long long __ll_rshift(const long long Mask, const int Bit)
887 {
888 unsigned long long retval = Mask;
889
890 __asm__
891 (
892 "shldl %b[Bit], %%eax, %%edx; sarl %b[Bit], %%eax" :
893 "+A" (retval) :
894 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
895 );
896
897 return retval;
898 }
899
900 static __inline__ __attribute__((always_inline)) unsigned long long __ull_rshift(const unsigned long long Mask, int Bit)
901 {
902 unsigned long long retval = Mask;
903
904 __asm__
905 (
906 "shrdl %b[Bit], %%eax, %%edx; shrl %b[Bit], %%eax" :
907 "+A" (retval) :
908 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
909 );
910
911 return retval;
912 }
913
914 static __inline__ __attribute__((always_inline)) unsigned short _byteswap_ushort(unsigned short value)
915 {
916 unsigned short retval;
917 __asm__("rorw $8, %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value));
918 return retval;
919 }
920
921 static __inline__ __attribute__((always_inline)) unsigned long _byteswap_ulong(unsigned long value)
922 {
923 unsigned long retval;
924 __asm__("bswapl %[retval]" : [retval] "=rm" (retval) : "[retval]" (value));
925 return retval;
926 }
927
928 #ifdef _M_AMD64
929 static __inline__ __attribute__((always_inline)) unsigned __int64 _byteswap_uint64(unsigned __int64 value)
930 {
931 unsigned __int64 retval;
932 __asm__("bswapq %[retval]" : [retval] "=rm" (retval) : "[retval]" (value));
933 return retval;
934 }
935 #else
936 static __inline__ __attribute__((always_inline)) unsigned __int64 _byteswap_uint64(unsigned __int64 value)
937 {
938 union {
939 __int64 int64part;
940 struct {
941 unsigned long lowpart;
942 unsigned long hipart;
943 };
944 } retval;
945 retval.int64part = value;
946 __asm__("bswapl %[lowpart]\n"
947 "bswapl %[hipart]\n"
948 : [lowpart] "=rm" (retval.hipart), [hipart] "=rm" (retval.lowpart) : "[lowpart]" (retval.lowpart), "[hipart]" (retval.hipart) );
949 return retval.int64part;
950 }
951 #endif
952
953 /*** 64-bit math ***/
954 static __inline__ __attribute__((always_inline)) long long __emul(const int a, const int b)
955 {
956 long long retval;
957 __asm__("imull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b));
958 return retval;
959 }
960
961 static __inline__ __attribute__((always_inline)) unsigned long long __emulu(const unsigned int a, const unsigned int b)
962 {
963 unsigned long long retval;
964 __asm__("mull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b));
965 return retval;
966 }
967
968
969 /*** Port I/O ***/
970 static __inline__ __attribute__((always_inline)) unsigned char __inbyte(const unsigned short Port)
971 {
972 unsigned char byte;
973 __asm__ __volatile__("inb %w[Port], %b[byte]" : [byte] "=a" (byte) : [Port] "Nd" (Port));
974 return byte;
975 }
976
977 static __inline__ __attribute__((always_inline)) unsigned short __inword(const unsigned short Port)
978 {
979 unsigned short word;
980 __asm__ __volatile__("inw %w[Port], %w[word]" : [word] "=a" (word) : [Port] "Nd" (Port));
981 return word;
982 }
983
984 static __inline__ __attribute__((always_inline)) unsigned long __indword(const unsigned short Port)
985 {
986 unsigned long dword;
987 __asm__ __volatile__("inl %w[Port], %k[dword]" : [dword] "=a" (dword) : [Port] "Nd" (Port));
988 return dword;
989 }
990
991 static __inline__ __attribute__((always_inline)) void __inbytestring(unsigned short Port, unsigned char * Buffer, unsigned long Count)
992 {
993 __asm__ __volatile__
994 (
995 "rep; insb" :
996 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
997 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
998 "memory"
999 );
1000 }
1001
1002 static __inline__ __attribute__((always_inline)) void __inwordstring(unsigned short Port, unsigned short * Buffer, unsigned long Count)
1003 {
1004 __asm__ __volatile__
1005 (
1006 "rep; insw" :
1007 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
1008 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
1009 "memory"
1010 );
1011 }
1012
1013 static __inline__ __attribute__((always_inline)) void __indwordstring(unsigned short Port, unsigned long * Buffer, unsigned long Count)
1014 {
1015 __asm__ __volatile__
1016 (
1017 "rep; insl" :
1018 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
1019 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
1020 "memory"
1021 );
1022 }
1023
1024 static __inline__ __attribute__((always_inline)) void __outbyte(unsigned short const Port, const unsigned char Data)
1025 {
1026 __asm__ __volatile__("outb %b[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
1027 }
1028
1029 static __inline__ __attribute__((always_inline)) void __outword(unsigned short const Port, const unsigned short Data)
1030 {
1031 __asm__ __volatile__("outw %w[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
1032 }
1033
1034 static __inline__ __attribute__((always_inline)) void __outdword(unsigned short const Port, const unsigned long Data)
1035 {
1036 __asm__ __volatile__("outl %k[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
1037 }
1038
1039 static __inline__ __attribute__((always_inline)) void __outbytestring(unsigned short const Port, const unsigned char * const Buffer, const unsigned long Count)
1040 {
1041 __asm__ __volatile__("rep; outsb" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
1042 }
1043
1044 static __inline__ __attribute__((always_inline)) void __outwordstring(unsigned short const Port, const unsigned short * const Buffer, const unsigned long Count)
1045 {
1046 __asm__ __volatile__("rep; outsw" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
1047 }
1048
1049 static __inline__ __attribute__((always_inline)) void __outdwordstring(unsigned short const Port, const unsigned long * const Buffer, const unsigned long Count)
1050 {
1051 __asm__ __volatile__("rep; outsl" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
1052 }
1053
1054
1055 /*** System information ***/
1056 static __inline__ __attribute__((always_inline)) void __cpuid(int CPUInfo[], const int InfoType)
1057 {
1058 __asm__ __volatile__("cpuid" : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3]) : "a" (InfoType));
1059 }
1060
1061 static __inline__ __attribute__((always_inline)) unsigned long long __rdtsc(void)
1062 {
1063 #ifdef _M_AMD64
1064 unsigned long long low, high;
1065 __asm__ __volatile__("rdtsc" : "=a"(low), "=d"(high));
1066 return low | (high << 32);
1067 #else
1068 unsigned long long retval;
1069 __asm__ __volatile__("rdtsc" : "=A"(retval));
1070 return retval;
1071 #endif
1072 }
1073
1074 static __inline__ __attribute__((always_inline)) void __writeeflags(uintptr_t Value)
1075 {
1076 __asm__ __volatile__("push %0\n popf" : : "rim"(Value));
1077 }
1078
1079 static __inline__ __attribute__((always_inline)) uintptr_t __readeflags(void)
1080 {
1081 uintptr_t retval;
1082 __asm__ __volatile__("pushf\n pop %0" : "=rm"(retval));
1083 return retval;
1084 }
1085
1086 /*** Interrupts ***/
1087 static __inline__ __attribute__((always_inline)) void __debugbreak(void)
1088 {
1089 __asm__("int $3");
1090 }
1091
1092 static __inline__ __attribute__((always_inline)) void __int2c(void)
1093 {
1094 __asm__("int $0x2c");
1095 }
1096
1097 static __inline__ __attribute__((always_inline)) void _disable(void)
1098 {
1099 __asm__("cli");
1100 }
1101
1102 static __inline__ __attribute__((always_inline)) void _enable(void)
1103 {
1104 __asm__("sti");
1105 }
1106
1107
1108 /*** Protected memory management ***/
1109
1110 static __inline__ __attribute__((always_inline)) void __writecr0(const unsigned __int64 Data)
1111 {
1112 __asm__("mov %[Data], %%cr0" : : [Data] "q" (Data) : "memory");
1113 }
1114
1115 static __inline__ __attribute__((always_inline)) void __writecr3(const unsigned __int64 Data)
1116 {
1117 __asm__("mov %[Data], %%cr3" : : [Data] "q" (Data) : "memory");
1118 }
1119
1120 static __inline__ __attribute__((always_inline)) void __writecr4(const unsigned __int64 Data)
1121 {
1122 __asm__("mov %[Data], %%cr4" : : [Data] "q" (Data) : "memory");
1123 }
1124
1125 #ifdef _M_AMD64
1126 static __inline__ __attribute__((always_inline)) void __writecr8(const unsigned __int64 Data)
1127 {
1128 __asm__("mov %[Data], %%cr8" : : [Data] "q" (Data) : "memory");
1129 }
1130 #endif
1131
1132 static __inline__ __attribute__((always_inline)) unsigned __int64 __readcr0(void)
1133 {
1134 unsigned __int64 value;
1135 __asm__ __volatile__("mov %%cr0, %[value]" : [value] "=q" (value));
1136 return value;
1137 }
1138
1139 static __inline__ __attribute__((always_inline)) unsigned __int64 __readcr2(void)
1140 {
1141 unsigned __int64 value;
1142 __asm__ __volatile__("mov %%cr2, %[value]" : [value] "=q" (value));
1143 return value;
1144 }
1145
1146 static __inline__ __attribute__((always_inline)) unsigned __int64 __readcr3(void)
1147 {
1148 unsigned __int64 value;
1149 __asm__ __volatile__("mov %%cr3, %[value]" : [value] "=q" (value));
1150 return value;
1151 }
1152
1153 static __inline__ __attribute__((always_inline)) unsigned __int64 __readcr4(void)
1154 {
1155 unsigned __int64 value;
1156 __asm__ __volatile__("mov %%cr4, %[value]" : [value] "=q" (value));
1157 return value;
1158 }
1159
1160 #ifdef _M_AMD64
1161 static __inline__ __attribute__((always_inline)) unsigned __int64 __readcr8(void)
1162 {
1163 unsigned __int64 value;
1164 __asm__ __volatile__("movq %%cr8, %q[value]" : [value] "=q" (value));
1165 return value;
1166 }
1167 #endif
1168
1169 #ifdef _M_AMD64
1170 static __inline__ __attribute__((always_inline)) unsigned __int64 __readdr(unsigned int reg)
1171 {
1172 unsigned __int64 value;
1173 switch (reg)
1174 {
1175 case 0:
1176 __asm__ __volatile__("movq %%dr0, %q[value]" : [value] "=q" (value));
1177 break;
1178 case 1:
1179 __asm__ __volatile__("movq %%dr1, %q[value]" : [value] "=q" (value));
1180 break;
1181 case 2:
1182 __asm__ __volatile__("movq %%dr2, %q[value]" : [value] "=q" (value));
1183 break;
1184 case 3:
1185 __asm__ __volatile__("movq %%dr3, %q[value]" : [value] "=q" (value));
1186 break;
1187 case 4:
1188 __asm__ __volatile__("movq %%dr4, %q[value]" : [value] "=q" (value));
1189 break;
1190 case 5:
1191 __asm__ __volatile__("movq %%dr5, %q[value]" : [value] "=q" (value));
1192 break;
1193 case 6:
1194 __asm__ __volatile__("movq %%dr6, %q[value]" : [value] "=q" (value));
1195 break;
1196 case 7:
1197 __asm__ __volatile__("movq %%dr7, %q[value]" : [value] "=q" (value));
1198 break;
1199 }
1200 return value;
1201 }
1202
1203 static __inline__ __attribute__((always_inline)) void __writedr(unsigned reg, unsigned __int64 value)
1204 {
1205 switch (reg)
1206 {
1207 case 0:
1208 __asm__("movq %q[value], %%dr0" : : [value] "q" (value) : "memory");
1209 break;
1210 case 1:
1211 __asm__("movq %q[value], %%dr1" : : [value] "q" (value) : "memory");
1212 break;
1213 case 2:
1214 __asm__("movq %q[value], %%dr2" : : [value] "q" (value) : "memory");
1215 break;
1216 case 3:
1217 __asm__("movq %q[value], %%dr3" : : [value] "q" (value) : "memory");
1218 break;
1219 case 4:
1220 __asm__("movq %q[value], %%dr4" : : [value] "q" (value) : "memory");
1221 break;
1222 case 5:
1223 __asm__("movq %q[value], %%dr5" : : [value] "q" (value) : "memory");
1224 break;
1225 case 6:
1226 __asm__("movq %q[value], %%dr6" : : [value] "q" (value) : "memory");
1227 break;
1228 case 7:
1229 __asm__("movq %q[value], %%dr7" : : [value] "q" (value) : "memory");
1230 break;
1231 }
1232 }
1233 #endif
1234
1235 static __inline__ __attribute__((always_inline)) void __invlpg(void * const Address)
1236 {
1237 __asm__("invlpg %[Address]" : : [Address] "m" (*((unsigned char *)(Address))));
1238 }
1239
1240
1241 /*** System operations ***/
1242 static __inline__ __attribute__((always_inline)) unsigned long long __readmsr(const int reg)
1243 {
1244 #ifdef _M_AMD64
1245 unsigned long low, high;
1246 __asm__ __volatile__("rdmsr" : "=a" (low), "=d" (high) : "c" (reg));
1247 return (high << 32) | low;
1248 #else
1249 unsigned long long retval;
1250 __asm__ __volatile__("rdmsr" : "=A" (retval) : "c" (reg));
1251 return retval;
1252 #endif
1253 }
1254
1255 static __inline__ __attribute__((always_inline)) void __writemsr(const unsigned long Register, const unsigned long long Value)
1256 {
1257 #ifdef _M_AMD64
1258 __asm__ __volatile__("wrmsr" : : "a" (Value), "d" (Value >> 32), "c" (Register));
1259 #else
1260 __asm__ __volatile__("wrmsr" : : "A" (Value), "c" (Register));
1261 #endif
1262 }
1263
1264 static __inline__ __attribute__((always_inline)) unsigned long long __readpmc(const int counter)
1265 {
1266 unsigned long long retval;
1267 __asm__ __volatile__("rdpmc" : "=A" (retval) : "c" (counter));
1268 return retval;
1269 }
1270
1271 /* NOTE: an immediate value for 'a' will raise an ICE in Visual C++ */
1272 static __inline__ __attribute__((always_inline)) unsigned long __segmentlimit(const unsigned long a)
1273 {
1274 unsigned long retval;
1275 __asm__ __volatile__("lsl %[a], %[retval]" : [retval] "=r" (retval) : [a] "rm" (a));
1276 return retval;
1277 }
1278
1279 static __inline__ __attribute__((always_inline)) void __wbinvd(void)
1280 {
1281 __asm__ __volatile__("wbinvd");
1282 }
1283
1284 static __inline__ __attribute__((always_inline)) void __lidt(void *Source)
1285 {
1286 __asm__ __volatile__("lidt %0" : : "m"(*(short*)Source));
1287 }
1288
1289 static __inline__ __attribute__((always_inline)) void __sidt(void *Destination)
1290 {
1291 __asm__ __volatile__("sidt %0" : : "m"(*(short*)Destination) : "memory");
1292 }
1293
1294 #endif /* KJK_INTRIN_X86_H_ */
1295
1296 /* EOF */