diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -72,6 +72,7 @@ // CHECK-NOT: __riscv_zvfbfwma {{.*$}} // CHECK-NOT: __riscv_zacas {{.*$}} // CHECK-NOT: __riscv_zicfilp {{.*$}} +// CHECK-NOT: __riscv_zicfiss {{.*$}} // RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32i -x c -E -dM %s \ // RUN: -o - | FileCheck %s @@ -783,3 +784,11 @@ // RUN: -march=rv64i_zicfilp0p2 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZICFILP-EXT %s // CHECK-ZICFILP-EXT: __riscv_zicfilp 2000{{$}} + +// RUN: %clang -target riscv32 -menable-experimental-extensions \ +// RUN: -march=rv32izicfiss0p2 -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZICFISS-EXT %s +// RUN: %clang -target riscv64 -menable-experimental-extensions \ +// RUN: -march=rv64izicfiss0p2 -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZICFISS-EXT %s +// CHECK-ZICFISS-EXT: __riscv_zicfiss 2000{{$}} diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -202,7 +202,7 @@ ``experimental-zfbfmin``, ``experimental-zvfbfmin``, ``experimental-zvfbfwma`` LLVM implements assembler support for the `0.8.0 draft specification `_. -``experimental-zicfilp`` +``experimental-zicfilp``, ``experimental-zicfiss`` LLVM implements the `0.2 draft specification `__. ``experimental-zicond`` diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -169,6 +169,8 @@ {"zfbfmin", RISCVExtensionVersion{0, 8}}, {"zicfilp", RISCVExtensionVersion{0, 2}}, + {"zicfiss", RISCVExtensionVersion{0, 2}}, + {"zicond", RISCVExtensionVersion{1, 0}}, {"ztso", RISCVExtensionVersion{0, 1}}, diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -662,6 +662,17 @@ bool isUImm8() const { return IsUImm<8>(); } bool isUImm20() const { return IsUImm<20>(); } + bool isUImm5NonZero() const { + if (!isImm()) + return false; + RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; + int64_t Imm; + bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); + return IsConstantImm && Imm != 0 && + isUInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) && + VK == RISCVMCExpr::VK_RISCV_None; + } + bool isUImm8GE32() const { int64_t Imm; RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; @@ -1407,6 +1418,8 @@ return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1); case Match_InvalidUImm5: return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); + case Match_InvalidUImm5NonZero: + return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1); case Match_InvalidUImm6: return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1); case Match_InvalidUImm7: diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp --- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -74,6 +74,17 @@ return MCDisassembler::Success; } +static DecodeStatus DecodeGPRRARegisterClass(MCInst &Inst, uint32_t RegNo, + uint64_t Address, + const MCDisassembler *Decoder) { + MCRegister Reg = RISCV::X0 + RegNo; + if (Reg != RISCV::X1 && Reg != RISCV::X5) + return MCDisassembler::Fail; + + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeFPR16RegisterClass(MCInst &Inst, uint32_t RegNo, uint64_t Address, const MCDisassembler *Decoder) { @@ -370,6 +381,10 @@ static DecodeStatus decodeZcmpSpimm(MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder); +static DecodeStatus decodeCSSPushPopchk(MCInst &Inst, uint32_t Insn, + uint64_t Address, + const MCDisassembler *Decoder); + #include "RISCVGenDisassemblerTables.inc" static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst &Inst, uint32_t Insn, @@ -384,6 +399,16 @@ return MCDisassembler::Success; } +static DecodeStatus decodeCSSPushPopchk(MCInst &Inst, uint32_t Insn, + uint64_t Address, + const MCDisassembler *Decoder) { + uint32_t Rs1 = fieldFromInstruction(Insn, 7, 5); + DecodeStatus Result = DecodeGPRRARegisterClass(Inst, Rs1, Address, Decoder); + (void)Result; + assert(Result == MCDisassembler::Success && "Invalid register"); + return MCDisassembler::Success; +} + static DecodeStatus decodeRVCInstrRdSImm(MCInst &Inst, uint32_t Insn, uint64_t Address, const MCDisassembler *Decoder) { diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h @@ -258,6 +258,7 @@ OPERAND_UIMM3, OPERAND_UIMM4, OPERAND_UIMM5, + OPERAND_UIMM5_NONZERO, OPERAND_UIMM6, OPERAND_UIMM7, OPERAND_UIMM7_LSB00, diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -79,6 +79,13 @@ AssemblerPredicate<(all_of FeatureStdExtZihintntl), "'Zihintntl' (Non-Temporal Locality Hints)">; +def FeatureStdExtZicfiss + : SubtargetFeature<"experimental-zicfiss", "HasStdExtZicfiss", "true", + "'Zicfiss' (Shadow stack)">; +def HasStdExtZicfiss : Predicate<"Subtarget->hasStdExtZicfiss()">, + AssemblerPredicate<(all_of FeatureStdExtZicfiss), + "'Zicfiss' (Shadow stack)">; + def FeatureStdExtZifencei : SubtargetFeature<"zifencei", "HasStdExtZifencei", "true", "'Zifencei' (fence.i)">; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1970,14 +1970,15 @@ include "RISCVInstrInfoV.td" include "RISCVInstrInfoZvk.td" -// Integer -include "RISCVInstrInfoZicbo.td" -include "RISCVInstrInfoZicond.td" - // Compressed include "RISCVInstrInfoC.td" include "RISCVInstrInfoZc.td" +// Integer +include "RISCVInstrInfoZicbo.td" +include "RISCVInstrInfoZicond.td" +include "RISCVInstrInfoZicfiss.td" + //===----------------------------------------------------------------------===// // Vendor extensions //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZicfiss.td @@ -0,0 +1,94 @@ +//===------ RISCVInstrInfoZicfiss.td - RISC-V Zicfiss -*- 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 +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Operand definitions. +//===----------------------------------------------------------------------===// + +def uimm5nonzero : Operand, + ImmLeaf(Imm);}]> { + let ParserMatchClass = UImmAsmOperand<5, "NonZero">; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeUImmNonZeroOperand<5>"; + let OperandType = "OPERAND_UIMM5_NONZERO"; + let OperandNamespace = "RISCVOp"; + let MCOperandPredicate = [{ + int64_t Imm; + if (MCOp.evaluateAsConstantImm(Imm)) + return (Imm != 0) && isUInt<5>(Imm); + return MCOp.isBareSymbolRef(); + }]; +} + +//===----------------------------------------------------------------------===// +// Instruction class templates +//===----------------------------------------------------------------------===// + +class RVC_SSInst rs1val, RegisterClass reg_class, string opcodestr> : + RVInst16<(outs), (ins reg_class:$rs1), opcodestr, "$rs1", [], InstFormatOther> { + let Inst{15-13} = 0b011; + let Inst{12} = 0; + let Inst{11-7} = rs1val; + let Inst{6-2} = 0b00000; + let Inst{1-0} = 0b01; + let DecoderMethod = "decodeCSSPushPopchk"; +} + +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +let Predicates = [HasStdExtZicfiss] in { +let Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { +def SSLOAD : RVInstI<0b100, OPC_SYSTEM, (outs GPRRA:$rd), (ins), "ssload", + "$rd"> { + let rs1 = 0; + let imm12 = 0b100000011100; +} + +def SSPOPCHK : RVInstI<0b100, OPC_SYSTEM, (outs), (ins GPRRA:$rs1), "sspopchk", + "$rs1"> { + let rd = 0; + let imm12 = 0b100000011100; +} // Uses = [SSP], hasSideEffects = 0, mayLoad = 1, mayStore = 0 +} // Predicates = [HasStdExtZicfiss] + +let Uses = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { +def SSPINC : RVInstI<0b100, OPC_SYSTEM, (outs), (ins uimm5nonzero:$rs1), + "sspinc", "$rs1"> { + let imm12 = 0b100000011101; + let rd = 0b00000; +} + +def SSPRR : RVInstR<0b1000011, 0b100, OPC_SYSTEM, (outs GPRNoX0:$rd), (ins), + "ssprr", "$rd"> { + let rs2 = 0b00000; + let rs1 = 0b00000; +} +} // Uses = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 0 + +let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { +def SSPUSH : RVInstR<0b1000101, 0b100, OPC_SYSTEM, (outs), (ins GPRRA:$rs2), + "sspush", "$rs2"> { + let rd = 0b00000; + let rs1 = 0b00000; +} + +def SSAMOSWAP : + RVInstRAtomic<0b10000, 0, 1, 0b100, OPC_SYSTEM, (outs GPRNoX0:$rd), + (ins GPR:$rs2, GPR:$rs1), "ssamoswap", "$rd, $rs2, (${rs1})">; +} // Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 +} // Predicates = [HasStdExtZicfiss] + +let Predicates = [HasStdExtZicfiss, HasStdExtCOrZca] in { +let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in +def C_SSPUSH : RVC_SSInst<0b00001, GPRX1, "c.sspush">; + +let Uses = [SSP], Defs = [SSP], hasSideEffects = 0, mayLoad = 0, mayStore = 1 in +def C_SSPOPCHK : RVC_SSInst<0b00101, GPRX5, "c.sspopchk">; +} // Predicates = [HasStdExtZicfiss, HasStdExtCOrZca] diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -119,6 +119,9 @@ markSuperRegs(Reserved, RISCV::FRM); markSuperRegs(Reserved, RISCV::FFLAGS); + // Shadow stack pointer. + markSuperRegs(Reserved, RISCV::SSP); + assert(checkAllSuperRegsMarked(Reserved)); return Reserved; } diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -137,6 +137,8 @@ (sequence "X%u", 0, 4))>; def GPRX0 : GPRRegisterClass<(add X0)>; +def GPRX1 : GPRRegisterClass<(add X1)>; +def GPRX5 : GPRRegisterClass<(add X5)>; def GPRNoX0 : GPRRegisterClass<(sub GPR, X0)>; @@ -165,6 +167,10 @@ def SR07 : GPRRegisterClass<(add (sequence "X%u", 8, 9), (sequence "X%u", 18, 23))>; +def GPRRA : RegisterClass<"RISCV", [XLenVT], 32, (add X1, X5)> { + let RegInfos = XLenRI; +} + // Floating point registers let RegAltNameIndices = [ABIRegAltName] in { def F0_H : RISCVReg16<0, "f0", ["ft0"]>, DwarfRegNum<[32]>; @@ -597,3 +603,6 @@ // Special registers def FFLAGS : RISCVReg<0, "fflags">; def FRM : RISCVReg<0, "frm">; + +// Shadow Stack register +def SSP : RISCVReg<0, "ssp">; diff --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s --- a/llvm/test/MC/RISCV/attribute-arch.s +++ b/llvm/test/MC/RISCV/attribute-arch.s @@ -302,3 +302,6 @@ .attribute arch, "rv32i_zicfilp0p2" # CHECK: attribute 5, "rv32i2p1_zicfilp0p2" + +.attribute arch, "rv32i_zicfiss0p2" +# CHECK: .attribute 5, "rv32i2p1_zicfiss0p2" diff --git a/llvm/test/MC/RISCV/zicfiss-invalid.s b/llvm/test/MC/RISCV/zicfiss-invalid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/zicfiss-invalid.s @@ -0,0 +1,28 @@ +# RUN: not llvm-mc %s -triple=riscv32 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \ +# RUN: 2>&1 | FileCheck -check-prefixes=CHECK-ERR %s +# RUN: not llvm-mc %s -triple=riscv32 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \ +# RUN: 2>&1 | FileCheck -check-prefixes=CHECK-ERR %s + +# CHECK-ERR: error: invalid operand for instruction +ssload a0 + +# CHECK-ERR: error: invalid operand for instruction +sspopchk a1 + +# CHECK-ERR: error: invalid operand for instruction +c.sspush t0 + +# CHECK-ERR: error: invalid operand for instruction +c.sspopchk ra + +# CHECK-ERR: error: immediate must be an integer in the range [1, 31] +sspinc 32 + +# CHECK-ERR: error: invalid operand for instruction +sspush a0 + +# CHECK-ERR: error: invalid operand for instruction +ssprr zero + +# CHECK-ERR: error: invalid operand for instruction +ssamoswap zero, x0, (a0) diff --git a/llvm/test/MC/RISCV/zicfiss-valid.s b/llvm/test/MC/RISCV/zicfiss-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/zicfiss-valid.s @@ -0,0 +1,110 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zicfiss,+c -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zicfiss,+c -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-zicfiss,+c < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zicfiss -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zicfiss,+c < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zicfiss -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s +# +# RUN: not llvm-mc -triple riscv32 -riscv-no-aliases -show-encoding < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK-NO-EXT %s +# RUN: not llvm-mc -triple riscv64 -riscv-no-aliases -show-encoding < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK-NO-EXT %s + +# CHECK-ASM-AND-OBJ: ssload ra +# CHECK-ASM: encoding: [0xf3,0x40,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +ssload x1 + +# CHECK-ASM-AND-OBJ: ssload ra +# CHECK-ASM: encoding: [0xf3,0x40,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +ssload ra + +# CHECK-ASM-AND-OBJ: ssload t0 +# CHECK-ASM: encoding: [0xf3,0x42,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +ssload x5 + +# CHECK-ASM-AND-OBJ: ssload t0 +# CHECK-ASM: encoding: [0xf3,0x42,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +ssload t0 + +# CHECK-ASM-AND-OBJ: sspopchk ra +# CHECK-ASM: encoding: [0x73,0xc0,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk x1 + +# CHECK-ASM-AND-OBJ: sspopchk ra +# CHECK-ASM: encoding: [0x73,0xc0,0xc0,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk ra + +# CHECK-ASM-AND-OBJ: sspopchk t0 +# CHECK-ASM: encoding: [0x73,0xc0,0xc2,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk x5 + +# CHECK-ASM-AND-OBJ: sspopchk t0 +# CHECK-ASM: encoding: [0x73,0xc0,0xc2,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspopchk t0 + +# CHECK-ASM-AND-OBJ: sspinc 4 +# CHECK-ASM: encoding: [0x73,0x40,0xd2,0x81] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspinc 4 + +# CHECK-ASM-AND-OBJ: sspush ra +# CHECK-ASM: encoding: [0x73,0x40,0x10,0x8a] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush x1 + +# CHECK-ASM-AND-OBJ: sspush ra +# CHECK-ASM: encoding: [0x73,0x40,0x10,0x8a] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush ra + +# check-asm-and-obj: sspush t0 +# check-asm: encoding: [0x73,0x40,0x50,0x8a] +# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush x5 + +# check-asm-and-obj: sspush t0 +# check-asm: encoding: [0x73,0x40,0x50,0x8a] +# check-no-ext: error: instruction requires the following: 'Zicfiss' (Shadow stack) +sspush t0 + +# CHECK-ASM-AND-OBJ: ssprr ra +# CHECK-ASM: encoding: [0xf3,0x40,0x00,0x86] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +ssprr ra + +# CHECK-ASM-AND-OBJ: ssamoswap t0, zero, (a0) +# CHECK-ASM: encoding: [0xf3,0x42,0x05,0x82] +# CHECK-NO-EXT: error: instruction requires the following: 'Zicfiss' (Shadow stack) +ssamoswap t0, x0, (a0) + +# CHECK-ASM-AND-OBJ: c.sspush ra +# CHECK-ASM: encoding: [0x81,0x60] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspush x1 + +# CHECK-ASM-AND-OBJ: c.sspush ra +# CHECK-ASM: encoding: [0x81,0x60] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspush ra + +# CHECK-ASM-AND-OBJ: c.sspopchk t0 +# CHECK-ASM: encoding: [0x81,0x62] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspopchk x5 + +# CHECK-ASM-AND-OBJ: c.sspopchk t0 +# CHECK-ASM: encoding: [0x81,0x62] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), 'Zicfiss' (Shadow stack) +c.sspopchk t0