cas

Compare and swap with operand 68020

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

XNZVC –●●●●
  • ● set from the result
  • – not changed

Forms

Operands

Dn
A data register, d0 to d7. 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 allowed d(An,Xn) or d(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: