Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenintrin_x86.h
Go to the documentation of this file.
00001 /* 00002 Compatibility <intrin_x86.h> header for GCC -- GCC equivalents of intrinsic 00003 Microsoft Visual C++ functions. Originally developed for the ReactOS 00004 (<http://www.reactos.org/>) and TinyKrnl (<http://www.tinykrnl.org/>) 00005 projects. 00006 00007 Copyright (c) 2006 KJK::Hyperion <hackbunny@reactos.com> 00008 00009 Permission is hereby granted, free of charge, to any person obtaining a 00010 copy of this software and associated documentation files (the "Software"), 00011 to deal in the Software without restriction, including without limitation 00012 the rights to use, copy, modify, merge, publish, distribute, sublicense, 00013 and/or sell copies of the Software, and to permit persons to whom the 00014 Software is furnished to do so, subject to the following conditions: 00015 00016 The above copyright notice and this permission notice shall be included in 00017 all copies or substantial portions of the Software. 00018 00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00024 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00025 DEALINGS IN THE SOFTWARE. 00026 */ 00027 00028 #ifndef KJK_INTRIN_X86_H_ 00029 #define KJK_INTRIN_X86_H_ 00030 00031 /* 00032 FIXME: review all "memory" clobbers, add/remove to match Visual C++ 00033 behavior: some "obvious" memory barriers are not present in the Visual C++ 00034 implementation - e.g. __stosX; on the other hand, some memory barriers that 00035 *are* present could have been missed 00036 */ 00037 00038 /* 00039 NOTE: this is a *compatibility* header. Some functions may look wrong at 00040 first, but they're only "as wrong" as they would be on Visual C++. Our 00041 priority is compatibility 00042 00043 NOTE: unlike most people who write inline asm for GCC, I didn't pull the 00044 constraints and the uses of __volatile__ out of my... hat. Do not touch 00045 them. I hate cargo cult programming 00046 00047 NOTE: be very careful with declaring "memory" clobbers. Some "obvious" 00048 barriers aren't there in Visual C++ (e.g. __stosX) 00049 00050 NOTE: review all intrinsics with a return value, add/remove __volatile__ 00051 where necessary. If an intrinsic whose value is ignored generates a no-op 00052 under Visual C++, __volatile__ must be omitted; if it always generates code 00053 (for example, if it has side effects), __volatile__ must be specified. GCC 00054 will only optimize out non-volatile asm blocks with outputs, so input-only 00055 blocks are safe. Oddities such as the non-volatile 'rdmsr' are intentional 00056 and follow Visual C++ behavior 00057 00058 NOTE: on GCC 4.1.0, please use the __sync_* built-ins for barriers and 00059 atomic operations. Test the version like this: 00060 00061 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 00062 ... 00063 00064 Pay attention to the type of barrier. Make it match with what Visual C++ 00065 would use in the same case 00066 */ 00067 00068 #ifdef __cplusplus 00069 extern "C" { 00070 #endif 00071 00072 /*** Stack frame juggling ***/ 00073 #define _ReturnAddress() (__builtin_return_address(0)) 00074 #define _AddressOfReturnAddress() (&(((void **)(__builtin_frame_address(0)))[1])) 00075 /* TODO: __getcallerseflags but how??? */ 00076 00077 /* Maybe the same for x86? */ 00078 #ifdef __x86_64__ 00079 #define _alloca(s) __builtin_alloca(s) 00080 #endif 00081 00082 /*** Memory barriers ***/ 00083 00084 __INTRIN_INLINE void _ReadWriteBarrier(void) 00085 { 00086 __asm__ __volatile__("" : : : "memory"); 00087 } 00088 00089 /* GCC only supports full barriers */ 00090 #define _ReadBarrier _ReadWriteBarrier 00091 #define _WriteBarrier _ReadWriteBarrier 00092 00093 __INTRIN_INLINE void _mm_mfence(void) 00094 { 00095 __asm__ __volatile__("mfence" : : : "memory"); 00096 } 00097 00098 __INTRIN_INLINE void _mm_lfence(void) 00099 { 00100 _ReadBarrier(); 00101 __asm__ __volatile__("lfence"); 00102 _ReadBarrier(); 00103 } 00104 00105 __INTRIN_INLINE void _mm_sfence(void) 00106 { 00107 _WriteBarrier(); 00108 __asm__ __volatile__("sfence"); 00109 _WriteBarrier(); 00110 } 00111 00112 #ifdef __x86_64__ 00113 __INTRIN_INLINE void __faststorefence(void) 00114 { 00115 long local; 00116 __asm__ __volatile__("lock; orl $0, %0;" : : "m"(local)); 00117 } 00118 #endif 00119 00120 00121 /*** Atomic operations ***/ 00122 00123 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 00124 00125 __INTRIN_INLINE char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand) 00126 { 00127 return __sync_val_compare_and_swap(Destination, Comperand, Exchange); 00128 } 00129 00130 __INTRIN_INLINE short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand) 00131 { 00132 return __sync_val_compare_and_swap(Destination, Comperand, Exchange); 00133 } 00134 00135 __INTRIN_INLINE long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand) 00136 { 00137 return __sync_val_compare_and_swap(Destination, Comperand, Exchange); 00138 } 00139 00140 __INTRIN_INLINE void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand) 00141 { 00142 return (void *)__sync_val_compare_and_swap(Destination, Comperand, Exchange); 00143 } 00144 00145 __INTRIN_INLINE long _InterlockedExchange(volatile long * const Target, const long Value) 00146 { 00147 /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */ 00148 __sync_synchronize(); 00149 return __sync_lock_test_and_set(Target, Value); 00150 } 00151 00152 #if defined(_M_AMD64) 00153 __INTRIN_INLINE long long _InterlockedExchange64(volatile long long * const Target, const long long Value) 00154 { 00155 /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */ 00156 __sync_synchronize(); 00157 return __sync_lock_test_and_set(Target, Value); 00158 } 00159 #endif 00160 00161 __INTRIN_INLINE void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value) 00162 { 00163 /* NOTE: ditto */ 00164 __sync_synchronize(); 00165 return (void *)__sync_lock_test_and_set(Target, Value); 00166 } 00167 00168 __INTRIN_INLINE long _InterlockedExchangeAdd16(volatile short * const Addend, const short Value) 00169 { 00170 return __sync_fetch_and_add(Addend, Value); 00171 } 00172 00173 __INTRIN_INLINE long _InterlockedExchangeAdd(volatile long * const Addend, const long Value) 00174 { 00175 return __sync_fetch_and_add(Addend, Value); 00176 } 00177 00178 #if defined(_M_AMD64) 00179 __INTRIN_INLINE long long _InterlockedExchangeAdd64(volatile long long * const Addend, const long long Value) 00180 { 00181 return __sync_fetch_and_add(Addend, Value); 00182 } 00183 #endif 00184 00185 __INTRIN_INLINE char _InterlockedAnd8(volatile char * const value, const char mask) 00186 { 00187 return __sync_fetch_and_and(value, mask); 00188 } 00189 00190 __INTRIN_INLINE short _InterlockedAnd16(volatile short * const value, const short mask) 00191 { 00192 return __sync_fetch_and_and(value, mask); 00193 } 00194 00195 __INTRIN_INLINE long _InterlockedAnd(volatile long * const value, const long mask) 00196 { 00197 return __sync_fetch_and_and(value, mask); 00198 } 00199 00200 #if defined(_M_AMD64) 00201 __INTRIN_INLINE long long _InterlockedAnd64(volatile long long * const value, const long long mask) 00202 { 00203 return __sync_fetch_and_and(value, mask); 00204 } 00205 #endif 00206 00207 __INTRIN_INLINE char _InterlockedOr8(volatile char * const value, const char mask) 00208 { 00209 return __sync_fetch_and_or(value, mask); 00210 } 00211 00212 __INTRIN_INLINE short _InterlockedOr16(volatile short * const value, const short mask) 00213 { 00214 return __sync_fetch_and_or(value, mask); 00215 } 00216 00217 __INTRIN_INLINE long _InterlockedOr(volatile long * const value, const long mask) 00218 { 00219 return __sync_fetch_and_or(value, mask); 00220 } 00221 00222 #if defined(_M_AMD64) 00223 __INTRIN_INLINE long long _InterlockedOr64(volatile long long * const value, const long long mask) 00224 { 00225 return __sync_fetch_and_or(value, mask); 00226 } 00227 #endif 00228 00229 __INTRIN_INLINE char _InterlockedXor8(volatile char * const value, const char mask) 00230 { 00231 return __sync_fetch_and_xor(value, mask); 00232 } 00233 00234 __INTRIN_INLINE short _InterlockedXor16(volatile short * const value, const short mask) 00235 { 00236 return __sync_fetch_and_xor(value, mask); 00237 } 00238 00239 __INTRIN_INLINE long _InterlockedXor(volatile long * const value, const long mask) 00240 { 00241 return __sync_fetch_and_xor(value, mask); 00242 } 00243 00244 #if defined(_M_AMD64) 00245 __INTRIN_INLINE long long _InterlockedXor64(volatile long long * const value, const long long mask) 00246 { 00247 return __sync_fetch_and_xor(value, mask); 00248 } 00249 #endif 00250 00251 #else 00252 00253 __INTRIN_INLINE char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand) 00254 { 00255 char retval = Comperand; 00256 __asm__("lock; cmpxchgb %b[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory"); 00257 return retval; 00258 } 00259 00260 __INTRIN_INLINE short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand) 00261 { 00262 short retval = Comperand; 00263 __asm__("lock; cmpxchgw %w[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory"); 00264 return retval; 00265 } 00266 00267 __INTRIN_INLINE long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand) 00268 { 00269 long retval = Comperand; 00270 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory"); 00271 return retval; 00272 } 00273 00274 __INTRIN_INLINE void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand) 00275 { 00276 void * retval = (void *)Comperand; 00277 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "=a" (retval) : "[retval]" (retval), [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory"); 00278 return retval; 00279 } 00280 00281 __INTRIN_INLINE long _InterlockedExchange(volatile long * const Target, const long Value) 00282 { 00283 long retval = Value; 00284 __asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory"); 00285 return retval; 00286 } 00287 00288 __INTRIN_INLINE void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value) 00289 { 00290 void * retval = Value; 00291 __asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory"); 00292 return retval; 00293 } 00294 00295 __INTRIN_INLINE long _InterlockedExchangeAdd16(volatile short * const Addend, const short Value) 00296 { 00297 long retval = Value; 00298 __asm__("lock; xaddw %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory"); 00299 return retval; 00300 } 00301 00302 __INTRIN_INLINE long _InterlockedExchangeAdd(volatile long * const Addend, const long Value) 00303 { 00304 long retval = Value; 00305 __asm__("lock; xaddl %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory"); 00306 return retval; 00307 } 00308 00309 __INTRIN_INLINE char _InterlockedAnd8(volatile char * const value, const char mask) 00310 { 00311 char x; 00312 char y; 00313 00314 y = *value; 00315 00316 do 00317 { 00318 x = y; 00319 y = _InterlockedCompareExchange8(value, x & mask, x); 00320 } 00321 while(y != x); 00322 00323 return y; 00324 } 00325 00326 __INTRIN_INLINE short _InterlockedAnd16(volatile short * const value, const short mask) 00327 { 00328 short x; 00329 short y; 00330 00331 y = *value; 00332 00333 do 00334 { 00335 x = y; 00336 y = _InterlockedCompareExchange16(value, x & mask, x); 00337 } 00338 while(y != x); 00339 00340 return y; 00341 } 00342 00343 __INTRIN_INLINE long _InterlockedAnd(volatile long * const value, const long mask) 00344 { 00345 long x; 00346 long y; 00347 00348 y = *value; 00349 00350 do 00351 { 00352 x = y; 00353 y = _InterlockedCompareExchange(value, x & mask, x); 00354 } 00355 while(y != x); 00356 00357 return y; 00358 } 00359 00360 __INTRIN_INLINE char _InterlockedOr8(volatile char * const value, const char mask) 00361 { 00362 char x; 00363 char y; 00364 00365 y = *value; 00366 00367 do 00368 { 00369 x = y; 00370 y = _InterlockedCompareExchange8(value, x | mask, x); 00371 } 00372 while(y != x); 00373 00374 return y; 00375 } 00376 00377 __INTRIN_INLINE short _InterlockedOr16(volatile short * const value, const short mask) 00378 { 00379 short x; 00380 short y; 00381 00382 y = *value; 00383 00384 do 00385 { 00386 x = y; 00387 y = _InterlockedCompareExchange16(value, x | mask, x); 00388 } 00389 while(y != x); 00390 00391 return y; 00392 } 00393 00394 __INTRIN_INLINE long _InterlockedOr(volatile long * const value, const long mask) 00395 { 00396 long x; 00397 long y; 00398 00399 y = *value; 00400 00401 do 00402 { 00403 x = y; 00404 y = _InterlockedCompareExchange(value, x | mask, x); 00405 } 00406 while(y != x); 00407 00408 return y; 00409 } 00410 00411 __INTRIN_INLINE char _InterlockedXor8(volatile char * const value, const char mask) 00412 { 00413 char x; 00414 char y; 00415 00416 y = *value; 00417 00418 do 00419 { 00420 x = y; 00421 y = _InterlockedCompareExchange8(value, x ^ mask, x); 00422 } 00423 while(y != x); 00424 00425 return y; 00426 } 00427 00428 __INTRIN_INLINE short _InterlockedXor16(volatile short * const value, const short mask) 00429 { 00430 short x; 00431 short y; 00432 00433 y = *value; 00434 00435 do 00436 { 00437 x = y; 00438 y = _InterlockedCompareExchange16(value, x ^ mask, x); 00439 } 00440 while(y != x); 00441 00442 return y; 00443 } 00444 00445 __INTRIN_INLINE long _InterlockedXor(volatile long * const value, const long mask) 00446 { 00447 long x; 00448 long y; 00449 00450 y = *value; 00451 00452 do 00453 { 00454 x = y; 00455 y = _InterlockedCompareExchange(value, x ^ mask, x); 00456 } 00457 while(y != x); 00458 00459 return y; 00460 } 00461 00462 #endif 00463 00464 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 && defined(__x86_64__) 00465 00466 __INTRIN_INLINE long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand) 00467 { 00468 return __sync_val_compare_and_swap(Destination, Comperand, Exchange); 00469 } 00470 00471 #else 00472 00473 __INTRIN_INLINE long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand) 00474 { 00475 long long retval = Comperand; 00476 00477 __asm__ 00478 ( 00479 "lock; cmpxchg8b %[Destination]" : 00480 [retval] "+A" (retval) : 00481 [Destination] "m" (*Destination), 00482 "b" ((unsigned long)((Exchange >> 0) & 0xFFFFFFFF)), 00483 "c" ((unsigned long)((Exchange >> 32) & 0xFFFFFFFF)) : 00484 "memory" 00485 ); 00486 00487 return retval; 00488 } 00489 00490 #endif 00491 00492 __INTRIN_INLINE long _InterlockedAddLargeStatistic(volatile long long * const Addend, const long Value) 00493 { 00494 __asm__ 00495 ( 00496 "lock; add %[Value], %[Lo32];" 00497 "jae LABEL%=;" 00498 "lock; adc $0, %[Hi32];" 00499 "LABEL%=:;" : 00500 [Lo32] "+m" (*((volatile long *)(Addend) + 0)), [Hi32] "+m" (*((volatile long *)(Addend) + 1)) : 00501 [Value] "ir" (Value) : 00502 "memory" 00503 ); 00504 00505 return Value; 00506 } 00507 00508 __INTRIN_INLINE long _InterlockedDecrement(volatile long * const lpAddend) 00509 { 00510 return _InterlockedExchangeAdd(lpAddend, -1) - 1; 00511 } 00512 00513 __INTRIN_INLINE long _InterlockedIncrement(volatile long * const lpAddend) 00514 { 00515 return _InterlockedExchangeAdd(lpAddend, 1) + 1; 00516 } 00517 00518 __INTRIN_INLINE short _InterlockedDecrement16(volatile short * const lpAddend) 00519 { 00520 return _InterlockedExchangeAdd16(lpAddend, -1) - 1; 00521 } 00522 00523 __INTRIN_INLINE short _InterlockedIncrement16(volatile short * const lpAddend) 00524 { 00525 return _InterlockedExchangeAdd16(lpAddend, 1) + 1; 00526 } 00527 00528 #if defined(_M_AMD64) 00529 __INTRIN_INLINE long long _InterlockedDecrement64(volatile long long * const lpAddend) 00530 { 00531 return _InterlockedExchangeAdd64(lpAddend, -1) - 1; 00532 } 00533 00534 __INTRIN_INLINE long long _InterlockedIncrement64(volatile long long * const lpAddend) 00535 { 00536 return _InterlockedExchangeAdd64(lpAddend, 1) + 1; 00537 } 00538 #endif 00539 00540 __INTRIN_INLINE unsigned char _interlockedbittestandreset(volatile long * a, const long b) 00541 { 00542 unsigned char retval; 00543 __asm__("lock; btrl %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory"); 00544 return retval; 00545 } 00546 00547 #if defined(_M_AMD64) 00548 __INTRIN_INLINE unsigned char _interlockedbittestandreset64(volatile long long * a, const long long b) 00549 { 00550 unsigned char retval; 00551 __asm__("lock; btrq %[b], %[a]; setb %b[retval]" : [retval] "=r" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory"); 00552 return retval; 00553 } 00554 #endif 00555 00556 __INTRIN_INLINE unsigned char _interlockedbittestandset(volatile long * a, const long b) 00557 { 00558 unsigned char retval; 00559 __asm__("lock; btsl %[b], %[a]; setc %b[retval]" : [retval] "=q" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory"); 00560 return retval; 00561 } 00562 00563 #if defined(_M_AMD64) 00564 __INTRIN_INLINE unsigned char _interlockedbittestandset64(volatile long long * a, const long long b) 00565 { 00566 unsigned char retval; 00567 __asm__("lock; btsq %[b], %[a]; setc %b[retval]" : [retval] "=r" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory"); 00568 return retval; 00569 } 00570 #endif 00571 00572 /*** String operations ***/ 00573 /* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */ 00574 __INTRIN_INLINE void __stosb(unsigned char * Dest, const unsigned char Data, size_t Count) 00575 { 00576 __asm__ __volatile__ 00577 ( 00578 "rep; stosb" : 00579 [Dest] "=D" (Dest), [Count] "=c" (Count) : 00580 "[Dest]" (Dest), "a" (Data), "[Count]" (Count) 00581 ); 00582 } 00583 00584 __INTRIN_INLINE void __stosw(unsigned short * Dest, const unsigned short Data, size_t Count) 00585 { 00586 __asm__ __volatile__ 00587 ( 00588 "rep; stosw" : 00589 [Dest] "=D" (Dest), [Count] "=c" (Count) : 00590 "[Dest]" (Dest), "a" (Data), "[Count]" (Count) 00591 ); 00592 } 00593 00594 __INTRIN_INLINE void __stosd(unsigned long * Dest, const unsigned long Data, size_t Count) 00595 { 00596 __asm__ __volatile__ 00597 ( 00598 "rep; stosl" : 00599 [Dest] "=D" (Dest), [Count] "=c" (Count) : 00600 "[Dest]" (Dest), "a" (Data), "[Count]" (Count) 00601 ); 00602 } 00603 00604 #ifdef _M_AMD64 00605 __INTRIN_INLINE void __stosq(unsigned __int64 * Dest, const unsigned __int64 Data, size_t Count) 00606 { 00607 __asm__ __volatile__ 00608 ( 00609 "rep; stosq" : 00610 [Dest] "=D" (Dest), [Count] "=c" (Count) : 00611 "[Dest]" (Dest), "a" (Data), "[Count]" (Count) 00612 ); 00613 } 00614 #endif 00615 00616 __INTRIN_INLINE void __movsb(unsigned char * Destination, const unsigned char * Source, size_t Count) 00617 { 00618 __asm__ __volatile__ 00619 ( 00620 "rep; movsb" : 00621 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) : 00622 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count) 00623 ); 00624 } 00625 00626 __INTRIN_INLINE void __movsw(unsigned short * Destination, const unsigned short * Source, size_t Count) 00627 { 00628 __asm__ __volatile__ 00629 ( 00630 "rep; movsw" : 00631 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) : 00632 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count) 00633 ); 00634 } 00635 00636 __INTRIN_INLINE void __movsd(unsigned long * Destination, const unsigned long * Source, size_t Count) 00637 { 00638 __asm__ __volatile__ 00639 ( 00640 "rep; movsd" : 00641 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) : 00642 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count) 00643 ); 00644 } 00645 00646 #ifdef _M_AMD64 00647 __INTRIN_INLINE void __movsq(unsigned long * Destination, const unsigned long * Source, size_t Count) 00648 { 00649 __asm__ __volatile__ 00650 ( 00651 "rep; movsq" : 00652 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) : 00653 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count) 00654 ); 00655 } 00656 #endif 00657 00658 #if defined(_M_AMD64) 00659 /*** GS segment addressing ***/ 00660 00661 __INTRIN_INLINE void __writegsbyte(const unsigned long Offset, const unsigned char Data) 00662 { 00663 __asm__ __volatile__("movb %b[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory"); 00664 } 00665 00666 __INTRIN_INLINE void __writegsword(const unsigned long Offset, const unsigned short Data) 00667 { 00668 __asm__ __volatile__("movw %w[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory"); 00669 } 00670 00671 __INTRIN_INLINE void __writegsdword(const unsigned long Offset, const unsigned long Data) 00672 { 00673 __asm__ __volatile__("movl %k[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory"); 00674 } 00675 00676 __INTRIN_INLINE void __writegsqword(const unsigned long Offset, const unsigned __int64 Data) 00677 { 00678 __asm__ __volatile__("movq %q[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory"); 00679 } 00680 00681 __INTRIN_INLINE unsigned char __readgsbyte(const unsigned long Offset) 00682 { 00683 unsigned char value; 00684 __asm__ __volatile__("movb %%gs:%a[Offset], %b[value]" : [value] "=r" (value) : [Offset] "ir" (Offset)); 00685 return value; 00686 } 00687 00688 __INTRIN_INLINE unsigned short __readgsword(const unsigned long Offset) 00689 { 00690 unsigned short value; 00691 __asm__ __volatile__("movw %%gs:%a[Offset], %w[value]" : [value] "=r" (value) : [Offset] "ir" (Offset)); 00692 return value; 00693 } 00694 00695 __INTRIN_INLINE unsigned long __readgsdword(const unsigned long Offset) 00696 { 00697 unsigned long value; 00698 __asm__ __volatile__("movl %%gs:%a[Offset], %k[value]" : [value] "=r" (value) : [Offset] "ir" (Offset)); 00699 return value; 00700 } 00701 00702 __INTRIN_INLINE unsigned __int64 __readgsqword(const unsigned long Offset) 00703 { 00704 unsigned __int64 value; 00705 __asm__ __volatile__("movq %%gs:%a[Offset], %q[value]" : [value] "=r" (value) : [Offset] "ir" (Offset)); 00706 return value; 00707 } 00708 00709 __INTRIN_INLINE void __incgsbyte(const unsigned long Offset) 00710 { 00711 __asm__ __volatile__("incb %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory"); 00712 } 00713 00714 __INTRIN_INLINE void __incgsword(const unsigned long Offset) 00715 { 00716 __asm__ __volatile__("incw %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory"); 00717 } 00718 00719 __INTRIN_INLINE void __incgsdword(const unsigned long Offset) 00720 { 00721 __asm__ __volatile__("incl %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory"); 00722 } 00723 00724 __INTRIN_INLINE void __addgsbyte(const unsigned long Offset, const unsigned char Data) 00725 { 00726 __asm__ __volatile__("addb %b[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory"); 00727 } 00728 00729 __INTRIN_INLINE void __addgsword(const unsigned long Offset, const unsigned short Data) 00730 { 00731 __asm__ __volatile__("addw %w[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory"); 00732 } 00733 00734 __INTRIN_INLINE void __addgsdword(const unsigned long Offset, const unsigned int Data) 00735 { 00736 __asm__ __volatile__("addl %k[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory"); 00737 } 00738 00739 __INTRIN_INLINE void __addgsqword(const unsigned long Offset, const unsigned __int64 Data) 00740 { 00741 __asm__ __volatile__("addq %k[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory"); 00742 } 00743 00744 #else 00745 /*** FS segment addressing ***/ 00746 __INTRIN_INLINE void __writefsbyte(const unsigned long Offset, const unsigned char Data) 00747 { 00748 __asm__ __volatile__("movb %b[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory"); 00749 } 00750 00751 __INTRIN_INLINE void __writefsword(const unsigned long Offset, const unsigned short Data) 00752 { 00753 __asm__ __volatile__("movw %w[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory"); 00754 } 00755 00756 __INTRIN_INLINE void __writefsdword(const unsigned long Offset, const unsigned long Data) 00757 { 00758 __asm__ __volatile__("movl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory"); 00759 } 00760 00761 __INTRIN_INLINE unsigned char __readfsbyte(const unsigned long Offset) 00762 { 00763 unsigned char value; 00764 __asm__ __volatile__("movb %%fs:%a[Offset], %b[value]" : [value] "=q" (value) : [Offset] "ir" (Offset)); 00765 return value; 00766 } 00767 00768 __INTRIN_INLINE unsigned short __readfsword(const unsigned long Offset) 00769 { 00770 unsigned short value; 00771 __asm__ __volatile__("movw %%fs:%a[Offset], %w[value]" : [value] "=r" (value) : [Offset] "ir" (Offset)); 00772 return value; 00773 } 00774 00775 __INTRIN_INLINE unsigned long __readfsdword(const unsigned long Offset) 00776 { 00777 unsigned long value; 00778 __asm__ __volatile__("movl %%fs:%a[Offset], %k[value]" : [value] "=r" (value) : [Offset] "ir" (Offset)); 00779 return value; 00780 } 00781 00782 __INTRIN_INLINE void __incfsbyte(const unsigned long Offset) 00783 { 00784 __asm__ __volatile__("incb %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory"); 00785 } 00786 00787 __INTRIN_INLINE void __incfsword(const unsigned long Offset) 00788 { 00789 __asm__ __volatile__("incw %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory"); 00790 } 00791 00792 __INTRIN_INLINE void __incfsdword(const unsigned long Offset) 00793 { 00794 __asm__ __volatile__("incl %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory"); 00795 } 00796 00797 /* NOTE: the bizarre implementation of __addfsxxx mimics the broken Visual C++ behavior */ 00798 __INTRIN_INLINE void __addfsbyte(const unsigned long Offset, const unsigned char Data) 00799 { 00800 if(!__builtin_constant_p(Offset)) 00801 __asm__ __volatile__("addb %b[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset) : "memory"); 00802 else 00803 __asm__ __volatile__("addb %b[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory"); 00804 } 00805 00806 __INTRIN_INLINE void __addfsword(const unsigned long Offset, const unsigned short Data) 00807 { 00808 if(!__builtin_constant_p(Offset)) 00809 __asm__ __volatile__("addw %w[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset) : "memory"); 00810 else 00811 __asm__ __volatile__("addw %w[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory"); 00812 } 00813 00814 __INTRIN_INLINE void __addfsdword(const unsigned long Offset, const unsigned int Data) 00815 { 00816 if(!__builtin_constant_p(Offset)) 00817 __asm__ __volatile__("addl %k[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset) : "memory"); 00818 else 00819 __asm__ __volatile__("addl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory"); 00820 } 00821 #endif 00822 00823 00824 /*** Bit manipulation ***/ 00825 __INTRIN_INLINE unsigned char _BitScanForward(unsigned long * const Index, const unsigned long Mask) 00826 { 00827 __asm__("bsfl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask)); 00828 return Mask ? 1 : 0; 00829 } 00830 00831 __INTRIN_INLINE unsigned char _BitScanReverse(unsigned long * const Index, const unsigned long Mask) 00832 { 00833 __asm__("bsrl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask)); 00834 return Mask ? 1 : 0; 00835 } 00836 00837 /* NOTE: again, the bizarre implementation follows Visual C++ */ 00838 __INTRIN_INLINE unsigned char _bittest(const long * const a, const long b) 00839 { 00840 unsigned char retval; 00841 00842 if(__builtin_constant_p(b)) 00843 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32)); 00844 else 00845 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b)); 00846 00847 return retval; 00848 } 00849 00850 #ifdef _M_AMD64 00851 __INTRIN_INLINE unsigned char _bittest64(const __int64 * const a, const __int64 b) 00852 { 00853 unsigned char retval; 00854 00855 if(__builtin_constant_p(b)) 00856 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 64))), [b] "Ir" (b % 64)); 00857 else 00858 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b)); 00859 00860 return retval; 00861 } 00862 #endif 00863 00864 __INTRIN_INLINE unsigned char _bittestandcomplement(long * const a, const long b) 00865 { 00866 unsigned char retval; 00867 00868 if(__builtin_constant_p(b)) 00869 __asm__("btc %[b], %[a]; setb %b[retval]" : [a] "+mr" (*(a + (b / 32))), [retval] "=q" (retval) : [b] "Ir" (b % 32)); 00870 else 00871 __asm__("btc %[b], %[a]; setb %b[retval]" : [a] "+mr" (*a), [retval] "=q" (retval) : [b] "r" (b)); 00872 00873 return retval; 00874 } 00875 00876 __INTRIN_INLINE unsigned char _bittestandreset(long * const a, const long b) 00877 { 00878 unsigned char retval; 00879 00880 if(__builtin_constant_p(b)) 00881 __asm__("btr %[b], %[a]; setb %b[retval]" : [a] "+mr" (*(a + (b / 32))), [retval] "=q" (retval) : [b] "Ir" (b % 32)); 00882 else 00883 __asm__("btr %[b], %[a]; setb %b[retval]" : [a] "+mr" (*a), [retval] "=q" (retval) : [b] "r" (b)); 00884 00885 return retval; 00886 } 00887 00888 __INTRIN_INLINE unsigned char _bittestandset(long * const a, const long b) 00889 { 00890 unsigned char retval; 00891 00892 if(__builtin_constant_p(b)) 00893 __asm__("bts %[b], %[a]; setb %b[retval]" : [a] "+mr" (*(a + (b / 32))), [retval] "=q" (retval) : [b] "Ir" (b % 32)); 00894 else 00895 __asm__("bts %[b], %[a]; setb %b[retval]" : [a] "+mr" (*a), [retval] "=q" (retval) : [b] "r" (b)); 00896 00897 return retval; 00898 } 00899 00900 __INTRIN_INLINE unsigned char _rotl8(unsigned char value, unsigned char shift) 00901 { 00902 unsigned char retval; 00903 __asm__("rolb %b[shift], %b[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); 00904 return retval; 00905 } 00906 00907 __INTRIN_INLINE unsigned short _rotl16(unsigned short value, unsigned char shift) 00908 { 00909 unsigned short retval; 00910 __asm__("rolw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); 00911 return retval; 00912 } 00913 00914 __INTRIN_INLINE unsigned int _rotl(unsigned int value, int shift) 00915 { 00916 unsigned long retval; 00917 __asm__("roll %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); 00918 return retval; 00919 } 00920 00921 __INTRIN_INLINE unsigned int _rotr(unsigned int value, int shift) 00922 { 00923 unsigned long retval; 00924 __asm__("rorl %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); 00925 return retval; 00926 } 00927 00928 __INTRIN_INLINE unsigned char _rotr8(unsigned char value, unsigned char shift) 00929 { 00930 unsigned char retval; 00931 __asm__("rorb %b[shift], %b[retval]" : [retval] "=qm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); 00932 return retval; 00933 } 00934 00935 __INTRIN_INLINE unsigned short _rotr16(unsigned short value, unsigned char shift) 00936 { 00937 unsigned short retval; 00938 __asm__("rorw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift)); 00939 return retval; 00940 } 00941 00942 /* 00943 NOTE: in __ll_lshift, __ll_rshift and __ull_rshift we use the "A" 00944 constraint (edx:eax) for the Mask argument, because it's the only way GCC 00945 can pass 64-bit operands around - passing the two 32 bit parts separately 00946 just confuses it. Also we declare Bit as an int and then truncate it to 00947 match Visual C++ behavior 00948 */ 00949 __INTRIN_INLINE unsigned long long __ll_lshift(const unsigned long long Mask, const int Bit) 00950 { 00951 unsigned long long retval = Mask; 00952 00953 __asm__ 00954 ( 00955 "shldl %b[Bit], %%eax, %%edx; sall %b[Bit], %%eax" : 00956 "+A" (retval) : 00957 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF) 00958 ); 00959 00960 return retval; 00961 } 00962 00963 __INTRIN_INLINE long long __ll_rshift(const long long Mask, const int Bit) 00964 { 00965 unsigned long long retval = Mask; 00966 00967 __asm__ 00968 ( 00969 "shldl %b[Bit], %%eax, %%edx; sarl %b[Bit], %%eax" : 00970 "+A" (retval) : 00971 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF) 00972 ); 00973 00974 return retval; 00975 } 00976 00977 __INTRIN_INLINE unsigned long long __ull_rshift(const unsigned long long Mask, int Bit) 00978 { 00979 unsigned long long retval = Mask; 00980 00981 __asm__ 00982 ( 00983 "shrdl %b[Bit], %%eax, %%edx; shrl %b[Bit], %%eax" : 00984 "+A" (retval) : 00985 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF) 00986 ); 00987 00988 return retval; 00989 } 00990 00991 __INTRIN_INLINE unsigned short _byteswap_ushort(unsigned short value) 00992 { 00993 unsigned short retval; 00994 __asm__("rorw $8, %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value)); 00995 return retval; 00996 } 00997 00998 __INTRIN_INLINE unsigned long _byteswap_ulong(unsigned long value) 00999 { 01000 unsigned long retval; 01001 __asm__("bswapl %[retval]" : [retval] "=r" (retval) : "[retval]" (value)); 01002 return retval; 01003 } 01004 01005 #ifdef _M_AMD64 01006 __INTRIN_INLINE unsigned __int64 _byteswap_uint64(unsigned __int64 value) 01007 { 01008 unsigned __int64 retval; 01009 __asm__("bswapq %[retval]" : [retval] "=r" (retval) : "[retval]" (value)); 01010 return retval; 01011 } 01012 #else 01013 __INTRIN_INLINE unsigned __int64 _byteswap_uint64(unsigned __int64 value) 01014 { 01015 union { 01016 __int64 int64part; 01017 struct { 01018 unsigned long lowpart; 01019 unsigned long hipart; 01020 }; 01021 } retval; 01022 retval.int64part = value; 01023 __asm__("bswapl %[lowpart]\n" 01024 "bswapl %[hipart]\n" 01025 : [lowpart] "=r" (retval.hipart), [hipart] "=r" (retval.lowpart) : "[lowpart]" (retval.lowpart), "[hipart]" (retval.hipart) ); 01026 return retval.int64part; 01027 } 01028 #endif 01029 01030 /*** 64-bit math ***/ 01031 __INTRIN_INLINE long long __emul(const int a, const int b) 01032 { 01033 long long retval; 01034 __asm__("imull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b)); 01035 return retval; 01036 } 01037 01038 __INTRIN_INLINE unsigned long long __emulu(const unsigned int a, const unsigned int b) 01039 { 01040 unsigned long long retval; 01041 __asm__("mull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b)); 01042 return retval; 01043 } 01044 01045 #ifdef _M_AMD64 01046 01047 __INTRIN_INLINE __int64 __mulh(__int64 a, __int64 b) 01048 { 01049 __int64 retval; 01050 __asm__("imulq %[b]" : "=d" (retval) : [a] "a" (a), [b] "rm" (b)); 01051 return retval; 01052 } 01053 01054 __INTRIN_INLINE unsigned __int64 __umulh(unsigned __int64 a, unsigned __int64 b) 01055 { 01056 unsigned __int64 retval; 01057 __asm__("mulq %[b]" : "=d" (retval) : [a] "a" (a), [b] "rm" (b)); 01058 return retval; 01059 } 01060 01061 #endif 01062 01063 /*** Port I/O ***/ 01064 __INTRIN_INLINE unsigned char __inbyte(const unsigned short Port) 01065 { 01066 unsigned char byte; 01067 __asm__ __volatile__("inb %w[Port], %b[byte]" : [byte] "=a" (byte) : [Port] "Nd" (Port)); 01068 return byte; 01069 } 01070 01071 __INTRIN_INLINE unsigned short __inword(const unsigned short Port) 01072 { 01073 unsigned short word; 01074 __asm__ __volatile__("inw %w[Port], %w[word]" : [word] "=a" (word) : [Port] "Nd" (Port)); 01075 return word; 01076 } 01077 01078 __INTRIN_INLINE unsigned long __indword(const unsigned short Port) 01079 { 01080 unsigned long dword; 01081 __asm__ __volatile__("inl %w[Port], %k[dword]" : [dword] "=a" (dword) : [Port] "Nd" (Port)); 01082 return dword; 01083 } 01084 01085 __INTRIN_INLINE void __inbytestring(unsigned short Port, unsigned char * Buffer, unsigned long Count) 01086 { 01087 __asm__ __volatile__ 01088 ( 01089 "rep; insb" : 01090 [Buffer] "=D" (Buffer), [Count] "=c" (Count) : 01091 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) : 01092 "memory" 01093 ); 01094 } 01095 01096 __INTRIN_INLINE void __inwordstring(unsigned short Port, unsigned short * Buffer, unsigned long Count) 01097 { 01098 __asm__ __volatile__ 01099 ( 01100 "rep; insw" : 01101 [Buffer] "=D" (Buffer), [Count] "=c" (Count) : 01102 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) : 01103 "memory" 01104 ); 01105 } 01106 01107 __INTRIN_INLINE void __indwordstring(unsigned short Port, unsigned long * Buffer, unsigned long Count) 01108 { 01109 __asm__ __volatile__ 01110 ( 01111 "rep; insl" : 01112 [Buffer] "=D" (Buffer), [Count] "=c" (Count) : 01113 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) : 01114 "memory" 01115 ); 01116 } 01117 01118 __INTRIN_INLINE void __outbyte(unsigned short const Port, const unsigned char Data) 01119 { 01120 __asm__ __volatile__("outb %b[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data)); 01121 } 01122 01123 __INTRIN_INLINE void __outword(unsigned short const Port, const unsigned short Data) 01124 { 01125 __asm__ __volatile__("outw %w[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data)); 01126 } 01127 01128 __INTRIN_INLINE void __outdword(unsigned short const Port, const unsigned long Data) 01129 { 01130 __asm__ __volatile__("outl %k[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data)); 01131 } 01132 01133 __INTRIN_INLINE void __outbytestring(unsigned short const Port, const unsigned char * const Buffer, const unsigned long Count) 01134 { 01135 __asm__ __volatile__("rep; outsb" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count)); 01136 } 01137 01138 __INTRIN_INLINE void __outwordstring(unsigned short const Port, const unsigned short * const Buffer, const unsigned long Count) 01139 { 01140 __asm__ __volatile__("rep; outsw" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count)); 01141 } 01142 01143 __INTRIN_INLINE void __outdwordstring(unsigned short const Port, const unsigned long * const Buffer, const unsigned long Count) 01144 { 01145 __asm__ __volatile__("rep; outsl" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count)); 01146 } 01147 01148 __INTRIN_INLINE int _inp(unsigned short Port) 01149 { 01150 return __inbyte(Port); 01151 } 01152 01153 __INTRIN_INLINE unsigned short _inpw(unsigned short Port) 01154 { 01155 return __inword(Port); 01156 } 01157 01158 __INTRIN_INLINE unsigned long _inpd(unsigned short Port) 01159 { 01160 return __indword(Port); 01161 } 01162 01163 __INTRIN_INLINE int _outp(unsigned short Port, int databyte) 01164 { 01165 __outbyte(Port, databyte); 01166 return databyte; 01167 } 01168 01169 __INTRIN_INLINE unsigned short _outpw(unsigned short Port, unsigned short dataword) 01170 { 01171 __outword(Port, dataword); 01172 return dataword; 01173 } 01174 01175 __INTRIN_INLINE unsigned long _outpd(unsigned short Port, unsigned long dataword) 01176 { 01177 __outdword(Port, dataword); 01178 return dataword; 01179 } 01180 01181 01182 /*** System information ***/ 01183 __INTRIN_INLINE void __cpuid(int CPUInfo[], const int InfoType) 01184 { 01185 __asm__ __volatile__("cpuid" : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3]) : "a" (InfoType)); 01186 } 01187 01188 __INTRIN_INLINE unsigned long long __rdtsc(void) 01189 { 01190 #ifdef _M_AMD64 01191 unsigned long long low, high; 01192 __asm__ __volatile__("rdtsc" : "=a"(low), "=d"(high)); 01193 return low | (high << 32); 01194 #else 01195 unsigned long long retval; 01196 __asm__ __volatile__("rdtsc" : "=A"(retval)); 01197 return retval; 01198 #endif 01199 } 01200 01201 __INTRIN_INLINE void __writeeflags(uintptr_t Value) 01202 { 01203 __asm__ __volatile__("push %0\n popf" : : "rim"(Value)); 01204 } 01205 01206 __INTRIN_INLINE uintptr_t __readeflags(void) 01207 { 01208 uintptr_t retval; 01209 __asm__ __volatile__("pushf\n pop %0" : "=rm"(retval)); 01210 return retval; 01211 } 01212 01213 /*** Interrupts ***/ 01214 #ifdef __clang__ 01215 #define __debugbreak() __asm__("int $3") 01216 #else 01217 __INTRIN_INLINE void __debugbreak(void) 01218 { 01219 __asm__("int $3"); 01220 } 01221 #endif 01222 01223 __INTRIN_INLINE void __int2c(void) 01224 { 01225 __asm__("int $0x2c"); 01226 } 01227 01228 __INTRIN_INLINE void _disable(void) 01229 { 01230 __asm__("cli" : : : "memory"); 01231 } 01232 01233 __INTRIN_INLINE void _enable(void) 01234 { 01235 __asm__("sti" : : : "memory"); 01236 } 01237 01238 __INTRIN_INLINE void __halt(void) 01239 { 01240 __asm__("hlt\n\t" : : : "memory"); 01241 } 01242 01243 /*** Protected memory management ***/ 01244 01245 #ifdef _M_AMD64 01246 __INTRIN_INLINE void __writecr0(const unsigned __int64 Data) 01247 { 01248 __asm__("mov %[Data], %%cr0" : : [Data] "r" (Data) : "memory"); 01249 } 01250 01251 __INTRIN_INLINE void __writecr3(const unsigned __int64 Data) 01252 { 01253 __asm__("mov %[Data], %%cr3" : : [Data] "r" (Data) : "memory"); 01254 } 01255 01256 __INTRIN_INLINE void __writecr4(const unsigned __int64 Data) 01257 { 01258 __asm__("mov %[Data], %%cr4" : : [Data] "r" (Data) : "memory"); 01259 } 01260 01261 __INTRIN_INLINE void __writecr8(const unsigned __int64 Data) 01262 { 01263 __asm__("mov %[Data], %%cr8" : : [Data] "r" (Data) : "memory"); 01264 } 01265 01266 __INTRIN_INLINE unsigned __int64 __readcr0(void) 01267 { 01268 unsigned __int64 value; 01269 __asm__ __volatile__("mov %%cr0, %[value]" : [value] "=r" (value)); 01270 return value; 01271 } 01272 01273 __INTRIN_INLINE unsigned __int64 __readcr2(void) 01274 { 01275 unsigned __int64 value; 01276 __asm__ __volatile__("mov %%cr2, %[value]" : [value] "=r" (value)); 01277 return value; 01278 } 01279 01280 __INTRIN_INLINE unsigned __int64 __readcr3(void) 01281 { 01282 unsigned __int64 value; 01283 __asm__ __volatile__("mov %%cr3, %[value]" : [value] "=r" (value)); 01284 return value; 01285 } 01286 01287 __INTRIN_INLINE unsigned __int64 __readcr4(void) 01288 { 01289 unsigned __int64 value; 01290 __asm__ __volatile__("mov %%cr4, %[value]" : [value] "=r" (value)); 01291 return value; 01292 } 01293 01294 __INTRIN_INLINE unsigned __int64 __readcr8(void) 01295 { 01296 unsigned __int64 value; 01297 __asm__ __volatile__("movq %%cr8, %q[value]" : [value] "=r" (value)); 01298 return value; 01299 } 01300 #else 01301 __INTRIN_INLINE void __writecr0(const unsigned int Data) 01302 { 01303 __asm__("mov %[Data], %%cr0" : : [Data] "r" (Data) : "memory"); 01304 } 01305 01306 __INTRIN_INLINE void __writecr3(const unsigned int Data) 01307 { 01308 __asm__("mov %[Data], %%cr3" : : [Data] "r" (Data) : "memory"); 01309 } 01310 01311 __INTRIN_INLINE void __writecr4(const unsigned int Data) 01312 { 01313 __asm__("mov %[Data], %%cr4" : : [Data] "r" (Data) : "memory"); 01314 } 01315 01316 __INTRIN_INLINE unsigned long __readcr0(void) 01317 { 01318 unsigned long value; 01319 __asm__ __volatile__("mov %%cr0, %[value]" : [value] "=r" (value)); 01320 return value; 01321 } 01322 01323 __INTRIN_INLINE unsigned long __readcr2(void) 01324 { 01325 unsigned long value; 01326 __asm__ __volatile__("mov %%cr2, %[value]" : [value] "=r" (value)); 01327 return value; 01328 } 01329 01330 __INTRIN_INLINE unsigned long __readcr3(void) 01331 { 01332 unsigned long value; 01333 __asm__ __volatile__("mov %%cr3, %[value]" : [value] "=r" (value)); 01334 return value; 01335 } 01336 01337 __INTRIN_INLINE unsigned long __readcr4(void) 01338 { 01339 unsigned long value; 01340 __asm__ __volatile__("mov %%cr4, %[value]" : [value] "=r" (value)); 01341 return value; 01342 } 01343 #endif 01344 01345 #ifdef _M_AMD64 01346 __INTRIN_INLINE unsigned __int64 __readdr(unsigned int reg) 01347 { 01348 unsigned __int64 value; 01349 switch (reg) 01350 { 01351 case 0: 01352 __asm__ __volatile__("movq %%dr0, %q[value]" : [value] "=r" (value)); 01353 break; 01354 case 1: 01355 __asm__ __volatile__("movq %%dr1, %q[value]" : [value] "=r" (value)); 01356 break; 01357 case 2: 01358 __asm__ __volatile__("movq %%dr2, %q[value]" : [value] "=r" (value)); 01359 break; 01360 case 3: 01361 __asm__ __volatile__("movq %%dr3, %q[value]" : [value] "=r" (value)); 01362 break; 01363 case 4: 01364 __asm__ __volatile__("movq %%dr4, %q[value]" : [value] "=r" (value)); 01365 break; 01366 case 5: 01367 __asm__ __volatile__("movq %%dr5, %q[value]" : [value] "=r" (value)); 01368 break; 01369 case 6: 01370 __asm__ __volatile__("movq %%dr6, %q[value]" : [value] "=r" (value)); 01371 break; 01372 case 7: 01373 __asm__ __volatile__("movq %%dr7, %q[value]" : [value] "=r" (value)); 01374 break; 01375 } 01376 return value; 01377 } 01378 01379 __INTRIN_INLINE void __writedr(unsigned reg, unsigned __int64 value) 01380 { 01381 switch (reg) 01382 { 01383 case 0: 01384 __asm__("movq %q[value], %%dr0" : : [value] "r" (value) : "memory"); 01385 break; 01386 case 1: 01387 __asm__("movq %q[value], %%dr1" : : [value] "r" (value) : "memory"); 01388 break; 01389 case 2: 01390 __asm__("movq %q[value], %%dr2" : : [value] "r" (value) : "memory"); 01391 break; 01392 case 3: 01393 __asm__("movq %q[value], %%dr3" : : [value] "r" (value) : "memory"); 01394 break; 01395 case 4: 01396 __asm__("movq %q[value], %%dr4" : : [value] "r" (value) : "memory"); 01397 break; 01398 case 5: 01399 __asm__("movq %q[value], %%dr5" : : [value] "r" (value) : "memory"); 01400 break; 01401 case 6: 01402 __asm__("movq %q[value], %%dr6" : : [value] "r" (value) : "memory"); 01403 break; 01404 case 7: 01405 __asm__("movq %q[value], %%dr7" : : [value] "r" (value) : "memory"); 01406 break; 01407 } 01408 } 01409 #else 01410 __INTRIN_INLINE unsigned int __readdr(unsigned int reg) 01411 { 01412 unsigned int value; 01413 switch (reg) 01414 { 01415 case 0: 01416 __asm__ __volatile__("mov %%dr0, %[value]" : [value] "=r" (value)); 01417 break; 01418 case 1: 01419 __asm__ __volatile__("mov %%dr1, %[value]" : [value] "=r" (value)); 01420 break; 01421 case 2: 01422 __asm__ __volatile__("mov %%dr2, %[value]" : [value] "=r" (value)); 01423 break; 01424 case 3: 01425 __asm__ __volatile__("mov %%dr3, %[value]" : [value] "=r" (value)); 01426 break; 01427 case 4: 01428 __asm__ __volatile__("mov %%dr4, %[value]" : [value] "=r" (value)); 01429 break; 01430 case 5: 01431 __asm__ __volatile__("mov %%dr5, %[value]" : [value] "=r" (value)); 01432 break; 01433 case 6: 01434 __asm__ __volatile__("mov %%dr6, %[value]" : [value] "=r" (value)); 01435 break; 01436 case 7: 01437 __asm__ __volatile__("mov %%dr7, %[value]" : [value] "=r" (value)); 01438 break; 01439 } 01440 return value; 01441 } 01442 01443 __INTRIN_INLINE void __writedr(unsigned reg, unsigned int value) 01444 { 01445 switch (reg) 01446 { 01447 case 0: 01448 __asm__("mov %[value], %%dr0" : : [value] "r" (value) : "memory"); 01449 break; 01450 case 1: 01451 __asm__("mov %[value], %%dr1" : : [value] "r" (value) : "memory"); 01452 break; 01453 case 2: 01454 __asm__("mov %[value], %%dr2" : : [value] "r" (value) : "memory"); 01455 break; 01456 case 3: 01457 __asm__("mov %[value], %%dr3" : : [value] "r" (value) : "memory"); 01458 break; 01459 case 4: 01460 __asm__("mov %[value], %%dr4" : : [value] "r" (value) : "memory"); 01461 break; 01462 case 5: 01463 __asm__("mov %[value], %%dr5" : : [value] "r" (value) : "memory"); 01464 break; 01465 case 6: 01466 __asm__("mov %[value], %%dr6" : : [value] "r" (value) : "memory"); 01467 break; 01468 case 7: 01469 __asm__("mov %[value], %%dr7" : : [value] "r" (value) : "memory"); 01470 break; 01471 } 01472 } 01473 #endif 01474 01475 __INTRIN_INLINE void __invlpg(void * const Address) 01476 { 01477 __asm__("invlpg %[Address]" : : [Address] "m" (*((unsigned char *)(Address))) : "memory"); 01478 } 01479 01480 01481 /*** System operations ***/ 01482 __INTRIN_INLINE unsigned long long __readmsr(const int reg) 01483 { 01484 #ifdef _M_AMD64 01485 unsigned long low, high; 01486 __asm__ __volatile__("rdmsr" : "=a" (low), "=d" (high) : "c" (reg)); 01487 return ((unsigned long long)high << 32) | low; 01488 #else 01489 unsigned long long retval; 01490 __asm__ __volatile__("rdmsr" : "=A" (retval) : "c" (reg)); 01491 return retval; 01492 #endif 01493 } 01494 01495 __INTRIN_INLINE void __writemsr(const unsigned long Register, const unsigned long long Value) 01496 { 01497 #ifdef _M_AMD64 01498 __asm__ __volatile__("wrmsr" : : "a" (Value), "d" (Value >> 32), "c" (Register)); 01499 #else 01500 __asm__ __volatile__("wrmsr" : : "A" (Value), "c" (Register)); 01501 #endif 01502 } 01503 01504 __INTRIN_INLINE unsigned long long __readpmc(const int counter) 01505 { 01506 unsigned long long retval; 01507 __asm__ __volatile__("rdpmc" : "=A" (retval) : "c" (counter)); 01508 return retval; 01509 } 01510 01511 /* NOTE: an immediate value for 'a' will raise an ICE in Visual C++ */ 01512 __INTRIN_INLINE unsigned long __segmentlimit(const unsigned long a) 01513 { 01514 unsigned long retval; 01515 __asm__ __volatile__("lsl %[a], %[retval]" : [retval] "=r" (retval) : [a] "rm" (a)); 01516 return retval; 01517 } 01518 01519 __INTRIN_INLINE void __wbinvd(void) 01520 { 01521 __asm__ __volatile__("wbinvd" : : : "memory"); 01522 } 01523 01524 __INTRIN_INLINE void __lidt(void *Source) 01525 { 01526 __asm__ __volatile__("lidt %0" : : "m"(*(short*)Source)); 01527 } 01528 01529 __INTRIN_INLINE void __sidt(void *Destination) 01530 { 01531 __asm__ __volatile__("sidt %0" : : "m"(*(short*)Destination) : "memory"); 01532 } 01533 01534 /*** Misc operations ***/ 01535 01536 __INTRIN_INLINE void _mm_pause(void) 01537 { 01538 __asm__ __volatile__("pause" : : : "memory"); 01539 } 01540 01541 __INTRIN_INLINE void __nop(void) 01542 { 01543 __asm__ __volatile__("nop"); 01544 } 01545 01546 #ifdef __cplusplus 01547 } 01548 #endif 01549 01550 #endif /* KJK_INTRIN_X86_H_ */ 01551 01552 /* EOF */ Generated on Sun May 27 2012 04:29:53 for ReactOS by
1.7.6.1
|