Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1379,6 +1379,15 @@ if ((Imm % 4 != 0) || !isIntN(25, Imm)) return Error(IDLoc, "immediate operand value out of range"); break; + case Mips::CACHE: + case Mips::PREF: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (!isUInt<5>(Imm)) + return Error(IDLoc, "immediate operand value out of range"); + break; } } Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -252,6 +252,11 @@ uint64_t Address, const void *Decoder); +static DecodeStatus DecodeCacheOpMM(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeSyncI(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1087,6 +1092,23 @@ return MCDisassembler::Success; } +static DecodeStatus DecodeCacheOpMM(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int Offset = SignExtend32<12>(Insn & 0xfff); + unsigned Base = fieldFromInstruction(Insn, 16, 5); + unsigned Hint = fieldFromInstruction(Insn, 21, 5); + + Base = getReg(Decoder, Mips::GPR32RegClassID, Base); + + Inst.addOperand(MCOperand::CreateReg(Base)); + Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::CreateImm(Hint)); + + return MCDisassembler::Success; +} + static DecodeStatus DecodeSyncI(MCInst &Inst, unsigned Insn, uint64_t Address, Index: lib/Target/Mips/MicroMipsInstrFormats.td =================================================================== --- lib/Target/Mips/MicroMipsInstrFormats.td +++ lib/Target/Mips/MicroMipsInstrFormats.td @@ -861,3 +861,29 @@ let Inst{25-23} = rs; let Inst{22-0} = imm; } + +class CACHE_PREF_FM_MM op, bits<4> funct> : MMArch { + bits<21> addr; + bits<5> hint; + bits<5> base = addr{20-16}; + bits<12> offset = addr{11-0}; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = hint; + let Inst{20-16} = base; + let Inst{15-12} = funct; + let Inst{11-0} = offset; +} + +class BARRIER_FM_MM op> : MMArch { + bits<32> Inst; + + let Inst{31-26} = 0x0; + let Inst{25-21} = 0x0; + let Inst{20-16} = 0x0; + let Inst{15-11} = op; + let Inst{10-6} = 0x0; + let Inst{5-0} = 0x0; +} Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -716,6 +716,16 @@ def LL_MM : LLBaseMM<"ll", GPR32Opnd>, LL_FM_MM<0x3>; def SC_MM : SCBaseMM<"sc", GPR32Opnd>, LL_FM_MM<0xb>; + let DecoderMethod = "DecodeCacheOpMM" in { + def CACHE_MM : MMRel, CacheOp<"cache", mem_mm_12>, + CACHE_PREF_FM_MM<0x08, 0x6>; + def PREF_MM : MMRel, CacheOp<"pref", mem_mm_12>, + CACHE_PREF_FM_MM<0x18, 0x2>; + } + def SSNOP_MM : MMRel, Barrier<"ssnop">, BARRIER_FM_MM<0x1>; + def EHB_MM : MMRel, Barrier<"ehb">, BARRIER_FM_MM<0x3>; + def PAUSE_MM : MMRel, Barrier<"pause">, BARRIER_FM_MM<0x5>; + def TLBP_MM : MMRel, TLB<"tlbp">, COP0_TLB_FM_MM<0x0d>; def TLBR_MM : MMRel, TLB<"tlbr">, COP0_TLB_FM_MM<0x4d>; def TLBWI_MM : MMRel, TLB<"tlbwi">, COP0_TLB_FM_MM<0x8d>; Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -1466,10 +1466,10 @@ def MTC2 : MFC3OP<"mtc2", GPR32Opnd>, MFC3OP_FM<0x12, 4>; class Barrier : InstSE<(outs), (ins), asmstr, [], NoItinerary, - FrmOther>; -def SSNOP : Barrier<"ssnop">, BARRIER_FM<1>; -def EHB : Barrier<"ehb">, BARRIER_FM<3>; -def PAUSE : Barrier<"pause">, BARRIER_FM<5>, ISA_MIPS32R2; + FrmOther, asmstr>; +def SSNOP : MMRel, Barrier<"ssnop">, BARRIER_FM<1>; +def EHB : MMRel, Barrier<"ehb">, BARRIER_FM<3>; +def PAUSE : MMRel, Barrier<"pause">, BARRIER_FM<5>, ISA_MIPS32R2; // JR_HB and JALR_HB are defined here using the new style naming // scheme because some of this code is shared with Mips32r6InstrInfo.td @@ -1520,13 +1520,14 @@ class CacheOp : InstSE<(outs), (ins MemOpnd:$addr, uimm5:$hint), - !strconcat(instr_asm, "\t$hint, $addr"), [], NoItinerary, FrmOther> { + !strconcat(instr_asm, "\t$hint, $addr"), [], NoItinerary, FrmOther, + instr_asm> { let DecoderMethod = "DecodeCacheOp"; } -def CACHE : CacheOp<"cache", mem>, CACHEOP_FM<0b101111>, +def CACHE : MMRel, CacheOp<"cache", mem>, CACHEOP_FM<0b101111>, INSN_MIPS3_32_NOT_32R6_64R6; -def PREF : CacheOp<"pref", mem>, CACHEOP_FM<0b110011>, +def PREF : MMRel, CacheOp<"pref", mem>, CACHEOP_FM<0b110011>, INSN_MIPS3_32_NOT_32R6_64R6; //===----------------------------------------------------------------------===// Index: test/MC/Disassembler/Mips/micromips.txt =================================================================== --- test/MC/Disassembler/Mips/micromips.txt +++ test/MC/Disassembler/Mips/micromips.txt @@ -310,6 +310,21 @@ # CHECK: tnei $9, 17767 0x41 0x89 0x45 0x67 +# CHECK: cache 1, 8($5) +0x20 0x25 0x60 0x08 + +# CHECK: pref 1, 8($5) +0x60 0x25 0x20 0x08 + +# CHECK: ssnop +0x00 0x00 0x08 0x00 + +# CHECK: ehb +0x00 0x00 0x18 0x00 + +# CHECK: pause +0x00 0x00 0x28 0x00 + # CHECK: ll $2, 8($4) 0x60 0x44 0x30 0x08 Index: test/MC/Disassembler/Mips/micromips_le.txt =================================================================== --- test/MC/Disassembler/Mips/micromips_le.txt +++ test/MC/Disassembler/Mips/micromips_le.txt @@ -310,6 +310,21 @@ # CHECK: tnei $9, 17767 0x89 0x41 0x67 0x45 +# CHECK: cache 1, 8($5) +0x25 0x20 0x08 0x60 + +# CHECK: pref 1, 8($5) +0x25 0x60 0x08 0x20 + +# CHECK: ssnop +0x00 0x00 0x00 0x08 + +# CHECK: ehb +0x00 0x00 0x00 0x18 + +# CHECK: pause +0x00 0x00 0x00 0x28 + # CHECK: ll $2, 8($4) 0x44 0x60 0x08 0x30 Index: test/MC/Mips/micromips-control-instructions.s =================================================================== --- test/MC/Mips/micromips-control-instructions.s +++ test/MC/Mips/micromips-control-instructions.s @@ -15,6 +15,11 @@ # CHECK-EL: .set mips32r2 # CHECK-EL: rdhwr $5, $29 # CHECK-EL: .set pop # encoding: [0xbd,0x00,0x3c,0x6b] +# CHECK-EL: cache 1, 8($5) # encoding: [0x25,0x20,0x08,0x60] +# CHECK-EL: pref 1, 8($5) # encoding: [0x25,0x60,0x08,0x20] +# CHECK-EL: ssnop # encoding: [0x00,0x00,0x00,0x08] +# CHECK-EL: ehb # encoding: [0x00,0x00,0x00,0x18] +# CHECK-EL: pause # encoding: [0x00,0x00,0x00,0x28] # CHECK-EL: break # encoding: [0x00,0x00,0x07,0x00] # CHECK-EL: break 7 # encoding: [0x07,0x00,0x07,0x00] # CHECK-EL: break 7, 5 # encoding: [0x07,0x00,0x47,0x01] @@ -43,6 +48,11 @@ # CHECK-EB: .set mips32r2 # CHECK-EB: rdhwr $5, $29 # CHECK-EB: .set pop # encoding: [0x00,0xbd,0x6b,0x3c] +# CHECK-EB: cache 1, 8($5) # encoding: [0x20,0x25,0x60,0x08] +# CHECK-EB: pref 1, 8($5) # encoding: [0x60,0x25,0x20,0x08] +# CHECK-EB: ssnop # encoding: [0x00,0x00,0x08,0x00] +# CHECK-EB: ehb # encoding: [0x00,0x00,0x18,0x00] +# CHECK-EB: pause # encoding: [0x00,0x00,0x28,0x00] # CHECK-EB: break # encoding: [0x00,0x00,0x00,0x07] # CHECK-EB: break 7 # encoding: [0x00,0x07,0x00,0x07] # CHECK-EB: break 7, 5 # encoding: [0x00,0x07,0x01,0x47] @@ -66,6 +76,11 @@ sdbbp sdbbp 34 rdhwr $5, $29 + cache 1, 8($5) + pref 1, 8($5) + ssnop + ehb + pause break break 7 break 7,5 Index: test/MC/Mips/micromips-invalid.s =================================================================== --- test/MC/Mips/micromips-invalid.s +++ test/MC/Mips/micromips-invalid.s @@ -65,3 +65,5 @@ sb16 $7, 4($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction sh16 $7, 8($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction sw16 $7, 4($10) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + cache 256, 8($5) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + pref 256, 8($5) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range