lzham_platform.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. // File: lzham_platform.h
  2. // See Copyright Notice and license at the end of include/lzham.h
  3. #pragma once
  4. bool lzham_is_debugger_present(void);
  5. void lzham_debug_break(void);
  6. void lzham_output_debug_string(const char* p);
  7. // actually in lzham_assert.cpp
  8. void lzham_assert(const char* pExp, const char* pFile, unsigned line);
  9. void lzham_fail(const char* pExp, const char* pFile, unsigned line);
  10. #ifdef WIN32
  11. #define LZHAM_BREAKPOINT DebuggerBreak();
  12. #define LZHAM_BUILTIN_EXPECT(c, v) c
  13. #elif defined(__GNUC__) && !defined EMSCRIPTEN // ESENTHEL CHANGED
  14. #define LZHAM_BREAKPOINT asm("int $3");
  15. #define LZHAM_BUILTIN_EXPECT(c, v) __builtin_expect(c, v)
  16. #else
  17. #define LZHAM_BREAKPOINT
  18. #define LZHAM_BUILTIN_EXPECT(c, v) c
  19. #endif
  20. #if defined(__GNUC__) && LZHAM_PLATFORM_PC
  21. extern __inline__ __attribute__((__always_inline__,__gnu_inline__)) void lzham_yield_processor()
  22. {
  23. __asm__ __volatile__("pause");
  24. }
  25. #elif LZHAM_PLATFORM_X360
  26. #define lzham_yield_processor() \
  27. YieldProcessor(); \
  28. __asm { or r0, r0, r0 } \
  29. YieldProcessor(); \
  30. __asm { or r1, r1, r1 } \
  31. YieldProcessor(); \
  32. __asm { or r0, r0, r0 } \
  33. YieldProcessor(); \
  34. __asm { or r1, r1, r1 } \
  35. YieldProcessor(); \
  36. __asm { or r0, r0, r0 } \
  37. YieldProcessor(); \
  38. __asm { or r1, r1, r1 } \
  39. YieldProcessor(); \
  40. __asm { or r0, r0, r0 } \
  41. YieldProcessor(); \
  42. __asm { or r1, r1, r1 }
  43. #else
  44. LZHAM_FORCE_INLINE void lzham_yield_processor()
  45. {
  46. #if LZHAM_USE_MSVC_INTRINSICS
  47. #if LZHAM_PLATFORM_PC_X64
  48. _mm_pause();
  49. #else
  50. YieldProcessor();
  51. #endif
  52. #else
  53. // No implementation
  54. #endif
  55. }
  56. #endif
  57. #ifndef _MSC_VER
  58. int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...);
  59. int vsprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, va_list args);
  60. #endif
  61. #if LZHAM_PLATFORM_X360
  62. #define LZHAM_MEMORY_EXPORT_BARRIER MemoryBarrier();
  63. #else
  64. // Barriers shouldn't be necessary on x86/x64.
  65. // TODO: Should use __sync_synchronize() on other platforms that support GCC.
  66. #define LZHAM_MEMORY_EXPORT_BARRIER
  67. #endif
  68. #if LZHAM_PLATFORM_X360
  69. #define LZHAM_MEMORY_IMPORT_BARRIER MemoryBarrier();
  70. #else
  71. // Barriers shouldn't be necessary on x86/x64.
  72. // TODO: Should use __sync_synchronize() on other platforms that support GCC.
  73. #define LZHAM_MEMORY_IMPORT_BARRIER
  74. #endif
  75. // Note: It's very important that LZHAM_READ_BIG_ENDIAN_UINT32() is fast on the target platform.
  76. // This is used to read every DWORD from the input stream.
  77. #if LZHAM_USE_UNALIGNED_INT_LOADS
  78. #if LZHAM_BIG_ENDIAN_CPU
  79. #define LZHAM_READ_BIG_ENDIAN_UINT32(p) *reinterpret_cast<const uint32*>(p)
  80. #else
  81. #if defined(LZHAM_USE_MSVC_INTRINSICS)
  82. #define LZHAM_READ_BIG_ENDIAN_UINT32(p) _byteswap_ulong(*reinterpret_cast<const uint32*>(p))
  83. #elif defined(__GNUC__)
  84. #define LZHAM_READ_BIG_ENDIAN_UINT32(p) __builtin_bswap32(*reinterpret_cast<const uint32*>(p))
  85. #else
  86. #define LZHAM_READ_BIG_ENDIAN_UINT32(p) utils::swap32(*reinterpret_cast<const uint32*>(p))
  87. #endif
  88. #endif
  89. #else
  90. #define LZHAM_READ_BIG_ENDIAN_UINT32(p) ((reinterpret_cast<const uint8*>(p)[0] << 24) | (reinterpret_cast<const uint8*>(p)[1] << 16) | (reinterpret_cast<const uint8*>(p)[2] << 8) | (reinterpret_cast<const uint8*>(p)[3]))
  91. #endif
  92. #if LZHAM_USE_WIN32_ATOMIC_FUNCTIONS
  93. extern "C" __int64 _InterlockedCompareExchange64(__int64 volatile * Destination, __int64 Exchange, __int64 Comperand);
  94. #if defined(_MSC_VER)
  95. #pragma intrinsic(_InterlockedCompareExchange64)
  96. #endif
  97. #endif // LZHAM_USE_WIN32_ATOMIC_FUNCTIONS
  98. namespace lzham
  99. {
  100. #if LZHAM_USE_WIN32_ATOMIC_FUNCTIONS
  101. typedef LONG atomic32_t;
  102. typedef LONGLONG atomic64_t;
  103. // Returns the original value.
  104. inline atomic32_t atomic_compare_exchange32(atomic32_t volatile *pDest, atomic32_t exchange, atomic32_t comparand)
  105. {
  106. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  107. return InterlockedCompareExchange(pDest, exchange, comparand);
  108. }
  109. // Returns the original value.
  110. inline atomic64_t atomic_compare_exchange64(atomic64_t volatile *pDest, atomic64_t exchange, atomic64_t comparand)
  111. {
  112. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 7) == 0);
  113. return _InterlockedCompareExchange64(pDest, exchange, comparand);
  114. }
  115. // Returns the resulting incremented value.
  116. inline atomic32_t atomic_increment32(atomic32_t volatile *pDest)
  117. {
  118. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  119. return InterlockedIncrement(pDest);
  120. }
  121. // Returns the resulting decremented value.
  122. inline atomic32_t atomic_decrement32(atomic32_t volatile *pDest)
  123. {
  124. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  125. return InterlockedDecrement(pDest);
  126. }
  127. // Returns the original value.
  128. inline atomic32_t atomic_exchange32(atomic32_t volatile *pDest, atomic32_t val)
  129. {
  130. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  131. return InterlockedExchange(pDest, val);
  132. }
  133. // Returns the resulting value.
  134. inline atomic32_t atomic_add32(atomic32_t volatile *pDest, atomic32_t val)
  135. {
  136. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  137. return InterlockedExchangeAdd(pDest, val) + val;
  138. }
  139. // Returns the original value.
  140. inline atomic32_t atomic_exchange_add(atomic32_t volatile *pDest, atomic32_t val)
  141. {
  142. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  143. return InterlockedExchangeAdd(pDest, val);
  144. }
  145. #elif LZHAM_USE_GCC_ATOMIC_BUILTINS
  146. typedef long atomic32_t;
  147. typedef long long atomic64_t;
  148. // Returns the original value.
  149. inline atomic32_t atomic_compare_exchange32(atomic32_t volatile *pDest, atomic32_t exchange, atomic32_t comparand)
  150. {
  151. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  152. return __sync_val_compare_and_swap(pDest, comparand, exchange);
  153. }
  154. // Returns the original value.
  155. inline atomic64_t atomic_compare_exchange64(atomic64_t volatile *pDest, atomic64_t exchange, atomic64_t comparand)
  156. {
  157. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 7) == 0);
  158. return __sync_val_compare_and_swap(pDest, comparand, exchange);
  159. }
  160. // Returns the resulting incremented value.
  161. inline atomic32_t atomic_increment32(atomic32_t volatile *pDest)
  162. {
  163. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  164. return __sync_add_and_fetch(pDest, 1);
  165. }
  166. // Returns the resulting decremented value.
  167. inline atomic32_t atomic_decrement32(atomic32_t volatile *pDest)
  168. {
  169. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  170. return __sync_sub_and_fetch(pDest, 1);
  171. }
  172. // Returns the original value.
  173. inline atomic32_t atomic_exchange32(atomic32_t volatile *pDest, atomic32_t val)
  174. {
  175. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  176. return __sync_lock_test_and_set(pDest, val);
  177. }
  178. // Returns the resulting value.
  179. inline atomic32_t atomic_add32(atomic32_t volatile *pDest, atomic32_t val)
  180. {
  181. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  182. return __sync_add_and_fetch(pDest, val);
  183. }
  184. // Returns the original value.
  185. inline atomic32_t atomic_exchange_add(atomic32_t volatile *pDest, atomic32_t val)
  186. {
  187. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  188. return __sync_fetch_and_add(pDest, val);
  189. }
  190. #else
  191. #define LZHAM_NO_ATOMICS 1
  192. // Atomic ops not supported - but try to do something reasonable. Assumes no threading at all.
  193. typedef long atomic32_t;
  194. typedef long long atomic64_t;
  195. inline atomic32_t atomic_compare_exchange32(atomic32_t volatile *pDest, atomic32_t exchange, atomic32_t comparand)
  196. {
  197. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  198. atomic32_t cur = *pDest;
  199. if (cur == comparand)
  200. *pDest = exchange;
  201. return cur;
  202. }
  203. inline atomic64_t atomic_compare_exchange64(atomic64_t volatile *pDest, atomic64_t exchange, atomic64_t comparand)
  204. {
  205. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 7) == 0);
  206. atomic64_t cur = *pDest;
  207. if (cur == comparand)
  208. *pDest = exchange;
  209. return cur;
  210. }
  211. inline atomic32_t atomic_increment32(atomic32_t volatile *pDest)
  212. {
  213. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  214. return (*pDest += 1);
  215. }
  216. inline atomic32_t atomic_decrement32(atomic32_t volatile *pDest)
  217. {
  218. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  219. return (*pDest -= 1);
  220. }
  221. inline atomic32_t atomic_exchange32(atomic32_t volatile *pDest, atomic32_t val)
  222. {
  223. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  224. atomic32_t cur = *pDest;
  225. *pDest = val;
  226. return cur;
  227. }
  228. inline atomic32_t atomic_add32(atomic32_t volatile *pDest, atomic32_t val)
  229. {
  230. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  231. return (*pDest += val);
  232. }
  233. inline atomic32_t atomic_exchange_add(atomic32_t volatile *pDest, atomic32_t val)
  234. {
  235. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
  236. atomic32_t cur = *pDest;
  237. *pDest += val;
  238. return cur;
  239. }
  240. #endif
  241. #if LZHAM_BUFFERED_PRINTF
  242. void lzham_buffered_printf(const char *format, ...);
  243. void lzham_flush_buffered_printf();
  244. #else
  245. inline void lzham_buffered_printf(const char *format, ...) { (void)format; }
  246. inline void lzham_flush_buffered_printf() { }
  247. #endif
  248. } // namespace lzham