assemblyatomicriscv

Risc-V atomic instructions


I have this definition of the amoswap amoswap.w rd,rs2,(rs1):

"atomically load a 32-bit signed data value from the address in rs1, place the value into register rd, swap the loaded value and the original 32-bit signed value in rs2, then store the result back to the address in rs1."

When I implement it like this amoswap t0,t0,0(a0) and let's say t0 = 1 and a0 is 0, what will a0 be after the instruction?


Solution

  • If, by typo, you mean to ask, "what will the value of t0 be after the instruction executes?" then the answer is that t0 will contain the value of the memory location pointed to by a0.

    In other words, after amoswap.w t0, t0, (a0) executes, with t0 initially 1, and a0 initially 0, then t0 will be the value at memory location 0x0 before the swap, and the memory location 0x0 will then contain the value 1.

    Note that there is no immediate offset like 0(a0) in the amoxxx instructions; short 12-bit immediate constant offsets only appear on the load and store instructions lw rd, imm11:0 and sw rd, imm11:0, respectively.

    An atomic operation is a trio of steps read, modify, and write (or, load, operate, and store) in that order and with no interruptions or re-ordering allowed in the instruction or data paths.

    In general, register rd is the result of the load, and does not reflect the operation of the specific amoxxx operation in any way. Further, the atomic operation is performed with an internal copy of the memory location loaded, not with the value placed in register rd. In other words, specifying x[0] (aka., 'zero') for rd won't have any effect on the atomic nature of the read-modify-write process; only the loaded value would go into the bit bucket, so to speak.

    In section 8.3 of the Unprivileged RISC-V Spec it is stated that "... AMO instructions atomically load a data value from the address in rs1, place the value into register rd, apply a binary operator to the loaded value and the original value in rs2, then store the result back to the address in rs1."

    In the amoxxx entries of Appendix A of The RISC-V Reader it is said, for example in case of amoand.w, "Atomically, let t be the value of the memory word at address x[rs1], then set this memory word to the bitwise AND of t and x[rs2]. Set x[rd] to the sign extension of t.

    The instruction expressions in the amoxxx entries of Appendix A of The RISC-V Reader appear to give a slightly different impression, but this appearance is only perceived. For example in case of amoand.w, "x[rd] = AMO32(M[x[rs1]] & x[rs2])". This seems to indicate that the value of register rd is the result of the atomic operation rather than simply the value before it has been performed. However, the way that macro AMO32(...) and, by extension, AMO64(...) are written, they have visibility into the originally loaded value of M[...] and, thus, pass that initial value through, unaltered in any way, as the macro's return value into the value of register x[rd].