Dulranga's Notes
Semester 3Computer Architecture

RISC-V Instruction Format (32bit)

There are 6 Standard Formats, for instructions. RISC-V keeps the critical parts of the instruction in the exact same spot almost every single time.

risc-v-instruction-types.png

In RISC-V, instructions grouped together like a hierarchy.

PartsizeUsecase
opcode7bitThese are main groups of opcodes.(like ADD, SUB, XOR, OR, AND, SLL) shares the exact same opcode
func33bitSubmenus of each opcode (uses to get specific instruction)
func77bitTie-breakers (helps get more specific instructions if both opcode and func3 are identical. Ex: ADD and SUB)
rs1, rs25bitSource Registers
rd5bitDestination Register

1. R-type (Register)

Used for Pure Math operations between registers It takes the data in Source Register 1 (rs1) and Source Register 2 (rs2), performs the math, and saves the result in the Destination Register (rd).

risc-v-r-type.png

Logical Shift vs Arithmetic Shift

logical-arithmatic-shift.png

  • Right Arithmetic shift preserve sign bit, whereas Right Logical shift can not preserve sign bit.
  • Arithmetic shift perform multiplication and division operation, whereas Logical shift perform only multiplication operation.
  • Arithmetic shift is used for signed interpretation, whereas Logical shift is used for unsigned interpretation.

2. I-type (Immediate)

Used for math operations that involve a hardcoded number (called an "immediate") or for LOAD instructions from RAM.

Example: ADDI x1, x2, 10 (Add the constant 10 to the value in x2 and store it in x1).

risc-v-i-type.png

Note:

  • uses Sign Extension for filling up bits when loading them to registers
  • Load instructions load data from Memory to registers. They only use Immediate values as memory address finders (like array offsets arr[imm])
	Final RAM Address = Base Register (rs1) + Immediate Value (imm)
  • lb means Load Byte (signed) and lbu means Load Byte (Unsigned)
  • for instructions like these, the RISC-V 5 Stage Pipeline solution comes in handy

3. S-Type (Store)

these instructions are used to write data back into memory from registers.

risc-v-s-type.png

Store instructions need two source registers.

  1. base address register (rs1) (this 32-bit register holds the memory address of which the value will be written)
  2. data address register (rs2) (this 32-bit register holds the data value of which will be written into the memory)
Note

The immediate value is used as the memory offset from the base register's memory address. this is useful for repetitive memory value insertions since we do not need to update the base register address each time Reduces the instruction complexity.

  • The immediate value is split into two parts to keep the instruction consistent with other ones. This reduce the hardware design
  • (rs1 and rs2 are in the exact position in all 32 bit instructions)
  • The split value will be automatically treated as one in the processor
  • 12 bit Immediate value is Signed. Range is [2048,2047][-2048, 2047]
Important

Each store instruction uses the correct potion of the given data register value when storing, such as byte only store the first 8 bits, word store the whole 32 bits

Example: sw x12, 8(x10)

Store word(32-bit) currently in register "x12", to the memory address calculated by adding "8" to the memory address in register "x10"

4. U-type (Upper Immediate)

This type of instructions are designed for loading full 32-bit values into registers. Since the RSIC-V support 32bit instructions, we cannot simply load a 32bit value into registers (since the opcode and other parts should fit into the same 32 bits)

risc-v-u-type.png

This instruction is really simple since the leftmost 20bits are occupied by the value.

Note

There is a psudo instruction called ld (load address) in RISC-V that actually uses auipc and addi instructions to load any value upto 32bits.

risc-v-ld.png

Step 1: AUIPC (U-type)

  • Calculates the PC-relative offset: Offset=Address of SymbolPC of AUIPC\text{Offset} = \text{Address of Symbol} - \text{PC of AUIPC}.
  • Extract the top 20 bits of this offset and loads them into rd, adding it to the PC.
  • Formula: rd=PC+(Offset12)\text{rd} = \text{PC} + (\text{Offset} \ll 12)

Step 2: ADDI (I-type)

  • Extracts the remaining lower 12 bits of the offset and adds them to rd.
  • Performs sign-extension compensation automatically if bit 11 of the 12-bit lower offset is 11.

5. B-Type (Branching)

These are used to alter the execution procedure of the program.

risc-v-b-type.png

Note

The immediate value is messed up (due to lowering wiring BS).

\begin{align*}
\text{Raw Instruction Bits} &= \{\mathbf{\text{imm}[12]},\ \mathbf{\text{imm}[10:5]}, \ \mathbf{\text{imm}[4:1]},\ \mathbf{\text{imm}[11]}\} \\
\text{Reconstructed Immediate} &= \{\mathbf{\text{imm}[12]},\ \mathbf{\text{imm}[11]},\ \mathbf{\text{imm}[10:5]}, \ \mathbf{\text{imm}[4:1]},\ \mathbf{0}\}
\end{align*}

Note: the immediate of 12bits given in instruction becomes 13bit actual immediate with the last 00. #Two Byte alignment trick

these branch instructions take two registers and perform some logical operation(equal, greater than, etc). If that operation is true, the branching happens otherwise not.

Note

There are no "less than" instructions. The reason is for simplicity. Less than just means Greater than with the registers swapped. There are pseudo instructions for less than operations but hardware level, everything is greater than.

Simple loop C Code:

C

int count = 10;
while (count > 0) {
    count--;
}

RISC-V Assembly:

Code snippet

    li   t0, 10         # t0 = count = 10
loop:
    blez t0, exit       # If t0 <= 0, jump to exit (pseudo for bge x0, t0, exit)
    addi t0, t0, -1     # t0 = t0 - 1
    j    loop           # Jump back to loop (pseudo for jal x0, loop)
exit:

Branch Addressing

PC relative Branch Addressing

It uses the current PC address as a reference. So its always about how much lines to jump, not the line number to jump. when a branch condition becomes true, the processor compute the new PC Address: Target PC=Current PC+SignExtended(Immediate Offset)\text{Target PC} = \text{Current PC} + \text{SignExtended}(\text{Immediate Offset}) Immediate Offset is a 13-bit signed value.

Two Byte alignment trick

This explains how 12bit instruction value become 13bit

RISC-V requires the Memory to be Byte-Addressed (i.e. addresses points to one byte (8bits)). So 32bit instructions will take 4 bytes for each. So instruction addresses always jump from 4 to 4. In the other hand, the extension C (Compressed) of RISC-V support 16bit instructions, still each instruction address jumps from 2 to 2

This makes every instruction address always even. Which means last bit is always 0. So branching instructions remove it from the actual immediate value and put it back as its an implicit value. This allows the instruction offset to go from 12bit to 13 bit, Branch offset range of 4096-4096 to +4094+4094 bytes.

6. J-type (Jump)

this just jumps to the given location without checking nothing. Jump instructions are in two types. one in I type and other one is in J type.

risc-v-j-type.png

Note: Jump instruction also being used in functional/procedural calls and returns because it saves the return address into register.

Linking?

jal - Jump and Link

In these instructions, Linking means, it stores the next instruction in the instruction sequence (before jumping) to the destination register rd

This is useful when the jump happened and all the instructions executed in the jump and it needs to return to the original place (which is PC + 4 bytes) This is how functions work.

If the linking is not required, we can pass x0 as the rd register value, it will just ignore it.

jal x1, label

This uses PC relative addressing same as Branch instruction. This also uses the 2 Byte alignment trick. (Lowest byte of offset is always implicit and its 00) Support 21-bit range using 20-bit address (±1 MB\pm 1\text{ MB} range from current PC)

Operation:

\begin{align*}
\text{rd} &= \text{PC} + 4 \\ 
\text{Target PC} &= \text{PC} + \text{SignExtended}(\text{offset})
\end{align*}

jalr x0, 0(rs1)

Key difference: This one get destination address dynamically using value in rs1 and a immediate offset. (Not the PC and Immediate offset)

On this page