Index: llvm/trunk/lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ llvm/trunk/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -455,6 +455,16 @@ DecodeBlezGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder); +template +static DecodeStatus +DecodeBgtzGroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, + const void *Decoder); + +template +static DecodeStatus +DecodeBlezGroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); @@ -2133,3 +2143,87 @@ Inst.addOperand(MCOperand::createImm(SignExtend32<25>(Insn << 2))); return MCDisassembler::Success; } + +template +static DecodeStatus DecodeBgtzGroupBranchMMR6(MCInst &MI, InsnType insn, + uint64_t Address, + const void *Decoder) { + // We have: + // 0b000111 ttttt sssss iiiiiiiiiiiiiiii + // Invalid if rt == 0 + // BGTZALC_MMR6 if rs == 0 && rt != 0 + // BLTZALC_MMR6 if rs != 0 && rs == rt + // BLTUC_MMR6 if rs != 0 && rs != rt + + InsnType Rt = fieldFromInstruction(insn, 21, 5); + InsnType Rs = fieldFromInstruction(insn, 16, 5); + InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2; + bool HasRs = false; + bool HasRt = false; + + if (Rt == 0) + return MCDisassembler::Fail; + else if (Rs == 0) { + MI.setOpcode(Mips::BGTZALC_MMR6); + HasRt = true; + } + else if (Rs == Rt) { + MI.setOpcode(Mips::BLTZALC_MMR6); + HasRs = true; + } + else { + MI.setOpcode(Mips::BLTUC_MMR6); + HasRs = true; + HasRt = true; + } + + if (HasRs) + MI.addOperand( + MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs))); + + if (HasRt) + MI.addOperand( + MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt))); + + MI.addOperand(MCOperand::createImm(Imm)); + + return MCDisassembler::Success; +} + +template +static DecodeStatus DecodeBlezGroupBranchMMR6(MCInst &MI, InsnType insn, + uint64_t Address, + const void *Decoder) { + // We have: + // 0b000110 ttttt sssss iiiiiiiiiiiiiiii + // Invalid if rs == 0 + // BLEZALC_MMR6 if rs == 0 && rt != 0 + // BGEZALC_MMR6 if rs == rt && rt != 0 + // BGEUC_MMR6 if rs != rt && rs != 0 && rt != 0 + + InsnType Rt = fieldFromInstruction(insn, 21, 5); + InsnType Rs = fieldFromInstruction(insn, 16, 5); + InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2; + bool HasRs = false; + + if (Rt == 0) + return MCDisassembler::Fail; + else if (Rs == 0) + MI.setOpcode(Mips::BLEZALC_MMR6); + else if (Rs == Rt) + MI.setOpcode(Mips::BGEZALC_MMR6); + else { + HasRs = true; + MI.setOpcode(Mips::BGEUC_MMR6); + } + + if (HasRs) + MI.addOperand( + MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs))); + MI.addOperand( + MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt))); + + MI.addOperand(MCOperand::createImm(Imm)); + + return MCDisassembler::Success; +} Index: llvm/trunk/lib/Target/Mips/MicroMips32r6InstrFormats.td =================================================================== --- llvm/trunk/lib/Target/Mips/MicroMips32r6InstrFormats.td +++ llvm/trunk/lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -14,6 +14,7 @@ class MMR6Arch { string Arch = "micromipsr6"; string BaseOpcode = opstr; + string DecoderNamespace = "MicroMipsR6"; } // Class used for microMIPS32r6 and microMIPS64r6 instructions. @@ -22,6 +23,24 @@ let InsnPredicates = [HasMicroMips32r6]; } +//===----------------------------------------------------------------------===// +// +// Disambiguators +// +//===----------------------------------------------------------------------===// +// +// Some encodings are ambiguous except by comparing field values. + +class MMDecodeDisambiguatedBy : DecodeDisambiguates { + string DecoderNamespace = "MicroMipsR6_Ambiguous"; +} + +//===----------------------------------------------------------------------===// +// +// Encoding Formats +// +//===----------------------------------------------------------------------===// + class BC16_FM_MM16R6 { bits<10> offset; @@ -449,7 +468,8 @@ let Inst{15-0} = imm16; } -class CMP_BRANCH_1R_RT_OFF16_FM_MMR6 funct> : MipsR6Inst { +class CMP_BRANCH_1R_RT_OFF16_FM_MMR6 funct> + : MMR6Arch, MipsR6Inst { bits<5> rt; bits<16> offset; @@ -461,7 +481,8 @@ let Inst{15-0} = offset; } -class CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6 funct> : MipsR6Inst { +class CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6 funct> + : MMR6Arch, MipsR6Inst { bits<5> rt; bits<16> offset; @@ -948,3 +969,18 @@ let Inst{11} = 0; let Inst{10-0} = offset; } + +class CMP_BRANCH_2R_OFF16_FM_MMR6 funct> + : MipsR6Inst, MMR6Arch { + bits<5> rt; + bits<5> rs; + bits<16> offset; + + bits<32> Inst; + + let Inst{31-26} = funct; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-0} = offset; +} + Index: llvm/trunk/lib/Target/Mips/MicroMips32r6InstrInfo.td =================================================================== --- llvm/trunk/lib/Target/Mips/MicroMips32r6InstrInfo.td +++ llvm/trunk/lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -40,12 +40,24 @@ 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>; -class BNEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b011111>; -class BGTZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b111000>; -class BLTZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<0b111000>; -class BGEZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<0b110000>; -class BLEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b110000>; +class BGEC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bgec", 0b111001>; +class BGEUC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bgeuc", 0b110000>, + DecodeDisambiguates<"BlezGroupBranchMMR6">; +class BLTC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bltc", 0b110001>; +class BLTUC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bltuc", 0b111000>, + DecodeDisambiguates<"BgtzGroupBranchMMR6">; +class BEQC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"beqc", 0b011101>; +class BNEC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bnec", 0b011111>; +class BEQZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"beqzalc", 0b011101>; +class BNEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"bnezalc", 0b011111>; +class BGTZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"bgtzalc", 0b111000>, + MMDecodeDisambiguatedBy<"BgtzGroupBranchMMR6">; +class BLTZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<"bltzalc", 0b111000>, + MMDecodeDisambiguatedBy<"BgtzGroupBranchMMR6">; +class BGEZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<"bgezalc", 0b110000>, + MMDecodeDisambiguatedBy<"BlezGroupBranchMMR6">; +class BLEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"blezalc", 0b110000>, + MMDecodeDisambiguatedBy<"BlezGroupBranchMMR6">; class CACHE_MMR6_ENC : CACHE_PREF_FM_MMR6<0b001000, 0b0110>; class CFC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"cfc1", 0b01000000>; class CFC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"cfc2", 0b1100110100>; @@ -191,7 +203,7 @@ class CMP_CBR_RT_Z_MMR6_DESC_BASE - : BRANCH_DESC_BASE, MMR6Arch { + : BRANCH_DESC_BASE { dag InOperandList = (ins GPROpnd:$rt, opnd:$offset); dag OutOperandList = (outs); string AsmString = !strconcat(instr_asm, "\t$rt, $offset"); @@ -228,6 +240,27 @@ list Defs = [RA]; } +class CMP_CBR_2R_MMR6_DESC_BASE : BRANCH_DESC_BASE { + dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, opnd:$offset); + dag OutOperandList = (outs); + string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $offset"); + list Defs = [AT]; +} + +class BGEC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bgec", brtarget_mm, + GPR32Opnd>; +class BGEUC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bgeuc", brtarget_mm, + GPR32Opnd>; +class BLTC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bltc", brtarget_mm, + GPR32Opnd>; +class BLTUC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bltuc", brtarget_mm, + GPR32Opnd>; +class BEQC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"beqc", brtarget_mm, + GPR32Opnd>; +class BNEC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bnec", brtarget_mm, + GPR32Opnd>; + /// Floating Point Instructions class FADD_S_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"add.s", 0, 0b00110000>; class FADD_D_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"add.d", 1, 0b00110000>; @@ -1140,14 +1173,6 @@ ISA_MICROMIPS32R6; def BEQZALC_MMR6 : R6MMR6Rel, BEQZALC_MMR6_ENC, BEQZALC_MMR6_DESC, ISA_MICROMIPS32R6; -def BGEZALC_MMR6 : R6MMR6Rel, BGEZALC_MMR6_ENC, BGEZALC_MMR6_DESC, - ISA_MICROMIPS32R6; -def BGTZALC_MMR6 : R6MMR6Rel, BGTZALC_MMR6_ENC, BGTZALC_MMR6_DESC, - ISA_MICROMIPS32R6; -def BLEZALC_MMR6 : R6MMR6Rel, BLEZALC_MMR6_ENC, BLEZALC_MMR6_DESC, - ISA_MICROMIPS32R6; -def BLTZALC_MMR6 : R6MMR6Rel, BLTZALC_MMR6_ENC, BLTZALC_MMR6_DESC, - ISA_MICROMIPS32R6; def BNEZALC_MMR6 : R6MMR6Rel, BNEZALC_MMR6_ENC, BNEZALC_MMR6_DESC, ISA_MICROMIPS32R6; def BREAK_MMR6 : StdMMR6Rel, BRK_MMR6_DESC, BRK_MMR6_ENC, ISA_MICROMIPS32R6; @@ -1426,6 +1451,21 @@ ISA_MICROMIPS32R6; } +def BGEC_MMR6 : R6MMR6Rel, BGEC_MMR6_ENC, BGEC_MMR6_DESC, ISA_MICROMIPS32R6; +def BGEUC_MMR6 : R6MMR6Rel, BGEUC_MMR6_ENC, BGEUC_MMR6_DESC, ISA_MICROMIPS32R6; +def BLTC_MMR6 : R6MMR6Rel, BLTC_MMR6_ENC, BLTC_MMR6_DESC, ISA_MICROMIPS32R6; +def BLTUC_MMR6 : R6MMR6Rel, BLTUC_MMR6_ENC, BLTUC_MMR6_DESC, ISA_MICROMIPS32R6; +def BEQC_MMR6 : R6MMR6Rel, BEQC_MMR6_ENC, BEQC_MMR6_DESC, ISA_MICROMIPS32R6; +def BNEC_MMR6 : R6MMR6Rel, BNEC_MMR6_ENC, BNEC_MMR6_DESC, ISA_MICROMIPS32R6; +def BGEZALC_MMR6 : R6MMR6Rel, BGEZALC_MMR6_ENC, BGEZALC_MMR6_DESC, + ISA_MICROMIPS32R6; +def BGTZALC_MMR6 : R6MMR6Rel, BGTZALC_MMR6_ENC, BGTZALC_MMR6_DESC, + ISA_MICROMIPS32R6; +def BLEZALC_MMR6 : R6MMR6Rel, BLEZALC_MMR6_ENC, BLEZALC_MMR6_DESC, + ISA_MICROMIPS32R6; +def BLTZALC_MMR6 : R6MMR6Rel, BLTZALC_MMR6_ENC, BLTZALC_MMR6_DESC, + ISA_MICROMIPS32R6; + //===----------------------------------------------------------------------===// // // MicroMips instruction aliases Index: llvm/trunk/lib/Target/Mips/Mips32r6InstrInfo.td =================================================================== --- llvm/trunk/lib/Target/Mips/Mips32r6InstrInfo.td +++ llvm/trunk/lib/Target/Mips/Mips32r6InstrInfo.td @@ -315,7 +315,8 @@ } class CMP_BC_DESC_BASE : BRANCH_DESC_BASE { + RegisterOperand GPROpnd> : BRANCH_DESC_BASE, + MipsR6Arch { dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, opnd:$offset); dag OutOperandList = (outs); string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $offset"); @@ -718,11 +719,11 @@ def BC2EQZ : BC2EQZ_ENC, BC2EQZ_DESC, ISA_MIPS32R6; def BC2NEZ : BC2NEZ_ENC, BC2NEZ_DESC, ISA_MIPS32R6; def BC : R6MMR6Rel, BC_ENC, BC_DESC, ISA_MIPS32R6; -def BEQC : BEQC_ENC, BEQC_DESC, ISA_MIPS32R6; +def BEQC : R6MMR6Rel, BEQC_ENC, BEQC_DESC, ISA_MIPS32R6; def BEQZALC : R6MMR6Rel, BEQZALC_ENC, BEQZALC_DESC, ISA_MIPS32R6; def BEQZC : BEQZC_ENC, BEQZC_DESC, ISA_MIPS32R6; -def BGEC : BGEC_ENC, BGEC_DESC, ISA_MIPS32R6; -def BGEUC : BGEUC_ENC, BGEUC_DESC, ISA_MIPS32R6; +def BGEC : R6MMR6Rel, BGEC_ENC, BGEC_DESC, ISA_MIPS32R6; +def BGEUC : R6MMR6Rel, BGEUC_ENC, BGEUC_DESC, ISA_MIPS32R6; def BGEZALC : R6MMR6Rel, BGEZALC_ENC, BGEZALC_DESC, ISA_MIPS32R6; def BGEZC : BGEZC_ENC, BGEZC_DESC, ISA_MIPS32R6; def BGTZALC : R6MMR6Rel, BGTZALC_ENC, BGTZALC_DESC, ISA_MIPS32R6; @@ -730,11 +731,11 @@ def BITSWAP : R6MMR6Rel, BITSWAP_ENC, BITSWAP_DESC, ISA_MIPS32R6; def BLEZALC : R6MMR6Rel, BLEZALC_ENC, BLEZALC_DESC, ISA_MIPS32R6; def BLEZC : BLEZC_ENC, BLEZC_DESC, ISA_MIPS32R6; -def BLTC : BLTC_ENC, BLTC_DESC, ISA_MIPS32R6; -def BLTUC : BLTUC_ENC, BLTUC_DESC, ISA_MIPS32R6; +def BLTC : R6MMR6Rel, BLTC_ENC, BLTC_DESC, ISA_MIPS32R6; +def BLTUC : R6MMR6Rel, BLTUC_ENC, BLTUC_DESC, ISA_MIPS32R6; def BLTZALC : R6MMR6Rel, BLTZALC_ENC, BLTZALC_DESC, ISA_MIPS32R6; def BLTZC : BLTZC_ENC, BLTZC_DESC, ISA_MIPS32R6; -def BNEC : BNEC_ENC, BNEC_DESC, ISA_MIPS32R6; +def BNEC : R6MMR6Rel, BNEC_ENC, BNEC_DESC, ISA_MIPS32R6; def BNEZALC : R6MMR6Rel, BNEZALC_ENC, BNEZALC_DESC, ISA_MIPS32R6; def BNEZC : BNEZC_ENC, BNEZC_DESC, ISA_MIPS32R6; def BNVC : BNVC_ENC, BNVC_DESC, ISA_MIPS32R6; Index: llvm/trunk/test/MC/Disassembler/Mips/micromips32r6/valid.txt =================================================================== --- llvm/trunk/test/MC/Disassembler/Mips/micromips32r6/valid.txt +++ llvm/trunk/test/MC/Disassembler/Mips/micromips32r6/valid.txt @@ -38,6 +38,12 @@ 0x00 0xa4 0x1a 0x50 # CHECK: and $3, $4, $5 0xd0 0x64 0x04 0xd2 # CHECK: andi $3, $4, 1234 0x10 0x62 0xff 0xe9 # CHECK: aui $3, $2, -23 +0x74 0x83 0x00 0x08 # CHECK: beqc $3, $4, 16 +0xe4 0x83 0x00 0x08 # CHECK: bgec $3, $4, 16 +0xc0 0x83 0x00 0x08 # CHECK: bgeuc $3, $4, 16 +0xc4 0x83 0x00 0x08 # CHECK: bltc $3, $4, 16 +0xe0 0x83 0x00 0x08 # CHECK: bltuc $3, $4, 16 +0x7c 0x83 0x00 0x08 # CHECK: bnec $3, $4, 16 0x74 0x40 0x02 0x9a # CHECK: beqzalc $2, 1332 0x7c 0x40 0x02 0x9a # CHECK: bnezalc $2, 1332 0xc0 0x42 0x02 0x9a # CHECK: bgezalc $2, 1332 Index: llvm/trunk/test/MC/Mips/micromips32r6/valid.s =================================================================== --- llvm/trunk/test/MC/Mips/micromips32r6/valid.s +++ llvm/trunk/test/MC/Mips/micromips32r6/valid.s @@ -20,6 +20,12 @@ auipc $3, -1 # CHECK: auipc $3, -1 # encoding: [0x78,0x7e,0xff,0xff] align $4, $2, $3, 2 # CHECK: align $4, $2, $3, 2 # encoding: [0x00,0x43,0x24,0x1f] aui $3,$2,-23 # CHECK: aui $3, $2, -23 # encoding: [0x10,0x62,0xff,0xe9] + beqc $3,$4, 16 # CHECK: beqc $3, $4, 16 # encoding: [0x74,0x83,0x00,0x08] + bgec $3,$4, 16 # CHECK: bgec $3, $4, 16 # encoding: [0xe4,0x83,0x00,0x08] + bgeuc $3,$4, 16 # CHECK: bgeuc $3, $4, 16 # encoding: [0xc0,0x83,0x00,0x08] + bltc $3,$4, 16 # CHECK: bltc $3, $4, 16 # encoding: [0xc4,0x83,0x00,0x08] + bltuc $3,$4, 16 # CHECK: bltuc $3, $4, 16 # encoding: [0xe0,0x83,0x00,0x08] + bnec $3,$4, 16 # CHECK: bnec $3, $4, 16 # encoding: [0x7c,0x83,0x00,0x08] beqzalc $2, 1332 # CHECK: beqzalc $2, 1332 # encoding: [0x74,0x40,0x02,0x9a] bnezalc $2, 1332 # CHECK: bnezalc $2, 1332 # encoding: [0x7c,0x40,0x02,0x9a] bgezalc $2, 1332 # CHECK: bgezalc $2, 1332 # encoding: [0xc0,0x42,0x02,0x9a]