Introduction
An atomic instruction reads a location, changes the value and writes it back, and no other write to that location can come between the read and the write. The Large System Extensions (FEAT_LSE, Armv8.1) added them as single instructions. Before that, code used the load-exclusive and store-exclusive loops on the Loads and stores page.
Each base name has a family of suffixes, and the table rows group them:
- no suffix: no ordering;
- a: the load has acquire ordering;
- l: the store has release ordering;
- al: both;
- b or h: the access is a byte or a halfword, placed after the ordering suffix. Without these it is a word or a doubleword, chosen by the register;
- p: a pair of registers, or a 128-bit operation;
- t: unprivileged access, explained below.
The usual operands are Rs, Rt, [Xn]. Rs holds the operand,
Rt receives the old value from memory, and Xn or
sp is the address, with no offset. The st forms are aliases
of the ld forms when the old value is not wanted: Rt is the
zero register and no acquire is requested.
Only the read-check-write group changes the flags.
The instructions
Compare and swap
These compare the value in memory with Rs. If equal, they write
Rt to memory. Rs always receives the value that was in
memory, so a success can be told from a failure by comparing it with the old
Rs.
| Mnemonic | Syntax | What it does | Flags |
|---|---|---|---|
cas, casa, casl, casal | cas Rs, Rt, [Xn] | Compare and swap of a word or doubleword. | – |
casb, casab, caslb, casalb | casb Ws, Wt, [Xn] | Compare and swap of a byte. | – |
cash, casah, caslh, casalh | cash Ws, Wt, [Xn] | Compare and swap of a halfword. | – |
casp, caspa, caspl, caspal | casp Rs, Rs+1, Rt, Rt+1, [Xn] | Compare and swap of two adjacent registers against two words or two doublewords. Each pair starts at an even register. | – |
Atomic operations
The new value is calculated from the old value in memory and Rs. The
ld forms return the old value in Rt. The st
forms discard it.
| Mnemonic | Syntax | What it does | Flags |
|---|---|---|---|
ldadd, ldadda, ldaddl, ldaddal, ldaddb, ldaddab, ldaddlb, ldaddalb, ldaddh, ldaddah, ldaddlh, ldaddalh | ldadd Rs, Rt, [Xn] | Atomic add. | – |
stadd, staddl, staddb, staddlb, staddh, staddlh | stadd Rs, [Xn] | Atomic add with no result. | – |
ldclr, ldclra, ldclrl, ldclral, ldclrb, ldclrab, ldclrlb, ldclralb, ldclrh, ldclrah, ldclrlh, ldclralh | ldclr Rs, Rt, [Xn] | Atomic bit clear: memory AND NOT Rs. | – |
stclr, stclrl, stclrb, stclrlb, stclrh, stclrlh | stclr Rs, [Xn] | Atomic bit clear with no result. | – |
ldeor, ldeora, ldeorl, ldeoral, ldeorb, ldeorab, ldeorlb, ldeoralb, ldeorh, ldeorah, ldeorlh, ldeoralh | ldeor Rs, Rt, [Xn] | Atomic exclusive OR. | – |
steor, steorl, steorb, steorlb, steorh, steorlh | steor Rs, [Xn] | Atomic exclusive OR with no result. | – |
ldset, ldseta, ldsetl, ldsetal, ldsetb, ldsetab, ldsetlb, ldsetalb, ldseth, ldsetah, ldsetlh, ldsetalh | ldset Rs, Rt, [Xn] | Atomic bit set: memory OR Rs. | – |
stset, stsetl, stsetb, stsetlb, stseth, stsetlh | stset Rs, [Xn] | Atomic bit set with no result. | – |
ldsmax, ldsmaxa, ldsmaxl, ldsmaxal, ldsmaxb, ldsmaxab, ldsmaxlb, ldsmaxalb, ldsmaxh, ldsmaxah, ldsmaxlh, ldsmaxalh | ldsmax Rs, Rt, [Xn] | Atomic signed maximum. | – |
stsmax, stsmaxl, stsmaxb, stsmaxlb, stsmaxh, stsmaxlh | stsmax Rs, [Xn] | Atomic signed maximum with no result. | – |
ldsmin, ldsmina, ldsminl, ldsminal, ldsminb, ldsminab, ldsminlb, ldsminalb, ldsminh, ldsminah, ldsminlh, ldsminalh | ldsmin Rs, Rt, [Xn] | Atomic signed minimum. | – |
stsmin, stsminl, stsminb, stsminlb, stsminh, stsminlh | stsmin Rs, [Xn] | Atomic signed minimum with no result. | – |
ldumax, ldumaxa, ldumaxl, ldumaxal, ldumaxb, ldumaxab, ldumaxlb, ldumaxalb, ldumaxh, ldumaxah, ldumaxlh, ldumaxalh | ldumax Rs, Rt, [Xn] | Atomic unsigned maximum. | – |
stumax, stumaxl, stumaxb, stumaxlb, stumaxh, stumaxlh | stumax Rs, [Xn] | Atomic unsigned maximum with no result. | – |
ldumin, ldumina, lduminl, lduminal, lduminb, lduminab, lduminlb, lduminalb, lduminh, lduminah, lduminlh, lduminalh | ldumin Rs, Rt, [Xn] | Atomic unsigned minimum. | – |
stumin, stuminl, stuminb, stuminlb, stuminh, stuminlh | stumin Rs, [Xn] | Atomic unsigned minimum with no result. | – |
swp, swpa, swpl, swpal, swpb, swpab, swplb, swpalb, swph, swpah, swplh, swpalh | swp Rs, Rt, [Xn] | Atomic swap: writes Rs to memory and returns the old value in Rt. | – |
128-bit atomics
These work on a 128-bit location, with each operand held in a pair of X registers.
| Mnemonic | Syntax | What it does | Flags |
|---|---|---|---|
ldclrp, ldclrpa, ldclrpl, ldclrpal | ldclrp Xs, Xt, [Xn] | Atomic bit clear on a quadword. | – |
ldsetp, ldsetpa, ldsetpl, ldsetpal | ldsetp Xs, Xt, [Xn] | Atomic bit set on a quadword. | – |
swpp, swppa, swppl, swppal | swpp Xs, Xt, [Xn] | Atomic swap of a quadword. | – |
Unprivileged atomics
These act like the instructions above but use lower privilege, as the unprivileged loads and stores on the Loads and stores page do. They let privileged code touch memory on behalf of a program, with that program’s access rights.
| Mnemonic | Syntax | What it does | Flags |
|---|---|---|---|
cast, casat, caslt, casalt | cast Xs, Xt, [Xn] | Unprivileged compare and swap of a doubleword. | – |
caspt, caspat, casplt, caspalt | caspt Xs, Xs+1, Xt, Xt+1, [Xn] | Unprivileged compare and swap of a pair of doublewords. | – |
ldtadd, ldtadda, ldtaddl, ldtaddal | ldtadd Rs, Rt, [Xn] | Unprivileged atomic add. | – |
ldtclr, ldtclra, ldtclrl, ldtclral | ldtclr Rs, Rt, [Xn] | Unprivileged atomic bit clear. | – |
ldtset, ldtseta, ldtsetl, ldtsetal | ldtset Rs, Rt, [Xn] | Unprivileged atomic bit set. | – |
swpt, swpta, swptl, swptal | swpt Rs, Rt, [Xn] | Unprivileged atomic swap. | – |
ldtxr, ldatxr | ldtxr Rt, [Xn] | Unprivileged load-exclusive. ldatxr has acquire ordering. | – |
sttxr, stltxr | sttxr Ws, Rt, [Xn] | Unprivileged store-exclusive. Ws is 0 if the store happened and 1 if not. stltxr has release ordering. | – |
Floating-point atomics
These do a floating-point operation on memory, in the same shape as the integer
atomics. ldf and stf work on h,
s and d registers. ldbf and stbf
work on BFloat16 values, in h registers. Those on the same row differ only in ordering.
| Mnemonic | Syntax | What it does | Flags |
|---|---|---|---|
ldfadd, ldfadda, ldfaddl, ldfaddal | ldfadd Hs, Ht, [Xn] | Atomic floating-point add. | – |
ldfmax, ldfmaxa, ldfmaxl, ldfmaxal | ldfmax Hs, Ht, [Xn] | Atomic floating-point maximum. | – |
ldfmaxnm, ldfmaxnma, ldfmaxnml, ldfmaxnmal | ldfmaxnm Hs, Ht, [Xn] | Atomic floating-point maximum number. | – |
ldfmin, ldfmina, ldfminl, ldfminal | ldfmin Hs, Ht, [Xn] | Atomic floating-point minimum. | – |
ldfminnm, ldfminnma, ldfminnml, ldfminnmal | ldfminnm Hs, Ht, [Xn] | Atomic floating-point minimum number. | – |
stfadd, stfaddl, stfmax, stfmaxl, stfmaxnm, stfmaxnml, stfmin, stfminl, stfminnm, stfminnml | stfadd Hs, [Xn] | The same five operations with no result. | – |
ldbfadd, ldbfadda, ldbfaddl, ldbfaddal | ldbfadd Hs, Ht, [Xn] | Atomic BFloat16 add. | – |
ldbfmax, ldbfmaxa, ldbfmaxl, ldbfmaxal | ldbfmax Hs, Ht, [Xn] | Atomic BFloat16 maximum. | – |
ldbfmaxnm, ldbfmaxnma, ldbfmaxnml, ldbfmaxnmal | ldbfmaxnm Hs, Ht, [Xn] | Atomic BFloat16 maximum number. | – |
ldbfmin, ldbfmina, ldbfminl, ldbfminal | ldbfmin Hs, Ht, [Xn] | Atomic BFloat16 minimum. | – |
ldbfminnm, ldbfminnma, ldbfminnml, ldbfminnmal | ldbfminnm Hs, Ht, [Xn] | Atomic BFloat16 minimum number. | – |
stbfadd, stbfaddl, stbfmax, stbfmaxl, stbfmaxnm, stbfmaxnml, stbfmin, stbfminl, stbfminnm, stbfminnml | stbfadd Hs, [Xn] | The same five BFloat16 operations with no result. | – |
Read-check-write
These are for updating translation table entries, not for general use. Each one
writes to memory only if a set of checks on the new value pass. The
rcws forms add further checks. These instructions set the condition
flags from the outcome. The rows with a p work on a 128-bit location,
using pairs of registers.
| Mnemonic | Syntax | What it does | Flags |
|---|---|---|---|
rcwcas, rcwcasa, rcwcasl, rcwcasal | rcwcas Xs, Xt, [Xn] | Checked compare and swap of a doubleword. | NZCV |
rcwcasp, rcwcaspa, rcwcaspl, rcwcaspal | rcwcasp Xs, Xs+1, Xt, Xt+1, [Xn] | Checked compare and swap of a quadword. | NZCV |
rcwclr, rcwclra, rcwclrl, rcwclral | rcwclr Xs, Xt, [Xn] | Checked atomic bit clear of a doubleword. | NZCV |
rcwclrp, rcwclrpa, rcwclrpl, rcwclrpal | rcwclrp Xs, Xt, [Xn] | Checked atomic bit clear of a quadword. | NZCV |
rcwset, rcwseta, rcwsetl, rcwsetal | rcwset Xs, Xt, [Xn] | Checked atomic bit set of a doubleword. | NZCV |
rcwsetp, rcwsetpa, rcwsetpl, rcwsetpal | rcwsetp Xs, Xt, [Xn] | Checked atomic bit set of a quadword. | NZCV |
rcwswp, rcwswpa, rcwswpl, rcwswpal | rcwswp Xs, Xt, [Xn] | Checked swap of a doubleword. | NZCV |
rcwswpp, rcwswppa, rcwswppl, rcwswppal | rcwswpp Xs, Xt, [Xn] | Checked swap of a quadword. | NZCV |
rcwscas, rcwscasa, rcwscasl, rcwscasal | rcwscas Xs, Xt, [Xn] | As rcwcas, with the further software checks. | NZCV |
rcwscasp, rcwscaspa, rcwscaspl, rcwscaspal | rcwscasp Xs, Xs+1, Xt, Xt+1, [Xn] | As rcwcasp, with the further software checks. | NZCV |
rcwsclr, rcwsclra, rcwsclrl, rcwsclral | rcwsclr Xs, Xt, [Xn] | As rcwclr, with the further software checks. | NZCV |
rcwsclrp, rcwsclrpa, rcwsclrpl, rcwsclrpal | rcwsclrp Xs, Xt, [Xn] | As rcwclrp, with the further software checks. | NZCV |
rcwsset, rcwsseta, rcwssetl, rcwssetal | rcwsset Xs, Xt, [Xn] | As rcwset, with the further software checks. | NZCV |
rcwssetp, rcwssetpa, rcwssetpl, rcwssetpal | rcwssetp Xs, Xt, [Xn] | As rcwsetp, with the further software checks. | NZCV |
rcwsswp, rcwsswpa, rcwsswpl, rcwsswpal | rcwsswp Xs, Xt, [Xn] | As rcwswp, with the further software checks. | NZCV |
rcwsswpp, rcwsswppa, rcwsswppl, rcwsswppal | rcwsswpp Xs, Xt, [Xn] | As rcwswpp, with the further software checks. | NZCV |
64-byte access
These read or write eight consecutive X registers as one single-copy atomic 64-byte access, on memory that supports it. The address must be 64-byte aligned. Which memory locations support them is implementation defined.
| Mnemonic | Syntax | What it does | Flags |
|---|---|---|---|
ld64b | ld64b Xt, [Xn] | Loads 64 bytes into Xt to Xt+7. | – |
st64b | st64b Xt, [Xn] | Stores 64 bytes from Xt to Xt+7. | – |
st64bv | st64bv Xs, Xt, [Xn] | Stores 64 bytes and writes a status to Xs. | – |
st64bv0 | st64bv0 Xs, Xt, [Xn] | Stores 64 bytes with the low 32 bits taken from ACCDATA_EL1, and writes a status to Xs. | – |
RCpc loads and unscaled ordered access
ldapr is a load-acquire with weaker ordering than ldar,
called RCpc: a load-acquire of this kind need not wait for an earlier store-release
to a different address.
| Mnemonic | Syntax | What it does | Flags |
|---|---|---|---|
ldapr, ldaprb, ldaprh | ldapr Rt, [Xn] | RCpc load-acquire of a word or doubleword, a byte or a halfword. The post-index form is on the Loads and stores page. | – |
ldapur, ldapurb, ldapurh | ldapur Rt, [Xn, #imm] | RCpc load-acquire with a signed 9-bit byte offset. | – |
ldapursb, ldapursh, ldapursw | ldapursb Rt, [Xn, #imm] | The same, sign-extending a byte, halfword or word. | – |
stlur, stlurb, stlurh | stlur Rt, [Xn, #imm] | Store-release with a signed 9-bit byte offset. | – |
ldiapp | ldiapp Rt1, Rt2, [Xn]; ldiapp Rt1, Rt2, [Xn], #size | Loads a pair with RCpc load-acquire ordering. There is also a post-index form. | – |
stilp | stilp Rt1, Rt2, [Xn]; stilp Rt1, Rt2, [Xn, #-size]! | Stores a pair with release ordering. There is also a pre-index form. | – |
Links
Reference
- Arm A64 Instruction Set Architecture – Arm’s description of each A64 instruction
- Arm Architecture Reference Manual for A-profile – the full architecture specification