{"d", RISCVExtensionVersion{2, 0}},
{"c", RISCVExtensionVersion{2, 0}},
+ {"zihintpause", RISCVExtensionVersion{2, 0}},
+
{"zfhmin", RISCVExtensionVersion{1, 0}},
{"zfh", RISCVExtensionVersion{1, 0}},
bool isFenceArg() const {
if (!isImm())
return false;
- const MCExpr *Val = getImm();
- auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
+
+ int64_t Imm;
+ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+ if (evaluateConstantImm(getImm(), Imm, VK)) {
+ // Only accept 0 as a constant immediate.
+ return VK == RISCVMCExpr::VK_RISCV_None && Imm == 0;
+ }
+
+ auto *SVal = dyn_cast<MCSymbolRefExpr>(getImm());
+
if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
return false;
void addFenceArgOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
+
+ int64_t Constant = 0;
+ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+ if (evaluateConstantImm(getImm(), Constant, VK)) {
+ if (Constant == 0) {
+ Inst.addOperand(MCOperand::createImm(Constant));
+ return;
+ }
+ llvm_unreachable("FenceArg must contain only [iorw] or be 0");
+ }
+
// isFenceArg has validated the operand, meaning this cast is safe
auto SE = cast<MCSymbolRefExpr>(getImm());
for (char c : SE->getSymbol().getName()) {
switch (c) {
default:
- llvm_unreachable("FenceArg must contain only [iorw]");
+ llvm_unreachable("FenceArg must contain only [iorw] or be 0");
case 'i':
Imm |= RISCVFenceField::I;
break;
}
case Match_InvalidFenceArg: {
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
- return Error(
- ErrorLoc,
- "operand must be formed of letters selected in-order from 'iorw'");
+ return Error(ErrorLoc, "operand must be formed of letters selected "
+ "in-order from 'iorw' or be 0");
}
case Match_InvalidFRMArg: {
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
if ((FenceArg & RISCVFenceField::W) != 0)
O << 'w';
if (FenceArg == 0)
- O << "unknown";
+ O << "0";
}
void RISCVInstPrinter::printFRMArg(const MCInst *MI, unsigned OpNo,
AssemblerPredicate<(all_of FeatureStdExtD),
"'D' (Double-Precision Floating-Point)">;
+def FeatureStdExtZihintpause
+ : SubtargetFeature<"zihintpause", "HasStdExtZihintpause", "true",
+ "'zihintpause' (Pause Hint)">;
+def HasStdExtZihintpause : Predicate<"Subtarget->hasStdExtZihintpause()">,
+ AssemblerPredicate<(all_of FeatureStdExtZihintpause),
+ "'Zihintpause' (Pause Hint)">;
+
def FeatureStdExtZfhmin
: SubtargetFeature<"zfhmin", "HasStdExtZfhmin", "true",
"'Zfhmin' (Half-Precision Floating-Point Minimal)",
def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw
+let Predicates = [HasStdExtZihintpause] in
+def : InstAlias<"pause", (FENCE 0x1, 0x0)>; // 0x1 == w
+
def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>;
def : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, CYCLE.Encoding, X0)>;
def : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, TIME.Encoding, X0)>;
bool HasStdExtF = false;
bool HasStdExtD = false;
bool HasStdExtC = false;
+ bool HasStdExtZihintpause = false;
bool HasStdExtZba = false;
bool HasStdExtZbb = false;
bool HasStdExtZbc = false;
bool hasStdExtD() const { return HasStdExtD; }
bool hasStdExtC() const { return HasStdExtC; }
bool hasStdExtV() const { return HasStdExtV; }
+ bool hasStdExtZihintpause() const { return HasStdExtZihintpause; }
bool hasStdExtZba() const { return HasStdExtZba; }
bool hasStdExtZbb() const { return HasStdExtZbb; }
bool hasStdExtZbc() const { return HasStdExtZbc; }
; RUN: llc -mtriple=riscv32 -mattr=+f %s -o - | FileCheck --check-prefix=RV32F %s
; RUN: llc -mtriple=riscv32 -mattr=+d %s -o - | FileCheck --check-prefix=RV32D %s
; RUN: llc -mtriple=riscv32 -mattr=+c %s -o - | FileCheck --check-prefix=RV32C %s
+; RUN: llc -mtriple=riscv32 -mattr=+zihintpause %s -o - | FileCheck --check-prefix=RV32ZIHINTPAUSE %s
; RUN: llc -mtriple=riscv32 -mattr=+zfhmin %s -o - | FileCheck --check-prefix=RV32ZFHMIN %s
; RUN: llc -mtriple=riscv32 -mattr=+zfh %s -o - | FileCheck --check-prefix=RV32ZFH %s
; RUN: llc -mtriple=riscv32 -mattr=+zba %s -o - | FileCheck --check-prefix=RV32ZBA %s
; RUN: llc -mtriple=riscv64 -mattr=+f %s -o - | FileCheck --check-prefix=RV64F %s
; RUN: llc -mtriple=riscv64 -mattr=+d %s -o - | FileCheck --check-prefix=RV64D %s
; RUN: llc -mtriple=riscv64 -mattr=+c %s -o - | FileCheck --check-prefix=RV64C %s
+; RUN: llc -mtriple=riscv64 -mattr=+zihintpause %s -o - | FileCheck --check-prefix=RV64ZIHINTPAUSE %s
; RUN: llc -mtriple=riscv64 -mattr=+zfhmin %s -o - | FileCheck --check-prefix=RV64ZFHMIN %s
; RUN: llc -mtriple=riscv64 -mattr=+zfh %s -o - | FileCheck --check-prefix=RV64ZFH %s
; RUN: llc -mtriple=riscv64 -mattr=+zba %s -o - | FileCheck --check-prefix=RV64ZBA %s
; RV32F: .attribute 5, "rv32i2p0_f2p0"
; RV32D: .attribute 5, "rv32i2p0_f2p0_d2p0"
; RV32C: .attribute 5, "rv32i2p0_c2p0"
+; RV32ZIHINTPAUSE: .attribute 5, "rv32i2p0_zihintpause2p0"
; RV32ZFHMIN: .attribute 5, "rv32i2p0_f2p0_zfhmin1p0"
; RV32ZFH: .attribute 5, "rv32i2p0_f2p0_zfh1p0"
; RV32ZBA: .attribute 5, "rv32i2p0_zba1p0"
; RV64F: .attribute 5, "rv64i2p0_f2p0"
; RV64D: .attribute 5, "rv64i2p0_f2p0_d2p0"
; RV64C: .attribute 5, "rv64i2p0_c2p0"
+; RV64ZIHINTPAUSE: .attribute 5, "rv64i2p0_zihintpause2p0"
; RV64ZFHMIN: .attribute 5, "rv64i2p0_f2p0_zfhmin1p0"
; RV64ZFH: .attribute 5, "rv64i2p0_f2p0_zfh1p0"
; RV64ZBA: .attribute 5, "rv64i2p0_zba1p0"
+++ /dev/null
-# RUN: llvm-mc -disassemble -triple=riscv32 < %s 2>&1 | FileCheck %s
-# RUN: llvm-mc -disassemble -triple=riscv64 < %s 2>&1 | FileCheck %s
-#
-# Test generated by a LLVM MC Disassembler Protocol Buffer Fuzzer
-# for the RISC-V assembly language.
-
-# This decodes as fence , iorw with invalid fence field as 0.
-[0x0f 0x00 0xf0 0x00]
-# CHECK: fence unknown, iorw
# Out of range immediates
## fencearg
-fence iorw, iore # CHECK: :[[@LINE]]:13: error: operand must be formed of letters selected in-order from 'iorw'
-fence wr, wr # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw'
-fence rw, rr # CHECK: :[[@LINE]]:11: error: operand must be formed of letters selected in-order from 'iorw'
-fence 1, rw # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw'
-fence unknown, unknown # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw'
+fence iorw, iore # CHECK: :[[@LINE]]:13: error: operand must be formed of letters selected in-order from 'iorw' or be 0
+fence wr, wr # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' or be 0
+fence rw, rr # CHECK: :[[@LINE]]:11: error: operand must be formed of letters selected in-order from 'iorw' or be 0
+fence 1, rw # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' or be 0
+fence unknown, unknown # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' or be 0
## uimm5
slli a0, a0, 32 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31]
clz a0, a1 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zbb' (Basic Bit-Manipulation)
clmul a0, a1, a2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zbc' (Carry-Less Multiplication)
bset a0, a1, a2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zbs' (Single-Bit Instructions)
+pause # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zihintpause' (Pause Hint)
# Using floating point registers when integer registers are expected
addi a2, ft0, 24 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
--- /dev/null
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+zihintpause -riscv-no-aliases -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+zihintpause -riscv-no-aliases -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+zihintpause < %s \
+# RUN: | llvm-objdump --mattr=+zihintpause -M no-aliases -d -r - \
+# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+zihintpause < %s \
+# RUN: | llvm-objdump --mattr=+zihintpause -M no-aliases -d -r - \
+# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: fence w, 0
+# CHECK-ASM: encoding: [0x0f,0x00,0x00,0x01]
+fence w,0
+# CHECK-ASM-AND-OBJ: fence 0, w
+# CHECK-ASM: encoding: [0x0f,0x00,0x10,0x00]
+fence 0,w
+# CHECK-ASM-AND-OBJ: fence 0, 0
+# CHECK-ASM: encoding: [0x0f,0x00,0x00,0x00]
+fence 0,0
--- /dev/null
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+zihintpause -M no-aliases \
+# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ-NOALIAS %s
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+zihintpause \
+# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+zihintpause -M no-aliases \
+# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ-NOALIAS %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+zihintpause \
+# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+zihintpause < %s \
+# RUN: | llvm-objdump --mattr=+zihintpause -d -r -M no-aliases - \
+# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ-NOALIAS %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+zihintpause < %s \
+# RUN: | llvm-objdump --mattr=+zihintpause -d -r - \
+# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+zihintpause < %s \
+# RUN: | llvm-objdump --mattr=+zihintpause -d -r -M no-aliases - \
+# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ-NOALIAS %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+zihintpause < %s \
+# RUN: | llvm-objdump --mattr=+zihintpause -d -r - \
+# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ %s
+
+# CHECK-S-OBJ-NOALIAS: fence w, 0
+# CHECK-S-OBJ: pause
+pause