0

I read several times, that Cortex-M4 does not support LDRD/STRD instructions. But when I try with gcc 13.2 I get these instructions. E.g. x3 = x1 for uint64_t gives:

ldrd    r2, [r0]        @ x1.0_1, x1
strd    r2, [r1]        @ x1.0_1, x3

Compiler options: -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -march=armv7e-m+fp -O3 -std=c++23 -fno-exceptions -fno-unwind-tables -fno -rtti -fno-threadsafe-statics -funsigned-char -funsigned-bitfields -fshort-enums -ffunction-sections -fdata-sections -fconcepts -ftemplate-depth=2048 -fstrict-aliasing

wimalopaan
  • 4,838
  • 1
  • 21
  • 39
  • According to this page, Cortex-M4 does support both instructions: https://developer.arm.com/documentation/ddi0439/b/Programmers-Model/Instruction-set-summary/Cortex-M4-instructions. Note that it seems these instruction does not perform atomic read/write: https://stackoverflow.com/questions/42651051/reading-a-64-bit-volatile-variable-on-cortex-m3, and that data needs to be aligned: https://stackoverflow.com/questions/67334962/arm-cortex-m4-ldrd-instruction-causing-hardfault. – Daniel Langr Aug 09 '23 at 09:10
  • Thanks. Is there a way to check from C / C++ what fundamental data-types are atomically read/write (I don't mean rmw-cycles). – wimalopaan Aug 09 '23 at 09:18
  • 3
    I don't think so (but I might be wrong). AFAIK, none of the fundamental data types are read/written atomically according to the C++ standard. That's why `std::atomic` and `std::atomic_ref` have been added. – Daniel Langr Aug 09 '23 at 09:20
  • Well, as you can see above, also 64-bit is read atomically. And all smaller types as well. – wimalopaan Aug 09 '23 at 09:22
  • One difference is that an `atomic` *has* to be read and written, while an ordinary variable can be kept in a register or moved out of a loop. It doesn't matter if store is atomic or not, if it is never actually stored. – BoP Aug 09 '23 at 09:26
  • @wimalopaan I don't think it is. Even compilers generate different machine code for atomic and non-atomic loads: https://godbolt.org/z/bs5z3E16n. The first one does not use `ldrd`. – Daniel Langr Aug 09 '23 at 09:45
  • "Is there a way to check" In C++, no fundamental data types are atomically read or write. However, you can atomically read or write to a suitably aligned fundamental type using std::atomic_ref. And when you do, it can tell you whether it will be lock free or not. – Jeff Garrett Aug 09 '23 at 12:40
  • You can check which types can be atomically used in C++ via `std::atomic::is_lockfree`, but you're supposed to use instances of `std::atomic` to invoke the atomic operations. If the `is_lockfree` method returns false, that means the atomic type will invoke complex code sequences, rather than some cheap single instruction operation. – Red.Wave Aug 09 '23 at 20:18
  • @DanielLangr: That's correct, even on AArch64, plain `uint64_t` isn't always atomic even in practice with GCC, as shown in *[Which types on a 64-bit computer are naturally atomic in gnu C and gnu C++? -- meaning they have atomic reads, and atomic writes](https://stackoverflow.com/q/71866535)*. Atomicity for types wider than a register (usually that means wider than `size_t`) won't happen even with `volatile`; you *need* `std::atomic` or GNU extensions like `__atomic_load_n`, or your own inline asm like the Linux kernel uses, to get the compiler to use special instructions. – Peter Cordes Aug 11 '23 at 06:04
  • `std::atomic` will let you detect whether what types have `is_always_lock_free == true`, for the others you need to know the target platform (and how GCC compiles for `__atomic` builtins) – Peter Cordes Aug 11 '23 at 06:06

1 Answers1

0

In section A3.5.3 of https://developer.arm.com/documentation/ddi0403/latest/ it clearly states, that LDRD/STRD or VLDR.64 are not single-copy atomic.

wimalopaan
  • 4,838
  • 1
  • 21
  • 39