Home/Instructions/CM-POPRET
CM.POPRET

RISC-V CM.POPRET Instruction Details

Instruction ManualC2 (Zcmp CMPP)

Restore registers, deallocate frame, and ret

Instruction Syntax

cm.popret {reg_list}, stack_adj
Operand Breakdown
RV32/RV64 Zcmp requires Zca and conflicts with Zcd; 16-bit CMPP, without x8–x15 compact-register fields.
rlist selects ra/x1 and a contiguous list of s0/x8, s1/x9, s2–s11/x18–x27; 0–3 are reserved, and RV32E permits only 4–6.
rlist=15 includes both s10/s11; stopping at s10 is not encodable. stack_adj is the list/XLEN size rounded up to 16 bytes, plus spimm×16 (spimm=0–3).
Pseudocode restores selected registers downward from old sp+stack_adj-XLEN/8; on success sp increases by stack_adj.
The final section adjusts sp and executes ret, clearing bit 0 of restored ra without changing a0 or writing a new link.
Accesses may reorder, group or repeat, with partial effects before faults; the final section commits only when the whole instruction can commit.
ZcmpStack & FunctionsCompressed Instruction

Instruction Behavior

CM.POPRET (Zcmp) pops registers in {reg_list}, adjusts sp, then executes ret. It does not write a0. It reuses c.fsdsp encoding and is therefore incompatible with Zcd. After the loads complete, the final atomic section commits the sp adjustment and ret. It is part of Zcmp and depends on Zca.

CM.POPRET Decode & Execute Animation

Shows only Zcmp architectural sequences and conditions; access order, grouping, or replay does not imply implementation detail.

cm.popret {reg_list}, stack_adj
Execution context

Zcmp depends on Zca and is incompatible with Zcd. Correct execution requires idempotent memory at sp; RV32E permits rlist=4-6 only. Values are pre-store registers or successfully loaded memory values; complete assumes the EEI permits all accesses, not that every address succeeds.

sp=0x00001000, rlist=7 -> s2/x18 <- mem32[0x0000103C]=0x00000030; s1/x9 <- mem32[0x00001038]=0x00000020; s0/x8 <- mem32[0x00001034]=0x00000010; ra/x1 <- mem32[0x00001030]=0x00002001; sp <- 0x00001040; PC <- restored ra & ~1 = 0x00002000
16-bit encoding fields
15..13
funct3
101
12..8
fixed
11110
7..4
rlist
0111
3..2
spimm
11
1..0
op
10
rlist=7 restores {ra/x1, s0/x8, s1/x9, s2/x18}; stack_adj_base=16; stack_adj=16+3×16=64 bytes.
Pseudocode address mapping: s2/x18 <- mem32[0x0000103C]=0x00000030; s1/x9 <- mem32[0x00001038]=0x00000020; s0/x8 <- mem32[0x00001034]=0x00000010; ra/x1 <- mem32[0x00001030]=0x00002001. The actual loads can occur in any order, be grouped, or repeat; sp' = 0x00001000 + 64 = 0x00001040; target = 0x00002001 & ~1 = 0x00002000.
s2/x18 <- mem32[0x0000103C]=0x00000030; s1/x9 <- mem32[0x00001038]=0x00000020; s0/x8 <- mem32[0x00001034]=0x00000010; ra/x1 <- mem32[0x00001030]=0x00002001; sp <- 0x00001040; PC <- restored ra & ~1 = 0x00002000
Architectural state has not been committed.

Quick Understanding & Search Notes

Load the listed registers from the stack, then add stack_adj to sp. Return through restored ra, leaving a0 unchanged.

RV32/RV64 Zcmp requires Zca and conflicts with Zcd. 16-bit CMPP: bits[15:13]=101, [12:8]=11110, rlist=[7:4], spimm=[3:2], [1:0]=10.
rlist=4 selects {ra}; 5–14 successively add s0 through s9; 15 selects {ra,s0-s11}, skipping {ra,s0-s10}. Values 0–3 are reserved; RV32E permits only 4–6.
stack_adj_base = ceil(register_count × XLEN / 8 / 16) × 16; stack_adj = base + spimm × 16, spimm=0–3. RV32E uses base=16.
Load selected registers in descending register-number order, starting at old sp + stack_adj - XLEN/8 and subtracting XLEN/8 per register. No direct single 32-bit equivalent encoding exists.
Accesses may reorder, group, or repeat; correct execution requires idempotent memory. A precise fault may follow partial register loads; final sp and ret commit atomically only when the entire instruction can commit.

Common Usage Scenarios

Function epilogue

RV32I Zcmp, accesses complete: {ra,s0-s2} occupies 16 bytes; stack_adj=64 encodes rlist=7, spimm=3. PUSH saves below old sp then sp-=64; POP forms restore from old sp+48 through old sp+60 then sp+=64. Return forms use restored ra; POPRETZ also zeros a0.

Pre-Use Checklist

Syntax Check
  • RV32/RV64 Zcmp requires Zca and conflicts with Zcd; 16-bit CMPP, without x8–x15 compact-register fields.
  • rlist selects ra/x1 and a contiguous list of s0/x8, s1/x9, s2–s11/x18–x27; 0–3 are reserved, and RV32E permits only 4–6.
Semantic Check
  • rlist=15 includes both s10/s11; stopping at s10 is not encodable. stack_adj is the list/XLEN size rounded up to 16 bytes, plus spimm×16 (spimm=0–3).
  • Pseudocode restores selected registers downward from old sp+stack_adj-XLEN/8; on success sp increases by stack_adj.
  • The final section adjusts sp and executes ret, clearing bit 0 of restored ra without changing a0 or writing a new link.
  • Accesses may reorder, group or repeat, with partial effects before faults; the final section commits only when the whole instruction can commit.

Pitfalls / Common Confusions

Incompatible with Zcd
Preserves a0 value (unlike POPRETZ)
sp adjustment and ret must commit atomically

FAQ

Can stack_adj be any multiple of 16?

No. The register list and XLEN determine base; only base, base+16, base+32, and base+48 are encodable.

Are accesses before a fault guaranteed to have no effect?

No. Some destination registers may already be loaded. The sequence re-executes after the trap handler; the loads are not collectively atomic.