89 changes: 79 additions & 10 deletions llvm/lib/Target/Mips/MipsInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ def NotMips64 : Predicate<"!Subtarget->hasMips64()">,
AssemblerPredicate<"!FeatureMips64">;
def HasMips64r2 : Predicate<"Subtarget->hasMips64r2()">,
AssemblerPredicate<"FeatureMips64r2">;
def HasMips64r5 : Predicate<"Subtarget->hasMips64r5()">,
AssemblerPredicate<"FeatureMips64r5">;
def HasMips64r6 : Predicate<"Subtarget->hasMips64r6()">,
AssemblerPredicate<"FeatureMips64r6">;
def NotMips64r6 : Predicate<"!Subtarget->hasMips64r6()">,
Expand Down Expand Up @@ -248,6 +250,8 @@ def NoIndirectJumpGuards : Predicate<"!Subtarget->useIndirectJumpsHazard()">,
AssemblerPredicate<"!FeatureUseIndirectJumpsHazard">;
def HasCRC : Predicate<"Subtarget->hasCRC()">,
AssemblerPredicate<"FeatureCRC">;
def HasVirt : Predicate<"Subtarget->hasVirt()">,
AssemblerPredicate<"FeatureVirt">;
//===----------------------------------------------------------------------===//
// Mips GPR size adjectives.
// They are mutually exclusive.
Expand Down Expand Up @@ -340,6 +344,10 @@ class ISA_MIPS64R2 {
list<Predicate> InsnPredicates = [HasMips64r2];
list<Predicate> EncodingPredicates = [HasStdEnc];
}
class ISA_MIPS64R5 {
list<Predicate> InsnPredicates = [HasMips64r5];
list<Predicate> EncodingPredicates = [HasStdEnc];
}
class ISA_MIPS32R6 {
list<Predicate> InsnPredicates = [HasMips32r6];
list<Predicate> EncodingPredicates = [HasStdEnc];
Expand All @@ -351,6 +359,10 @@ class ISA_MIPS64R6 {
class ISA_MICROMIPS {
list<Predicate> EncodingPredicates = [InMicroMips];
}
class ISA_MICROMIPS32R5 {
list<Predicate> InsnPredicates = [HasMips32r5];
list<Predicate> EncodingPredicates = [InMicroMips];
}
class ISA_MICROMIPS32R6 {
list<Predicate> InsnPredicates = [HasMips32r6];
list<Predicate> EncodingPredicates = [InMicroMips];
Expand Down Expand Up @@ -449,6 +461,10 @@ class ASE_CRC {
list <Predicate> ASEPredicate = [HasCRC];
}

class ASE_VIRT {
list <Predicate> 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 {
Expand Down Expand Up @@ -1844,12 +1860,16 @@ class SCBase<string opstr, RegisterOperand RO> :
class MFC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD,
InstrItinClass itin> :
InstSE<(outs RO:$rt), (ins RD:$rd, uimm3:$sel),
!strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR>;
!strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR> {
let BaseOpcode = asmstr;
}

class MTC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD,
InstrItinClass itin> :
InstSE<(outs RO:$rd), (ins RD:$rt, uimm3:$sel),
!strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR>;
!strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR> {
let BaseOpcode = asmstr;
}

class TrapBase<Instruction RealInst>
: PseudoSE<(outs), (ins), [(trap)], II_TRAP>,
Expand Down Expand Up @@ -2329,14 +2349,14 @@ let AdditionalPredicates = [NotInMicroMips] in {
}
/// 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;
}

class Barrier<string asmstr, InstrItinClass itin = NoItinerary> :
Expand Down Expand Up @@ -2502,6 +2522,38 @@ def MULOUMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs,
"mulou\t$rd, $rs, $rt">,
ISA_MIPS1_NOT_32R6_64R6;

// Virtualization ASE
class HYPCALL_FT<string opstr> :
InstSE<(outs), (ins uimm10:$code_),
!strconcat(opstr, "\t$code_"), [], II_HYPCALL, FrmOther, opstr> {
let BaseOpcode = opstr;
}

let AdditionalPredicates = [NotInMicroMips] in {
def MFGC0 : MMRel, MFC3OP<"mfgc0", GPR32Opnd, COP0Opnd, II_MFGC0>,
MFC3OP_FM<0x10, 3, 0>, ISA_MIPS32R5, ASE_VIRT;
def MTGC0 : MMRel, MTC3OP<"mtgc0", COP0Opnd, GPR32Opnd, II_MTGC0>,
MFC3OP_FM<0x10, 3, 2>, ISA_MIPS32R5, ASE_VIRT;
def MFHGC0 : MMRel, MFC3OP<"mfhgc0", GPR32Opnd, COP0Opnd, II_MFHGC0>,
MFC3OP_FM<0x10, 3, 4>, ISA_MIPS32R5, ASE_VIRT;
def MTHGC0 : MMRel, MTC3OP<"mthgc0", COP0Opnd, GPR32Opnd, II_MTHGC0>,
MFC3OP_FM<0x10, 3, 6>, ISA_MIPS32R5, ASE_VIRT;
def TLBGINV : MMRel, TLB<"tlbginv", II_TLBGINV>, COP0_TLB_FM<0b001011>,
ISA_MIPS32R5, ASE_VIRT;
def TLBGINVF : MMRel, TLB<"tlbginvf", II_TLBGINVF>, COP0_TLB_FM<0b001100>,
ISA_MIPS32R5, ASE_VIRT;
def TLBGP : MMRel, TLB<"tlbgp", II_TLBGP>, COP0_TLB_FM<0b010000>,
ISA_MIPS32R5, ASE_VIRT;
def TLBGR : MMRel, TLB<"tlbgr", II_TLBGR>, COP0_TLB_FM<0b001001>,
ISA_MIPS32R5, ASE_VIRT;
def TLBGWI : MMRel, TLB<"tlbgwi", II_TLBGWI>, COP0_TLB_FM<0b001010>,
ISA_MIPS32R5, ASE_VIRT;
def TLBGWR : MMRel, TLB<"tlbgwr", II_TLBGWR>, COP0_TLB_FM<0b001110>,
ISA_MIPS32R5, ASE_VIRT;
def HYPCALL : MMRel, HYPCALL_FT<"hypcall">,
HYPCALL_FM<0b101000>, ISA_MIPS32R5, ASE_VIRT;
}

//===----------------------------------------------------------------------===//
// Instruction aliases
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -2584,6 +2636,20 @@ let AdditionalPredicates = [NotInMicroMips] in {
}
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_MIPS32R5, ASE_VIRT;
def : MipsInstAlias<"mtgc0 $rt, $rd",
(MTGC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>,
ISA_MIPS32R5, 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 {
Expand Down Expand Up @@ -2658,6 +2724,9 @@ def : MipsInstAlias<"mulou $rs, $rt",
(MULOUMacro GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>,
ISA_MIPS1_NOT_32R6_64R6;

let AdditionalPredicates = [NotInMicroMips] in
def : MipsInstAlias<"hypcall", (HYPCALL 0), 1>, ISA_MIPS32R5, ASE_VIRT;

//===----------------------------------------------------------------------===//
// Assembler Pseudo Instructions
//===----------------------------------------------------------------------===//
Expand Down
28 changes: 27 additions & 1 deletion llvm/lib/Target/Mips/MipsSchedule.td
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ def II_DIVU : InstrItinClass;
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;
Expand Down Expand Up @@ -128,6 +130,7 @@ def II_EVPE : InstrItinClass;
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;
Expand Down Expand Up @@ -233,6 +236,8 @@ def II_MFHC0 : InstrItinClass;
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;
Expand Down Expand Up @@ -263,6 +268,8 @@ def II_MTHC0 : InstrItinClass;
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;
Expand Down Expand Up @@ -354,6 +361,12 @@ def II_CACHEE : InstrItinClass;
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;
Expand Down Expand Up @@ -702,5 +715,18 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [
InstrItinData<II_CRC32CB , [InstrStage<1, [ALU]>]>,
InstrItinData<II_CRC32CH , [InstrStage<1, [ALU]>]>,
InstrItinData<II_CRC32CW , [InstrStage<1, [ALU]>]>,
InstrItinData<II_CRC32CD , [InstrStage<1, [ALU]>]>
InstrItinData<II_CRC32CD , [InstrStage<1, [ALU]>]>,
InstrItinData<II_MFGC0 , [InstrStage<2, [ALU]>]>,
InstrItinData<II_MTGC0 , [InstrStage<2, [ALU]>]>,
InstrItinData<II_MFHGC0 , [InstrStage<2, [ALU]>]>,
InstrItinData<II_MTHGC0 , [InstrStage<2, [ALU]>]>,
InstrItinData<II_HYPCALL , [InstrStage<2, [ALU]>]>,
InstrItinData<II_TLBGINV , [InstrStage<2, [ALU]>]>,
InstrItinData<II_TLBGINVF , [InstrStage<2, [ALU]>]>,
InstrItinData<II_TLBGP , [InstrStage<2, [ALU]>]>,
InstrItinData<II_TLBGR , [InstrStage<2, [ALU]>]>,
InstrItinData<II_TLBWI , [InstrStage<2, [ALU]>]>,
InstrItinData<II_TLBWR , [InstrStage<2, [ALU]>]>,
InstrItinData<II_DMFGC0 , [InstrStage<2, [ALU]>]>,
InstrItinData<II_DMTGC0 , [InstrStage<2, [ALU]>]>
]>;
3 changes: 2 additions & 1 deletion llvm/lib/Target/Mips/MipsSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ 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),
UseIndirectJumpsHazard(false), StackAlignOverride(StackAlignOverride),
HasVirt(false), UseIndirectJumpsHazard(false),
StackAlignOverride(StackAlignOverride),
TM(TM), TargetTriple(TT), TSInfo(),
InstrInfo(
MipsInstrInfo::create(initializeSubtargetDependencies(CPU, FS, TM))),
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/Mips/MipsSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
// 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;
Expand Down Expand Up @@ -290,6 +293,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
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();
}
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/Mips/MipsTargetStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class MipsTargetStreamer : public MCTargetStreamer {
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();
Expand Down Expand Up @@ -107,6 +109,8 @@ class MipsTargetStreamer : public MCTargetStreamer {
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);
Expand Down Expand Up @@ -219,6 +223,8 @@ class MipsTargetAsmStreamer : public MipsTargetStreamer {
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;
Expand Down Expand Up @@ -286,6 +292,8 @@ class MipsTargetAsmStreamer : public MipsTargetStreamer {
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;
Expand Down
19 changes: 19 additions & 0 deletions llvm/test/MC/Disassembler/Mips/virt/valid-32-el.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# RUN: llvm-mc --disassemble %s -triple=mipsel-unknown-linux-gnu \
# RUN: -mcpu=mips32r5 -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
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
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
19 changes: 19 additions & 0 deletions llvm/test/MC/Disassembler/Mips/virt/valid-32.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# RUN: llvm-mc --disassemble %s -triple=mips-unknown-linux-gnu \
# RUN: -mcpu=mips32r5 -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
0x40 0x64 0x2c 0x00 # CHECK: mfhgc0 $4, $5, 0
0x40 0x64 0x2c 0x04 # CHECK: mfhgc0 $4, $5, 4
0x40 0x64 0x2e 0x00 # CHECK: mthgc0 $4, $5, 0
0x40 0x64 0x2e 0x04 # CHECK: mthgc0 $4, $5, 4
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
7 changes: 7 additions & 0 deletions llvm/test/MC/Disassembler/Mips/virt/valid-64-el.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=mips64el-unknown-linux-gnu \
# RUN: -mcpu=mips64r5 -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
7 changes: 7 additions & 0 deletions llvm/test/MC/Disassembler/Mips/virt/valid-64.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# RUN: llvm-mc --disassemble %s -triple=mips64-unknown-linux-gnu \
# RUN: -mcpu=mips64r5 -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
19 changes: 19 additions & 0 deletions llvm/test/MC/Disassembler/Mips/virt/valid-micromips-el.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# RUN: llvm-mc --disassemble %s -triple=mipsel-unknown-linux-gnu \
# RUN: -mcpu=mips32r5 -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
0x85 0x00 0xf4 0x04 # CHECK: mfhgc0 $4, $5, 0
0x85 0x00 0xf4 0x14 # CHECK: mfhgc0 $4, $5, 2
0xa4 0x00 0xf4 0x06 # CHECK: mthgc0 $5, $4, 0
0xa4 0x00 0xf4 0x16 # CHECK: mthgc0 $5, $4, 2
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
19 changes: 19 additions & 0 deletions llvm/test/MC/Disassembler/Mips/virt/valid-micromips.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# RUN: llvm-mc --disassemble %s -triple=mips-unknown-linux-gnu \
# RUN: -mcpu=mips32r5 -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
0x00 0x85 0x04 0xf4 # CHECK: mfhgc0 $4, $5, 0
0x00 0x85 0x14 0xf4 # CHECK: mfhgc0 $4, $5, 2
0x00 0xa4 0x06 0xf4 # CHECK: mthgc0 $5, $4, 0
0x00 0xa4 0x16 0xf4 # CHECK: mthgc0 $5, $4, 2
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
103 changes: 103 additions & 0 deletions llvm/test/MC/Mips/virt/invalid.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# 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=mips32r5 -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
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
hypcall $4 # CHECK: :[[@LINE]]:11: error: expected 10-bit unsigned immediate
hypcall 0, $4 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction
hypcall 0, $4, $5 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction
hypcall $4, 0, $5 # CHECK: :[[@LINE]]:11: error: expected 10-bit unsigned immediate
hypcall $4, $5, 8 # CHECK: :[[@LINE]]:11: error: expected 10-bit unsigned immediate
hypcall $4, $5, -1 # CHECK: :[[@LINE]]:11: error: expected 10-bit unsigned immediate
hypcall $4, $5, 0($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 0 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
tlbginv $4 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
tlbginv 0, $4 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
tlbginv 0, $4, $5 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
tlbginv $4, 0, $5 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
tlbginv $4, $5, 8 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
tlbginv $4, $5, -1 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
tlbginv $4, $5, 0($4) # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
tlbginvf 0 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
tlbginvf $4 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
tlbginvf 0, $4 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
tlbginvf 0, $4, $5 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
tlbginvf $4, 0, $5 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
tlbginvf $4, $5, 8 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
tlbginvf $4, $5, -1 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
tlbginvf $4, $5, 0($4) # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
tlbgp 0 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgp $4 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgp 0, $4 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgp 0, $4, $5 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgp $4, 0, $5 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgp $4, $5, 8 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgp $4, $5, -1 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgp $4, $5, 0($4) # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgr 0 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgr $4 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgr 0, $4 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgr 0, $4, $5 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgr $4, 0, $5 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgr $4, $5, 8 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgr $4, $5, -1 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgr $4, $5, 0($4) # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
tlbgwi 0 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwi $4 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwi 0, $4 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwi 0, $4, $5 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwi $4, 0, $5 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwi $4, $5, 8 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwi $4, $5, -1 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwi $4, $5, 0($4) # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwr 0 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwr $4 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwr 0, $4 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwr 0, $4, $5 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwr $4, 0, $5 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwr $4, $5, 8 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwr $4, $5, -1 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
tlbgwr $4, $5, 0($4) # CHECK: :[[@LINE]]:10: error: invalid operand for instruction
23 changes: 23 additions & 0 deletions llvm/test/MC/Mips/virt/invalid64.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Instructions that are invalid.
#
# RUN: not llvm-mc %s -arch=mips -mcpu=mips64r5 -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
21 changes: 21 additions & 0 deletions llvm/test/MC/Mips/virt/module-novirt.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# RUN: llvm-mc %s -arch=mips -mcpu=mips32r5 -mattr=+virt | \
# RUN: FileCheck %s -check-prefix=CHECK-ASM
#
# RUN: llvm-mc %s -arch=mips -mcpu=mips32r5 -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.
22 changes: 22 additions & 0 deletions llvm/test/MC/Mips/virt/module-virt.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# RUN: llvm-mc %s -triple=mips-unknown-linux-gnu -mcpu=mips32r5 | \
# RUN: FileCheck %s -check-prefix=CHECK-ASM
#
# RUN: llvm-mc %s -triple=mips-unknown-linux-gnu -mcpu=mips32r5 \
# 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.
9 changes: 9 additions & 0 deletions llvm/test/MC/Mips/virt/set-novirt-directive.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# RUN: not llvm-mc %s -triple=mips-unknown-linux-gnu -show-encoding \
# RUN: -mcpu=mips32r5 -mattr=+virt 2>%t1
# RUN: FileCheck %s < %t1
# RUN: not llvm-mc %s -triple=mips64-unknown-linux-gnu -show-encoding \
# RUN: -mcpu=mips64r5 -mattr=+virt 2>%t1
# RUN: FileCheck %s < %t1

.set novirt
hypcall # CHECK: instruction requires a CPU feature not currently enabled
7 changes: 7 additions & 0 deletions llvm/test/MC/Mips/virt/set-virt-directive.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# RUN: llvm-mc %s -show-encoding -triple=mips-unknown-linux-gnu \
# RUN: -mcpu=mips32r5 | FileCheck %s
# RUN: llvm-mc %s -show-encoding -triple=mips64-unknown-linux-gnu \
# RUN: -mcpu=mips64r5 | FileCheck %s

.set virt
hypcall # CHECK: hypcall # encoding: [0x42,0x00,0x00,0x28]
19 changes: 19 additions & 0 deletions llvm/test/MC/Mips/virt/valid-micromips.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# RUN: llvm-mc %s -triple=mips-unknown-linux-gnu -show-encoding \
# RUN: -mcpu=mips32r5 -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]
21 changes: 21 additions & 0 deletions llvm/test/MC/Mips/virt/valid.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# 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

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]
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]
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]
7 changes: 7 additions & 0 deletions llvm/test/MC/Mips/virt/valid64.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# RUN: llvm-mc %s -triple=mips64-unknown-linux-gnu -show-encoding \
# RUN: -mcpu=mips64r5 -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 $4, $5, 0 # encoding: [0x40,0x64,0x2b,0x00]
dmtgc0 $4,$5,4 # CHECK: dmtgc0 $4, $5, 4 # encoding: [0x40,0x64,0x2b,0x04]