# ARM64 atomics assembly survey This survey only concerns header files that are involved in atomic operations. *commit `ae8b3a83fb9de394f609035041cd7a668fda2ab3`* ## Headers of interest - `arch/arm64/include/asm/atomic.h` which includes - `arch/arm64/include/asm/cmpxchg.h` - `arch/arm64/include/asm/lse.h` - `arch/arm64/include/asm/atomic-ll-sc.h` - `arch/arm64/include/asm/barrier.h` ## Syntactical variants in use ### Key operand modifiers The following translation is derived from [Rust reference on inline assembly](https://doc.rust-lang.org/stable/reference/inline-assembly.html#r-asm.template-modifiers.supported-modifiers). #### .. on Output - `=r` - corresponds to Rust `lateout(reg)` - `=&r` - corresponds to Rust `out(reg)` - `+&r` - corresponds to Rust `inout(reg)` - `=Q` - specific to AArch64 - discard existing value in memory reference - corresponds to Rust `latein(reg)` with *rewrite* into a memref - Translation needs to know assembly dialect, which is Intel syntax mostly - Let's say it is translated into `[{..}]` - `+Q` - specific to AArch64 - may use existing value in memory reference - corresponds to Rust `latein(reg)` with *rewrite* into a memref - Translation needs to know assembly dialect #### .. on Input - `rZ` - This is specific to some machine like AArch64 - ... which is just `xzr`/`wzr` - Requires rewrite into Rust dialect, in this case just replacing it with `xzr`/`wzr` - `r` - well... register - one of {`I`,`J`,`K`,`L`} + `r`: See `atomic_ll_sc.h` - This is specific to AArch64 - Modifies the size of immediate value - There is no clear Rust equivalent - In fact, when `Ir` or `rI` is specified, LLVM prefers to consider inserting an immediate of width `I/J/K/L` first, then a register as per `r` second - `I` has higher precedence over `r` - See `llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp` ... - `TargetLowering::getConstraintPreferences` called by ... - `TargetLowering::ComputeConstraintToUse` called by ... - `llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp`: `SelectionDAGBuilder::visitInlineAsm` whose purpose is quite clear - It is safe to translate it into `r`-equivalent constraint, unless benchmarks show deficiency. ### Clobbers - *einfach nix* - Translates to Rust `options(nomem, pure)` - `memory` - Rust has this by default, opt out with `options(nomem)` - `cc` + `memory` - `atomic_ll_sc`, e.g. `__ll_sc_atomic64_dec_if_positive` - `cc` maps to `options(preserve_flags)` - **we probably should add `options(nostack)`** # Categories of C operands ## Input - uninitized ... - `unsigned long` temporaries with `=&r` - counter like `v->counter` where `v` is `atomic_t*` - `+Q` ## Output Simple place expression really, either being pointer to a place or a variable used for return value. # Observation ## asm blocks appears in various context - it can be fully expanded into `static inline` functions; - we probably already link into today with `helpers` - it can be embedded in `do`-expression blocks, in a macro - we can similarly materialise them, too