VincentWu updated this revision to Diff 517494.
VincentWu marked 3 inline comments as done.
VincentWu added a comment.

address comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132819/new/

https://reviews.llvm.org/D132819

Files:
  clang/test/Preprocessor/riscv-target-features.c
  llvm/docs/RISCVUsage.rst
  llvm/lib/Support/RISCVISAInfo.cpp
  llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
  llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
  llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
  llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
  llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
  llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
  llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
  llvm/lib/Target/RISCV/RISCVFeatures.td
  llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
  llvm/lib/Target/RISCV/RISCVRegisterInfo.td
  llvm/test/MC/RISCV/attribute-arch.s
  llvm/test/MC/RISCV/rv32zcmp-invalid.s
  llvm/test/MC/RISCV/rv32zcmp-valid.s
  llvm/test/MC/RISCV/rv64zcmp-invalid.s
  llvm/test/MC/RISCV/rv64zcmp-valid.s

Index: llvm/test/MC/RISCV/rv64zcmp-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64zcmp-valid.s
@@ -0,0 +1,149 @@
+# RUN: llvm-mc %s -triple=riscv64 -mattr=experimental-zcmp -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=experimental-zcmp < %s \
+# RUN:     | llvm-objdump --mattr=-c,experimental-zcmp -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: cm.mvsa01 s1, s0
+# CHECK-ASM: encoding: [0xa2,0xac]
+cm.mvsa01 s1, s0
+
+# CHECK-ASM-AND-OBJ: cm.mva01s s1, s0
+# CHECK-ASM: encoding: [0xe2,0xac]
+cm.mva01s s1, s0
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra}, 16
+# CHECK-ASM: encoding: [0x42,0xbe]
+cm.popret {ra}, 16
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra}, 32
+# CHECK-ASM: encoding: [0x46,0xbe]
+cm.popret {ra}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0}, 64
+# CHECK-ASM: encoding: [0x5e,0xbe]
+cm.popret {ra, s0}, 64
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s1}, 32
+# CHECK-ASM: encoding: [0x62,0xbe]
+cm.popret {ra,s0-s1}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s2}, 32
+# CHECK-ASM: encoding: [0x72,0xbe]
+cm.popret {ra, s0-s2}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s3}, 64
+# CHECK-ASM: encoding: [0x86,0xbe]
+cm.popret {ra, s0-s3}, 64
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s5}, 64
+# CHECK-ASM: encoding: [0xa2,0xbe]
+cm.popret {ra, s0-s5}, 64
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s7}, 80
+# CHECK-ASM: encoding: [0xc2,0xbe]
+cm.popret {ra, s0-s7}, 80
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s11}, 112
+# CHECK-ASM: encoding: [0xf2,0xbe]
+cm.popret {ra, s0-s11}, 112
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra}, 16
+# CHECK-ASM: encoding: [0x42,0xbc]
+cm.popretz {ra}, 16
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra}, 32
+# CHECK-ASM: encoding: [0x46,0xbc]
+cm.popretz {ra}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0}, 64
+# CHECK-ASM: encoding: [0x5e,0xbc]
+cm.popretz {ra, s0}, 64
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s1}, 32
+# CHECK-ASM: encoding: [0x62,0xbc]
+cm.popretz {ra, s0-s1}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s2}, 32
+# CHECK-ASM: encoding: [0x72,0xbc]
+cm.popretz {ra, s0-s2}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s3}, 64
+# CHECK-ASM: encoding: [0x86,0xbc]
+cm.popretz {ra, s0-s3}, 64
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s5}, 64
+# CHECK-ASM: encoding: [0xa2,0xbc]
+cm.popretz {ra, s0-s5}, 64
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s7}, 80
+# CHECK-ASM: encoding: [0xc2,0xbc]
+cm.popretz {ra, s0-s7}, 80
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s11}, 112
+# CHECK-ASM: encoding: [0xf2,0xbc]
+cm.popretz {ra, s0-s11}, 112
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra}, 16
+# CHECK-ASM: encoding: [0x42,0xba]
+cm.pop {ra}, 16
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra}, 32
+# CHECK-ASM: encoding: [0x46,0xba]
+cm.pop {ra}, 32
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0}, 16
+# CHECK-ASM: encoding: [0x52,0xba]
+cm.pop {ra, s0}, 16
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s1}, 32
+# CHECK-ASM: encoding: [0x62,0xba]
+cm.pop {ra, s0-s1}, 32
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s2}, 32
+# CHECK-ASM: encoding: [0x72,0xba]
+cm.pop {ra, s0-s2}, 32
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s5}, 64
+# CHECK-ASM: encoding: [0xa2,0xba]
+cm.pop {ra, s0-s5}, 64
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s7}, 80
+# CHECK-ASM: encoding: [0xc2,0xba]
+cm.pop {ra, s0-s7}, 80
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s11}, 112
+# CHECK-ASM: encoding: [0xf2,0xba]
+cm.pop {ra, s0-s11}, 112
+
+# CHECK-ASM-AND-OBJ: cm.push {ra}, -16
+# CHECK-ASM: encoding: [0x42,0xb8]
+cm.push {ra}, -16
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0}, -32
+# CHECK-ASM: encoding: [0x56,0xb8]
+cm.push {ra, s0}, -32
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s1}, -32
+# CHECK-ASM: encoding: [0x62,0xb8]
+cm.push {ra, s0-s1}, -32
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s3}, -64
+# CHECK-ASM: encoding: [0x86,0xb8]
+cm.push {ra, s0-s3}, -64
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s7}, -80
+# CHECK-ASM: encoding: [0xc2,0xb8]
+cm.push {ra, s0-s7}, -80
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s7}, -80
+# CHECK-ASM: encoding: [0xc2,0xb8]
+cm.push {ra, s0-s7}, -80
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s11}, -112
+# CHECK-ASM: encoding: [0xf2,0xb8]
+cm.push {ra, s0-s11}, -112
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s11}, -128
+# CHECK-ASM: encoding: [0xf6,0xb8]
+cm.push {ra, s0-s11}, -128
Index: llvm/test/MC/RISCV/rv64zcmp-invalid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64zcmp-invalid.s
@@ -0,0 +1,17 @@
+# RUN: not llvm-mc -triple=riscv64 -mattr=experimental-zcmp -riscv-no-aliases -show-encoding < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK-ERROR %s
+
+# CHECK-ERROR: error: invalid operand for instruction
+cm.mvsa01 a1, a2
+
+# CHECK-ERROR: error: 'rs1' and 'rs2' mast be different
+cm.mvsa01 s0, s0
+
+# CHECK-ERROR: error: invalid operand for instruction
+cm.mva01s a1, a2
+
+# CHECK-ERROR: error: invalid register list, {ra, s0-s10} or {x1, x8-x9, x18-x26} is not supported
+cm.popretz {ra, s0-s10}, 112
+
+# CHECK-ERROR: error: This stack adjustment is invalid for this instruction and register list, Please refer to Zc spec for a detailed range of stack adjustment
+cm.popretz {ra, s0-s1}, 112
Index: llvm/test/MC/RISCV/rv32zcmp-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zcmp-valid.s
@@ -0,0 +1,289 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=experimental-zcmp -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=experimental-zcmp < %s \
+# RUN:     | llvm-objdump --mattr=-c,experimental-zcmp -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: cm.mvsa01 s1, s0
+# CHECK-ASM: encoding: [0xa2,0xac]
+cm.mvsa01 s1, s0
+
+# CHECK-ASM-AND-OBJ: cm.mva01s s1, s0
+# CHECK-ASM: encoding: [0xe2,0xac]
+cm.mva01s s1, s0
+
+# CHECK-ASM-AND-OBJ: cm.mva01s s0, s0
+# CHECK-ASM: encoding: [0x62,0xac] 
+cm.mva01s s0, s0
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra}, 16
+# CHECK-ASM: encoding: [0x42,0xbe]
+cm.popret {ra}, 16
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra}, 16
+# CHECK-ASM: encoding: [0x42,0xbe]
+cm.popret {x1}, 16
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra}, 32
+# CHECK-ASM: encoding: [0x46,0xbe]
+cm.popret {ra}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra}, 32
+# CHECK-ASM: encoding: [0x46,0xbe]
+cm.popret {x1}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0}, 64
+# CHECK-ASM: encoding: [0x5e,0xbe]
+cm.popret {ra, s0}, 64
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0}, 64
+# CHECK-ASM: encoding: [0x5e,0xbe]
+cm.popret {x1, x8}, 64
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s1}, 16
+# CHECK-ASM: encoding: [0x62,0xbe]
+cm.popret {ra,s0-s1}, 16
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s1}, 16
+# CHECK-ASM: encoding: [0x62,0xbe]
+cm.popret {x1, x8-x9}, 16
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s2}, 32
+# CHECK-ASM: encoding: [0x76,0xbe]
+cm.popret {ra, s0-s2}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s2}, 32
+# CHECK-ASM: encoding: [0x76,0xbe]
+cm.popret {x1, x8-x9, x18}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s3}, 32
+# CHECK-ASM: encoding: [0x82,0xbe]
+cm.popret {ra, s0-s3}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s3}, 32
+# CHECK-ASM: encoding: [0x82,0xbe]
+cm.popret {x1, x8-x9, x18-x19}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s5}, 32
+# CHECK-ASM: encoding: [0xa2,0xbe]
+cm.popret {ra, s0-s5}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s5}, 32
+# CHECK-ASM: encoding: [0xa2,0xbe]
+cm.popret {x1, x8-x9, x18-x21}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s7}, 48
+# CHECK-ASM: encoding: [0xc2,0xbe]
+cm.popret {ra, s0-s7}, 48
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s7}, 48
+# CHECK-ASM: encoding: [0xc2,0xbe]
+cm.popret {x1, x8-x9, x18-x23}, 48
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s11}, 112
+# CHECK-ASM: encoding: [0xfe,0xbe]
+cm.popret {ra, s0-s11}, 112
+
+# CHECK-ASM-AND-OBJ: cm.popret   {ra, s0-s11}, 112
+# CHECK-ASM: encoding: [0xfe,0xbe]
+cm.popret {x1, x8-x9, x18-x27}, 112
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra}, 16
+# CHECK-ASM: encoding: [0x42,0xbc]
+cm.popretz {ra}, 16
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra}, 16
+# CHECK-ASM: encoding: [0x42,0xbc]
+cm.popretz {x1}, 16
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra}, 32
+# CHECK-ASM: encoding: [0x46,0xbc]
+cm.popretz {ra}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra}, 32
+# CHECK-ASM: encoding: [0x46,0xbc]
+cm.popretz {x1}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0}, 64
+# CHECK-ASM: encoding: [0x5e,0xbc]
+cm.popretz {ra, s0}, 64
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0}, 64
+# CHECK-ASM: encoding: [0x5e,0xbc]
+cm.popretz {x1, x8}, 64
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s1}, 16
+# CHECK-ASM: encoding: [0x62,0xbc]
+cm.popretz {ra, s0-s1}, 16
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s1}, 16
+# CHECK-ASM: encoding: [0x62,0xbc]
+cm.popretz {x1, x8-x9}, 16
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s2}, 32
+# CHECK-ASM: encoding: [0x76,0xbc]
+cm.popretz {ra, s0-s2}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s2}, 32
+# CHECK-ASM: encoding: [0x76,0xbc]
+cm.popretz {x1, x8-x9, x18}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s3}, 32
+# CHECK-ASM: encoding: [0x82,0xbc]
+cm.popretz {ra, s0-s3}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s3}, 32
+# CHECK-ASM: encoding: [0x82,0xbc]
+cm.popretz {x1, x8-x9, x18-x19}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s5}, 32
+# CHECK-ASM: encoding: [0xa2,0xbc]
+cm.popretz {ra, s0-s5}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s5}, 32
+# CHECK-ASM: encoding: [0xa2,0xbc]
+cm.popretz {x1, x8-x9, x18-x21}, 32
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s7}, 48
+# CHECK-ASM: encoding: [0xc2,0xbc]
+cm.popretz {ra, s0-s7}, 48
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s7}, 48
+# CHECK-ASM: encoding: [0xc2,0xbc]
+cm.popretz {x1, x8-x9, x18-x23}, 48
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s11}, 112
+# CHECK-ASM: encoding: [0xfe,0xbc]
+cm.popretz {ra, s0-s11}, 112
+
+# CHECK-ASM-AND-OBJ: cm.popretz   {ra, s0-s11}, 112
+# CHECK-ASM: encoding: [0xfe,0xbc]
+cm.popretz {x1, x8-x9, x18-x27}, 112
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra}, 16
+# CHECK-ASM: encoding: [0x42,0xba]
+cm.pop {ra}, 16
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra}, 16
+# CHECK-ASM: encoding: [0x42,0xba]
+cm.pop {x1}, 16
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra}, 32
+# CHECK-ASM: encoding: [0x46,0xba]
+cm.pop {ra}, 32
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra}, 32
+# CHECK-ASM: encoding: [0x46,0xba]
+cm.pop {x1}, 32
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0}, 16
+# CHECK-ASM: encoding: [0x52,0xba]
+cm.pop {ra, s0}, 16
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0}, 16
+# CHECK-ASM: encoding: [0x52,0xba]
+cm.pop {x1, x8}, 16
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s1}, 32
+# CHECK-ASM: encoding: [0x66,0xba]
+cm.pop {ra, s0-s1}, 32
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s1}, 32
+# CHECK-ASM: encoding: [0x66,0xba]
+cm.pop {x1, x8-x9}, 32
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s2}, 32
+# CHECK-ASM: encoding: [0x76,0xba]
+cm.pop {ra, s0-s2}, 32
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s2}, 32
+# CHECK-ASM: encoding: [0x76,0xba]
+cm.pop {x1, x8-x9, x18}, 32
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s5}, 32
+# CHECK-ASM: encoding: [0xa2,0xba]
+cm.pop {ra, s0-s5}, 32
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s5}, 32
+# CHECK-ASM: encoding: [0xa2,0xba]
+cm.pop {x1, x8-x9, x18-x21}, 32
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s7}, 48
+# CHECK-ASM: encoding: [0xc2,0xba]
+cm.pop {ra, s0-s7}, 48
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s7}, 48
+# CHECK-ASM: encoding: [0xc2,0xba]
+cm.pop {x1, x8-x9, x18-x23}, 48
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s11}, 64
+# CHECK-ASM: encoding: [0xf2,0xba]
+cm.pop {ra, s0-s11}, 64
+
+# CHECK-ASM-AND-OBJ: cm.pop  {ra, s0-s11}, 64
+# CHECK-ASM: encoding: [0xf2,0xba]
+cm.pop {x1, x8-x9, x18-x27}, 64
+
+# CHECK-ASM-AND-OBJ: cm.push {ra}, -16
+# CHECK-ASM: encoding: [0x42,0xb8]
+cm.push {ra}, -16
+
+# CHECK-ASM-AND-OBJ: cm.push {ra}, -16
+# CHECK-ASM: encoding: [0x42,0xb8]
+cm.push {x1}, -16
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0}, -32
+# CHECK-ASM: encoding: [0x56,0xb8]
+cm.push {ra, s0}, -32
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0}, -32
+# CHECK-ASM: encoding: [0x56,0xb8]
+cm.push {x1, x8}, -32
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s1}, -16
+# CHECK-ASM: encoding: [0x62,0xb8]
+cm.push {ra, s0-s1}, -16
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s1}, -16
+# CHECK-ASM: encoding: [0x62,0xb8]
+cm.push {x1, x8-x9}, -16
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s3}, -32
+# CHECK-ASM: encoding: [0x82,0xb8]
+cm.push {ra, s0-s3}, -32
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s3}, -32
+# CHECK-ASM: encoding: [0x82,0xb8]
+cm.push {x1, x8-x9, x18-x19}, -32
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s7}, -48
+# CHECK-ASM: encoding: [0xc2,0xb8]
+cm.push {ra, s0-s7}, -48
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s7}, -48
+# CHECK-ASM: encoding: [0xc2,0xb8]
+cm.push {x1, x8-x9, x18-x23}, -48
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s7}, -64
+# CHECK-ASM: encoding: [0xc6,0xb8]
+cm.push {ra, s0-s7}, -64
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s7}, -64
+# CHECK-ASM: encoding: [0xc6,0xb8]
+cm.push {x1, x8-x9, x18-x23}, -64
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s11}, -80
+# CHECK-ASM: encoding: [0xf6,0xb8]
+cm.push {ra, s0-s11}, -80
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s11}, -80
+# CHECK-ASM: encoding: [0xf6,0xb8]
+cm.push {x1, x8-x9, x18-x27}, -80
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s11}, -112
+# CHECK-ASM: encoding: [0xfe,0xb8]
+cm.push {ra, s0-s11}, -112
+
+# CHECK-ASM-AND-OBJ: cm.push {ra, s0-s11}, -112
+# CHECK-ASM: encoding: [0xfe,0xb8]
+cm.push {x1, x8-x9, x18-x27}, -112
Index: llvm/test/MC/RISCV/rv32zcmp-invalid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zcmp-invalid.s
@@ -0,0 +1,17 @@
+# RUN: not llvm-mc -triple=riscv32 -mattr=experimental-zcmp -riscv-no-aliases -show-encoding < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK-ERROR %s
+
+# CHECK-ERROR: error: invalid operand for instruction
+cm.mvsa01 a1, a2
+
+# CHECK-ERROR: error: 'rs1' and 'rs2' mast be different
+cm.mvsa01 s0, s0
+
+# CHECK-ERROR: error: invalid operand for instruction
+cm.mva01s a1, a2
+
+# CHECK-ERROR: error: invalid register list, {ra, s0-s10} or {x1, x8-x9, x18-x26} is not supported
+cm.popretz {ra, s0-s10}, 112
+
+# CHECK-ERROR: error: This stack adjustment is invalid for this instruction and register list, Please refer to Zc spec for a detailed range of stack adjustment
+cm.popretz {ra, s0-s1}, 112
Index: llvm/test/MC/RISCV/attribute-arch.s
===================================================================
--- llvm/test/MC/RISCV/attribute-arch.s
+++ llvm/test/MC/RISCV/attribute-arch.s
@@ -231,6 +231,9 @@
 .attribute arch, "rv32izcb1p0"
 # CHECK: attribute      5, "rv32i2p1_zca1p0_zcb1p0"
 
+.attribute arch, "rv32izcmp1p0"
+# CHECK: attribute      5, "rv32i2p1_zca1p0_zcmp1p0"
+
 .attribute arch, "rv64i_xsfvcp"
 # CHECK: attribute      5, "rv64i2p1_zicsr2p0_zve32x1p0_zvl32b1p0_xsfvcp1p0"
 
Index: llvm/lib/Target/RISCV/RISCVRegisterInfo.td
===================================================================
--- llvm/lib/Target/RISCV/RISCVRegisterInfo.td
+++ llvm/lib/Target/RISCV/RISCVRegisterInfo.td
@@ -175,6 +175,14 @@
   let RegInfos = XLenRI;
 }
 
+// Saved Registers from s0 to s7, for C.MVA01S07 instruction in Zcmp extension
+def SR07 : RegisterClass<"RISCV", [XLenVT], 32, (add
+    (sequence "X%u", 8, 9),
+    (sequence "X%u", 18, 23)
+  )> {
+  let RegInfos = XLenRI;
+}
+
 // Floating point registers
 let RegAltNameIndices = [ABIRegAltName] in {
   def F0_H  : RISCVReg16<0, "f0", ["ft0"]>, DwarfRegNum<[32]>;
Index: llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
===================================================================
--- llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
+++ llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 ///
 /// This file describes the RISC-V instructions from the 'Zc*' compressed
-/// instruction extensions, version 1.0.1.
+/// instruction extensions, version 1.0.3.
 /// This version is still experimental as the 'Zc*' extensions haven't been
 /// ratified yet.
 ///
@@ -32,6 +32,45 @@
   }];
 }
 
+def RlistAsmOperand : AsmOperandClass {
+  let Name = "Rlist";
+  let ParserMethod = "parseReglist";
+  let DiagnosticType = "InvalidRlist";
+}
+
+def SpimmAsmOperand : AsmOperandClass {
+  let Name = "Spimm";
+  let ParserMethod = "parseZcmpSpimm";
+  let DiagnosticType = "InvalidSpimm";
+}
+
+def rlist : Operand<OtherVT>, ImmLeaf<OtherVT, [{return isUInt<4>(Imm);}]> {
+   let ParserMatchClass = RlistAsmOperand;
+   let PrintMethod = "printRlist";
+   let DecoderMethod = "decodeZcmpRlist";
+   let EncoderMethod = "getRlistOpValue";
+   let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    if (!isUInt<4>(Imm)) return false;
+    // 0~3 Reserved for EABI
+    return (Imm>=4) && (Imm <=15);
+  }];
+ }
+
+def spimm : Operand<OtherVT>, ImmLeaf<OtherVT, [{return  isShiftedUInt<5, 4>(Imm);}]>{
+  let ParserMatchClass = SpimmAsmOperand;
+  let PrintMethod = "printSpimm";
+  let DecoderMethod = "decodeZcmpSpimm";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    return isShiftedUInt<5, 4>(Imm);
+  }];
+}
+
 //===----------------------------------------------------------------------===//
 // Instruction Class Templates
 //===----------------------------------------------------------------------===//
@@ -83,6 +122,13 @@
   let Constraints = "$rd = $rd_wb";
 }
 
+class RVInstZcCPPP<dag outs, dag ins, string opcodestr, string argstr>
+    : RVInst16<outs, ins, opcodestr, argstr, [], InstFormatOther> {
+
+  let Inst{1-0} = 0b10;
+  let Inst{15-13} = 0b101;
+}
+
 //===----------------------------------------------------------------------===//
 // Instructions
 //===----------------------------------------------------------------------===//
@@ -125,6 +171,62 @@
            Sched<[WriteSTH, ReadStoreData, ReadMemBase]>;
 }
 
+// Zcmp
+let Predicates = [HasStdExtZcmp], Defs = [X10, X11],
+    hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
+def CM_MVA01S : RVInst16CA<0b101011, 0b11, 0b10, (outs),
+                            (ins SR07:$rs1, SR07:$rs2), "cm.mva01s", "$rs1, $rs2">;
+
+def CM_MVSA01 : RVInst16CA<0b101011, 0b01, 0b10, (outs SR07:$rs1, SR07:$rs2),
+                            (ins), "cm.mvsa01", "$rs1, $rs2">;
+}
+
+let Predicates = [HasStdExtZcmp] in {
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in 
+def CM_PUSH : RVInstZcCPPP<(outs), (ins rlist:$rlist, spimm:$spimm), 
+    "cm.push", "{$rlist}, $spimm"> {
+  bits<4> rlist;
+  bits<16> spimm;
+
+  let Inst{12-8} = 0b11000;
+  let Inst{7-4} = rlist;
+  let Inst{3-2} = spimm{5-4};
+}
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in 
+def CM_POPRET : RVInstZcCPPP<(outs), (ins rlist:$rlist, spimm:$spimm), 
+    "cm.popret", "{$rlist}, $spimm"> {
+  bits<4> rlist;
+  bits<16> spimm;
+
+  let Inst{12-8} = 0b11110;
+  let Inst{7-4} = rlist;
+  let Inst{3-2} = spimm{5-4};
+}
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in 
+def CM_POPRETZ : RVInstZcCPPP<(outs), (ins rlist:$rlist, spimm:$spimm), 
+    "cm.popretz", "{$rlist}, $spimm"> {
+  bits<4> rlist;
+  bits<16> spimm;
+
+  let Inst{12-8} = 0b11100;
+  let Inst{7-4} = rlist;
+  let Inst{3-2} = spimm{5-4};
+}
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in 
+def CM_POP : RVInstZcCPPP<(outs), (ins rlist:$rlist, spimm:$spimm), 
+    "cm.pop", "{$rlist}, $spimm"> {
+  bits<4> rlist;
+  bits<16> spimm;
+
+  let Inst{12-8} = 0b11010;
+  let Inst{7-4} = rlist;
+  let Inst{3-2} = spimm{5-4};
+}
+}
+
 let Predicates = [HasStdExtZcb, HasStdExtMOrZmmul] in{
 def : CompressPat<(MUL GPRC:$rs1, GPRC:$rs1, GPRC:$rs2),
                   (C_MUL GPRC:$rs1, GPRC:$rs2)>;
Index: llvm/lib/Target/RISCV/RISCVFeatures.td
===================================================================
--- llvm/lib/Target/RISCV/RISCVFeatures.td
+++ llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -351,6 +351,14 @@
                                    "'C' (Compressed Instructions) or "
                                    "'Zcf' (Compressed Single-Precision Floating-Point Instructions)">;
 
+def FeatureStdExtZcmp
+    : SubtargetFeature<"experimental-zcmp", "HasStdExtZcmp", "true",
+                       "'Zcmp' (sequenced instuctions for code-size reduction)", 
+                       [FeatureStdExtZca]>;
+def HasStdExtZcmp : Predicate<"Subtarget->hasStdExtZcmp() && !Subtarget->hasStdExtC()">,
+                               AssemblerPredicate<(all_of FeatureStdExtZcmp, (not FeatureStdExtC)),
+                               "'Zcmp' (sequenced instuctions for code-size reduction)">;
+
 def FeatureNoRVCHints
     : SubtargetFeature<"no-rvc-hints", "EnableRVCHintInstrs", "false",
                        "Disable RVC Hint Instructions.">;
Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
===================================================================
--- llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -88,6 +88,10 @@
   unsigned getVMaskReg(const MCInst &MI, unsigned OpNo,
                        SmallVectorImpl<MCFixup> &Fixups,
                        const MCSubtargetInfo &STI) const;
+
+  unsigned getRlistOpValue(const MCInst &MI, unsigned OpNo,
+                           SmallVectorImpl<MCFixup> &Fixups,
+                           const MCSubtargetInfo &STI) const;
 };
 } // end anonymous namespace
 
@@ -483,4 +487,14 @@
   }
 }
 
+unsigned RISCVMCCodeEmitter::getRlistOpValue(const MCInst &MI, unsigned OpNo,
+                                             SmallVectorImpl<MCFixup> &Fixups,
+                                             const MCSubtargetInfo &STI) const {
+  MCOperand MO = MI.getOperand(OpNo);
+  assert(MO.isImm() && "Rlist operand must be immidiate");
+  auto Imm = MO.getImm();
+  assert(Imm >= 4 && "EABI is currently not implemented");
+  return Imm;
+}
+
 #include "RISCVGenMCCodeEmitter.inc"
Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
===================================================================
--- llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
+++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
@@ -48,6 +48,10 @@
                    raw_ostream &O);
   void printVMaskReg(const MCInst *MI, unsigned OpNo,
                      const MCSubtargetInfo &STI, raw_ostream &O);
+  void printRlist(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
+                  raw_ostream &O);
+  void printSpimm(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
+                  raw_ostream &O);
 
   // Autogenerated by tblgen.
   std::pair<const char *, uint64_t> getMnemonic(const MCInst *MI) override;
Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
===================================================================
--- llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
+++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
@@ -202,6 +202,31 @@
   RISCVVType::printVType(Imm, O);
 }
 
+void RISCVInstPrinter::printRlist(const MCInst *MI, unsigned OpNo,
+                                  const MCSubtargetInfo &STI, raw_ostream &O) {
+  unsigned Imm = MI->getOperand(OpNo).getImm();
+  RISCVZC::printRlist(Imm, O);
+}
+
+void RISCVInstPrinter::printSpimm(const MCInst *MI, unsigned OpNo,
+                                  const MCSubtargetInfo &STI, raw_ostream &O) {
+  int64_t Imm = MI->getOperand(OpNo).getImm();
+  unsigned Opcode = MI->getOpcode();
+  bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit);
+  bool IsEABI = STI.hasFeature(RISCV::FeatureRVE);
+  int64_t Spimm = 0;
+  auto RlistVal = MI->getOperand(0).getImm();
+  assert(RlistVal != 16 && "Incorrect rlist.");
+  auto Base = RISCVZC::getStackAdjBase(RlistVal, IsRV64, IsEABI);
+  Spimm = Imm + Base;
+  assert((Spimm >= Base && Spimm <= Base + 48) && "Incorrect spimm");
+  if (Opcode == RISCV::CM_PUSH) {
+    Spimm *= -1;
+  }
+
+  RISCVZC::printSpimm(Spimm, O);
+}
+
 void RISCVInstPrinter::printVMaskReg(const MCInst *MI, unsigned OpNo,
                                      const MCSubtargetInfo &STI,
                                      raw_ostream &O) {
Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
===================================================================
--- llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -492,6 +492,124 @@
 bool uncompress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI);
 } // namespace RISCVRVC
 
+namespace RISCVZC {
+enum RLISTENCODE {
+  RA = 4,
+  RA_S0,
+  RA_S0_S1,
+  RA_S0_S2,
+  RA_S0_S3,
+  RA_S0_S4,
+  RA_S0_S5,
+  RA_S0_S6,
+  RA_S0_S7,
+  RA_S0_S8,
+  RA_S0_S9,
+  // note - to include s10, s11 must also be included
+  RA_S0_S11,
+  INVALID_RLIST,
+};
+
+inline unsigned encodeRlist(MCRegister EndReg, bool IsRV32E = false) {
+  assert((!IsRV32E || EndReg <= RISCV::X9) && "Invalid Rlist for RV32E");
+  switch (EndReg) {
+  case RISCV::X1:
+    return RLISTENCODE::RA;
+  case RISCV::X8:
+    return RLISTENCODE::RA_S0;
+  case RISCV::X9:
+    return RLISTENCODE::RA_S0_S1;
+  case RISCV::X18:
+    return RLISTENCODE::RA_S0_S2;
+  case RISCV::X19:
+    return RLISTENCODE::RA_S0_S3;
+  case RISCV::X20:
+    return RLISTENCODE::RA_S0_S4;
+  case RISCV::X21:
+    return RLISTENCODE::RA_S0_S5;
+  case RISCV::X22:
+    return RLISTENCODE::RA_S0_S6;
+  case RISCV::X23:
+    return RLISTENCODE::RA_S0_S7;
+  case RISCV::X24:
+    return RLISTENCODE::RA_S0_S8;
+  case RISCV::X25:
+    return RLISTENCODE::RA_S0_S9;
+  case RISCV::X26:
+    return RLISTENCODE::INVALID_RLIST;
+  case RISCV::X27:
+    return RLISTENCODE::RA_S0_S11;
+  default:
+    llvm_unreachable("Undefined input.");
+  }
+}
+
+inline static unsigned getStackAdjBase(unsigned RlistVal, bool IsRV64,
+                                       bool IsEABI) {
+  if (RlistVal == RLISTENCODE::INVALID_RLIST)
+    assert(0 && "{ra, s0-s10} is not supported, s11 must be included.");
+  if (IsEABI)
+    return 16;
+  if (!IsRV64) {
+    switch (RlistVal) {
+    case RLISTENCODE::RA:
+    case RLISTENCODE::RA_S0:
+    case RLISTENCODE::RA_S0_S1:
+    case RLISTENCODE::RA_S0_S2:
+      return 16;
+    case RLISTENCODE::RA_S0_S3:
+    case RLISTENCODE::RA_S0_S4:
+    case RLISTENCODE::RA_S0_S5:
+    case RLISTENCODE::RA_S0_S6:
+      return 32;
+    case RLISTENCODE::RA_S0_S7:
+    case RLISTENCODE::RA_S0_S8:
+    case RLISTENCODE::RA_S0_S9:
+      return 48;
+    case RLISTENCODE::RA_S0_S11:
+      return 64;
+    }
+  } else {
+    switch (RlistVal) {
+    case RLISTENCODE::RA:
+    case RLISTENCODE::RA_S0:
+      return 16;
+    case RLISTENCODE::RA_S0_S1:
+    case RLISTENCODE::RA_S0_S2:
+      return 32;
+    case RLISTENCODE::RA_S0_S3:
+    case RLISTENCODE::RA_S0_S4:
+      return 48;
+    case RLISTENCODE::RA_S0_S5:
+    case RLISTENCODE::RA_S0_S6:
+      return 64;
+    case RLISTENCODE::RA_S0_S7:
+    case RLISTENCODE::RA_S0_S8:
+      return 80;
+    case RLISTENCODE::RA_S0_S9:
+      return 96;
+    case RLISTENCODE::RA_S0_S11:
+      return 112;
+    }
+  }
+  llvm_unreachable("Unexpected RlistVal");
+}
+
+inline static bool getSpimm(unsigned RlistVal, unsigned &SpimmVal,
+                            int64_t StackAdjustment, bool IsRV64, bool IsEABI) {
+  if (RlistVal == RLISTENCODE::INVALID_RLIST)
+    return false;
+  unsigned stackAdj = getStackAdjBase(RlistVal, IsRV64, IsEABI);
+  SpimmVal = (StackAdjustment - stackAdj) / 16;
+  if (SpimmVal > 3)
+    return false;
+  return true;
+}
+
+void printRlist(unsigned SlistEncode, raw_ostream &OS);
+void printSpimm(int64_t Spimm, raw_ostream &OS);
+} // namespace RISCVZC
+
 } // namespace llvm
 
 #endif
Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
===================================================================
--- llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
+++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
@@ -295,4 +295,18 @@
   return bit_cast<float>(I);
 }
 
+void RISCVZC::printRlist(unsigned SlistEncode, raw_ostream &OS) {
+  OS << "{ra";
+  if (SlistEncode > 4) {
+    OS << ", s0";
+    if (SlistEncode == 15)
+      OS << "-s11";
+    else if (SlistEncode > 5 && SlistEncode <= 14)
+      OS << "-s" << (SlistEncode - 5);
+  }
+  OS << "}";
+}
+
+void RISCVZC::printSpimm(int64_t Spimm, raw_ostream &OS) { OS << Spimm; }
+
 } // namespace llvm
Index: llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
===================================================================
--- llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -168,6 +168,17 @@
   return MCDisassembler::Success;
 }
 
+static DecodeStatus DecodeSR07RegisterClass(MCInst &Inst, uint64_t RegNo,
+                                            uint64_t Address,
+                                            const void *Decoder) {
+  if (RegNo >= 8)
+    return MCDisassembler::Fail;
+
+  MCRegister Reg = (RegNo < 2) ? (RegNo + RISCV::X8) : (RegNo - 2 + RISCV::X18);
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus DecodeVRRegisterClass(MCInst &Inst, uint32_t RegNo,
                                           uint64_t Address,
                                           const MCDisassembler *Decoder) {
@@ -371,6 +382,12 @@
                                         uint64_t Address,
                                         const MCDisassembler *Decoder);
 
+static DecodeStatus decodeZcmpRlist(MCInst &Inst, unsigned Imm,
+                                    uint64_t Address, const void *Decoder);
+
+static DecodeStatus decodeZcmpSpimm(MCInst &Inst, unsigned Imm,
+                                    uint64_t Address, const void *Decoder);
+
 #include "RISCVGenDisassemblerTables.inc"
 
 static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst &Inst, uint32_t Insn,
@@ -457,6 +474,22 @@
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeZcmpRlist(MCInst &Inst, unsigned Imm,
+                                    uint64_t Address, const void *Decoder) {
+  if (Imm <= 3)
+    return MCDisassembler::Fail;
+  Inst.addOperand(MCOperand::createImm(Imm));
+  return MCDisassembler::Success;
+}
+
+// spimm is based on rlist now.
+static DecodeStatus decodeZcmpSpimm(MCInst &Inst, unsigned Imm,
+                                    uint64_t Address, const void *Decoder) {
+  // TODO: check if spimm matches rlist
+  Inst.addOperand(MCOperand::createImm(Imm));
+  return MCDisassembler::Success;
+}
+
 DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
                                                ArrayRef<uint8_t> Bytes,
                                                uint64_t Address,
Index: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
===================================================================
--- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -180,6 +180,9 @@
   OperandMatchResultTy parseGPRAsFPR(OperandVector &Operands);
   OperandMatchResultTy parseFRMArg(OperandVector &Operands);
   OperandMatchResultTy parseFenceArg(OperandVector &Operands);
+  OperandMatchResultTy parseReglist(OperandVector &Operands);
+  OperandMatchResultTy parseRetval(OperandVector &Operands);
+  OperandMatchResultTy parseZcmpSpimm(OperandVector &Operands);
 
   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
 
@@ -290,6 +293,8 @@
     VType,
     FRM,
     Fence,
+    Rlist,
+    Spimm,
   } Kind;
 
   struct RegOp {
@@ -326,6 +331,14 @@
     unsigned Val;
   };
 
+  struct RlistOp {
+    unsigned Val;
+  };
+
+  struct SpimmOp {
+    unsigned Val;
+  };
+
   SMLoc StartLoc, EndLoc;
   union {
     StringRef Tok;
@@ -336,6 +349,8 @@
     struct VTypeOp VType;
     struct FRMOp FRM;
     struct FenceOp Fence;
+    struct RlistOp Rlist;
+    struct SpimmOp Spimm;
   };
 
   RISCVOperand(KindTy K) : Kind(K) {}
@@ -370,6 +385,12 @@
     case KindTy::Fence:
       Fence = o.Fence;
       break;
+    case KindTy::Rlist:
+      Rlist = o.Rlist;
+      break;
+    case KindTy::Spimm:
+      Spimm = o.Spimm;
+      break;
     }
   }
 
@@ -394,6 +415,8 @@
   bool isImm() const override { return Kind == KindTy::Immediate; }
   bool isMem() const override { return false; }
   bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
+  bool isRlist() const { return Kind == KindTy::Rlist; }
+  bool isSpimm() const { return Kind == KindTy::Spimm; }
 
   bool isGPR() const {
     return Kind == KindTy::Register &&
@@ -936,6 +959,16 @@
       OS << getFence();
       OS << '>';
       break;
+    case KindTy::Rlist:
+      OS << "<rlist: ";
+      RISCVZC::printRlist(Rlist.Val, OS);
+      OS << '>';
+      break;
+    case KindTy::Spimm:
+      OS << "<Spimm: ";
+      RISCVZC::printSpimm(Spimm.Val, OS);
+      OS << '>';
+      break;
     }
   }
 
@@ -1011,6 +1044,22 @@
     return Op;
   }
 
+  static std::unique_ptr<RISCVOperand> createRlist(unsigned RlistEncode,
+                                                   SMLoc S, bool IsRV64) {
+    auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);
+    Op->Rlist.Val = RlistEncode;
+    Op->StartLoc = S;
+    return Op;
+  }
+
+  static std::unique_ptr<RISCVOperand> createSpimm(unsigned Spimm, SMLoc S,
+                                                   bool IsRV64) {
+    auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);
+    Op->Spimm.Val = Spimm;
+    Op->StartLoc = S;
+    return Op;
+  }
+
   static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
     assert(Expr && "Expr shouldn't be null!");
     int64_t Imm = 0;
@@ -1074,6 +1123,16 @@
     Inst.addOperand(MCOperand::createImm(Imm));
   }
 
+  void addRlistOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::createImm(Rlist.Val));
+  }
+
+  void addSpimmOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::createImm(Spimm.Val));
+  }
+
   void addFRMArgOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     Inst.addOperand(MCOperand::createImm(getFRM()));
@@ -1401,6 +1460,20 @@
                                       (1 << 4),
                                       "immediate must be in the range");
   }
+  case Match_InvalidRlist: {
+    SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(
+        ErrorLoc,
+        "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
+  }
+  case Match_InvalidSpimm: {
+    SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(
+        ErrorLoc,
+        "This stack adjustment is invalid for this instruction and register "
+        "list, "
+        "Please refer to Zc spec for a detailed range of stack adjustment");
+  }
   case Match_InvalidRnumArg: {
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
   }
@@ -2242,6 +2315,148 @@
   return MatchOperand_Success;
 }
 
+OperandMatchResultTy RISCVAsmParser::parseReglist(OperandVector &Operands) {
+  // Rlist: {ra [, s0[-sN]]}
+  // XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
+  SMLoc S = getLoc();
+  if (getLexer().isNot(AsmToken::LCurly)) {
+    Error(getLoc(), "Rlist must start with '{'");
+    return MatchOperand_ParseFail;
+  }
+  getLexer().Lex(); // eat '{'
+  bool IsEABI = isRVE();
+
+  MCRegister RegStart = RISCV::NoRegister;
+  MCRegister RegEnd = RISCV::NoRegister;
+  StringRef RegName = getLexer().getTok().getIdentifier();
+  matchRegisterNameHelper(IsEABI, RegStart, RegName);
+  if (RegStart != RISCV::X1) {
+    Error(getLoc(), "Register list must start from 'ra' or 'x1'");
+    return MatchOperand_ParseFail;
+  }
+  getLexer().Lex();
+
+  // parse case like ,s0
+  if (getLexer().is(AsmToken::Comma)) {
+    getLexer().Lex();
+    if (getLexer().isNot(AsmToken::Identifier)) {
+      Error(getLoc(), "Invalid register");
+      return MatchOperand_ParseFail;
+    }
+    StringRef RegName = getLexer().getTok().getIdentifier();
+    if (matchRegisterNameHelper(IsEABI, RegStart, RegName)) {
+      Error(getLoc(), "Invalid register");
+      return MatchOperand_ParseFail;
+    }
+    if (RegStart != RISCV::X8) {
+      Error(getLoc(), "Continuous registers list must start from 's0' or 'x8'");
+      return MatchOperand_ParseFail;
+    }
+    getLexer().Lex(); // eat reg
+  }
+
+  // parse case like -s1
+  if (getLexer().is(AsmToken::Minus)) {
+    getLexer().Lex();
+    StringRef EndName = getLexer().getTok().getIdentifier();
+    // FIXME: the register mapping and checks of EABI is wrong
+    if (matchRegisterNameHelper(IsEABI, RegEnd, EndName)) {
+      Error(getLoc(), "Invalid register");
+      return MatchOperand_ParseFail;
+    }
+    if (IsEABI && RegEnd != RISCV::X9) {
+      Error(getLoc(),
+            "Contiguous registers list of EABI only can be 's0-s1' or "
+            "'x8-x9' pair");
+      return MatchOperand_ParseFail;
+    }
+    getLexer().Lex();
+  }
+
+  if (!IsEABI) {
+    // parse extra part like ', x18[-x20]' for XRegList
+    if (getLexer().is(AsmToken::Comma)) {
+      if (RegEnd != RISCV::X9) {
+        Error(getLoc(),
+              "First contiguous registers pair of XRlist must be 'x8-x9'");
+        return MatchOperand_ParseFail;
+      }
+
+      // parse ', x18' for extra part
+      getLexer().Lex();
+      if (getLexer().isNot(AsmToken::Identifier)) {
+        Error(getLoc(), "Invalid register");
+        return MatchOperand_ParseFail;
+      }
+      StringRef EndName = getLexer().getTok().getIdentifier();
+      if (MatchRegisterName(EndName) != RISCV::X18) {
+        Error(
+            getLoc(),
+            "Second contiguous registers pair of XRlist must start from 'x18'");
+        return MatchOperand_ParseFail;
+      }
+      getLexer().Lex();
+
+      // parse '-x20' for extra part
+      if (getLexer().is(AsmToken::Minus)) {
+        getLexer().Lex();
+        if (getLexer().isNot(AsmToken::Identifier)) {
+          Error(getLoc(), "Invalid register");
+          return MatchOperand_ParseFail;
+        }
+        EndName = getLexer().getTok().getIdentifier();
+        if (MatchRegisterName(EndName) == RISCV::NoRegister) {
+          Error(getLoc(), "Invalid register");
+          return MatchOperand_ParseFail;
+        }
+        getLexer().Lex();
+      }
+      RegEnd = MatchRegisterName(EndName);
+    }
+  }
+
+  if (RegEnd == RISCV::X26) {
+    Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
+                    "x18-x26} is not supported");
+    return MatchOperand_ParseFail;
+  }
+
+  if (getLexer().isNot(AsmToken::RCurly)) {
+    Error(getLoc(), "Rlist must end with '}'");
+    return MatchOperand_ParseFail;
+  }
+  getLexer().Lex(); // eat '}'
+
+  if (RegEnd == RISCV::NoRegister)
+    RegEnd = RegStart;
+
+  auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI);
+  if (Encode == 16) {
+    Error(S, "invalid Register list");
+    return MatchOperand_ParseFail;
+  }
+  Operands.push_back(RISCVOperand::createRlist(Encode, S, IsEABI));
+
+  return MatchOperand_Success;
+}
+
+OperandMatchResultTy RISCVAsmParser::parseZcmpSpimm(OperandVector &Operands) {
+  if (getLexer().is(AsmToken::Minus))
+    getLexer().Lex();
+
+  SMLoc S = getLoc();
+  int64_t StackAdjustment = getLexer().getTok().getIntVal();
+  unsigned Spimm = 0;
+  unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val;
+
+  bool IsEABI = isRVE();
+  if (!RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64(), IsEABI))
+    return MatchOperand_NoMatch;
+  Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S, isRV64()));
+  getLexer().Lex();
+  return MatchOperand_Success;
+}
+
 /// Looks at a token type and creates the relevant operand from this
 /// information, adding to Operands. If operand was parsed, returns false, else
 /// true.
@@ -2927,6 +3142,15 @@
     }
   }
 
+  if (Opcode == RISCV::CM_MVSA01) {
+    unsigned Rd1 = Inst.getOperand(0).getReg();
+    unsigned Rd2 = Inst.getOperand(1).getReg();
+    if (Rd1 == Rd2) {
+      SMLoc Loc = Operands[1]->getStartLoc();
+      return Error(Loc, "'rs1' and 'rs2' mast be different.");
+    }
+  }
+
   bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
                            Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
   bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
@@ -3163,7 +3387,16 @@
                               .addImm(Imm - 1)
                               .addOperand(Inst.getOperand(3)));
     }
-
+    return false;
+  }
+  case RISCV::CM_POPRET:
+  case RISCV::CM_POPRETZ:
+  case RISCV::CM_POP:
+  case RISCV::CM_PUSH: {
+    unsigned Opc = Inst.getOpcode();
+    emitToStreamer(Out, MCInstBuilder(Opc)
+                            .addOperand(Inst.getOperand(0))
+                            .addOperand(Inst.getOperand(1)));
     return false;
   }
   }
Index: llvm/lib/Support/RISCVISAInfo.cpp
===================================================================
--- llvm/lib/Support/RISCVISAInfo.cpp
+++ llvm/lib/Support/RISCVISAInfo.cpp
@@ -139,6 +139,7 @@
     {"zcb", RISCVExtensionVersion{1, 0}},
     {"zcd", RISCVExtensionVersion{1, 0}},
     {"zcf", RISCVExtensionVersion{1, 0}},
+    {"zcmp", RISCVExtensionVersion{1, 0}},
     {"zfa", RISCVExtensionVersion{0, 2}},
     {"zicond", RISCVExtensionVersion{1, 0}},
     {"zvfh", RISCVExtensionVersion{0, 1}},
@@ -919,6 +920,7 @@
 static const char *ImpliedExtsXTHeadVdot[] = {"v"};
 static const char *ImpliedExtsXsfvcp[] = {"zve32x"};
 static const char *ImpliedExtsZcb[] = {"zca"};
+static const char *ImpliedExtsZcmp[] = {"zca"};
 static const char *ImpliedExtsZdinx[] = {"zfinx"};
 static const char *ImpliedExtsZfa[] = {"f"};
 static const char *ImpliedExtsZfh[] = {"f"};
@@ -974,6 +976,7 @@
     {{"xsfvcp"}, {ImpliedExtsXsfvcp}},
     {{"xtheadvdot"}, {ImpliedExtsXTHeadVdot}},
     {{"zcb"}, {ImpliedExtsZcb}},
+    {{"zcmp"}, {ImpliedExtsZcmp}},
     {{"zdinx"}, {ImpliedExtsZdinx}},
     {{"zfa"}, {ImpliedExtsZfa}},
     {{"zfh"}, {ImpliedExtsZfh}},
Index: llvm/docs/RISCVUsage.rst
===================================================================
--- llvm/docs/RISCVUsage.rst
+++ llvm/docs/RISCVUsage.rst
@@ -187,6 +187,9 @@
 ``experimental-zcf``
   LLVM implements the `1.0.1 draft specification <https://github.com/riscv/riscv-code-size-reduction/releases/tag/v1.0.1>`__.
 
+``experimental-zcmp``
+  LLVM implements the `1.0.1 draft specification <https://github.com/riscv/riscv-code-size-reduction/releases/tag/v1.0.1>`__.
+
 ``experimental-zfa``
   LLVM implements the `0.2 draft specification <https://github.com/riscv/riscv-isa-manual/releases/download/draft-20230131-c0b298a/zfa-20230414.pdf>`__.
 
Index: clang/test/Preprocessor/riscv-target-features.c
===================================================================
--- clang/test/Preprocessor/riscv-target-features.c
+++ clang/test/Preprocessor/riscv-target-features.c
@@ -48,6 +48,7 @@
 // CHECK-NOT: __riscv_zcb {{.*$}}
 // CHECK-NOT: __riscv_zcd {{.*$}}
 // CHECK-NOT: __riscv_zcf {{.*$}}
+// CHECK-NOT: __riscv_zcmp
 // CHECK-NOT: __riscv_h {{.*$}}
 // CHECK-NOT: __riscv_zvbb {{.*$}}
 // CHECK-NOT: __riscv_zvbc {{.*$}}
@@ -509,6 +510,13 @@
 // RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCF-EXT %s
 // CHECK-ZCF-EXT: __riscv_zcf 1000000{{$}}
 
+// RUN: %clang -target riscv32 -march=rv32izcmp1p0 -menable-experimental-extensions \
+// RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCMP-EXT %s
+// RUN: %clang -target riscv64 -march=rv64izcmp1p0 -menable-experimental-extensions \
+// RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCMP-EXT %s
+// CHECK-ZCMP-EXT: __riscv_zca 1000000{{$}}
+// CHECK-ZCMP-EXT: __riscv_zcmp 1000000{{$}}
+
 // RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32izicsr2p0 -x c -E -dM %s \
 // RUN: -o - | FileCheck --check-prefix=CHECK-ZICSR-EXT %s
 // RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64izicsr2p0 -x c -E -dM %s \
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to