CpuArch.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /* CpuArch.h -- CPU specific code
  2. 2016-06-09: Igor Pavlov : Public domain */
  3. #ifndef __CPU_ARCH_H
  4. #define __CPU_ARCH_H
  5. #include "7zTypes.h"
  6. EXTERN_C_BEGIN
  7. /*
  8. MY_CPU_LE means that CPU is LITTLE ENDIAN.
  9. MY_CPU_BE means that CPU is BIG ENDIAN.
  10. If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform.
  11. MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
  12. */
  13. #if defined(_M_X64) \
  14. || defined(_M_AMD64) \
  15. || defined(__x86_64__) \
  16. || defined(__AMD64__) \
  17. || defined(__amd64__)
  18. #define MY_CPU_AMD64
  19. #endif
  20. #if defined(MY_CPU_AMD64) \
  21. || defined(_M_IA64) \
  22. || defined(__AARCH64EL__) \
  23. || defined(__AARCH64EB__)
  24. #define MY_CPU_64BIT
  25. #endif
  26. #if defined(_M_IX86) || defined(__i386__)
  27. #define MY_CPU_X86
  28. #endif
  29. #if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
  30. #define MY_CPU_X86_OR_AMD64
  31. #endif
  32. #if defined(MY_CPU_X86) \
  33. || defined(_M_ARM) \
  34. || defined(__ARMEL__) \
  35. || defined(__THUMBEL__) \
  36. || defined(__ARMEB__) \
  37. || defined(__THUMBEB__)
  38. #define MY_CPU_32BIT
  39. #endif
  40. #if defined(_WIN32) && defined(_M_ARM)
  41. #define MY_CPU_ARM_LE
  42. #endif
  43. #if defined(_WIN32) && defined(_M_IA64)
  44. #define MY_CPU_IA64_LE
  45. #endif
  46. #if defined(MY_CPU_X86_OR_AMD64) \
  47. || defined(MY_CPU_ARM_LE) \
  48. || defined(MY_CPU_IA64_LE) \
  49. || defined(__LITTLE_ENDIAN__) \
  50. || defined(__ARMEL__) \
  51. || defined(__THUMBEL__) \
  52. || defined(__AARCH64EL__) \
  53. || defined(__MIPSEL__) \
  54. || defined(__MIPSEL) \
  55. || defined(_MIPSEL) \
  56. || defined(__BFIN__) \
  57. || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
  58. #define MY_CPU_LE
  59. #endif
  60. #if defined(__BIG_ENDIAN__) \
  61. || defined(__ARMEB__) \
  62. || defined(__THUMBEB__) \
  63. || defined(__AARCH64EB__) \
  64. || defined(__MIPSEB__) \
  65. || defined(__MIPSEB) \
  66. || defined(_MIPSEB) \
  67. || defined(__m68k__) \
  68. || defined(__s390__) \
  69. || defined(__s390x__) \
  70. || defined(__zarch__) \
  71. || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
  72. #define MY_CPU_BE
  73. #endif
  74. #if defined(MY_CPU_LE) && defined(MY_CPU_BE)
  75. Stop_Compiling_Bad_Endian
  76. #endif
  77. #ifdef MY_CPU_LE
  78. #if defined(MY_CPU_X86_OR_AMD64) \
  79. /* || defined(__AARCH64EL__) */
  80. #define MY_CPU_LE_UNALIGN
  81. #endif
  82. #endif
  83. #ifdef MY_CPU_LE_UNALIGN
  84. #define GetUi16(p) (*(const UInt16 *)(const void *)(p))
  85. #define GetUi32(p) (*(const UInt32 *)(const void *)(p))
  86. #define GetUi64(p) (*(const UInt64 *)(const void *)(p))
  87. #define SetUi16(p, v) { *(UInt16 *)(p) = (v); }
  88. #define SetUi32(p, v) { *(UInt32 *)(p) = (v); }
  89. #define SetUi64(p, v) { *(UInt64 *)(p) = (v); }
  90. #else
  91. #define GetUi16(p) ( (UInt16) ( \
  92. ((const Byte *)(p))[0] | \
  93. ((UInt16)((const Byte *)(p))[1] << 8) ))
  94. #define GetUi32(p) ( \
  95. ((const Byte *)(p))[0] | \
  96. ((UInt32)((const Byte *)(p))[1] << 8) | \
  97. ((UInt32)((const Byte *)(p))[2] << 16) | \
  98. ((UInt32)((const Byte *)(p))[3] << 24))
  99. #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
  100. #define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
  101. _ppp_[0] = (Byte)_vvv_; \
  102. _ppp_[1] = (Byte)(_vvv_ >> 8); }
  103. #define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
  104. _ppp_[0] = (Byte)_vvv_; \
  105. _ppp_[1] = (Byte)(_vvv_ >> 8); \
  106. _ppp_[2] = (Byte)(_vvv_ >> 16); \
  107. _ppp_[3] = (Byte)(_vvv_ >> 24); }
  108. #define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \
  109. SetUi32(_ppp2_ , (UInt32)_vvv2_); \
  110. SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); }
  111. #endif
  112. #if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300)
  113. /* Note: we use bswap instruction, that is unsupported in 386 cpu */
  114. #include <stdlib.h>
  115. #pragma intrinsic(_byteswap_ulong)
  116. #pragma intrinsic(_byteswap_uint64)
  117. #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
  118. #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
  119. #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v)
  120. #elif defined(MY_CPU_LE_UNALIGN) && defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
  121. #define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p))
  122. #define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p))
  123. #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v)
  124. #else
  125. #define GetBe32(p) ( \
  126. ((UInt32)((const Byte *)(p))[0] << 24) | \
  127. ((UInt32)((const Byte *)(p))[1] << 16) | \
  128. ((UInt32)((const Byte *)(p))[2] << 8) | \
  129. ((const Byte *)(p))[3] )
  130. #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
  131. #define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
  132. _ppp_[0] = (Byte)(_vvv_ >> 24); \
  133. _ppp_[1] = (Byte)(_vvv_ >> 16); \
  134. _ppp_[2] = (Byte)(_vvv_ >> 8); \
  135. _ppp_[3] = (Byte)_vvv_; }
  136. #endif
  137. #define GetBe16(p) ( (UInt16) ( \
  138. ((UInt16)((const Byte *)(p))[0] << 8) | \
  139. ((const Byte *)(p))[1] ))
  140. #ifdef MY_CPU_X86_OR_AMD64
  141. typedef struct
  142. {
  143. UInt32 maxFunc;
  144. UInt32 vendor[3];
  145. UInt32 ver;
  146. UInt32 b;
  147. UInt32 c;
  148. UInt32 d;
  149. } Cx86cpuid;
  150. enum
  151. {
  152. CPU_FIRM_INTEL,
  153. CPU_FIRM_AMD,
  154. CPU_FIRM_VIA
  155. };
  156. void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);
  157. Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
  158. int x86cpuid_GetFirm(const Cx86cpuid *p);
  159. #define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))
  160. #define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
  161. #define x86cpuid_GetStepping(ver) (ver & 0xF)
  162. Bool CPU_Is_InOrder();
  163. Bool CPU_Is_Aes_Supported();
  164. #endif
  165. EXTERN_C_END
  166. #endif