Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -57,18 +57,24 @@ public: /// Constructor - Initializes the disassembler. /// - MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, - bool bigEndian) : - MipsDisassemblerBase(STI, Ctx, bigEndian) { - IsMicroMips = STI.getFeatureBits() & Mips::FeatureMicroMips; - } + MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool bigEndian) + : MipsDisassemblerBase(STI, Ctx, bigEndian) { + IsMicroMips = STI.getFeatureBits() & Mips::FeatureMicroMips; + } - bool isMips32r6() const { + bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; } + bool hasMips32() const { return STI.getFeatureBits() & Mips::FeatureMips32; } + bool hasMips32r6() const { return STI.getFeatureBits() & Mips::FeatureMips32r6; } bool isGP64() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; } + bool hasCOP3() const { + // Only present in MIPS-I and MIPS-II + return !hasMips32() && !hasMips3(); + } + /// getInstruction - See MCDisassembler. DecodeStatus getInstruction(MCInst &instr, uint64_t &size, @@ -690,7 +696,17 @@ return MCDisassembler::Fail; } - if (isMips32r6() && isGP64()) { + if (hasCOP3()) { + DEBUG(dbgs() << "Trying COP3_ table (32-bit opcodes):\n"); + Result = + decodeInstruction(DecoderTableCOP3_32, instr, Insn, Address, this, STI); + if (Result != MCDisassembler::Fail) { + Size = 4; + return Result; + } + } + + if (hasMips32r6() && isGP64()) { DEBUG(dbgs() << "Trying Mips32r6_64r6 (GPR64) table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMips32r6_64r6_GP6432, instr, Insn, Address, this, STI); @@ -700,7 +716,7 @@ } } - if (isMips32r6()) { + if (hasMips32r6()) { DEBUG(dbgs() << "Trying Mips32r6_64r6 table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMips32r6_64r632, instr, Insn, Address, this, STI); Index: lib/Target/Mips/Mips32r6InstrFormats.td =================================================================== --- lib/Target/Mips/Mips32r6InstrFormats.td +++ lib/Target/Mips/Mips32r6InstrFormats.td @@ -74,6 +74,8 @@ def OPCODE6_BITSWAP : OPCODE6<0b100000>; def OPCODE6_DBITSWAP : OPCODE6<0b100100>; def OPCODE6_JALR : OPCODE6<0b001001>; +def OPCODE6_CACHE : OPCODE6<0b100101>; +def OPCODE6_PREF : OPCODE6<0b110101>; class FIELD_FMT Val> { bits<5> Value = Val; @@ -260,6 +262,22 @@ let Inst{5-0} = Operation.Value; } +class SPECIAL3_MEM_FM : MipsR6Inst { + bits<21> addr; + bits<5> hint; + bits<5> base = addr{20-16}; + bits<9> offset = addr{8-0}; + + bits<32> Inst; + + let Inst{31-26} = OPGROUP_SPECIAL3.Value; + let Inst{25-21} = base; + let Inst{20-16} = hint; + let Inst{15-7} = offset; + let Inst{6} = 0; + let Inst{5-0} = Operation.Value; +} + class SPECIAL_3R_FM mulop, bits<6> funct> : MipsR6Inst { bits<5> rd; bits<5> rs; Index: lib/Target/Mips/Mips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/Mips32r6InstrInfo.td +++ lib/Target/Mips/Mips32r6InstrInfo.td @@ -15,7 +15,6 @@ // Notes about removals/changes from MIPS32r6: // Unclear: ssnop -// Reencoded: cache, pref // Reencoded: clo, clz // Reencoded: jr -> jalr // Reencoded: jr.hb -> jalr.hb @@ -150,6 +149,9 @@ class CLASS_S_ENC : COP1_2R_FM<0b011011, FIELD_FMT_S>; class CLASS_D_ENC : COP1_2R_FM<0b011011, FIELD_FMT_D>; +class CACHE_ENC : SPECIAL3_MEM_FM; +class PREF_ENC : SPECIAL3_MEM_FM; + class CMP_CONDN_DESC_BASE { @@ -520,6 +522,17 @@ class CLASS_S_DESC : CLASS_RINT_DESC_BASE<"class.s", FGR32Opnd>; class CLASS_D_DESC : CLASS_RINT_DESC_BASE<"class.d", FGR64Opnd>; +class CACHE_HINT_DESC { + dag OutOperandList = (outs); + dag InOperandList = (ins MemOpnd:$addr, uimm5:$hint); + string AsmString = !strconcat(instr_asm, "\t$hint, $addr"); + list Pattern = []; +} + +class CACHE_DESC : CACHE_HINT_DESC<"cache", mem_simm9, GPR32Opnd>; +class PREF_DESC : CACHE_HINT_DESC<"pref", mem_simm9, GPR32Opnd>; + //===----------------------------------------------------------------------===// // // Instruction Definitions @@ -559,6 +572,7 @@ def BNEZC : BNEZC_ENC, BNEZC_DESC, ISA_MIPS32R6; def BNVC : BNVC_ENC, BNVC_DESC, ISA_MIPS32R6; def BOVC : BOVC_ENC, BOVC_DESC, ISA_MIPS32R6; +def CACHE_R6 : CACHE_ENC, CACHE_DESC, ISA_MIPS32R6; def CLASS_D : CLASS_D_ENC, CLASS_D_DESC, ISA_MIPS32R6; def CLASS_S : CLASS_S_ENC, CLASS_S_DESC, ISA_MIPS32R6; defm S : CMP_CC_M; @@ -590,6 +604,7 @@ def MUL_R6 : MUL_R6_ENC, MUL_R6_DESC, ISA_MIPS32R6; def MULU : MULU_ENC, MULU_DESC, ISA_MIPS32R6; def NAL; // BAL with rd=0 +def PREF_R6 : PREF_ENC, PREF_DESC, ISA_MIPS32R6; def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6; def RINT_S : RINT_S_ENC, RINT_S_DESC, ISA_MIPS32R6; def SELEQZ : SELEQZ_ENC, SELEQZ_DESC, ISA_MIPS32R6, GPR_32; Index: lib/Target/Mips/MipsInstrFPU.td =================================================================== --- lib/Target/Mips/MipsInstrFPU.td +++ lib/Target/Mips/MipsInstrFPU.td @@ -411,10 +411,14 @@ // Cop3 Memory Instructions // FIXME: These aren't really FPU instructions and as such don't belong in this // file -def LWC3 : LW_FT<"lwc3", COP3Opnd, NoItinerary, load>, LW_FM<0x33>; -def SWC3 : SW_FT<"swc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3b>; -def LDC3 : LW_FT<"ldc3", COP3Opnd, NoItinerary, load>, LW_FM<0x37>, ISA_MIPS2; -def SDC3 : SW_FT<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>, ISA_MIPS2; +let DecoderNamespace = "COP3_" in { + def LWC3 : LW_FT<"lwc3", COP3Opnd, NoItinerary, load>, LW_FM<0x33>; + def SWC3 : SW_FT<"swc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3b>; + def LDC3 : LW_FT<"ldc3", COP3Opnd, NoItinerary, load>, LW_FM<0x37>, + ISA_MIPS2; + def SDC3 : SW_FT<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>, + ISA_MIPS2; +} // Indexed loads and stores. // Base register + offset register addressing mode (indicated by "x" in the Index: lib/Target/Mips/MipsInstrFormats.td =================================================================== --- lib/Target/Mips/MipsInstrFormats.td +++ lib/Target/Mips/MipsInstrFormats.td @@ -880,3 +880,17 @@ let Inst{24-6} = 0; let Inst{5-0} = op; // Operation } + +class CACHEOP_FM op> : StdArch { + bits<21> addr; + bits<5> hint; + bits<5> base = addr{20-16}; + bits<16> offset = addr{15-0}; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = base; + let Inst{20-16} = hint; + let Inst{15-0} = offset; +} Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -247,6 +247,12 @@ // The portions of MIPS-III that were also added to MIPS32 class INSN_MIPS3_32 { list InsnPredicates = [HasMips3_32]; } +// The portions of MIPS-III that were also added to MIPS32 but were removed in +// MIPS32r6 and MIPS64r6. +class INSN_MIPS3_32_NOT_32R6_64R6 { + list InsnPredicates = [HasMips3_32, NotMips32r6, NotMips64r6]; +} + // The portions of MIPS-III that were also added to MIPS32 class INSN_MIPS3_32R2 { list InsnPredicates = [HasMips3_32r2]; } @@ -343,6 +349,7 @@ let ParserMatchClass = MipsJumpTargetAsmOperand; } +def simm9 : Operand; def simm10 : Operand; def simm16 : Operand { @@ -437,6 +444,11 @@ let EncoderMethod = "getMSAMemEncoding"; } +def mem_simm9 : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm9); + let EncoderMethod = "getMemEncoding"; +} + def mem_ea : Operand { let PrintMethod = "printMemOperandEA"; let MIOperandInfo = (ops ptr_rc, simm16); @@ -1359,6 +1371,15 @@ def TLBWI : TLB<"tlbwi">, COP0_TLB_FM<0x02>; def TLBWR : TLB<"tlbwr">, COP0_TLB_FM<0x06>; +class CacheOp : + InstSE<(outs), (ins MemOpnd:$addr, uimm5:$hint), + !strconcat(instr_asm, "\t$hint, $addr"), [], NoItinerary, FrmOther>; + +def CACHE : CacheOp<"cache", mem, GPR32Opnd>, CACHEOP_FM<0b101111>, + INSN_MIPS3_32_NOT_32R6_64R6; +def PREF : CacheOp<"pref", mem, GPR32Opnd>, CACHEOP_FM<0b110011>, + INSN_MIPS3_32_NOT_32R6_64R6; + //===----------------------------------------------------------------------===// // Instruction aliases //===----------------------------------------------------------------------===// Index: test/MC/Mips/mips3/valid.s =================================================================== --- test/MC/Mips/mips3/valid.s +++ test/MC/Mips/mips3/valid.s @@ -19,6 +19,7 @@ bgezal $0, 21100 # CHECK: bal 21100 # encoding: [0x04,0x11,0x14,0x9b] bgezal $6, 21100 # CHECK: bgezal $6, 21100 # encoding: [0x04,0xd1,0x14,0x9b] bltzal $6, 21100 # CHECK: bltzal $6, 21100 # encoding: [0x04,0xd0,0x14,0x9b] + cache 1, 8($5) # CHECK: cache 1, 8($5) # encoding: [0xbc,0xa1,0x00,0x08] c.ngl.d $f29,$f29 c.ngle.d $f0,$f16 c.sf.d $f30,$f0 Index: test/MC/Mips/mips32/valid.s =================================================================== --- test/MC/Mips/mips32/valid.s +++ test/MC/Mips/mips32/valid.s @@ -21,6 +21,7 @@ bgezal $0, 21100 # CHECK: bal 21100 # encoding: [0x04,0x11,0x14,0x9b] bgezal $6, 21100 # CHECK: bgezal $6, 21100 # encoding: [0x04,0xd1,0x14,0x9b] bltzal $6, 21100 # CHECK: bltzal $6, 21100 # encoding: [0x04,0xd0,0x14,0x9b] + cache 1, 8($5) # CHECK: cache 1, 8($5) # encoding: [0xbc,0xa1,0x00,0x08] c.ngl.d $f29,$f29 c.ngle.d $f0,$f16 c.sf.d $f30,$f0 @@ -106,6 +107,7 @@ nop nor $a3,$zero,$a3 or $12,$s0,$sp + pref 1, 8($5) # CHECK: pref 1, 8($5) # encoding: [0xcc,0xa1,0x00,0x08] round.w.d $f6,$f4 round.w.s $f27,$f28 sb $s6,-19857($14) Index: test/MC/Mips/mips32r2/valid.s =================================================================== --- test/MC/Mips/mips32r2/valid.s +++ test/MC/Mips/mips32r2/valid.s @@ -21,6 +21,7 @@ bgezal $0, 21100 # CHECK: bal 21100 # encoding: [0x04,0x11,0x14,0x9b] bgezal $6, 21100 # CHECK: bgezal $6, 21100 # encoding: [0x04,0xd1,0x14,0x9b] bltzal $6, 21100 # CHECK: bltzal $6, 21100 # encoding: [0x04,0xd0,0x14,0x9b] + cache 1, 8($5) # CHECK: cache 1, 8($5) # encoding: [0xbc,0xa1,0x00,0x08] c.ngl.d $f29,$f29 c.ngle.d $f0,$f16 c.sf.d $f30,$f0 @@ -127,6 +128,7 @@ nor $a3,$zero,$a3 or $12,$s0,$sp pause # CHECK: pause # encoding: [0x00,0x00,0x01,0x40] + pref 1, 8($5) # CHECK: pref 1, 8($5) # encoding: [0xcc,0xa1,0x00,0x08] rdhwr $sp,$11 rotr $1,15 # CHECK: rotr $1, $1, 15 # encoding: [0x00,0x21,0x0b,0xc2] rotr $1,$14,15 # CHECK: rotr $1, $14, 15 # encoding: [0x00,0x2e,0x0b,0xc2] Index: test/MC/Mips/mips32r6/valid.s =================================================================== --- test/MC/Mips/mips32r6/valid.s +++ test/MC/Mips/mips32r6/valid.s @@ -57,6 +57,7 @@ bovc $0, $0, 4 # CHECK: bovc $zero, $zero, 4 # encoding: [0x20,0x00,0x00,0x01] bovc $2, $0, 4 # CHECK: bovc $2, $zero, 4 # encoding: [0x20,0x40,0x00,0x01] bovc $4, $2, 4 # CHECK: bovc $4, $2, 4 # encoding: [0x20,0x82,0x00,0x01] + cache 1, 8($5) # CHECK: cache 1, 8($5) # encoding: [0x7c,0xa1,0x04,0x25] cmp.f.s $f2,$f3,$f4 # CHECK: cmp.f.s $f2, $f3, $f4 # encoding: [0x46,0x84,0x18,0x80] cmp.f.d $f2,$f3,$f4 # CHECK: cmp.f.d $f2, $f3, $f4 # encoding: [0x46,0xa4,0x18,0x80] cmp.un.s $f2,$f3,$f4 # CHECK: cmp.un.s $f2, $f3, $f4 # encoding: [0x46,0x84,0x18,0x81] @@ -105,6 +106,7 @@ maddf.d $f2,$f3,$f4 # CHECK: maddf.d $f2, $f3, $f4 # encoding: [0x46,0x24,0x18,0x98] msubf.s $f2,$f3,$f4 # CHECK: msubf.s $f2, $f3, $f4 # encoding: [0x46,0x04,0x18,0x99] msubf.d $f2,$f3,$f4 # CHECK: msubf.d $f2, $f3, $f4 # encoding: [0x46,0x24,0x18,0x99] + pref 1, 8($5) # CHECK: pref 1, 8($5) # encoding: [0x7c,0xa1,0x04,0x35] sel.d $f0,$f1,$f2 # CHECK: sel.d $f0, $f1, $f2 # encoding: [0x46,0x22,0x08,0x10] sel.s $f0,$f1,$f2 # CHECK: sel.s $f0, $f1, $f2 # encoding: [0x46,0x02,0x08,0x10] seleqz $2,$3,$4 # CHECK: seleqz $2, $3, $4 # encoding: [0x00,0x64,0x10,0x35] Index: test/MC/Mips/mips4/valid.s =================================================================== --- test/MC/Mips/mips4/valid.s +++ test/MC/Mips/mips4/valid.s @@ -21,6 +21,7 @@ bgezal $0, 21100 # CHECK: bal 21100 # encoding: [0x04,0x11,0x14,0x9b] bgezal $6, 21100 # CHECK: bgezal $6, 21100 # encoding: [0x04,0xd1,0x14,0x9b] bltzal $6, 21100 # CHECK: bltzal $6, 21100 # encoding: [0x04,0xd0,0x14,0x9b] + cache 1, 8($5) # CHECK: cache 1, 8($5) # encoding: [0xbc,0xa1,0x00,0x08] c.ngl.d $f29,$f29 c.ngle.d $f0,$f16 c.sf.d $f30,$f0 @@ -149,6 +150,7 @@ nop nor $a3,$zero,$a3 or $12,$s0,$sp + pref 1, 8($5) # CHECK: pref 1, 8($5) # encoding: [0xcc,0xa1,0x00,0x08] round.l.d $f12,$f1 round.l.s $f25,$f5 round.w.d $f6,$f4 Index: test/MC/Mips/mips5/valid.s =================================================================== --- test/MC/Mips/mips5/valid.s +++ test/MC/Mips/mips5/valid.s @@ -21,6 +21,7 @@ bgezal $0, 21100 # CHECK: bal 21100 # encoding: [0x04,0x11,0x14,0x9b] bgezal $6, 21100 # CHECK: bgezal $6, 21100 # encoding: [0x04,0xd1,0x14,0x9b] bltzal $6, 21100 # CHECK: bltzal $6, 21100 # encoding: [0x04,0xd0,0x14,0x9b] + cache 1, 8($5) # CHECK: cache 1, 8($5) # encoding: [0xbc,0xa1,0x00,0x08] c.ngl.d $f29,$f29 c.ngle.d $f0,$f16 c.sf.d $f30,$f0 @@ -150,6 +151,7 @@ nop nor $a3,$zero,$a3 or $12,$s0,$sp + pref 1, 8($5) # CHECK: pref 1, 8($5) # encoding: [0xcc,0xa1,0x00,0x08] round.l.d $f12,$f1 round.l.s $f25,$f5 round.w.d $f6,$f4 Index: test/MC/Mips/mips64/valid.s =================================================================== --- test/MC/Mips/mips64/valid.s +++ test/MC/Mips/mips64/valid.s @@ -21,6 +21,7 @@ bgezal $0, 21100 # CHECK: bal 21100 # encoding: [0x04,0x11,0x14,0x9b] bgezal $6, 21100 # CHECK: bgezal $6, 21100 # encoding: [0x04,0xd1,0x14,0x9b] bltzal $6, 21100 # CHECK: bltzal $6, 21100 # encoding: [0x04,0xd0,0x14,0x9b] + cache 1, 8($5) # CHECK: cache 1, 8($5) # encoding: [0xbc,0xa1,0x00,0x08] c.ngl.d $f29,$f29 c.ngle.d $f0,$f16 c.sf.d $f30,$f0 @@ -164,6 +165,7 @@ nop nor $a3,$zero,$a3 or $12,$s0,$sp + pref 1, 8($5) # CHECK: pref 1, 8($5) # encoding: [0xcc,0xa1,0x00,0x08] round.l.d $f12,$f1 round.l.s $f25,$f5 round.w.d $f6,$f4 Index: test/MC/Mips/mips64r2/valid.s =================================================================== --- test/MC/Mips/mips64r2/valid.s +++ test/MC/Mips/mips64r2/valid.s @@ -21,6 +21,7 @@ bgezal $0, 21100 # CHECK: bal 21100 # encoding: [0x04,0x11,0x14,0x9b] bgezal $6, 21100 # CHECK: bgezal $6, 21100 # encoding: [0x04,0xd1,0x14,0x9b] bltzal $6, 21100 # CHECK: bltzal $6, 21100 # encoding: [0x04,0xd0,0x14,0x9b] + cache 1, 8($5) # CHECK: cache 1, 8($5) # encoding: [0xbc,0xa1,0x00,0x08] c.ngl.d $f29,$f29 c.ngle.d $f0,$f16 c.sf.d $f30,$f0 @@ -185,6 +186,7 @@ nor $a3,$zero,$a3 or $12,$s0,$sp pause # CHECK: pause # encoding: [0x00,0x00,0x01,0x40] + pref 1, 8($5) # CHECK: pref 1, 8($5) # encoding: [0xcc,0xa1,0x00,0x08] rdhwr $sp,$11 rotr $1,15 # CHECK: rotr $1, $1, 15 # encoding: [0x00,0x21,0x0b,0xc2] rotr $1,$14,15 # CHECK: rotr $1, $14, 15 # encoding: [0x00,0x2e,0x0b,0xc2] Index: test/MC/Mips/mips64r6/valid.s =================================================================== --- test/MC/Mips/mips64r6/valid.s +++ test/MC/Mips/mips64r6/valid.s @@ -57,6 +57,7 @@ bovc $0, $0, 4 # CHECK: bovc $zero, $zero, 4 # encoding: [0x20,0x00,0x00,0x01] bovc $2, $0, 4 # CHECK: bovc $2, $zero, 4 # encoding: [0x20,0x40,0x00,0x01] bovc $4, $2, 4 # CHECK: bovc $4, $2, 4 # encoding: [0x20,0x82,0x00,0x01] + cache 1, 8($5) # CHECK: cache 1, 8($5) # encoding: [0x7c,0xa1,0x04,0x25] cmp.f.s $f2,$f3,$f4 # CHECK: cmp.f.s $f2, $f3, $f4 # encoding: [0x46,0x84,0x18,0x80] cmp.f.d $f2,$f3,$f4 # CHECK: cmp.f.d $f2, $f3, $f4 # encoding: [0x46,0xa4,0x18,0x80] cmp.un.s $f2,$f3,$f4 # CHECK: cmp.un.s $f2, $f3, $f4 # encoding: [0x46,0x84,0x18,0x81] @@ -119,6 +120,7 @@ maddf.d $f2,$f3,$f4 # CHECK: maddf.d $f2, $f3, $f4 # encoding: [0x46,0x24,0x18,0x98] msubf.s $f2,$f3,$f4 # CHECK: msubf.s $f2, $f3, $f4 # encoding: [0x46,0x04,0x18,0x99] msubf.d $f2,$f3,$f4 # CHECK: msubf.d $f2, $f3, $f4 # encoding: [0x46,0x24,0x18,0x99] + pref 1, 8($5) # CHECK: pref 1, 8($5) # encoding: [0x7c,0xa1,0x04,0x35] sel.d $f0,$f1,$f2 # CHECK: sel.d $f0, $f1, $f2 # encoding: [0x46,0x22,0x08,0x10] sel.s $f0,$f1,$f2 # CHECK: sel.s $f0, $f1, $f2 # encoding: [0x46,0x02,0x08,0x10] seleqz $2,$3,$4 # CHECK: seleqz $2, $3, $4 # encoding: [0x00,0x64,0x10,0x35]