首页/指令库/C-SSPUSH
C.SSPUSH

RISC-V C.SSPUSH 指令详解

指令手册C-type

xSSE=1 时,C.SSPUSH 将固定 x1 的值压入影子栈。

指令语法

c.sspush x1
操作数说明
该压缩形式固定为 x1,没有可变的显式寄存器操作数。
C.MOP.1 编码在 xSSE=1 时展开为 SSPUSH x1;ssp 是隐式基址,访问宽度为 XLEN。
xSSE=0 时不执行影子栈操作,C.MOP.1 不写寄存器。
ZicfissZcmop安全机制

指令行为说明

C.SSPUSH x1(Zicfiss,依赖 Zcmop)使用 C.MOP.1 编码,在 xSSE=1 时等价于 SSPUSH x1:向 ssp - XLEN/8 地址存储 x1 的值;只有存储成功后 ssp 才递减 XLEN/8 并提交更新。未启用 Zicfiss 时按 C.MOP.1 的 Zcmop 行为执行。

C.SSPUSH 指令解析与执行动画

仅展示官方定义的编码、条件和架构可见结果,不表示微架构实现。

c.sspush x1

该压缩编码没有可变的显式寄存器:C.SSPUSH 固定 x1;C.SSPOPCHK 固定 x5。

执行环境

假定 Zicfiss、Zcmop 及其依赖扩展存在;xSSE 为当前权限模式的有效使能值。只演示对齐的 ssp;RV64 场景假定 UXLEN/SXLEN 始终为 64。

mem[0x0000000000001FF8] <- 0x0123456789ABCDEF; ssp <- 0x0000000000001FF8
16 位编码字段
15..13
funct3
011
12..11
fixed high bits
00
10..8
C.MOP.1 selector
000
7
fixed bit
1
6..2
fixed low bits
00000
1..0
op
01
固定压缩字段选择隐式寄存器。
address = 0x0000000000002000 - 8 = 0x0000000000001FF8; store 0x0123456789ABCDEF
mem[0x0000000000001FF8] <- 0x0123456789ABCDEF; ssp <- 0x0000000000001FF8
尚未提交架构状态。

快速理解与检索要点

C.SSPUSH 是固定 x1 的 Zicfiss 影子栈压入;只有 xSSE=1 且存储成功时才提交 ssp 递减。

影子栈操作隐式使用 ssp,宽度为 XLEN。
不要把 CFI MOP 兼容性误解为安全检查总是执行;xSSE=0 时这两个压缩 C.MOP 形式不访问影子栈且不写寄存器。
Zicfiss 不用于 M-mode;U-mode 使用需要实现 S-mode。xSSE 是当前权限模式的有效使能值。

常见使用场景

影子栈返回地址副本存储

结合 «c.sspush x1 # push ra onto shadow stack» 等实际代码理解该场景。

固定 x1 的压缩影子栈压入

结合 «c.sspush x1 # push ra onto shadow stack» 等实际代码理解该场景。

使用前检查清单

语法检查
  • 确认 16 位 C.MOP.1 固定选择 x1;该压缩形式没有可变显式寄存器。
  • 确认 Zicfiss、Zcmop 及其所依赖的 Zicsr、Zimop、Zaamo 可用,并且不在 M-mode 使用 Zicfiss。
语义检查
  • xSSE=1 时先以 XLEN/8 计算新 ssp,再向该地址存储 x1;只有存储完成后才提交 ssp。
  • xSSE=0 时按 C.MOP.1 行为,不执行影子栈访问且不写寄存器。

容易混淆 / 常见误区

压缩形式只提供 x1;完整 SSPUSH 支持 x1 和 x5。
Zicfiss 依赖 Zicsr、Zimop 和 Zaamo;压缩形式还需要 Zcmop。
M-mode 不支持使用 Zicfiss。
SSPUSH/C.SSPUSH 只有在影子栈存储成功后才递减 ssp。

常见问题

C.SSPUSH 未启用相关 CFI 时会怎样?

假定 Zcmop 存在,xSSE=0 时保留对应 C.MOP 的行为:不访问影子栈,不更新 ssp,也不写任何寄存器。

C.SSPUSH 何时更新 ssp?

xSSE=1 时,向 ssp−XLEN/8 存储 x1;仅存储成功才将 ssp 减少 XLEN/8。存储故障不提交该更新。