Mnemonic |
Expansion |
Syntax |
Description |
Implementation |
<10> |
<10> |
<25> |
<40> |
<70> |
lui |
load upper immediate. |
lui rd,imm20 |
Build 32-bit constants and uses the U-type format. LUI places the U-immediate value in the top 20 bits of the destination register rd, filling in the lowest 12 bits with zeros. |
x[rd] = sext(imm20) << 12 |
auipc |
add upper immediate to pc |
auipc rd,imm20 |
Build pc-relative addresses and uses the U-type format. AUIPC forms a 32-bit offset from the 20-bit U-immediate, filling in the lowest 12 bits with zeros, adds this offset to the pc, then places the result in register rd. |
x[rd] = pc.get() + (sext(imm20) << 12) |
addi |
add immediate |
addi rd,rs1,imm |
Adds the sign-extended 12-bit immediate to register rs1. Arithmetic overflow is ignored and the result is simply the low XLEN bits of the result. ADDI rd, rs1, 0 is used to implement the MV rd, rs1 assembler pseudo-instruction. |
x[rd] = x[rs1] + sext(imm) |
slti |
set less than immediate |
slti rd,rs1,imm |
Place the value 1 in register rd if register rs1 is less than the signextended immediate when both are treated as signed numbers, else 0 is written to rd. |
x[rd] = signed_lt(x[rs1], sext(imm)).into() |
sltiu |
|
sltiu rd,rs1,imm |
Place the value 1 in register rd if register rs1 is less than the immediate when both are treated as unsigned numbers, else 0 is written to rd. |
x[rd] = (x[rs1] < sext(imm)).into() |
xori |
|
xori rd,rs1,imm |
Performs bitwise XOR on register rs1 and the sign-extended 12-bit immediate and place the result in rd. Note, “XORI rd, rs1, -1” performs a bitwise logical inversion of register rs1(assembler pseudo-instruction NOT rd, rs) |
x[rd] = x[rs1] ^ sext(imm) |
ori |
|
ori rd,rs1,imm |
Performs bitwise OR on register rs1 and the sign-extended 12-bit immediate and place the result in rd |
x[rd] = x[rs1] BITWISE_OR sext(imm) |
andi |
|
andi rd,rs1,imm |
Performs bitwise AND on register rs1 and the sign-extended 12-bit immediate and place the result in rd |
x[rd] = x[rs1] & sext(imm) |
slli |
|
slli rd,rs1,shamt |
Performs logical left shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate. In RV64, bit-25 is used to shamt[5]. |
x[rd] = x[rs1] << shamt |
srli |
|
srli rd,rs1,shamt |
Performs logical right shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate In RV64, bit-25 is used to shamt[5]. |
x[rd] = x[rs1] >> shamt |
srai |
|
srai rd,rs1,shamt |
Performs arithmetic right shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate. In RV64, bit-25 is used to shamt[5]. |
x[rd] = arith_r_shift_i(x[rs1], shamt) |
add |
|
add rd,rs1,rs2 |
Adds the registers rs1 and rs2 and stores the result in rd. Arithmetic overflow is ignored and the result is simply the low XLEN bits of the result. |
x[rd] = x[rs1] + x[rs2] |
sub |
|
sub rd,rs1,rs2 |
Subs the register rs2 from rs1 and stores the result in rd. Arithmetic overflow is ignored and the result is simply the low XLEN bits of the result. |
x[rd] = x[rs1] - x[rs2] |
sll |
|
sll rd,rs1,rs2 |
Performs logical left shift on the value in register rs1 by the shift amount held in the lower 5 bits of register rs2. |
x[rd] = x[rs1] << x[rs2] |
slt |
|
slt rd,rs1,rs2 |
Place the value 1 in register rd if register rs1 is less than register rs2 when both are treated as signed numbers, else 0 is written to rd. |
x[rd] = signed_lt(x[rs1], x[rs2]).into() |
sltu |
|
sltu rd,rs1,rs2 |
Place the value 1 in register rd if register rs1 is less than register rs2 when both are treated as unsigned numbers, else 0 is written to rd. |
x[rd] = (x[rs1] < x[rs2]).into() |
xor |
|
xor rd,rs1,rs2 |
Performs bitwise XOR on registers rs1 and rs2 and place the result in rd |
x[rd] = x[rs1] ^ x[rs2] |
srl |
|
srl rd,rs1,rs2 |
Logical right shift on the value in register rs1 by the shift amount held in the lower 5 bits of register rs2 |
x[rd] = x[rs1] >> x[rs2] |
sra |
|
sra rd,rs1,rs2 |
Performs arithmetic right shift on the value in register rs1 by the shift amount held in the lower 5 bits of register rs2 |
x[rd] = arith_r_shift(x[rs1], x[rs2]) |
or |
|
or rd,rs1,rs2 |
Performs bitwise OR on registers rs1 and rs2 and place the result in rd |
x[rd] = x[rs1] BITWISE_OR x[rs2] |
and |
|
and rd,rs1,rs2 |
Performs bitwise AND on registers rs1 and rs2 and place the result in rd |
x[rd] = x[rs1] & x[rs2] |
fence |
|
fence pred, succ |
Used to order device I/O and memory accesses as viewed by other RISC-V harts and external devices or coprocessors. Any combination of device input (I), device output (O), memory reads (R), and memory writes (W) may be ordered with respect to any combination of the same. Informally, no other RISC-V hart or external device can observe any operation in the successor set following a FENCE before any operation in the predecessor set preceding the FENCE. |
* Fence(pred, succ) * |
fence.i |
|
fence.i |
Provides explicit synchronization between writes to instruction memory and instruction fetches on the same hart. |
* Fence(Store, Fetch) * |
csrrw |
atomic read/write CSR. |
csrrw rd,offset,rs1 |
Atomically swaps values in the CSRs and integer registers. CSRRW reads the old value of the CSR, zero-extends the value to XLEN bits, then writes it to integer register rd. The initial value in rs1 is written to the CSR. If rd=x0, then the instruction shall not read the CSR and shall not cause any of the side effects that might occur on a CSR read. |
* t = CSRs[csr]; CSRs[csr] = x[rs1]; x[rd] = t * |
csrrs |
atomic read and set bits in CSR. |
csrrs rd,offset,rs1 |
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 unaffected (though CSRs might have side effects when written). |
* t = CSRs[csr]; CSRs[csr] = t BITWISE_OR x[rs1]; x[rd] = t * |
csrrc |
atomic read and clear bits in CSR. |
csrrc rd,offset,rs1 |
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 cleared in the CSR. Any bit that is high in rs1 will cause the corresponding bit to be cleared in the CSR, if that CSR bit is writable. Other bits in the CSR are unaffected. |
* t = CSRs[csr]; CSRs[csr] = t &~x[rs1]; x[rd] = t * |
csrrwi |
|
csrrwi rd,offset,uimm |
Update the CSR using an XLEN-bit value obtained by zero-extending a 5-bit unsigned immediate (uimm[4:0]) field encoded in the rs1 field. |
* x[rd] = CSRs[csr]; CSRs[csr] = zimm * |
csrrsi |
|
csrrsi rd,offset,uimm |
Set CSR bit using an XLEN-bit value obtained by zero-extending a 5-bit unsigned immediate (uimm[4:0]) field encoded in the rs1 field. |
* t = CSRs[csr]; CSRs[csr] = t BITWISE_OR zimm; x[rd] = t * |
csrrci |
|
csrrci rd,offset,uimm |
Clear CSR bit using an XLEN-bit value obtained by zero-extending a 5-bit unsigned immediate (uimm[4:0]) field encoded in the rs1 field. |
* t = CSRs[csr]; CSRs[csr] = t &~zimm; x[rd] = t * |
ecall |
|
ecall |
Make a request to the supporting execution environment. When executed in U-mode, S-mode, or M-mode, it generates an environment-call-from-U-mode exception, environment-call-from-S-mode exception, or environment-call-from-M-mode exception, respectively, and performs no other operation. |
* RaiseException(EnvironmentCall) * |
ebreak |
|
ebreak |
Used by debuggers to cause control to be transferred back to a debugging environment. It generates a breakpoint exception and performs no other operation. |
* RaiseException(Breakpoint) * |
uret |
|
uret |
Return from traps in U-mode, and URET copies UPIE into UIE, then sets UPIE. |
* ExceptionReturn(User) * |
sret |
|
sret |
Return from traps in S-mode, and SRET copies SPIE into SIE, then sets SPIE. |
* ExceptionReturn(User) * |
mret |
|
mret |
Return from traps in M-mode, and MRET copies MPIE into MIE, then sets MPIE. |
* ExceptionReturn(Machine) * |
wfi |
wait for interrupt. |
wfi |
Provides a hint to the implementation that the current hart can be stalled until an interrupt might need servicing. Execution of the WFI instruction can also be used to inform the hardware platform that suitable interrupts should preferentially be routed to this hart. WFI is available in all privileged modes, and optionally available to U-mode. This instruction may raise an illegal instruction exception when TW=1 in mstatus. |
* while (noInterruptsPending) idle * |
sfence.vma |
|
sfence.vma rs1,rs2 |
Guarantees that any previous stores already visible to the current RISC-V hart are ordered before all subsequent implicit references from that hart to the memory-management data structures. The SFENCE.VMA is used to flush any local hardware caches related to address translation. It is specified as a fence rather than a TLB flush to provide cleaner semantics with respect to which instructions are affected by the flush operation and to support a wider variety of dynamic caching structures and memory-management schemes. SFENCE.VMA is also used by higher privilege levels to synchronize page table writes and the address translation hardware. |
* Fence(Store, AddressTranslation) * |
lb |
|
lb rd,offset(rs1) |
Loads a 8-bit value from memory and sign-extends this to XLEN bits before storing it in register rd. |
x[rd] = read_sext(mem, x[rs1] + sext(offset), 8) |
lh |
|
lh rd,offset(rs1) |
Loads a 16-bit value from memory and sign-extends this to XLEN bits before storing it in register rd. |
x[rd] = read_sext(mem, x[rs1] + sext(offset), 16) |
lw |
|
lw rd,offset(rs1) |
Loads a 32-bit value from memory and sign-extends this to XLEN bits before storing it in register rd. |
x[rd] = read_sext(mem, x[rs1] + sext(offset), 32) |
lbu |
|
lbu rd,offset(rs1) |
Loads a 8-bit value from memory and zero-extends this to XLEN bits before storing it in register rd. |
x[rd] = read(mem, x[rs1] + sext(offset), 8) |
lhu |
|
lhu rd,offset(rs1) |
Loads a 16-bit value from memory and zero-extends this to XLEN bits before storing it in register rd. |
x[rd] = read(mem, x[rs1] + sext(offset), 16) |
sb |
|
sb rs2,offset(rs1) |
Store 8-bit, values from the low bits of register rs2 to memory. |
write(mem, x[rs1] + sext(offset), 8, x[rs2]) |
sh |
|
sh rs2,offset(rs1) |
Store 16-bit, values from the low bits of register rs2 to memory. |
write(mem, x[rs1] + sext(offset), 16, x[rs2]) |
sw |
|
sw rs2,offset(rs1) |
Store 32-bit, values from the low bits of register rs2 to memory. |
write(mem, x[rs1] + sext(offset), 32, x[rs2]) |
jal |
|
jal rd,offset |
Jump to address and place return address in rd. |
x[rd] = pc.get()+4; pc.inc(sext(offset)) |
jalr |
|
jalr rd, offset(rs1) |
Jump to address and place return address in rd. |
let t = pc.get()+4; pc.set((x[rs1]+sext(offset)) & !1); x[rd]=t |
beq |
|
beq rs1,rs2,offset |
Take the branch if registers rs1 and rs2 are equal. |
if x[rs1] == x[rs2] { pc.inc(sext(offset)) } |
bne |
|
bne rs1,rs2,offset |
Take the branch if registers rs1 and rs2 are not equal. |
if x[rs1] != x[rs2] { pc.inc(sext(offset)) } |
blt |
|
blt rs1,rs2,offset |
Take the branch if registers rs1 is less than rs2, using signed comparison. |
if signed_lt(x[rs1], x[rs2]) { pc.inc(sext(offset)) } |
bge |
|
bge rs1,rs2,offset |
Take the branch if registers rs1 is greater than rs2, using signed comparison. |
if !signed_lt(x[rs1], x[rs2]) { pc.inc(sext(offset)) } |
bltu |
|
bltu rs1,rs2,offset |
Take the branch if registers rs1 is less than rs2, using unsigned comparison. |
if x[rs1] > x[rs2] { pc.inc(sext(offset)) } |
bgeu |
|
bgeu rs1,rs2,offset |
Take the branch if registers rs1 is greater than rs2, using unsigned comparison. |
if x[rs1] >= x[rs2] { pc.inc(sext(offset)) } |
addiw |
|
addiw rd,rs1,imm |
Adds the sign-extended 12-bit immediate to register rs1 and produces the proper sign-extension of a 32-bit result in rd. Overflows are ignored and the result is the low 32 bits of the result sign-extended to 64 bits. Note, ADDIW rd, rs1, 0 writes the sign-extension of the lower 32 bits of register rs1 into register rd (assembler pseudoinstruction SEXT.W). |
x[rd] = sext_n(x[rs1] + sext(imm), 32) |
slliw |
|
slliw rd,rs1,shamt |
Performs logical left shift on the 32-bit of value in register rs1 by the shift amount held in the lower 5 bits of the immediate. Encodings with $imm[5] ≠ 0$ are reserved. |
x[rd] = sext_n(x[rs1] << shamt, 32) |
srliw |
|
srliw rd,rs1,shamt |
Performs logical right shift on the 32-bit of value in register rs1 by the shift amount held in the lower 5 bits of the immediate. Encodings with $imm[5] ≠ 0$ are reserved. |
x[rd] = sext_n(x[rs1] & 0xFFFF >> shamt, 32) |
sraiw |
|
sraiw rd,rs1,shamt |
Performs arithmetic right shift on the 32-bit of value in register rs1 by the shift amount held in the lower 5 bits of the immediate. Encodings with $imm[5] ≠ 0$ are reserved. |
x[rd] = sext_n(arith_r_shift_i(x[rs1] & 0xFFFF, shamt), 32) |
addw |
|
addw rd,rs1,rs2 |
Adds the 32-bit of registers rs1 and 32-bit of register rs2 and stores the result in rd. Arithmetic overflow is ignored and the low 32-bits of the result is sign-extended to 64-bits and written to the destination register. |
x[rd] = sext_n(x[rs1] + x[rs2], 32) |
subw |
|
subw rd,rs1,rs2 |
Subtract the 32-bit of registers rs1 and 32-bit of register rs2 and stores the result in rd. Arithmetic overflow is ignored and the low 32-bits of the result is sign-extended to 64-bits and written to the destination register. |
x[rd] = sext_n(x[rs1] - x[rs2], 32) |
sllw |
|
sllw rd,rs1,rs2 |
Performs logical left shift on the low 32-bits value in register rs1 by the shift amount held in the lower 5 bits of register rs2 and produce 32-bit results and written to the destination register rd. |
x[rd] = sext_n(x[rs1] << x[rs2] & 0x1F, 32) |
srlw |
|
srlw rd,rs1,rs2 |
Performs logical right shift on the low 32-bits value in register rs1 by the shift amount held in the lower 5 bits of register rs2 and produce 32-bit results and written to the destination register rd. |
x[rd] = sext_n(x[rs1] & 0xFFFF >> x[rs2] & 0x1F, 32) |
sraw |
|
sraw rd,rs1,rs2 |
Performs arithmetic right shift on the low 32-bits value in register rs1 by the shift amount held in the lower 5 bits of register rs2 and produce 32-bit results and written to the destination register rd. |
x[rd] = sext_n(arith_r_shift(x[rs1] & 0xFFFF, x[rs2] & 0x1F), 32) |
lwu |
|
lwu rd,offset(rs1) |
Loads a 32-bit value from memory and zero-extends this to 64 bits before storing it in register rd. |
x[rd] = read(mem, x[rs1] + sext(offset), 32) |
ld |
|
ld rd,offset(rs1) |
Loads a 64-bit value from memory into register rd for RV64I. |
x[rd] = read(mem, x[rs1] + sext(offset), 64) |
sd |
|
sd rs2,offset(rs1) |
Store 64-bit, values from register rs2 to memory. |
write(mem, x[rs1] + sext(offset), 64, x[rs2]) |