Shadowrun: Awakened 29 September 2011 - Build 871
Platform.hpp
Go to the documentation of this file.
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.

GNU Lesser General Public License 3 Sourceforge.net