3 dnl Copyright (C) 2002-2024 Free Software Foundation, Inc.
4 dnl This file is free software; the Free Software Foundation
5 dnl gives unlimited permission to copy and/or distribute it,
6 dnl with or without modifications, as long as this notice is preserved.
8 dnl From Bruno Haible and Sam Steingold.
10 dnl Sets the HOST_CPU variable to the canonical name of the CPU.
11 dnl Sets the HOST_CPU_C_ABI variable to the canonical name of the CPU with its
12 dnl C language ABI (application binary interface).
13 dnl Also defines __${HOST_CPU}__ and __${HOST_CPU_C_ABI}__ as C macros in
16 dnl This canonical name can be used to select a particular assembly language
17 dnl source file that will interoperate with C code on the given host.
20 dnl * 'i386' and 'sparc' are different canonical names, because code for i386
21 dnl will not run on SPARC CPUs and vice versa. They have different
23 dnl * 'sparc' and 'sparc64' are different canonical names, because code for
24 dnl 'sparc' and code for 'sparc64' cannot be linked together: 'sparc' code
25 dnl contains 32-bit instructions, whereas 'sparc64' code contains 64-bit
26 dnl instructions. A process on a SPARC CPU can be in 32-bit mode or in 64-bit
27 dnl mode, but not both.
28 dnl * 'mips' and 'mipsn32' are different canonical names, because they use
29 dnl different argument passing and return conventions for C functions, and
30 dnl although the instruction set of 'mips' is a large subset of the
31 dnl instruction set of 'mipsn32'.
32 dnl * 'mipsn32' and 'mips64' are different canonical names, because they use
33 dnl different sizes for the C types like 'int' and 'void *', and although
34 dnl the instruction sets of 'mipsn32' and 'mips64' are the same.
35 dnl * The same canonical name is used for different endiannesses. You can
36 dnl determine the endianness through preprocessor symbols:
37 dnl - 'arm': test __ARMEL__.
38 dnl - 'mips', 'mipsn32', 'mips64': test _MIPSEB vs. _MIPSEL.
39 dnl - 'powerpc64': test _BIG_ENDIAN vs. _LITTLE_ENDIAN.
40 dnl * The same name 'i386' is used for CPUs of type i386, i486, i586
41 dnl (Pentium), AMD K7, Pentium II, Pentium IV, etc., because
42 dnl - Instructions that do not exist on all of these CPUs (cmpxchg,
43 dnl MMX, SSE, SSE2, 3DNow! etc.) are not frequently used. If your
44 dnl assembly language source files use such instructions, you will
45 dnl need to make the distinction.
46 dnl - Speed of execution of the common instruction set is reasonable across
47 dnl the entire family of CPUs. If you have assembly language source files
48 dnl that are optimized for particular CPU types (like GNU gmp has), you
49 dnl will need to make the distinction.
50 dnl See <https://en.wikipedia.org/wiki/X86_instruction_listings>.
51 AC_DEFUN([gl_HOST_CPU_C_ABI],
53 AC_REQUIRE([AC_CANONICAL_HOST])
54 AC_REQUIRE([gl_C_ASM])
55 AC_CACHE_CHECK([host CPU and C ABI], [gl_cv_host_cpu_c_abi],
61 gl_cv_host_cpu_c_abi=i386
65 # On x86_64 systems, the C compiler may be generating code in one of
67 # - 64-bit instruction set, 64-bit pointers, 64-bit 'long': x86_64.
68 # - 64-bit instruction set, 64-bit pointers, 32-bit 'long': x86_64
69 # with native Windows (mingw, MSVC).
70 # - 64-bit instruction set, 32-bit pointers, 32-bit 'long': x86_64-x32.
71 # - 32-bit instruction set, 32-bit pointers, 32-bit 'long': i386.
74 [[#if (defined __x86_64__ || defined __amd64__ \
75 || defined _M_X64 || defined _M_AMD64)
83 [[#if defined __ILP32__ || defined _ILP32
89 [gl_cv_host_cpu_c_abi=x86_64-x32],
90 [gl_cv_host_cpu_c_abi=x86_64])],
91 [gl_cv_host_cpu_c_abi=i386])
95 alphaev[4-8] | alphaev56 | alphapca5[67] | alphaev6[78] )
97 gl_cv_host_cpu_c_abi=alpha
101 # Assume arm with EABI.
102 # On arm64 systems, the C compiler may be generating code in one of
104 # - aarch64 instruction set, 64-bit pointers, 64-bit 'long': arm64.
105 # - aarch64 instruction set, 32-bit pointers, 32-bit 'long': arm64-ilp32.
106 # - 32-bit instruction set, 32-bit pointers, 32-bit 'long': arm or armhf.
117 [[#if defined __ILP32__ || defined _ILP32
123 [gl_cv_host_cpu_c_abi=arm64-ilp32],
124 [gl_cv_host_cpu_c_abi=arm64])],
125 [# Don't distinguish little-endian and big-endian arm, since they
126 # don't require different machine code for simple operations and
127 # since the user can distinguish them through the preprocessor
128 # defines __ARMEL__ vs. __ARMEB__.
129 # But distinguish arm which passes floating-point arguments and
130 # return values in integer registers (r0, r1, ...) - this is
131 # gcc -mfloat-abi=soft or gcc -mfloat-abi=softfp - from arm which
132 # passes them in float registers (s0, s1, ...) and double registers
133 # (d0, d1, ...) - this is gcc -mfloat-abi=hard. GCC 4.6 or newer
134 # sets the preprocessor defines __ARM_PCS (for the first case) and
135 # __ARM_PCS_VFP (for the second case), but older GCC does not.
136 echo 'double ddd; void func (double dd) { ddd = dd; }' > conftest.c
137 # Look for a reference to the register d0 in the .s file.
138 AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $gl_c_asm_opt conftest.c) >/dev/null 2>&1
139 if LC_ALL=C grep 'd0,' conftest.$gl_asmext >/dev/null; then
140 gl_cv_host_cpu_c_abi=armhf
142 gl_cv_host_cpu_c_abi=arm
148 hppa1.0 | hppa1.1 | hppa2.0* | hppa64 )
149 # On hppa, the C compiler may be generating 32-bit code or 64-bit
150 # code. In the latter case, it defines _LP64 and __LP64__.
159 [gl_cv_host_cpu_c_abi=hppa64],
160 [gl_cv_host_cpu_c_abi=hppa])
164 # On ia64 on HP-UX, the C compiler may be generating 64-bit code or
165 # 32-bit code. In the latter case, it defines _ILP32.
174 [gl_cv_host_cpu_c_abi=ia64-ilp32],
175 [gl_cv_host_cpu_c_abi=ia64])
179 # We should also check for (_MIPS_SZPTR == 64), but gcc keeps this
183 [[#if defined _MIPS_SZLONG && (_MIPS_SZLONG == 64)
189 [gl_cv_host_cpu_c_abi=mips64],
190 [# In the n32 ABI, _ABIN32 is defined, _ABIO32 is not defined (but
191 # may later get defined by <sgidefs.h>), and _MIPS_SIM == _ABIN32.
192 # In the 32 ABI, _ABIO32 is defined, _ABIN32 is not defined (but
193 # may later get defined by <sgidefs.h>), and _MIPS_SIM == _ABIO32.
196 [[#if (_MIPS_SIM == _ABIN32)
202 [gl_cv_host_cpu_c_abi=mipsn32],
203 [gl_cv_host_cpu_c_abi=mips])])
207 # Different ABIs are in use on AIX vs. Mac OS X vs. Linux,*BSD.
208 # No need to distinguish them here; the caller may distinguish
209 # them based on the OS.
210 # On powerpc64 systems, the C compiler may still be generating
211 # 32-bit code. And on powerpc-ibm-aix systems, the C compiler may
212 # be generating 64-bit code.
215 [[#if defined __powerpc64__ || defined __LP64__
221 [# On powerpc64, there are two ABIs on Linux: The AIX compatible
222 # one and the ELFv2 one. The latter defines _CALL_ELF=2.
225 [[#if defined _CALL_ELF && _CALL_ELF == 2
231 [gl_cv_host_cpu_c_abi=powerpc64-elfv2],
232 [gl_cv_host_cpu_c_abi=powerpc64])
234 [gl_cv_host_cpu_c_abi=powerpc])
238 gl_cv_host_cpu_c_abi=powerpc
242 # There are 2 architectures (with variants): rv32* and rv64*.
245 [[#if __riscv_xlen == 64
253 # There are 6 ABIs: ilp32, ilp32f, ilp32d, lp64, lp64f, lp64d.
254 # Size of 'long' and 'void *':
257 [[#if defined __LP64__
266 # __riscv_float_abi_double:
267 # 'float' and 'double' are passed in floating-point registers.
268 # __riscv_float_abi_single:
269 # 'float' are passed in floating-point registers.
270 # __riscv_float_abi_soft:
271 # No values are passed in floating-point registers.
274 [[#if defined __riscv_float_abi_double
283 [[#if defined __riscv_float_abi_single
292 gl_cv_host_cpu_c_abi="${cpu}-${main_abi}${float_abi}"
296 # On s390x, the C compiler may be generating 64-bit (= s390x) code
297 # or 31-bit (= s390) code.
300 [[#if defined __LP64__ || defined __s390x__
306 [gl_cv_host_cpu_c_abi=s390x],
307 [gl_cv_host_cpu_c_abi=s390])
311 # UltraSPARCs running Linux have `uname -m` = "sparc64", but the
312 # C compiler still generates 32-bit code.
315 [[#if defined __sparcv9 || defined __arch64__
321 [gl_cv_host_cpu_c_abi=sparc64],
322 [gl_cv_host_cpu_c_abi=sparc])
326 gl_cv_host_cpu_c_abi="$host_cpu"
331 dnl In most cases, $HOST_CPU and $HOST_CPU_C_ABI are the same.
332 HOST_CPU=`echo "$gl_cv_host_cpu_c_abi" | sed -e 's/-.*//'`
333 HOST_CPU_C_ABI="$gl_cv_host_cpu_c_abi"
335 AC_SUBST([HOST_CPU_C_ABI])
338 # AC_DEFINE_UNQUOTED([__${HOST_CPU}__])
339 # AC_DEFINE_UNQUOTED([__${HOST_CPU_C_ABI}__])
340 # earlier, but KAI C++ 3.2d doesn't like this.
341 sed -e 's/-/_/g' >> confdefs.h <<EOF
342 #ifndef __${HOST_CPU}__
343 #define __${HOST_CPU}__ 1
345 #ifndef __${HOST_CPU_C_ABI}__
346 #define __${HOST_CPU_C_ABI}__ 1
349 AH_TOP([/* CPU and C ABI indicator */
353 #ifndef __x86_64_x32__
354 #undef __x86_64_x32__
368 #ifndef __arm64_ilp32__
369 #undef __arm64_ilp32__
380 #ifndef __ia64_ilp32__
381 #undef __ia64_ilp32__
386 #ifndef __loongarch64__
387 #undef __loongarch64__
404 #ifndef __powerpc64__
407 #ifndef __powerpc64_elfv2__
408 #undef __powerpc64_elfv2__
416 #ifndef __riscv32_ilp32__
417 #undef __riscv32_ilp32__
419 #ifndef __riscv32_ilp32f__
420 #undef __riscv32_ilp32f__
422 #ifndef __riscv32_ilp32d__
423 #undef __riscv32_ilp32d__
425 #ifndef __riscv64_ilp32__
426 #undef __riscv64_ilp32__
428 #ifndef __riscv64_ilp32f__
429 #undef __riscv64_ilp32f__
431 #ifndef __riscv64_ilp32d__
432 #undef __riscv64_ilp32d__
434 #ifndef __riscv64_lp64__
435 #undef __riscv64_lp64__
437 #ifndef __riscv64_lp64f__
438 #undef __riscv64_lp64f__
440 #ifndef __riscv64_lp64d__
441 #undef __riscv64_lp64d__
463 dnl Sets the HOST_CPU_C_ABI_32BIT variable to 'yes' if the C language ABI
464 dnl (application binary interface) is a 32-bit one, to 'no' if it is a 64-bit
466 dnl This is a simplified variant of gl_HOST_CPU_C_ABI.
467 AC_DEFUN([gl_HOST_CPU_C_ABI_32BIT],
469 AC_REQUIRE([AC_CANONICAL_HOST])
470 AC_CACHE_CHECK([32-bit host C ABI], [gl_cv_host_cpu_c_abi_32bit],
473 # CPUs that only support a 32-bit ABI.
482 | microblaze | microblazeel \
483 | nds32 | nds32le | nds32be \
484 | nios2 | nios2eb | nios2el \
487 | sh | sh[1234] | sh[1234]e[lb] \
490 gl_cv_host_cpu_c_abi_32bit=yes
493 # CPUs that only support a 64-bit ABI.
495 alpha | alphaev[4-8] | alphaev56 | alphapca5[67] | alphaev6[78] \
498 gl_cv_host_cpu_c_abi_32bit=no
502 if test -n "$gl_cv_host_cpu_c_abi"; then
503 dnl gl_HOST_CPU_C_ABI has already been run. Use its result.
504 case "$gl_cv_host_cpu_c_abi" in
505 i386 | x86_64-x32 | arm | armhf | arm64-ilp32 | hppa | ia64-ilp32 | mips | mipsn32 | powerpc | riscv*-ilp32* | s390 | sparc)
506 gl_cv_host_cpu_c_abi_32bit=yes ;;
507 x86_64 | alpha | arm64 | aarch64c | hppa64 | ia64 | mips64 | powerpc64 | powerpc64-elfv2 | riscv*-lp64* | s390x | sparc64 )
508 gl_cv_host_cpu_c_abi_32bit=no ;;
510 gl_cv_host_cpu_c_abi_32bit=unknown ;;
513 gl_cv_host_cpu_c_abi_32bit=unknown
515 if test $gl_cv_host_cpu_c_abi_32bit = unknown; then
518 [[int test_pointer_size[sizeof (void *) - 5];
520 [gl_cv_host_cpu_c_abi_32bit=no],
521 [gl_cv_host_cpu_c_abi_32bit=yes])
527 HOST_CPU_C_ABI_32BIT="$gl_cv_host_cpu_c_abi_32bit"