arch
—
Architecture-specific details
Differences between CPU architectures and platforms supported by
FreeBSD.
This document is a quick reference of key ABI details of
FreeBSD architecture ports. For full details consult
the processor-specific ABI supplement documentation.
If not explicitly mentioned, sizes are in bytes. The architecture details in
this document apply to
FreeBSD 10.0 and later, unless
otherwise noted.
FreeBSD uses a flat address space. Variables of types
unsigned long,
uintptr_t, and
size_t and pointers all have the same
representation.
In order to maximize compatibility with future pointer integrity mechanisms,
manipulations of pointers as integers should be performed via
uintptr_t or
intptr_t and no other types. In particular,
long and
ptrdiff_t should be avoided.
On some architectures, e.g.,
sparc64
,
powerpc
and AIM variants of
powerpc64
, the kernel uses a separate
address space. On other architectures, kernel and a user mode process share a
single address space. The kernel is located at the highest addresses.
On each architecture, the main user mode thread's stack starts near the highest
user address and grows down.
FreeBSD architecture support varies by release. This
table shows the first
FreeBSD release to support each
architecture, and, for discontinued architectures, the final release.
Architecture |
Initial Release |
Final Release |
aarch64 |
11.0 |
alpha |
3.2 |
6.4 |
amd64 |
5.1 |
arm |
6.0 |
armeb |
8.0 |
11.x |
armv6 |
10.0 |
armv7 |
12.0 |
ia64 |
5.0 |
10.x |
i386 |
1.0 |
mips |
8.0 |
mipsel |
9.0 |
mipselhf |
12.0 |
mipshf |
12.0 |
mipsn32 |
9.0 |
mips64 |
9.0 |
mips64el |
9.0 |
mips64elhf |
12.0 |
mips64hf |
12.0 |
pc98 |
2.2 |
11.x |
powerpc |
6.0 |
powerpcspe |
12.0 |
powerpc64 |
6.0 |
riscv64 |
12.0 |
riscv64sf |
12.0 |
sparc64 |
5.0 |
All
FreeBSD architectures use some variant of the ELF
(see
elf(5))
Application Binary Interface (ABI) for the
machine processor. All supported ABIs can be divided into two groups:
ILP32
- int,
long, void
* types machine representations all have 4-byte size.
LP64
- int type machine representation uses 4
bytes, while long and
void * are 8 bytes.
Compilers define the
_LP64
symbol when
compiling for an
LP64
ABI.
Some machines support more that one
FreeBSD ABI.
Typically these are 64-bit machines, where the “native”
LP64
execution environment is accompanied
by the “legacy”
ILP32
environment, which was historical 32-bit predecessor for 64-bit evolution.
Examples are:
aarch64
currently does not support execution
of
armv6
or
armv7
binaries, even if the CPU implements
AArch32
execution state.
On all supported architectures:
Type |
Size |
short |
2 |
int |
4 |
long |
sizeof(void*) |
long long |
8 |
float |
4 |
double |
8 |
Integers are represented in two's complement. Alignment of integer and pointer
types is natural, that is, the address of the variable must be congruent to
zero modulo the type size. Most ILP32 ABIs, except
arm
, require only 4-byte alignment for
64-bit integers.
Machine-dependent type sizes:
Architecture |
void * |
long double |
time_t |
aarch64 |
8 |
16 |
8 |
amd64 |
8 |
16 |
8 |
arm |
4 |
8 |
8 |
armv6 |
4 |
8 |
8 |
i386 |
4 |
12 |
4 |
mips |
4 |
8 |
8 |
mipsel |
4 |
8 |
8 |
mipselhf |
4 |
8 |
8 |
mipshf |
4 |
8 |
8 |
mipsn32 |
4 |
8 |
8 |
mips64 |
8 |
8 |
8 |
mips64el |
8 |
8 |
8 |
mips64elhf |
8 |
8 |
8 |
mips64hf |
8 |
8 |
8 |
powerpc |
4 |
8 |
8 |
powerpcspe |
4 |
8 |
8 |
powerpc64 |
8 |
8 |
8 |
riscv64 |
8 |
16 |
8 |
riscv64sf |
8 |
16 |
8 |
sparc64 |
8 |
16 |
8 |
time_t is 8 bytes on all supported architectures
except i386.
Architecture |
Endianness |
char Signedness |
aarch64 |
little |
unsigned |
amd64 |
little |
signed |
arm |
little |
unsigned |
armv6 |
little |
unsigned |
armv7 |
little |
unsigned |
i386 |
little |
signed |
mips |
big |
signed |
mipsel |
little |
signed |
mipselhf |
little |
signed |
mipshf |
big |
signed |
mipsn32 |
big |
signed |
mips64 |
big |
signed |
mips64el |
little |
signed |
mips64elhf |
little |
signed |
mips64hf |
big |
signed |
powerpc |
big |
unsigned |
powerpcspe |
big |
unsigned |
powerpc64 |
big |
unsigned |
riscv64 |
little |
signed |
riscv64sf |
little |
signed |
sparc64 |
big |
signed |
Architecture |
Page Sizes |
aarch64 |
4K, 2M, 1G |
amd64 |
4K, 2M, 1G |
arm |
4K |
armv6 |
4K, 1M |
armv7 |
4K, 1M |
i386 |
4K, 2M (PAE), 4M |
mips |
4K |
mipsel |
4K |
mipselhf |
4K |
mipshf |
4K |
mipsn32 |
4K |
mips64 |
4K |
mips64el |
4K |
mips64elhf |
4K |
mips64hf |
4K |
powerpc |
4K |
powerpcspe |
4K |
powerpc64 |
4K |
riscv64 |
4K |
riscv64sf |
4K |
sparc64 |
8K |
Architecture |
float, double |
long double |
aarch64 |
hard |
soft, quad precision |
amd64 |
hard |
hard, 80 bit |
arm |
soft |
soft, double precision |
armv6 |
hard(1) |
hard, double precision |
armv7 |
hard(1) |
hard, double precision |
i386 |
hard |
hard, 80 bit |
mips |
soft |
identical to double |
mipsel |
soft |
identical to double |
mipselhf |
hard |
identical to double |
mipshf |
hard |
identical to double |
mipsn32 |
soft |
identical to double |
mips64 |
soft |
identical to double |
mips64el |
soft |
identical to double |
mips64elhf |
hard |
identical to double |
mips64hf |
hard |
identical to double |
powerpc |
hard |
hard, double precision |
powerpcspe |
hard |
hard, double precision |
powerpc64 |
hard |
hard, double precision |
riscv64 |
hard |
hard, double precision |
riscv64sf |
soft |
soft, double precision |
sparc64 |
hard |
hard, quad precision |
(1) Prior to
FreeBSD 11.0, armv6 used the softfp ABI
even though it supported only processors with a floating point unit.
The compiler provides a number of predefined macros. Some of these provide
architecture-specific details and are explained below. Other macros, including
those required by the language standard, are not included here.
The full set of predefined macros can be obtained with this command:
Common type size and endianness macros:
Macro |
Meaning |
__LP64__ |
64-bit (8-byte) long and pointer, 32-bit (4-byte) int |
__ILP32__ |
32-bit (4-byte) int, long and pointer |
BYTE_ORDER |
Either BIG_ENDIAN or
LITTLE_ENDIAN .
PDP11_ENDIAN is not used on
FreeBSD. |
Architecture-specific macros:
Architecture |
Predefined macros |
aarch64 |
__aarch64__ |
amd64 |
__amd64__,
__x86_64__ |
arm |
__arm__ |
armv6 |
__arm__,
__ARM_ARCH >= 6 |
armv7 |
__arm__,
__ARM_ARCH >= 7 |
i386 |
__i386__ |
mips |
__mips__,
__MIPSEB__,
__mips_o32 |
mipsel |
__mips__,
__mips_o32 |
mipselhf |
__mips__,
__mips_o32 |
mipshf |
__mips__,
__MIPSEB__,
__mips_o32 |
mipsn32 |
__mips__,
__MIPSEB__,
__mips_n32 |
mips64 |
__mips__,
__MIPSEB__,
__mips_n64 |
mips64el |
__mips__,
__mips_n64 |
mips64elhf |
__mips__,
__mips_n64 |
mips64hf |
__mips__,
__MIPSEB__,
__mips_n64 |
powerpc |
__powerpc__ |
powerpcspe |
__powerpc__,
__SPE__ |
powerpc64 |
__powerpc__,
__powerpc64__ |
riscv64 |
__riscv,
__riscv_xlen == 64 |
riscv64sf |
__riscv,
__riscv_xlen == 64 |
sparc64 |
__sparc64__ |
Compilers may define additional variants of architecture-specific macros. The
macros above are preferred for use in
FreeBSD.
Important
make(1)
variables
Most of the externally settable variables are defined in the
build(7)
man page. These variables are not otherwise documented and are used
extensively in the build system.
MACHINE |
Represent the hardware platform. This is the same as the native
platform's
uname(1)
-m output. It defines both the userland
/ kernel interface, as well as the bootloader / kernel interface. It
should only be used in these contexts. Each CPU architecture may have
multiple hardware platforms it supports where
MACHINE differs among them. It is used
to collect together all the files from
config(8)
to build the kernel. It is often the same as
MACHINE_ARCH just as one CPU
architecture can be implemented by many different hardware platforms, one
hardware platform may support multiple CPU architecture family members,
though with different binaries. For example,
MACHINE of i386 supported the IBM-AT
hardware platform while the MACHINE of
pc98 supported the Japanese company NEC's PC-9801 and PC-9821 hardware
platforms. Both of these hardware platforms supported only the
MACHINE_ARCH of i386 where they shared
a common ABI, except for certain kernel / userland interfaces relating to
underlying hardware platform differences in bus architecture, device
enumeration and boot interface. Generally,
MACHINE should only be used in src/sys
and src/stand or in system imagers or installers. |
MACHINE_ARCH |
Represents the CPU processor architecture. This is the same as the
native platforms
uname(1)
-p output. It defines the CPU
instruction family supported. It may also encode a variation in the byte
ordering of multi-byte integers (endian). It may also encode a variation
in the size of the integer or pointer. It may also encode a ISA revision.
It may also encode hard versus soft floating point ABI and usage. It may
also encode a variant ABI when the other factors do not uniquely define
the ABI (e.g., MIPS' n32 ABI). It, along with
MACHINE , defines the ABI used by the
system. For example, the MIPS CPU processor family supports 9 different
combinations encoding pointer size, endian and hard versus soft float (for
8 combinations) as well as N32 (which only ever had one variation of all
these). Generally, the plain CPU name specifies the most common (or at
least first) variant of the CPU. This is why mips and mips64 imply 'big
endian' while 'arm' and 'armv7' imply little endian. If we ever were to
support the so-called x32 ABI (using 32-bit pointers on the amd64
architecture), it would most likely be encoded as amd64-x32. It is
unfortunate that amd64 specifies the 64-bit evolution of the x86 platform
(it matches the 'first rule') as everybody else uses x86_64. There is no
standard name for the processor: each OS selects its own conventions. |
MACHINE_CPUARCH |
Represents the source location for a given
MACHINE_ARCH . For example,
MACHINE_CPUARCH is defined to be mips
for all the flavors of mips that we support since we support them all with
a shared set of sources. While amd64 and i386 are closely related,
MACHINE_CPUARCH is not x86 for them. The FreeBSD source base supports
amd64 and i386 with two distinct source bases living in subdirectories
named amd64 and i386 (though behind the scenes there's some sharing that
fits into this framework). |
CPUTYPE |
Sets the flavor of MACHINE_ARCH to
build. It is used to optimize the build for a specific CPU / core that the
binaries run on. Generally, this does not change the ABI, though it can be
a fine line between optimization for specific cases. |
TARGET |
Used to set MACHINE in the top level
Makefile for cross building. Unused outside of that scope. It is not
passed down to the rest of the build. Makefiles outside of the top level
should not use it at all (though some have their own private copy for
hysterical raisons). |
TARGET_ARCH |
Used to set MACHINE_ARCH by the top
level Makefile for cross building. Like
TARGET , it
is unused outside of that scope. |
src.conf(5),
build(7)
An
arch
manual page appeared in
FreeBSD 12.