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

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]] = max
```_{u}(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]] = max
```_{u}(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]] = min
```_{u}(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]] = min
```_{u}(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 |

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 |

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 |

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 |

**call** imm

Call far-away subroutine. Pseudoinstruction.

```
auipc x6, imm[31:12]
jalr 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 |

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 |

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.

```
auipc rs, imm[31:12]
fld 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.

```
auipc rs1, imm[31:12]
flw 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 |

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 |

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 |

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.

```
auipc rs1, imm[31:12]
fsd 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.

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

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

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 |

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 |

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 |

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 |

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 |

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 |

**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 |

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 |

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

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 |

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

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

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 |

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 |

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 |

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

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 |

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 |

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 |

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 |

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 |

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 |

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

**tail** imm

Tail call far-away subroutine. Pseudoinstruction.

```
auipc x6, imm[31:12]
jalr 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 |