diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -302,6 +302,7 @@ return Features; // Keep "c" feature if there is one in PlatformFlags. } + bool HasZca = false; Optional Attr = Attributes.getAttributeString(RISCVAttrs::ARCH); if (Attr) { // The Arch pattern is [rv32|rv64][i|e]version(_[m|a|f|d|c]version)* @@ -313,6 +314,7 @@ else if (Arch.consume_front("rv64")) Features.AddFeature("64bit"); + HasZca = Arch.contains("zca"); while (!Arch.empty()) { switch (Arch[0]) { default: @@ -338,6 +340,11 @@ } } + if (HasZca) { + Features.AddFeature("c", false); + Features.AddFeature("experimental-zca"); + } + return Features; } 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 @@ -109,6 +109,7 @@ {"zbr", RISCVExtensionVersion{0, 93}}, {"zbt", RISCVExtensionVersion{0, 93}}, {"zvfh", RISCVExtensionVersion{0, 1}}, + {"zca", RISCVExtensionVersion{0, 70}}, }; static bool stripExperimentalPrefix(StringRef &Ext) { diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -355,7 +355,8 @@ bool RISCVAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, const MCSubtargetInfo *STI) const { bool HasStdExtC = STI->getFeatureBits()[RISCV::FeatureStdExtC]; - unsigned MinNopLen = HasStdExtC ? 2 : 4; + bool HasStdExtZca = STI->getFeatureBits()[RISCV::FeatureExtZca]; + unsigned MinNopLen = (HasStdExtC || HasStdExtZca) ? 2 : 4; if ((Count % MinNopLen) != 0) return false; @@ -365,7 +366,7 @@ OS.write("\x13\0\0\0", 4); // The canonical nop on RVC is c.nop. - if (Count && HasStdExtC) + if (Count && (HasStdExtC || HasStdExtZca)) OS.write("\x01\0", 2); return true; @@ -588,7 +589,8 @@ return false; bool HasStdExtC = STI->getFeatureBits()[RISCV::FeatureStdExtC]; - unsigned MinNopLen = HasStdExtC ? 2 : 4; + bool HasStdExtZca = STI->getFeatureBits()[RISCV::FeatureExtZca]; + unsigned MinNopLen = (HasStdExtC || HasStdExtZca) ? 2 : 4; if (AF.getAlignment() <= MinNopLen) { return false; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h @@ -46,6 +46,10 @@ raw_ostream &O); void printVMaskReg(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O); + void printRlist(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, + raw_ostream &O); + void printSpimm(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, + raw_ostream &O); // Autogenerated by tblgen. std::pair getMnemonic(const MCInst *MI) override; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCObjectFileInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCObjectFileInfo.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCObjectFileInfo.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCObjectFileInfo.cpp @@ -19,5 +19,8 @@ unsigned RISCVMCObjectFileInfo::getTextSectionAlignment() const { const MCSubtargetInfo *STI = getContext().getSubtargetInfo(); - return STI->hasFeature(RISCV::FeatureStdExtC) ? 2 : 4; + return (STI->hasFeature(RISCV::FeatureStdExtC) || + STI->hasFeature(RISCV::FeatureExtZca)) + ? 2 + : 4; } 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 @@ -327,6 +327,19 @@ FeatureStdExtZkr, FeatureStdExtZkt]>; +def FeatureExtZca + : SubtargetFeature<"experimental-zca", "HasStdExtZca", "true", + "'Zca' (part of the C extension, excluding all 16-bit floating point loads and stores)">; +def HasStdExtZca : Predicate<"Subtarget->hasStdExtZca()">, + AssemblerPredicate<(all_of FeatureExtZca), + "'Zca' (part of the C extension)">; + +def HasStdExtCOrZca + : Predicate<"Subtarget->hasStdExtC() || Subtarget->hasStdExtZca()">, + AssemblerPredicate<(any_of FeatureStdExtC, FeatureExtZca), + "'C' (Compressed Instructions) or " + "'Zca' (part of the C extension)">; + def FeatureNoRVCHints : SubtargetFeature<"no-rvc-hints", "EnableRVCHintInstrs", "false", "Disable RVC Hint Instructions.">; diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.h b/llvm/lib/Target/RISCV/RISCVFrameLowering.h --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.h +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.h @@ -45,6 +45,8 @@ bool hasBP(const MachineFunction &MF) const; + bool isCSIpushable(const std::vector &CSI) const; + bool hasReservedCallFrame(const MachineFunction &MF) const override; MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -933,7 +933,8 @@ } // Function alignments. - const Align FunctionAlignment(Subtarget.hasStdExtC() ? 2 : 4); + const Align FunctionAlignment( + (Subtarget.hasStdExtC() || Subtarget.hasStdExtZca()) ? 2 : 4); setMinFunctionAlignment(FunctionAlignment); setPrefFunctionAlignment(FunctionAlignment); 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 @@ -58,7 +58,8 @@ STI(STI) {} MCInst RISCVInstrInfo::getNop() const { - if (STI.getFeatureBits()[RISCV::FeatureStdExtC]) + if (STI.getFeatureBits()[RISCV::FeatureStdExtC] || + STI.getFeatureBits()[RISCV::FeatureExtZca]) return MCInstBuilder(RISCV::C_NOP); return MCInstBuilder(RISCV::ADDI) .addReg(RISCV::X0) @@ -1242,8 +1243,14 @@ // jr t0 = 4 bytes, 2 bytes if compressed instructions are enabled. unsigned FrameOverhead = 4; - if (RepeatedSequenceLocs[0].getMF()->getSubtarget() - .getFeatureBits()[RISCV::FeatureStdExtC]) + if (RepeatedSequenceLocs[0] + .getMF() + ->getSubtarget() + .getFeatureBits()[RISCV::FeatureStdExtC] || + RepeatedSequenceLocs[0] + .getMF() + ->getSubtarget() + .getFeatureBits()[RISCV::FeatureExtZca]) FrameOverhead = 2; return outliner::OutlinedFunction(RepeatedSequenceLocs, SequenceSize, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td @@ -281,7 +281,7 @@ // Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasStdExtC] in { +let Predicates = [HasStdExtCOrZca] in { let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [X2] in def C_ADDI4SPN : RVInst16CIW<0b000, 0b00, (outs GPRC:$rd), @@ -321,7 +321,7 @@ let Inst{5} = imm{6}; } -let Predicates = [HasStdExtC, IsRV64] in +let Predicates = [HasStdExtCOrZca, IsRV64] in def C_LD : CLoad_ri<0b011, "c.ld", GPRC, uimm8_lsb000>, Sched<[WriteLDD, ReadMemBase]> { bits<8> imm; @@ -355,7 +355,7 @@ let Inst{5} = imm{6}; } -let Predicates = [HasStdExtC, IsRV64] in +let Predicates = [HasStdExtCOrZca, IsRV64] in def C_SD : CStore_rri<0b111, "c.sd", GPRC, uimm8_lsb000>, Sched<[WriteSTD, ReadStoreData, ReadMemBase]> { bits<8> imm; @@ -391,12 +391,12 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall = 1, DecoderNamespace = "RISCV32Only_", Defs = [X1], - Predicates = [HasStdExtC, IsRV32] in + Predicates = [HasStdExtCOrZca, IsRV32] in def C_JAL : RVInst16CJ<0b001, 0b01, (outs), (ins simm12_lsb0:$offset), "c.jal", "$offset">, Sched<[WriteJal]>; let hasSideEffects = 0, mayLoad = 0, mayStore = 0, - Predicates = [HasStdExtC, IsRV64] in + Predicates = [HasStdExtCOrZca, IsRV64] in def C_ADDIW : RVInst16CI<0b001, 0b01, (outs GPRNoX0:$rd_wb), (ins GPRNoX0:$rd, simm6:$imm), "c.addiw", "$rd, $imm">, @@ -405,7 +405,7 @@ let Inst{6-2} = imm{4-0}; } -let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Predicates = [HasStdExtCOrZca]in def C_LI : RVInst16CI<0b010, 0b01, (outs GPRNoX0:$rd), (ins simm6:$imm), "c.li", "$rd, $imm">, Sched<[WriteIALU]> { @@ -458,7 +458,7 @@ def C_AND : CS_ALU<0b100011, 0b11, "c.and", GPRC>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -let Predicates = [HasStdExtC, IsRV64] in { +let Predicates = [HasStdExtCOrZca, IsRV64] in { def C_SUBW : CS_ALU<0b100111, 0b00, "c.subw", GPRC>, Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; def C_ADDW : CS_ALU<0b100111, 0b01, "c.addw", GPRC>, @@ -506,7 +506,7 @@ let Inst{3-2} = imm{7-6}; } -let Predicates = [HasStdExtC, IsRV64] in +let Predicates = [HasStdExtCOrZca, IsRV64] in def C_LDSP : CStackLoad<0b011, "c.ldsp", GPRNoX0, uimm9_lsb000>, Sched<[WriteLDD, ReadMemBase]> { let Inst{6-5} = imm{4-3}; @@ -566,7 +566,7 @@ let Inst{8-7} = imm{7-6}; } -let Predicates = [HasStdExtC, IsRV64] in +let Predicates = [HasStdExtCOrZca, IsRV64] in def C_SDSP : CStackStore<0b111, "c.sdsp", GPR, uimm9_lsb000>, Sched<[WriteSTD, ReadStoreData, ReadMemBase]> { let Inst{12-10} = imm{5-3}; @@ -581,13 +581,13 @@ let Inst{15-0} = 0; } -} // Predicates = [HasStdExtC] +} // Predicates = [HasStdExtCOrZca] //===----------------------------------------------------------------------===// // HINT Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasStdExtC, HasRVCHints], hasSideEffects = 0, mayLoad = 0, +let Predicates = [HasStdExtCOrZca, HasRVCHints], hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { @@ -688,7 +688,7 @@ let Inst{12} = 0; } -} // Predicates = [HasStdExtC, HasRVCHints], hasSideEffects = 0, mayLoad = 0, +} // Predicates = [HasStdExtCOrZca, HasRVCHints], hasSideEffects = 0, mayLoad = 0, // mayStore = 0 //===----------------------------------------------------------------------===// @@ -704,7 +704,7 @@ let Predicates = [HasStdExtC, HasStdExtF, IsRV32] in def : InstAlias<"c.flw $rd, (${rs1})", (C_FLW FPR32C:$rd, GPRC:$rs1, 0)>; -let Predicates = [HasStdExtC, IsRV64] in +let Predicates = [HasStdExtCOrZca, IsRV64] in def : InstAlias<"c.ld $rd, (${rs1})", (C_LD GPRC:$rd, GPRC:$rs1, 0)>; let Predicates = [HasStdExtC, HasStdExtD] in @@ -715,7 +715,7 @@ let Predicates = [HasStdExtC, HasStdExtF, IsRV32] in def : InstAlias<"c.fsw $rs2, (${rs1})", (C_FSW FPR32C:$rs2, GPRC:$rs1, 0)>; -let Predicates = [HasStdExtC, IsRV64] in +let Predicates = [HasStdExtCOrZca, IsRV64] in def : InstAlias<"c.sd $rs2, (${rs1})", (C_SD GPRC:$rs2, GPRC:$rs1, 0)>; let Predicates = [HasStdExtC, HasStdExtD] in @@ -726,7 +726,7 @@ let Predicates = [HasStdExtC, HasStdExtF, IsRV32] in def : InstAlias<"c.flwsp $rd, (${rs1})", (C_FLWSP FPR32C:$rd, SP:$rs1, 0)>; -let Predicates = [HasStdExtC, IsRV64] in +let Predicates = [HasStdExtCOrZca, IsRV64] in def : InstAlias<"c.ldsp $rd, (${rs1})", (C_LDSP GPRC:$rd, SP:$rs1, 0)>; let Predicates = [HasStdExtC, HasStdExtD] in @@ -737,7 +737,7 @@ let Predicates = [HasStdExtC, HasStdExtF, IsRV32] in def : InstAlias<"c.fswsp $rs2, (${rs1})", (C_FSWSP FPR32C:$rs2, SP:$rs1, 0)>; -let Predicates = [HasStdExtC, IsRV64] in +let Predicates = [HasStdExtCOrZca, IsRV64] in def : InstAlias<"c.sdsp $rs2, (${rs1})", (C_SDSP GPRC:$rs2, SP:$rs1, 0)>; } @@ -749,69 +749,69 @@ // on page 82 of the ISA manual. // Quadrant 0 -let Predicates = [HasStdExtC] in { +let Predicates = [HasStdExtCOrZca] in { def : CompressPat<(ADDI GPRC:$rd, SP:$rs1, uimm10_lsb00nonzero:$imm), (C_ADDI4SPN GPRC:$rd, SP:$rs1, uimm10_lsb00nonzero:$imm)>; -} // Predicates = [HasStdExtC] +} // Predicates = [HasStdExtCOrZca] let Predicates = [HasStdExtC, HasStdExtD] in { def : CompressPat<(FLD FPR64C:$rd, GPRC:$rs1, uimm8_lsb000:$imm), (C_FLD FPR64C:$rd, GPRC:$rs1, uimm8_lsb000:$imm)>; } // Predicates = [HasStdExtC, HasStdExtD] -let Predicates = [HasStdExtC] in { +let Predicates = [HasStdExtCOrZca] in { def : CompressPat<(LW GPRC:$rd, GPRC:$rs1, uimm7_lsb00:$imm), (C_LW GPRC:$rd, GPRC:$rs1, uimm7_lsb00:$imm)>; -} // Predicates = [HasStdExtC] +} // Predicates = [HasStdExtCOrZca] let Predicates = [HasStdExtC, HasStdExtF, IsRV32] in { def : CompressPat<(FLW FPR32C:$rd, GPRC:$rs1, uimm7_lsb00:$imm), (C_FLW FPR32C:$rd, GPRC:$rs1, uimm7_lsb00:$imm)>; } // Predicates = [HasStdExtC, HasStdExtF, IsRV32] -let Predicates = [HasStdExtC, IsRV64] in { +let Predicates = [HasStdExtCOrZca, IsRV64] in { def : CompressPat<(LD GPRC:$rd, GPRC:$rs1, uimm8_lsb000:$imm), (C_LD GPRC:$rd, GPRC:$rs1, uimm8_lsb000:$imm)>; -} // Predicates = [HasStdExtC, IsRV64] +} // Predicates = [HasStdExtCOrZca, IsRV64] let Predicates = [HasStdExtC, HasStdExtD] in { def : CompressPat<(FSD FPR64C:$rs2, GPRC:$rs1, uimm8_lsb000:$imm), (C_FSD FPR64C:$rs2, GPRC:$rs1, uimm8_lsb000:$imm)>; } // Predicates = [HasStdExtC, HasStdExtD] -let Predicates = [HasStdExtC] in { +let Predicates = [HasStdExtCOrZca] in { def : CompressPat<(SW GPRC:$rs2, GPRC:$rs1, uimm7_lsb00:$imm), (C_SW GPRC:$rs2, GPRC:$rs1, uimm7_lsb00:$imm)>; -} // Predicates = [HasStdExtC] +} // Predicates = [HasStdExtCOrZca] let Predicates = [HasStdExtC, HasStdExtF, IsRV32] in { def : CompressPat<(FSW FPR32C:$rs2, GPRC:$rs1, uimm7_lsb00:$imm), (C_FSW FPR32C:$rs2, GPRC:$rs1, uimm7_lsb00:$imm)>; } // Predicates = [HasStdExtC, HasStdExtF, IsRV32] -let Predicates = [HasStdExtC, IsRV64] in { +let Predicates = [HasStdExtCOrZca, IsRV64] in { def : CompressPat<(SD GPRC:$rs2, GPRC:$rs1, uimm8_lsb000:$imm), (C_SD GPRC:$rs2, GPRC:$rs1, uimm8_lsb000:$imm)>; -} // Predicates = [HasStdExtC, IsRV64] +} // Predicates = [HasStdExtCOrZca, IsRV64] // Quadrant 1 -let Predicates = [HasStdExtC] in { +let Predicates = [HasStdExtCOrZca] in { def : CompressPat<(ADDI X0, X0, 0), (C_NOP)>; def : CompressPat<(ADDI GPRNoX0:$rs1, GPRNoX0:$rs1, simm6nonzero:$imm), (C_ADDI GPRNoX0:$rs1, simm6nonzero:$imm)>; -} // Predicates = [HasStdExtC] +} // Predicates = [HasStdExtCOrZca] -let Predicates = [HasStdExtC, IsRV32] in { +let Predicates = [HasStdExtCOrZca, IsRV32] in { def : CompressPat<(JAL X1, simm12_lsb0:$offset), (C_JAL simm12_lsb0:$offset)>; -} // Predicates = [HasStdExtC, IsRV32] +} // Predicates = [HasStdExtCOrZca, IsRV32] -let Predicates = [HasStdExtC, IsRV64] in { +let Predicates = [HasStdExtCOrZca, IsRV64] in { def : CompressPat<(ADDIW GPRNoX0:$rs1, GPRNoX0:$rs1, simm6:$imm), (C_ADDIW GPRNoX0:$rs1, simm6:$imm)>; -} // Predicates = [HasStdExtC, IsRV64] +} // Predicates = [HasStdExtCOrZca, IsRV64] -let Predicates = [HasStdExtC] in { +let Predicates = [HasStdExtCOrZca] in { def : CompressPat<(ADDI GPRNoX0:$rd, X0, simm6:$imm), (C_LI GPRNoX0:$rd, simm6:$imm)>; def : CompressPat<(ADDI X2, X2, simm10_lsb0000nonzero:$imm), @@ -841,9 +841,9 @@ let isCompressOnly = true in def : CompressPat<(AND GPRC:$rs1, GPRC:$rs2, GPRC:$rs1), (C_AND GPRC:$rs1, GPRC:$rs2)>; -} // Predicates = [HasStdExtC] +} // Predicates = [HasStdExtCOrZca] -let Predicates = [HasStdExtC, IsRV64] in { +let Predicates = [HasStdExtCOrZca, IsRV64] in { let isCompressOnly = true in def : CompressPat<(ADDIW GPRNoX0:$rd, X0, simm6:$imm), (C_LI GPRNoX0:$rd, simm6:$imm)>; @@ -854,44 +854,44 @@ let isCompressOnly = true in def : CompressPat<(ADDW GPRC:$rs1, GPRC:$rs2, GPRC:$rs1), (C_ADDW GPRC:$rs1, GPRC:$rs2)>; -} // Predicates = [HasStdExtC, IsRV64] +} // Predicates = [HasStdExtCOrZca, IsRV64] -let Predicates = [HasStdExtC] in { +let Predicates = [HasStdExtCOrZca] in { def : CompressPat<(JAL X0, simm12_lsb0:$offset), (C_J simm12_lsb0:$offset)>; def : CompressPat<(BEQ GPRC:$rs1, X0, simm9_lsb0:$imm), (C_BEQZ GPRC:$rs1, simm9_lsb0:$imm)>; def : CompressPat<(BNE GPRC:$rs1, X0, simm9_lsb0:$imm), (C_BNEZ GPRC:$rs1, simm9_lsb0:$imm)>; -} // Predicates = [HasStdExtC] +} // Predicates = [HasStdExtCOrZca] // Quadrant 2 -let Predicates = [HasStdExtC] in { +let Predicates = [HasStdExtCOrZca] in { def : CompressPat<(SLLI GPRNoX0:$rs1, GPRNoX0:$rs1, uimmlog2xlennonzero:$imm), (C_SLLI GPRNoX0:$rs1, uimmlog2xlennonzero:$imm)>; -} // Predicates = [HasStdExtC] +} // Predicates = [HasStdExtCOrZca] let Predicates = [HasStdExtC, HasStdExtD] in { def : CompressPat<(FLD FPR64:$rd, SP:$rs1, uimm9_lsb000:$imm), (C_FLDSP FPR64:$rd, SP:$rs1, uimm9_lsb000:$imm)>; } // Predicates = [HasStdExtC, HasStdExtD] -let Predicates = [HasStdExtC] in { +let Predicates = [HasStdExtCOrZca] in { def : CompressPat<(LW GPRNoX0:$rd, SP:$rs1, uimm8_lsb00:$imm), (C_LWSP GPRNoX0:$rd, SP:$rs1, uimm8_lsb00:$imm)>; -} // Predicates = [HasStdExtC] +} // Predicates = [HasStdExtCOrZca] let Predicates = [HasStdExtC, HasStdExtF, IsRV32] in { def : CompressPat<(FLW FPR32:$rd, SP:$rs1, uimm8_lsb00:$imm), (C_FLWSP FPR32:$rd, SP:$rs1, uimm8_lsb00:$imm)>; } // Predicates = [HasStdExtC, HasStdExtF, IsRV32] -let Predicates = [HasStdExtC, IsRV64] in { +let Predicates = [HasStdExtCOrZca, IsRV64] in { def : CompressPat<(LD GPRNoX0:$rd, SP:$rs1, uimm9_lsb000:$imm), (C_LDSP GPRNoX0:$rd, SP:$rs1, uimm9_lsb000:$imm)>; -} // Predicates = [HasStdExtC, IsRV64] +} // Predicates = [HasStdExtCOrZca, IsRV64] -let Predicates = [HasStdExtC] in { +let Predicates = [HasStdExtCOrZca] in { def : CompressPat<(JALR X0, GPRNoX0:$rs1, 0), (C_JR GPRNoX0:$rs1)>; let isCompressOnly = true in { @@ -911,24 +911,24 @@ let isCompressOnly = true in def : CompressPat<(ADD GPRNoX0:$rs1, GPRNoX0:$rs2, GPRNoX0:$rs1), (C_ADD GPRNoX0:$rs1, GPRNoX0:$rs2)>; -} // Predicates = [HasStdExtC] +} // Predicates = [HasStdExtCOrZca] let Predicates = [HasStdExtC, HasStdExtD] in { def : CompressPat<(FSD FPR64:$rs2, SP:$rs1, uimm9_lsb000:$imm), (C_FSDSP FPR64:$rs2, SP:$rs1, uimm9_lsb000:$imm)>; } // Predicates = [HasStdExtC, HasStdExtD] -let Predicates = [HasStdExtC] in { +let Predicates = [HasStdExtCOrZca] in { def : CompressPat<(SW GPR:$rs2, SP:$rs1, uimm8_lsb00:$imm), (C_SWSP GPR:$rs2, SP:$rs1, uimm8_lsb00:$imm)>; -} // Predicates = [HasStdExtC] +} // Predicates = [HasStdExtCOrZca] let Predicates = [HasStdExtC, HasStdExtF, IsRV32] in { def : CompressPat<(FSW FPR32:$rs2, SP:$rs1, uimm8_lsb00:$imm), (C_FSWSP FPR32:$rs2, SP:$rs1, uimm8_lsb00:$imm)>; } // Predicates = [HasStdExtC, HasStdExtF, IsRV32] -let Predicates = [HasStdExtC, IsRV64] in { +let Predicates = [HasStdExtCOrZca, IsRV64] in { def : CompressPat<(SD GPR:$rs2, SP:$rs1, uimm9_lsb000:$imm), (C_SDSP GPR:$rs2, SP:$rs1, uimm9_lsb000:$imm)>; -} // Predicates = [HasStdExtC, IsRV64] +} // Predicates = [HasStdExtCOrZca, IsRV64] 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 @@ -60,6 +60,7 @@ bool HasStdExtZbr = false; bool HasStdExtZbs = false; bool HasStdExtZbt = false; + bool HasStdExtZca = false; bool HasStdExtV = false; bool HasStdExtZve32x = false; bool HasStdExtZve32f = false; @@ -166,6 +167,7 @@ bool hasStdExtZbt() const { return HasStdExtZbt; } bool hasStdExtZvl() const { return ZvlLen != 0; } bool hasStdExtZvfh() const { return HasStdExtZvfh; } + bool hasStdExtZca() const { return HasStdExtZca; } bool hasStdExtZfhmin() const { return HasStdExtZfhmin; } bool hasStdExtZfh() const { return HasStdExtZfh; } bool hasStdExtZfinx() const { return HasStdExtZfinx; } diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll --- a/llvm/test/CodeGen/RISCV/attributes.ll +++ b/llvm/test/CodeGen/RISCV/attributes.ll @@ -39,6 +39,8 @@ ; RUN: llc -mtriple=riscv32 -mattr=+zicbom %s -o - | FileCheck --check-prefix=RV32ZICBOM %s ; RUN: llc -mtriple=riscv32 -mattr=+zicboz %s -o - | FileCheck --check-prefix=RV32ZICBOZ %s ; RUN: llc -mtriple=riscv32 -mattr=+zicbop %s -o - | FileCheck --check-prefix=RV32ZICBOP %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-zca %s -o - | FileCheck --check-prefix=RV32ZCA %s + ; RUN: llc -mtriple=riscv64 -mattr=+m %s -o - | FileCheck --check-prefix=RV64M %s ; RUN: llc -mtriple=riscv64 -mattr=+a %s -o - | FileCheck --check-prefix=RV64A %s ; RUN: llc -mtriple=riscv64 -mattr=+f %s -o - | FileCheck --check-prefix=RV64F %s @@ -78,6 +80,7 @@ ; RUN: llc -mtriple=riscv64 -mattr=+zicbom %s -o - | FileCheck --check-prefix=RV64ZICBOM %s ; RUN: llc -mtriple=riscv64 -mattr=+zicboz %s -o - | FileCheck --check-prefix=RV64ZICBOZ %s ; RUN: llc -mtriple=riscv64 -mattr=+zicbop %s -o - | FileCheck --check-prefix=RV64ZICBOP %s +; RUN: llc -mtriple=riscv64 -mattr=+experimental-zca %s -o - | FileCheck --check-prefix=RV64ZCA %s ; RV32M: .attribute 5, "rv32i2p0_m2p0" ; RV32A: .attribute 5, "rv32i2p0_a2p0" @@ -118,6 +121,7 @@ ; RV32ZICBOM: .attribute 5, "rv32i2p0_zicbom1p0" ; RV32ZICBOZ: .attribute 5, "rv32i2p0_zicboz1p0" ; RV32ZICBOP: .attribute 5, "rv32i2p0_zicbop1p0" +; RV32ZCA: .attribute 5, "rv32i2p0_zca0p70" ; RV64M: .attribute 5, "rv64i2p0_m2p0" ; RV64A: .attribute 5, "rv64i2p0_a2p0" @@ -158,6 +162,7 @@ ; RV64ZICBOM: .attribute 5, "rv64i2p0_zicbom1p0" ; RV64ZICBOZ: .attribute 5, "rv64i2p0_zicboz1p0" ; RV64ZICBOP: .attribute 5, "rv64i2p0_zicbop1p0" +; RV64ZCA: .attribute 5, "rv64i2p0_zca0p70" define i32 @addi(i32 %a) { %1 = add i32 %a, 1 diff --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s --- a/llvm/test/MC/RISCV/attribute-arch.s +++ b/llvm/test/MC/RISCV/attribute-arch.s @@ -187,3 +187,6 @@ .attribute arch, "rv32if_zkt1p0_zve32f1p0_zve32x1p0_zvl32b1p0" # CHECK: attribute 5, "rv32i2p0_f2p0_zkt1p0_zve32f1p0_zve32x1p0_zvl32b1p0" + +.attribute arch, "rv32izca0p70" +# CHECK: attribute 5, "rv32i2p0_zca0p70" diff --git a/llvm/test/MC/RISCV/rv32c-only-valid.s b/llvm/test/MC/RISCV/rv32c-only-valid.s --- a/llvm/test/MC/RISCV/rv32c-only-valid.s +++ b/llvm/test/MC/RISCV/rv32c-only-valid.s @@ -19,5 +19,5 @@ # CHECK-ASM: encoding: [0xfd,0x2f] # CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) # CHECK-NO-RV32: error: instruction requires the following: RV32I Base Instruction Set -# CHECK-NO-RV32-AND-EXT: error: instruction requires the following: 'C' (Compressed Instructions), RV32I Base Instruction Set +# CHECK-NO-RV32-AND-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension), RV32I Base Instruction Set c.jal 2046 diff --git a/llvm/test/MC/RISCV/rv32zca-aliases-valid.s b/llvm/test/MC/RISCV/rv32zca-aliases-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zca-aliases-valid.s @@ -0,0 +1,66 @@ +# RUN: llvm-mc -triple=riscv32 -mattr=+experimental-zca -riscv-no-aliases < %s \ +# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-zca < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zca -d -M no-aliases - \ +# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-INST %s + +# The following check prefixes are used in this test: +# CHECK-INST.....Match the canonical instr (tests alias to instr. mapping) +# CHECK-EXPAND...Match canonical instr. unconditionally (tests alias expansion) +# CHECK-INST: {{^}} + +# CHECK-EXPAND: c.li a0, 0 +li x10, 0 +# CHECK-EXPAND: c.li a0, 1 +li x10, 1 +# CHECK-EXPAND: c.li a0, -1 +li x10, -1 +# CHECK-EXPAND: addi a0, zero, 2047 +li x10, 2047 +# CHECK-EXPAND: addi a0, zero, -2047 +li x10, -2047 +# CHECK-EXPAND: c.lui a1, 1 +# CHECK-EXPAND: addi a1, a1, -2048 +li x11, 2048 +# CHECK-EXPAND: addi a1, zero, -2048 +li x11, -2048 +# CHECK-EXPAND: c.lui a1, 1 +# CHECK-EXPAND: addi a1, a1, -2047 +li x11, 2049 +# CHECK-EXPAND: lui a1, 1048575 +# CHECK-EXPAND: addi a1, a1, 2047 +li x11, -2049 +# CHECK-EXPAND: c.lui a1, 1 +# CHECK-EXPAND: c.addi a1, -1 +li x11, 4095 +# CHECK-EXPAND: lui a1, 1048575 +# CHECK-EXPAND: c.addi a1, 1 +li x11, -4095 +# CHECK-EXPAND: c.lui a2, 1 +li x12, 4096 +# CHECK-EXPAND: lui a2, 1048575 +li x12, -4096 +# CHECK-EXPAND: c.lui a2, 1 +# CHECK-EXPAND: c.addi a2, 1 +li x12, 4097 +# CHECK-EXPAND: lui a2, 1048575 +# CHECK-EXPAND: c.addi a2, -1 +li x12, -4097 +# CHECK-EXPAND: lui a2, 524288 +# CHECK-EXPAND: c.addi a2, -1 +li x12, 2147483647 +# CHECK-EXPAND: lui a2, 524288 +# CHECK-EXPAND: c.addi a2, 1 +li x12, -2147483647 +# CHECK-EXPAND: lui a2, 524288 +li x12, -2147483648 +# CHECK-EXPAND: lui a2, 524288 +li x12, -0x80000000 + +# CHECK-EXPAND: lui a2, 524288 +li x12, 0x80000000 +# CHECK-EXPAND: c.li a2, -1 +li x12, 0xFFFFFFFF + +# CHECK-EXPAND: c.mv sp, sp +addi x2, x2, 0 diff --git a/llvm/test/MC/RISCV/rv32zca-invalid.s b/llvm/test/MC/RISCV/rv32zca-invalid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zca-invalid.s @@ -0,0 +1,93 @@ +# RUN: not llvm-mc -triple=riscv32 -mattr=+experimental-zca -mattr=+no-rvc-hints < %s 2>&1 \ +# RUN: | FileCheck %s + +## GPRC +.LBB: +c.lw ra, 4(sp) # CHECK: :[[@LINE]]:7: error: invalid operand for instruction +c.sw sp, 4(sp) # CHECK: :[[@LINE]]:7: error: invalid operand for instruction +c.beqz t0, .LBB # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.bnez s8, .LBB # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.addi4spn s4, sp, 12 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction +c.srli s7, 12 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.srai t0, 12 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.andi t1, 12 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.and t1, a0 # CHECK: :[[@LINE]]:8: error: invalid operand for instruction +c.or a0, s8 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction +c.xor t2, a0 # CHECK: :[[@LINE]]:8: error: invalid operand for instruction +c.sub a0, s8 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction + +## GPRNoX0 +c.lwsp x0, 4(sp) # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.lwsp zero, 4(sp) # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.jr x0 # CHECK: :[[@LINE]]:7: error: invalid operand for instruction +c.jalr zero # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.addi x0, x0, 1 # CHECK: :[[@LINE]]:13: error: immediate must be zero +c.li zero, 2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RVC Hint Instructions +c.slli zero, zero, 4 # CHECK: :[[@LINE]]:15: error: invalid operand for instruction +c.mv zero, s0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RVC Hint Instructions +c.mv ra, x0 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction +c.add ra, ra, x0 # CHECK: :[[@LINE]]:16: error: invalid operand for instruction +c.add zero, zero, sp # CHECK: :[[@LINE]]:14: error: invalid operand for instruction + +## GPRNoX0X2 +c.lui x0, 4 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RVC Hint Instructions +c.lui x2, 4 # CHECK: :[[@LINE]]:7: error: invalid operand for instruction + +## SP +c.addi4spn a0, a0, 12 # CHECK: :[[@LINE]]:17: error: invalid operand for instruction +c.addi16sp t0, 16 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction + +# Out of range immediates + +## uimmlog2xlennonzero +c.slli t0, 64 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 31] +c.srli a0, 32 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 31] +c.srai a0, 0 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 31] + +## simm6 +c.li t0, 128 # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [-32, 31] +c.li t0, foo # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [-32, 31] +c.li t0, %lo(foo) # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [-32, 31] +c.li t0, %hi(foo) # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [-32, 31] +c.andi a0, -33 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [-32, 31] +c.andi a0, foo # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [-32, 31] +c.andi a0, %lo(foo) # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [-32, 31] +c.andi a0, %hi(foo) # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [-32, 31] + +## simm6nonzero +c.addi t0, 0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RVC Hint Instructions +c.addi t0, -33 # CHECK: :[[@LINE]]:12: error: immediate must be non-zero in the range [-32, 31] +c.addi t0, 32 # CHECK: :[[@LINE]]:12: error: immediate must be non-zero in the range [-32, 31] +c.addi t0, foo # CHECK: :[[@LINE]]:12: error: immediate must be non-zero in the range [-32, 31] +c.addi t0, %lo(foo) # CHECK: :[[@LINE]]:12: error: immediate must be non-zero in the range [-32, 31] +c.addi t0, %hi(foo) # CHECK: :[[@LINE]]:12: error: immediate must be non-zero in the range [-32, 31] + +## c_lui_imm +c.lui t0, 0 # CHECK: :[[@LINE]]:11: error: immediate must be in [0xfffe0, 0xfffff] or [1, 31] +c.lui t0, 32 # CHECK: :[[@LINE]]:11: error: immediate must be in [0xfffe0, 0xfffff] or [1, 31] +c.lui t0, 0xffffdf # CHECK: :[[@LINE]]:11: error: immediate must be in [0xfffe0, 0xfffff] or [1, 31] +c.lui t0, 0x1000000 # CHECK: :[[@LINE]]:11: error: immediate must be in [0xfffe0, 0xfffff] or [1, 31] + +## uimm8_lsb00 +c.lwsp ra, 256(sp) # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 4 bytes in the range [0, 252] +c.swsp ra, -4(sp) # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 4 bytes in the range [0, 252] +## uimm7_lsb00 +c.lw s0, -4(sp) # CHECK: :[[@LINE]]:11: error: immediate must be a multiple of 4 bytes in the range [0, 124] +c.sw s0, 128(sp) # CHECK: :[[@LINE]]:11: error: immediate must be a multiple of 4 bytes in the range [0, 124] + +## simm9_lsb0 +c.bnez s1, -258 # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 2 bytes in the range [-256, 254] +c.beqz a0, 256 # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 2 bytes in the range [-256, 254] + +## simm12_lsb0 +c.j 2048 # CHECK: :[[@LINE]]:5: error: immediate must be a multiple of 2 bytes in the range [-2048, 2046] +c.jal -2050 # CHECK: :[[@LINE]]:7: error: immediate must be a multiple of 2 bytes in the range [-2048, 2046] + +## uimm10_lsb00nonzero +c.addi4spn a0, sp, 0 # CHECK: :[[@LINE]]:21: error: immediate must be a multiple of 4 bytes in the range [4, 1020] +c.addi4spn a0, sp, 1024 # CHECK: :[[@LINE]]:21: error: immediate must be a multiple of 4 bytes in the range [4, 1020] + +## simm10_lsb0000nonzero +c.addi16sp sp, -528 # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 16 bytes and non-zero in the range [-512, 496] +c.addi16sp sp, 512 # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 16 bytes and non-zero in the range [-512, 496] +c.addi16sp sp, 0 # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 16 bytes and non-zero in the range [-512, 496] diff --git a/llvm/test/MC/RISCV/rv32zca-valid.s b/llvm/test/MC/RISCV/rv32zca-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zca-valid.s @@ -0,0 +1,111 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zca -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zca < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zca -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefixes=CHECK-OBJ,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zca -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zca < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zca -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s + +# TODO: more exhaustive testing of immediate encoding. + +# CHECK-ASM-AND-OBJ: c.lwsp ra, 0(sp) +# CHECK-ASM: encoding: [0x82,0x40] +c.lwsp ra, 0(sp) +# CHECK-ASM-AND-OBJ: c.swsp ra, 252(sp) +# CHECK-ASM: encoding: [0x86,0xdf] +c.swsp ra, 252(sp) +# CHECK-ASM-AND-OBJ: c.lw a2, 0(a0) +# CHECK-ASM: encoding: [0x10,0x41] +c.lw a2, 0(a0) +# CHECK-ASM-AND-OBJ: c.sw a5, 124(a3) +# CHECK-ASM: encoding: [0xfc,0xde] +c.sw a5, 124(a3) + +# CHECK-OBJ: c.j 0xfffff808 +# CHECK-ASM: c.j -2048 +# CHECK-ASM: encoding: [0x01,0xb0] +c.j -2048 +# CHECK-ASM-AND-OBJ: c.jr a7 +# CHECK-ASM: encoding: [0x82,0x88] +c.jr a7 +# CHECK-ASM-AND-OBJ: c.jalr a1 +# CHECK-ASM: encoding: [0x82,0x95] +c.jalr a1 +# CHECK-OBJ: c.beqz a3, 0xffffff0e +# CHECK-ASM: c.beqz a3, -256 +# CHECK-ASM: encoding: [0x81,0xd2] +c.beqz a3, -256 +# CHECK-OBJ: c.bnez a5, 0x10e +# CHECK-ASM: c.bnez a5, 254 +# CHECK-ASM: encoding: [0xfd,0xef] +c.bnez a5, 254 + +# CHECK-ASM-AND-OBJ: c.li a7, 31 +# CHECK-ASM: encoding: [0xfd,0x48] +c.li a7, 31 +# CHECK-ASM-AND-OBJ: c.addi a3, -32 +# CHECK-ASM: encoding: [0x81,0x16] +c.addi a3, -32 +# CHECK-ASM-AND-OBJ: c.addi16sp sp, -512 +# CHECK-ASM: encoding: [0x01,0x71] +c.addi16sp sp, -512 +# CHECK-ASM-AND-OBJ: c.addi16sp sp, 496 +# CHECK-ASM: encoding: [0x7d,0x61] +c.addi16sp sp, 496 +# CHECK-ASM-AND-OBJ: c.addi4spn a3, sp, 1020 +# CHECK-ASM: encoding: [0xf4,0x1f] +c.addi4spn a3, sp, 1020 +# CHECK-ASM-AND-OBJ: c.addi4spn a3, sp, 4 +# CHECK-ASM: encoding: [0x54,0x00] +c.addi4spn a3, sp, 4 +# CHECK-ASM-AND-OBJ: c.slli a1, 1 +# CHECK-ASM: encoding: [0x86,0x05] +c.slli a1, 1 +# CHECK-ASM-AND-OBJ: c.srli a3, 31 +# CHECK-ASM: encoding: [0xfd,0x82] +c.srli a3, 31 +# CHECK-ASM-AND-OBJ: c.srai a4, 2 +# CHECK-ASM: encoding: [0x09,0x87] +c.srai a4, 2 +# CHECK-ASM-AND-OBJ: c.andi a5, 15 +# CHECK-ASM: encoding: [0xbd,0x8b] +c.andi a5, 15 +# CHECK-ASM-AND-OBJ: c.mv a7, s0 +# CHECK-ASM: encoding: [0xa2,0x88] +c.mv a7, s0 +# CHECK-ASM-AND-OBJ: c.and a1, a2 +# CHECK-ASM: encoding: [0xf1,0x8d] +c.and a1, a2 +# CHECK-ASM-AND-OBJ: c.or a2, a3 +# CHECK-ASM: encoding: [0x55,0x8e] +c.or a2, a3 +# CHECK-ASM-AND-OBJ: c.xor a3, a4 +# CHECK-ASM: encoding: [0xb9,0x8e] +c.xor a3, a4 +# CHECK-ASM-AND-OBJ: c.sub a4, a5 +# CHECK-ASM: encoding: [0x1d,0x8f] +c.sub a4, a5 +# CHECK-ASM-AND-OBJ: c.nop +# CHECK-ASM: encoding: [0x01,0x00] +c.nop +# CHECK-ASM-AND-OBJ: c.ebreak +# CHECK-ASM: encoding: [0x02,0x90] +c.ebreak +# CHECK-ASM-AND-OBJ: c.lui s0, 1 +# CHECK-ASM: encoding: [0x05,0x64] +c.lui s0, 1 +# CHECK-ASM-AND-OBJ: c.lui s0, 31 +# CHECK-ASM: encoding: [0x7d,0x64] +c.lui s0, 31 +# CHECK-ASM-AND-OBJ: c.lui s0, 1048544 +# CHECK-ASM: encoding: [0x01,0x74] +c.lui s0, 0xfffe0 +# CHECK-ASM-AND-OBJ: c.lui s0, 1048575 +# CHECK-ASM: encoding: [0x7d,0x74] +c.lui s0, 0xfffff +# CHECK-ASM-AND-OBJ: c.unimp +# CHECK-ASM: encoding: [0x00,0x00] +c.unimp diff --git a/llvm/test/MC/RISCV/rv64zca-aliases-valid.s b/llvm/test/MC/RISCV/rv64zca-aliases-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv64zca-aliases-valid.s @@ -0,0 +1,105 @@ +# RUN: llvm-mc -triple=riscv64 -mattr=+experimental-zca -riscv-no-aliases < %s \ +# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+experimental-zca < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zca -d -M no-aliases - \ +# RUN: | FileCheck -check-prefixes=CHECK-EXPAND,CHECK-INST %s + +# The following check prefixes are used in this test: +# CHECK-INST.....Match the canonical instr (tests alias to instr. mapping) +# CHECK-EXPAND...Match canonical instr. unconditionally (tests alias expansion) +# CHECK-INST: {{^}} + +# CHECK-EXPAND: c.li a0, 0 +li x10, 0 +# CHECK-EXPAND: c.li a0, 1 +li x10, 1 +# CHECK-EXPAND: c.li a0, -1 +li x10, -1 +# CHECK-EXPAND: addi a0, zero, 2047 +li x10, 2047 +# CHECK-EXPAND: addi a0, zero, -2047 +li x10, -2047 +# CHECK-EXPAND: c.lui a1, 1 +# CHECK-EXPAND: addiw a1, a1, -2048 +li x11, 2048 +# CHECK-EXPAND: addi a1, zero, -2048 +li x11, -2048 +# CHECK-EXPAND: c.lui a1, 1 +# CHECK-EXPAND: addiw a1, a1, -2047 +li x11, 2049 +# CHECK-EXPAND: c.lui a1, 1048575 +# CHECK-EXPAND: addiw a1, a1, 2047 +li x11, -2049 +# CHECK-EXPAND: c.lui a1, 1 +# CHECK-EXPAND: c.addiw a1, -1 +li x11, 4095 +# CHECK-EXPAND: lui a1, 1048575 +# CHECK-EXPAND: c.addiw a1, 1 +li x11, -4095 +# CHECK-EXPAND: c.lui a2, 1 +li x12, 4096 +# CHECK-EXPAND: lui a2, 1048575 +li x12, -4096 +# CHECK-EXPAND: c.lui a2, 1 +# CHECK-EXPAND: c.addiw a2, 1 +li x12, 4097 +# CHECK-EXPAND: lui a2, 1048575 +# CHECK-EXPAND: c.addiw a2, -1 +li x12, -4097 +# CHECK-EXPAND: lui a2, 524288 +# CHECK-EXPAND: c.addiw a2, -1 +li x12, 2147483647 +# CHECK-EXPAND: lui a2, 524288 +# CHECK-EXPAND: c.addiw a2, 1 +li x12, -2147483647 +# CHECK-EXPAND: lui a2, 524288 +li x12, -2147483648 +# CHECK-EXPAND: lui a2, 524288 +li x12, -0x80000000 + +# CHECK-EXPAND: c.li a2, 1 +# CHECK-EXPAND: c.slli a2, 31 +li x12, 0x80000000 +# CHECK-EXPAND: c.li a2, -1 +# CHECK-EXPAND: c.srli a2, 32 +li x12, 0xFFFFFFFF + +# CHECK-EXPAND: c.li t0, 1 +# CHECK-EXPAND: c.slli t0, 32 +li t0, 0x100000000 +# CHECK-EXPAND: c.li t1, -1 +# CHECK-EXPAND: c.slli t1, 63 +li t1, 0x8000000000000000 +# CHECK-EXPAND: c.li t1, -1 +# CHECK-EXPAND: c.slli t1, 63 +li t1, -0x8000000000000000 +# CHECK-EXPAND: lui t2, 9321 +# CHECK-EXPAND: addiw t2, t2, -1329 +# CHECK-EXPAND: c.slli t2, 35 +li t2, 0x1234567800000000 +# CHECK-EXPAND: c.li t3, 7 +# CHECK-EXPAND: c.slli t3, 36 +# CHECK-EXPAND: c.addi t3, 11 +# CHECK-EXPAND: c.slli t3, 24 +# CHECK-EXPAND: c.addi t3, 15 +li t3, 0x700000000B00000F +# CHECK-EXPAND: lui t4, 583 +# CHECK-EXPAND: addiw t4, t4, -1875 +# CHECK-EXPAND: c.slli t4, 14 +# CHECK-EXPAND: addi t4, t4, -947 +# CHECK-EXPAND: c.slli t4, 12 +# CHECK-EXPAND: addi t4, t4, 1511 +# CHECK-EXPAND: c.slli t4, 13 +# CHECK-EXPAND: addi t4, t4, -272 +li t4, 0x123456789abcdef0 +# CHECK-EXPAND: c.li t5, -1 +li t5, 0xFFFFFFFFFFFFFFFF + +# CHECK-EXPAND: c.ld s0, 0(s1) +c.ld x8, (x9) +# CHECK-EXPAND: c.sd s0, 0(s1) +c.sd x8, (x9) +# CHECK-EXPAND: c.ldsp s0, 0(sp) +c.ldsp x8, (x2) +# CHECK-EXPAND: c.sdsp s0, 0(sp) +c.sdsp x8, (x2) diff --git a/llvm/test/MC/RISCV/rv64zca-hints-valid.s b/llvm/test/MC/RISCV/rv64zca-hints-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv64zca-hints-valid.s @@ -0,0 +1,9 @@ +# RUN: llvm-mc %s -triple riscv64 -mattr=+experimental-zca -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zca < %s \ +# RUN: | llvm-objdump --mattr=+experimental-zca -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s + +# CHECK-ASM-AND-OBJ: c.slli zero, 63 +# CHECK-ASM: encoding: [0x7e,0x10] +c.slli x0, 63 diff --git a/llvm/test/MC/RISCV/rv64zca-invalid.s b/llvm/test/MC/RISCV/rv64zca-invalid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv64zca-invalid.s @@ -0,0 +1,32 @@ +# RUN: not llvm-mc -triple=riscv64 -mattr=+experimental-zca < %s 2>&1 | FileCheck %s + +## GPRC +c.ld ra, 4(sp) # CHECK: :[[@LINE]]:6: error: invalid operand for instruction +c.sd sp, 4(sp) # CHECK: :[[@LINE]]:6: error: invalid operand for instruction +c.addw a0, a7 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction +c.subw a0, a6 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction + +## GPRNoX0 +c.ldsp x0, 4(sp) # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.ldsp zero, 4(sp) # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + +# Out of range immediates + +## uimmlog2xlennonzero +c.slli t0, 64 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 63] +c.srli a0, -1 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 63] +c.srai a0, 0 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 63] + +## simm6 +c.addiw t0, -33 # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [-32, 31] +c.addiw t0, 32 # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [-32, 31] +c.addiw t0, foo # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [-32, 31] +c.addiw t0, %lo(foo) # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [-32, 31] +c.addiw t0, %hi(foo) # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [-32, 31] + +## uimm9_lsb000 +c.ldsp ra, 512(sp) # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 8 bytes in the range [0, 504] +c.sdsp ra, -8(sp) # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 8 bytes in the range [0, 504] +## uimm8_lsb000 +c.ld s0, -8(sp) # CHECK: :[[@LINE]]:11: error: immediate must be a multiple of 8 bytes in the range [0, 248] +c.sd s0, 256(sp) # CHECK: :[[@LINE]]:11: error: immediate must be a multiple of 8 bytes in the range [0, 248] diff --git a/llvm/test/MC/RISCV/rv64zca-valid.s b/llvm/test/MC/RISCV/rv64zca-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv64zca-valid.s @@ -0,0 +1,68 @@ +# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zca -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+c < %s \ +# RUN: | llvm-objdump --mattr=+c -M no-aliases -d -r - \ +# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s +# +# +# RUN: not llvm-mc -triple riscv64 \ +# RUN: -riscv-no-aliases -show-encoding < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK-NO-EXT %s +# RUN: not llvm-mc -triple riscv32 -mattr=+c \ +# RUN: -riscv-no-aliases -show-encoding < %s 2>&1 \ +# RUN: | FileCheck -check-prefixes=CHECK-NO-RV64 %s + +# TODO: more exhaustive testing of immediate encoding. + +# CHECK-ASM-AND-OBJ: c.ldsp ra, 0(sp) +# CHECK-ASM: encoding: [0x82,0x60] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) +# CHECK-NO-RV64: error: instruction requires the following: RV64I Base Instruction Set +c.ldsp ra, 0(sp) +# CHECK-ASM-AND-OBJ: c.sdsp ra, 504(sp) +# CHECK-ASM: encoding: [0x86,0xff] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) +# CHECK-NO-RV64: error: instruction requires the following: RV64I Base Instruction Set +c.sdsp ra, 504(sp) +# CHECK-ASM-AND-OBJ: c.ld a4, 0(a3) +# CHECK-ASM: encoding: [0x98,0x62] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) +# CHECK-NO-RV64: error: instruction requires the following: RV64I Base Instruction Set +c.ld a4, 0(a3) +# CHECK-ASM-AND-OBJ: c.sd a5, 248(a3) +# CHECK-ASM: encoding: [0xfc,0xfe] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) +# CHECK-NO-RV64: error: instruction requires the following: RV64I Base Instruction Set +c.sd a5, 248(a3) + +# CHECK-ASM-AND-OBJ: c.subw a3, a4 +# CHECK-ASM: encoding: [0x99,0x9e] +c.subw a3, a4 +# CHECK-ASM-AND-OBJ: c.addw a0, a2 +# CHECK-ASM: encoding: [0x31,0x9d] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) +# CHECK-NO-RV64: error: instruction requires the following: RV64I Base Instruction Set +c.addw a0, a2 + +# CHECK-ASM-AND-OBJ: c.addiw a3, -32 +# CHECK-ASM: encoding: [0x81,0x36] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) +# CHECK-NO-RV64: error: instruction requires the following: RV64I Base Instruction Set +c.addiw a3, -32 +# CHECK-ASM-AND-OBJ: c.addiw a3, 31 +# CHECK-ASM: encoding: [0xfd,0x26] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) +# CHECK-NO-RV64: error: instruction requires the following: RV64I Base Instruction Set +c.addiw a3, 31 + +# CHECK-ASM-AND-OBJ: c.slli s0, 1 +# CHECK-ASM: encoding: [0x06,0x04] +# CHECK-NO-EXT: error: instruction requires the following: 'C' (Compressed Instructions) +# CHECK-NO-RV64: error: instruction requires the following: RV64I Base Instruction Set +c.slli s0, 1 +# CHECK-ASM-AND-OBJ: c.srli a3, 63 +# CHECK-ASM: encoding: [0xfd,0x92] +c.srli a3, 63 +# CHECK-ASM-AND-OBJ: c.srai a2, 63 +# CHECK-ASM: encoding: [0x7d,0x96] +c.srai a2, 63