Contents:
Term | Meaning |
---|---|
imm | Immediate integer value |
pc | Program counter |
rd | Destination integer register |
fd | Destination floating-point register |
rs* | Source integer register |
fs* | Source floating-point register |
sext(n) | Sign extend n |
1ext(n) | 1-extend n; fill upper bits with ones; called "nan-boxing" when done with floating-point values |
x[n] | Integer register number n |
f[n] | Floating-point register number n |
M[n] | Memory at address n |
<s | Less than (signed) |
<u | Less than (unsigned) |
^ | Bitwise Exclusive OR |
| | Bitwise OR |
& | Bitwise AND |
~ | Bitwise NOT |
<< | Logical bitshift left |
>>u | Logical bitshift right |
>>s | Arithmetic bitshift right |
XLEN | The size of a register in bits (32 on RV32, 64 on RV64) |
XHI | The index of the highest bit (XLEN - 1) |
DXHI | The index of the highest bit of a double sized register (XLEN * 2 - 1) |
byte | 8-bit number |
halfword | 16-bit number |
word | 32-bit number |
doubleword | 64-bit number |
Some of the instructions are called "pseudoinstructions". They are not real instructions for the processor with their own encoding, but a syntax that your assembler may compile into one or more real instructions. The reason that they have been defined is probably to make assembly code easier to read and write. An example of a pseudoinstruction is "j" to jump, which is defined as a special use of "jal" that doesn't link.
Floating-point instructions have a field called "rm". This field selects the rounding mode. Possible values are:
Value | Name | Description |
---|---|---|
000 | RNE | Round to nearest, ties to even. |
001 | RTZ | Round towards zero. |
010 | RDN | Round down. |
011 | RUP | Round up. |
100 | RMM | Round to nearest, ties to max magnitude. |
101 | Invalid. | |
110 | Invalid. | |
111 | DYN | Dynamic; use rounding mode specified in rounding mode register. |
Atomic instructions have the fields "aq" and "rl". They work like the "fence" instruction. If "aq" is 1 then no memory operation following the atomic instruction can be observed before the atomic instruction by any hart. If "rl" is 1 then no memory operation before the atomic instruction can be observed after the atomic instruction by any hart.
For full specifications, see https://riscv.org/technical/specifications/.
These are the instructions that your assembler parses and compiles to machine code.
add | rd, rs1, rs2 | Add |
addi | rd, rs1, imm | Add immediate |
addiw | rd, rs1, imm | Add word immediate |
addw | rd, rs1, rs2 | Add word |
amoadd.d | rd, rs2, (rs1) | Atomic add doubleword |
amoadd.w | rd, rs2, (rs1) | Atomic add word |
amoand.d | rd, rs2, (rs1) | Atomic AND doubleword |
amoand.w | rd, rs2, (rs1) | Atomic AND word |
amomax.d | rd, rs2, (rs1) | Atomic maximum doubleword |
amomaxu.d | rd, rs2, (rs1) | Atomic unsigned maximum word |
amomaxu.w | rd, rs2, (rs1) | Atomic unsigned maximum word |
amomax.w | rd, rs2, (rs1) | Atomic maximum word |
amomin.d | rd, rs2, (rs1) | Atomic minimum doubleword |
amominu.d | rd, rs2, (rs1) | Atomic unsigned minimum word |
amominu.w | rd, rs2, (rs1) | Atomic unsigned minimum word |
amomin.w | rd, rs2, (rs1) | Atomic minimum word |
amoor.d | rd, rs2, (rs1) | Atomic OR doubleword |
amoor.w | rd, rs2, (rs1) | Atomic OR word |
amoswap.d | rd, rs2, (rs1) | Atomic swap doubleword |
amoswap.w | rd, rs2, (rs1) | Atomic swap word |
amoxor.d | rd, rs2, (rs1) | Atomic XOR doubleword |
amoxor.w | rd, rs2, (rs1) | Atomic XOR word |
and | rd, rs1, rs2 | AND |
andi | rd, rs1, imm | AND immediate |
auipc | rd, imm[31:12] |
Add upper immediate to pc |
beq | rs1, rs2, imm | Branch if = |
beqz | rs1, imm | Branch if = zero |
bge | rs1, rs2, imm | Branch if ≥ |
bgeu | rs1, rs2, imm | Branch if ≥, unsigned |
bgez | rs1, imm | Branch if ≥ zero |
bgt | rs1, rs2, imm | Branch if > |
bgtu | rs1, rs2, imm | Branch if >, unsigned |
bgtz | rs1, imm | Branch if > zero |
ble | rs1, rs2, imm | Branch if ≤ |
bleu | rs1, rs2, imm | Branch if ≤, unsigned |
blez | rs, imm | Branch if ≤ zero |
blt | rs1, rs2, imm | Branch if < |
bltu | rs1, rs2, imm | Branch if <, unsigned |
bltz | rs, imm | Branch if < zero |
bne | rs1, rs2, imm | Branch if ≠ |
bnez | rs, imm | Branch if ≠ zero |
call | imm | Call far-away subroutine |
csrrc | rd csr rs1 | Control and status register read and clear |
csrrci | rd csr imm[4:0] | Control and status register read and clear immediate |
csrrs | rd, csr, rs1 | Control and status register read and set |
csrrsi | rd, csr, imm[4:0] | Control and status register read and set immediate |
csrrw | rd, csr, rs1 | Control and status register read and write |
csrrwi | rd, csr, imm[4:0] | Control and status register read and write immediate |
div | rd, rs1, rs2 | Divide |
divu | rd, rs1, rs2 | Divide unsigned |
divuw | rd, rs1, rs2 | Divide unsigned word |
divw | rd, rs1, rs2 | Divide word |
ebreak | Environment breakpoint | |
ecall | Environment call | |
fabs.d | fd, fs | Double-precision absolute value |
fabs.s | fd, fs | Single-precision absolute value |
fadd.d | fd, fs1, fs2 | Add double-precision floating-point |
fadd.s | fd, fs1, fs2 | Add single-precision floating-point |
fclass.d | rd, fs | Classify double-precision floating-point |
fclass.s | rd, fs | Classify single-precision floating-point |
fcvt.d.l | fd, rs1 | Convert 64-bit integer to double-precision floating-point |
fcvt.d.lu | fd, rs1 | Convert 64-bit unsigned integer to double-precision floating-point |
fcvt.d.s | fd, fs1 | Convert single-precision to double-precision floating-point |
fcvt.d.w | fd, rs1 | Convert 32-bit integer to double-precision floating-point |
fcvt.d.wu | fd, rs1 | Convert 32-bit unsigned integer to double-precision floating-point |
fcvt.l.d | rd, fs1 | Convert double-precision floating-point to 64-bit integer |
fcvt.l.s | rd, fs1 | Convert single-precision floating-point to 64-bit integer |
fcvt.lu.d | rd, fs1 | Convert double-precision floating-point to unsigned 64-bit integer |
fcvt.lu.s | rd, fs1 | Convert single-precision floating-point to unsigned 64-bit integer |
fcvt.s.d | fd, fs1 | Convert double-precision to single-precision floating-point |
fcvt.s.l | fd, rs1 | Convert 64-bit integer to single-precision floating-point |
fcvt.s.lu | fd, rs1 | Convert 64-bit unsigned integer to single-precision floating-point |
fcvt.s.w | fd, rs1 | Convert 32-bit integer to single-precision floating-point |
fcvt.s.wu | fd, rs1 | Convert 32-bit unsigned integer to single-precision floating-point |
fcvt.w.d | rd, fs1 | Convert double-precision floating-point to 32-bit integer |
fcvt.w.s | rd, fs1 | Convert single-precision floating-point to 32-bit integer |
fcvt.wu.d | rd, fs1 | Convert double-precision floating-point to unsigned 32-bit integer |
fcvt.wu.s | rd, fs1 | Convert single-precision floating-point to unsigned 32-bit integer |
fdiv.d | fd, fs1, fs2 | Divide double-precision floating-point |
fdiv.s | fd, fs1, fs2 | Divide single-precision floating-point |
fence | pred, succ | Fence memory and I/O |
fence.i | Fence instruction stream | |
feq.d | rd, fs1, fs2 | Set if equal double-precision floating-point |
feq.s | rd, fs1, fs2 | Set if equal single-precision floating-point |
fld | fd, imm(rs1) | Load double-precision floating-point |
fle.d | rd, fs1, fs2 | Set if <= double-precision floating-point |
fle.s | rd, fs1, fs2 | Set if <= single-precision floating-point |
flt.d | rd, fs1, fs2 | Set if < double-precision floating-point |
flt.s | rd, fs1, fs2 | Set if < single-precision floating-point |
flw | fd, imm(rs1) | Load single-precision floating-point |
fmadd.d | fd, fs1, fs2, fs3 | Multiply and add double-precision floating-point |
fmadd.s | fd, fs1, fs2, fs3 | Multiply and add single-precision floating-point |
fmax.d | fd, fs1, fs2 | Maximum double-precision floating-point |
fmax.s | fd, fs1, fs2 | Maximum single-precision floating-point |
fmin.d | fd, fs1, fs2 | Minimum double-precision floating-point |
fmin.s | fd, fs1, fs2 | Minimum single-precision floating-point |
fmsub.d | fd, fs1, fs2, fs3 | Multiply and subtract double-precision floating-point |
fmsub.s | fd, fs1, fs2, fs3 | Multiply and subtract single-precision floating-point |
fmul.d | fd, fs1, fs2 | Multiply double-precision floating-point |
fmul.s | fd, fs1, fs2 | Multiply single-precision floating-point |
fmv.d | fd, fs | Copy double-precision register |
fmv.d.x | fd, rs | Move 64-bit integer to single-precision floating-point |
fmv.s | fd, fs | Copy single-precision register |
fmv.w.x | fd, rs | Move 32-bit integer to single-precision floating-point |
fmv.x.d | rd, fs | Move double-precision floating-point to 64-bit integer |
fmv.x.w | rd, fs | Move single-precision floating-point to 32-bit integer |
fneg.d | fd, fs | Double-precision negate |
fneg.s | fd, fs | Single-precision negate |
fnmadd.d | fd, fs1, fs2, fs3 | Negative multiply and add double-precision floating-point |
fnmadd.s | fd, fs1, fs2, fs3 | Negative multiply and add single-precision floating-point |
fnmsub.d | fd, fs1, fs2, fs3 | Negative multiply and subtract double-precision floating-point |
fnmsub.s | fd, fs1, fs2, fs3 | Negative multiply and subtract single-precision floating-point |
fsd | fs2, imm(rs1) | Store double-precision floating-point |
fsgnj.d | fd, fs1, fs2 | Sign inject for double-precision floating-point |
fsgnjn.d | fd, fs1, fs2 | Negative sign inject for double-precision floating-point |
fsgnjn.s | fd, fs1, fs2 | Negative sign inject for single-precision floating-point |
fsgnj.s | fd, fs1, fs2 | Sign inject for single-precision floating-point |
fsgnjx.d | fd, fs1, fs2 | Xor sign inject for double-precision floating-point |
fsgnjx.s | fd, fs1, fs2 | Xor sign inject for single-precision floating-point |
fsqrt.d | fd, fs1 | Square root double-precision floating-point |
fsqrt.s | fd, fs1 | Square root single-precision floating-point |
fsub.d | fd, fs1, fs2 | Subtract double-precision floating-point |
fsub.s | fd, fs1, fs2 | Subtract single-precision floating-point |
fsw | fs2, imm(rs1) | Store single-precision floating-point |
j | imm | Jump |
jal | rd, imm | Jump and link |
jalr | rd, imm(rs1) | Jump and link register |
jr | rs | Jump register |
la | rd, imm | Load address |
lb | rd, imm(rs1) | Load byte |
lbu | rd, imm(rs1) | Load byte, unsigned |
ld | rd, imm(rs1) | Load doubleword |
lh | rd, imm(rs1) | Load halfword |
lhu | rd, imm(rs1) | Load halfword, unsigned |
li | rd, imm | Load immediate |
lr.d | rd, rs1 | Load-reserve doubleword |
lr.w | rd, rs1 | Load-reserve word |
lui | rd, imm[31:12] | Load upper immediate |
lw | rd, imm(rs1) | Load word |
lwu | rd, imm(rs1) | Load word, unsigned |
mul | rd, rs1, rs2 | Multiply |
mulh | rd, rs1, rs2 | Multiply upper |
mulhsu | rd, rs1, rs2 | Multiply upper signed*unsigned |
mulhu | rd, rs1, rs2 | Multiply upper unsigned |
mulw | rd, rs1, rs2 | Multiply word |
mv | rd, rs | Copy register |
neg | rd, rs | Two's complement |
negw | rd, rs | Two's complement word |
nop | No operation | |
not | rd, rs | One's complement |
or | rd, rs1, rs2 | OR |
ori | rd, rs1, imm | OR immediate |
rem | rd, rs1, rs2 | Remainder |
remu | rd, rs1, rs2 | Remainder unsigned |
remuw | rd, rs1, rs2 | Remainder unsigned word |
remw | rd, rs1, rs2 | Remainder word |
ret | Return from subroutine | |
sb | rs2, imm(rs1) | Store byte |
sc.d | rd, rs1, rs2 | Store-conditional doubleword |
sc.w | rd, rs1, rs2 | Store-conditional word |
sd | rs2, imm(rs1) | Store doubleword |
sext.w | rd, rs | Sign extend word |
seqz | rd, rs | Set if = zero |
sgtz | rd, rs | Set if > zero |
sh | rs2, imm(rs1) | Store halfword |
sll | rd, rs1, rs2 | Shift left logical |
slli | rd, rs1, imm | Shift left logical immediate |
slli | rd, rs1, imm | Shift left logical immediate |
slliw | rd, rs1, imm | Shift left logical word immediate |
sllw | rd, rs1, rs2 | Shift left logical word |
slt | rd, rs1, rs2 | Set if < |
slti | rd, rs1, imm | Set if < immediate |
sltiu | rd, rs1, imm | Set if < immediate, unsigned |
sltu | rd, rs1, rs2 | Set if <, unsigned |
sltz | rd, rs | Set if < zero |
snez | rd, rs | Set if ≠ zero |
sra | rd, rs1, rs2 | Shift right arithmetic |
srai | rd, rs1, imm | Shift right arithmetic immediate |
srai | rd, rs1, imm | Shift right arithmetic immediate |
sraiw | rd, rs1, imm | Shift right arithmetic word immediate |
sraw | rd, rs1, rs2 | Shift right arithmetic word |
srl | rd, rs1, rs2 | Shift right logical |
srli | rd, rs1, imm | Shift right logical immediate |
srli | rd, rs1, imm | Shift right logical immediate |
srliw | rd, rs1, imm | Shift right logical word immediate |
srlw | rd, rs1, rs2 | Shift right logical word |
sub | rd, rs1, rs2 | Subtract |
subw | rd, rs1, rs2 | Subtract word |
sw | rs2, imm(rs1) | Store word |
tail | imm | Tail call far-away subroutine |
xor | rd, rs1, rs2 | Exclusive OR |
xori | rd, rs1, imm | Exclusive OR immediate |
These are the instructions that your processor decodes and executes.
RV32I, RV64I
add
rd[4:0]
rs1[4:0]
rs2[4:0]
Add. Add rs1
and rs2
and put the result in rd
. Arithmetic overflow is ignored.
x[rd] = x[rs1] + x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000 | rs2 | rs1 | 000 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
addi
rd[4:0]
rs1[4:0]
imm[11:0]
Add immediate. Add rs1
and imm
and put the result in rd
. Arithmetic overflow is ignored.
x[rd] = x[rs1] + sext(imm)
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 000 | rd | 0010011 |
12 | 5 | 3 | 5 | 7 |
RV64I
addiw
rd[4:0]
rs1[4:0]
imm[11:0]
Add word immediate. Add rs1
and imm
and put the result in rd
. Arithmetic overflow is ignored.
x[rd] = sext((x[rs1] + sext(imm))[31:0])
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 000 | rd | 0011011 |
12 | 5 | 3 | 5 | 7 |
RV64I
addw
rd[4:0]
rs1[4:0]
rs2[4:0]
Add word. Add rs1
and rs2
and put the result in rd
. Arithmetic overflow is ignored.
x[rd] = sext((x[rs1] + x[rs2])[31:0])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000 | rs2 | rs1 | 000 | rd | 0111011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64A
amoadd.d
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic add doubleword. Atomically load the value at address rs1
into rd
, add rd
and rs2
and put the result in memory at address rs1
. Arithmetic overflow is ignored.
The address in rs1
must be aligned to 8 bytes.
x[rd] = M[x[rs1]][63:0]
M[x[rs1]] = (x[rd] + x[rs2])[63:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
00000, aq, rl | rs2 | rs1 | 011 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: add
RV32A, RV64A
amoadd.w
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic add word. Atomically load the value at address rs1
into rd
, add rd
and rs2
and put the result in memory at address rs1
. Arithmetic overflow is ignored.
The address in rs1
must be aligned to 4 bytes.
x[rd] = sext(M[x[rs1]][31:0])
M[x[rs1]] = (M[x[rs1]][31:0] + x[rs2])[31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
00000, aq, rl | rs2 | rs1 | 010 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: addw
RV64A
amoand.d
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic AND doubleword. Atomically load the value at address rs1
into rd
, calculate the bitwise AND on rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 8 bytes.
x[rd] = sext(M[x[rs1]][63:0])
M[x[rs1]] = (M[x[rs1]][63:0] & x[rs2])[63:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
01100, aq, rl | rs2 | rs1 | 011 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: and
RV32A, RV64A
amoand.w
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic AND word. Atomically load the value at address rs1
into rd
, calculate the bitwise AND on rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 4 bytes.
x[rd] = sext(M[x[rs1]][31:0])
M[x[rs1]] = (M[x[rs1]][31:0] & x[rs2])[31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
01100, aq, rl | rs2 | rs1 | 010 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: and
RV64A
amomax.d
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic maximum doubleword. Atomically load the value at address rs1
into rd
, calculate the maximum value of rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 8 bytes.
x[rd] = sext(M[x[rs1]][63:0])
M[x[rs1]] = max(M[x[rs1]][63:0], x[rs2])[63:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
10100, aq, rl | rs2 | rs1 | 011 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64A
amomaxu.d
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic unsigned maximum word. Atomically load the value at address rs1
into rd
, calculate the unsigned maximum value of rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 8 bytes.
x[rd] = sext(M[x[rs1]][63:0])
M[x[rs1]] = maxu(M[x[rs1]][63:0], x[rs2])[63:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
11100, aq, rl | rs2 | rs1 | 011 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32A, RV64A
amomaxu.w
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic unsigned maximum word. Atomically load the value at address rs1
into rd
, calculate the unsigned maximum value of rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 4 bytes.
x[rd] = sext(M[x[rs1]][31:0])
M[x[rs1]] = maxu(M[x[rs1]][31:0], x[rs2])[31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
11100, aq, rl | rs2 | rs1 | 010 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32A, RV64A
amomax.w
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic maximum word. Atomically load the value at address rs1
into rd
, calculate the maximum value of rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 4 bytes.
x[rd] = sext(M[x[rs1]][31:0])
M[x[rs1]] = max(M[x[rs1]][31:0], x[rs2])[31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
10100, aq, rl | rs2 | rs1 | 010 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64A
amomin.d
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic minimum doubleword. Atomically load the value at address rs1
into rd
, calculate the minimum value of rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 8 bytes.
x[rd] = sext(M[x[rs1]][63:0])
M[x[rs1]] = min(M[x[rs1]][63:0], x[rs2])[63:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
10000, aq, rl | rs2 | rs1 | 011 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64A
amominu.d
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic unsigned minimum word. Atomically load the value at address rs1
into rd
, calculate the unsigned minimum value of rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 8 bytes.
x[rd] = sext(M[x[rs1]][63:0])
M[x[rs1]] = minu(M[x[rs1]][63:0], x[rs2])[63:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
11000, aq, rl | rs2 | rs1 | 011 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32A, RV64A
amominu.w
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic unsigned minimum word. Atomically load the value at address rs1
into rd
, calculate the unsigned minimum value of rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 4 bytes.
x[rd] = sext(M[x[rs1]][31:0])
M[x[rs1]] = minu(M[x[rs1]][31:0], x[rs2])[31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
11000, aq, rl | rs2 | rs1 | 010 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32A, RV64A
amomin.w
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic minimum word. Atomically load the value at address rs1
into rd
, calculate the minimum value of rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 4 bytes.
x[rd] = sext(M[x[rs1]][31:0])
M[x[rs1]] = min(M[x[rs1]][31:0], x[rs2])[31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
10000, aq, rl | rs2 | rs1 | 010 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64A
amoor.d
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic OR doubleword. Atomically load the value at address rs1
into rd
, calculate the bitwise OR on rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 8 bytes.
x[rd] = sext(M[x[rs1]][63:0])
M[x[rs1]] = (M[x[rs1]][63:0] | x[rs2])[63:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
01000, aq, rl | rs2 | rs1 | 011 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: or
RV32A, RV64A
amoor.w
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic OR word. Atomically load the value at address rs1
into rd
, calculate the bitwise OR on rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 4 bytes.
x[rd] = sext(M[x[rs1]][31:0])
M[x[rs1]] = (M[x[rs1]][31:0] | x[rs2])[31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
01000, aq, rl | rs2 | rs1 | 010 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: or
RV64A
amoswap.d
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic swap doubleword. Atomically load the value at address rs1
into rd
and write the value of rs2
to address rs1
.
The address in rs1
must be aligned to 8 bytes.
x[rd] = sext(M[x[rs1]][63:0])
M[x[rs1]] = x[rs2][63:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
00001, aq, rl | rs2 | rs1 | 011 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32A, RV64A
amoswap.w
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic swap word. Atomically load the value at address rs1
into rd
and write the value of rs2
to address rs1
.
The address in rs1
must be aligned to 4 bytes.
x[rd] = sext(M[x[rs1]][31:0])
M[x[rs1]] = x[rs2][31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
00001, aq, rl | rs2 | rs1 | 010 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64A
amoxor.d
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic XOR doubleword. Atomically load the value at address rs1
into rd
, calculate the bitwise XOR on rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 8 bytes.
x[rd] = sext(M[x[rs1]][63:0])
M[x[rs1]] = (M[x[rs1]][63:0] ^ x[rs2])[63:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
00100, aq, rl | rs2 | rs1 | 011 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: xor
RV32A, RV64A
amoxor.w
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Atomic XOR word. Atomically load the value at address rs1
into rd
, calculate the bitwise XOR on rd
and rs2
and put the result in memory at address rs1
.
The address in rs1
must be aligned to 4 bytes.
x[rd] = sext(M[x[rs1]][31:0])
M[x[rs1]] = (M[x[rs1]][31:0] ^ x[rs2])[31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
00100, aq, rl | rs2 | rs1 | 010 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: xor
RV32I, RV64I
and
rd[4:0]
rs1[4:0]
rs2[4:0]
AND. Calculate bitwise AND on rs1
and rs2
and put the result in rd
.
x[rd] = x[rs1] & x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000 | rs2 | rs1 | 111 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
andi
rd[4:0]
rs1[4:0]
imm[11:0]
AND immediate. Calculate bitwise AND on rs1
and imm
and put the result in rd
.
x[rd] = x[rs1] & sext(imm)
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 111 | rd | 0010011 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
auipc
rd[4:0]
imm[31:12]
Add upper immediate to pc
. Can be used to build addresses relative to program counter. Add imm
(with lower 12 bits = 0) and pc
and put the result in rd
.
x[rd] = pc + sext(imm[31:12] << 12)
31 12 | 11 7 | 6 0 |
imm[31:12] | rd | 0010111 |
20 | 5 | 7 |
Related: lui
RV32I, RV64I
beq
rs1[4:0]
rs2[4:0]
imm[12:1]
Branch if =. Add imm
(multiple of 2) to pc
if rs1
and rs2
are equal.
if (rs1 == rs2) pc += sext(imm)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[12,10:5] | rs2 | rs1 | 000 | imm[4:1,11] | 1100011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
bge
rs1[4:0]
rs2[4:0]
imm[12:1]
Branch if ≥. Add imm
(multiple of 2) to pc
if rs1
is greater than (signed) or equal to rs2
.
if (rs1 ≥s rs2) pc += sext(imm)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[12,10:5] | rs2 | rs1 | 101 | imm[4:1,11] | 1100011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
bgeu
rs1[4:0]
rs2[4:0]
imm[12:1]
Branch if ≥, unsigned. Add imm
(multiple of 2) to pc
if rs1
is greater than (unsigned) or equal to rs2
.
if (rs1 ≥u rs2) pc += sext(imm)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[12,10:5] | rs2 | rs1 | 111 | imm[4:1,11] | 1100011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
blt
rs1[4:0]
rs2[4:0]
imm[12:1]
Branch if <. Add imm
(multiple of 2) to pc
if rs1
is less than (signed) rs2
.
if (rs1 <s rs2) pc += sext(imm)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[12,10:5] | rs2 | rs1 | 100 | imm[4:1,11] | 1100011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
bltu
rs1[4:0]
rs2[4:0]
imm[12:1]
Branch if <, unsigned. Add imm
(multiple of 2) to pc
if rs1
is less than (unsigned) rs2
.
if (rs1 <u rs2) pc += sext(imm)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[12,10:5] | rs2 | rs1 | 110 | imm[4:1,11] | 1100011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
bne
rs1[4:0]
rs2[4:0]
imm[12:1]
Branch if ≠. Add imm
(multiple of 2) to pc
if rs1
and rs2
are not equal.
if (rs1 ≠ rs2) pc += sext(imm)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[12,10:5] | rs2 | rs1 | 001 | imm[4:1,11] | 1100011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
csrrc
rd[4:0]
csr[11:0]
rs1[4:0]
Control and status register read and clear. Atomically writes the old value of csr
to rd
and clears the csr
bits that are set in rs1
. Unwritable bits in csr
are unaffected.
If rs1
is x0
then csr
is not written to and no side effects from writing to it will occur (this is not the same when rs1
is another register that holds value 0).
t = CSRs[csr]
CSRs[csr] = t & ∼x[rs1]
x[rd] = t
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
csr | rs1 | 011 | rd | 1110011 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
csrrci
rd[4:0]
csr[11:0]
imm[4:0]
Control and status register read and clear immediate. Atomically writes the old value of csr
to rd
and clears the csr
bits that are set in imm
. Unwritable bits in csr
are unaffected.
If imm
is 0 then csr
is not written to and no side effects from writing to it will occur.
t = CSRs[csr]
CSRs[csr] = t & ∼imm
x[rd] = t
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
csr | imm | 111 | rd | 1110011 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
csrrs
rd[4:0]
csr[11:0]
rs1[4:0]
Control and status register read and set. Atomically writes the old value of csr
to rd
and sets the csr
bits that are set in rs1
. Unwritable bits in csr
are unaffected.
If rs1
is x0
then csr
is not written to and no side effects from writing to it will occur (this is not the same when rs1
is another register that holds value 0).
t = CSRs[csr]
CSRs[csr] = t | x[rs1]
x[rd] = t
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
csr | rs1 | 010 | rd | 1110011 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
csrrsi
rd[4:0]
csr[11:0]
imm[4:0]
Control and status register read and set immediate. Atomically writes the old value of csr
to rd
and sets the csr
bits that are set in imm
. Unwritable bits in csr
are unaffected.
If imm
is 0 then csr
is not written to and no side effects from writing to it will occur.
t = CSRs[csr]
CSRs[csr] = t | imm
x[rd] = t
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
csr | imm | 110 | rd | 1110011 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
csrrw
rd[4:0]
csr[11:0]
rs1[4:0]
Control and status register read and write. Atomically writes the old value of csr
to rd
and rs1
to csr
.
If rd
is x0
then csr
is not read and no side effects from reading it will occur.
t = CSRs[csr]
CSRs[csr] = x[rs1]
x[rd] = t
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
csr | rs1 | 001 | rd | 1110011 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
csrrwi
rd[4:0]
csr[11:0]
imm[4:0]
Control and status register read and write immediate. Atomically writes the old value of csr
to rd
and imm
to csr
.
If rd
is x0
then csr
is not read and no side effects from reading it will occur.
t = CSRs[csr]
CSRs[csr] = imm
x[rd] = t
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
csr | imm | 101 | rd | 1110011 |
12 | 5 | 3 | 5 | 7 |
RV32M, RV64M
div
rd[4:0]
rs1[4:0]
rs2[4:0]
Divide. Divide rs1
by rs2
and put the result (rounded towards zero) in rd
.
x[rd] = x[rs1] /s x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | rs2 | rs1 | 100 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: rem
RV32M, RV64M
divu
rd[4:0]
rs1[4:0]
rs2[4:0]
Divide unsigned. Divide unsigned rs1
by unsigned rs2
and put the result (rounded towards zero) in rd
.
x[rd] = x[rs1] /u x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | rs2 | rs1 | 101 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: remu
RV64M
divuw
rd[4:0]
rs1[4:0]
rs2[4:0]
Divide unsigned word. Divide the lower 32 bits of unsigned rs1
by the lower 32 bits of unsigned rs2
and put the result (rounded towards zero) in rd
.
x[rd] = x[rs1][31:0] /u x[rs2][31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | rs2 | rs1 | 101 | rd | 0111011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: remuw
RV64M
divw
rd[4:0]
rs1[4:0]
rs2[4:0]
Divide word. Divide the lower 32 bits of rs1
by the lower 32 bits of rs2
and put the result (rounded towards zero) in rd
.
x[rd] = x[rs1][31:0] /s x[rs2][31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | rs2 | rs1 | 100 | rd | 0111011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: remw
RV32I, RV64I
ebreak
Environment breakpoint. Used by debuggers to cause control to be transferred back to the debugger.
RaiseException(Breakpoint)
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
000000000001 | 00000 | 000 | 00000 | 1110011 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
ecall
Environment call. Make a request to the supporting execution environment (usually the operating system).
RaiseException(EnvironmentCall)
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
000000000000 | 00000 | 000 | 00000 | 1110011 |
12 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fadd.d
fd[4:0]
fs1[4:0]
fs2[4:0]
rm[2:0]
Add double-precision floating-point. Calculate fs1+fs2 and put the result in fd.
The rm field is rounding mode.
f[fd] = f[fs1] + f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | fs2 | fs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fadd.s
fd[4:0]
fs1[4:0]
fs2[4:0]
rm[2:0]
Add single-precision floating-point. Calculate fs1+fs2 and put the result in fd.
The rm field is rounding mode.
f[fd] = f[fs1] + f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000 | fs2 | fs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fclass.d
rd[4:0]
fs[4:0]
Classify double-precision floating-point. Set flags in rd depending on the properties of fs. Other bits are set to 0.
rd bit | Meaning |
---|---|
0 | fs is -infinity |
1 | fs is a negative normal number |
2 | fs is a negative subnormal number |
3 | fs is -0 |
4 | fs is +0 |
5 | fs is a positive subnormal number |
6 | fs is a positive normal number |
7 | fs is +infinity |
8 | fs is a signaling NaN |
9 | fs is a quiet NaN |
r[rd] = Classify(f[fs])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1110001 | 00000 | fs | 001 | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fclass.s
rd[4:0]
fs[4:0]
Classify single-precision floating-point. Set flags in rd depending on the properties of fs. Other bits are set to 0.
rd bit | Meaning |
---|---|
0 | fs is -infinity |
1 | fs is a negative normal number |
2 | fs is a negative subnormal number |
3 | fs is -0 |
4 | fs is +0 |
5 | fs is a positive subnormal number |
6 | fs is a positive normal number |
7 | fs is +infinity |
8 | fs is a signaling NaN |
9 | fs is a quiet NaN |
r[rd] = Classify(f[fs])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1110000 | 00000 | fs | 001 | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64D
fcvt.d.l
fd[4:0]
rs1[4:0]
rm[2:0]
Convert 64-bit integer to double-precision floating-point.
The rm field is rounding mode.
f[fd] = 1ext(i64_to_f32(x[rs1]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1101001 | 00010 | rs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64D
fcvt.d.lu
fd[4:0]
rs1[4:0]
rm[2:0]
Convert 64-bit unsigned integer to double-precision floating-point.
The rm field is rounding mode.
f[fd] = 1ext(u64_to_f32(x[rs1]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1101001 | 00011 | rs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64D
fcvt.d.s
fd[4:0]
fs1[4:0]
rm[2:0]
Convert single-precision to double-precision floating-point.
The rm field is rounding mode.
f[fd] = 1ext(f32_to_f64(f[fs1][31:0]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0100001 | 00000 | fs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: fcvt.s.d
RV32D, RV64D
fcvt.d.w
fd[4:0]
rs1[4:0]
rm[2:0]
Convert 32-bit integer to double-precision floating-point.
The rm field is rounding mode.
f[fd] = 1ext(i32_to_f32(x[rs1][31:0]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1101001 | 00000 | rs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fcvt.d.wu
fd[4:0]
rs1[4:0]
rm[2:0]
Convert 32-bit unsigned integer to double-precision floating-point.
The rm field is rounding mode.
f[fd] = 1ext(u32_to_f32(x[rs1][31:0]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1101001 | 00001 | rs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64D
fcvt.l.d
rd[4:0]
fs1[4:0]
rm[2:0]
Convert double-precision floating-point to 64-bit integer.
Out of bounds results are clamped between minimum and maximum 64-bit signed integer values and the invalid flag is set. NaN counts as positive infinity.
The rm field is rounding mode.
x[rd] = f64_to_i64(f[fs1])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1100001 | 00010 | fs1 | rm | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64F
fcvt.l.s
rd[4:0]
fs1[4:0]
rm[2:0]
Convert single-precision floating-point to 64-bit integer.
Out of bounds results are clamped between minimum and maximum 64-bit signed integer values and the invalid flag is set. NaN counts as positive infinity.
The rm field is rounding mode.
x[rd] = f32_to_i64(f[fs1])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1100000 | 00010 | fs1 | rm | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64D
fcvt.lu.d
rd[4:0]
fs1[4:0]
rm[2:0]
Convert double-precision floating-point to unsigned 64-bit integer.
Out of bounds results are clamped between minimum and maximum 64-bit unsigned integer values and the invalid flag is set. NaN counts as positive infinity.
The rm field is rounding mode.
x[rd] = f32_to_u64(f[fs1])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1100001 | 00011 | fs1 | rm | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64F
fcvt.lu.s
rd[4:0]
fs1[4:0]
rm[2:0]
Convert single-precision floating-point to unsigned 64-bit integer.
Out of bounds results are clamped between minimum and maximum 64-bit unsigned integer values and the invalid flag is set. NaN counts as positive infinity.
The rm field is rounding mode.
x[rd] = f32_to_u64(f[fs1])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1100000 | 00011 | fs1 | rm | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64D
fcvt.s.d
fd[4:0]
fs1[4:0]
rm[2:0]
Convert double-precision to single-precision floating-point.
The rm field is rounding mode.
f[fd] = 1ext(f64_to_f632(f[fs1][63:0]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0100000 | 00001 | fs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: fcvt.d.s
RV64F
fcvt.s.l
fd[4:0]
rs1[4:0]
rm[2:0]
Convert 64-bit integer to single-precision floating-point.
The rm field is rounding mode.
f[fd] = 1ext(i64_to_f32(x[rs1]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1101000 | 00010 | rs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64F
fcvt.s.lu
fd[4:0]
rs1[4:0]
rm[2:0]
Convert 64-bit unsigned integer to single-precision floating-point.
The rm field is rounding mode.
f[fd] = 1ext(u64_to_f32(x[rs1]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1101000 | 00011 | rs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fcvt.s.w
fd[4:0]
rs1[4:0]
rm[2:0]
Convert 32-bit integer to single-precision floating-point.
The rm field is rounding mode.
f[fd] = 1ext(i32_to_f32(x[rs1][31:0]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1101000 | 00000 | rs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fcvt.s.wu
fd[4:0]
rs1[4:0]
rm[2:0]
Convert 32-bit unsigned integer to single-precision floating-point.
The rm field is rounding mode.
f[fd] = 1ext(u32_to_f32(x[rs1][31:0]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1101000 | 00001 | rs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fcvt.w.d
rd[4:0]
fs1[4:0]
rm[2:0]
Convert double-precision floating-point to 32-bit integer.
Out of bounds results are clamped between minimum and maximum 32-bit signed integer values and the invalid flag is set. NaN counts as positive infinity.
The rm field is rounding mode.
x[rd] = sext(f64_to_i32(f[fs1]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1100001 | 00000 | fs1 | rm | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fcvt.w.s
rd[4:0]
fs1[4:0]
rm[2:0]
Convert single-precision floating-point to 32-bit integer.
Out of bounds results are clamped between minimum and maximum 32-bit signed integer values and the invalid flag is set. NaN counts as positive infinity.
The rm field is rounding mode.
x[rd] = sext(f32_to_i32(f[fs1]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1100000 | 00000 | fs1 | rm | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fcvt.wu.d
rd[4:0]
fs1[4:0]
rm[2:0]
Convert double-precision floating-point to unsigned 32-bit integer.
Out of bounds results are clamped between minimum and maximum 32-bit unsigned integer values and the invalid flag is set. NaN counts as positive infinity.
The rm field is rounding mode.
x[rd] = sext(f32_to_u32(f[fs1]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1100001 | 00001 | fs1 | rm | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fcvt.wu.s
rd[4:0]
fs1[4:0]
rm[2:0]
Convert single-precision floating-point to unsigned 32-bit integer.
Out of bounds results are clamped between minimum and maximum 32-bit unsigned integer values and the invalid flag is set. NaN counts as positive infinity.
The rm field is rounding mode.
x[rd] = sext(f32_to_u32(f[fs1]))
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1100000 | 00001 | fs1 | rm | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fdiv.d
fd[4:0]
fs1[4:0]
fs2[4:0]
rm[2:0]
Divide double-precision floating-point. Calculate fs1/fs2 and put the result in fd.
The rm field is rounding mode.
f[fd] = f[fs1] / f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0001101 | fs2 | fs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fdiv.s
fd[4:0]
fs1[4:0]
fs2[4:0]
rm[2:0]
Divide single-precision floating-point. Calculate fs1/fs2 and put the result in fd.
The rm field is rounding mode.
f[fd] = f[fs1] / f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0001100 | fs2 | fs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
fence
pred[3:0]
succ[3:0]
fm[3:0]
Fence memory and I/O. Ensure that no operation following the fence (that is specified in succ
) can be observed before any operation preceding the fence (that is specified in pred
), by any other RISC-V hart or external device.
Example: "fence r, w" means that all reads before the fence must be observed before all writes after the fence by all harts and devices.
Address space is divided into two types: main memory and input/output. Load and store operations to main memory are ordered by the R and W bits. Load and store operations to I/O addresses are ordered by the I and O bits.
pred
and succ
are 4 bit values specifying the types of operations where bit3=input, bit2=output, bit1=read, bit0=write. Any combination may be specified.
fm
(fence mode): 0000 = normal fence, as described above; 1000 "TSO" (with pred=RW and succ=RW) = like normal fence but allow pred writes to be ordered after succ reads.
Fence(pred, succ)
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
fm,pred,succ | 00000 | 000 | 00000 | 0001111 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
fence.i
Fence instruction stream. Ensure that a subsequent instruction fetch on a RISC-V hart will see any previous data stores already visible to the same RISC-V hart. It does not ensure that other RISC-V harts will see the stores.
Fence(Store, Fetch)
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
000000000000 | 00000 | 001 | 00000 | 0001111 |
12 | 5 | 3 | 5 | 7 |
RV32D, RV64D
feq.d
rd[4:0]
fs1[4:0]
fs2[4:0]
Set if equal double-precision floating-point. Calculate fs1==fs2 and write 1 to rd if true, else 0.
If either input is NaN, the result is 0 and the invalid operation flag is only set if either result is a signaling NaN.
r[rd] = f[fs1] == f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1010001 | fs2 | fs1 | 010 | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
feq.s
rd[4:0]
fs1[4:0]
fs2[4:0]
Set if equal single-precision floating-point. Calculate fs1==fs2 and write 1 to rd if true, else 0.
If either input is NaN, the result is 0 and the invalid operation flag is only set if either result is a signaling NaN.
r[rd] = f[fs1] == f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1010000 | fs2 | fs1 | 010 | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fld
fd[4:0]
rs1[4:0]
imm[11:0]
Load double-precision floating-point. Copy doubleword from memory at address imm
+rs1
into register fd
.
f[fd] = M[x[rs1] + sext(imm)]
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 011 | fd | 0000111 |
12 | 5 | 3 | 5 | 7 |
Related: fsd
RV32D, RV64D
fle.d
rd[4:0]
fs1[4:0]
fs2[4:0]
Set if <= double-precision floating-point. Calculate fs1<=fs2 and write 1 to rd if true, else 0.
If either input is NaN, the result is 0 and the invalid operation flag is set.
r[rd] = f[fs1] <= f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1010001 | fs2 | fs1 | 000 | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fle.s
rd[4:0]
fs1[4:0]
fs2[4:0]
Set if <= single-precision floating-point. Calculate fs1<=fs2 and write 1 to rd if true, else 0.
If either input is NaN, the result is 0 and the invalid operation flag is set.
r[rd] = f[fs1] <= f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1010000 | fs2 | fs1 | 000 | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
flt.d
rd[4:0]
fs1[4:0]
fs2[4:0]
Set if < double-precision floating-point. Calculate fs1<fs2 and write 1 to rd if true, else 0.
If either input is NaN, the result is 0 and the invalid operation flag is set.
r[rd] = f[fs1] < f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1010001 | fs2 | fs1 | 001 | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
flt.s
rd[4:0]
fs1[4:0]
fs2[4:0]
Set if < single-precision floating-point. Calculate fs1<fs2 and write 1 to rd if true, else 0.
If either input is NaN, the result is 0 and the invalid operation flag is set.
r[rd] = f[fs1] < f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1010000 | fs2 | fs1 | 001 | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
flw
fd[4:0]
rs1[4:0]
imm[11:0]
Load single-precision floating-point. Copy word from memory at address imm
+rs1
into register fd
.
f[fd] = 1ext(M[x[rs1] + sext(imm)][31:0])
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 010 | fd | 0000111 |
12 | 5 | 3 | 5 | 7 |
Related: fsw
RV32D, RV64D
fmadd.d
fd[4:0]
fs1[4:0]
fs2[4:0]
fs3[4:0]
Multiply and add double-precision floating-point. Calculate fs1*fs2+fs3 and put the result in fd.
f[fd] = (f[fs1] * f[fs2]) + f[fs3]
31 27 | 26 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
fs3 | 01 | fs2 | fs1 | 000 | fd | 1000011 |
5 | 2 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fmadd.s
fd[4:0]
fs1[4:0]
fs2[4:0]
fs3[4:0]
Multiply and add single-precision floating-point. Calculate fs1*fs2+fs3 and put the result in fd.
f[fd] = (f[fs1] * f[fs2]) + f[fs3]
31 27 | 26 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
fs3 | 00 | fs2 | fs1 | 000 | fd | 1000011 |
5 | 2 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fmax.d
fd[4:0]
fs1[4:0]
fs2[4:0]
Maximum double-precision floating-point. Calculate the maximum value of fs1 and fs2 and put the result in fd.
f[fd] = max(f[fs1], f[fs2])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0010101 | fs2 | fs1 | 001 | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fmax.s
fd[4:0]
fs1[4:0]
fs2[4:0]
Maximum single-precision floating-point. Calculate the maximum value of fs1 and fs2 and put the result in fd.
f[fd] = max(f[fs1], f[fs2])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0010100 | fs2 | fs1 | 001 | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fmin.d
fd[4:0]
fs1[4:0]
fs2[4:0]
Minimum double-precision floating-point. Calculate the minimum value of fs1 and fs2 and put the result in fd.
f[fd] = min(f[fs1], f[fs2])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0010101 | fs2 | fs1 | 000 | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fmin.s
fd[4:0]
fs1[4:0]
fs2[4:0]
Minimum single-precision floating-point. Calculate the minimum value of fs1 and fs2 and put the result in fd.
f[fd] = min(f[fs1], f[fs2])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0010100 | fs2 | fs1 | 000 | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fmsub.d
fd[4:0]
fs1[4:0]
fs2[4:0]
fs3[4:0]
Multiply and subtract double-precision floating-point. Calculate fs1*fs2-fs3 and put the result in fd.
f[fd] = (f[fs1] * f[fs2]) - f[fs3]
31 27 | 26 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
fs3 | 01 | fs2 | fs1 | 000 | fd | 1000111 |
5 | 2 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fmsub.s
fd[4:0]
fs1[4:0]
fs2[4:0]
fs3[4:0]
Multiply and subtract single-precision floating-point. Calculate fs1*fs2-fs3 and put the result in fd.
f[fd] = (f[fs1] * f[fs2]) - f[fs3]
31 27 | 26 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
fs3 | 00 | fs2 | fs1 | 000 | fd | 1000111 |
5 | 2 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fmul.d
fd[4:0]
fs1[4:0]
fs2[4:0]
rm[2:0]
Multiply double-precision floating-point. Calculate fs1*fs2 and put the result in fd.
The rm field is rounding mode.
f[fd] = f[fs1] * f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0001001 | fs2 | fs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fmul.s
fd[4:0]
fs1[4:0]
fs2[4:0]
rm[2:0]
Multiply single-precision floating-point. Calculate fs1*fs2 and put the result in fd.
The rm field is rounding mode.
f[fd] = f[fs1] * f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0001000 | fs2 | fs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64D
fmv.d.x
fd[4:0]
rs[4:0]
Move 64-bit integer to single-precision floating-point. The bits are not modified.
f[fd] = r[rs]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1111001 | 00000 | rs | 000 | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fmv.w.x
fd[4:0]
rs[4:0]
Move 32-bit integer to single-precision floating-point. The bits are not modified.
f[fd] = 1ext(r[rs][31:0])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1111000 | 00000 | rs | 000 | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64D
fmv.x.d
rd[4:0]
fs[4:0]
Move double-precision floating-point to 64-bit integer. The bits are not modified.
x[rd] = sext(f[fs])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1110001 | 00000 | fs | 000 | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fmv.x.w
rd[4:0]
fs[4:0]
Move single-precision floating-point to 32-bit integer. The bits are not modified.
x[rd] = sext(f[fs][31:0])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
1110000 | 00000 | fs | 000 | rd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fnmadd.d
fd[4:0]
fs1[4:0]
fs2[4:0]
fs3[4:0]
Negative multiply and add double-precision floating-point. Calculate -(fs1*fs2)-fs3 and put the result in fd.
f[fd] = -(f[fs1] * f[fs2]) - f[fs3]
31 27 | 26 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
fs3 | 01 | fs2 | fs1 | 000 | fd | 1001111 |
5 | 2 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fnmadd.s
fd[4:0]
fs1[4:0]
fs2[4:0]
fs3[4:0]
Negative multiply and add single-precision floating-point. Calculate -(fs1*fs2)-fs3 and put the result in fd.
f[fd] = -(f[fs1] * f[fs2]) - f[fs3]
31 27 | 26 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
fs3 | 00 | fs2 | fs1 | 000 | fd | 1001111 |
5 | 2 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fnmsub.d
fd[4:0]
fs1[4:0]
fs2[4:0]
fs3[4:0]
Negative multiply and subtract double-precision floating-point. Calculate -(fs1*fs2)+fs3 and put the result in fd.
f[fd] = -(f[fs1] * f[fs2]) + f[fs3]
31 27 | 26 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
fs3 | 01 | fs2 | fs1 | 000 | fd | 1001011 |
5 | 2 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fnmsub.s
fd[4:0]
fs1[4:0]
fs2[4:0]
fs3[4:0]
Negative multiply and subtract single-precision floating-point. Calculate -(fs1*fs2)+fs3 and put the result in fd.
f[fd] = -(f[fs1] * f[fs2]) + f[fs3]
31 27 | 26 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
fs3 | 00 | fs2 | fs1 | 000 | fd | 1001011 |
5 | 2 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fsd
fs2
rs1[4:0]
imm[11:0]
Store double-precision floating-point. Copy register fs2
as doubleword into memory at address imm
+rs1
.
M[x[rs1] + sext(imm)] = f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:5] | fs2 | rs1 | 011 | imm[4:0] | 0100111 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: fld
RV32D, RV64D
fsgnj.d
fd[4:0]
fs1[4:0]
fs2[4:0]
Sign inject for double-precision floating-point.
Move fs1, with the sign bit of fs2, into fd.
f[fd] = f[fs1][62:0] | (f[fs2][63] << 63)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0010001 | fs2 | fs1 | 000 | fd | 1001011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fsgnjn.d
fd[4:0]
fs1[4:0]
fs2[4:0]
Negative sign inject for double-precision floating-point.
Move fs1, with the sign bit of ~fs2, into fd.
f[fd] = f[fs1][62:0] | (~(f[fs2][63]) << 63)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0010001 | fs2 | fs1 | 001 | fd | 1001011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fsgnjn.s
fd[4:0]
fs1[4:0]
fs2[4:0]
Negative sign inject for single-precision floating-point.
Move fs1, with the sign bit of ~fs2, into fd.
f[fd] = f[fs1][30:0] | (~(f[fs2][31]) << 31)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0010000 | fs2 | fs1 | 001 | fd | 1001011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fsgnj.s
fd[4:0]
fs1[4:0]
fs2[4:0]
Sign inject for single-precision floating-point.
Move fs1, with the sign bit of fs2, into fd.
f[fd] = f[fs1][30:0] | (f[fs2][31] << 31)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0010000 | fs2 | fs1 | 000 | fd | 1001011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fsgnjx.d
fd[4:0]
fs1[4:0]
fs2[4:0]
Xor sign inject for double-precision floating-point.
Move fs1, with the sign bit of fs1^fs2, into fd.
f[fd] = f[fs1][62:0] | ((f[fs1][63] ^ f[fs2][63]) << 63)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0010001 | fs2 | fs1 | 010 | fd | 1001011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fsgnjx.s
fd[4:0]
fs1[4:0]
fs2[4:0]
Xor sign inject for single-precision floating-point.
Move fs1, with the sign bit of fs1^fs2, into fd.
f[fd] = f[fs1][30:0] | ((f[fs1][31] ^ f[fs2][31]) << 31)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0010000 | fs2 | fs1 | 010 | fd | 1001011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fsqrt.d
fd[4:0]
fs1[4:0]
rm[2:0]
Square root double-precision floating-point. Calculate sqrt(fs1) and put the result in fd.
The rm field is rounding mode.
f[fd] = sqrt(f[fs1])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0101101 | 00000 | fs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fsqrt.s
fd[4:0]
fs1[4:0]
rm[2:0]
Square root single-precision floating-point. Calculate sqrt(fs1) and put the result in fd.
The rm field is rounding mode.
f[fd] = sqrt(f[fs1])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0101100 | 00000 | fs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32D, RV64D
fsub.d
fd[4:0]
fs1[4:0]
fs2[4:0]
rm[2:0]
Subtract double-precision floating-point. Calculate fs1-fs2 and put the result in fd.
The rm field is rounding mode.
f[fd] = f[fs1] - f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000101 | fs2 | fs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fsub.s
fd[4:0]
fs1[4:0]
fs2[4:0]
rm[2:0]
Subtract single-precision floating-point. Calculate fs1-fs2 and put the result in fd.
The rm field is rounding mode.
f[fd] = f[fs1] - f[fs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000100 | fs2 | fs1 | rm | fd | 1010011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32F, RV64F
fsw
fs2
rs1[4:0]
imm[11:0]
Store single-precision floating-point. Copy register fs2
as word into memory at address imm
+rs1
.
M[x[rs1] + sext(imm)] = f[fs2][31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:5] | fs2 | rs1 | 010 | imm[4:0] | 0100111 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: flw
RV32I, RV64I
jal
rd[4:0]
imm[20:1]
Jump and link. Add imm
(multiple of 2 bytes) to pc
. Put the address of the instruction following the jump (pc
+ 4 before adding) in rd
.
x[rd] = pc + 4
pc += sext(imm)
31 12 | 11 7 | 6 0 |
imm[20,10:1,11,19:12] | rd | 1101111 |
20 | 5 | 7 |
Related: jalr
RV32I, RV64I
jalr
rd[4:0]
rs1[4:0]
imm[11:0]
Jump and link register. Add imm
and rs1
, clear the least-significant bit and put the result in pc
. Put the address of the instruction following the jump (pc
+ 4 before changing pc
) in rd
.
t = pc + 4
pc = (x[rs1] + sext(imm)) & ∼1
x[rd] = t
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 000 | rd | 1100111 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
lb
rd[4:0]
rs1[4:0]
imm[11:0]
Load byte. Copy one byte from memory at address imm
+rs1
into register rd
.
x[rd] = sext(M[x[rs1] + sext(imm)][7:0])
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 000 | rd | 0000011 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
lbu
rd[4:0]
rs1[4:0]
imm[11:0]
Load byte, unsigned. Copy one byte from memory at address imm
+rs1
into register rd
.
x[rd] = M[x[rs1] + sext(imm)][7:0]
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 100 | rd | 0000011 |
12 | 5 | 3 | 5 | 7 |
RV64I
ld
rd[4:0]
rs1[4:0]
imm[11:0]
Load doubleword. Copy doubleword from memory at address imm
+rs1
into register rd
.
x[rd] = sext(M[x[rs1] + sext(imm)][63:0])
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 011 | rd | 0000011 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
lh
rd[4:0]
rs1[4:0]
imm[11:0]
Load halfword. Copy halfword from memory at address imm
+rs1
into register rd
.
x[rd] = sext(M[x[rs1] + sext(imm)][15:0])
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 001 | rd | 0000011 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
lhu
rd[4:0]
rs1[4:0]
imm[11:0]
Load halfword, unsigned. Copy halfword from memory at address imm
+rs1
into register rd
.
x[rd] = M[x[rs1] + sext(imm)][15:0]
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 101 | rd | 0000011 |
12 | 5 | 3 | 5 | 7 |
RV64IA
lr.d
rd[4:0]
rs1[4:0]
aq[0]
rl[0]
Load-reserve doubleword. Copy doubleword from memory at address rs1
and put it in rd
.
In addition to loading memory, remember what bytes were loaded so that this instruction can be paired with sc.d
.
x[rd] = sext(M[x[rs1]][63:0])
Reserve(x[rs1]:x[rs1]+63)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
00010, aq, rl | 00000 | rs1 | 011 | rd | 0100000 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32IA, RV64IA
lr.w
rd[4:0]
rs1[4:0]
aq[0]
rl[0]
Load-reserve word. Copy word from memory at address rs1
and put it in rd
.
In addition to loading memory, remember what bytes were loaded so that this instruction can be paired with sc.w
.
x[rd] = sext(M[x[rs1]][31:0])
Reserve(x[rs1]:x[rs1]+31)
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
00010, aq, rl | 00000 | rs1 | 010 | rd | 0100000 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
lui
rd[4:0]
imm[31:12]
Load upper immediate. Can be used to build 32-bit constants. Put upper 20 bits of imm
in rd
and fill lower 12 bits with zeros.
x[rd] = sext(imm[31:12] << 12)
31 12 | 11 7 | 6 0 |
imm[31:12] | rd | 0110111 |
20 | 5 | 7 |
Related: auipc
RV32I, RV64I
lw
rd[4:0]
rs1[4:0]
imm[11:0]
Load word. Copy word from memory at address imm
+rs1
into register rd
.
x[rd] = sext(M[x[rs1] + sext(imm)][31:0])
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 010 | rd | 0000011 |
12 | 5 | 3 | 5 | 7 |
Related: sw
RV64I
lwu
rd[4:0]
rs1[4:0]
imm[11:0]
Load word, unsigned. Copy word from memory at address imm
+rs1
into register rd
.
x[rd] = M[x[rs1] + sext(imm)][31:0]
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 110 | rd | 0000011 |
12 | 5 | 3 | 5 | 7 |
Related: lw
RV32M, RV64M
mul
rd[4:0]
rs1[4:0]
rs2[4:0]
Multiply. Multiply rs1
and rs2
and put the lower bits of the result in rd
. Arithmetic overflow is ignored.
x[rd] = (x[rs1] *s x[rs2])[XHI:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | rs2 | rs1 | 000 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32M, RV64M
mulh
rd[4:0]
rs1[4:0]
rs2[4:0]
Multiply upper. Multiply rs1
and rs2
and put the upper bits of the result in rd
.
x[rd] = (x[rs1] *s x[rs2])[DXHI:XLEN]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | rs2 | rs1 | 001 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32M, RV64M
mulhsu
rd[4:0]
rs1[4:0]
rs2[4:0]
Multiply upper signed*unsigned. Multiply signed rs1
and unsigned rs2
and put the upper bits of the result in rd
.
x[rd] = (x[rs1] *s,u x[rs2])[DXHI:XLEN]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | rs2 | rs1 | 010 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32M, RV64M
mulhu
rd[4:0]
rs1[4:0]
rs2[4:0]
Multiply upper unsigned. Multiply unsigned rs1
and unsigned rs2
and put the upper bits of the result in rd
.
x[rd] = (x[rs1] *u x[rs2])[DXHI:XLEN]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | rs2 | rs1 | 011 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64M
mulw
rd[4:0]
rs1[4:0]
rs2[4:0]
Multiply word. Multiply the lower 32 bits of rs1
and rs2
and put the lower bits of the result in rd
. Arithmetic overflow is ignored.
x[rd] = sext((x[rs1] *s x[rs2])[31:0])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | rs2 | rs1 | 000 | rd | 0111011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
or
rd[4:0]
rs1[4:0]
rs2[4:0]
OR. Calculate bitwise OR on rs1
and rs2
and put the result in rd
.
x[rd] = x[rs1] | x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000 | rs2 | rs1 | 110 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
ori
rd[4:0]
rs1[4:0]
imm[11:0]
OR immediate. Calculate bitwise OR on rs1
and imm
and put the result in rd
.
x[rd] = x[rs1] | sext(imm)
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 110 | rd | 0010011 |
12 | 5 | 3 | 5 | 7 |
RV32M, RV64M
rem
rd[4:0]
rs1[4:0]
rs2[4:0]
Remainder. Divide rs1
by rs2
and put the remainder of the result (rounded towards zero) in rd
.
x[rd] = x[rs1] /s x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | rs2 | rs1 | 110 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: div
RV32M, RV64M
remu
rd[4:0]
rs1[4:0]
rs2[4:0]
Remainder unsigned. Divide unsigned rs1
by unsigned rs2
and put the remainder of the result (rounded towards zero) in rd
.
x[rd] = x[rs1] /u x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | rs2 | rs1 | 111 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: divu
RV64M
remuw
rd[4:0]
rs1[4:0]
rs2[4:0]
Remainder unsigned word. Divide the lower 32 bits of unsigned rs1
by the lower 32 bits of unsigned rs2
and put the remainder of the result (rounded towards zero) in rd
.
x[rd] = x[rs1][31:0] /u x[rs2][31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | rs2 | rs1 | 111 | rd | 0111011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: divuw
RV64M
remw
rd[4:0]
rs1[4:0]
rs2[4:0]
Remainder word. Divide the lower 32 bits of rs1
by the lower 32 bits of rs2
and put the remainder of the result (rounded towards zero) in rd
.
x[rd] = x[rs1][31:0] /s x[rs2][31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000001 | rs2 | rs1 | 110 | rd | 0111011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: divw
RV32I, RV64I
sb
rs2[4:0]
rs1[4:0]
imm[11:0]
Store byte. Copy register rs2
as byte into memory at address imm
+rs1
.
M[x[rs1] + sext(imm)] = x[rs2][7:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:5] | rs2 | rs1 | 000 | imm[4:0] | 0100011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: lb
RV64IA
sc.d
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Store-conditional doubleword. Conditionally copy register rs2
as doubleword into memory at address rs1
and return error code in rd
.
Result in rd
: 0=success, non-0=failure. Success means that the value at the target address has not changed since the last load-reserve by the same hart and that the target range of memory is included in the reserved range by the last load-reserve.
if (ReservationIsValid(x[rs1]:x[rs1]+63)) {
M[x[rs1]] = x[rs2][63:0]
x[rd] = 0
} else {
x[rd] = 1 // or other non-0
}
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
00011, aq, rl | rs2 | rs1 | 011 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32IA, RV64IA
sc.w
rd[4:0]
rs1[4:0]
rs2[4:0]
aq[0]
rl[0]
Store-conditional word. Conditionally copy register rs2
as word into memory at address rs1
and return error code in rd
.
Result in rd
: 0=success, non-0=failure. Success means that the value at the target address has not changed since the last load-reserve by the same hart and that the target range of memory is included in the reserved range by the last load-reserve.
if (ReservationIsValid(x[rs1]:x[rs1]+31)) {
M[x[rs1]] = x[rs2][31:0]
x[rd] = 0
} else {
x[rd] = 1 // or other non-0
}
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
00011, aq, rl | rs2 | rs1 | 010 | rd | 0101111 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64I
sd
rs2[4:0]
rs1[4:0]
imm[11:0]
Store doubleword. Copy register rs2
as doubleword into memory at address imm
+rs1
.
M[x[rs1] + sext(imm)] = x[rs2][63:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:5] | rs2 | rs1 | 011 | imm[4:0] | 0100011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
sh
rs2[4:0]
rs1[4:0]
imm[11:0]
Store halfword. Copy register rs2
as halfword into memory at address imm
+rs1
.
M[x[rs1] + sext(imm)] = x[rs2][15:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:5] | rs2 | rs1 | 001 | imm[4:0] | 0100011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: lh
RV32I, RV64I
sll
rd[4:0]
rs1[4:0]
rs2[4:0]
Shift left logical. Shift rs1
left rs2
bits and put the result in rd
. The lower bits are filled with zeros. Only the lower 5 bits (RV32I) or 6 bits (RV64I) in rs2
are used.
x[rd] = x[rs1] << x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000 | rs2 | rs1 | 001 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: srl
RV32I
slli
rd[4:0]
rs1[4:0]
imm[4:0]
Shift left logical immediate. Shift rs1
left imm
bits. The lower bits are filled with zeros.
x[rd] = x[rs1] << imm
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000, imm[4:0] | rs1 | 001 | rd | 0010011 |
12 | 5 | 3 | 5 | 7 |
Related: srli
RV64I
slli
rd[4:0]
rs1[4:0]
imm[5:0]
Shift left logical immediate. Shift rs1
left imm
bits. The lower bits are filled with zeros.
x[rd] = x[rs1] << imm
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
000000, imm[5:0] | rs1 | 001 | rd | 0010011 |
12 | 5 | 3 | 5 | 7 |
Related: srli
RV64I
slliw
rd[4:0]
rs1[4:0]
imm[5:0]
Shift left logical word immediate. Shift rs1
left imm
bits. The lower bits are filled with zeros. imm[5]
must be 0.
x[rd] = sext((x[rs1] << imm)[31:0])
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
000000, imm[5:0] | rs1 | 001 | rd | 0011011 |
12 | 5 | 3 | 5 | 7 |
Related: srliw
RV64I
sllw
rd[4:0]
rs1[4:0]
rs2[4:0]
Shift left logical word. Shift rs1
left rs2
bits and put the result in rd
. The lower bits are filled with zeros. Only the lower 5 bits of rs2
are used.
x[rd] = sext((x[rs1] << x[rs2][4:0])[31:0])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000 | rs2 | rs1 | 001 | rd | 0111011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: srlw
RV32I, RV64I
slt
rd[4:0]
rs1[4:0]
rs2[4:0]
Set if <. Put 1 in rd
if rs1
is less than (signed) rs2
, else 0 is written to rd
.
x[rd] = x[rs1] <s x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000 | rs2 | rs1 | 010 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
slti
rd[4:0]
rs1[4:0]
imm[11:0]
Set if < immediate. Put 1 in rd
if rs1
is less than (signed) imm
, else 0 is written to rd
.
x[rd] = x[rs1] <s sext(imm)
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 010 | rd | 0010011 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
sltiu
rd[4:0]
rs1[4:0]
imm[11:0]
Set if < immediate, unsigned. Put 1 in rd
if rs1
is less than (unsigned) imm
, else 0 is written to rd
.
x[rd] = x[rs1] <u sext(imm)
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 011 | rd | 0010011 |
12 | 5 | 3 | 5 | 7 |
RV32I, RV64I
sltu
rd[4:0]
rs1[4:0]
rs2[4:0]
Set if <, unsigned. Put 1 in rd
if rs1
is less than (unsigned) rs2
, else 0 is written to rd
.
x[rd] = x[rs1] <u x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000 | rs2 | rs1 | 011 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
sra
rd[4:0]
rs1[4:0]
rs2[4:0]
Shift right arithmetic. Shift rs1
right rs2
bits and put the result in rd
. The upper bits are filled with the original sign bit. Only the lower 5 bits (RV32I) or 6 bits (RV64I) in rs2
are used.
x[rd] = x[rs1] >>s x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0100000 | rs2 | rs1 | 101 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: srl
RV32I
srai
rd[4:0]
rs1[4:0]
imm[4:0]
Shift right arithmetic immediate. Shift rs1
right imm
bits. The upper bits are filled with the original sign bit.
x[rd] = x[rs1] >>s imm
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0100000, imm[4:0] | rs1 | 101 | rd | 0010011 |
12 | 5 | 3 | 5 | 7 |
Related: srli
RV64I
srai
rd[4:0]
rs1[4:0]
imm[5:0]
Shift right arithmetic immediate. Shift rs1
right imm
bits. The upper bits are filled with the original sign bit.
x[rd] = x[rs1] >>s imm
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
010000, imm[5:0] | rs1 | 101 | rd | 0010011 |
12 | 5 | 3 | 5 | 7 |
Related: srli
RV64I
sraiw
rd[4:0]
rs1[4:0]
imm[5:0]
Shift right arithmetic word immediate. Shift rs1
right imm
bits. The upper bits are filled with the original sign bit.
x[rd] = sext(x[rs1][31:0] >>s imm)
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
010000, imm[5:0] | rs1 | 101 | rd | 0011011 |
12 | 5 | 3 | 5 | 7 |
Related: srliw
RV64I
sraw
rd[4:0]
rs1[4:0]
rs2[4:0]
Shift right arithmetic word. Shift rs1
right rs2
bits and put the result in rd
. The upper bits are filled with the original sign bit. Only the lower 5 bits in rs2
are used.
x[rd] = sext(x[rs1][31:0] >>s x[rs2][4:0])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0100000 | rs2 | rs1 | 101 | rd | 0111011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: srlw
RV32I, RV64I
srl
rd[4:0]
rs1[4:0]
rs2[4:0]
Shift right logical. Shift rs1
right rs2
bits and put the result in rd
. The upper bits are filled with zeros. Only the lower 5 bits (RV32I) or 6 bits (RV64I) in rs2
are used.
x[rd] = x[rs1] >>u x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000 | rs2 | rs1 | 101 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I
srli
rd[4:0]
rs1[4:0]
imm[4:0]
Shift right logical immediate. Shift rs1
right imm
bits. The upper bits are filled with zeros.
x[rd] = x[rs1] >>u imm
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000, imm[4:0] | rs1 | 101 | rd | 0010011 |
12 | 5 | 3 | 5 | 7 |
RV64I
srli
rd[4:0]
rs1[4:0]
imm[5:0]
Shift right logical immediate. Shift rs1
right imm
bits. The upper bits are filled with zeros.
x[rd] = x[rs1] >>u imm
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
000000, imm[5:0] | rs1 | 101 | rd | 0010011 |
12 | 5 | 3 | 5 | 7 |
RV64I
srliw
rd[4:0]
rs1[4:0]
imm[5:0]
Shift right logical word immediate. Shift rs1
right imm
bits. The upper bits are filled with zeros. imm[5]
must be 0.
x[rd] = sext(x[rs1][31:0] >>u imm)
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
000000, imm[5:0] | rs1 | 101 | rd | 0011011 |
12 | 5 | 3 | 5 | 7 |
RV64I
srlw
rd[4:0]
rs1[4:0]
rs2[4:0]
Shift right logical word. Shift rs1
right rs2
bits and put the result in rd
. The upper bits are filled with zeros. Only the lower 5 bits in rs2
are used.
x[rd] = sext(x[rs1][31:0] >>u x[rs2][4:0])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000 | rs2 | rs1 | 101 | rd | 0111011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
sub
rd[4:0]
rs1[4:0]
rs2[4:0]
Subtract. Subtract rs2
from rs1
and put the result in rd
. Arithmetic overflow is ignored.
x[rd] = x[rs1] - x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0100000 | rs2 | rs1 | 000 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV64I
subw
rd[4:0]
rs1[4:0]
rs2[4:0]
Subtract word. Subtract rs2
from rs1
and put the result in rd
. Arithmetic overflow is ignored.
x[rd] = sext((x[rs1] - x[rs2])[31:0])
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0100000 | rs2 | rs1 | 000 | rd | 0111011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
sw
rs2[4:0]
rs1[4:0]
imm[11:0]
Store word. Copy register rs2
as word into memory at address imm
+rs1
.
M[x[rs1] + sext(imm)] = x[rs2][31:0]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:5] | rs2 | rs1 | 010 | imm[4:0] | 0100011 |
7 | 5 | 5 | 3 | 5 | 7 |
Related: lw
RV32I, RV64I
xor
rd[4:0]
rs1[4:0]
rs2[4:0]
Exclusive OR. Calculate bitwise XOR on rs1
and rs2
and put the result in rd
.
x[rd] = x[rs1] ^ x[rs2]
31 25 | 24 20 | 19 15 | 14 12 | 11 7 | 6 0 |
0000000 | rs2 | rs1 | 100 | rd | 0110011 |
7 | 5 | 5 | 3 | 5 | 7 |
RV32I, RV64I
xori
rd[4:0]
rs1[4:0]
imm[11:0]
Exclusive OR immediate. Calculate bitwise XOR on rs1
and imm
and put the result in rd
.
x[rd] = x[rs1] ^ sext(imm)
31 20 | 19 15 | 14 12 | 11 7 | 6 0 |
imm[11:0] | rs1 | 100 | rd | 0010011 |
12 | 5 | 3 | 5 | 7 |