diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -58,6 +58,7 @@ {"zicbom", RISCVExtensionVersion{1, 0}}, {"zicboz", RISCVExtensionVersion{1, 0}}, + {"zicbop", RISCVExtensionVersion{1, 0}}, }; static const RISCVSupportedExtension SupportedExperimentalExtensions[] = { diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -676,6 +676,16 @@ bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); } + bool isSImm12Lsb00000() const { + if (!isImm()) + return false; + RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; + int64_t Imm; + bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); + return IsConstantImm && isShiftedInt<7, 5>(Imm) && + VK == RISCVMCExpr::VK_RISCV_None; + } + bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); } bool isSImm10Lsb0000NonZero() const { @@ -1172,6 +1182,10 @@ return generateImmOutOfRangeError( Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2, "immediate must be a multiple of 2 bytes in the range"); + case Match_InvalidSImm12Lsb00000: + return generateImmOutOfRangeError( + Operands, ErrorInfo, -(1 << 11), (1 << 11) - 32, + "immediate must be a multiple of 32 bytes in the range"); case Match_InvalidSImm13Lsb0: return generateImmOutOfRangeError( Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h @@ -189,6 +189,7 @@ OPERAND_UIMM7, OPERAND_UIMM12, OPERAND_SIMM12, + OPERAND_SIMM12_LSB00000, OPERAND_UIMM20, OPERAND_UIMMLOG2XLEN, OPERAND_LAST_RISCV_IMM = OPERAND_UIMMLOG2XLEN, diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -194,6 +194,13 @@ AssemblerPredicate<(all_of FeatureStdExtZicboz), "'Zicboz' (Cache-Block Zero Instructions)">; +def FeatureStdExtZicbop + : SubtargetFeature<"zicbop", "HasStdExtZicbop", "true", + "'Zicbop' (Cache-Block Prefetch Instructions)">; +def HasStdExtZicbop : Predicate<"Subtarget->hasStdExtZicbop()">, + AssemblerPredicate<(all_of FeatureStdExtZicbop), + "'Zicbop' (Cache-Block Prefetch Instructions)">; + def Feature64Bit : SubtargetFeature<"64bit", "HasRV64", "true", "Implements RV64">; def IsRV64 : Predicate<"Subtarget->is64Bit()">, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -1137,6 +1137,9 @@ case RISCVOp::OPERAND_SIMM12: Ok = isInt<12>(Imm); break; + case RISCVOp::OPERAND_SIMM12_LSB00000: + Ok = isShiftedInt<7, 5>(Imm); + break; case RISCVOp::OPERAND_UIMM20: Ok = isUInt<20>(Imm); break; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZicbo.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZicbo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZicbo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZicbo.td @@ -11,6 +11,26 @@ // //===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// Operand definitions. +//===----------------------------------------------------------------------===// + +// A 12-bit signed immediate where the least significant five bits are zero. +def simm12_lsb00000 : Operand, + ImmLeaf(Imm);}]> { + let ParserMatchClass = SImmAsmOperand<12, "Lsb00000">; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeSImmOperand<12>"; + let MCOperandPredicate = [{ + int64_t Imm; + if (MCOp.evaluateAsConstantImm(Imm)) + return isShiftedInt<7, 5>(Imm); + return MCOp.isBareSymbolRef(); + }]; + let OperandType = "OPERAND_SIMM12_LSB00000"; + let OperandNamespace = "RISCVOp"; +} + //===----------------------------------------------------------------------===// // Instruction Class Templates //===----------------------------------------------------------------------===// @@ -22,6 +42,13 @@ let rd = 0b00000; } +let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in +class Prefetch_ri optype, string opcodestr> + : RVInstS<0b110, OPC_OP_IMM, (outs), (ins GPR:$rs1, simm12_lsb00000:$imm12), + opcodestr, "${imm12}(${rs1})"> { + let rs2 = optype; +} + //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// @@ -35,3 +62,9 @@ let Predicates = [HasStdExtZicboz] in { def CBO_ZERO : CBO_r<0b000000000100, "cbo.zero">, Sched<[]>; } // Predicates = [HasStdExtZicboz] + +let Predicates = [HasStdExtZicbop] in { +def PREFETCH_I : Prefetch_ri<0b00000, "prefetch.i">, Sched<[]>; +def PREFETCH_R : Prefetch_ri<0b00001, "prefetch.r">, Sched<[]>; +def PREFETCH_W : Prefetch_ri<0b00011, "prefetch.w">, Sched<[]>; +} // Predicates = [HasStdExtZicbop] diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -81,6 +81,7 @@ bool HasStdExtZfh = false; bool HasStdExtZicbom = false; bool HasStdExtZicboz = false; + bool HasStdExtZicbop = false; bool HasRV64 = false; bool IsRV32E = false; bool EnableLinkerRelax = false; @@ -158,6 +159,7 @@ bool hasStdExtZfh() const { return HasStdExtZfh; } bool hasStdExtZicbom() const { return HasStdExtZicbom; } bool hasStdExtZicboz() const { return HasStdExtZicboz; } + bool hasStdExtZicbop() const { return HasStdExtZicbop; } bool is64Bit() const { return HasRV64; } bool isRV32E() const { return IsRV32E; } bool enableLinkerRelax() const { return EnableLinkerRelax; } diff --git a/llvm/test/MC/RISCV/rv32zicbom-invalid.s b/llvm/test/MC/RISCV/rv32zicbom-invalid.s --- a/llvm/test/MC/RISCV/rv32zicbom-invalid.s +++ b/llvm/test/MC/RISCV/rv32zicbom-invalid.s @@ -17,3 +17,6 @@ # Instructions from other zicbo* extensions aren't avalable with enabling the # appropriate -mattr flag. cbo.zero t0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicboz' (Cache-Block Zero Instructions) +prefetch.i 0(t3) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbop' (Cache-Block Prefetch Instructions) +prefetch.r 0(t4) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbop' (Cache-Block Prefetch Instructions) +prefetch.w 0(t5) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbop' (Cache-Block Prefetch Instructions) diff --git a/llvm/test/MC/RISCV/rv32zicbop-invalid.s b/llvm/test/MC/RISCV/rv32zicbop-invalid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zicbop-invalid.s @@ -0,0 +1,29 @@ +# RUN: not llvm-mc -triple riscv32 -mattr=+zicbop < %s 2>&1 | FileCheck %s +# RUN: not llvm-mc -triple riscv64 -mattr=+zicbop < %s 2>&1 | FileCheck %s + +# Memory operand not formatted correctly. +prefetch.i a0, 32 # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.r 32, a0 # CHECK: :[[@LINE]]:16: error: invalid operand for instruction +prefetch.w a0(32) # CHECK: :[[@LINE]]:14: error: unexpected token + +# Out of range offset. +prefetch.i -2080(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.r 2048(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.w 2050(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] + +# Offsets that aren't multiples of 32. +prefetch.i 31(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.r -31(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.w 2047(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] + +# Symbols should not be accepted. +prefetch.i foo(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.r %lo(foo)(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] +prefetch.w %pcrel_lo(foo)(a0) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 32 bytes in the range [-2048, 2016] + +# Instructions from other zicbo* extensions aren't avalable with enabling the +# appropriate -mattr flag. +cbo.clean t0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbom' (Cache-Block Management Instructions) +cbo.flush t1 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbom' (Cache-Block Management Instructions) +cbo.inval t2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbom' (Cache-Block Management Instructions) +cbo.zero t0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicboz' (Cache-Block Zero Instructions) diff --git a/llvm/test/MC/RISCV/rv32zicbop-valid.s b/llvm/test/MC/RISCV/rv32zicbop-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zicbop-valid.s @@ -0,0 +1,31 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+zicbop -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+zicbop -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+zicbop < %s \ +# RUN: | llvm-objdump --mattr=+zicbop -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+zicbop < %s \ +# RUN: | llvm-objdump --mattr=+zicbop -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s + +# CHECK-ASM-AND-OBJ: prefetch.i -2048(t0) +# CHECK-ASM: encoding: [0x13,0xe0,0x02,0x80] +prefetch.i -2048(t0) +# CHECK-ASM-AND-OBJ: prefetch.i 2016(t0) +# CHECK-ASM: encoding: [0x13,0xe0,0x02,0x7e] +prefetch.i 2016(t0) + +# CHECK-ASM-AND-OBJ: prefetch.r -2048(t1) +# CHECK-ASM: encoding: [0x13,0x60,0x13,0x80] +prefetch.r -0x800(t1) +# CHECK-ASM-AND-OBJ: prefetch.r 2016(t1) +# CHECK-ASM: encoding: [0x13,0x60,0x13,0x7e] +prefetch.r 0x7e0(t1) + +# CHECK-ASM-AND-OBJ: prefetch.w -2048(t2) +# CHECK-ASM: encoding: [0x13,0xe0,0x33,0x80] +prefetch.w -2048(t2) +# CHECK-ASM-AND-OBJ: prefetch.w 2016(t2) +# CHECK-ASM: encoding: [0x13,0xe0,0x33,0x7e] +prefetch.w 2016(t2) diff --git a/llvm/test/MC/RISCV/rv32zicboz-invalid.s b/llvm/test/MC/RISCV/rv32zicboz-invalid.s --- a/llvm/test/MC/RISCV/rv32zicboz-invalid.s +++ b/llvm/test/MC/RISCV/rv32zicboz-invalid.s @@ -11,3 +11,6 @@ cbo.clean t0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbom' (Cache-Block Management Instructions) cbo.flush t1 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbom' (Cache-Block Management Instructions) cbo.inval t2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbom' (Cache-Block Management Instructions) +prefetch.i 0(t3) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbop' (Cache-Block Prefetch Instructions) +prefetch.r 0(t4) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbop' (Cache-Block Prefetch Instructions) +prefetch.w 0(t5) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zicbop' (Cache-Block Prefetch Instructions)