Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -349,6 +349,7 @@ bool parseSetMtDirective(); bool parseSetNoMtDirective(); bool parseSetNoCRCDirective(); + bool parseSetNoVirtDirective(); bool parseSetAssignment(); @@ -649,6 +650,10 @@ return getSTI().getFeatureBits()[Mips::FeatureCRC]; } + bool hasVirt() const { + return getSTI().getFeatureBits()[Mips::FeatureVirt]; + } + /// Warn if RegIndex is the same as the current AT. void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc); @@ -6694,6 +6699,23 @@ return false; } +bool MipsAsmParser::parseSetNoVirtDirective() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); // Eat "novirt". + + // 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::FeatureVirt, "virt"); + + getTargetStreamer().emitDirectiveSetNoVirt(); + Parser.Lex(); // Consume the EndOfStatement. + return false; +} + bool MipsAsmParser::parseSetPopDirective() { MCAsmParser &Parser = getParser(); SMLoc Loc = getLexer().getLoc(); @@ -6919,6 +6941,10 @@ setFeatureBits(Mips::FeatureCRC, "crc"); getTargetStreamer().emitDirectiveSetCRC(); break; + case Mips::FeatureVirt: + setFeatureBits(Mips::FeatureVirt, "virt"); + getTargetStreamer().emitDirectiveSetVirt(); + break; } return false; } @@ -7227,6 +7253,10 @@ return parseSetFeature(Mips::FeatureCRC); } else if (Tok.getString() == "nocrc") { return parseSetNoCRCDirective(); + } else if (Tok.getString() == "virt") { + return parseSetFeature(Mips::FeatureVirt); + } else if (Tok.getString() == "novirt") { + return parseSetNoVirtDirective(); } else { // It is just an identifier, look for an assignment. parseSetAssignment(); @@ -7475,6 +7505,8 @@ /// ::= .module mt /// ::= .module crc /// ::= .module nocrc +/// ::= .module virt +/// ::= .module novirt bool MipsAsmParser::parseDirectiveModule() { MCAsmParser &Parser = getParser(); MCAsmLexer &Lexer = getLexer(); @@ -7631,6 +7663,44 @@ } return false; // parseDirectiveModule has finished successfully. + } else if (Option == "virt") { + setModuleFeatureBits(Mips::FeatureVirt, "virt"); + + // 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().emitDirectiveModuleVirt(); + + // 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 == "novirt") { + clearModuleFeatureBits(Mips::FeatureVirt, "virt"); + + // 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().emitDirectiveModuleNoVirt(); + + // 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."); } Index: lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h +++ lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h @@ -163,6 +163,8 @@ ASESet |= Mips::AFL_ASE_MT; if (P.hasCRC()) ASESet |= Mips::AFL_ASE_CRC; + if (P.hasVirt()) + ASESet |= Mips::AFL_ASE_VIRT; } template Index: lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -54,6 +54,8 @@ void MipsTargetStreamer::emitDirectiveSetNoMt() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetCRC() {} void MipsTargetStreamer::emitDirectiveSetNoCRC() {} +void MipsTargetStreamer::emitDirectiveSetVirt() {} +void MipsTargetStreamer::emitDirectiveSetNoVirt() {} void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) { forbidModuleDirective(); @@ -126,6 +128,8 @@ void MipsTargetStreamer::emitDirectiveModuleMT() {} void MipsTargetStreamer::emitDirectiveModuleCRC() {} void MipsTargetStreamer::emitDirectiveModuleNoCRC() {} +void MipsTargetStreamer::emitDirectiveModuleVirt() {} +void MipsTargetStreamer::emitDirectiveModuleNoVirt() {} void MipsTargetStreamer::emitDirectiveSetFp( MipsABIFlagsSection::FpABIKind Value) { forbidModuleDirective(); @@ -435,6 +439,16 @@ MipsTargetStreamer::emitDirectiveSetNoCRC(); } +void MipsTargetAsmStreamer::emitDirectiveSetVirt() { + OS << "\t.set\tvirt\n"; + MipsTargetStreamer::emitDirectiveSetVirt(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetNoVirt() { + OS << "\t.set\tnovirt\n"; + MipsTargetStreamer::emitDirectiveSetNoVirt(); +} + void MipsTargetAsmStreamer::emitDirectiveSetAt() { OS << "\t.set\tat\n"; MipsTargetStreamer::emitDirectiveSetAt(); @@ -716,6 +730,14 @@ OS << "\t.module\tnocrc\n"; } +void MipsTargetAsmStreamer::emitDirectiveModuleVirt() { + OS << "\t.module\tvirt\n"; +} + +void MipsTargetAsmStreamer::emitDirectiveModuleNoVirt() { + OS << "\t.module\tnovirt\n"; +} + // This part is for ELF object output. MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI) Index: lib/Target/Mips/MicroMips32r6InstrFormats.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrFormats.td +++ lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -876,6 +876,18 @@ let Inst{8-0} = funct; } +class POOL32A_HYPCALL_FM_MMR6 + : MMR6Arch, MipsR6Inst { + bits<32> Inst; + + bits<10> code_; + + let Inst{31-26} = 0x0; + let Inst{25-16} = code_; + let Inst{15-6} = 0b1100001101; + let Inst{5-0} = 0b111100; +} + class POOL32A_TLBINV_FM_MMR6 funct> : MMR6Arch, MipsR6Inst { bits<32> Inst; Index: lib/Target/Mips/MicroMips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrInfo.td +++ lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -106,6 +106,7 @@ 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 HYPCALL_MMR6_ENC : POOL32A_HYPCALL_FM_MMR6<"hypcall">; 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>; @@ -116,6 +117,8 @@ class LWPC_MMR6_ENC : PCREL19_FM_MMR6<0b01>; class LWM16_MMR6_ENC : POOL16C_LWM_SWM_FM_MM16R6<0x2>; class MFC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mfc0", 0b00011, 0b111100>; +class MFGC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mfgc0", 0b10011, 0b111100>; +class MFHGC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mfhgc0", 0b10011, 0b110100>; class MFC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"mfc1", 0b10000000>; class MFC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mfc2", 0b0100110100>; class MFHC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mfhc0", 0b00011, 0b110100>; @@ -131,6 +134,8 @@ class MTC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mtc2", 0b0101110100>; class MTHC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mthc0", 0b01011, 0b110100>; class MTHC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mthc2", 0b1001110100>; +class MTGC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mtgc0", 0b11011, 0b111100>; +class MTHGC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mthgc0", 0b11011, 0b110100>; class NOR_MMR6_ENC : ARITH_FM_MMR6<"nor", 0x2d0>; class OR_MMR6_ENC : ARITH_FM_MMR6<"or", 0x290>; class ORI_MMR6_ENC : ADDI_FM_MMR6<"ori", 0x14>; @@ -221,6 +226,12 @@ class XOR16_MMR6_ENC : POOL16C_OR16_XOR16_FM_MMR6<0b1000>; class TLBINV_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbinv", 0x10d>; class TLBINVF_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbinvf", 0x14d>; +class TLBGINV_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbginvf", 0x105>; +class TLBGINVF_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbginvf", 0x145>; +class TLBGP_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbgp", 0x5>; +class TLBGR_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbgr", 0x45>; +class TLBGWI_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbgwi", 0x85>; +class TLBGWR_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbgwr", 0xc5>; class DVP_MMR6_ENC : POOL32A_DVPEVP_FM_MMR6<"dvp", 0b0001100101>; class EVP_MMR6_ENC : POOL32A_DVPEVP_FM_MMR6<"evp", 0b0011100101>; class BC1EQZC_MMR6_ENC : POOL32I_BRANCH_COP_1_2_FM_MMR6<"bc1eqzc", 0b01000>; @@ -778,6 +789,27 @@ class MFHC2_MMR6_DESC : MFC2_MMR6_DESC_BASE<"mfhc2", GPR32Opnd, COP2Opnd, II_MFC2>; +class MFGC0_MMR6_DESC : MFC0_MMR6_DESC_BASE<"mfgc0", GPR32Opnd, COP0Opnd, + II_MFGC0>; +class MTGC0_MMR6_DESC : MTC0_MMR6_DESC_BASE<"mtgc0", COP0Opnd, GPR32Opnd, + II_MTGC0>; +class MFHGC0_MMR6_DESC : MFC0_MMR6_DESC_BASE<"mfhgc0", GPR32Opnd, COP0Opnd, + II_MFHGC0>; +class MTHGC0_MMR6_DESC : MTC0_MMR6_DESC_BASE<"mthgc0", COP0Opnd, GPR32Opnd, + II_MTHGC0>; + +class HYPCALL_MMR6_DESC_BASE { + dag InOperandList = (ins uimm10:$code_); + dag OutOperandList = (outs); + string AsmString = !strconcat(opstr, "\t$code_"); + list Pattern = []; + Format f = FrmOther; + string BaseOpcode = opstr; + InstrItinClass Itinerary = II_HYPCALL; +} + +class HYPCALL_MMR6_DESC : HYPCALL_MMR6_DESC_BASE<"hypcall">; + class LDC1_D64_MMR6_DESC : MipsR6Inst, HARDFLOAT, FGR_64 { dag InOperandList = (ins mem_mm_16:$addr); dag OutOperandList = (outs FGR64Opnd:$ft); @@ -1211,6 +1243,12 @@ class TLBINV_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbinv", II_TLBINV>; class TLBINVF_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbinvf", II_TLBINVF>; +class TLBGINV_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbginv", II_TLBGINV>; +class TLBGINVF_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbginvf", II_TLBGINVF>; +class TLBGP_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbgp", II_TLBGP>; +class TLBGR_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbgr", II_TLBGR>; +class TLBGWI_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbgwi", II_TLBGWI>; +class TLBGWR_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbgwr", II_TLBGWR>; class DVPEVP_MMR6_DESC_BASE { dag OutOperandList = (outs GPR32Opnd:$rs); @@ -1350,6 +1388,8 @@ 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 HYPCALL_MMR6 : StdMMR6Rel, HYPCALL_MMR6_ENC, HYPCALL_MMR6_DESC, + ISA_MICROMIPS32R6, ASE_VIRT; def JALRC16_MMR6 : R6MMR6Rel, JALRC16_MMR6_DESC, JALRC16_MMR6_ENC, ISA_MICROMIPS32R6; def JIALC_MMR6 : R6MMR6Rel, JIALC_MMR6_ENC, JIALC_MMR6_DESC, ISA_MICROMIPS32R6; @@ -1367,6 +1407,10 @@ def MTHC0_MMR6 : R6MMR6Rel, MTHC0_MMR6_ENC, MTHC0_MMR6_DESC, ISA_MICROMIPS32R6; def MTHC2_MMR6 : StdMMR6Rel, MTHC2_MMR6_ENC, MTHC2_MMR6_DESC, ISA_MICROMIPS32R6; def MFC0_MMR6 : StdMMR6Rel, MFC0_MMR6_ENC, MFC0_MMR6_DESC, ISA_MICROMIPS32R6; +def MFGC0_MMR6 : StdMMR6Rel, MFGC0_MMR6_ENC, MFGC0_MMR6_DESC, ISA_MICROMIPS32R6, ASE_VIRT; +def MTGC0_MMR6 : StdMMR6Rel, MTGC0_MMR6_ENC, MTGC0_MMR6_DESC, ISA_MICROMIPS32R6, ASE_VIRT; +def MFHGC0_MMR6 : StdMMR6Rel, MFHGC0_MMR6_ENC, MFHGC0_MMR6_DESC, ISA_MICROMIPS32R6, ASE_VIRT; +def MTHGC0_MMR6 : StdMMR6Rel, MTHGC0_MMR6_ENC, MTHGC0_MMR6_DESC, ISA_MICROMIPS32R6, ASE_VIRT; def MFC1_MMR6 : StdMMR6Rel, MFC1_MMR6_DESC, MFC1_MMR6_ENC, ISA_MICROMIPS32R6; def MFC2_MMR6 : StdMMR6Rel, MFC2_MMR6_ENC, MFC2_MMR6_DESC, ISA_MICROMIPS32R6; def MFHC0_MMR6 : R6MMR6Rel, MFHC0_MMR6_ENC, MFHC0_MMR6_DESC, ISA_MICROMIPS32R6; @@ -1552,6 +1596,18 @@ ISA_MICROMIPS32R6; def TLBINVF_MMR6 : StdMMR6Rel, TLBINVF_MMR6_ENC, TLBINVF_MMR6_DESC, ISA_MICROMIPS32R6; +def TLBGINV_MMR6 : StdMMR6Rel, TLBGINV_MMR6_ENC, TLBGINV_MMR6_DESC, + ISA_MICROMIPS32R6, ASE_VIRT; +def TLBGINVF_MMR6 : StdMMR6Rel, TLBGINVF_MMR6_ENC, TLBGINVF_MMR6_DESC, + ISA_MICROMIPS32R6, ASE_VIRT; +def TLBGP_MMR6 : StdMMR6Rel, TLBGP_MMR6_ENC, TLBGP_MMR6_DESC, + ISA_MICROMIPS32R6, ASE_VIRT; +def TLBGR_MMR6 : StdMMR6Rel, TLBGR_MMR6_ENC, TLBGR_MMR6_DESC, + ISA_MICROMIPS32R6, ASE_VIRT; +def TLBGWI_MMR6 : StdMMR6Rel, TLBGWI_MMR6_ENC, TLBGWI_MMR6_DESC, + ISA_MICROMIPS32R6, ASE_VIRT; +def TLBGWR_MMR6 : StdMMR6Rel, TLBGWR_MMR6_ENC, TLBGWR_MMR6_DESC, + ISA_MICROMIPS32R6, ASE_VIRT; def DVP_MMR6 : R6MMR6Rel, DVP_MMR6_ENC, DVP_MMR6_DESC, ISA_MICROMIPS32R6; def EVP_MMR6 : R6MMR6Rel, EVP_MMR6_ENC, EVP_MMR6_DESC, ISA_MICROMIPS32R6; def BC1EQZC_MMR6 : R6MMR6Rel, BC1EQZC_MMR6_DESC, BC1EQZC_MMR6_ENC, @@ -1631,6 +1687,20 @@ def : MipsInstAlias<"mfhc0 $rt, $rs", (MFHC0_MMR6 GPR32Opnd:$rt, COP0Opnd:$rs, 0), 0>, ISA_MICROMIPS32R6; +def : MipsInstAlias<"mfgc0 $rt, $rs", + (MFGC0_MMR6 GPR32Opnd:$rt, COP0Opnd:$rs, 0), 0>, + ISA_MICROMIPS32R6, ASE_VIRT; +def : MipsInstAlias<"mfhgc0 $rt, $rs", + (MFHGC0_MMR6 GPR32Opnd:$rt, COP0Opnd:$rs, 0), 0>, + ISA_MICROMIPS32R6, ASE_VIRT; +def : MipsInstAlias<"mtgc0 $rt, $rs", + (MTGC0_MMR6 COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>, + ISA_MICROMIPS32R6, ASE_VIRT; +def : MipsInstAlias<"mthgc0 $rt, $rs", + (MTHGC0_MMR6 COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>, + ISA_MICROMIPS32R6, ASE_VIRT; +def : MipsInstAlias<"hypcall", (HYPCALL_MMR6 0), 1>, + ISA_MICROMIPS32R6, ASE_VIRT; def : MipsInstAlias<"jalrc.hb $rs", (JALRC_HB_MMR6 RA, GPR32Opnd:$rs), 1>, ISA_MICROMIPS32R6; def : MipsInstAlias<"dvp", (DVP_MMR6 ZERO), 0>, ISA_MICROMIPS32R6; Index: lib/Target/Mips/Mips.td =================================================================== --- lib/Target/Mips/Mips.td +++ lib/Target/Mips/Mips.td @@ -178,6 +178,9 @@ def FeatureCRC : SubtargetFeature<"crc", "HasCRC", "true", "Mips R6 CRC ASE">; +def FeatureVirt : SubtargetFeature<"virt", "HasVirt", "true", + "Mips Virtualization ASE">; + def FeatureMicroMips : SubtargetFeature<"micromips", "InMicroMipsMode", "true", "microMips mode">; Index: lib/Target/Mips/Mips64InstrInfo.td =================================================================== --- lib/Target/Mips/Mips64InstrInfo.td +++ lib/Target/Mips/Mips64InstrInfo.td @@ -545,16 +545,23 @@ /// Move between CPU and coprocessor registers let DecoderNamespace = "Mips64", Predicates = [HasMips64] in { -def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd, COP0Opnd, II_DMFC0>, MFC3OP_FM<0x10, 1>, - ISA_MIPS3; -def DMTC0 : MTC3OP<"dmtc0", COP0Opnd, GPR64Opnd, II_DMTC0>, MFC3OP_FM<0x10, 5>, - ISA_MIPS3; -def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd, COP2Opnd, II_DMFC2>, MFC3OP_FM<0x12, 1>, - ISA_MIPS3; -def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GPR64Opnd, II_DMTC2>, MFC3OP_FM<0x12, 5>, - ISA_MIPS3; +def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd, COP0Opnd, II_DMFC0>, + MFC3OP_FM<0x10, 1, 0>, ISA_MIPS3; +def DMTC0 : MTC3OP<"dmtc0", COP0Opnd, GPR64Opnd, II_DMTC0>, + MFC3OP_FM<0x10, 5, 0>, ISA_MIPS3; +def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd, COP2Opnd, II_DMFC2>, + MFC3OP_FM<0x12, 1, 0>, ISA_MIPS3; +def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GPR64Opnd, II_DMTC2>, + MFC3OP_FM<0x12, 5, 0>, ISA_MIPS3; } +/// Move between CPU and guest coprocessor registers (Virtualization ASE) +let DecoderNamespace = "Mips64", Predicates = [HasMips64] in { + def DMFGC0 : MFC3OP<"dmfgc0", GPR64Opnd, COP0Opnd, II_DMFGC0>, + MFC3OP_FM<0x10, 3, 1>, ISA_MIPS64, ASE_VIRT; + def DMTGC0 : MFC3OP<"dmtgc0", COP0Opnd, GPR64Opnd, II_DMTGC0>, + MFC3OP_FM<0x10, 3, 3>, ISA_MIPS64, ASE_VIRT; +} let AdditionalPredicates = [UseIndirectJumpsHazard] in def JALRHB64Pseudo : JumpLinkRegPseudo; @@ -873,6 +880,12 @@ (DMTC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>; def : MipsInstAlias<"dmfc0 $rt, $rd", (DMFC0 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>; + def : MipsInstAlias<"dmfgc0 $rt, $rd", + (DMFGC0 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>, + ISA_MIPS64, ASE_VIRT; + def : MipsInstAlias<"dmtgc0 $rt, $rd", + (DMTGC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>, + ISA_MIPS64, ASE_VIRT; } def : MipsInstAlias<"dmfc2 $rt, $rd", (DMFC2 GPR64Opnd:$rt, COP2Opnd:$rd, 0), 0>; def : MipsInstAlias<"dmtc2 $rt, $rd", (DMTC2 COP2Opnd:$rd, GPR64Opnd:$rt, 0), 0>; Index: lib/Target/Mips/MipsEVAInstrFormats.td =================================================================== --- lib/Target/Mips/MipsEVAInstrFormats.td +++ lib/Target/Mips/MipsEVAInstrFormats.td @@ -52,6 +52,15 @@ def OPGROUP_COP0_TLB : OPGROUP<0b010000>; +// TLBG* from Virtualization ASE +def OPCODE6_TLBGINV : OPCODE6<0b001011>; +def OPCODE6_TLBGINVF : OPCODE6<0b001100>; +def OPCODE6_TLBGP : OPCODE6<0b010000>; +def OPCODE6_TLBGR : OPCODE6<0b001001>; +def OPCODE6_TLBGWI : OPCODE6<0b001010>; +def OPCODE6_TLBGWR : OPCODE6<0b001110>; +def OPCODE6_HYPCALL : OPCODE6<0b101000>; + //===----------------------------------------------------------------------===// // // Encoding Formats @@ -82,3 +91,15 @@ let Inst{24-6} = 0; let Inst{5-0} = Operation.Value; } + +class HYPCALL_FM : StdArch +{ + bits<10> code_; + + bits<32> Inst; + + let Inst{31-26} = OPGROUP_COP0_TLB.Value; + let Inst{25} = 1; // CO + let Inst{20-11} = code_; + let Inst{5-0} = Operation.Value; +} Index: lib/Target/Mips/MipsEVAInstrInfo.td =================================================================== --- lib/Target/Mips/MipsEVAInstrInfo.td +++ lib/Target/Mips/MipsEVAInstrInfo.td @@ -44,6 +44,14 @@ class CACHEE_ENC : SPECIAL3_EVA_LOAD_STORE_FM; class PREFE_ENC : SPECIAL3_EVA_LOAD_STORE_FM; +// Virtualization ASE +class TLBGINV_ENC : TLB_FM; +class TLBGINVF_ENC : TLB_FM; +class TLBGP_ENC : TLB_FM; +class TLBGR_ENC : TLB_FM; +class TLBGWI_ENC : TLB_FM; +class TLBGWR_ENC : TLB_FM; + //===----------------------------------------------------------------------===// // // Instruction descriptions @@ -156,8 +164,14 @@ InstrItinClass Itinerary = itin; } -class TLBINV_DESC : TLB_DESC_BASE<"tlbinv", II_TLBINV>; -class TLBINVF_DESC : TLB_DESC_BASE<"tlbinvf", II_TLBINVF>; +class TLBINV_DESC : TLB_DESC_BASE<"tlbinv", II_TLBINV>; +class TLBINVF_DESC : TLB_DESC_BASE<"tlbinvf", II_TLBINVF>; +class TLBGINV_DESC : TLB_DESC_BASE<"tlbginv", II_TLBGINV>; +class TLBGINVF_DESC : TLB_DESC_BASE<"tlbginvf", II_TLBGINVF>; +class TLBGP_DESC : TLB_DESC_BASE<"tlbgp", II_TLBGP>; +class TLBGR_DESC : TLB_DESC_BASE<"tlbgr", II_TLBGR>; +class TLBGWI_DESC : TLB_DESC_BASE<"tlbgwi", II_TLBGWI>; +class TLBGWR_DESC : TLB_DESC_BASE<"tlbgwr", II_TLBGWR>; class CACHEE_DESC_BASE { @@ -173,6 +187,10 @@ class CACHEE_DESC : CACHEE_DESC_BASE<"cachee", mem_simm9, II_CACHEE>; class PREFE_DESC : CACHEE_DESC_BASE<"prefe", mem_simm9, II_PREFE>; +class HYPCALL_FT : + InstSE<(outs), (ins uimm10:$code_), + !strconcat(opstr, "\t$code_"), [], II_HYPCALL, FrmOther, opstr>; + //===----------------------------------------------------------------------===// // // Instruction definitions @@ -207,4 +225,16 @@ /// EVA versions of cache and pref def CACHEE : MMRel, CACHEE_ENC, CACHEE_DESC, ISA_MIPS32R2, ASE_EVA; def PREFE : MMRel, PREFE_ENC, PREFE_DESC, ISA_MIPS32R2, ASE_EVA; + + /// Virtualization ASE + def TLBGINV : TLBGINV_ENC, TLBGINV_DESC, ISA_MIPS32, ASE_VIRT; + def TLBGINVF : TLBGINVF_ENC, TLBGINVF_DESC, ISA_MIPS32, ASE_VIRT; + def TLBGP : TLBGP_ENC, TLBGP_DESC, ISA_MIPS32, ASE_VIRT; + def TLBGR : TLBGR_ENC, TLBGR_DESC, ISA_MIPS32, ASE_VIRT; + def TLBGWI : TLBGWI_ENC, TLBGWI_DESC, ISA_MIPS32, ASE_VIRT; + def TLBGWR : TLBGWR_ENC, TLBGWR_DESC, ISA_MIPS32, ASE_VIRT; + def HYPCALL : MMRel, StdMMR6Rel, HYPCALL_FT<"hypcall">, + HYPCALL_FM, ISA_MIPS32, ASE_VIRT; + + def : MipsInstAlias<"hypcall", (HYPCALL 0), 1>, ISA_MIPS32, ASE_VIRT; } Index: lib/Target/Mips/MipsInstrFormats.td =================================================================== --- lib/Target/Mips/MipsInstrFormats.td +++ lib/Target/Mips/MipsInstrFormats.td @@ -220,9 +220,9 @@ } //===----------------------------------------------------------------------===// -// MFC instruction class in Mips : <|op|mf|rt|rd|0000000|sel|> +// MFC instruction class in Mips : <|op|mf|rt|rd|gst|0000|sel|> //===----------------------------------------------------------------------===// -class MFC3OP_FM op, bits<5> mfmt> +class MFC3OP_FM op, bits<5> mfmt, bits<3> guest> { bits<5> rt; bits<5> rd; @@ -234,7 +234,8 @@ let Inst{25-21} = mfmt; let Inst{20-16} = rt; let Inst{15-11} = rd; - let Inst{10-3} = 0; + let Inst{10-8} = guest; + let Inst{7-3} = 0; let Inst{2-0} = sel; } Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -248,6 +248,8 @@ AssemblerPredicate<"!FeatureUseIndirectJumpsHazard">; def HasCRC : Predicate<"Subtarget->hasCRC()">, AssemblerPredicate<"FeatureCRC">; +def HasVirt : Predicate<"Subtarget->hasVirt()">, + AssemblerPredicate<"FeatureVirt">; //===----------------------------------------------------------------------===// // Mips GPR size adjectives. // They are mutually exclusive. @@ -449,6 +451,10 @@ list ASEPredicate = [HasCRC]; } +class ASE_VIRT { + list ASEPredicate = [HasVirt]; +} + // 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 { @@ -2312,14 +2318,26 @@ } /// Move Control Registers From/To CPU Registers let AdditionalPredicates = [NotInMicroMips] in { - def MTC0 : MTC3OP<"mtc0", COP0Opnd, GPR32Opnd, II_MTC0>, MFC3OP_FM<0x10, 4>, - ISA_MIPS1; - def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd, II_MFC0>, MFC3OP_FM<0x10, 0>, - ISA_MIPS1; - def MFC2 : MFC3OP<"mfc2", GPR32Opnd, COP2Opnd, II_MFC2>, MFC3OP_FM<0x12, 0>, - ISA_MIPS1; - def MTC2 : MTC3OP<"mtc2", COP2Opnd, GPR32Opnd, II_MTC2>, MFC3OP_FM<0x12, 4>, - ISA_MIPS1; + def MTC0 : MTC3OP<"mtc0", COP0Opnd, GPR32Opnd, II_MTC0>, + MFC3OP_FM<0x10, 4, 0>, ISA_MIPS1; + def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd, II_MFC0>, + MFC3OP_FM<0x10, 0, 0>, ISA_MIPS1; + def MFC2 : MFC3OP<"mfc2", GPR32Opnd, COP2Opnd, II_MFC2>, + MFC3OP_FM<0x12, 0, 0>, ISA_MIPS1; + def MTC2 : MTC3OP<"mtc2", COP2Opnd, GPR32Opnd, II_MTC2>, + MFC3OP_FM<0x12, 4, 0>, ISA_MIPS1; +} + +/// Move Control Registers From/To Guest CPU Registers (Virtualization ASE) +let AdditionalPredicates = [NotInMicroMips] in { + def MFGC0 : MFC3OP<"mfgc0", GPR32Opnd, COP0Opnd, II_MFGC0>, + MFC3OP_FM<0x10, 3, 0>, ISA_MIPS32, ASE_VIRT; + def MTGC0 : MTC3OP<"mtgc0", COP0Opnd, GPR32Opnd, II_MFGC0>, + MFC3OP_FM<0x10, 3, 2>, ISA_MIPS32, ASE_VIRT; + def MFHGC0 : MFC3OP<"mfhgc0", GPR32Opnd, COP0Opnd, II_MFGC0>, + MFC3OP_FM<0x10, 3, 4>, ISA_MIPS32R5, ASE_VIRT; + def MTHGC0 : MTC3OP<"mthgc0", COP0Opnd, GPR32Opnd, II_MFGC0>, + MFC3OP_FM<0x10, 3, 6>, ISA_MIPS32R5, ASE_VIRT; } class Barrier : @@ -2565,6 +2583,20 @@ } def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>; def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>; +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsInstAlias<"mfgc0 $rt, $rd", + (MFGC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>, + ISA_MIPS32, ASE_VIRT; + def : MipsInstAlias<"mtgc0 $rt, $rd", + (MTGC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>, + ISA_MIPS32, ASE_VIRT; + def : MipsInstAlias<"mfhgc0 $rt, $rd", + (MFHGC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>, + ISA_MIPS32R5, ASE_VIRT; + def : MipsInstAlias<"mthgc0 $rt, $rd", + (MTHGC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>, + ISA_MIPS32R5, ASE_VIRT; +} def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, COP2Opnd:$rd, 0), 0>; def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 COP2Opnd:$rd, GPR32Opnd:$rt, 0), 0>; let AdditionalPredicates = [NotInMicroMips] in { Index: lib/Target/Mips/MipsSchedule.td =================================================================== --- lib/Target/Mips/MipsSchedule.td +++ lib/Target/Mips/MipsSchedule.td @@ -92,8 +92,10 @@ def II_DIV_D : InstrItinClass; def II_DIV_S : InstrItinClass; def II_DMFC0 : InstrItinClass; +def II_DMFGC0 : InstrItinClass; def II_DMT : InstrItinClass; def II_DMTC0 : InstrItinClass; +def II_DMTGC0 : InstrItinClass; def II_DMFC1 : InstrItinClass; def II_DMTC1 : InstrItinClass; def II_DMOD : InstrItinClass; @@ -128,6 +130,7 @@ def II_EXT : InstrItinClass; // Any EXT instruction def II_FLOOR : InstrItinClass; def II_FORK : InstrItinClass; +def II_HYPCALL : InstrItinClass; def II_INS : InstrItinClass; // Any INS instruction def II_IndirectBranchPseudo : InstrItinClass; // Indirect branch pseudo. def II_J : InstrItinClass; @@ -233,6 +236,8 @@ def II_MFC1 : InstrItinClass; def II_MFHC1 : InstrItinClass; def II_MFC2 : InstrItinClass; +def II_MFGC0 : InstrItinClass; +def II_MFHGC0 : InstrItinClass; def II_MFHI_MFLO : InstrItinClass; // mfhi and mflo def II_MFTR : InstrItinClass; def II_MOD : InstrItinClass; @@ -263,6 +268,8 @@ def II_MTC1 : InstrItinClass; def II_MTHC1 : InstrItinClass; def II_MTC2 : InstrItinClass; +def II_MTGC0 : InstrItinClass; +def II_MTHGC0 : InstrItinClass; def II_MTHI_MTLO : InstrItinClass; // mthi and mtlo def II_MTTR : InstrItinClass; def II_MUL : InstrItinClass; @@ -354,6 +361,12 @@ def II_PREFE : InstrItinClass; def II_LLE : InstrItinClass; def II_SCE : InstrItinClass; +def II_TLBGINV : InstrItinClass; +def II_TLBGINVF : InstrItinClass; +def II_TLBGP : InstrItinClass; +def II_TLBGR : InstrItinClass; +def II_TLBGWI : InstrItinClass; +def II_TLBGWR : InstrItinClass; def II_TLBINV : InstrItinClass; def II_TLBINVF : InstrItinClass; def II_WRPGPR : InstrItinClass; @@ -702,5 +715,18 @@ InstrItinData]>, InstrItinData]>, InstrItinData]>, - InstrItinData]> + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]> ]>; Index: lib/Target/Mips/MipsSubtarget.h =================================================================== --- lib/Target/Mips/MipsSubtarget.h +++ lib/Target/Mips/MipsSubtarget.h @@ -165,6 +165,9 @@ // HasCRC -- supports R6 CRC ASE bool HasCRC; + // HasVirt -- supports Virtualization ASE + bool HasVirt; + // Use hazard variants of the jump register instructions for indirect // function calls and jump tables. bool UseIndirectJumpsHazard; @@ -290,6 +293,7 @@ bool hasEVA() const { return HasEVA; } bool hasMT() const { return HasMT; } bool hasCRC() const { return HasCRC; } + bool hasVirt() const { return HasVirt; } bool useIndirectJumpsHazard() const { return UseIndirectJumpsHazard && hasMips32r2(); } Index: lib/Target/Mips/MipsSubtarget.cpp =================================================================== --- lib/Target/Mips/MipsSubtarget.cpp +++ lib/Target/Mips/MipsSubtarget.cpp @@ -79,7 +79,8 @@ 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), - UseIndirectJumpsHazard(false), StackAlignOverride(StackAlignOverride), + HasVirt(false), UseIndirectJumpsHazard(false), + StackAlignOverride(StackAlignOverride), TM(TM), TargetTriple(TT), TSInfo(), InstrInfo( MipsInstrInfo::create(initializeSubtargetDependencies(CPU, FS, TM))), Index: lib/Target/Mips/MipsTargetStreamer.h =================================================================== --- lib/Target/Mips/MipsTargetStreamer.h +++ lib/Target/Mips/MipsTargetStreamer.h @@ -44,6 +44,8 @@ virtual void emitDirectiveSetNoMt(); virtual void emitDirectiveSetCRC(); virtual void emitDirectiveSetNoCRC(); + virtual void emitDirectiveSetVirt(); + virtual void emitDirectiveSetNoVirt(); virtual void emitDirectiveSetAt(); virtual void emitDirectiveSetAtWithArg(unsigned RegNo); virtual void emitDirectiveSetNoAt(); @@ -107,6 +109,8 @@ virtual void emitDirectiveSetNoOddSPReg(); virtual void emitDirectiveModuleCRC(); virtual void emitDirectiveModuleNoCRC(); + virtual void emitDirectiveModuleVirt(); + virtual void emitDirectiveModuleNoVirt(); void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, const MCSubtargetInfo *STI); @@ -219,6 +223,8 @@ void emitDirectiveSetNoMt() override; void emitDirectiveSetCRC() override; void emitDirectiveSetNoCRC() override; + void emitDirectiveSetVirt() override; + void emitDirectiveSetNoVirt() override; void emitDirectiveSetAt() override; void emitDirectiveSetAtWithArg(unsigned RegNo) override; void emitDirectiveSetNoAt() override; @@ -286,6 +292,8 @@ void emitDirectiveModuleMT() override; void emitDirectiveModuleCRC() override; void emitDirectiveModuleNoCRC() override; + void emitDirectiveModuleVirt() override; + void emitDirectiveModuleNoVirt() override; void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value) override; void emitDirectiveSetOddSPReg() override; void emitDirectiveSetNoOddSPReg() override; Index: test/MC/Disassembler/Mips/virt/valid-32-el.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/Mips/virt/valid-32-el.txt @@ -0,0 +1,15 @@ +# RUN: llvm-mc --disassemble %s -triple=mipsel-unknown-linux-gnu \ +# RUN: -mcpu=mips32 -mattr=+virt | FileCheck %s + +0x00 0x28 0x64 0x40 # CHECK: mfgc0 $4, $5, 0 +0x02 0x28 0x64 0x40 # CHECK: mfgc0 $4, $5, 2 +0x00 0x2a 0x64 0x40 # CHECK: mtgc0 $4, $5, 0 +0x02 0x22 0x65 0x40 # CHECK: mtgc0 $5, $4, 2 +0x28 0x00 0x00 0x42 # CHECK: hypcall +0x28 0x50 0x00 0x42 # CHECK: hypcall 10 +0x0b 0x00 0x00 0x42 # CHECK: tlbginv +0x0c 0x00 0x00 0x42 # CHECK: tlbginvf +0x10 0x00 0x00 0x42 # CHECK: tlbgp +0x09 0x00 0x00 0x42 # CHECK: tlbgr +0x0a 0x00 0x00 0x42 # CHECK: tlbgwi +0x0e 0x00 0x00 0x42 # CHECK: tlbgwr Index: test/MC/Disassembler/Mips/virt/valid-32.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/Mips/virt/valid-32.txt @@ -0,0 +1,15 @@ +# RUN: llvm-mc --disassemble %s -triple=mips-unknown-linux-gnu \ +# RUN: -mcpu=mips32 -mattr=+virt | FileCheck %s + +0x40 0x64 0x28 0x00 # CHECK: mfgc0 $4, $5, 0 +0x40 0x64 0x28 0x02 # CHECK: mfgc0 $4, $5, 2 +0x40 0x64 0x2a 0x00 # CHECK: mtgc0 $4, $5, 0 +0x40 0x65 0x22 0x02 # CHECK: mtgc0 $5, $4, 2 +0x42 0x00 0x00 0x28 # CHECK: hypcall +0x42 0x00 0x50 0x28 # CHECK: hypcall 10 +0x42 0x00 0x00 0x0b # CHECK: tlbginv +0x42 0x00 0x00 0x0c # CHECK: tlbginvf +0x42 0x00 0x00 0x10 # CHECK: tlbgp +0x42 0x00 0x00 0x09 # CHECK: tlbgr +0x42 0x00 0x00 0x0a # CHECK: tlbgwi +0x42 0x00 0x00 0x0e # CHECK: tlbgwr Index: test/MC/Disassembler/Mips/virt/valid-32r5-el.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/Mips/virt/valid-32r5-el.txt @@ -0,0 +1,7 @@ +# RUN: llvm-mc --disassemble %s -triple=mipsel-unknown-linux-gnu \ +# RUN: -mcpu=mips32r5 -mattr=+virt | FileCheck %s + +0x00 0x2c 0x64 0x40 # CHECK: mfhgc0 $4, $5, 0 +0x04 0x2c 0x64 0x40 # CHECK: mfhgc0 $4, $5, 4 +0x00 0x2e 0x64 0x40 # CHECK: mthgc0 $4, $5, 0 +0x04 0x2e 0x64 0x40 # CHECK: mthgc0 $4, $5, 4 Index: test/MC/Disassembler/Mips/virt/valid-32r5.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/Mips/virt/valid-32r5.txt @@ -0,0 +1,7 @@ +# RUN: llvm-mc --disassemble %s -triple=mips-unknown-linux-gnu \ +# RUN: -mcpu=mips32r5 -mattr=+virt | FileCheck %s + +0x40 0x6f 0x7e 0x00 # CHECK: mthgc0 $15, $15, 0 +0x40 0x79 0xee 0x01 # CHECK: mthgc0 $25, $29, 1 +0x40 0x6f 0x7c 0x00 # CHECK: mfhgc0 $15, $15, 0 +0x40 0x6f 0x7c 0x07 # CHECK: mfhgc0 $15, $15, 7 Index: test/MC/Disassembler/Mips/virt/valid-64-el.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/Mips/virt/valid-64-el.txt @@ -0,0 +1,7 @@ +# RUN: llvm-mc --disassemble %s -triple=mips64el-unknown-linux-gnu \ +# RUN: -mcpu=mips64 -mattr=+virt | FileCheck %s + +0x00 0x29 0x64 0x40 # CHECK: dmfgc0 $4, $5, 0 +0x04 0x29 0x64 0x40 # CHECK: dmfgc0 $4, $5, 4 +0x00 0x23 0x65 0x40 # CHECK: dmtgc0 $5, $4, 0 +0x04 0x2b 0x64 0x40 # CHECK: dmtgc0 $4, $5, 4 Index: test/MC/Disassembler/Mips/virt/valid-64.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/Mips/virt/valid-64.txt @@ -0,0 +1,7 @@ +# RUN: llvm-mc --disassemble %s -triple=mips64-unknown-linux-gnu \ +# RUN: -mcpu=mips64 -mattr=+virt | FileCheck %s + +0x40 0x64 0x29 0x00 # CHECK: dmfgc0 $4, $5, 0 +0x40 0x64 0x29 0x04 # CHECK: dmfgc0 $4, $5, 4 +0x40 0x65 0x23 0x00 # CHECK: dmtgc0 $5, $4, 0 +0x40 0x64 0x2b 0x04 # CHECK: dmtgc0 $4, $5, 4 Index: test/MC/Disassembler/Mips/virt/valid-micromips-el.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/Mips/virt/valid-micromips-el.txt @@ -0,0 +1,19 @@ +# RUN: llvm-mc --disassemble %s -triple=mipsel-unknown-linux-gnu \ +# RUN: -mcpu=mips32r6 -mattr=+micromips,+virt | FileCheck %s + +0x85 0x00 0xfc 0x04 # CHECK: mfgc0 $4, $5, 0 +0x85 0x00 0xfc 0x14 # CHECK: mfgc0 $4, $5, 2 +0xa4 0x00 0xfc 0x06 # CHECK: mtgc0 $5, $4, 0 +0xa4 0x00 0xfc 0x16 # CHECK: mtgc0 $5, $4, 2 +0xef 0x01 0xf4 0x06 # CHECK: mthgc0 $15, $15, 0 +0x3d 0x03 0xf4 0x0e # CHECK: mthgc0 $25, $29, 1 +0xef 0x01 0xf4 0x04 # CHECK: mfhgc0 $15, $15, 0 +0xef 0x01 0xf4 0x3c # CHECK: mfhgc0 $15, $15, 7 +0x00 0x00 0x7c 0xc3 # CHECK: hypcall +0x0a 0x00 0x7c 0xc3 # CHECK: hypcall 10 +0x00 0x00 0x7c 0x41 # CHECK: tlbginv +0x00 0x00 0x7c 0x51 # CHECK: tlbginvf +0x00 0x00 0x7c 0x01 # CHECK: tlbgp +0x00 0x00 0x7c 0x11 # CHECK: tlbgr +0x00 0x00 0x7c 0x21 # CHECK: tlbgwi +0x00 0x00 0x7c 0x31 # CHECK: tlbgwr Index: test/MC/Disassembler/Mips/virt/valid-micromips.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/Mips/virt/valid-micromips.txt @@ -0,0 +1,19 @@ +# RUN: llvm-mc --disassemble %s -triple=mips-unknown-linux-gnu \ +# RUN: -mcpu=mips32r6 -mattr=+micromips,+virt | FileCheck %s + +0x00 0x85 0x04 0xfc # CHECK: mfgc0 $4, $5, 0 +0x00 0x85 0x14 0xfc # CHECK: mfgc0 $4, $5, 2 +0x00 0xa4 0x06 0xfc # CHECK: mtgc0 $5, $4, 0 +0x00 0xa4 0x16 0xfc # CHECK: mtgc0 $5, $4, 2 +0x01 0xef 0x06 0xf4 # CHECK: mthgc0 $15, $15, 0 +0x03 0x3d 0x0e 0xf4 # CHECK: mthgc0 $25, $29, 1 +0x01 0xef 0x04 0xf4 # CHECK: mfhgc0 $15, $15, 0 +0x01 0xef 0x3c 0xf4 # CHECK: mfhgc0 $15, $15, 7 +0x00 0x00 0xc3 0x7c # CHECK: hypcall +0x00 0x0a 0xc3 0x7c # CHECK: hypcall 10 +0x00 0x00 0x41 0x7c # CHECK: tlbginv +0x00 0x00 0x51 0x7c # CHECK: tlbginvf +0x00 0x00 0x01 0x7c # CHECK: tlbgp +0x00 0x00 0x11 0x7c # CHECK: tlbgr +0x00 0x00 0x21 0x7c # CHECK: tlbgwi +0x00 0x00 0x31 0x7c # CHECK: tlbgwr Index: test/MC/Mips/virt/invalid-r5.s =================================================================== --- /dev/null +++ test/MC/Mips/virt/invalid-r5.s @@ -0,0 +1,27 @@ +# Instructions that are invalid. +# +# RUN: not llvm-mc %s -arch=mips -mcpu=mips32r5 -mattr=+virt 2>%t1 +# RUN: FileCheck %s < %t1 +# RUN: not llvm-mc %s -arch=mips64 -mcpu=mips64r5 -mattr=+virt 2>%t1 +# RUN: FileCheck %s < %t1 +# RUN: not llvm-mc %s -arch=mips -mcpu=mips32r6 -mattr=+micromips,+virt 2>%t1 +# RUN: FileCheck %s < %t1 + + mfhgc0 # CHECK: :[[@LINE]]:3: error: too few operands for instruction + mfhgc0 0 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + mfhgc0 $4 # CHECK: :[[@LINE]]:3: error: too few operands for instruction + mfhgc0 0, $4 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + mfhgc0 0, $4, $5 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + mfhgc0 $4, 0, $5 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction + mfhgc0 $4, $5, 8 # CHECK: :[[@LINE]]:18: error: expected 3-bit unsigned immediate + mfhgc0 $4, $5, -1 # CHECK: :[[@LINE]]:18: error: expected 3-bit unsigned immediate + mfhgc0 $4, $5, 0($4) # CHECK: :[[@LINE]]:19: error: invalid operand for instruction + mthgc0 # CHECK: :[[@LINE]]:3: error: too few operands for instruction + mthgc0 0 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + mthgc0 $4 # CHECK: :[[@LINE]]:3: error: too few operands for instruction + mthgc0 0, $4 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + mthgc0 0, $4, $5 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + mthgc0 $4, 0, $5 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction + mthgc0 $4, $5, 8 # CHECK: :[[@LINE]]:18: error: expected 3-bit unsigned immediate + mthgc0 $4, $5, -1 # CHECK: :[[@LINE]]:18: error: expected 3-bit unsigned immediate + mthgc0 $4, $5, 0($4) # CHECK: :[[@LINE]]:19: error: invalid operand for instruction Index: test/MC/Mips/virt/invalid.s =================================================================== --- /dev/null +++ test/MC/Mips/virt/invalid.s @@ -0,0 +1,43 @@ +# Instructions that are invalid. +# +# RUN: not llvm-mc %s -arch=mips -mcpu=mips32 -mattr=+virt 2>%t1 +# RUN: FileCheck %s < %t1 +# RUN: not llvm-mc %s -arch=mips64 -mcpu=mips64 -mattr=+virt 2>%t1 +# RUN: FileCheck %s < %t1 +# RUN: not llvm-mc %s -arch=mips -mcpu=mips32r6 -mattr=+micromips,+virt 2>%t1 +# RUN: FileCheck %s < %t1 + + mfgc0 # CHECK: :[[@LINE]]:3: error: too few operands for instruction + mfgc0 0 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + mfgc0 $4 # CHECK: :[[@LINE]]:3: error: too few operands for instruction + mfgc0 0, $4 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + mfgc0 0, $4, $5 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + mfgc0 $4, 0, $5 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction + mfgc0 $4, $5, 8 # CHECK: :[[@LINE]]:17: error: expected 3-bit unsigned immediate + mfgc0 $4, $5, -1 # CHECK: :[[@LINE]]:17: error: expected 3-bit unsigned immediate + mfgc0 $4, $5, 0($4) # CHECK: :[[@LINE]]:18: error: invalid operand for instruction + mtgc0 # CHECK: :[[@LINE]]:3: error: too few operands for instruction + mtgc0 0 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + mtgc0 $4 # CHECK: :[[@LINE]]:3: error: too few operands for instruction + mtgc0 0, $4 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + mtgc0 0, $4, $5 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + mtgc0 $4, 0, $5 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction + mtgc0 $4, $5, 8 # CHECK: :[[@LINE]]:17: error: expected 3-bit unsigned immediate + mtgc0 $4, $5, -1 # CHECK: :[[@LINE]]:17: error: expected 3-bit unsigned immediate + mtgc0 $4, $5, 0($4) # CHECK: :[[@LINE]]:18: error: invalid operand for instruction + hypcall $4 # CHECK: :[[@LINE]]:11: error: expected 10-bit unsigned immediate + hypcall 2048 # CHECK: :[[@LINE]]:11: error: expected 10-bit unsigned immediate + hypcall -1 # CHECK: :[[@LINE]]:11: error: expected 10-bit unsigned immediate + hypcall 0($4) # CHECK: :[[@LINE]]:12: error: unexpected token in argument list + tlbginv $2 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction + tlbginv 0 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction + tlbginvf $2 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction + tlbginvf 0 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction + tlbgp $2 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + tlbgp 0 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + tlbgr $2 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + tlbgr 0 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + tlbgwi $2 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + tlbgwi 0 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + tlbgwr $2 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + tlbgwr 0 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction Index: test/MC/Mips/virt/invalid64.s =================================================================== --- /dev/null +++ test/MC/Mips/virt/invalid64.s @@ -0,0 +1,23 @@ +# Instructions that are invalid. +# +# RUN: not llvm-mc %s -arch=mips -mcpu=mips64 -mattr=+virt 2>%t1 +# RUN: FileCheck %s < %t1 + + dmfgc0 # CHECK: :[[@LINE]]:3: error: too few operands for instruction + dmfgc0 0 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + dmfgc0 $4 # CHECK: :[[@LINE]]:3: error: too few operands for instruction + dmfgc0 0, $4 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + dmfgc0 0, $4, $5 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + dmfgc0 $4, 0, $5 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction + dmfgc0 $4, $5, 8 # CHECK: :[[@LINE]]:18: error: expected 3-bit unsigned immediate + dmfgc0 $4, $5, -1 # CHECK: :[[@LINE]]:18: error: expected 3-bit unsigned immediate + dmfgc0 $4, $5, 0($4) # CHECK: :[[@LINE]]:19: error: invalid operand for instruction + dmtgc0 # CHECK: :[[@LINE]]:3: error: too few operands for instruction + dmtgc0 0 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + dmtgc0 $4 # CHECK: :[[@LINE]]:3: error: too few operands for instruction + dmtgc0 0, $4 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + dmtgc0 0, $4, $5 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + dmtgc0 $4, 0, $5 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction + dmtgc0 $4, $5, 8 # CHECK: :[[@LINE]]:18: error: expected 3-bit unsigned immediate + dmtgc0 $4, $5, -1 # CHECK: :[[@LINE]]:18: error: expected 3-bit unsigned immediate + dmtgc0 $4, $5, 0($4) # CHECK: :[[@LINE]]:19: error: invalid operand for instruction Index: test/MC/Mips/virt/module-novirt.s =================================================================== --- /dev/null +++ test/MC/Mips/virt/module-novirt.s @@ -0,0 +1,21 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -mattr=+virt | \ +# RUN: FileCheck %s -check-prefix=CHECK-ASM +# +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -filetype=obj -o - -mattr=+virt | \ +# RUN: llvm-readobj -mips-abi-flags - | \ +# RUN: FileCheck %s -check-prefix=CHECK-OBJ + +# CHECK-ASM: .module novirt + +# Check that MIPS.abiflags has no VZ flag. +# CHECK-OBJ: MIPS ABI Flags { +# CHECK-OBJ: ASEs [ (0x0) +# CHECK-OBJ-NOT: ASEs [ (0x100) +# CHECK-OBJ-NOT: VZ (0x100) +# CHECK-OBJ: } + + .module novirt + +# 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. Index: test/MC/Mips/virt/module-virt.s =================================================================== --- /dev/null +++ test/MC/Mips/virt/module-virt.s @@ -0,0 +1,22 @@ +# RUN: llvm-mc %s -triple=mips-unknown-linux-gnu -mcpu=mips32 | \ +# RUN: FileCheck %s -check-prefix=CHECK-ASM +# +# RUN: llvm-mc %s -triple=mips-unknown-linux-gnu -mcpu=mips32 \ +# RUN: -filetype=obj -o - | \ +# RUN: llvm-readobj -mips-abi-flags - | \ +# RUN: FileCheck %s -check-prefix=CHECK-OBJ + +# CHECK-ASM: .module virt + +# Check if the MIPS.abiflags section was correctly emitted: +# CHECK-OBJ: MIPS ABI Flags { +# CHECK-OBJ: ASEs [ (0x100) +# CHECK-OBJ: VZ (0x100) +# CHECK-OBJ: } + + .module virt + hypcall + +# 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. Index: test/MC/Mips/virt/set-novirt-directive.s =================================================================== --- /dev/null +++ test/MC/Mips/virt/set-novirt-directive.s @@ -0,0 +1,9 @@ +# RUN: not llvm-mc %s -triple=mips-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips32 -mattr=+virt 2>%t1 +# RUN: FileCheck %s < %t1 +# RUN: not llvm-mc %s -triple=mips64-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips64 -mattr=+virt 2>%t1 +# RUN: FileCheck %s < %t1 + + .set novirt + hypcall # CHECK: instruction requires a CPU feature not currently enabled Index: test/MC/Mips/virt/set-virt-directive.s =================================================================== --- /dev/null +++ test/MC/Mips/virt/set-virt-directive.s @@ -0,0 +1,7 @@ +# RUN: llvm-mc %s -show-encoding -triple=mips-unknown-linux-gnu \ +# RUN: -mcpu=mips32 | FileCheck %s +# RUN: llvm-mc %s -show-encoding -triple=mips64-unknown-linux-gnu \ +# RUN: -mcpu=mips64 | FileCheck %s + + .set virt + hypcall # CHECK: hypcall # encoding: [0x42,0x00,0x00,0x28] Index: test/MC/Mips/virt/valid-micromips.s =================================================================== --- /dev/null +++ test/MC/Mips/virt/valid-micromips.s @@ -0,0 +1,19 @@ +# RUN: llvm-mc %s -triple=mips-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips32r6 -mattr=+micromips,+virt | FileCheck %s + + mfgc0 $4, $5 # CHECK: mfgc0 $4, $5, 0 # encoding: [0x00,0x85,0x04,0xfc] + mfgc0 $4, $5, 2 # CHECK: mfgc0 $4, $5, 2 # encoding: [0x00,0x85,0x14,0xfc] + mtgc0 $5, $4 # CHECK: mtgc0 $5, $4, 0 # encoding: [0x00,0xa4,0x06,0xfc] + mtgc0 $5, $4, 2 # CHECK: mtgc0 $5, $4, 2 # encoding: [0x00,0xa4,0x16,0xfc] + mthgc0 $5, $4 # CHECK: mthgc0 $5, $4, 0 # encoding: [0x00,0xa4,0x06,0xf4] + mthgc0 $5, $4, 1 # CHECK: mthgc0 $5, $4, 1 # encoding: [0x00,0xa4,0x0e,0xf4] + mfhgc0 $5, $4 # CHECK: mfhgc0 $5, $4, 0 # encoding: [0x00,0xa4,0x04,0xf4] + mfhgc0 $5, $4, 7 # CHECK: mfhgc0 $5, $4, 7 # encoding: [0x00,0xa4,0x3c,0xf4] + hypcall # CHECK: hypcall # encoding: [0x00,0x00,0xc3,0x7c] + hypcall 10 # CHECK: hypcall 10 # encoding: [0x00,0x0a,0xc3,0x7c] + tlbginv # CHECK: tlbginv # encoding: [0x00,0x00,0x41,0x7c] + tlbginvf # CHECK: tlbginvf # encoding: [0x00,0x00,0x51,0x7c] + tlbgp # CHECK: tlbgp # encoding: [0x00,0x00,0x01,0x7c] + tlbgr # CHECK: tlbgr # encoding: [0x00,0x00,0x11,0x7c] + tlbgwi # CHECK: tlbgwi # encoding: [0x00,0x00,0x21,0x7c] + tlbgwr # CHECK: tlbgwr # encoding: [0x00,0x00,0x31,0x7c] Index: test/MC/Mips/virt/valid-r5.s =================================================================== --- /dev/null +++ test/MC/Mips/virt/valid-r5.s @@ -0,0 +1,9 @@ +# RUN: llvm-mc %s -triple=mips-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips32r5 -mattr=+virt | FileCheck %s +# RUN: llvm-mc %s -triple=mips64-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips64r5 -mattr=+virt | FileCheck %s + + mthgc0 $5, $4 # CHECK: mthgc0 $5, $4, 0 # encoding: [0x40,0x65,0x26,0x00] + mthgc0 $5, $4, 1 # CHECK: mthgc0 $5, $4, 1 # encoding: [0x40,0x65,0x26,0x01] + mfhgc0 $5, $4 # CHECK: mfhgc0 $5, $4, 0 # encoding: [0x40,0x65,0x24,0x00] + mfhgc0 $5, $4, 7 # CHECK: mfhgc0 $5, $4, 7 # encoding: [0x40,0x65,0x24,0x07] Index: test/MC/Mips/virt/valid.s =================================================================== --- /dev/null +++ test/MC/Mips/virt/valid.s @@ -0,0 +1,17 @@ +# RUN: llvm-mc %s -triple=mips-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips32 -mattr=+virt | FileCheck %s +# RUN: llvm-mc %s -triple=mips64-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips64 -mattr=+virt | FileCheck %s + + mfgc0 $4, $5 # CHECK: mfgc0 $4, $5, 0 # encoding: [0x40,0x64,0x28,0x00] + mfgc0 $4, $5, 2 # CHECK: mfgc0 $4, $5, 2 # encoding: [0x40,0x64,0x28,0x02] + mtgc0 $4, $5 # CHECK: mtgc0 $4, $5, 0 # encoding: [0x40,0x64,0x2a,0x00] + mtgc0 $5, $4, 2 # CHECK: mtgc0 $5, $4, 2 # encoding: [0x40,0x65,0x22,0x02] + hypcall # CHECK: hypcall # encoding: [0x42,0x00,0x00,0x28] + hypcall 10 # CHECK: hypcall 10 # encoding: [0x42,0x00,0x50,0x28] + tlbginv # CHECK: tlbginv # encoding: [0x42,0x00,0x00,0x0b] + tlbginvf # CHECK: tlbginvf # encoding: [0x42,0x00,0x00,0x0c] + tlbgp # CHECK: tlbgp # encoding: [0x42,0x00,0x00,0x10] + tlbgr # CHECK: tlbgr # encoding: [0x42,0x00,0x00,0x09] + tlbgwi # CHECK: tlbgwi # encoding: [0x42,0x00,0x00,0x0a] + tlbgwr # CHECK: tlbgwr # encoding: [0x42,0x00,0x00,0x0e] Index: test/MC/Mips/virt/valid64.s =================================================================== --- /dev/null +++ test/MC/Mips/virt/valid64.s @@ -0,0 +1,7 @@ +# RUN: llvm-mc %s -triple=mips64-unknown-linux-gnu -show-encoding \ +# RUN: -mcpu=mips64 -mattr=+virt | FileCheck %s + + dmfgc0 $4,$5 # CHECK: dmfgc0 $4, $5, 0 # encoding: [0x40,0x64,0x29,0x00] + dmfgc0 $4,$5,4 # CHECK: dmfgc0 $4, $5, 4 # encoding: [0x40,0x64,0x29,0x04] + dmtgc0 $4,$5 # CHECK: dmtgc0 $5, $4, 0 # encoding: [0x40,0x65,0x23,0x00] + dmtgc0 $4,$5,4 # CHECK: dmtgc0 $4, $5, 4 # encoding: [0x40,0x64,0x2b,0x04]