CM.PUSH

RISC-V CM.PUSH Instruction Details

Instruction ManualC2 (Zcmp CMPP)

Save the ra and 0 to 12 s-registers selected by reg_list, then adjust sp

Instruction Syntax

cm.push {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 stores selected registers downward from old sp-XLEN/8; on success sp decreases by stack_adj, with other integer registers unchanged.
No implicit ret or a0 zeroing; no direct single 32-bit equivalent encoding exists.
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.PUSH (Zcmp) pushes registers in {reg_list} (ra and up to 12 s-registers) to stack and decrements sp by stack_adj. stack_adj = stack_adj_base + spimm×16. Reuses c.fsdsp encoding, incompatible with Zcd. Stores may execute multiple times (fault recovery); sp adjustment commits atomically. Part of Zcmp, depends on Zca.

CM.PUSH Decode & Execute Animation

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

cm.push {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 -> mem32[0x00000FFC] <- s2/x18=0x00000030; mem32[0x00000FF8] <- s1/x9=0x00000020; mem32[0x00000FF4] <- s0/x8=0x00000010; mem32[0x00000FF0] <- ra/x1=0x00002001; sp <- 0x00000FC0
16-bit encoding fields
15..13
funct3
101
12..8
fixed
11000
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: mem32[0x00000FFC] <- s2/x18=0x00000030; mem32[0x00000FF8] <- s1/x9=0x00000020; mem32[0x00000FF4] <- s0/x8=0x00000010; mem32[0x00000FF0] <- ra/x1=0x00002001. The actual stores can occur in any order, be grouped, or repeat; sp' = 0x00001000 - 64 = 0x00000FC0.
mem32[0x00000FFC] <- s2/x18=0x00000030; mem32[0x00000FF8] <- s1/x9=0x00000020; mem32[0x00000FF4] <- s0/x8=0x00000010; mem32[0x00000FF0] <- ra/x1=0x00002001; sp <- 0x00000FC0
Architectural state has not been committed.

Quick Understanding & Search Notes

Store the listed registers below old sp, then subtract stack_adj from sp.

RV32/RV64 Zcmp requires Zca and conflicts with Zcd. 16-bit CMPP: bits[15:13]=101, [12:8]=11000, 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.
Store selected registers in descending register-number order, starting at old sp - 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 stores; sp updates only when the entire instruction can commit.

Common Usage Scenarios

Function prologue

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 stores selected registers downward from old sp-XLEN/8; on success sp decreases by stack_adj, with other integer registers unchanged.
  • No implicit ret or a0 zeroing; no direct single 32-bit equivalent encoding exists.
  • 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 (reuses c.fsdsp encoding)
Register list and stack adjustment constrained by encoding
Requires idempotent memory (stores may replay after faults)
No {ra, s0-s10} without s11 — must use {ra, s0-s11}

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. Stores may already be visible. Waiting for imprecise bus-fault responses before commit or handling them after completion is platform-defined.