csrrs
Atomic Read and Set Bits in CSR
This instruction is defined by:
-
Zicsr, version >= 0
This instruction is included in the following profiles:
Synopsis
Atomically read and set bits in a CSR.
Reads the value of the CSR, zero-extends the value to XLEN
bits,
and writes it to integer register rd
. The initial value in integer
register rs1
is treated as a bit mask that specifies bit positions
to be set in the CSR. Any bit that is high in rs1
will cause the
corresponding bit to be set in the CSR, if that CSR bit is writable.
Other bits in the CSR are not explicitly written.
Decode Variables
Bits<12> csr = $encoding[31:20];
Bits<5> rs1 = $encoding[19:15];
Bits<5> rd = $encoding[11:7];
Execution
-
IDL
-
Sail
XReg initial_csr_value = CSR[csr].sw_read();
XReg mask = X[rs1];
CSR[csr].sw_write(initial_csr_value | mask);
X[rd] = initial_csr_value;
{
let rs1_val : xlenbits = if is_imm then zero_extend(rs1) else X(rs1);
let isWrite : bool = match op {
CSRRW => true,
_ => if is_imm then unsigned(rs1_val) != 0 else unsigned(rs1) != 0
};
if not(check_CSR(csr, cur_privilege, isWrite))
then { handle_illegal(); RETIRE_FAIL }
else if not(ext_check_CSR(csr, cur_privilege, isWrite))
then { ext_check_CSR_fail(); RETIRE_FAIL }
else {
let csr_val = readCSR(csr); /* could have side-effects, so technically shouldn't perform for CSRW[I] with rd == 0 */
if isWrite then {
let new_val : xlenbits = match op {
CSRRW => rs1_val,
CSRRS => csr_val | rs1_val,
CSRRC => csr_val & ~(rs1_val)
};
writeCSR(csr, new_val)
};
X(rd) = csr_val;
RETIRE_SUCCESS
}
}