1 /* CpuArch.h -- CPU specific code 2 2023-04-02 : Igor Pavlov : Public domain */ 3 4 #ifndef ZIP7_INC_CPU_ARCH_H 5 #define ZIP7_INC_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 MY_CPU_64BIT means that processor can work with 64-bit registers. 19 MY_CPU_64BIT can be used to select fast code branch 20 MY_CPU_64BIT doesn't mean that (sizeof(void *) == 8) 21 */ 22 23 #if defined(_M_X64) \ 24 || defined(_M_AMD64) \ 25 || defined(__x86_64__) \ 26 || defined(__AMD64__) \ 27 || defined(__amd64__) 28 #define MY_CPU_AMD64 29 #ifdef __ILP32__ 30 #define MY_CPU_NAME "x32" 31 #define MY_CPU_SIZEOF_POINTER 4 32 #else 33 #define MY_CPU_NAME "x64" 34 #define MY_CPU_SIZEOF_POINTER 8 35 #endif 36 #define MY_CPU_64BIT 37 #endif 38 39 40 #if defined(_M_IX86) \ 41 || defined(__i386__) 42 #define MY_CPU_X86 43 #define MY_CPU_NAME "x86" 44 /* #define MY_CPU_32BIT */ 45 #define MY_CPU_SIZEOF_POINTER 4 46 #endif 47 48 49 #if defined(_M_ARM64) \ 50 || defined(__AARCH64EL__) \ 51 || defined(__AARCH64EB__) \ 52 || defined(__aarch64__) 53 #define MY_CPU_ARM64 54 #ifdef __ILP32__ 55 #define MY_CPU_NAME "arm64-32" 56 #define MY_CPU_SIZEOF_POINTER 4 57 #else 58 #define MY_CPU_NAME "arm64" 59 #define MY_CPU_SIZEOF_POINTER 8 60 #endif 61 #define MY_CPU_64BIT 62 #endif 63 64 65 #if defined(_M_ARM) \ 66 || defined(_M_ARM_NT) \ 67 || defined(_M_ARMT) \ 68 || defined(__arm__) \ 69 || defined(__thumb__) \ 70 || defined(__ARMEL__) \ 71 || defined(__ARMEB__) \ 72 || defined(__THUMBEL__) \ 73 || defined(__THUMBEB__) 74 #define MY_CPU_ARM 75 76 #if defined(__thumb__) || defined(__THUMBEL__) || defined(_M_ARMT) 77 #define MY_CPU_ARMT 78 #define MY_CPU_NAME "armt" 79 #else 80 #define MY_CPU_ARM32 81 #define MY_CPU_NAME "arm" 82 #endif 83 /* #define MY_CPU_32BIT */ 84 #define MY_CPU_SIZEOF_POINTER 4 85 #endif 86 87 88 #if defined(_M_IA64) \ 89 || defined(__ia64__) 90 #define MY_CPU_IA64 91 #define MY_CPU_NAME "ia64" 92 #define MY_CPU_64BIT 93 #endif 94 95 96 #if defined(__mips64) \ 97 || defined(__mips64__) \ 98 || (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3)) 99 #define MY_CPU_NAME "mips64" 100 #define MY_CPU_64BIT 101 #elif defined(__mips__) 102 #define MY_CPU_NAME "mips" 103 /* #define MY_CPU_32BIT */ 104 #endif 105 106 107 #if defined(__ppc64__) \ 108 || defined(__powerpc64__) \ 109 || defined(__ppc__) \ 110 || defined(__powerpc__) \ 111 || defined(__PPC__) \ 112 || defined(_POWER) 113 114 #define MY_CPU_PPC_OR_PPC64 115 116 #if defined(__ppc64__) \ 117 || defined(__powerpc64__) \ 118 || defined(_LP64) \ 119 || defined(__64BIT__) 120 #ifdef __ILP32__ 121 #define MY_CPU_NAME "ppc64-32" 122 #define MY_CPU_SIZEOF_POINTER 4 123 #else 124 #define MY_CPU_NAME "ppc64" 125 #define MY_CPU_SIZEOF_POINTER 8 126 #endif 127 #define MY_CPU_64BIT 128 #else 129 #define MY_CPU_NAME "ppc" 130 #define MY_CPU_SIZEOF_POINTER 4 131 /* #define MY_CPU_32BIT */ 132 #endif 133 #endif 134 135 136 #if defined(__riscv) \ 137 || defined(__riscv__) 138 #if __riscv_xlen == 32 139 #define MY_CPU_NAME "riscv32" 140 #elif __riscv_xlen == 64 141 #define MY_CPU_NAME "riscv64" 142 #else 143 #define MY_CPU_NAME "riscv" 144 #endif 145 #endif 146 147 148 #if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) 149 #define MY_CPU_X86_OR_AMD64 150 #endif 151 152 #if defined(MY_CPU_ARM) || defined(MY_CPU_ARM64) 153 #define MY_CPU_ARM_OR_ARM64 154 #endif 155 156 157 #ifdef _WIN32 158 159 #ifdef MY_CPU_ARM 160 #define MY_CPU_ARM_LE 161 #endif 162 163 #ifdef MY_CPU_ARM64 164 #define MY_CPU_ARM64_LE 165 #endif 166 167 #ifdef _M_IA64 168 #define MY_CPU_IA64_LE 169 #endif 170 171 #endif 172 173 174 #if defined(MY_CPU_X86_OR_AMD64) \ 175 || defined(MY_CPU_ARM_LE) \ 176 || defined(MY_CPU_ARM64_LE) \ 177 || defined(MY_CPU_IA64_LE) \ 178 || defined(__LITTLE_ENDIAN__) \ 179 || defined(__ARMEL__) \ 180 || defined(__THUMBEL__) \ 181 || defined(__AARCH64EL__) \ 182 || defined(__MIPSEL__) \ 183 || defined(__MIPSEL) \ 184 || defined(_MIPSEL) \ 185 || defined(__BFIN__) \ 186 || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) 187 #define MY_CPU_LE 188 #endif 189 190 #if defined(__BIG_ENDIAN__) \ 191 || defined(__ARMEB__) \ 192 || defined(__THUMBEB__) \ 193 || defined(__AARCH64EB__) \ 194 || defined(__MIPSEB__) \ 195 || defined(__MIPSEB) \ 196 || defined(_MIPSEB) \ 197 || defined(__m68k__) \ 198 || defined(__s390__) \ 199 || defined(__s390x__) \ 200 || defined(__zarch__) \ 201 || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) 202 #define MY_CPU_BE 203 #endif 204 205 206 #if defined(MY_CPU_LE) && defined(MY_CPU_BE) 207 #error Stop_Compiling_Bad_Endian 208 #endif 209 210 #if !defined(MY_CPU_LE) && !defined(MY_CPU_BE) 211 #error Stop_Compiling_CPU_ENDIAN_must_be_detected_at_compile_time 212 #endif 213 214 #if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT) 215 #error Stop_Compiling_Bad_32_64_BIT 216 #endif 217 218 #ifdef __SIZEOF_POINTER__ 219 #ifdef MY_CPU_SIZEOF_POINTER 220 #if MY_CPU_SIZEOF_POINTER != __SIZEOF_POINTER__ 221 #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE 222 #endif 223 #else 224 #define MY_CPU_SIZEOF_POINTER __SIZEOF_POINTER__ 225 #endif 226 #endif 227 228 #if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4) 229 #if defined (_LP64) 230 #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE 231 #endif 232 #endif 233 234 #ifdef _MSC_VER 235 #if _MSC_VER >= 1300 236 #define MY_CPU_pragma_pack_push_1 __pragma(pack(push, 1)) 237 #define MY_CPU_pragma_pop __pragma(pack(pop)) 238 #else 239 #define MY_CPU_pragma_pack_push_1 240 #define MY_CPU_pragma_pop 241 #endif 242 #else 243 #ifdef __xlC__ 244 #define MY_CPU_pragma_pack_push_1 _Pragma("pack(1)") 245 #define MY_CPU_pragma_pop _Pragma("pack()") 246 #else 247 #define MY_CPU_pragma_pack_push_1 _Pragma("pack(push, 1)") 248 #define MY_CPU_pragma_pop _Pragma("pack(pop)") 249 #endif 250 #endif 251 252 253 #ifndef MY_CPU_NAME 254 #ifdef MY_CPU_LE 255 #define MY_CPU_NAME "LE" 256 #elif defined(MY_CPU_BE) 257 #define MY_CPU_NAME "BE" 258 #else 259 /* 260 #define MY_CPU_NAME "" 261 */ 262 #endif 263 #endif 264 265 266 267 268 269 #ifdef __has_builtin 270 #define Z7_has_builtin(x) __has_builtin(x) 271 #else 272 #define Z7_has_builtin(x) 0 273 #endif 274 275 276 #define Z7_BSWAP32_CONST(v) \ 277 ( (((UInt32)(v) << 24) ) \ 278 | (((UInt32)(v) << 8) & (UInt32)0xff0000) \ 279 | (((UInt32)(v) >> 8) & (UInt32)0xff00 ) \ 280 | (((UInt32)(v) >> 24) )) 281 282 283 #if defined(_MSC_VER) && (_MSC_VER >= 1300) 284 285 #include <stdlib.h> 286 287 /* Note: these macros will use bswap instruction (486), that is unsupported in 386 cpu */ 288 289 #pragma intrinsic(_byteswap_ushort) 290 #pragma intrinsic(_byteswap_ulong) 291 #pragma intrinsic(_byteswap_uint64) 292 293 #define Z7_BSWAP16(v) _byteswap_ushort(v) 294 #define Z7_BSWAP32(v) _byteswap_ulong (v) 295 #define Z7_BSWAP64(v) _byteswap_uint64(v) 296 #define Z7_CPU_FAST_BSWAP_SUPPORTED 297 298 #elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ 299 || (defined(__clang__) && Z7_has_builtin(__builtin_bswap16)) 300 301 #define Z7_BSWAP16(v) __builtin_bswap16(v) 302 #define Z7_BSWAP32(v) __builtin_bswap32(v) 303 #define Z7_BSWAP64(v) __builtin_bswap64(v) 304 #define Z7_CPU_FAST_BSWAP_SUPPORTED 305 306 #else 307 308 #define Z7_BSWAP16(v) ((UInt16) \ 309 ( ((UInt32)(v) << 8) \ 310 | ((UInt32)(v) >> 8) \ 311 )) 312 313 #define Z7_BSWAP32(v) Z7_BSWAP32_CONST(v) 314 315 #define Z7_BSWAP64(v) \ 316 ( ( ( (UInt64)(v) ) << 8 * 7 ) \ 317 | ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 1) ) << 8 * 5 ) \ 318 | ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 2) ) << 8 * 3 ) \ 319 | ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 3) ) << 8 * 1 ) \ 320 | ( ( (UInt64)(v) >> 8 * 1 ) & ((UInt32)0xff << 8 * 3) ) \ 321 | ( ( (UInt64)(v) >> 8 * 3 ) & ((UInt32)0xff << 8 * 2) ) \ 322 | ( ( (UInt64)(v) >> 8 * 5 ) & ((UInt32)0xff << 8 * 1) ) \ 323 | ( ( (UInt64)(v) >> 8 * 7 ) ) \ 324 ) 325 326 #endif 327 328 329 330 #ifdef MY_CPU_LE 331 #if defined(MY_CPU_X86_OR_AMD64) \ 332 || defined(MY_CPU_ARM64) 333 #define MY_CPU_LE_UNALIGN 334 #define MY_CPU_LE_UNALIGN_64 335 #elif defined(__ARM_FEATURE_UNALIGNED) 336 /* gcc9 for 32-bit arm can use LDRD instruction that requires 32-bit alignment. 337 So we can't use unaligned 64-bit operations. */ 338 #define MY_CPU_LE_UNALIGN 339 #endif 340 #endif 341 342 343 #ifdef MY_CPU_LE_UNALIGN 344 345 #define GetUi16(p) (*(const UInt16 *)(const void *)(p)) 346 #define GetUi32(p) (*(const UInt32 *)(const void *)(p)) 347 #ifdef MY_CPU_LE_UNALIGN_64 348 #define GetUi64(p) (*(const UInt64 *)(const void *)(p)) 349 #define SetUi64(p, v) { *(UInt64 *)(void *)(p) = (v); } 350 #endif 351 352 #define SetUi16(p, v) { *(UInt16 *)(void *)(p) = (v); } 353 #define SetUi32(p, v) { *(UInt32 *)(void *)(p) = (v); } 354 355 #else 356 357 #define GetUi16(p) ( (UInt16) ( \ 358 ((const Byte *)(p))[0] | \ 359 ((UInt16)((const Byte *)(p))[1] << 8) )) 360 361 #define GetUi32(p) ( \ 362 ((const Byte *)(p))[0] | \ 363 ((UInt32)((const Byte *)(p))[1] << 8) | \ 364 ((UInt32)((const Byte *)(p))[2] << 16) | \ 365 ((UInt32)((const Byte *)(p))[3] << 24)) 366 367 #define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ 368 _ppp_[0] = (Byte)_vvv_; \ 369 _ppp_[1] = (Byte)(_vvv_ >> 8); } 370 371 #define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ 372 _ppp_[0] = (Byte)_vvv_; \ 373 _ppp_[1] = (Byte)(_vvv_ >> 8); \ 374 _ppp_[2] = (Byte)(_vvv_ >> 16); \ 375 _ppp_[3] = (Byte)(_vvv_ >> 24); } 376 377 #endif 378 379 380 #ifndef GetUi64 381 #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) 382 #endif 383 384 #ifndef SetUi64 385 #define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \ 386 SetUi32(_ppp2_ , (UInt32)_vvv2_) \ 387 SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)) } 388 #endif 389 390 391 #if defined(MY_CPU_LE_UNALIGN) && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) 392 393 #define GetBe32(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p)) 394 #define SetBe32(p, v) { (*(UInt32 *)(void *)(p)) = Z7_BSWAP32(v); } 395 396 #if defined(MY_CPU_LE_UNALIGN_64) 397 #define GetBe64(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p)) 398 #endif 399 400 #else 401 402 #define GetBe32(p) ( \ 403 ((UInt32)((const Byte *)(p))[0] << 24) | \ 404 ((UInt32)((const Byte *)(p))[1] << 16) | \ 405 ((UInt32)((const Byte *)(p))[2] << 8) | \ 406 ((const Byte *)(p))[3] ) 407 408 #define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ 409 _ppp_[0] = (Byte)(_vvv_ >> 24); \ 410 _ppp_[1] = (Byte)(_vvv_ >> 16); \ 411 _ppp_[2] = (Byte)(_vvv_ >> 8); \ 412 _ppp_[3] = (Byte)_vvv_; } 413 414 #endif 415 416 #ifndef GetBe64 417 #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) 418 #endif 419 420 #ifndef GetBe16 421 #define GetBe16(p) ( (UInt16) ( \ 422 ((UInt16)((const Byte *)(p))[0] << 8) | \ 423 ((const Byte *)(p))[1] )) 424 #endif 425 426 427 #if defined(MY_CPU_BE) 428 #define Z7_CONV_BE_TO_NATIVE_CONST32(v) (v) 429 #define Z7_CONV_LE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v) 430 #define Z7_CONV_NATIVE_TO_BE_32(v) (v) 431 #elif defined(MY_CPU_LE) 432 #define Z7_CONV_BE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v) 433 #define Z7_CONV_LE_TO_NATIVE_CONST32(v) (v) 434 #define Z7_CONV_NATIVE_TO_BE_32(v) Z7_BSWAP32(v) 435 #else 436 #error Stop_Compiling_Unknown_Endian_CONV 437 #endif 438 439 440 #if defined(MY_CPU_BE) 441 442 #define GetBe32a(p) (*(const UInt32 *)(const void *)(p)) 443 #define GetBe16a(p) (*(const UInt16 *)(const void *)(p)) 444 #define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); } 445 #define SetBe16a(p, v) { *(UInt16 *)(void *)(p) = (v); } 446 447 #define GetUi32a(p) GetUi32(p) 448 #define GetUi16a(p) GetUi16(p) 449 #define SetUi32a(p, v) SetUi32(p, v) 450 #define SetUi16a(p, v) SetUi16(p, v) 451 452 #elif defined(MY_CPU_LE) 453 454 #define GetUi32a(p) (*(const UInt32 *)(const void *)(p)) 455 #define GetUi16a(p) (*(const UInt16 *)(const void *)(p)) 456 #define SetUi32a(p, v) { *(UInt32 *)(void *)(p) = (v); } 457 #define SetUi16a(p, v) { *(UInt16 *)(void *)(p) = (v); } 458 459 #define GetBe32a(p) GetBe32(p) 460 #define GetBe16a(p) GetBe16(p) 461 #define SetBe32a(p, v) SetBe32(p, v) 462 #define SetBe16a(p, v) SetBe16(p, v) 463 464 #else 465 #error Stop_Compiling_Unknown_Endian_CPU_a 466 #endif 467 468 469 #if defined(MY_CPU_X86_OR_AMD64) \ 470 || defined(MY_CPU_ARM_OR_ARM64) \ 471 || defined(MY_CPU_PPC_OR_PPC64) 472 #define Z7_CPU_FAST_ROTATE_SUPPORTED 473 #endif 474 475 476 #ifdef MY_CPU_X86_OR_AMD64 477 478 void Z7_FASTCALL z7_x86_cpuid(UInt32 a[4], UInt32 function); 479 UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void); 480 #if defined(MY_CPU_AMD64) 481 #define Z7_IF_X86_CPUID_SUPPORTED 482 #else 483 #define Z7_IF_X86_CPUID_SUPPORTED if (z7_x86_cpuid_GetMaxFunc()) 484 #endif 485 486 BoolInt CPU_IsSupported_AES(void); 487 BoolInt CPU_IsSupported_AVX(void); 488 BoolInt CPU_IsSupported_AVX2(void); 489 BoolInt CPU_IsSupported_VAES_AVX2(void); 490 BoolInt CPU_IsSupported_CMOV(void); 491 BoolInt CPU_IsSupported_SSE(void); 492 BoolInt CPU_IsSupported_SSE2(void); 493 BoolInt CPU_IsSupported_SSSE3(void); 494 BoolInt CPU_IsSupported_SSE41(void); 495 BoolInt CPU_IsSupported_SHA(void); 496 BoolInt CPU_IsSupported_PageGB(void); 497 498 #elif defined(MY_CPU_ARM_OR_ARM64) 499 500 BoolInt CPU_IsSupported_CRC32(void); 501 BoolInt CPU_IsSupported_NEON(void); 502 503 #if defined(_WIN32) 504 BoolInt CPU_IsSupported_CRYPTO(void); 505 #define CPU_IsSupported_SHA1 CPU_IsSupported_CRYPTO 506 #define CPU_IsSupported_SHA2 CPU_IsSupported_CRYPTO 507 #define CPU_IsSupported_AES CPU_IsSupported_CRYPTO 508 #else 509 BoolInt CPU_IsSupported_SHA1(void); 510 BoolInt CPU_IsSupported_SHA2(void); 511 BoolInt CPU_IsSupported_AES(void); 512 #endif 513 514 #endif 515 516 #if defined(__APPLE__) 517 int z7_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize); 518 int z7_sysctlbyname_Get_UInt32(const char *name, UInt32 *val); 519 #endif 520 521 EXTERN_C_END 522 523 #endif 524