---
# System prepended metadata

title: ARM64 atomics assembly survey

---

# 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
