29.13.8Zcmp: cm.pop

Part I Linux boot: optional Vol. I (Unprivileged) pp. 198–202 · ~2 min read

cm.pop {reg_list}, stack_adj destroys a stack frame: reload ra and the listed s-registers from their canonical slots, then release the frame by adding stack_adj to sp. No return — cm.pop is the epilogue for tail-calling functions, where a jump (not ret) follows.

101151311010128rlist74spimm321010cm.pop
Click a field for its role.

The expansion mirrors the push exactly — same slots, positive offsets, sp adjustment last:

# cm.pop {ra, s0-s3}, 48   (rlist=8, spimm=1, RV32)
lw   s3, 44(sp)     # top of frame, just below where old sp was
lw   s2, 40(sp)
lw   s1, 36(sp)
lw   s0, 32(sp)
lw   ra, 28(sp)
addi sp, sp, 48     # the atomic tail: commits only when all loads are safe

All the sequence semantics apply: loads may reorder, repeat, and partially update destinations before a trap (xEPC = the cm.pop PC; full re-execution after); the sp adjustment is all-or-nothing; idempotent memory required.

Hardware Designer Notes

cm.pop is the same microsequence skeleton as cm.push with loads instead of stores and the frame math shifted by +stack_adj. If your sequencer parameterizes direction, base offset, and tail ops, all four PUSH/POP instructions are one state machine.

Minimal Linux-boot hart MUST

  • Read the canonical slot layout (identical to cm.push) — unwinders and longjmp implementations depend on the frame shape
  • Commit the sp adjustment only after every load has cleared its fault checks

MAY simplify / trap-and-emulate

  • Reuse the cm.push µop sequencer with direction=load and offset base sp+stack_adj−bytes

Check yourself — cm.pop

1.How does cm.pop's frame layout relate to cm.push's?

2.Where does cm.pop differ from cm.popret in the tail commit group?

2 questions