Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenintrin_ppc.h
Go to the documentation of this file.
00001 /* 00002 Compatibility <intrin.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_PPC_H_ 00029 #define KJK_INTRIN_PPC_H_ 00030 00031 //#define PPC_QUAL static __inline__ __attribute__((always_inline)) 00032 #define PPC_QUAL extern __inline__ 00033 00034 #ifndef __GNUC__ 00035 #error Unsupported compiler 00036 #endif 00037 00038 /*** Stack frame juggling ***/ 00039 #define _ReturnAddress() (__builtin_return_address(0)) 00040 #define _AddressOfReturnAddress() (&(((void **)(__builtin_frame_address(0)))[1])) 00041 /* TODO: __getcallerseflags but how??? */ 00042 00043 00044 /*** Atomic operations ***/ 00045 /* TODO: _ReadBarrier */ 00046 /* TODO: _WriteBarrier */ 00047 00048 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 00049 #define _ReadWriteBarrier() __sync_synchronize() 00050 #else 00051 /* TODO: _ReadWriteBarrier() */ 00052 #endif 00053 00054 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 00055 00056 PPC_QUAL char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand) 00057 { 00058 return __sync_val_compare_and_swap(Destination, Comperand, Exchange); 00059 } 00060 00061 PPC_QUAL short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand) 00062 { 00063 return __sync_val_compare_and_swap(Destination, Comperand, Exchange); 00064 } 00065 00066 PPC_QUAL long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand) 00067 { 00068 return __sync_val_compare_and_swap(Destination, Comperand, Exchange); 00069 } 00070 00071 PPC_QUAL long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand) 00072 { 00073 return __sync_val_compare_and_swap(Destination, Comperand, Exchange); 00074 } 00075 00076 PPC_QUAL void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand) 00077 { 00078 return __sync_val_compare_and_swap(Destination, Comperand, Exchange); 00079 } 00080 00081 PPC_QUAL long _InterlockedExchange(volatile long * const Target, const long Value) 00082 { 00083 /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */ 00084 __sync_synchronize(); 00085 return __sync_lock_test_and_set(Target, Value); 00086 } 00087 00088 PPC_QUAL void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value) 00089 { 00090 /* NOTE: ditto */ 00091 __sync_synchronize(); 00092 return __sync_lock_test_and_set(Target, Value); 00093 } 00094 00095 PPC_QUAL long _InterlockedExchangeAdd(volatile long * const Addend, const long Value) 00096 { 00097 return __sync_fetch_and_add(Addend, Value); 00098 } 00099 00100 PPC_QUAL char _InterlockedAnd8(volatile char * const value, const char mask) 00101 { 00102 return __sync_fetch_and_and(value, mask); 00103 } 00104 00105 PPC_QUAL short _InterlockedAnd16(volatile short * const value, const short mask) 00106 { 00107 return __sync_fetch_and_and(value, mask); 00108 } 00109 00110 PPC_QUAL long _InterlockedAnd(volatile long * const value, const long mask) 00111 { 00112 return __sync_fetch_and_and(value, mask); 00113 } 00114 00115 PPC_QUAL char _InterlockedOr8(volatile char * const value, const char mask) 00116 { 00117 return __sync_fetch_and_or(value, mask); 00118 } 00119 00120 PPC_QUAL short _InterlockedOr16(volatile short * const value, const short mask) 00121 { 00122 return __sync_fetch_and_or(value, mask); 00123 } 00124 00125 PPC_QUAL long _InterlockedOr(volatile long * const value, const long mask) 00126 { 00127 return __sync_fetch_and_or(value, mask); 00128 } 00129 00130 PPC_QUAL char _InterlockedXor8(volatile char * const value, const char mask) 00131 { 00132 return __sync_fetch_and_xor(value, mask); 00133 } 00134 00135 PPC_QUAL short _InterlockedXor16(volatile short * const value, const short mask) 00136 { 00137 return __sync_fetch_and_xor(value, mask); 00138 } 00139 00140 PPC_QUAL long _InterlockedXor(volatile long * const value, const long mask) 00141 { 00142 return __sync_fetch_and_xor(value, mask); 00143 } 00144 00145 #else 00146 00147 PPC_QUAL char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand) 00148 { 00149 volatile long retval __asm__("r8") = 0; 00150 __asm__ __volatile__ ( 00151 "sync\n" 00152 "1: lbarx %0,0,%1\n" 00153 : "=r" (retval) : "r" (Destination)); 00154 __asm__ __volatile__ ( 00155 " cmpw %3,%1\n" 00156 " bne- 2f\n" 00157 " stbcx. %2,0,%0\n" 00158 " bne- 1b\n" 00159 "2: isync" 00160 : 00161 : "r" (Destination), "r" (Comperand), "r" (Exchange), "r" (retval)); 00162 return retval; 00163 } 00164 00165 PPC_QUAL short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand) 00166 { 00167 volatile long retval __asm__("r8") = 0; 00168 __asm__ __volatile__ ( 00169 "sync\n" 00170 "1: lharx %0,0,%1\n" 00171 : "=&r" (retval) : "r" (Destination)); 00172 __asm__ __volatile__ ( 00173 " cmpw %3,%1\n" 00174 " bne- 2f\n" 00175 " sthcx. %2,0,%0\n" 00176 " bne- 1b\n" 00177 "2: isync" 00178 : 00179 : "r" (Destination), "r" (Comperand), "r" (Exchange), "r" (retval)); 00180 return retval; 00181 } 00182 00183 PPC_QUAL long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand) 00184 { 00185 volatile long retval __asm__("r8") = 0; 00186 __asm__ __volatile__ ( 00187 "sync\n" 00188 "1: lwarx %0,0,%1\n" 00189 : "=&r" (retval) : "r" (Destination)); 00190 __asm__ __volatile__ ( 00191 " cmpw %3,%1\n" 00192 " bne- 2f\n" 00193 " stwcx. %2,0,%0\n" 00194 " bne- 1b\n" 00195 "2: isync" 00196 : 00197 : "r" (Destination), "r" (Comperand), "r" (Exchange), "r" (retval)); 00198 return retval; 00199 } 00200 00201 PPC_QUAL long long _InterlockedCompareExchange64(volatile long long * const Target, const long long Exchange, const long long Comperand) 00202 { 00203 long long capture = *Target; 00204 if (*Target == Comperand) *Target = Exchange; 00205 return capture; 00206 } 00207 00208 PPC_QUAL void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand) 00209 { 00210 return (void *)_InterlockedCompareExchange 00211 ((long *)Destination, (long) Exchange, (long) Comperand); 00212 } 00213 00214 PPC_QUAL long _InterlockedExchange(volatile long * const Target, const long Value) 00215 { 00216 long retval __asm__("r8"); 00217 __asm__ __volatile__ ( 00218 "sync\n" 00219 "1: lwarx 8,0,3\n" 00220 " stwcx. 4,0,3\n" 00221 " bne- 1b\n" 00222 " mr 3,8\n" 00223 : "=b" (retval) 00224 : "b" (Target), "b" (Value) 00225 : "cr0", "memory"); 00226 return retval; 00227 } 00228 00229 PPC_QUAL void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value) 00230 { 00231 return (void *)_InterlockedExchange((long *)Target, (long)Value); 00232 } 00233 00234 #define PPC_MakeInterlockedFunction(type,name,op,proto) \ 00235 PPC_QUAL type name proto \ 00236 { \ 00237 long addend, y; \ 00238 do \ 00239 { \ 00240 addend = *value; \ 00241 y = _InterlockedCompareExchange(value, addend op modify, addend); \ 00242 } \ 00243 while(y != addend); \ 00244 \ 00245 return y; \ 00246 } 00247 00248 PPC_QUAL unsigned char _interlockedbittestandreset(volatile long * const a, const long b) 00249 { 00250 long x; 00251 long y; 00252 long mask = ~(1<<b); 00253 00254 do 00255 { 00256 x = *a; 00257 y = _InterlockedCompareExchange(a, x & mask, x); 00258 } 00259 while(y != x); 00260 00261 return (y & ~mask) != 0; 00262 } 00263 00264 PPC_MakeInterlockedFunction(long,_InterlockedExchangeAdd,+,(volatile long * const value, const long modify)) 00265 PPC_MakeInterlockedFunction(char,_InterlockedAnd8,&,(volatile char * const value, const char modify)) 00266 PPC_MakeInterlockedFunction(short,_InterlockedAnd16,&,(volatile short * const value, const short modify)) 00267 PPC_MakeInterlockedFunction(long,_InterlockedAnd,&,(volatile long * const value, const long modify)) 00268 PPC_MakeInterlockedFunction(char,_InterlockedOr8,|,(volatile char * const value, const char modify)) 00269 PPC_MakeInterlockedFunction(short,_InterlockedOr16,|,(volatile short * const value, const short modify)) 00270 PPC_MakeInterlockedFunction(long,_InterlockedOr,|,(volatile long * const value, const long modify)) 00271 PPC_MakeInterlockedFunction(char,_InterlockedXor8,^,(volatile char * const value, const char modify)) 00272 PPC_MakeInterlockedFunction(short,_InterlockedXor16,^,(volatile short * const value, const short modify)) 00273 PPC_MakeInterlockedFunction(long,_InterlockedXor,^,(volatile long * const value, const long modify)) 00274 00275 PPC_QUAL unsigned char _interlockedbittestandset(volatile long * const a, const long b) 00276 { 00277 long x; 00278 long y; 00279 long mask = 1<<b; 00280 00281 do 00282 { 00283 x = *a; 00284 y = _InterlockedCompareExchange(a, x | mask, x); 00285 } 00286 while(y != x); 00287 00288 return (y & ~mask) != 0; 00289 } 00290 #endif 00291 00292 PPC_QUAL long _InterlockedDecrement(volatile long * const lpAddend) 00293 { 00294 return _InterlockedExchangeAdd(lpAddend, -1) - 1; 00295 } 00296 00297 PPC_QUAL long _InterlockedIncrement(volatile long * const lpAddend) 00298 { 00299 return _InterlockedExchangeAdd(lpAddend, 1) + 1; 00300 } 00301 00302 /*** String operations ***/ 00303 /* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */ 00304 /* Note that the PPC store multiple operations may raise an exception in LE 00305 * mode */ 00306 PPC_QUAL void __stosb(unsigned char * Dest, const unsigned char Data, unsigned long Count) 00307 { 00308 memset(Dest, Data, Count); 00309 } 00310 00311 PPC_QUAL void __stosw(unsigned short * Dest, const unsigned short Data, unsigned long Count) 00312 { 00313 while(Count--) 00314 *Dest++ = Data; 00315 } 00316 00317 PPC_QUAL void __stosd(unsigned long * Dest, const unsigned long Data, unsigned long Count) 00318 { 00319 while(Count--) 00320 *Dest++ = Data; 00321 } 00322 00323 PPC_QUAL void __movsb(unsigned char * Destination, const unsigned char * Source, unsigned long Count) 00324 { 00325 memcpy(Destination, Source, Count); 00326 } 00327 00328 PPC_QUAL void __movsw(unsigned short * Destination, const unsigned short * Source, unsigned long Count) 00329 { 00330 memcpy(Destination, Source, Count * sizeof(*Source)); 00331 } 00332 00333 PPC_QUAL void __movsd(unsigned long * Destination, const unsigned long * Source, unsigned long Count) 00334 { 00335 memcpy(Destination, Source, Count * sizeof(*Source)); 00336 } 00337 00338 00339 /*** FS segment addressing ***/ 00340 /* On PowerPC, r13 points to TLS data, including the TEB at 0(r13) from what I 00341 * can tell */ 00342 PPC_QUAL void __writefsbyte(const unsigned long Offset, const unsigned char Data) 00343 { 00344 char *addr; 00345 __asm__("\tadd %0,13,%1\n\tstb %2,0(%0)" : "=r" (addr) : "r" (Offset), "r" (Data)); 00346 } 00347 00348 PPC_QUAL void __writefsword(const unsigned long Offset, const unsigned short Data) 00349 { 00350 char *addr; 00351 __asm__("\tadd %0,13,%1\n\tsth %2,0(%0)" : "=r" (addr) : "r" (Offset), "r" (Data)); 00352 } 00353 00354 PPC_QUAL void __writefsdword(const unsigned long Offset, const unsigned long Data) 00355 { 00356 char *addr; 00357 __asm__("\tadd %0,13,%1\n\tstw %2,0(%0)" : "=r" (addr) : "r" (Offset), "r" (Data)); 00358 } 00359 00360 PPC_QUAL unsigned char __readfsbyte(const unsigned long Offset) 00361 { 00362 unsigned short result; 00363 __asm__("\tadd 7,13,%1\n" 00364 "\tlbz %0,0(7)\n" 00365 : "=r" (result) 00366 : "r" (Offset) 00367 : "r7"); 00368 return result; 00369 } 00370 00371 PPC_QUAL unsigned short __readfsword(const unsigned long Offset) 00372 { 00373 unsigned short result; 00374 __asm__("\tadd 7,13,%1\n" 00375 "\tlhz %0,0(7)\n" 00376 : "=r" (result) 00377 : "r" (Offset) 00378 : "r7"); 00379 return result; 00380 } 00381 00382 PPC_QUAL unsigned long __readfsdword(const unsigned long Offset) 00383 { 00384 unsigned long result; 00385 __asm__("\tadd 7,13,%1\n" 00386 "\tlwz %0,0(7)\n" 00387 : "=r" (result) 00388 : "r" (Offset) 00389 : "r7"); 00390 return result; 00391 } 00392 00393 PPC_QUAL void __incfsbyte(const unsigned long Offset) 00394 { 00395 __writefsbyte(Offset, __readfsbyte(Offset)+1); 00396 } 00397 00398 PPC_QUAL void __incfsword(const unsigned long Offset) 00399 { 00400 __writefsword(Offset, __readfsword(Offset)+1); 00401 } 00402 00403 PPC_QUAL void __incfsdword(const unsigned long Offset) 00404 { 00405 __writefsdword(Offset, __readfsdword(Offset)+1); 00406 } 00407 00408 /* NOTE: the bizarre implementation of __addfsxxx mimics the broken Visual C++ behavior */ 00409 /* PPC Note: Not sure about the bizarre behavior. We'll try to emulate it later */ 00410 PPC_QUAL void __addfsbyte(const unsigned long Offset, const unsigned char Data) 00411 { 00412 __writefsbyte(Offset, __readfsbyte(Offset) + Data); 00413 } 00414 00415 PPC_QUAL void __addfsword(const unsigned long Offset, const unsigned short Data) 00416 { 00417 __writefsword(Offset, __readfsword(Offset) + Data); 00418 } 00419 00420 PPC_QUAL void __addfsdword(const unsigned long Offset, const unsigned int Data) 00421 { 00422 __writefsdword(Offset, __readfsdword(Offset) + Data); 00423 } 00424 00425 00426 /*** Bit manipulation ***/ 00427 PPC_QUAL unsigned char _BitScanForward(unsigned long * const Index, const unsigned long Mask) 00428 { 00429 if(Mask == 0) return 0; 00430 else { 00431 unsigned long mask = Mask; 00432 mask &= -mask; 00433 *Index = 00434 ((mask & 0xffff0000) ? 16 : 0) + 00435 ((mask & 0xff00ff00) ? 8 : 0) + 00436 ((mask & 0xf0f0f0f0) ? 4 : 0) + 00437 ((mask & 0xcccccccc) ? 2 : 0) + 00438 ((mask & 0xaaaaaaaa) ? 1 : 0); 00439 return 1; 00440 } 00441 } 00442 00443 /* Thanks http://www.jjj.de/bitwizardry/files/bithigh.h */ 00444 PPC_QUAL unsigned char _BitScanReverse(unsigned long * const Index, const unsigned long Mask) 00445 { 00446 unsigned long check = 16, checkmask; 00447 if(Mask == 0) return 0; 00448 else { 00449 unsigned long mask = Mask; 00450 *Index = 0; 00451 while(check) { 00452 checkmask = ((1<<check)-1) << check; 00453 if( mask & checkmask ) { 00454 mask >>= check; 00455 *Index += check; 00456 } 00457 check >>= 1; 00458 } 00459 return 1; 00460 } 00461 } 00462 00463 /* NOTE: again, the bizarre implementation follows Visual C++ */ 00464 PPC_QUAL unsigned char _bittest(const long * const a, const long b) 00465 { 00466 return ((*a) & (1<<b)) != 0; 00467 } 00468 00469 PPC_QUAL unsigned char _bittestandcomplement(long * const a, const long b) 00470 { 00471 unsigned char ret = ((*a) & (1<<b)) != 0; 00472 (*a) ^= (1<<b); 00473 return ret; 00474 } 00475 00476 PPC_QUAL unsigned char _bittestandreset(long * const a, const long b) 00477 { 00478 unsigned char ret = ((*a) & (1<<b)) != 0; 00479 (*a) &= ~(1<<b); 00480 return ret; 00481 } 00482 00483 PPC_QUAL unsigned char _bittestandset(long * const a, const long b) 00484 { 00485 unsigned char ret = ((*a) & (1<<b)) != 0; 00486 (*a) |= (1<<b); 00487 return ret; 00488 } 00489 00490 PPC_QUAL unsigned char _rotl8(const unsigned char value, const unsigned char shift) 00491 { 00492 return (value << shift) | (value >> (8-shift)); 00493 } 00494 00495 PPC_QUAL unsigned short _rotl16(const unsigned short value, const unsigned char shift) 00496 { 00497 return (value << shift) | (value >> (16-shift)); 00498 } 00499 00500 PPC_QUAL unsigned char _rotr8(const unsigned char value, const unsigned char shift) 00501 { 00502 return (value >> shift) | (value << (8-shift)); 00503 } 00504 00505 PPC_QUAL unsigned short _rotr16(const unsigned short value, const unsigned char shift) 00506 { 00507 return (value >> shift) | (value << (16-shift)); 00508 } 00509 00510 PPC_QUAL unsigned long long __ll_lshift(const unsigned long long Mask, int Bit) 00511 { 00512 return Mask << Bit; 00513 } 00514 00515 PPC_QUAL long long __ll_rshift(const long long Mask, const int Bit) 00516 { 00517 return Mask >> Bit; 00518 } 00519 00520 PPC_QUAL unsigned long long __ull_rshift(const unsigned long long Mask, int Bit) 00521 { 00522 return Mask >> Bit; 00523 } 00524 00525 00526 /*** 64-bit math ***/ 00527 PPC_QUAL long long __emul(const int a, const int b) 00528 { 00529 return a * b; 00530 } 00531 00532 PPC_QUAL unsigned long long __emulu(const unsigned int a, const unsigned int b) 00533 { 00534 return a * b; 00535 } 00536 00537 00538 /*** Port I/O ***/ 00539 PPC_QUAL unsigned char __inbyte(const unsigned long Port) 00540 { 00541 int ret; 00542 __asm__( 00543 "mfmsr 5\n\t" 00544 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ 00545 "mtmsr 6\n\t" 00546 "isync\n\t" 00547 "sync\n\t" 00548 "lbz %0,0(%1)\n\t" /* Get actual value at phys addr r3 */ 00549 "mtmsr 5\n\t" : "=r" (ret) : "b" (Port) 00550 ); 00551 return ret; 00552 } 00553 00554 PPC_QUAL unsigned short __inword(const unsigned long Port) 00555 { 00556 int ret; 00557 __asm__( 00558 "mfmsr 5\n\t" 00559 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ 00560 "mtmsr 6\n\t" 00561 "isync\n\t" 00562 "sync\n\t" 00563 "lhz %0,0(%1)\n\t" /* Get actual value at phys addr r3 */ 00564 "mtmsr 5\n\t" : "=r" (ret) : "b" (Port) 00565 ); 00566 return ret; 00567 } 00568 00569 PPC_QUAL unsigned long __indword(const unsigned long Port) 00570 { 00571 int ret; 00572 __asm__( 00573 "mfmsr 5\n\t" 00574 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ 00575 "mtmsr 6\n\t" 00576 "isync\n\t" 00577 "sync\n\t" 00578 "lwz %0,0(%1)\n\t" /* Get actual value at phys addr r3 */ 00579 "mtmsr 5\n\t" : "=r" (ret) : "b" (Port) 00580 ); 00581 return ret; 00582 } 00583 00584 PPC_QUAL void __inbytestring(unsigned long Port, unsigned char * Buffer, unsigned long Count) 00585 { 00586 while(Count--) { 00587 *Buffer++ = __inbyte(Port); 00588 } 00589 } 00590 00591 PPC_QUAL void __inwordstring(unsigned long Port, unsigned short * Buffer, unsigned long Count) 00592 { 00593 while(Count--) { 00594 *Buffer++ = __inword(Port); 00595 } 00596 } 00597 00598 PPC_QUAL void __indwordstring(unsigned long Port, unsigned long * Buffer, unsigned long Count) 00599 { 00600 while(Count--) { 00601 *Buffer++ = __indword(Port); 00602 } 00603 } 00604 00605 PPC_QUAL void __outbyte(unsigned long const Port, const unsigned char Data) 00606 { 00607 __asm__( 00608 "mfmsr 5\n\t" 00609 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ 00610 "mtmsr 6\n\t" 00611 "sync\n\t" 00612 "eieio\n\t" 00613 "stb %1,0(%0)\n\t" /* Set actual value at phys addr r3 */ 00614 "dcbst 0,%1\n\t" 00615 "mtmsr 5\n\t" 00616 "sync\n\t" 00617 "eieio\n\t" : : "b" (Port), "r" (Data) 00618 ); 00619 } 00620 00621 PPC_QUAL void __outword(unsigned long const Port, const unsigned short Data) 00622 { 00623 __asm__( 00624 "mfmsr 5\n\t" 00625 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ 00626 "mtmsr 6\n\t" 00627 "sync\n\t" 00628 "eieio\n\t" 00629 "sth %1,0(%0)\n\t" /* Set actual value at phys addr r3 */ 00630 "dcbst 0,%1\n\t" 00631 "mtmsr 5\n\t" 00632 "sync\n\t" 00633 "eieio\n\t" : : "b" (Port), "b" (Data) 00634 ); 00635 } 00636 00637 PPC_QUAL void __outdword(unsigned long const Port, const unsigned long Data) 00638 { 00639 __asm__( 00640 "mfmsr 5\n\t" 00641 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ 00642 "mtmsr 6\n\t" 00643 "sync\n\t" 00644 "eieio\n\t" 00645 "stw %1,0(%0)\n\t" /* Set actual value at phys addr r3 */ 00646 "dcbst 0,%1\n\t" 00647 "mtmsr 5\n\t" 00648 "sync\n\t" 00649 "eieio\n\t" : : "b" (Port), "b" (Data) 00650 ); 00651 } 00652 00653 PPC_QUAL void __outbytestring(unsigned long const Port, const unsigned char * const Buffer, const unsigned long Count) 00654 { 00655 unsigned long count = Count; 00656 const unsigned char *buffer = Buffer; 00657 while(count--) { 00658 __outbyte(Port, *buffer++); 00659 } 00660 } 00661 00662 PPC_QUAL void __outwordstring(unsigned long const Port, const unsigned short * const Buffer, const unsigned long Count) 00663 { 00664 unsigned long count = Count; 00665 const unsigned short *buffer = Buffer; 00666 while(count--) { 00667 __outword(Port, *buffer++); 00668 } 00669 } 00670 00671 PPC_QUAL void __outdwordstring(unsigned long const Port, const unsigned long * const Buffer, const unsigned long Count) 00672 { 00673 unsigned long count = Count; 00674 const unsigned long *buffer = Buffer; 00675 while(count--) { 00676 __outdword(Port, *buffer++); 00677 } 00678 } 00679 00680 00681 /*** System information ***/ 00682 PPC_QUAL void __cpuid(int CPUInfo[], const int InfoType) 00683 { 00684 unsigned long lo32; 00685 __asm__("mfpvr" : "=b" (lo32)); 00686 } 00687 00688 PPC_QUAL unsigned long long __rdtsc(void) 00689 { 00690 unsigned long lo32; 00691 __asm__("mfdec %0" : "=b" (lo32)); 00692 return -lo32; 00693 } 00694 00695 00696 /*** Interrupts ***/ 00697 /* Finally decided to do this by enabling single step trap */ 00698 PPC_QUAL void __debugbreak(void) 00699 { 00700 00701 } 00702 00703 PPC_QUAL void __int2c(void) 00704 { 00705 /* Not sure yet */ 00706 } 00707 00708 #ifndef _ENABLE_DISABLE_DEFINED 00709 #define _ENABLE_DISABLE_DEFINED 00710 PPC_QUAL void _disable(void) 00711 { 00712 __asm__ __volatile__("mfmsr 0\n\t" \ 00713 "li 8,0x7fff\n\t" \ 00714 "and 0,8,0\n\t" \ 00715 "mtmsr 0\n\t"); 00716 } 00717 00718 PPC_QUAL void _enable(void) 00719 { 00720 __asm__ __volatile__("mfmsr 8\n\t" \ 00721 "ori 8,8,0x8000\n\t" \ 00722 "mtmsr 8\n\t"); 00723 } 00724 00725 /*** Protected memory management ***/ 00726 PPC_QUAL unsigned long __readsdr1(void) 00727 { 00728 unsigned long value; 00729 __asm__("mfsdr1 %0" : "=b" (value)); 00730 return value; 00731 } 00732 00733 PPC_QUAL void __writesdr1(const unsigned long long Data) 00734 { 00735 __asm__("mtsdr1 %0" : : "b" (Data)); 00736 } 00737 00738 /*** System operations ***/ 00739 /* This likely has a different meaning from the X86 equivalent. We'll keep 00740 * the name cause it fits */ 00741 PPC_QUAL unsigned long long __readmsr() 00742 { 00743 unsigned long temp; 00744 __asm__("mfmsr %0" : "=b" (temp)); 00745 return temp; 00746 } 00747 00748 PPC_QUAL void __writemsr(const unsigned long Value) 00749 { 00750 __asm__("mtmsr %0" : : "b" (Value)); 00751 } 00752 00753 /* We'll make sure of the following: 00754 * IO operations have completed 00755 * Write operations through cache have completed 00756 * We've reloaded anything in the data or instruction cache that might have 00757 * changed in real ram. 00758 */ 00759 PPC_QUAL void __wbinvd(void) 00760 { 00761 __asm__("eieio\n\t" 00762 "dcs\n\t" 00763 "sync\n\t" 00764 "isync\n\t"); 00765 } 00766 #endif 00767 00768 PPC_QUAL long _InterlockedAddLargeStatistic(volatile long long * const Addend, const long Value) 00769 { 00770 #if 0 00771 __asm__ 00772 ( 00773 "lock; add %[Value], %[Lo32];" 00774 "jae LABEL%=;" 00775 "lock; adc $0, %[Hi32];" 00776 "LABEL%=:;" : 00777 [Lo32] "=m" (*((volatile long *)(Addend) + 0)), [Hi32] "=m" (*((volatile long *)(Addend) + 1)) : 00778 [Value] "ir" (Value) 00779 ); 00780 #endif 00781 return Value; 00782 } 00783 00784 /*** Miscellaneous ***/ 00785 /* BUGBUG: only good for use in macros. Cannot be taken the address of */ 00786 #define __noop(...) ((void)0) 00787 00788 /* TODO: __assume. GCC only supports the weaker __builtin_expect */ 00789 00790 #endif 00791 /* EOF */ Generated on Sat May 26 2012 04:28:28 for ReactOS by
1.7.6.1
|