CpuArch.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /* CpuArch.h -- CPU specific code
  2. 2015-12-01: 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(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
  57. #define MY_CPU_LE
  58. #endif
  59. #if defined(__BIG_ENDIAN__) \
  60. || defined(__ARMEB__) \
  61. || defined(__THUMBEB__) \
  62. || defined(__AARCH64EB__) \
  63. || defined(__MIPSEB__) \
  64. || defined(__MIPSEB) \
  65. || defined(_MIPSEB) \
  66. || defined(__m68k__) \
  67. || defined(__s390__) \
  68. || defined(__s390x__) \
  69. || defined(__zarch__) \
  70. || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
  71. #define MY_CPU_BE
  72. #endif
  73. #if defined(MY_CPU_LE) && defined(MY_CPU_BE)
  74. Stop_Compiling_Bad_Endian
  75. #endif
  76. #ifdef MY_CPU_LE
  77. #if defined(MY_CPU_X86_OR_AMD64) \
  78. /* || defined(__AARCH64EL__) */
  79. #define MY_CPU_LE_UNALIGN
  80. #endif
  81. #endif
  82. #ifdef MY_CPU_LE_UNALIGN
  83. #define GetUi16(p) (*(const UInt16 *)(const void *)(p))
  84. #define GetUi32(p) (*(const UInt32 *)(const void *)(p))
  85. #define GetUi64(p) (*(const UInt64 *)(const void *)(p))
  86. #define SetUi16(p, v) { *(UInt16 *)(p) = (v); }
  87. #define SetUi32(p, v) { *(UInt32 *)(p) = (v); }
  88. #define SetUi64(p, v) { *(UInt64 *)(p) = (v); }
  89. #else
  90. #define GetUi16(p) ( (UInt16) ( \
  91. ((const Byte *)(p))[0] | \
  92. ((UInt16)((const Byte *)(p))[1] << 8) ))
  93. #define GetUi32(p) ( \
  94. ((const Byte *)(p))[0] | \
  95. ((UInt32)((const Byte *)(p))[1] << 8) | \
  96. ((UInt32)((const Byte *)(p))[2] << 16) | \
  97. ((UInt32)((const Byte *)(p))[3] << 24))
  98. #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
  99. #define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
  100. _ppp_[0] = (Byte)_vvv_; \
  101. _ppp_[1] = (Byte)(_vvv_ >> 8); }
  102. #define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
  103. _ppp_[0] = (Byte)_vvv_; \
  104. _ppp_[1] = (Byte)(_vvv_ >> 8); \
  105. _ppp_[2] = (Byte)(_vvv_ >> 16); \
  106. _ppp_[3] = (Byte)(_vvv_ >> 24); }
  107. #define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \
  108. SetUi32(_ppp2_ , (UInt32)_vvv2_); \
  109. SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); }
  110. #endif
  111. #if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300)
  112. /* Note: we use bswap instruction, that is unsupported in 386 cpu */
  113. #include <stdlib.h>
  114. #pragma intrinsic(_byteswap_ulong)
  115. #pragma intrinsic(_byteswap_uint64)
  116. #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
  117. #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
  118. #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v)
  119. #elif defined(MY_CPU_LE_UNALIGN) && defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
  120. #define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p))
  121. #define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p))
  122. #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v)
  123. #else
  124. #define GetBe32(p) ( \
  125. ((UInt32)((const Byte *)(p))[0] << 24) | \
  126. ((UInt32)((const Byte *)(p))[1] << 16) | \
  127. ((UInt32)((const Byte *)(p))[2] << 8) | \
  128. ((const Byte *)(p))[3] )
  129. #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
  130. #define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
  131. _ppp_[0] = (Byte)(_vvv_ >> 24); \
  132. _ppp_[1] = (Byte)(_vvv_ >> 16); \
  133. _ppp_[2] = (Byte)(_vvv_ >> 8); \
  134. _ppp_[3] = (Byte)_vvv_; }
  135. #endif
  136. #define GetBe16(p) ( (UInt16) ( \
  137. ((UInt16)((const Byte *)(p))[0] << 8) | \
  138. ((const Byte *)(p))[1] ))
  139. #ifdef MY_CPU_X86_OR_AMD64
  140. typedef struct
  141. {
  142. UInt32 maxFunc;
  143. UInt32 vendor[3];
  144. UInt32 ver;
  145. UInt32 b;
  146. UInt32 c;
  147. UInt32 d;
  148. } Cx86cpuid;
  149. enum
  150. {
  151. CPU_FIRM_INTEL,
  152. CPU_FIRM_AMD,
  153. CPU_FIRM_VIA
  154. };
  155. void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);
  156. Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
  157. int x86cpuid_GetFirm(const Cx86cpuid *p);
  158. #define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))
  159. #define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
  160. #define x86cpuid_GetStepping(ver) (ver & 0xF)
  161. Bool CPU_Is_InOrder();
  162. Bool CPU_Is_Aes_Supported();
  163. #endif
  164. EXTERN_C_END
  165. #endif