# RISC-V Assembler: Shift

In this post we look at RISC-V shift instructions, such as **sll** and **srai**. These instructions are included in **RV32I**, the base integer instruction set. New to the series? Check out the first part on arithmetic instructions.

In the last few years, we’ve seen an explosion of RISC-V CPU designs, especially on FPGA. Thankfully, RISC-V is ideal for assembly programming with its compact, easy-to-learn instruction set. This series will help you learn and understand 32-bit RISC-V instructions (RV32) and the RISC-V ABI.

Share your thoughts with @WillFlux on Mastodon or Twitter. If you like what I do, sponsor me. 🙏

## Left Shift

There are two left shift instructions, **sll** and **slli**; they shift left, filling vacated bits with zeros. Left shift is almost the same as multiplying by powers of two, provided the number is positive.

```
sll rd, rs1, rs2 # rd = rs1 << rs2
slli rd, rs, imm # rd = rs1 << imm
```

ProTip: Remember shift instructions as initialisms: **sll** is **s**hift **l**eft **l**ogical.

The following examples shift a register two bits to the left:

```
li t0, 42 # t0 = (0000 0000 0000 0000 0000 0000 0010 1010)
li t2, 2 # t2 = (0000 0000 0000 0000 0000 0000 0000 0010)
sll t3, t0, t2 # t3 = (0000 0000 0000 0000 0000 0000 1010 1000)
slli t4, t0, 2 # t4 = (0000 0000 0000 0000 0000 0000 1010 1000)
```

Note how the result of shifting 42 two bits to the left is 168 (4×42).

## Right Shift

There are four right shift instructions. **srl** and **srli** fill vacated bits with zeros. **sra** and **srai** perform sign extension, filling vacated bits with the most significant bit (MSB).

```
# shift right logical
srl rd, rs1, rs2 # rd = rs1 >> rs2
srli rd, rs, imm # rd = rs1 >> imm
# shift right arithmetic
sra rd, rs1, rs2 # rd = rs1 >>> rs2
srai rd, rs, imm # rd = rs1 >>> imm
```

Our right-shift examples use the immediate version of the instruction to compare logical and arithmetic shifts:

```
li t0, 42 # t0 = (0000 0000 0000 0000 0000 0000 0010 1010)
li t1, -42 # t1 = (1111 1111 1111 1111 1111 1111 1101 0110)
# right shift by 2 bits (MSB=0)
srli t2, t0, 2 # t2 = (0000 0000 0000 0000 0000 0000 0000 1010)
srai t3, t0, 2 # t3 = (0000 0000 0000 0000 0000 0000 0000 1010)
# right shift by 2 bits (MSB=1)
srli t4, t1, 2 # t4 = (0011 1111 1111 1111 1111 1111 1111 0101)
srai t5, t1, 2 # t5 = (1111 1111 1111 1111 1111 1111 1111 0101)
```

Both signed and unsigned numbers are positive when the MSB (most significant bit) is 0. So, both right shift instructions fill vacated bits with **0**.

When the MSB is **1**, signed numbers are **negative**. Arithmetic shift fills vacated bits with **1**, while logical shifts fill them with **0**. The results are dramatically different! Treating the result as a signed number:

`t4 = 1,073,741,813`

`t5 = -11`

In summary, consider whether a value is signed before choosing a right shift instruction.

Learn more about the representation of signed numbers from two’s complement on Wikipedia.

## Shift Bits

RV32 shift instructions use the 5 least significant bits for the shift amount (0-31); other bits are ignored. For example, left shifting by 32 does nothing (you might expect it to set the register to zero).

GNU assembler errors if you try to shift by an immediate not in the range 0-31: `Error: improper shift amount (32)`

.

## What’s Next?

The next instalment of *RISC-V Assembler* covers **Load and Store Instructions**.

Other parts of this series include: Arithmetic and Logical. Or check out my FPGA & RISC-V Tutorials and my series on early Macintosh History.

### References

- RISC-V Technical Specifications (riscv.org)