• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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