-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[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
Changes from 8 commits
c93d0db
080c331
4c7a2b3
c367921
41fba70
85bac48
d701195
3c4cfb7
8c0cf41
944cb41
064ff78
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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, | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -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 = "decodeUImmPlus1OperandGE<5,6>"; | ||||||
| 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,11 @@ class QCIStore_ScaleIdx<bits<4> funct4, string opcodestr> | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| class QCIRVInstI<bits<4> funct4, string opcodestr> | ||||||
| : RVInstIUnary<{0b000, funct4, 0b00000}, 0b011, OPC_CUSTOM_0, | ||||||
| (outs GPRNoX0:$rd), (ins GPRNoX0:$rs1), opcodestr, | ||||||
| "$rd, $rs1">; | ||||||
|
|
||||||
| 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 +119,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_plus1:$width, uimm5:$shamt), | ||||||
| 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 +238,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 +397,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_plus1:$width, | ||||||
| uimm5:$shamt), "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">; | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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: I think it should be
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, I will raise it.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The spec is generated from |
||||||
| 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{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.
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 Immargument 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:
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 ofwidth_minus1is 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.