Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1365,7 +1365,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()) @@ -1665,6 +1667,7 @@ case Mips::LoadAddrImm32: case Mips::LoadAddrReg32: case Mips::B_MM_Pseudo: + case Mips::B_MMR6_Pseudo: case Mips::LWM_MM: case Mips::SWM_MM: case Mips::JalOneReg: @@ -1701,6 +1704,8 @@ return expandLoadAddressReg(Inst, true, IDLoc, Instructions); case Mips::B_MM_Pseudo: return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions); + case Mips::B_MMR6_Pseudo: + return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions); case Mips::SWM_MM: case Mips::LWM_MM: return expandLoadStoreMultiple(Inst, IDLoc, Instructions); @@ -2123,7 +2128,10 @@ 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() && (hasMips32r6() || hasMips64r6())) + Inst.setOpcode(Mips::BC16_MMR6); + else + Inst.setOpcode(Mips::B16_MM); } else { if (!isIntN(17, Offset.getImm())) Error(IDLoc, "branch target out of range"); @@ -2139,7 +2147,7 @@ Instructions.push_back(Inst); // If .set reorder is active, emit a NOP after the branch instruction. - if (AssemblerOptions.back()->isReorder()) + if (AssemblerOptions.back()->isReorder() && Inst.getOpcode() != Mips::BC16_MMR6) 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 @@ -834,10 +834,18 @@ if (IsMicroMips) { Result = readInstruction16(Bytes, Address, Size, Insn, IsBigEndian); - DEBUG(dbgs() << "Trying MicroMips16 table (16-bit instructions):\n"); - // Calling the auto-generated decoder function. - Result = decodeInstruction(DecoderTableMicroMips16, Instr, Insn, Address, - this, STI); + if (hasMips32r6()) { + DEBUG(dbgs() << "Trying MicroMipsR616 table (16-bit instructions):\n"); + // Calling the auto-generated decoder function. + Result = decodeInstruction(DecoderTableMicroMips32r6_64r616, Instr, Insn, + Address, this, STI); + } else { + DEBUG(dbgs() << "Trying MicroMips16 table (16-bit instructions):\n"); + // Calling the auto-generated decoder function. + Result = decodeInstruction(DecoderTableMicroMips16, Instr, Insn, Address, + this, STI); + } + if (Result != MCDisassembler::Fail) { Size = 2; return Result; Index: lib/Target/Mips/MicroMips32r6InstrFormats.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrFormats.td +++ lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -16,6 +16,26 @@ string BaseOpcode = opstr; } +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> { + 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>; @@ -135,6 +138,32 @@ 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"> { + let DecoderNamespace = "MicroMips32r6_64r6"; + let isBranch = 1; + let isTerminator = 1; + let isBarrier = 1; + let hasDelaySlot = 0; + let Predicates = [RelocPIC, HasStdEnc, HasMicroMips32r6]; + let Defs = [AT]; +} + +class BEQZC_BNEZC_MM16R6_DESC_BASE : + CBranchZeroMM, MMR6Arch { + let DecoderNamespace = "MicroMips32r6_64r6"; + let isBranch = 1; + let isTerminator = 1; + let hasDelaySlot = 0; + let Predicates = [HasStdEnc, HasMicroMips32r6]; + 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>; @@ -298,6 +327,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, @@ -358,3 +392,7 @@ 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")> { + let Predicates = [HasMicroMips32r6]; +} Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -928,7 +928,9 @@ MipsAsmPseudoInst<(outs), (ins brtarget_mm:$offset), !strconcat(opstr, "\t$offset")>; - def B_MM_Pseudo : UncondBranchMMPseudo<"b">; +let Predicates = [InMicroMips] in { +def B_MM_Pseudo : UncondBranchMMPseudo<"b">; +} def : MipsInstAlias<"wait", (WAIT_MM 0x0), 1>; def : MipsInstAlias<"nop", (SLL_MM ZERO, ZERO, 0), 1>; Index: test/MC/Disassembler/Mips/micromips32r6.txt =================================================================== --- test/MC/Disassembler/Mips/micromips32r6.txt +++ test/MC/Disassembler/Mips/micromips32r6.txt @@ -36,6 +36,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 @@ -1,4 +1,10 @@ # RUN: llvm-mc --disassemble %s -triple=mips-unknown-linux -mcpu=mips64r6 -mattr=micromips | FileCheck %s +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 Index: test/MC/Mips/micromips32r6/invalid.s =================================================================== --- test/MC/Mips/micromips32r6/invalid.s +++ test/MC/Mips/micromips32r6/invalid.s @@ -1,6 +1,12 @@ # RUN: not llvm-mc %s -triple=mips -show-encoding -mcpu=mips32r6 -mattr=micromips 2>%t1 # RUN: FileCheck %s < %t1 + 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 @@ -18,7 +18,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 =================================================================== --- /dev/null +++ test/MC/Mips/micromips64r6/invalid.s @@ -0,0 +1,9 @@ +# RUN: not llvm-mc %s -triple=mips -show-encoding -mcpu=mips64r6 -mattr=micromips 2>%t1 +# RUN: FileCheck %s < %t1 + + 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 Index: test/MC/Mips/micromips64r6/valid.s =================================================================== --- test/MC/Mips/micromips64r6/valid.s +++ test/MC/Mips/micromips64r6/valid.s @@ -1,6 +1,10 @@ # RUN: llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips64r6 -mattr=micromips | FileCheck %s a: .set noat + 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] 1: