diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index c2d9b00b489c7..0136651bb65b8 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3911,6 +3911,14 @@ def mno_xcheri_norvc : Flag<["-"], "mno-xcheri-norvc">, Group; def mxcheri_rvc : Flag<["-"], "mxcheri-rvc">, Alias; +def mxcheri_std_compat : Flag<["-"], "mxcheri-std-compat">, + Group, + HelpText<"Enable the subset of CHERI features that " + "are compatible with the upcoming standard">; +def mno_xcheri_std_compat : Flag<["-"], "mno-xcheri-std-compat">, + Group, + HelpText<"Enable non-standard CHERI features">; + def munaligned_access : Flag<["-"], "munaligned-access">, Group, HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64/LoongArch only)">; def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group, diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index add1f0e4b3849..79cd4f2abdd14 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -177,8 +177,11 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, auto ExtName = Extension.first; auto ExtInfo = Extension.second; + // Replace '-' with '_' to ensure the result is a single PP token. + std::string EscapedName = ExtName; + std::replace(EscapedName.begin(), EscapedName.end(), '-', '_'); Builder.defineMacro( - Twine("__riscv_", ExtName), + Twine("__riscv_", EscapedName), Twine(getVersionValue(ExtInfo.MajorVersion, ExtInfo.MinorVersion))); } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index c4cabad76c27b..efa67df94830a 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -236,6 +236,18 @@ static bool SemaBuiltinCHERICapCreate(Sema &S, CallExpr *TheCall) { return false; } +/// Check whether we are targeting the RISC-V CHERI standard, and if we are emit +/// an appropriate error message +static bool checkNonStdCheriIntrin(Sema &S, CallExpr *TheCall) { + const auto &TI = S.Context.getTargetInfo(); + if (TI.getTriple().isRISCV() && TI.hasFeature("xcheri-std-compat")) { + S.Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_requires_extension) + << true << TheCall->getSourceRange() << "xcheri (without std-compat)"; + return true; + } + return false; +} + /// Check that argument \p ArgIndex is a capability type (or an array/function /// that decays to a capability type. static bool checkCapArg(Sema &S, CallExpr *TheCall, unsigned ArgIndex, @@ -2639,10 +2651,16 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } break; } + case Builtin::BI__builtin_cheri_cap_load_tags: + if (checkNonStdCheriIntrin(*this, TheCall)) + return ExprError(); // Not supported in standard CHERI RISC-V + break; case Builtin::BI__builtin_cheri_seal: case Builtin::BI__builtin_cheri_unseal: case Builtin::BI__builtin_cheri_conditional_seal: case Builtin::BI__builtin_cheri_cap_type_copy: { + if (checkNonStdCheriIntrin(*this, TheCall)) + return ExprError(); // Not supported in standard CHERI RISC-V // Seal/unseal work in almost same way as the setters: value to be // unsealed/sealed comes first and should therefore be the result type, // second argument is overloaded to be any capability type. diff --git a/clang/test/CodeGen/cheri/riscv/riscv-default-ir-features.c b/clang/test/CodeGen/cheri/riscv/riscv-default-ir-features.c index 8486821da8622..dd7ada1fd27ed 100644 --- a/clang/test/CodeGen/cheri/riscv/riscv-default-ir-features.c +++ b/clang/test/CodeGen/cheri/riscv/riscv-default-ir-features.c @@ -52,6 +52,7 @@ // RV32-NOCHERI-SAME: -xcheri, // RV64-NOCHERI-SAME: -xcheri, // XCHERI-RVC-SAME: -xcheri-norvc, +// CHECK-SAME: -xcheri-std-compat, // CHECK-NOT: xcheri // CHECK-SAME: } diff --git a/clang/test/Driver/riscv-default-features.c b/clang/test/Driver/riscv-default-features.c index 2558e6a150a03..46f379e1a33ba 100644 --- a/clang/test/Driver/riscv-default-features.c +++ b/clang/test/Driver/riscv-default-features.c @@ -13,6 +13,16 @@ // RUN: %clang --target=riscv32-unknown-elf -march=rv32ixcheri -S -mno-xcheri-norvc -emit-llvm %s -o - | FileCheck %s --check-prefixes=RV32-XCHERI,XCHERI,XCHERI-RVC // RUN: %clang --target=riscv64-unknown-elf -march=rv64ixcheri -S -mno-xcheri-norvc -emit-llvm %s -o - | FileCheck %s --check-prefixes=RV64-XCHERI,XCHERI,XCHERI-RVC +/// The standards-compatible mode can be enable either using the arch string or the -mxcheri-std-compat flag +// RUN: %clang --target=riscv64-unknown-elf -march=rv64ixcheri -mxcheri-std-compat -S -emit-llvm %s -o - 2>&1 | FileCheck %s -check-prefix=RV64-XCHERI-STD-COMPAT +// RUN: %clang --target=riscv64-unknown-elf -march=rv64ixcheri_xcheri-std-compat -S -emit-llvm %s -o - 2>&1 | FileCheck %s -check-prefix=RV64-XCHERI-STD-COMPAT +// RUN: %clang --target=riscv64-unknown-elf -march=rv64ixcheri-std-compat -S -emit-llvm %s -o - | FileCheck %s -check-prefix=RV64-XCHERI-STD-COMPAT +/// In the case of rv64i -mxcheri-std-compat, +xcheri is not inferred, but this will be fixed in future upstream merges +// RUN: %clang --target=riscv64-unknown-elf -march=rv64i -mxcheri-std-compat -S -emit-llvm %s -o - | FileCheck %s -check-prefix=RV64-XCHERI-STD-COMPAT-ONLY +/// Check that we can override the flag with -mno-xcheri-std-compat +// RUN: %clang --target=riscv64-unknown-elf -march=rv64ixcheri -mxcheri-std-compat -mno-xcheri-std-compat -S -emit-llvm %s -o - | FileCheck %s -check-prefix=RV64-XCHERI + + // RV32: "target-features"="+32bit,+a,+c,+m,+relax, // RV32-SAME: -save-restore // RV64: "target-features"="+64bit,+a,+c,+m,+relax, @@ -32,10 +42,14 @@ // RV32-XCHERI-EXPLICIT-RVC: "target-features"="+32bit,+relax,+xcheri // RV32-XCHERI-EXPLICIT-RVC-SAME -save-restore // XCHERI-RVC-SAME: ,-xcheri-norvc, +// XCHERI-SAME: -xcheri-std-compat, // RV64-XCHERI-EXPLICIT-RVC: "target-features"="+64bit,+relax,+xcheri // XCHERI-NOT: xcheri +// RV64-XCHERI-STD-COMPAT: "target-features"="+64bit,+relax,+xcheri,+xcheri-std-compat, +// RV64-XCHERI-STD-COMPAT-ONLY: "target-features"="+64bit,+relax,+xcheri-std-compat, + // Dummy function int foo(void){ return 3; diff --git a/clang/test/Driver/riscv-features.c b/clang/test/Driver/riscv-features.c index 419339b00d353..cc20840e7894f 100644 --- a/clang/test/Driver/riscv-features.c +++ b/clang/test/Driver/riscv-features.c @@ -32,6 +32,7 @@ // RUN: %clang --target=riscv32-unknown-elf -### %s -march=rv64ixcheri -mxcheri-norvc 2>&1 | FileCheck %s --check-prefixes=XCHERI,XCHERI-NORVC // RUN: %clang --target=riscv32-unknown-elf -### %s -march=rv64ixcheri -mno-xcheri-rvc 2>&1 | FileCheck %s --check-prefixes=XCHERI,XCHERI-NORVC // XCHERI: "-target-feature" "+xcheri" +// XCHERI: "-xcheri-std-compat" // XCHERI-NOT: "{{[+|-]}}xcheri- // XCHERI-EXPLICIT-RVC: "-target-feature" "-xcheri-norvc" // XCHERI-NORVC: "-target-feature" "+xcheri-norvc" diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 27c089494de17..9d33610c4fc7a 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -780,3 +780,39 @@ // RUN: -march=rv64i_zacas1p0 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s // CHECK-ZACAS-EXT: __riscv_zacas 1000000{{$}} + +// RUN: %clang -target riscv64-unknown-none -march=rv64gcxcheri -x c -E -dM %s \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK-XCHERI --implicit-check-not=__riscv_ +// RUN: %clang -target riscv64-unknown-none -march=rv64gcxcheri -mxcheri-std-compat -x c -E -dM %s \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK-XCHERI,CHECK-XCHERI-STD-COMPAT --implicit-check-not=__riscv_ + + +// CHECK-XCHERI: #define __riscv 1 +// CHECK-XCHERI-NEXT: #define __riscv_a 2001000 +// CHECK-XCHERI-NEXT: #define __riscv_arch_test 1 +// CHECK-XCHERI-NEXT: #define __riscv_atomic 1 +// CHECK-XCHERI-NEXT: #define __riscv_c 2000000 +// CHECK-XCHERI-NEXT: #define __riscv_clen 128 +// CHECK-XCHERI-NEXT: #define __riscv_cmodel_medlow 1 +// CHECK-XCHERI-NEXT: #define __riscv_compressed 1 +// CHECK-XCHERI-NEXT: #define __riscv_d 2002000 +// CHECK-XCHERI-NEXT: #define __riscv_div 1 +// CHECK-XCHERI-NEXT: #define __riscv_f 2002000 +// CHECK-XCHERI-NEXT: #define __riscv_fdiv 1 +// CHECK-XCHERI-NEXT: #define __riscv_flen 64 +// CHECK-XCHERI-NEXT: #define __riscv_float_abi_double 1 +// CHECK-XCHERI-NEXT: #define __riscv_fsqrt 1 +// CHECK-XCHERI-NEXT: #define __riscv_i 2001000 +// CHECK-XCHERI-NEXT: #define __riscv_m 2000000 +// CHECK-XCHERI-NEXT: #define __riscv_mul 1 +// CHECK-XCHERI-NEXT: #define __riscv_muldiv 1 +// CHECK-XCHERI-NEXT: #define __riscv_xcheri 0 +// CHECK-XCHERI-NEXT: #define __riscv_xcheri_mode_dependent_jumps 1 +// CHECK-XCHERI-NEXT: #define __riscv_xcheri_no_relocation 1 +// CHECK-XCHERI-STD-COMPAT-NEXT: #define __riscv_xcheri_std_compat 0 +// CHECK-XCHERI-NEXT: #define __riscv_xcheri_tag_clear 1 +// CHECK-XCHERI-NEXT: #define __riscv_xlen 64 +// CHECK-XCHERI-NEXT: #define __riscv_zicsr 2000000 +// CHECK-XCHERI-NEXT: #define __riscv_zifencei 2000000 + + diff --git a/clang/test/Sema/cheri/cheri-std-unsupported-builtins.c b/clang/test/Sema/cheri/cheri-std-unsupported-builtins.c new file mode 100644 index 0000000000000..68949b45a4d4e --- /dev/null +++ b/clang/test/Sema/cheri/cheri-std-unsupported-builtins.c @@ -0,0 +1,25 @@ +/// In the RISC-V standard compat mode not all builtins are supported since we do not perform the expansion in the backend. +// RUN: %riscv64_cheri_purecap_cc1 -target-feature +xcheri %s -fsyntax-only -verify=xcheri +// RUN: %riscv64_cheri_purecap_cc1 -target-feature +xcheri-std-compat %s -fsyntax-only -verify=std-compat +// xcheri-no-diagnostics + +void *cseal(void *a, void *b) { + _Static_assert(__has_builtin(__builtin_cheri_seal), ""); // TODO: would be nice to report false here + return __builtin_cheri_seal(a, b); // std-compat-error{{builtin requires at least one of the following extensions to be enabled: xcheri (without std-compat)}} +} +void *cunseal(void *a, void *b) { + _Static_assert(__has_builtin(__builtin_cheri_unseal), ""); // TODO: would be nice to report false here + return __builtin_cheri_unseal(a, b); // std-compat-error{{builtin requires at least one of the following extensions to be enabled: xcheri (without std-compat)}} +} +void *ccseal(void *a, void *b) { + _Static_assert(__has_builtin(__builtin_cheri_conditional_seal), ""); // TODO: would be nice to report false here + return __builtin_cheri_conditional_seal(a, b); // std-compat-error{{builtin requires at least one of the following extensions to be enabled: xcheri (without std-compat)}} +} +void *ccopytype(void *a, void *b) { + _Static_assert(__has_builtin(__builtin_cheri_cap_type_copy), ""); // TODO: would be nice to report false here + return __builtin_cheri_cap_type_copy(a, b); // std-compat-error{{builtin requires at least one of the following extensions to be enabled: xcheri (without std-compat)}} +} +unsigned long cloadtags(void *a) { + _Static_assert(__has_builtin(__builtin_cheri_cap_load_tags), ""); // TODO: would be nice to report false here + return __builtin_cheri_cap_load_tags(a); // std-compat-error{{builtin requires at least one of the following extensions to be enabled: xcheri (without std-compat)}} +} diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index 065d787867657..bf88927ce8cdb 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -3258,6 +3258,7 @@ class TargetLoweringBase { // Return true if the target has a capability set address instruction. virtual bool hasCapabilitySetAddress() const { return false; } + virtual bool hasCapabilitySetOffset() const { return true; } MVT cheriCapabilityType() const { return CapType; } bool cheriCapabilityTypeHasPreciseBounds() const { return CapTypeHasPreciseBounds; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 82136e6639e7f..ab439697eb9cc 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -7488,6 +7488,33 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, setValue(&I, Res); return; } + case Intrinsic::cheri_cap_offset_set: { + if (TLI.hasCapabilitySetOffset()) { + visitTargetIntrinsic(I, Intrinsic); + return; + } + assert(TLI.hasCapabilitySetAddress() && + "Expansion of offset_set requires address_set!"); + Value *CapV = I.getArgOperand(0); + SDValue Cap = getValue(CapV); + Value *OffsetV = I.getArgOperand(1); + SDValue Offset = getValue(OffsetV); + // offset_set(cap, offset) -> address_set(cap, base_get(cap) + offset) + EVT AddrVT = TLI.getPointerRangeTy( + DAG.getDataLayout(), CapV->getType()->getPointerAddressSpace()); + EVT CapVT = TLI.getPointerTy(DAG.getDataLayout(), + CapV->getType()->getPointerAddressSpace()); + SDValue CapBase = DAG.getNode( + ISD::INTRINSIC_WO_CHAIN, sdl, AddrVT, + DAG.getConstant(Intrinsic::cheri_cap_base_get, sdl, AddrVT), Cap); + SDValue NewAddr = DAG.getNode(ISD::ADD, sdl, AddrVT, CapBase, Offset); + Res = DAG.getNode( + ISD::INTRINSIC_WO_CHAIN, sdl, CapVT, + DAG.getConstant(Intrinsic::cheri_cap_address_set, sdl, AddrVT), Cap, + NewAddr); + setValue(&I, Res); + return; + } case Intrinsic::threadlocal_address: { setValue(&I, getValue(I.getOperand(0))); return; diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp index 5e4af8a8cbc25..52f952771908b 100644 --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -68,6 +68,7 @@ static const RISCVSupportedExtension SupportedExtensions[] = { // vendor-defined ('X') extensions {"xcheri", RISCVExtensionVersion{0, 0}}, + {"xcheri-std-compat", RISCVExtensionVersion{0, 0}}, {"xcvbitmanip", RISCVExtensionVersion{1, 0}}, {"xcvmac", RISCVExtensionVersion{1, 0}}, {"xsfcie", RISCVExtensionVersion{1, 0}}, @@ -955,6 +956,7 @@ Error RISCVISAInfo::checkDependency() { static const char *ImpliedExtsD[] = {"f"}; static const char *ImpliedExtsF[] = {"zicsr"}; static const char *ImpliedExtsV[] = {"zvl128b", "zve64d"}; +static const char *ImpliedExtsXCheriStdCompat[] = {"xcheri"}; static const char *ImpliedExtsXTHeadVdot[] = {"v"}; static const char *ImpliedExtsXsfvcp[] = {"zve32x"}; static const char *ImpliedExtsZacas[] = {"a"}; @@ -1021,6 +1023,7 @@ static constexpr ImpliedExtsEntry ImpliedExts[] = { {{"d"}, {ImpliedExtsD}}, {{"f"}, {ImpliedExtsF}}, {{"v"}, {ImpliedExtsV}}, + {{"xcheri-std-compat"}, {ImpliedExtsXCheriStdCompat}}, {{"xsfvcp"}, {ImpliedExtsXsfvcp}}, {{"xtheadvdot"}, {ImpliedExtsXTHeadVdot}}, {{"zacas"}, {ImpliedExtsZacas}}, diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 37f7e3b7d61fa..900c2f6ddb2c5 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -119,7 +119,7 @@ class RISCVAsmParser : public MCTargetAsmParser { ParseStatus parseDirective(AsmToken DirectiveID) override; bool isCheri() const override { - return getSTI().getFeatureBits()[RISCV::FeatureCheri]; + return getSTI().getFeatureBits()[RISCV::FeatureCheriCommon]; } unsigned getCheriCapabilitySize() const override { @@ -3064,7 +3064,7 @@ bool RISCVAsmParser::parseDirectiveOption() { if (Parser.parseEOL()) return true; - if (!getSTI().hasFeature(RISCV::FeatureCheri)) + if (!getSTI().hasFeature(RISCV::FeatureXCheri)) return Error(Parser.getTok().getLoc(), "option requires 'xcheri' extension"); @@ -3077,7 +3077,7 @@ bool RISCVAsmParser::parseDirectiveOption() { if (Parser.parseEOL()) return true; - if (!getSTI().hasFeature(RISCV::FeatureCheri)) + if (!getSTI().hasFeature(RISCV::FeatureXCheri)) return Error(Parser.getTok().getLoc(), "option requires 'xcheri' extension"); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp index 5386dd5eda793..97aa0e2529e5a 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp @@ -63,9 +63,9 @@ ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits, "target-abi)\n"; TargetABI = ABI_Unknown; } else if ((ABIName.startswith("il32pc") || ABIName.startswith("l64pc")) && - !FeatureBits[RISCV::FeatureCheri]) { + !FeatureBits[RISCV::FeatureCheriCommon]) { errs() << "Pure-capability ABI can't be used for a target that " - "doesn't support the XCheri instruction set extension (ignoring " + "doesn't support the CHERI instruction set extension (ignoring " "target-abi)\n"; TargetABI = ABI_Unknown; } else if (!IsRV64 && IsRVE && TargetABI != ABI_ILP32E && diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp index 9bdad7641449b..d9704537a8dd7 100644 --- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp +++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp @@ -62,6 +62,10 @@ class RISCVExpandPseudo : public MachineFunctionPass { bool expandCapLoadTLSGDCap(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineBasicBlock::iterator &NextMBBI); + bool expandCheriExplicitCapLoadStore(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned ExplicitModeOp, + unsigned OtherModeOp, bool IsCapOp); bool expandCGetAddr(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI); bool expandCCOp(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineBasicBlock::iterator &NextMBBI); @@ -130,6 +134,30 @@ bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB, return expandCapLoadLocalCap(MBB, MBBI, NextMBBI); case RISCV::PseudoCLGC: return expandCapLoadGlobalCap(MBB, MBBI, NextMBBI); +#define EXPAND_MODE(insn) \ + case RISCV::Pseudo_##insn##_CAP: \ + return expandCheriExplicitCapLoadStore(MBB, MBBI, RISCV::insn##_CAP, \ + RISCV::insn, true); \ + case RISCV::Pseudo_##insn##_DDC: \ + return expandCheriExplicitCapLoadStore(MBB, MBBI, RISCV::insn##_DDC, \ + RISCV::C##insn, false); + + EXPAND_MODE(LB) + EXPAND_MODE(LBU) + EXPAND_MODE(LH) + EXPAND_MODE(LHU) + EXPAND_MODE(LW) + EXPAND_MODE(LWU) + EXPAND_MODE(LD) + EXPAND_MODE(LC_64) + EXPAND_MODE(LC_128) + EXPAND_MODE(SB) + EXPAND_MODE(SH) + EXPAND_MODE(SW) + EXPAND_MODE(SD) + EXPAND_MODE(SC_64) + EXPAND_MODE(SC_128) + case RISCV::PseudoCLA_TLS_IE: return expandCapLoadTLSIEAddress(MBB, MBBI, NextMBBI); case RISCV::PseudoCLC_TLS_GD: @@ -257,6 +285,52 @@ bool RISCVExpandPseudo::expandCapLoadTLSGDCap( RISCV::CIncOffsetImm); } +/// Expands an expilict capability load (in hybrid mode) to a mode switch around +/// the normal load/store operation to execute it in capability mode. +bool RISCVExpandPseudo::expandCheriExplicitCapLoadStore( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + unsigned ExplicitModeOp, unsigned OtherModeOp, bool IsCapOp) { + MachineFunction *MF = MBB.getParent(); + MachineInstr &MI = *MBBI; + DebugLoc DL = MI.getDebugLoc(); + if (MF->getSubtarget().hasXCheriNonStd()) { + // If we have the non-standard extensions, use the explicit mode insns. + BuildMI(MBB, MBBI, DL, TII->get(ExplicitModeOp)) + .add(MI.getOperand(0)) + .add(MI.getOperand(1)); + MI.eraseFromParent(); + return true; + } + Register BaseReg; + auto *TRI = MF->getRegInfo().getTargetRegisterInfo(); + if (IsCapOp) + BaseReg = TRI->getSubReg(MI.getOperand(1).getReg(), RISCV::sub_cap_addr); + else + BaseReg = TRI->getMatchingSuperReg( + MI.getOperand(1).getReg(), RISCV::sub_cap_addr, &RISCV::GPCRRegClass); + + assert(BaseReg.isValid()); + + // NB: We emit the "wrong mode" load/store here since using the other + // instruction will result in e.g. "Attempting to emit CLB instruction but the + // Feature_IsCapMode predicate(s) are not met". This is safe since the raw + // encoding is the same. + // Note: This pass runs right at the end of the pipeline, so instructions will + // not move around (so we don't need a TargetOpcode::BUNDLE here which is + // not handled by the remaining RISC-V codegen infrastructure). + BuildMI(MBB, MBBI, DL, + TII->get(IsCapOp ? RISCV::ModeSwitchCap : RISCV::ModeSwitchInt)); + BuildMI(MBB, MBBI, DL, TII->get(OtherModeOp)) + .add(MI.getOperand(0)) + .addReg(BaseReg, MI.getOperand(1).getTargetFlags()) + .addImm(0); + BuildMI(MBB, MBBI, DL, + TII->get(IsCapOp ? RISCV::ModeSwitchInt : RISCV::ModeSwitchCap)); + MI.eraseFromParent(); + + return true; +} + bool RISCVExpandPseudo::expandCGetAddr(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) { const auto &STI = MBB.getParent()->getSubtarget(); diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index feb285e040a00..f340871cd5ade 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -816,12 +816,16 @@ def FeatureRVE def IsRVE : Predicate<"Subtarget->isRVE()">, AssemblerPredicate<(all_of FeatureRVE)>; -def FeatureCheri - : SubtargetFeature<"xcheri", "HasCheri", "true", - "Implements CHERI extension">; -def HasCheri : Predicate<"Subtarget->hasCheri()">, - AssemblerPredicate<(all_of FeatureCheri), - "CHERI Extension">; +def FeatureCheriCommon + : SubtargetFeature<"cheri-common", "HasCheri", "true", + "Implements CHERI (ISAv9 or standard extension)">; +def HasCheriCommon + : Predicate<"Subtarget->hasCheri()">, + AssemblerPredicate<(all_of FeatureCheriCommon), "CHERI Extension">; + +def FeatureXCheri + : SubtargetFeature<"xcheri", "HasXCheri", "true", + "Implements CHERI extension", [FeatureCheriCommon]>; def FeatureCheriNoRVC : SubtargetFeature<"xcheri-norvc", "EnableCheriRVCInstrs", "false", "Disable CHERI RVC Instructions.">; @@ -829,6 +833,19 @@ def HasCheriRVC : Predicate<"Subtarget->enableCheriRVCInstrs()">, AssemblerPredicate<(all_of (not FeatureCheriNoRVC)), "CHERI RVC Instructions">; +def FeatureXCheriStdCompat + : SubtargetFeature<"xcheri-std-compat", "HasXCheriStdCompat", "true", + "Implements CHERI extension subset compatible with the " + "upcoming standard", + [FeatureCheriCommon, FeatureXCheri]>; +def HasXCheriAll + : Predicate<"Subtarget->hasXCheriNonStd()">, + AssemblerPredicate<(all_of FeatureXCheri, (not FeatureXCheriStdCompat)), + "'xcheri' extension with non-standard instructions">; +def HasXCheriStdCompat : Predicate<"Subtarget->hasXCheriStdCompat()">, + AssemblerPredicate<(all_of FeatureXCheriStdCompat), + "CHERI standard-compatible subset">; + def FeatureCapMode : SubtargetFeature<"cap-mode", "IsCapMode", "true", "Capability mode">; diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 95bb7b58c2fcd..38144e2f4782c 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -7460,6 +7460,10 @@ static SDValue lowerGetVectorLength(SDNode *N, SelectionDAG &DAG, return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, XLenVT, ID, AVL, Sew, LMul); } +bool RISCVTargetLowering::hasCapabilitySetOffset() const { + return Subtarget.hasXCheriNonStd(); +} + SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const { unsigned IntNo = Op.getConstantOperandVal(0); @@ -13562,12 +13566,27 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, ISD::SETNE); } case Intrinsic::cheri_cap_sealed_get: { - SDValue IntRes = - DAG.getNode(RISCVISD::CAP_SEALED_GET, DL, XLenVT, N->getOperand(1)); - IntRes = DAG.getNode(ISD::AssertZext, DL, XLenVT, IntRes, - DAG.getValueType(MVT::i1)); - return DAG.getSetCC(DL, MVT::i1, IntRes, DAG.getConstant(0, DL, XLenVT), - ISD::SETNE); + if (!Subtarget.hasXCheriNonStd()) { + // The RISC-V standard does not have CGetSealed, use GCTYPE and + // compare to unsealed instead. + SDValue Type = DAG.getNode( + ISD::INTRINSIC_WO_CHAIN, DL, XLenVT, + DAG.getConstant(Intrinsic::cheri_cap_type_get, DL, MVT::i64), + N->getOperand(1)); + // Note in the RISC-V standard unsealed capabilities have a zero type, + // but in ISAv9 unsealed is otype - 1. + int64_t UnsealedOtype = Subtarget.hasXCheri() ? -1 : 0; + return DAG.getSetCC(DL, MVT::i1, Type, + DAG.getConstant(UnsealedOtype, DL, XLenVT), + ISD::SETNE); + } else { + SDValue IntRes = + DAG.getNode(RISCVISD::CAP_SEALED_GET, DL, XLenVT, N->getOperand(1)); + IntRes = DAG.getNode(ISD::AssertZext, DL, XLenVT, IntRes, + DAG.getValueType(MVT::i1)); + return DAG.getSetCC(DL, MVT::i1, IntRes, DAG.getConstant(0, DL, XLenVT), + ISD::SETNE); + } } case Intrinsic::cheri_cap_subset_test: { SDValue IntRes = DAG.getNode(RISCVISD::CAP_SUBSET_TEST, DL, XLenVT, @@ -16568,11 +16587,11 @@ bool RISCVTargetLowering::isUsedByReturnOnly(SDNode *N, SDValue &Chain) const { return false; SDNode *Copy = *N->use_begin(); - + if (Copy->getOpcode() == ISD::BITCAST) { return isUsedByReturnOnly(Copy, Chain); } - + // TODO: Handle additional opcodes in order to support tail-calling libcalls // with soft float ABIs. if (Copy->getOpcode() != ISD::CopyToReg) { diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index 0539e6a77e516..af40ab5846672 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -935,6 +935,7 @@ class RISCVTargetLowering : public TargetLowering { SDValue expandUnalignedRVVStore(SDValue Op, SelectionDAG &DAG) const; bool hasCapabilitySetAddress() const override { return true; } + bool hasCapabilitySetOffset() const override; TailPaddingAmount getTailPaddingForPreciseBounds(uint64_t Size) const override; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td index 3406ff37639b6..00f695d165bb9 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td @@ -167,6 +167,20 @@ class CheriLoad_r op, string opcodestr, RegisterClass rdClass, : RVInstCheriSrcDst<0x7d, op, 0, OPC_CHERI, (outs rdClass:$rd), (ins rs1Operand:$rs1), opcodestr, "$rd, $rs1">; +multiclass ExplicitCheriLoad_r op, string opcodestr, RegisterClass rdClass, + RegisterOperand rs1Operand, + list ExtraPreds = []> { + let Predicates = !listconcat([HasXCheriAll], ExtraPreds) in + def NAME: CheriLoad_r; + // Adding a mode switch either side of the load expands to 3 instructions. + // The predicate here is HasCheriCommon, since in the xcheri case we can + // just expand this to an explicit mode load. + let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 12, + Predicates = !listconcat([HasCheriCommon], ExtraPreds) in + def Pseudo_#NAME : Pseudo<(outs rdClass:$rd), (ins rs1Operand:$rs1), [], + "pseudo_"#opcodestr, "$rd, $rs1">; +} + let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in class CheriStore_r op, string opcodestr, RegisterClass rs2Class, RegisterOperand rs1Operand> @@ -174,6 +188,20 @@ class CheriStore_r op, string opcodestr, RegisterClass rs2Class, (ins rs2Class:$rs2, rs1Operand:$rs1), opcodestr, "$rs2, $rs1">; +multiclass ExplicitCheriStore_r op, string opcodestr, RegisterClass rs2Class, + RegisterOperand rs1Operand, + list ExtraPreds = []> { + let Predicates = !listconcat([HasXCheriAll], ExtraPreds) in + def NAME: CheriStore_r; + // Adding a mode switch either side of the load expands to 3 instructions. + // The predicate here is HasCheriCommon, since in the xcheri case we can + // just expand this to an explicit mode load. + let hasSideEffects = 0, mayLoad = 0, mayStore = 1, Size = 12, + Predicates = !listconcat([HasCheriCommon], ExtraPreds) in + def Pseudo_#NAME : Pseudo<(outs), (ins rs2Class:$rs2, rs1Operand:$rs1), [], + "pseudo_"#opcodestr, "$rs2, $rs1">; +} + let hasSideEffects = 0, mayLoad = 0, mayStore = 1, Constraints = "$rd = $rs2" in class CheriStoreCond_r op, string opcodestr, RegisterClass rs2Class, RegisterOperand rs1Operand> @@ -355,16 +383,21 @@ class CCheriStore_rri funct3, string OpcodeStr, // Capability-Inspection Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasCheri] in { +let Predicates = [HasCheriCommon] in { def CGetPerm : Cheri_r<0x0, "cgetperm">; +def : MnemonicAlias<"gcperm", "cgetperm">; def CGetType : Cheri_r<0x1, "cgettype">; +def : MnemonicAlias<"gctype", "cgettype">; def CGetBase : Cheri_r<0x2, "cgetbase">; +def : MnemonicAlias<"gcbase", "cgetbase">; def CGetLen : Cheri_r<0x3, "cgetlen">; +def : MnemonicAlias<"gclen", "cgetlen">; def CGetTag : Cheri_r<0x4, "cgettag">; -def CGetSealed : Cheri_r<0x5, "cgetsealed">; -def CGetOffset : Cheri_r<0x6, "cgetoffset">; +def : MnemonicAlias<"gctag", "cgettag">; def CGetFlags : Cheri_r<0x7, "cgetflags">; +// NB: No alias for gcmode->cgetflags since the result is inverted. def CGetHigh : Cheri_r<0x17, "cgethigh">; +def : MnemonicAlias<"gchi", "cgethigh">; // For backwards compatibility we still accept cgetaddr from assembly. let mayStore = false, mayLoad = false, Size = 4, isCodeGenOnly = false, hasSideEffects = false in @@ -372,46 +405,76 @@ def PseudoCGetAddr : Pseudo<(outs GPR:$rd), (ins GPCR:$cs1), [], "cgetaddr", "$rd, $cs1">; } +let Predicates = [HasXCheriAll] in { +def CGetSealed : Cheri_r<0x5, "cgetsealed">; +def CGetOffset : Cheri_r<0x6, "cgetoffset">; +} + //===----------------------------------------------------------------------===// // Capability-Modification Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasCheri] in { -let defsCanBeSealed = 1 in -def CSeal : Cheri_rr<0xb, "cseal", GPCR, GPCR>; -def CUnseal : Cheri_rr<0xc, "cunseal", GPCR, GPCR>; +let Predicates = [HasCheriCommon] in { def CAndPerm : Cheri_rr<0xd, "candperm">; +def : MnemonicAlias<"acperm", "candperm">; def CSetFlags : Cheri_rr<0xe, "csetflags">; -def CSetOffset : Cheri_rr<0xf, "csetoffset">; +// NB: No alias for scmode->csetflags since the argument is inverted. def CSetAddr : Cheri_rr<0x10, "csetaddr">; +def : MnemonicAlias<"scaddr", "csetaddr">; def CSetHigh : Cheri_rr<0x16, "csethigh">; +def : MnemonicAlias<"schi", "csethigh">; let isReMaterializable = 1, isAsCheapAsAMove = 1 in def CIncOffset : Cheri_rr<0x11, "cincoffset">; +def : InstAlias<"add $cd, $cs1, $rs2", + (CIncOffset GPCR:$cd, GPCR:$cs1, GPR:$rs2), 0>; let isReMaterializable = 1, isAsCheapAsAMove = 1 in def CIncOffsetImm : Cheri_ri<0x1, "cincoffset", 1>; +def : InstAlias<"addi $cd, $cs1, $imm", + (CIncOffsetImm GPCR:$cd, GPCR:$cs1, simm12:$imm), 0>; +def : InstAlias<"add $cd, $cs1, $imm", + (CIncOffsetImm GPCR:$cd, GPCR:$cs1, simm12:$imm), 0>; def CSetBounds : Cheri_rr<0x8, "csetbounds">; +def : InstAlias<"scbndsr $cd, $cs1, $rs2", + (CSetBounds GPCR:$cd, GPCR:$cs1, GPR:$rs2), 0>; def CSetBoundsExact : Cheri_rr<0x9, "csetboundsexact">; +def : InstAlias<"scbnds $cd, $cs1, $rs2", + (CSetBoundsExact GPCR:$cd, GPCR:$cs1, GPR:$rs2), 0>; def CSetBoundsImm : Cheri_ri<0x2, "csetbounds", 0>; -def CClearTag : Cheri_r<0xb, "ccleartag", GPCR>; +// TODO: should restrict the valid immediates for scbnds(i) +def : InstAlias<"scbndsi $cd, $cs1, $imm", + (CSetBoundsImm GPCR:$cd, GPCR:$cs1, uimm12:$imm), 0>; +def : InstAlias<"scbnds $cd, $cs1, $imm", + (CSetBoundsImm GPCR:$cd, GPCR:$cs1, uimm12:$imm), 0>; let defsCanBeSealed = 1 in def CBuildCap : Cheri_rr<0x1d, "cbuildcap", GPCR, GPCR, GPCRC0IsDDC>; -def CCopyType : Cheri_rr<0x1e, "ccopytype", GPCR, GPCR>; -let defsCanBeSealed = 1 in -def CCSeal : Cheri_rr<0x1f, "ccseal", GPCR, GPCR>; +def : InstAlias<"cbld $cd, $cs1, $cs2", + (CBuildCap GPCR:$cd, GPCRNoC0:$cs1, GPCR:$cs2), 0>; let defsCanBeSealed = 1 in def CSealEntry : Cheri_r<0x11, "csealentry", GPCR>; +def : MnemonicAlias<"sentry", "csealentry">; def : InstAlias<"cincoffsetimm $cd, $cs1, $imm", (CIncOffsetImm GPCR:$cd, GPCR:$cs1, simm12:$imm), 0>; def : InstAlias<"csetboundsimm $cd, $cs1, $imm", (CSetBoundsImm GPCR:$cd, GPCR:$cs1, uimm12:$imm), 0>; -} +} // Predicates = [HasCheriCommon] + +let Predicates = [HasXCheriAll] in { +let defsCanBeSealed = 1 in +def CSeal : Cheri_rr<0xb, "cseal", GPCR, GPCR>; +def CUnseal : Cheri_rr<0xc, "cunseal", GPCR, GPCR>; +def CSetOffset : Cheri_rr<0xf, "csetoffset">; +def CClearTag : Cheri_r<0xb, "ccleartag", GPCR>; +def CCopyType : Cheri_rr<0x1e, "ccopytype", GPCR, GPCR>; +let defsCanBeSealed = 1 in +def CCSeal : Cheri_rr<0x1f, "ccseal", GPCR, GPCR>; +} // Predicates = [HasXCheriAll] //===----------------------------------------------------------------------===// // Pointer-Arithmetic Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasCheri] in { +let Predicates = [HasCheriCommon] in { let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in def PseudoCSub : Pseudo<(outs GPR:$rd), (ins GPCR:$cs1, GPCR:$cs2), [], @@ -425,7 +488,7 @@ def CMove : Cheri_r<0xa, "cmove", GPCR>; // Control-Flow Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasCheri] in { +let Predicates = [HasXCheriAll] in { let isCall = 1, hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def JALR_CAP : RVInstCheriSrcDst<0x7f, 0xc, 0, OPC_CHERI, (outs GPCR:$rd), (ins GPCR:$rs1), "jalr.cap", "$rd, $rs1">; @@ -452,18 +515,21 @@ def : InstAlias<"ret.pcc", (JALR_PCC X0, X1), 2>; // Assertion Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasCheri] in { +let Predicates = [HasCheriCommon] in { def CTestSubset : Cheri_rr<0x20, "ctestsubset", GPR, GPCR, GPCRC0IsDDC>; +def : InstAlias<"scss $rd, $cs1, $cs2", + (CTestSubset GPR:$rd, GPCRNoC0:$cs1, GPCR:$cs2), 0>; def CSEQX : Cheri_rr<0x21, "csetequalexact", GPR, GPCR, GPCR>; def : InstAlias<"cseqx $rd, $cs1, $cs2", (CSEQX GPR:$rd, GPCR:$cs1, GPCR:$cs2)>; +def : InstAlias<"sceq $rd, $cs1, $cs2", (CSEQX GPR:$rd, GPCR:$cs1, GPCR:$cs2), 0>; } //===----------------------------------------------------------------------===// // Special Capabilty Register Access Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasCheri] in { +let Predicates = [HasCheriCommon] in { let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in def CSpecialRW : RVInstCheriSCR<0x1, 0, OPC_CHERI, (outs GPCR:$rd), (ins special_capreg:$imm5, GPCR:$rs1), @@ -479,7 +545,7 @@ def : InstAlias<"cspecialw $scr, $cs", // Fast Register-Clearing Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasCheri], hasSideEffects = 1 in { +let Predicates = [HasXCheriAll], hasSideEffects = 1 in { def CClear : Cheri_clear<0xe, "cclear">; def FPClear : Cheri_clear<0x10, "fpclear">; } @@ -488,11 +554,12 @@ def FPClear : Cheri_clear<0x10, "fpclear">; // Adjusting to Compressed Capability Precision Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasCheri] in { +let Predicates = [HasXCheriAll] in { def CRRL : Cheri_r<0x8, "croundrepresentablelength", GPR, GPR>; -def CRAM : Cheri_r<0x9, "crepresentablealignmentmask", GPR, GPR>; - def : InstAlias<"crrl $rd, $rs1", (CRRL GPR:$rd, GPR:$rs1)>; +} +let Predicates = [HasCheriCommon] in { +def CRAM : Cheri_r<0x9, "crepresentablealignmentmask", GPR, GPR>; def : InstAlias<"cram $rd, $rs1", (CRAM GPR:$rd, GPR:$rs1)>; } @@ -500,156 +567,126 @@ def : InstAlias<"cram $rd, $rs1", (CRAM GPR:$rd, GPR:$rs1)>; // Tag-Memory Access Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasCheri], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in +let Predicates = [HasXCheriAll], hasSideEffects = 0, mayLoad = 1, mayStore = 0 in def CLoadTags : Cheri_r<0x12, "cloadtags", GPR, GPCRMemZeroOffset>; //===----------------------------------------------------------------------===// // Memory-Access with Explicit Address Type Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasCheri] in { -def LB_DDC : CheriLoad_r<0b00000, "lb.ddc", GPR, GPRMemZeroOffset>; -def LH_DDC : CheriLoad_r<0b00001, "lh.ddc", GPR, GPRMemZeroOffset>; -def LW_DDC : CheriLoad_r<0b00010, "lw.ddc", GPR, GPRMemZeroOffset>; -def LBU_DDC : CheriLoad_r<0b00100, "lbu.ddc", GPR, GPRMemZeroOffset>; -def LHU_DDC : CheriLoad_r<0b00101, "lhu.ddc", GPR, GPRMemZeroOffset>; -} - -let Predicates = [HasCheri, IsRV64] in { -def LWU_DDC : CheriLoad_r<0b00110, "lwu.ddc", GPR, GPRMemZeroOffset>; -def LD_DDC : CheriLoad_r<0b00011, "ld.ddc", GPR, GPRMemZeroOffset>; -} - -let DecoderNamespace = "RISCV32Only_", - Predicates = [HasCheri, IsRV32] in -def LC_DDC_64 : CheriLoad_r<0b00011, "lc.ddc", GPCR, GPRMemZeroOffset>; - -let Predicates = [HasCheri, IsRV64] in -def LC_DDC_128 : CheriLoad_r<0b10111, "lc.ddc", GPCR, GPRMemZeroOffset>; - -let Predicates = [HasCheri] in { -def SB_DDC : CheriStore_r<0b00000, "sb.ddc", GPR, GPRMemZeroOffset>; -def SH_DDC : CheriStore_r<0b00001, "sh.ddc", GPR, GPRMemZeroOffset>; -def SW_DDC : CheriStore_r<0b00010, "sw.ddc", GPR, GPRMemZeroOffset>; -} - -let Predicates = [HasCheri, IsRV64] in { -def SD_DDC : CheriStore_r<0b00011, "sd.ddc", GPR, GPRMemZeroOffset>; -} - -let DecoderNamespace = "RISCV32Only_", - Predicates = [HasCheri, IsRV32] in -def SC_DDC_64 : CheriStore_r<0b00011, "sc.ddc", GPCR, GPRMemZeroOffset>; +defm LB_DDC : ExplicitCheriLoad_r<0b00000, "lb.ddc", GPR, GPRMemZeroOffset>; +defm LH_DDC : ExplicitCheriLoad_r<0b00001, "lh.ddc", GPR, GPRMemZeroOffset>; +defm LW_DDC : ExplicitCheriLoad_r<0b00010, "lw.ddc", GPR, GPRMemZeroOffset>; +defm LBU_DDC : ExplicitCheriLoad_r<0b00100, "lbu.ddc", GPR, GPRMemZeroOffset>; +defm LHU_DDC : ExplicitCheriLoad_r<0b00101, "lhu.ddc", GPR, GPRMemZeroOffset>; -let Predicates = [HasCheri, IsRV64] in -def SC_DDC_128 : CheriStore_r<0b00100, "sc.ddc", GPCR, GPRMemZeroOffset>; +defm LWU_DDC : ExplicitCheriLoad_r<0b00110, "lwu.ddc", GPR, GPRMemZeroOffset, [IsRV64]>; +defm LD_DDC : ExplicitCheriLoad_r<0b00011, "ld.ddc", GPR, GPRMemZeroOffset, [IsRV64]>; -let Predicates = [HasCheri] in { -def LB_CAP : CheriLoad_r<0b01000, "lb.cap", GPR, GPCRMemZeroOffset>; -def LH_CAP : CheriLoad_r<0b01001, "lh.cap", GPR, GPCRMemZeroOffset>; -def LW_CAP : CheriLoad_r<0b01010, "lw.cap", GPR, GPCRMemZeroOffset>; -def LBU_CAP : CheriLoad_r<0b01100, "lbu.cap", GPR, GPCRMemZeroOffset>; -def LHU_CAP : CheriLoad_r<0b01101, "lhu.cap", GPR, GPCRMemZeroOffset>; -} +let DecoderNamespace = "RISCV32Only_" in +defm LC_64_DDC : ExplicitCheriLoad_r<0b00011, "lc.ddc", GPCR, GPRMemZeroOffset, [IsRV32]>; -let Predicates = [HasCheri, IsRV64] in { -def LWU_CAP : CheriLoad_r<0b01110, "lwu.cap", GPR, GPCRMemZeroOffset>; -def LD_CAP : CheriLoad_r<0b01011, "ld.cap", GPR, GPCRMemZeroOffset>; -} +defm LC_128_DDC : ExplicitCheriLoad_r<0b10111, "lc.ddc", GPCR, GPRMemZeroOffset, [IsRV64]>; -let DecoderNamespace = "RISCV32Only_", - Predicates = [HasCheri, IsRV32] in -def LC_CAP_64 : CheriLoad_r<0b01011, "lc.cap", GPCR, GPCRMemZeroOffset>; +defm SB_DDC : ExplicitCheriStore_r<0b00000, "sb.ddc", GPR, GPRMemZeroOffset>; +defm SH_DDC : ExplicitCheriStore_r<0b00001, "sh.ddc", GPR, GPRMemZeroOffset>; +defm SW_DDC : ExplicitCheriStore_r<0b00010, "sw.ddc", GPR, GPRMemZeroOffset>; +defm SD_DDC : ExplicitCheriStore_r<0b00011, "sd.ddc", GPR, GPRMemZeroOffset, [IsRV64]>; +let DecoderNamespace = "RISCV32Only_" in +defm SC_64_DDC : ExplicitCheriStore_r<0b00011, "sc.ddc", GPCR, GPRMemZeroOffset, [IsRV32]>; +defm SC_128_DDC : ExplicitCheriStore_r<0b00100, "sc.ddc", GPCR, GPRMemZeroOffset, [IsRV64]>; -let Predicates = [HasCheri, IsRV64] in -def LC_CAP_128 : CheriLoad_r<0b11111, "lc.cap", GPCR, GPCRMemZeroOffset>; +defm LB_CAP : ExplicitCheriLoad_r<0b01000, "lb.cap", GPR, GPCRMemZeroOffset>; +defm LH_CAP : ExplicitCheriLoad_r<0b01001, "lh.cap", GPR, GPCRMemZeroOffset>; +defm LW_CAP : ExplicitCheriLoad_r<0b01010, "lw.cap", GPR, GPCRMemZeroOffset>; +defm LBU_CAP : ExplicitCheriLoad_r<0b01100, "lbu.cap", GPR, GPCRMemZeroOffset>; +defm LHU_CAP : ExplicitCheriLoad_r<0b01101, "lhu.cap", GPR, GPCRMemZeroOffset>; -let Predicates = [HasCheri] in { -def SB_CAP : CheriStore_r<0b01000, "sb.cap", GPR, GPCRMemZeroOffset>; -def SH_CAP : CheriStore_r<0b01001, "sh.cap", GPR, GPCRMemZeroOffset>; -def SW_CAP : CheriStore_r<0b01010, "sw.cap", GPR, GPCRMemZeroOffset>; -} +defm LWU_CAP : ExplicitCheriLoad_r<0b01110, "lwu.cap", GPR, GPCRMemZeroOffset, [IsRV64]>; +defm LD_CAP : ExplicitCheriLoad_r<0b01011, "ld.cap", GPR, GPCRMemZeroOffset, [IsRV64]>; -let Predicates = [HasCheri, IsRV64] in { -def SD_CAP : CheriStore_r<0b01011, "sd.cap", GPR, GPCRMemZeroOffset>; -} +let DecoderNamespace = "RISCV32Only_" in +defm LC_64_CAP : ExplicitCheriLoad_r<0b01011, "lc.cap", GPCR, GPCRMemZeroOffset, [IsRV32]>; -let DecoderNamespace = "RISCV32Only_", - Predicates = [HasCheri, IsRV32] in -def SC_CAP_64 : CheriStore_r<0b01011, "sc.cap", GPCR, GPCRMemZeroOffset>; +defm LC_128_CAP : ExplicitCheriLoad_r<0b11111, "lc.cap", GPCR, GPCRMemZeroOffset, [IsRV64]>; -let Predicates = [HasCheri, IsRV64] in -def SC_CAP_128 : CheriStore_r<0b01100, "sc.cap", GPCR, GPCRMemZeroOffset>; +defm SB_CAP : ExplicitCheriStore_r<0b01000, "sb.cap", GPR, GPCRMemZeroOffset>; +defm SH_CAP : ExplicitCheriStore_r<0b01001, "sh.cap", GPR, GPCRMemZeroOffset>; +defm SW_CAP : ExplicitCheriStore_r<0b01010, "sw.cap", GPR, GPCRMemZeroOffset>; +defm SD_CAP : ExplicitCheriStore_r<0b01011, "sd.cap", GPR, GPCRMemZeroOffset, [IsRV64]>; +let DecoderNamespace = "RISCV32Only_" in +defm SC_64_CAP : ExplicitCheriStore_r<0b01011, "sc.cap", GPCR, GPCRMemZeroOffset, [IsRV32]>; +defm SC_128_CAP : ExplicitCheriStore_r<0b01100, "sc.cap", GPCR, GPCRMemZeroOffset, [IsRV64]>; -let Predicates = [HasCheri, HasStdExtA] in { +let Predicates = [HasXCheriAll, HasStdExtA] in { def LR_B_DDC : CheriLoad_r<0b10000, "lr.b.ddc", GPR, GPRMemZeroOffset>; def LR_H_DDC : CheriLoad_r<0b10001, "lr.h.ddc", GPR, GPRMemZeroOffset>; def LR_W_DDC : CheriLoad_r<0b10010, "lr.w.ddc", GPR, GPRMemZeroOffset>; } -let Predicates = [HasCheri, HasStdExtA, IsRV64] in +let Predicates = [HasXCheriAll, HasStdExtA, IsRV64] in def LR_D_DDC : CheriLoad_r<0b10011, "lr.d.ddc", GPR, GPRMemZeroOffset>; let DecoderNamespace = "RISCV32Only_", - Predicates = [HasCheri, HasStdExtA, IsRV32] in + Predicates = [HasXCheriAll, HasStdExtA, IsRV32] in def LR_C_DDC_64 : CheriLoad_r<0b10011, "lr.c.ddc", GPCR, GPRMemZeroOffset>; -let Predicates = [HasCheri, HasStdExtA, IsRV64] in +let Predicates = [HasXCheriAll, HasStdExtA, IsRV64] in def LR_C_DDC_128 : CheriLoad_r<0b10100, "lr.c.ddc", GPCR, GPRMemZeroOffset>; -let Predicates = [HasCheri, HasStdExtA] in { +let Predicates = [HasXCheriAll, HasStdExtA] in { def LR_B_CAP : CheriLoad_r<0b11000, "lr.b.cap", GPR, GPCRMemZeroOffset>; def LR_H_CAP : CheriLoad_r<0b11001, "lr.h.cap", GPR, GPCRMemZeroOffset>; def LR_W_CAP : CheriLoad_r<0b11010, "lr.w.cap", GPR, GPCRMemZeroOffset>; } -let Predicates = [HasCheri, HasStdExtA, IsRV64] in +let Predicates = [HasXCheriAll, HasStdExtA, IsRV64] in def LR_D_CAP : CheriLoad_r<0b11011, "lr.d.cap", GPR, GPCRMemZeroOffset>; let DecoderNamespace = "RISCV32Only_", - Predicates = [HasCheri, HasStdExtA, IsRV32] in + Predicates = [HasXCheriAll, HasStdExtA, IsRV32] in def LR_C_CAP_64 : CheriLoad_r<0b11011, "lr.c.cap", GPCR, GPCRMemZeroOffset>; -let Predicates = [HasCheri, HasStdExtA, IsRV64] in +let Predicates = [HasXCheriAll, HasStdExtA, IsRV64] in def LR_C_CAP_128 : CheriLoad_r<0b11100, "lr.c.cap", GPCR, GPCRMemZeroOffset>; -let Predicates = [HasCheri, HasStdExtA] in { +let Predicates = [HasXCheriAll, HasStdExtA] in { def SC_B_DDC : CheriStoreCond_r<0b10000, "sc.b.ddc", GPR, GPRMemZeroOffset>; def SC_H_DDC : CheriStoreCond_r<0b10001, "sc.h.ddc", GPR, GPRMemZeroOffset>; def SC_W_DDC : CheriStoreCond_r<0b10010, "sc.w.ddc", GPR, GPRMemZeroOffset>; } -let Predicates = [HasCheri, HasStdExtA, IsRV64] in +let Predicates = [HasXCheriAll, HasStdExtA, IsRV64] in def SC_D_DDC : CheriStoreCond_r<0b10011, "sc.d.ddc", GPR, GPRMemZeroOffset>; let DecoderNamespace = "RISCV32Only_", - Predicates = [HasCheri, HasStdExtA, IsRV32] in + Predicates = [HasXCheriAll, HasStdExtA, IsRV32] in def SC_C_DDC_64 : CheriStoreCond_r<0b10011, "sc.c.ddc", GPCR, GPRMemZeroOffset>; -let Predicates = [HasCheri, HasStdExtA, IsRV64] in +let Predicates = [HasXCheriAll, HasStdExtA, IsRV64] in def SC_C_DDC_128 : CheriStoreCond_r<0b10100, "sc.c.ddc", GPCR, GPRMemZeroOffset>; -let Predicates = [HasCheri, HasStdExtA] in { +let Predicates = [HasXCheriAll, HasStdExtA] in { def SC_B_CAP : CheriStoreCond_r<0b11000, "sc.b.cap", GPR, GPCRMemZeroOffset>; def SC_H_CAP : CheriStoreCond_r<0b11001, "sc.h.cap", GPR, GPCRMemZeroOffset>; def SC_W_CAP : CheriStoreCond_r<0b11010, "sc.w.cap", GPR, GPCRMemZeroOffset>; } -let Predicates = [HasCheri, HasStdExtA, IsRV64] in +let Predicates = [HasXCheriAll, HasStdExtA, IsRV64] in def SC_D_CAP : CheriStoreCond_r<0b11011, "sc.d.cap", GPR, GPCRMemZeroOffset>; let DecoderNamespace = "RISCV32Only_", - Predicates = [HasCheri, HasStdExtA, IsRV32] in + Predicates = [HasXCheriAll, HasStdExtA, IsRV32] in def SC_C_CAP_64 : CheriStoreCond_r<0b11011, "sc.c.cap", GPCR, GPCRMemZeroOffset>; -let Predicates = [HasCheri, HasStdExtA, IsRV64] in +let Predicates = [HasXCheriAll, HasStdExtA, IsRV64] in def SC_C_CAP_128 : CheriStoreCond_r<0b11100, "sc.c.cap", GPCR, GPCRMemZeroOffset>; //===----------------------------------------------------------------------===// // Memory-Access Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasCheri, IsRV32, NotCapMode] in { +let Predicates = [HasCheriCommon, IsRV32, NotCapMode] in { let DecoderNamespace = "RISCV32Only_", hasSideEffects = 0, mayLoad = 1, mayStore = 0 in def LC_64 : RVInstI<0x3, OPC_LOAD, (outs GPCR:$rd), @@ -670,7 +707,7 @@ def : InstAlias<"sc $rs2, (${rs1})", } } -let Predicates = [HasCheri, IsRV64, NotCapMode] in { +let Predicates = [HasCheriCommon, IsRV64, NotCapMode] in { let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in def LC_128 : RVInstI<0x2, OPC_MISC_MEM, (outs GPCR:$rd), (ins GPR:$rs1, simm12:$imm12), @@ -690,13 +727,13 @@ def : InstAlias<"sc $rs2, (${rs1})", } let DecoderNamespace = "RISCV32Only_", - Predicates = [HasCheri, HasStdExtA, IsRV32, NotCapMode] in { + Predicates = [HasCheriCommon, HasStdExtA, IsRV32, NotCapMode] in { defm LR_C : LR_C_r_aq_rl<"64", 0b011, "lr.c">; defm SC_C : AMO_C_rr_aq_rl<"64", 0b00011, 0b011, "sc.c", GPR>; defm AMOSWAP_C : AMO_C_rr_aq_rl<"64", 0b00001, 0b011, "amoswap.c", GPCR>; } -let Predicates = [HasCheri, HasStdExtA, IsRV64, NotCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtA, IsRV64, NotCapMode] in { defm LR_C : LR_C_r_aq_rl<"128", 0b100, "lr.c">; defm SC_C : AMO_C_rr_aq_rl<"128", 0b00011, 0b100, "sc.c", GPR>; defm AMOSWAP_C : AMO_C_rr_aq_rl<"128", 0b00001, 0b100, "amoswap.c", GPCR>; @@ -711,7 +748,7 @@ defm AMOSWAP_C : AMO_C_rr_aq_rl<"128", 0b00001, 0b100, "amoswap.c", GPCR>; let DecoderNamespace = "CapModeOnly_" in { let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { -let Predicates = [HasCheri, IsCapMode] in { +let Predicates = [HasCheriCommon, IsCapMode] in { def AUIPCC : RVInstU; @@ -723,41 +760,54 @@ let isCall = 1 in def CJALR : RVInstI<0b000, OPC_JALR, (outs GPCR:$rd), (ins GPCR:$rs1, simm12:$imm12), "cjalr", "$rd, ${imm12}(${rs1})">; -} // Predicates = [HasCheri, IsCapMode] +} // Predicates = [HasCheriCommon, IsCapMode] } // hasSideEffects = 0, mayLoad = 0, mayStore = 0 } // DecoderNameSpace = "CapModeOnly_" -let Predicates = [HasCheri, IsCapMode] in { -def : InstAlias<"j $offset", (CJAL C0, simm21_lsb0_jal:$offset)>; -def : InstAlias<"cjal $offset", (CJAL C1, simm21_lsb0_jal:$offset)>; +// Expands to an instruction alias with and without a c prefix for loads/stores/jumps +multiclass CPrefixedInstAlias { + def : InstAlias<"c" # Asm, Result, Emit>; + def : InstAlias; +} -// Non-canonical form; JAL X0 and CJAL X0 are semantically identical so "j" is -// the canonical form, but we provide this for completeness. -def : InstAlias<"cj $offset", (CJAL C0, simm21_lsb0_jal:$offset), 0>; +let Predicates = [HasCheriCommon, IsCapMode] in { +// "cj" is the non-canonical form, but we provide this for completeness. +defm: CPrefixedInstAlias<"j $offset", (CJAL C0, simm21_lsb0_jal:$offset), 1>; +defm: CPrefixedInstAlias<"jal $offset", (CJAL C1, simm21_lsb0_jal:$offset), 1>; // Non-zero offset aliases of "cjalr" are the lowest weight, followed by the // two-register form, then the one-register forms and finally "cret". -def : InstAlias<"cjr $rs", (CJALR C0, GPCR:$rs, 0), 3>; -def : InstAlias<"cjr ${offset}(${rs})", (CJALR C0, GPCR:$rs, simm12:$offset)>; -def : InstAlias<"cjalr $rs", (CJALR C1, GPCR:$rs, 0), 3>; -def : InstAlias<"cjalr ${offset}(${rs})", (CJALR C1, GPCR:$rs, simm12:$offset)>; -def : InstAlias<"cjalr $rd, $rs", (CJALR GPCR:$rd, GPCR:$rs, 0), 2>; -def : InstAlias<"cret", (CJALR C0, C1, 0), 4>; +defm: CPrefixedInstAlias<"jr $rs", (CJALR C0, GPCR:$rs, 0), 3>; +defm: CPrefixedInstAlias<"jr ${offset}(${rs})", (CJALR C0, GPCR:$rs, simm12:$offset), 1>; +defm: CPrefixedInstAlias<"jalr $rs", (CJALR C1, GPCR:$rs, 0), 3>; +defm: CPrefixedInstAlias<"jalr ${offset}(${rs})", (CJALR C1, GPCR:$rs, simm12:$offset), 1>; +defm: CPrefixedInstAlias<"jalr $rd, $rs", (CJALR GPCR:$rd, GPCR:$rs, 0), 2>; +defm: CPrefixedInstAlias<"ret", (CJALR C0, C1, 0), 4>; // Non-canonical forms for jump targets also accepted by the assembler. -def : InstAlias<"cjr $rs, $offset", (CJALR C0, GPCR:$rs, simm12:$offset), 0>; -def : InstAlias<"cjalr $rs, $offset", (CJALR C1, GPCR:$rs, simm12:$offset), 0>; -def : InstAlias<"cjalr $rd, $rs, $offset", (CJALR GPCR:$rd, GPCR:$rs, simm12:$offset), 0>; -} // Predicates = [HasCheri, IsCapMode] - -// Expands to an instruction alias with and without a c prefix for loads/stores -multiclass CPrefixedInstAlias { - def : InstAlias<"c" # Asm, Result, 0>; - def : InstAlias; +defm: CPrefixedInstAlias<"jr $rs, $offset", (CJALR C0, GPCR:$rs, simm12:$offset), 0>; +defm: CPrefixedInstAlias<"jalr $rs, $offset", (CJALR C1, GPCR:$rs, simm12:$offset), 0>; +defm: CPrefixedInstAlias<"jalr $rd, $rs, $offset", (CJALR GPCR:$rd, GPCR:$rs, simm12:$offset), 0>; +} // Predicates = [HasCheriCommon, IsCapMode] + +let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in +class CheriModeSw funct7, string opcodestr> + : RVInst<(outs ), (ins ), opcodestr, "", [], InstFormatR> { + let Inst{31-25} = funct7; + let Inst{24-20} = 0b00000; + let Inst{19-15} = 0b00000; + let Inst{14-12} = 0b001; + let Inst{11-7} = 0b00000; + let Inst{6-0} = 0b0110011; } +let Predicates = [HasXCheriStdCompat] in { +def ModeSwitchCap : CheriModeSw<0b0001001, "modesw.cap">; +def ModeSwitchInt : CheriModeSw<0b0001010, "modesw.int">; +} // HasXCheriStdCompat + -let Predicates = [HasCheri, IsCapMode] in { +let Predicates = [HasCheriCommon, IsCapMode] in { defm CLB : CheriLoad_ri<0b000, "lb">; defm CLH : CheriLoad_ri<0b001, "lh">; defm CLW : CheriLoad_ri<0b010, "lw">; @@ -767,15 +817,15 @@ defm CLHU : CheriLoad_ri<0b101, "lhu">; defm CSB : CheriStore_ri<0b000, "sb">; defm CSH : CheriStore_ri<0b001, "sh">; defm CSW : CheriStore_ri<0b010, "sw">; -} // Predicates = [HasCheri, IsCapMode] +} // Predicates = [HasCheriCommon, IsCapMode] -let Predicates = [HasCheri, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, IsRV64, IsCapMode] in { defm CLWU : CheriLoad_ri<0b110, "lwu">; defm CLD : CheriLoad_ri<0b011, "ld">; defm CSD : CheriStore_ri<0b011, "sd">; -} // Predicates = [HasCheri, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, IsRV64, IsCapMode] -let Predicates = [HasCheri, IsRV32, IsCapMode] in { +let Predicates = [HasCheriCommon, IsRV32, IsCapMode] in { let DecoderNamespace = "RISCV32CapModeOnly_", hasSideEffects = 0, mayLoad = 1, mayStore = 0 in def CLC_64 : RVInstI<0x3, OPC_LOAD, (outs GPCR:$rd), @@ -798,7 +848,7 @@ defm : CPrefixedInstAlias<"sc $rs2, (${rs1})", (CSC_64 GPCR:$rs2, GPCR:$rs1, 0)>; } -let Predicates = [HasCheri, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, IsRV64, IsCapMode] in { let DecoderNamespace = "CapModeOnly_", hasSideEffects = 0, mayLoad = 1, mayStore = 0 in def CLC_128 : RVInstI<0x2, OPC_MISC_MEM, (outs GPCR:$rd), @@ -821,7 +871,7 @@ defm : CPrefixedInstAlias<"sc $rs2, (${rs1})", (CSC_128 GPCR:$rs2, GPCR:$rs1, 0)>; } -let Predicates = [HasCheri, IsCapMode] in { +let Predicates = [HasCheriCommon, IsCapMode] in { defm : CPrefixedInstAlias<"lb $rd, (${rs1})", (CLB GPR:$rd, GPCR:$rs1, 0)>; defm : CPrefixedInstAlias<"lh $rd, (${rs1})", (CLH GPR:$rd, GPCR:$rs1, 0)>; defm : CPrefixedInstAlias<"lw $rd, (${rs1})", (CLW GPR:$rd, GPCR:$rs1, 0)>; @@ -831,17 +881,17 @@ defm : CPrefixedInstAlias<"lhu $rd, (${rs1})", (CLHU GPR:$rd, GPCR:$rs1, 0)>; defm : CPrefixedInstAlias<"sb $rs2, (${rs1})", (CSB GPR:$rs2, GPCR:$rs1, 0)>; defm : CPrefixedInstAlias<"sh $rs2, (${rs1})", (CSH GPR:$rs2, GPCR:$rs1, 0)>; defm : CPrefixedInstAlias<"sw $rs2, (${rs1})", (CSW GPR:$rs2, GPCR:$rs1, 0)>; -} // Predicates = [HasCheri, IsCapMode] +} // Predicates = [HasCheriCommon, IsCapMode] -let Predicates = [HasCheri, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, IsRV64, IsCapMode] in { defm : CPrefixedInstAlias<"lwu $rd, (${rs1})", (CLWU GPR:$rd, GPCR:$rs1, 0)>; defm : CPrefixedInstAlias<"ld $rd, (${rs1})", (CLD GPR:$rd, GPCR:$rs1, 0)>; defm : CPrefixedInstAlias<"sd $rs2, (${rs1})", (CSD GPR:$rs2, GPCR:$rs1, 0)>; -} // Predicates = [HasCheri, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, IsRV64, IsCapMode] /// 'A' (Atomic Instructions) extension -let Predicates = [HasCheri, HasStdExtA, IsCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtA, IsCapMode] in { defm CLR_B : CLR_r_aq_rl<0b000, "lr.b">; defm CSC_B : CAMO_rr_aq_rl<0b00011, 0b000, "sc.b">; @@ -859,9 +909,9 @@ defm CAMOMIN_W : CAMO_rr_aq_rl<0b10000, 0b010, "amomin.w">; defm CAMOMAX_W : CAMO_rr_aq_rl<0b10100, 0b010, "amomax.w">; defm CAMOMINU_W : CAMO_rr_aq_rl<0b11000, 0b010, "amominu.w">; defm CAMOMAXU_W : CAMO_rr_aq_rl<0b11100, 0b010, "amomaxu.w">; -} // Predicates = [HasCheri, HasStdExtA, IsCapMode] +} // Predicates = [HasCheriCommon, HasStdExtA, IsCapMode] -let Predicates = [HasCheri, HasStdExtA, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtA, IsRV64, IsCapMode] in { defm CLR_D : CLR_r_aq_rl<0b011, "lr.d">; defm CSC_D : CAMO_rr_aq_rl<0b00011, 0b011, "sc.d">; defm CAMOSWAP_D : CAMO_rr_aq_rl<0b00001, 0b011, "amoswap.d">; @@ -873,9 +923,9 @@ defm CAMOMIN_D : CAMO_rr_aq_rl<0b10000, 0b011, "amomin.d">; defm CAMOMAX_D : CAMO_rr_aq_rl<0b10100, 0b011, "amomax.d">; defm CAMOMINU_D : CAMO_rr_aq_rl<0b11000, 0b011, "amominu.d">; defm CAMOMAXU_D : CAMO_rr_aq_rl<0b11100, 0b011, "amomaxu.d">; -} // Predicates = [HasCheri, HasStdExtA, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, HasStdExtA, IsRV64, IsCapMode] -let Predicates = [HasCheri, HasStdExtA, IsRV32, IsCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtA, IsRV32, IsCapMode] in { defm CLR_C : CLR_C_r_aq_rl<"64", 0b011, "lr.c", "RISCV32CapModeOnly_">; defm CSC_C : CAMO_C_rr_aq_rl<"64", 0b00011, 0b011, "sc.c", GPR, "RISCV32CapModeOnly_">; @@ -883,7 +933,7 @@ defm CAMOSWAP_C : CAMO_C_rr_aq_rl<"64", 0b00001, 0b011, "amoswap.c", GPCR, "RISCV32CapModeOnly_">; } -let Predicates = [HasCheri, HasStdExtA, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtA, IsRV64, IsCapMode] in { defm CLR_C : CLR_C_r_aq_rl<"128", 0b100, "lr.c">; defm CSC_C : CAMO_C_rr_aq_rl<"128", 0b00011, 0b100, "sc.c", GPR>; defm CAMOSWAP_C : CAMO_C_rr_aq_rl<"128", 0b00001, 0b100, "amoswap.c", GPCR>; @@ -891,7 +941,7 @@ defm CAMOSWAP_C : CAMO_C_rr_aq_rl<"128", 0b00001, 0b100, "amoswap.c", GPCR>; /// 'F' (Single-Precision Floating-Point) extension -let Predicates = [HasCheri, HasStdExtF, IsCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtF, IsCapMode] in { let DecoderNamespace = "CapModeOnly_", hasSideEffects = 0, mayLoad = 1, mayStore = 0 in def CFLW : RVInstI<0b010, OPC_LOAD_FP, (outs FPR32:$rd), @@ -911,11 +961,11 @@ def : InstAlias<"flw $rd, ${imm12}(${rs1})", (CFLW FPR32:$rd, GPCR:$rs1, simm12:$imm12), 0>; def : InstAlias<"fsw $rs2, ${imm12}(${rs1})", (CFSW FPR32:$rs2, GPCR:$rs1, simm12:$imm12), 0>; -} // Predicates = [HasCheri, HasStdExtF, IsCapMode] +} // Predicates = [HasCheriCommon, HasStdExtF, IsCapMode] /// 'D' (Single-Precision Floating-Point) extension -let Predicates = [HasCheri, HasStdExtD, IsCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtD, IsCapMode] in { let DecoderNamespace = "CapModeOnly_", hasSideEffects = 0, mayLoad = 1, mayStore = 0 in def CFLD : RVInstI<0b011, OPC_LOAD_FP, (outs FPR64:$rd), @@ -935,12 +985,12 @@ def : InstAlias<"fld $rd, ${imm12}(${rs1})", (CFLD FPR64:$rd, GPCR:$rs1, simm12:$imm12), 0>; def : InstAlias<"fsd $rs2, ${imm12}(${rs1})", (CFSD FPR64:$rs2, GPCR:$rs1, simm12:$imm12), 0>; -} // Predicates = [HasCheri, HasStdExtD, IsCapMode] +} // Predicates = [HasCheriCommon, HasStdExtD, IsCapMode] /// 'C' (Compressed Instructions) extension let DecoderNamespace = "CapModeOnly_" in { -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] in { let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [C2] in def C_CIncOffsetImm4CSPN : RVInst16CIW<0b000, 0b00, (outs GPCRC:$rd), @@ -954,14 +1004,14 @@ def C_CIncOffsetImm4CSPN : RVInst16CIW<0b000, 0b00, (outs GPCRC:$rd), } let DecoderNamespace = "RISCV32CapModeOnly_", - Predicates = [HasCheri, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in + Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in def C_CFLD : CCheriLoad_ri<0b001, "c.cfld", FPR64C, uimm8_lsb000> { bits<8> imm; let Inst{12-10} = imm{5-3}; let Inst{6-5} = imm{7-6}; } -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in def C_CLC_128 : CCheriLoad_ri<0b001, "c.clc", GPCRC, uimm9_lsb0000> { bits<9> imm; let Inst{12-11} = imm{5-4}; @@ -977,14 +1027,14 @@ def C_CLW : CCheriLoad_ri<0b010, "c.clw", GPRC, uimm7_lsb00> { } let DecoderNamespace = "RISCV32CapModeOnly_", - Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in + Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in def C_CLC_64 : CCheriLoad_ri<0b011, "c.clc", GPCRC, uimm8_lsb000> { bits<8> imm; let Inst{12-10} = imm{5-3}; let Inst{6-5} = imm{7-6}; } -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in def C_CLD : CCheriLoad_ri<0b011, "c.cld", GPRC, uimm8_lsb000> { bits<8> imm; let Inst{12-10} = imm{5-3}; @@ -992,14 +1042,14 @@ def C_CLD : CCheriLoad_ri<0b011, "c.cld", GPRC, uimm8_lsb000> { } let DecoderNamespace = "RISCV32CapModeOnly_", - Predicates = [HasCheri, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in + Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in def C_CFSD : CCheriStore_rri<0b101, "c.cfsd", FPR64C, uimm8_lsb000> { bits<8> imm; let Inst{12-10} = imm{5-3}; let Inst{6-5} = imm{7-6}; } -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in def C_CSC_128 : CCheriStore_rri<0b101, "c.csc", GPCRC, uimm9_lsb0000> { bits<9> imm; let Inst{12-11} = imm{5-4}; @@ -1015,14 +1065,14 @@ def C_CSW : CCheriStore_rri<0b110, "c.csw", GPRC, uimm7_lsb00> { } let DecoderNamespace = "RISCV32CapModeOnly_", - Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in + Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in def C_CSC_64 : CCheriStore_rri<0b111, "c.csc", GPCRC, uimm8_lsb000> { bits<8> imm; let Inst{12-10} = imm{5-3}; let Inst{6-5} = imm{7-6}; } -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in def C_CSD : CCheriStore_rri<0b111, "c.csd", GPRC, uimm8_lsb000> { bits<8> imm; let Inst{12-10} = imm{5-3}; @@ -1031,7 +1081,7 @@ def C_CSD : CCheriStore_rri<0b111, "c.csd", GPRC, uimm8_lsb000> { let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall = 1, DecoderNamespace = "RISCV32CapModeOnly_", Defs = [C1], - Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in + Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in def C_CJAL : RVInst16CJ<0b001, 0b01, (outs), (ins simm12_lsb0:$offset), "c.cjal", "$offset">; @@ -1049,13 +1099,13 @@ def C_CIncOffsetImm16CSP : RVInst16CI<0b011, 0b01, (outs CSP:$rd_wb), } let DecoderNamespace = "RISCV32CapModeOnly_", - Predicates = [HasCheri, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in + Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in def C_CFLDCSP : CCheriStackLoad<0b001, "c.cfldcsp", FPR64, uimm9_lsb000> { let Inst{6-5} = imm{4-3}; let Inst{4-2} = imm{8-6}; } -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in def C_CLCCSP_128 : CCheriStackLoad<0b001, "c.clccsp", GPCRNoC0, uimm10_lsb0000> { let Inst{6} = imm{4}; let Inst{5-2} = imm{9-6}; @@ -1067,13 +1117,13 @@ def C_CLWCSP : CCheriStackLoad<0b010, "c.clwcsp", GPRNoX0, uimm8_lsb00> { } let DecoderNamespace = "RISCV32CapModeOnly_", - Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in + Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in def C_CLCCSP_64 : CCheriStackLoad<0b011, "c.clccsp", GPCRNoC0, uimm9_lsb000> { let Inst{6-5} = imm{4-3}; let Inst{4-2} = imm{8-6}; } -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in def C_CLDCSP : CCheriStackLoad<0b011, "c.cldcsp", GPRNoX0, uimm9_lsb000> { let Inst{6-5} = imm{4-3}; let Inst{4-2} = imm{8-6}; @@ -1095,13 +1145,13 @@ def C_CJALR : RVInst16CR<0b1001, 0b10, (outs), (ins GPCRNoC0:$rs1), "c.cjalr", "$rs1">; let DecoderNamespace = "RISCV32CapModeOnly_", - Predicates = [HasCheri, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in + Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in def C_CFSDCSP : CCheriStackStore<0b101, "c.cfsdcsp", FPR64, uimm9_lsb000> { let Inst{12-10} = imm{5-3}; let Inst{9-7} = imm{8-6}; } -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in def C_CSCCSP_128 : CCheriStackStore<0b101, "c.csccsp", GPCR, uimm10_lsb0000> { let Inst{12-11} = imm{5-4}; let Inst{10-7} = imm{9-6}; @@ -1113,22 +1163,22 @@ def C_CSWCSP : CCheriStackStore<0b110, "c.cswcsp", GPR, uimm8_lsb00> { } let DecoderNamespace = "RISCV32CapModeOnly_", - Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in + Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in def C_CSCCSP_64 : CCheriStackStore<0b111, "c.csccsp", GPCR, uimm9_lsb000> { let Inst{12-10} = imm{5-3}; let Inst{9-7} = imm{8-6}; } -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in def C_CSDCSP : CCheriStackStore<0b111, "c.csdcsp", GPR, uimm9_lsb000> { let Inst{12-10} = imm{5-3}; let Inst{9-7} = imm{8-6}; } -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] } // DecoderNamespace = "CapModeOnly_" -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] in { def : InstAlias<"c.cincoffsetimm4cspn $rd, $rs1, $imm", (C_CIncOffsetImm4CSPN GPCRC:$rd, CSP:$rs1, uimm10_lsb00nonzero:$imm), 0>; def : InstAlias<"c.cincoffsetimm16csp $rd, $imm", @@ -1141,14 +1191,14 @@ def : MnemonicAlias<"c.lwsp", "c.clwcsp">; def : MnemonicAlias<"c.swsp", "c.cswcsp">; def : MnemonicAlias<"c.scsp", "c.csccsp">; def : MnemonicAlias<"c.lcsp", "c.clccsp">; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { def : MnemonicAlias<"c.ld", "c.cld">; def : MnemonicAlias<"c.sd", "c.csd">; def : MnemonicAlias<"c.ldsp", "c.cldcsp">; def : MnemonicAlias<"c.sdsp", "c.csdcsp">; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in { def : MnemonicAlias<"c.fld", "c.cfld">; def : MnemonicAlias<"c.fsd", "c.cfsd">; @@ -1160,7 +1210,7 @@ def : MnemonicAlias<"c.fsdsp", "c.cfsdcsp">; // Pseudo-instructions and codegen patterns //===----------------------------------------------------------------------===// -let Predicates = [HasCheri, IsCapMode] in { +let Predicates = [HasCheriCommon, IsCapMode] in { let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1, Size = 8 in def PseudoCLLC : Pseudo<(outs GPCR:$dst), (ins bare_symbol:$src), [], @@ -1202,7 +1252,7 @@ def PseudoCIncOffsetTPRel : Pseudo<(outs GPCR:$rd), "cincoffset", "$rd, $rs1, $rs2, $src">; } -let Predicates = [HasCheri, HasStdExtD, IsRV32] in { +let Predicates = [HasCheriCommon, HasStdExtD, IsRV32] in { // Stores an FPR via splitting to two GPRs. let hasSideEffects = 0, mayLoad = 0, mayStore = 1, @@ -1220,7 +1270,7 @@ def CheriSplitStoreF64Pseudo : Pseudo<(outs GPR:$tmplo, GPR:$tmphi, GPCR:$tmpdst), (ins FPR64:$src, GPCR:$dst), []>; -} // Predicates = [HasCheri, HasStdExtD, IsRV32] +} // Predicates = [HasCheriCommon, HasStdExtD, IsRV32] class PatGpcr : Pat<(RetVt (OpNode GPCR:$rs1)), (Inst GPCR:$rs1)>; @@ -1247,18 +1297,27 @@ def : PatGpcr; def : PatGpcr; def : PatGpcr; def : PatGpcr; +let Predicates = [HasXCheriAll] in def : PatGpcr; +let Predicates = [HasXCheriAll] in def : PatGpcr; +let Predicates = [HasXCheriStdCompat] in +def : Pat<(XLenVT (int_cheri_cap_offset_get GPCR:$cs1)), + (SUB (XLenVT (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr)), + (CGetBase GPCR:$cs1))>; def : PatGpcr; def : Pat<(XLenVT (int_cheri_cap_address_get GPCR:$cs1)), (PseudoCGetAddr GPCR:$cs1)>; def : PatGpcr; /// Capability-Modification Instructions +let Predicates = [HasXCheriAll] in def : PatGpcrGpcr; +let Predicates = [HasXCheriAll] in def : PatGpcrGpcr; def : PatGpcrGpr; def : PatGpcrGpr; +let Predicates = [HasXCheriAll] in def : PatGpcrGpr; def : PatGpcrGpr; def : PatGpcrGpr; @@ -1267,9 +1326,15 @@ def : PatGpcrSimm12; def : PatGpcrGpr; def : PatGpcrGpr; def : PatGpcrUimm12; +let Predicates = [HasXCheriAll] in def : PatGpcr; +let Predicates = [HasXCheriStdCompat] in +def : Pat<(int_cheri_cap_tag_clear GPCR:$cs1), + (CSetHigh GPCR:$cs1, (CGetHigh GPCR:$cs1))>; def : PatGpcrGpcr; +let Predicates = [HasXCheriAll] in def : PatGpcrGpcr; +let Predicates = [HasXCheriAll] in def : PatGpcrGpcr; def : PatGpcr; @@ -1416,24 +1481,30 @@ def : PatGpcrGpcr; /// Special Capability Register Access Instructions def : Pat<(int_cheri_ddc_get), (CSpecialRW SCR_DDC.Encoding, C0)>; -let Predicates = [HasCheri, IsPureCapABI] in +let Predicates = [HasCheriCommon, IsPureCapABI] in def : Pat<(int_cheri_stack_cap_get), (CLenVT (COPY C2))>; -let Predicates = [HasCheri, IsCapMode] in +let Predicates = [HasCheriCommon, IsCapMode] in def : Pat<(int_cheri_pcc_get), (AUIPCC 0)>; -let Predicates = [HasCheri, NotCapMode] in +let Predicates = [HasCheriCommon, NotCapMode] in def : Pat<(int_cheri_pcc_get), (CSpecialRW SCR_PCC.Encoding, C0)>; /// Fast Register-Clearing Instructions /// Adjusting to Compressed Capability Precision Instructions +let Predicates = [HasXCheriAll] in def : PatGpr; +// CRRL is equivalent to (length + ~mask) & mask. +let Predicates = [HasXCheriStdCompat] in +def : Pat<(XLenVT (int_cheri_round_representable_length (XLenVT GPR:$rs1))), + (AND (ADD GPR:$rs1, (XORI (CRAM GPR:$rs1), -1)), (CRAM GPR:$rs1))>; def : PatGpr; /// Tag-Memory Access Instructions +let Predicates = [HasXCheriAll] in def : PatGpcr; /// Memory-Access with Explicit Address Type Instructions @@ -1442,19 +1513,21 @@ multiclass CheriExplicitLdPat { - def : Pat<(ReturnVt (LoadOp (AddrVt AddrTy:$rs1))), (Inst AddrTy:$rs1)>; + def : Pat<(ReturnVt (LoadOp (AddrVt AddrTy:$rs1))), + (!cast("Pseudo_"#Inst) AddrTy:$rs1)>; } multiclass CheriExplicitStPat { - def : Pat<(StoreOp (StoreVt StTy:$rs2), (AddrVt AddrTy:$rs1)), (Inst StTy:$rs2, AddrTy:$rs1)>; + def : Pat<(StoreOp (StoreVt StTy:$rs2), (AddrVt AddrTy:$rs1)), + (!cast("Pseudo_"#Inst) StTy:$rs2, AddrTy:$rs1)>; } /// DDC-relative loads -let Predicates = [HasCheri, IsCapMode] in { +let Predicates = [HasCheriCommon, IsCapMode] in { defm : CheriExplicitLdPat; defm : CheriExplicitLdPat; defm : CheriExplicitLdPat; @@ -1463,63 +1536,63 @@ defm : CheriExplicitLdPat; defm : CheriExplicitLdPat; } -let Predicates = [HasCheri, IsCapMode, IsRV32] in { +let Predicates = [HasCheriCommon, IsCapMode, IsRV32] in { defm : CheriExplicitLdPat; -defm : CheriExplicitLdPat; +defm : CheriExplicitLdPat; } -let Predicates = [HasCheri, IsCapMode, IsRV64] in { +let Predicates = [HasCheriCommon, IsCapMode, IsRV64] in { defm : CheriExplicitLdPat; defm : CheriExplicitLdPat; defm : CheriExplicitLdPat; defm : CheriExplicitLdPat; -defm : CheriExplicitLdPat; +defm : CheriExplicitLdPat; } -let Predicates = [HasCheri, IsCapMode, HasStdExtF] in -def : Pat<(load (XLenVT GPR:$rs1)), (FMV_W_X (LW_DDC (XLenVT GPR:$rs1)))>; +let Predicates = [HasCheriCommon, IsCapMode, HasStdExtF] in +def : Pat<(load (XLenVT GPR:$rs1)), (FMV_W_X (Pseudo_LW_DDC (XLenVT GPR:$rs1)))>; -let Predicates = [HasCheri, IsCapMode, HasStdExtD, IsRV32] in +let Predicates = [HasCheriCommon, IsCapMode, HasStdExtD, IsRV32] in def : Pat<(load (XLenVT GPR:$rs1)), - (BuildPairF64Pseudo (LW_DDC (XLenVT GPR:$rs1)), - (LW_DDC (ADDI (XLenVT GPR:$rs1), 4)))>; + (BuildPairF64Pseudo (Pseudo_LW_DDC (XLenVT GPR:$rs1)), + (Pseudo_LW_DDC (ADDI (XLenVT GPR:$rs1), 4)))>; -let Predicates = [HasCheri, IsCapMode, HasStdExtD, IsRV64] in -def : Pat<(load (XLenVT GPR:$rs1)), (FMV_D_X (LD_DDC (XLenVT GPR:$rs1)))>; +let Predicates = [HasCheriCommon, IsCapMode, HasStdExtD, IsRV64] in +def : Pat<(load (XLenVT GPR:$rs1)), (FMV_D_X (Pseudo_LD_DDC (XLenVT GPR:$rs1)))>; /// DDC-relative stores -let Predicates = [HasCheri, IsCapMode] in { +let Predicates = [HasCheriCommon, IsCapMode] in { defm : CheriExplicitStPat; defm : CheriExplicitStPat; } -let Predicates = [HasCheri, IsCapMode, IsRV32] in { +let Predicates = [HasCheriCommon, IsCapMode, IsRV32] in { defm : CheriExplicitStPat; -defm : CheriExplicitStPat; +defm : CheriExplicitStPat; } -let Predicates = [HasCheri, IsCapMode, IsRV64] in { +let Predicates = [HasCheriCommon, IsCapMode, IsRV64] in { defm : CheriExplicitStPat; defm : CheriExplicitStPat; -defm : CheriExplicitStPat; +defm : CheriExplicitStPat; } -let Predicates = [HasCheri, IsCapMode, HasStdExtF] in +let Predicates = [HasCheriCommon, IsCapMode, HasStdExtF] in def : Pat<(store FPR32:$rs2, (XLenVT GPR:$rs1)), - (SW_DDC (FMV_X_W FPR32:$rs2), (XLenVT GPR:$rs1))>; + (Pseudo_SW_DDC (FMV_X_W FPR32:$rs2), (XLenVT GPR:$rs1))>; -let Predicates = [HasCheri, IsCapMode, HasStdExtD, IsRV32] in +let Predicates = [HasCheriCommon, IsCapMode, HasStdExtD, IsRV32] in def : Pat<(store FPR64:$rs2, (XLenVT GPR:$rs1)), (KILL (SplitStoreF64Pseudo FPR64:$rs2, (XLenVT GPR:$rs1)))>; -let Predicates = [HasCheri, IsCapMode, HasStdExtD, IsRV64] in +let Predicates = [HasCheriCommon, IsCapMode, HasStdExtD, IsRV64] in def : Pat<(store FPR64:$rs2, (XLenVT GPR:$rs1)), - (SD_DDC (FMV_X_D FPR64:$rs2), (XLenVT GPR:$rs1))>; + (Pseudo_SD_DDC (FMV_X_D FPR64:$rs2), (XLenVT GPR:$rs1))>; /// Capability loads -let Predicates = [HasCheri, NotCapMode] in { +let Predicates = [HasCheriCommon, NotCapMode] in { defm : CheriExplicitLdPat; defm : CheriExplicitLdPat; defm : CheriExplicitLdPat; @@ -1528,59 +1601,59 @@ defm : CheriExplicitLdPat; defm : CheriExplicitLdPat; } -let Predicates = [HasCheri, NotCapMode, IsRV32] in { +let Predicates = [HasCheriCommon, NotCapMode, IsRV32] in { defm : CheriExplicitLdPat; -defm : CheriExplicitLdPat; +defm : CheriExplicitLdPat; } -let Predicates = [HasCheri, NotCapMode, IsRV64] in { +let Predicates = [HasCheriCommon, NotCapMode, IsRV64] in { defm : CheriExplicitLdPat; defm : CheriExplicitLdPat; defm : CheriExplicitLdPat; defm : CheriExplicitLdPat; -defm : CheriExplicitLdPat; +defm : CheriExplicitLdPat; } -let Predicates = [HasCheri, NotCapMode, HasStdExtF] in -def : Pat<(load GPCR:$rs1), (FMV_W_X (LW_CAP GPCR:$rs1))>; +let Predicates = [HasCheriCommon, NotCapMode, HasStdExtF] in +def : Pat<(load GPCR:$rs1), (FMV_W_X (Pseudo_LW_CAP GPCR:$rs1))>; -let Predicates = [HasCheri, NotCapMode, HasStdExtD, IsRV32] in +let Predicates = [HasCheriCommon, NotCapMode, HasStdExtD, IsRV32] in def : Pat<(load GPCR:$rs1), - (BuildPairF64Pseudo (LW_CAP GPCR:$rs1), - (LW_CAP (CIncOffsetImm GPCR:$rs1, 4)))>; + (BuildPairF64Pseudo (Pseudo_LW_CAP GPCR:$rs1), + (Pseudo_LW_CAP (CIncOffsetImm GPCR:$rs1, 4)))>; -let Predicates = [HasCheri, NotCapMode, HasStdExtD, IsRV64] in -def : Pat<(load GPCR:$rs1), (FMV_D_X (LD_CAP GPCR:$rs1))>; +let Predicates = [HasCheriCommon, NotCapMode, HasStdExtD, IsRV64] in +def : Pat<(load GPCR:$rs1), (FMV_D_X (Pseudo_LD_CAP GPCR:$rs1))>; /// Capability stores -let Predicates = [HasCheri, NotCapMode] in { +let Predicates = [HasCheriCommon, NotCapMode] in { defm : CheriExplicitStPat; defm : CheriExplicitStPat; } -let Predicates = [HasCheri, NotCapMode, IsRV32] in { +let Predicates = [HasCheriCommon, NotCapMode, IsRV32] in { defm : CheriExplicitStPat; -defm : CheriExplicitStPat; +defm : CheriExplicitStPat; } -let Predicates = [HasCheri, NotCapMode, IsRV64] in { +let Predicates = [HasCheriCommon, NotCapMode, IsRV64] in { defm : CheriExplicitStPat; defm : CheriExplicitStPat; -defm : CheriExplicitStPat; +defm : CheriExplicitStPat; } -let Predicates = [HasCheri, NotCapMode, HasStdExtF] in +let Predicates = [HasCheriCommon, NotCapMode, HasStdExtF] in def : Pat<(store FPR32:$rs2, GPCR:$rs1), - (SW_CAP (FMV_X_W FPR32:$rs2), GPCR:$rs1)>; + (Pseudo_SW_CAP (FMV_X_W FPR32:$rs2), GPCR:$rs1)>; -let Predicates = [HasCheri, NotCapMode, HasStdExtD, IsRV32] in +let Predicates = [HasCheriCommon, NotCapMode, HasStdExtD, IsRV32] in def : Pat<(store FPR64:$rs2, GPCR:$rs1), (KILL (CheriSplitStoreF64Pseudo FPR64:$rs2, GPCR:$rs1))>; -let Predicates = [HasCheri, NotCapMode, HasStdExtD, IsRV64] in +let Predicates = [HasCheriCommon, NotCapMode, HasStdExtD, IsRV64] in def : Pat<(store FPR64:$rs2, GPCR:$rs1), - (SD_CAP (FMV_X_D FPR64:$rs2), GPCR:$rs1)>; + (Pseudo_SD_CAP (FMV_X_D FPR64:$rs2), GPCR:$rs1)>; /// Non-Capability Mode Instructions @@ -1599,29 +1672,29 @@ multiclass AMOCapPat { !cast(BaseInst#"_AQ_RL_"#CLenStr)>; } -let Predicates = [HasCheri, IsRV32, NotCapMode] in { +let Predicates = [HasCheriCommon, IsRV32, NotCapMode] in { def : LdPat; def : StPat; -} // Predicates = [HasCheri, IsRV32, NotCapMode] +} // Predicates = [HasCheriCommon, IsRV32, NotCapMode] -let Predicates = [HasCheri, IsRV64, NotCapMode] in { +let Predicates = [HasCheriCommon, IsRV64, NotCapMode] in { def : LdPat; def : StPat; -} // Predicates = [HasCheri, IsRV64, NotCapMode] +} // Predicates = [HasCheriCommon, IsRV64, NotCapMode] -let Predicates = [HasCheri, HasStdExtA, IsRV32, NotCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtA, IsRV32, NotCapMode] in { def : LdPat; def : AtomicStPat; defm : AMOCapPat<"64", "atomic_swap_cap", "AMOSWAP_C">; -} // Predicates = [HasCheri, HasStdExtA, IsRV32, NotCapMode] +} // Predicates = [HasCheriCommon, HasStdExtA, IsRV32, NotCapMode] -let Predicates = [HasCheri, HasStdExtA, IsRV64, NotCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtA, IsRV64, NotCapMode] in { def : LdPat; def : AtomicStPat; defm : AMOCapPat<"128", "atomic_swap_cap", "AMOSWAP_C">; -} // Predicates = [HasCheri, HasStdExtA, IsRV64, NotCapMode] +} // Predicates = [HasCheriCommon, HasStdExtA, IsRV64, NotCapMode] -let Predicates = [HasCheri, HasStdExtA] in { +let Predicates = [HasCheriCommon, HasStdExtA] in { def PseudoAtomicLoadAddCap : PseudoAMO { let Size = 16; } def PseudoAtomicLoadSubCap : PseudoAMO { let Size = 20; } def PseudoAtomicLoadAndCap : PseudoAMO { let Size = 20; } @@ -1633,9 +1706,9 @@ def PseudoAtomicLoadUMaxCap : PseudoAMO { let Size = 24; } def PseudoAtomicLoadUMinCap : PseudoAMO { let Size = 24; } def PseudoAtomicLoadNandCap : PseudoAMO { let Size = 24; } def PseudoCmpXchgCap : PseudoCmpXchg { let Size = 16; } -} // Predicates = [HasCheri, HasStdExtA]f +} // Predicates = [HasCheriCommon, HasStdExtA]f -let Predicates = [HasCheri, HasStdExtA, NotCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtA, NotCapMode] in { defm : PseudoAMOPat<"atomic_load_add_cap", PseudoAtomicLoadAddCap, GPCR>; defm : PseudoAMOPat<"atomic_load_sub_cap", PseudoAtomicLoadSubCap, GPCR>; defm : PseudoAMOPat<"atomic_load_and_cap", PseudoAtomicLoadAndCap, GPCR>; @@ -1647,7 +1720,7 @@ defm : PseudoAMOPat<"atomic_load_umax_cap", PseudoAtomicLoadUMaxCap, GPCR>; defm : PseudoAMOPat<"atomic_load_umin_cap", PseudoAtomicLoadUMinCap, GPCR>; defm : PseudoAMOPat<"atomic_load_nand_cap", PseudoAtomicLoadNandCap, GPCR>; defm : PseudoCmpXchgPat<"atomic_cmp_swap_cap", PseudoCmpXchgCap, CLenVT, GPCR>; -} // Predicates = [HasCheri, HasStdExtA, NotCapMode] +} // Predicates = [HasCheriCommon, HasStdExtA, NotCapMode] /// Capability Mode Instructions @@ -1751,7 +1824,7 @@ multiclass CheriAMOCapPat { !cast(BaseInst#"_AQ_RL_"#CLenStr), CLenVT>; } -let Predicates = [HasCheri, HasStdExtA] in { +let Predicates = [HasCheriCommon, HasStdExtA] in { def PseudoCheriAtomicSwap8 : PseudoCheriAMO { let Size = 16; } def PseudoCheriAtomicLoadAdd8 : PseudoCheriAMO { let Size = 16; } def PseudoCheriAtomicLoadSub8 : PseudoCheriAMO { let Size = 16; } @@ -1792,16 +1865,16 @@ def PseudoCheriAtomicLoadUMaxCap : PseudoCheriAMO { let Size = 24; } def PseudoCheriAtomicLoadUMinCap : PseudoCheriAMO { let Size = 24; } def PseudoCheriAtomicLoadNandCap : PseudoCheriAMO { let Size = 24; } def PseudoCheriCmpXchgCap : PseudoCheriCmpXchg { let Size = 16; } -} // Predicates = [HasCheri, HasStdExtA] +} // Predicates = [HasCheriCommon, HasStdExtA] -let Predicates = [HasCheri, HasStdExtA, IsRV64] in { +let Predicates = [HasCheriCommon, HasStdExtA, IsRV64] in { def PseudoCheriAtomicLoadNand64 : PseudoCheriAMO { let Size = 20; } def PseudoCheriCmpXchg64 : PseudoCheriCmpXchg { let Size = 16; } -} // Predicates = [HasCheri, HasStdExtA, IsRV64] +} // Predicates = [HasCheriCommon, HasStdExtA, IsRV64] /// 'I' (Integer) base -let Predicates = [HasCheri, IsCapMode, IsPureCapABI] in { +let Predicates = [HasCheriCommon, IsCapMode, IsPureCapABI] in { let isBarrier = 1, isBranch = 1, isTerminator = 1 in def PseudoCBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>, PseudoInstExpansion<(CJAL C0, simm21_lsb0_jal:$imm20)>; @@ -1814,9 +1887,9 @@ def PseudoCBRIND : Pseudo<(outs), (ins GPCR:$rs1, simm12:$imm12), []>, def : Pat<(brind GPCR:$rs1), (PseudoCBRIND GPCR:$rs1, 0)>; def : Pat<(brind (cptradd GPCR:$rs1, simm12:$imm12)), (PseudoCBRIND GPCR:$rs1, simm12:$imm12)>; -} // Predicates = [HasCheri, IsCapMode, IsPureCapABI] +} // Predicates = [HasCheriCommon, IsCapMode, IsPureCapABI] -let Predicates = [HasCheri, IsCapMode], +let Predicates = [HasCheriCommon, IsCapMode], isCall = 1, isBarrier = 1, isCodeGenOnly = 0, hasSideEffects = 0, mayStore = 0, mayLoad = 0, Size = 8 in def PseudoCCALLReg : Pseudo<(outs GPCR:$rd), @@ -1824,51 +1897,51 @@ def PseudoCCALLReg : Pseudo<(outs GPCR:$rd), let AsmString = "ccall\t$rd, $func"; } -let Predicates = [HasCheri, IsCapMode], +let Predicates = [HasCheriCommon, IsCapMode], isCall = 1, Defs = [C1], isCodeGenOnly = 0, Size = 8 in def PseudoCCALL : Pseudo<(outs), (ins cap_call_symbol:$func), []> { let AsmString = "ccall\t$func"; } -let Predicates = [HasCheri, IsCapMode, IsPureCapABI] in { +let Predicates = [HasCheriCommon, IsCapMode, IsPureCapABI] in { def : Pat<(riscv_cap_call tglobaladdr:$func), (PseudoCCALL tglobaladdr:$func)>; def : Pat<(riscv_cap_call texternalsym:$func), (PseudoCCALL texternalsym:$func)>; -} // Predicates = [HasCheri, IsCapMode, IsPureCapABI] +} // Predicates = [HasCheriCommon, IsCapMode, IsPureCapABI] -let Predicates = [HasCheri, IsCapMode, IsPureCapABI], +let Predicates = [HasCheriCommon, IsCapMode, IsPureCapABI], isCall = 1, Defs = [C1] in def PseudoCCALLIndirect : Pseudo<(outs), (ins GPCR:$rs1), [(riscv_cap_call GPCR:$rs1)]>, PseudoInstExpansion<(CJALR C1, GPCR:$rs1, 0)>; -let Predicates = [HasCheri, IsCapMode, IsPureCapABI], +let Predicates = [HasCheriCommon, IsCapMode, IsPureCapABI], isBarrier = 1, isReturn = 1, isTerminator = 1 in def PseudoCRET : Pseudo<(outs), (ins), [(riscv_ret_glue)]>, PseudoInstExpansion<(CJALR C0, C1, 0)>; -let Predicates = [HasCheri, IsCapMode], +let Predicates = [HasCheriCommon, IsCapMode], isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [C2], isCodeGenOnly = 0, Size = 8 in def PseudoCTAIL : Pseudo<(outs), (ins cap_call_symbol:$dst), []> { let AsmString = "ctail\t$dst"; } -let Predicates = [HasCheri, IsCapMode, IsPureCapABI], +let Predicates = [HasCheriCommon, IsCapMode, IsPureCapABI], isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [C2] in def PseudoCTAILIndirect : Pseudo<(outs), (ins GPCRTC:$rs1), [(riscv_cap_tail GPCRTC:$rs1)]>, PseudoInstExpansion<(CJALR C0, GPCR:$rs1, 0)>; -let Predicates = [HasCheri, IsCapMode, IsPureCapABI] in { +let Predicates = [HasCheriCommon, IsCapMode, IsPureCapABI] in { def : Pat<(riscv_cap_tail tglobaladdr:$dst), (PseudoCTAIL texternalsym:$dst)>; def : Pat<(riscv_cap_tail texternalsym:$dst), (PseudoCTAIL texternalsym:$dst)>; -} // Predicates = [HasCheri, IsCapMode, IsPureCapABI] +} // Predicates = [HasCheriCommon, IsCapMode, IsPureCapABI] -let Predicates = [HasCheri, IsCapMode, IsPureCapABI] in +let Predicates = [HasCheriCommon, IsCapMode, IsPureCapABI] in let isCall = 0, isBarrier = 1, isBranch = 1, isTerminator = 1, Size = 8, isCodeGenOnly = 0, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in def PseudoCJump : Pseudo<(outs GPCR:$rd), @@ -1876,19 +1949,19 @@ def PseudoCJump : Pseudo<(outs GPCR:$rd), let AsmString = "cjump\t$target, $rd"; } -defm : CheriLdPat, Requires<[HasCheri, IsCapMode]>; -defm : CheriLdPat, Requires<[HasCheri, IsCapMode]>; -defm : CheriLdPat, Requires<[HasCheri, IsCapMode]>; -defm : CheriLdPat, Requires<[HasCheri, IsCapMode]>; -defm : CheriLdPat, Requires<[HasCheri, IsRV32, IsCapMode]>; -defm : CheriLdPat, Requires<[HasCheri, IsCapMode]>; -defm : CheriLdPat, Requires<[HasCheri, IsCapMode]>; +defm : CheriLdPat, Requires<[HasCheriCommon, IsCapMode]>; +defm : CheriLdPat, Requires<[HasCheriCommon, IsCapMode]>; +defm : CheriLdPat, Requires<[HasCheriCommon, IsCapMode]>; +defm : CheriLdPat, Requires<[HasCheriCommon, IsCapMode]>; +defm : CheriLdPat, Requires<[HasCheriCommon, IsRV32, IsCapMode]>; +defm : CheriLdPat, Requires<[HasCheriCommon, IsCapMode]>; +defm : CheriLdPat, Requires<[HasCheriCommon, IsCapMode]>; -defm : CheriStPat, Requires<[HasCheri, IsCapMode]>; -defm : CheriStPat, Requires<[HasCheri, IsCapMode]>; -defm : CheriStPat, Requires<[HasCheri, IsRV32, IsCapMode]>; +defm : CheriStPat, Requires<[HasCheriCommon, IsCapMode]>; +defm : CheriStPat, Requires<[HasCheriCommon, IsCapMode]>; +defm : CheriStPat, Requires<[HasCheriCommon, IsRV32, IsCapMode]>; -let Predicates = [HasCheri, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, IsRV64, IsCapMode] in { /// Loads @@ -1901,23 +1974,23 @@ defm : CheriLdPat; defm : CheriStPat; defm : CheriStPat; -} // Predicates = [HasCheri, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, IsRV64, IsCapMode] /// Other pseudo-instructions // Pessimistically assume the stack pointer will be clobbered -let Predicates = [HasCheri, IsPureCapABI] in { +let Predicates = [HasCheriCommon, IsPureCapABI] in { let Defs = [C2], Uses = [C2] in { def ADJCALLSTACKDOWNCAP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), [(callseq_start timm:$amt1, timm:$amt2)]>; def ADJCALLSTACKUPCAP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), [(callseq_end timm:$amt1, timm:$amt2)]>; } // Defs = [C2], Uses = [C2] -} // Predicates = [HasCheri, IsPureCapABI] +} // Predicates = [HasCheriCommon, IsPureCapABI] /// 'A' (Atomic Instructions) extension -let Predicates = [HasCheri, HasStdExtA, IsCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtA, IsCapMode] in { /// Atomic loads and stores @@ -1992,9 +2065,9 @@ defm : PseudoCheriCmpXchgPat<"atomic_cmp_swap_32", PseudoCheriCmpXchg32>; defm : PseudoCheriCmpXchgPat<"atomic_cmp_swap_cap", PseudoCheriCmpXchgCap, GPCR>; -} // Predicates = [HasCheri, HasStdExtA, IsCapMode] +} // Predicates = [HasCheriCommon, HasStdExtA, IsCapMode] -let Predicates = [HasCheri, HasStdExtA, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtA, IsRV64, IsCapMode] in { /// 64-bit atomic loads and stores @@ -2024,23 +2097,23 @@ defm : PseudoCheriAMOPat<"atomic_load_nand_64", PseudoCheriAtomicLoadNand64>; defm : PseudoCheriCmpXchgPat<"atomic_cmp_swap_64", PseudoCheriCmpXchg64>; -} // Predicates = [HasCheri, HasStdExtA, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, HasStdExtA, IsRV64, IsCapMode] -let Predicates = [HasCheri, HasStdExtA, IsRV32, IsCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtA, IsRV32, IsCapMode] in { defm : CheriLdPat; defm : CheriAtomicStPat; defm : CheriAMOCapPat<"64", "atomic_swap_cap", "CAMOSWAP_C">; -} // Predicates = [HasCheri, HasStdExtA, IsRV32, IsCapMode] +} // Predicates = [HasCheriCommon, HasStdExtA, IsRV32, IsCapMode] -let Predicates = [HasCheri, HasStdExtA, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtA, IsRV64, IsCapMode] in { defm : CheriLdPat; defm : CheriAtomicStPat; defm : CheriAMOCapPat<"128", "atomic_swap_cap", "CAMOSWAP_C">; -} // Predicates = [HasCheri, HasStdExtA, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, HasStdExtA, IsRV64, IsCapMode] /// 'F' (Single-Precision Floating-Point) extension -let Predicates = [HasCheri, HasStdExtF, IsCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtF, IsCapMode] in { /// Loads @@ -2050,11 +2123,11 @@ defm : CheriLdPat; defm : CheriStPat; -} // Predicates = [HasCheri, HasStdExtF, IsCapMode] +} // Predicates = [HasCheriCommon, HasStdExtF, IsCapMode] /// 'D' (Single-Precision Floating-Point) extension -let Predicates = [HasCheri, HasStdExtD, IsCapMode] in { +let Predicates = [HasCheriCommon, HasStdExtD, IsCapMode] in { /// Loads @@ -2064,153 +2137,153 @@ defm : CheriLdPat; defm : CheriStPat; -} // Predicates = [HasCheri, HasStdExtD, IsCapMode] +} // Predicates = [HasCheriCommon, HasStdExtD, IsCapMode] /// 'XCheri' extension -let Predicates = [HasCheri, IsRV32, IsCapMode] in { +let Predicates = [HasCheriCommon, IsRV32, IsCapMode] in { defm : CheriLdPat; defm : CheriStPat; -} // Predicates = [HasCheri, IsRV32, IsCapMode] +} // Predicates = [HasCheriCommon, IsRV32, IsCapMode] -let Predicates = [HasCheri, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, IsRV64, IsCapMode] in { defm : CheriLdPat; defm : CheriStPat; -} // Predicates = [HasCheri, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, IsRV64, IsCapMode] //===----------------------------------------------------------------------===// // Compress Instruction tablegen backend. //===----------------------------------------------------------------------===// // Quadrant 0 -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] in { def : CompressPat<(CIncOffsetImm GPCRC:$rd, CSP:$rs1, uimm10_lsb00nonzero:$imm), (C_CIncOffsetImm4CSPN GPCRC:$rd, CSP:$rs1, uimm10_lsb00nonzero:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in { def : CompressPat<(CFLD FPR64C:$rd, GPCRC:$rs1, uimm8_lsb000:$imm), (C_CFLD FPR64C:$rd, GPCRC:$rs1, uimm8_lsb000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { def : CompressPat<(CLC_128 GPCRC:$rd, GPCRC:$rs1, uimm9_lsb0000:$imm), (C_CLC_128 GPCRC:$rd, GPCRC:$rs1, uimm9_lsb0000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] in { def : CompressPat<(CLW GPRC:$rd, GPCRC:$rs1, uimm7_lsb00:$imm), (C_CLW GPRC:$rd, GPCRC:$rs1, uimm7_lsb00:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in { def : CompressPat<(CLC_64 GPCRC:$rd, GPCRC:$rs1, uimm8_lsb000:$imm), (C_CLC_64 GPCRC:$rd, GPCRC:$rs1, uimm8_lsb000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { def : CompressPat<(CLD GPRC:$rd, GPCRC:$rs1, uimm8_lsb000:$imm), (C_CLD GPRC:$rd, GPCRC:$rs1, uimm8_lsb000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in { def : CompressPat<(CFSD FPR64C:$rs2, GPCRC:$rs1, uimm8_lsb000:$imm), (C_CFSD FPR64C:$rs2, GPCRC:$rs1, uimm8_lsb000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { def : CompressPat<(CSC_128 GPCRC:$rs2, GPCRC:$rs1, uimm9_lsb0000:$imm), (C_CSC_128 GPCRC:$rs2, GPCRC:$rs1, uimm9_lsb0000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] in { def : CompressPat<(CSW GPRC:$rs2, GPCRC:$rs1, uimm7_lsb00:$imm), (C_CSW GPRC:$rs2, GPCRC:$rs1, uimm7_lsb00:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in { def : CompressPat<(CSC_64 GPCRC:$rs2, GPCRC:$rs1, uimm8_lsb000:$imm), (C_CSC_64 GPCRC:$rs2, GPCRC:$rs1, uimm8_lsb000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { def : CompressPat<(CSD GPRC:$rs2, GPCRC:$rs1, uimm8_lsb000:$imm), (C_CSD GPRC:$rs2, GPCRC:$rs1, uimm8_lsb000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] // Quadrant 1 -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in { def : CompressPat<(CJAL C1, simm12_lsb0:$offset), (C_CJAL simm12_lsb0:$offset)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] in { def : CompressPat<(CIncOffsetImm C2, C2, simm10_lsb0000nonzero:$imm), (C_CIncOffsetImm16CSP C2, simm10_lsb0000nonzero:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] in { def : CompressPat<(CJAL C0, simm12_lsb0:$offset), (C_J simm12_lsb0:$offset)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] // Quadrant 2 -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in { def : CompressPat<(CFLD FPR64:$rd, CSP:$rs1, uimm9_lsb000:$imm), (C_CFLDCSP FPR64:$rd, CSP:$rs1, uimm9_lsb000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { def : CompressPat<(CLC_128 GPCRNoC0:$rd, CSP:$rs1, uimm10_lsb0000:$imm), (C_CLCCSP_128 GPCRNoC0:$rd, CSP:$rs1, uimm10_lsb0000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] in { def : CompressPat<(CLW GPRNoX0:$rd, CSP:$rs1, uimm8_lsb00:$imm), (C_CLWCSP GPRNoX0:$rd, CSP:$rs1, uimm8_lsb00:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in { def : CompressPat<(CLC_64 GPCRNoC0:$rd, CSP:$rs1, uimm9_lsb000:$imm), (C_CLCCSP_64 GPCRNoC0:$rd, CSP:$rs1, uimm9_lsb000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { def : CompressPat<(CLD GPRNoX0:$rd, CSP:$rs1, uimm9_lsb000:$imm), (C_CLDCSP GPRNoX0:$rd, CSP:$rs1, uimm9_lsb000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] in { def : CompressPat<(CJALR C0, GPCRNoC0:$rs1, 0), (C_CJR GPCRNoC0:$rs1)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] in { def : CompressPat<(CJALR C1, GPCRNoC0:$rs1, 0), (C_CJALR GPCRNoC0:$rs1)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] in { def : CompressPat<(CFSD FPR64:$rs2, CSP:$rs1, uimm9_lsb000:$imm), (C_CFSDCSP FPR64:$rs2, CSP:$rs1, uimm9_lsb000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, HasStdExtD, IsRV32, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { def : CompressPat<(CSC_128 GPCR:$rs2, CSP:$rs1, uimm10_lsb0000:$imm), (C_CSCCSP_128 GPCR:$rs2, CSP:$rs1, uimm10_lsb0000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] in { def : CompressPat<(CSW GPR:$rs2, CSP:$rs1, uimm8_lsb00:$imm), (C_CSWCSP GPR:$rs2, CSP:$rs1, uimm8_lsb00:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] in { def : CompressPat<(CSC_64 GPCR:$rs2, CSP:$rs1, uimm9_lsb000:$imm), (C_CSCCSP_64 GPCR:$rs2, CSP:$rs1, uimm9_lsb000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV32, IsCapMode] -let Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { +let Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] in { def : CompressPat<(CSD GPR:$rs2, CSP:$rs1, uimm9_lsb000:$imm), (C_CSDCSP GPR:$rs2, CSP:$rs1, uimm9_lsb000:$imm)>; -} // Predicates = [HasCheri, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] +} // Predicates = [HasCheriCommon, HasCheriRVC, HasStdExtC, IsRV64, IsCapMode] diff --git a/llvm/lib/Target/RISCV/RISCVSchedRocket.td b/llvm/lib/Target/RISCV/RISCVSchedRocket.td index bb5cb36e6e170..6fef3e6ba012d 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedRocket.td +++ b/llvm/lib/Target/RISCV/RISCVSchedRocket.td @@ -17,7 +17,7 @@ def RocketModel : SchedMachineModel { let LoadLatency = 3; let MispredictPenalty = 3; let CompleteModel = false; - let UnsupportedFeatures = [HasCheri, HasStdExtZbkb, HasStdExtZbkc, HasStdExtZbkx, + let UnsupportedFeatures = [HasCheriCommon, HasStdExtZbkb, HasStdExtZbkc, HasStdExtZbkx, HasStdExtZcmt, HasStdExtZknd, HasStdExtZkne, HasStdExtZknh, HasStdExtZksed, HasStdExtZksh, HasStdExtZkr, HasVInstructions, HasVInstructionsI64]; diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h index 733f6dd2229dc..817cd775bba9d 100644 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -168,6 +168,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo { assert(HasCheri && "Cannot get capability type for non-CHERI"); return is64Bit() ? MVT::c128 : MVT::c64; } + bool hasXCheriNonStd() const { return HasXCheri && !HasXCheriStdCompat; } bool hasMacroFusion() const { return hasLUIADDIFusion(); } diff --git a/llvm/test/CodeGen/RISCV/cheri/std-compat/clear-tag.ll b/llvm/test/CodeGen/RISCV/cheri/std-compat/clear-tag.ll new file mode 100644 index 0000000000000..bef3edce503e4 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/cheri/std-compat/clear-tag.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +;; CClearTag is not part of the standard, check that we don't emit it +; RUN: %riscv64_cheri_purecap_llc -verify-machineinstrs < %s | FileCheck %s --check-prefix=XCHERI +; RUN: %riscv64_cheri_purecap_llc -mattr=+xcheri-std-compat -verify-machineinstrs < %s | FileCheck %s --check-prefix=STD-COMPAT + +define internal ptr addrspace(200) @test(ptr addrspace(200) %dst, ptr addrspace(200) %cap) addrspace(200) nounwind { +; XCHERI-LABEL: test: +; XCHERI: # %bb.0: # %entry +; XCHERI-NEXT: ccleartag ca1, ca1 +; XCHERI-NEXT: csc ca1, 0(ca0) +; XCHERI-NEXT: cmove ca0, ca1 +; XCHERI-NEXT: cret +; +; STD-COMPAT-LABEL: test: +; STD-COMPAT: # %bb.0: # %entry +; STD-COMPAT-NEXT: cgethigh a2, ca1 +; STD-COMPAT-NEXT: csethigh ca1, ca1, a2 +; STD-COMPAT-NEXT: csc ca1, 0(ca0) +; STD-COMPAT-NEXT: cmove ca0, ca1 +; STD-COMPAT-NEXT: cret +entry: + %new = call ptr addrspace(200) @llvm.cheri.cap.tag.clear(ptr addrspace(200) %cap) + store ptr addrspace(200) %new, ptr addrspace(200) %dst, align 16 + ret ptr addrspace(200) %new +} + +declare ptr addrspace(200) @llvm.cheri.cap.tag.clear(ptr addrspace(200)) addrspace(200) diff --git a/llvm/test/CodeGen/RISCV/cheri/std-compat/crrl.ll b/llvm/test/CodeGen/RISCV/cheri/std-compat/crrl.ll new file mode 100644 index 0000000000000..4734247c4bfd8 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/cheri/std-compat/crrl.ll @@ -0,0 +1,24 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +;; CRRL is not part of the standard, check that we emit ((len + ~mask) & mask) instead. +; RUN: %riscv64_cheri_purecap_llc -verify-machineinstrs < %s | FileCheck %s --check-prefix=XCHERI +; RUN: %riscv64_cheri_purecap_llc -mattr=+xcheri-std-compat -verify-machineinstrs < %s | FileCheck %s --check-prefix=STD-COMPAT + +define internal i64 @crrl(i64 %len) addrspace(200) nounwind { +; XCHERI-LABEL: crrl: +; XCHERI: # %bb.0: # %entry +; XCHERI-NEXT: crrl a0, a0 +; XCHERI-NEXT: cret +; +; STD-COMPAT-LABEL: crrl: +; STD-COMPAT: # %bb.0: # %entry +; STD-COMPAT-NEXT: cram a1, a0 +; STD-COMPAT-NEXT: not a2, a1 +; STD-COMPAT-NEXT: add a0, a0, a2 +; STD-COMPAT-NEXT: and a0, a0, a1 +; STD-COMPAT-NEXT: cret +entry: + %result = call addrspace(200) i64 @llvm.cheri.round.representable.length.i64(i64 %len) + ret i64 %result +} + +declare i64 @llvm.cheri.round.representable.length.i64(i64) addrspace(200) diff --git a/llvm/test/CodeGen/RISCV/cheri/std-compat/get-offset.ll b/llvm/test/CodeGen/RISCV/cheri/std-compat/get-offset.ll new file mode 100644 index 0000000000000..e5599154c6753 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/cheri/std-compat/get-offset.ll @@ -0,0 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +;; CGetOffset is not part of of the standard, check that we emit (addr - base) instead. +; RUN: %riscv64_cheri_purecap_llc -verify-machineinstrs < %s | FileCheck %s --check-prefix=XCHERI +; RUN: %riscv64_cheri_purecap_llc -mattr=+xcheri-std-compat -verify-machineinstrs < %s | FileCheck %s --check-prefix=STD-COMPAT + +define internal i64 @test(ptr addrspace(200) %dst, ptr addrspace(200) %cap) addrspace(200) nounwind { +; XCHERI-LABEL: test: +; XCHERI: # %bb.0: # %entry +; XCHERI-NEXT: cgetoffset a1, ca1 +; XCHERI-NEXT: csd a1, 0(ca0) +; XCHERI-NEXT: mv a0, a1 +; XCHERI-NEXT: cret +; +; STD-COMPAT-LABEL: test: +; STD-COMPAT: # %bb.0: # %entry +; STD-COMPAT-NEXT: cgetbase a2, ca1 +; STD-COMPAT-NEXT: sub a1, a1, a2 +; STD-COMPAT-NEXT: csd a1, 0(ca0) +; STD-COMPAT-NEXT: mv a0, a1 +; STD-COMPAT-NEXT: cret +entry: + %addr = call addrspace(200) i64 @llvm.cheri.cap.offset.get.i64(ptr addrspace(200) %cap) + store i64 %addr, ptr addrspace(200) %dst, align 8 + ret i64 %addr +} + +declare i64 @llvm.cheri.cap.offset.get.i64(ptr addrspace(200)) addrspace(200) + diff --git a/llvm/test/CodeGen/RISCV/cheri/std-compat/get-sealed.ll b/llvm/test/CodeGen/RISCV/cheri/std-compat/get-sealed.ll new file mode 100644 index 0000000000000..1b426da9cbbd5 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/cheri/std-compat/get-sealed.ll @@ -0,0 +1,39 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +;; CGetSealed is not part of the standard, check that we emit an otype != unsealed comparison instead. + +; RUN: %riscv64_cheri_purecap_llc -verify-machineinstrs < %s | FileCheck %s --check-prefix=XCHERI +; RUN: %riscv64_cheri_purecap_llc -mattr=+xcheri-std-compat -verify-machineinstrs < %s | FileCheck %s --check-prefix=STD-COMPAT + +define internal i64 @test(ptr addrspace(200) %cap) addrspace(200) nounwind { +; XCHERI-LABEL: test: +; XCHERI: # %bb.0: # %entry +; XCHERI-NEXT: cgetsealed a0, ca0 +; XCHERI-NEXT: beqz a0, .LBB0_2 +; XCHERI-NEXT: # %bb.1: # %if.then +; XCHERI-NEXT: li a0, 4 +; XCHERI-NEXT: cret +; XCHERI-NEXT: .LBB0_2: # %if.end +; XCHERI-NEXT: li a0, 2 +; XCHERI-NEXT: cret +; +; STD-COMPAT-LABEL: test: +; STD-COMPAT: # %bb.0: # %entry +; STD-COMPAT-NEXT: cgettype a0, ca0 +; STD-COMPAT-NEXT: li a1, -1 +; STD-COMPAT-NEXT: beq a0, a1, .LBB0_2 +; STD-COMPAT-NEXT: # %bb.1: # %if.then +; STD-COMPAT-NEXT: li a0, 4 +; STD-COMPAT-NEXT: cret +; STD-COMPAT-NEXT: .LBB0_2: # %if.end +; STD-COMPAT-NEXT: li a0, 2 +; STD-COMPAT-NEXT: cret +entry: + %sealed = call addrspace(200) i1 @llvm.cheri.cap.sealed.get(ptr addrspace(200) %cap) + br i1 %sealed, label %if.then, label %if.end +if.then: + ret i64 4 +if.end: + ret i64 2 +} + +declare i1 @llvm.cheri.cap.sealed.get(ptr addrspace(200)) addrspace(200) diff --git a/llvm/test/CodeGen/RISCV/cheri/std-compat/hybrid-load-store.ll b/llvm/test/CodeGen/RISCV/cheri/std-compat/hybrid-load-store.ll new file mode 100644 index 0000000000000..be2c3d1b94d46 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/cheri/std-compat/hybrid-load-store.ll @@ -0,0 +1,747 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; TODO: support +zfhmin patterns for load_f16 +; RUN: llc -mtriple=riscv64 -target-abi l64pc128d -mattr=+d,-zfhmin,+xcheri,+cap-mode,+xcheri-std-compat < %s | FileCheck %s --check-prefix=PURECAP +; RUN: llc -mtriple=riscv64 -target-abi lp64d -mattr=+d,-zfhmin,+xcheri,-cap-mode,+xcheri-std-compat < %s | FileCheck %s --check-prefix=HYBRID +; RUN: llc -mtriple=riscv64 -target-abi lp64d -mattr=+d,-zfhmin,+xcheri,-cap-mode,-xcheri-std-compat < %s | FileCheck %s --check-prefix=HYBRID-XCHERI +; RUN: sed 's/addrspace(200)/addrspace(0)/g' %s | llc -mtriple=riscv64 -target-abi l64pc128d -mattr=+d,-zfhmin,+xcheri,+cap-mode,+xcheri-std-compat | FileCheck %s --check-prefix=PURECAP-DDC-LOADS + +define internal i64 @load_i8_sext(i8 addrspace(200)* %cap) nounwind { +; PURECAP-LABEL: load_i8_sext: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: clb a0, 0(ca0) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: load_i8_sext: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: lb a0, 0(a0) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: load_i8_sext: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: lb.cap a0, (ca0) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: load_i8_sext: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: clb a0, 0(ca0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %result = load i8, i8 addrspace(200)* %cap + %ext = sext i8 %result to i64 + ret i64 %ext +} + +define internal i64 @load_i8_zext(i8 addrspace(200)* %cap) nounwind { +; PURECAP-LABEL: load_i8_zext: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: clbu a0, 0(ca0) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: load_i8_zext: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: lbu a0, 0(a0) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: load_i8_zext: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: lbu.cap a0, (ca0) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: load_i8_zext: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: clbu a0, 0(ca0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %result = load i8, i8 addrspace(200)* %cap + %ext = zext i8 %result to i64 + ret i64 %ext +} + +define internal i64 @load_i16_sext(i16 addrspace(200)* %cap) nounwind { +; PURECAP-LABEL: load_i16_sext: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: clh a0, 0(ca0) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: load_i16_sext: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: lh a0, 0(a0) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: load_i16_sext: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: lh.cap a0, (ca0) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: load_i16_sext: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: clh a0, 0(ca0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %result = load i16, i16 addrspace(200)* %cap + %ext = sext i16 %result to i64 + ret i64 %ext +} + +define internal i64 @load_i16_zext(i16 addrspace(200)* %cap) nounwind { +; PURECAP-LABEL: load_i16_zext: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: clhu a0, 0(ca0) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: load_i16_zext: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: lhu a0, 0(a0) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: load_i16_zext: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: lhu.cap a0, (ca0) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: load_i16_zext: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: clhu a0, 0(ca0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %result = load i16, i16 addrspace(200)* %cap + %ext = zext i16 %result to i64 + ret i64 %ext +} + +define internal i64 @load_i32_sext(i32 addrspace(200)* %cap) nounwind { +; PURECAP-LABEL: load_i32_sext: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: clw a0, 0(ca0) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: load_i32_sext: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: lw a0, 0(a0) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: load_i32_sext: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: lw.cap a0, (ca0) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: load_i32_sext: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: clw a0, 0(ca0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %result = load i32, i32 addrspace(200)* %cap + %ext = sext i32 %result to i64 + ret i64 %ext +} + +define internal i64 @load_32_zext(i32 addrspace(200)* %cap) nounwind { +; PURECAP-LABEL: load_32_zext: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: clwu a0, 0(ca0) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: load_32_zext: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: lwu a0, 0(a0) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: load_32_zext: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: lwu.cap a0, (ca0) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: load_32_zext: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: clwu a0, 0(ca0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %result = load i32, i32 addrspace(200)* %cap + %ext = zext i32 %result to i64 + ret i64 %ext +} + +define internal i64 @load_i64(i64 addrspace(200)* %cap) nounwind { +; PURECAP-LABEL: load_i64: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: cld a0, 0(ca0) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: load_i64: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: ld a0, 0(a0) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: load_i64: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: ld.cap a0, (ca0) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: load_i64: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: cld a0, 0(ca0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %result = load i64, i64 addrspace(200)* %cap + ret i64 %result +} + +define internal i8 addrspace(200)* @load_cap(i8 addrspace(200)* addrspace(200)* %cap) nounwind { +; PURECAP-LABEL: load_cap: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: clc ca0, 0(ca0) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: load_cap: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: lc ca0, 0(a0) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: load_cap: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: lc.cap ca0, (ca0) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: load_cap: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: cld a0, 0(ca0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %result = load i8 addrspace(200)*, i8 addrspace(200)* addrspace(200)* %cap + ret i8 addrspace(200)* %result +} + +define internal half @load_f16(half addrspace(200)* %cap) nounwind { +; PURECAP-LABEL: load_f16: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: cincoffset csp, csp, -16 +; PURECAP-NEXT: csc cra, 0(csp) # 16-byte Folded Spill +; PURECAP-NEXT: clhu a0, 0(ca0) +; PURECAP-NEXT: fmv.w.x fa0, a0 +; PURECAP-NEXT: ccall __extendhfsf2 +; PURECAP-NEXT: lui a0, 260096 +; PURECAP-NEXT: fmv.w.x fa5, a0 +; PURECAP-NEXT: fadd.s fa0, fa0, fa5 +; PURECAP-NEXT: ccall __truncsfhf2 +; PURECAP-NEXT: fmv.x.w a0, fa0 +; PURECAP-NEXT: lui a1, 1048560 +; PURECAP-NEXT: or a0, a0, a1 +; PURECAP-NEXT: fmv.w.x fa0, a0 +; PURECAP-NEXT: clc cra, 0(csp) # 16-byte Folded Reload +; PURECAP-NEXT: cincoffset csp, csp, 16 +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: load_f16: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: addi sp, sp, -16 +; HYBRID-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: lhu a0, 0(a0) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: fmv.w.x fa0, a0 +; HYBRID-NEXT: call __extendhfsf2@plt +; HYBRID-NEXT: lui a0, 260096 +; HYBRID-NEXT: fmv.w.x fa5, a0 +; HYBRID-NEXT: fadd.s fa0, fa0, fa5 +; HYBRID-NEXT: call __truncsfhf2@plt +; HYBRID-NEXT: fmv.x.w a0, fa0 +; HYBRID-NEXT: lui a1, 1048560 +; HYBRID-NEXT: or a0, a0, a1 +; HYBRID-NEXT: fmv.w.x fa0, a0 +; HYBRID-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; HYBRID-NEXT: addi sp, sp, 16 +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: load_f16: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: addi sp, sp, -16 +; HYBRID-XCHERI-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; HYBRID-XCHERI-NEXT: lhu.cap a0, (ca0) +; HYBRID-XCHERI-NEXT: fmv.w.x fa0, a0 +; HYBRID-XCHERI-NEXT: call __extendhfsf2@plt +; HYBRID-XCHERI-NEXT: lui a0, 260096 +; HYBRID-XCHERI-NEXT: fmv.w.x fa5, a0 +; HYBRID-XCHERI-NEXT: fadd.s fa0, fa0, fa5 +; HYBRID-XCHERI-NEXT: call __truncsfhf2@plt +; HYBRID-XCHERI-NEXT: fmv.x.w a0, fa0 +; HYBRID-XCHERI-NEXT: lui a1, 1048560 +; HYBRID-XCHERI-NEXT: or a0, a0, a1 +; HYBRID-XCHERI-NEXT: fmv.w.x fa0, a0 +; HYBRID-XCHERI-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; HYBRID-XCHERI-NEXT: addi sp, sp, 16 +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: load_f16: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: cincoffset csp, csp, -16 +; PURECAP-DDC-LOADS-NEXT: csc cra, 0(csp) # 16-byte Folded Spill +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: clhu a0, 0(ca0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: fmv.w.x fa0, a0 +; PURECAP-DDC-LOADS-NEXT: ccall __extendhfsf2 +; PURECAP-DDC-LOADS-NEXT: lui a0, 260096 +; PURECAP-DDC-LOADS-NEXT: fmv.w.x fa5, a0 +; PURECAP-DDC-LOADS-NEXT: fadd.s fa0, fa0, fa5 +; PURECAP-DDC-LOADS-NEXT: ccall __truncsfhf2 +; PURECAP-DDC-LOADS-NEXT: fmv.x.w a0, fa0 +; PURECAP-DDC-LOADS-NEXT: lui a1, 1048560 +; PURECAP-DDC-LOADS-NEXT: or a0, a0, a1 +; PURECAP-DDC-LOADS-NEXT: fmv.w.x fa0, a0 +; PURECAP-DDC-LOADS-NEXT: clc cra, 0(csp) # 16-byte Folded Reload +; PURECAP-DDC-LOADS-NEXT: cincoffset csp, csp, 16 +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %result = load half, half addrspace(200)* %cap + %plus_one = fadd half %result, 1.0 + ret half %plus_one +} + +define internal float @load_f32(float addrspace(200)* %cap) nounwind { +; PURECAP-LABEL: load_f32: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: cflw fa5, 0(ca0) +; PURECAP-NEXT: lui a0, 260096 +; PURECAP-NEXT: fmv.w.x fa4, a0 +; PURECAP-NEXT: fadd.s fa0, fa5, fa4 +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: load_f32: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: lw a0, 0(a0) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: fmv.w.x fa5, a0 +; HYBRID-NEXT: lui a0, 260096 +; HYBRID-NEXT: fmv.w.x fa4, a0 +; HYBRID-NEXT: fadd.s fa0, fa5, fa4 +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: load_f32: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: lw.cap a0, (ca0) +; HYBRID-XCHERI-NEXT: fmv.w.x fa5, a0 +; HYBRID-XCHERI-NEXT: lui a0, 260096 +; HYBRID-XCHERI-NEXT: fmv.w.x fa4, a0 +; HYBRID-XCHERI-NEXT: fadd.s fa0, fa5, fa4 +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: load_f32: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: clw a0, 0(ca0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: fmv.w.x fa5, a0 +; PURECAP-DDC-LOADS-NEXT: lui a0, 260096 +; PURECAP-DDC-LOADS-NEXT: fmv.w.x fa4, a0 +; PURECAP-DDC-LOADS-NEXT: fadd.s fa0, fa5, fa4 +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %result = load float, float addrspace(200)* %cap + %plus_one = fadd float %result, 1.0 + ret float %plus_one +} + +define internal double @load_f64(double addrspace(200)* %cap) nounwind { +; PURECAP-LABEL: load_f64: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: cfld fa5, 0(ca0) +; PURECAP-NEXT: .LBB10_1: # %entry +; PURECAP-NEXT: # Label of block must be emitted +; PURECAP-NEXT: auipcc ca0, %pcrel_hi(.LCPI10_0) +; PURECAP-NEXT: cincoffset ca0, ca0, %pcrel_lo(.LBB10_1) +; PURECAP-NEXT: cfld fa4, 0(ca0) +; PURECAP-NEXT: fadd.d fa0, fa5, fa4 +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: load_f64: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: ld a0, 0(a0) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: lui a1, %hi(.LCPI10_0) +; HYBRID-NEXT: fld fa5, %lo(.LCPI10_0)(a1) +; HYBRID-NEXT: fmv.d.x fa4, a0 +; HYBRID-NEXT: fadd.d fa0, fa4, fa5 +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: load_f64: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: ld.cap a0, (ca0) +; HYBRID-XCHERI-NEXT: lui a1, %hi(.LCPI10_0) +; HYBRID-XCHERI-NEXT: fld fa5, %lo(.LCPI10_0)(a1) +; HYBRID-XCHERI-NEXT: fmv.d.x fa4, a0 +; HYBRID-XCHERI-NEXT: fadd.d fa0, fa4, fa5 +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: load_f64: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: cld a0, 0(ca0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: .LBB10_1: # %entry +; PURECAP-DDC-LOADS-NEXT: # Label of block must be emitted +; PURECAP-DDC-LOADS-NEXT: auipcc ca1, %pcrel_hi(.LCPI10_0) +; PURECAP-DDC-LOADS-NEXT: cincoffset ca1, ca1, %pcrel_lo(.LBB10_1) +; PURECAP-DDC-LOADS-NEXT: cfld fa5, 0(ca1) +; PURECAP-DDC-LOADS-NEXT: fmv.d.x fa4, a0 +; PURECAP-DDC-LOADS-NEXT: fadd.d fa0, fa4, fa5 +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %result = load double, double addrspace(200)* %cap + %plus_one = fadd double %result, 1.0 + ret double %plus_one +} + +define internal void @store_8(i8 %value, i8 addrspace(200)* %dst) nounwind { +; PURECAP-LABEL: store_8: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: csb a0, 0(ca1) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: store_8: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: sb a0, 0(a1) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: store_8: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: sb.cap a0, (ca1) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: store_8: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: csb a0, 0(ca1) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + store i8 %value, i8 addrspace(200)* %dst + ret void +} + +define internal void @store_16(i16 %value, i16 addrspace(200)* %dst) nounwind { +; PURECAP-LABEL: store_16: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: csh a0, 0(ca1) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: store_16: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: sh a0, 0(a1) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: store_16: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: sh.cap a0, (ca1) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: store_16: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: csh a0, 0(ca1) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + store i16 %value, i16 addrspace(200)* %dst + ret void +} + +define internal void @store_32(i32 %value, i32 addrspace(200)* %dst) nounwind { +; PURECAP-LABEL: store_32: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: csw a0, 0(ca1) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: store_32: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: sw a0, 0(a1) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: store_32: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: sw.cap a0, (ca1) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: store_32: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: csw a0, 0(ca1) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + store i32 %value, i32 addrspace(200)* %dst + ret void +} + +define internal void @store_64(i64 %value, i64 addrspace(200)* %dst) nounwind { +; PURECAP-LABEL: store_64: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: csd a0, 0(ca1) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: store_64: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: sd a0, 0(a1) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: store_64: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: sd.cap a0, (ca1) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: store_64: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: csd a0, 0(ca1) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + store i64 %value, i64 addrspace(200)* %dst + ret void +} + +define internal void @store_cap(i8 addrspace(200)* %value, i8 addrspace(200)* addrspace(200)* %dst) nounwind { +; PURECAP-LABEL: store_cap: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: csc ca0, 0(ca1) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: store_cap: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: sc ca0, 0(a1) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: store_cap: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: sc.cap ca0, (ca1) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: store_cap: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: csd a0, 0(ca1) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + store i8 addrspace(200)* %value, i8 addrspace(200)* addrspace(200)* %dst + ret void +} + +define internal void @store_f16(half %value, half addrspace(200)* %dst) nounwind { +; PURECAP-LABEL: store_f16: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: cincoffset csp, csp, -32 +; PURECAP-NEXT: csc cra, 16(csp) # 16-byte Folded Spill +; PURECAP-NEXT: csc cs0, 0(csp) # 16-byte Folded Spill +; PURECAP-NEXT: cmove cs0, ca0 +; PURECAP-NEXT: ccall __extendhfsf2 +; PURECAP-NEXT: lui a0, 260096 +; PURECAP-NEXT: fmv.w.x fa5, a0 +; PURECAP-NEXT: fadd.s fa0, fa0, fa5 +; PURECAP-NEXT: ccall __truncsfhf2 +; PURECAP-NEXT: fmv.x.w a0, fa0 +; PURECAP-NEXT: csh a0, 0(cs0) +; PURECAP-NEXT: clc cra, 16(csp) # 16-byte Folded Reload +; PURECAP-NEXT: clc cs0, 0(csp) # 16-byte Folded Reload +; PURECAP-NEXT: cincoffset csp, csp, 32 +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: store_f16: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: addi sp, sp, -32 +; HYBRID-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; HYBRID-NEXT: sc ca0, 0(sp) # 16-byte Folded Spill +; HYBRID-NEXT: call __extendhfsf2@plt +; HYBRID-NEXT: lui a0, 260096 +; HYBRID-NEXT: fmv.w.x fa5, a0 +; HYBRID-NEXT: fadd.s fa0, fa0, fa5 +; HYBRID-NEXT: call __truncsfhf2@plt +; HYBRID-NEXT: fmv.x.w a0, fa0 +; HYBRID-NEXT: lc ca1, 0(sp) # 16-byte Folded Reload +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: sh a0, 0(a1) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; HYBRID-NEXT: addi sp, sp, 32 +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: store_f16: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: addi sp, sp, -32 +; HYBRID-XCHERI-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; HYBRID-XCHERI-NEXT: sc ca0, 0(sp) # 16-byte Folded Spill +; HYBRID-XCHERI-NEXT: call __extendhfsf2@plt +; HYBRID-XCHERI-NEXT: lui a0, 260096 +; HYBRID-XCHERI-NEXT: fmv.w.x fa5, a0 +; HYBRID-XCHERI-NEXT: fadd.s fa0, fa0, fa5 +; HYBRID-XCHERI-NEXT: call __truncsfhf2@plt +; HYBRID-XCHERI-NEXT: fmv.x.w a0, fa0 +; HYBRID-XCHERI-NEXT: lc ca1, 0(sp) # 16-byte Folded Reload +; HYBRID-XCHERI-NEXT: sh.cap a0, (ca1) +; HYBRID-XCHERI-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; HYBRID-XCHERI-NEXT: addi sp, sp, 32 +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: store_f16: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: cincoffset csp, csp, -32 +; PURECAP-DDC-LOADS-NEXT: csc cra, 16(csp) # 16-byte Folded Spill +; PURECAP-DDC-LOADS-NEXT: csc cs0, 0(csp) # 16-byte Folded Spill +; PURECAP-DDC-LOADS-NEXT: mv s0, a0 +; PURECAP-DDC-LOADS-NEXT: ccall __extendhfsf2 +; PURECAP-DDC-LOADS-NEXT: lui a0, 260096 +; PURECAP-DDC-LOADS-NEXT: fmv.w.x fa5, a0 +; PURECAP-DDC-LOADS-NEXT: fadd.s fa0, fa0, fa5 +; PURECAP-DDC-LOADS-NEXT: ccall __truncsfhf2 +; PURECAP-DDC-LOADS-NEXT: fmv.x.w a0, fa0 +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: csh a0, 0(cs0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: clc cra, 16(csp) # 16-byte Folded Reload +; PURECAP-DDC-LOADS-NEXT: clc cs0, 0(csp) # 16-byte Folded Reload +; PURECAP-DDC-LOADS-NEXT: cincoffset csp, csp, 32 +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %plus_one = fadd half %value, 1.0 + store half %plus_one, half addrspace(200)* %dst + ret void +} + +define internal void @store_f32(float %value, float addrspace(200)* %dst) nounwind { +; PURECAP-LABEL: store_f32: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: lui a1, 260096 +; PURECAP-NEXT: fmv.w.x fa5, a1 +; PURECAP-NEXT: fadd.s fa5, fa0, fa5 +; PURECAP-NEXT: cfsw fa5, 0(ca0) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: store_f32: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: lui a1, 260096 +; HYBRID-NEXT: fmv.w.x fa5, a1 +; HYBRID-NEXT: fadd.s fa5, fa0, fa5 +; HYBRID-NEXT: fmv.x.w a1, fa5 +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: sw a1, 0(a0) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: store_f32: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: lui a1, 260096 +; HYBRID-XCHERI-NEXT: fmv.w.x fa5, a1 +; HYBRID-XCHERI-NEXT: fadd.s fa5, fa0, fa5 +; HYBRID-XCHERI-NEXT: fmv.x.w a1, fa5 +; HYBRID-XCHERI-NEXT: sw.cap a1, (ca0) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: store_f32: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: lui a1, 260096 +; PURECAP-DDC-LOADS-NEXT: fmv.w.x fa5, a1 +; PURECAP-DDC-LOADS-NEXT: fadd.s fa5, fa0, fa5 +; PURECAP-DDC-LOADS-NEXT: fmv.x.w a1, fa5 +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: csw a1, 0(ca0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %plus_one = fadd float %value, 1.0 + store float %plus_one, float addrspace(200)* %dst + ret void +} + +define internal void @store_f64(double %value, double addrspace(200)* %dst) nounwind { +; PURECAP-LABEL: store_f64: +; PURECAP: # %bb.0: # %entry +; PURECAP-NEXT: .LBB18_1: # %entry +; PURECAP-NEXT: # Label of block must be emitted +; PURECAP-NEXT: auipcc ca1, %pcrel_hi(.LCPI18_0) +; PURECAP-NEXT: cincoffset ca1, ca1, %pcrel_lo(.LBB18_1) +; PURECAP-NEXT: cfld fa5, 0(ca1) +; PURECAP-NEXT: fadd.d fa5, fa0, fa5 +; PURECAP-NEXT: cfsd fa5, 0(ca0) +; PURECAP-NEXT: cret +; +; HYBRID-LABEL: store_f64: +; HYBRID: # %bb.0: # %entry +; HYBRID-NEXT: lui a1, %hi(.LCPI18_0) +; HYBRID-NEXT: fld fa5, %lo(.LCPI18_0)(a1) +; HYBRID-NEXT: fadd.d fa5, fa0, fa5 +; HYBRID-NEXT: fmv.x.d a1, fa5 +; HYBRID-NEXT: modesw.cap +; HYBRID-NEXT: sd a1, 0(a0) +; HYBRID-NEXT: modesw.int +; HYBRID-NEXT: ret +; +; HYBRID-XCHERI-LABEL: store_f64: +; HYBRID-XCHERI: # %bb.0: # %entry +; HYBRID-XCHERI-NEXT: lui a1, %hi(.LCPI18_0) +; HYBRID-XCHERI-NEXT: fld fa5, %lo(.LCPI18_0)(a1) +; HYBRID-XCHERI-NEXT: fadd.d fa5, fa0, fa5 +; HYBRID-XCHERI-NEXT: fmv.x.d a1, fa5 +; HYBRID-XCHERI-NEXT: sd.cap a1, (ca0) +; HYBRID-XCHERI-NEXT: ret +; +; PURECAP-DDC-LOADS-LABEL: store_f64: +; PURECAP-DDC-LOADS: # %bb.0: # %entry +; PURECAP-DDC-LOADS-NEXT: .LBB18_1: # %entry +; PURECAP-DDC-LOADS-NEXT: # Label of block must be emitted +; PURECAP-DDC-LOADS-NEXT: auipcc ca1, %pcrel_hi(.LCPI18_0) +; PURECAP-DDC-LOADS-NEXT: cincoffset ca1, ca1, %pcrel_lo(.LBB18_1) +; PURECAP-DDC-LOADS-NEXT: cfld fa5, 0(ca1) +; PURECAP-DDC-LOADS-NEXT: fadd.d fa5, fa0, fa5 +; PURECAP-DDC-LOADS-NEXT: fmv.x.d a1, fa5 +; PURECAP-DDC-LOADS-NEXT: modesw.int +; PURECAP-DDC-LOADS-NEXT: csd a1, 0(ca0) +; PURECAP-DDC-LOADS-NEXT: modesw.cap +; PURECAP-DDC-LOADS-NEXT: cret +entry: + %plus_one = fadd double %value, 1.0 + store double %plus_one, double addrspace(200)* %dst + ret void +} diff --git a/llvm/test/CodeGen/RISCV/cheri/std-compat/set-offset.ll b/llvm/test/CodeGen/RISCV/cheri/std-compat/set-offset.ll new file mode 100644 index 0000000000000..e65cb2a44a2b5 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/cheri/std-compat/set-offset.ll @@ -0,0 +1,50 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +;; CSetOffset is not part of the standard, check that we emit SCADDR(c, GCBASE(c)+offset) instead. +; RUN: %riscv64_cheri_purecap_llc -verify-machineinstrs < %s | FileCheck %s --check-prefix=XCHERI +; RUN: %riscv64_cheri_purecap_llc -mattr=+xcheri-std-compat -verify-machineinstrs < %s | FileCheck %s --check-prefix=STD-COMPAT + +define internal ptr addrspace(200) @test(ptr addrspace(200) %dst, ptr addrspace(200) %cap, i64 %offset) addrspace(200) nounwind { +; XCHERI-LABEL: test: +; XCHERI: # %bb.0: # %entry +; XCHERI-NEXT: csetoffset ca1, ca1, a2 +; XCHERI-NEXT: csc ca1, 0(ca0) +; XCHERI-NEXT: cmove ca0, ca1 +; XCHERI-NEXT: cret +; +; STD-COMPAT-LABEL: test: +; STD-COMPAT: # %bb.0: # %entry +; STD-COMPAT-NEXT: cgetbase a3, ca1 +; STD-COMPAT-NEXT: add a2, a3, a2 +; STD-COMPAT-NEXT: csetaddr ca1, ca1, a2 +; STD-COMPAT-NEXT: csc ca1, 0(ca0) +; STD-COMPAT-NEXT: cmove ca0, ca1 +; STD-COMPAT-NEXT: cret +entry: + %new = call addrspace(200) ptr addrspace(200) @llvm.cheri.cap.offset.set.i64(ptr addrspace(200) %cap, i64 %offset) + store ptr addrspace(200) %new, ptr addrspace(200) %dst, align 16 + ret ptr addrspace(200) %new +} + +;; SetOffset with zero should be folded to setaddr(getbase()) +define internal ptr addrspace(200) @test_zero_offset(ptr addrspace(200) %dst, ptr addrspace(200) %cap) addrspace(200) nounwind { +; XCHERI-LABEL: test_zero_offset: +; XCHERI: # %bb.0: # %entry +; XCHERI-NEXT: csetoffset ca1, ca1, zero +; XCHERI-NEXT: csc ca1, 0(ca0) +; XCHERI-NEXT: cmove ca0, ca1 +; XCHERI-NEXT: cret +; +; STD-COMPAT-LABEL: test_zero_offset: +; STD-COMPAT: # %bb.0: # %entry +; STD-COMPAT-NEXT: cgetbase a2, ca1 +; STD-COMPAT-NEXT: csetaddr ca1, ca1, a2 +; STD-COMPAT-NEXT: csc ca1, 0(ca0) +; STD-COMPAT-NEXT: cmove ca0, ca1 +; STD-COMPAT-NEXT: cret +entry: + %new = call addrspace(200) ptr addrspace(200) @llvm.cheri.cap.offset.set.i64(ptr addrspace(200) %cap, i64 0) + store ptr addrspace(200) %new, ptr addrspace(200) %dst, align 16 + ret ptr addrspace(200) %new +} + +declare ptr addrspace(200) @llvm.cheri.cap.offset.set.i64(ptr addrspace(200), i64) addrspace(200) diff --git a/llvm/test/CodeGen/RISCV/cheri/std-compat/variable-length-stack-alloc.ll b/llvm/test/CodeGen/RISCV/cheri/std-compat/variable-length-stack-alloc.ll new file mode 100644 index 0000000000000..f9ff96718290f --- /dev/null +++ b/llvm/test/CodeGen/RISCV/cheri/std-compat/variable-length-stack-alloc.ll @@ -0,0 +1,55 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +;; Aligning variable-size stack allocations uses a CRRL intrinsic. +;; However, CRRL is not part of the RISC-V Standard -- check that we expand it. +; RUN: %riscv64_cheri_purecap_llc -verify-machineinstrs < %s | FileCheck %s --check-prefix=XCHERI +; RUN: %riscv64_cheri_purecap_llc -mattr=+xcheri-std-compat -verify-machineinstrs < %s | FileCheck %s --check-prefix=STD-COMPAT + +define internal i64 @cmd_stackstomp(i64 %0) addrspace(200) nounwind { +; XCHERI-LABEL: cmd_stackstomp: +; XCHERI: # %bb.0: # %entry +; XCHERI-NEXT: cincoffset csp, csp, -32 +; XCHERI-NEXT: csc cra, 16(csp) # 16-byte Folded Spill +; XCHERI-NEXT: csc cs0, 0(csp) # 16-byte Folded Spill +; XCHERI-NEXT: cincoffset cs0, csp, 32 +; XCHERI-NEXT: addi a0, a0, 15 +; XCHERI-NEXT: andi a0, a0, -16 +; XCHERI-NEXT: crrl a1, a0 +; XCHERI-NEXT: sub a1, sp, a1 +; XCHERI-NEXT: cram a0, a0 +; XCHERI-NEXT: and a0, a1, a0 +; XCHERI-NEXT: csetaddr csp, csp, a0 +; XCHERI-NEXT: li a0, 0 +; XCHERI-NEXT: cincoffset csp, cs0, -32 +; XCHERI-NEXT: clc cra, 16(csp) # 16-byte Folded Reload +; XCHERI-NEXT: clc cs0, 0(csp) # 16-byte Folded Reload +; XCHERI-NEXT: cincoffset csp, csp, 32 +; XCHERI-NEXT: cret +; +; STD-COMPAT-LABEL: cmd_stackstomp: +; STD-COMPAT: # %bb.0: # %entry +; STD-COMPAT-NEXT: cincoffset csp, csp, -32 +; STD-COMPAT-NEXT: csc cra, 16(csp) # 16-byte Folded Spill +; STD-COMPAT-NEXT: csc cs0, 0(csp) # 16-byte Folded Spill +; STD-COMPAT-NEXT: cincoffset cs0, csp, 32 +; STD-COMPAT-NEXT: addi a0, a0, 15 +; STD-COMPAT-NEXT: andi a0, a0, -16 +; STD-COMPAT-NEXT: cram a1, a0 +; STD-COMPAT-NEXT: not a2, a1 +; STD-COMPAT-NEXT: add a0, a0, a2 +; STD-COMPAT-NEXT: and a0, a0, a1 +; STD-COMPAT-NEXT: sub a0, sp, a0 +; STD-COMPAT-NEXT: and a0, a0, a1 +; STD-COMPAT-NEXT: csetaddr csp, csp, a0 +; STD-COMPAT-NEXT: li a0, 0 +; STD-COMPAT-NEXT: cincoffset csp, cs0, -32 +; STD-COMPAT-NEXT: clc cra, 16(csp) # 16-byte Folded Reload +; STD-COMPAT-NEXT: clc cs0, 0(csp) # 16-byte Folded Reload +; STD-COMPAT-NEXT: cincoffset csp, csp, 32 +; STD-COMPAT-NEXT: cret +entry: + br label %if.then +if.then: + %vla = alloca i8, i64 %0, align 1, addrspace(200) + %ret = ptrtoint i8 addrspace(200)* %vla to i64 + ret i64 0 +} diff --git a/llvm/test/MC/RISCV/cheri/rv32axcheri-only-valid.s b/llvm/test/MC/RISCV/cheri/rv32axcheri-only-valid.s index e7d75d3a0e6e1..a0e7d02226449 100644 --- a/llvm/test/MC/RISCV/cheri/rv32axcheri-only-valid.s +++ b/llvm/test/MC/RISCV/cheri/rv32axcheri-only-valid.s @@ -3,6 +3,8 @@ # RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+a,+xcheri < %s \ # RUN: | llvm-objdump -M no-aliases --mattr=+a,+xcheri -d - \ # RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s +# RUN: not llvm-mc %s --triple=riscv64 --mattr=+a,+xcheri-std-compat --filetype=obj -o /dev/null 2>&1 \ +# RUN: | FileCheck --check-prefix=STD-COMPAT-ERROR --implicit-check-not="error:" %s # CHECK-ASM-AND-OBJ: lr.c ct0, (t1) # CHECK-ASM: encoding: [0xaf,0x32,0x03,0x10] @@ -44,17 +46,29 @@ amoswap.c.rl ca4, cra, (s0) amoswap.c.aqrl ca4, cra, (s0) # CHECK-ASM-AND-OBJ: lr.c.ddc cra, (sp) +# STD-COMPAT-ERROR: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lr.c.ddc c1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x00,0x31,0xfb] lr.c.ddc c1, (x2) # CHECK-ASM-AND-OBJ: sc.c.ddc cra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.c.ddc c1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x09,0x11,0xf8] sc.c.ddc c1, (x2) # CHECK-ASM-AND-OBJ: lr.c.cap cra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lr.c.cap c1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x00,0xb1,0xfb] lr.c.cap c1, (c2) # CHECK-ASM-AND-OBJ: sc.c.cap cra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.c.cap c1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x0d,0x11,0xf8] sc.c.cap c1, (c2) diff --git a/llvm/test/MC/RISCV/cheri/rv32axcheri-valid.s b/llvm/test/MC/RISCV/cheri/rv32axcheri-valid.s index ed594ba57bb97..8206adbe05db5 100644 --- a/llvm/test/MC/RISCV/cheri/rv32axcheri-valid.s +++ b/llvm/test/MC/RISCV/cheri/rv32axcheri-valid.s @@ -8,43 +8,81 @@ # RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+a,+xcheri < %s \ # RUN: | llvm-objdump -M no-aliases --mattr=+a,+xcheri -d - \ # RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s +# RUN: not llvm-mc %s --triple=riscv64 --mattr=+a,+xcheri-std-compat --filetype=obj -o /dev/null 2>&1 \ +# RUN: | FileCheck --check-prefix=STD-COMPAT-ERROR --implicit-check-not="error:" %s # CHECK-ASM-AND-OBJ: lr.b.ddc ra, (sp) +# STD-COMPAT-ERROR: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lr.b.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x00,0x01,0xfb] lr.b.ddc x1, (x2) # CHECK-ASM-AND-OBJ: lr.h.ddc ra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lr.h.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x00,0x11,0xfb] lr.h.ddc x1, (x2) # CHECK-ASM-AND-OBJ: lr.w.ddc ra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lr.w.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x00,0x21,0xfb] lr.w.ddc x1, (x2) # CHECK-ASM-AND-OBJ: sc.b.ddc ra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.b.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0x5b,0x08,0x11,0xf8] sc.b.ddc x1, (x2) # CHECK-ASM-AND-OBJ: sc.h.ddc ra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.h.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x08,0x11,0xf8] sc.h.ddc x1, (x2) # CHECK-ASM-AND-OBJ: sc.w.ddc ra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.w.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0x5b,0x09,0x11,0xf8] sc.w.ddc x1, (x2) # CHECK-ASM-AND-OBJ: lr.b.cap ra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lr.b.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x00,0x81,0xfb] lr.b.cap x1, (c2) # CHECK-ASM-AND-OBJ: lr.h.cap ra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lr.h.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x00,0x91,0xfb] lr.h.cap x1, (c2) # CHECK-ASM-AND-OBJ: lr.w.cap ra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lr.w.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x00,0xa1,0xfb] lr.w.cap x1, (c2) # CHECK-ASM-AND-OBJ: sc.b.cap ra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.b.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0x5b,0x0c,0x11,0xf8] sc.b.cap x1, (c2) # CHECK-ASM-AND-OBJ: sc.h.cap ra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.h.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x0c,0x11,0xf8] sc.h.cap x1, (c2) # CHECK-ASM-AND-OBJ: sc.w.cap ra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.w.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0x5b,0x0d,0x11,0xf8] sc.w.cap x1, (c2) diff --git a/llvm/test/MC/RISCV/cheri/rv32xcheri-cap-mode-valid.s b/llvm/test/MC/RISCV/cheri/rv32xcheri-cap-mode-valid.s index aa1699f1e56ec..ceeb5287b3111 100644 --- a/llvm/test/MC/RISCV/cheri/rv32xcheri-cap-mode-valid.s +++ b/llvm/test/MC/RISCV/cheri/rv32xcheri-cap-mode-valid.s @@ -4,10 +4,10 @@ # RUN: | FileCheck --check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s # RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+xcheri,+cap-mode < %s \ # RUN: | llvm-objdump -M no-aliases --mattr=+xcheri,+cap-mode -d - \ -# RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s +# RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ,CHECK-OBJ %s # RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+xcheri,+cap-mode < %s \ # RUN: | llvm-objdump -M no-aliases --mattr=+xcheri,+cap-mode -d - \ -# RUN: | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ %s +# RUN: | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ,CHECK-OBJ %s ## Same test again without the "c" prefix on all lines # RUN: sed -e 's/^c//' < %s > %t.s @@ -17,10 +17,10 @@ # RUN: | FileCheck --check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s # RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+xcheri,+cap-mode < %t.s \ # RUN: | llvm-objdump -M no-aliases --mattr=+xcheri,+cap-mode -d - \ -# RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s +# RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ,CHECK-OBJ %s # RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+xcheri,+cap-mode < %t.s \ # RUN: | llvm-objdump -M no-aliases --mattr=+xcheri,+cap-mode -d - \ -# RUN: | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ %s +# RUN: | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ,CHECK-OBJ %s # CHECK-ASM-AND-OBJ: clb a2, 17(ca0) # CHECK-ASM-SAME: encoding: [0x03,0x06,0x15,0x01] @@ -79,3 +79,41 @@ clbu ra, (csp) # CHECK-ASM-AND-OBJ: clhu ra, 0(csp) # CHECK-ASM-SAME: encoding: [0x83,0x50,0x01,0x00] clhu ra, (csp) + + +# Jump instructions +# CHECK-ASM: cjal cnull, 16 +# CHECK-OBJ: cjal cnull, 0x50 <.text+0x50> +# CHECK-ASM-SAME: encoding: [0x6f,0x00,0x00,0x01] +cj 16 +# CHECK-ASM: cjal cra, 16 +# CHECK-OBJ: cjal cra, 0x54 <.text+0x54> +# CHECK-ASM-SAME: encoding: [0xef,0x00,0x00,0x01] +cjal 16 +# CHECK-ASM-AND-OBJ: cjalr cnull, 0(cgp) +# CHECK-ASM-SAME: encoding: [0x67,0x80,0x01,0x00] +cjr c3 +# CHECK-ASM-AND-OBJ: cjalr cnull, 2(cgp) +# CHECK-ASM-SAME: encoding: [0x67,0x80,0x21,0x00] +cjr 2(c3) +# CHECK-ASM-AND-OBJ: cjalr cra, 0(cgp) +# CHECK-ASM-SAME: encoding: [0xe7,0x80,0x01,0x00] +cjalr c3 +# CHECK-ASM-AND-OBJ: cjalr cra, 2(cgp) +# CHECK-ASM-SAME:encoding: [0xe7,0x80,0x21,0x00] +cjalr 2(c3) +# CHECK-ASM-AND-OBJ: cjalr cra, 0(cgp) +# CHECK-ASM-SAME: encoding: [0xe7,0x80,0x01,0x00] +cjalr c1, c3 +# CHECK-ASM-AND-OBJ: cjalr cnull, 0(cra) +# CHECK-ASM-SAME: encoding: [0x67,0x80,0x00,0x00] +cret +# CHECK-ASM-AND-OBJ: cjalr cnull, 16(cgp) +# CHECK-ASM-SAME: encoding: [0x67,0x80,0x01,0x01] +cjr c3, 16 +# CHECK-ASM-AND-OBJ: cjalr cra, 16(cgp) +# CHECK-ASM-SAME: encoding: [0xe7,0x80,0x01,0x01] +cjalr c3, 16 +# CHECK-ASM-AND-OBJ: cjalr cra, 16(cgp) +# CHECK-ASM-SAME: encoding: [0xe7,0x80,0x01,0x01] +cjalr c1, c3, 16 diff --git a/llvm/test/MC/RISCV/cheri/rv32xcheri-only-valid.s b/llvm/test/MC/RISCV/cheri/rv32xcheri-only-valid.s index a174c336183c1..e08181ea915f4 100644 --- a/llvm/test/MC/RISCV/cheri/rv32xcheri-only-valid.s +++ b/llvm/test/MC/RISCV/cheri/rv32xcheri-only-valid.s @@ -3,6 +3,8 @@ # RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+xcheri < %s \ # RUN: | llvm-objdump -M no-aliases --mattr=+xcheri -d - \ # RUN: | FileCheck -check-prefix=CHECK-INST %s +# RUN: not llvm-mc %s --triple=riscv64 --mattr=+xcheri-std-compat --filetype=obj -o /dev/null 2>&1 \ +# RUN: | FileCheck --check-prefix=STD-COMPAT-ERROR --implicit-check-not="error:" %s # CHECK-INST: lc cra, 3(sp) # CHECK: encoding: [0x83,0x30,0x31,0x00] @@ -12,18 +14,24 @@ lc c1, 3(x2) # CHECK: encoding: [0xa3,0x31,0x11,0x00] sc c1, 3(x2) -# CHECK-INST: lc.ddc cra, (sp) +# STD-COMPAT-ERROR: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lc.ddc c1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0xdb,0x00,0x31,0xfa] lc.ddc c1, (x2) - -# CHECK-INST: sc.ddc cra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.ddc c1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0xdb,0x01,0x11,0xf8] sc.ddc c1, (x2) - -# CHECK-INST: lc.cap cra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lc.cap c1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0xdb,0x00,0xb1,0xfa] lc.cap c1, (c2) - -# CHECK-INST: sc.cap cra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.cap c1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0xdb,0x05,0x11,0xf8] sc.cap c1, (c2) +# STD-COMPAT-ERROR-EMPTY: diff --git a/llvm/test/MC/RISCV/cheri/rv32xcheri-std-compat-valid.s b/llvm/test/MC/RISCV/cheri/rv32xcheri-std-compat-valid.s new file mode 100644 index 0000000000000..b164d9c903ee0 --- /dev/null +++ b/llvm/test/MC/RISCV/cheri/rv32xcheri-std-compat-valid.s @@ -0,0 +1,24 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+xcheri-std-compat -riscv-no-aliases -show-encoding +# RUN: llvm-mc %s -triple=riscv32 -mattr=+xcheri-std-compat -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+xcheri-std-compat -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s + +# RUN: not llvm-mc %s --triple=riscv64 --mattr=+xcheri,-xcheri-std-compat --filetype=obj -o /dev/null 2>&1 \ +# RUN: | FileCheck --check-prefix=NO-STD-COMPAT-ERROR --implicit-check-not="error:" %s + +# CHECK-INST: modesw.cap +# NO-STD-COMPAT-ERROR: [[#@LINE+4]]:1: error: instruction requires the following: CHERI standard-compatible subset{{$}} +# NO-STD-COMPAT-ERROR-NEXT: modesw.cap +# NO-STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0x33,0x10,0x00,0x12] +modesw.cap +# CHECK-INST: modesw.int +# NO-STD-COMPAT-ERROR: [[#@LINE+4]]:1: error: instruction requires the following: CHERI standard-compatible subset{{$}} +# NO-STD-COMPAT-ERROR-NEXT: modesw.int +# NO-STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0x33,0x10,0x00,0x14] +modesw.int + +# Should not see any further errors +# NO-STD-COMPAT-ERROR-EMPTY: diff --git a/llvm/test/MC/RISCV/cheri/rv32xcheri-valid.s b/llvm/test/MC/RISCV/cheri/rv32xcheri-valid.s index 7a9bff2e3d7bc..c0e1d2fb02b14 100644 --- a/llvm/test/MC/RISCV/cheri/rv32xcheri-valid.s +++ b/llvm/test/MC/RISCV/cheri/rv32xcheri-valid.s @@ -9,232 +9,413 @@ # RUN: | llvm-objdump -M no-aliases --mattr=+xcheri -d - \ # RUN: | FileCheck -check-prefix=CHECK-INST %s +# RUN: not llvm-mc %s --triple=riscv64 --mattr=+xcheri-std-compat --filetype=obj -o /dev/null 2>&1 \ +# RUN: | FileCheck --check-prefix=STD-COMPAT-ERROR --implicit-check-not="error:" %s + # CHECK-INST: cgetperm ra, csp -# CHECK: encoding: [0xdb,0x00,0x01,0xfe] +# CHECK-SAME: encoding: [0xdb,0x00,0x01,0xfe] cgetperm x1, c2 +# CHECK-INST: cgetperm ra, csp +# CHECK-SAME: encoding: [0xdb,0x00,0x01,0xfe] +gcperm x1, c2 # CHECK-INST: cgettype ra, csp -# CHECK: encoding: [0xdb,0x00,0x11,0xfe] +# CHECK-SAME: encoding: [0xdb,0x00,0x11,0xfe] cgettype x1, c2 +# CHECK-INST: cgettype ra, csp +# CHECK-SAME: encoding: [0xdb,0x00,0x11,0xfe] +gctype x1, c2 # CHECK-INST: cgetbase ra, csp -# CHECK: encoding: [0xdb,0x00,0x21,0xfe] +# CHECK-SAME: encoding: [0xdb,0x00,0x21,0xfe] cgetbase x1, c2 +# CHECK-INST: cgetbase ra, csp +# CHECK-SAME: encoding: [0xdb,0x00,0x21,0xfe] +gcbase x1, c2 # CHECK-INST: cgetlen ra, csp -# CHECK: encoding: [0xdb,0x00,0x31,0xfe] +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0xfe] cgetlen x1, c2 +# CHECK-INST: cgetlen ra, csp +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0xfe] +gclen x1, c2 # CHECK-INST: cgettag ra, csp -# CHECK: encoding: [0xdb,0x00,0x41,0xfe] +# CHECK-SAME: encoding: [0xdb,0x00,0x41,0xfe] cgettag x1, c2 +# CHECK-INST: cgettag ra, csp +# CHECK-SAME: encoding: [0xdb,0x00,0x41,0xfe] +gctag x1, c2 # CHECK-INST: cgetsealed ra, csp -# CHECK: encoding: [0xdb,0x00,0x51,0xfe] +# STD-COMPAT-ERROR: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: cgetsealed x1, c2 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x51,0xfe] cgetsealed x1, c2 # CHECK-INST: cgetoffset ra, csp -# CHECK: encoding: [0xdb,0x00,0x61,0xfe] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: cgetoffset x1, c2 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x61,0xfe] cgetoffset x1, c2 # CHECK-INST: cgetflags ra, csp -# CHECK: encoding: [0xdb,0x00,0x71,0xfe] +# CHECK-SAME: encoding: [0xdb,0x00,0x71,0xfe] cgetflags x1, c2 +# TODO: gcmode = cgetflags xor 1 # CHECK-INST: addi ra, sp, 0 -# CHECK: encoding: [0x93,0x00,0x01,0x00] +# CHECK-SAME: encoding: [0x93,0x00,0x01,0x00] cgetaddr x1, c2 # CHECK-INST: cgethigh ra, csp -# CHECK: encoding: [0xdb,0x00,0x71,0xff] +# CHECK-SAME: encoding: [0xdb,0x00,0x71,0xff] cgethigh x1, c2 +# CHECK-INST: cgethigh ra, csp +# CHECK-SAME: encoding: [0xdb,0x00,0x71,0xff] +gchi x1, c2 # CHECK-INST: cseal cra, csp, cgp -# CHECK: encoding: [0xdb,0x00,0x31,0x16] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: cseal c1, c2, c3 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x16] cseal c1, c2, c3 # CHECK-INST: cunseal cra, csp, cgp -# CHECK: encoding: [0xdb,0x00,0x31,0x18] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: cunseal c1, c2, c3 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x18] cunseal c1, c2, c3 # CHECK-INST: candperm cra, csp, gp -# CHECK: encoding: [0xdb,0x00,0x31,0x1a] +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x1a] candperm c1, c2, x3 +# CHECK-INST: candperm cra, csp, gp +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x1a] +acperm c1, c2, x3 # CHECK-INST: csetflags cra, csp, gp -# CHECK: encoding: [0xdb,0x00,0x31,0x1c] +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x1c] csetflags c1, c2, x3 # CHECK-INST: csetoffset cra, csp, gp -# CHECK: encoding: [0xdb,0x00,0x31,0x1e] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: csetoffset c1, c2, x3 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x1e] csetoffset c1, c2, x3 # CHECK-INST: csetaddr cra, csp, gp -# CHECK: encoding: [0xdb,0x00,0x31,0x20] +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x20] csetaddr c1, c2, x3 +# CHECK-INST: csetaddr cra, csp, gp +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x20] +scaddr c1, c2, x3 # CHECK-INST: csethigh cra, csp, gp -# CHECK: encoding: [0xdb,0x00,0x31,0x2c] +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x2c] csethigh c1, c2, x3 +# CHECK-INST: csethigh cra, csp, gp +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x2c] +schi c1, c2, x3 # CHECK-INST: cincoffset cra, csp, gp -# CHECK: encoding: [0xdb,0x00,0x31,0x22] +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x22] cincoffset c1, c2, x3 +# CHECK-INST: cincoffset cra, csp, gp +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x22] +add c1, c2, x3 # CHECK-INST: cincoffset cra, csp, -173 -# CHECK: encoding: [0xdb,0x10,0x31,0xf5] +# CHECK-SAME: encoding: [0xdb,0x10,0x31,0xf5] cincoffset c1, c2, -173 # CHECK-INST: cincoffset cra, csp, -173 -# CHECK: encoding: [0xdb,0x10,0x31,0xf5] +# CHECK-SAME: encoding: [0xdb,0x10,0x31,0xf5] +add c1, c2, -173 +# CHECK-INST: cincoffset cra, csp, -173 +# CHECK-SAME: encoding: [0xdb,0x10,0x31,0xf5] cincoffsetimm c1, c2, -173 +# CHECK-INST: cincoffset cra, csp, -173 +# CHECK-SAME: encoding: [0xdb,0x10,0x31,0xf5] +addi c1, c2, -173 # CHECK-INST: csetbounds cra, csp, gp -# CHECK: encoding: [0xdb,0x00,0x31,0x10] +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x10] csetbounds c1, c2, x3 +# CHECK-INST: csetbounds cra, csp, gp +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x10] +scbndsr c1, c2, x3 # CHECK-INST: csetboundsexact cra, csp, gp -# CHECK: encoding: [0xdb,0x00,0x31,0x12] +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x12] csetboundsexact c1, c2, x3 +# CHECK-INST: csetboundsexact cra, csp, gp +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x12] +scbnds c1, c2, x3 # CHECK-INST: csetbounds cra, csp, 3029 -# CHECK: encoding: [0xdb,0x20,0x51,0xbd] +# CHECK-SAME: encoding: [0xdb,0x20,0x51,0xbd] csetbounds c1, c2, 0xbd5 # CHECK-INST: csetbounds cra, csp, 3029 -# CHECK: encoding: [0xdb,0x20,0x51,0xbd] +# CHECK-SAME: encoding: [0xdb,0x20,0x51,0xbd] +scbnds c1, c2, 0xbd5 +# CHECK-INST: csetbounds cra, csp, 3029 +# CHECK-SAME: encoding: [0xdb,0x20,0x51,0xbd] csetboundsimm c1, c2, 0xbd5 +# CHECK-INST: csetbounds cra, csp, 3029 +# CHECK-SAME: encoding: [0xdb,0x20,0x51,0xbd] +scbndsi c1, c2, 0xbd5 # CHECK-INST: ccleartag cra, csp -# CHECK: encoding: [0xdb,0x00,0xb1,0xfe] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: ccleartag c1, c2 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0xb1,0xfe] ccleartag c1, c2 # CHECK-INST: cbuildcap cra, csp, cgp -# CHECK: encoding: [0xdb,0x00,0x31,0x3a] +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x3a] cbuildcap c1, c2, c3 +# CHECK-INST: cbuildcap cra, csp, cgp +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x3a] +cbld c1, c2, c3 # CHECK-INST: cbuildcap cra, ddc, cgp -# CHECK: encoding: [0xdb,0x00,0x30,0x3a] -cbuildcap c1, ddc, c3 +# CHECK-SAME: encoding: [0xdb,0x00,0x30,0x3a] +cbuildcap c1, ddc, c3 # Note: Not supported with the cbld syntax # CHECK-INST: ccopytype cra, csp, cgp -# CHECK: encoding: [0xdb,0x00,0x31,0x3c] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: ccopytype c1, c2, c3 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x3c] ccopytype c1, c2, c3 # CHECK-INST: ccseal cra, csp, cgp -# CHECK: encoding: [0xdb,0x00,0x31,0x3e] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: ccseal c1, c2, c3 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x3e] ccseal c1, c2, c3 # CHECK-INST: csealentry cra, csp -# CHECK: encoding: [0xdb,0x00,0x11,0xff] +# CHECK-SAME: encoding: [0xdb,0x00,0x11,0xff] csealentry c1, c2 +# CHECK-INST: csealentry cra, csp +# CHECK-SAME: encoding: [0xdb,0x00,0x11,0xff] +sentry c1, c2 # CHECK-INST: sub ra, sp, gp -# CHECK: encoding: [0xb3,0x00,0x31,0x40] +# CHECK-SAME: encoding: [0xb3,0x00,0x31,0x40] csub x1, c2, c3 # CHECK-INST: cmove cra, csp -# CHECK: encoding: [0xdb,0x00,0xa1,0xfe] +# CHECK-SAME: encoding: [0xdb,0x00,0xa1,0xfe] cmove c1, c2 # CHECK-INST: jalr.cap cra, csp -# CHECK: encoding: [0xdb,0x00,0xc1,0xfe] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: jalr.cap c1, c2 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0xc1,0xfe] jalr.cap c1, c2 # CHECK-INST: jalr.cap cra, csp -# CHECK: encoding: [0xdb,0x00,0xc1,0xfe] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: jalr.cap c2 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0xc1,0xfe] jalr.cap c2 # CHECK-INST: jalr.cap cnull, cra -# CHECK: encoding: [0x5b,0x80,0xc0,0xfe] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: jr.cap c1 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0x5b,0x80,0xc0,0xfe] jr.cap c1 # CHECK-INST: jalr.cap cnull, cra -# CHECK: encoding: [0x5b,0x80,0xc0,0xfe] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: ret.cap +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0x5b,0x80,0xc0,0xfe] ret.cap # CHECK-INST: jalr.pcc ra, sp -# CHECK: encoding: [0xdb,0x00,0x41,0xff] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: jalr.pcc x1, x2 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x41,0xff] jalr.pcc x1, x2 # CHECK-INST: jalr.pcc ra, sp -# CHECK: encoding: [0xdb,0x00,0x41,0xff] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: jalr.pcc x2 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x41,0xff] jalr.pcc x2 # CHECK-INST: jalr.pcc zero, ra -# CHECK: encoding: [0x5b,0x80,0x40,0xff] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: jr.pcc x1 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0x5b,0x80,0x40,0xff] jr.pcc x1 # CHECK-INST: jalr.pcc zero, ra -# CHECK: encoding: [0x5b,0x80,0x40,0xff] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: ret.pcc +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0x5b,0x80,0x40,0xff] ret.pcc # CHECK-INST: cinvoke cra, csp -# CHECK: encoding: [0xdb,0x80,0x20,0xfc] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: cinvoke c1, c2 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x80,0x20,0xfc] cinvoke c1, c2 # CHECK-INST: ctestsubset ra, csp, cgp -# CHECK: encoding: [0xdb,0x00,0x31,0x40] +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x40] ctestsubset x1, c2, c3 +# CHECK-INST: ctestsubset ra, csp, cgp +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x40] +scss x1, c2, c3 # CHECK-INST: ctestsubset ra, ddc, cgp -# CHECK: encoding: [0xdb,0x00,0x30,0x40] -ctestsubset x1, ddc, c3 +# CHECK-SAME: encoding: [0xdb,0x00,0x30,0x40] +ctestsubset x1, ddc, c3 # Note: Not supported with the scss syntax # CHECK-INST: csetequalexact ra, csp, cgp -# CHECK: encoding: [0xdb,0x00,0x31,0x42] +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x42] csetequalexact x1, c2, c3 # CHECK-INST: csetequalexact ra, csp, cgp -# CHECK: encoding: [0xdb,0x00,0x31,0x42] +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x42] cseqx x1, c2, c3 +# CHECK-INST: csetequalexact ra, csp, cgp +# CHECK-SAME: encoding: [0xdb,0x00,0x31,0x42] +sceq x1, c2, c3 # CHECK-INST: cspecialrw cra, uscratchc, csp -# CHECK: encoding: [0xdb,0x00,0x61,0x02] +# CHECK-SAME: encoding: [0xdb,0x00,0x61,0x02] cspecialrw c1, uscratchc, c2 # CHECK-INST: cspecialrw cra, uscratchc, csp -# CHECK: encoding: [0xdb,0x00,0x61,0x02] +# CHECK-SAME: encoding: [0xdb,0x00,0x61,0x02] cspecialrw c1, 0x6, c2 # CHECK-INST: cspecialrw cra, uscratchc, cnull -# CHECK: encoding: [0xdb,0x00,0x60,0x02] +# CHECK-SAME: encoding: [0xdb,0x00,0x60,0x02] cspecialr c1, uscratchc # CHECK-INST: cspecialrw cnull, uscratchc, csp -# CHECK: encoding: [0x5b,0x00,0x61,0x02] +# CHECK-SAME: encoding: [0x5b,0x00,0x61,0x02] cspecialw uscratchc, c2 # CHECK-INST: cclear 1, 66 -# CHECK: encoding: [0x5b,0x01,0xe5,0xfe] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: cclear 1, 0x42 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0x5b,0x01,0xe5,0xfe] cclear 1, 0x42 # CHECK-INST: fpclear 1, 66 -# CHECK: encoding: [0x5b,0x01,0x05,0xff] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: fpclear 1, 0x42 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0x5b,0x01,0x05,0xff] fpclear 1, 0x42 # CHECK-INST: croundrepresentablelength ra, sp -# CHECK: encoding: [0xdb,0x00,0x81,0xfe] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: croundrepresentablelength x1, x2 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x81,0xfe] croundrepresentablelength x1, x2 # CHECK-INST: croundrepresentablelength ra, sp -# CHECK: encoding: [0xdb,0x00,0x81,0xfe] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: crrl x1, x2 +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x81,0xfe] crrl x1, x2 # CHECK-INST: crepresentablealignmentmask ra, sp -# CHECK: encoding: [0xdb,0x00,0x91,0xfe] +# CHECK-SAME: encoding: [0xdb,0x00,0x91,0xfe] crepresentablealignmentmask x1, x2 # CHECK-INST: crepresentablealignmentmask ra, sp -# CHECK: encoding: [0xdb,0x00,0x91,0xfe] +# CHECK-SAME: encoding: [0xdb,0x00,0x91,0xfe] cram x1, x2 # CHECK-INST: cloadtags ra, (csp) -# CHECK: encoding: [0xdb,0x00,0x21,0xff] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: cloadtags x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x21,0xff] cloadtags x1, (c2) # CHECK-INST: lb.ddc ra, (sp) -# CHECK: encoding: [0xdb,0x00,0x01,0xfa] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lb.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x01,0xfa] lb.ddc x1, (x2) # CHECK-INST: lh.ddc ra, (sp) -# CHECK: encoding: [0xdb,0x00,0x11,0xfa] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lh.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x11,0xfa] lh.ddc x1, (x2) # CHECK-INST: lw.ddc ra, (sp) -# CHECK: encoding: [0xdb,0x00,0x21,0xfa] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lw.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x21,0xfa] lw.ddc x1, (x2) # CHECK-INST: lbu.ddc ra, (sp) -# CHECK: encoding: [0xdb,0x00,0x41,0xfa] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lbu.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x41,0xfa] lbu.ddc x1, (x2) # CHECK-INST: lhu.ddc ra, (sp) -# CHECK: encoding: [0xdb,0x00,0x51,0xfa] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lhu.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x51,0xfa] lhu.ddc x1, (x2) # CHECK-INST: sb.ddc ra, (sp) -# CHECK: encoding: [0x5b,0x00,0x11,0xf8] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sb.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0x5b,0x00,0x11,0xf8] sb.ddc x1, (x2) # CHECK-INST: sh.ddc ra, (sp) -# CHECK: encoding: [0xdb,0x00,0x11,0xf8] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sh.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x11,0xf8] sh.ddc x1, (x2) # CHECK-INST: sw.ddc ra, (sp) -# CHECK: encoding: [0x5b,0x01,0x11,0xf8] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sw.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0x5b,0x01,0x11,0xf8] sw.ddc x1, (x2) # CHECK-INST: lb.cap ra, (csp) -# CHECK: encoding: [0xdb,0x00,0x81,0xfa] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lb.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x81,0xfa] lb.cap x1, (c2) # CHECK-INST: lh.cap ra, (csp) -# CHECK: encoding: [0xdb,0x00,0x91,0xfa] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lh.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0x91,0xfa] lh.cap x1, (c2) # CHECK-INST: lw.cap ra, (csp) -# CHECK: encoding: [0xdb,0x00,0xa1,0xfa] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lw.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0xa1,0xfa] lw.cap x1, (c2) # CHECK-INST: lbu.cap ra, (csp) -# CHECK: encoding: [0xdb,0x00,0xc1,0xfa] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lbu.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0xc1,0xfa] lbu.cap x1, (c2) # CHECK-INST: lhu.cap ra, (csp) -# CHECK: encoding: [0xdb,0x00,0xd1,0xfa] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lhu.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x00,0xd1,0xfa] lhu.cap x1, (c2) # CHECK-INST: sb.cap ra, (csp) -# CHECK: encoding: [0x5b,0x04,0x11,0xf8] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sb.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0x5b,0x04,0x11,0xf8] sb.cap x1, (c2) # CHECK-INST: sh.cap ra, (csp) -# CHECK: encoding: [0xdb,0x04,0x11,0xf8] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sh.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0xdb,0x04,0x11,0xf8] sh.cap x1, (c2) # CHECK-INST: sw.cap ra, (csp) -# CHECK: encoding: [0x5b,0x05,0x11,0xf8] +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sw.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} +# CHECK-SAME: encoding: [0x5b,0x05,0x11,0xf8] sw.cap x1, (c2) + +# Should not see any further errors +# STD-COMPAT-ERROR-EMPTY: diff --git a/llvm/test/MC/RISCV/cheri/rv64axcheri-valid.s b/llvm/test/MC/RISCV/cheri/rv64axcheri-valid.s index 39e61d3c7696d..92612b4912bd9 100644 --- a/llvm/test/MC/RISCV/cheri/rv64axcheri-valid.s +++ b/llvm/test/MC/RISCV/cheri/rv64axcheri-valid.s @@ -3,6 +3,8 @@ # RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+a,+xcheri < %s \ # RUN: | llvm-objdump -M no-aliases --mattr=+a,+xcheri -d - \ # RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s +# RUN: not llvm-mc %s --triple=riscv64 --mattr=+a,+xcheri-std-compat --filetype=obj -o /dev/null 2>&1 \ +# RUN: | FileCheck --check-prefix=STD-COMPAT-ERROR --implicit-check-not="error:" %s # CHECK-ASM-AND-OBJ: lr.c ct0, (t1) # CHECK-ASM: encoding: [0xaf,0x42,0x03,0x10] @@ -44,29 +46,53 @@ amoswap.c.rl ca4, cra, (s0) amoswap.c.aqrl ca4, cra, (s0) # CHECK-ASM-AND-OBJ: lr.d.ddc ra, (sp) +# STD-COMPAT-ERROR: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lr.d.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x00,0x31,0xfb] lr.d.ddc x1, (x2) # CHECK-ASM-AND-OBJ: lr.c.ddc cra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lr.c.ddc c1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x00,0x41,0xfb] lr.c.ddc c1, (x2) # CHECK-ASM-AND-OBJ: sc.d.ddc ra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.d.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x09,0x11,0xf8] sc.d.ddc x1, (x2) # CHECK-ASM-AND-OBJ: sc.c.ddc cra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.c.ddc c1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0x5b,0x0a,0x11,0xf8] sc.c.ddc c1, (x2) # CHECK-ASM-AND-OBJ: lr.d.cap ra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lr.d.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x00,0xb1,0xfb] lr.d.cap x1, (c2) # CHECK-ASM-AND-OBJ: lr.c.cap cra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lr.c.cap c1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x00,0xc1,0xfb] lr.c.cap c1, (c2) # CHECK-ASM-AND-OBJ: sc.d.cap ra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.d.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0xdb,0x0d,0x11,0xf8] sc.d.cap x1, (c2) # CHECK-ASM-AND-OBJ: sc.c.cap cra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.c.cap c1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK-ASM: encoding: [0x5b,0x0e,0x11,0xf8] sc.c.cap c1, (c2) diff --git a/llvm/test/MC/RISCV/cheri/rv64xcheri-valid.s b/llvm/test/MC/RISCV/cheri/rv64xcheri-valid.s index a2e75fe375707..9b510f9116008 100644 --- a/llvm/test/MC/RISCV/cheri/rv64xcheri-valid.s +++ b/llvm/test/MC/RISCV/cheri/rv64xcheri-valid.s @@ -3,6 +3,8 @@ # RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+xcheri < %s \ # RUN: | llvm-objdump -M no-aliases --mattr=+xcheri -d - \ # RUN: | FileCheck -check-prefix=CHECK-INST %s +# RUN: not llvm-mc %s --triple=riscv64 --mattr=+a,+xcheri-std-compat --filetype=obj -o /dev/null 2>&1 \ +# RUN: | FileCheck --check-prefix=STD-COMPAT-ERROR --implicit-check-not="error:" %s # CHECK-INST: lc cra, 3(sp) # CHECK: encoding: [0x8f,0x20,0x31,0x00] @@ -13,35 +15,65 @@ lc c1, 3(x2) sc c1, 3(x2) # CHECK-INST: ld.ddc ra, (sp) +# STD-COMPAT-ERROR: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: ld.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0xdb,0x00,0x31,0xfa] ld.ddc x1, (x2) # CHECK-INST: lwu.ddc ra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lwu.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0xdb,0x00,0x61,0xfa] lwu.ddc x1, (x2) # CHECK-INST: lc.ddc cra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lc.ddc c1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0xdb,0x00,0x71,0xfb] lc.ddc c1, (x2) # CHECK-INST: sd.ddc ra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sd.ddc x1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0xdb,0x01,0x11,0xf8] sd.ddc x1, (x2) # CHECK-INST: sc.ddc cra, (sp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.ddc c1, (x2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0x5b,0x02,0x11,0xf8] sc.ddc c1, (x2) # CHECK-INST: ld.cap ra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: ld.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0xdb,0x00,0xb1,0xfa] ld.cap x1, (c2) # CHECK-INST: lwu.cap ra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lwu.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0xdb,0x00,0xe1,0xfa] lwu.cap x1, (c2) # CHECK-INST: lc.cap cra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: lc.cap c1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0xdb,0x00,0xf1,0xfb] lc.cap c1, (c2) # CHECK-INST: sd.cap ra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sd.cap x1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0xdb,0x05,0x11,0xf8] sd.cap x1, (c2) # CHECK-INST: sc.cap cra, (csp) +# STD-COMPAT-ERROR-NEXT: [[#@LINE+4]]:1: error: instruction requires the following: 'xcheri' extension with non-standard instructions{{$}} +# STD-COMPAT-ERROR-NEXT: sc.cap c1, (c2) +# STD-COMPAT-ERROR-NEXT: ^{{$}} # CHECK: encoding: [0x5b,0x06,0x11,0xf8] sc.cap c1, (c2)