summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Support/MipsABIFlags.h3
-rw-r--r--llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp70
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h2
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp22
-rw-r--r--llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td17
-rw-r--r--llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td25
-rw-r--r--llvm/lib/Target/Mips/Mips.td3
-rw-r--r--llvm/lib/Target/Mips/Mips32r6InstrFormats.td12
-rw-r--r--llvm/lib/Target/Mips/Mips32r6InstrInfo.td24
-rw-r--r--llvm/lib/Target/Mips/MipsInstrInfo.td6
-rw-r--r--llvm/lib/Target/Mips/MipsSchedule.td6
-rw-r--r--llvm/lib/Target/Mips/MipsSubtarget.cpp2
-rw-r--r--llvm/lib/Target/Mips/MipsSubtarget.h4
-rw-r--r--llvm/lib/Target/Mips/MipsTargetStreamer.h8
-rw-r--r--llvm/test/MC/Disassembler/Mips/ginv/valid-el.txt5
-rw-r--r--llvm/test/MC/Disassembler/Mips/ginv/valid-micromips-el.txt5
-rw-r--r--llvm/test/MC/Disassembler/Mips/ginv/valid-micromips.txt5
-rw-r--r--llvm/test/MC/Disassembler/Mips/ginv/valid.txt5
-rw-r--r--llvm/test/MC/Mips/ginv/invalid.s23
-rw-r--r--llvm/test/MC/Mips/ginv/module-ginv.s22
-rw-r--r--llvm/test/MC/Mips/ginv/module-noginv.s21
-rw-r--r--llvm/test/MC/Mips/ginv/set-ginv-directive.s7
-rw-r--r--llvm/test/MC/Mips/ginv/set-noginv-directive.s9
-rw-r--r--llvm/test/MC/Mips/ginv/valid-micromips.s5
-rw-r--r--llvm/test/MC/Mips/ginv/valid.s7
-rw-r--r--llvm/tools/llvm-readobj/ELFDumper.cpp1
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[] = {
OpenPOWER on IntegriCloud