__asm__("wbinvd");\r
}\r
\r
+#elif defined(_M_PPC)\r
+\r
+/*** Stack frame juggling ***/\r
+#define _ReturnAddress() (__builtin_return_address(0))\r
+#define _AddressOfReturnAddress() (&(((void **)(__builtin_frame_address(0)))[1]))\r
+/* TODO: __getcallerseflags but how??? */\r
+\r
+\r
+/*** Atomic operations ***/\r
+/* TODO: _ReadBarrier */\r
+/* TODO: _WriteBarrier */\r
+\r
+#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100\r
+#define _ReadWriteBarrier() __sync_synchronize()\r
+#else\r
+/* TODO: _ReadWriteBarrier() */\r
+#endif\r
+\r
+#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100\r
+\r
+static __inline__ __attribute__((always_inline)) char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)\r
+{\r
+ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)\r
+{\r
+ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)\r
+{\r
+ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)\r
+{\r
+ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)\r
+{\r
+ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedExchange(volatile long * const Target, const long Value)\r
+{\r
+ /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */\r
+ __sync_synchronize();\r
+ return __sync_lock_test_and_set(Target, Value);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)\r
+{\r
+ /* NOTE: ditto */\r
+ __sync_synchronize();\r
+ return __sync_lock_test_and_set(Target, Value);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)\r
+{\r
+ return __sync_fetch_and_add(Addend, Value);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask)\r
+{\r
+ return __sync_fetch_and_and(value, mask);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask)\r
+{\r
+ return __sync_fetch_and_and(value, mask);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedAnd(volatile long * const value, const long mask)\r
+{\r
+ return __sync_fetch_and_and(value, mask);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask)\r
+{\r
+ return __sync_fetch_and_or(value, mask);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask)\r
+{\r
+ return __sync_fetch_and_or(value, mask);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedOr(volatile long * const value, const long mask)\r
+{\r
+ return __sync_fetch_and_or(value, mask);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask)\r
+{\r
+ return __sync_fetch_and_xor(value, mask);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask)\r
+{\r
+ return __sync_fetch_and_xor(value, mask);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedXor(volatile long * const value, const long mask)\r
+{\r
+ return __sync_fetch_and_xor(value, mask);\r
+}\r
+\r
+#else\r
+\r
+static __inline__ __attribute__((always_inline)) char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)\r
+{\r
+ char retval = Comperand;\r
+ __asm__ __volatile__ (\r
+ "sync\n"\r
+ "1: lbarx %0,0,%1\n"\r
+ " subf. %0,%2,%0\n"\r
+ " bne 2f\n"\r
+ " stbcx. %3,0,%1\n"\r
+ " bne- 1b\n"\r
+ "2: isync"\r
+ : "=b" (retval)\r
+ : "b" (Destination), "r" (Comperand), "r" (Exchange)\r
+ : "cr0", "memory");\r
+ return retval;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)\r
+{\r
+ short retval = Comperand;\r
+ __asm__ __volatile__ (\r
+ "sync\n"\r
+ "1: lharx %0,0,%1\n"\r
+ " subf. %0,%2,%0\n"\r
+ " bne 2f\n"\r
+ " sthcx. %3,0,%1\n"\r
+ " bne- 1b\n"\r
+ "2: isync"\r
+ : "=b" (retval)\r
+ : "b" (Destination), "r" (Comperand), "r" (Exchange)\r
+ : "cr0", "memory");\r
+ return retval;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)\r
+{\r
+ long retval = Comperand;\r
+ __asm__ __volatile__ (\r
+ "sync\n"\r
+ "1: lwarx %0,0,%1\n"\r
+ " subf. %0,%2,%0\n"\r
+ " bne 2f\n"\r
+ " stwcx. %3,0,%1\n"\r
+ " bne- 1b\n"\r
+ "2: isync"\r
+ : "=b" (retval)\r
+ : "b" (Destination), "r" (Comperand), "r" (Exchange)\r
+ : "cr0", "memory");\r
+ return retval;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)\r
+{\r
+ unsigned long lo32Retval = (unsigned long)((Comperand >> 0) & 0xFFFFFFFF);\r
+ long hi32Retval = (unsigned long)((Comperand >> 32) & 0xFFFFFFFF);\r
+\r
+ unsigned long lo32Exchange = (unsigned long)((Exchange >> 0) & 0xFFFFFFFF);\r
+ long hi32Exchange = (unsigned long)((Exchange >> 32) & 0xFFFFFFFF);\r
+\r
+#if 0\r
+ __asm__\r
+ (\r
+ "cmpxchg8b %[Destination]" :\r
+ "a" (lo32Retval), "d" (hi32Retval) :\r
+ [Destination] "rm" (Destination), "b" (lo32Exchange), "c" (hi32Exchange) :\r
+ "memory"\r
+ );\r
+#endif\r
+ {\r
+ union u_\r
+ {\r
+ long long ll;\r
+ struct s_\r
+ {\r
+ unsigned long lo32;\r
+ long hi32;\r
+ }\r
+ s;\r
+ }\r
+ u = { s : { lo32 : lo32Retval, hi32 : hi32Retval } };\r
+\r
+ return u.ll;\r
+ }\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)\r
+{\r
+ return (void *)_InterlockedCompareExchange\r
+ ((long *)Destination, (long) Exchange, (long) Comperand);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedExchange(volatile long * const Target, const long Value)\r
+{\r
+ long retval;\r
+ __asm__ __volatile__ (\r
+ "sync\n"\r
+ "1: lwarx %0,0,%1\n"\r
+ " stwcx. %2,0,%1\n"\r
+ " bne- 1b\n"\r
+ : "=b" (retval)\r
+ : "b" (Target), "b" (Value)\r
+ : "cr0", "memory");\r
+ return retval;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)\r
+{\r
+ void * retval;\r
+ __asm__ __volatile__ (\r
+ "sync\n"\r
+ "1: lwarx %0,0,%1\n"\r
+ " stwcx. %2,0,%1\n"\r
+ " bne- 1b\n"\r
+ : "=b" (retval)\r
+ : "b" (Target), "b" (Value)\r
+ : "cr0", "memory");\r
+ return retval;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)\r
+{\r
+ long x;\r
+ long y = *Addend;\r
+ long addend = y;\r
+ \r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange(Addend, addend + Value, x);\r
+ } \r
+ while(y != x);\r
+\r
+ return y;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask)\r
+{\r
+ char x;\r
+ char y;\r
+\r
+ y = *value;\r
+\r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange8(value, x & mask, x);\r
+ }\r
+ while(y != x);\r
+\r
+ return y;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask)\r
+{\r
+ short x;\r
+ short y;\r
+\r
+ y = *value;\r
+\r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange16(value, x & mask, x);\r
+ }\r
+ while(y != x);\r
+\r
+ return y;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedAnd(volatile long * const value, const long mask)\r
+{\r
+ long x;\r
+ long y;\r
+\r
+ y = *value;\r
+\r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange(value, x & mask, x);\r
+ }\r
+ while(y != x);\r
+\r
+ return y;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask)\r
+{\r
+ char x;\r
+ char y;\r
+\r
+ y = *value;\r
+\r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange8(value, x | mask, x);\r
+ }\r
+ while(y != x);\r
+\r
+ return y;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask)\r
+{\r
+ short x;\r
+ short y;\r
+\r
+ y = *value;\r
+\r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange16(value, x | mask, x);\r
+ }\r
+ while(y != x);\r
+\r
+ return y;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedOr(volatile long * const value, const long mask)\r
+{\r
+ long x;\r
+ long y;\r
+\r
+ y = *value;\r
+\r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange(value, x | mask, x);\r
+ }\r
+ while(y != x);\r
+\r
+ return y;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask)\r
+{\r
+ char x;\r
+ char y;\r
+\r
+ y = *value;\r
+\r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange8(value, x ^ mask, x);\r
+ }\r
+ while(y != x);\r
+\r
+ return y;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask)\r
+{\r
+ short x;\r
+ short y;\r
+\r
+ y = *value;\r
+\r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange16(value, x ^ mask, x);\r
+ }\r
+ while(y != x);\r
+\r
+ return y;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedXor(volatile long * const value, const long mask)\r
+{\r
+ long x;\r
+ long y;\r
+\r
+ y = *value;\r
+\r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange(value, x ^ mask, x);\r
+ }\r
+ while(y != x);\r
+\r
+ return y;\r
+}\r
+\r
+#endif\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedAddLargeStatistic(volatile long long * const Addend, const long Value)\r
+{\r
+#if 0\r
+ __asm__\r
+ (\r
+ "lock; add %[Value], %[Lo32];"\r
+ "jae LABEL%=;"\r
+ "lock; adc $0, %[Hi32];"\r
+ "LABEL%=:;" :\r
+ [Lo32] "=m" (*((volatile long *)(Addend) + 0)), [Hi32] "=m" (*((volatile long *)(Addend) + 1)) :\r
+ [Value] "ir" (Value)\r
+ );\r
+#endif\r
+ return Value;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedDecrement(volatile long * const lpAddend)\r
+{\r
+ return _InterlockedExchangeAdd(lpAddend, -1) - 1;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long _InterlockedIncrement(volatile long * const lpAddend)\r
+{\r
+ return _InterlockedExchangeAdd(lpAddend, 1) + 1;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned char _interlockedbittestandreset(volatile long * const a, const long b)\r
+{\r
+ long x;\r
+ long y;\r
+ long mask = ~(1<<b);\r
+\r
+ y = *a;\r
+\r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange(a, x & mask, x);\r
+ }\r
+ while(y != x);\r
+\r
+ return (y & ~mask) != 0;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned char _interlockedbittestandset(volatile long * const a, const long b)\r
+{\r
+ long x;\r
+ long y;\r
+ long mask = 1<<b;\r
+\r
+ y = *a;\r
+\r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange(a, x | mask, x);\r
+ }\r
+ while(y != x);\r
+\r
+ return (y & ~mask) != 0;\r
+}\r
+\r
+\r
+/*** String operations ***/\r
+/* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */\r
+/* Note that the PPC store multiple operations may raise an exception in LE \r
+ * mode */\r
+static __inline__ __attribute__((always_inline)) void __stosb(unsigned char * Dest, const unsigned char Data, size_t Count)\r
+{\r
+ memset(Dest, Data, Count);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __stosw(unsigned short * Dest, const unsigned short Data, size_t Count)\r
+{\r
+ while(Count--) \r
+ *Dest++ = Data;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __stosd(unsigned long * Dest, const unsigned long Data, size_t Count)\r
+{\r
+ while(Count--)\r
+ *Dest++ = Data;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __movsb(unsigned char * Destination, const unsigned char * Source, size_t Count)\r
+{\r
+ memcpy(Destination, Source, Count);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __movsw(unsigned short * Destination, const unsigned short * Source, size_t Count)\r
+{\r
+ memcpy(Destination, Source, Count * sizeof(*Source));\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __movsd(unsigned long * Destination, const unsigned long * Source, size_t Count)\r
+{\r
+ memcpy(Destination, Source, Count * sizeof(*Source));\r
+}\r
+\r
+\r
+/*** FS segment addressing ***/\r
+/* On PowerPC, r13 points to TLS data, including the TEB at 0(r13) from what I\r
+ * can tell */\r
+static __inline__ __attribute__((always_inline)) void __writefsbyte(const unsigned long Offset, const unsigned char Data)\r
+{\r
+ char *addr;\r
+ __asm__("\tadd %2,13,%0\n"\r
+ "\tstb %1,0(%2)\n" \r
+ : \r
+ : "b" (Offset), "b" (Data), "b" (addr));\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __writefsword(const unsigned long Offset, const unsigned short Data)\r
+{\r
+ char *addr;\r
+ __asm__("\tadd %2,13,%0\n"\r
+ "\tsth %1,0(%2)\n"\r
+ : \r
+ : "b" (Offset), "b" (Data), "b" (addr));\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __writefsdword(const unsigned long Offset, const unsigned long Data)\r
+{\r
+ char *addr;\r
+ __asm__("\tadd %2,13,%0\n"\r
+ "\tstw %1,0(%2)\n" \r
+ : \r
+ : "b" (Offset), "b" (Data), "b" (addr));\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned char __readfsbyte(const unsigned long Offset)\r
+{\r
+ char result;\r
+ char *addr;\r
+ __asm__("\tadd %2,13,%1\n"\r
+ "\tlbz %0,0(%2)\n"\r
+ : "=b" (result)\r
+ : "b" (Offset), "b" (addr));\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned short __readfsword(const unsigned long Offset)\r
+{\r
+ unsigned short result;\r
+ char *addr;\r
+ __asm__("\tadd %2,13,%1\n"\r
+ "\tlhz %0,0(%2)\n"\r
+ : "=b" (result)\r
+ : "b" (Offset), "b" (addr));\r
+ return result;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned long __readfsdword(const unsigned long Offset)\r
+{\r
+ unsigned long result;\r
+ char *addr;\r
+ __asm__("\tadd %2,13,%1\n"\r
+ "\tlwz %0,0(%2)\n"\r
+ : "=b" (result)\r
+ : "b" (Offset), "b" (addr));\r
+ return result;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __incfsbyte(const unsigned long Offset)\r
+{\r
+ __writefsbyte(Offset, __readfsbyte(Offset)+1);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __incfsword(const unsigned long Offset)\r
+{\r
+ __writefsword(Offset, __readfsword(Offset)+1);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __incfsdword(const unsigned long Offset)\r
+{\r
+ __writefsdword(Offset, __readfsdword(Offset)+1);\r
+}\r
+\r
+/* NOTE: the bizarre implementation of __addfsxxx mimics the broken Visual C++ behavior */\r
+/* PPC Note: Not sure about the bizarre behavior. We'll try to emulate it later */\r
+static __inline__ __attribute__((always_inline)) void __addfsbyte(const unsigned long Offset, const unsigned char Data)\r
+{\r
+ __writefsbyte(Offset, __readfsbyte(Offset) + Data);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __addfsword(const unsigned long Offset, const unsigned short Data)\r
+{\r
+ __writefsword(Offset, __readfsword(Offset) + Data);\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __addfsdword(const unsigned long Offset, const unsigned int Data)\r
+{\r
+ __writefsdword(Offset, __readfsdword(Offset) + Data);\r
+}\r
+\r
+\r
+/*** Bit manipulation ***/\r
+static __inline__ __attribute__((always_inline)) unsigned char _BitScanForward(unsigned long * const Index, const unsigned long Mask)\r
+{\r
+ if(Mask == 0) return 0;\r
+ else {\r
+ unsigned long mask = Mask;\r
+ mask &= -mask;\r
+ *Index = \r
+ ((mask & 0xffff0000) ? 16 : 0) +\r
+ ((mask & 0xff00ff00) ? 8 : 0) +\r
+ ((mask & 0xf0f0f0f0) ? 4 : 0) +\r
+ ((mask & 0xcccccccc) ? 2 : 0) +\r
+ ((mask & 0xaaaaaaaa) ? 1 : 0);\r
+ return 1;\r
+ }\r
+}\r
+\r
+/* Thanks http://www.jjj.de/bitwizardry/files/bithigh.h */\r
+static __inline__ __attribute__((always_inline)) unsigned char _BitScanReverse(unsigned long * const Index, const unsigned long Mask)\r
+{\r
+ unsigned long check = 16, checkmask;\r
+ if(Mask == 0) return 0;\r
+ else {\r
+ unsigned long mask = Mask;\r
+ *Index = 0;\r
+ while(check) {\r
+ checkmask = ((1<<check)-1) << check;\r
+ if( mask & checkmask ) {\r
+ mask >>= check;\r
+ *Index += check;\r
+ }\r
+ check >>= 1;\r
+ }\r
+ return 1;\r
+ }\r
+}\r
+\r
+/* NOTE: again, the bizarre implementation follows Visual C++ */\r
+static __inline__ __attribute__((always_inline)) unsigned char _bittest(const long * const a, const long b)\r
+{\r
+ return ((*a) & (1<<b)) != 0;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned char _bittestandcomplement(long * const a, const long b)\r
+{\r
+ unsigned char ret = ((*a) & (1<<b)) != 0;\r
+ (*a) ^= (1<<b);\r
+ return ret;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned char _bittestandreset(long * const a, const long b)\r
+{\r
+ unsigned char ret = ((*a) & (1<<b)) != 0;\r
+ (*a) &= ~(1<<b);\r
+ return ret;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned char _bittestandset(long * const a, const long b)\r
+{\r
+ unsigned char ret = ((*a) & (1<<b)) != 0;\r
+ (*a) |= (1<<b);\r
+ return ret;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned char _rotl8(const unsigned char value, const unsigned char shift)\r
+{\r
+ return (value << shift) | (value >> (8-shift));\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned short _rotl16(const unsigned short value, const unsigned char shift)\r
+{\r
+ return (value << shift) | (value >> (16-shift)); \r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned char _rotr8(const unsigned char value, const unsigned char shift)\r
+{\r
+ return (value >> shift) | (value << (8-shift)); \r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned short _rotr16(const unsigned short value, const unsigned char shift)\r
+{\r
+ return (value >> shift) | (value << (16-shift)); \r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned long long __ll_lshift(const unsigned long long Mask, int Bit)\r
+{\r
+ return Mask << Bit;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) long long __ll_rshift(const long long Mask, const int Bit)\r
+{\r
+ return Mask >> Bit;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned long long __ull_rshift(const unsigned long long Mask, int Bit)\r
+{\r
+ return Mask >> Bit;\r
+}\r
+\r
+\r
+/*** 64-bit math ***/\r
+static __inline__ __attribute__((always_inline)) long long __emul(const int a, const int b)\r
+{\r
+ return a * b;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned long long __emulu(const unsigned int a, const unsigned int b)\r
+{\r
+ return a * b;\r
+}\r
+\r
+\r
+/*** Port I/O ***/\r
+static __inline__ __attribute__((always_inline)) unsigned char __inbyte(const unsigned short Port)\r
+{\r
+ int ret;\r
+ __asm__(\r
+ "mfmsr 5\n\t"\r
+ "xori %1,%1,7\n\t" /* Undo effects of LE without swapping */\r
+ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */\r
+ "mtmsr 6\n\t"\r
+ "isync\n\t"\r
+ "sync\n\t"\r
+ "lbz %0,0(%1)\n\t" /* Get actual value at phys addr r3 */\r
+ "mtmsr 5\n\t" : "=r" (ret) : "b" (Port)\r
+ );\r
+ return ret;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned short __inword(const unsigned short Port)\r
+{\r
+ int ret;\r
+ __asm__(\r
+ "mfmsr 5\n\t"\r
+ "xori %1,%1,6\n\t" /* Undo effects of LE without swapping */\r
+ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */\r
+ "mtmsr 6\n\t"\r
+ "isync\n\t"\r
+ "sync\n\t"\r
+ "lhz %0,0(%1)\n\t" /* Get actual value at phys addr r3 */\r
+ "mtmsr 5\n\t" : "=r" (ret) : "b" (Port)\r
+ );\r
+ return ret;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned long __indword(const unsigned short Port)\r
+{\r
+ int ret;\r
+ __asm__(\r
+ "mfmsr 5\n\t"\r
+ "xori %1,%1,4\n\t" /* Undo effects of LE without swapping */\r
+ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */\r
+ "mtmsr 6\n\t"\r
+ "isync\n\t"\r
+ "sync\n\t"\r
+ "lwz %0,0(%1)\n\t" /* Get actual value at phys addr r3 */\r
+ "mtmsr 5\n\t" : "=r" (ret) : "b" (Port)\r
+ );\r
+ return ret;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __inbytestring(unsigned short Port, unsigned char * Buffer, unsigned long Count)\r
+{\r
+ while(Count--) {\r
+ *Buffer++ = __inbyte(Port);\r
+ }\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __inwordstring(unsigned short Port, unsigned short * Buffer, unsigned long Count)\r
+{\r
+ while(Count--) {\r
+ *Buffer++ = __inword(Port);\r
+ }\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __indwordstring(unsigned short Port, unsigned long * Buffer, unsigned long Count)\r
+{\r
+ while(Count--) {\r
+ *Buffer++ = __indword(Port);\r
+ }\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __outbyte(unsigned short const Port, const unsigned char Data)\r
+{\r
+ __asm__(\r
+ "mfmsr 5\n\t"\r
+ "xori %0,%0,7\n\t" /* Undo effects of LE without swapping */\r
+ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */\r
+ "mtmsr 6\n\t"\r
+ "sync\n\t"\r
+ "eieio\n\t"\r
+ "stb %1,0(%0)\n\t" /* Set actual value at phys addr r3 */\r
+ "dcbst 0,%1\n\t"\r
+ "mtmsr 5\n\t"\r
+ "sync\n\t"\r
+ "eieio\n\t" : : "b" (Port), "r" (Data)\r
+ );\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __outword(unsigned short const Port, const unsigned short Data)\r
+{\r
+ __asm__(\r
+ "mfmsr 5\n\t"\r
+ "xori %0,%0,7\n\t" /* Undo effects of LE without swapping */\r
+ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */\r
+ "mtmsr 6\n\t"\r
+ "sync\n\t"\r
+ "eieio\n\t"\r
+ "sth %1,0(%0)\n\t" /* Set actual value at phys addr r3 */\r
+ "dcbst 0,%1\n\t"\r
+ "mtmsr 5\n\t"\r
+ "sync\n\t"\r
+ "eieio\n\t" : : "b" (Port), "b" (Data)\r
+ );\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __outdword(unsigned short const Port, const unsigned long Data)\r
+{\r
+ __asm__(\r
+ "mfmsr 5\n\t"\r
+ "xori %0,%0,7\n\t" /* Undo effects of LE without swapping */\r
+ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */\r
+ "mtmsr 6\n\t"\r
+ "sync\n\t"\r
+ "eieio\n\t"\r
+ "stw %1,0(%0)\n\t" /* Set actual value at phys addr r3 */\r
+ "dcbst 0,%1\n\t"\r
+ "mtmsr 5\n\t"\r
+ "sync\n\t"\r
+ "eieio\n\t" : : "b" (Port), "b" (Data)\r
+ );\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __outbytestring(unsigned short const Port, const unsigned char * const Buffer, const unsigned long Count)\r
+{\r
+ unsigned long count = Count;\r
+ unsigned char *buffer = Buffer;\r
+ while(count--) {\r
+ __outbyte(Port, *buffer++);\r
+ }\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __outwordstring(unsigned short const Port, const unsigned short * const Buffer, const unsigned long Count)\r
+{\r
+ unsigned long count = Count;\r
+ unsigned short *buffer = Buffer;\r
+ while(count--) {\r
+ __outword(Port, *buffer++);\r
+ }\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __outdwordstring(unsigned short const Port, const unsigned long * const Buffer, const unsigned long Count)\r
+{\r
+ unsigned long count = Count;\r
+ unsigned long *buffer = Buffer;\r
+ while(count--) {\r
+ __outdword(Port, *buffer++);\r
+ }\r
+}\r
+\r
+\r
+/*** System information ***/\r
+static __inline__ __attribute__((always_inline)) void __cpuid(int CPUInfo[], const int InfoType)\r
+{\r
+ unsigned long lo32;\r
+ __asm__("mfpvr" : "=b" (lo32));\r
+ return lo32;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) unsigned long long __rdtsc(void)\r
+{\r
+ unsigned long lo32;\r
+ __asm__("mfdec" : "=b" (lo32));\r
+ return lo32;\r
+}\r
+\r
+\r
+/*** Interrupts ***/\r
+/* Finally decided to do this by enabling single step trap */\r
+static __inline__ __attribute__((always_inline)) void __debugbreak(void)\r
+{\r
+ \r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __int2c(void)\r
+{\r
+ /* Not sure yet */\r
+}\r
+\r
+#ifndef _ENABLE_DISABLE_DEFINED\r
+#define _ENABLE_DISABLE_DEFINED\r
+static __inline__ __attribute__((always_inline)) void _disable(void)\r
+{\r
+ __asm__ __volatile__("mfmsr 0\n\t" \\r
+ "li 8,0x7fff\n\t" \\r
+ "and 0,8,0\n\t" \\r
+ "mtmsr 0\n\t");\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void _enable(void)\r
+{\r
+ __asm__ __volatile__("mfmsr 0\n\t" \\r
+ "lis 8,0x8000@ha\n\t" \\r
+ "or 0,8,0\n\t" \\r
+ "mtmsr 0\n\t");\r
+}\r
+#endif\r
+\r
+/*** Protected memory management ***/\r
+static __inline__ __attribute__((always_inline)) unsigned long __readsdr1(void)\r
+{\r
+ unsigned long value;\r
+ __asm__("mfsdr1 %0" : "=b" (value));\r
+ return value;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __writesdr1(const unsigned long long Data)\r
+{\r
+ __asm__("mtsdr1 %0" : : "b" (Data));\r
+}\r
+\r
+/*** System operations ***/\r
+/* This likely has a different meaning from the X86 equivalent. We'll keep\r
+ * the name cause it fits */\r
+static __inline__ __attribute__((always_inline)) unsigned long long __readmsr()\r
+{\r
+ unsigned long temp;\r
+ __asm__("mfmsr %0" : "=b" (temp));\r
+ return temp;\r
+}\r
+\r
+static __inline__ __attribute__((always_inline)) void __writemsr(const unsigned long Value)\r
+{\r
+ __asm__("mtmsr %0" : : "b" (Value));\r
+}\r
+\r
+/* We'll make sure of the following:\r
+ * IO operations have completed\r
+ * Write operations through cache have completed\r
+ * We've reloaded anything in the data or instruction cache that might have\r
+ * changed in real ram.\r
+ */\r
+static __inline__ __attribute__((always_inline)) void __wbinvd(void)\r
+{\r
+ __asm__("eieio\n\t"\r
+ "dcs\n\t"\r
+ "sync\n\t"\r
+ "isync\n\t");\r
+}\r
#else\r
/* TODO: the x64 architecture shares most of the intrinsics. It should be easy to support */\r
#error Unsupported architecture\r