Immediate Encoding

See how one value is carried into a 32-bit instruction

When learning immediate encoding, it helps to start with one path: the assembly immediate is processed, sliced, placed into fixed instruction bits, then rebuilt by immediate bit number during decode. The field tables are easier to map after that.

B-type

Why does a beq offset look scrambled?

Branch targets are 2-byte aligned, so imm[0] is not encoded; the other bits are spread out.

Example
beq x1, x2, -4
assembly value01
-4
slice by format02
imm[12] imm[10:5] imm[4:1] imm[11] imm[0]
place into instruction03
inst[31] inst[30:25] inst[11:8] inst[7]
decode and rebuild04
-4
31..25
imm[12|10:5]
24..20
rs2
19..15
rs1
14..12
funct3
11..7
imm[4:1|11]
6..0
opcode
310
sign bitimmediateregisterimm[0] = 0
Value
-4
Encoded bits
1111111111100
Restored
-4

These bit layouts follow the RISC-V Unprivileged ISA Manual base instruction formats and immediate variants. CSR 5-bit immediates, compressed instructions, and extension-specific encodings are outside this introductory I/S/B/U/J model.

General rule

Except for special cases such as CSR 5-bit immediates, the sign bit in base formats is always in inst[31].

Branch/jump

B/J omit bit 0, so offsets are at least 2-byte aligned.

Upper immediate

U-type forms a 32-bit U-immediate: [31:12] comes from the instruction, [11:0] is zero.

Learn by question

Understand the use case before memorizing the format name

Each section uses the same path: what assembly writes, where the encoder places the bits, and how the CPU rebuilds them during decode.

I-type

I-type: a contiguous 12-bit signed immediate

Range
-2048..2047
Remember This

Put one signed 12-bit value directly into the top 12 instruction bits.

Used by addi, loads, jalr, and related instructions. imm[11:0] occupies inst[31:20]; imm[11] is in inst[31], and the immediate is sign-extended to XLEN before use. Shift-immediate instructions are I-type specializations that use shamt rather than a normal signed 12-bit value.

contiguous field12-bit signedaddi / load / jalrshift immediates are specialized

Where the Bits Go

imm[11:0]inst[31:20]

complete 12-bit immediate field

imm[11]inst[31]

sign bit

How Decode Rebuilds It

  1. 01Read imm[11:0] from inst[31:20].
  2. 02Use imm[11] as the sign bit and extend to XLEN.
  3. 03Feed the sign-extended immediate to addi, load, or jalr semantics.
Practice
addi x1, x2, -1
Open in EncoderRead addi
S-type

S-type: store offset split into two fields

Range
-2048..2047
Remember This

Stores have no rd, so the old rd position carries the low 5 offset bits.

Used by stores such as sb, sh, sw, and sd. There is no rd field, so the 12-bit offset is split across inst[31:25] and inst[11:7], then reassembled as imm[11:0] and sign-extended.

split field12-bit signedstore offset

Where the Bits Go

imm[11:5]inst[31:25]

upper 7 offset bits

imm[4:0]inst[11:7]

lower 5 offset bits

How Decode Rebuilds It

  1. 01Read imm[11:5] from inst[31:25].
  2. 02Read imm[4:0] from inst[11:7].
  3. 03Join imm[11:0], then sign-extend from imm[11].
  4. 04Add the result to rs1 to form the store address.
Practice
sw x1, -8(x2)
Open in EncoderRead sw
B-type

B-type: branch offset bit 0 is implicit zero

Range
-4096..4094
Remember This

Branch targets are 2-byte aligned, so imm[0] is not encoded; the other bits are spread out.

Used by conditional branches. The target is a PC-relative offset. The encoding stores imm[12], imm[10:5], imm[4:1], and imm[11]; imm[0] is not stored, representing 2-byte target alignment.

PC-relativebit 0 implicit 0scrambled layout

Where the Bits Go

imm[12]inst[31]

sign bit

imm[10:5]inst[30:25]

middle upper offset bits

imm[4:1]inst[11:8]

low offset bits; imm[0] is omitted

imm[11]inst[7]

placed at the end of the low field

How Decode Rebuilds It

  1. 01Read imm[12] from inst[31]; this is the sign bit.
  2. 02Read imm[10:5] from inst[30:25].
  3. 03Read imm[4:1] from inst[11:8], and imm[11] from inst[7].
  4. 04Restore imm[0]=0, sign-extend from imm[12], then add to PC.
Practice
beq x1, x2, -4
Open in EncoderRead beq
U-type

U-type: a 20-bit field forms a 32-bit U-immediate

Range
imm[31:12] << 12
Remember This

The encoded field goes into the upper 20 bits of the 32-bit U-immediate; the low 12 bits are zero.

Used by lui and auipc. The encoded imm[31:12] supplies the upper 20 bits of a 32-bit U-immediate, while the low 12 bits are zero; its sign bit still comes from inst[31]. Large constants and addresses usually need addi, load/store, or relocation pairs.

upper immediatelow 12 bits are zerosign bit is still inst[31]lui / auipc

Where the Bits Go

imm[31:12]inst[31:12]

20-bit upper field

0x000imm[11:0]

low 12 bits of the 32-bit U-immediate are zero

How Decode Rebuilds It

  1. 01Read the 20-bit field from inst[31:12].
  2. 02Place it into bits [31:12] of the 32-bit U-immediate.
  3. 03Fill bits [11:0] with zero; LUI sign-extends that 32-bit value to XLEN and writes rd, while AUIPC adds the sign-extended offset to PC.
Practice
lui x1, 0x10
Open in EncoderRead lui
J-type

J-type: large PC-relative offset for jal

Range
-1048576..1048574
Remember This

jal is also a PC-relative offset with imm[0] omitted, but it uses 20 encoded bits for a larger reach.

Used by jal. Like B-type, imm[0] is not stored, but the reach is larger. The encoding stores imm[20], imm[10:1], imm[11], and imm[19:12], then sign-extends and adds the offset to PC.

PC-relativebit 0 implicit 0±1 MiB target range

Where the Bits Go

imm[20]inst[31]

sign bit

imm[10:1]inst[30:21]

lower middle offset bits

imm[11]inst[20]

separate bit 11

imm[19:12]inst[19:12]

upper offset bits

How Decode Rebuilds It

  1. 01Read imm[20] from inst[31]; this is the sign bit.
  2. 02Read imm[10:1] from inst[30:21].
  3. 03Read imm[11] from inst[20], and imm[19:12] from inst[19:12].
  4. 04Restore imm[0]=0, sign-extend from imm[20], then add to PC.
Practice
jal x1, -4
Open in EncoderRead jal
Reference after the concept

I/S/B/U/J Immediate Reference

Use this table after the flow is clear to check range, sign extension, and which bits are not stored contiguously.

FormatUseImmediate bitsRange / resultKey idea
Iaddi x1, x2, -1imm[11:0]-2048..2047Put one signed 12-bit value directly into the top 12 instruction bits.
Ssw x1, -8(x2)imm[11:5] + imm[4:0]-2048..2047Stores have no rd, so the old rd position carries the low 5 offset bits.
Bbeq x1, x2, -4imm[12] + imm[10:5] + imm[4:1] + imm[11] + 0-4096..4094Branch targets are 2-byte aligned, so imm[0] is not encoded; the other bits are spread out.
Ului x1, 0x10imm[31:12]imm[31:12] << 12The encoded field goes into the upper 20 bits of the 32-bit U-immediate; the low 12 bits are zero.
Jjal x1, -4imm[20] + imm[10:1] + imm[11] + imm[19:12] + 0-1048576..1048574jal is also a PC-relative offset with imm[0] omitted, but it uses 20 encoded bits for a larger reach.

Mistake Lab

Wrong intuition
lui x1, 0x10 => 0x00000010
Correct model
lui x1, 0x10 => 0x00010000

Treating a U-type assembly operand as the final constant. lui x1, 0x10 produces a U-immediate shaped like 0x00010000, not 0x10.

Official References

This page is organized with reference to the official RISC-V documents below for architecture, ABI, CSR, and pseudo-instruction notes; platform or OS ABI differences still need to be checked against their own specifications.