diff options
26 files changed, 316 insertions, 3 deletions
diff --git a/llvm/include/llvm/Support/MipsABIFlags.h b/llvm/include/llvm/Support/MipsABIFlags.h index 40e62e7bd81..12c350015b2 100644 --- a/llvm/include/llvm/Support/MipsABIFlags.h +++ b/llvm/include/llvm/Support/MipsABIFlags.h @@ -43,7 +43,8 @@ enum AFL_ASE { AFL_ASE_MIPS16 = 0x00000400, // MIPS16 ASE AFL_ASE_MICROMIPS = 0x00000800, // MICROMIPS ASE AFL_ASE_XPA = 0x00001000, // XPA ASE - AFL_ASE_CRC = 0x00008000 // CRC ASE + AFL_ASE_CRC = 0x00008000, // CRC ASE + AFL_ASE_GINV = 0x00020000 // GINV ASE }; // Values for the isa_ext word of an ABI flags structure. diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 4e28d910ecb..6eb01b270a4 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -350,6 +350,7 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseSetNoMtDirective(); bool parseSetNoCRCDirective(); bool parseSetNoVirtDirective(); + bool parseSetNoGINVDirective(); bool parseSetAssignment(); @@ -654,6 +655,10 @@ public: return getSTI().getFeatureBits()[Mips::FeatureVirt]; } + bool hasGINV() const { + return getSTI().getFeatureBits()[Mips::FeatureGINV]; + } + /// Warn if RegIndex is the same as the current AT. void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc); @@ -6740,6 +6745,23 @@ bool MipsAsmParser::parseSetNoVirtDirective() { return false; } +bool MipsAsmParser::parseSetNoGINVDirective() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); // Eat "noginv". + + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); + return false; + } + + clearFeatureBits(Mips::FeatureGINV, "ginv"); + + getTargetStreamer().emitDirectiveSetNoGINV(); + Parser.Lex(); // Consume the EndOfStatement. + return false; +} + bool MipsAsmParser::parseSetPopDirective() { MCAsmParser &Parser = getParser(); SMLoc Loc = getLexer().getLoc(); @@ -6969,6 +6991,10 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) { setFeatureBits(Mips::FeatureVirt, "virt"); getTargetStreamer().emitDirectiveSetVirt(); break; + case Mips::FeatureGINV: + setFeatureBits(Mips::FeatureGINV, "ginv"); + getTargetStreamer().emitDirectiveSetGINV(); + break; } return false; } @@ -7281,6 +7307,10 @@ bool MipsAsmParser::parseDirectiveSet() { return parseSetFeature(Mips::FeatureVirt); } else if (Tok.getString() == "novirt") { return parseSetNoVirtDirective(); + } else if (Tok.getString() == "ginv") { + return parseSetFeature(Mips::FeatureGINV); + } else if (Tok.getString() == "noginv") { + return parseSetNoGINVDirective(); } else { // It is just an identifier, look for an assignment. parseSetAssignment(); @@ -7531,6 +7561,8 @@ bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) { /// ::= .module nocrc /// ::= .module virt /// ::= .module novirt +/// ::= .module ginv +/// ::= .module noginv bool MipsAsmParser::parseDirectiveModule() { MCAsmParser &Parser = getParser(); MCAsmLexer &Lexer = getLexer(); @@ -7725,6 +7757,44 @@ bool MipsAsmParser::parseDirectiveModule() { } return false; // parseDirectiveModule has finished successfully. + } else if (Option == "ginv") { + setModuleFeatureBits(Mips::FeatureGINV, "ginv"); + + // Synchronize the ABI Flags information with the FeatureBits information we + // updated above. + getTargetStreamer().updateABIInfo(*this); + + // If printing assembly, use the recently updated ABI Flags information. + // If generating ELF, don't do anything (the .MIPS.abiflags section gets + // emitted later). + getTargetStreamer().emitDirectiveModuleGINV(); + + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); + return false; + } + + return false; // parseDirectiveModule has finished successfully. + } else if (Option == "noginv") { + clearModuleFeatureBits(Mips::FeatureGINV, "ginv"); + + // Synchronize the ABI Flags information with the FeatureBits information we + // updated above. + getTargetStreamer().updateABIInfo(*this); + + // If printing assembly, use the recently updated ABI Flags information. + // If generating ELF, don't do anything (the .MIPS.abiflags section gets + // emitted later). + getTargetStreamer().emitDirectiveModuleNoGINV(); + + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); + return false; + } + + return false; // parseDirectiveModule has finished successfully. } else { return Error(L, "'" + Twine(Option) + "' is not a valid .module option."); } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h index bced1e96002..68bf3829aab 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h @@ -165,6 +165,8 @@ public: ASESet |= Mips::AFL_ASE_CRC; if (P.hasVirt()) ASESet |= Mips::AFL_ASE_VIRT; + if (P.hasGINV()) + ASESet |= Mips::AFL_ASE_GINV; } template <class PredicateLibrary> diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 96c6f08908e..1eb21b6cc82 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -56,6 +56,8 @@ void MipsTargetStreamer::emitDirectiveSetCRC() {} void MipsTargetStreamer::emitDirectiveSetNoCRC() {} void MipsTargetStreamer::emitDirectiveSetVirt() {} void MipsTargetStreamer::emitDirectiveSetNoVirt() {} +void MipsTargetStreamer::emitDirectiveSetGINV() {} +void MipsTargetStreamer::emitDirectiveSetNoGINV() {} void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) { forbidModuleDirective(); @@ -130,6 +132,8 @@ void MipsTargetStreamer::emitDirectiveModuleCRC() {} void MipsTargetStreamer::emitDirectiveModuleNoCRC() {} void MipsTargetStreamer::emitDirectiveModuleVirt() {} void MipsTargetStreamer::emitDirectiveModuleNoVirt() {} +void MipsTargetStreamer::emitDirectiveModuleGINV() {} +void MipsTargetStreamer::emitDirectiveModuleNoGINV() {} void MipsTargetStreamer::emitDirectiveSetFp( MipsABIFlagsSection::FpABIKind Value) { forbidModuleDirective(); @@ -449,6 +453,16 @@ void MipsTargetAsmStreamer::emitDirectiveSetNoVirt() { MipsTargetStreamer::emitDirectiveSetNoVirt(); } +void MipsTargetAsmStreamer::emitDirectiveSetGINV() { + OS << "\t.set\tginv\n"; + MipsTargetStreamer::emitDirectiveSetGINV(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetNoGINV() { + OS << "\t.set\tnoginv\n"; + MipsTargetStreamer::emitDirectiveSetNoGINV(); +} + void MipsTargetAsmStreamer::emitDirectiveSetAt() { OS << "\t.set\tat\n"; MipsTargetStreamer::emitDirectiveSetAt(); @@ -738,6 +752,14 @@ void MipsTargetAsmStreamer::emitDirectiveModuleNoVirt() { OS << "\t.module\tnovirt\n"; } +void MipsTargetAsmStreamer::emitDirectiveModuleGINV() { + OS << "\t.module\tginv\n"; +} + +void MipsTargetAsmStreamer::emitDirectiveModuleNoGINV() { + OS << "\t.module\tnoginv\n"; +} + // This part is for ELF object output. MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI) diff --git a/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td b/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td index db7764cdc51..159eefe3979 100644 --- a/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td +++ b/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -889,6 +889,23 @@ class POOL32A_MFTC0_FM_MMR6<string instr_asm, bits<5> funct, bits<6> opcode> let Inst{5-0} = opcode; } +class POOL32A_GINV_FM_MMR6<string instr_asm, bits<2> ginv> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rs; + bits<2> type; + + bits<32> Inst; + + let Inst{31-26} = 0x0; + let Inst{25-21} = 0x0; + let Inst{20-16} = rs; + let Inst{15-13} = 0b011; + let Inst{12-11} = ginv; + let Inst{10-9} = type; + let Inst{8-6} = 0b101; + let Inst{5-0} = 0b111100; +} + class POOL32F_MFTC1_FM_MMR6<string instr_asm, bits<8> funct> : MMR6Arch<instr_asm> { bits<5> rt; diff --git a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td index bf587bb194e..44fec45cb29 100644 --- a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -106,6 +106,8 @@ class DI_MMR6_ENC : POOL32A_EIDI_MMR6_ENC<"di", 0b0100011101>; class ERET_MMR6_ENC : POOL32A_ERET_FM_MMR6<"eret", 0x3cd>; class DERET_MMR6_ENC : POOL32A_ERET_FM_MMR6<"eret", 0b1110001101>; class ERETNC_MMR6_ENC : ERETNC_FM_MMR6<"eretnc">; +class GINVI_MMR6_ENC : POOL32A_GINV_FM_MMR6<"ginvi", 0b00>; +class GINVT_MMR6_ENC : POOL32A_GINV_FM_MMR6<"ginvt", 0b10>; class JALRC16_MMR6_ENC : POOL16C_JALRC_FM_MM16R6<0xb>; class JIALC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b100000>; class JIC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b101000>; @@ -826,6 +828,25 @@ class SDC2_SWC2_MMR6_DESC_BASE<string opstr, InstrItinClass itin> { class SDC2_MMR6_DESC : SDC2_SWC2_MMR6_DESC_BASE<"sdc2", II_SDC2>; class SWC2_MMR6_DESC : SDC2_SWC2_MMR6_DESC_BASE<"swc2", II_SWC2>; +class GINV_MMR6_DESC_BASE<string opstr, + RegisterOperand SrcRC, InstrItinClass Itin> { + dag InOperandList = (ins SrcRC:$rs, uimm2:$type); + dag OutOperandList = (outs); + string AsmString = !strconcat(opstr, "\t$rs, $type"); + list<dag> Pattern = []; + Format f = FrmFR; + string BaseOpcode = opstr; + InstrItinClass Itinerary = Itin; +} + +class GINVI_MMR6_DESC : GINV_MMR6_DESC_BASE<"ginvi", GPR32Opnd, + II_GINVI> { + dag InOperandList = (ins GPR32Opnd:$rs); + string AsmString = "ginvi\t$rs"; +} +class GINVT_MMR6_DESC : GINV_MMR6_DESC_BASE<"ginvt", GPR32Opnd, + II_GINVT>; + /// Floating Point Instructions class FARITH_MMR6_DESC_BASE<string instr_asm, RegisterOperand RC, InstrItinClass Itin, bit isComm, @@ -1346,6 +1367,10 @@ def ERET_MMR6 : StdMMR6Rel, ERET_MMR6_DESC, ERET_MMR6_ENC, ISA_MICROMIPS32R6; def DERET_MMR6 : StdMMR6Rel, DERET_MMR6_DESC, DERET_MMR6_ENC, ISA_MICROMIPS32R6; def ERETNC_MMR6 : R6MMR6Rel, ERETNC_MMR6_DESC, ERETNC_MMR6_ENC, ISA_MICROMIPS32R6; +def GINVI_MMR6 : R6MMR6Rel, GINVI_MMR6_ENC, GINVI_MMR6_DESC, + ISA_MICROMIPS32R6, ASE_GINV; +def GINVT_MMR6 : R6MMR6Rel, GINVT_MMR6_ENC, GINVT_MMR6_DESC, + ISA_MICROMIPS32R6, ASE_GINV; def JALRC16_MMR6 : R6MMR6Rel, JALRC16_MMR6_DESC, JALRC16_MMR6_ENC, ISA_MICROMIPS32R6; def JIALC_MMR6 : R6MMR6Rel, JIALC_MMR6_ENC, JIALC_MMR6_DESC, ISA_MICROMIPS32R6; diff --git a/llvm/lib/Target/Mips/Mips.td b/llvm/lib/Target/Mips/Mips.td index 38559a9b2ad..2f3a1c399d3 100644 --- a/llvm/lib/Target/Mips/Mips.td +++ b/llvm/lib/Target/Mips/Mips.td @@ -182,6 +182,9 @@ def FeatureCRC : SubtargetFeature<"crc", "HasCRC", "true", "Mips R6 CRC ASE">; def FeatureVirt : SubtargetFeature<"virt", "HasVirt", "true", "Mips Virtualization ASE">; +def FeatureGINV : SubtargetFeature<"ginv", "HasGINV", "true", + "Mips Global Invalidate ASE">; + def FeatureMicroMips : SubtargetFeature<"micromips", "InMicroMipsMode", "true", "microMips mode">; diff --git a/llvm/lib/Target/Mips/Mips32r6InstrFormats.td b/llvm/lib/Target/Mips/Mips32r6InstrFormats.td index f34da308701..84f1760716e 100644 --- a/llvm/lib/Target/Mips/Mips32r6InstrFormats.td +++ b/llvm/lib/Target/Mips/Mips32r6InstrFormats.td @@ -591,3 +591,15 @@ class SPECIAL3_2R_SZ_CRC<bits<2> sz, bits<3> direction> : MipsR6Inst { string DecoderMethod = "DecodeCRC"; } + +class SPECIAL3_GINV<bits<2> ginv> : MipsR6Inst { + bits<5> rs; + bits<2> type_; + + let Inst{31-26} = OPGROUP_SPECIAL3.Value; + let Inst{25-21} = rs; + let Inst{20-10} = 0x0; + let Inst{9-8} = type_; + let Inst{7-6} = ginv; + let Inst{5-0} = 0b111101; +} diff --git a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td index 93bed9b5384..d71ee242cdf 100644 --- a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td @@ -197,6 +197,9 @@ class CRC32CB_ENC : SPECIAL3_2R_SZ_CRC<0,1>; class CRC32CH_ENC : SPECIAL3_2R_SZ_CRC<1,1>; class CRC32CW_ENC : SPECIAL3_2R_SZ_CRC<2,1>; +class GINVI_ENC : SPECIAL3_GINV<0>; +class GINVT_ENC : SPECIAL3_GINV<2>; + //===----------------------------------------------------------------------===// // // Instruction Multiclasses @@ -827,6 +830,22 @@ class CRC32CB_DESC : CRC_DESC_BASE<"crc32cb", GPR32Opnd, II_CRC32CB>; class CRC32CH_DESC : CRC_DESC_BASE<"crc32ch", GPR32Opnd, II_CRC32CH>; class CRC32CW_DESC : CRC_DESC_BASE<"crc32cw", GPR32Opnd, II_CRC32CW>; +class GINV_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin> : MipsR6Arch<instr_asm> { + dag OutOperandList = (outs); + dag InOperandList = (ins GPROpnd:$rs, uimm2:$type_); + string AsmString = !strconcat(instr_asm, "\t$rs, $type_"); + list<dag> Pattern = []; + InstrItinClass Itinerary = itin; + bit hasSideEffects = 1; +} + +class GINVI_DESC : GINV_DESC_BASE<"ginvi", GPR32Opnd, II_GINVI> { + dag InOperandList = (ins GPR32Opnd:$rs); + string AsmString = "ginvi\t$rs"; +} +class GINVT_DESC : GINV_DESC_BASE<"ginvt", GPR32Opnd, II_GINVT>; + //===----------------------------------------------------------------------===// // // Instruction Definitions @@ -955,6 +974,11 @@ let AdditionalPredicates = [NotInMicroMips] in { def CRC32CW : R6MMR6Rel, CRC32CW_ENC, CRC32CW_DESC, ISA_MIPS32R6, ASE_CRC; } +let AdditionalPredicates = [NotInMicroMips] in { + def GINVI : R6MMR6Rel, GINVI_ENC, GINVI_DESC, ISA_MIPS32R6, ASE_GINV; + def GINVT : R6MMR6Rel, GINVT_ENC, GINVT_DESC, ISA_MIPS32R6, ASE_GINV; +} + //===----------------------------------------------------------------------===// // // Instruction Aliases diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index cdcf997ff8e..2a7f5404e43 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -252,6 +252,8 @@ def HasCRC : Predicate<"Subtarget->hasCRC()">, AssemblerPredicate<"FeatureCRC">; def HasVirt : Predicate<"Subtarget->hasVirt()">, AssemblerPredicate<"FeatureVirt">; +def HasGINV : Predicate<"Subtarget->hasGINV()">, + AssemblerPredicate<"FeatureGINV">; // TODO: Add support for FPOpFusion::Standard def AllowFPOpFusion : Predicate<"TM.Options.AllowFPOpFusion ==" " FPOpFusion::Fast">; @@ -468,6 +470,10 @@ class ASE_VIRT { list <Predicate> ASEPredicate = [HasVirt]; } +class ASE_GINV { + list <Predicate> ASEPredicate = [HasGINV]; +} + // Class used for separating microMIPSr6 and microMIPS (r3) instruction. // It can be used only on instructions that doesn't inherit PredicateControl. class ISA_MICROMIPS_NOT_32R6 : PredicateControl { diff --git a/llvm/lib/Target/Mips/MipsSchedule.td b/llvm/lib/Target/Mips/MipsSchedule.td index e9f1cb7601c..64db815a0f4 100644 --- a/llvm/lib/Target/Mips/MipsSchedule.td +++ b/llvm/lib/Target/Mips/MipsSchedule.td @@ -130,6 +130,8 @@ def II_EVPE : InstrItinClass; def II_EXT : InstrItinClass; // Any EXT instruction def II_FLOOR : InstrItinClass; def II_FORK : InstrItinClass; +def II_GINVI : InstrItinClass; +def II_GINVT : InstrItinClass; def II_HYPCALL : InstrItinClass; def II_INS : InstrItinClass; // Any INS instruction def II_IndirectBranchPseudo : InstrItinClass; // Indirect branch pseudo. @@ -728,5 +730,7 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [ InstrItinData<II_TLBWI , [InstrStage<2, [ALU]>]>, InstrItinData<II_TLBWR , [InstrStage<2, [ALU]>]>, InstrItinData<II_DMFGC0 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_DMTGC0 , [InstrStage<2, [ALU]>]> + InstrItinData<II_DMTGC0 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_GINVI , [InstrStage<1, [ALU]>]>, + InstrItinData<II_GINVT , [InstrStage<1, [ALU]>]> ]>; diff --git a/llvm/lib/Target/Mips/MipsSubtarget.cpp b/llvm/lib/Target/Mips/MipsSubtarget.cpp index a4d159c411f..f71031c9cf6 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -79,7 +79,7 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, HasDSPR2(false), HasDSPR3(false), AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasSym32(false), HasEVA(false), DisableMadd4(false), HasMT(false), HasCRC(false), - HasVirt(false), UseIndirectJumpsHazard(false), + HasVirt(false), HasGINV(false), UseIndirectJumpsHazard(false), StackAlignOverride(StackAlignOverride), TM(TM), TargetTriple(TT), TSInfo(), InstrInfo( diff --git a/llvm/lib/Target/Mips/MipsSubtarget.h b/llvm/lib/Target/Mips/MipsSubtarget.h index 7aebfe1e74c..0504fc2c579 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/llvm/lib/Target/Mips/MipsSubtarget.h @@ -168,6 +168,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // HasVirt -- supports Virtualization ASE bool HasVirt; + // HasGINV -- supports R6 Global INValidate ASE + bool HasGINV; + // Use hazard variants of the jump register instructions for indirect // function calls and jump tables. bool UseIndirectJumpsHazard; @@ -294,6 +297,7 @@ public: bool hasMT() const { return HasMT; } bool hasCRC() const { return HasCRC; } bool hasVirt() const { return HasVirt; } + bool hasGINV() const { return HasGINV; } bool useIndirectJumpsHazard() const { return UseIndirectJumpsHazard && hasMips32r2(); } diff --git a/llvm/lib/Target/Mips/MipsTargetStreamer.h b/llvm/lib/Target/Mips/MipsTargetStreamer.h index f9714d2b439..a282366f6d4 100644 --- a/llvm/lib/Target/Mips/MipsTargetStreamer.h +++ b/llvm/lib/Target/Mips/MipsTargetStreamer.h @@ -46,6 +46,8 @@ public: virtual void emitDirectiveSetNoCRC(); virtual void emitDirectiveSetVirt(); virtual void emitDirectiveSetNoVirt(); + virtual void emitDirectiveSetGINV(); + virtual void emitDirectiveSetNoGINV(); virtual void emitDirectiveSetAt(); virtual void emitDirectiveSetAtWithArg(unsigned RegNo); virtual void emitDirectiveSetNoAt(); @@ -111,6 +113,8 @@ public: virtual void emitDirectiveModuleNoCRC(); virtual void emitDirectiveModuleVirt(); virtual void emitDirectiveModuleNoVirt(); + virtual void emitDirectiveModuleGINV(); + virtual void emitDirectiveModuleNoGINV(); void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, const MCSubtargetInfo *STI); @@ -225,6 +229,8 @@ public: void emitDirectiveSetNoCRC() override; void emitDirectiveSetVirt() override; void emitDirectiveSetNoVirt() override; + void emitDirectiveSetGINV() override; + void emitDirectiveSetNoGINV() override; void emitDirectiveSetAt() override; void emitDirectiveSetAtWithArg(unsigned RegNo) override; void emitDirectiveSetNoAt() override; @@ -294,6 +300,8 @@ public: void emitDirectiveModuleNoCRC() override; void emitDirectiveModuleVirt() override; void emitDirectiveModuleNoVirt() override; + void emitDirectiveModuleGINV() override; + void emitDirectiveModuleNoGINV() override; void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value) override; void emitDirectiveSetOddSPReg() override; void emitDirectiveSetNoOddSPReg() override; diff --git a/llvm/test/MC/Disassembler/Mips/ginv/valid-el.txt b/llvm/test/MC/Disassembler/Mips/ginv/valid-el.txt new file mode 100644 index 00000000000..4b8d6ddcd41 --- /dev/null +++ b/llvm/test/MC/Disassembler/Mips/ginv/valid-el.txt @@ -0,0 +1,5 @@ +# RUN: llvm-mc --disassemble %s -triple=mipsel-unknown-linux-gnu \ +# RUN: -mcpu=mips32r6 -mattr=+ginv | FileCheck %s + +0x3d 0x02 0x40 0x7c # CHECK: ginvi $2 +0xbd 0x02 0x40 0x7c # CHECK: ginvt $2, 2 diff --git a/llvm/test/MC/Disassembler/Mips/ginv/valid-micromips-el.txt b/llvm/test/MC/Disassembler/Mips/ginv/valid-micromips-el.txt new file mode 100644 index 00000000000..964934143c1 --- /dev/null +++ b/llvm/test/MC/Disassembler/Mips/ginv/valid-micromips-el.txt @@ -0,0 +1,5 @@ +# RUN: llvm-mc --disassemble %s -triple=mipsel-unknown-linux-gnu \ +# RUN: -mcpu=mips32r6 -mattr=+micromips,+ginv | FileCheck %s + +0x02 0x00 0x7c 0x65 # CHECK: ginvi $2 +0x02 0x00 0x7c 0x75 # CHECK: ginvt $2, 2 diff --git a/llvm/test/MC/Disassembler/Mips/ginv/valid-micromips.txt b/llvm/test/MC/Disassembler/Mips/ginv/valid-micromips.txt new file mode 100644 index 00000000000..f14406ae758 --- /dev/null +++ b/llvm/test/MC/Disassembler/Mips/ginv/valid-micromips.txt @@ -0,0 +1,5 @@ +# RUN: llvm-mc --disassemble %s -triple=mips-unknown-linux-gnu \ +# RUN: -mcpu=mips32r6 -mattr=+micromips,+ginv | FileCheck %s + +0x00 0x02 0x65 0x7c # CHECK: ginvi $2 +0x00 0x02 0x75 0x7c # CHECK: ginvt $2, 2 diff --git a/llvm/test/MC/Disassembler/Mips/ginv/valid.txt b/llvm/test/MC/Disassembler/Mips/ginv/valid.txt new file mode 100644 index 00000000000..570a540a917 --- /dev/null +++ b/llvm/test/MC/Disassembler/Mips/ginv/valid.txt @@ -0,0 +1,5 @@ +# RUN: llvm-mc --disassemble %s -triple=mips-unknown-linux-gnu \ +# RUN: -mcpu=mips32r6 -mattr=+ginv | FileCheck %s + +0x7c 0x40 0x02 0x3d # CHECK: ginvi $2 +0x7c 0x40 0x02 0xbd # CHECK: ginvt $2, 2 diff --git a/llvm/test/MC/Mips/ginv/invalid.s b/llvm/test/MC/Mips/ginv/invalid.s new file mode 100644 index 00000000000..4bc77891c4c --- /dev/null +++ b/llvm/test/MC/Mips/ginv/invalid.s @@ -0,0 +1,23 @@ +# Instructions that are invalid. +# +# RUN: not llvm-mc %s -arch=mips -mcpu=mips32r6 -mattr=+ginv 2>%t1 +# RUN: FileCheck %s < %t1 +# RUN: not llvm-mc %s -arch=mips64 -mcpu=mips64r6 -mattr=+ginv 2>%t1 +# RUN: FileCheck %s < %t1 +# RUN: not llvm-mc %s -arch=mips -mcpu=mips32r6 \ +# RUN: -mattr=+micromips,+ginv 2>%t1 +# RUN: FileCheck %s < %t1 + + ginvi # CHECK: :[[@LINE]]:3: error: too few operands for instruction + ginvi 0 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + ginvi $4, 0 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction + ginvi $4, $5 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction + ginvi 0($4) # CHECK: :[[@LINE]]:10: error: unexpected token in argument list + ginvt # CHECK: :[[@LINE]]:3: error: too few operands for instruction + ginvt 0 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + ginvt $4 # CHECK: :[[@LINE]]:3: error: too few operands for instruction + ginvt $4, $5 # CHECK: :[[@LINE]]:13: error: expected 2-bit unsigned immediate + ginvt $4, 4 # CHECK: :[[@LINE]]:13: error: expected 2-bit unsigned immediate + ginvt $4, -1 # CHECK: :[[@LINE]]:13: error: expected 2-bit unsigned immediate + ginvt $4, 0, 1 # CHECK: :[[@LINE]]:16: error: invalid operand for instruction + ginvt $4, 0($4) # CHECK: :[[@LINE]]:14: error: invalid operand for instruction diff --git a/llvm/test/MC/Mips/ginv/module-ginv.s b/llvm/test/MC/Mips/ginv/module-ginv.s new file mode 100644 index 00000000000..49f3aa5628e --- /dev/null +++ b/llvm/test/MC/Mips/ginv/module-ginv.s @@ -0,0 +1,22 @@ +# RUN: llvm-mc %s -triple=mips-unknown-linux-gnu -mcpu=mips32r6 | \ +# RUN: FileCheck %s -check-prefix=CHECK-ASM +# +# RUN: llvm-mc %s -triple=mips-unknown-linux-gnu -mcpu=mips32r6 \ +# RUN: -filetype=obj -o - | \ +# RUN: llvm-readobj -mips-abi-flags - | \ +# RUN: FileCheck %s -check-prefix=CHECK-OBJ + +# CHECK-ASM: .module ginv + +# Check if the MIPS.abiflags section was correctly emitted: +# CHECK-OBJ: MIPS ABI Flags { +# CHECK-OBJ: ASEs [ (0x20000) +# CHECK-OBJ: GINV (0x20000) +# CHECK-OBJ: } + + .module ginv + ginvi $4 + +# FIXME: Test should include gnu_attributes directive when implemented. +# An explicit .gnu_attribute must be checked against the effective +# command line options and any inconsistencies reported via a warning. diff --git a/llvm/test/MC/Mips/ginv/module-noginv.s b/llvm/test/MC/Mips/ginv/module-noginv.s new file mode 100644 index 00000000000..86edb03c80a --- /dev/null +++ b/llvm/test/MC/Mips/ginv/module-noginv.s @@ -0,0 +1,21 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32r6 -mattr=+ginv | \ +# RUN: FileCheck %s -check-prefix=CHECK-ASM +# +# RUN: llvm-mc %s -arch=mips -mcpu=mips32r6 -filetype=obj -o - -mattr=+ginv | \ +# RUN: llvm-readobj -mips-abi-flags - | \ +# RUN: FileCheck %s -check-prefix=CHECK-OBJ + +# CHECK-ASM: .module noginv + +# Check that MIPS.abiflags has no GINV flag. +# CHECK-OBJ: MIPS ABI Flags { +# CHECK-OBJ: ASEs [ (0x0) +# CHECK-OBJ-NOT: ASEs [ (0x20000) +# CHECK-OBJ-NOT: GINV (0x20000) +# CHECK-OBJ: } + + .module noginv + +# FIXME: Test should include gnu_attributes directive when implemented. +# An explicit .gnu_attribute must be checked against the effective +# command line options and any inconsistencies reported via a warning. diff --git a/llvm/test/MC/Mips/ginv/set-ginv-directive.s b/llvm/test/MC/Mips/ginv/set-ginv-directive.s new file mode 100644 index 00000000000..1f9e787d37a --- /dev/null +++ b/llvm/test/MC/Mips/ginv/set-ginv-directive.s @@ -0,0 +1,7 @@ +# RUN: llvm-mc %s -triple=mips-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips32r6 -mattr=+ginv | FileCheck %s +# RUN: llvm-mc %s -triple=mips64-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips64r6 -mattr=+ginv | FileCheck %s + + .set ginv + ginvi $4 # CHECK: ginvi $4 # encoding: [0x7c,0x80,0x00,0x3d] diff --git a/llvm/test/MC/Mips/ginv/set-noginv-directive.s b/llvm/test/MC/Mips/ginv/set-noginv-directive.s new file mode 100644 index 00000000000..dad40db154c --- /dev/null +++ b/llvm/test/MC/Mips/ginv/set-noginv-directive.s @@ -0,0 +1,9 @@ +# RUN: not llvm-mc %s -triple=mips-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips32r6 -mattr=+ginv 2>%t1 +# RUN: FileCheck %s < %t1 +# RUN: not llvm-mc %s -triple=mips64-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips64r6 -mattr=+ginv 2>%t1 +# RUN: FileCheck %s < %t1 + + .set noginv + ginvi $4, 2 # CHECK: instruction requires a CPU feature not currently enabled diff --git a/llvm/test/MC/Mips/ginv/valid-micromips.s b/llvm/test/MC/Mips/ginv/valid-micromips.s new file mode 100644 index 00000000000..061b123ebb1 --- /dev/null +++ b/llvm/test/MC/Mips/ginv/valid-micromips.s @@ -0,0 +1,5 @@ +# RUN: llvm-mc %s -triple=mips-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips32r6 -mattr=+micromips,+ginv | FileCheck %s + + ginvi $4 # CHECK: ginvi $4 # encoding: [0x00,0x04,0x61,0x7c] + ginvt $4, 2 # CHECK: ginvt $4, 2 # encoding: [0x00,0x04,0x75,0x7c] diff --git a/llvm/test/MC/Mips/ginv/valid.s b/llvm/test/MC/Mips/ginv/valid.s new file mode 100644 index 00000000000..d80daaad8d3 --- /dev/null +++ b/llvm/test/MC/Mips/ginv/valid.s @@ -0,0 +1,7 @@ +# RUN: llvm-mc %s -triple=mips-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips32r6 -mattr=+ginv | FileCheck %s +# RUN: llvm-mc %s -triple=mips64-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips64r6 -mattr=+ginv | FileCheck %s + + ginvi $4 # CHECK: ginvi $4 # encoding: [0x7c,0x80,0x00,0x3d] + ginvt $4, 2 # CHECK: ginvt $4, 2 # encoding: [0x7c,0x80,0x02,0xbd] diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 32ab126d8d5..6ca28e273cc 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -2233,6 +2233,7 @@ static const EnumEntry<unsigned> ElfMipsASEFlags[] = { {"microMIPS", Mips::AFL_ASE_MICROMIPS}, {"XPA", Mips::AFL_ASE_XPA}, {"CRC", Mips::AFL_ASE_CRC}, + {"GINV", Mips::AFL_ASE_GINV}, }; static const EnumEntry<unsigned> ElfMipsFpABIType[] = { |