RISC-V Instruction Format
Pricinple idea: keep all instruction same bit length (32-bit)
Machine Language
Big Idea: Stored-Program Computer
- Instructions are represented as bit patterns – can think of these as numbers
- Therefore, entire programs can be stored in memory to be read or written just like data
Implications:
- Everything Has a Memory Address
- Instructions have memory address
- Branches and jumps use these address
- One register keeps address of instruction being executed: “Program Counter” (PC)
- A pointer to memory
- Instructions have memory address
- Programs are distributed in binary form (asssembled machine code)
- Programs bound to specific instruction set
- Different version for phones and PCs
- Programs bound to specific instruction set
Instruction Format
- ISA defines instructions for CPU down to the bit level
- RISC-V instructions are fixed size, 32-bit words
- Same size for a data word
- Instruction words are divided into fields
- Each field represents some information for processor
- RISC-V six basic type of instruction formats
- Use same format for similar instructions
| Format | Description |
|---|---|
| R-Format | Register-register arithmetic operations |
| I-Format | Register-immediate arithmetic operations and loads |
| S-Format | Stores |
| B-Format | Branches (S variant) |
| U-Format | 20-bit upper immediate instructions |
| J-Format | Jumps (U variant) |
R-Format Layout
Register-register arithmetic operations (add, xor, sll, etc.)
31 25 24 20 19 15 14 12 11 7 6 0
| funct7 | rs2 | rs1 |funct3| rd | opcode |
7 5 5 3 5 7opname rd, rs1, rs2- opcode partially specify which instruction it is.
- All R-Format instructions have opcode
0110011
- All R-Format instructions have opcode
- funct7, funct3 combined with opcode describe what operation to perform.
- funct7: Extra 7-bit identifier for extremely similar instructions with the same opcode and funct3 (such as
sraandsrl)
- funct7: Extra 7-bit identifier for extremely similar instructions with the same opcode and funct3 (such as
- rs1, rs2: first and second register oprend
- rd: destination register
| funct7 | rs2 | rs1 | funct3 | rd | opcode | Instruction |
|---|---|---|---|---|---|---|
0000000 | 000 | 0110011 | add | |||
0100000 | 000 | 0110011 | sub | |||
0000000 | 001 | 0110011 | sll | |||
0000000 | 010 | 0110011 | slt | |||
0000000 | 011 | 0110011 | sltu | |||
0000000 | 100 | 0110011 | xor | |||
0000000 | 101 | 0110011 | srl | |||
0100000 | 101 | 0110011 | sra | |||
0000000 | 110 | 0110011 | or | |||
0000000 | 111 | 0110011 | and |
- One higher-order immediate bit used for sign extend (
sra/srl,add/sub)
I-Format Layout
31 20 19 15 14 12 11 7 6 0
| imm[11:0] | rs1 |funct3| rd | opcode |
12 5 3 5 7opname rd, rs1, imm- All arithmetic immediate instructions have opcode
0010011 - imm[11:0] holds 12-bit-wide immediate values
- Values in range [-2048, +2047]
- CPU sign-extends to 32 bits before use in an arithmetic operation
Immediate
Register-immediate arithmetic operations
- Mostly consistent with R-Format. Simplify how the CPU processes instructions
- Immediate fields need to be wider
| imm[11:0] | rs1 | funct3 | rd | opcode | Instruction |
|---|---|---|---|---|---|
000 | 0010011 | addi | |||
010 | 0010011 | slti | |||
011 | 0010011 | sltiu | |||
100 | 0010011 | xori | |||
110 | 0010011 | ori | |||
111 | 0010011 | andi | |||
0000000 | shamt | 001 | 0010011 | slli | ||
0000000 | shamt | 101 | 0010011 | srli | ||
0100000 | shamt | 101 | 0010011 | srai |
- Shift by Immediate instructions encode the
shift amountin the lower-order 5 bits- Only shift a 32-b word by 0-31 positions is meaningful
Load
Load operations
- All load instructions have opcode
0000011
loadop rd, imm(rs1)- imm[11:0] is the offset from rs1
- rs1 is the register that holds the base address
| imm[11:0] | rs1 | funct3 | rd | opcode | Instruction |
|---|---|---|---|---|---|
000 | 0000011 | lb | |||
001 | 0000011 | lh | |||
010 | 0000011 | lw | |||
100 | 0000011 | lbu | |||
101 | 0000011 | lhu |
lb: load byte,lh: load halfword (16 bits)- Sign extend to fill upper bits of
rd
- Sign extend to fill upper bits of
lbu: load unsigned byte,lhu: load unsigned half word- Zero extend to fill upper bits of
rd
- Zero extend to fill upper bits of
S-Format Layout
Store operations
31 25 24 20 19 15 14 12 11 7 6 0
| imm[11:5] | rs2 | rs1 |funct3| imm[4:0] | opcode |
7 5 5 3 5 7storeop rs2, imm(rs1)- All store instructions have opcode
0100011 - rs2 source register
- Data to be stored in memory
- rs1 base register
- Base address of store
- imm immediate offset added to base address to form memory address
- Higher 7 bits and lower 5 bits are in seperate fields
- RISC-V design prioritizes keeping register fields in the same places. Immediates are less critical to hardward
| imm[11:5] | rs1 | rs2 | funct3 | imm[4:0] | opcode | Instruction |
|---|---|---|---|---|---|---|
000 | 0100011 | sb | ||||
001 | 0100011 | sh | ||||
010 | 0100011 | sw |
Program Counter (PC)
The Program Counter is a special internal register inside the processor holding the byte address of the instruction being executed.
- Seperate from the 32-registers Register File
PC = PC + 4for most instructions- Branches update PC to "Jump"
- Unconditional Branches update PC to the line of instructions
- Conditional Branches update PC to the line of instructions if taken, if not,
PC = PC + 4
PC-Relative Addressing
Supply a signed offset to update PC
PC = PC + byteoffset- Position-Independent Code: If all code removes, relative offsets don't change
Contract: Absolute Addressing
- Supply new address to overwrite PC (
PC = new_address)
B-Format (SB-Type) Layout
Conditional Branches
- RISC-V uses PC-relative addressing to encode labels
- Don't branch:
PC = PC + 4 - Do branch:
PC = PC + relative_offset
- Don't branch:
- The 12-bit immediate field for conditional branches is in units of 2 bytes
- For 16-bit microprocessor extension
- Variable-length instructions that are multiples of 16b in length
- One branch reaches
x 32-bit instructions from PC
31 25 24 20 19 15 14 12 11 7 6 0
| imm[12|10:5] | rs2 | rs1 |funct3|im[4:1|11]| opcode |
7 5 5 3 5 7opname rs1, rs2, Label- All conditional branch instructions have opcode
1100011 - imm represents relative in increments of 2 bytes
- 1 bit: 2's complement (+/- offset) (index 12 MSB)
- 1 bit: 16-b instruction support (index 11)
- Index zero (lowest bit) of offset is always zero, so no need to store in instruction (multiply by 2)
| imm[12|10:5] | rs1 | rs2 | funct3 | imm[4:1|11] | opcode | Instruction |
|---|---|---|---|---|---|---|
000 | 1100011 | beq | ||||
001 | 1100011 | bne | ||||
100 | 1100011 | blt | ||||
101 | 1100011 | bge | ||||
110 | 1100011 | bltu | ||||
111 | 1100011 | bgeu |
Immediate Format Design
Immediate bit encoding is optimized to reduce hardware cost
31 25 24 20 19 15 14 12 11 7 6 0
| imm[11:0] | rs1 |funct3| rd | opcode | I
| yxxxxxx | wwwwv | | | |
| imm[11:5] | rs2 | rs1 |funct3| imm[4:0] | opcode | S
| yxxxxxx | | | wwwwv | |
| imm[12|10:5] | rs2 | rs1 |funct3|im[4:1|11]| opcode | B
| zxxxxxx | | | wwwwy | |- Bit positions of immediates are consistent
- Instruction bit 31 is always the sign bit
Conditionally Branching Further
- B-Format has limited range:
- Destination is further away: Enter unconditional jump
# >>>>>
beq x10, x0, far # This doesn't work
# <<<<<
bne x10, x0, next # Use this instead
j far
next: # next instructionJ-Format (UJ-Type)
Unconditional jumps
31 25 24 20 19 12 11 7 6 0
| imm[20|10:5] |im[4:1,11]| imm[19:12] | rd | opcode |
7 5 8 5 7jal rd, Label- opcode
1101111 - rd: Destination Register gets "return address"
rd = PC + 4
- immediate represents relative offset in increments of 2 bytes
- To compute new PC:
PC = PC + byte_offsite - 20 immediate bits implies
32-bit instructions reachable - 1 bit: 2's complement (index 20)
- 1 bit: 16-bit instruction support (index 11)
- To compute new PC:
U-Format
Upper Immediate instructions
31 12 11 7 6 0
| imm[31:12] | rd | opcode |
7 5 8 5 7opname rd, immed- Immediate represents upper 20 bits of a 32-bit immediate
imm = immed << 12
lui for Long Immediates
lui rd, immedThe lui instruction, Load Upper Immediate:
- Write a 20-bit immediate value into the upper 20-bits of register
rd - Clear the lower 12 bits
Effect: rd = immed << 12
lui together with an addi (to set lower 12 bits) can create any 32-bit value in a register:
lui x10, 0x87654 # x10 = 0x87654000
addi x10, x10, 0x321 # x10 = 0x87654321- The
lipersudoinstrucion resolves tolui + addias needed - Problem:
addisign-extends the 12-bit immediate- If sign bit set, subtracts 1 from the upper 20-bits
- Solution: If 12-bit immediate is negative, add 1 to the upper 20-bit load
lido it immediately
auipc Loads the PC into the Register File
auipc rd, immedThe auipc instruction
- Adds an Upper Immediate plus the PC to
rd
Effect: rd = PC + (immed << 12)
In practice:
Label: auipc x5, 0 # puts address of Label in x5- Loads the PC into a register accessible by other instructions
I-Format (jalr)
jalr rd, rs1, immThe jalr instruction does a Jump and Link Register
- Jump to
rs1 + imm - Write address of the following instruction to
rd - Allows for bigger jumps
Efffect: PC = rs1 + imm, rd = PC + 4
The ja persudoinstruction:
jr ra # <=> jalr x0, ra, 0Use cases:
- Return to callee
jr ra - Jump to absolute address (external lib) by
auipc+jalr
Layout
31 20 19 15 14 12 11 7 6 0
| imm[11:0] | rs1 |funct3| rd | opcode |
12 5 3 5 7- opcode
1100111 - Immediate:
immandrs1are added together to update PCPC = rs1 + imm- I-Type will not multiply
immby 2