Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -425,11 +425,21 @@ template static DecodeStatus +DecodeAddiGroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, + const void *Decoder); + +template +static DecodeStatus DecodeDaddiGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder); template static DecodeStatus +DecodeDaddiGroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, + const void *Decoder); + +template +static DecodeStatus DecodeBlezlGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder); @@ -595,6 +605,37 @@ } template +static DecodeStatus DecodeAddiGroupBranchMMR6(MCInst &MI, InsnType insn, + uint64_t Address, + const void *Decoder) { + InsnType Rt = fieldFromInstruction(insn, 21, 5); + InsnType Rs = fieldFromInstruction(insn, 16, 5); + InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2; + + if (Rs >= Rt) { + MI.setOpcode(Mips::BOVC_MMR6); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rs))); + } else if (Rs != 0 && Rs < Rt) { + MI.setOpcode(Mips::BEQC_MMR6); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rs))); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + } else { + MI.setOpcode(Mips::BEQZALC_MMR6); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + } + + MI.addOperand(MCOperand::createImm(Imm)); + + return MCDisassembler::Success; +} + +template static DecodeStatus DecodeDaddiGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder) { @@ -634,6 +675,37 @@ } template +static DecodeStatus DecodeDaddiGroupBranchMMR6(MCInst &MI, InsnType insn, + uint64_t Address, + const void *Decoder) { + InsnType Rt = fieldFromInstruction(insn, 21, 5); + InsnType Rs = fieldFromInstruction(insn, 16, 5); + InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2; + + if (Rs >= Rt) { + MI.setOpcode(Mips::BNVC_MMR6); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rs))); + } else if (Rs != 0 && Rs < Rt) { + MI.setOpcode(Mips::BNEC_MMR6); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rs))); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + } else { + MI.setOpcode(Mips::BNEZALC_MMR6); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + } + + MI.addOperand(MCOperand::createImm(Imm)); + + return MCDisassembler::Success; +} + +template static DecodeStatus DecodeBlezlGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder) { Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -102,6 +102,13 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + // getBranchTargetOpValueMMR6 - Return binary encoding of the branch + // target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + // getBranchTarget7OpValue - Return binary encoding of the microMIPS branch // target operand. If the machine operand requires relocation, // record the relocation and return zero. Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -237,6 +237,29 @@ return 0; } +/// getBranchTargetOpValueMMR6 - Return binary encoding of the branch +/// target operand. If the machine operand requires relocation, +/// record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + + // If the destination is an immediate, divide by 2. + if (MO.isImm()) return MO.getImm() >> 1; + + assert(MO.isExpr() && + "getBranchTargetOpValueMMR6 expects only expressions or immediates"); + + const MCExpr *FixupExpression = MCBinaryExpr::createAdd( + MO.getExpr(), MCConstantExpr::create(-2, Ctx), Ctx); + Fixups.push_back(MCFixup::create(0, FixupExpression, + MCFixupKind(Mips::fixup_Mips_PC16))); + return 0; +} + /// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch /// target operand. If the machine operand requires relocation, /// record the relocation and return zero. Index: lib/Target/Mips/MicroMips32r6InstrFormats.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrFormats.td +++ lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -65,6 +65,32 @@ let Inst{4-0} = op; } +class POP35_BOVC_FM_MMR6 : MipsR6Inst, MMR6Arch { + bits<5> rt; + bits<5> rs; + bits<16> offset; + + bits<32> Inst; + + let Inst{31-26} = 0b011101; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-0} = offset; +} + +class POP37_BOVC_FM_MMR6 : MipsR6Inst, MMR6Arch { + bits<5> rt; + bits<5> rs; + bits<16> offset; + + bits<32> Inst; + + let Inst{31-26} = 0b011111; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-0} = offset; +} + class POOL16C_JRCADDIUSP_FM_MM16R6 op> { bits<5> imm; @@ -488,6 +514,36 @@ let Inst{15-0} = offset; } +class POOL32A_EXT_INS_FM_MMR6 funct> { + bits<5> rt; + bits<5> rs; + bits<5> size; + bits<5> pos; + + bits<32> Inst; + + let Inst{31-26} = 0; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = size; + let Inst{10-6} = pos; + let Inst{5-0} = funct; +} + +class POOL32A_JALRC_FM_MMR6 + : MipsR6Inst, MMR6Arch { + bits<5> rt; + bits<5> rs; + + bits<32> Inst; + + let Inst{31-26} = 0; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-6} = 0b0000111100; + let Inst{5-0} = 0b111100; +} + class ERET_FM_MMR6 : MMR6Arch { bits<32> Inst; Index: lib/Target/Mips/MicroMips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrInfo.td +++ lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -11,6 +11,13 @@ // //===----------------------------------------------------------------------===// +def brtargetr6 : Operand { + let EncoderMethod = "getBranchTargetOpValueMMR6"; + let OperandType = "OPERAND_PCREL"; + let DecoderMethod = "DecodeBranchTargetMM"; + let ParserMatchClass = MipsJumpTargetAsmOperand; +} + //===----------------------------------------------------------------------===// // // Instruction Encodings @@ -49,8 +56,10 @@ 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 BEQC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"beqc", 0b011101>, + DecodeDisambiguates<"AddiGroupBranchMMR6">; +class BNEC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bnec", 0b011111>, + DecodeDisambiguates<"DaddiGroupBranchMMR6">; class CACHE_MMR6_ENC : CACHE_PREF_FM_MMR6<0b001000, 0b0110>; class CLO_MMR6_ENC : POOL32A_2R_FM_MMR6<0b0100101100>; class CLZ_MMR6_ENC : SPECIAL_2R_FM_MMR6<0b010000>; @@ -137,6 +146,13 @@ class LWE_MMR6_ENC : LOAD_WORD_EVA_FM_MMR6<0b111>; class LW_MMR6_ENC : LOAD_WORD_FM_MMR6; class LUI_MMR6_ENC : LOAD_UPPER_IMM_FM_MMR6<"lui">; +class EXT_MMR6_ENC : POOL32A_EXT_INS_FM_MMR6<0b101100>; +class INS_MMR6_ENC : POOL32A_EXT_INS_FM_MMR6<0b001100>; +class JALRC_MMR6_ENC : POOL32A_JALRC_FM_MMR6<"jalrc">; +class BOVC_MMR6_ENC : POP35_BOVC_FM_MMR6<"bovc">, + MMDecodeDisambiguatedBy<"AddiGroupBranchMMR6">; +class BNVC_MMR6_ENC : POP37_BOVC_FM_MMR6<"bnvc">, + MMDecodeDisambiguatedBy<"DaddiGroupBranchMMR6">; class ADDU16_MMR6_ENC : POOL16A_ADDU16_FM_MMR6; class AND16_MMR6_ENC : POOL16C_AND16_FM_MMR6; @@ -899,6 +915,50 @@ let mayStore = 1; } +class EXT_MMR6_DESC : MMR6Arch<"ext">, MipsR6Inst { + dag OutOperandList = (outs GPR32Opnd:$rt); + dag InOperandList = (ins GPR32Opnd:$rs, uimm5:$pos, size_ext:$size); + string AsmString = !strconcat("ext", "\t$rt, $rs, $pos, $size"); + list Pattern = [(set GPR32Opnd:$rt, (MipsExt GPR32Opnd:$rs, imm:$pos, imm:$size))]; + InstrItinClass Itinerary = II_EXT; + Format Form = FrmR; + string BaseOpcode = "ext"; +} + +class INS_MMR6_DESC : MMR6Arch<"ins">, MipsR6Inst { + dag OutOperandList = (outs GPR32Opnd:$rt); + dag InOperandList = (ins GPR32Opnd:$rs, uimm5:$pos, size_ins:$size, GPR32Opnd:$src); + string AsmString = !strconcat("ins", "\t$rt, $rs, $pos, $size"); + list Pattern = [(set GPR32Opnd:$rt, (MipsIns GPR32Opnd:$rs, imm:$pos, imm:$size, GPR32Opnd:$src))]; + InstrItinClass Itinerary = II_INS; + Format Form = FrmR; + string BaseOpcode = "ins"; + string Constraints = "$src = $rt"; +} + +class JALRC_MMR6_DESC { + dag OutOperandList = (outs GPR32Opnd:$rt); + dag InOperandList = (ins GPR32Opnd:$dst, GPR32Opnd:$rs); + string AsmString = !strconcat("jalrc", "\t$rt, $rs"); + list Pattern = []; + InstrItinClass Itinerary = II_JALRC; + string Constraints = "$dst = $rt"; + bit isCall = 1; + bit hasDelaySlot = 0; +} + +class BOVC_BNVC_MMR6_DESC_BASE + : BRANCH_DESC_BASE { + dag InOperandList = (ins GPROpnd:$rt, GPROpnd:$rs, opnd:$offset); + dag OutOperandList = (outs); + string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $offset"); + list Defs = [AT]; +} + +class BOVC_MMR6_DESC : BOVC_BNVC_MMR6_DESC_BASE<"bovc", brtargetr6, GPR32Opnd>; +class BNVC_MMR6_DESC : BOVC_BNVC_MMR6_DESC_BASE<"bnvc", brtargetr6, GPR32Opnd>; + //===----------------------------------------------------------------------===// // // Instruction Definitions @@ -1152,6 +1212,11 @@ ISA_MICROMIPS32R6; def XOR16_MMR6 : StdMMR6Rel, XOR16_MMR6_DESC, XOR16_MMR6_ENC, ISA_MICROMIPS32R6; +def EXT_MMR6 : StdMMR6Rel, EXT_MMR6_DESC, EXT_MMR6_ENC, ISA_MICROMIPS32R6; +def INS_MMR6 : StdMMR6Rel, INS_MMR6_DESC, INS_MMR6_ENC, ISA_MICROMIPS32R6; +def JALRC_MMR6 : R6MMR6Rel, JALRC_MMR6_ENC, JALRC_MMR6_DESC, ISA_MICROMIPS32R6; +def BOVC_MMR6 : R6MMR6Rel, BOVC_MMR6_ENC, BOVC_MMR6_DESC, ISA_MICROMIPS32R6; +def BNVC_MMR6 : R6MMR6Rel, BNVC_MMR6_ENC, BNVC_MMR6_DESC, ISA_MICROMIPS32R6; //===----------------------------------------------------------------------===// // @@ -1170,6 +1235,10 @@ def : MipsInstAlias<"rdhwr $rt, $rs", (RDHWR_MMR6 GPR32Opnd:$rt, HWRegsOpnd:$rs, 0), 1>, ISA_MICROMIPS32R6; +def : MipsInstAlias<"jalrc $src", (JALRC_MMR6 RA, GPR32Opnd:$src), 1>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"jr $src", (JALRC_MMR6 ZERO, GPR32Opnd:$src), 1>, + ISA_MICROMIPS32R6; //===----------------------------------------------------------------------===// // Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -666,6 +666,8 @@ ISA_MICROMIPS32_NOT_MIPS32R6; def LWM16_MM : LoadMultMM16<"lwm16">, LWM_FM_MM16<0x4>, ISA_MICROMIPS32_NOT_MIPS32R6; + def JR_MM : MMRel, IndirectBranch<"jr", GPR32Opnd>, JR_FM_MM<0x3c>, + ISA_MICROMIPS32_NOT_MIPS32R6; } class WaitMM : @@ -870,7 +872,7 @@ def JAL_MM : MMRel, JumpLink<"jal", calltarget_mm>, J_FM_MM<0x3d>; def JALX_MM : MMRel, JumpLink<"jalx", calltarget>, J_FM_MM<0x3c>; } - def JR_MM : MMRel, IndirectBranch<"jr", GPR32Opnd>, JR_FM_MM<0x3c>; + def JALR_MM : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM_MM<0x03c>; /// Jump Instructions - Short Delay Slot Index: lib/Target/Mips/Mips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/Mips32r6InstrInfo.td +++ lib/Target/Mips/Mips32r6InstrInfo.td @@ -685,8 +685,8 @@ 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; -def BOVC : BOVC_ENC, BOVC_DESC, ISA_MIPS32R6; +def BNVC : R6MMR6Rel, BNVC_ENC, BNVC_DESC, ISA_MIPS32R6; +def BOVC : R6MMR6Rel, BOVC_ENC, BOVC_DESC, ISA_MIPS32R6; def CACHE_R6 : R6MMR6Rel, CACHE_ENC, CACHE_DESC, ISA_MIPS32R6; def CLASS_D : CLASS_D_ENC, CLASS_D_DESC, ISA_MIPS32R6, HARDFLOAT; def CLASS_S : CLASS_S_ENC, CLASS_S_DESC, ISA_MIPS32R6, HARDFLOAT; @@ -754,8 +754,8 @@ let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"sdbbp", (SDBBP_R6 0)>, ISA_MIPS32R6; -} def : MipsInstAlias<"jr $rs", (JALR ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS32R6; +} //===----------------------------------------------------------------------===// // Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -1427,7 +1427,9 @@ /// Jump and Branch Instructions def J : MMRel, JumpFJ, FJ<2>, AdditionalRequires<[RelocStatic]>, IsBranch; +let AdditionalPredicates = [NotInMicroMips] in { def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>; +} def BEQ : MMRel, CBranch<"beq", brtarget, seteq, GPR32Opnd>, BEQ_FM<4>; def BEQL : MMRel, CBranch<"beql", brtarget, seteq, GPR32Opnd, 0>, BEQ_FM<20>, ISA_MIPS2_NOT_32R6_64R6; @@ -1607,9 +1609,11 @@ 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; let AdditionalPredicates = [NotInMicroMips] in { def RDHWR : MMRel, ReadHardware, RDHWR_FM; +def EXT : MMRel, StdMMR6Rel, ExtBase<"ext", GPR32Opnd, uimm5, MipsExt>, + EXT_FM<0>; +def INS : MMRel, StdMMR6Rel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>, + EXT_FM<4>; } -def EXT : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, MipsExt>, EXT_FM<0>; -def INS : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>, EXT_FM<4>; /// Move Control Registers From/To CPU Registers def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd>, MFC3OP_FM<0x10, 0>, ISA_MIPS32; Index: test/MC/Disassembler/Mips/micromips32r6/valid.txt =================================================================== --- test/MC/Disassembler/Mips/micromips32r6/valid.txt +++ test/MC/Disassembler/Mips/micromips32r6/valid.txt @@ -243,3 +243,10 @@ 0xea 0x11 # CHECK: sw16 $4, 4($17) 0xe8 0x11 # CHECK: sw16 $zero, 4($17) 0x45 0x2a # CHECK: swm16 $16, $17, $ra, 8($sp) +0x01 0x26 0x30 0xec # CHECK: ext $9, $6, 3, 7 +0x01 0x26 0x48 0xcc # CHECK: ins $9, $6, 3, 7 +0x00 0x85 0x0f 0x3c # CHECK: jalrc $4, $5 +0x03 0xe5 0x0f 0x3c # CHECK: jalrc $ra, $5 +0x00 0x05 0x0f 0x3c # CHECK: jalrc $zero, $5 +0x74 0x44 0x00 0x0c # CHECK: bovc $2, $4, 24 +0x7c 0x44 0x00 0x0c # CHECK: bnvc $2, $4, 24 Index: test/MC/Mips/micromips32r6/valid.s =================================================================== --- test/MC/Mips/micromips32r6/valid.s +++ test/MC/Mips/micromips32r6/valid.s @@ -236,3 +236,10 @@ lbu $4, 8($5) # CHECK: lbu $4, 8($5) # encoding: [0x14,0x85,0x00,0x08] lbe $4, 8($5) # CHECK: lbe $4, 8($5) # encoding: [0x60,0x85,0x68,0x08] lbue $4, 8($5) # CHECK: lbue $4, 8($5) # encoding: [0x60,0x85,0x60,0x08] + ins $9, $6, 3, 7 # CHECK: ins $9, $6, 3, 7 # encoding: [0x01,0x26,0x48,0xcc] + jalrc $4, $5 # CHECK: jalrc $4, $5 # encoding: [0x00,0x85,0x0f,0x3c] + jalrc $5 # CHECK: jalrc $ra, $5 # encoding: [0x03,0xe5,0x0f,0x3c] + jr $5 # CHECK: jalrc $zero, $5 # encoding: [0x00,0x05,0x0f,0x3c] + ext $9, $6, 3, 7 # CHECK: ext $9, $6, 3, 7 # encoding: [0x01,0x26,0x30,0xec] + bovc $2, $4, 24 # CHECK: bovc $2, $4, 24 # encoding: [0x74,0x44,0x00,0x0c] + bnvc $2, $4, 24 # CHECK: bnvc $2, $4, 24 # encoding: [0x7c,0x44,0x00,0x0c]