diff options
author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2021-12-27 00:00:00 +0000 |
---|---|---|
committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2022-03-18 15:35:13 +0500 |
commit | f19f813537c7aea1c20749c914e756b54a9c3cf5 (patch) | |
tree | 816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /C/CpuArch.h | |
parent | 98e06a519b63b81986abe76d28887f6984a7732b (diff) | |
download | 7zip-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.h | 442 |
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 | ||
2 | 2021-07-13 : 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 | 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 | #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 | |||
381 | typedef struct | ||
382 | { | ||
383 | UInt32 maxFunc; | ||
384 | UInt32 vendor[3]; | ||
385 | UInt32 ver; | ||
386 | UInt32 b; | ||
387 | UInt32 c; | ||
388 | UInt32 d; | ||
389 | } Cx86cpuid; | ||
390 | |||
391 | enum | ||
392 | { | ||
393 | CPU_FIRM_INTEL, | ||
394 | CPU_FIRM_AMD, | ||
395 | CPU_FIRM_VIA | ||
396 | }; | ||
397 | |||
398 | void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d); | ||
399 | |||
400 | BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p); | ||
401 | int 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 | |||
407 | BoolInt CPU_Is_InOrder(void); | ||
408 | |||
409 | BoolInt CPU_IsSupported_AES(void); | ||
410 | BoolInt CPU_IsSupported_AVX2(void); | ||
411 | BoolInt CPU_IsSupported_VAES_AVX2(void); | ||
412 | BoolInt CPU_IsSupported_SSSE3(void); | ||
413 | BoolInt CPU_IsSupported_SSE41(void); | ||
414 | BoolInt CPU_IsSupported_SHA(void); | ||
415 | BoolInt CPU_IsSupported_PageGB(void); | ||
416 | |||
417 | #elif defined(MY_CPU_ARM_OR_ARM64) | ||
418 | |||
419 | BoolInt CPU_IsSupported_CRC32(void); | ||
420 | BoolInt CPU_IsSupported_NEON(void); | ||
421 | |||
422 | #if defined(_WIN32) | ||
423 | BoolInt 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 | ||
428 | BoolInt CPU_IsSupported_SHA1(void); | ||
429 | BoolInt CPU_IsSupported_SHA2(void); | ||
430 | BoolInt CPU_IsSupported_AES(void); | ||
431 | #endif | ||
432 | |||
433 | #endif | ||
434 | |||
435 | #if defined(__APPLE__) | ||
436 | int My_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize); | ||
437 | int My_sysctlbyname_Get_UInt32(const char *name, UInt32 *val); | ||
438 | #endif | ||
439 | |||
440 | EXTERN_C_END | ||
441 | |||
442 | #endif | ||