Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qprocessordetection.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5
6#if 0
7#pragma qt_class(QtProcessorDetection)
8#pragma qt_sync_skip_header_check
9#pragma qt_sync_stop_processing
10#endif
11
12#ifndef QPROCESSORDETECTION_H
13#define QPROCESSORDETECTION_H
14
15/*
16 This file uses preprocessor #defines to set various Q_PROCESSOR_* #defines
17 based on the following patterns:
18
19 Q_PROCESSOR_{FAMILY}
20 Q_PROCESSOR_{FAMILY}_{VARIANT}
21 Q_PROCESSOR_{FAMILY}_{REVISION}
22
23 The first is always defined. Defines for the various revisions/variants are
24 optional and usually dependent on how the compiler was invoked. Variants
25 that are a superset of another should have a define for the superset.
26
27 In addition to the processor family, variants, and revisions, we also set
28 Q_BYTE_ORDER appropriately for the target processor. For bi-endian
29 processors, we try to auto-detect the byte order using the __BIG_ENDIAN__,
30 __LITTLE_ENDIAN__, or __BYTE_ORDER__ preprocessor macros.
31
32 Note: when adding support for new processors, be sure to update
33 config.tests/arch/arch.cpp to ensure that configure can detect the target
34 and host architectures.
35*/
36
37/* Machine byte-order, reuse preprocessor provided macros when available */
38#if defined(__ORDER_BIG_ENDIAN__)
39# define Q_BIG_ENDIAN __ORDER_BIG_ENDIAN__
40#else
41# define Q_BIG_ENDIAN 4321
42#endif
43#if defined(__ORDER_LITTLE_ENDIAN__)
44# define Q_LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
45#else
46# define Q_LITTLE_ENDIAN 1234
47#endif
48
49/*
50 Alpha family, no revisions or variants
51
52 Alpha is bi-endian, use endianness auto-detection implemented below.
53*/
54#if defined(__alpha__) || defined(_M_ALPHA)
55# define Q_PROCESSOR_ALPHA
56// Q_BYTE_ORDER not defined, use endianness auto-detection
57
58/*
59 ARM family, known revisions: V5, V6, V7, V8
60
61 ARM is bi-endian, detect using __ARMEL__ or __ARMEB__, falling back to
62 auto-detection implemented below.
63*/
64#elif defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__) || defined(_ARM64EC_)
65# if defined(__aarch64__) || defined(__ARM64__) || defined(_M_ARM64) || defined(_ARM64EC_)
66# define Q_PROCESSOR_ARM_64
67# define Q_PROCESSOR_WORDSIZE 8
68# else
69# define Q_PROCESSOR_ARM_32
70# endif
71# if defined(__ARM_ARCH) && __ARM_ARCH > 1
72# define Q_PROCESSOR_ARM __ARM_ARCH
73# elif defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM > 1
74# define Q_PROCESSOR_ARM __TARGET_ARCH_ARM
75# elif defined(_M_ARM) && _M_ARM > 1
76# define Q_PROCESSOR_ARM _M_ARM
77# elif defined(__ARM64_ARCH_8__)
78 || defined(__aarch64__)
79 || defined(__ARMv8__)
80 || defined(__ARMv8_A__)
81 || defined(_M_ARM64)
82 || defined (_ARM64EC_)
83# define Q_PROCESSOR_ARM 8
84# elif defined(__ARM_ARCH_7__)
85 || defined(__ARM_ARCH_7A__)
86 || defined(__ARM_ARCH_7R__)
87 || defined(__ARM_ARCH_7M__)
88 || defined(__ARM_ARCH_7S__)
89 || defined(_ARM_ARCH_7)
90 || defined(__CORE_CORTEXA__)
91# define Q_PROCESSOR_ARM 7
92# elif defined(__ARM_ARCH_6__)
93 || defined(__ARM_ARCH_6J__)
94 || defined(__ARM_ARCH_6T2__)
95 || defined(__ARM_ARCH_6Z__)
96 || defined(__ARM_ARCH_6K__)
97 || defined(__ARM_ARCH_6ZK__)
98 || defined(__ARM_ARCH_6M__)
99# define Q_PROCESSOR_ARM 6
100# elif defined(__ARM_ARCH_5TEJ__)
101 || defined(__ARM_ARCH_5TE__)
102# define Q_PROCESSOR_ARM 5
103# else
104# define Q_PROCESSOR_ARM 0
105# endif
106# if Q_PROCESSOR_ARM >= 8
107# define Q_PROCESSOR_ARM_V8
108# endif
109# if Q_PROCESSOR_ARM >= 7
110# define Q_PROCESSOR_ARM_V7
111# endif
112# if Q_PROCESSOR_ARM >= 6
113# define Q_PROCESSOR_ARM_V6
114# endif
115# if Q_PROCESSOR_ARM >= 5
116# define Q_PROCESSOR_ARM_V5
117# else
118# error "ARM architecture too old"
119# endif
120# if defined(_ARM64EC_)
121# define Q_PROCESSOR_ARM_64_EC
122# endif
123# if defined(__ARMEL__) || defined(_M_ARM64) || defined(_ARM64EC_)
124# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
125# elif defined(__ARMEB__)
126# define Q_BYTE_ORDER Q_BIG_ENDIAN
127# else
128// Q_BYTE_ORDER not defined, use endianness auto-detection
129#endif
130
131/*
132 AVR32 family, no revisions or variants
133
134 AVR32 is big-endian.
135*/
136// #elif defined(__avr32__)
137// # define Q_PROCESSOR_AVR32
138// # define Q_BYTE_ORDER Q_BIG_ENDIAN
139
140/*
141 Blackfin family, no revisions or variants
142
143 Blackfin is little-endian.
144*/
145// #elif defined(__bfin__)
146// # define Q_PROCESSOR_BLACKFIN
147// # define Q_BYTE_ORDER Q_LITTLE_ENDIAN
148
149/*
150 PA-RISC family, no revisions or variants
151
152 PA-RISC is big-endian.
153*/
154#elif defined(__hppa__)
155# define Q_PROCESSOR_HPPA
156# define Q_BYTE_ORDER Q_BIG_ENDIAN
157
158/*
159 X86 family, known variants: 32- and 64-bit
160
161 X86 is little-endian.
162*/
163#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
164# define Q_PROCESSOR_X86_32
165# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
166# define Q_PROCESSOR_WORDSIZE 4
167
168/*
169 * We define Q_PROCESSOR_X86 == 6 for anything above a equivalent or better
170 * than a Pentium Pro (the processor whose architecture was called P6) or an
171 * Athlon.
172 *
173 * All processors since the Pentium III and the Athlon 4 have SSE support, so
174 * we use that to detect. That leaves the original Athlon, Pentium Pro and
175 * Pentium II.
176 */
177
178# if defined(_M_IX86)
179# define Q_PROCESSOR_X86 (_M_IX86/100)
180# elif defined(__i686__) || defined(__athlon__) || defined(__SSE__) || defined(__pentiumpro__)
181# define Q_PROCESSOR_X86 6
182# elif defined(__i586__) || defined(__k6__) || defined(__pentium__)
183# define Q_PROCESSOR_X86 5
184# elif defined(__i486__) || defined(__80486__)
185# define Q_PROCESSOR_X86 4
186# else
187# define Q_PROCESSOR_X86 3
188# endif
189
190#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
191# define Q_PROCESSOR_X86 6
192# define Q_PROCESSOR_X86_64
193# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
194# define Q_PROCESSOR_WORDSIZE 8
195
196/*
197 Itanium (IA-64) family, no revisions or variants
198
199 Itanium is bi-endian, use endianness auto-detection implemented below.
200*/
201#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
202# define Q_PROCESSOR_IA64
203# define Q_PROCESSOR_WORDSIZE 8
204// Q_BYTE_ORDER not defined, use endianness auto-detection
205
206/*
207 LoongArch family, known variants: 32- and 64-bit
208
209 LoongArch is little-endian.
210*/
211#elif defined(__loongarch__)
212# define Q_PROCESSOR_LOONGARCH
213# if __loongarch_grlen == 64
214# define Q_PROCESSOR_LOONGARCH_64
215# else
216# define Q_PROCESSOR_LOONGARCH_32
217# endif
218# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
219
220/*
221 Motorola 68000 family, no revisions or variants
222
223 M68K is big-endian.
224*/
225#elif defined(__m68k__)
226# define Q_PROCESSOR_M68K
227# define Q_BYTE_ORDER Q_BIG_ENDIAN
228
229/*
230 MIPS family, known revisions: I, II, III, IV, 32, 64
231
232 MIPS is bi-endian, use endianness auto-detection implemented below.
233*/
234#elif defined(__mips) || defined(__mips__) || defined(_M_MRX000)
235# define Q_PROCESSOR_MIPS
236# if defined(_MIPS_ARCH_MIPS1) || (defined(__mips) && __mips - 0 >= 1)
237# define Q_PROCESSOR_MIPS_I
238# endif
239# if defined(_MIPS_ARCH_MIPS2) || (defined(__mips) && __mips - 0 >= 2)
240# define Q_PROCESSOR_MIPS_II
241# endif
242# if defined(_MIPS_ARCH_MIPS3) || (defined(__mips) && __mips - 0 >= 3)
243# define Q_PROCESSOR_MIPS_III
244# endif
245# if defined(_MIPS_ARCH_MIPS4) || (defined(__mips) && __mips - 0 >= 4)
246# define Q_PROCESSOR_MIPS_IV
247# endif
248# if defined(_MIPS_ARCH_MIPS5) || (defined(__mips) && __mips - 0 >= 5)
249# define Q_PROCESSOR_MIPS_V
250# endif
251# if defined(_MIPS_ARCH_MIPS32) || defined(__mips32) || (defined(__mips) && __mips - 0 >= 32)
252# define Q_PROCESSOR_MIPS_32
253# endif
254# if defined(_MIPS_ARCH_MIPS64) || defined(__mips64)
255# define Q_PROCESSOR_MIPS_64
256# define Q_PROCESSOR_WORDSIZE 8
257# endif
258# if defined(__MIPSEL__)
259# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
260# elif defined(__MIPSEB__)
261# define Q_BYTE_ORDER Q_BIG_ENDIAN
262# else
263// Q_BYTE_ORDER not defined, use endianness auto-detection
264# endif
265
266/*
267 Power family, known variants: 32- and 64-bit
268
269 There are many more known variants/revisions that we do not handle/detect.
270 See http://en.wikipedia.org/wiki/Power_Architecture
271 and http://en.wikipedia.org/wiki/File:PowerISA-evolution.svg
272
273 Power is bi-endian, use endianness auto-detection implemented below.
274*/
275#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__)
276 || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC)
277 || defined(_M_MPPC) || defined(_M_PPC)
278# define Q_PROCESSOR_POWER
279# if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__)
280# define Q_PROCESSOR_POWER_64
281# define Q_PROCESSOR_WORDSIZE 8
282# else
283# define Q_PROCESSOR_POWER_32
284# endif
285// Q_BYTE_ORDER not defined, use endianness auto-detection
286
287/*
288 RISC-V family, known variants: 32- and 64-bit
289
290 RISC-V is little-endian.
291*/
292#elif defined(__riscv)
293# define Q_PROCESSOR_RISCV
294# if __riscv_xlen == 64
295# define Q_PROCESSOR_RISCV_64
296# else
297# define Q_PROCESSOR_RISCV_32
298# endif
299# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
300
301/*
302 S390 family, known variant: S390X (64-bit)
303
304 S390 is big-endian.
305*/
306#elif defined(__s390__)
307# define Q_PROCESSOR_S390
308# if defined(__s390x__)
309# define Q_PROCESSOR_S390_X
310# endif
311# define Q_BYTE_ORDER Q_BIG_ENDIAN
312
313/*
314 SuperH family, optional revision: SH-4A
315
316 SuperH is bi-endian, use endianness auto-detection implemented below.
317*/
318// #elif defined(__sh__)
319// # define Q_PROCESSOR_SH
320// # if defined(__sh4a__)
321// # define Q_PROCESSOR_SH_4A
322// # endif
323// Q_BYTE_ORDER not defined, use endianness auto-detection
324
325/*
326 SPARC family, optional revision: V9
327
328 SPARC is big-endian only prior to V9, while V9 is bi-endian with big-endian
329 as the default byte order. Assume all SPARC systems are big-endian.
330*/
331#elif defined(__sparc__)
332# define Q_PROCESSOR_SPARC
333# if defined(__sparc_v9__) || defined(__sparcv9)
334# define Q_PROCESSOR_SPARC_V9
335# endif
336# if defined(__sparc64__)
337# define Q_PROCESSOR_SPARC_64
338# endif
339# define Q_BYTE_ORDER Q_BIG_ENDIAN
340
341// -- Web Assembly --
342#elif defined(__EMSCRIPTEN__)
343# define Q_PROCESSOR_WASM
344# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
345# define Q_PROCESSOR_WORDSIZE 8
346#ifdef QT_COMPILER_SUPPORTS_SSE2
347# define Q_PROCESSOR_X86 6 // enables SIMD support
348# define Q_PROCESSOR_X86_64 // wasm64
349# define Q_PROCESSOR_WASM_64
350#endif
351
352#endif
353
354/*
355 NOTE:
356 GCC 4.6 added __BYTE_ORDER__, __ORDER_BIG_ENDIAN__, __ORDER_LITTLE_ENDIAN__
357 and __ORDER_PDP_ENDIAN__ in SVN r165881. If you are using GCC 4.6 or newer,
358 this code will properly detect your target byte order; if you are not, and
359 the __LITTLE_ENDIAN__ or __BIG_ENDIAN__ macros are not defined, then this
360 code will fail to detect the target byte order.
361*/
362// Some processors support either endian format, try to detect which we are using.
363#if !defined(Q_BYTE_ORDER)
364# if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == Q_BIG_ENDIAN || __BYTE_ORDER__ == Q_LITTLE_ENDIAN)
365// Reuse __BYTE_ORDER__ as-is, since our Q_*_ENDIAN #defines match the preprocessor defaults
366# define Q_BYTE_ORDER __BYTE_ORDER__
367# elif defined(__BIG_ENDIAN__) || defined(_big_endian__) || defined(_BIG_ENDIAN)
368# define Q_BYTE_ORDER Q_BIG_ENDIAN
369# elif defined(__LITTLE_ENDIAN__) || defined(_little_endian__) || defined(_LITTLE_ENDIAN)
370# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
371# else
372# error "Unable to determine byte order!"
373# endif
374#endif
375
376/*
377 Size of a pointer and the machine register size. We detect a 64-bit system by:
378 * GCC and compatible compilers (Clang, ICC on OS X and Windows) always define
379 __SIZEOF_POINTER__. This catches all known cases of ILP32 builds on 64-bit
380 processors.
381 * Most other Unix compilers define __LP64__ or _LP64 on 64-bit mode
382 (Long and Pointer 64-bit)
383 * If Q_PROCESSOR_WORDSIZE was defined above, it's assumed to match the pointer
384 size.
385 Otherwise, we assume to be 32-bit and then check in qglobal.cpp that it is right.
386*/
387
388#if defined __SIZEOF_POINTER__
389# define QT_POINTER_SIZE __SIZEOF_POINTER__
390#elif defined(__LP64__) || defined(_LP64)
391# define QT_POINTER_SIZE 8
392#elif defined(Q_PROCESSOR_WORDSIZE)
393# define QT_POINTER_SIZE Q_PROCESSOR_WORDSIZE
394#else
395# define QT_POINTER_SIZE 4
396#endif
397
398/*
399 Define Q_PROCESSOR_WORDSIZE to be the size of the machine's word (usually,
400 the size of the register). On some architectures where a pointer could be
401 smaller than the register, the macro is defined above.
402
403 Falls back to QT_POINTER_SIZE if not set explicitly for the platform.
404*/
406# define Q_PROCESSOR_WORDSIZE QT_POINTER_SIZE
407#endif
408
409
410#endif // QPROCESSORDETECTION_H
#define ARCH_POINTER
#define ARCH_PROCESSOR
#define ARCH_ABI
#define ARCH_COORD_TYPE
#define ARCH_ABI1
#define ARCH_ABI2
#define QT_POINTER_SIZE
#define Q_PROCESSOR_WORDSIZE
#define Q_LITTLE_ENDIAN