![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
00001 /* 00002 Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved. 00003 00004 Redistribution and use in source and binary forms, with or without 00005 modification, are permitted provided that the following conditions are met: 00006 00007 * Redistributions of source code must retain the above copyright notice, 00008 this list of conditions and the following disclaimer. 00009 * Redistributions in binary form must reproduce the above copyright notice, 00010 this list of conditions and the following disclaimer in the documentation 00011 and/or other materials provided with the distribution. 00012 * Neither the name of LibCat nor the names of its contributors may be used 00013 to endorse or promote products derived from this software without 00014 specific prior written permission. 00015 00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00019 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00020 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00021 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00022 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00023 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00024 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00025 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00026 POSSIBILITY OF SUCH DAMAGE. 00027 */ 00028 00029 #ifndef CAT_PLATFORM_HPP 00030 #define CAT_PLATFORM_HPP 00031 00032 #include <cat/Config.hpp> 00033 00034 namespace cat { 00035 00036 00038 00039 // Mac OS X additional compilation flags 00040 #ifdef __APPLE__ 00041 # include <TargetConditionals.h> 00042 #endif 00043 00044 //----------------------------------------------------------------------------- 00045 // Intel C++ Compiler : Interoperates with MSVC and GCC 00046 #if defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) 00047 # define CAT_COMPILER_ICC 00048 # define CAT_FENCE_COMPILER __memory_barrier(); 00049 #endif 00050 00051 //----------------------------------------------------------------------------- 00052 // Borland C++ Compiler : Compatible with MSVC syntax 00053 #if defined(__BORLANDC__) 00054 # define CAT_COMPILER_BORLAND 00055 # define CAT_COMPILER_COMPAT_MSVC 00056 # define CAT_INLINE __inline 00057 # define CAT_ASM_EMIT __emit__ 00058 00059 //----------------------------------------------------------------------------- 00060 // Digital Mars C++ Compiler (previously known as Symantec C++) 00061 #elif defined(__DMC__) || defined(__SC__) || defined(__SYMANTECC__) 00062 # define CAT_COMPILER_DMARS 00063 # define CAT_COMPILER_COMPAT_MSVC 00064 # define CAT_INLINE __inline 00065 # define CAT_ASM_EMIT __emit__ 00066 00067 //----------------------------------------------------------------------------- 00068 // Codeplay VectorC C++ Compiler : Compatible with GCC and MSVC syntax, prefer GCC 00069 #elif defined(__VECTORC__) 00070 # define CAT_COMPILER_CODEPLAY 00071 # define CAT_COMPILER_COMPAT_GCC 00072 00073 //----------------------------------------------------------------------------- 00074 // Pathscale C++ Compiler : Compatible with GCC syntax 00075 #elif defined(__PATHSCALE__) 00076 # define CAT_COMPILER_PATHSCALE 00077 # define CAT_COMPILER_COMPAT_GCC 00078 00079 //----------------------------------------------------------------------------- 00080 // Watcom C++ Compiler : Compatible with GCC and MSVC syntax, prefer GCC 00081 #elif defined(__WATCOMC__) 00082 # define CAT_COMPILER_WATCOM 00083 # define CAT_COMPILER_COMPAT_GCC 00084 00085 //----------------------------------------------------------------------------- 00086 // SUN C++ Compiler : Compatible with GCC syntax 00087 #elif defined(__SUNPRO_CC) 00088 # define CAT_COMPILER_SUN 00089 # define CAT_COMPILER_COMPAT_GCC 00090 00091 //----------------------------------------------------------------------------- 00092 // Metrowerks C++ Compiler : Compatible with MSVC syntax 00093 #elif defined(__MWERKS__) 00094 # define CAT_COMPILER_MWERKS 00095 # define CAT_COMPILER_COMPAT_MSVC 00096 # define CAT_INLINE inline 00097 # define CAT_ASM_BEGIN _asm { 00098 # define CAT_ASM_EMIT __emit__ 00099 00100 //----------------------------------------------------------------------------- 00101 // GNU C++ Compiler 00102 // SN Systems ProDG C++ Compiler : Compatible with GCC 00103 #elif defined(__GNUC__) || defined(__APPLE_CC__) || defined(__SNC__) 00104 # define CAT_COMPILER_GCC 00105 # define CAT_COMPILER_COMPAT_GCC 00106 # define CAT_FASTCALL __attribute__ ((fastcall)) 00107 00108 //----------------------------------------------------------------------------- 00109 // Microsoft Visual Studio C++ Compiler 00110 #elif defined(_MSC_VER) 00111 # define CAT_COMPILER_MSVC 00112 # define CAT_COMPILER_COMPAT_MSVC 00113 # define CAT_FASTCALL __fastcall 00114 00115 } // namespace cat 00116 # include <cstdlib> // Intrinsics 00117 # include <intrin.h> // Intrinsics 00118 namespace cat { 00119 00120 //----------------------------------------------------------------------------- 00121 // Otherwise unknown compiler 00122 #else 00123 # define CAT_COMPILER_UNKNOWN 00124 # define CAT_ALIGNED(n) /* no way to detect alignment syntax */ 00125 # define CAT_PACKED /* no way to detect packing syntax */ 00126 # define CAT_INLINE inline 00127 // No way to support inline assembly code here 00128 # define CAT_RESTRICT 00129 00130 #endif 00131 00132 /* 00133 A lot of compilers have similar syntax to MSVC or GCC, 00134 so for simplicity I have those two defined below, and 00135 any deviations are implemented with overrides above. 00136 */ 00137 00138 // MSVC-compatible compilers 00139 #if defined(CAT_COMPILER_COMPAT_MSVC) 00140 00141 #if !defined(CAT_ALIGNED) 00142 # define CAT_ALIGNED(n) __declspec(align(n)) 00143 #endif 00144 #if !defined(CAT_PACKED) 00145 # define CAT_PACKED 00146 # define CAT_PRAGMA_PACK 00147 #endif 00148 #if !defined(CAT_INLINE) 00149 # define CAT_INLINE __forceinline 00150 #endif 00151 #if !defined(CAT_ASM_INTEL) 00152 # define CAT_ASM_INTEL 00153 #endif 00154 #if !defined(CAT_ASM_BEGIN) 00155 # define CAT_ASM_BEGIN __asm { 00156 #endif 00157 #if !defined(CAT_ASM_EMIT) 00158 # define CAT_ASM_EMIT _emit 00159 #endif 00160 #if !defined(CAT_ASM_END) 00161 # define CAT_ASM_END } 00162 #endif 00163 #if !defined(CAT_TLS) 00164 # define CAT_TLS __declspec( thread ) 00165 #endif 00166 #if !defined(CAT_RESTRICT) 00167 # define CAT_RESTRICT __restrict 00168 #endif 00169 #if !defined(CAT_FENCE_COMPILER) 00170 # if defined(CAT_COMPILER_MSVC) 00171 # pragma intrinsic(_ReadWriteBarrier) 00172 # endif 00173 # define CAT_FENCE_COMPILER _ReadWriteBarrier(); 00174 #endif 00175 00176 // GCC-compatible compilers 00177 #elif defined(CAT_COMPILER_COMPAT_GCC) 00178 00179 #if !defined(CAT_ALIGNED) 00180 # define CAT_ALIGNED(n) __attribute__ ((aligned (n))) 00181 #endif 00182 #if !defined(CAT_PACKED) 00183 # define CAT_PACKED __attribute__ ((packed)) 00184 #endif 00185 #if !defined(CAT_INLINE) 00186 # define CAT_INLINE inline /* __inline__ __attribute__((always_inline)) */ 00187 #endif 00188 #if !defined(CAT_ASM_ATT) 00189 # define CAT_ASM_ATT 00190 #endif 00191 #if !defined(CAT_ASM_BEGIN) 00192 # define CAT_ASM_BEGIN __asm__ __volatile__ ( 00193 #endif 00194 #if !defined(CAT_ASM_EMIT) 00195 # define CAT_ASM_EMIT .byte 00196 #endif 00197 #if !defined(CAT_ASM_END) 00198 # define CAT_ASM_END ); 00199 #endif 00200 #if !defined(CAT_TLS) 00201 # define CAT_TLS __thread 00202 #endif 00203 #if !defined(CAT_RESTRICT) 00204 # define CAT_RESTRICT __restrict__ 00205 #endif 00206 #if !defined(CAT_FENCE_COMPILER) 00207 # define CAT_FENCE_COMPILER CAT_ASM_BEGIN "" ::: "memory" CAT_ASM_END 00208 #endif 00209 00210 #endif // CAT_COMPILER_COMPAT_* 00211 00212 00214 00215 #if defined(CAT_COMPILER_MSVC) 00216 00217 # if defined(_DEBUG) 00218 # define CAT_DEBUG 00219 # endif 00220 00221 #else 00222 00223 # if !defined(NDEBUG) 00224 # define CAT_DEBUG 00225 # endif 00226 00227 #endif 00228 00229 00231 00232 #if defined(__powerpc__) || defined(__ppc__) || defined(_POWER) || defined(_M_PPC) || \ 00233 defined(_M_MPPC) || defined(__POWERPC) || defined(powerpc) || defined(__ppc64__) || \ 00234 defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3) || defined(__POWERPC__) 00235 # define CAT_ISA_PPC 00236 00237 #elif defined(__i386__) || defined(i386) || defined(intel) || defined(_M_IX86) || \ 00238 defined(__ia64) || defined(__ia64__) || defined(__x86_64) || defined(_M_IA64) || \ 00239 defined(_M_X64) 00240 # define CAT_ISA_X86 00241 00242 #elif defined(TARGET_CPU_ARM) 00243 # define CAT_ISA_ARM 00244 00245 #elif defined(__mips__) 00246 # define CAT_ISA_MIPS 00247 00248 #elif defined(__ALPHA__) 00249 # define CAT_ISA_ALPHA 00250 00251 #else 00252 # define CAT_ISA_UNKNOWN 00253 #endif 00254 00255 00257 00258 // Okay -- Technically IA64 and PPC can switch endianness with an MSR bit 00259 // flip, but come on no one does that! ...Right? 00260 // If it's not right, make sure that one of the first two flags are defined. 00261 #if defined(__LITTLE_ENDIAN__) 00262 # define CAT_ENDIAN_LITTLE 00263 #elif defined(__BIG_ENDIAN__) 00264 # define CAT_ENDIAN_BIG 00265 #elif defined(CAT_ISA_X86) 00266 # define CAT_ENDIAN_LITTLE 00267 #elif defined(CAT_ISA_PPC) 00268 # define CAT_ENDIAN_BIG 00269 #else 00270 # define CAT_ENDIAN_UNKNOWN /* Must be detected at runtime */ 00271 #endif 00272 00273 00275 00276 #if defined(_LP64) || defined(__LP64__) || defined(__arch64__) || \ 00277 defined(_WIN64) || defined(_M_X64) || defined(__ia64) || \ 00278 defined(__ia64__) || defined(__x86_64) || defined(_M_IA64) || \ 00279 defined(__mips64) 00280 00281 # define CAT_WORD_64 00282 00283 // 64-bit MSVC does not support inline assembly 00284 # if defined(CAT_COMPILER_MSVC) 00285 # undef CAT_ASM_INTEL 00286 # endif 00287 00288 #else // Assuming 32-bit otherwise! 00289 00290 # define CAT_WORD_32 00291 00292 #endif 00293 00294 // __fastcall calling convention is rarely supported, and doesn't make sense for 64-bit targets 00295 #if !defined(CAT_FASTCALL) 00296 # define CAT_FASTCALL 00297 #elif defined(CAT_WORD_64) 00298 # undef CAT_FASTCALL 00299 # define CAT_FASTCALL 00300 #endif 00301 00302 00304 00305 #if defined(__APPLE__) && defined(TARGET_OS_IPHONE) 00306 # define CAT_OS_IPHONE 00307 00308 #elif defined(__APPLE__) && (defined(__MACH__) || defined(__DARWIN__)) 00309 # define CAT_OS_OSX 00310 00311 #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) 00312 # define CAT_OS_BSD 00313 00314 #elif defined(__linux__) || defined(__unix__) 00315 # define CAT_OS_LINUX 00316 00317 #elif defined(_WIN32_WCE) 00318 # define CAT_OS_WINDOWS_CE 00319 # define CAT_OS_WINDOWS /* Also defined */ 00320 00321 #elif defined(_WIN32) 00322 # define CAT_OS_WINDOWS 00323 00324 #elif defined(_XBOX) || defined(_X360) 00325 # define CAT_OS_XBOX 00326 00327 #elif defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3) 00328 # define CAT_OS_PS3 00329 00330 #elif defined(__OS2__) 00331 # define CAT_OS_OS2 00332 00333 #else 00334 # define CAT_OS_UNKNOWN 00335 #endif 00336 00337 00339 00340 #if defined(CAT_COMPILER_MSVC) 00341 00342 // MSVC does not ship with stdint.h (C99 standard...) 00343 typedef unsigned __int8 u8; 00344 typedef signed __int8 s8; 00345 typedef unsigned __int16 u16; 00346 typedef signed __int16 s16; 00347 typedef unsigned __int32 u32; 00348 typedef signed __int32 s32; 00349 typedef unsigned __int64 u64; 00350 typedef signed __int64 s64; 00351 00352 #else 00353 00354 } // namespace cat 00355 #include <stdint.h> 00356 namespace cat { 00357 00358 // All other compilers use this 00359 typedef uint8_t u8; 00360 typedef int8_t s8; 00361 typedef uint16_t u16; 00362 typedef int16_t s16; 00363 typedef uint32_t u32; 00364 typedef int32_t s32; 00365 typedef uint64_t u64; 00366 typedef int64_t s64; 00367 00368 #endif 00369 00370 #if defined(CAT_COMPILER_GCC) && defined(CAT_WORD_64) 00371 00372 // GCC also adds 128-bit types :D 00373 typedef __uint128_t u128; 00374 typedef __int128_t s128; 00375 00376 #endif 00377 00378 typedef float f32; 00379 typedef double f64; 00380 00381 union Float32 { 00382 float f; 00383 u32 i; 00384 00385 Float32(float n) { f = n; } 00386 Float32(u32 n) { i = n; } 00387 }; 00388 00389 00391 00392 // Same as strncpy() in all ways except that the result is guaranteed to 00393 // be a nul-terminated C string 00394 #if defined(CAT_COMPILER_MSVC) 00395 # define CAT_STRNCPY(dest, src, size) { strncpy_s(dest, size, src, size); (dest)[(size)-1] = '\0'; } 00396 #else 00397 # define CAT_STRNCPY(dest, src, size) { strncpy(dest, src, size); (dest)[(size)-1] = '\0'; } 00398 #endif 00399 00400 // Because memory clearing is a frequent operation 00401 #define CAT_CLR(dest, size) memset(dest, 0, size) 00402 00403 // Works for arrays, also 00404 #define CAT_OBJCLR(object) memset((void*)&(object), 0, sizeof(object)) 00405 00406 // Stringize 00407 #define CAT_STRINGIZE(X) DO_CAT_STRINGIZE(X) 00408 #define DO_CAT_STRINGIZE(X) #X 00409 00410 // Variable-length data trailing a struct 00411 template<typename T> CAT_INLINE u8 *GetTrailingBytes(T *t) { return reinterpret_cast<u8*>( t ) + sizeof(T); } 00412 00413 // Bounds 00414 template<typename T> CAT_INLINE T BoundMin(const T &minimum, const T &x) 00415 { 00416 if (x < minimum) return minimum; 00417 return x; 00418 } 00419 00420 template<typename T> CAT_INLINE T BoundMax(const T &maximum, const T &x) 00421 { 00422 if (x > maximum) return maximum; 00423 return x; 00424 } 00425 00426 template<typename T> CAT_INLINE T Bound(const T &minimum, const T &maximum, const T &x) 00427 { 00428 if (x < minimum) return minimum; 00429 if (x > maximum) return maximum; 00430 return x; 00431 } 00432 00433 00435 00436 #define CAT_BITCLRHI8(reg, count) ((u8)((u8)(reg) << (count)) >> (count)) /* sets to zero a number of high bits in a byte */ 00437 #define CAT_BITCLRLO8(reg, count) ((u8)((u8)(reg) >> (count)) << (count)) /* sets to zero a number of low bits in a byte */ 00438 #define CAT_BITCLRHI16(reg, count) ((u16)((u16)(reg) << (count)) >> (count)) /* sets to zero a number of high bits in a 16-bit word */ 00439 #define CAT_BITCLRLO16(reg, count) ((u16)((u16)(reg) >> (count)) << (count)) /* sets to zero a number of low bits in a 16-bit word */ 00440 #define CAT_BITCLRHI32(reg, count) ((u32)((u32)(reg) << (count)) >> (count)) /* sets to zero a number of high bits in a 32-bit word */ 00441 #define CAT_BITCLRLO32(reg, count) ((u32)((u32)(reg) >> (count)) << (count)) /* sets to zero a number of low bits in a 32-bit word */ 00442 00443 00445 00446 #define CAT_AT_LEAST_2_BITS(n) ( (n) & ((n) - 1) ) 00447 #define CAT_LEAST_SIGNIFICANT_BIT(n) ( (n) & (u32)(-(s32)(n)) ) /* 0 -> 0 */ 00448 #define CAT_IS_POWER_OF_2(n) ( n && !CAT_AT_LEAST_2_BITS(n) ) 00449 00450 // Safely take the average of two numbers without possibility of overflow 00451 #define CAT_SAFE_AVERAGE(A, B) (((A) & (B)) + (((A) ^ (B)) >> 1)) 00452 00453 // Bump 'n' to the next unit of 'width' 00454 // 0=CAT_CEIL_UNIT(0, 16), 1=CAT_CEIL_UNIT(1, 16), 1=CAT_CEIL_UNIT(16, 16), 2=CAT_CEIL_UNIT(17, 16) 00455 #define CAT_CEIL_UNIT(n, width) ( ( (n) + (width) - 1 ) / (width) ) 00456 // 0=CAT_CEIL(0, 16), 16=CAT_CEIL(1, 16), 16=CAT_CEIL(16, 16), 32=CAT_CEIL(17, 16) 00457 #define CAT_CEIL(n, width) ( CAT_CEIL_UNIT(n, width) * (width) ) 00458 00459 00461 00462 #define CAT_ROL8(n, r) ( ((u8)(n) << (r)) | ((u8)(n) >> ( 8 - (r))) ) /* only works for u8 */ 00463 #define CAT_ROR8(n, r) ( ((u8)(n) >> (r)) | ((u8)(n) << ( 8 - (r))) ) /* only works for u8 */ 00464 #define CAT_ROL16(n, r) ( ((u16)(n) << (r)) | ((u16)(n) >> (16 - (r))) ) /* only works for u16 */ 00465 #define CAT_ROR16(n, r) ( ((u16)(n) >> (r)) | ((u16)(n) << (16 - (r))) ) /* only works for u16 */ 00466 #define CAT_ROL32(n, r) ( ((u32)(n) << (r)) | ((u32)(n) >> (32 - (r))) ) /* only works for u32 */ 00467 #define CAT_ROR32(n, r) ( ((u32)(n) >> (r)) | ((u32)(n) << (32 - (r))) ) /* only works for u32 */ 00468 #define CAT_ROL64(n, r) ( ((u64)(n) << (r)) | ((u64)(n) >> (64 - (r))) ) /* only works for u64 */ 00469 #define CAT_ROR64(n, r) ( ((u64)(n) >> (r)) | ((u64)(n) << (64 - (r))) ) /* only works for u64 */ 00470 00471 00473 00474 #define CAT_BOSWAP16(n) CAT_ROL16(n, 8) 00475 #define CAT_BOSWAP32(n) ( (CAT_ROL32(n, 8) & 0x00ff00ff) | (CAT_ROL32(n, 24) & 0xff00ff00) ) 00476 #define CAT_BOSWAP64(n) ( ((u64)CAT_BOSWAP32((u32)n) << 32) | CAT_BOSWAP32((u32)(n >> 32)) ) 00477 00478 00480 00481 #if defined(CAT_OS_WINDOWS_CE) 00482 00483 #pragma intrinsic(_lrotl) 00484 #pragma intrinsic(_lrotr) 00485 00486 #undef CAT_ROL32 00487 #undef CAT_ROR32 00488 00489 #define CAT_ROL32(n, r) _lrotl(n, r) 00490 #define CAT_ROR32(n, r) _lrotr(n, r) 00491 00492 #elif defined(CAT_COMPILER_MSVC) 00493 00494 #pragma intrinsic(_rotl) 00495 #pragma intrinsic(_rotr) 00496 #pragma intrinsic(_rotl64) 00497 #pragma intrinsic(_rotr64) 00498 #pragma intrinsic(_byteswap_ushort) 00499 #pragma intrinsic(_byteswap_ulong) 00500 #pragma intrinsic(_byteswap_uint64) 00501 #pragma intrinsic(_BitScanForward) 00502 #pragma intrinsic(_BitScanReverse) 00503 #pragma intrinsic(__emulu) 00504 #pragma intrinsic(_InterlockedExchange) 00505 #pragma intrinsic(_interlockedbittestandset) 00506 #pragma intrinsic(_interlockedbittestandreset) 00507 00508 #if defined(CAT_WORD_64) 00509 #pragma intrinsic(__rdtsc) 00510 #pragma intrinsic(_umul128) 00511 #pragma intrinsic(_BitScanForward64) 00512 #pragma intrinsic(_BitScanReverse64) 00513 #pragma intrinsic(_InterlockedCompareExchange128) 00514 #else 00515 #pragma intrinsic(_InterlockedCompareExchange64) 00516 #endif 00517 00518 #undef CAT_ROL32 00519 #undef CAT_ROR32 00520 #undef CAT_ROL64 00521 #undef CAT_ROR64 00522 #undef CAT_BOSWAP16 00523 #undef CAT_BOSWAP32 00524 #undef CAT_BOSWAP64 00525 00526 #define CAT_ROL32(n, r) _rotl(n, r) 00527 #define CAT_ROR32(n, r) _rotr(n, r) 00528 #define CAT_ROL64(n, r) _rotl64(n, r) 00529 #define CAT_ROR64(n, r) _rotr64(n, r) 00530 #define CAT_BOSWAP16(n) _byteswap_ushort(n) 00531 #define CAT_BOSWAP32(n) _byteswap_ulong(n) 00532 #define CAT_BOSWAP64(n) _byteswap_uint64(n) 00533 00534 #endif 00535 00536 00537 } // namespace cat 00538 00539 #endif // CAT_PLATFORM_HPP
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.