1 /* CpuArch.h -- CPU specific code 2 2018-07-04 : Igor Pavlov : Public domain */ 3 4 #ifndef __CPU_ARCH_H 5 #define __CPU_ARCH_H 6 7 #include "7zTypes.h" 8 9 EXTERN_C_BEGIN 10 11 /* 12 MY_CPU_LE means that CPU is LITTLE ENDIAN. 13 MY_CPU_BE means that CPU is BIG ENDIAN. 14 If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform. 15 16 MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. 17 */ 18 19 #if defined(_M_X64) \ 20 || defined(_M_AMD64) \ 21 || defined(__x86_64__) \ 22 || defined(__AMD64__) \ 23 || defined(__amd64__) 24 #define MY_CPU_AMD64 25 #ifdef __ILP32__ 26 #define MY_CPU_NAME "x32" 27 #else 28 #define MY_CPU_NAME "x64" 29 #endif 30 #define MY_CPU_64BIT 31 #endif 32 33 34 #if defined(_M_IX86) \ 35 || defined(__i386__) 36 #define MY_CPU_X86 37 #define MY_CPU_NAME "x86" 38 #define MY_CPU_32BIT 39 #endif 40 41 42 #if defined(_M_ARM64) \ 43 || defined(__AARCH64EL__) \ 44 || defined(__AARCH64EB__) \ 45 || defined(__aarch64__) 46 #define MY_CPU_ARM64 47 #define MY_CPU_NAME "arm64" 48 #define MY_CPU_64BIT 49 #endif 50 51 52 #if defined(_M_ARM) \ 53 || defined(_M_ARM_NT) \ 54 || defined(_M_ARMT) \ 55 || defined(__arm__) \ 56 || defined(__thumb__) \ 57 || defined(__ARMEL__) \ 58 || defined(__ARMEB__) \ 59 || defined(__THUMBEL__) \ 60 || defined(__THUMBEB__) 61 #define MY_CPU_ARM 62 #define MY_CPU_NAME "arm" 63 #define MY_CPU_32BIT 64 #endif 65 66 67 #if defined(_M_IA64) \ 68 || defined(__ia64__) 69 #define MY_CPU_IA64 70 #define MY_CPU_NAME "ia64" 71 #define MY_CPU_64BIT 72 #endif 73 74 75 #if defined(__mips64) \ 76 || defined(__mips64__) \ 77 || (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3)) 78 #define MY_CPU_NAME "mips64" 79 #define MY_CPU_64BIT 80 #elif defined(__mips__) 81 #define MY_CPU_NAME "mips" 82 /* #define MY_CPU_32BIT */ 83 #endif 84 85 86 #if defined(__ppc64__) \ 87 || defined(__powerpc64__) 88 #ifdef __ILP32__ 89 #define MY_CPU_NAME "ppc64-32" 90 #else 91 #define MY_CPU_NAME "ppc64" 92 #endif 93 #define MY_CPU_64BIT 94 #elif defined(__ppc__) \ 95 || defined(__powerpc__) 96 #define MY_CPU_NAME "ppc" 97 #define MY_CPU_32BIT 98 #endif 99 100 101 #if defined(__sparc64__) 102 #define MY_CPU_NAME "sparc64" 103 #define MY_CPU_64BIT 104 #elif defined(__sparc__) 105 #define MY_CPU_NAME "sparc" 106 /* #define MY_CPU_32BIT */ 107 #endif 108 109 110 #if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) 111 #define MY_CPU_X86_OR_AMD64 112 #endif 113 114 115 #ifdef _WIN32 116 117 #ifdef MY_CPU_ARM 118 #define MY_CPU_ARM_LE 119 #endif 120 121 #ifdef MY_CPU_ARM64 122 #define MY_CPU_ARM64_LE 123 #endif 124 125 #ifdef _M_IA64 126 #define MY_CPU_IA64_LE 127 #endif 128 129 #endif 130 131 132 #if defined(MY_CPU_X86_OR_AMD64) \ 133 || defined(MY_CPU_ARM_LE) \ 134 || defined(MY_CPU_ARM64_LE) \ 135 || defined(MY_CPU_IA64_LE) \ 136 || defined(__LITTLE_ENDIAN__) \ 137 || defined(__ARMEL__) \ 138 || defined(__THUMBEL__) \ 139 || defined(__AARCH64EL__) \ 140 || defined(__MIPSEL__) \ 141 || defined(__MIPSEL) \ 142 || defined(_MIPSEL) \ 143 || defined(__BFIN__) \ 144 || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) 145 #define MY_CPU_LE 146 #endif 147 148 #if defined(__BIG_ENDIAN__) \ 149 || defined(__ARMEB__) \ 150 || defined(__THUMBEB__) \ 151 || defined(__AARCH64EB__) \ 152 || defined(__MIPSEB__) \ 153 || defined(__MIPSEB) \ 154 || defined(_MIPSEB) \ 155 || defined(__m68k__) \ 156 || defined(__s390__) \ 157 || defined(__s390x__) \ 158 || defined(__zarch__) \ 159 || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) 160 #define MY_CPU_BE 161 #endif 162 163 164 #if defined(MY_CPU_LE) && defined(MY_CPU_BE) 165 #error Stop_Compiling_Bad_Endian 166 #endif 167 168 169 #if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT) 170 #error Stop_Compiling_Bad_32_64_BIT 171 #endif 172 173 174 #ifndef MY_CPU_NAME 175 #ifdef MY_CPU_LE 176 #define MY_CPU_NAME "LE" 177 #elif defined(MY_CPU_BE) 178 #define MY_CPU_NAME "BE" 179 #else 180 /* 181 #define MY_CPU_NAME "" 182 */ 183 #endif 184 #endif 185 186 187 188 189 190 #ifdef MY_CPU_LE 191 #if defined(MY_CPU_X86_OR_AMD64) \ 192 || defined(MY_CPU_ARM64) \ 193 || defined(__ARM_FEATURE_UNALIGNED) 194 #define MY_CPU_LE_UNALIGN 195 #endif 196 #endif 197 198 199 #ifdef MY_CPU_LE_UNALIGN 200 201 #define GetUi16(p) (*(const UInt16 *)(const void *)(p)) 202 #define GetUi32(p) (*(const UInt32 *)(const void *)(p)) 203 #define GetUi64(p) (*(const UInt64 *)(const void *)(p)) 204 205 #define SetUi16(p, v) { *(UInt16 *)(p) = (v); } 206 #define SetUi32(p, v) { *(UInt32 *)(p) = (v); } 207 #define SetUi64(p, v) { *(UInt64 *)(p) = (v); } 208 209 #else 210 211 #define GetUi16(p) ( (UInt16) ( \ 212 ((const Byte *)(p))[0] | \ 213 ((UInt16)((const Byte *)(p))[1] << 8) )) 214 215 #define GetUi32(p) ( \ 216 ((const Byte *)(p))[0] | \ 217 ((UInt32)((const Byte *)(p))[1] << 8) | \ 218 ((UInt32)((const Byte *)(p))[2] << 16) | \ 219 ((UInt32)((const Byte *)(p))[3] << 24)) 220 221 #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) 222 223 #define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ 224 _ppp_[0] = (Byte)_vvv_; \ 225 _ppp_[1] = (Byte)(_vvv_ >> 8); } 226 227 #define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ 228 _ppp_[0] = (Byte)_vvv_; \ 229 _ppp_[1] = (Byte)(_vvv_ >> 8); \ 230 _ppp_[2] = (Byte)(_vvv_ >> 16); \ 231 _ppp_[3] = (Byte)(_vvv_ >> 24); } 232 233 #define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \ 234 SetUi32(_ppp2_ , (UInt32)_vvv2_); \ 235 SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); } 236 237 #endif 238 239 #ifdef __has_builtin 240 #define MY__has_builtin(x) __has_builtin(x) 241 #else 242 #define MY__has_builtin(x) 0 243 #endif 244 245 #if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300) 246 247 /* Note: we use bswap instruction, that is unsupported in 386 cpu */ 248 249 #include <stdlib.h> 250 251 #pragma intrinsic(_byteswap_ushort) 252 #pragma intrinsic(_byteswap_ulong) 253 #pragma intrinsic(_byteswap_uint64) 254 255 /* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */ 256 #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) 257 #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) 258 259 #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v) 260 261 #elif defined(MY_CPU_LE_UNALIGN) && ( \ 262 (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ 263 || (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) ) 264 265 /* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const Byte *)(p)) */ 266 #define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p)) 267 #define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p)) 268 269 #define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v) 270 271 #else 272 273 #define GetBe32(p) ( \ 274 ((UInt32)((const Byte *)(p))[0] << 24) | \ 275 ((UInt32)((const Byte *)(p))[1] << 16) | \ 276 ((UInt32)((const Byte *)(p))[2] << 8) | \ 277 ((const Byte *)(p))[3] ) 278 279 #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) 280 281 #define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ 282 _ppp_[0] = (Byte)(_vvv_ >> 24); \ 283 _ppp_[1] = (Byte)(_vvv_ >> 16); \ 284 _ppp_[2] = (Byte)(_vvv_ >> 8); \ 285 _ppp_[3] = (Byte)_vvv_; } 286 287 #endif 288 289 290 #ifndef GetBe16 291 292 #define GetBe16(p) ( (UInt16) ( \ 293 ((UInt16)((const Byte *)(p))[0] << 8) | \ 294 ((const Byte *)(p))[1] )) 295 296 #endif 297 298 299 300 #ifdef MY_CPU_X86_OR_AMD64 301 302 typedef struct 303 { 304 UInt32 maxFunc; 305 UInt32 vendor[3]; 306 UInt32 ver; 307 UInt32 b; 308 UInt32 c; 309 UInt32 d; 310 } Cx86cpuid; 311 312 enum 313 { 314 CPU_FIRM_INTEL, 315 CPU_FIRM_AMD, 316 CPU_FIRM_VIA 317 }; 318 319 void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d); 320 321 BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p); 322 int x86cpuid_GetFirm(const Cx86cpuid *p); 323 324 #define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF)) 325 #define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF)) 326 #define x86cpuid_GetStepping(ver) (ver & 0xF) 327 328 BoolInt CPU_Is_InOrder(); 329 BoolInt CPU_Is_Aes_Supported(); 330 331 #endif 332 333 EXTERN_C_END 334 335 #endif 336