From: Zoran Jovanovic Date: Mon, 7 Sep 2015 11:56:37 +0000 (+0000) Subject: [mips][microMIPS] Implement BC16, BEQZC16 and BNEZC16 instructions X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=75a08f5633bac28851d9489c6cc7a46eaa7b21a2 [mips][microMIPS] Implement BC16, BEQZC16 and BNEZC16 instructions Differential Revision: http://reviews.llvm.org/D11181 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@246963 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 77e7e6f186f..8f4a05f6346 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1425,7 +1425,9 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 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()) @@ -1815,6 +1817,7 @@ bool MipsAsmParser::needsExpansion(MCInst &Inst) { 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: @@ -1869,6 +1872,7 @@ bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc, 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: @@ -2370,7 +2374,8 @@ bool MipsAsmParser::expandUncondBranchMMPseudo( 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"); @@ -2385,8 +2390,10 @@ bool MipsAsmParser::expandUncondBranchMMPseudo( } 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; diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 1b4bcf5f21a..897f4bb2423 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -836,8 +836,21 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, 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 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, // 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; diff --git a/lib/Target/Mips/MicroMips32r6InstrFormats.td b/lib/Target/Mips/MicroMips32r6InstrFormats.td index 5a852a0a7c1..8827a74267e 100644 --- a/lib/Target/Mips/MicroMips32r6InstrFormats.td +++ b/lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -16,6 +16,32 @@ class MMR6Arch { 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; diff --git a/lib/Target/Mips/MicroMips32r6InstrInfo.td b/lib/Target/Mips/MicroMips32r6InstrInfo.td index 07b1cb0b0e6..f8cc5a785ca 100644 --- a/lib/Target/Mips/MicroMips32r6InstrInfo.td +++ b/lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -28,6 +28,9 @@ class ALIGN_MMR6_ENC : POOL32A_ALIGN_FM_MMR6<0b011111>; 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>; @@ -194,6 +197,29 @@ class BALC_MMR6_DESC : BC_MMR6_DESC_BASE<"balc", brtarget26> { 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>; @@ -532,6 +558,11 @@ def ALIGN_MMR6 : R6MMR6Rel, ALIGN_MMR6_ENC, ALIGN_MMR6_DESC, ISA_MICROMIPS32R6; 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, @@ -665,3 +696,6 @@ defm D_MMR6 : CMP_CC_MMR6<0b010101, "d", FGR64Opnd>; 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; diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td index 39393840c6f..619f9f6dcf6 100644 --- a/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/lib/Target/Mips/MicroMipsInstrInfo.td @@ -928,7 +928,7 @@ class UncondBranchMMPseudo : 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>; diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 18fd6e50ca2..b704fad7084 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -255,6 +255,7 @@ class ISA_MIPS64_NOT_64R6 { 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]; } diff --git a/test/MC/Disassembler/Mips/micromips32r6.txt b/test/MC/Disassembler/Mips/micromips32r6.txt index 5b6fed9f94a..29aad983ed6 100644 --- a/test/MC/Disassembler/Mips/micromips32r6.txt +++ b/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 diff --git a/test/MC/Disassembler/Mips/micromips64r6.txt b/test/MC/Disassembler/Mips/micromips64r6.txt index 41a1663a3d3..e89001679de 100644 --- a/test/MC/Disassembler/Mips/micromips64r6.txt +++ b/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 diff --git a/test/MC/Mips/micromips32r6/invalid.s b/test/MC/Mips/micromips32r6/invalid.s index f75bcf99362..ff9e245c3ba 100644 --- a/test/MC/Mips/micromips32r6/invalid.s +++ b/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 diff --git a/test/MC/Mips/micromips32r6/valid.s b/test/MC/Mips/micromips32r6/valid.s index efd7ddbe105..e6d920f9cbf 100644 --- a/test/MC/Mips/micromips32r6/valid.s +++ b/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] diff --git a/test/MC/Mips/micromips64r6/invalid.s b/test/MC/Mips/micromips64r6/invalid.s index 830c907c1f1..6e753030e8f 100644 --- a/test/MC/Mips/micromips64r6/invalid.s +++ b/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 diff --git a/test/MC/Mips/micromips64r6/valid.s b/test/MC/Mips/micromips64r6/valid.s index 0aded8b73e3..26924f0e10a 100644 --- a/test/MC/Mips/micromips64r6/valid.s +++ b/test/MC/Mips/micromips64r6/valid.s @@ -10,6 +10,10 @@ a: 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]