Chapter 7: RISC-V Hazard3 ISA Overview

September 17, 2026 · View on GitHub

Introduction

The instruction set architecture (ISA) defines every operation the processor can perform. The Hazard3 core in the RP2350 implements the RV32IMAC_Zicsr architecture — a 32-bit RISC-V base integer ISA augmented with integer multiply/divide, atomic operations, compressed instructions, and control/status register access. This chapter surveys the ISA at a high level and identifies every instruction our blink driver uses.

The RISC-V Design Philosophy

RISC-V follows an exceptionally clean RISC (Reduced Instruction Set Computer) philosophy:

  • Fixed-width instructions — base instructions are always 32 bits (4 bytes)
  • Load-store architecture — only lw/sw family instructions access memory
  • Large register file — 32 general-purpose integer registers (x0–x31)
  • Simple addressing modes — base register + 12-bit signed immediate
  • No condition flags — branches compare registers directly
  • Modular extensions — functionality added via lettered extensions (M, A, C, Zicsr)

The RV32IMAC_Zicsr Extensions

The Hazard3 core supports these extensions:

ExtensionNamePurpose
IBase IntegerCore instruction set: arithmetic, logic, loads, stores, branches
MMultiply/Dividemul, div, rem and their variants
AAtomicAtomic memory operations (not used in our firmware)
CCompressed16-bit encodings for common instructions
ZicsrCSR Accesscsrr, csrw, csrrw for control/status registers

Instruction Encoding Formats

RV32I defines six base instruction formats. Every 32-bit instruction uses one of these:

FormatFieldsUsed For
R-typefunct7, rs2, rs1, funct3, rd, opcodeRegister-register operations: add, sub, and, or, sll, mul
I-typeimm[11:0], rs1, funct3, rd, opcodeImmediates and loads: addi, ori, andi, lw, jalr
S-typeimm[11:5], rs2, rs1, funct3, imm[4:0], opcodeStores: sw
B-typeimm[12|10:5], rs2, rs1, funct3, imm[4:1|11], opcodeBranches: beq, bne, bge, blt
U-typeimm[31:12], rd, opcodeUpper immediates: lui, auipc
J-typeimm[20|10:1|11|19:12], rd, opcodeJumps: jal
R-type:  [funct7 ][rs2  ][rs1  ][f3 ][rd   ][opcode ]
         31    25 24  20 19  15 14 12 11   7 6      0

I-type:  [imm[11:0]      ][rs1  ][f3 ][rd   ][opcode ]
         31            20 19  15 14 12 11   7 6      0

S-type:  [imm[11:5]  ][rs2  ][rs1  ][f3 ][imm[4:0] ][opcode ]
         31        25 24  20 19  15 14 12 11       7 6      0

The C Extension (Compressed Instructions)

The C extension provides 16-bit (2-byte) encodings for the most common operations. The assembler chooses compressed encodings automatically when possible:

32-bit Instruction16-bit EquivalentCondition
addi rd, rd, immc.addi rd, immimm fits in 6 bits
lw rd, off(rs1)c.lw rd, off(rs1)Registers in x8–x15, offset aligned
sw rs2, off(rs1)c.sw rs2, off(rs1)Registers in x8–x15, offset aligned
jal x1, offsetc.jal offsetOffset fits in 12 bits (RV32 only)
jalr x0, 0(x1)c.jr x1Always
add rd, x0, rs2c.mv rd, rs2Always
addi x2, x2, immc.addi16sp immStack pointer adjustment

Compressed instructions improve code density — the same logic fits in less flash. The programmer writes standard instructions; the assembler compresses them transparently.

Instructions Used in Our Firmware

Here is the complete list of instructions appearing in our blink driver:

InstructionFormatDescription
li rd, immPseudoLoad immediate (expands to lui+addi or just addi)
la rd, symbolPseudoLoad address (expands to auipc+addi)
lw rd, off(rs1)I-typeLoad word from memory
sw rs2, off(rs1)S-typeStore word to memory
add rd, rs1, rs2R-typeAdd two registers
addi rd, rs1, immI-typeAdd register and immediate
mul rd, rs1, rs2R-type (M)Multiply two registers
and rd, rs1, rs2R-typeBitwise AND
andi rd, rs1, immI-typeBitwise AND with immediate
or rd, rs1, rs2R-typeBitwise OR
ori rd, rs1, immI-typeBitwise OR with immediate
not rd, rs1PseudoBitwise NOT (expands to xori rd, rs1, -1)
sll rd, rs1, rs2R-typeShift left logical
beqz rs1, labelPseudoBranch if equal to zero (expands to beq rs1, x0, label)
bnez rs1, labelPseudoBranch if not zero (expands to bne rs1, x0, label)
bgez rs1, labelPseudoBranch if >= zero (expands to bge rs1, x0, label)
blez rs1, labelPseudoBranch if <= zero (expands to ble rs1, x0, label)
j labelPseudoUnconditional jump (expands to jal x0, label)
jal rd, labelJ-typeJump and link
jalr rd, off(rs1)I-typeJump and link register
call labelPseudoCall function (expands to auipc ra, … + jalr ra, …)
retPseudoReturn (expands to jalr x0, 0(x1))
csrw csr, rs1PseudoWrite CSR (expands to csrrw x0, csr, rs1)

Summary

  • The Hazard3 core implements RV32IMAC_Zicsr: base integer, multiply, atomics, compressed, and CSR access.
  • All base instructions are 32 bits, with six encoding formats (R, I, S, B, U, J).
  • The C extension provides automatic 16-bit compression for common instructions.
  • Our blink driver uses approximately 22 distinct instructions (including pseudo-instructions) to achieve full GPIO control from bare metal.