Document RFC 2867: instruction_set attribute by xd009642 · Pull Request #1253 · rust-lang/reference (original) (raw)
So first minor point: ARMv? (with a v
) and ARM? (without a v
) are different numbering systems, because of course. So, if you go looking up details about this stuff keep that in mind.
Starting with ARMv4T and onward, ARM CPUs support a system called "interworking". This is currently what the instruction_set
attribute is all about. I'm told that theoretically MIPS also has some sort of system where the instruction_set
attribute would be appropriate, but I was told that once ever in passing so we can reasonably treat this attribute at ARM only for now.
Interworking is available in most ARM architectures that came after ARMv4T, but not all of them.
I had to go double check on wikipedia:
All ARMv7 chips support the Thumb instruction set. All chips in the Cortex-A series, Cortex-R series, and ARM11 series support both "ARM instruction set state" and "Thumb instruction set state", while chips in the Cortex-M series support only the Thumb instruction set.
Looking at Rust's target list, thumbv6m-none-eabi
is described as "Bare Cortex-M0, M0+, M1", so I have to assume that you should not use the instruction_set
attribute on that target to set a function for a32
code. However, it's still logically consistent to set a function for t32
on a Cortex-M. That's already the default, and you'd basically be just more strongly re-stating that.
In terms of what you can check with cfg
at compile time, beyond target_arch="arm"
, there's also target_feature = "thumb-mode"
which at least tells you the default code mode.
As far as I know, there isn't a specific way to check for the presence of interworking. If I ask rustc what it thinks about the thumbv4t-none-eabi
target:
$ rustc --print cfg --target thumbv4t-none-eabi
debug_assertions
panic="abort"
target_abi="eabi"
target_arch="arm"
target_endian="little"
target_env=""
target_feature="llvm14-builtins-abi"
target_feature="thumb-mode"
target_has_atomic_equal_alignment="16"
target_has_atomic_equal_alignment="32"
target_has_atomic_equal_alignment="8"
target_has_atomic_equal_alignment="ptr"
target_has_atomic_load_store="16"
target_has_atomic_load_store="32"
target_has_atomic_load_store="8"
target_has_atomic_load_store="ptr"
target_os="none"
target_pointer_width="32"
target_vendor="unknown"
Which... sure doesn't seem to indicate if interworking is specifically allowed.
I know that the assembler knows if it's assembling interworking code (example, but I don't know if rustc lets you know this in any way.
But if we go check the thumbv6m-none-eabi
target we see:
$ rustc --print cfg --target thumbv6m-none-eabi
debug_assertions
panic="abort"
target_abi="eabi"
target_arch="arm"
target_endian="little"
target_env=""
target_feature="llvm14-builtins-abi"
target_feature="mclass"
target_feature="thumb-mode"
target_feature="v5te"
target_feature="v6"
target_has_atomic_equal_alignment="16"
target_has_atomic_equal_alignment="32"
target_has_atomic_equal_alignment="8"
target_has_atomic_equal_alignment="ptr"
target_has_atomic_load_store="16"
target_has_atomic_load_store="32"
target_has_atomic_load_store="8"
target_has_atomic_load_store="ptr"
target_os="none"
target_pointer_width="32"
target_vendor="unknown"
So we can probably say that if target_feature="mclass"
is set then you should not try interworking.
@xd009642 how does the rustc
decide if the attribute is allowed?