-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[RISCV] Add Qualcomm uC Xqcibm (Bit Manipulation) extension #129504
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This extension adds thirty eight bit manipulation instructions. The current spec can be found at: https://github.com/quic/riscv-unified-db/releases/latest This patch adds assembler only support. Change-Id: Ie4cbec5d86ca015088cf8fecd634c0ce43903885
Change-Id: I93aecbd1b71e3fdccbbef93332a2aef39873b092
Change-Id: Ia85aee7e87e3a829e3f71c8937fab51c37a41414
Change-Id: Iaedaa0e298abb2dc28082db36b3dc48d031ad8b1
Change-Id: I91edbbc60d44450cc42440e33c2ee17a0d86c86b
Change-Id: Ia340d862a6404611ef92bd159f913400de82532d
@llvm/pr-subscribers-mc @llvm/pr-subscribers-clang-driver Author: quic_hchandel (hchandel) ChangesThis extension adds thirty eight bit manipulation instructions. The current spec can be found at: This patch adds assembler only support. Co-authored-by: Sudharsan Veeravalli <[email protected]> Patch is 45.43 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/129504.diff 14 Files Affected:
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 4d6e112f4e387..69b76f0c4c4cd 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -196,6 +196,7 @@
// CHECK-NEXT: xqccmp 0.1 'Xqccmp' (Qualcomm 16-bit Push/Pop and Double Moves)
// CHECK-NEXT: xqcia 0.4 'Xqcia' (Qualcomm uC Arithmetic Extension)
// CHECK-NEXT: xqciac 0.3 'Xqciac' (Qualcomm uC Load-Store Address Calculation Extension)
+// CHECK-NEXT: xqcibm 0.4 'Xqcibm' (Qualcomm uC Bit Manipulation Extension)
// CHECK-NEXT: xqcicli 0.2 'Xqcicli' (Qualcomm uC Conditional Load Immediate Extension)
// CHECK-NEXT: xqcicm 0.2 'Xqcicm' (Qualcomm uC Conditional Move Extension)
// CHECK-NEXT: xqcics 0.2 'Xqcics' (Qualcomm uC Conditional Select Extension)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 63185fe67440c..62c6a4fd80fd4 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -438,6 +438,9 @@ The current vendor extensions supported are:
``experimental-Xqciac``
LLVM implements `version 0.3 of the Qualcomm uC Load-Store Address Calculation extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm. All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
+``experimental-Xqcibm``
+ LLVM implements `version 0.4 of the Qualcomm uC Bit Manipulation extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm. All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
+
``experimental-Xqcicli``
LLVM implements `version 0.2 of the Qualcomm uC Conditional Load Immediate extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm. All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index f1f64f77ee71a..75ac0d1caf81d 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -109,6 +109,8 @@ Changes to the RISC-V Backend
* Adds experimental assembler support for the Qualcomm uC 'Xqcilia` (Large Immediate Arithmetic)
extension.
+* Adds experimental assembler support for the Qualcomm uC 'Xqcibm` (Bit Manipulation)
+ extension.
* Adds experimental assembler support for the Qualcomm 'Xqccmp' extension, which
is a frame-pointer convention compatible version of Zcmp.
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 541979a0f70e8..44c19f5da1e26 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -745,6 +745,26 @@ struct RISCVOperand final : public MCParsedAsmOperand {
VK == RISCVMCExpr::VK_RISCV_None;
}
+ bool isUImm5Plus1() const {
+ if (!isImm())
+ return false;
+ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+ int64_t Imm;
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+ return IsConstantImm && ((isUInt<5>(Imm) && (Imm != 0)) || (Imm == 32)) &&
+ VK == RISCVMCExpr::VK_RISCV_None;
+ }
+
+ bool isUImm5GE6Plus1() const {
+ if (!isImm())
+ return false;
+ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+ int64_t Imm;
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+ return IsConstantImm && ((isUInt<5>(Imm) && (Imm >= 6)) || (Imm == 32)) &&
+ VK == RISCVMCExpr::VK_RISCV_None;
+ }
+
bool isUImm8GE32() const {
int64_t Imm;
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
@@ -937,6 +957,16 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return SignExtend64<32>(Imm);
}
+ bool isSImm11() const {
+ if (!isImm())
+ return false;
+ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+ int64_t Imm;
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+ return IsConstantImm && isInt<11>(fixImmediateForRV32(Imm, isRV64Imm())) &&
+ VK == RISCVMCExpr::VK_RISCV_None;
+ }
+
bool isSImm12() const {
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
int64_t Imm;
@@ -1562,6 +1592,10 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
case Match_InvalidUImm5GT3:
return generateImmOutOfRangeError(Operands, ErrorInfo, 4, (1 << 5) - 1);
+ case Match_InvalidUImm5Plus1:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5));
+ case Match_InvalidUImm5GE6Plus1:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, 6, (1 << 5));
case Match_InvalidUImm6:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
case Match_InvalidUImm7:
@@ -1620,6 +1654,9 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
"immediate must be a multiple of 16 bytes and non-zero in the range");
+ case Match_InvalidSImm11:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 10),
+ (1 << 10) - 1);
case Match_InvalidUImm10:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 10) - 1);
case Match_InvalidUImm11:
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 61deaa827a6df..b6e575816cf4f 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -371,6 +371,15 @@ decodeUImmLog2XLenNonZeroOperand(MCInst &Inst, uint32_t Imm, int64_t Address,
return decodeUImmLog2XLenOperand(Inst, Imm, Address, Decoder);
}
+template <unsigned N>
+static DecodeStatus decodeUImmPlus1Operand(MCInst &Inst, uint32_t Imm,
+ int64_t Address,
+ const MCDisassembler *Decoder) {
+ assert(isUInt<N>(Imm) && "Invalid immediate");
+ Inst.addOperand(MCOperand::createImm(Imm + 1));
+ return MCDisassembler::Success;
+}
+
template <unsigned N>
static DecodeStatus decodeSImmOperand(MCInst &Inst, uint32_t Imm,
int64_t Address,
@@ -629,11 +638,11 @@ static constexpr FeatureBitset XRivosFeatureGroup = {
static constexpr FeatureBitset XqciFeatureGroup = {
RISCV::FeatureVendorXqcia, RISCV::FeatureVendorXqciac,
- RISCV::FeatureVendorXqcicli, RISCV::FeatureVendorXqcicm,
- RISCV::FeatureVendorXqcics, RISCV::FeatureVendorXqcicsr,
- RISCV::FeatureVendorXqciint, RISCV::FeatureVendorXqcilia,
- RISCV::FeatureVendorXqcilo, RISCV::FeatureVendorXqcilsm,
- RISCV::FeatureVendorXqcisls,
+ RISCV::FeatureVendorXqcibm, RISCV::FeatureVendorXqcicli,
+ RISCV::FeatureVendorXqcicm, RISCV::FeatureVendorXqcics,
+ RISCV::FeatureVendorXqcicsr, RISCV::FeatureVendorXqciint,
+ RISCV::FeatureVendorXqcilia, RISCV::FeatureVendorXqcilo,
+ RISCV::FeatureVendorXqcilsm, RISCV::FeatureVendorXqcisls,
};
static constexpr FeatureBitset XSfVectorGroup = {
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 185a5d8a9c9b2..5a44f0f878845 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -296,6 +296,8 @@ enum OperandType : unsigned {
OPERAND_UIMM5,
OPERAND_UIMM5_NONZERO,
OPERAND_UIMM5_GT3,
+ OPERAND_UIMM5_PLUS1,
+ OPERAND_UIMM5_GE6_PLUS1,
OPERAND_UIMM5_LSB0,
OPERAND_UIMM6,
OPERAND_UIMM6_LSB0,
@@ -324,6 +326,7 @@ enum OperandType : unsigned {
OPERAND_SIMM6,
OPERAND_SIMM6_NONZERO,
OPERAND_SIMM10_LSB0000_NONZERO,
+ OPERAND_SIMM11,
OPERAND_SIMM12,
OPERAND_SIMM12_LSB00000,
OPERAND_SIMM26,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index 06d9cce48692a..df8320107d894 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -80,6 +80,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ uint64_t getImmOpValueMinus1(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
uint64_t getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
@@ -385,6 +389,20 @@ RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
return 0;
}
+uint64_t
+RISCVMCCodeEmitter::getImmOpValueMinus1(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+
+ if (MO.isImm()) {
+ uint64_t Res = MO.getImm();
+ return (Res - 1);
+ }
+
+ return getImmOpValue(MI, OpNo, Fixups, STI);
+}
+
uint64_t
RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 24828cde28079..51d911aa7c4f1 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1366,6 +1366,14 @@ def HasVendorXqcilia
AssemblerPredicate<(all_of FeatureVendorXqcilia),
"'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)">;
+def FeatureVendorXqcibm
+ : RISCVExperimentalExtension<0, 4, "Qualcomm uC Bit Manipulation Extension",
+ [FeatureStdExtZca]>;
+def HasVendorXqcibm
+ : Predicate<"Subtarget->hasVendorXqcibm()">,
+ AssemblerPredicate<(all_of FeatureVendorXqcibm),
+ "'Xqcibm' (Qualcomm uC Bit Manipulation Extension)">;
+
def FeatureVendorXqcilo
: RISCVExperimentalExtension<0, 2, "Qualcomm uC Large Offset Load Store Extension",
[FeatureStdExtZca]>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 1f4bd60e7d4c8..8b8f1d8b8f0f9 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -28,10 +28,34 @@ def uimm5gt3 : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
let OperandType = "OPERAND_UIMM5_GT3";
}
+def UImm5Plus1AsmOperand : AsmOperandClass {
+ let Name = "UImm5Plus1";
+ let RenderMethod = "addImmOperands";
+ let DiagnosticType = "InvalidUImm5Plus1";
+}
+
+def uimm5_plus1 : RISCVOp, ImmLeaf<XLenVT,
+ [{return (isUInt<5>(Imm) && (Imm != 0)) || (Imm == 32);}]> {
+ let ParserMatchClass = UImm5Plus1AsmOperand;
+ let EncoderMethod = "getImmOpValueMinus1";
+ let DecoderMethod = "decodeUImmPlus1Operand<5>";
+ let OperandType = "OPERAND_UIMM5_PLUS1";
+}
+
+def uimm5ge6_plus1 : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
+ [{return (Imm >= 6) && (isUInt<5>(Imm) || (Imm == 32));}]> {
+ let ParserMatchClass = UImmAsmOperand<5, "GE6Plus1">;
+ let EncoderMethod = "getImmOpValueMinus1";
+ let DecoderMethod = "decodeUImmPlus1Operand<5>";
+ let OperandType = "OPERAND_UIMM5_GE6_PLUS1";
+}
+
def uimm10 : RISCVUImmLeafOp<10>;
def uimm11 : RISCVUImmLeafOp<11>;
+def simm11 : RISCVSImmLeafOp<11>;
+
def simm26 : RISCVSImmLeafOp<26>;
// 32-bit Immediate, used by RV32 Instructions in 32-bit operations, so no
@@ -80,6 +104,12 @@ class QCIStore_ScaleIdx<bits<4> funct4, string opcodestr>
}
}
+class QCIRVInstI<bits<4> funct4, string opcodestr>
+ : RVInstI<0b011, OPC_CUSTOM_0, (outs GPRNoX0:$rd),
+ (ins GPRNoX0:$rs1), opcodestr, "$rd, $rs1"> {
+ let imm12 = {0b000, funct4, 0b00000};
+}
+
class QCIRVInstR<bits<4> funct4, string opcodestr>
: RVInstR<{0b000, funct4}, 0b011, OPC_CUSTOM_0, (outs GPRNoX0:$rd),
(ins GPRNoX0:$rs1), opcodestr, "$rd, $rs1"> {
@@ -90,6 +120,30 @@ class QCIRVInstRR<bits<5> funct5, DAGOperand InTyRs1, string opcodestr>
: RVInstR<{0b00, funct5}, 0b011, OPC_CUSTOM_0, (outs GPRNoX0:$rd),
(ins InTyRs1:$rs1, GPRNoX0:$rs2), opcodestr, "$rd, $rs1, $rs2">;
+class QCIBitManipRII<bits<3> funct3, bits<2> funct2,
+ DAGOperand InTyRs1, string opcodestr>
+ : RVInstIBase<funct3, OPC_CUSTOM_0, (outs GPRNoX0:$rd),
+ (ins InTyRs1:$rs1, uimm5:$shamt, uimm5_plus1:$width),
+ opcodestr, "$rd, $rs1, $width, $shamt"> {
+ bits<5> shamt;
+ bits<6> width;
+
+ let Inst{31-30} = funct2;
+ let Inst{29-25} = width{4-0};
+ let Inst{24-20} = shamt;
+}
+
+class QCIRVInstRI<bits<1> funct1, DAGOperand InTyImm11,
+ string opcodestr>
+ : RVInstIBase<0b000, OPC_CUSTOM_0, (outs GPRNoX0:$rd),
+ (ins GPRNoX0:$rs1, InTyImm11:$imm11), opcodestr,
+ "$rd, $rs1, $imm11"> {
+ bits<11> imm11;
+
+ let Inst{31-31} = funct1;
+ let Inst{30-20} = imm11;
+}
+
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class QCISELECTIICC<bits<3> funct3, string opcodestr>
: RVInstR4<0b00, funct3, OPC_CUSTOM_2, (outs GPRNoX0:$rd_wb),
@@ -185,6 +239,17 @@ class QCIMVCCI<bits<3> funct3, string opcodestr, DAGOperand immType>
let rs2 = imm;
}
+class QCI_RVInst16CB_BM<bits<2> funct2, string opcodestr>
+ : RVInst16CB<0b100, 0b01, (outs GPRC:$rd),
+ (ins GPRC:$rs1, uimmlog2xlennonzero:$shamt),
+ opcodestr, "$rs1, $shamt"> {
+ bits<5> shamt;
+ let Constraints = "$rs1 = $rd";
+ let Inst{12} = 0b1;
+ let Inst{11-10} = funct2;
+ let Inst{6-2} = shamt{4-0};
+}
+
let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
class QCIRVInst16CI_RS1<bits<5> funct5, string OpcodeStr>
: RVInst16CI<0b000, 0b10, (outs), (ins GPRNoX0:$rs1), OpcodeStr, "$rs1"> {
@@ -333,6 +398,59 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
} // Predicates = [HasVendorXqcia, IsRV32]
+let Predicates = [HasVendorXqcibm, IsRV32] in {
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
+ def QC_INSBRI : QCIRVInstRI<0b1, simm11, "qc.insbri">;
+ def QC_INSBI : RVInstIBase<0b001, OPC_CUSTOM_0, (outs GPRNoX0:$rd),
+ (ins simm5:$imm5, uimm5:$shamt,
+ uimm5_plus1:$width), "qc.insbi",
+ "$rd, $imm5, $width, $shamt"> {
+ bits<5> imm5;
+ bits<5> shamt;
+ bits<6> width;
+ let rs1 = imm5;
+ let Inst{31-30} = 0b00;
+ let Inst{29-25} = width{4-0};
+ let Inst{24-20} = shamt;
+ }
+ def QC_INSB : QCIBitManipRII<0b001, 0b01, GPR, "qc.insb">;
+ def QC_INSBH : QCIBitManipRII<0b001, 0b10, GPR, "qc.insbh">;
+ def QC_INSBR : QCIRVInstRR<0b00000, GPR, "qc.insbr">;
+ def QC_INSBHR : QCIRVInstRR<0b00001, GPR, "qc.insbhr">;
+ def QC_INSBPR : QCIRVInstRR<0b00010, GPR, "qc.insbpr">;
+ def QC_INSBPRH : QCIRVInstRR<0b00011, GPR, "qc.insbprh">;
+ def QC_EXTU : QCIBitManipRII<0b010, 0b00, GPRNoX0, "qc.extu">;
+ def QC_EXTDU : QCIBitManipRII<0b010, 0b10, GPR, "qc.extdu">;
+ def QC_EXTDUR : QCIRVInstRR<0b00100, GPR, "qc.extdur">;
+ def QC_EXTDUPR : QCIRVInstRR<0b00110, GPR, "qc.extdupr">;
+ def QC_EXTDUPRH : QCIRVInstRR<0b00111, GPR, "qc.extduprh">;
+ def QC_EXT : QCIBitManipRII<0b010, 0b01, GPRNoX0, "qc.ext">;
+ def QC_EXTD : QCIBitManipRII<0b010, 0b11, GPR, "qc.extd">;
+ def QC_EXTDR : QCIRVInstRR<0b00101, GPR, "qc.extdr">;
+ def QC_EXTDPR : QCIRVInstRR<0b01000, GPR, "qc.extdpr">;
+ def QC_EXTDPRH : QCIRVInstRR<0b01001, GPR, "qc.extdprh">;
+ def QC_COMPRESS2 : QCIRVInstI<0b0000, "qc.compress2">;
+ def QC_COMPRESS3 : QCIRVInstI<0b0001, "qc.compress3">;
+ def QC_EXPAND2 : QCIRVInstI<0b0010, "qc.expand2">;
+ def QC_EXPAND3 : QCIRVInstI<0b0011, "qc.expand3">;
+ def QC_CLO : QCIRVInstI<0b0100, "qc.clo">;
+ def QC_CTO : QCIRVInstI<0b0101, "qc.cto">;
+ def QC_BREV32 : QCIRVInstI<0b0110, "qc.brev32">;
+ def QC_C_BEXTI : QCI_RVInst16CB_BM<0b00, "qc.c.bexti">;
+ def QC_C_BSETI : QCI_RVInst16CB_BM<0b01, "qc.c.bseti">;
+ def QC_C_EXTU : RVInst16CI<0b000, 0b10, (outs GPRNoX0:$rd_wb),
+ (ins GPRNoX0:$rd, uimm5ge6_plus1:$width),
+ "qc.c.extu", "$rd, $width"> {
+ bits<5> rd;
+ bits<5> width;
+ let Constraints = "$rd = $rd_wb";
+ let Inst{6-2} = width{4-0};
+ let Inst{11-7} = rd;
+ let Inst{12} = 0b1;
+ }
+} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
+} // Predicates = [HasVendorXqcibm, IsRV32]
+
let Predicates = [HasVendorXqciac, IsRV32] in {
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
def QC_C_MULIADD : RVInst16CL<0b001, 0b10, (outs GPRC:$rd_wb),
diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index 932db759cb7ac..dd74f79f04b92 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -742,9 +742,9 @@ Error RISCVISAInfo::checkDependency() {
bool HasZvl = MinVLen != 0;
bool HasZcmt = Exts.count("zcmt") != 0;
static constexpr StringLiteral XqciExts[] = {
- {"xqcia"}, {"xqciac"}, {"xqcicli"}, {"xqcicm"},
- {"xqcics"}, {"xqcicsr"}, {"xqciint"}, {"xqcilia"},
- {"xqcilo"}, {"xqcilsm"}, {"xqcisls"}};
+ {"xqcia"}, {"xqciac"}, {"xqcibm"}, {"xqcicli"},
+ {"xqcicm"}, {"xqcics"}, {"xqcicsr"}, {"xqciint"},
+ {"xqcilia"}, {"xqcilo"}, {"xqcilsm"}, {"xqcisls"}};
bool HasZcmp = Exts.count("zcmp") != 0;
bool HasXqccmp = Exts.count("xqccmp") != 0;
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index 29f84dc79b6ae..abda392fc369c 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -84,6 +84,7 @@
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqccmp %s -o - | FileCheck --check-prefix=RV32XQCCMP %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcia %s -o - | FileCheck --check-prefix=RV32XQCIA %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqciac %s -o - | FileCheck --check-prefix=RV32XQCIAC %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcibm %s -o - | FileCheck --check-prefix=RV32XQCIBM %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicli %s -o - | FileCheck --check-prefix=RV32XQCICLI %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicm %s -o - | FileCheck --check-prefix=RV32XQCICM %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcics %s -o - | FileCheck --check-prefix=RV32XQCICS %s
@@ -404,6 +405,7 @@
; RV32XQCCMP: .attribute 5, "rv32i2p1_zca1p0_xqccmp0p1"
; RV32XQCIA: .attribute 5, "rv32i2p1_xqcia0p4"
; RV32XQCIAC: .attribute 5, "rv32i2p1_zca1p0_xqciac0p3"
+; RV32XQCIBM: .attribute 5, "rv32i2p1_zca1p0_xqcibm0p4"
; RV32XQCICLI: .attribute 5, "rv32i2p1_xqcicli0p2"
; RV32XQCICM: .attribute 5, "rv32i2p1_zca1p0_xqcicm0p2"
; RV32XQCICS: .attribute 5, "rv32i2p1_xqcics0p2"
diff --git a/llvm/test/MC/RISCV/xqcibm-invalid.s b/llvm/test/MC/RISCV/xqcibm-invalid.s
new file mode 100644
index 0000000000000..7bb305fa9fa30
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcibm-invalid.s
@@ -0,0 +1,539 @@
+# Xqcibm - Qualcomm uC Bit Manipulation Extension
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcibm < %s 2>&1 \
+# RUN: | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
+# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcibm < %s 2>&1 \
+# RUN: | FileCheck -check-prefixes=CHECK,CHECK-MINUS %s
+
+# CHECK-PLUS: :[[@LINE+2]]:18: error: register must be a GPR excluding zero (x0)
+# CHECK-MINUS: :[[@LINE+1]]:18: error: invalid operand for instruction
+qc.compr...
[truncated]
|
This takes you to the latest release from the whole repo. Right now it points to Xqccmp 0.2.0. |
[{return (Imm >= 6) && (isUInt<5>(Imm) || (Imm == 32));}]> { | ||
let ParserMatchClass = UImmAsmOperand<5, "GE6Plus1">; | ||
let EncoderMethod = "getImmOpValueMinus1"; | ||
let DecoderMethod = "decodeUImmPlus1Operand<5>"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the DecoderMethod need to verify the final immediate is >= 6?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented a new decoder function where this check is performed.
def QC_EXPAND2 : QCIRVInstI<0b0010, "qc.expand2">; | ||
def QC_EXPAND3 : QCIRVInstI<0b0011, "qc.expand3">; | ||
def QC_CLO : QCIRVInstI<0b0100, "qc.clo">; | ||
def QC_CTO : QCIRVInstI<0b0101, "qc.cto">; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lenary I think the sail code for qc.cto in the spec is incorrect:
X[rd] = (xlen() - 1) - $signed(lowest_set_bit(~X[rs1]));
I think it should be
X[rd] = lowest_set_bit(~X[rs1]);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, I will raise it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirmed internally. Looks like there was a problem with the Operation code for both CTO and CTZ.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no CTZ in this patch or the spec. Did you mean CLO? That looked ok to me if highest_set_bit returns -1 for no bits set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spec is generated from riscv-unified-db
, which includes a description of Zbb's CTZ instruction: https://github.com/riscv-software-src/riscv-unified-db/blob/main/arch/inst/B/ctz.yaml#L33
Change-Id: I4b8f1435ea575ab30ab3d7af5a7a37dd86b7766d
✅ With the latest revision this PR passed the C/C++ code formatter. |
Change-Id: Ic02800302b258840b40bf409d6354c5430ca348d
Yeah, this has been a problem with how we do releases. The right link is https://github.com/quic/riscv-unified-db/releases/tag/Xqci-0.6 and we need to use that in more places. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One issue that needs a small change and a test, otherwise looking good.
if (Imm < LowerBound) | ||
return MCDisassembler::Fail; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this confusing, and I think how this is used is incorrect.
The uin32_t Imm
argument to this function will be the 5-bit field out of the instruction encoding (with the bits in the right place if they were moved around). This method is for taking the bits of that encoding, and turning it back into the correct value (or failing to disassemble).
In this case, I think you want the code to be the following, instead, because this gives the Lower Bound in terms of the decoded immediate (which we prefer to match the value the instruction aims to use), rather than in terms of the encoded value:
if (Imm < LowerBound) | |
return MCDisassembler::Fail; | |
if ((Imm + 1) < LowerBound) | |
return MCDisassembler::Fail; |
I think we should have a test to check this case. Add one to llvm/test/MC/Disassembler/RISCV/xqci-invalid.txt
, where you hand encode a list of bytes. The case you want to hit is where the encoding would be rejected - I think in this case where the encoding value of width_minus1
is equal to 4.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Please have a look at the test and let me know if I should change anything.
def QC_EXPAND2 : QCIRVInstI<0b0010, "qc.expand2">; | ||
def QC_EXPAND3 : QCIRVInstI<0b0011, "qc.expand3">; | ||
def QC_CLO : QCIRVInstI<0b0100, "qc.clo">; | ||
def QC_CTO : QCIRVInstI<0b0101, "qc.cto">; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, I will raise it.
return (Res - 1); | ||
} | ||
|
||
return getImmOpValue(MI, OpNo, Fixups, STI); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's not an immediate, getImmOpValue is going to do the wrong thing. So we should just do llvm_unreachable here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
bits<5> rd; | ||
bits<5> width; | ||
let Constraints = "$rd = $rd_wb"; | ||
let Inst{6-2} = width{4-0}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
width
is declared as 5 bits so the {4-0}
is unneeded or width
needs to be 6 bits like the earlier instructions. I'm not sure which is right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a 5-bit field in the encoding, so I think this is right:
let Inst{6-2} = width{4-0}; | |
let Inst{6-2} = width; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
(ins InTyRs1:$rs1, uimm5_plus1:$width, uimm5:$shamt), | ||
opcodestr, "$rd, $rs1, $width, $shamt"> { | ||
bits<5> shamt; | ||
bits<6> width; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lenary so this should be bits<5>
and let Inst{29-25} = width
below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bits<5> makes sense. Did the change.
"$rd, $imm5, $width, $shamt"> { | ||
bits<5> imm5; | ||
bits<5> shamt; | ||
bits<6> width; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lenary so this should be bits<5> and let Inst{29-25} = width below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Change-Id: Idd3deec94bd324b2ab2b3fbc57bec16426673ad2
Change-Id: Ibe104399de785537ff19961aa48d5f18f2227fb0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Some test lines were added in llvm#129504 for Qualcomm uC Xqcibm extension. This patch improves those test lines. Change-Id: I6d6fb7c7d13b3c516c52adaba84fb094bae92901
Some test lines were added in #129504 for Qualcomm uC Xqcibm extension. This patch improves those test lines.
Some test lines were added in llvm#129504 for Qualcomm uC Xqcibm extension. This patch improves those test lines.
) This extension adds thirty eight bit manipulation instructions. The current spec can be found at: https://github.com/quic/riscv-unified-db/releases/tag/Xqci-0.6 This patch adds assembler only support. Co-authored-by: Sudharsan Veeravalli <[email protected]>
This extension adds thirty eight bit manipulation instructions.
The current spec can be found at:
https://github.com/quic/riscv-unified-db/releases/tag/Xqci-0.6
This patch adds assembler only support.
Co-authored-by: Sudharsan Veeravalli [email protected]