b24e7fce |
1 | /* CpuArch.h -- CPU specific code |
2 | 2018-02-18 : 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 | BoolInt CPU_IsSupported_PageGB(); |
331 | |
332 | #endif |
333 | |
334 | EXTERN_C_END |
335 | |
336 | #endif |