RISC-V instructions

Contents:

Instructions by category

Int Arith:add addi addiw addw amoadd.d amoadd.w amomax.d amomaxu.d amomaxu.w amomax.w amomin.d amominu.d amominu.w amomin.w div divu divuw divw mul mulh mulhsu mulhu mulw rem remu remuw remw sub subw
Float Arith:fadd.d fadd.s fdiv.d fdiv.s fmadd.d fmadd.s fmax.d fmax.s fmin.d fmin.s fmsub.d fmsub.s fmul.d fmul.s fnmadd.d fnmadd.s fnmsub.d fnmsub.s fsqrt.d fsqrt.s fsub.d fsub.s
Logic:amoand.d amoand.w amoor.d amoor.w amoxor.d amoxor.w and andi or ori xor xori
Shift:sll slli slliw sllw sra srai sraiw sraw srl srli srliw srlw
Branch:beq bge bgeu blt bltu bne
Jump:jal jalr
Memory:amoswap.d amoswap.w fence fence.i fld flw fsd fsw lb lbu ld lh lhu lr.d lr.w lw lwu sb sc.d sc.w sd sh sw
Convert:fcvt.d.l fcvt.d.lu fcvt.d.s fcvt.d.w fcvt.d.wu fcvt.l.d fcvt.l.s fcvt.lu.d fcvt.lu.s fcvt.s.d fcvt.s.l fcvt.s.lu fcvt.s.w fcvt.s.wu fcvt.w.d fcvt.w.s fcvt.wu.d fcvt.wu.s
Conditional:feq.d feq.s fle.d fle.s flt.d flt.s slt slti sltiu sltu
Control/Status:csrrc csrrci csrrs csrrsi csrrw csrrwi
Uncategorized:auipc ebreak ecall fclass.d fclass.s fmv.d.x fmv.w.x fmv.x.d fmv.x.w fsgnj.d fsgnjn.d fsgnjn.s fsgnj.s fsgnjx.d fsgnjx.s lui

Explanations

TermMeaning
immImmediate integer value
pcProgram counter
rdDestination integer register
fdDestination 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
<sLess than (signed)
<uLess than (unsigned)
^Bitwise Exclusive OR
|Bitwise OR
&Bitwise AND
~Bitwise NOT
<<Logical bitshift left
>>uLogical bitshift right
>>sArithmetic bitshift right
XLENThe size of a register in bits (32 on RV32, 64 on RV64)
XHIThe index of the highest bit (XLEN - 1)
DXHIThe index of the highest bit of a double sized register (XLEN * 2 - 1)
byte8-bit number
halfword16-bit number
word32-bit number
doubleword64-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:

ValueNameDescription
000RNERound to nearest, ties to even.
001RTZRound towards zero.
010RDNRound down.
011RUPRound up.
100RMMRound to nearest, ties to max magnitude.
101Invalid.
110Invalid.
111DYNDynamic; 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/.

Assembler Instructions

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

Hardware Instructions

These are the instructions that your processor decodes and executes.


RV32I, RV64I

add rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

Add. Add rs1 and rs2 and put the result in rd. Arithmetic overflow is ignored.

x[rd] = x[rs1] + x[rs2]
31 2524 2019 1514 1211 76 0
0000000rs2rs1000rd0110011
755357

RV32I, RV64I

addi rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[11:0] const

Add immediate. Add rs1 and imm and put the result in rd. Arithmetic overflow is ignored.

x[rd] = x[rs1] + sext(imm)
31 2019 1514 1211 76 0
imm[11:0]rs1000rd0010011
125357

RV64I

addiw rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[11:0] const

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 2019 1514 1211 76 0
imm[11:0]rs1000rd0011011
125357

RV64I

addw rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000000rs2rs1000rd0111011
755357

RV64A

amoadd.d rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
00000, aq, rlrs2rs1011rd0101111
755357

Related: add


RV32A, RV64A

amoadd.w rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
00000, aq, rlrs2rs1010rd0101111
755357

Related: addw


RV64A

amoand.d rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
01100, aq, rlrs2rs1011rd0101111
755357

Related: and


RV32A, RV64A

amoand.w rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
01100, aq, rlrs2rs1010rd0101111
755357

Related: and


RV64A

amomax.d rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
10100, aq, rlrs2rs1011rd0101111
755357

RV64A

amomaxu.d rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
11100, aq, rlrs2rs1011rd0101111
755357

RV32A, RV64A

amomaxu.w rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
11100, aq, rlrs2rs1010rd0101111
755357

RV32A, RV64A

amomax.w rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
10100, aq, rlrs2rs1010rd0101111
755357

RV64A

amomin.d rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
10000, aq, rlrs2rs1011rd0101111
755357

RV64A

amominu.d rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
11000, aq, rlrs2rs1011rd0101111
755357

RV32A, RV64A

amominu.w rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
11000, aq, rlrs2rs1010rd0101111
755357

RV32A, RV64A

amomin.w rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
10000, aq, rlrs2rs1010rd0101111
755357

RV64A

amoor.d rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
01000, aq, rlrs2rs1011rd0101111
755357

Related: or


RV32A, RV64A

amoor.w rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
01000, aq, rlrs2rs1010rd0101111
755357

Related: or


RV64A

amoswap.d rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
00001, aq, rlrs2rs1011rd0101111
755357

RV32A, RV64A

amoswap.w rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
00001, aq, rlrs2rs1010rd0101111
755357

RV64A

amoxor.d rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
00100, aq, rlrs2rs1011rd0101111
755357

Related: xor


RV32A, RV64A

amoxor.w rd, rs2, (rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(RW)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
00100, aq, rlrs2rs1010rd0101111
755357

Related: xor


RV32I, RV64I

and rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

AND. Calculate bitwise AND on rs1 and rs2 and put the result in rd.

x[rd] = x[rs1] & x[rs2]
31 2524 2019 1514 1211 76 0
0000000rs2rs1111rd0110011
755357

RV32I, RV64I

andi rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[11:0] const

AND immediate. Calculate bitwise AND on rs1 and imm and put the result in rd.

x[rd] = x[rs1] & sext(imm)
31 2019 1514 1211 76 0
imm[11:0]rs1111rd0010011
125357

RV32I, RV64I

auipc rd, imm[31:12]

rd[4:0] reg(W)
imm[31:12] const

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 1211 76 0
imm[31:12]rd0010111
2057

Related: lui


RV32I, RV64I

beq rs1, rs2, imm

rs1[4:0] reg(R)
rs2[4:0] reg(R)
imm[12:1] const

Branch if =. Add imm (multiple of 2) to pc if rs1 and rs2 are equal.

if (x[rs1] == x[rs2]) pc += sext(imm)
31 2524 2019 1514 1211 76 0
imm[12,10:5]rs2rs1000imm[4:1,11]1100011
755357

RV32I, RV64I

bge rs1, rs2, imm

rs1[4:0] reg(R)
rs2[4:0] reg(R)
imm[12:1] const

Branch if ≥. Add imm (multiple of 2) to pc if rs1 is greater than (signed) or equal to rs2.

if (x[rs1] ≥s x[rs2]) pc += sext(imm)
31 2524 2019 1514 1211 76 0
imm[12,10:5]rs2rs1101imm[4:1,11]1100011
755357

RV32I, RV64I

bgeu rs1, rs2, imm

rs1[4:0] reg(R)
rs2[4:0] reg(R)
imm[12:1] const

Branch if ≥, unsigned. Add imm (multiple of 2) to pc if rs1 is greater than (unsigned) or equal to rs2.

if (x[rs1] ≥u x[rs2]) pc += sext(imm)
31 2524 2019 1514 1211 76 0
imm[12,10:5]rs2rs1111imm[4:1,11]1100011
755357

RV32I, RV64I

blt rs1, rs2, imm

rs1[4:0] reg(R)
rs2[4:0] reg(R)
imm[12:1] const

Branch if <. Add imm (multiple of 2) to pc if rs1 is less than (signed) rs2.

if (x[rs1] <s x[rs2]) pc += sext(imm)
31 2524 2019 1514 1211 76 0
imm[12,10:5]rs2rs1100imm[4:1,11]1100011
755357

RV32I, RV64I

bltu rs1, rs2, imm

rs1[4:0] reg(R)
rs2[4:0] reg(R)
imm[12:1] const

Branch if <, unsigned. Add imm (multiple of 2) to pc if rs1 is less than (unsigned) rs2.

if (x[rs1] <u x[rs2]) pc += sext(imm)
31 2524 2019 1514 1211 76 0
imm[12,10:5]rs2rs1110imm[4:1,11]1100011
755357

RV32I, RV64I

bne rs1, rs2, imm

rs1[4:0] reg(R)
rs2[4:0] reg(R)
imm[12:1] const

Branch if ≠. Add imm (multiple of 2) to pc if rs1 and rs2 are not equal.

if (x[rs1] ≠ x[rs2]) pc += sext(imm)
31 2524 2019 1514 1211 76 0
imm[12,10:5]rs2rs1001imm[4:1,11]1100011
755357

RV32I, RV64I

csrrc rd csr rs1

rd[4:0] reg(W)
csr[11:0] reg(RW)
rs1[4:0] reg(R)

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 2019 1514 1211 76 0
csrrs1011rd1110011
125357

RV32I, RV64I

csrrci rd csr imm[4:0]

rd[4:0] reg(W)
csr[11:0] reg(RW)
imm[4:0] const

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 2019 1514 1211 76 0
csrimm111rd1110011
125357

RV32I, RV64I

csrrs rd, csr, rs1

rd[4:0] reg(W)
csr[11:0] reg(RW)
rs1[4:0] reg(R)

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 2019 1514 1211 76 0
csrrs1010rd1110011
125357

RV32I, RV64I

csrrsi rd, csr, imm[4:0]

rd[4:0] reg(W)
csr[11:0] reg(RW)
imm[4:0] const

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 2019 1514 1211 76 0
csrimm110rd1110011
125357

RV32I, RV64I

csrrw rd, csr, rs1

rd[4:0] reg(W)
csr[11:0] reg(RW)
rs1[4:0] reg(R)

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 2019 1514 1211 76 0
csrrs1001rd1110011
125357

RV32I, RV64I

csrrwi rd, csr, imm[4:0]

rd[4:0] reg(W)
csr[11:0] reg(RW)
imm[4:0] const

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 2019 1514 1211 76 0
csrimm101rd1110011
125357

RV32M, RV64M

div rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

Divide. Divide rs1 by rs2 and put the result (rounded towards zero) in rd.

x[rd] = x[rs1] /s x[rs2]
31 2524 2019 1514 1211 76 0
0000001rs2rs1100rd0110011
755357

Related: rem


RV32M, RV64M

divu rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000001rs2rs1101rd0110011
755357

Related: remu


RV64M

divuw rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000001rs2rs1101rd0111011
755357

Related: remuw


RV64M

divw rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000001rs2rs1100rd0111011
755357

Related: remw


RV32I, RV64I

ebreak

Environment breakpoint. Used by debuggers to cause control to be transferred back to the debugger.

RaiseException(Breakpoint)
31 2019 1514 1211 76 0
00000000000100000000000001110011
125357

RV32I, RV64I

ecall

Environment call. Make a request to the supporting execution environment (usually the operating system).

RaiseException(EnvironmentCall)
31 2019 1514 1211 76 0
00000000000000000000000001110011
125357

RV32D, RV64D

fadd.d fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
0000001fs2fs1rmfd1010011
755357

RV32F, RV64F

fadd.s fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
0000000fs2fs1rmfd1010011
755357

RV32D, RV64D

fclass.d rd, fs

rd[4:0] reg(W)
fs[4:0] reg(R)

Classify double-precision floating-point. Set flags in rd depending on the properties of fs. Other bits are set to 0.

rd bitMeaning
0fs is -infinity
1fs is a negative normal number
2fs is a negative subnormal number
3fs is -0
4fs is +0
5fs is a positive subnormal number
6fs is a positive normal number
7fs is +infinity
8fs is a signaling NaN
9fs is a quiet NaN
r[rd] = Classify(f[fs])
31 2524 2019 1514 1211 76 0
111000100000fs001rd1010011
755357

RV32F, RV64F

fclass.s rd, fs

rd[4:0] reg(W)
fs[4:0] reg(R)

Classify single-precision floating-point. Set flags in rd depending on the properties of fs. Other bits are set to 0.

rd bitMeaning
0fs is -infinity
1fs is a negative normal number
2fs is a negative subnormal number
3fs is -0
4fs is +0
5fs is a positive subnormal number
6fs is a positive normal number
7fs is +infinity
8fs is a signaling NaN
9fs is a quiet NaN
r[rd] = Classify(f[fs])
31 2524 2019 1514 1211 76 0
111000000000fs001rd1010011
755357

RV64D

fcvt.d.l fd, rs1

fd[4:0] reg(W)
rs1[4:0] reg(R)
rm[2:0] const

Convert 64-bit integer to double-precision floating-point.

The rm field is rounding mode.

f[fd] = 1ext(i64_to_f32(x[rs1]))
31 2524 2019 1514 1211 76 0
110100100010rs1rmfd1010011
755357

RV64D

fcvt.d.lu fd, rs1

fd[4:0] reg(W)
rs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110100100011rs1rmfd1010011
755357

RV64D

fcvt.d.s fd, fs1

fd[4:0] reg(W)
fs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
010000100000fs1rmfd1010011
755357

Related: fcvt.s.d


RV32D, RV64D

fcvt.d.w fd, rs1

fd[4:0] reg(W)
rs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110100100000rs1rmfd1010011
755357

RV32D, RV64D

fcvt.d.wu fd, rs1

fd[4:0] reg(W)
rs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110100100001rs1rmfd1010011
755357

RV64D

fcvt.l.d rd, fs1

rd[4:0] reg(W)
fs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110000100010fs1rmrd1010011
755357

RV64F

fcvt.l.s rd, fs1

rd[4:0] reg(W)
fs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110000000010fs1rmrd1010011
755357

RV64D

fcvt.lu.d rd, fs1

rd[4:0] reg(W)
fs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110000100011fs1rmrd1010011
755357

RV64F

fcvt.lu.s rd, fs1

rd[4:0] reg(W)
fs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110000000011fs1rmrd1010011
755357

RV64D

fcvt.s.d fd, fs1

fd[4:0] reg(W)
fs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
010000000001fs1rmfd1010011
755357

Related: fcvt.d.s


RV64F

fcvt.s.l fd, rs1

fd[4:0] reg(W)
rs1[4:0] reg(R)
rm[2:0] const

Convert 64-bit integer to single-precision floating-point.

The rm field is rounding mode.

f[fd] = 1ext(i64_to_f32(x[rs1]))
31 2524 2019 1514 1211 76 0
110100000010rs1rmfd1010011
755357

RV64F

fcvt.s.lu fd, rs1

fd[4:0] reg(W)
rs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110100000011rs1rmfd1010011
755357

RV32F, RV64F

fcvt.s.w fd, rs1

fd[4:0] reg(W)
rs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110100000000rs1rmfd1010011
755357

RV32F, RV64F

fcvt.s.wu fd, rs1

fd[4:0] reg(W)
rs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110100000001rs1rmfd1010011
755357

RV32D, RV64D

fcvt.w.d rd, fs1

rd[4:0] reg(W)
fs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110000100000fs1rmrd1010011
755357

RV32F, RV64F

fcvt.w.s rd, fs1

rd[4:0] reg(W)
fs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110000000000fs1rmrd1010011
755357

RV32D, RV64D

fcvt.wu.d rd, fs1

rd[4:0] reg(W)
fs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110000100001fs1rmrd1010011
755357

RV32F, RV64F

fcvt.wu.s rd, fs1

rd[4:0] reg(W)
fs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
110000000001fs1rmrd1010011
755357

RV32D, RV64D

fdiv.d fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
0001101fs2fs1rmfd1010011
755357

RV32F, RV64F

fdiv.s fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
0001100fs2fs1rmfd1010011
755357

RV32I, RV64I

fence pred, succ

pred[3:0] const
succ[3:0] const
fm[3:0] const

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 2019 1514 1211 76 0
fm,pred,succ00000000000000001111
125357

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 2019 1514 1211 76 0
00000000000000000001000000001111
125357

RV32D, RV64D

feq.d rd, fs1, fs2

rd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
1010001fs2fs1010rd1010011
755357

RV32F, RV64F

feq.s rd, fs1, fs2

rd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
1010000fs2fs1010rd1010011
755357

RV32D, RV64D

fld fd, imm(rs1)

fd[4:0] reg(W)
rs1[4:0] reg(R)+mem(R)
imm[11:0] mem(R)

Load double-precision floating-point. Copy doubleword from memory at address imm+rs1 into register fd.

f[fd] = M[x[rs1] + sext(imm)]
31 2019 1514 1211 76 0
imm[11:0]rs1011fd0000111
125357

Related: fsd


RV32D, RV64D

fle.d rd, fs1, fs2

rd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
1010001fs2fs1000rd1010011
755357

RV32F, RV64F

fle.s rd, fs1, fs2

rd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
1010000fs2fs1000rd1010011
755357

RV32D, RV64D

flt.d rd, fs1, fs2

rd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
1010001fs2fs1001rd1010011
755357

RV32F, RV64F

flt.s rd, fs1, fs2

rd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
1010000fs2fs1001rd1010011
755357

RV32F, RV64F

flw fd, imm(rs1)

fd[4:0] reg(W)
rs1[4:0] reg(R)+mem(R)
imm[11:0] mem(R)

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 2019 1514 1211 76 0
imm[11:0]rs1010fd0000111
125357

Related: fsw


RV32D, RV64D

fmadd.d fd, fs1, fs2, fs3

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
fs3[4:0] reg(R)

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 2726 2524 2019 1514 1211 76 0
fs301fs2fs1000fd1000011
5255357

RV32F, RV64F

fmadd.s fd, fs1, fs2, fs3

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
fs3[4:0] reg(R)

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 2726 2524 2019 1514 1211 76 0
fs300fs2fs1000fd1000011
5255357

RV32D, RV64D

fmax.d fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0010101fs2fs1001fd1010011
755357

RV32F, RV64F

fmax.s fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0010100fs2fs1001fd1010011
755357

RV32D, RV64D

fmin.d fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0010101fs2fs1000fd1010011
755357

RV32F, RV64F

fmin.s fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0010100fs2fs1000fd1010011
755357

RV32D, RV64D

fmsub.d fd, fs1, fs2, fs3

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
fs3[4:0] reg(R)

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 2726 2524 2019 1514 1211 76 0
fs301fs2fs1000fd1000111
5255357

RV32F, RV64F

fmsub.s fd, fs1, fs2, fs3

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
fs3[4:0] reg(R)

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 2726 2524 2019 1514 1211 76 0
fs300fs2fs1000fd1000111
5255357

RV32D, RV64D

fmul.d fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
0001001fs2fs1rmfd1010011
755357

RV32F, RV64F

fmul.s fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
0001000fs2fs1rmfd1010011
755357

RV64D

fmv.d.x fd, rs

fd[4:0] reg(W)
rs[4:0] reg(R)

Move 64-bit integer to single-precision floating-point. The bits are not modified.

f[fd] = r[rs]
31 2524 2019 1514 1211 76 0
111100100000rs000fd1010011
755357

RV32F, RV64F

fmv.w.x fd, rs

fd[4:0] reg(W)
rs[4:0] reg(R)

Move 32-bit integer to single-precision floating-point. The bits are not modified.

f[fd] = 1ext(r[rs][31:0])
31 2524 2019 1514 1211 76 0
111100000000rs000fd1010011
755357

RV64D

fmv.x.d rd, fs

rd[4:0] reg(W)
fs[4:0] reg(R)

Move double-precision floating-point to 64-bit integer. The bits are not modified.

x[rd] = sext(f[fs])
31 2524 2019 1514 1211 76 0
111000100000fs000rd1010011
755357

RV32F, RV64F

fmv.x.w rd, fs

rd[4:0] reg(W)
fs[4:0] reg(R)

Move single-precision floating-point to 32-bit integer. The bits are not modified.

x[rd] = sext(f[fs][31:0])
31 2524 2019 1514 1211 76 0
111000000000fs000rd1010011
755357

RV32D, RV64D

fnmadd.d fd, fs1, fs2, fs3

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
fs3[4:0] reg(R)

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 2726 2524 2019 1514 1211 76 0
fs301fs2fs1000fd1001111
5255357

RV32F, RV64F

fnmadd.s fd, fs1, fs2, fs3

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
fs3[4:0] reg(R)

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 2726 2524 2019 1514 1211 76 0
fs300fs2fs1000fd1001111
5255357

RV32D, RV64D

fnmsub.d fd, fs1, fs2, fs3

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
fs3[4:0] reg(R)

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 2726 2524 2019 1514 1211 76 0
fs301fs2fs1000fd1001011
5255357

RV32F, RV64F

fnmsub.s fd, fs1, fs2, fs3

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
fs3[4:0] reg(R)

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 2726 2524 2019 1514 1211 76 0
fs300fs2fs1000fd1001011
5255357

RV32D, RV64D

fsd fs2, imm(rs1)

fs2[4:0] reg(R)
rs1[4:0] reg(R)+mem(W)
imm[11:0] mem(W)

Store double-precision floating-point. Copy register fs2 as doubleword into memory at address imm+rs1.

M[x[rs1] + sext(imm)] = f[fs2]
31 2524 2019 1514 1211 76 0
imm[11:5]fs2rs1011imm[4:0]0100111
755357

Related: fld


RV32D, RV64D

fsgnj.d fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0010001fs2fs1000fd1001011
755357

RV32D, RV64D

fsgnjn.d fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0010001fs2fs1001fd1001011
755357

RV32F, RV64F

fsgnjn.s fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0010000fs2fs1001fd1001011
755357

RV32F, RV64F

fsgnj.s fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0010000fs2fs1000fd1001011
755357

RV32D, RV64D

fsgnjx.d fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0010001fs2fs1010fd1001011
755357

RV32F, RV64F

fsgnjx.s fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0010000fs2fs1010fd1001011
755357

RV32D, RV64D

fsqrt.d fd, fs1

fd[4:0] reg(W)
fs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
010110100000fs1rmfd1010011
755357

RV32F, RV64F

fsqrt.s fd, fs1

fd[4:0] reg(W)
fs1[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
010110000000fs1rmfd1010011
755357

RV32D, RV64D

fsub.d fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
0000101fs2fs1rmfd1010011
755357

RV32F, RV64F

fsub.s fd, fs1, fs2

fd[4:0] reg(W)
fs1[4:0] reg(R)
fs2[4:0] reg(R)
rm[2:0] const

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 2524 2019 1514 1211 76 0
0000100fs2fs1rmfd1010011
755357

RV32F, RV64F

fsw fs2, imm(rs1)

fs2[4:0] reg(R)
rs1[4:0] reg(R)+mem(W)
imm[11:0] mem(W)

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 2524 2019 1514 1211 76 0
imm[11:5]fs2rs1010imm[4:0]0100111
755357

Related: flw


RV32I, RV64I

jal rd, imm

rd[4:0] reg(W)
imm[20:1] const

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 1211 76 0
imm[20,10:1,11,19:12]rd1101111
2057

Related: jalr


RV32I, RV64I

jalr rd, imm(rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[11:0] const

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 2019 1514 1211 76 0
imm[11:0]rs1000rd1100111
125357

Related: jal, call, tail


RV32I, RV64I

lb rd, imm(rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(R)
imm[11:0] mem(R)

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 2019 1514 1211 76 0
imm[11:0]rs1000rd0000011
125357

Related: lbu, sb


RV32I, RV64I

lbu rd, imm(rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(R)
imm[11:0] mem(R)

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 2019 1514 1211 76 0
imm[11:0]rs1100rd0000011
125357

Related: lb, sb


RV64I

ld rd, imm(rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(R)
imm[11:0] mem(R)

Load doubleword. Copy doubleword from memory at address imm+rs1 into register rd.

x[rd] = sext(M[x[rs1] + sext(imm)][63:0])
31 2019 1514 1211 76 0
imm[11:0]rs1011rd0000011
125357

Related: sd, lr.d


RV32I, RV64I

lh rd, imm(rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(R)
imm[11:0] mem(R)

Load halfword. Copy halfword from memory at address imm+rs1 into register rd.

x[rd] = sext(M[x[rs1] + sext(imm)][15:0])
31 2019 1514 1211 76 0
imm[11:0]rs1001rd0000011
125357

Related: lhu, sh


RV32I, RV64I

lhu rd, imm(rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(R)
imm[11:0] mem(R)

Load halfword, unsigned. Copy halfword from memory at address imm+rs1 into register rd.

x[rd] = M[x[rs1] + sext(imm)][15:0]
31 2019 1514 1211 76 0
imm[11:0]rs1101rd0000011
125357

Related: lh, sh


RV64IA

lr.d rd, rs1

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
00010, aq, rl00000rs1011rd0100000
755357

Related: sc.d, ld


RV32IA, RV64IA

lr.w rd, rs1

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
00010, aq, rl00000rs1010rd0100000
755357

Related: sc.w, lw


RV32I, RV64I

lui rd, imm[31:12]

rd[4:0] reg(W)
imm[31:12] const

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 1211 76 0
imm[31:12]rd0110111
2057

Related: auipc


RV32I, RV64I

lw rd, imm(rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(R)
imm[11:0] mem(R)

Load word. Copy word from memory at address imm+rs1 into register rd.

x[rd] = sext(M[x[rs1] + sext(imm)][31:0])
31 2019 1514 1211 76 0
imm[11:0]rs1010rd0000011
125357

Related: sw


RV64I

lwu rd, imm(rs1)

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(R)
imm[11:0] mem(R)

Load word, unsigned. Copy word from memory at address imm+rs1 into register rd.

x[rd] = M[x[rs1] + sext(imm)][31:0]
31 2019 1514 1211 76 0
imm[11:0]rs1110rd0000011
125357

Related: lw


RV32M, RV64M

mul rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000001rs2rs1000rd0110011
755357

RV32M, RV64M

mulh rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000001rs2rs1001rd0110011
755357

RV32M, RV64M

mulhsu rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000001rs2rs1010rd0110011
755357

RV32M, RV64M

mulhu rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000001rs2rs1011rd0110011
755357

RV64M

mulw rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000001rs2rs1000rd0111011
755357

RV32I, RV64I

or rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

OR. Calculate bitwise OR on rs1 and rs2 and put the result in rd.

x[rd] = x[rs1] | x[rs2]
31 2524 2019 1514 1211 76 0
0000000rs2rs1110rd0110011
755357

RV32I, RV64I

ori rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[11:0] const

OR immediate. Calculate bitwise OR on rs1 and imm and put the result in rd.

x[rd] = x[rs1] | sext(imm)
31 2019 1514 1211 76 0
imm[11:0]rs1110rd0010011
125357

RV32M, RV64M

rem rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000001rs2rs1110rd0110011
755357

Related: div


RV32M, RV64M

remu rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000001rs2rs1111rd0110011
755357

Related: divu


RV64M

remuw rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000001rs2rs1111rd0111011
755357

Related: divuw


RV64M

remw rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000001rs2rs1110rd0111011
755357

Related: divw


RV32I, RV64I

sb rs2, imm(rs1)

rs2[4:0] reg(R)
rs1[4:0] reg(R)+mem(W)
imm[11:0] mem(W)

Store byte. Copy register rs2 as byte into memory at address imm+rs1.

M[x[rs1] + sext(imm)] = x[rs2][7:0]
31 2524 2019 1514 1211 76 0
imm[11:5]rs2rs1000imm[4:0]0100011
755357

Related: lb


RV64IA

sc.d rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(W)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
00011, aq, rlrs2rs1011rd0101111
755357

Related: lr.d, sd


RV32IA, RV64IA

sc.w rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)+mem(W)
rs2[4:0] reg(R)
aq[0] const
rl[0] const

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 2524 2019 1514 1211 76 0
00011, aq, rlrs2rs1010rd0101111
755357

Related: lr.w, sw


RV64I

sd rs2, imm(rs1)

rs2[4:0] reg(R)
rs1[4:0] reg(R)+mem(W)
imm[11:0] mem(W)

Store doubleword. Copy register rs2 as doubleword into memory at address imm+rs1.

M[x[rs1] + sext(imm)] = x[rs2][63:0]
31 2524 2019 1514 1211 76 0
imm[11:5]rs2rs1011imm[4:0]0100011
755357

Related: ld, sc.d


RV32I, RV64I

sh rs2, imm(rs1)

rs2[4:0] reg(R)
rs1[4:0] reg(R)+mem(W)
imm[11:0] mem(W)

Store halfword. Copy register rs2 as halfword into memory at address imm+rs1.

M[x[rs1] + sext(imm)] = x[rs2][15:0]
31 2524 2019 1514 1211 76 0
imm[11:5]rs2rs1001imm[4:0]0100011
755357

Related: lh


RV32I, RV64I

sll rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000000rs2rs1001rd0110011
755357

Related: srl


RV32I

slli rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[4:0] const

Shift left logical immediate. Shift rs1 left imm bits. The lower bits are filled with zeros.

x[rd] = x[rs1] << imm
31 2019 1514 1211 76 0
0000000, imm[4:0]rs1001rd0010011
125357

Related: srli


RV64I

slli rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[5:0] const

Shift left logical immediate. Shift rs1 left imm bits. The lower bits are filled with zeros.

x[rd] = x[rs1] << imm
31 2019 1514 1211 76 0
000000, imm[5:0]rs1001rd0010011
125357

Related: srli


RV64I

slliw rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[5:0] const

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 2019 1514 1211 76 0
000000, imm[5:0]rs1001rd0011011
125357

Related: srliw


RV64I

sllw rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000000rs2rs1001rd0111011
755357

Related: srlw


RV32I, RV64I

slt rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000000rs2rs1010rd0110011
755357

RV32I, RV64I

slti rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[11:0] const

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 2019 1514 1211 76 0
imm[11:0]rs1010rd0010011
125357

RV32I, RV64I

sltiu rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[11:0] const

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 2019 1514 1211 76 0
imm[11:0]rs1011rd0010011
125357

RV32I, RV64I

sltu rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000000rs2rs1011rd0110011
755357

RV32I, RV64I

sra rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0100000rs2rs1101rd0110011
755357

Related: srl


RV32I

srai rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[4:0] const

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 2019 1514 1211 76 0
0100000, imm[4:0]rs1101rd0010011
125357

Related: srli


RV64I

srai rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[5:0] const

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 2019 1514 1211 76 0
010000, imm[5:0]rs1101rd0010011
125357

Related: srli


RV64I

sraiw rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[5:0] const

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 2019 1514 1211 76 0
010000, imm[5:0]rs1101rd0011011
125357

Related: srliw


RV64I

sraw rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0100000rs2rs1101rd0111011
755357

Related: srlw


RV32I, RV64I

srl rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000000rs2rs1101rd0110011
755357

Related: sll, sra


RV32I

srli rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[4:0] const

Shift right logical immediate. Shift rs1 right imm bits. The upper bits are filled with zeros.

x[rd] = x[rs1] >>u imm
31 2019 1514 1211 76 0
0000000, imm[4:0]rs1101rd0010011
125357

Related: slli, srai


RV64I

srli rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[5:0] const

Shift right logical immediate. Shift rs1 right imm bits. The upper bits are filled with zeros.

x[rd] = x[rs1] >>u imm
31 2019 1514 1211 76 0
000000, imm[5:0]rs1101rd0010011
125357

Related: slli, srai


RV64I

srliw rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[5:0] const

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 2019 1514 1211 76 0
000000, imm[5:0]rs1101rd0011011
125357

Related: slliw, sraiw


RV64I

srlw rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0000000rs2rs1101rd0111011
755357

Related: sllw, sraw


RV32I, RV64I

sub rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

Subtract. Subtract rs2 from rs1 and put the result in rd. Arithmetic overflow is ignored.

x[rd] = x[rs1] - x[rs2]
31 2524 2019 1514 1211 76 0
0100000rs2rs1000rd0110011
755357

RV64I

subw rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

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 2524 2019 1514 1211 76 0
0100000rs2rs1000rd0111011
755357

RV32I, RV64I

sw rs2, imm(rs1)

rs2[4:0] reg(R)
rs1[4:0] reg(R)+mem(W)
imm[11:0] mem(W)

Store word. Copy register rs2 as word into memory at address imm+rs1.

M[x[rs1] + sext(imm)] = x[rs2][31:0]
31 2524 2019 1514 1211 76 0
imm[11:5]rs2rs1010imm[4:0]0100011
755357

Related: lw


RV32I, RV64I

xor rd, rs1, rs2

rd[4:0] reg(W)
rs1[4:0] reg(R)
rs2[4:0] reg(R)

Exclusive OR. Calculate bitwise XOR on rs1 and rs2 and put the result in rd.

x[rd] = x[rs1] ^ x[rs2]
31 2524 2019 1514 1211 76 0
0000000rs2rs1100rd0110011
755357

RV32I, RV64I

xori rd, rs1, imm

rd[4:0] reg(W)
rs1[4:0] reg(R)
imm[11:0] const

Exclusive OR immediate. Calculate bitwise XOR on rs1 and imm and put the result in rd.

x[rd] = x[rs1] ^ sext(imm)
31 2019 1514 1211 76 0
imm[11:0]rs1100rd0010011
125357