cas
Compare and swap with operand
Compares a data register with an operand in memory, and writes a second register there only if they are equal.
Sizes .b .w .l, .w by default68020 only: select opt p=68020 before any code or data
- ● set from the result
- – not changed
Forms
Operands
Dn- A data register,
d0tod7. More <ea>- An operand using one of the addressing modes listed for this form. The list determines whether it can be a register, memory or an immediate value. With
opt p=68020, an allowedd(An,Xn)ord(PC,Xn)mode also permits the corresponding 68020 indexed and memory indirect forms. See 68020 addressing. More
cas.l d0, d1, (a0) compares d0 with the long at a0. If they match, it writes d1 there. Otherwise, it copies the memory value into d0 and leaves memory unchanged.
N, Z, V and C describe memory minus the compare register, at the selected size. X is unchanged. Z is set on success, so beq after cas branches when the update was written. On failure, a byte or word copied into the compare register preserves its upper bits.
The read, comparison and write form one indivisible step, including with respect to interrupts. To update a shared value, read it into the compare register, calculate a new value in the update register, then use cas to store it only if memory still holds the value read. If it fails, retry with the value returned in the compare register. cas2 updates two values together.
opt p=68020
* --- Add 5 to a counter that an interrupt handler could also change ---
lea counter, a0
retry:
move.l (a0), d0 ; the value read
move.l d0, d1
addq.l #5, d1 ; the value wanted
cas.l d0, d1, (a0) ; write d1 only if the counter still holds d0
bne retry ; it changed in between: try again
move.l counter, d2 ; d2 = 15
bra END
counter:
dc.l 10
END: