Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -340,6 +340,10 @@ uint64_t Address, const void *Decoder); +static DecodeStatus DecodeFMemMMR6(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeFMem2(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); @@ -352,6 +356,10 @@ uint64_t Address, const void *Decoder); +static DecodeStatus DecodeFMemCop2MMR6(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1592,6 +1600,22 @@ return MCDisassembler::Success; } +static DecodeStatus DecodeFMemMMR6(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + int Offset = SignExtend32<16>(Insn & 0xffff); + unsigned Base = fieldFromInstruction(Insn, 16, 5); + unsigned Reg = fieldFromInstruction(Insn, 21, 5); + + Reg = getReg(Decoder, Mips::FGR64RegClassID, Reg); + Base = getReg(Decoder, Mips::GPR32RegClassID, Base); + + Inst.addOperand(MCOperand::createReg(Reg)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); + + return MCDisassembler::Success; +} + static DecodeStatus DecodeFMem2(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1645,6 +1669,22 @@ return MCDisassembler::Success; } + +static DecodeStatus DecodeFMemCop2MMR6(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + int Offset = SignExtend32<11>(Insn & 0x07ff); + unsigned Reg = fieldFromInstruction(Insn, 21, 5); + unsigned Base = fieldFromInstruction(Insn, 16, 5); + + Reg = getReg(Decoder, Mips::COP2RegClassID, Reg); + Base = getReg(Decoder, Mips::GPR32RegClassID, Base); + + Inst.addOperand(MCOperand::createReg(Reg)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); + + return MCDisassembler::Success; +} static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst, unsigned Insn, uint64_t Address, Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -182,6 +182,9 @@ unsigned getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -797,6 +797,19 @@ } unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Base register is encoded in bits 20-16, offset is encoded in bits 10-0. + assert(MI.getOperand(OpNo).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, + STI) << 16; + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); + + return (OffBits & 0x07FF) | RegBits; +} + +unsigned MipsMCCodeEmitter:: getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { Index: lib/Target/Mips/MicroMips32r6InstrFormats.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrFormats.td +++ lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -916,3 +916,35 @@ let Inst{15-6} = funct; let Inst{5-0} = 0b111100; } + +class LDWC1_SDWC1_FM_MMR6 funct> + : MMR6Arch { + bits<5> ft; + bits<21> addr; + bits<5> base = addr{20-16}; + bits<16> offset = addr{15-0}; + + bits<32> Inst; + + let Inst{31-26} = funct; + let Inst{25-21} = ft; + let Inst{20-16} = base; + let Inst{15-0} = offset; +} + +class POOL32B_LDWC2_SDWC2_FM_MMR6 funct> + : MMR6Arch, MipsR6Inst { + bits<5> rt; + bits<21> addr; + bits<5> base = addr{20-16}; + bits<11> offset = addr{10-0}; + + bits<32> Inst; + + let Inst{31-26} = 0b001000; + let Inst{25-21} = rt; + let Inst{20-16} = base; + let Inst{15-12} = funct; + let Inst{11} = 0; + let Inst{10-0} = offset; +} Index: lib/Target/Mips/MicroMips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrInfo.td +++ lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -47,6 +47,10 @@ class BGEZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<0b110000>; class BLEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b110000>; class CACHE_MMR6_ENC : CACHE_PREF_FM_MMR6<0b001000, 0b0110>; +class CFC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"cfc1", 0b01000000>; +class CFC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"cfc2", 0b1100110100>; +class CTC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"ctc1", 0b01100000>; +class CTC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"ctc2", 0b1101110100>; class CLO_MMR6_ENC : POOL32A_2R_FM_MMR6<0b0100101100>; class CLZ_MMR6_ENC : SPECIAL_2R_FM_MMR6<0b010000>; class DIV_MMR6_ENC : ARITH_FM_MMR6<"div", 0x118>; @@ -62,6 +66,8 @@ class JIC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b101000>; class JRC16_MMR6_ENC: POOL16C_JALRC_FM_MM16R6<0x3>; class JRCADDIUSP_MMR6_ENC : POOL16C_JRCADDIUSP_FM_MM16R6<0x13>; +class LDC1_MMR6_ENC : LDWC1_SDWC1_FM_MMR6<"ldc1", 0b101111>; +class LDC2_MMR6_ENC : POOL32B_LDWC2_SDWC2_FM_MMR6<"ldc2", 0b0010>; class LSA_MMR6_ENC : POOL32A_LSA_FM<0b001111>; class LWPC_MMR6_ENC : PCREL19_FM_MMR6<0b01>; class LWM16_MMR6_ENC : POOL16C_LWM_SWM_FM_MM16R6<0x2>; @@ -617,6 +623,48 @@ HARDFLOAT, FGR_64; class MTHC2_MMR6_DESC : MTC2_MMR6_DESC_BASE<"mthc2", COP2Opnd, GPR32Opnd>; +class CFC1_MMR6_DESC : MTC1_MMR6_DESC_BASE<"cfc1", GPR32Opnd, CCROpnd, II_CFC1>, + HARDFLOAT; +class CFC2_MMR6_DESC : MTC2_MMR6_DESC_BASE<"cfc2", GPR32Opnd, COP2Opnd>; +class CTC1_MMR6_DESC : MTC1_MMR6_DESC_BASE<"ctc1", CCROpnd, GPR32Opnd, II_CTC1>, + HARDFLOAT; +class CTC2_MMR6_DESC : MTC2_MMR6_DESC_BASE<"ctc2", COP2Opnd, GPR32Opnd>; + +class LDWC1_DESC_BASE< + string opstr, RegisterOperand RC, InstrItinClass Itin, + SDPatternOperator OpNode = null_frag> : MipsR6Inst, HARDFLOAT { + dag InOperandList = (ins mem_mm_16:$addr); + dag OutOperandList = (outs RC:$ft); + string AsmString = !strconcat(opstr, "\t$ft, $addr"); + list Pattern = [(set RC:$ft, (OpNode addrDefault:$addr))]; + Format f = FrmFI; + InstrItinClass Itinerary = Itin; + string BaseOpcode = opstr; + bit mayLoad = 1; + let DecoderMethod = "DecodeFMemMMR6"; +} +class LDC1_D32_MMR6_DESC : LDWC1_DESC_BASE< + "ldc1", AFGR64Opnd, II_LDC1, load>, FGR_32; +class LDC1_D64_MMR6_DESC : LDWC1_DESC_BASE< + "ldc1", FGR64Opnd, II_LDC1, load>, FGR_64; + +class COP2LD_MMR6_DESC_BASE< + string opstr, RegisterOperand COPOpnd, InstrItinClass Itin, + SDPatternOperator OpNode = null_frag> { + dag OutOperandList = (outs COPOpnd:$rt); + dag InOperandList = (ins mem_mm_11:$addr); + string AsmString = !strconcat(opstr, "\t$rt, $addr"); + list Pattern = [(set COPOpnd:$rt, (OpNode addrDefault:$addr))]; + Format f = FrmFI; + InstrItinClass Itinerary = Itin; + string BaseOpcode = opstr; + bit mayLoad = 1; + string DecoderMethod = "DecodeFMemCop2MMR6"; +} + +class LDC2_MMR6_DESC : COP2LD_MMR6_DESC_BASE<"ldc2", COP2Opnd, NoItinerary, + load>; + /// Floating Point Instructions class FARITH_MMR6_DESC_BASE, LW_FM_MM<0x27>; def SWC1_MM : MMRel, SW_FT<"swc1", FGR32Opnd, II_SWC1, store>, LW_FM_MM<0x26>; -def LDC1_MM : MMRel, LW_FT<"ldc1", AFGR64Opnd, II_LDC1, load>, LW_FM_MM<0x2f>; def SDC1_MM : MMRel, SW_FT<"sdc1", AFGR64Opnd, II_SDC1, store>, LW_FM_MM<0x2e>; def LWXC1_MM : MMRel, LWXC1_FT<"lwxc1", FGR32Opnd, II_LWXC1, load>, @@ -147,4 +146,9 @@ fsqrt>, ROUND_W_FM_MM<0, 0x28>; def MTHC1_MM : MMRel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, MFC1_FM_MM<0xe0>, ISA_MIPS32R2, FGR_32; + def LDC1_MM : MMRel, LW_FT<"ldc1", AFGR64Opnd, II_LDC1, load>, + LW_FM_MM<0x2f>, FGR_32{ + let DecoderNamespace = "MicroMips"; + let DecoderMethod = "DecodeFMemMMR6"; + } } Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -96,6 +96,14 @@ let OperandType = "OPERAND_MEMORY"; } +def mem_mm_11 : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops ptr_rc, simm11); + let EncoderMethod = "getMemEncodingMMImm11"; + let ParserMatchClass = MipsMemSimm11AsmOperand; + let OperandType = "OPERAND_MEMORY"; +} + def mem_mm_12 : Operand { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops ptr_rc, simm12); Index: lib/Target/Mips/Mips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/Mips32r6InstrInfo.td +++ lib/Target/Mips/Mips32r6InstrInfo.td @@ -753,7 +753,9 @@ def JIALC : R6MMR6Rel, JIALC_ENC, JIALC_DESC, ISA_MIPS32R6; def JIC : R6MMR6Rel, JIC_ENC, JIC_DESC, ISA_MIPS32R6; def JR_HB_R6 : JR_HB_R6_ENC, JR_HB_R6_DESC, ISA_MIPS32R6; -def LDC2_R6 : LDC2_R6_ENC, LDC2_R6_DESC, ISA_MIPS32R6; +let AdditionalPredicates = [NotInMicroMips] in { + def LDC2_R6 : LDC2_R6_ENC, LDC2_R6_DESC, ISA_MIPS32R6; +} def LL_R6 : LL_R6_ENC, LL_R6_DESC, ISA_MIPS32R6; def LSA_R6 : R6MMR6Rel, LSA_R6_ENC, LSA_R6_DESC, ISA_MIPS32R6; def LWC2_R6 : LWC2_R6_ENC, LWC2_R6_DESC, ISA_MIPS32R6; Index: lib/Target/Mips/MipsInstrFPU.td =================================================================== --- lib/Target/Mips/MipsInstrFPU.td +++ lib/Target/Mips/MipsInstrFPU.td @@ -402,14 +402,17 @@ def SWC1 : MMRel, SW_FT<"swc1", FGR32Opnd, II_SWC1, store>, LW_FM<0x39>; let DecoderNamespace = "Mips64" in { - def LDC164 : LW_FT<"ldc1", FGR64Opnd, II_LDC1, load>, LW_FM<0x35>, ISA_MIPS2, - FGR_64; + let AdditionalPredicates = [NotInMicroMips] in { + def LDC164 : LW_FT<"ldc1", FGR64Opnd, II_LDC1, load>, LW_FM<0x35>, + ISA_MIPS2, FGR_64; + } def SDC164 : SW_FT<"sdc1", FGR64Opnd, II_SDC1, store>, LW_FM<0x3d>, ISA_MIPS2, FGR_64; } - -def LDC1 : MMRel, LW_FT<"ldc1", AFGR64Opnd, II_LDC1, load>, LW_FM<0x35>, - ISA_MIPS2, FGR_32; +let AdditionalPredicates = [NotInMicroMips] in { + def LDC1 : MMRel, StdMMR6Rel, LW_FT<"ldc1", AFGR64Opnd, II_LDC1, load>, + LW_FM<0x35>, ISA_MIPS2, FGR_32; +} def SDC1 : MMRel, SW_FT<"sdc1", AFGR64Opnd, II_SDC1, store>, LW_FM<0x3d>, ISA_MIPS2, FGR_32; Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -1085,9 +1085,9 @@ } // COP2 Load/Store -class LW_FT2 : - InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + InstSE<(outs RC:$rt), (ins MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"), [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr> { let DecoderMethod = "DecodeFMem2"; let mayLoad = 1; @@ -1640,11 +1640,11 @@ let AdditionalPredicates = [NotInMicroMips] in { // COP2 Memory Instructions -def LWC2 : LW_FT2<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>, +def LWC2 : LW_FT2<"lwc2", COP2Opnd, mem, NoItinerary, load>, LW_FM<0x32>, ISA_MIPS1_NOT_32R6_64R6; def SWC2 : SW_FT2<"swc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3a>, ISA_MIPS1_NOT_32R6_64R6; -def LDC2 : LW_FT2<"ldc2", COP2Opnd, NoItinerary, load>, LW_FM<0x36>, +def LDC2 : StdMMR6Rel, LW_FT2<"ldc2", COP2Opnd, mem_simm16, NoItinerary, load>, LW_FM<0x36>, ISA_MIPS2_NOT_32R6_64R6; def SDC2 : SW_FT2<"sdc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3e>, ISA_MIPS2_NOT_32R6_64R6; Index: test/MC/Disassembler/Mips/micromips32r6/valid.txt =================================================================== --- test/MC/Disassembler/Mips/micromips32r6/valid.txt +++ test/MC/Disassembler/Mips/micromips32r6/valid.txt @@ -268,3 +268,9 @@ 0x01 0x2a 0x0a 0xf4 # CHECK: mthc0 $9, $10, 1 0x55 0x6c 0x38 0x3b # CHECK: mthc1 $11, $f12 0x01 0xae 0x9d 0x3c # CHECK: mthc2 $13, $14 +0x54 0x22 0x10 0x3b # CHECK: cfc1 $1, $2 +0x00 0x64 0xcd 0x3c # CHECK: cfc2 $3, $4 +0x54 0xa6 0x18 0x3b # CHECK: ctc1 $5, $6 +0x00 0xe8 0xdd 0x3c # CHECK: ctc2 $7, $8 +0xbd 0x0a 0x01 0x2c # CHECK: ldc1 $f8, 300($10) +0x21 0x6c 0x23 0xff # CHECK: ldc2 $11, 1023($12) Index: test/MC/Mips/micromips32r6/invalid-wrong-error.s =================================================================== --- test/MC/Mips/micromips32r6/invalid-wrong-error.s +++ test/MC/Mips/micromips32r6/invalid-wrong-error.s @@ -25,3 +25,5 @@ tne $8, $9, $2 # CHECK: :[[@LINE]]:15: error: expected 10-bit unsigned immediate tne $8, $9, -1 # CHECK: :[[@LINE]]:15: error: expected 10-bit unsigned immediate tne $8, $9, 16 # CHECK: :[[@LINE]]:3: error: instruction requires a CPU feature not currently enabled + ldc2 $11, -1025($12) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + ldc2 $11, 1024($12) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled Index: test/MC/Mips/micromips32r6/valid.s =================================================================== --- test/MC/Mips/micromips32r6/valid.s +++ test/MC/Mips/micromips32r6/valid.s @@ -267,3 +267,9 @@ mthc0 $9, $10, 1 # CHECK: mthc0 $9, $10, 1 # encoding: [0x01,0x2a,0x0a,0xf4] mthc1 $11, $f12 # CHECK: mthc1 $11, $f12 # encoding: [0x55,0x6c,0x38,0x3b] mthc2 $13, $14 # CHECK: mthc2 $13, $14 # encoding: [0x01,0xae,0x9d,0x3c] + cfc1 $1, $2 # CHECK: cfc1 $1, $2 # encoding: [0x54,0x22,0x10,0x3b] + cfc2 $3, $4 # CHECK: cfc2 $3, $4 # encoding: [0x00,0x64,0xcd,0x3c] + ctc1 $5, $6 # CHECK: ctc1 $5, $6 # encoding: [0x54,0xa6,0x18,0x3b] + ctc2 $7, $8 # CHECK: ctc2 $7, $8 # encoding: [0x00,0xe8,0xdd,0x3c] + ldc1 $f8, 300($10) # CHECK: ldc1 $f8, 300($10) # encoding: [0xbd,0x0a,0x01,0x2c] + ldc2 $11, 1023($12) # CHECK: ldc2 $11, 1023($12) # encoding: [0x21,0x6c,0x23,0xff] Index: test/MC/Mips/mips32r5/invalid.s =================================================================== --- test/MC/Mips/mips32r5/invalid.s +++ test/MC/Mips/mips32r5/invalid.s @@ -20,3 +20,5 @@ mfc0 $4, $3, 8 # CHECK: :[[@LINE]]:23: error: expected 3-bit unsigned immediate mfc2 $4, $3, -1 # CHECK: :[[@LINE]]:23: error: expected 3-bit unsigned immediate mfc2 $4, $3, 8 # CHECK: :[[@LINE]]:23: error: expected 3-bit unsigned immediate + ldc2 $11, -32769($12) # CHECK: :[[@LINE]]:19: error: invalid operand for instruction + ldc2 $11, 32768($12) # CHECK: :[[@LINE]]:19: error: invalid operand for instruction Index: test/MC/Mips/mips32r6/invalid.s =================================================================== --- test/MC/Mips/mips32r6/invalid.s +++ test/MC/Mips/mips32r6/invalid.s @@ -13,6 +13,7 @@ jalr.hb $31 # CHECK: :[[@LINE]]:9: error: source and destination must be different jalr.hb $31, $31 # CHECK: :[[@LINE]]:9: error: source and destination must be different ldc2 $8,-21181($at) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + ldc2 $11, 1024($12) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled sdc2 $20,23157($s2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled swc2 $25,24880($s0) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled break -1 # CHECK: :[[@LINE]]:15: error: expected 10-bit unsigned immediate Index: test/MC/Mips/mips64r5/invalid.s =================================================================== --- test/MC/Mips/mips64r5/invalid.s +++ test/MC/Mips/mips64r5/invalid.s @@ -18,3 +18,5 @@ dmtc0 $4, $3, 8 # CHECK: :[[@LINE]]:24: error: expected 3-bit unsigned immediate dmfc0 $4, $3, -1 # CHECK: :[[@LINE]]:24: error: expected 3-bit unsigned immediate dmfc0 $4, $3, 8 # CHECK: :[[@LINE]]:24: error: expected 3-bit unsigned immediate + ldc2 $11, -32769($12) # CHECK: :[[@LINE]]:19: error: invalid operand for instruction + ldc2 $11, 32768($12) # CHECK: :[[@LINE]]:19: error: invalid operand for instruction Index: test/MC/Mips/mips64r6/invalid.s =================================================================== --- test/MC/Mips/mips64r6/invalid.s +++ test/MC/Mips/mips64r6/invalid.s @@ -13,6 +13,7 @@ jalr.hb $31 # CHECK: :[[@LINE]]:9: error: source and destination must be different jalr.hb $31, $31 # CHECK: :[[@LINE]]:9: error: source and destination must be different ldc2 $8,-21181($at) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + ldc2 $11, 1024($12) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled break -1 # CHECK: :[[@LINE]]:15: error: expected 10-bit unsigned immediate break 1024 # CHECK: :[[@LINE]]:15: error: expected 10-bit unsigned immediate break -1, 5 # CHECK: :[[@LINE]]:15: error: expected 10-bit unsigned immediate