Table of Contents

Overview
#

RISC-V is an open-source instruction set architecture. R-type instructions perform register-to-register operations, the most common instruction type.

R-Type Instruction Format
#

Bit Fields
#

31       25 24    20 19    15 14  12 11     7 6      0
┌──────────┬────────┬────────┬──────┬────────┬────────┐
│  funct7  │   rs2  │   rs1  │funct3│   rd   │ opcode │
│  (7 bit) │ (5 bit)│ (5 bit)│(3bit)│ (5 bit)│ (7 bit)│
└──────────┴────────┴────────┴──────┴────────┴────────┘

Field Descriptions
#

FieldBitsPurpose
opcode6:0Operation class (0110011 for R-type)
rd11:7Destination register
funct314:12Operation type
rs119:15Source register 1
rs224:20Source register 2
funct731:25Operation variant

Basic R-Type Instructions
#

Arithmetic Operations
#

Instructionfunct7funct3Operation
ADD0000000000rd = rs1 + rs2
SUB0100000000rd = rs1 - rs2
SLL0000000001rd = rs1 « rs2
SLT0000000010rd = (rs1 < rs2) ? 1 : 0
SLTU0000000011rd = (rs1 < rs2) unsigned
XOR0000000100rd = rs1 ^ rs2
SRL0000000101rd = rs1 » rs2 (logical)
SRA0100000101rd = rs1 » rs2 (arithmetic)
OR0000000110rd = rs1
AND0000000111rd = rs1 & rs2

Logical Instructions
#

Bitwise Operations
#

AND:  rd = rs1 & rs2
      1010 & 1100 = 1000

OR:   rd = rs1 | rs2
      1010 | 1100 = 1110

XOR:  rd = rs1 ^ rs2
      1010 ^ 1100 = 0110

Shift Operations
#

SLL (Shift Left Logical):
      rs1 = 0001_0100
      rs2 = 2
      rd  = 0101_0000

SRL (Shift Right Logical):
      rs1 = 1000_0100
      rs2 = 2
      rd  = 0010_0001

SRA (Shift Right Arithmetic):
      rs1 = 1000_0100 (negative)
      rs2 = 2
      rd  = 1110_0001 (sign-extended)

Comparison Instructions
#

SLT (Set Less Than)
#

SLT rd, rs1, rs2    ; rd = (rs1 < rs2) ? 1 : 0

Signed comparison:

  • If rs1 < rs2 (signed), rd = 1
  • Otherwise, rd = 0

SLTU (Set Less Than Unsigned)
#

SLTU rd, rs1, rs2   ; rd = (rs1 < rs2) ? 1 : 0

Unsigned comparison.

Encoding Example
#

ADD x5, x6, x7
#

rs2 = x7  = 00111
rs1 = x6  = 00110
rd  = x5  = 00101
funct7    = 0000000
funct3    = 000
opcode    = 0110011

Binary: 0000000_00111_00110_000_00101_0110011
Hex:    0x007302B3

SUB x5, x6, x7
#

funct7    = 0100000  (different from ADD)
funct3    = 000      (same as ADD)

Binary: 0100000_00111_00110_000_00101_0110011
Hex:    0x407302B3

Register Conventions
#

RegisterABI NamePurpose
x0zeroHardwired zero
x1raReturn address
x2spStack pointer
x5-x7t0-t2Temporaries
x10-x11a0-a1Arguments/Return
x12-x17a2-a7Arguments
x28-x31t3-t6Temporaries

M Extension (Multiply/Divide)
#

Additional R-type instructions:

Instructionfunct7funct3Operation
MUL0000001000rd = (rs1 × rs2)[31:0]
MULH0000001001rd = (rs1 × rs2)[63:32] signed
MULHSU0000001010rd = (rs1 × rs2)[63:32] signed×unsigned
MULHU0000001011rd = (rs1 × rs2)[63:32] unsigned
DIV0000001100rd = rs1 / rs2 signed
DIVU0000001101rd = rs1 / rs2 unsigned
REM0000001110rd = rs1 % rs2 signed
REMU0000001111rd = rs1 % rs2 unsigned

Decoding Logic
#

Opcode Check
#

if (opcode == 0110011)
    // R-type instruction

Operation Selection
#

switch (funct3) {
    case 000:
        if (funct7 == 0000000) ADD
        if (funct7 == 0100000) SUB
    case 001: SLL
    case 010: SLT
    ...
}

Why This Design?
#

Regularity
#

  • Fixed field positions
  • Easy decoding
  • Simple hardware

Flexibility
#

  • funct7 allows instruction variants
  • Extensible for custom instructions

Efficiency
#

  • 32 registers addressable (5 bits)
  • All operations in one cycle