Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -967,6 +967,12 @@ && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP); } + bool isUImm5Lsl2() const { + if (!isImm() || !isConstantImm()) + return false; + int64_t val = getConstantImm(); + return val >= 0 && val <= 32; + } bool isRegList16() const { if (!isRegList()) return false; @@ -1945,7 +1951,7 @@ if (Opcode == Mips::JalOneReg) { // jal $rs => jalr $rs if (inMicroMipsMode()) { - JalrInst.setOpcode(Mips::JALR16_MM); + JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM); JalrInst.addOperand(FirstRegOp); } else { JalrInst.setOpcode(Mips::JALR); @@ -1961,16 +1967,13 @@ } Instructions.push_back(JalrInst); - // If .set reorder is active, emit a NOP after it. - if (AssemblerOptions.back()->isReorder()) { + // If .set reorder is active and branch instruction has a delay slot, + // emit a NOP after it. + const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode()); + if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) { // This is a 32-bit NOP because these 2 pseudo-instructions // do not have a short delay slot. - MCInst NopInst; - NopInst.setOpcode(Mips::SLL); - NopInst.addOperand(MCOperand::createReg(Mips::ZERO)); - NopInst.addOperand(MCOperand::createReg(Mips::ZERO)); - NopInst.addOperand(MCOperand::createImm(0)); - Instructions.push_back(NopInst); + createNop(false, IDLoc, Instructions); } return false; Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -836,8 +836,21 @@ if (IsMicroMips) { Result = readInstruction16(Bytes, Address, Size, Insn, IsBigEndian); + if (hasMips32r6()) { + DEBUG(dbgs() << "Trying MicroMipsR616 table (16-bit instructions):\n"); + // Calling the auto-generated decoder function for microMIPS32R6 + // (and microMIPS64R6) 16-bit instructions. + Result = decodeInstruction(DecoderTableMicroMipsR616, Instr, Insn, + Address, this, STI); + if (Result != MCDisassembler::Fail) { + Size = 2; + return Result; + } + } + DEBUG(dbgs() << "Trying MicroMips16 table (16-bit instructions):\n"); - // Calling the auto-generated decoder function. + // Calling the auto-generated decoder function for microMIPS 16-bit + // instructions. Result = decodeInstruction(DecoderTableMicroMips16, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) { @@ -854,13 +867,16 @@ // Calling the auto-generated decoder function. Result = decodeInstruction(DecoderTableMicroMipsR632, Instr, Insn, Address, this, STI); - } else { - DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n"); - // Calling the auto-generated decoder function. - Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address, - this, STI); + if (Result != MCDisassembler::Fail) { + Size = 4; + return Result; + } } + DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n"); + // Calling the auto-generated decoder function. + Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address, + this, STI); if (Result != MCDisassembler::Fail) { Size = 4; return Result; Index: lib/Target/Mips/MicroMips32r6InstrFormats.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrFormats.td +++ lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -16,6 +16,32 @@ string BaseOpcode = opstr; } +// Class used for microMIPS32r6 and microMIPS64r6 instructions. +class MicroMipsR6Inst16 : PredicateControl { + string DecoderNamespace = "MicroMipsR6"; + let InsnPredicates = [HasMicroMips32r6]; +} + +class POOL16C_JALRC_FM_MM16R6 op> { + bits<5> rs; + + bits<16> Inst; + + let Inst{15-10} = 0x11; + let Inst{9-5} = rs; + let Inst{4-0} = op; +} + +class POOL16C_JRCADDIUSP_FM_MM16R6 op> { + bits<5> imm; + + bits<16> Inst; + + let Inst{15-10} = 0x11; + let Inst{9-5} = imm; + let Inst{4-0} = op; +} + class POOL32A_BITSWAP_FM_MMR6 funct> : MipsR6Inst { bits<5> rd; bits<5> rt; Index: lib/Target/Mips/MicroMips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrInfo.td +++ lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -45,8 +45,11 @@ class EI_MMR6_ENC : EIDI_MMR6_ENC<"ei", 0x15d>; class ERET_MMR6_ENC : ERET_FM_MMR6<"eret">; class ERETNC_MMR6_ENC : ERETNC_FM_MMR6<"eretnc">; +class JALRC16_MMR6_ENC : POOL16C_JALRC_FM_MM16R6<0xb>; class JIALC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b100000>; 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 LSA_MMR6_ENC : POOL32A_LSA_FM<0b001111>; class LWPC_MMR6_ENC : PCREL19_FM_MMR6<0b01>; class MOD_MMR6_ENC : ARITH_FM_MMR6<"mod", 0x158>; @@ -200,6 +203,16 @@ class ERET_MMR6_DESC : ER_FT<"eret">; class ERETNC_MMR6_DESC : ER_FT<"eretnc">; +class JALRC16_MMR6_DESC_BASE + : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), + [(MipsJmpLink RO:$rs)], IIBranch, FrmR>, + MMR6Arch, MicroMipsR6Inst16 { + let isCall = 1; + let hasDelaySlot = 0; + let Defs = [RA]; +} +class JALRC16_MMR6_DESC : JALRC16_MMR6_DESC_BASE<"jalr", GPR32Opnd>; + class JMP_MMR6_IDX_COMPACT_DESC_BASE : MMR6Arch { @@ -222,6 +235,27 @@ list Defs = [AT]; } +class JRC16_MMR6_DESC_BASE + : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), + [], IIBranch, FrmR>, + MMR6Arch, MicroMipsR6Inst16 { + let hasDelaySlot = 0; + let isBranch = 1; + let isIndirectBranch = 1; +} +class JRC16_MMR6_DESC : JRC16_MMR6_DESC_BASE<"jrc16", GPR32Opnd>; + +class JRCADDIUSP_MMR6_DESC + : MicroMipsInst16<(outs), (ins uimm5_lsl2:$imm), "jrcaddiusp\t$imm", + [], IIBranch, FrmR>, + MMR6Arch<"jrcaddiusp">, MicroMipsR6Inst16 { + let hasDelaySlot = 0; + let isTerminator = 1; + let isBarrier = 1; + let isBranch = 1; + let isIndirectBranch = 1; +} + class ALIGN_MMR6_DESC_BASE : MMR6Arch { dag OutOperandList = (outs GPROpnd:$rd); @@ -357,8 +391,13 @@ def ERET_MMR6 : R6MMR6Rel, ERET_MMR6_DESC, ERET_MMR6_ENC, ISA_MICROMIPS32R6; def ERETNC_MMR6 : R6MMR6Rel, ERETNC_MMR6_DESC, ERETNC_MMR6_ENC, ISA_MICROMIPS32R6; +def JALRC16_MMR6 : R6MMR6Rel, JALRC16_MMR6_DESC, JALRC16_MMR6_ENC, + ISA_MICROMIPS32R6; 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 JRC16_MMR6 : R6MMR6Rel, JRC16_MMR6_DESC, JRC16_MMR6_ENC, ISA_MICROMIPS32R6; +def JRCADDIUSP_MMR6 : R6MMR6Rel, JRCADDIUSP_MMR6_DESC, JRCADDIUSP_MMR6_ENC, + ISA_MICROMIPS32R6; def LSA_MMR6 : R6MMR6Rel, LSA_MMR6_ENC, LSA_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; Index: lib/Target/Mips/MicroMipsInstrFormats.td =================================================================== --- lib/Target/Mips/MicroMipsInstrFormats.td +++ lib/Target/Mips/MicroMipsInstrFormats.td @@ -37,6 +37,12 @@ bits<6> Opcode = 0x0; } +// Class used for separating microMIPSr6 and microMIPS (r3) instruction. +// It can be used only on instructions that doesn't inherit PredicateControl. +class MicroMipsNotMips32r6 : PredicateControl { + let InsnPredicates = [InMicroMips, NotMips32r6]; +} + //===----------------------------------------------------------------------===// // MicroMIPS 16-bit Instruction Formats //===----------------------------------------------------------------------===// Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -13,9 +13,17 @@ let DecoderMethod = "DecodeSimm12"; } +def MipsUimm5Lsl2AsmOperand : AsmOperandClass { + let Name = "Uimm5Lsl2"; + let RenderMethod = "addImmOperands"; + let ParserMethod = "parseImm"; + let PredicateMethod = "isUImm5Lsl2"; +} + def uimm5_lsl2 : Operand { let EncoderMethod = "getUImm5Lsl2Encoding"; let DecoderMethod = "DecodeUImm5lsl2"; + let ParserMatchClass = MipsUimm5Lsl2AsmOperand; } def uimm6_lsl2 : Operand { @@ -597,7 +605,8 @@ def MOVEP_MM : MovePMM16<"movep", GPRMM16OpndMoveP>, MOVEP_FM_MM16; def LI16_MM : LoadImmMM16<"li16", li_simm7, GPRMM16Opnd>, LI_FM_MM16, IsAsCheapAsAMove; -def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>; +def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>, + MicroMipsNotMips32r6; def JALRS16_MM : JumpLinkRegSMM16<"jalrs16", GPR32Opnd>, JALR_FM_MM16<0x0f>; def JRC16_MM : JumpRegCMM16<"jrc", GPR32Opnd>, JALR_FM_MM16<0x0d>; def JRADDIUSP : JumpRAddiuStackMM16, JRADDIUSP_FM_MM16<0x18>; Index: test/MC/Disassembler/Mips/micromips32r6.txt =================================================================== --- test/MC/Disassembler/Mips/micromips32r6.txt +++ test/MC/Disassembler/Mips/micromips32r6.txt @@ -82,10 +82,16 @@ 0x00 0x01 0xf3 0x7c # CHECK: eretnc +0x45 0x2b # CHECK: jalr $9 + 0x80 0x05 0x01 0x00 # CHECK: jialc $5, 256 0xa0 0x05 0x01 0x00 # CHECK: jic $5, 256 +0x45 0x23 # CHECK: jrc16 $9 + +0x44 0xb3 # CHECK: jrcaddiusp 20 + 0x78 0x48 0x00 0x43 # CHECK: lwpc $2, 268 0x00 0x43 0x26 0x0f # CHECK: lsa $2, $3, $4, 3 Index: test/MC/Disassembler/Mips/micromips64r6.txt =================================================================== --- test/MC/Disassembler/Mips/micromips64r6.txt +++ test/MC/Disassembler/Mips/micromips64r6.txt @@ -39,3 +39,9 @@ 0x58 0x64 0x29 0x98 # CHECK: ddivu $3, $4, $5 0x58 0x64 0x29 0xd8 # CHECK: dmodu $3, $4, $5 + +0x45 0x2b # CHECK: jalr $9 + +0x45 0x23 # CHECK: jrc16 $9 + +0x44 0xb3 # CHECK: jrcaddiusp 20 Index: test/MC/Mips/micromips32r6/invalid.s =================================================================== --- test/MC/Mips/micromips32r6/invalid.s +++ test/MC/Mips/micromips32r6/invalid.s @@ -14,3 +14,4 @@ swe $33, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction swe $5, 8($34) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction swe $5, 512($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jraddiusp 33 # 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 @@ -43,8 +43,11 @@ ei $10 # CHECK: ei $10 # encoding: [0x00,0x0a,0x57,0x7c] eret # CHECK: eret # encoding: [0x00,0x00,0xf3,0x7c] eretnc # CHECK: eretnc # encoding: [0x00,0x01,0xf3,0x7c] + jalr $9 # CHECK: jalr $9 # encoding: [0x45,0x2b] jialc $5, 256 # CHECK: jialc $5, 256 # encoding: [0x80,0x05,0x01,0x00] jic $5, 256 # CHECK: jic $5, 256 # encoding: [0xa0,0x05,0x01,0x00] + jrc16 $9 # CHECK: jrc16 $9 # encoding: [0x45,0x23] + jrcaddiusp 20 # CHECK: jrcaddiusp 20 # encoding: [0x44,0xb3] lsa $2, $3, $4, 3 # CHECK: lsa $2, $3, $4, 3 # encoding: [0x00,0x43,0x26,0x0f] 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] Index: test/MC/Mips/micromips64r6/invalid.s =================================================================== --- test/MC/Mips/micromips64r6/invalid.s +++ test/MC/Mips/micromips64r6/invalid.s @@ -20,3 +20,4 @@ dmodu $32, $4, $5 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction dmodu $3, $34, $5 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction dmodu $3, $4, $35 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jraddiusp 33 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction Index: test/MC/Mips/micromips64r6/valid.s =================================================================== --- test/MC/Mips/micromips64r6/valid.s +++ test/MC/Mips/micromips64r6/valid.s @@ -21,5 +21,8 @@ dmod $3, $4, $5 # CHECK: dmod $3, $4, $5 # encoding: [0x58,0x64,0x29,0x58] ddivu $3, $4, $5 # CHECK: ddivu $3, $4, $5 # encoding: [0x58,0x64,0x29,0x98] dmodu $3, $4, $5 # CHECK: dmodu $3, $4, $5 # encoding: [0x58,0x64,0x29,0xd8] + jalr $9 # CHECK: jalr $9 # encoding: [0x45,0x2b] + jrc16 $9 # CHECK: jrc16 $9 # encoding: [0x45,0x23] + jrcaddiusp 20 # CHECK: jrcaddiusp 20 # encoding: [0x44,0xb3] 1: