VincentWu updated this revision to Diff 459617.
VincentWu edited the summary of this revision.
VincentWu added a reviewer: asb.
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/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/RISCV.td
  llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
  llvm/lib/Target/RISCV/RISCVInstrInfo.h
  llvm/lib/Target/RISCV/RISCVInstrInfo.td
  llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
  llvm/lib/Target/RISCV/RISCVRegisterInfo.td
  llvm/lib/Target/RISCV/RISCVSchedRocket.td
  llvm/lib/Target/RISCV/RISCVSchedSiFive7.td
  llvm/lib/Target/RISCV/RISCVSubtarget.h
  llvm/test/MC/RISCV/attribute-arch.s
  llvm/test/MC/RISCV/rv32zcb-invalid.s
  llvm/test/MC/RISCV/rv32zcb-valid.s
  llvm/test/MC/RISCV/rv32zcmp-Invalid.s
  llvm/test/MC/RISCV/rv32zcmp-valid.s
  llvm/test/MC/RISCV/rv64zcb-invalid.s
  llvm/test/MC/RISCV/rv64zcb-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,14 @@
+# 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: invalid operand for instruction
+cm.mva01s a1, a2
+
+# CHECK-ERROR: error: invalid register list, {ra, s0-s10} 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/rv64zcb-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64zcb-valid.s
@@ -0,0 +1,74 @@
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+m,+zbb,+zba,+experimental-zcb -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+m,+zbb,+zba,+experimental-zcb < %s \
+# RUN:     | llvm-objdump --mattr=+m,+zbb,+zba,experimental-zcb -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ %s
+#
+# RUN: not llvm-mc -triple riscv64 \
+# RUN:     -riscv-no-aliases -show-encoding < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK-NO-EXT %s
+# RUN: not llvm-mc -triple riscv32 -mattr=+m,+zbb,+zba,+experimental-zcb \
+# RUN:     -riscv-no-aliases -show-encoding < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK-NO-RV64 %s
+
+
+# CHECK-ASM-AND-OBJ: c.zext.b s0
+# CHECK-ASM: encoding: [0x61,0x9c]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.zext.b s0
+
+# CHECK-ASM-AND-OBJ: c.sext.b s0
+# CHECK-ASM: encoding: [0x65,0x9c]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zbb' (Basic Bit-Manipulation), 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.sext.b s0
+
+# CHECK-ASM-AND-OBJ: c.zext.h s0
+# CHECK-ASM: encoding: [0x69,0x9c]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zbb' (Basic Bit-Manipulation), 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.zext.h s0
+
+# CHECK-ASM-AND-OBJ: c.sext.h s0
+# CHECK-ASM: encoding: [0x6d,0x9c]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zbb' (Basic Bit-Manipulation), 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.sext.h s0
+
+# CHECK-ASM-AND-OBJ: c.zext.w s0
+# CHECK-ASM: encoding: [0x71,0x9c]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zba' (Address Generation Instructions), 'Zcb' (Shortened format for basic bit manipulation instructions) 
+# CHECK-NO-RV64: error: instruction requires the following: RV64I Base Instruction Set
+c.zext.w s0
+
+# CHECK-ASM-AND-OBJ: c.not s0
+# CHECK-ASM: encoding: [0x75,0x9c]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.not s0
+
+# CHECK-ASM-AND-OBJ: c.mul s0, s1
+# CHECK-ASM: encoding: [0x45,0x9c]
+# CHECK-NO-EXT: error: instruction requires the following: 'M' (Integer Multiplication and Division) or 'Zmmul' (Integer Multiplication), 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.mul s0, s1
+
+# CHECK-ASM-AND-OBJ: c.lbu a5, 2(a4)
+# CHECK-ASM: encoding: [0x3c,0x83]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.lbu a5, 2(a4)
+
+# CHECK-ASM-AND-OBJ: c.lhu a5, 2(a4)
+# CHECK-ASM: encoding: [0x3c,0x87]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.lhu a5, 2(a4)
+
+# CHECK-ASM-AND-OBJ: c.lh a5, 2(a4)
+# CHECK-ASM: encoding: [0x7c,0x87]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.lh a5, 2(a4)
+
+# CHECK-ASM-AND-OBJ: c.sb a5, 2(a4)
+# CHECK-ASM: encoding: [0x3c,0x8b]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.sb a5, 2(a4)
+
+# CHECK-ASM-AND-OBJ: c.sh a5, 2(a4)
+# CHECK-ASM: encoding: [0x7c,0x8f]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.sh a5, 2(a4)
Index: llvm/test/MC/RISCV/rv64zcb-invalid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv64zcb-invalid.s
@@ -0,0 +1,17 @@
+# RUN: not llvm-mc -triple=riscv64 -mattr=experimental-zcb -riscv-no-aliases -show-encoding < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK-ERROR %s
+
+# CHECK-ERROR: error: immediate must be an integer in the range [0, 3]
+c.lbu a5, 10(a4)
+
+# CHECK-ERROR: error: immediate must be one of [0, 2]
+c.lhu a5, 10(a4)
+
+# CHECK-ERROR: error: immediate must be one of [0, 2]
+c.lh a5, 10(a4)
+
+# CHECK-ERROR: error: immediate must be an integer in the range [0, 3]
+c.sb a5, 10(a4)
+
+# CHECK-ERROR: error: immediate must be one of [0, 2]
+c.sh a5, 10(a4)
Index: llvm/test/MC/RISCV/rv32zcmp-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zcmp-valid.s
@@ -0,0 +1,285 @@
+# 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.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,14 @@
+# 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: invalid operand for instruction
+cm.mva01s a1, a2
+
+# CHECK-ERROR: error: invalid register list, {ra, s0-s10} 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/rv32zcb-valid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zcb-valid.s
@@ -0,0 +1,64 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+m,+zbb,+experimental-zcb -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+m,+zbb,+experimental-zcb < %s \
+# RUN:     | llvm-objdump --mattr=+m,+zbb,+experimental-zcb -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ %s
+#
+# RUN: not llvm-mc -triple riscv64 \
+# RUN:     -riscv-no-aliases -show-encoding < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK-NO-EXT %s
+
+# CHECK-ASM-AND-OBJ: c.zext.b s0
+# CHECK-ASM: encoding: [0x61,0x9c]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.zext.b s0
+
+# CHECK-ASM-AND-OBJ: c.sext.b s0
+# CHECK-ASM: encoding: [0x65,0x9c]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zbb' (Basic Bit-Manipulation), 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.sext.b s0
+
+# CHECK-ASM-AND-OBJ: c.zext.h s0
+# CHECK-ASM: encoding: [0x69,0x9c]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zbb' (Basic Bit-Manipulation), 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.zext.h s0
+
+# CHECK-ASM-AND-OBJ: c.sext.h s0
+# CHECK-ASM: encoding: [0x6d,0x9c]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zbb' (Basic Bit-Manipulation), 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.sext.h s0
+
+# CHECK-ASM-AND-OBJ: c.not s0
+# CHECK-ASM: encoding: [0x75,0x9c]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.not s0
+
+# CHECK-ASM-AND-OBJ: c.mul s0, s1
+# CHECK-ASM: encoding: [0x45,0x9c]
+# CHECK-NO-EXT: error: instruction requires the following: 'M' (Integer Multiplication and Division) or 'Zmmul' (Integer Multiplication), 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.mul s0, s1
+
+# CHECK-ASM-AND-OBJ: c.lbu a5, 2(a4)
+# CHECK-ASM: encoding: [0x3c,0x83]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.lbu a5, 2(a4)
+
+# CHECK-ASM-AND-OBJ: c.lhu a5, 2(a4)
+# CHECK-ASM: encoding: [0x3c,0x87]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.lhu a5, 2(a4)
+
+# CHECK-ASM-AND-OBJ: c.lh a5, 2(a4)
+# CHECK-ASM: encoding: [0x7c,0x87]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.lh a5, 2(a4)
+
+# CHECK-ASM-AND-OBJ: c.sb a5, 2(a4)
+# CHECK-ASM: encoding: [0x3c,0x8b]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.sb a5, 2(a4)
+
+# CHECK-ASM-AND-OBJ: c.sh a5, 2(a4)
+# CHECK-ASM: encoding: [0x7c,0x8f]
+# CHECK-NO-EXT: error: instruction requires the following: 'Zcb' (Shortened format for basic bit manipulation instructions)
+c.sh a5, 2(a4)
Index: llvm/test/MC/RISCV/rv32zcb-invalid.s
===================================================================
--- /dev/null
+++ llvm/test/MC/RISCV/rv32zcb-invalid.s
@@ -0,0 +1,17 @@
+# RUN: not llvm-mc -triple=riscv32 -mattr=experimental-zcb -riscv-no-aliases -show-encoding %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK-ERROR %s
+
+# CHECK-ERROR: error: immediate must be an integer in the range [0, 3]
+c.lbu a5, 10(a4)
+
+# CHECK-ERROR: error: immediate must be one of [0, 2]
+c.lhu a5, 10(a4)
+
+# CHECK-ERROR: error: immediate must be one of [0, 2]
+c.lh a5, 10(a4)
+
+# CHECK-ERROR: error: immediate must be an integer in the range [0, 3]
+c.sb a5, 10(a4)
+
+# CHECK-ERROR: error: immediate must be one of [0, 2]
+c.sh a5, 10(a4)
Index: llvm/test/MC/RISCV/attribute-arch.s
===================================================================
--- llvm/test/MC/RISCV/attribute-arch.s
+++ llvm/test/MC/RISCV/attribute-arch.s
@@ -185,8 +185,20 @@
 .attribute arch, "rv32i_zk1p0"
 # CHECK: attribute      5, "rv32i2p0_zbkb1p0_zbkc1p0_zbkx1p0_zk1p0_zkn1p0_zknd1p0_zkne1p0_zknh1p0_zkr1p0_zkt1p0"
 
+.attribute arch, "rv32izihintntl0p2"
+# CHECK: attribute      5, "rv32i2p0_zihintntl0p2"
+
+.attribute arch, "rv32iczihintntl0p2"
+# CHECK: attribute      5, "rv32i2p0_c2p0_zihintntl0p2"
+
 .attribute arch, "rv32if_zkt1p0_zve32f1p0_zve32x1p0_zvl32b1p0"
 # CHECK: attribute      5, "rv32i2p0_f2p0_zkt1p0_zve32f1p0_zve32x1p0_zvl32b1p0"
 
 .attribute arch, "rv32izca0p70"
 # CHECK: attribute      5, "rv32i2p0_zca0p70"
+
+.attribute arch, "rv32izcb0p70"
+# CHECK: attribute      5, "rv32i2p0_zcb0p70"
+
+.attribute arch, "rv32izcmp0p70"
+# CHECK: attribute      5, "rv32i2p0_zca0p70_zcmp0p70"
Index: llvm/lib/Target/RISCV/RISCVSubtarget.h
===================================================================
--- llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -62,6 +62,8 @@
   bool HasStdExtZbs = false;
   bool HasStdExtZbt = false;
   bool HasStdExtZca = false;
+  bool HasStdExtZcb = false;
+  bool HasStdExtZcmp = false;
   bool HasStdExtV = false;
   bool HasStdExtZve32x = false;
   bool HasStdExtZve32f = false;
@@ -171,6 +173,8 @@
   bool hasStdExtZbs() const { return HasStdExtZbs; }
   bool hasStdExtZbt() const { return HasStdExtZbt; }
   bool hasStdExtZca() const { return HasStdExtZca; }
+  bool hasStdExtZcb() const { return HasStdExtZcb; }
+  bool hasStdExtZcmp() const { return HasStdExtZcmp; }
   bool hasStdExtZvl() const { return ZvlLen != 0; }
   bool hasStdExtZvfh() const { return HasStdExtZvfh; }
   bool hasStdExtZfhmin() const { return HasStdExtZfhmin; }
Index: llvm/lib/Target/RISCV/RISCVSchedSiFive7.td
===================================================================
--- llvm/lib/Target/RISCV/RISCVSchedSiFive7.td
+++ llvm/lib/Target/RISCV/RISCVSchedSiFive7.td
@@ -16,9 +16,9 @@
   let MispredictPenalty = 3;
   let CompleteModel = 0;
   let UnsupportedFeatures = [HasStdExtZbkb, HasStdExtZbkc, HasStdExtZbkx,
-                             HasStdExtZknd, HasStdExtZkne, HasStdExtZknh,
-                             HasStdExtZksed, HasStdExtZksh, HasStdExtZkr,
-                             HasVInstructions];
+                             HasStdExtZcb, HasStdExtZknd, HasStdExtZkne,
+                             HasStdExtZknh, HasStdExtZksed, HasStdExtZksh,
+                             HasStdExtZkr, HasVInstructions];
 }
 
 // The SiFive7 microarchitecture has two pipelines: A and B.
Index: llvm/lib/Target/RISCV/RISCVSchedRocket.td
===================================================================
--- llvm/lib/Target/RISCV/RISCVSchedRocket.td
+++ llvm/lib/Target/RISCV/RISCVSchedRocket.td
@@ -18,9 +18,9 @@
   let MispredictPenalty = 3;
   let CompleteModel = false;
   let UnsupportedFeatures = [HasStdExtZbkb, HasStdExtZbkc, HasStdExtZbkx,
-                             HasStdExtZknd, HasStdExtZkne, HasStdExtZknh,
-                             HasStdExtZksed, HasStdExtZksh, HasStdExtZkr,
-                             HasVInstructions, HasVInstructionsI64];
+                             HasStdExtZcb, HasStdExtZknd, HasStdExtZkne,
+                             HasStdExtZknh, HasStdExtZksed, HasStdExtZksh,
+                             HasStdExtZkr, HasVInstructions, HasVInstructionsI64];
 }
 
 //===----------------------------------------------------------------------===//
Index: llvm/lib/Target/RISCV/RISCVRegisterInfo.td
===================================================================
--- llvm/lib/Target/RISCV/RISCVRegisterInfo.td
+++ llvm/lib/Target/RISCV/RISCVRegisterInfo.td
@@ -177,6 +177,24 @@
   let RegInfos = XLenRI;
 }
 
+// Saved Registers from s0 to s7, for C.MVA01S07 instruction in Zc extension
+def SR07 : RegisterClass<"RISCV", [XLenVT], 32, (add
+    (sequence "X%u", 8, 9),
+    (sequence "X%u", 18, 23)
+  )> {
+  let RegInfos = XLenRI;
+}
+
+// Registers saveable by PUSH instruction in Zc extension
+def PGPR : RegisterClass<"RISCV", [XLenVT], 32, (add
+    (sequence "X%u", 8, 9),
+    (sequence "X%u", 18, 25),
+    X27,
+    X1
+  )> {
+  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
===================================================================
--- /dev/null
+++ llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
@@ -0,0 +1,265 @@
+//===-- RISCVInstrInfoZc.td - RISC-V 'Zc' instructions -----*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// This file describes the RISC-V instructions from the 'Zc' Code-size 
+/// reduction extension, version 0.70.4.
+/// This version is still experimental as the 'Zc' extension hasn't been
+/// ratified yet.
+///
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Operand and SDNode transformation definitions.
+//===----------------------------------------------------------------------===//
+
+def uimm2_zc : Operand<XLenVT>,
+                 ImmLeaf<XLenVT, [{return isUInt<2>(Imm);}]> {
+  let ParserMatchClass = UImmAsmOperand<2>;
+  let DecoderMethod = "decodeUImmOperand<2>";
+  let OperandType = "OPERAND_UIMM2";
+  let OperandNamespace = "RISCVOp";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    return isUInt<2>(Imm);
+  }];
+}
+
+def uimm2_lsb0 : Operand<XLenVT>,
+                 ImmLeaf<XLenVT, [{return isShiftedUInt<1, 1>(Imm);}]> {
+  let ParserMatchClass = UImmAsmOperand<2, "Lsb0">;
+  let EncoderMethod = "getImmOpValue";
+  let DecoderMethod = "decodeUImmOperand<2>";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    return isShiftedUInt<1, 1>(Imm);
+  }];
+}
+
+def RlistAsmOperand : AsmOperandClass {
+  let Name = "Rlist";
+  let ParserMethod = "parseReglist";
+  let DiagnosticType = "InvalidRlist";
+}
+
+def SpimmAsmOperand : AsmOperandClass {
+  let Name = "Spimm";
+  let ParserMethod = "parseZcSpimm";
+  let DiagnosticType = "InvalidSpimm";
+}
+
+def rlist : Operand<OtherVT>, ImmLeaf<OtherVT, [{return isUInt<4>(Imm);}]> {
+   let ParserMatchClass = RlistAsmOperand;
+   let PrintMethod = "printRlist";
+   let DecoderMethod = "decodeZcRlist";
+   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 = "decodeZcSpimm";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    return  isShiftedUInt<5, 4>(Imm);
+  }];
+}
+
+//===----------------------------------------------------------------------===//
+// Instruction Class Templates
+//===----------------------------------------------------------------------===//
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class RVZcArith_r<bits<2> funct2, bits<3> opcode, string opcodestr>
+    : RVInst16<(outs GPRC:$rs_wb), (ins GPRC:$rs),
+                opcodestr, "$rs", [], InstFormatCB>{
+  bits<3> rs;
+  let Constraints = "$rs = $rs_wb";
+
+  let Inst{15-13} = 0b100;
+  let Inst{12-10} = 0b111;
+  let Inst{9-7} = rs;
+  let Inst{6-5} = funct2;
+  let Inst{4-2} = opcode;
+  let Inst{1-0} = 0b01;
+}
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class RVZcArith_rr<bits<6> funct6,bits<2> funct2, bits<2> opcode, string opcodestr>
+    : RVInst16<(outs GPRC:$rs1_wb), (ins GPRC:$rs1, GPRC:$rs2),
+                opcodestr, "$rs1, $rs2", [], InstFormatCB> {
+  bits<3> rs1;
+  bits<3> rs2;
+  let Constraints = "$rs1 = $rs1_wb";
+
+  let Inst{15-10} = funct6;
+  let Inst{9-7} = rs1;
+  let Inst{6-5} = funct2;
+  let Inst{4-2} = rs2;
+  let Inst{1-0} = opcode;
+}
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+class ZcLoad_ri<bits<3> funct3, bits<2> opcode, string opcodestr,
+                 RegisterClass cls, DAGOperand opnd>
+    : RVInst16CL<funct3, opcode, (outs cls:$rd), (ins GPRC:$rs1, opnd:$imm),
+                 opcodestr, "$rd, ${imm}(${rs1})">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
+class ZcStore_ri<bits<3> funct3, bits<2> opcode, string opcodestr,
+                 RegisterClass cls, DAGOperand opnd>
+    : RVInst16CS<funct3, opcode, (outs), (ins cls:$rs2, GPRC:$rs1, opnd:$imm),
+                 opcodestr, "$rs2, ${imm}(${rs1})">;
+
+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
+//===----------------------------------------------------------------------===//
+
+// ZCB
+
+let Predicates = [HasStdExtZcb, HasStdExtZba, IsRV64] in {
+def C_ZEXT_W : RVZcArith_r<0b11, 0b100 , "c.zext.w">;
+}
+
+let Predicates = [HasStdExtZcb, HasStdExtZbb] in {
+def C_ZEXT_H  : RVZcArith_r<0b11, 0b010 , "c.zext.h">;
+
+def C_SEXT_B  : RVZcArith_r<0b11, 0b001 , "c.sext.b">;
+def C_SEXT_H  : RVZcArith_r<0b11, 0b011 , "c.sext.h">;
+}
+
+let Predicates = [HasStdExtZcb] in
+def C_ZEXT_B  : RVZcArith_r<0b11, 0b000 , "c.zext.b">;
+
+let Predicates = [HasStdExtZcb, HasStdExtMOrZmmul] in
+def C_MUL     : RVZcArith_rr<0b100111, 0b10, 0b01, "c.mul">;
+
+let Predicates = [HasStdExtZcb] in {
+def C_NOT : RVZcArith_r<0b11, 0b101 , "c.not">;
+
+def C_LBU : ZcLoad_ri<0b100, 0b00, "c.lbu", GPRC, uimm2_zc>,
+          Sched<[]> {
+bits<2> imm;
+
+let Inst{12-10} = 0b000;
+let Inst{6-5} = imm{0,1};
+}
+
+def C_LHU : ZcLoad_ri<0b100, 0b00, "c.lhu", GPRC, uimm2_lsb0>,
+          Sched<[]> {
+bits<2> imm;
+
+let Inst{12-10} = 0b001;
+let Inst{6} = 0b0;
+let Inst{5} = imm{1};
+}
+
+def C_LH : ZcLoad_ri<0b100, 0b00, "c.lh", GPRC, uimm2_lsb0>,
+          Sched<[]> {
+bits<2> imm;
+
+let Inst{12-10} = 0b001;
+let Inst{6} = 0b1;
+let Inst{5} = imm{1};
+}
+
+def C_SB : ZcStore_ri<0b100, 0b00, "c.sb", GPRC, uimm2_zc>,
+          Sched<[]> {
+  bits<2> imm;
+
+  let Inst{12-10} = 0b010;
+  let Inst{6-5} = imm{0,1};
+}
+
+def C_SH : ZcStore_ri<0b100, 0b00, "c.sh", GPRC, uimm2_lsb0>,
+          Sched<[]> {
+  bits<2> imm;
+
+  let Inst{12-10} = 0b011;
+  let Inst{6} = 0b1;
+  let Inst{5} = imm{1};
+}
+}
+
+// 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">,
+                Sched<[]>;
+
+def CM_MVSA01 : RVInst16CA<0b101011, 0b01, 0b10, (outs SR07:$rs1, SR07:$rs2),
+                            (ins), "cm.mvsa01", "$rs1, $rs2">,
+                Sched<[]>;
+}
+
+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">, Sched<[]> {
+  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">, Sched<[]> {
+  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">, Sched<[]> {
+  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">, Sched<[]> {
+  bits<4> rlist;
+  bits<16> spimm;
+
+  let Inst{12-8} = 0b11010;
+  let Inst{7-4} = rlist;
+  let Inst{3-2} = spimm{5-4};
+}
+}
Index: llvm/lib/Target/RISCV/RISCVInstrInfo.td
===================================================================
--- llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -1688,6 +1688,7 @@
 include "RISCVInstrInfoD.td"
 include "RISCVInstrInfoC.td"
 include "RISCVInstrInfoZb.td"
+include "RISCVInstrInfoZc.td"
 include "RISCVInstrInfoZk.td"
 include "RISCVInstrInfoV.td"
 include "RISCVInstrInfoZfh.td"
Index: llvm/lib/Target/RISCV/RISCVInstrInfo.h
===================================================================
--- llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -112,6 +112,8 @@
 
   bool isAsCheapAsAMove(const MachineInstr &MI) const override;
 
+  Optional<DestSourcePair> isLoadImmImpl(const MachineInstr &MI) const;
+
   Optional<DestSourcePair>
   isCopyInstrImpl(const MachineInstr &MI) const override;
 
Index: llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
===================================================================
--- llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -1073,6 +1073,24 @@
   return MI.isAsCheapAsAMove();
 }
 
+Optional<DestSourcePair>
+RISCVInstrInfo::isLoadImmImpl(const MachineInstr &MI) const {
+  if (MI.isMoveImmediate())
+    return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
+  switch (MI.getOpcode()) {
+  default:
+    break;
+  case RISCV::ADDIW:
+  case RISCV::ADDI:
+    // Operand 1 can be a frameindex but callers expect registers
+    if (MI.getOperand(1).isReg() && MI.getOperand(2).isImm() &&
+        MI.getOperand(1).getReg() == RISCV::X0)
+      return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
+    break;
+  }
+  return None;
+}
+
 Optional<DestSourcePair>
 RISCVInstrInfo::isCopyInstrImpl(const MachineInstr &MI) const {
   if (MI.isMoveReg())
@@ -1080,6 +1098,16 @@
   switch (MI.getOpcode()) {
   default:
     break;
+  case RISCV::ADD:
+    if (!MI.getOperand(1).isReg() || !MI.getOperand(2).isReg())
+      break;
+    if ((MI.getOperand(1).getReg() == RISCV::X0) &&
+        (MI.getOperand(2).getReg() != RISCV::X0))
+      return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
+    if ((MI.getOperand(1).getReg() != RISCV::X0) &&
+        (MI.getOperand(2).getReg() == RISCV::X0))
+      return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
+    break;
   case RISCV::ADDI:
     // Operand 1 can be a frameindex but callers expect registers
     if (MI.getOperand(1).isReg() && MI.getOperand(2).isImm() &&
Index: llvm/lib/Target/RISCV/RISCV.td
===================================================================
--- llvm/lib/Target/RISCV/RISCV.td
+++ llvm/lib/Target/RISCV/RISCV.td
@@ -360,6 +360,22 @@
                                    "'C' (Compressed Instructions) or "
                                    "'Zca' (part of the C extension, excluding compressed floating point loads/stores)">;
 
+def FeatureExtZcb
+    : SubtargetFeature<"experimental-zcb", "HasStdExtZcb", "true",
+                       "'Zcb' (Shortened format for basic bit manipulation instructions)", 
+                       [FeatureExtZca]>;
+def HasStdExtZcb : Predicate<"Subtarget->hasStdExtZcb()">,
+                           AssemblerPredicate<(all_of FeatureExtZcb),
+                           "'Zcb' (Shortened format for basic bit manipulation instructions)">;
+
+def FeatureExtZcmp
+    : SubtargetFeature<"experimental-zcmp", "HasStdExtZcmp", "true",
+                       "'Zcmp' (sequenced instuctions for code-size reduction.)", 
+                       [FeatureExtZca]>;
+def HasStdExtZcmp : Predicate<"Subtarget->hasStdExtZcmp() && !Subtarget->hasStdExtC()">,
+                           AssemblerPredicate<(all_of FeatureExtZcmp, (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
@@ -84,6 +84,16 @@
   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;
+
+private:
+  FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const;
+  void
+  verifyInstructionPredicates(const MCInst &MI,
+                              const FeatureBitset &AvailableFeatures) const;
 };
 } // end anonymous namespace
 
@@ -394,4 +404,16 @@
   }
 }
 
+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();
+  if (Imm < 4)
+    assert(0 && "EABI is currently not implemented");
+  else
+    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
@@ -46,6 +46,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
@@ -181,6 +181,33 @@
   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.getFeatureBits()[RISCV::Feature64Bit];
+  int64_t spimm = 0;
+  bool isEABI = false; // Reserved for future implementation
+  auto rlistVal = MI->getOperand(0).getImm();
+  if (rlistVal == 16)
+    assert(0 && "Incorrect rlist.");
+  auto base = RISCVZC::getStackAdjBase(rlistVal, isRV64, isEABI);
+  spimm = Imm + base;
+  if (spimm < base || spimm > base + 48)
+    llvm_unreachable("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
@@ -433,6 +433,130 @@
 
 } // namespace RISCVVType
 
+namespace RISCVZC {
+
+enum class 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,
+  RA_S0_S10, // This is for error checking.
+};
+
+inline unsigned encodeRlist(MCRegister EndReg, bool isCInst,
+                            bool IsRV32E = false) {
+  auto RlistEncode = [=] {
+    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::RA_S0_S10;
+    case RISCV::X27:
+      return RLISTENCODE::RA_S0_S11;
+    default:
+      llvm_unreachable("Undefined input.");
+    }
+  }();
+  return static_cast<unsigned int>(RlistEncode);
+}
+
+inline static unsigned getStackAdjBase(unsigned rlistVal, bool isRV64,
+                                       bool isEABI) {
+  if (rlistVal == 16)
+    assert(0 && "{ra, s0-s10} is not supported, s11 must be included.");
+  if (isEABI) {
+    return 16;
+  }
+  if (!isRV64) {
+    switch (rlistVal) {
+    case /*ra*/ 4:
+    case /*s0*/ 5:
+    case /*s1*/ 6:
+    case /*s2*/ 7:
+      return 16;
+    case /*s3*/ 8:
+    case /*s4*/ 9:
+    case /*s5*/ 10:
+    case /*s6*/ 11:
+      return 32;
+    case /*s7*/ 12:
+    case /*s8*/ 13:
+    case /*s9*/ 14:
+      return 48;
+    case /*s11*/ 15:
+      return 64;
+    }
+  } else {
+    switch (rlistVal) {
+    case /*ra*/ 4:
+    case /*s0*/ 5:
+      return 16;
+    case /*s1*/ 6:
+    case /*s2*/ 7:
+      return 32;
+    case /*s3*/ 8:
+    case /*s4*/ 9:
+      return 48;
+    case /*s5*/ 10:
+    case /*s6*/ 11:
+      return 64;
+    case /*s7*/ 12:
+    case /*s8*/ 13:
+      return 80;
+    case /*s9*/ 14:
+      return 96;
+    case /*s11*/ 15:
+      return 112;
+    }
+  }
+  llvm_unreachable("Unexpected rlistVal");
+}
+
+inline static bool getSpimm(unsigned rlistVal, unsigned &spimmVal,
+                            int64_t stackAdjustment, bool isRV64, bool isEABI) {
+  if (rlistVal == 16)
+    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
@@ -185,4 +185,49 @@
     OS << ", mu";
 }
 
+void RISCVZC::printRlist(unsigned SlistEncode, raw_ostream &OS) {
+  OS << "{";
+  switch (SlistEncode) {
+  case 4:
+    OS << "ra";
+    break;
+  case 5:
+    OS << "ra, s0";
+    break;
+  case 6:
+    OS << "ra, s0-s1";
+    break;
+  case 7:
+    OS << "ra, s0-s2";
+    break;
+  case 8:
+    OS << "ra, s0-s3";
+    break;
+  case 9:
+    OS << "ra, s0-s4";
+    break;
+  case 10:
+    OS << "ra, s0-s5";
+    break;
+  case 11:
+    OS << "ra, s0-s6";
+    break;
+  case 12:
+    OS << "ra, s0-s7";
+    break;
+  case 13:
+    OS << "ra, s0-s8";
+    break;
+  case 14:
+    OS << "ra, s0-s9";
+    break;
+  case 15:
+    OS << "ra, s0-s11";
+    break;
+  }
+  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
@@ -170,6 +170,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, uint64_t RegNo,
                                           uint64_t Address,
                                           const MCDisassembler *Decoder) {
@@ -369,6 +380,12 @@
                                            uint64_t Address,
                                            const MCDisassembler *Decoder);
 
+static DecodeStatus decodeZcRlist(MCInst &Inst, unsigned Imm, uint64_t Address,
+                                  const void *Decoder);
+
+static DecodeStatus decodeZcSpimm(MCInst &Inst, unsigned Imm, uint64_t Address,
+                                  const void *Decoder);
+
 #include "RISCVGenDisassemblerTables.inc"
 
 static DecodeStatus decodeRVCInstrSImm(MCInst &Inst, unsigned Insn,
@@ -428,6 +445,23 @@
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeZcRlist(MCInst &Inst, unsigned Imm, uint64_t Address,
+                                  const void *Decoder) {
+  // Sign-extend the number in the bottom N bits of Imm
+  if (Imm <= 3)
+    return MCDisassembler::Fail;
+  Inst.addOperand(MCOperand::createImm(Imm));
+  return MCDisassembler::Success;
+}
+
+// spimm is based on rlist now.
+static DecodeStatus decodeZcSpimm(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
@@ -172,6 +172,9 @@
   OperandMatchResultTy parseMaskReg(OperandVector &Operands);
   OperandMatchResultTy parseInsnDirectiveOpcode(OperandVector &Operands);
   OperandMatchResultTy parseGPRAsFPR(OperandVector &Operands);
+  OperandMatchResultTy parseReglist(OperandVector &Operands);
+  OperandMatchResultTy parseRetval(OperandVector &Operands);
+  OperandMatchResultTy parseZcSpimm(OperandVector &Operands);
 
   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
 
@@ -276,6 +279,8 @@
     Immediate,
     SystemRegister,
     VType,
+    Rlist,
+    Spimm,
   } Kind;
 
   bool IsRV64;
@@ -302,6 +307,15 @@
     unsigned Val;
   };
 
+  struct RlistOp {
+    bool isCInst;
+    unsigned Val;
+  };
+
+  struct SpimmOp {
+    unsigned Val;
+  };
+
   SMLoc StartLoc, EndLoc;
   union {
     StringRef Tok;
@@ -309,6 +323,8 @@
     ImmOp Imm;
     struct SysRegOp SysReg;
     struct VTypeOp VType;
+    struct RlistOp Rlist;
+    struct SpimmOp Spimm;
   };
 
   RISCVOperand(KindTy K) : Kind(K) {}
@@ -335,6 +351,12 @@
     case KindTy::VType:
       VType = o.VType;
       break;
+    case KindTy::Rlist:
+      Rlist = o.Rlist;
+      break;
+    case KindTy::Spimm:
+      Spimm = o.Spimm;
+      break;
     }
   }
 
@@ -346,6 +368,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 &&
@@ -618,6 +642,16 @@
            VK == RISCVMCExpr::VK_RISCV_None;
   }
 
+  bool isUImm2Lsb0() const {
+    int64_t Imm;
+    RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+    if (!isImm())
+      return false;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
+           VK == RISCVMCExpr::VK_RISCV_None;
+  }
+
   bool isUImm7Lsb00() const {
     if (!isImm())
       return false;
@@ -830,6 +864,16 @@
       RISCVVType::printVType(getVType(), OS);
       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;
     }
   }
 
@@ -887,6 +931,25 @@
     return Op;
   }
 
+  static std::unique_ptr<RISCVOperand>
+  createRlist(unsigned RlistEncode, SMLoc S, bool IsRV64, bool isCInst) {
+    auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);
+    Op->Rlist.Val = RlistEncode;
+    Op->Rlist.isCInst = isCInst;
+    Op->StartLoc = S;
+    Op->IsRV64 = IsRV64;
+    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;
+    Op->IsRV64 = IsRV64;
+    return Op;
+  }
+
   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
     assert(Expr && "Expr shouldn't be null!");
     int64_t Imm = 0;
@@ -970,6 +1033,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));
+  }
+
   // Returns the rounding mode represented by this RISCVOperand. Should only
   // be called after checking isFRMArg.
   RISCVFPRndMode::RoundingMode getRoundingMode() const {
@@ -1151,6 +1224,9 @@
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
   case Match_InvalidUImm2:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
+  case Match_InvalidUImm2Lsb0:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 2,
+                                      "immediate must be one of");
   case Match_InvalidUImm3:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
   case Match_InvalidUImm5:
@@ -1279,6 +1355,18 @@
                                       (1 << 4),
                                       "immediate must be in the range");
   }
+  case Match_InvalidRlist: {
+    SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(ErrorLoc, "operand must be {}, {a0}, or {a0-a[1|2|3]}");
+  }
+  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);
   }
@@ -1922,6 +2010,115 @@
 
   return MatchOperand_Success;
 }
+OperandMatchResultTy RISCVAsmParser::parseReglist(OperandVector &Operands) {
+  // Rlist grammar: {ra [, s0[-sN]]} (UABI)
+  // XRlist :{x1 [, x8[-x9][, x18[-xN]]]} (UABI)
+  SMLoc S = getLoc();
+  if (getLexer().isNot(AsmToken::LCurly))
+    return MatchOperand_NoMatch;
+  getLexer().Lex(); // eat '{'
+  bool IsEmptyList = getLexer().is(AsmToken::RCurly);
+
+  StringRef Memonic =
+      static_cast<RISCVOperand *>(Operands.front().get())->getToken();
+  bool Is16Bit = Memonic.startswith("cm.");
+  bool IsEABI = isRV32E() || Memonic.endswith(".e");
+  bool IsXReglist = Memonic.find("x");
+
+  MCRegister RegStart = RISCV::NoRegister;
+  MCRegister RegEnd = RISCV::NoRegister;
+  if (!IsEmptyList) {
+    StringRef RegName = getLexer().getTok().getIdentifier();
+    matchRegisterNameHelper(IsEABI, RegStart, RegName);
+    if (RegStart != RISCV::X1)
+      return MatchOperand_NoMatch;
+    getLexer().Lex();
+  }
+
+  // parse case like ,s0
+  if (getLexer().is(AsmToken::Comma)) {
+    getLexer().Lex();
+    if (getLexer().isNot(AsmToken::Identifier))
+      return MatchOperand_NoMatch;
+    StringRef RegName = getLexer().getTok().getIdentifier();
+    if (matchRegisterNameHelper(/*IsEABI*/ false, RegStart, RegName))
+      return MatchOperand_NoMatch;
+    if (RegStart != RISCV::X8)
+      return MatchOperand_NoMatch;
+    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*/ false, RegEnd, EndName))
+      return MatchOperand_NoMatch;
+    getLexer().Lex();
+  }
+
+  // parse extra part like ', x18[-x20]' for XRegList
+  if (IsXReglist && getLexer().is(AsmToken::Comma)) {
+    if (RegEnd != RISCV::X9)
+      return MatchOperand_NoMatch;
+
+    // parse ', x18' for extra part
+    getLexer().Lex();
+    if (getLexer().isNot(AsmToken::Identifier))
+      return MatchOperand_NoMatch;
+    StringRef EndName = getLexer().getTok().getIdentifier();
+    if (MatchRegisterName(EndName) != RISCV::X18)
+      return MatchOperand_NoMatch;
+    getLexer().Lex();
+
+    // parse '-x20' for extra part
+    if (getLexer().is(AsmToken::Minus)) {
+      getLexer().Lex();
+      if (getLexer().isNot(AsmToken::Identifier))
+        return MatchOperand_NoMatch;
+      EndName = getLexer().getTok().getIdentifier();
+      if (MatchRegisterName(EndName) == RISCV::NoRegister)
+        return MatchOperand_NoMatch;
+      getLexer().Lex();
+    }
+    RegEnd = MatchRegisterName(EndName);
+  }
+
+  if (getLexer().isNot(AsmToken::RCurly))
+    return MatchOperand_NoMatch;
+  getLexer().Lex(); // eat '}'
+
+  if (RegEnd == RISCV::NoRegister)
+    RegEnd = RegStart;
+
+  auto Encode = RISCVZC::encodeRlist(RegEnd, Is16Bit, IsEABI);
+  if (Encode == 16)
+    Error(getLoc(), "invalid register list, {ra, s0-s10} is not supported.");
+  Operands.push_back(RISCVOperand::createRlist(Encode, S, isRV64(), Is16Bit));
+
+  return MatchOperand_Success;
+}
+
+OperandMatchResultTy RISCVAsmParser::parseZcSpimm(OperandVector &Operands) {
+  if (getLexer().is(AsmToken::Minus))
+    getLexer().Lex();
+
+  SMLoc S = getLoc();
+
+  StringRef Memonic =
+      static_cast<RISCVOperand *>(Operands.front().get())->getToken();
+  int64_t StackAdjustment = getLexer().getTok().getIntVal();
+  unsigned Spimm = 0;
+  unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val;
+
+  bool IsEABI = isRV32E() || Memonic.endswith(".e");
+  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
@@ -2794,7 +2991,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
@@ -113,6 +113,8 @@
     {"zbr", RISCVExtensionVersion{0, 93}},
     {"zbt", RISCVExtensionVersion{0, 93}},
     {"zca", RISCVExtensionVersion{0, 70}},
+    {"zcb", RISCVExtensionVersion{0, 70}},
+    {"zcmp", RISCVExtensionVersion{0, 70}},
     {"zvfh", RISCVExtensionVersion{0, 1}},
 };
 
@@ -778,6 +780,7 @@
 static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"};
 static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"};
 static const char *ImpliedExtsZvfh[] = {"zve32f"};
+static const char *ImpliedExtsZcmp[] = {"zca"};
 
 struct ImpliedExtsEntry {
   StringLiteral Name;
@@ -793,6 +796,7 @@
 // Note: The table needs to be sorted by name.
 static constexpr ImpliedExtsEntry ImpliedExts[] = {
     {{"v"}, {ImpliedExtsV}},
+    {{"zcmp"}, {ImpliedExtsZcmp}},
     {{"zdinx"}, {ImpliedExtsZdinx}},
     {{"zfh"}, {ImpliedExtsZfh}},
     {{"zfhmin"}, {ImpliedExtsZfhmin}},
Index: clang/test/Preprocessor/riscv-target-features.c
===================================================================
--- clang/test/Preprocessor/riscv-target-features.c
+++ clang/test/Preprocessor/riscv-target-features.c
@@ -45,6 +45,7 @@
 // CHECK-NOT: __riscv_zk
 // CHECK-NOT: __riscv_zicbom
 // CHECK-NOT: __riscv_zicboz
+// CHECK-NOT: __riscv_zcmp
 
 // RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32im -x c -E -dM %s \
 // RUN: -o - | FileCheck --check-prefix=CHECK-M-EXT %s
@@ -462,3 +463,10 @@
 // RUN: %clang -target riscv64 -march=rv64izicbop -x c -E -dM %s \
 // RUN: -o - | FileCheck --check-prefix=CHECK-ZICBOP-EXT %s
 // CHECK-ZICBOP-EXT: __riscv_zicbop 1000000{{$}}
+
+// RUN: %clang -target riscv32 -march=rv32izcmp0p70 -menable-experimental-extensions \
+// RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCMP-EXT %s
+// RUN: %clang -target riscv64 -march=rv64izcmp0p70 -menable-experimental-extensions \
+// RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCMP-EXT %s
+// CHECK-ZCMP-EXT: __riscv_zca 70000{{$}}
+// CHECK-ZCMP-EXT: __riscv_zcmp 70000{{$}}
\ No newline at end of file
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to