aboutsummaryrefslogtreecommitdiff
path: root/C/CpuArch.h
diff options
context:
space:
mode:
authorIgor Pavlov <87184205+ip7z@users.noreply.github.com>2021-12-27 00:00:00 +0000
committerIgor Pavlov <87184205+ip7z@users.noreply.github.com>2022-03-18 15:35:13 +0500
commitf19f813537c7aea1c20749c914e756b54a9c3cf5 (patch)
tree816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /C/CpuArch.h
parent98e06a519b63b81986abe76d28887f6984a7732b (diff)
download7zip-21.07.tar.gz
7zip-21.07.tar.bz2
7zip-21.07.zip
'21.07'21.07
Diffstat (limited to 'C/CpuArch.h')
-rw-r--r--C/CpuArch.h442
1 files changed, 442 insertions, 0 deletions
diff --git a/C/CpuArch.h b/C/CpuArch.h
new file mode 100644
index 0000000..529d3a5
--- /dev/null
+++ b/C/CpuArch.h
@@ -0,0 +1,442 @@
1/* CpuArch.h -- CPU specific code
22021-07-13 : Igor Pavlov : Public domain */
3
4#ifndef __CPU_ARCH_H
5#define __CPU_ARCH_H
6
7#include "7zTypes.h"
8
9EXTERN_C_BEGIN
10
11/*
12MY_CPU_LE means that CPU is LITTLE ENDIAN.
13MY_CPU_BE means that CPU is BIG ENDIAN.
14If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform.
15
16MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
17
18MY_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 #define MY_CPU_NAME "arm64"
55 #define MY_CPU_64BIT
56#endif
57
58
59#if defined(_M_ARM) \
60 || defined(_M_ARM_NT) \
61 || defined(_M_ARMT) \
62 || defined(__arm__) \
63 || defined(__thumb__) \
64 || defined(__ARMEL__) \
65 || defined(__ARMEB__) \
66 || defined(__THUMBEL__) \
67 || defined(__THUMBEB__)
68 #define MY_CPU_ARM
69
70 #if defined(__thumb__) || defined(__THUMBEL__) || defined(_M_ARMT)
71 #define MY_CPU_NAME "armt"
72 #else
73 #define MY_CPU_NAME "arm"
74 #endif
75 /* #define MY_CPU_32BIT */
76 #define MY_CPU_SIZEOF_POINTER 4
77#endif
78
79
80#if defined(_M_IA64) \
81 || defined(__ia64__)
82 #define MY_CPU_IA64
83 #define MY_CPU_NAME "ia64"
84 #define MY_CPU_64BIT
85#endif
86
87
88#if defined(__mips64) \
89 || defined(__mips64__) \
90 || (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3))
91 #define MY_CPU_NAME "mips64"
92 #define MY_CPU_64BIT
93#elif defined(__mips__)
94 #define MY_CPU_NAME "mips"
95 /* #define MY_CPU_32BIT */
96#endif
97
98
99#if defined(__ppc64__) \
100 || defined(__powerpc64__) \
101 || defined(__ppc__) \
102 || defined(__powerpc__) \
103 || defined(__PPC__) \
104 || defined(_POWER)
105
106#if defined(__ppc64__) \
107 || defined(__powerpc64__) \
108 || defined(_LP64) \
109 || defined(__64BIT__)
110 #ifdef __ILP32__
111 #define MY_CPU_NAME "ppc64-32"
112 #define MY_CPU_SIZEOF_POINTER 4
113 #else
114 #define MY_CPU_NAME "ppc64"
115 #define MY_CPU_SIZEOF_POINTER 8
116 #endif
117 #define MY_CPU_64BIT
118#else
119 #define MY_CPU_NAME "ppc"
120 #define MY_CPU_SIZEOF_POINTER 4
121 /* #define MY_CPU_32BIT */
122#endif
123#endif
124
125
126#if defined(__sparc64__)
127 #define MY_CPU_NAME "sparc64"
128 #define MY_CPU_64BIT
129#elif defined(__sparc__)
130 #define MY_CPU_NAME "sparc"
131 /* #define MY_CPU_32BIT */
132#endif
133
134
135#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
136#define MY_CPU_X86_OR_AMD64
137#endif
138
139#if defined(MY_CPU_ARM) || defined(MY_CPU_ARM64)
140#define MY_CPU_ARM_OR_ARM64
141#endif
142
143
144#ifdef _WIN32
145
146 #ifdef MY_CPU_ARM
147 #define MY_CPU_ARM_LE
148 #endif
149
150 #ifdef MY_CPU_ARM64
151 #define MY_CPU_ARM64_LE
152 #endif
153
154 #ifdef _M_IA64
155 #define MY_CPU_IA64_LE
156 #endif
157
158#endif
159
160
161#if defined(MY_CPU_X86_OR_AMD64) \
162 || defined(MY_CPU_ARM_LE) \
163 || defined(MY_CPU_ARM64_LE) \
164 || defined(MY_CPU_IA64_LE) \
165 || defined(__LITTLE_ENDIAN__) \
166 || defined(__ARMEL__) \
167 || defined(__THUMBEL__) \
168 || defined(__AARCH64EL__) \
169 || defined(__MIPSEL__) \
170 || defined(__MIPSEL) \
171 || defined(_MIPSEL) \
172 || defined(__BFIN__) \
173 || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
174 #define MY_CPU_LE
175#endif
176
177#if defined(__BIG_ENDIAN__) \
178 || defined(__ARMEB__) \
179 || defined(__THUMBEB__) \
180 || defined(__AARCH64EB__) \
181 || defined(__MIPSEB__) \
182 || defined(__MIPSEB) \
183 || defined(_MIPSEB) \
184 || defined(__m68k__) \
185 || defined(__s390__) \
186 || defined(__s390x__) \
187 || defined(__zarch__) \
188 || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
189 #define MY_CPU_BE
190#endif
191
192
193#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
194 #error Stop_Compiling_Bad_Endian
195#endif
196
197
198#if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT)
199 #error Stop_Compiling_Bad_32_64_BIT
200#endif
201
202#ifdef __SIZEOF_POINTER__
203 #ifdef MY_CPU_SIZEOF_POINTER
204 #if MY_CPU_SIZEOF_POINTER != __SIZEOF_POINTER__
205 #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE
206 #endif
207 #else
208 #define MY_CPU_SIZEOF_POINTER __SIZEOF_POINTER__
209 #endif
210#endif
211
212#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)
213#if defined (_LP64)
214 #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE
215#endif
216#endif
217
218#ifdef _MSC_VER
219 #if _MSC_VER >= 1300
220 #define MY_CPU_pragma_pack_push_1 __pragma(pack(push, 1))
221 #define MY_CPU_pragma_pop __pragma(pack(pop))
222 #else
223 #define MY_CPU_pragma_pack_push_1
224 #define MY_CPU_pragma_pop
225 #endif
226#else
227 #ifdef __xlC__
228 #define MY_CPU_pragma_pack_push_1 _Pragma("pack(1)")
229 #define MY_CPU_pragma_pop _Pragma("pack()")
230 #else
231 #define MY_CPU_pragma_pack_push_1 _Pragma("pack(push, 1)")
232 #define MY_CPU_pragma_pop _Pragma("pack(pop)")
233 #endif
234#endif
235
236
237#ifndef MY_CPU_NAME
238 #ifdef MY_CPU_LE
239 #define MY_CPU_NAME "LE"
240 #elif defined(MY_CPU_BE)
241 #define MY_CPU_NAME "BE"
242 #else
243 /*
244 #define MY_CPU_NAME ""
245 */
246 #endif
247#endif
248
249
250
251
252
253#ifdef MY_CPU_LE
254 #if defined(MY_CPU_X86_OR_AMD64) \
255 || defined(MY_CPU_ARM64)
256 #define MY_CPU_LE_UNALIGN
257 #define MY_CPU_LE_UNALIGN_64
258 #elif defined(__ARM_FEATURE_UNALIGNED)
259 /* gcc9 for 32-bit arm can use LDRD instruction that requires 32-bit alignment.
260 So we can't use unaligned 64-bit operations. */
261 #define MY_CPU_LE_UNALIGN
262 #endif
263#endif
264
265
266#ifdef MY_CPU_LE_UNALIGN
267
268#define GetUi16(p) (*(const UInt16 *)(const void *)(p))
269#define GetUi32(p) (*(const UInt32 *)(const void *)(p))
270#ifdef MY_CPU_LE_UNALIGN_64
271#define GetUi64(p) (*(const UInt64 *)(const void *)(p))
272#endif
273
274#define SetUi16(p, v) { *(UInt16 *)(void *)(p) = (v); }
275#define SetUi32(p, v) { *(UInt32 *)(void *)(p) = (v); }
276#ifdef MY_CPU_LE_UNALIGN_64
277#define SetUi64(p, v) { *(UInt64 *)(void *)(p) = (v); }
278#endif
279
280#else
281
282#define GetUi16(p) ( (UInt16) ( \
283 ((const Byte *)(p))[0] | \
284 ((UInt16)((const Byte *)(p))[1] << 8) ))
285
286#define GetUi32(p) ( \
287 ((const Byte *)(p))[0] | \
288 ((UInt32)((const Byte *)(p))[1] << 8) | \
289 ((UInt32)((const Byte *)(p))[2] << 16) | \
290 ((UInt32)((const Byte *)(p))[3] << 24))
291
292#define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
293 _ppp_[0] = (Byte)_vvv_; \
294 _ppp_[1] = (Byte)(_vvv_ >> 8); }
295
296#define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
297 _ppp_[0] = (Byte)_vvv_; \
298 _ppp_[1] = (Byte)(_vvv_ >> 8); \
299 _ppp_[2] = (Byte)(_vvv_ >> 16); \
300 _ppp_[3] = (Byte)(_vvv_ >> 24); }
301
302#endif
303
304
305#ifndef MY_CPU_LE_UNALIGN_64
306
307#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
308
309#define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \
310 SetUi32(_ppp2_ , (UInt32)_vvv2_); \
311 SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); }
312
313#endif
314
315
316
317
318#ifdef __has_builtin
319 #define MY__has_builtin(x) __has_builtin(x)
320#else
321 #define MY__has_builtin(x) 0
322#endif
323
324#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ defined(_MSC_VER) && (_MSC_VER >= 1300)
325
326/* Note: we use bswap instruction, that is unsupported in 386 cpu */
327
328#include <stdlib.h>
329
330#pragma intrinsic(_byteswap_ushort)
331#pragma intrinsic(_byteswap_ulong)
332#pragma intrinsic(_byteswap_uint64)
333
334/* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */
335#define GetBe32(p) _byteswap_ulong (*(const UInt32 *)(const void *)(p))
336#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const void *)(p))
337
338#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v)
339
340#elif defined(MY_CPU_LE_UNALIGN) && ( \
341 (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \
342 || (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) )
343
344/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const void *)(p)) */
345#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const void *)(p))
346#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const void *)(p))
347
348#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v)
349
350#else
351
352#define GetBe32(p) ( \
353 ((UInt32)((const Byte *)(p))[0] << 24) | \
354 ((UInt32)((const Byte *)(p))[1] << 16) | \
355 ((UInt32)((const Byte *)(p))[2] << 8) | \
356 ((const Byte *)(p))[3] )
357
358#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
359
360#define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
361 _ppp_[0] = (Byte)(_vvv_ >> 24); \
362 _ppp_[1] = (Byte)(_vvv_ >> 16); \
363 _ppp_[2] = (Byte)(_vvv_ >> 8); \
364 _ppp_[3] = (Byte)_vvv_; }
365
366#endif
367
368
369#ifndef GetBe16
370
371#define GetBe16(p) ( (UInt16) ( \
372 ((UInt16)((const Byte *)(p))[0] << 8) | \
373 ((const Byte *)(p))[1] ))
374
375#endif
376
377
378
379#ifdef MY_CPU_X86_OR_AMD64
380
381typedef struct
382{
383 UInt32 maxFunc;
384 UInt32 vendor[3];
385 UInt32 ver;
386 UInt32 b;
387 UInt32 c;
388 UInt32 d;
389} Cx86cpuid;
390
391enum
392{
393 CPU_FIRM_INTEL,
394 CPU_FIRM_AMD,
395 CPU_FIRM_VIA
396};
397
398void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);
399
400BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p);
401int x86cpuid_GetFirm(const Cx86cpuid *p);
402
403#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))
404#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
405#define x86cpuid_GetStepping(ver) (ver & 0xF)
406
407BoolInt CPU_Is_InOrder(void);
408
409BoolInt CPU_IsSupported_AES(void);
410BoolInt CPU_IsSupported_AVX2(void);
411BoolInt CPU_IsSupported_VAES_AVX2(void);
412BoolInt CPU_IsSupported_SSSE3(void);
413BoolInt CPU_IsSupported_SSE41(void);
414BoolInt CPU_IsSupported_SHA(void);
415BoolInt CPU_IsSupported_PageGB(void);
416
417#elif defined(MY_CPU_ARM_OR_ARM64)
418
419BoolInt CPU_IsSupported_CRC32(void);
420BoolInt CPU_IsSupported_NEON(void);
421
422#if defined(_WIN32)
423BoolInt CPU_IsSupported_CRYPTO(void);
424#define CPU_IsSupported_SHA1 CPU_IsSupported_CRYPTO
425#define CPU_IsSupported_SHA2 CPU_IsSupported_CRYPTO
426#define CPU_IsSupported_AES CPU_IsSupported_CRYPTO
427#else
428BoolInt CPU_IsSupported_SHA1(void);
429BoolInt CPU_IsSupported_SHA2(void);
430BoolInt CPU_IsSupported_AES(void);
431#endif
432
433#endif
434
435#if defined(__APPLE__)
436int My_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize);
437int My_sysctlbyname_Get_UInt32(const char *name, UInt32 *val);
438#endif
439
440EXTERN_C_END
441
442#endif