RISC-V instructions

Riscv instructions

robalni.org

Instructions by category

Arithmetic:

Logic:

Branch:

Jump:

Memory:

Convert:

Conditional:

Uncategorized:

Explanations

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/.

Instructions

RV32I, RV64I

add rd, rs1, rs2

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, rs1, imm

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, rs1, imm

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, rs1, rs2

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs2, (rs1)

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, rs1, rs2

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, rs1, imm

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, 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, rs2, imm

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


beqz rs1, imm

Branch if = zero. Pseudoinstruction.

 rs1, x0, imm

RV32I, RV64I

bge rs1, rs2, imm

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, rs2, imm

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


bgez rs1, imm

Branch if ≥ zero. Pseudoinstruction.

 rs1, x0, imm

bgt rs1, rs2, imm

Branch if >. Pseudoinstruction.

 rs2, rs1, imm

bgtu rs1, rs2, imm

Branch if >, unsigned. Pseudoinstruction.

 rs2, rs1, imm

bgtz rs1, imm

Branch if > zero. Pseudoinstruction.

 x0, rs1, imm

ble rs1, rs2, imm

Branch if ≤. Pseudoinstruction.

 rs2, rs1, imm

bleu rs1, rs2, imm

Branch if ≤, unsigned. Pseudoinstruction.

 rs2, rs1, imm

blez rs, imm

Branch if ≤ zero. Pseudoinstruction.

 x0, rs, imm

RV32I, RV64I

blt rs1, rs2, imm

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, rs2, imm

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


bltz rs, imm

Branch if < zero. Pseudoinstruction.

 rs, x0, imm

RV32I, RV64I

bne rs1, rs2, imm

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


bnez rs, imm

Branch if ≠ zero. Pseudoinstruction.

 rs, x0, imm

call imm

Call far-away subroutine. Pseudoinstruction.

 x6, imm[31:12]
 x1, imm[11:0](x6)

Related: tail


RV32I, RV64I

csrrc rd csr rs1

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 csr 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, csr, rs1

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, csr, 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, csr, rs1

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, csr, 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, rs1, rs2

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, rs1, rs2

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, rs1, rs2

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, rs1, rs2

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


fabs.d fd, fs

Double-precision absolute value. Pseudoinstruction.

 fd, fs, fs

fabs.s fd, fs

Single-precision absolute value. Pseudoinstruction.

 fd, fs, fs

RV32D, RV64D

fadd.d fd, fs1, fs2

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, fs1, fs2

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, fs

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, fs

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, rs1

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, rs1

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, fs1

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, rs1

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, rs1

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, fs1

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, fs1

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, fs1

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, fs1

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, fs1

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, rs1

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, rs1

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, rs1

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, rs1

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, fs1

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, fs1

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, fs1

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, fs1

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, fs1, fs2

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, fs1, fs2

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, succ

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


fence

Fence on all memory and I/O. Pseudoinstruction.

 iorw, iorw

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

imm[11:0]

00000

001

00000

0001111

12

5

3

5

7


RV32D, RV64D

feq.d rd, fs1, fs2

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, fs1, fs2

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, imm(rs1)

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


fld fd, imm(rs)

Floating-point load doubleword. Pseudoinstruction.

 rs, imm[31:12]
 fd, imm[11:0](rs)

RV32D, RV64D

fle.d rd, fs1, fs2

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, fs1, fs2

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, fs1, fs2

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, fs1, fs2

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, imm(rs1)

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


flw fd, imm(rs1)

Load single-precision floating-point. Pseudoinstruction.

 rs1, imm[31:12]
 fd, imm[11:0](rs1)

RV32D, RV64D

fmadd.d fd, fs1, fs2, fs3

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, fs1, fs2, fs3

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, fs1, fs2

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, fs1, fs2

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, fs1, fs2

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, fs1, fs2

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, fs1, fs2, fs3

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, fs1, fs2, fs3

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, fs1, fs2

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, fs1, fs2

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


fmv.d fd, fs

Copy double-precision register. Pseudoinstruction.

 fd, fs, fs

RV64D

fmv.d.x fd, rs

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


fmv.s fd, fs

Copy single-precision register. Pseudoinstruction.

 fd, fs, fs

RV32F, RV64F

fmv.w.x fd, rs

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, fs

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, fs

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


fneg.d fd, fs

Double-precision negate. Pseudoinstruction.

 fd, fs, fs

fneg.s fd, fs

Single-precision negate. Pseudoinstruction.

 fd, fs, fs

RV32D, RV64D

fnmadd.d fd, fs1, fs2, fs3

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, fs1, fs2, fs3

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, fs1, fs2, fs3

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, fs1, fs2, fs3

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, imm(rs1)

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


fsd fs2, imm(rs1)

Floating-point store doubleword. Pseudoinstruction.

 rs1, imm[31:12]
 fs2, imm[11:0](rs1)

RV32D, RV64D

fsgnj.d fd, fs1, fs2

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, fs1, fs2

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, fs1, fs2

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, fs1, fs2

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, fs1, fs2

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, fs1, fs2

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, fs1

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, fs1

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, fs1, fs2

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, fs1, fs2

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, imm(rs1)

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


fsw fs2, imm(rs1)

Store single-precision floating-point. Pseudoinstruction.

 rs1, imm[31:12]
 fs2, imm[11:0](rs1)

j imm

Jump. Pseudoinstruction.

 x0, imm

RV32I, RV64I

jal rd, imm

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


jal imm

Jump and link. Pseudoinstruction.

 x1, imm

RV32I, RV64I

jalr rd, imm(rs1)

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

Related: jal, call, tail


jalr rs

Jump and link register. Pseudoinstruction.

 x1, 0(rs)

jr rs

Jump register. Pseudoinstruction.

 x0, 0(rs)

la rd, imm

Load address. Pseudoinstruction.

 rd, imm[31:12]
 rd, rd, imm[11:0]

RV32I, RV64I

lb rd, imm(rs1)

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

Related: lbu, sb


lb rd, imm

Load byte. Pseudoinstruction.

 rd, imm[31:12]
 rd, imm[11:0](rd)

RV32I, RV64I

lbu rd, imm(rs1)

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

Related: lb, sb


RV64I

ld rd, imm(rs1)

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

Related: sd, lr.d


ld rd, imm

Load doubleword. Pseudoinstruction.

 rd, imm[31:12]
 rd, imm[11:0](rd)

RV32I, RV64I

lh rd, imm(rs1)

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

Related: lhu, sh


lh rd, imm

Load halfword. Pseudoinstruction.

 rd, imm[31:12]
 rd, imm[11:0](rd)

RV32I, RV64I

lhu rd, imm(rs1)

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

Related: lh, sh


li rd, imm

Load immediate. Pseudoinstruction.


RV64IA

lr.d rd, rs1

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

Related: sc.d, ld


RV32IA, RV64IA

lr.w rd, rs1

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

Related: sc.w, lw


RV32I, RV64I

lui rd, 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, imm(rs1)

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


lw rd, imm

Load word. Pseudoinstruction.

 rd, imm[31:12]
 rd, imm[11:0](rd)

RV64I

lwu rd, imm(rs1)

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, rs1, rs2

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, rs1, rs2

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, rs1, rs2

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, rs1, rs2

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, rs1, rs2

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


mv rd, rs

Copy register. Pseudoinstruction.

 rd, rs, 0

neg rd, rs

Two's complement. Pseudoinstruction.

 rd, x0, rs

negw rd, rs

Two's complement word. Pseudoinstruction.

 rd, x0, rs

nop

No operation. Pseudoinstruction.

 x0, x0, 0

not rd, rs

One's complement. Pseudoinstruction.

 rd, rs, -1

RV32I, RV64I

or rd, rs1, rs2

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, rs1, imm

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, rs1, rs2

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, rs1, rs2

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, rs1, rs2

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, rs1, rs2

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


ret

Return from subroutine. Pseudoinstruction.

 x0, 0(x1)

RV32I, RV64I

sb rs2, imm(rs1)

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


sb rd, imm, rs1

Store byte. Pseudoinstruction.

 rs1, imm[31:12]
 rd, imm[11:0](rs1)

RV64IA

sc.d rd, rs1, rs2

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

Related: lr.d, sd


RV32IA, RV64IA

sc.w rd, rs1, rs2

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

Related: lr.w, sw


RV64I

sd rs2, imm(rs1)

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

Related: ld, sc.d


sd rd, imm, rs1

Store doubleword. Pseudoinstruction.

 rs1, imm[31:12]
 rd, imm[11:0](rs1)

sext.w rd, rs

Sign extend word. Pseudoinstruction.

 rd, rs, 0

seqz rd, rs

Set if = zero. Pseudoinstruction.

 rd, rs, 1

sgtz rd, rs

Set if > zero. Pseudoinstruction.

 rd, x0, rs

RV32I, RV64I

sh rs2, imm(rs1)

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


sh rd, imm(rs)

Store halfword. Pseudoinstruction.

 rs, imm[31:12]
 rd, imm[11:0](rs)

RV32I, RV64I

sll rd, rs1, rs2

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, rs1, imm

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, rs1, imm

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, rs1, imm

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, rs1, rs2

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, rs1, rs2

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, rs1, imm

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, rs1, imm

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, rs1, rs2

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


sltz rd, rs

Set if < zero. Pseudoinstruction.

 rd, rs, x0

snez rd, rs

Set if ≠ zero. Pseudoinstruction.

 rd, x0, rs

RV32I, RV64I

sra rd, rs1, rs2

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, rs1, imm

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, rs1, imm

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, rs1, imm

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, rs1, rs2

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, rs1, rs2

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

Related: sll, sra


RV32I

srli rd, rs1, imm

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

Related: slli, srai


RV64I

srli rd, rs1, imm

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

Related: slli, srai


RV64I

srliw rd, rs1, imm

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

Related: slliw, sraiw


RV64I

srlw rd, rs1, rs2

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

Related: sllw, sraw


RV32I, RV64I

sub rd, rs1, rs2

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, rs1, rs2

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, imm(rs1)

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


sw rd, imm(rs)

Store word. Pseudoinstruction.

 rs, imm[31:12]
 rd, imm[11:0](rs)

tail imm

Tail call far-away subroutine. Pseudoinstruction.

 x6, imm[31:12]
 x0, imm[11:0](x6)

Related: call


RV32I, RV64I

xor rd, rs1, rs2

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, rs1, imm

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


Updated: 2023-01-09

Last updated