Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -900,6 +900,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(); } @@ -3442,6 +3446,12 @@ SMLoc E = Parser.getTok().getLoc(); MipsOperand &Op = static_cast(*Operands.back()); + + if (!Op.isGPRAsmReg()) { + Error(E, "invalid operand for instruction"); + return MatchOperand_ParseFail; + } + unsigned Reg = Op.getGPR32Reg(); Operands.pop_back(); Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this)); Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -1323,7 +1323,9 @@ // 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 @@ -240,3 +240,31 @@ let Inst{15-6} = 0x3cd; let Inst{5-0} = 0x3c; } + +class LWM_FM_MMR6 funct> : MipsR6Inst { + bits<5> rd; + bits<21> addr; + + bits<32> Inst; + + let Inst{31-26} = 0x8; + let Inst{25-21} = rd; + let Inst{20-16} = addr{20-16}; + let Inst{15-12} = funct; + let Inst{11-0} = addr{11-0}; +} + +class LWXS_MMR6_ENC : MipsR6Inst { + bits<5> rd; + bits<5> base; + bits<5> index; + + bits<32> Inst; + + let Inst{31-26} = 0x0; + let Inst{25-21} = index; + let Inst{20-16} = base; + let Inst{15-11} = rd; + let Inst{10} = 0; + let Inst{9-0} = 0x100; +} Index: lib/Target/Mips/MicroMips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrInfo.td +++ lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -45,6 +45,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>; @@ -62,6 +63,7 @@ class SELNEZ_MMR6_ENC : POOL32A_FM_MMR6<0b0110000000>; 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>; @@ -245,6 +247,49 @@ 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 LWXS_MMR6_DESC_BASE + : MMR6Arch { + dag OutOperandList = (outs RO:$rd); + dag InOperandList = (ins PtrRC:$base, PtrRC:$index); + string AsmString = !strconcat(instr_asm, "\t$rd, ${index}(${base})"); + list Pattern = []; + InstrItinClass Itin = NoItinerary; + SDPatternOperator OpNode = null_frag; + Format f = FrmFI; + string BaseOpcode = instr_asm; +} +class LWXS_MMR6_DESC : LWXS_MMR6_DESC_BASE<"lwxs", GPR32Opnd>; + +class LWP_MMR6_DESC_BASE + : MMR6Arch { + dag OutOperandList = (outs regpair:$rd); + dag InOperandList = (ins mem_simm12gpr:$addr); + string AsmString = !strconcat(instr_asm, "\t$rd, $addr"); + list Pattern = []; + InstrItinClass Itin = NoItinerary; + ComplexPattern Addr = addr; + Format f = FrmI; + string BaseOpcode = instr_asm; + string DecoderMethod = "DecodeMemMMImm12"; + bit mayLoad = 1; +} +class LWP_MMR6_DESC : LWP_MMR6_DESC_BASE<"lwp">; + +class SWP_MMR6_DESC_BASE + : MMR6Arch { + dag OutOperandList = (outs); + dag InOperandList = (ins regpair:$rd, mem_simm12gpr:$addr); + string AsmString = !strconcat(instr_asm, "\t$rd, $addr"); + list Pattern = []; + InstrItinClass Itin = NoItinerary; + ComplexPattern Addr = addr; + Format f = FrmI; + string BaseOpcode = instr_asm; + string DecoderMethod = "DecodeMemMMImm12"; + bit mayStore = 1; +} +class SWP_MMR6_DESC : SWP_MMR6_DESC_BASE<"swp">; + class SELEQNE_Z_MMR6_DESC_BASE : MMR6Arch { dag OutOperandList = (outs GPROpnd:$rd); @@ -313,7 +358,9 @@ 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 LWXS_MMR6 : StdMMR6Rel, LWXS_MMR6_ENC, LWXS_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; def MUL_MMR6 : R6MMR6Rel, MUL_MMR6_DESC, MUL_MMR6_ENC, ISA_MICROMIPS32R6; @@ -332,6 +379,7 @@ 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"; } @@ -230,7 +244,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 +252,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 @@ -56,8 +56,12 @@ 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 0x64 0x11 0x00 # CHECK: lwxs $2, $3($4) + 0x00 0x43 0x26 0x0f # CHECK: lsa $2, $3, $4, 3 0x00 0xa4 0x19 0x58 # CHECK: mod $3, $4, $5 @@ -88,6 +92,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,12 @@ 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 + lwxs $33, $3($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lwxs $2, $34($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lwxs $2, $3($34) # 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 =================================================================== --- /dev/null +++ test/MC/Mips/micromips32r6/invalid.s @@ -0,0 +1,12 @@ +# RUN: not llvm-mc %s -triple=mips -show-encoding -mcpu=mips32r6 -mattr=micromips 2>%t1 +# RUN: FileCheck %s < %t1 + + 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 + lwxs $33, $3($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lwxs $2, $34($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lwxs $2, $3($34) # 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 @@ -30,7 +30,9 @@ 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] + lwxs $2, $3($4) # CHECK: lwxs $2, $3($4) # encoding: [0x00,0x64,0x11,0x00] 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] mul $3, $4, $5 # CHECK mul $3, $4, $5 # encoding: [0x00,0xa4,0x18,0x18] @@ -47,6 +49,7 @@ selnez $2,$3,$4 # CHECK: selnez $2, $3, $4 # encoding: [0x00,0x83,0x11,0x80] 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]