Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1417,7 +1417,9 @@ return Error(IDLoc, "branch to misaligned address"); break; case Mips::BEQZ16_MM: + case Mips::BEQZC16_MMR6: case Mips::BNEZ16_MM: + case Mips::BNEZC16_MMR6: assert(MCID.getNumOperands() == 2 && "unexpected number of operands"); Offset = Inst.getOperand(1); if (!Offset.isImm()) @@ -1807,6 +1809,7 @@ case Mips::LoadAddrReg32: case Mips::LoadAddrReg64: case Mips::B_MM_Pseudo: + case Mips::B_MMR6_Pseudo: case Mips::LWM_MM: case Mips::SWM_MM: case Mips::JalOneReg: @@ -1857,6 +1860,7 @@ Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2), Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions); case Mips::B_MM_Pseudo: + case Mips::B_MMR6_Pseudo: return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions); case Mips::SWM_MM: case Mips::LWM_MM: @@ -2326,7 +2330,8 @@ if (isIntN(11, Offset.getImm())) { // If offset fits into 11 bits then this instruction becomes microMIPS // 16-bit unconditional branch instruction. - Inst.setOpcode(Mips::B16_MM); + if (inMicroMipsMode()) + Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM); } else { if (!isIntN(17, Offset.getImm())) Error(IDLoc, "branch target out of range"); @@ -2341,8 +2346,10 @@ } Instructions.push_back(Inst); - // If .set reorder is active, emit a NOP after the branch instruction. - 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(Inst.getOpcode()); + if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) createNop(true, 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 BC16_FM_MM16R6 { + bits<10> offset; + + bits<16> Inst; + + let Inst{15-10} = 0x33; + let Inst{9-0} = offset; +} + +class BEQZC_BNEZC_FM_MM16R6 op> : MicroMipsR6Inst16 { + bits<3> rs; + bits<7> offset; + + bits<16> Inst; + + let Inst{15-10} = op; + let Inst{9-7} = rs; + let Inst{6-0} = offset; +} + 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 @@ -28,6 +28,9 @@ class AUI_MMR6_ENC : AUI_FM_MMR6; class BALC_MMR6_ENC : BRANCH_OFF26_FM<0b101101>; class BC_MMR6_ENC : BRANCH_OFF26_FM<0b100101>; +class BC16_MMR6_ENC : BC16_FM_MM16R6; +class BEQZC16_MMR6_ENC : BEQZC_BNEZC_FM_MM16R6<0x23>; +class BNEZC16_MMR6_ENC : BEQZC_BNEZC_FM_MM16R6<0x2b>; class BITSWAP_MMR6_ENC : POOL32A_BITSWAP_FM_MMR6<0b101100>; class BRK_MMR6_ENC : BREAK_MMR6_ENC<"break">; class BEQZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b011101>; @@ -157,6 +160,29 @@ list Defs = [RA]; } class BC_MMR6_DESC : BC_MMR6_DESC_BASE<"bc", brtarget26>; + +class BC16_MMR6_DESC : MicroMipsInst16<(outs), (ins brtarget10_mm:$offset), + !strconcat("bc16", "\t$offset"), [], + IIBranch, FrmI>, + MMR6Arch<"bc16">, MicroMipsR6Inst16 { + let isBranch = 1; + let isTerminator = 1; + let isBarrier = 1; + let hasDelaySlot = 0; + let AdditionalPredicates = [RelocPIC]; + let Defs = [AT]; +} + +class BEQZC_BNEZC_MM16R6_DESC_BASE + : CBranchZeroMM, MMR6Arch { + let isBranch = 1; + let isTerminator = 1; + let hasDelaySlot = 0; + let Defs = [AT]; +} +class BEQZC16_MMR6_DESC : BEQZC_BNEZC_MM16R6_DESC_BASE<"beqzc16">; +class BNEZC16_MMR6_DESC : BEQZC_BNEZC_MM16R6_DESC_BASE<"bnezc16">; + class SUB_MMR6_DESC : ArithLogicR<"sub", GPR32Opnd>; class SUBU_MMR6_DESC : ArithLogicR<"subu", GPR32Opnd>; @@ -332,6 +358,11 @@ def AUI_MMR6 : R6MMR6Rel, AUI_MMR6_ENC, AUI_MMR6_DESC, ISA_MICROMIPS32R6; def BALC_MMR6 : R6MMR6Rel, BALC_MMR6_ENC, BALC_MMR6_DESC, ISA_MICROMIPS32R6; def BC_MMR6 : R6MMR6Rel, BC_MMR6_ENC, BC_MMR6_DESC, ISA_MICROMIPS32R6; +def BC16_MMR6 : StdMMR6Rel, BC16_MMR6_DESC, BC16_MMR6_ENC, ISA_MICROMIPS32R6; +def BEQZC16_MMR6 : StdMMR6Rel, BEQZC16_MMR6_DESC, BEQZC16_MMR6_ENC, + ISA_MICROMIPS32R6; +def BNEZC16_MMR6 : StdMMR6Rel, BNEZC16_MMR6_DESC, BNEZC16_MMR6_ENC, + ISA_MICROMIPS32R6; def BITSWAP_MMR6 : R6MMR6Rel, BITSWAP_MMR6_ENC, BITSWAP_MMR6_DESC, ISA_MICROMIPS32R6; def BEQZALC_MMR6 : R6MMR6Rel, BEQZALC_MMR6_ENC, BEQZALC_MMR6_DESC, @@ -398,3 +429,6 @@ def : MipsInstAlias<"ei", (EI_MMR6 ZERO), 1>, ISA_MICROMIPS32R6; def : MipsInstAlias<"nop", (SLL_MMR6 ZERO, ZERO, 0), 1>, ISA_MICROMIPS32R6; +def B_MMR6_Pseudo : MipsAsmPseudoInst<(outs), (ins brtarget_mm:$offset), + !strconcat("b", "\t$offset")>, + MicroMipsR6Inst16; Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -928,7 +928,7 @@ MipsAsmPseudoInst<(outs), (ins brtarget_mm:$offset), !strconcat(opstr, "\t$offset")>; - def B_MM_Pseudo : UncondBranchMMPseudo<"b">; +def B_MM_Pseudo : UncondBranchMMPseudo<"b">, ISA_MICROMIPS; def : MipsInstAlias<"wait", (WAIT_MM 0x0), 1>; def : MipsInstAlias<"nop", (SLL_MM ZERO, ZERO, 0), 1>; Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -254,6 +254,7 @@ class ISA_MIPS64R2 { list InsnPredicates = [HasMips64r2]; } class ISA_MIPS32R6 { list InsnPredicates = [HasMips32r6]; } class ISA_MIPS64R6 { list InsnPredicates = [HasMips64r6]; } +class ISA_MICROMIPS { list InsnPredicates = [InMicroMips]; } class ISA_MICROMIPS32R6 { list InsnPredicates = [HasMicroMips32r6]; } Index: test/MC/Disassembler/Mips/micromips32r6.txt =================================================================== --- test/MC/Disassembler/Mips/micromips32r6.txt +++ test/MC/Disassembler/Mips/micromips32r6.txt @@ -54,6 +54,12 @@ 0x94 0x37 0x96 0xb8 # CHECK: bc 14572256 +0xcc 0x42 # CHECK: bc16 132 + +0x8f 0x0a # CHECK: beqzc16 $6, 20 + +0xaf 0x0a # CHECK: bnezc16 $6, 20 + 0x00 0x44 0x0b 0x3c # CHECK: bitswap $4, $2 0x00 0x00 0x00 0x07 # CHECK: break Index: test/MC/Disassembler/Mips/micromips64r6.txt =================================================================== --- test/MC/Disassembler/Mips/micromips64r6.txt +++ test/MC/Disassembler/Mips/micromips64r6.txt @@ -18,6 +18,12 @@ 0x4f 0xf9 # CHECK: addiusp -16 +0xcc 0x42 # CHECK: bc16 132 + +0x8f 0x0a # CHECK: beqzc16 $6, 20 + +0xaf 0x0a # CHECK: bnezc16 $6, 20 + 0xf0 0x64 0x00 0x05 # CHECK: daui $3, $4, 5 0x42 0x23 0x00 0x04 # CHECK: dahi $3, 4 Index: test/MC/Mips/micromips32r6/invalid.s =================================================================== --- test/MC/Mips/micromips32r6/invalid.s +++ test/MC/Mips/micromips32r6/invalid.s @@ -8,6 +8,12 @@ addiur2 $6, $7, 10 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range addius5 $7, 9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range addiusp 1032 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + beqzc16 $9, 20 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + beqzc16 $6, 31 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch to misaligned address + beqzc16 $6, 130 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch target out of range + bnezc16 $9, 20 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + bnezc16 $6, 31 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch to misaligned address + bnezc16 $6, 130 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch target out of range 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 Index: test/MC/Mips/micromips32r6/valid.s =================================================================== --- test/MC/Mips/micromips32r6/valid.s +++ test/MC/Mips/micromips32r6/valid.s @@ -27,7 +27,11 @@ bltzalc $2, 1332 # CHECK: bltzalc $2, 1332 # encoding: [0xe0,0x42,0x02,0x9a] blezalc $2, 1332 # CHECK: blezalc $2, 1332 # encoding: [0xc0,0x40,0x02,0x9a] balc 14572256 # CHECK: balc 14572256 # encoding: [0xb4,0x37,0x96,0xb8] + b 132 # CHECK: bc16 132 # encoding: [0xcc,0x42] bc 14572256 # CHECK: bc 14572256 # encoding: [0x94,0x37,0x96,0xb8] + bc16 132 # CHECK: bc16 132 # encoding: [0xcc,0x42] + beqzc16 $6, 20 # CHECK: beqzc16 $6, 20 # encoding: [0x8f,0x0a] + bnezc16 $6, 20 # CHECK: bnezc16 $6, 20 # encoding: [0xaf,0x0a] bitswap $4, $2 # CHECK: bitswap $4, $2 # encoding: [0x00,0x44,0x0b,0x3c] break # CHECK: break # encoding: [0x00,0x00,0x00,0x07] break 7 # CHECK: break 7 # encoding: [0x00,0x07,0x00,0x07] Index: test/MC/Mips/micromips64r6/invalid.s =================================================================== --- test/MC/Mips/micromips64r6/invalid.s +++ test/MC/Mips/micromips64r6/invalid.s @@ -8,6 +8,12 @@ addiur2 $6, $7, 10 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range addius5 $7, 9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range addiusp 1032 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + beqzc16 $9, 20 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + beqzc16 $6, 31 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch to misaligned address + beqzc16 $6, 130 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch target out of range + bnezc16 $9, 20 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + bnezc16 $6, 31 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch to misaligned address + bnezc16 $6, 130 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch target out of range ddiv $32, $4, $5 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction ddiv $3, $34, $5 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction ddiv $3, $4, $35 # 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 @@ -10,6 +10,10 @@ addiusp 1024 # CHECK: addiusp 1024 # encoding: [0x4c,0x01] addiusp 1028 # CHECK: addiusp 1028 # encoding: [0x4c,0x03] addiusp -16 # CHECK: addiusp -16 # encoding: [0x4f,0xf9] + b 132 # CHECK: bc16 132 # encoding: [0xcc,0x42] + bc16 132 # CHECK: bc16 132 # encoding: [0xcc,0x42] + beqzc16 $6, 20 # CHECK: beqzc16 $6, 20 # encoding: [0x8f,0x0a] + bnezc16 $6, 20 # CHECK: bnezc16 $6, 20 # encoding: [0xaf,0x0a] daui $3, $4, 5 # CHECK: daui $3, $4, 5 # encoding: [0xf0,0x64,0x00,0x05] dahi $3, 4 # CHECK: dahi $3, 4 # encoding: [0x42,0x23,0x00,0x04] dati $3, 4 # CHECK: dati $3, 4 # encoding: [0x42,0x03,0x00,0x04]