This is a PR for thumbv6-none-eabi (bere-metal Armv6k in Thumb mode)
which proposed to be added by
https://github.com/rust-lang/rust/pull/150138.
Armv6k supports atomic instructions, but they are unavailable in Thumb
mode unless Thumb-2 instructions available (v6t2).
Using Thumb interworking (can be used via `#[instruction_set]`) allows
us to use these instructions even from Thumb mode without Thumb-2
instructions, but LLVM does not implement that processing (as of LLVM
21), so this PR implements it in compiler-builtins.
The code around `__sync` builtins is basically copied from
`arm_linux.rs` which uses kernel_user_helpers for atomic implementation.
The atomic implementation is a port of my [atomic-maybe-uninit inline
assembly code].
This PR has been tested on QEMU 10.2.0 using patched compiler-builtins
and core that applied the changes in this PR and
https://github.com/rust-lang/rust/pull/150138 and the [portable-atomic
no-std test suite] (can be run with `./tools/no-std.sh
thumbv6-none-eabi` on that repo) which tests wrappers around
`core::sync::atomic`. (Note that the target-spec used in test sets
max-atomic-width to 32 and atomic_cas to true, unlike the current
https://github.com/rust-lang/rust/pull/150138.) The original
atomic-maybe-uninit implementation has been tested on real Arm hardware.
(Note that Armv6k also supports 64-bit atomic instructions, but they are
skipped here. This is because there is no corresponding code in
`arm_linux.rs` (since the kernel requirements increased in 1.64, it may
be possible to implement 64-bit atomics there as well. see also
https://github.com/taiki-e/portable-atomic/pull/82), the code becomes
more complex than for 32-bit and smaller atomics.)
[atomic-maybe-uninit inline assembly code]: https://github.com/taiki-e/atomic-maybe-uninit/blob/HEAD/src/arch/arm.rs
[portable-atomic no-std test suite]: https://github.com/taiki-e/portable-atomic/tree/HEAD/tests/no-std-qemu
The `rustc` probe done in our build scripts needs to pass `--target` to
get the correct configuration, which usually comes from the `TARGET`
environment variable. However, for targets specified via a `target.json`
file, `TARGET` gets set to the file name without an extension or path.
`rustc` will check a search path to attempt to locate the file, but this
is likely to fail since the directory where Cargo invokes build scripts
(and hence where those scripts invoke `rustc`) might not have any
relation to the JSON spec file.
Resolve this for now by leaving `f16` and `f128` disabled if the `rustc`
command fails. Result of the discussion at CARGO-14208 may eventually
provide a better solution.
A CI test is also added since custom JSON files are an edge case that
could fail in other ways. I verified this fails without the fix here.
The JSON file is the output for `thumbv7em-none-eabi`, just renamed so
`rustc` doesn't identify it.
Get performance closer to the glibc implementations by adding assembly
fma routines, with runtime feature detection so they are used even if
not compiled with `+fma` (as the distributed standard library is often
not). Glibc uses ifuncs, this implementation stores a function pointer
in an atomic.
Results of CPU flags are also cached in order to avoid repeating the
startup time in calls to different functions. The feature detection code
is a slightly simplified version of `std-detect`.
Musl sources were used as a reference [1].
Fixes: https://github.com/rust-lang/rust/issues/140452 once synced
[1]: c47ad25ea3/src/math/x32/fma.c
Update `run.sh` to start testing `libm`. Currently this is somewhat
inefficient because `builtins-test` gets run more than once on some
targets; this can be cleaned up later.
Distribute everything from `libm/` to better locations in the repo.
`libm/libm/*` has not moved yet to avoid Git seeing the move as an edit
to `Cargo.toml`.
Files that remain to be merged somehow are in `etc/libm`.