Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -551,6 +551,7 @@ struct RegIdxOp { unsigned Index; /// Index into the register class + unsigned ParsedRegNum; /// Parsed register number RegKind Kind; /// Bitfield of the kinds it could possibly be const MCRegisterInfo *RegInfo; }; @@ -941,6 +942,10 @@ template bool isMemWithSimmOffset() const { return isMem() && isConstantMemOff() && isInt(getConstantMemOff()); } + template bool isMemWithSimmOffsetGPR() const { + return isMem() && isConstantMemOff() && isInt(getConstantMemOff()) + && getMemBase()->isGPRAsmReg(); + } bool isMemWithGRPMM16Base() const { return isMem() && getMemBase()->isMM16AsmReg(); } @@ -1004,7 +1009,9 @@ assert(Kind == k_Token && "Invalid access!"); return StringRef(Tok.Data, Tok.Length); } - bool isRegPair() const { return Kind == k_RegPair; } + bool isRegPair() const { + return Kind == k_RegPair && RegIdx.ParsedRegNum <= 31; + } unsigned getReg() const override { // As a special case until we sort out the definition of div/divu, pretend @@ -1159,9 +1166,14 @@ } static std::unique_ptr - CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { + CreateRegPair(MipsOperand MOP, SMLoc S, SMLoc E, MipsAsmParser &Parser) { + unsigned ClassID = Mips::GPR32RegClassID; + unsigned Idx = + MOP.RegIdx.RegInfo->getRegClass(ClassID).RegsBegin[MOP.RegIdx.Index]; + auto Op = make_unique(k_RegPair, Parser); - Op->RegIdx.Index = RegNo; + Op->RegIdx.Index = Idx; + Op->RegIdx.ParsedRegNum = MOP.RegIdx.Index; Op->StartLoc = S; Op->EndLoc = E; return Op; @@ -3664,9 +3676,9 @@ SMLoc E = Parser.getTok().getLoc(); MipsOperand &Op = static_cast(*Operands.back()); - unsigned Reg = Op.getGPR32Reg(); + Operands.pop_back(); - Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this)); + Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this)); return MatchOperand_Success; } Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -1328,7 +1328,8 @@ // fallthrough default: Inst.addOperand(MCOperand::createReg(Reg)); - if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) + if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM + || Inst.getOpcode() == Mips::LWP_MMR6 || Inst.getOpcode() == Mips::SWP_MMR6) Inst.addOperand(MCOperand::createReg(Reg+1)); Inst.addOperand(MCOperand::createReg(Base)); Index: lib/Target/Mips/MicroMips32r6InstrFormats.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrFormats.td +++ lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -287,3 +287,19 @@ let Inst{10} = rotate; let Inst{9-0} = funct; } + +class LWM_FM_MMR6 funct> : MipsR6Inst { + bits<5> rd; + bits<21> addr; + bits<5> base = addr{20-16}; + bits<12> offset = addr{11-0}; + + bits<32> Inst; + + let Inst{31-26} = 0x8; + let Inst{25-21} = rd; + let Inst{20-16} = base; + let Inst{15-12} = funct; + let Inst{11-0} = offset; +} + Index: lib/Target/Mips/MicroMips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrInfo.td +++ lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -48,6 +48,7 @@ class JIALC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b100000>; class JIC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b101000>; class LSA_MMR6_ENC : POOL32A_LSA_FM<0b001111>; +class LWP_MMR6_ENC : LWM_FM_MMR6<0x1>; class LWPC_MMR6_ENC : PCREL19_FM_MMR6<0b01>; class MOD_MMR6_ENC : ARITH_FM_MMR6<"mod", 0x158>; class MODU_MMR6_ENC : ARITH_FM_MMR6<"modu", 0x1d8>; @@ -66,6 +67,7 @@ class SLL_MMR6_ENC : SHIFT_MMR6_ENC<"sll", 0x00, 0b0>; class SUB_MMR6_ENC : ARITH_FM_MMR6<"sub", 0x190>; class SUBU_MMR6_ENC : ARITH_FM_MMR6<"subu", 0x1d0>; +class SWP_MMR6_ENC : LWM_FM_MMR6<0x9>; class XOR_MMR6_ENC : ARITH_FM_MMR6<"xor", 0x310>; class XORI_MMR6_ENC : ADDI_FM_MMR6<"xori", 0x1c>; @@ -254,6 +256,32 @@ class ADDIUPC_MMR6_DESC : PCREL_MMR6_DESC_BASE<"addiupc", GPR32Opnd, simm19_lsl2>; class LWPC_MMR6_DESC: PCREL_MMR6_DESC_BASE<"lwpc", GPR32Opnd, simm19_lsl2>; +class LWP_MMR6_DESC : MMR6Arch<"lwp"> { + dag OutOperandList = (outs regpair:$rd); + dag InOperandList = (ins mem_simm12gpr:$addr); + string AsmString = !strconcat("lwp", "\t$rd, $addr"); + list Pattern = []; + InstrItinClass Itin = NoItinerary; + ComplexPattern Addr = addr; + Format f = FrmI; + string BaseOpcode = "lwp"; + string DecoderMethod = "DecodeMemMMImm12"; + bit mayLoad = 1; +} + +class SWP_MMR6_DESC : MMR6Arch<"swp"> { + dag OutOperandList = (outs); + dag InOperandList = (ins regpair:$rd, mem_simm12gpr:$addr); + string AsmString = !strconcat("swp", "\t$rd, $addr"); + list Pattern = []; + InstrItinClass Itin = NoItinerary; + ComplexPattern Addr = addr; + Format f = FrmI; + string BaseOpcode = "swp"; + string DecoderMethod = "DecodeMemMMImm12"; + bit mayStore = 1; +} + class SELEQNE_Z_MMR6_DESC_BASE : MMR6Arch { dag OutOperandList = (outs GPROpnd:$rd); @@ -326,6 +354,7 @@ def JIALC_MMR6 : R6MMR6Rel, JIALC_MMR6_ENC, JIALC_MMR6_DESC, ISA_MICROMIPS32R6; def JIC_MMR6 : R6MMR6Rel, JIC_MMR6_ENC, JIC_MMR6_DESC, ISA_MICROMIPS32R6; def LSA_MMR6 : R6MMR6Rel, LSA_MMR6_ENC, LSA_MMR6_DESC, ISA_MICROMIPS32R6; +def LWP_MMR6 : StdMMR6Rel, LWP_MMR6_ENC, LWP_MMR6_DESC, ISA_MICROMIPS32R6; def LWPC_MMR6 : R6MMR6Rel, LWPC_MMR6_ENC, LWPC_MMR6_DESC, ISA_MICROMIPS32R6; def MOD_MMR6 : R6MMR6Rel, MOD_MMR6_DESC, MOD_MMR6_ENC, ISA_MICROMIPS32R6; def MODU_MMR6 : R6MMR6Rel, MODU_MMR6_DESC, MODU_MMR6_ENC, ISA_MICROMIPS32R6; @@ -346,6 +375,7 @@ def SLL_MMR6 : StdMMR6Rel, SLL_MMR6_DESC, SLL_MMR6_ENC, ISA_MICROMIPS32R6; def SUB_MMR6 : StdMMR6Rel, SUB_MMR6_DESC, SUB_MMR6_ENC, ISA_MICROMIPS32R6; def SUBU_MMR6 : StdMMR6Rel, SUBU_MMR6_DESC, SUBU_MMR6_ENC, ISA_MICROMIPS32R6; +def SWP_MMR6 : StdMMR6Rel, SWP_MMR6_ENC, SWP_MMR6_DESC, ISA_MICROMIPS32R6; def XOR_MMR6 : StdMMR6Rel, XOR_MMR6_DESC, XOR_MMR6_ENC, ISA_MICROMIPS32R6; def XORI_MMR6 : StdMMR6Rel, XORI_MMR6_DESC, XORI_MMR6_ENC, ISA_MICROMIPS32R6; } Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -129,6 +129,20 @@ let OperandType = "OPERAND_MEMORY"; } +def MipsMemSimm12GPRAsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm12GPR"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmOffsetGPR<12>"; +} + +def mem_simm12gpr : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm12); + let EncoderMethod = "getMemEncoding"; + let ParserMatchClass = MipsMemSimm12GPRAsmOperand; +} + def jmptarget_mm : Operand { let EncoderMethod = "getJumpTargetOpValueMM"; } @@ -218,6 +232,7 @@ def RegPairAsmOperand : AsmOperandClass { let Name = "RegPair"; let ParserMethod = "parseRegisterPair"; + let PredicateMethod = "isRegPair"; } def regpair : Operand { @@ -230,7 +245,7 @@ class StorePairMM : - InstSE<(outs), (ins regpair:$rt, mem_mm_12:$addr), + InstSE<(outs), (ins regpair:$rt, mem_simm12gpr:$addr), !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMemMMImm12"; let mayStore = 1; @@ -238,7 +253,7 @@ class LoadPairMM : - InstSE<(outs regpair:$rt), (ins mem_mm_12:$addr), + InstSE<(outs regpair:$rt), (ins mem_simm12gpr:$addr), !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMemMMImm12"; let mayLoad = 1; Index: test/MC/Disassembler/Mips/micromips32r6.txt =================================================================== --- test/MC/Disassembler/Mips/micromips32r6.txt +++ test/MC/Disassembler/Mips/micromips32r6.txt @@ -68,6 +68,8 @@ 0xa0 0x05 0x01 0x00 # CHECK: jic $5, 256 +0x22 0x04 0x10 0x08 # CHECK: lwp $16, 8($4) + 0x78 0x48 0x00 0x43 # CHECK: lwpc $2, 268 0x00 0x43 0x26 0x0f # CHECK: lsa $2, $3, $4, 3 @@ -104,6 +106,8 @@ 0x00 0xa4 0x19 0xd0 # CHECK: subu $3, $4, $5 +0x22 0x04 0x90 0x08 # CHECK: swp $16, 8($4) + 0x00 0xa4 0x1b 0x10 # CHECK: xor $3, $4, $5 0x70 0x64 0x04 0xd2 # CHECK: xori $3, $4, 1234 Index: test/MC/Mips/micromips-invalid.s =================================================================== --- test/MC/Mips/micromips-invalid.s +++ test/MC/Mips/micromips-invalid.s @@ -78,3 +78,9 @@ break 7, 1024 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction break 1024, 1024 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction wait 1024 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lwp $33, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lwp $16, 8($34) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lwp $16, 4096($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + swp $33, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + swp $16, 8($34) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + swp $16, 4096($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction Index: test/MC/Mips/micromips32r6/invalid.s =================================================================== --- test/MC/Mips/micromips32r6/invalid.s +++ test/MC/Mips/micromips32r6/invalid.s @@ -4,3 +4,9 @@ break 1024 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction break 1023, 1024 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction ei $32 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lwp $33, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lwp $16, 8($34) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lwp $16, 4096($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + swp $33, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + swp $16, 8($34) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + swp $16, 4096($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction Index: test/MC/Mips/micromips32r6/valid.s =================================================================== --- test/MC/Mips/micromips32r6/valid.s +++ test/MC/Mips/micromips32r6/valid.s @@ -37,6 +37,7 @@ jialc $5, 256 # CHECK: jialc $5, 256 # encoding: [0x80,0x05,0x01,0x00] jic $5, 256 # CHECK: jic $5, 256 # encoding: [0xa0,0x05,0x01,0x00] lsa $2, $3, $4, 3 # CHECK: lsa $2, $3, $4, 3 # encoding: [0x00,0x43,0x26,0x0f] + lwp $16, 8($4) # CHECK: lwp $16, 8($4) # encoding: [0x22,0x04,0x10,0x08] lwpc $2,268 # CHECK: lwpc $2, 268 # encoding: [0x78,0x48,0x00,0x43] mod $3, $4, $5 # CHECK: mod $3, $4, $5 # encoding: [0x00,0xa4,0x19,0x58] modu $3, $4, $5 # CHECK: modu $3, $4, $5 # encoding: [0x00,0xa4,0x19,0xd8] @@ -56,6 +57,7 @@ sll $4, $3, 7 # CHECK: sll $4, $3, 7 # encoding: [0x00,0x83,0x38,0x00] sub $3, $4, $5 # CHECK: sub $3, $4, $5 # encoding: [0x00,0xa4,0x19,0x90] subu $3, $4, $5 # CHECK: subu $3, $4, $5 # encoding: [0x00,0xa4,0x19,0xd0] + swp $16, 8($4) # CHECK: swp $16, 8($4) # encoding: [0x22,0x04,0x90,0x08] xor $3, $4, $5 # CHECK: xor $3, $4, $5 # encoding: [0x00,0xa4,0x1b,0x10] xori $3, $4, 1234 # CHECK: xori $3, $4, 1234 # encoding: [0x70,0x64,0x04,0xd2]